cec: make sure we're not trying to unlock the mutex too many times
[deb_libcec.git] / src / LibCecSharp / LibCecSharp.cpp
... / ...
CommitLineData
1/*
2 * This file is part of the libCEC(R) library.
3 *
4 * libCEC(R) is Copyright (C) 2011 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 <windows.h>
34#include <vcclr.h>
35#include <msclr/marshal.h>
36#include <cec.h>
37#using <System.dll>
38
39using namespace System;
40using namespace System::Runtime::InteropServices;
41using namespace CEC;
42using namespace msclr::interop;
43
44public enum class CecDeviceType
45{
46 Tv = 0,
47 RecordingDevice = 1,
48 Reserved = 2,
49 Tuner = 3,
50 PlaybackDevice = 4,
51 AudioSystem = 5
52};
53
54public enum class CecLogLevel
55{
56 None = 0,
57 Error = 1,
58 Warning = 2,
59 Notice = 4,
60 Traffic = 8,
61 Debug = 16,
62 All = 31
63};
64
65public enum class CecLogicalAddress
66{
67 Unknown = -1, //not a valid logical address
68 Tv = 0,
69 RecordingDevice1 = 1,
70 RecordingDevice2 = 2,
71 Tuner1 = 3,
72 PlaybackDevice1 = 4,
73 AudioSystem = 5,
74 Tuner2 = 6,
75 Tuner3 = 7,
76 PlaybackDevice2 = 8,
77 RecordingDevice3 = 9,
78 Tuner4 = 10,
79 PlaybackDevice3 = 11,
80 Reserved1 = 12,
81 Reserved2 = 13,
82 FreeUse = 14,
83 Unregistered = 15,
84 Broadcast = 15
85};
86
87public enum class CecPowerStatus
88{
89 On = 0x00,
90 Standby = 0x01,
91 InTransitionStandbyToOn = 0x02,
92 InTransitionOnToStandby = 0x03,
93 Unknown = 0x99
94};
95
96public enum class CecVersion
97{
98 Unknown = 0x00,
99 V1_2 = 0x01,
100 V1_2A = 0x02,
101 V1_3 = 0x03,
102 V1_3A = 0x04,
103 V1_4 = 0x05
104};
105
106public enum class CecDisplayControl
107{
108 DisplayForDefaultTime = 0x00,
109 DisplayUntilCleared = 0x40,
110 ClearPreviousMessage = 0x80,
111 ReservedForFutureUse = 0xC0
112};
113
114public enum class CecMenuState
115{
116 Activated = 0,
117 Deactivated = 1
118};
119
120public enum class CecDeckControlMode
121{
122 SkipForwardWind = 1,
123 SkipReverseRewind = 2,
124 Stop = 3,
125 Eject = 4
126};
127
128public enum class CecDeckInfo
129{
130 Play = 0x11,
131 Record = 0x12,
132 Reverse = 0x13,
133 Still = 0x14,
134 Slow = 0x15,
135 SlowReverse = 0x16,
136 FastForward = 0x17,
137 FastReverse = 0x18,
138 NoMedia = 0x19,
139 Stop = 0x1A,
140 SkipForwardWind = 0x1B,
141 SkipReverseRewind = 0x1C,
142 IndexSearchForward = 0x1D,
143 IndexSearchReverse = 0x1E,
144 OtherStatus = 0x1F
145};
146
147public enum class CecUserControlCode
148{
149 Select = 0x00,
150 Up = 0x01,
151 Down = 0x02,
152 Left = 0x03,
153 Right = 0x04,
154 RightUp = 0x05,
155 RightDown = 0x06,
156 LeftUp = 0x07,
157 LeftDown = 0x08,
158 RootMenu = 0x09,
159 SetupMenu = 0x0A,
160 ContentsMenu = 0x0B,
161 FavoriteMenu = 0x0C,
162 Exit = 0x0D,
163 Number0 = 0x20,
164 Number1 = 0x21,
165 Number2 = 0x22,
166 Number3 = 0x23,
167 Number4 = 0x24,
168 Number5 = 0x25,
169 Number6 = 0x26,
170 Number7 = 0x27,
171 Number8 = 0x28,
172 Number9 = 0x29,
173 Dot = 0x2A,
174 Enter = 0x2B,
175 Clear = 0x2C,
176 NextFavorite = 0x2F,
177 ChannelUp = 0x30,
178 ChannelDown = 0x31,
179 PreviousChannel = 0x32,
180 SoundSelect = 0x33,
181 InputSelect = 0x34,
182 DisplayInformation = 0x35,
183 Help = 0x36,
184 PageUp = 0x37,
185 PageDown = 0x38,
186 Power = 0x40,
187 VolumeUp = 0x41,
188 VolumeDown = 0x42,
189 Mute = 0x43,
190 Play = 0x44,
191 Stop = 0x45,
192 Pause = 0x46,
193 Record = 0x47,
194 Rewind = 0x48,
195 FastForward = 0x49,
196 Eject = 0x4A,
197 Forward = 0x4B,
198 Backward = 0x4C,
199 StopRecord = 0x4D,
200 PauseRecord = 0x4E,
201 Angle = 0x50,
202 SubPicture = 0x51,
203 VideoOnDemand = 0x52,
204 ElectronicProgramGuide = 0x53,
205 TimerProgramming = 0x54,
206 InitialConfiguration = 0x55,
207 PlayFunction = 0x60,
208 PausePlayFunction = 0x61,
209 RecordFunction = 0x62,
210 PauseRecordFunction = 0x63,
211 StopFunction = 0x64,
212 MuteFunction = 0x65,
213 RestoreVolumeFunction = 0x66,
214 TuneFunction = 0x67,
215 SelectMediaFunction = 0x68,
216 SelectAVInputFunction = 0x69,
217 SelectAudioInputFunction = 0x6A,
218 PowerToggleFunction = 0x6B,
219 PowerOffFunction = 0x6C,
220 PowerOnFunction = 0x6D,
221 F1Blue = 0x71,
222 F2Red = 0X72,
223 F3Green = 0x73,
224 F4Yellow = 0x74,
225 F5 = 0x75,
226 Data = 0x76,
227 Max = 0x76,
228 Unknown
229};
230
231public enum class CecVendorId
232{
233 Samsung = 0x00F0,
234 LG = 0xE091,
235 Panasonic = 0x8045,
236 Pioneer = 0xE036,
237 Onkyo = 0x09B0,
238 Yamaha = 0xA0DE,
239 Philips = 0x903E,
240 Unknown = 0
241};
242
243public enum class CecAudioStatus
244{
245 MuteStatusMask = 0x80,
246 VolumeStatusMask = 0x7F,
247 VolumeMin = 0x00,
248 VolumeMax = 0x64,
249 VolumeStatusUnknown = 0x7F
250};
251
252public enum class CecOpcode
253{
254 ActiveSource = 0x82,
255 ImageViewOn = 0x04,
256 TextViewOn = 0x0D,
257 InactiveSource = 0x9D,
258 RequestActiveSource = 0x85,
259 RoutingChange = 0x80,
260 RoutingInformation = 0x81,
261 SetStreamPath = 0x86,
262 Standby = 0x36,
263 RecordOff = 0x0B,
264 RecordOn = 0x09,
265 RecordStatus = 0x0A,
266 RecordTvScreen = 0x0F,
267 ClearAnalogueTimer = 0x33,
268 ClearDigitalTimer = 0x99,
269 ClearExternalTimer = 0xA1,
270 SetAnalogueTimer = 0x34,
271 SetDigitalTimer = 0x97,
272 SetExternalTimer = 0xA2,
273 SetTimerProgramTitle = 0x67,
274 TimerClearedStatus = 0x43,
275 TimerStatus = 0x35,
276 CecVersion = 0x9E,
277 GetCecVersion = 0x9F,
278 GivePhysicalAddress = 0x83,
279 GetMenuLanguage = 0x91,
280 ReportPhysicalAddress = 0x84,
281 SetMenuLanguage = 0x32,
282 DeckControl = 0x42,
283 DeckStatus = 0x1B,
284 GiveDeckStatus = 0x1A,
285 Play = 0x41,
286 GiveTunerDeviceStatus = 0x08,
287 SelectAnalogueService = 0x92,
288 SelectDigtalService = 0x93,
289 TunerDeviceStatus = 0x07,
290 TunerStepDecrement = 0x06,
291 TunerStepIncrement = 0x05,
292 DeviceVendorId = 0x87,
293 GiveDeviceVendorId = 0x8C,
294 VendorCommand = 0x89,
295 VendorCommandWithId = 0xA0,
296 VendorRemoteButtonDown = 0x8A,
297 VendorRemoteButtonUp = 0x8B,
298 SetOsdString = 0x64,
299 GiveOsdName = 0x46,
300 SetOsdName = 0x47,
301 MenuRequest = 0x8D,
302 MenuStatus = 0x8E,
303 UserControlPressed = 0x44,
304 UserControlRelease = 0x45,
305 GiveDevicePowerStatus = 0x8F,
306 ReportPowerStatus = 0x90,
307 FeatureAbort = 0x00,
308 Abort = 0xFF,
309 GiveAudioStatus = 0x71,
310 GiveSystemAudioMode = 0x7D,
311 ReportAudioStatus = 0x7A,
312 SetSystemAudioMode = 0x72,
313 SystemAudioModeRequest = 0x70,
314 SystemAudioModeStatus = 0x7E,
315 SetAudioRate = 0x9A,
316 /* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
317 None = 0xFD
318};
319
320public enum class CecSystemAudioStatus
321{
322 Off = 0,
323 On = 1
324};
325
326public ref class CecAdapter
327{
328public:
329 CecAdapter(String ^ strPath, String ^ strComPort)
330 {
331 Path = strPath;
332 ComPort = strComPort;
333 }
334
335 property String ^ Path;
336 property String ^ ComPort;
337};
338
339public ref class CecDeviceTypeList
340{
341public:
342 CecDeviceTypeList(void)
343 {
344 Types = gcnew array<CecDeviceType>(5);
345 for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
346 Types[iPtr] = CecDeviceType::Reserved;
347 }
348
349 property array<CecDeviceType> ^ Types;
350};
351
352public ref class CecLogicalAddresses
353{
354public:
355 CecLogicalAddresses(void)
356 {
357 Addresses = gcnew array<CecLogicalAddress>(16);
358 for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
359 Addresses[iPtr] = CecLogicalAddress::Unregistered;
360 }
361
362 bool IsSet(CecLogicalAddress iAddress)
363 {
364 return Addresses[(unsigned int)iAddress] != CecLogicalAddress::Unregistered;
365 }
366
367 property array<CecLogicalAddress> ^ Addresses;
368};
369
370public ref class CecDatapacket
371{
372public:
373 CecDatapacket(void)
374 {
375 Data = gcnew array<uint8_t>(100);
376 Size = 0;
377 }
378
379 void PushBack(uint8_t data)
380 {
381 if (Size < 100)
382 {
383 Data[Size] = data;
384 Size++;
385 }
386 }
387
388 property array<uint8_t> ^ Data;
389 property uint8_t Size;
390};
391
392public ref class CecCommand
393{
394public:
395 CecCommand(CecLogicalAddress iInitiator, CecLogicalAddress iDestination, bool bAck, bool bEom, CecOpcode iOpcode, int32_t iTransmitTimeout)
396 {
397 Initiator = iInitiator;
398 Destination = iDestination;
399 Ack = bAck;
400 Eom = bEom;
401 Opcode = iOpcode;
402 OpcodeSet = true;
403 TransmitTimeout = iTransmitTimeout;
404 Parameters = gcnew CecDatapacket;
405 Empty = false;
406 }
407
408 CecCommand(void)
409 {
410 Initiator = CecLogicalAddress::Unknown;
411 Destination = CecLogicalAddress::Unknown;
412 Ack = false;
413 Eom = false;
414 Opcode = CecOpcode::None;
415 OpcodeSet = false;
416 TransmitTimeout = 0;
417 Parameters = gcnew CecDatapacket;
418 Empty = true;
419 }
420
421 void PushBack(uint8_t data)
422 {
423 if (Initiator == CecLogicalAddress::Unknown && Destination == CecLogicalAddress::Unknown)
424 {
425 Initiator = (CecLogicalAddress) (data >> 4);
426 Destination = (CecLogicalAddress) (data & 0xF);
427 }
428 else if (!OpcodeSet)
429 {
430 OpcodeSet = true;
431 Opcode = (CecOpcode)data;
432 }
433 else
434 {
435 Parameters->PushBack(data);
436 }
437 }
438
439 property bool Empty;
440 property CecLogicalAddress Initiator;
441 property CecLogicalAddress Destination;
442 property bool Ack;
443 property bool Eom;
444 property CecOpcode Opcode;
445 property CecDatapacket ^ Parameters;
446 property bool OpcodeSet;
447 property int32_t TransmitTimeout;
448};
449
450public ref class CecKeypress
451{
452public:
453 CecKeypress(int iKeycode, unsigned int iDuration)
454 {
455 Keycode = iKeycode;
456 Duration = iDuration;
457 Empty = false;
458 }
459
460 CecKeypress(void)
461 {
462 Keycode = 0;
463 Duration = 0;
464 Empty = true;
465 }
466
467 property bool Empty;
468 property int Keycode;
469 property unsigned int Duration;
470};
471
472public ref class CecLogMessage
473{
474public:
475 CecLogMessage(String ^ strMessage, CecLogLevel iLevel, int64_t iTime)
476 {
477 Message = strMessage;
478 Level = iLevel;
479 Time = iTime;
480 Empty = false;
481 }
482
483 CecLogMessage(void)
484 {
485 Message = "";
486 Level = CecLogLevel::None;
487 Time = 0;
488 Empty = true;
489 }
490
491 property bool Empty;
492 property String ^ Message;
493 property CecLogLevel Level;
494 property int64_t Time;
495};
496
497public ref class CecCallbackMethods
498{
499public:
500 virtual int ReceiveLogMessage(CecLogMessage ^ message)
501 {
502 return 0;
503 }
504
505 virtual int ReceiveKeypress(CecKeypress ^ key)
506 {
507 return 0;
508 }
509
510 virtual int ReceiveCommand(CecCommand ^ command)
511 {
512 return 0;
513 }
514};
515
516#pragma unmanaged
517// unmanaged callback methods
518typedef int (__stdcall *LOGCB) (const cec_log_message &message);
519typedef int (__stdcall *KEYCB) (const cec_keypress &key);
520typedef int (__stdcall *COMMANDCB)(const cec_command &command);
521
522static LOGCB g_logCB;
523static KEYCB g_keyCB;
524static COMMANDCB g_commandCB;
525static ICECCallbacks g_cecCallbacks;
526
527int CecLogMessageCB(void *cbParam, const cec_log_message &message)
528{
529 if (g_logCB)
530 return g_logCB(message);
531 return 0;
532}
533
534int CecKeyPressCB(void *cbParam, const cec_keypress &key)
535{
536 if (g_keyCB)
537 return g_keyCB(key);
538 return 0;
539}
540
541int CecCommandCB(void *cbParam, const cec_command &command)
542{
543 if (g_commandCB)
544 return g_commandCB(command);
545 return 0;
546}
547
548#pragma managed
549// delegates for the unmanaged callback methods
550public delegate int CecLogMessageManagedDelegate(const cec_log_message &);
551public delegate int CecKeyPressManagedDelegate(const cec_keypress &);
552public delegate int CecCommandManagedDelegate(const cec_command &);
553
554public ref class LibCecSharp
555{
556public:
557 LibCecSharp(String ^ strDeviceName, CecDeviceTypeList ^ deviceTypes)
558 {
559 marshal_context ^ context = gcnew marshal_context();
560 m_bHasCallbacks = false;
561 const char* strDeviceNameC = context->marshal_as<const char*>(strDeviceName);
562
563 cec_device_type_list types;
564 for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
565 types.types[iPtr] = (cec_device_type)deviceTypes->Types[iPtr];
566 m_libCec = (ICECAdapter *) CECInit(strDeviceNameC, types);
567
568 // create the delegate method for the log message callback
569 m_logMessageDelegate = gcnew CecLogMessageManagedDelegate(this, &LibCecSharp::CecLogMessageManaged);
570 m_logMessageGCHandle = GCHandle::Alloc(m_logMessageDelegate);
571 g_logCB = static_cast<LOGCB>(Marshal::GetFunctionPointerForDelegate(m_logMessageDelegate).ToPointer());
572 g_cecCallbacks.CBCecLogMessage = CecLogMessageCB;
573
574 // create the delegate method for the keypress callback
575 m_keypressDelegate = gcnew CecKeyPressManagedDelegate(this, &LibCecSharp::CecKeyPressManaged);
576 m_keypressGCHandle = GCHandle::Alloc(m_keypressDelegate);
577 g_keyCB = static_cast<KEYCB>(Marshal::GetFunctionPointerForDelegate(m_keypressDelegate).ToPointer());
578 g_cecCallbacks.CBCecKeyPress = CecKeyPressCB;
579
580 // create the delegate method for the command callback
581 m_commandDelegate = gcnew CecCommandManagedDelegate(this, &LibCecSharp::CecCommandManaged);
582 m_commandGCHandle = GCHandle::Alloc(m_commandDelegate);
583 g_commandCB = static_cast<COMMANDCB>(Marshal::GetFunctionPointerForDelegate(m_commandDelegate).ToPointer());
584 g_cecCallbacks.CBCecCommand = CecCommandCB;
585
586 delete context;
587 }
588
589 ~LibCecSharp(void)
590 {
591 CECDestroy(m_libCec);
592 DestroyDelegates();
593 m_libCec = NULL;
594 }
595
596protected:
597 !LibCecSharp(void)
598 {
599 CECDestroy(m_libCec);
600 DestroyDelegates();
601 m_libCec = NULL;
602 }
603
604public:
605 array<CecAdapter ^> ^ FindAdapters(String ^ path)
606 {
607 cec_adapter *devices = new cec_adapter[10];
608
609 marshal_context ^ context = gcnew marshal_context();
610 const char* strPathC = path->Length > 0 ? context->marshal_as<const char*>(path) : NULL;
611
612 uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL);
613
614 array<CecAdapter ^> ^ adapters = gcnew array<CecAdapter ^>(iDevicesFound);
615 for (unsigned int iPtr = 0; iPtr < iDevicesFound; iPtr++)
616 adapters[iPtr] = gcnew CecAdapter(gcnew String(devices[iPtr].path), gcnew String(devices[iPtr].comm));
617
618 delete devices;
619 delete context;
620 return adapters;
621 }
622
623 bool Open(String ^ strPort, int iTimeoutMs)
624 {
625 marshal_context ^ context = gcnew marshal_context();
626 const char* strPortC = context->marshal_as<const char*>(strPort);
627 bool bReturn = m_libCec->Open(strPortC, iTimeoutMs);
628 delete context;
629 return bReturn;
630 }
631
632 void Close(void)
633 {
634 m_libCec->Close();
635 }
636
637 bool EnableCallbacks(CecCallbackMethods ^ callbacks)
638 {
639 if (m_libCec && !m_bHasCallbacks)
640 {
641 m_bHasCallbacks = true;
642 m_callbacks = callbacks;
643 return m_libCec->EnableCallbacks(NULL, &g_cecCallbacks);
644 }
645
646 return false;
647 }
648
649 bool PingAdapter(void)
650 {
651 return m_libCec->PingAdapter();
652 }
653
654 bool StartBootloader(void)
655 {
656 return m_libCec->StartBootloader();
657 }
658
659 int GetMinLibVersion(void)
660 {
661 return m_libCec->GetMinLibVersion();
662 }
663
664 int GetLibVersionMajor(void)
665 {
666 return m_libCec->GetLibVersionMajor();
667 }
668
669 int GetLibVersionMinor(void)
670 {
671 return m_libCec->GetLibVersionMinor();
672 }
673
674 CecLogMessage ^ GetNextLogMessage(void)
675 {
676 cec_log_message msg;
677 if (m_libCec->GetNextLogMessage(&msg))
678 {
679 return gcnew CecLogMessage(gcnew String(msg.message), (CecLogLevel)msg.level, msg.time);
680 }
681
682 return gcnew CecLogMessage();
683 }
684
685 CecKeypress ^ GetNextKeypress(void)
686 {
687 cec_keypress key;
688 if (m_libCec->GetNextKeypress(&key))
689 {
690 return gcnew CecKeypress(key.keycode, key.duration);
691 }
692
693 return gcnew CecKeypress();
694 }
695
696 CecCommand ^ GetNextCommand(void)
697 {
698 cec_command command;
699 if (m_libCec->GetNextCommand(&command))
700 {
701 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);
702 for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
703 retVal->Parameters->PushBack(command.parameters[iPtr]);
704 return retVal;
705 }
706
707 return gcnew CecCommand();
708 }
709
710 bool Transmit(CecCommand ^ command)
711 {
712 cec_command ccommand;
713 cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode);
714 ccommand.transmit_timeout = command->TransmitTimeout;
715 ccommand.eom = command->Eom;
716 ccommand.ack = command->Ack;
717 for (unsigned int iPtr = 0; iPtr < command->Parameters->Size; iPtr++)
718 ccommand.parameters.PushBack(command->Parameters->Data[iPtr]);
719
720 return m_libCec->Transmit(ccommand);
721 }
722
723 bool SetLogicalAddress(CecLogicalAddress logicalAddress)
724 {
725 return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress);
726 }
727
728 bool SetPhysicalAddress(int16_t physicalAddress)
729 {
730 return m_libCec->SetPhysicalAddress(physicalAddress);
731 }
732
733 bool PowerOnDevices(CecLogicalAddress logicalAddress)
734 {
735 return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress);
736 }
737
738 bool StandbyDevices(CecLogicalAddress logicalAddress)
739 {
740 return m_libCec->StandbyDevices((cec_logical_address) logicalAddress);
741 }
742
743 bool PollDevice(CecLogicalAddress logicalAddress)
744 {
745 return m_libCec->PollDevice((cec_logical_address) logicalAddress);
746 }
747
748 bool SetActiveSource(CecDeviceType type)
749 {
750 return m_libCec->SetActiveSource((cec_device_type) type);
751 }
752
753 bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate)
754 {
755 return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate);
756 }
757
758 bool SetDeckInfo(CecDeckInfo info, bool sendUpdate)
759 {
760 return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate);
761 }
762
763 bool SetInactiveView(void)
764 {
765 return m_libCec->SetInactiveView();
766 }
767
768 bool SetMenuState(CecMenuState state, bool sendUpdate)
769 {
770 return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate);
771 }
772
773 bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message)
774 {
775 marshal_context ^ context = gcnew marshal_context();
776 const char* strMessageC = context->marshal_as<const char*>(message);
777
778 bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC);
779
780 delete context;
781 return bReturn;
782 }
783
784 bool SwitchMonitoring(bool enable)
785 {
786 return m_libCec->SwitchMonitoring(enable);
787 }
788
789 CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress)
790 {
791 return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress);
792 }
793
794 String ^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress)
795 {
796 cec_menu_language lang;
797 if (m_libCec->GetDeviceMenuLanguage((cec_logical_address) logicalAddress, &lang))
798 {
799 return gcnew String(lang.language);
800 }
801
802 return gcnew String("");
803 }
804
805 CecVendorId GetDeviceVendorId(CecLogicalAddress logicalAddress)
806 {
807 return (CecVendorId)m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress);
808 }
809
810 CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress)
811 {
812 return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress);
813 }
814
815 CecLogicalAddresses ^ GetActiveDevices(void)
816 {
817 CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses();
818 unsigned int iDevices = 0;
819
820 cec_logical_addresses activeDevices = m_libCec->GetActiveDevices();
821
822 for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
823 if (activeDevices[iPtr])
824 retVal->Addresses[iDevices++] = (CecLogicalAddress)iPtr;
825
826 return retVal;
827 }
828
829 bool IsActiveDevice(CecLogicalAddress logicalAddress)
830 {
831 return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress);
832 }
833
834 bool IsActiveDeviceType(CecDeviceType type)
835 {
836 return m_libCec->IsActiveDeviceType((cec_device_type)type);
837 }
838
839 bool SetHDMIPort(CecLogicalAddress address, uint8_t port)
840 {
841 return m_libCec->SetHDMIPort((cec_logical_address)address, port);
842 }
843
844 uint8_t VolumeUp(bool wait)
845 {
846 return m_libCec->VolumeUp(wait);
847 }
848
849 uint8_t VolumeDown(bool wait)
850 {
851 return m_libCec->VolumeDown(wait);
852 }
853
854 uint8_t MuteAudio(bool wait)
855 {
856 return m_libCec->MuteAudio(wait);
857 }
858
859 bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait)
860 {
861 return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait);
862 }
863
864 bool SendKeyRelease(CecLogicalAddress destination, bool wait)
865 {
866 return m_libCec->SendKeyRelease((cec_logical_address)destination, wait);
867 }
868
869 String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress)
870 {
871 cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress);
872 return gcnew String(osd.name);
873 }
874
875 CecLogicalAddress GetActiveSource()
876 {
877 return (CecLogicalAddress)m_libCec->GetActiveSource();
878 }
879
880 bool IsActiveSource(CecLogicalAddress logicalAddress)
881 {
882 return m_libCec->IsActiveSource((cec_logical_address)logicalAddress);
883 }
884
885 uint16_t GetDevicePhysicalAddress(CecLogicalAddress iAddress)
886 {
887 return m_libCec->GetDevicePhysicalAddress((cec_logical_address)iAddress);
888 }
889
890 String ^ ToString(CecLogicalAddress iAddress)
891 {
892 const char *retVal = m_libCec->ToString((cec_logical_address)iAddress);
893 return gcnew String(retVal);
894 }
895
896 String ^ ToString(CecVendorId iVendorId)
897 {
898 const char *retVal = m_libCec->ToString((cec_vendor_id)iVendorId);
899 return gcnew String(retVal);
900 }
901
902 String ^ ToString(CecVersion iVersion)
903 {
904 const char *retVal = m_libCec->ToString((cec_version)iVersion);
905 return gcnew String(retVal);
906 }
907
908 String ^ ToString(CecPowerStatus iState)
909 {
910 const char *retVal = m_libCec->ToString((cec_power_status)iState);
911 return gcnew String(retVal);
912 }
913
914 String ^ ToString(CecMenuState iState)
915 {
916 const char *retVal = m_libCec->ToString((cec_menu_state)iState);
917 return gcnew String(retVal);
918 }
919
920 String ^ ToString(CecDeckControlMode iMode)
921 {
922 const char *retVal = m_libCec->ToString((cec_deck_control_mode)iMode);
923 return gcnew String(retVal);
924 }
925
926 String ^ ToString(CecDeckInfo status)
927 {
928 const char *retVal = m_libCec->ToString((cec_deck_info)status);
929 return gcnew String(retVal);
930 }
931
932 String ^ ToString(CecOpcode opcode)
933 {
934 const char *retVal = m_libCec->ToString((cec_opcode)opcode);
935 return gcnew String(retVal);
936 }
937
938 String ^ ToString(CecSystemAudioStatus mode)
939 {
940 const char *retVal = m_libCec->ToString((cec_system_audio_status)mode);
941 return gcnew String(retVal);
942 }
943
944 String ^ ToString(CecAudioStatus status)
945 {
946 const char *retVal = m_libCec->ToString((cec_audio_status)status);
947 return gcnew String(retVal);
948 }
949
950private:
951 void DestroyDelegates()
952 {
953 m_logMessageGCHandle.Free();
954 m_keypressGCHandle.Free();
955 m_commandGCHandle.Free();
956 }
957
958 // managed callback methods
959 int CecLogMessageManaged(const cec_log_message &message)
960 {
961 int iReturn(0);
962 if (m_bHasCallbacks)
963 iReturn = m_callbacks->ReceiveLogMessage(gcnew CecLogMessage(gcnew String(message.message), (CecLogLevel)message.level, message.time));
964 return iReturn;
965 }
966
967 int CecKeyPressManaged(const cec_keypress &key)
968 {
969 int iReturn(0);
970 if (m_bHasCallbacks)
971 iReturn = m_callbacks->ReceiveKeypress(gcnew CecKeypress(key.keycode, key.duration));
972 return iReturn;
973 }
974
975 int CecCommandManaged(const cec_command &command)
976 {
977 int iReturn(0);
978 if (m_bHasCallbacks)
979 {
980 CecCommand ^ newCommand = gcnew CecCommand((CecLogicalAddress)command.initiator, (CecLogicalAddress)command.destination, command.ack == 1 ? true : false, command.eom == 1 ? true : false, (CecOpcode)command.opcode, command.transmit_timeout);
981 for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
982 newCommand->Parameters->PushBack(command.parameters[iPtr]);
983 iReturn = m_callbacks->ReceiveCommand(newCommand);
984 }
985 return iReturn;
986 }
987
988 ICECAdapter * m_libCec;
989 CecCallbackMethods ^ m_callbacks;
990 bool m_bHasCallbacks;
991
992 CecLogMessageManagedDelegate ^ m_logMessageDelegate;
993 static GCHandle m_logMessageGCHandle;
994 LOGCB m_logMessageCallback;
995
996 CecKeyPressManagedDelegate ^ m_keypressDelegate;
997 static GCHandle m_keypressGCHandle;
998 KEYCB m_keypressCallback;
999
1000 CecCommandManagedDelegate ^ m_commandDelegate;
1001 static GCHandle m_commandGCHandle;
1002 COMMANDCB m_commandCallback;
1003};