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