node-libcec 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js ADDED
@@ -0,0 +1,433 @@
1
+ const EventEmitter = require('events');
2
+
3
+ // Load native addon
4
+ let native;
5
+ try {
6
+ native = require('../build/Release/cec.node');
7
+ } catch (e) {
8
+ try {
9
+ native = require('../build/Debug/cec.node');
10
+ } catch (e2) {
11
+ throw new Error('Failed to load native cec module. Did you run npm run build?');
12
+ }
13
+ }
14
+
15
+ const constants = require('./constants');
16
+
17
+ /**
18
+ * CEC Adapter class - provides high-level interface to libcec
19
+ */
20
+ class CECAdapter extends EventEmitter {
21
+ /**
22
+ * Create a new CEC adapter instance
23
+ * @param {Object} options - Configuration options
24
+ * @param {string} [options.deviceName='node-libcec'] - OSD name for this device
25
+ * @param {number[]} [options.deviceTypes] - Array of device types (default: [DeviceType.RECORDING_DEVICE])
26
+ * @param {number} [options.physicalAddress] - Physical address (auto-detected if not specified)
27
+ * @param {number} [options.baseDevice] - Base device logical address
28
+ * @param {number} [options.hdmiPort] - HDMI port number
29
+ * @param {boolean} [options.activateSource=false] - Whether to activate as source on connect
30
+ */
31
+ constructor(options = {}) {
32
+ super();
33
+ this._adapter = new native.CECAdapter(options);
34
+ this._setupCallbacks();
35
+ }
36
+
37
+ /**
38
+ * Set up internal callbacks that emit events
39
+ */
40
+ _setupCallbacks() {
41
+ this._adapter.setCallbacks({
42
+ onLogMessage: (msg) => this.emit('log', msg),
43
+ onKeyPress: (key) => this.emit('keypress', key),
44
+ onCommand: (cmd) => this.emit('command', cmd),
45
+ onConfigurationChanged: (config) => this.emit('configurationChanged', config),
46
+ onAlert: (alert) => this.emit('alert', alert),
47
+ onSourceActivated: (source) => this.emit('sourceActivated', source)
48
+ });
49
+ }
50
+
51
+ /**
52
+ * Detect available CEC adapters
53
+ * @returns {Array} Array of adapter descriptors
54
+ */
55
+ static detectAdapters() {
56
+ return native.CECAdapter.detectAdapters();
57
+ }
58
+
59
+ /**
60
+ * Open connection to a CEC adapter
61
+ * @param {string} [port] - COM port path (auto-detected if not specified)
62
+ * @param {number} [timeout=10000] - Connection timeout in milliseconds
63
+ * @returns {boolean} True if connection successful
64
+ */
65
+ open(port, timeout = 10000) {
66
+ return this._adapter.open(port, timeout);
67
+ }
68
+
69
+ /**
70
+ * Close the adapter connection
71
+ */
72
+ close() {
73
+ this._adapter.close();
74
+ }
75
+
76
+ /**
77
+ * Check if the adapter is responding
78
+ * @returns {boolean} True if adapter responds to ping
79
+ */
80
+ pingAdapter() {
81
+ return this._adapter.pingAdapter();
82
+ }
83
+
84
+ /**
85
+ * Get the adapter's USB vendor ID
86
+ * @returns {number} Vendor ID
87
+ */
88
+ getAdapterVendorId() {
89
+ return this._adapter.getAdapterVendorId();
90
+ }
91
+
92
+ /**
93
+ * Get the adapter's USB product ID
94
+ * @returns {number} Product ID
95
+ */
96
+ getAdapterProductId() {
97
+ return this._adapter.getAdapterProductId();
98
+ }
99
+
100
+ /**
101
+ * Get libcec library information
102
+ * @returns {string} Library info string
103
+ */
104
+ getLibInfo() {
105
+ return this._adapter.getLibInfo();
106
+ }
107
+
108
+ // === Device Control ===
109
+
110
+ /**
111
+ * Power on devices
112
+ * @param {number} [address=LogicalAddress.TV] - Target device address
113
+ * @returns {boolean} True if command sent successfully
114
+ */
115
+ powerOnDevices(address = constants.LogicalAddress.TV) {
116
+ return this._adapter.powerOnDevices(address);
117
+ }
118
+
119
+ /**
120
+ * Put devices into standby
121
+ * @param {number} [address=LogicalAddress.BROADCAST] - Target device address
122
+ * @returns {boolean} True if command sent successfully
123
+ */
124
+ standbyDevices(address = constants.LogicalAddress.BROADCAST) {
125
+ return this._adapter.standbyDevices(address);
126
+ }
127
+
128
+ /**
129
+ * Set this device as the active source
130
+ * @param {number} [deviceType] - Device type
131
+ * @returns {boolean} True if command sent successfully
132
+ */
133
+ setActiveSource(deviceType) {
134
+ return this._adapter.setActiveSource(deviceType);
135
+ }
136
+
137
+ /**
138
+ * Mark this device as inactive source
139
+ * @returns {boolean} True if command sent successfully
140
+ */
141
+ setInactiveView() {
142
+ return this._adapter.setInactiveView();
143
+ }
144
+
145
+ // === Command Transmission ===
146
+
147
+ /**
148
+ * Transmit a raw CEC command
149
+ * @param {Object} command - Command object
150
+ * @param {number} command.initiator - Source logical address
151
+ * @param {number} command.destination - Target logical address
152
+ * @param {number} command.opcode - CEC opcode
153
+ * @param {number[]} [command.parameters] - Command parameters
154
+ * @returns {boolean} True if command sent successfully
155
+ */
156
+ transmit(command) {
157
+ return this._adapter.transmit(command);
158
+ }
159
+
160
+ /**
161
+ * Send a keypress to a device
162
+ * @param {number} destination - Target device address
163
+ * @param {number} keycode - User control code
164
+ * @param {boolean} [wait=false] - Wait for ACK
165
+ * @returns {boolean} True if command sent successfully
166
+ */
167
+ sendKeypress(destination, keycode, wait = false) {
168
+ return this._adapter.sendKeypress(destination, keycode, wait);
169
+ }
170
+
171
+ /**
172
+ * Send a key release to a device
173
+ * @param {number} destination - Target device address
174
+ * @param {boolean} [wait=false] - Wait for ACK
175
+ * @returns {boolean} True if command sent successfully
176
+ */
177
+ sendKeyRelease(destination, wait = false) {
178
+ return this._adapter.sendKeyRelease(destination, wait);
179
+ }
180
+
181
+ // === Device Information ===
182
+
183
+ /**
184
+ * Get the CEC version of a device
185
+ * @param {number} address - Device logical address
186
+ * @returns {number} CEC version
187
+ */
188
+ getDeviceCecVersion(address) {
189
+ return this._adapter.getDeviceCecVersion(address);
190
+ }
191
+
192
+ /**
193
+ * Get the menu language of a device
194
+ * @param {number} address - Device logical address
195
+ * @returns {string} Menu language (3-letter code)
196
+ */
197
+ getDeviceMenuLanguage(address) {
198
+ return this._adapter.getDeviceMenuLanguage(address);
199
+ }
200
+
201
+ /**
202
+ * Get the vendor ID of a device
203
+ * @param {number} address - Device logical address
204
+ * @returns {number} Vendor ID
205
+ */
206
+ getDeviceVendorId(address) {
207
+ return this._adapter.getDeviceVendorId(address);
208
+ }
209
+
210
+ /**
211
+ * Get the power status of a device
212
+ * @param {number} address - Device logical address
213
+ * @returns {number} Power status (see PowerStatus)
214
+ */
215
+ getDevicePowerStatus(address) {
216
+ return this._adapter.getDevicePowerStatus(address);
217
+ }
218
+
219
+ /**
220
+ * Get the OSD name of a device
221
+ * @param {number} address - Device logical address
222
+ * @returns {string} OSD name
223
+ */
224
+ getDeviceOSDName(address) {
225
+ return this._adapter.getDeviceOSDName(address);
226
+ }
227
+
228
+ /**
229
+ * Get the physical address of a device
230
+ * @param {number} address - Device logical address
231
+ * @returns {number} Physical address
232
+ */
233
+ getDevicePhysicalAddress(address) {
234
+ return this._adapter.getDevicePhysicalAddress(address);
235
+ }
236
+
237
+ // === Device Status ===
238
+
239
+ /**
240
+ * Poll a device to check if it's present
241
+ * @param {number} address - Device logical address
242
+ * @returns {boolean} True if device responds
243
+ */
244
+ pollDevice(address) {
245
+ return this._adapter.pollDevice(address);
246
+ }
247
+
248
+ /**
249
+ * Get all active devices on the bus
250
+ * @returns {number[]} Array of active logical addresses
251
+ */
252
+ getActiveDevices() {
253
+ return this._adapter.getActiveDevices();
254
+ }
255
+
256
+ /**
257
+ * Check if a device is active
258
+ * @param {number} address - Device logical address
259
+ * @returns {boolean} True if device is active
260
+ */
261
+ isActiveDevice(address) {
262
+ return this._adapter.isActiveDevice(address);
263
+ }
264
+
265
+ /**
266
+ * Check if a device type is active
267
+ * @param {number} type - Device type
268
+ * @returns {boolean} True if device type is active
269
+ */
270
+ isActiveDeviceType(type) {
271
+ return this._adapter.isActiveDeviceType(type);
272
+ }
273
+
274
+ /**
275
+ * Get the current active source
276
+ * @returns {number} Logical address of active source
277
+ */
278
+ getActiveSource() {
279
+ return this._adapter.getActiveSource();
280
+ }
281
+
282
+ /**
283
+ * Check if a device is the active source
284
+ * @param {number} address - Device logical address
285
+ * @returns {boolean} True if device is active source
286
+ */
287
+ isActiveSource(address) {
288
+ return this._adapter.isActiveSource(address);
289
+ }
290
+
291
+ /**
292
+ * Check if libcec is the active source
293
+ * @returns {boolean} True if libcec controls active source
294
+ */
295
+ isLibCECActiveSource() {
296
+ return this._adapter.isLibCECActiveSource();
297
+ }
298
+
299
+ // === Audio Control ===
300
+
301
+ /**
302
+ * Increase volume
303
+ * @param {boolean} [sendRelease=true] - Send key release after
304
+ * @returns {number} New audio status
305
+ */
306
+ volumeUp(sendRelease = true) {
307
+ return this._adapter.volumeUp(sendRelease);
308
+ }
309
+
310
+ /**
311
+ * Decrease volume
312
+ * @param {boolean} [sendRelease=true] - Send key release after
313
+ * @returns {number} New audio status
314
+ */
315
+ volumeDown(sendRelease = true) {
316
+ return this._adapter.volumeDown(sendRelease);
317
+ }
318
+
319
+ /**
320
+ * Mute audio
321
+ * @returns {number} Audio status
322
+ */
323
+ muteAudio() {
324
+ return this._adapter.muteAudio();
325
+ }
326
+
327
+ /**
328
+ * Toggle mute
329
+ * @returns {number} Audio status
330
+ */
331
+ audioToggleMute() {
332
+ return this._adapter.audioToggleMute();
333
+ }
334
+
335
+ /**
336
+ * Get current audio status
337
+ * @returns {number} Audio status
338
+ */
339
+ audioStatus() {
340
+ return this._adapter.audioStatus();
341
+ }
342
+
343
+ // === Display Control ===
344
+
345
+ /**
346
+ * Display a message on a device's OSD
347
+ * @param {number} address - Target device address
348
+ * @param {number} duration - Display control (see DisplayControl)
349
+ * @param {string} message - Message to display
350
+ * @returns {boolean} True if command sent successfully
351
+ */
352
+ setOSDString(address, duration, message) {
353
+ return this._adapter.setOSDString(address, duration, message);
354
+ }
355
+
356
+ // === Address Configuration ===
357
+
358
+ /**
359
+ * Set the logical address
360
+ * @param {number} [address=LogicalAddress.PLAYBACK_DEVICE_1] - Logical address
361
+ * @returns {boolean} True if successful
362
+ */
363
+ setLogicalAddress(address = constants.LogicalAddress.PLAYBACK_DEVICE_1) {
364
+ return this._adapter.setLogicalAddress(address);
365
+ }
366
+
367
+ /**
368
+ * Set the physical address
369
+ * @param {number} address - Physical address (e.g., 0x1000 for HDMI 1)
370
+ * @returns {boolean} True if successful
371
+ */
372
+ setPhysicalAddress(address) {
373
+ return this._adapter.setPhysicalAddress(address);
374
+ }
375
+
376
+ /**
377
+ * Set the HDMI port
378
+ * @param {number} baseDevice - Base device logical address (usually TV)
379
+ * @param {number} port - HDMI port number (1-15)
380
+ * @returns {boolean} True if successful
381
+ */
382
+ setHDMIPort(baseDevice, port) {
383
+ return this._adapter.setHDMIPort(baseDevice, port);
384
+ }
385
+
386
+ /**
387
+ * Get the logical addresses controlled by this adapter
388
+ * @returns {Object} Object with primary address and array of all addresses
389
+ */
390
+ getLogicalAddresses() {
391
+ return this._adapter.getLogicalAddresses();
392
+ }
393
+
394
+ // === Configuration ===
395
+
396
+ /**
397
+ * Get the current configuration
398
+ * @returns {Object} Configuration object
399
+ */
400
+ getCurrentConfiguration() {
401
+ return this._adapter.getCurrentConfiguration();
402
+ }
403
+
404
+ /**
405
+ * Set the configuration
406
+ * @param {Object} config - Configuration object
407
+ * @returns {boolean} True if successful
408
+ */
409
+ setConfiguration(config) {
410
+ return this._adapter.setConfiguration(config);
411
+ }
412
+
413
+ /**
414
+ * Rescan for active devices
415
+ */
416
+ rescanActiveDevices() {
417
+ this._adapter.rescanActiveDevices();
418
+ }
419
+
420
+ /**
421
+ * Disable all callbacks
422
+ * @returns {boolean} True if successful
423
+ */
424
+ disableCallbacks() {
425
+ return this._adapter.disableCallbacks();
426
+ }
427
+ }
428
+
429
+ // Export everything
430
+ module.exports = {
431
+ CECAdapter,
432
+ ...constants
433
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "node-libcec",
3
+ "version": "1.0.0",
4
+ "description": "Node.js bindings for libcec - control CEC devices over HDMI",
5
+ "main": "lib/index.js",
6
+ "scripts": {
7
+ "build": "node-gyp rebuild",
8
+ "clean": "node-gyp clean",
9
+ "prepare": "npm run build",
10
+ "test": "node --test test/"
11
+ },
12
+ "keywords": [
13
+ "cec",
14
+ "hdmi",
15
+ "libcec",
16
+ "pulse-eight",
17
+ "consumer-electronics-control",
18
+ "tv",
19
+ "remote",
20
+ "home-automation",
21
+ "smart-home",
22
+ "native-addon"
23
+ ],
24
+ "author": "fajitacat",
25
+ "license": "MIT",
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ },
29
+ "os": [
30
+ "linux",
31
+ "darwin",
32
+ "win32"
33
+ ],
34
+ "files": [
35
+ "lib/",
36
+ "src/",
37
+ "binding.gyp"
38
+ ],
39
+ "dependencies": {
40
+ "node-addon-api": "^8.0.0"
41
+ },
42
+ "devDependencies": {
43
+ "node-gyp": "^10.0.0"
44
+ },
45
+ "gypfile": true
46
+ }