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