f8607004e50c257ed01a3ebc50c485ab2c89d2fb
[deb_libcec.git] / src / lib / LibCEC.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 "LibCEC.h"
34
35 #include "adapter/USBCECAdapterDetection.h"
36 #include "adapter/USBCECAdapterCommunication.h"
37 #include "CECProcessor.h"
38 #include "devices/CECAudioSystem.h"
39 #include "devices/CECBusDevice.h"
40 #include "devices/CECPlaybackDevice.h"
41 #include "devices/CECTV.h"
42 #include "platform/util/timeutils.h"
43 #include "platform/util/StdString.h"
44
45 #include "CECClient.h"
46
47 using namespace std;
48 using namespace CEC;
49 using namespace PLATFORM;
50
51 CLibCEC::CLibCEC(void) :
52 m_client(NULL),
53 m_iStartTime(GetTimeMs())
54 {
55 m_cec = new CCECProcessor(this);
56 }
57
58 CLibCEC::~CLibCEC(void)
59 {
60 delete m_client;
61 m_client = NULL;
62 delete m_cec;
63 m_cec = NULL;
64 }
65
66 bool CLibCEC::Open(const char *strPort, uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */)
67 {
68 if (m_cec->IsRunning())
69 {
70 AddLog(CEC_LOG_ERROR, "connection already open");
71 return false;
72 }
73
74 if (!m_cec->Start(strPort, CEC_SERIAL_DEFAULT_BAUDRATE, iTimeoutMs))
75 {
76 AddLog(CEC_LOG_ERROR, "could not start CEC communications");
77 return false;
78 }
79
80 for (vector<CCECClient *>::iterator it = m_clients.begin(); it != m_clients.end(); it++)
81 {
82 if (!m_cec->RegisterClient(*it))
83 {
84 AddLog(CEC_LOG_ERROR, "failed to register a CEC client");
85 return false;
86 }
87 }
88
89 return true;
90 }
91
92 void CLibCEC::Close(void)
93 {
94 m_clients.clear();
95
96 if (m_client)
97 {
98 delete m_client;
99 m_client = NULL;
100 }
101 if (m_cec)
102 {
103 delete m_cec;
104 m_cec = NULL;
105 }
106 }
107
108 int8_t CLibCEC::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
109 {
110 return CUSBCECAdapterDetection::FindAdapters(deviceList, iBufSize, strDevicePath);
111 }
112
113 bool CLibCEC::PingAdapter(void)
114 {
115 return m_cec ? m_cec->PingAdapter() : false;
116 }
117
118 bool CLibCEC::StartBootloader(void)
119 {
120 return m_cec ? m_cec->StartBootloader() : false;
121 }
122
123 bool CLibCEC::SwitchMonitoring(bool bEnable)
124 {
125 return m_cec ? m_cec->SwitchMonitoring(bEnable) : false;
126 }
127
128 cec_logical_address CLibCEC::GetActiveSource(void)
129 {
130 return m_cec ? m_cec->GetActiveSource() : CECDEVICE_UNKNOWN;
131 }
132
133 bool CLibCEC::IsActiveSource(cec_logical_address iAddress)
134 {
135 return m_cec ? m_cec->IsActiveSource(iAddress) : false;
136 }
137
138 bool CLibCEC::PollDevice(cec_logical_address iAddress)
139 {
140 return m_cec ? m_cec->PollDevice(iAddress) : false;
141 }
142
143 cec_logical_addresses CLibCEC::GetActiveDevices(void)
144 {
145 CECDEVICEVEC activeDevices;
146 if (m_cec)
147 m_cec->GetDevices()->GetActive(activeDevices);
148 return CCECDeviceMap::ToLogicalAddresses(activeDevices);
149 }
150
151 bool CLibCEC::IsActiveDevice(cec_logical_address iAddress)
152 {
153 cec_logical_addresses activeDevices = GetActiveDevices();
154 return activeDevices.IsSet(iAddress);
155 }
156
157 bool CLibCEC::IsActiveDeviceType(cec_device_type type)
158 {
159 CECDEVICEVEC activeDevices;
160 if (m_cec)
161 m_cec->GetDevices()->GetActive(activeDevices);
162 CCECDeviceMap::FilterType(type, activeDevices);
163 return !activeDevices.empty();
164 }
165
166 bool CLibCEC::SetStreamPath(cec_logical_address iAddress)
167 {
168 uint16_t iPhysicalAddress = GetDevicePhysicalAddress(iAddress);
169 if (iPhysicalAddress != CEC_INVALID_PHYSICAL_ADDRESS)
170 return SetStreamPath(iPhysicalAddress);
171 return false;
172 }
173
174 bool CLibCEC::SetStreamPath(uint16_t iPhysicalAddress)
175 {
176 return m_cec->SetStreamPath(iPhysicalAddress);
177 }
178
179 bool CLibCEC::IsLibCECActiveSource(void)
180 {
181 bool bReturn(false);
182 if (m_cec)
183 {
184 cec_logical_address activeSource = m_cec->GetActiveSource();
185 CCECBusDevice *device = m_cec->GetDevice(activeSource);
186 if (device)
187 bReturn = device->IsHandledByLibCEC();
188 }
189 return bReturn;
190 }
191
192 bool CLibCEC::CanPersistConfiguration(void)
193 {
194 return m_cec->CanPersistConfiguration();
195 }
196
197 bool CLibCEC::PersistConfiguration(libcec_configuration *configuration)
198 {
199 return m_cec->PersistConfiguration(configuration);
200 }
201
202 void CLibCEC::RescanActiveDevices(void)
203 {
204 return m_cec->RescanActiveDevices();
205 }
206
207 bool CLibCEC::EnableCallbacks(void *cbParam, ICECCallbacks *callbacks)
208 {
209 return m_client ? m_client->EnableCallbacks(cbParam, callbacks) : false;
210 }
211
212 bool CLibCEC::GetCurrentConfiguration(libcec_configuration *configuration)
213 {
214 return m_client ? m_client->GetCurrentConfiguration(configuration) : false;
215 }
216
217 bool CLibCEC::SetConfiguration(const libcec_configuration *configuration)
218 {
219 return m_client ? m_client->SetConfiguration(configuration) : false;
220 }
221
222 bool CLibCEC::Transmit(const cec_command &data)
223 {
224 return m_client ? m_client->Transmit(data) : false;
225 }
226
227 bool CLibCEC::SetLogicalAddress(cec_logical_address iLogicalAddress)
228 {
229 return m_client ? m_client->SetLogicalAddress(iLogicalAddress) : false;
230 }
231
232 bool CLibCEC::SetPhysicalAddress(uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
233 {
234 return m_client ? m_client->SetPhysicalAddress(iPhysicalAddress) : false;
235 }
236
237 bool CLibCEC::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort /* = CEC_DEFAULT_HDMI_PORT */)
238 {
239 return m_client ? m_client->SetHDMIPort(iBaseDevice, iPort) : false;
240 }
241
242 bool CLibCEC::PowerOnDevices(cec_logical_address address /* = CECDEVICE_TV */)
243 {
244 return m_client ? m_client->SendPowerOnDevices(address) : false;
245 }
246
247 bool CLibCEC::StandbyDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
248 {
249 return m_client ? m_client->SendStandbyDevices(address) : false;
250 }
251
252 bool CLibCEC::SetActiveSource(cec_device_type type /* = CEC_DEVICE_TYPE_RESERVED */)
253 {
254 return m_client ? m_client->SendSetActiveSource(type) : false;
255 }
256
257 bool CLibCEC::SetDeckControlMode(cec_deck_control_mode mode, bool bSendUpdate /* = true */)
258 {
259 return m_client ? m_client->SendSetDeckControlMode(mode, bSendUpdate) : false;
260 }
261
262 bool CLibCEC::SetDeckInfo(cec_deck_info info, bool bSendUpdate /* = true */)
263 {
264 return m_client ? m_client->SendSetDeckInfo(info, bSendUpdate) : false;
265 }
266
267 bool CLibCEC::SetInactiveView(void)
268 {
269 return m_client ? m_client->SendSetInactiveView() : false;
270 }
271
272 bool CLibCEC::SetMenuState(cec_menu_state state, bool bSendUpdate /* = true */)
273 {
274 return m_client ? m_client->SendSetMenuState(state, bSendUpdate) : false;
275 }
276
277 bool CLibCEC::SetOSDString(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage)
278 {
279 return m_client ? m_client->SendSetOSDString(iLogicalAddress, duration, strMessage) : false;
280 }
281
282 cec_version CLibCEC::GetDeviceCecVersion(cec_logical_address iAddress)
283 {
284 return m_client ? m_client->GetDeviceCecVersion(iAddress) : CEC_VERSION_UNKNOWN;
285 }
286
287 bool CLibCEC::GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language)
288 {
289 return m_client ? m_client->GetDeviceMenuLanguage(iAddress, language) : false;
290 }
291
292 uint64_t CLibCEC::GetDeviceVendorId(cec_logical_address iAddress)
293 {
294 return m_client ? m_client->GetDeviceVendorId(iAddress) : (uint64_t)CEC_VENDOR_UNKNOWN;
295 }
296
297 uint16_t CLibCEC::GetDevicePhysicalAddress(cec_logical_address iAddress)
298 {
299 return m_client ? m_client->GetDevicePhysicalAddress(iAddress) : CEC_INVALID_PHYSICAL_ADDRESS;
300 }
301
302 cec_power_status CLibCEC::GetDevicePowerStatus(cec_logical_address iAddress)
303 {
304 return m_client ? m_client->GetDevicePowerStatus(iAddress) : CEC_POWER_STATUS_UNKNOWN;
305 }
306
307 uint8_t CLibCEC::VolumeUp(bool bSendRelease /* = true */)
308 {
309 return m_client ? m_client->SendVolumeUp(bSendRelease) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
310 }
311
312 uint8_t CLibCEC::VolumeDown(bool bSendRelease /* = true */)
313 {
314 return m_client ? m_client->SendVolumeDown(bSendRelease) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
315 }
316
317 uint8_t CLibCEC::MuteAudio(bool UNUSED(bSendRelease) /* = true */)
318 {
319 return m_client ? m_client->SendMuteAudio() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
320 }
321
322 bool CLibCEC::SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = true */)
323 {
324 return m_client ? m_client->SendKeypress(iDestination, key, bWait) : false;
325 }
326
327 bool CLibCEC::SendKeyRelease(cec_logical_address iDestination, bool bWait /* = true */)
328 {
329 return m_client ? m_client->SendKeyRelease(iDestination, bWait) : false;
330 }
331
332 cec_osd_name CLibCEC::GetDeviceOSDName(cec_logical_address iAddress)
333 {
334 cec_osd_name retVal;
335 if (m_client)
336 retVal = m_client->GetDeviceOSDName(iAddress);
337 return retVal;
338 }
339
340 cec_logical_addresses CLibCEC::GetLogicalAddresses(void)
341 {
342 cec_logical_addresses addresses;
343 if (m_cec)
344 addresses = m_cec->GetLogicalAddresses();
345 return addresses;
346 }
347
348 bool CLibCEC::GetNextLogMessage(cec_log_message *message)
349 {
350 return m_client ? m_client->GetNextLogMessage(message) : false;
351 }
352
353 bool CLibCEC::GetNextKeypress(cec_keypress *key)
354 {
355 return m_client ? m_client->GetNextKeypress(key) : false;
356 }
357
358 bool CLibCEC::GetNextCommand(cec_command *command)
359 {
360 return m_client ? m_client->GetNextCommand(command) : false;
361 }
362
363 cec_device_type CLibCEC::GetType(cec_logical_address address)
364 {
365 switch (address)
366 {
367 case CECDEVICE_AUDIOSYSTEM:
368 return CEC_DEVICE_TYPE_AUDIO_SYSTEM;
369 case CECDEVICE_PLAYBACKDEVICE1:
370 case CECDEVICE_PLAYBACKDEVICE2:
371 case CECDEVICE_PLAYBACKDEVICE3:
372 return CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
373 case CECDEVICE_RECORDINGDEVICE1:
374 case CECDEVICE_RECORDINGDEVICE2:
375 case CECDEVICE_RECORDINGDEVICE3:
376 return CEC_DEVICE_TYPE_RECORDING_DEVICE;
377 case CECDEVICE_TUNER1:
378 case CECDEVICE_TUNER2:
379 case CECDEVICE_TUNER3:
380 case CECDEVICE_TUNER4:
381 return CEC_DEVICE_TYPE_TUNER;
382 case CECDEVICE_TV:
383 return CEC_DEVICE_TYPE_TV;
384 default:
385 return CEC_DEVICE_TYPE_RESERVED;
386 }
387 }
388
389 uint16_t CLibCEC::GetMaskForType(cec_logical_address address)
390 {
391 return GetMaskForType(GetType(address));
392 }
393
394 uint16_t CLibCEC::GetMaskForType(cec_device_type type)
395 {
396 switch (type)
397 {
398 case CEC_DEVICE_TYPE_AUDIO_SYSTEM:
399 {
400 cec_logical_addresses addr;
401 addr.Clear();
402 addr.Set(CECDEVICE_AUDIOSYSTEM);
403 return addr.AckMask();
404 }
405 case CEC_DEVICE_TYPE_PLAYBACK_DEVICE:
406 {
407 cec_logical_addresses addr;
408 addr.Clear();
409 addr.Set(CECDEVICE_PLAYBACKDEVICE1);
410 addr.Set(CECDEVICE_PLAYBACKDEVICE2);
411 addr.Set(CECDEVICE_PLAYBACKDEVICE3);
412 return addr.AckMask();
413 }
414 case CEC_DEVICE_TYPE_RECORDING_DEVICE:
415 {
416 cec_logical_addresses addr;
417 addr.Clear();
418 addr.Set(CECDEVICE_RECORDINGDEVICE1);
419 addr.Set(CECDEVICE_RECORDINGDEVICE2);
420 addr.Set(CECDEVICE_RECORDINGDEVICE3);
421 return addr.AckMask();
422 }
423 case CEC_DEVICE_TYPE_TUNER:
424 {
425 cec_logical_addresses addr;
426 addr.Clear();
427 addr.Set(CECDEVICE_TUNER1);
428 addr.Set(CECDEVICE_TUNER2);
429 addr.Set(CECDEVICE_TUNER3);
430 addr.Set(CECDEVICE_TUNER4);
431 return addr.AckMask();
432 }
433 case CEC_DEVICE_TYPE_TV:
434 {
435 cec_logical_addresses addr;
436 addr.Clear();
437 addr.Set(CECDEVICE_TV);
438 return addr.AckMask();
439 }
440 default:
441 return 0;
442 }
443 }
444
445 bool CLibCEC::IsValidPhysicalAddress(uint16_t iPhysicalAddress)
446 {
447 return iPhysicalAddress >= CEC_MIN_PHYSICAL_ADDRESS &&
448 iPhysicalAddress <= CEC_MAX_PHYSICAL_ADDRESS;
449 }
450
451 const char *CLibCEC::ToString(const cec_device_type type)
452 {
453 switch (type)
454 {
455 case CEC_DEVICE_TYPE_AUDIO_SYSTEM:
456 return "audio system";
457 case CEC_DEVICE_TYPE_PLAYBACK_DEVICE:
458 return "playback device";
459 case CEC_DEVICE_TYPE_RECORDING_DEVICE:
460 return "recording device";
461 case CEC_DEVICE_TYPE_RESERVED:
462 return "reserved";
463 case CEC_DEVICE_TYPE_TUNER:
464 return "tuner";
465 case CEC_DEVICE_TYPE_TV:
466 return "TV";
467 default:
468 return "unknown";
469 }
470 }
471
472 const char *CLibCEC::ToString(const cec_menu_state state)
473 {
474 switch (state)
475 {
476 case CEC_MENU_STATE_ACTIVATED:
477 return "activated";
478 case CEC_MENU_STATE_DEACTIVATED:
479 return "deactivated";
480 default:
481 return "unknown";
482 }
483 }
484
485 const char *CLibCEC::ToString(const cec_version version)
486 {
487 switch (version)
488 {
489 case CEC_VERSION_1_2:
490 return "1.2";
491 case CEC_VERSION_1_2A:
492 return "1.2a";
493 case CEC_VERSION_1_3:
494 return "1.3";
495 case CEC_VERSION_1_3A:
496 return "1.3a";
497 case CEC_VERSION_1_4:
498 return "1.4";
499 default:
500 return "unknown";
501 }
502 }
503
504 const char *CLibCEC::ToString(const cec_power_status status)
505 {
506 switch (status)
507 {
508 case CEC_POWER_STATUS_ON:
509 return "on";
510 case CEC_POWER_STATUS_STANDBY:
511 return "standby";
512 case CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY:
513 return "in transition from on to standby";
514 case CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON:
515 return "in transition from standby to on";
516 default:
517 return "unknown";
518 }
519 }
520
521 const char *CLibCEC::ToString(const cec_logical_address address)
522 {
523 switch(address)
524 {
525 case CECDEVICE_AUDIOSYSTEM:
526 return "Audio";
527 case CECDEVICE_BROADCAST:
528 return "Broadcast";
529 case CECDEVICE_FREEUSE:
530 return "Free use";
531 case CECDEVICE_PLAYBACKDEVICE1:
532 return "Playback 1";
533 case CECDEVICE_PLAYBACKDEVICE2:
534 return "Playback 2";
535 case CECDEVICE_PLAYBACKDEVICE3:
536 return "Playback 3";
537 case CECDEVICE_RECORDINGDEVICE1:
538 return "Recorder 1";
539 case CECDEVICE_RECORDINGDEVICE2:
540 return "Recorder 2";
541 case CECDEVICE_RECORDINGDEVICE3:
542 return "Recorder 3";
543 case CECDEVICE_RESERVED1:
544 return "Reserved 1";
545 case CECDEVICE_RESERVED2:
546 return "Reserved 2";
547 case CECDEVICE_TUNER1:
548 return "Tuner 1";
549 case CECDEVICE_TUNER2:
550 return "Tuner 2";
551 case CECDEVICE_TUNER3:
552 return "Tuner 3";
553 case CECDEVICE_TUNER4:
554 return "Tuner 4";
555 case CECDEVICE_TV:
556 return "TV";
557 default:
558 return "unknown";
559 }
560 }
561
562 const char *CLibCEC::ToString(const cec_deck_control_mode mode)
563 {
564 switch (mode)
565 {
566 case CEC_DECK_CONTROL_MODE_SKIP_FORWARD_WIND:
567 return "skip forward wind";
568 case CEC_DECK_CONTROL_MODE_EJECT:
569 return "eject";
570 case CEC_DECK_CONTROL_MODE_SKIP_REVERSE_REWIND:
571 return "reverse rewind";
572 case CEC_DECK_CONTROL_MODE_STOP:
573 return "stop";
574 default:
575 return "unknown";
576 }
577 }
578
579 const char *CLibCEC::ToString(const cec_deck_info status)
580 {
581 switch (status)
582 {
583 case CEC_DECK_INFO_PLAY:
584 return "play";
585 case CEC_DECK_INFO_RECORD:
586 return "record";
587 case CEC_DECK_INFO_PLAY_REVERSE:
588 return "play reverse";
589 case CEC_DECK_INFO_STILL:
590 return "still";
591 case CEC_DECK_INFO_SLOW:
592 return "slow";
593 case CEC_DECK_INFO_SLOW_REVERSE:
594 return "slow reverse";
595 case CEC_DECK_INFO_FAST_FORWARD:
596 return "fast forward";
597 case CEC_DECK_INFO_FAST_REVERSE:
598 return "fast reverse";
599 case CEC_DECK_INFO_NO_MEDIA:
600 return "no media";
601 case CEC_DECK_INFO_STOP:
602 return "stop";
603 case CEC_DECK_INFO_SKIP_FORWARD_WIND:
604 return "info skip forward wind";
605 case CEC_DECK_INFO_SKIP_REVERSE_REWIND:
606 return "info skip reverse rewind";
607 case CEC_DECK_INFO_INDEX_SEARCH_FORWARD:
608 return "info index search forward";
609 case CEC_DECK_INFO_INDEX_SEARCH_REVERSE:
610 return "info index search reverse";
611 case CEC_DECK_INFO_OTHER_STATUS:
612 return "other";
613 case CEC_DECK_INFO_OTHER_STATUS_LG:
614 return "LG other";
615 default:
616 return "unknown";
617 }
618 }
619
620 const char *CLibCEC::ToString(const cec_opcode opcode)
621 {
622 switch (opcode)
623 {
624 case CEC_OPCODE_ACTIVE_SOURCE:
625 return "active source";
626 case CEC_OPCODE_IMAGE_VIEW_ON:
627 return "image view on";
628 case CEC_OPCODE_TEXT_VIEW_ON:
629 return "text view on";
630 case CEC_OPCODE_INACTIVE_SOURCE:
631 return "inactive source";
632 case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
633 return "request active source";
634 case CEC_OPCODE_ROUTING_CHANGE:
635 return "routing change";
636 case CEC_OPCODE_ROUTING_INFORMATION:
637 return "routing information";
638 case CEC_OPCODE_SET_STREAM_PATH:
639 return "set stream path";
640 case CEC_OPCODE_STANDBY:
641 return "standby";
642 case CEC_OPCODE_RECORD_OFF:
643 return "record off";
644 case CEC_OPCODE_RECORD_ON:
645 return "record on";
646 case CEC_OPCODE_RECORD_STATUS:
647 return "record status";
648 case CEC_OPCODE_RECORD_TV_SCREEN:
649 return "record tv screen";
650 case CEC_OPCODE_CLEAR_ANALOGUE_TIMER:
651 return "clear analogue timer";
652 case CEC_OPCODE_CLEAR_DIGITAL_TIMER:
653 return "clear digital timer";
654 case CEC_OPCODE_CLEAR_EXTERNAL_TIMER:
655 return "clear external timer";
656 case CEC_OPCODE_SET_ANALOGUE_TIMER:
657 return "set analogue timer";
658 case CEC_OPCODE_SET_DIGITAL_TIMER:
659 return "set digital timer";
660 case CEC_OPCODE_SET_EXTERNAL_TIMER:
661 return "set external timer";
662 case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE:
663 return "set timer program title";
664 case CEC_OPCODE_TIMER_CLEARED_STATUS:
665 return "timer cleared status";
666 case CEC_OPCODE_TIMER_STATUS:
667 return "timer status";
668 case CEC_OPCODE_CEC_VERSION:
669 return "cec version";
670 case CEC_OPCODE_GET_CEC_VERSION:
671 return "get cec version";
672 case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
673 return "give physical address";
674 case CEC_OPCODE_GET_MENU_LANGUAGE:
675 return "get menu language";
676 case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS:
677 return "report physical address";
678 case CEC_OPCODE_SET_MENU_LANGUAGE:
679 return "set menu language";
680 case CEC_OPCODE_DECK_CONTROL:
681 return "deck control";
682 case CEC_OPCODE_DECK_STATUS:
683 return "deck status";
684 case CEC_OPCODE_GIVE_DECK_STATUS:
685 return "give deck status";
686 case CEC_OPCODE_PLAY:
687 return "play";
688 case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS:
689 return "give tuner status";
690 case CEC_OPCODE_SELECT_ANALOGUE_SERVICE:
691 return "select analogue service";
692 case CEC_OPCODE_SELECT_DIGITAL_SERVICE:
693 return "set digital service";
694 case CEC_OPCODE_TUNER_DEVICE_STATUS:
695 return "tuner device status";
696 case CEC_OPCODE_TUNER_STEP_DECREMENT:
697 return "tuner step decrement";
698 case CEC_OPCODE_TUNER_STEP_INCREMENT:
699 return "tuner step increment";
700 case CEC_OPCODE_DEVICE_VENDOR_ID:
701 return "device vendor id";
702 case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
703 return "give device vendor id";
704 case CEC_OPCODE_VENDOR_COMMAND:
705 return "vendor command";
706 case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
707 return "vendor command with id";
708 case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
709 return "vendor remote button down";
710 case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
711 return "vendor remote button up";
712 case CEC_OPCODE_SET_OSD_STRING:
713 return "set osd string";
714 case CEC_OPCODE_GIVE_OSD_NAME:
715 return "give osd name";
716 case CEC_OPCODE_SET_OSD_NAME:
717 return "set osd name";
718 case CEC_OPCODE_MENU_REQUEST:
719 return "menu request";
720 case CEC_OPCODE_MENU_STATUS:
721 return "menu status";
722 case CEC_OPCODE_USER_CONTROL_PRESSED:
723 return "user control pressed";
724 case CEC_OPCODE_USER_CONTROL_RELEASE:
725 return "user control release";
726 case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
727 return "give device power status";
728 case CEC_OPCODE_REPORT_POWER_STATUS:
729 return "report power status";
730 case CEC_OPCODE_FEATURE_ABORT:
731 return "feature abort";
732 case CEC_OPCODE_ABORT:
733 return "abort";
734 case CEC_OPCODE_GIVE_AUDIO_STATUS:
735 return "give audio status";
736 case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
737 return "give audio mode status";
738 case CEC_OPCODE_REPORT_AUDIO_STATUS:
739 return "report audio status";
740 case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE:
741 return "set system audio mode";
742 case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST:
743 return "system audio mode request";
744 case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS:
745 return "system audio mode status";
746 case CEC_OPCODE_SET_AUDIO_RATE:
747 return "set audio rate";
748 case CEC_OPCODE_START_ARC:
749 return "start ARC";
750 case CEC_OPCODE_REPORT_ARC_STARTED:
751 return "report ARC started";
752 case CEC_OPCODE_REPORT_ARC_ENDED:
753 return "report ARC ended";
754 case CEC_OPCODE_REQUEST_ARC_START:
755 return "request ARC start";
756 case CEC_OPCODE_REQUEST_ARC_END:
757 return "request ARC end";
758 case CEC_OPCODE_END_ARC:
759 return "end ARC";
760 case CEC_OPCODE_CDC:
761 return "CDC";
762 case CEC_OPCODE_NONE:
763 return "poll";
764 default:
765 return "UNKNOWN";
766 }
767 }
768
769 const char *CLibCEC::ToString(const cec_system_audio_status mode)
770 {
771 switch(mode)
772 {
773 case CEC_SYSTEM_AUDIO_STATUS_ON:
774 return "on";
775 case CEC_SYSTEM_AUDIO_STATUS_OFF:
776 return "off";
777 default:
778 return "unknown";
779 }
780 }
781
782 const char *CLibCEC::ToString(const cec_audio_status UNUSED(status))
783 {
784 // TODO this is a mask
785 return "TODO";
786 }
787
788 const char *CLibCEC::ToString(const cec_vendor_id vendor)
789 {
790 switch (vendor)
791 {
792 case CEC_VENDOR_SAMSUNG:
793 return "Samsung";
794 case CEC_VENDOR_LG:
795 return "LG";
796 case CEC_VENDOR_PANASONIC:
797 return "Panasonic";
798 case CEC_VENDOR_PIONEER:
799 return "Pioneer";
800 case CEC_VENDOR_ONKYO:
801 return "Onkyo";
802 case CEC_VENDOR_YAMAHA:
803 return "Yamaha";
804 case CEC_VENDOR_PHILIPS:
805 return "Philips";
806 case CEC_VENDOR_SONY:
807 return "Sony";
808 case CEC_VENDOR_TOSHIBA:
809 return "Toshiba";
810 default:
811 return "Unknown";
812 }
813 }
814
815 const char *CLibCEC::ToString(const cec_client_version version)
816 {
817 switch (version)
818 {
819 case CEC_CLIENT_VERSION_PRE_1_5:
820 return "pre-1.5";
821 case CEC_CLIENT_VERSION_1_5_0:
822 return "1.5.0";
823 case CEC_CLIENT_VERSION_1_5_1:
824 return "1.5.1";
825 case CEC_CLIENT_VERSION_1_5_2:
826 return "1.5.2";
827 case CEC_CLIENT_VERSION_1_5_3:
828 return "1.5.3";
829 case CEC_CLIENT_VERSION_1_6_0:
830 return "1.6.0";
831 case CEC_CLIENT_VERSION_1_6_1:
832 return "1.6.1";
833 case CEC_CLIENT_VERSION_1_6_2:
834 return "1.6.2";
835 default:
836 return "Unknown";
837 }
838 }
839
840 const char *CLibCEC::ToString(const cec_server_version version)
841 {
842 switch (version)
843 {
844 case CEC_SERVER_VERSION_PRE_1_5:
845 return "pre-1.5";
846 case CEC_SERVER_VERSION_1_5_0:
847 return "1.5.0";
848 case CEC_SERVER_VERSION_1_5_1:
849 return "1.5.1";
850 case CEC_SERVER_VERSION_1_5_2:
851 return "1.5.2";
852 case CEC_SERVER_VERSION_1_5_3:
853 return "1.5.3";
854 case CEC_SERVER_VERSION_1_6_0:
855 return "1.6.0";
856 case CEC_SERVER_VERSION_1_6_1:
857 return "1.6.1";
858 case CEC_SERVER_VERSION_1_6_2:
859 return "1.6.2";
860 default:
861 return "Unknown";
862 }
863 }
864
865 void CLibCEC::CheckKeypressTimeout(void)
866 {
867 // check all clients
868 for (vector<CCECClient *>::iterator it = m_clients.begin(); it != m_clients.end(); it++)
869 (*it)->CheckKeypressTimeout();
870 }
871
872 void CLibCEC::AddLog(const cec_log_level level, const char *strFormat, ...)
873 {
874 CStdString strLog;
875
876 va_list argList;
877 va_start(argList, strFormat);
878 strLog.FormatV(strFormat, argList);
879 va_end(argList);
880
881 cec_log_message message;
882 message.level = level;
883 message.time = GetTimeMs() - m_iStartTime;
884 snprintf(message.message, sizeof(message.message), "%s", strLog.c_str());
885
886 // send the message to all clients
887 for (vector<CCECClient *>::iterator it = m_clients.begin(); it != m_clients.end(); it++)
888 (*it)->AddLog(message);
889 }
890
891 void CLibCEC::Alert(const libcec_alert type, const libcec_parameter &param)
892 {
893 // send the alert to all clients
894 for (vector<CCECClient *>::iterator it = m_clients.begin(); it != m_clients.end(); it++)
895 (*it)->Alert(type, param);
896 }
897
898 bool CLibCEC::SetActiveView(void)
899 {
900 AddLog(CEC_LOG_WARNING, "deprecated method %s called", __FUNCTION__);
901 return SetActiveSource();
902 }
903
904 bool CLibCEC::EnablePhysicalAddressDetection(void)
905 {
906 AddLog(CEC_LOG_WARNING, "deprecated method %s called", __FUNCTION__);
907 return true;
908 }
909
910 CCECClient *CLibCEC::RegisterClient(libcec_configuration *configuration)
911 {
912 if (!m_cec)
913 return NULL;
914
915 CCECClient *newClient = new CCECClient(m_cec, configuration);
916 if (!newClient)
917 return NULL;
918
919 m_clients.push_back(newClient);
920 if (!m_client)
921 m_client = newClient;
922
923 if (m_cec->IsRunning())
924 m_cec->RegisterClient(newClient);
925
926 return m_client;
927 }
928
929 void CLibCEC::UnregisterClients(void)
930 {
931 m_clients.clear();
932 delete m_client;
933 m_client = NULL;
934 }
935
936 void * CECInitialise(libcec_configuration *configuration)
937 {
938 if (!configuration)
939 return NULL;
940
941 CLibCEC *lib = new CLibCEC;
942 if (lib)
943 lib->RegisterClient(configuration);
944
945 return static_cast< void* > (lib);
946 }
947
948 void * CECInit(const char *strDeviceName, CEC::cec_device_type_list types, uint16_t iPhysicalAddress /* = 0 */)
949 {
950 libcec_configuration configuration;
951 configuration.serverVersion = LIBCEC_VERSION_CURRENT;
952
953 // client version < 1.5.0
954 snprintf(configuration.strDeviceName, 13, "%s", strDeviceName);
955 configuration.deviceTypes = types;
956 configuration.iPhysicalAddress = iPhysicalAddress;
957
958 if (configuration.deviceTypes.IsEmpty())
959 configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
960
961 return CECInitialise(&configuration);
962 }
963
964 bool CECStartBootloader(void)
965 {
966 bool bReturn(false);
967 cec_adapter deviceList[1];
968 if (CUSBCECAdapterDetection::FindAdapters(deviceList, 1) > 0)
969 {
970 CUSBCECAdapterCommunication comm(NULL, deviceList[0].comm);
971 CTimeout timeout(CEC_DEFAULT_CONNECT_TIMEOUT);
972 while (timeout.TimeLeft() > 0 && (bReturn = comm.Open(timeout.TimeLeft() / CEC_CONNECT_TRIES, true)) == false)
973 {
974 comm.Close();
975 CEvent::Sleep(500);
976 }
977 if (comm.IsOpen())
978 bReturn = comm.StartBootloader();
979 }
980
981 return bReturn;
982 }
983
984 void CECDestroy(CEC::ICECAdapter *instance)
985 {
986 delete instance;
987 }
988
989 bool CLibCEC::GetDeviceInformation(const char *strPort, libcec_configuration *config, uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */)
990 {
991 if (m_cec->IsRunning())
992 return false;
993
994 return m_cec->GetDeviceInformation(strPort, config, iTimeoutMs);
995 }