Commit | Line | Data |
---|---|---|
61f3c2ad | 1 | /* |
f9717bcc LOK |
2 | * This file is part of the libCEC(R) library. |
3 | * | |
16f47961 | 4 | * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited. All rights reserved. |
f9717bcc LOK |
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 | */ | |
61f3c2ad | 32 | |
4ef3b314 | 33 | #include "CecSharpTypes.h" |
61f3c2ad LOK |
34 | #using <System.dll> |
35 | ||
36 | using namespace System; | |
0cac9547 | 37 | using namespace System::Runtime::InteropServices; |
61f3c2ad LOK |
38 | using namespace CEC; |
39 | using namespace msclr::interop; | |
40 | ||
4ef3b314 | 41 | namespace CecSharp |
61f3c2ad | 42 | { |
f9717bcc LOK |
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 | { | |
11fea069 | 62 | m_callbacks = config->Callbacks; |
f9717bcc LOK |
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> | |
e3aabeac LOK |
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> | |
f9717bcc LOK |
79 | array<CecAdapter ^> ^ FindAdapters(String ^ path) |
80 | { | |
81 | cec_adapter *devices = new cec_adapter[10]; | |
4ef3b314 | 82 | |
f9717bcc LOK |
83 | marshal_context ^ context = gcnew marshal_context(); |
84 | const char* strPathC = path->Length > 0 ? context->marshal_as<const char*>(path) : NULL; | |
4ef3b314 | 85 | |
f9717bcc | 86 | uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL); |
4ef3b314 | 87 | |
f9717bcc LOK |
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)); | |
4ef3b314 | 91 | |
f9717bcc LOK |
92 | delete devices; |
93 | delete context; | |
94 | return adapters; | |
95 | } | |
4ef3b314 | 96 | |
e3aabeac LOK |
97 | /// <summary> |
98 | /// Open a connection to the CEC adapter. | |
99 | /// </summary> | |
f9717bcc LOK |
100 | /// <param name="strPort">The COM port of the adapter</param> |
101 | /// <param name="iTimeoutMs">Connection timeout in milliseconds</param> | |
e3aabeac | 102 | /// <returns>True when a connection was opened, false otherwise.</returns> |
f9717bcc LOK |
103 | bool Open(String ^ strPort, int iTimeoutMs) |
104 | { | |
11fea069 LOK |
105 | CecCallbackMethods::EnableCallbacks(m_callbacks); |
106 | EnableCallbacks(m_callbacks); | |
f9717bcc LOK |
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> | |
e3aabeac LOK |
115 | /// Close the connection to the CEC adapter |
116 | /// </summary> | |
f9717bcc LOK |
117 | void Close(void) |
118 | { | |
119 | DisableCallbacks(); | |
120 | m_libCec->Close(); | |
121 | } | |
8670c970 | 122 | |
f9717bcc | 123 | /// <summary> |
e3aabeac LOK |
124 | /// Disable all calls to callback methods. |
125 | /// </summary> | |
f9717bcc LOK |
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 | } | |
4ef3b314 | 133 | |
f9717bcc | 134 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
139 | virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) override |
140 | { | |
141 | if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks)) | |
142 | return m_libCec->EnableCallbacks((void*)GetCallbackPtr(), &g_cecCallbacks); | |
4ef3b314 | 143 | |
f9717bcc LOK |
144 | return false; |
145 | } | |
4ef3b314 | 146 | |
f9717bcc | 147 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
151 | bool PingAdapter(void) |
152 | { | |
153 | return m_libCec->PingAdapter(); | |
154 | } | |
4ef3b314 | 155 | |
f9717bcc | 156 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
160 | bool StartBootloader(void) |
161 | { | |
162 | return m_libCec->StartBootloader(); | |
163 | } | |
164 | ||
165 | /// <summary> | |
e3aabeac LOK |
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> | |
f9717bcc LOK |
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> | |
e3aabeac LOK |
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> | |
f9717bcc LOK |
188 | bool SetLogicalAddress(CecLogicalAddress logicalAddress) |
189 | { | |
190 | return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress); | |
191 | } | |
4ef3b314 | 192 | |
f9717bcc | 193 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
198 | bool SetPhysicalAddress(uint16_t physicalAddress) |
199 | { | |
200 | return m_libCec->SetPhysicalAddress(physicalAddress); | |
201 | } | |
4ef3b314 | 202 | |
f9717bcc | 203 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
208 | bool PowerOnDevices(CecLogicalAddress logicalAddress) |
209 | { | |
210 | return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress); | |
211 | } | |
4ef3b314 | 212 | |
f9717bcc | 213 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
218 | bool StandbyDevices(CecLogicalAddress logicalAddress) |
219 | { | |
220 | return m_libCec->StandbyDevices((cec_logical_address) logicalAddress); | |
221 | } | |
4ef3b314 | 222 | |
f9717bcc | 223 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
228 | bool PollDevice(CecLogicalAddress logicalAddress) |
229 | { | |
230 | return m_libCec->PollDevice((cec_logical_address) logicalAddress); | |
231 | } | |
4ef3b314 | 232 | |
f9717bcc | 233 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
238 | bool SetActiveSource(CecDeviceType type) |
239 | { | |
240 | return m_libCec->SetActiveSource((cec_device_type) type); | |
241 | } | |
4ef3b314 | 242 | |
f9717bcc | 243 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc | 247 | /// <param name="sendUpdate">True to send the new status over the CEC line.</param> |
e3aabeac | 248 | /// <returns>True if set, false otherwise.</returns> |
f9717bcc LOK |
249 | bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate) |
250 | { | |
251 | return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate); | |
252 | } | |
4ef3b314 | 253 | |
f9717bcc | 254 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc | 258 | /// <param name="sendUpdate">True to send the new status over the CEC line.</param> |
e3aabeac | 259 | /// <returns>True if set, false otherwise.</returns> |
f9717bcc LOK |
260 | bool SetDeckInfo(CecDeckInfo info, bool sendUpdate) |
261 | { | |
262 | return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate); | |
263 | } | |
4ef3b314 | 264 | |
f9717bcc | 265 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
269 | bool SetInactiveView(void) |
270 | { | |
271 | return m_libCec->SetInactiveView(); | |
272 | } | |
4ef3b314 | 273 | |
f9717bcc | 274 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc | 278 | /// <param name="sendUpdate">True to send the new status over the CEC line.</param> |
e3aabeac | 279 | /// <returns>True if set, false otherwise.</returns> |
f9717bcc LOK |
280 | bool SetMenuState(CecMenuState state, bool sendUpdate) |
281 | { | |
282 | return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate); | |
283 | } | |
4ef3b314 | 284 | |
f9717bcc | 285 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
289 | /// <param name="duration">The duration of the message</param> |
290 | /// <param name="message">The message to display.</param> | |
e3aabeac | 291 | /// <returns>True when the command was sent, false otherwise.</returns> |
f9717bcc LOK |
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); | |
4ef3b314 | 296 | |
f9717bcc | 297 | bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC); |
4ef3b314 | 298 | |
f9717bcc LOK |
299 | delete context; |
300 | return bReturn; | |
301 | } | |
4ef3b314 | 302 | |
f9717bcc | 303 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
308 | bool SwitchMonitoring(bool enable) |
309 | { | |
310 | return m_libCec->SwitchMonitoring(enable); | |
311 | } | |
4ef3b314 | 312 | |
f9717bcc | 313 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
318 | CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress) |
319 | { | |
320 | return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress); | |
321 | } | |
4ef3b314 | 322 | |
f9717bcc | 323 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
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> | |
e3aabeac LOK |
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> | |
f9717bcc LOK |
344 | CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress) |
345 | { | |
346 | return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress); | |
347 | } | |
4ef3b314 | 348 | |
f9717bcc | 349 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
354 | CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress) |
355 | { | |
356 | return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress); | |
357 | } | |
4ef3b314 | 358 | |
f9717bcc | 359 | /// <summary> |
e3aabeac LOK |
360 | /// Tell libCEC to poll for active devices on the bus. |
361 | /// </summary> | |
f9717bcc LOK |
362 | void RescanActiveDevices(void) |
363 | { | |
364 | m_libCec->RescanActiveDevices(); | |
365 | } | |
3efda01a | 366 | |
f9717bcc | 367 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
371 | CecLogicalAddresses ^ GetActiveDevices(void) |
372 | { | |
373 | CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses(); | |
374 | unsigned int iDevices = 0; | |
4ef3b314 | 375 | |
f9717bcc | 376 | cec_logical_addresses activeDevices = m_libCec->GetActiveDevices(); |
4ef3b314 | 377 | |
f9717bcc LOK |
378 | for (uint8_t iPtr = 0; iPtr < 16; iPtr++) |
379 | if (activeDevices[iPtr]) | |
f053b05d | 380 | retVal->Set((CecLogicalAddress)iPtr); |
4ef3b314 | 381 | |
f9717bcc LOK |
382 | return retVal; |
383 | } | |
4ef3b314 | 384 | |
f9717bcc | 385 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
390 | bool IsActiveDevice(CecLogicalAddress logicalAddress) |
391 | { | |
392 | return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress); | |
393 | } | |
4ef3b314 | 394 | |
f9717bcc | 395 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
400 | bool IsActiveDeviceType(CecDeviceType type) |
401 | { | |
402 | return m_libCec->IsActiveDeviceType((cec_device_type)type); | |
403 | } | |
4ef3b314 | 404 | |
f9717bcc | 405 | /// <summary> |
e3aabeac LOK |
406 | /// Changes the active HDMI port. |
407 | /// </summary> | |
408 | /// <param name="address">The device to which this libCEC is connected.</param> | |
f9717bcc | 409 | /// <param name="port">The new port number.</param> |
e3aabeac | 410 | /// <returns>True when changed, false otherwise.</returns> |
f9717bcc LOK |
411 | bool SetHDMIPort(CecLogicalAddress address, uint8_t port) |
412 | { | |
413 | return m_libCec->SetHDMIPort((cec_logical_address)address, port); | |
414 | } | |
4ef3b314 | 415 | |
f9717bcc | 416 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
421 | uint8_t VolumeUp(bool sendRelease) |
422 | { | |
423 | return m_libCec->VolumeUp(sendRelease); | |
424 | } | |
4ef3b314 | 425 | |
f9717bcc | 426 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
431 | uint8_t VolumeDown(bool sendRelease) |
432 | { | |
433 | return m_libCec->VolumeDown(sendRelease); | |
434 | } | |
4ef3b314 | 435 | |
f9717bcc | 436 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
441 | uint8_t MuteAudio(bool sendRelease) |
442 | { | |
443 | return m_libCec->MuteAudio(sendRelease); | |
444 | } | |
4ef3b314 | 445 | |
f9717bcc | 446 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
450 | /// <param name="key">The key to send.</param> |
451 | /// <param name="wait">True to wait for a response, false otherwise.</param> | |
e3aabeac | 452 | /// <returns>True when the keypress was acked, false otherwise.</returns> |
f9717bcc LOK |
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 | } | |
4ef3b314 | 457 | |
f9717bcc | 458 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc | 462 | /// <param name="wait">True to wait for a response, false otherwise.</param> |
e3aabeac | 463 | /// <returns>True when the key release was acked, false otherwise.</returns> |
f9717bcc LOK |
464 | bool SendKeyRelease(CecLogicalAddress destination, bool wait) |
465 | { | |
466 | return m_libCec->SendKeyRelease((cec_logical_address)destination, wait); | |
467 | } | |
4ef3b314 | 468 | |
f9717bcc | 469 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
474 | String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress) |
475 | { | |
476 | cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress); | |
cf845048 LOK |
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); | |
f9717bcc | 482 | } |
4ef3b314 | 483 | |
f9717bcc | 484 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
488 | CecLogicalAddress GetActiveSource() |
489 | { | |
490 | return (CecLogicalAddress)m_libCec->GetActiveSource(); | |
491 | } | |
4ef3b314 | 492 | |
f9717bcc | 493 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
498 | bool IsActiveSource(CecLogicalAddress logicalAddress) |
499 | { | |
500 | return m_libCec->IsActiveSource((cec_logical_address)logicalAddress); | |
501 | } | |
4ef3b314 | 502 | |
f9717bcc | 503 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
508 | uint16_t GetDevicePhysicalAddress(CecLogicalAddress address) |
509 | { | |
510 | return m_libCec->GetDevicePhysicalAddress((cec_logical_address)address); | |
511 | } | |
4ef3b314 | 512 | |
f9717bcc | 513 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
518 | bool SetStreamPath(CecLogicalAddress address) |
519 | { | |
520 | return m_libCec->SetStreamPath((cec_logical_address)address); | |
521 | } | |
a9fb46b4 | 522 | |
f9717bcc | 523 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
528 | bool SetStreamPath(uint16_t physicalAddress) |
529 | { | |
530 | return m_libCec->SetStreamPath(physicalAddress); | |
531 | } | |
a9fb46b4 | 532 | |
f9717bcc | 533 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
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> | |
e3aabeac LOK |
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> | |
f9717bcc LOK |
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> | |
e3aabeac LOK |
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> | |
5085a852 | 569 | bool CanPersistConfiguration(void) |
f9717bcc LOK |
570 | { |
571 | return m_libCec->CanPersistConfiguration(); | |
572 | } | |
5085a852 | 573 | |
f9717bcc | 574 | /// <summary> |
e3aabeac LOK |
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> | |
5085a852 | 579 | bool PersistConfiguration(LibCECConfiguration ^configuration) |
f9717bcc LOK |
580 | { |
581 | marshal_context ^ context = gcnew marshal_context(); | |
582 | libcec_configuration config; | |
583 | ConvertConfiguration(context, configuration, config); | |
5085a852 | 584 | |
f9717bcc | 585 | bool bReturn = m_libCec->PersistConfiguration(&config); |
5085a852 | 586 | |
f9717bcc LOK |
587 | delete context; |
588 | return bReturn; | |
589 | } | |
5085a852 | 590 | |
f9717bcc | 591 | /// <summary> |
e3aabeac LOK |
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> | |
f9717bcc LOK |
596 | bool SetConfiguration(LibCECConfiguration ^configuration) |
597 | { | |
598 | marshal_context ^ context = gcnew marshal_context(); | |
599 | libcec_configuration config; | |
600 | ConvertConfiguration(context, configuration, config); | |
32403cc3 | 601 | |
f9717bcc | 602 | bool bReturn = m_libCec->SetConfiguration(&config); |
32403cc3 | 603 | |
f9717bcc LOK |
604 | delete context; |
605 | return bReturn; | |
606 | } | |
32403cc3 | 607 | |
f9717bcc | 608 | /// <summary> |
e3aabeac LOK |
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> | |
bd624ba8 LOK |
612 | bool IsLibCECActiveSource() |
613 | { | |
614 | return m_libCec->IsLibCECActiveSource(); | |
615 | } | |
616 | ||
f9717bcc | 617 | /// <summary> |
e3aabeac LOK |
618 | /// Get information about the given CEC adapter. |
619 | /// </summary> | |
620 | /// <param name="port">The COM port to which the device is connected</param> | |
f9717bcc LOK |
621 | /// <param name="configuration">The device configuration</param> |
622 | /// <param name="timeoutMs">The timeout in milliseconds</param> | |
e3aabeac | 623 | /// <returns>True when the device was found, false otherwise</returns> |
bd624ba8 LOK |
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; | |
f9717bcc | 630 | config.Clear(); |
bd624ba8 LOK |
631 | |
632 | const char* strPortC = port->Length > 0 ? context->marshal_as<const char*>(port) : NULL; | |
633 | ||
634 | if (m_libCec->GetDeviceInformation(strPortC, &config, timeoutMs)) | |
f9717bcc LOK |
635 | { |
636 | configuration->Update(config); | |
bd624ba8 | 637 | bReturn = true; |
f9717bcc | 638 | } |
bd624ba8 LOK |
639 | |
640 | delete context; | |
641 | return bReturn; | |
642 | } | |
643 | ||
f9717bcc LOK |
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> | |
e3aabeac LOK |
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> | |
f9717bcc LOK |
720 | String ^ GetLibInfo() |
721 | { | |
722 | const char *retVal = m_libCec->GetLibInfo(); | |
723 | return gcnew String(retVal); | |
724 | } | |
2b44051c | 725 | |
f9717bcc | 726 | /// <summary> |
e3aabeac | 727 | /// Calling this method will initialise the host on which libCEC is running. |
f9717bcc | 728 | /// On the RPi, it calls bcm_host_init(), which may only be called once per process, and is called by any process using |
e3aabeac LOK |
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> | |
f9717bcc LOK |
733 | void InitVideoStandalone() |
734 | { | |
735 | m_libCec->InitVideoStandalone(); | |
736 | } | |
737 | ||
8768aeca LOK |
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 | ||
f9717bcc LOK |
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 | ||
22190f06 LOK |
826 | if (netConfig->ServerVersion >= CecServerVersion::Version1_8_0) |
827 | config.cecVersion = (cec_version)netConfig->CECVersion; | |
828 | ||
d18ea27b JM |
829 | if (netConfig->ServerVersion >= CecServerVersion::Version2_1_0) |
830 | config.bPowerOnScreensaver = netConfig->PowerOnScreensaver ? 1 : 0; | |
831 | ||
f9717bcc LOK |
832 | config.callbacks = &g_cecCallbacks; |
833 | } | |
834 | ||
63a0b02b | 835 | |
f9717bcc | 836 | ICECAdapter * m_libCec; |
11fea069 | 837 | CecCallbackMethods ^ m_callbacks; |
f9717bcc | 838 | }; |
0cac9547 | 839 | } |