1c073d9baedaae0e15989df8daf2821f54447c63
[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.bPowerOnStartup = netConfig->PowerOnStartup;
102 config.bPowerOffShutdown = netConfig->PowerOffShutdown;
103 config.bPowerOffScreensaver = netConfig->PowerOffScreensaver;
104 config.bPowerOffOnStandby = netConfig->PowerOffOnStandby;
105 config.callbacks = &g_cecCallbacks;
106 }
107
108 public:
109 array<CecAdapter ^> ^ FindAdapters(String ^ path)
110 {
111 cec_adapter *devices = new cec_adapter[10];
112
113 marshal_context ^ context = gcnew marshal_context();
114 const char* strPathC = path->Length > 0 ? context->marshal_as<const char*>(path) : NULL;
115
116 uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL);
117
118 array<CecAdapter ^> ^ adapters = gcnew array<CecAdapter ^>(iDevicesFound);
119 for (unsigned int iPtr = 0; iPtr < iDevicesFound; iPtr++)
120 adapters[iPtr] = gcnew CecAdapter(gcnew String(devices[iPtr].path), gcnew String(devices[iPtr].comm));
121
122 delete devices;
123 delete context;
124 return adapters;
125 }
126
127 bool Open(String ^ strPort, int iTimeoutMs)
128 {
129 marshal_context ^ context = gcnew marshal_context();
130 const char* strPortC = context->marshal_as<const char*>(strPort);
131 bool bReturn = m_libCec->Open(strPortC, iTimeoutMs);
132 delete context;
133 return bReturn;
134 }
135
136 void Close(void)
137 {
138 // delete the callbacks, since these might already have been destroyed in .NET
139 m_libCec->EnableCallbacks(NULL, NULL);
140 m_libCec->Close();
141 }
142
143 virtual bool EnableCallbacks(CecCallbackMethods ^ callbacks) override
144 {
145 if (m_libCec && CecCallbackMethods::EnableCallbacks(callbacks))
146 return m_libCec->EnableCallbacks(NULL, &g_cecCallbacks);
147
148 return false;
149 }
150
151 bool PingAdapter(void)
152 {
153 return m_libCec->PingAdapter();
154 }
155
156 bool StartBootloader(void)
157 {
158 return m_libCec->StartBootloader();
159 }
160
161 int GetMinLibVersion(void)
162 {
163 return m_libCec->GetMinLibVersion();
164 }
165
166 int GetLibVersionMajor(void)
167 {
168 return m_libCec->GetLibVersionMajor();
169 }
170
171 int GetLibVersionMinor(void)
172 {
173 return m_libCec->GetLibVersionMinor();
174 }
175
176 CecLogMessage ^ GetNextLogMessage(void)
177 {
178 cec_log_message msg;
179 if (m_libCec->GetNextLogMessage(&msg))
180 {
181 return gcnew CecLogMessage(gcnew String(msg.message), (CecLogLevel)msg.level, msg.time);
182 }
183
184 return gcnew CecLogMessage();
185 }
186
187 CecKeypress ^ GetNextKeypress(void)
188 {
189 cec_keypress key;
190 if (m_libCec->GetNextKeypress(&key))
191 {
192 return gcnew CecKeypress(key.keycode, key.duration);
193 }
194
195 return gcnew CecKeypress();
196 }
197
198 CecCommand ^ GetNextCommand(void)
199 {
200 cec_command command;
201 if (m_libCec->GetNextCommand(&command))
202 {
203 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);
204 for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
205 retVal->Parameters->PushBack(command.parameters[iPtr]);
206 return retVal;
207 }
208
209 return gcnew CecCommand();
210 }
211
212 bool Transmit(CecCommand ^ command)
213 {
214 cec_command ccommand;
215 cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode);
216 ccommand.transmit_timeout = command->TransmitTimeout;
217 ccommand.eom = command->Eom;
218 ccommand.ack = command->Ack;
219 for (unsigned int iPtr = 0; iPtr < command->Parameters->Size; iPtr++)
220 ccommand.parameters.PushBack(command->Parameters->Data[iPtr]);
221
222 return m_libCec->Transmit(ccommand);
223 }
224
225 bool SetLogicalAddress(CecLogicalAddress logicalAddress)
226 {
227 return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress);
228 }
229
230 bool SetPhysicalAddress(uint16_t physicalAddress)
231 {
232 return m_libCec->SetPhysicalAddress(physicalAddress);
233 }
234
235 bool PowerOnDevices(CecLogicalAddress logicalAddress)
236 {
237 return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress);
238 }
239
240 bool StandbyDevices(CecLogicalAddress logicalAddress)
241 {
242 return m_libCec->StandbyDevices((cec_logical_address) logicalAddress);
243 }
244
245 bool PollDevice(CecLogicalAddress logicalAddress)
246 {
247 return m_libCec->PollDevice((cec_logical_address) logicalAddress);
248 }
249
250 bool SetActiveSource(CecDeviceType type)
251 {
252 return m_libCec->SetActiveSource((cec_device_type) type);
253 }
254
255 bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate)
256 {
257 return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate);
258 }
259
260 bool SetDeckInfo(CecDeckInfo info, bool sendUpdate)
261 {
262 return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate);
263 }
264
265 bool SetInactiveView(void)
266 {
267 return m_libCec->SetInactiveView();
268 }
269
270 bool SetMenuState(CecMenuState state, bool sendUpdate)
271 {
272 return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate);
273 }
274
275 bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message)
276 {
277 marshal_context ^ context = gcnew marshal_context();
278 const char* strMessageC = context->marshal_as<const char*>(message);
279
280 bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC);
281
282 delete context;
283 return bReturn;
284 }
285
286 bool SwitchMonitoring(bool enable)
287 {
288 return m_libCec->SwitchMonitoring(enable);
289 }
290
291 CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress)
292 {
293 return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress);
294 }
295
296 String ^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress)
297 {
298 cec_menu_language lang;
299 if (m_libCec->GetDeviceMenuLanguage((cec_logical_address) logicalAddress, &lang))
300 {
301 return gcnew String(lang.language);
302 }
303
304 return gcnew String("");
305 }
306
307 CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress)
308 {
309 return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress);
310 }
311
312 CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress)
313 {
314 return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress);
315 }
316
317 CecLogicalAddresses ^ GetActiveDevices(void)
318 {
319 CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses();
320 unsigned int iDevices = 0;
321
322 cec_logical_addresses activeDevices = m_libCec->GetActiveDevices();
323
324 for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
325 if (activeDevices[iPtr])
326 retVal->Addresses[iDevices++] = (CecLogicalAddress)iPtr;
327
328 return retVal;
329 }
330
331 bool IsActiveDevice(CecLogicalAddress logicalAddress)
332 {
333 return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress);
334 }
335
336 bool IsActiveDeviceType(CecDeviceType type)
337 {
338 return m_libCec->IsActiveDeviceType((cec_device_type)type);
339 }
340
341 bool SetHDMIPort(CecLogicalAddress address, uint8_t port)
342 {
343 return m_libCec->SetHDMIPort((cec_logical_address)address, port);
344 }
345
346 uint8_t VolumeUp(bool wait)
347 {
348 return m_libCec->VolumeUp(wait);
349 }
350
351 uint8_t VolumeDown(bool wait)
352 {
353 return m_libCec->VolumeDown(wait);
354 }
355
356 uint8_t MuteAudio(bool wait)
357 {
358 return m_libCec->MuteAudio(wait);
359 }
360
361 bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait)
362 {
363 return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait);
364 }
365
366 bool SendKeyRelease(CecLogicalAddress destination, bool wait)
367 {
368 return m_libCec->SendKeyRelease((cec_logical_address)destination, wait);
369 }
370
371 String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress)
372 {
373 cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress);
374 return gcnew String(osd.name);
375 }
376
377 CecLogicalAddress GetActiveSource()
378 {
379 return (CecLogicalAddress)m_libCec->GetActiveSource();
380 }
381
382 bool IsActiveSource(CecLogicalAddress logicalAddress)
383 {
384 return m_libCec->IsActiveSource((cec_logical_address)logicalAddress);
385 }
386
387 uint16_t GetDevicePhysicalAddress(CecLogicalAddress iAddress)
388 {
389 return m_libCec->GetDevicePhysicalAddress((cec_logical_address)iAddress);
390 }
391
392 bool SetStreamPath(CecLogicalAddress iAddress)
393 {
394 return m_libCec->SetStreamPath((cec_logical_address)iAddress);
395 }
396
397 bool SetStreamPath(uint16_t iPhysicalAddress)
398 {
399 return m_libCec->SetStreamPath(iPhysicalAddress);
400 }
401
402 CecLogicalAddresses ^GetLogicalAddresses(void)
403 {
404 CecLogicalAddresses ^addr = gcnew CecLogicalAddresses();
405 cec_logical_addresses libAddr = m_libCec->GetLogicalAddresses();
406 for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
407 addr->Addresses[iPtr] = (CecLogicalAddress)libAddr.addresses[iPtr];
408 addr->Primary = (CecLogicalAddress)libAddr.primary;
409 return addr;
410 }
411
412 bool GetCurrentConfiguration(LibCECConfiguration ^configuration)
413 {
414 libcec_configuration config;
415 config.Clear();
416
417 if (m_libCec->GetCurrentConfiguration(&config))
418 {
419 configuration->BaseDevice = (CecLogicalAddress)config.baseDevice;
420 configuration->DeviceName = gcnew String(config.strDeviceName);
421 configuration->HDMIPort = config.iHDMIPort;
422 configuration->PhysicalAddress = config.iPhysicalAddress;
423 configuration->PowerOffOnStandby = config.bPowerOffOnStandby == 1;
424 configuration->PowerOffScreensaver = config.bPowerOffScreensaver == 1;
425 configuration->PowerOffShutdown = config.bPowerOffShutdown == 1;
426 configuration->PowerOnStartup = config.bPowerOnStartup == 1;
427 configuration->UseTVMenuLanguage = config.bUseTVMenuLanguage == 1;
428 for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
429 configuration->DeviceTypes->Types[iPtr] = (CecDeviceType)config.deviceTypes.types[iPtr];
430 return true;
431 }
432 return false;
433 }
434
435 bool CanPersistConfiguration(void)
436 {
437 return m_libCec->CanPersistConfiguration();
438 }
439
440 bool PersistConfiguration(LibCECConfiguration ^configuration)
441 {
442 marshal_context ^ context = gcnew marshal_context();
443 libcec_configuration config;
444 ConvertConfiguration(context, configuration, config);
445
446 bool bReturn = m_libCec->PersistConfiguration(&config);
447
448 delete context;
449 return bReturn;
450 }
451
452 bool SetConfiguration(LibCECConfiguration ^configuration)
453 {
454 marshal_context ^ context = gcnew marshal_context();
455 libcec_configuration config;
456 ConvertConfiguration(context, configuration, config);
457
458 bool bReturn = m_libCec->SetConfiguration(&config);
459
460 delete context;
461 return bReturn;
462 }
463
464 String ^ ToString(CecLogicalAddress iAddress)
465 {
466 const char *retVal = m_libCec->ToString((cec_logical_address)iAddress);
467 return gcnew String(retVal);
468 }
469
470 String ^ ToString(CecVendorId iVendorId)
471 {
472 const char *retVal = m_libCec->ToString((cec_vendor_id)iVendorId);
473 return gcnew String(retVal);
474 }
475
476 String ^ ToString(CecVersion iVersion)
477 {
478 const char *retVal = m_libCec->ToString((cec_version)iVersion);
479 return gcnew String(retVal);
480 }
481
482 String ^ ToString(CecPowerStatus iState)
483 {
484 const char *retVal = m_libCec->ToString((cec_power_status)iState);
485 return gcnew String(retVal);
486 }
487
488 String ^ ToString(CecMenuState iState)
489 {
490 const char *retVal = m_libCec->ToString((cec_menu_state)iState);
491 return gcnew String(retVal);
492 }
493
494 String ^ ToString(CecDeckControlMode iMode)
495 {
496 const char *retVal = m_libCec->ToString((cec_deck_control_mode)iMode);
497 return gcnew String(retVal);
498 }
499
500 String ^ ToString(CecDeckInfo status)
501 {
502 const char *retVal = m_libCec->ToString((cec_deck_info)status);
503 return gcnew String(retVal);
504 }
505
506 String ^ ToString(CecOpcode opcode)
507 {
508 const char *retVal = m_libCec->ToString((cec_opcode)opcode);
509 return gcnew String(retVal);
510 }
511
512 String ^ ToString(CecSystemAudioStatus mode)
513 {
514 const char *retVal = m_libCec->ToString((cec_system_audio_status)mode);
515 return gcnew String(retVal);
516 }
517
518 String ^ ToString(CecAudioStatus status)
519 {
520 const char *retVal = m_libCec->ToString((cec_audio_status)status);
521 return gcnew String(retVal);
522 }
523
524 private:
525 ICECAdapter * m_libCec;
526 };
527 }