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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 fajitacat
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # node-libcec
2
+
3
+ Node.js bindings for [libcec](https://github.com/Pulse-Eight/libcec) - control CEC (Consumer Electronics Control) devices over HDMI.
4
+
5
+ ## Prerequisites
6
+
7
+ You must have libcec installed on your system:
8
+
9
+ **Linux (Debian/Ubuntu):**
10
+ ```bash
11
+ sudo apt-get install libcec-dev
12
+ ```
13
+
14
+ **macOS (Homebrew):**
15
+ ```bash
16
+ brew install libcec
17
+ ```
18
+
19
+ **Windows:**
20
+ Install the [Pulse-Eight USB-CEC Adapter software](https://www.pulse-eight.com/downloads).
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install node-libcec
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```javascript
31
+ const { CECAdapter, LogicalAddress, DeviceType } = require('node-libcec');
32
+
33
+ // Create adapter
34
+ const cec = new CECAdapter({
35
+ deviceName: 'MyApp',
36
+ deviceTypes: [DeviceType.RECORDING_DEVICE]
37
+ });
38
+
39
+ // Listen for events
40
+ cec.on('keypress', (key) => {
41
+ console.log('Remote key pressed:', key.keycode);
42
+ });
43
+
44
+ cec.on('command', (cmd) => {
45
+ console.log('CEC command received:', cmd);
46
+ });
47
+
48
+ // Connect to adapter (auto-detects port)
49
+ cec.open();
50
+
51
+ // Discover devices on the bus
52
+ const devices = cec.getActiveDevices();
53
+ devices.forEach(addr => {
54
+ console.log(`Device ${addr}: ${cec.getDeviceOSDName(addr)}`);
55
+ });
56
+
57
+ // Control devices
58
+ cec.powerOnDevices(LogicalAddress.TV);
59
+ cec.setActiveSource();
60
+
61
+ // Cleanup
62
+ cec.close();
63
+ ```
64
+
65
+ ## API
66
+
67
+ ### CECAdapter
68
+
69
+ #### Constructor Options
70
+
71
+ ```javascript
72
+ new CECAdapter({
73
+ deviceName: 'node-libcec', // OSD name (max 13 chars)
74
+ deviceTypes: [DeviceType.RECORDING_DEVICE],
75
+ physicalAddress: 0x1000, // Optional: fixed physical address
76
+ baseDevice: LogicalAddress.TV, // Base device for address detection
77
+ hdmiPort: 1, // HDMI port number
78
+ activateSource: false // Auto-activate as source on connect
79
+ });
80
+ ```
81
+
82
+ #### Static Methods
83
+
84
+ - `CECAdapter.detectAdapters()` - Returns array of detected CEC adapters
85
+
86
+ #### Connection
87
+
88
+ - `open(port?, timeout?)` - Connect to adapter (auto-detects if no port)
89
+ - `close()` - Disconnect
90
+ - `pingAdapter()` - Check if adapter is responsive
91
+
92
+ #### Device Discovery
93
+
94
+ - `getActiveDevices()` - Get array of active logical addresses
95
+ - `pollDevice(address)` - Check if device exists
96
+ - `isActiveDevice(address)` - Check if device is active
97
+ - `getActiveSource()` - Get current active source address
98
+
99
+ #### Device Information
100
+
101
+ - `getDeviceOSDName(address)` - Get device name
102
+ - `getDeviceVendorId(address)` - Get vendor ID
103
+ - `getDevicePhysicalAddress(address)` - Get physical address
104
+ - `getDevicePowerStatus(address)` - Get power status
105
+ - `getDeviceCecVersion(address)` - Get CEC version
106
+ - `getDeviceMenuLanguage(address)` - Get menu language
107
+
108
+ #### Power Control
109
+
110
+ - `powerOnDevices(address?)` - Power on device(s)
111
+ - `standbyDevices(address?)` - Put device(s) in standby
112
+
113
+ #### Source Control
114
+
115
+ - `setActiveSource(deviceType?)` - Set this adapter as active source
116
+ - `setInactiveView()` - Set this adapter as inactive
117
+
118
+ #### Audio Control
119
+
120
+ - `volumeUp(sendRelease?)` - Increase volume
121
+ - `volumeDown(sendRelease?)` - Decrease volume
122
+ - `muteAudio()` - Mute audio
123
+ - `audioToggleMute()` - Toggle mute
124
+ - `audioStatus()` - Get audio status
125
+
126
+ #### Commands
127
+
128
+ - `transmit(command)` - Send raw CEC command
129
+ - `sendKeypress(destination, keycode, wait?)` - Send remote keypress
130
+ - `sendKeyRelease(destination, wait?)` - Send key release
131
+ - `setOSDString(address, duration, message)` - Display message on device
132
+
133
+ ### Events
134
+
135
+ ```javascript
136
+ cec.on('log', (message) => { }); // Library log messages
137
+ cec.on('keypress', (key) => { }); // Remote control keypresses
138
+ cec.on('command', (command) => { }); // CEC commands
139
+ cec.on('sourceActivated', (info) => { }); // Source activation changes
140
+ cec.on('alert', (alert) => { }); // System alerts
141
+ cec.on('configurationChanged', (config) => { }); // Config changes
142
+ ```
143
+
144
+ ### Constants
145
+
146
+ ```javascript
147
+ const {
148
+ LogicalAddress, // TV, RECORDING_DEVICE_1, PLAYBACK_DEVICE_1, etc.
149
+ DeviceType, // TV, RECORDING_DEVICE, PLAYBACK_DEVICE, etc.
150
+ PowerStatus, // ON, STANDBY, IN_TRANSITION_*, UNKNOWN
151
+ Opcode, // STANDBY, ACTIVE_SOURCE, USER_CONTROL_PRESSED, etc.
152
+ UserControlCode, // SELECT, UP, DOWN, PLAY, PAUSE, etc.
153
+ LogLevel, // ERROR, WARNING, NOTICE, TRAFFIC, DEBUG
154
+ AlertType // SERVICE_DEVICE, CONNECTION_LOST, etc.
155
+ } = require('node-libcec');
156
+ ```
157
+
158
+ ## Examples
159
+
160
+ See the [examples](./examples) directory for more usage patterns:
161
+
162
+ - `basic.js` - Simple device discovery and event handling
163
+ - `advanced.js` - Interactive CLI with full feature demonstration
164
+
165
+ ## Platform Support
166
+
167
+ | Platform | Status | Notes |
168
+ |----------|--------|-------|
169
+ | Linux | Supported | Requires libcec-dev |
170
+ | macOS | Supported | Requires Homebrew libcec |
171
+ | Windows | Supported | Requires Pulse-Eight SDK |
172
+
173
+ ## Requirements
174
+
175
+ - Node.js >= 18.0.0
176
+ - libcec system library
177
+ - A CEC-compatible USB adapter (e.g., Pulse-Eight USB-CEC)
178
+
179
+ ## License
180
+
181
+ MIT
package/binding.gyp ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "cec",
5
+ "cflags!": ["-fno-exceptions"],
6
+ "cflags_cc!": ["-fno-exceptions"],
7
+ "sources": [
8
+ "src/native/cec_addon.cc",
9
+ "src/native/cec_adapter.cc",
10
+ "src/native/cec_callbacks.cc"
11
+ ],
12
+ "include_dirs": [
13
+ "<!@(node -p \"require('node-addon-api').include\")",
14
+ "/usr/include",
15
+ "/usr/local/include"
16
+ ],
17
+ "libraries": [
18
+ "-lcec"
19
+ ],
20
+ "defines": ["NAPI_DISABLE_CPP_EXCEPTIONS"],
21
+ "conditions": [
22
+ ["OS=='mac'", {
23
+ "xcode_settings": {
24
+ "GCC_ENABLE_CPP_EXCEPTIONS": "YES",
25
+ "CLANG_CXX_LIBRARY": "libc++",
26
+ "MACOSX_DEPLOYMENT_TARGET": "10.15"
27
+ },
28
+ "include_dirs": [
29
+ "/usr/local/include",
30
+ "/opt/homebrew/include"
31
+ ],
32
+ "libraries": [
33
+ "-L/usr/local/lib",
34
+ "-L/opt/homebrew/lib"
35
+ ]
36
+ }],
37
+ ["OS=='linux'", {
38
+ "cflags_cc": [
39
+ "-std=c++17",
40
+ "-fexceptions"
41
+ ],
42
+ "include_dirs": [
43
+ "/usr/include/libcec"
44
+ ]
45
+ }],
46
+ ["OS=='win'", {
47
+ "msvs_settings": {
48
+ "VCCLCompilerTool": {
49
+ "ExceptionHandling": 1
50
+ }
51
+ },
52
+ "include_dirs": [
53
+ "C:/Program Files (x86)/Pulse-Eight/USB-CEC Adapter/include"
54
+ ],
55
+ "libraries": [
56
+ "-lC:/Program Files (x86)/Pulse-Eight/USB-CEC Adapter/cec.lib"
57
+ ]
58
+ }]
59
+ ]
60
+ }
61
+ ]
62
+ }
@@ -0,0 +1,275 @@
1
+ /**
2
+ * CEC Logical Addresses
3
+ */
4
+ const LogicalAddress = {
5
+ TV: 0,
6
+ RECORDING_DEVICE_1: 1,
7
+ RECORDING_DEVICE_2: 2,
8
+ TUNER_1: 3,
9
+ PLAYBACK_DEVICE_1: 4,
10
+ AUDIO_SYSTEM: 5,
11
+ TUNER_2: 6,
12
+ TUNER_3: 7,
13
+ PLAYBACK_DEVICE_2: 8,
14
+ RECORDING_DEVICE_3: 9,
15
+ TUNER_4: 10,
16
+ PLAYBACK_DEVICE_3: 11,
17
+ RESERVED_1: 12,
18
+ RESERVED_2: 13,
19
+ FREE_USE: 14,
20
+ BROADCAST: 15,
21
+ UNKNOWN: 15
22
+ };
23
+
24
+ /**
25
+ * CEC Device Types
26
+ */
27
+ const DeviceType = {
28
+ TV: 0,
29
+ RECORDING_DEVICE: 1,
30
+ RESERVED: 2,
31
+ TUNER: 3,
32
+ PLAYBACK_DEVICE: 4,
33
+ AUDIO_SYSTEM: 5
34
+ };
35
+
36
+ /**
37
+ * CEC Power Status
38
+ */
39
+ const PowerStatus = {
40
+ ON: 0x00,
41
+ STANDBY: 0x01,
42
+ IN_TRANSITION_STANDBY_TO_ON: 0x02,
43
+ IN_TRANSITION_ON_TO_STANDBY: 0x03,
44
+ UNKNOWN: 0x99
45
+ };
46
+
47
+ /**
48
+ * CEC Opcodes
49
+ */
50
+ const Opcode = {
51
+ ACTIVE_SOURCE: 0x82,
52
+ IMAGE_VIEW_ON: 0x04,
53
+ TEXT_VIEW_ON: 0x0D,
54
+ INACTIVE_SOURCE: 0x9D,
55
+ REQUEST_ACTIVE_SOURCE: 0x85,
56
+ ROUTING_CHANGE: 0x80,
57
+ ROUTING_INFORMATION: 0x81,
58
+ SET_STREAM_PATH: 0x86,
59
+ STANDBY: 0x36,
60
+ RECORD_OFF: 0x0B,
61
+ RECORD_ON: 0x09,
62
+ RECORD_STATUS: 0x0A,
63
+ RECORD_TV_SCREEN: 0x0F,
64
+ CLEAR_ANALOGUE_TIMER: 0x33,
65
+ CLEAR_DIGITAL_TIMER: 0x99,
66
+ CLEAR_EXTERNAL_TIMER: 0xA1,
67
+ SET_ANALOGUE_TIMER: 0x34,
68
+ SET_DIGITAL_TIMER: 0x97,
69
+ SET_EXTERNAL_TIMER: 0xA2,
70
+ SET_TIMER_PROGRAM_TITLE: 0x67,
71
+ TIMER_CLEARED_STATUS: 0x43,
72
+ TIMER_STATUS: 0x35,
73
+ CEC_VERSION: 0x9E,
74
+ GET_CEC_VERSION: 0x9F,
75
+ GIVE_PHYSICAL_ADDRESS: 0x83,
76
+ GET_MENU_LANGUAGE: 0x91,
77
+ REPORT_PHYSICAL_ADDRESS: 0x84,
78
+ SET_MENU_LANGUAGE: 0x32,
79
+ DECK_CONTROL: 0x42,
80
+ DECK_STATUS: 0x1B,
81
+ GIVE_DECK_STATUS: 0x1A,
82
+ PLAY: 0x41,
83
+ GIVE_TUNER_DEVICE_STATUS: 0x08,
84
+ SELECT_ANALOGUE_SERVICE: 0x92,
85
+ SELECT_DIGITAL_SERVICE: 0x93,
86
+ TUNER_DEVICE_STATUS: 0x07,
87
+ TUNER_STEP_DECREMENT: 0x06,
88
+ TUNER_STEP_INCREMENT: 0x05,
89
+ DEVICE_VENDOR_ID: 0x87,
90
+ GIVE_DEVICE_VENDOR_ID: 0x8C,
91
+ VENDOR_COMMAND: 0x89,
92
+ VENDOR_COMMAND_WITH_ID: 0xA0,
93
+ VENDOR_REMOTE_BUTTON_DOWN: 0x8A,
94
+ VENDOR_REMOTE_BUTTON_UP: 0x8B,
95
+ SET_OSD_STRING: 0x64,
96
+ GIVE_OSD_NAME: 0x46,
97
+ SET_OSD_NAME: 0x47,
98
+ MENU_REQUEST: 0x8D,
99
+ MENU_STATUS: 0x8E,
100
+ USER_CONTROL_PRESSED: 0x44,
101
+ USER_CONTROL_RELEASE: 0x45,
102
+ GIVE_DEVICE_POWER_STATUS: 0x8F,
103
+ REPORT_POWER_STATUS: 0x90,
104
+ FEATURE_ABORT: 0x00,
105
+ ABORT: 0xFF,
106
+ GIVE_AUDIO_STATUS: 0x71,
107
+ GIVE_SYSTEM_AUDIO_MODE_STATUS: 0x7D,
108
+ REPORT_AUDIO_STATUS: 0x7A,
109
+ SET_SYSTEM_AUDIO_MODE: 0x72,
110
+ SYSTEM_AUDIO_MODE_REQUEST: 0x70,
111
+ SYSTEM_AUDIO_MODE_STATUS: 0x7E,
112
+ SET_AUDIO_RATE: 0x9A,
113
+ REPORT_SHORT_AUDIO_DESCRIPTORS: 0xA3,
114
+ REQUEST_SHORT_AUDIO_DESCRIPTORS: 0xA4,
115
+ START_ARC: 0xC0,
116
+ REPORT_ARC_STARTED: 0xC1,
117
+ REPORT_ARC_ENDED: 0xC2,
118
+ REQUEST_ARC_START: 0xC3,
119
+ REQUEST_ARC_END: 0xC4,
120
+ END_ARC: 0xC5,
121
+ CDC: 0xF8,
122
+ NONE: 0xFD
123
+ };
124
+
125
+ /**
126
+ * CEC User Control Codes (Remote buttons)
127
+ */
128
+ const UserControlCode = {
129
+ SELECT: 0x00,
130
+ UP: 0x01,
131
+ DOWN: 0x02,
132
+ LEFT: 0x03,
133
+ RIGHT: 0x04,
134
+ RIGHT_UP: 0x05,
135
+ RIGHT_DOWN: 0x06,
136
+ LEFT_UP: 0x07,
137
+ LEFT_DOWN: 0x08,
138
+ ROOT_MENU: 0x09,
139
+ SETUP_MENU: 0x0A,
140
+ CONTENTS_MENU: 0x0B,
141
+ FAVORITE_MENU: 0x0C,
142
+ EXIT: 0x0D,
143
+ TOP_MENU: 0x10,
144
+ DVD_MENU: 0x11,
145
+ NUMBER_ENTRY_MODE: 0x1D,
146
+ NUMBER11: 0x1E,
147
+ NUMBER12: 0x1F,
148
+ NUMBER0: 0x20,
149
+ NUMBER1: 0x21,
150
+ NUMBER2: 0x22,
151
+ NUMBER3: 0x23,
152
+ NUMBER4: 0x24,
153
+ NUMBER5: 0x25,
154
+ NUMBER6: 0x26,
155
+ NUMBER7: 0x27,
156
+ NUMBER8: 0x28,
157
+ NUMBER9: 0x29,
158
+ DOT: 0x2A,
159
+ ENTER: 0x2B,
160
+ CLEAR: 0x2C,
161
+ NEXT_FAVORITE: 0x2F,
162
+ CHANNEL_UP: 0x30,
163
+ CHANNEL_DOWN: 0x31,
164
+ PREVIOUS_CHANNEL: 0x32,
165
+ SOUND_SELECT: 0x33,
166
+ INPUT_SELECT: 0x34,
167
+ DISPLAY_INFORMATION: 0x35,
168
+ HELP: 0x36,
169
+ PAGE_UP: 0x37,
170
+ PAGE_DOWN: 0x38,
171
+ POWER: 0x40,
172
+ VOLUME_UP: 0x41,
173
+ VOLUME_DOWN: 0x42,
174
+ MUTE: 0x43,
175
+ PLAY: 0x44,
176
+ STOP: 0x45,
177
+ PAUSE: 0x46,
178
+ RECORD: 0x47,
179
+ REWIND: 0x48,
180
+ FAST_FORWARD: 0x49,
181
+ EJECT: 0x4A,
182
+ FORWARD: 0x4B,
183
+ BACKWARD: 0x4C,
184
+ STOP_RECORD: 0x4D,
185
+ PAUSE_RECORD: 0x4E,
186
+ ANGLE: 0x50,
187
+ SUB_PICTURE: 0x51,
188
+ VIDEO_ON_DEMAND: 0x52,
189
+ ELECTRONIC_PROGRAM_GUIDE: 0x53,
190
+ TIMER_PROGRAMMING: 0x54,
191
+ INITIAL_CONFIGURATION: 0x55,
192
+ SELECT_BROADCAST_TYPE: 0x56,
193
+ SELECT_SOUND_PRESENTATION: 0x57,
194
+ PLAY_FUNCTION: 0x60,
195
+ PAUSE_PLAY_FUNCTION: 0x61,
196
+ RECORD_FUNCTION: 0x62,
197
+ PAUSE_RECORD_FUNCTION: 0x63,
198
+ STOP_FUNCTION: 0x64,
199
+ MUTE_FUNCTION: 0x65,
200
+ RESTORE_VOLUME_FUNCTION: 0x66,
201
+ TUNE_FUNCTION: 0x67,
202
+ SELECT_MEDIA_FUNCTION: 0x68,
203
+ SELECT_AV_INPUT_FUNCTION: 0x69,
204
+ SELECT_AUDIO_INPUT_FUNCTION: 0x6A,
205
+ POWER_TOGGLE_FUNCTION: 0x6B,
206
+ POWER_OFF_FUNCTION: 0x6C,
207
+ POWER_ON_FUNCTION: 0x6D,
208
+ F1_BLUE: 0x71,
209
+ F2_RED: 0x72,
210
+ F3_GREEN: 0x73,
211
+ F4_YELLOW: 0x74,
212
+ F5: 0x75,
213
+ DATA: 0x76,
214
+ AN_RETURN: 0x91,
215
+ AN_CHANNELS_LIST: 0x96,
216
+ UNKNOWN: 0xFF
217
+ };
218
+
219
+ /**
220
+ * CEC Log Level
221
+ */
222
+ const LogLevel = {
223
+ ERROR: 1,
224
+ WARNING: 2,
225
+ NOTICE: 4,
226
+ TRAFFIC: 8,
227
+ DEBUG: 16,
228
+ ALL: 31
229
+ };
230
+
231
+ /**
232
+ * CEC Display Control (for OSD strings)
233
+ */
234
+ const DisplayControl = {
235
+ DISPLAY_FOR_DEFAULT_TIME: 0x00,
236
+ DISPLAY_UNTIL_CLEARED: 0x40,
237
+ CLEAR_PREVIOUS_MESSAGE: 0x80,
238
+ RESERVED_FOR_FUTURE_USE: 0xC0
239
+ };
240
+
241
+ /**
242
+ * CEC Version
243
+ */
244
+ const Version = {
245
+ UNKNOWN: 0x00,
246
+ V1_2: 0x01,
247
+ V1_2A: 0x02,
248
+ V1_3: 0x03,
249
+ V1_3A: 0x04,
250
+ V1_4: 0x05,
251
+ V2_0: 0x06
252
+ };
253
+
254
+ /**
255
+ * Alert Types
256
+ */
257
+ const AlertType = {
258
+ SERVICE_DEVICE: 1,
259
+ CONNECTION_LOST: 2,
260
+ PERMISSION_ERROR: 3,
261
+ PORT_BUSY: 4,
262
+ PHYSICAL_ADDRESS_ERROR: 5
263
+ };
264
+
265
+ module.exports = {
266
+ LogicalAddress,
267
+ DeviceType,
268
+ PowerStatus,
269
+ Opcode,
270
+ UserControlCode,
271
+ LogLevel,
272
+ DisplayControl,
273
+ Version,
274
+ AlertType
275
+ };