cec: sync C and .NET interfaces with C++
[deb_libcec.git] / src / LibCecSharp / LibCecSharp.cpp
CommitLineData
61f3c2ad
LOK
1/*
2 * This file is part of the libCEC(R) library.
3 *
5d6aa900 4 * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
61f3c2ad
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 */
32
4ef3b314 33#include "CecSharpTypes.h"
61f3c2ad
LOK
34#using <System.dll>
35
36using namespace System;
0cac9547 37using namespace System::Runtime::InteropServices;
61f3c2ad
LOK
38using namespace CEC;
39using namespace msclr::interop;
40
4ef3b314 41namespace CecSharp
61f3c2ad 42{
4ef3b314
LOK
43 public ref class LibCecSharp : public CecCallbackMethods
44 {
45 public:
41297a45
LOK
46 LibCecSharp(LibCECConfiguration ^config)
47 {
11fea069
LOK
48 m_callbacks = config->Callbacks;
49 CecCallbackMethods::EnableCallbacks(m_callbacks);
32403cc3 50 if (!InitialiseLibCec(config))
41297a45
LOK
51 throw gcnew Exception("Could not initialise LibCecSharp");
52 }
53
4ef3b314 54 LibCecSharp(String ^ strDeviceName, CecDeviceTypeList ^ deviceTypes)
41297a45 55 {
11fea069 56 m_callbacks = gcnew CecCallbackMethods();
32403cc3
LOK
57 LibCECConfiguration ^config = gcnew LibCECConfiguration();
58 config->SetCallbacks(this);
59 config->DeviceName = strDeviceName;
60 config->DeviceTypes = deviceTypes;
61 if (!InitialiseLibCec(config))
41297a45
LOK
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
32403cc3 78 bool InitialiseLibCec(LibCECConfiguration ^config)
4ef3b314
LOK
79 {
80 marshal_context ^ context = gcnew marshal_context();
32403cc3
LOK
81 libcec_configuration libCecConfig;
82 ConvertConfiguration(context, config, libCecConfig);
4ef3b314 83
32403cc3 84 m_libCec = (ICECAdapter *) CECInitialise(&libCecConfig);
4ef3b314
LOK
85
86 delete context;
41297a45
LOK
87 return m_libCec != NULL;
88 }
89
32403cc3 90 void ConvertConfiguration(marshal_context ^context, LibCECConfiguration ^netConfig, CEC::libcec_configuration &config)
41297a45
LOK
91 {
92 config.Clear();
93
32403cc3 94 _snprintf_s(config.strDeviceName, 13, context->marshal_as<const char*>(netConfig->DeviceName));
41297a45 95 for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
32403cc3 96 config.deviceTypes.types[iPtr] = (cec_device_type)netConfig->DeviceTypes->Types[iPtr];
41297a45 97
8670c970 98 config.bAutodetectAddress = netConfig->AutodetectAddress ? 1 : 0;
32403cc3
LOK
99 config.iPhysicalAddress = netConfig->PhysicalAddress;
100 config.baseDevice = (cec_logical_address)netConfig->BaseDevice;
101 config.iHDMIPort = netConfig->HDMIPort;
102 config.clientVersion = (cec_client_version)netConfig->ClientVersion;
8670c970
LOK
103 config.bGetSettingsFromROM = netConfig->GetSettingsFromROM ? 1 : 0;
104 config.bActivateSource = netConfig->ActivateSource ? 1 : 0;
b7907707
LOK
105 config.tvVendor = (cec_vendor_id)netConfig->TvVendor;
106 config.wakeDevices.Clear();
107 for (int iPtr = 0; iPtr < 16; iPtr++)
108 {
109 if (netConfig->WakeDevices->IsSet((CecLogicalAddress)iPtr))
110 config.wakeDevices.Set((cec_logical_address)iPtr);
111 }
112 config.powerOffDevices.Clear();
113 for (int iPtr = 0; iPtr < 16; iPtr++)
114 {
115 if (netConfig->PowerOffDevices->IsSet((CecLogicalAddress)iPtr))
116 config.powerOffDevices.Set((cec_logical_address)iPtr);
117 }
8670c970
LOK
118 config.bPowerOffScreensaver = netConfig->PowerOffScreensaver ? 1 : 0;
119 config.bPowerOffOnStandby = netConfig->PowerOffOnStandby ? 1 : 0;
a8fffd1b 120 config.bSendInactiveSource = netConfig->SendInactiveSource ? 1 : 0;
32403cc3 121 config.callbacks = &g_cecCallbacks;
4ef3b314 122 }
4ef3b314
LOK
123
124 public:
125 array<CecAdapter ^> ^ FindAdapters(String ^ path)
126 {
127 cec_adapter *devices = new cec_adapter[10];
128
129 marshal_context ^ context = gcnew marshal_context();
130 const char* strPathC = path->Length > 0 ? context->marshal_as<const char*>(path) : NULL;
131
132 uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL);
133
134 array<CecAdapter ^> ^ adapters = gcnew array<CecAdapter ^>(iDevicesFound);
135 for (unsigned int iPtr = 0; iPtr < iDevicesFound; iPtr++)
136 adapters[iPtr] = gcnew CecAdapter(gcnew String(devices[iPtr].path), gcnew String(devices[iPtr].comm));
137
138 delete devices;
139 delete context;
140 return adapters;
141 }
142
143 bool Open(String ^ strPort, int iTimeoutMs)
144 {
11fea069
LOK
145 CecCallbackMethods::EnableCallbacks(m_callbacks);
146 EnableCallbacks(m_callbacks);
4ef3b314
LOK
147 marshal_context ^ context = gcnew marshal_context();
148 const char* strPortC = context->marshal_as<const char*>(strPort);
149 bool bReturn = m_libCec->Open(strPortC, iTimeoutMs);
150 delete context;
151 return bReturn;
152 }
153
154 void Close(void)
8670c970
LOK
155 {
156 DisableCallbacks();
157 m_libCec->Close();
158 }
159
160 virtual void DisableCallbacks(void) override
4ef3b314 161 {
7e24a7d2 162 // delete the callbacks, since these might already have been destroyed in .NET
dae4328c 163 CecCallbackMethods::DisableCallbacks();
8670c970
LOK
164 if (m_libCec)
165 m_libCec->EnableCallbacks(NULL, NULL);
4ef3b314
LOK
166 }
167
168 virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) override
169 {
170 if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks))
171 return m_libCec->EnableCallbacks(NULL, &g_cecCallbacks);
172
173 return false;
174 }
175
176 bool PingAdapter(void)
177 {
178 return m_libCec->PingAdapter();
179 }
180
181 bool StartBootloader(void)
182 {
183 return m_libCec->StartBootloader();
184 }
185
186 int GetMinLibVersion(void)
187 {
188 return m_libCec->GetMinLibVersion();
189 }
190
191 int GetLibVersionMajor(void)
192 {
193 return m_libCec->GetLibVersionMajor();
194 }
195
196 int GetLibVersionMinor(void)
197 {
198 return m_libCec->GetLibVersionMinor();
199 }
200
201 CecLogMessage ^ GetNextLogMessage(void)
202 {
203 cec_log_message msg;
204 if (m_libCec->GetNextLogMessage(&msg))
205 {
206 return gcnew CecLogMessage(gcnew String(msg.message), (CecLogLevel)msg.level, msg.time);
207 }
208
209 return gcnew CecLogMessage();
210 }
211
212 CecKeypress ^ GetNextKeypress(void)
213 {
214 cec_keypress key;
215 if (m_libCec->GetNextKeypress(&key))
216 {
217 return gcnew CecKeypress(key.keycode, key.duration);
218 }
219
220 return gcnew CecKeypress();
221 }
222
223 CecCommand ^ GetNextCommand(void)
224 {
225 cec_command command;
226 if (m_libCec->GetNextCommand(&command))
227 {
228 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);
229 for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
230 retVal->Parameters->PushBack(command.parameters[iPtr]);
231 return retVal;
232 }
233
234 return gcnew CecCommand();
235 }
236
237 bool Transmit(CecCommand ^ command)
238 {
239 cec_command ccommand;
240 cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode);
241 ccommand.transmit_timeout = command->TransmitTimeout;
242 ccommand.eom = command->Eom;
243 ccommand.ack = command->Ack;
244 for (unsigned int iPtr = 0; iPtr < command->Parameters->Size; iPtr++)
245 ccommand.parameters.PushBack(command->Parameters->Data[iPtr]);
246
247 return m_libCec->Transmit(ccommand);
248 }
249
250 bool SetLogicalAddress(CecLogicalAddress logicalAddress)
251 {
252 return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress);
253 }
254
006b76b9 255 bool SetPhysicalAddress(uint16_t physicalAddress)
4ef3b314
LOK
256 {
257 return m_libCec->SetPhysicalAddress(physicalAddress);
258 }
259
260 bool PowerOnDevices(CecLogicalAddress logicalAddress)
261 {
262 return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress);
263 }
264
265 bool StandbyDevices(CecLogicalAddress logicalAddress)
266 {
267 return m_libCec->StandbyDevices((cec_logical_address) logicalAddress);
268 }
269
270 bool PollDevice(CecLogicalAddress logicalAddress)
271 {
272 return m_libCec->PollDevice((cec_logical_address) logicalAddress);
273 }
274
275 bool SetActiveSource(CecDeviceType type)
276 {
277 return m_libCec->SetActiveSource((cec_device_type) type);
278 }
279
280 bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate)
281 {
282 return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate);
283 }
284
285 bool SetDeckInfo(CecDeckInfo info, bool sendUpdate)
286 {
287 return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate);
288 }
289
290 bool SetInactiveView(void)
291 {
292 return m_libCec->SetInactiveView();
293 }
294
295 bool SetMenuState(CecMenuState state, bool sendUpdate)
296 {
297 return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate);
298 }
299
300 bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message)
301 {
302 marshal_context ^ context = gcnew marshal_context();
303 const char* strMessageC = context->marshal_as<const char*>(message);
304
305 bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC);
306
307 delete context;
308 return bReturn;
309 }
310
311 bool SwitchMonitoring(bool enable)
312 {
313 return m_libCec->SwitchMonitoring(enable);
314 }
315
316 CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress)
317 {
318 return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress);
319 }
320
321 String ^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress)
322 {
323 cec_menu_language lang;
324 if (m_libCec->GetDeviceMenuLanguage((cec_logical_address) logicalAddress, &lang))
325 {
326 return gcnew String(lang.language);
327 }
328
329 return gcnew String("");
330 }
331
332 CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress)
333 {
334 return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress);
335 }
336
337 CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress)
338 {
339 return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress);
340 }
341
3efda01a
LOK
342 void RescanActiveDevices(void)
343 {
344 m_libCec->RescanActiveDevices();
345 }
346
4ef3b314
LOK
347 CecLogicalAddresses ^ GetActiveDevices(void)
348 {
349 CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses();
350 unsigned int iDevices = 0;
351
352 cec_logical_addresses activeDevices = m_libCec->GetActiveDevices();
353
354 for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
355 if (activeDevices[iPtr])
356 retVal->Addresses[iDevices++] = (CecLogicalAddress)iPtr;
357
358 return retVal;
359 }
360
361 bool IsActiveDevice(CecLogicalAddress logicalAddress)
362 {
363 return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress);
364 }
365
366 bool IsActiveDeviceType(CecDeviceType type)
367 {
368 return m_libCec->IsActiveDeviceType((cec_device_type)type);
369 }
370
371 bool SetHDMIPort(CecLogicalAddress address, uint8_t port)
372 {
373 return m_libCec->SetHDMIPort((cec_logical_address)address, port);
374 }
375
376 uint8_t VolumeUp(bool wait)
377 {
378 return m_libCec->VolumeUp(wait);
379 }
380
381 uint8_t VolumeDown(bool wait)
382 {
383 return m_libCec->VolumeDown(wait);
384 }
385
386 uint8_t MuteAudio(bool wait)
387 {
388 return m_libCec->MuteAudio(wait);
389 }
390
391 bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait)
392 {
393 return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait);
394 }
395
396 bool SendKeyRelease(CecLogicalAddress destination, bool wait)
397 {
398 return m_libCec->SendKeyRelease((cec_logical_address)destination, wait);
399 }
400
401 String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress)
402 {
403 cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress);
404 return gcnew String(osd.name);
405 }
406
407 CecLogicalAddress GetActiveSource()
408 {
409 return (CecLogicalAddress)m_libCec->GetActiveSource();
410 }
411
412 bool IsActiveSource(CecLogicalAddress logicalAddress)
413 {
414 return m_libCec->IsActiveSource((cec_logical_address)logicalAddress);
415 }
416
417 uint16_t GetDevicePhysicalAddress(CecLogicalAddress iAddress)
418 {
419 return m_libCec->GetDevicePhysicalAddress((cec_logical_address)iAddress);
420 }
421
a9fb46b4
LOK
422 bool SetStreamPath(CecLogicalAddress iAddress)
423 {
424 return m_libCec->SetStreamPath((cec_logical_address)iAddress);
425 }
426
427 bool SetStreamPath(uint16_t iPhysicalAddress)
428 {
429 return m_libCec->SetStreamPath(iPhysicalAddress);
430 }
431
432 CecLogicalAddresses ^GetLogicalAddresses(void)
433 {
434 CecLogicalAddresses ^addr = gcnew CecLogicalAddresses();
435 cec_logical_addresses libAddr = m_libCec->GetLogicalAddresses();
436 for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
437 addr->Addresses[iPtr] = (CecLogicalAddress)libAddr.addresses[iPtr];
438 addr->Primary = (CecLogicalAddress)libAddr.primary;
439 return addr;
440 }
441
5085a852
LOK
442 bool GetCurrentConfiguration(LibCECConfiguration ^configuration)
443 {
444 libcec_configuration config;
006b76b9
LOK
445 config.Clear();
446
5085a852
LOK
447 if (m_libCec->GetCurrentConfiguration(&config))
448 {
3efda01a 449 configuration->Update(config);
5085a852
LOK
450 return true;
451 }
452 return false;
453 }
454
455 bool CanPersistConfiguration(void)
456 {
457 return m_libCec->CanPersistConfiguration();
458 }
459
460 bool PersistConfiguration(LibCECConfiguration ^configuration)
461 {
462 marshal_context ^ context = gcnew marshal_context();
463 libcec_configuration config;
32403cc3 464 ConvertConfiguration(context, configuration, config);
5085a852
LOK
465
466 bool bReturn = m_libCec->PersistConfiguration(&config);
467
468 delete context;
469 return bReturn;
470 }
471
32403cc3
LOK
472 bool SetConfiguration(LibCECConfiguration ^configuration)
473 {
474 marshal_context ^ context = gcnew marshal_context();
475 libcec_configuration config;
476 ConvertConfiguration(context, configuration, config);
477
478 bool bReturn = m_libCec->SetConfiguration(&config);
479
480 delete context;
481 return bReturn;
482 }
483
bd624ba8
LOK
484 bool IsLibCECActiveSource()
485 {
486 return m_libCec->IsLibCECActiveSource();
487 }
488
489 bool GetDeviceInformation(String ^ port, LibCECConfiguration ^configuration, uint32_t timeoutMs)
490 {
491 bool bReturn(false);
492 marshal_context ^ context = gcnew marshal_context();
493
494 libcec_configuration config;
495 config.Clear();
496
497 const char* strPortC = port->Length > 0 ? context->marshal_as<const char*>(port) : NULL;
498
499 if (m_libCec->GetDeviceInformation(strPortC, &config, timeoutMs))
500 {
501 configuration->Update(config);
502 bReturn = true;
503 }
504
505 delete context;
506 return bReturn;
507 }
508
4ef3b314
LOK
509 String ^ ToString(CecLogicalAddress iAddress)
510 {
511 const char *retVal = m_libCec->ToString((cec_logical_address)iAddress);
512 return gcnew String(retVal);
513 }
514
515 String ^ ToString(CecVendorId iVendorId)
516 {
517 const char *retVal = m_libCec->ToString((cec_vendor_id)iVendorId);
518 return gcnew String(retVal);
519 }
520
521 String ^ ToString(CecVersion iVersion)
522 {
523 const char *retVal = m_libCec->ToString((cec_version)iVersion);
524 return gcnew String(retVal);
525 }
526
527 String ^ ToString(CecPowerStatus iState)
528 {
529 const char *retVal = m_libCec->ToString((cec_power_status)iState);
530 return gcnew String(retVal);
531 }
532
533 String ^ ToString(CecMenuState iState)
534 {
535 const char *retVal = m_libCec->ToString((cec_menu_state)iState);
536 return gcnew String(retVal);
537 }
538
539 String ^ ToString(CecDeckControlMode iMode)
540 {
541 const char *retVal = m_libCec->ToString((cec_deck_control_mode)iMode);
542 return gcnew String(retVal);
543 }
544
545 String ^ ToString(CecDeckInfo status)
546 {
547 const char *retVal = m_libCec->ToString((cec_deck_info)status);
548 return gcnew String(retVal);
549 }
550
551 String ^ ToString(CecOpcode opcode)
552 {
553 const char *retVal = m_libCec->ToString((cec_opcode)opcode);
554 return gcnew String(retVal);
555 }
556
557 String ^ ToString(CecSystemAudioStatus mode)
558 {
559 const char *retVal = m_libCec->ToString((cec_system_audio_status)mode);
560 return gcnew String(retVal);
561 }
562
563 String ^ ToString(CecAudioStatus status)
564 {
565 const char *retVal = m_libCec->ToString((cec_audio_status)status);
566 return gcnew String(retVal);
567 }
568
3efda01a
LOK
569 String ^ ToString(CecClientVersion version)
570 {
571 const char *retVal = m_libCec->ToString((cec_client_version)version);
572 return gcnew String(retVal);
573 }
574
575 String ^ ToString(CecServerVersion version)
576 {
577 const char *retVal = m_libCec->ToString((cec_server_version)version);
578 return gcnew String(retVal);
579 }
580
4ef3b314
LOK
581 private:
582 ICECAdapter * m_libCec;
11fea069 583 CecCallbackMethods ^ m_callbacks;
4ef3b314 584 };
0cac9547 585}