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]) | |
380 | retVal->Addresses[iDevices++] = (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); | |
477 | return gcnew String(osd.name); | |
478 | } | |
4ef3b314 | 479 | |
f9717bcc | 480 | /// <summary> |
e3aabeac LOK |
481 | /// Get the logical address of the device that is currently the active source on the CEC bus. |
482 | /// </summary> | |
483 | /// <returns>The active source or CECDEVICE_UNKNOWN when unknown.</returns> | |
f9717bcc LOK |
484 | CecLogicalAddress GetActiveSource() |
485 | { | |
486 | return (CecLogicalAddress)m_libCec->GetActiveSource(); | |
487 | } | |
4ef3b314 | 488 | |
f9717bcc | 489 | /// <summary> |
e3aabeac LOK |
490 | /// Check whether a device is currently the active source on the CEC bus. |
491 | /// </summary> | |
492 | /// <param name="logicalAddress">The logical address of the device to check.</param> | |
493 | /// <returns>True when it is the active source, false otherwise.</returns> | |
f9717bcc LOK |
494 | bool IsActiveSource(CecLogicalAddress logicalAddress) |
495 | { | |
496 | return m_libCec->IsActiveSource((cec_logical_address)logicalAddress); | |
497 | } | |
4ef3b314 | 498 | |
f9717bcc | 499 | /// <summary> |
e3aabeac LOK |
500 | /// Get the physical address of the device with the given logical address. |
501 | /// </summary> | |
502 | /// <param name="address">The logical address of the device to get the physical address for.</param> | |
503 | /// <returns>The physical address or 0 if it wasn't found.</returns> | |
f9717bcc LOK |
504 | uint16_t GetDevicePhysicalAddress(CecLogicalAddress address) |
505 | { | |
506 | return m_libCec->GetDevicePhysicalAddress((cec_logical_address)address); | |
507 | } | |
4ef3b314 | 508 | |
f9717bcc | 509 | /// <summary> |
e3aabeac LOK |
510 | /// Sets the stream path to the device on the given logical address. |
511 | /// </summary> | |
512 | /// <param name="address">The address to activate.</param> | |
513 | /// <returns>True when the command was sent, false otherwise.</returns> | |
f9717bcc LOK |
514 | bool SetStreamPath(CecLogicalAddress address) |
515 | { | |
516 | return m_libCec->SetStreamPath((cec_logical_address)address); | |
517 | } | |
a9fb46b4 | 518 | |
f9717bcc | 519 | /// <summary> |
e3aabeac LOK |
520 | /// Sets the stream path to the device on the given physical address. |
521 | /// </summary> | |
522 | /// <param name="physicalAddress">The address to activate.</param> | |
523 | /// <returns>True when the command was sent, false otherwise.</returns> | |
f9717bcc LOK |
524 | bool SetStreamPath(uint16_t physicalAddress) |
525 | { | |
526 | return m_libCec->SetStreamPath(physicalAddress); | |
527 | } | |
a9fb46b4 | 528 | |
f9717bcc | 529 | /// <summary> |
e3aabeac LOK |
530 | /// Get the list of logical addresses that libCEC is controlling |
531 | /// </summary> | |
532 | /// <returns>The list of logical addresses that libCEC is controlling</returns> | |
f9717bcc LOK |
533 | CecLogicalAddresses ^GetLogicalAddresses(void) |
534 | { | |
535 | CecLogicalAddresses ^addr = gcnew CecLogicalAddresses(); | |
536 | cec_logical_addresses libAddr = m_libCec->GetLogicalAddresses(); | |
537 | for (unsigned int iPtr = 0; iPtr < 16; iPtr++) | |
538 | addr->Addresses[iPtr] = (CecLogicalAddress)libAddr.addresses[iPtr]; | |
539 | addr->Primary = (CecLogicalAddress)libAddr.primary; | |
540 | return addr; | |
541 | } | |
542 | ||
543 | /// <summary> | |
e3aabeac LOK |
544 | /// Get libCEC's current configuration. |
545 | /// </summary> | |
546 | /// <param name="configuration">The configuration.</param> | |
547 | /// <returns>True when the configuration was updated, false otherwise.</returns> | |
f9717bcc LOK |
548 | bool GetCurrentConfiguration(LibCECConfiguration ^configuration) |
549 | { | |
550 | libcec_configuration config; | |
551 | config.Clear(); | |
552 | ||
553 | if (m_libCec->GetCurrentConfiguration(&config)) | |
554 | { | |
555 | configuration->Update(config); | |
556 | return true; | |
557 | } | |
558 | return false; | |
559 | } | |
560 | ||
561 | /// <summary> | |
e3aabeac LOK |
562 | /// Check whether the CEC adapter can persist a configuration. |
563 | /// </summary> | |
564 | /// <returns>True when this CEC adapter can persist the user configuration, false otherwise.</returns> | |
5085a852 | 565 | bool CanPersistConfiguration(void) |
f9717bcc LOK |
566 | { |
567 | return m_libCec->CanPersistConfiguration(); | |
568 | } | |
5085a852 | 569 | |
f9717bcc | 570 | /// <summary> |
e3aabeac LOK |
571 | /// Persist the given configuration in adapter (if supported) |
572 | /// </summary> | |
573 | /// <param name="configuration">The configuration to store.</param> | |
574 | /// <returns>True when the configuration was persisted, false otherwise.</returns> | |
5085a852 | 575 | bool PersistConfiguration(LibCECConfiguration ^configuration) |
f9717bcc LOK |
576 | { |
577 | marshal_context ^ context = gcnew marshal_context(); | |
578 | libcec_configuration config; | |
579 | ConvertConfiguration(context, configuration, config); | |
5085a852 | 580 | |
f9717bcc | 581 | bool bReturn = m_libCec->PersistConfiguration(&config); |
5085a852 | 582 | |
f9717bcc LOK |
583 | delete context; |
584 | return bReturn; | |
585 | } | |
5085a852 | 586 | |
f9717bcc | 587 | /// <summary> |
e3aabeac LOK |
588 | /// Change libCEC's configuration. |
589 | /// </summary> | |
590 | /// <param name="configuration">The new configuration.</param> | |
591 | /// <returns>True when the configuration was changed successfully, false otherwise.</returns> | |
f9717bcc LOK |
592 | bool SetConfiguration(LibCECConfiguration ^configuration) |
593 | { | |
594 | marshal_context ^ context = gcnew marshal_context(); | |
595 | libcec_configuration config; | |
596 | ConvertConfiguration(context, configuration, config); | |
32403cc3 | 597 | |
f9717bcc | 598 | bool bReturn = m_libCec->SetConfiguration(&config); |
32403cc3 | 599 | |
f9717bcc LOK |
600 | delete context; |
601 | return bReturn; | |
602 | } | |
32403cc3 | 603 | |
f9717bcc | 604 | /// <summary> |
e3aabeac LOK |
605 | /// Check whether libCEC is the active source on the bus. |
606 | /// </summary> | |
607 | /// <returns>True when libCEC is the active source on the bus, false otherwise.</returns> | |
bd624ba8 LOK |
608 | bool IsLibCECActiveSource() |
609 | { | |
610 | return m_libCec->IsLibCECActiveSource(); | |
611 | } | |
612 | ||
f9717bcc | 613 | /// <summary> |
e3aabeac LOK |
614 | /// Get information about the given CEC adapter. |
615 | /// </summary> | |
616 | /// <param name="port">The COM port to which the device is connected</param> | |
f9717bcc LOK |
617 | /// <param name="configuration">The device configuration</param> |
618 | /// <param name="timeoutMs">The timeout in milliseconds</param> | |
e3aabeac | 619 | /// <returns>True when the device was found, false otherwise</returns> |
bd624ba8 LOK |
620 | bool GetDeviceInformation(String ^ port, LibCECConfiguration ^configuration, uint32_t timeoutMs) |
621 | { | |
622 | bool bReturn(false); | |
623 | marshal_context ^ context = gcnew marshal_context(); | |
624 | ||
625 | libcec_configuration config; | |
f9717bcc | 626 | config.Clear(); |
bd624ba8 LOK |
627 | |
628 | const char* strPortC = port->Length > 0 ? context->marshal_as<const char*>(port) : NULL; | |
629 | ||
630 | if (m_libCec->GetDeviceInformation(strPortC, &config, timeoutMs)) | |
f9717bcc LOK |
631 | { |
632 | configuration->Update(config); | |
bd624ba8 | 633 | bReturn = true; |
f9717bcc | 634 | } |
bd624ba8 LOK |
635 | |
636 | delete context; | |
637 | return bReturn; | |
638 | } | |
639 | ||
f9717bcc LOK |
640 | String ^ ToString(CecLogicalAddress iAddress) |
641 | { | |
642 | const char *retVal = m_libCec->ToString((cec_logical_address)iAddress); | |
643 | return gcnew String(retVal); | |
644 | } | |
645 | ||
646 | String ^ ToString(CecVendorId iVendorId) | |
647 | { | |
648 | const char *retVal = m_libCec->ToString((cec_vendor_id)iVendorId); | |
649 | return gcnew String(retVal); | |
650 | } | |
651 | ||
652 | String ^ ToString(CecVersion iVersion) | |
653 | { | |
654 | const char *retVal = m_libCec->ToString((cec_version)iVersion); | |
655 | return gcnew String(retVal); | |
656 | } | |
657 | ||
658 | String ^ ToString(CecPowerStatus iState) | |
659 | { | |
660 | const char *retVal = m_libCec->ToString((cec_power_status)iState); | |
661 | return gcnew String(retVal); | |
662 | } | |
663 | ||
664 | String ^ ToString(CecMenuState iState) | |
665 | { | |
666 | const char *retVal = m_libCec->ToString((cec_menu_state)iState); | |
667 | return gcnew String(retVal); | |
668 | } | |
669 | ||
670 | String ^ ToString(CecDeckControlMode iMode) | |
671 | { | |
672 | const char *retVal = m_libCec->ToString((cec_deck_control_mode)iMode); | |
673 | return gcnew String(retVal); | |
674 | } | |
675 | ||
676 | String ^ ToString(CecDeckInfo status) | |
677 | { | |
678 | const char *retVal = m_libCec->ToString((cec_deck_info)status); | |
679 | return gcnew String(retVal); | |
680 | } | |
681 | ||
682 | String ^ ToString(CecOpcode opcode) | |
683 | { | |
684 | const char *retVal = m_libCec->ToString((cec_opcode)opcode); | |
685 | return gcnew String(retVal); | |
686 | } | |
687 | ||
688 | String ^ ToString(CecSystemAudioStatus mode) | |
689 | { | |
690 | const char *retVal = m_libCec->ToString((cec_system_audio_status)mode); | |
691 | return gcnew String(retVal); | |
692 | } | |
693 | ||
694 | String ^ ToString(CecAudioStatus status) | |
695 | { | |
696 | const char *retVal = m_libCec->ToString((cec_audio_status)status); | |
697 | return gcnew String(retVal); | |
698 | } | |
699 | ||
700 | String ^ ToString(CecClientVersion version) | |
701 | { | |
702 | const char *retVal = m_libCec->ToString((cec_client_version)version); | |
703 | return gcnew String(retVal); | |
704 | } | |
705 | ||
706 | String ^ ToString(CecServerVersion version) | |
707 | { | |
708 | const char *retVal = m_libCec->ToString((cec_server_version)version); | |
709 | return gcnew String(retVal); | |
710 | } | |
711 | ||
712 | /// <summary> | |
e3aabeac LOK |
713 | /// Get a string with information about how libCEC was compiled. |
714 | /// </summary> | |
715 | /// <returns>A string with information about how libCEC was compiled.</returns> | |
f9717bcc LOK |
716 | String ^ GetLibInfo() |
717 | { | |
718 | const char *retVal = m_libCec->GetLibInfo(); | |
719 | return gcnew String(retVal); | |
720 | } | |
2b44051c | 721 | |
f9717bcc | 722 | /// <summary> |
e3aabeac | 723 | /// Calling this method will initialise the host on which libCEC is running. |
f9717bcc | 724 | /// 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 |
725 | /// the video api on that system. So only call this method if libCEC is used in an application that |
726 | /// does not already initialise the video api. | |
727 | /// </summary> | |
728 | /// <remarks>Should be called as first call to libCEC, directly after CECInitialise() and before using Open()</remarks> | |
f9717bcc LOK |
729 | void InitVideoStandalone() |
730 | { | |
731 | m_libCec->InitVideoStandalone(); | |
732 | } | |
733 | ||
8768aeca LOK |
734 | /// <summary> |
735 | /// Get the (virtual) USB vendor id | |
736 | /// </summary> | |
737 | /// <returns>The (virtual) USB vendor id</returns> | |
738 | uint16_t GetAdapterVendorId() | |
739 | { | |
740 | return m_libCec->GetAdapterVendorId(); | |
741 | } | |
742 | ||
743 | /// <summary> | |
744 | /// Get the (virtual) USB product id | |
745 | /// </summary> | |
746 | /// <returns>The (virtual) USB product id</returns> | |
747 | uint16_t GetAdapterProductId() | |
748 | { | |
749 | return m_libCec->GetAdapterProductId(); | |
750 | } | |
751 | ||
f9717bcc LOK |
752 | private: |
753 | !LibCecSharp(void) | |
754 | { | |
755 | Close(); | |
756 | m_libCec = NULL; | |
757 | } | |
758 | ||
759 | bool InitialiseLibCec(LibCECConfiguration ^config) | |
760 | { | |
761 | marshal_context ^ context = gcnew marshal_context(); | |
762 | libcec_configuration libCecConfig; | |
763 | ConvertConfiguration(context, config, libCecConfig); | |
764 | ||
765 | m_libCec = (ICECAdapter *) CECInitialise(&libCecConfig); | |
766 | config->Update(libCecConfig); | |
767 | ||
768 | delete context; | |
769 | return m_libCec != NULL; | |
770 | } | |
771 | ||
772 | void ConvertConfiguration(marshal_context ^context, LibCECConfiguration ^netConfig, CEC::libcec_configuration &config) | |
773 | { | |
774 | config.Clear(); | |
775 | ||
776 | const char *strDeviceName = context->marshal_as<const char*>(netConfig->DeviceName); | |
777 | memcpy_s(config.strDeviceName, 13, strDeviceName, 13); | |
778 | for (unsigned int iPtr = 0; iPtr < 5; iPtr++) | |
779 | config.deviceTypes.types[iPtr] = (cec_device_type)netConfig->DeviceTypes->Types[iPtr]; | |
780 | ||
781 | config.bAutodetectAddress = netConfig->AutodetectAddress ? 1 : 0; | |
782 | config.iPhysicalAddress = netConfig->PhysicalAddress; | |
783 | config.baseDevice = (cec_logical_address)netConfig->BaseDevice; | |
784 | config.iHDMIPort = netConfig->HDMIPort; | |
785 | config.clientVersion = (cec_client_version)netConfig->ClientVersion; | |
786 | config.bGetSettingsFromROM = netConfig->GetSettingsFromROM ? 1 : 0; | |
787 | config.bActivateSource = netConfig->ActivateSource ? 1 : 0; | |
788 | config.tvVendor = (cec_vendor_id)netConfig->TvVendor; | |
789 | config.wakeDevices.Clear(); | |
790 | for (int iPtr = 0; iPtr < 16; iPtr++) | |
791 | { | |
792 | if (netConfig->WakeDevices->IsSet((CecLogicalAddress)iPtr)) | |
793 | config.wakeDevices.Set((cec_logical_address)iPtr); | |
794 | } | |
795 | config.powerOffDevices.Clear(); | |
796 | for (int iPtr = 0; iPtr < 16; iPtr++) | |
797 | { | |
798 | if (netConfig->PowerOffDevices->IsSet((CecLogicalAddress)iPtr)) | |
799 | config.powerOffDevices.Set((cec_logical_address)iPtr); | |
800 | } | |
801 | config.bPowerOffScreensaver = netConfig->PowerOffScreensaver ? 1 : 0; | |
802 | config.bPowerOffOnStandby = netConfig->PowerOffOnStandby ? 1 : 0; | |
803 | ||
804 | if (netConfig->ServerVersion >= CecServerVersion::Version1_5_1) | |
805 | config.bSendInactiveSource = netConfig->SendInactiveSource ? 1 : 0; | |
806 | ||
807 | if (netConfig->ServerVersion >= CecServerVersion::Version1_6_0) | |
808 | { | |
809 | config.bPowerOffDevicesOnStandby = netConfig->PowerOffDevicesOnStandby ? 1 : 0; | |
810 | config.bShutdownOnStandby = netConfig->ShutdownOnStandby ? 1 : 0; | |
811 | } | |
812 | ||
813 | if (netConfig->ServerVersion >= CecServerVersion::Version1_6_2) | |
814 | { | |
815 | const char *strDeviceLanguage = context->marshal_as<const char*>(netConfig->DeviceLanguage); | |
816 | memcpy_s(config.strDeviceLanguage, 3, strDeviceLanguage, 3); | |
817 | } | |
818 | ||
819 | if (netConfig->ServerVersion >= CecServerVersion::Version1_6_3) | |
820 | config.bMonitorOnly = netConfig->MonitorOnlyClient ? 1 : 0; | |
821 | ||
22190f06 LOK |
822 | if (netConfig->ServerVersion >= CecServerVersion::Version1_8_0) |
823 | config.cecVersion = (cec_version)netConfig->CECVersion; | |
824 | ||
d18ea27b JM |
825 | if (netConfig->ServerVersion >= CecServerVersion::Version2_1_0) |
826 | config.bPowerOnScreensaver = netConfig->PowerOnScreensaver ? 1 : 0; | |
827 | ||
f9717bcc LOK |
828 | config.callbacks = &g_cecCallbacks; |
829 | } | |
830 | ||
63a0b02b | 831 | |
f9717bcc | 832 | ICECAdapter * m_libCec; |
11fea069 | 833 | CecCallbackMethods ^ m_callbacks; |
f9717bcc | 834 | }; |
0cac9547 | 835 | } |