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