673739a71d9e4ea1affcadabfa5058ad5b69dca9
[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 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 "stdafx.h"
34 #include <windows.h>
35 #include <vcclr.h>
36 #include <msclr/marshal.h>
37 #include <cec.h>
38 #using <System.dll>
39
40 using namespace System;
41 using namespace CEC;
42 using namespace msclr::interop;
43
44 public enum class CecDeviceType
45 {
46 Tv = 0,
47 RecordingDevice = 1,
48 Reserved = 2,
49 Tuner = 3,
50 PlaybackDevice = 4,
51 AudioSystem = 5
52 };
53
54 public 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
65 public 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
87 public enum class CecPowerStatus
88 {
89 On = 0x00,
90 Standby = 0x01,
91 InTransitionStandbyToOn = 0x02,
92 InTransitionOnToStandby = 0x03,
93 Unknown = 0x99
94 };
95
96 public 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
106 public enum class CecDisplayControl
107 {
108 DisplayForDefaultTime = 0x00,
109 DisplayUntilCleared = 0x40,
110 ClearPreviousMessage = 0x80,
111 ReservedForFutureUse = 0xC0
112 };
113
114 public enum class CecMenuState
115 {
116 Activated = 0,
117 Deactivated = 1
118 };
119
120 public enum class CecDeckControlMode
121 {
122 SkipForwardWind = 1,
123 SkipReverseRewind = 2,
124 Stop = 3,
125 Eject = 4
126 };
127
128 public 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
147 public 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
231 public ref class CecAdapter
232 {
233 public:
234 CecAdapter(String ^ strPath, String ^ strComPort)
235 {
236 Path = strPath;
237 ComPort = strComPort;
238 }
239
240 property String ^ Path;
241 property String ^ ComPort;
242 };
243
244 public ref class CecDeviceTypeList
245 {
246 public:
247 CecDeviceTypeList(void)
248 {
249 Types = gcnew array<CecDeviceType>(5);
250 for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
251 Types[iPtr] = CecDeviceType::Reserved;
252 }
253
254 property array<CecDeviceType> ^ Types;
255 };
256
257 public ref class CecLogicalAddresses
258 {
259 public:
260 CecLogicalAddresses(void)
261 {
262 Addresses = gcnew array<CecLogicalAddress>(16);
263 for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
264 Addresses[iPtr] = CecLogicalAddress::Unregistered;
265 }
266
267 property array<CecLogicalAddress> ^ Addresses;
268 };
269
270 public ref class CecDatapacket
271 {
272 public:
273 CecDatapacket(void)
274 {
275 Data = gcnew array<uint8_t>(100);
276 Size = 0;
277 }
278
279 void PushBack(uint8_t data)
280 {
281 if (Size < 100)
282 {
283 Data[Size] = data;
284 Size++;
285 }
286 }
287
288 property array<uint8_t> ^ Data;
289 property uint8_t Size;
290 };
291
292 public ref class CecCommand
293 {
294 public:
295 CecCommand(CecLogicalAddress iInitiator, CecLogicalAddress iDestination, bool bAck, bool bEom, int8_t iOpcode, int32_t iTransmitTimeout)
296 {
297 Initiator = iInitiator;
298 Destination = iDestination;
299 Ack = bAck;
300 Eom = bEom;
301 Opcode = iOpcode;
302 OpcodeSet = true;
303 TransmitTimeout = iTransmitTimeout;
304 Parameters = gcnew CecDatapacket;
305 Empty = false;
306 }
307
308 CecCommand(void)
309 {
310 Initiator = CecLogicalAddress::Unknown;
311 Destination = CecLogicalAddress::Unknown;
312 Ack = false;
313 Eom = false;
314 Opcode = 0;
315 OpcodeSet = false;
316 TransmitTimeout = 0;
317 Parameters = gcnew CecDatapacket;
318 Empty = true;
319 }
320
321 void PushBack(uint8_t data)
322 {
323 if (Initiator == CecLogicalAddress::Unknown && Destination == CecLogicalAddress::Unknown)
324 {
325 Initiator = (CecLogicalAddress) (data >> 4);
326 Destination = (CecLogicalAddress) (data & 0xF);
327 }
328 else if (!OpcodeSet)
329 {
330 OpcodeSet = true;
331 Opcode = data;
332 }
333 else
334 {
335 Parameters->PushBack(data);
336 }
337 }
338
339 property bool Empty;
340 property CecLogicalAddress Initiator;
341 property CecLogicalAddress Destination;
342 property bool Ack;
343 property bool Eom;
344 property int8_t Opcode;
345 property CecDatapacket ^ Parameters;
346 property bool OpcodeSet;
347 property int32_t TransmitTimeout;
348 };
349
350 public ref class CecKeypress
351 {
352 public:
353 CecKeypress(int iKeycode, unsigned int iDuration)
354 {
355 Keycode = iKeycode;
356 Duration = iDuration;
357 Empty = false;
358 }
359
360 CecKeypress(void)
361 {
362 Keycode = 0;
363 Duration = 0;
364 Empty = true;
365 }
366
367 property bool Empty;
368 property int Keycode;
369 property unsigned int Duration;
370 };
371
372 public ref class CecLogMessage
373 {
374 public:
375 CecLogMessage(String ^ strMessage, CecLogLevel iLevel, int64_t iTime)
376 {
377 Message = strMessage;
378 Level = iLevel;
379 Time = iTime;
380 Empty = false;
381 }
382
383 CecLogMessage(void)
384 {
385 Message = "";
386 Level = CecLogLevel::None;
387 Time = 0;
388 Empty = true;
389 }
390
391 property bool Empty;
392 property String ^ Message;
393 property CecLogLevel Level;
394 property int64_t Time;
395 };
396
397 public ref class LibCecSharp
398 {
399 public:
400 LibCecSharp(String ^ strDeviceName, CecDeviceTypeList ^ deviceTypes)
401 {
402 marshal_context ^ context = gcnew marshal_context();
403
404 const char* strDeviceNameC = context->marshal_as<const char*>(strDeviceName);
405
406 cec_device_type_list types;
407 for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
408 types.types[iPtr] = (cec_device_type)deviceTypes->Types[iPtr];
409 m_libCec = (ICECAdapter *) CECInit(strDeviceNameC, types);
410 delete context;
411 }
412
413 ~LibCecSharp(void)
414 {
415 CECDestroy(m_libCec);
416 m_libCec = NULL;
417 }
418
419 protected:
420 !LibCecSharp(void)
421 {
422 CECDestroy(m_libCec);
423 m_libCec = NULL;
424 }
425
426 public:
427 array<CecAdapter ^> ^ FindAdapters(String ^ path)
428 {
429 cec_adapter *devices = new cec_adapter[10];
430
431 marshal_context ^ context = gcnew marshal_context();
432 const char* strPathC = path->Length > 0 ? context->marshal_as<const char*>(path) : NULL;
433
434 uint8_t iDevicesFound = m_libCec->FindAdapters(devices, 10, NULL);
435
436 array<CecAdapter ^> ^ adapters = gcnew array<CecAdapter ^>(iDevicesFound);
437 for (unsigned int iPtr = 0; iPtr < iDevicesFound; iPtr++)
438 adapters[iPtr] = gcnew CecAdapter(gcnew String(devices[iPtr].path), gcnew String(devices[iPtr].comm));
439
440 delete devices;
441 delete context;
442 return adapters;
443 }
444
445 bool Open(String ^ strPort, int iTimeoutMs)
446 {
447 marshal_context ^ context = gcnew marshal_context();
448 const char* strPortC = context->marshal_as<const char*>(strPort);
449 bool bReturn = m_libCec->Open(strPortC, iTimeoutMs);
450 delete context;
451 return bReturn;
452 }
453
454 void Close(void)
455 {
456 m_libCec->Close();
457 }
458
459 bool PingAdapter(void)
460 {
461 return m_libCec->PingAdapter();
462 }
463
464 bool StartBootloader(void)
465 {
466 return m_libCec->StartBootloader();
467 }
468
469 int GetMinLibVersion(void)
470 {
471 return m_libCec->GetMinLibVersion();
472 }
473
474 int GetLibVersionMajor(void)
475 {
476 return m_libCec->GetLibVersionMajor();
477 }
478
479 int GetLibVersionMinor(void)
480 {
481 return m_libCec->GetLibVersionMinor();
482 }
483
484 CecLogMessage ^ GetNextLogMessage(void)
485 {
486 cec_log_message msg;
487 if (m_libCec->GetNextLogMessage(&msg))
488 {
489 return gcnew CecLogMessage(gcnew String(msg.message), (CecLogLevel)msg.level, msg.time);
490 }
491
492 return gcnew CecLogMessage();
493 }
494
495 CecKeypress ^ GetNextKeypress(void)
496 {
497 cec_keypress key;
498 if (m_libCec->GetNextKeypress(&key))
499 {
500 return gcnew CecKeypress(key.keycode, key.duration);
501 }
502
503 return gcnew CecKeypress();
504 }
505
506 CecCommand ^ GetNextCommand(void)
507 {
508 cec_command command;
509 if (m_libCec->GetNextCommand(&command))
510 {
511 CecCommand ^ retVal = gcnew CecCommand((CecLogicalAddress)command.initiator, (CecLogicalAddress)command.destination, command.ack == 1 ? true : false, command.eom == 1 ? true : false, command.opcode, command.transmit_timeout);
512 for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
513 retVal->Parameters->PushBack(command.parameters[iPtr]);
514 return retVal;
515 }
516
517 return gcnew CecCommand();
518 }
519
520 bool Transmit(CecCommand ^ command)
521 {
522 cec_command ccommand;
523 cec_command::Format(ccommand, (cec_logical_address)command->Initiator, (cec_logical_address)command->Destination, (cec_opcode)command->Opcode);
524 ccommand.transmit_timeout = command->TransmitTimeout;
525 ccommand.eom = command->Eom;
526 ccommand.ack = command->Ack;
527 for (unsigned int iPtr = 0; iPtr < command->Parameters->Size; iPtr++)
528 ccommand.parameters.PushBack(command->Parameters->Data[iPtr]);
529
530 return m_libCec->Transmit(ccommand);
531 }
532
533 bool SetLogicalAddress(CecLogicalAddress logicalAddress)
534 {
535 return m_libCec->SetLogicalAddress((cec_logical_address) logicalAddress);
536 }
537
538 bool SetPhysicalAddress(int16_t physicalAddress)
539 {
540 return m_libCec->SetPhysicalAddress(physicalAddress);
541 }
542
543 bool PowerOnDevices(CecLogicalAddress logicalAddress)
544 {
545 return m_libCec->PowerOnDevices((cec_logical_address) logicalAddress);
546 }
547
548 bool StandbyDevices(CecLogicalAddress logicalAddress)
549 {
550 return m_libCec->StandbyDevices((cec_logical_address) logicalAddress);
551 }
552
553 bool PollDevice(CecLogicalAddress logicalAddress)
554 {
555 return m_libCec->PollDevice((cec_logical_address) logicalAddress);
556 }
557
558 bool SetActiveSource(CecDeviceType type)
559 {
560 return m_libCec->SetActiveSource((cec_device_type) type);
561 }
562
563 bool SetDeckControlMode(CecDeckControlMode mode, bool sendUpdate)
564 {
565 return m_libCec->SetDeckControlMode((cec_deck_control_mode) mode, sendUpdate);
566 }
567
568 bool SetDeckInfo(CecDeckInfo info, bool sendUpdate)
569 {
570 return m_libCec->SetDeckInfo((cec_deck_info) info, sendUpdate);
571 }
572
573 bool SetInactiveView(void)
574 {
575 return m_libCec->SetInactiveView();
576 }
577
578 bool SetMenuState(CecMenuState state, bool sendUpdate)
579 {
580 return m_libCec->SetMenuState((cec_menu_state) state, sendUpdate);
581 }
582
583 bool SetOSDString(CecLogicalAddress logicalAddress, CecDisplayControl duration, String ^ message)
584 {
585 marshal_context ^ context = gcnew marshal_context();
586 const char* strMessageC = context->marshal_as<const char*>(message);
587
588 bool bReturn = m_libCec->SetOSDString((cec_logical_address) logicalAddress, (cec_display_control) duration, strMessageC);
589
590 delete context;
591 return bReturn;
592 }
593
594 bool SwitchMonitoring(bool enable)
595 {
596 return m_libCec->SwitchMonitoring(enable);
597 }
598
599 CecVersion GetDeviceCecVersion(CecLogicalAddress logicalAddress)
600 {
601 return (CecVersion) m_libCec->GetDeviceCecVersion((cec_logical_address) logicalAddress);
602 }
603
604 String ^ GetDeviceMenuLanguage(CecLogicalAddress logicalAddress)
605 {
606 cec_menu_language lang;
607 if (m_libCec->GetDeviceMenuLanguage((cec_logical_address) logicalAddress, &lang))
608 {
609 return gcnew String(lang.language);
610 }
611
612 return gcnew String("");
613 }
614
615 uint64_t GetDeviceVendorId(CecLogicalAddress logicalAddress)
616 {
617 return m_libCec->GetDeviceVendorId((cec_logical_address) logicalAddress);
618 }
619
620 CecPowerStatus GetDevicePowerStatus(CecLogicalAddress logicalAddress)
621 {
622 return (CecPowerStatus) m_libCec->GetDevicePowerStatus((cec_logical_address) logicalAddress);
623 }
624
625 CecLogicalAddresses ^ GetActiveDevices(void)
626 {
627 CecLogicalAddresses ^ retVal = gcnew CecLogicalAddresses();
628 unsigned int iDevices = 0;
629
630 cec_logical_addresses activeDevices = m_libCec->GetActiveDevices();
631
632 for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
633 if (activeDevices[iPtr])
634 retVal->Addresses[iDevices++] = (CecLogicalAddress)iPtr;
635
636 return retVal;
637 }
638
639 bool IsActiveDevice(CecLogicalAddress logicalAddress)
640 {
641 return m_libCec->IsActiveDevice((cec_logical_address)logicalAddress);
642 }
643
644 bool IsActiveDeviceType(CecDeviceType type)
645 {
646 return m_libCec->IsActiveDeviceType((cec_device_type)type);
647 }
648
649 bool SetHDMIPort(CecLogicalAddress address, uint8_t port)
650 {
651 return m_libCec->SetHDMIPort((cec_logical_address)address, port);
652 }
653
654 uint8_t VolumeUp(bool wait)
655 {
656 return m_libCec->VolumeUp(wait);
657 }
658
659 uint8_t VolumeDown(bool wait)
660 {
661 return m_libCec->VolumeDown(wait);
662 }
663
664 uint8_t MuteAudio(bool wait)
665 {
666 return m_libCec->MuteAudio(wait);
667 }
668
669 bool SendKeypress(CecLogicalAddress destination, CecUserControlCode key, bool wait)
670 {
671 return m_libCec->SendKeypress((cec_logical_address)destination, (cec_user_control_code)key, wait);
672 }
673
674 bool SendKeyRelease(CecLogicalAddress destination, bool wait)
675 {
676 return m_libCec->SendKeyRelease((cec_logical_address)destination, wait);
677 }
678
679 String ^ GetDeviceOSDName(CecLogicalAddress logicalAddress)
680 {
681 cec_osd_name osd = m_libCec->GetDeviceOSDName((cec_logical_address) logicalAddress);
682 return gcnew String(osd.name);
683 }
684
685 CecLogicalAddress GetActiveSource()
686 {
687 return (CecLogicalAddress)m_libCec->GetActiveSource();
688 }
689
690 bool IsActiveSource(CecLogicalAddress logicalAddress)
691 {
692 return m_libCec->IsActiveSource((cec_logical_address)logicalAddress);
693 }
694
695 private:
696 ICECAdapter *m_libCec;
697 };