Commit | Line | Data |
---|---|---|
cbbe90dd JB |
1 | /* |
2 | * This file is part of the libCEC(R) library. | |
3 | * | |
4 | * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. | |
5 | * libCEC(R) is an original work, containing original code. | |
6 | * | |
7 | * libCEC(R) is a trademark of Pulse-Eight Limited. | |
8 | * | |
9 | * This program is dual-licensed; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
22 | * | |
23 | * | |
24 | * Alternatively, you can license this library under a commercial license, | |
25 | * please contact Pulse-Eight Licensing for more information. | |
26 | * | |
27 | * For more information contact: | |
28 | * Pulse-Eight Licensing <license@pulse-eight.com> | |
29 | * http://www.pulse-eight.com/ | |
30 | * http://www.pulse-eight.net/ | |
31 | */ | |
32 | ||
33 | #include "CecSharpTypes.h" | |
34 | #using <System.dll> | |
35 | ||
36 | using namespace System; | |
37 | using namespace System::Runtime::InteropServices; | |
38 | using namespace CEC; | |
39 | using namespace msclr::interop; | |
40 | ||
41 | namespace CecSharp | |
42 | { | |
43 | /// <summary> | |
44 | /// Create a LibCecSharp instance and pass the configuration as argument. | |
45 | /// Then call Open() to open a connection to the adapter. Close() closes the | |
46 | /// connection. | |
47 | /// | |
48 | /// libCEC can send commands to other devices on the CEC bus via the methods | |
49 | /// on this interface, and all commands that libCEC received are sent back | |
50 | /// to the application via callback methods. The callback methods can be | |
51 | /// found in CecSharpTypes.h, CecCallbackMethods. | |
52 | /// </summary> | |
53 | public ref class LibCecSharp : public CecCallbackMethods | |
54 | { | |
55 | public: | |
56 | /// <summary> | |
57 | /// Create a new LibCecSharp instance. | |
58 | /// </summary> | |
59 | /// <param name="config">The configuration to pass to libCEC.</param> | |
60 | LibCecSharp(LibCECConfiguration ^config) | |
61 | { | |
62 | m_callbacks = config->Callbacks; | |
63 | CecCallbackMethods::EnableCallbacks(m_callbacks); | |
64 | if (!InitialiseLibCec(config)) | |
65 | throw gcnew Exception("Could not initialise LibCecSharp"); | |
66 | } | |
67 | ||
68 | ~LibCecSharp(void) | |
69 | { | |
70 | Close(); | |
71 | m_libCec = NULL; | |
72 | } | |
73 | ||
74 | /// <summary> | |
75 | /// Try to find all connected CEC adapters. | |
76 | /// </summary> | |
77 | /// <param name="path">The path filter for adapters. Leave empty to return all adapters.</param> | |
78 | /// <returns>The adapters that were found.</returns> | |
79 | array<CecAdapter ^> ^ FindAdapters(String ^ path) | |
80 | { | |
81 | cec_adapter *devices = new cec_adapter[10]; | |
82 | ||
83 | marshal_context ^ context = gcnew marshal_context(); | |
84 | const char* strPathC = path->Length > 0 ? context->marshal_as<const char*>(path) : NULL; | |
85 | ||
86 | uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL); | |
87 | ||
88 | array<CecAdapter ^> ^ adapters = gcnew array<CecAdapter ^>(iDevicesFound); | |
89 | for (unsigned int iPtr = 0; iPtr < iDevicesFound; iPtr++) | |
90 | adapters[iPtr] = gcnew CecAdapter(gcnew String(devices[iPtr].path), gcnew String(devices[iPtr].comm)); | |
91 | ||
92 | delete devices; | |
93 | delete context; | |
94 | return adapters; | |
95 | } | |
96 | ||
97 | /// <summary> | |
98 | /// Open a connection to the CEC adapter. | |
99 | /// </summary> | |
100 | /// <param name="strPort">The COM port of the adapter</param> | |
101 | /// <param name="iTimeoutMs">Connection timeout in milliseconds</param> | |
102 | /// <returns>True when a connection was opened, false otherwise.</returns> | |
103 | bool Open(String ^ strPort, int iTimeoutMs) | |
104 | { | |
105 | CecCallbackMethods::EnableCallbacks(m_callbacks); | |
106 | EnableCallbacks(m_callbacks); | |
107 | marshal_context ^ context = gcnew marshal_context(); | |
108 | const char* strPortC = context->marshal_as<const char*>(strPort); | |
109 | bool bReturn = m_libCec->Open(strPortC, iTimeoutMs); | |
110 | delete context; | |
111 | return bReturn; | |
112 | } | |
113 | ||
114 | /// <summary> | |
115 | /// Close the connection to the CEC adapter | |
116 | /// </summary> | |
117 | void Close(void) | |
118 | { | |
119 | DisableCallbacks(); | |
120 | m_libCec->Close(); | |
121 | } | |
122 | ||
123 | /// <summary> | |
124 | /// Disable all calls to callback methods. | |
125 | /// </summary> | |
126 | virtual void DisableCallbacks(void) override | |
127 | { | |
128 | // delete the callbacks, since these might already have been destroyed in .NET | |
129 | CecCallbackMethods::DisableCallbacks(); | |
130 | if (m_libCec) | |
131 | m_libCec->EnableCallbacks(NULL, NULL); | |
132 | } | |
133 | ||
134 | /// <summary> | |
135 | /// Enable or change the callback methods that libCEC uses to send changes to the client application. | |
136 | /// </summary> | |
137 | /// <param name="callbacks">The new callback methods to use.</param> | |
138 | /// <returns>True when the callbacks were changed, false otherwise</returns> | |
139 | virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) override | |
140 | { | |
141 | if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks)) | |
142 | return m_libCec->EnableCallbacks((void*)GetCallbackPtr(), &g_cecCallbacks); | |
143 | ||
144 | return false; | |
145 | } | |
146 | ||
147 | /// <summary> | |
148 | /// Sends a ping command to the adapter, to check if it's responding. | |
149 | /// </summary> | |
150 | /// <returns>True when the ping was succesful, false otherwise</returns> | |
151 | bool PingAdapter(void) | |
152 | { | |
153 | return m_libCec->PingAdapter(); | |
154 | } | |
155 | ||
156 | /// <summary> | |
157 | /// Start the bootloader of the CEC adapter. Closes the connection when successful. | |
158 | /// </summary> | |
159 | /// <returns>True when the command was sent successfully, false otherwise.</returns> | |
160 | bool StartBootloader(void) | |
161 | { | |
162 | return m_libCec->StartBootloader(); | |
163 | } | |
164 | ||
165 | /// <summary> | |
166 | /// Transmit a raw CEC command over the CEC line. | |
167 | /// </summary> | |
168 | /// <param name="command">The command to transmit</param> | |
169 | /// <returns>True when the data was sent and acked, false otherwise.</returns> | |
170 | bool Transmit(CecCommand ^ command) | |
171 | { | |
172 | cec_command ccommand; | |
173 | cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode); | |
174 | ccommand.transmit_timeout = command->TransmitTimeout; | |
175 | ccommand.eom = command->Eom; | |
176 | ccommand.ack = command->Ack; | |
177 | for (unsigned int iPtr = 0; iPtr < command->Parameters->Size; iPtr++) | |
178 | ccommand.parameters.PushBack(command->Parameters->Data[iPtr]); | |
179 | ||
180 | return m_libCec->Transmit(ccommand); | |
181 | } | |
182 | ||
183 | /// <summary> | |
184 | /// Change the logical address on the CEC bus of the CEC adapter. libCEC automatically assigns a logical address, and this method is only available for debugging purposes. | |
185 | /// </summary> | |
186 | /// <param name="logicalAddress">The CEC adapter's new logical address.</param> | |
187 | /// <returns>True when the logical address was set successfully, false otherwise.</returns> | |
188 | bool SetLogicalAddress(CecLogicalAddress logicalAddress) | |
189 | { | |
190 | return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress); | |
191 | } | |
192 | ||
193 | /// <summary> | |
194 | /// Change the physical address (HDMI port) of the CEC adapter. libCEC will try to autodetect the physical address when connecting. If it did, it's set in libcec_configuration. | |
195 | /// </summary> | |
196 | /// <param name="physicalAddress">The CEC adapter's new physical address.</param> | |
197 | /// <returns>True when the physical address was set successfully, false otherwise.</returns> | |
198 | bool SetPhysicalAddress(uint16_t physicalAddress) | |
199 | { | |
200 | return m_libCec->SetPhysicalAddress(physicalAddress); | |
201 | } | |
202 | ||
203 | /// <summary> | |
204 | /// Power on the given CEC capable devices. If CECDEVICE_BROADCAST is used, then wakeDevice in libcec_configuration will be used. | |
205 | /// </summary> | |
206 | /// <param name="logicalAddress">The logical address to power on.</param> | |
207 | /// <returns>True when the command was sent succesfully, false otherwise.</returns> | |
208 | bool PowerOnDevices(CecLogicalAddress logicalAddress) | |
209 | { | |
210 | return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress); | |
211 | } | |
212 | ||
213 | /// <summary> | |
214 | /// Put the given CEC capable devices in standby mode. If CECDEVICE_BROADCAST is used, then standbyDevices in libcec_configuration will be used. | |
215 | /// </summary> | |
216 | /// <param name="logicalAddress">The logical address of the device to put in standby.</param> | |
217 | /// <returns>True when the command was sent succesfully, false otherwise.</returns> | |
218 | bool StandbyDevices(CecLogicalAddress logicalAddress) | |
219 | { | |
220 | return m_libCec->StandbyDevices((cec_logical_address) logicalAddress); | |
221 | } | |
222 | ||
223 | /// <summary> | |
224 | /// Sends a POLL message to a device, to check if it's present and responding. | |
225 | /// </summary> | |
226 | /// <param name="logicalAddress">The device to send the message to.</param> | |
227 | /// <returns>True if the POLL was acked, false otherwise.</returns> | |
228 | bool PollDevice(CecLogicalAddress logicalAddress) | |
229 | { | |
230 | return m_libCec->PollDevice((cec_logical_address) logicalAddress); | |
231 | } | |
232 | ||
233 | /// <summary> | |
234 | /// Change the active source to a device type handled by libCEC. Use CEC_DEVICE_TYPE_RESERVED to make the default type used by libCEC active. | |
235 | /// </summary> | |
236 | /// <param name="type">The new active source. Use CEC_DEVICE_TYPE_RESERVED to use the primary type</param> | |
237 | /// <returns>True when the command was sent succesfully, false otherwise.</returns> | |
238 | bool SetActiveSource(CecDeviceType type) | |
239 | { | |
240 | return m_libCec->SetActiveSource((cec_device_type) type); | |
241 | } | |
242 | ||
243 | /// <summary> | |
244 | /// Change the deck control mode, if this adapter is registered as playback or recording device. | |
245 | /// </summary> | |
246 | /// <param name="mode">The new control mode.</param> | |
247 | /// <param name="sendUpdate">True to send the new status over the CEC line.</param> | |
248 | /// <returns>True if set, false otherwise.</returns> | |
249 | bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate) | |
250 | { | |
251 | return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate); | |
252 | } | |
253 | ||
254 | /// <summary> | |
255 | /// Change the deck info, if this adapter is a playback or recording device. | |
256 | /// </summary> | |
257 | /// <param name="info">The new deck info.</param> | |
258 | /// <param name="sendUpdate">True to send the new status over the CEC line.</param> | |
259 | /// <returns>True if set, false otherwise.</returns> | |
260 | bool SetDeckInfo(CecDeckInfo info, bool sendUpdate) | |
261 | { | |
262 | return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate); | |
263 | } | |
264 | ||
265 | /// <summary> | |
266 | /// Broadcast a message that notifies connected CEC capable devices that this device is no longer the active source. | |
267 | /// </summary> | |
268 | /// <returns>True when the command was sent succesfully, false otherwise.</returns> | |
269 | bool SetInactiveView(void) | |
270 | { | |
271 | return m_libCec->SetInactiveView(); | |
272 | } | |
273 | ||
274 | /// <summary> | |
275 | /// Change the menu state. This value is already changed by libCEC automatically if a device is (de)activated. | |
276 | /// </summary> | |
277 | /// <param name="state">The new state.</param> | |
278 | /// <param name="sendUpdate">True to send the new status over the CEC line.</param> | |
279 | /// <returns>True if set, false otherwise.</returns> | |
280 | bool SetMenuState(CecMenuState state, bool sendUpdate) | |
281 | { | |
282 | return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate); | |
283 | } | |
284 | ||
285 | /// <summary> | |
286 | /// Display a message on the device with the given logical address. Not supported by most TVs. | |
287 | /// </summary> | |
288 | /// <param name="logicalAddress">The logical address of the device to display the message on.</param> | |
289 | /// <param name="duration">The duration of the message</param> | |
290 | /// <param name="message">The message to display.</param> | |
291 | /// <returns>True when the command was sent, false otherwise.</returns> | |
292 | bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message) | |
293 | { | |
294 | marshal_context ^ context = gcnew marshal_context(); | |
295 | const char* strMessageC = context->marshal_as<const char*>(message); | |
296 | ||
297 | bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC); | |
298 | ||
299 | delete context; | |
300 | return bReturn; | |
301 | } | |
302 | ||
303 | /// <summary> | |
304 | /// Enable or disable monitoring mode, for debugging purposes. If monitoring mode is enabled, libCEC won't respond to any command, but only log incoming data. | |
305 | /// </summary> | |
306 | /// <param name="enable">True to enable, false to disable.</param> | |
307 | /// <returns>True when switched successfully, false otherwise.</returns> | |
308 | bool SwitchMonitoring(bool enable) | |
309 | { | |
310 | return m_libCec->SwitchMonitoring(enable); | |
311 | } | |
312 | ||
313 | /// <summary> | |
314 | /// Get the CEC version of the device with the given logical address | |
315 | /// </summary> | |
316 | /// <param name="logicalAddress">The logical address of the device to get the CEC version for.</param> | |
317 | /// <returns>The version or CEC_VERSION_UNKNOWN when the version couldn't be fetched.</returns> | |
318 | CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress) | |
319 | { | |
320 | return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress); | |
321 | } | |
322 | ||
323 | /// <summary> | |
324 | /// Get the menu language of the device with the given logical address | |
325 | /// </summary> | |
326 | /// <param name="logicalAddress">The logical address of the device to get the menu language for.</param> | |
327 | /// <returns>The requested menu language.</returns> | |
328 | String ^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress) | |
329 | { | |
330 | cec_menu_language lang; | |
331 | if (m_libCec->GetDeviceMenuLanguage((cec_logical_address) logicalAddress, &lang)) | |
332 | { | |
333 | return gcnew String(lang.language); | |
334 | } | |
335 | ||
336 | return gcnew String(""); | |
337 | } | |
338 | ||
339 | /// <summary> | |
340 | /// Get the vendor ID of the device with the given logical address. | |
341 | /// </summary> | |
342 | /// <param name="logicalAddress">The logical address of the device to get the vendor ID for.</param> | |
343 | /// <returns>The vendor ID or 0 if it wasn't found.</returns> | |
344 | CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress) | |
345 | { | |
346 | return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress); | |
347 | } | |
348 | ||
349 | /// <summary> | |
350 | /// Get the power status of the device with the given logical address. | |
351 | /// </summary> | |
352 | /// <param name="logicalAddress">The logical address of the device to get the power status for.</param> | |
353 | /// <returns>The power status or CEC_POWER_STATUS_UNKNOWN if it wasn't found.</returns> | |
354 | CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress) | |
355 | { | |
356 | return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress); | |
357 | } | |
358 | ||
359 | /// <summary> | |
360 | /// Tell libCEC to poll for active devices on the bus. | |
361 | /// </summary> | |
362 | void RescanActiveDevices(void) | |
363 | { | |
364 | m_libCec->RescanActiveDevices(); | |
365 | } | |
366 | ||
367 | /// <summary> | |
368 | /// Get the logical addresses of the devices that are active on the bus, including those handled by libCEC. | |
369 | /// </summary> | |
370 | /// <returns>The logical addresses of the active devices</returns> | |
371 | CecLogicalAddresses ^ GetActiveDevices(void) | |
372 | { | |
373 | CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses(); | |
374 | unsigned int iDevices = 0; | |
375 | ||
376 | cec_logical_addresses activeDevices = m_libCec->GetActiveDevices(); | |
377 | ||
378 | for (uint8_t iPtr = 0; iPtr < 16; iPtr++) | |
379 | if (activeDevices[iPtr]) | |
380 | retVal->Set((CecLogicalAddress)iPtr); | |
381 | ||
382 | return retVal; | |
383 | } | |
384 | ||
385 | /// <summary> | |
386 | /// Check whether a device is active on the bus. | |
387 | /// </summary> | |
388 | /// <param name="logicalAddress">The address to check.</param> | |
389 | /// <returns>True when active, false otherwise.</returns> | |
390 | bool IsActiveDevice(CecLogicalAddress logicalAddress) | |
391 | { | |
392 | return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress); | |
393 | } | |
394 | ||
395 | /// <summary> | |
396 | /// Check whether a device of the given type is active on the bus. | |
397 | /// </summary> | |
398 | /// <param name="type">The type to check.</param> | |
399 | /// <returns>True when active, false otherwise.</returns> | |
400 | bool IsActiveDeviceType(CecDeviceType type) | |
401 | { | |
402 | return m_libCec->IsActiveDeviceType((cec_device_type)type); | |
403 | } | |
404 | ||
405 | /// <summary> | |
406 | /// Changes the active HDMI port. | |
407 | /// </summary> | |
408 | /// <param name="address">The device to which this libCEC is connected.</param> | |
409 | /// <param name="port">The new port number.</param> | |
410 | /// <returns>True when changed, false otherwise.</returns> | |
411 | bool SetHDMIPort(CecLogicalAddress address, uint8_t port) | |
412 | { | |
413 | return m_libCec->SetHDMIPort((cec_logical_address)address, port); | |
414 | } | |
415 | ||
416 | /// <summary> | |
417 | /// Sends a volume up keypress to an audiosystem if it's present. | |
418 | /// </summary> | |
419 | /// <param name="sendRelease">Send a key release after the keypress.</param> | |
420 | /// <returns>The new audio status.</returns> | |
421 | uint8_t VolumeUp(bool sendRelease) | |
422 | { | |
423 | return m_libCec->VolumeUp(sendRelease); | |
424 | } | |
425 | ||
426 | /// <summary> | |
427 | /// Sends a volume down keypress to an audiosystem if it's present. | |
428 | /// </summary> | |
429 | /// <param name="sendRelease">Send a key release after the keypress.</param> | |
430 | /// <returns>The new audio status.</returns> | |
431 | uint8_t VolumeDown(bool sendRelease) | |
432 | { | |
433 | return m_libCec->VolumeDown(sendRelease); | |
434 | } | |
435 | ||
436 | /// <summary> | |
437 | /// Sends a mute keypress to an audiosystem if it's present. | |
438 | /// </summary> | |
439 | /// <param name="sendRelease">Send a key release after the keypress.</param> | |
440 | /// <returns>The new audio status.</returns> | |
441 | uint8_t MuteAudio(bool sendRelease) | |
442 | { | |
443 | return m_libCec->MuteAudio(sendRelease); | |
444 | } | |
445 | ||
446 | /// <summary> | |
447 | /// Send a keypress to a device on the CEC bus. | |
448 | /// </summary> | |
449 | /// <param name="destination">The logical address of the device to send the message to.</param> | |
450 | /// <param name="key">The key to send.</param> | |
451 | /// <param name="wait">True to wait for a response, false otherwise.</param> | |
452 | /// <returns>True when the keypress was acked, false otherwise.</returns> | |
453 | bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait) | |
454 | { | |
455 | return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait); | |
456 | } | |
457 | ||
458 | /// <summary> | |
459 | /// Send a key release to a device on the CEC bus. | |
460 | /// </summary> | |
461 | /// <param name="destination">The logical address of the device to send the message to.</param> | |
462 | /// <param name="wait">True to wait for a response, false otherwise.</param> | |
463 | /// <returns>True when the key release was acked, false otherwise.</returns> | |
464 | bool SendKeyRelease(CecLogicalAddress destination, bool wait) | |
465 | { | |
466 | return m_libCec->SendKeyRelease((cec_logical_address)destination, wait); | |
467 | } | |
468 | ||
469 | /// <summary> | |
470 | /// Get the OSD name of a device on the CEC bus. | |
471 | /// </summary> | |
472 | /// <param name="logicalAddress">The logical address of the device to get the OSD name for.</param> | |
473 | /// <returns>The OSD name.</returns> | |
474 | String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress) | |
475 | { | |
476 | cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress); | |
477 | // we need to terminate with \0, and we only got 14 chars in osd.name | |
478 | char strOsdName[15]; | |
479 | memset(strOsdName, 0, sizeof(strOsdName)); | |
480 | memcpy(strOsdName, osd.name, sizeof(osd.name)); | |
481 | return gcnew String(strOsdName); | |
482 | } | |
483 | ||
484 | /// <summary> | |
485 | /// Get the logical address of the device that is currently the active source on the CEC bus. | |
486 | /// </summary> | |
487 | /// <returns>The active source or CECDEVICE_UNKNOWN when unknown.</returns> | |
488 | CecLogicalAddress GetActiveSource() | |
489 | { | |
490 | return (CecLogicalAddress)m_libCec->GetActiveSource(); | |
491 | } | |
492 | ||
493 | /// <summary> | |
494 | /// Check whether a device is currently the active source on the CEC bus. | |
495 | /// </summary> | |
496 | /// <param name="logicalAddress">The logical address of the device to check.</param> | |
497 | /// <returns>True when it is the active source, false otherwise.</returns> | |
498 | bool IsActiveSource(CecLogicalAddress logicalAddress) | |
499 | { | |
500 | return m_libCec->IsActiveSource((cec_logical_address)logicalAddress); | |
501 | } | |
502 | ||
503 | /// <summary> | |
504 | /// Get the physical address of the device with the given logical address. | |
505 | /// </summary> | |
506 | /// <param name="address">The logical address of the device to get the physical address for.</param> | |
507 | /// <returns>The physical address or 0 if it wasn't found.</returns> | |
508 | uint16_t GetDevicePhysicalAddress(CecLogicalAddress address) | |
509 | { | |
510 | return m_libCec->GetDevicePhysicalAddress((cec_logical_address)address); | |
511 | } | |
512 | ||
513 | /// <summary> | |
514 | /// Sets the stream path to the device on the given logical address. | |
515 | /// </summary> | |
516 | /// <param name="address">The address to activate.</param> | |
517 | /// <returns>True when the command was sent, false otherwise.</returns> | |
518 | bool SetStreamPath(CecLogicalAddress address) | |
519 | { | |
520 | return m_libCec->SetStreamPath((cec_logical_address)address); | |
521 | } | |
522 | ||
523 | /// <summary> | |
524 | /// Sets the stream path to the device on the given physical address. | |
525 | /// </summary> | |
526 | /// <param name="physicalAddress">The address to activate.</param> | |
527 | /// <returns>True when the command was sent, false otherwise.</returns> | |
528 | bool SetStreamPath(uint16_t physicalAddress) | |
529 | { | |
530 | return m_libCec->SetStreamPath(physicalAddress); | |
531 | } | |
532 | ||
533 | /// <summary> | |
534 | /// Get the list of logical addresses that libCEC is controlling | |
535 | /// </summary> | |
536 | /// <returns>The list of logical addresses that libCEC is controlling</returns> | |
537 | CecLogicalAddresses ^GetLogicalAddresses(void) | |
538 | { | |
539 | CecLogicalAddresses ^addr = gcnew CecLogicalAddresses(); | |
540 | cec_logical_addresses libAddr = m_libCec->GetLogicalAddresses(); | |
541 | for (unsigned int iPtr = 0; iPtr < 16; iPtr++) | |
542 | addr->Addresses[iPtr] = (CecLogicalAddress)libAddr.addresses[iPtr]; | |
543 | addr->Primary = (CecLogicalAddress)libAddr.primary; | |
544 | return addr; | |
545 | } | |
546 | ||
547 | /// <summary> | |
548 | /// Get libCEC's current configuration. | |
549 | /// </summary> | |
550 | /// <param name="configuration">The configuration.</param> | |
551 | /// <returns>True when the configuration was updated, false otherwise.</returns> | |
552 | bool GetCurrentConfiguration(LibCECConfiguration ^configuration) | |
553 | { | |
554 | libcec_configuration config; | |
555 | config.Clear(); | |
556 | ||
557 | if (m_libCec->GetCurrentConfiguration(&config)) | |
558 | { | |
559 | configuration->Update(config); | |
560 | return true; | |
561 | } | |
562 | return false; | |
563 | } | |
564 | ||
565 | /// <summary> | |
566 | /// Check whether the CEC adapter can persist a configuration. | |
567 | /// </summary> | |
568 | /// <returns>True when this CEC adapter can persist the user configuration, false otherwise.</returns> | |
569 | bool CanPersistConfiguration(void) | |
570 | { | |
571 | return m_libCec->CanPersistConfiguration(); | |
572 | } | |
573 | ||
574 | /// <summary> | |
575 | /// Persist the given configuration in adapter (if supported) | |
576 | /// </summary> | |
577 | /// <param name="configuration">The configuration to store.</param> | |
578 | /// <returns>True when the configuration was persisted, false otherwise.</returns> | |
579 | bool PersistConfiguration(LibCECConfiguration ^configuration) | |
580 | { | |
581 | marshal_context ^ context = gcnew marshal_context(); | |
582 | libcec_configuration config; | |
583 | ConvertConfiguration(context, configuration, config); | |
584 | ||
585 | bool bReturn = m_libCec->PersistConfiguration(&config); | |
586 | ||
587 | delete context; | |
588 | return bReturn; | |
589 | } | |
590 | ||
591 | /// <summary> | |
592 | /// Change libCEC's configuration. | |
593 | /// </summary> | |
594 | /// <param name="configuration">The new configuration.</param> | |
595 | /// <returns>True when the configuration was changed successfully, false otherwise.</returns> | |
596 | bool SetConfiguration(LibCECConfiguration ^configuration) | |
597 | { | |
598 | marshal_context ^ context = gcnew marshal_context(); | |
599 | libcec_configuration config; | |
600 | ConvertConfiguration(context, configuration, config); | |
601 | ||
602 | bool bReturn = m_libCec->SetConfiguration(&config); | |
603 | ||
604 | delete context; | |
605 | return bReturn; | |
606 | } | |
607 | ||
608 | /// <summary> | |
609 | /// Check whether libCEC is the active source on the bus. | |
610 | /// </summary> | |
611 | /// <returns>True when libCEC is the active source on the bus, false otherwise.</returns> | |
612 | bool IsLibCECActiveSource() | |
613 | { | |
614 | return m_libCec->IsLibCECActiveSource(); | |
615 | } | |
616 | ||
617 | /// <summary> | |
618 | /// Get information about the given CEC adapter. | |
619 | /// </summary> | |
620 | /// <param name="port">The COM port to which the device is connected</param> | |
621 | /// <param name="configuration">The device configuration</param> | |
622 | /// <param name="timeoutMs">The timeout in milliseconds</param> | |
623 | /// <returns>True when the device was found, false otherwise</returns> | |
624 | bool GetDeviceInformation(String ^ port, LibCECConfiguration ^configuration, uint32_t timeoutMs) | |
625 | { | |
626 | bool bReturn(false); | |
627 | marshal_context ^ context = gcnew marshal_context(); | |
628 | ||
629 | libcec_configuration config; | |
630 | config.Clear(); | |
631 | ||
632 | const char* strPortC = port->Length > 0 ? context->marshal_as<const char*>(port) : NULL; | |
633 | ||
634 | if (m_libCec->GetDeviceInformation(strPortC, &config, timeoutMs)) | |
635 | { | |
636 | configuration->Update(config); | |
637 | bReturn = true; | |
638 | } | |
639 | ||
640 | delete context; | |
641 | return bReturn; | |
642 | } | |
643 | ||
644 | String ^ ToString(CecLogicalAddress iAddress) | |
645 | { | |
646 | const char *retVal = m_libCec->ToString((cec_logical_address)iAddress); | |
647 | return gcnew String(retVal); | |
648 | } | |
649 | ||
650 | String ^ ToString(CecVendorId iVendorId) | |
651 | { | |
652 | const char *retVal = m_libCec->ToString((cec_vendor_id)iVendorId); | |
653 | return gcnew String(retVal); | |
654 | } | |
655 | ||
656 | String ^ ToString(CecVersion iVersion) | |
657 | { | |
658 | const char *retVal = m_libCec->ToString((cec_version)iVersion); | |
659 | return gcnew String(retVal); | |
660 | } | |
661 | ||
662 | String ^ ToString(CecPowerStatus iState) | |
663 | { | |
664 | const char *retVal = m_libCec->ToString((cec_power_status)iState); | |
665 | return gcnew String(retVal); | |
666 | } | |
667 | ||
668 | String ^ ToString(CecMenuState iState) | |
669 | { | |
670 | const char *retVal = m_libCec->ToString((cec_menu_state)iState); | |
671 | return gcnew String(retVal); | |
672 | } | |
673 | ||
674 | String ^ ToString(CecDeckControlMode iMode) | |
675 | { | |
676 | const char *retVal = m_libCec->ToString((cec_deck_control_mode)iMode); | |
677 | return gcnew String(retVal); | |
678 | } | |
679 | ||
680 | String ^ ToString(CecDeckInfo status) | |
681 | { | |
682 | const char *retVal = m_libCec->ToString((cec_deck_info)status); | |
683 | return gcnew String(retVal); | |
684 | } | |
685 | ||
686 | String ^ ToString(CecOpcode opcode) | |
687 | { | |
688 | const char *retVal = m_libCec->ToString((cec_opcode)opcode); | |
689 | return gcnew String(retVal); | |
690 | } | |
691 | ||
692 | String ^ ToString(CecSystemAudioStatus mode) | |
693 | { | |
694 | const char *retVal = m_libCec->ToString((cec_system_audio_status)mode); | |
695 | return gcnew String(retVal); | |
696 | } | |
697 | ||
698 | String ^ ToString(CecAudioStatus status) | |
699 | { | |
700 | const char *retVal = m_libCec->ToString((cec_audio_status)status); | |
701 | return gcnew String(retVal); | |
702 | } | |
703 | ||
704 | String ^ ToString(CecClientVersion version) | |
705 | { | |
706 | const char *retVal = m_libCec->ToString((cec_client_version)version); | |
707 | return gcnew String(retVal); | |
708 | } | |
709 | ||
710 | String ^ ToString(CecServerVersion version) | |
711 | { | |
712 | const char *retVal = m_libCec->ToString((cec_server_version)version); | |
713 | return gcnew String(retVal); | |
714 | } | |
715 | ||
716 | /// <summary> | |
717 | /// Get a string with information about how libCEC was compiled. | |
718 | /// </summary> | |
719 | /// <returns>A string with information about how libCEC was compiled.</returns> | |
720 | String ^ GetLibInfo() | |
721 | { | |
722 | const char *retVal = m_libCec->GetLibInfo(); | |
723 | return gcnew String(retVal); | |
724 | } | |
725 | ||
726 | /// <summary> | |
727 | /// Calling this method will initialise the host on which libCEC is running. | |
728 | /// On the RPi, it calls bcm_host_init(), which may only be called once per process, and is called by any process using | |
729 | /// the video api on that system. So only call this method if libCEC is used in an application that | |
730 | /// does not already initialise the video api. | |
731 | /// </summary> | |
732 | /// <remarks>Should be called as first call to libCEC, directly after CECInitialise() and before using Open()</remarks> | |
733 | void InitVideoStandalone() | |
734 | { | |
735 | m_libCec->InitVideoStandalone(); | |
736 | } | |
737 | ||
738 | /// <summary> | |
739 | /// Get the (virtual) USB vendor id | |
740 | /// </summary> | |
741 | /// <returns>The (virtual) USB vendor id</returns> | |
742 | uint16_t GetAdapterVendorId() | |
743 | { | |
744 | return m_libCec->GetAdapterVendorId(); | |
745 | } | |
746 | ||
747 | /// <summary> | |
748 | /// Get the (virtual) USB product id | |
749 | /// </summary> | |
750 | /// <returns>The (virtual) USB product id</returns> | |
751 | uint16_t GetAdapterProductId() | |
752 | { | |
753 | return m_libCec->GetAdapterProductId(); | |
754 | } | |
755 | ||
756 | private: | |
757 | !LibCecSharp(void) | |
758 | { | |
759 | Close(); | |
760 | m_libCec = NULL; | |
761 | } | |
762 | ||
763 | bool InitialiseLibCec(LibCECConfiguration ^config) | |
764 | { | |
765 | marshal_context ^ context = gcnew marshal_context(); | |
766 | libcec_configuration libCecConfig; | |
767 | ConvertConfiguration(context, config, libCecConfig); | |
768 | ||
769 | m_libCec = (ICECAdapter *) CECInitialise(&libCecConfig); | |
770 | config->Update(libCecConfig); | |
771 | ||
772 | delete context; | |
773 | return m_libCec != NULL; | |
774 | } | |
775 | ||
776 | void ConvertConfiguration(marshal_context ^context, LibCECConfiguration ^netConfig, CEC::libcec_configuration &config) | |
777 | { | |
778 | config.Clear(); | |
779 | ||
780 | const char *strDeviceName = context->marshal_as<const char*>(netConfig->DeviceName); | |
781 | memcpy_s(config.strDeviceName, 13, strDeviceName, 13); | |
782 | for (unsigned int iPtr = 0; iPtr < 5; iPtr++) | |
783 | config.deviceTypes.types[iPtr] = (cec_device_type)netConfig->DeviceTypes->Types[iPtr]; | |
784 | ||
785 | config.bAutodetectAddress = netConfig->AutodetectAddress ? 1 : 0; | |
786 | config.iPhysicalAddress = netConfig->PhysicalAddress; | |
787 | config.baseDevice = (cec_logical_address)netConfig->BaseDevice; | |
788 | config.iHDMIPort = netConfig->HDMIPort; | |
789 | config.clientVersion = (cec_client_version)netConfig->ClientVersion; | |
790 | config.bGetSettingsFromROM = netConfig->GetSettingsFromROM ? 1 : 0; | |
791 | config.bActivateSource = netConfig->ActivateSource ? 1 : 0; | |
792 | config.tvVendor = (cec_vendor_id)netConfig->TvVendor; | |
793 | config.wakeDevices.Clear(); | |
794 | for (int iPtr = 0; iPtr < 16; iPtr++) | |
795 | { | |
796 | if (netConfig->WakeDevices->IsSet((CecLogicalAddress)iPtr)) | |
797 | config.wakeDevices.Set((cec_logical_address)iPtr); | |
798 | } | |
799 | config.powerOffDevices.Clear(); | |
800 | for (int iPtr = 0; iPtr < 16; iPtr++) | |
801 | { | |
802 | if (netConfig->PowerOffDevices->IsSet((CecLogicalAddress)iPtr)) | |
803 | config.powerOffDevices.Set((cec_logical_address)iPtr); | |
804 | } | |
805 | config.bPowerOffScreensaver = netConfig->PowerOffScreensaver ? 1 : 0; | |
806 | config.bPowerOffOnStandby = netConfig->PowerOffOnStandby ? 1 : 0; | |
807 | ||
808 | if (netConfig->ServerVersion >= CecServerVersion::Version1_5_1) | |
809 | config.bSendInactiveSource = netConfig->SendInactiveSource ? 1 : 0; | |
810 | ||
811 | if (netConfig->ServerVersion >= CecServerVersion::Version1_6_0) | |
812 | { | |
813 | config.bPowerOffDevicesOnStandby = netConfig->PowerOffDevicesOnStandby ? 1 : 0; | |
814 | config.bShutdownOnStandby = netConfig->ShutdownOnStandby ? 1 : 0; | |
815 | } | |
816 | ||
817 | if (netConfig->ServerVersion >= CecServerVersion::Version1_6_2) | |
818 | { | |
819 | const char *strDeviceLanguage = context->marshal_as<const char*>(netConfig->DeviceLanguage); | |
820 | memcpy_s(config.strDeviceLanguage, 3, strDeviceLanguage, 3); | |
821 | } | |
822 | ||
823 | if (netConfig->ServerVersion >= CecServerVersion::Version1_6_3) | |
824 | config.bMonitorOnly = netConfig->MonitorOnlyClient ? 1 : 0; | |
825 | ||
826 | if (netConfig->ServerVersion >= CecServerVersion::Version1_8_0) | |
827 | config.cecVersion = (cec_version)netConfig->CECVersion; | |
828 | ||
829 | if (netConfig->ServerVersion >= CecServerVersion::Version2_1_0) | |
830 | config.bPowerOnScreensaver = netConfig->PowerOnScreensaver ? 1 : 0; | |
831 | ||
832 | config.callbacks = &g_cecCallbacks; | |
833 | } | |
834 | ||
835 | ||
836 | ICECAdapter * m_libCec; | |
837 | CecCallbackMethods ^ m_callbacks; | |
838 | }; | |
839 | } |