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