cec: send a feature abort again for all unhandled commands, removed statics, refactor...
[deb_libcec.git] / src / lib / LibCEC.cpp
CommitLineData
2abe74eb
LOK
1/*
2 * This file is part of the libCEC(R) library.
3 *
b492c10e 4 * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
2abe74eb
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
33#include "LibCEC.h"
34
7bb4ed43 35#include "adapter/USBCECAdapterDetection.h"
08d80226 36#include "adapter/USBCECAdapterCommunication.h"
2abe74eb 37#include "CECProcessor.h"
004b8382 38#include "devices/CECAudioSystem.h"
0f23c85c 39#include "devices/CECBusDevice.h"
004b8382
LOK
40#include "devices/CECPlaybackDevice.h"
41#include "devices/CECTV.h"
ba65909d
LOK
42#include "platform/util/timeutils.h"
43#include "platform/util/StdString.h"
2abe74eb 44
004b8382
LOK
45#include "CECClient.h"
46
2abe74eb
LOK
47using namespace std;
48using namespace CEC;
f00ff009 49using namespace PLATFORM;
2abe74eb 50
004b8382
LOK
51CLibCEC::CLibCEC(void) :
52 m_client(NULL),
53 m_iStartTime(GetTimeMs())
caca2d81 54{
004b8382 55 m_cec = new CCECProcessor(this);
f8513317
LOK
56}
57
2abe74eb
LOK
58CLibCEC::~CLibCEC(void)
59{
004b8382
LOK
60 delete m_client;
61 m_client = NULL;
2abe74eb 62 delete m_cec;
004b8382 63 m_cec = NULL;
2abe74eb
LOK
64}
65
b32ffd87 66bool CLibCEC::Open(const char *strPort, uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */)
2abe74eb 67{
1113cb7d 68 if (m_cec->IsRunning())
2abe74eb
LOK
69 {
70 AddLog(CEC_LOG_ERROR, "connection already open");
71 return false;
72 }
73
b32ffd87 74 if (!m_cec->Start(strPort, CEC_SERIAL_DEFAULT_BAUDRATE, iTimeoutMs))
2abe74eb
LOK
75 {
76 AddLog(CEC_LOG_ERROR, "could not start CEC communications");
77 return false;
78 }
79
004b8382
LOK
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
2abe74eb
LOK
89 return true;
90}
91
92void CLibCEC::Close(void)
93{
004b8382 94 m_clients.clear();
2abe74eb 95
004b8382
LOK
96 if (m_client)
97 {
98 delete m_client;
99 m_client = NULL;
100 }
fa4798bd 101 if (m_cec)
547b390d 102 {
004b8382
LOK
103 delete m_cec;
104 m_cec = NULL;
547b390d 105 }
fa4798bd
LOK
106}
107
25701fa6 108int8_t CLibCEC::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
2abe74eb 109{
7bb4ed43 110 return CUSBCECAdapterDetection::FindAdapters(deviceList, iBufSize, strDevicePath);
2abe74eb
LOK
111}
112
113bool CLibCEC::PingAdapter(void)
114{
1113cb7d 115 return m_cec ? m_cec->PingAdapter() : false;
2abe74eb
LOK
116}
117
118bool CLibCEC::StartBootloader(void)
119{
1113cb7d 120 return m_cec ? m_cec->StartBootloader() : false;
2abe74eb
LOK
121}
122
004b8382 123bool CLibCEC::SwitchMonitoring(bool bEnable)
16b1e052 124{
004b8382 125 return m_cec ? m_cec->SwitchMonitoring(bEnable) : false;
16b1e052
LOK
126}
127
004b8382 128cec_logical_address CLibCEC::GetActiveSource(void)
2dbd78f8 129{
004b8382 130 return m_cec ? m_cec->GetActiveSource() : CECDEVICE_UNKNOWN;
2dbd78f8
LOK
131}
132
004b8382 133bool CLibCEC::IsActiveSource(cec_logical_address iAddress)
2abe74eb 134{
004b8382 135 return m_cec ? m_cec->IsActiveSource(iAddress) : false;
2abe74eb
LOK
136}
137
004b8382 138bool CLibCEC::PollDevice(cec_logical_address iAddress)
2abe74eb 139{
004b8382 140 return m_cec ? m_cec->PollDevice(iAddress) : false;
2abe74eb
LOK
141}
142
004b8382 143cec_logical_addresses CLibCEC::GetActiveDevices(void)
18203d17 144{
004b8382
LOK
145 CECDEVICEVEC activeDevices;
146 if (m_cec)
147 m_cec->GetDevices()->GetActive(activeDevices);
148 return CCECDeviceMap::ToLogicalAddresses(activeDevices);
18203d17
LOK
149}
150
004b8382 151bool CLibCEC::IsActiveDevice(cec_logical_address iAddress)
2abe74eb 152{
004b8382
LOK
153 cec_logical_addresses activeDevices = GetActiveDevices();
154 return activeDevices.IsSet(iAddress);
2abe74eb
LOK
155}
156
004b8382 157bool CLibCEC::IsActiveDeviceType(cec_device_type type)
a9232a79 158{
004b8382
LOK
159 CECDEVICEVEC activeDevices;
160 if (m_cec)
161 m_cec->GetDevices()->GetActive(activeDevices);
162 CCECDeviceMap::FilterType(type, activeDevices);
163 return !activeDevices.empty();
a9232a79
LOK
164}
165
004b8382 166bool CLibCEC::SetStreamPath(cec_logical_address iAddress)
a9232a79 167{
004b8382
LOK
168 uint16_t iPhysicalAddress = GetDevicePhysicalAddress(iAddress);
169 if (iPhysicalAddress != CEC_INVALID_PHYSICAL_ADDRESS)
170 return SetStreamPath(iPhysicalAddress);
171 return false;
a9232a79
LOK
172}
173
004b8382 174bool CLibCEC::SetStreamPath(uint16_t iPhysicalAddress)
2abe74eb 175{
004b8382 176 return m_cec->SetStreamPath(iPhysicalAddress);
2abe74eb
LOK
177}
178
004b8382 179bool CLibCEC::IsLibCECActiveSource(void)
28fa6c97 180{
004b8382
LOK
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;
28fa6c97
LOK
190}
191
004b8382 192bool CLibCEC::CanPersistConfiguration(void)
1969b140 193{
004b8382 194 return m_cec->CanPersistConfiguration();
1969b140
LOK
195}
196
004b8382 197bool CLibCEC::PersistConfiguration(libcec_configuration *configuration)
8b7e5ff6 198{
004b8382 199 return m_cec->PersistConfiguration(configuration);
8b7e5ff6
LOK
200}
201
004b8382 202void CLibCEC::RescanActiveDevices(void)
6a1c0009 203{
004b8382 204 return m_cec->RescanActiveDevices();
6a1c0009
LOK
205}
206
004b8382 207bool CLibCEC::EnableCallbacks(void *cbParam, ICECCallbacks *callbacks)
a3269a0a 208{
004b8382 209 return m_client ? m_client->EnableCallbacks(cbParam, callbacks) : false;
a3269a0a
LOK
210}
211
004b8382 212bool CLibCEC::GetCurrentConfiguration(libcec_configuration *configuration)
44c74256 213{
004b8382 214 return m_client ? m_client->GetCurrentConfiguration(configuration) : false;
44c74256
LOK
215}
216
004b8382 217bool CLibCEC::SetConfiguration(const libcec_configuration *configuration)
eab72c40 218{
004b8382 219 return m_client ? m_client->SetConfiguration(configuration) : false;
eab72c40
LOK
220}
221
004b8382 222bool CLibCEC::Transmit(const cec_command &data)
b4b1b49b 223{
004b8382 224 return m_client ? m_client->Transmit(data) : false;
b4b1b49b
LOK
225}
226
004b8382 227bool CLibCEC::SetLogicalAddress(cec_logical_address iLogicalAddress)
b4b1b49b 228{
004b8382 229 return m_client ? m_client->SetLogicalAddress(iLogicalAddress) : false;
b4b1b49b
LOK
230}
231
004b8382 232bool CLibCEC::SetPhysicalAddress(uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
e55f3f70 233{
004b8382 234 return m_client ? m_client->SetPhysicalAddress(iPhysicalAddress) : false;
e55f3f70 235}
44c74256 236
004b8382 237bool CLibCEC::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort /* = CEC_DEFAULT_HDMI_PORT */)
57f45e6c 238{
004b8382 239 return m_client ? m_client->SetHDMIPort(iBaseDevice, iPort) : false;
57f45e6c
LOK
240}
241
004b8382 242bool CLibCEC::PowerOnDevices(cec_logical_address address /* = CECDEVICE_TV */)
6d858ba4 243{
004b8382 244 return m_client ? m_client->SendPowerOnDevices(address) : false;
6d858ba4
LOK
245}
246
004b8382 247bool CLibCEC::StandbyDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
6d858ba4 248{
004b8382 249 return m_client ? m_client->SendStandbyDevices(address) : false;
6d858ba4
LOK
250}
251
004b8382 252bool CLibCEC::SetActiveSource(cec_device_type type /* = CEC_DEVICE_TYPE_RESERVED */)
6d858ba4 253{
004b8382 254 return m_client ? m_client->SendSetActiveSource(type) : false;
6d858ba4
LOK
255}
256
004b8382 257bool CLibCEC::SetDeckControlMode(cec_deck_control_mode mode, bool bSendUpdate /* = true */)
04e637f9 258{
004b8382 259 return m_client ? m_client->SendSetDeckControlMode(mode, bSendUpdate) : false;
04e637f9
LOK
260}
261
004b8382 262bool CLibCEC::SetDeckInfo(cec_deck_info info, bool bSendUpdate /* = true */)
04e637f9 263{
004b8382 264 return m_client ? m_client->SendSetDeckInfo(info, bSendUpdate) : false;
04e637f9
LOK
265}
266
004b8382 267bool CLibCEC::SetInactiveView(void)
04e637f9 268{
004b8382 269 return m_client ? m_client->SendSetInactiveView() : false;
04e637f9
LOK
270}
271
004b8382 272bool CLibCEC::SetMenuState(cec_menu_state state, bool bSendUpdate /* = true */)
a33794d8 273{
004b8382 274 return m_client ? m_client->SendSetMenuState(state, bSendUpdate) : false;
a33794d8
LOK
275}
276
004b8382 277bool CLibCEC::SetOSDString(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage)
a33794d8 278{
004b8382 279 return m_client ? m_client->SendSetOSDString(iLogicalAddress, duration, strMessage) : false;
a33794d8
LOK
280}
281
004b8382 282cec_version CLibCEC::GetDeviceCecVersion(cec_logical_address iAddress)
ed21be2a 283{
004b8382 284 return m_client ? m_client->GetDeviceCecVersion(iAddress) : CEC_VERSION_UNKNOWN;
ed21be2a
LOK
285}
286
004b8382 287bool CLibCEC::GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language)
2abe74eb 288{
004b8382 289 return m_client ? m_client->GetDeviceMenuLanguage(iAddress, language) : false;
2abe74eb
LOK
290}
291
004b8382 292uint64_t CLibCEC::GetDeviceVendorId(cec_logical_address iAddress)
95ba7a09 293{
004b8382 294 return m_client ? m_client->GetDeviceVendorId(iAddress) : (uint64_t)CEC_VENDOR_UNKNOWN;
02e7043e
LOK
295}
296
004b8382 297uint16_t CLibCEC::GetDevicePhysicalAddress(cec_logical_address iAddress)
32403cc3 298{
004b8382 299 return m_client ? m_client->GetDevicePhysicalAddress(iAddress) : CEC_INVALID_PHYSICAL_ADDRESS;
32403cc3
LOK
300}
301
004b8382 302cec_power_status CLibCEC::GetDevicePowerStatus(cec_logical_address iAddress)
02e7043e 303{
004b8382 304 return m_client ? m_client->GetDevicePowerStatus(iAddress) : CEC_POWER_STATUS_UNKNOWN;
95ba7a09
LOK
305}
306
004b8382 307uint8_t CLibCEC::VolumeUp(bool bSendRelease /* = true */)
2abe74eb 308{
004b8382 309 return m_client ? m_client->SendVolumeUp(bSendRelease) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
2abe74eb
LOK
310}
311
004b8382 312uint8_t CLibCEC::VolumeDown(bool bSendRelease /* = true */)
2abe74eb 313{
004b8382 314 return m_client ? m_client->SendVolumeDown(bSendRelease) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
2abe74eb
LOK
315}
316
004b8382 317uint8_t CLibCEC::MuteAudio(bool UNUSED(bSendRelease) /* = true */)
b1c47f9d 318{
004b8382 319 return m_client ? m_client->SendMuteAudio() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN;
b1c47f9d
LOK
320}
321
004b8382 322bool CLibCEC::SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = true */)
2abe74eb 323{
004b8382 324 return m_client ? m_client->SendKeypress(iDestination, key, bWait) : false;
2abe74eb
LOK
325}
326
004b8382 327bool CLibCEC::SendKeyRelease(cec_logical_address iDestination, bool bWait /* = true */)
e1804a4e 328{
004b8382 329 return m_client ? m_client->SendKeyRelease(iDestination, bWait) : false;
e1804a4e
LOK
330}
331
004b8382 332cec_osd_name CLibCEC::GetDeviceOSDName(cec_logical_address iAddress)
f42d3e0f 333{
004b8382
LOK
334 cec_osd_name retVal;
335 if (m_client)
336 retVal = m_client->GetDeviceOSDName(iAddress);
337 return retVal;
f42d3e0f
LOK
338}
339
004b8382 340cec_logical_addresses CLibCEC::GetLogicalAddresses(void)
f42d3e0f 341{
004b8382
LOK
342 cec_logical_addresses addresses;
343 if (m_cec)
344 addresses = m_cec->GetLogicalAddresses();
345 return addresses;
f42d3e0f
LOK
346}
347
004b8382 348bool CLibCEC::GetNextLogMessage(cec_log_message *message)
80b72250 349{
004b8382 350 return m_client ? m_client->GetNextLogMessage(message) : false;
80b72250
LOK
351}
352
004b8382 353bool CLibCEC::GetNextKeypress(cec_keypress *key)
5477a250 354{
004b8382 355 return m_client ? m_client->GetNextKeypress(key) : false;
5477a250
LOK
356}
357
004b8382 358bool CLibCEC::GetNextCommand(cec_command *command)
5477a250 359{
004b8382 360 return m_client ? m_client->GetNextCommand(command) : false;
5477a250
LOK
361}
362
004b8382 363cec_device_type CLibCEC::GetType(cec_logical_address address)
f8513317 364{
004b8382
LOK
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 }
f8513317
LOK
387}
388
004b8382 389uint16_t CLibCEC::GetMaskForType(cec_logical_address address)
caca2d81 390{
004b8382 391 return GetMaskForType(GetType(address));
caca2d81
LOK
392}
393
004b8382 394uint16_t CLibCEC::GetMaskForType(cec_device_type type)
a2198e5e 395{
004b8382 396 switch (type)
a2198e5e 397 {
004b8382 398 case CEC_DEVICE_TYPE_AUDIO_SYSTEM:
08d80226 399 {
004b8382
LOK
400 cec_logical_addresses addr;
401 addr.Clear();
402 addr.Set(CECDEVICE_AUDIOSYSTEM);
403 return addr.AckMask();
08d80226 404 }
004b8382
LOK
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;
a2198e5e 442 }
004b8382 443}
08d80226 444
004b8382
LOK
445bool CLibCEC::IsValidPhysicalAddress(uint16_t iPhysicalAddress)
446{
447 return iPhysicalAddress >= CEC_MIN_PHYSICAL_ADDRESS &&
448 iPhysicalAddress <= CEC_MAX_PHYSICAL_ADDRESS;
a2198e5e
LOK
449}
450
004b8382 451const char *CLibCEC::ToString(const cec_device_type type)
25701fa6 452{
004b8382
LOK
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 }
25701fa6 470}
03ae897d
LOK
471
472const char *CLibCEC::ToString(const cec_menu_state state)
473{
004b8382
LOK
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 }
03ae897d
LOK
483}
484
485const char *CLibCEC::ToString(const cec_version version)
486{
004b8382
LOK
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 }
03ae897d
LOK
502}
503
504const char *CLibCEC::ToString(const cec_power_status status)
505{
004b8382
LOK
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 }
03ae897d
LOK
519}
520
521const char *CLibCEC::ToString(const cec_logical_address address)
522{
004b8382
LOK
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 }
03ae897d
LOK
560}
561
562const char *CLibCEC::ToString(const cec_deck_control_mode mode)
563{
004b8382
LOK
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 }
03ae897d
LOK
577}
578
579const char *CLibCEC::ToString(const cec_deck_info status)
580{
004b8382
LOK
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 }
03ae897d
LOK
618}
619
620const char *CLibCEC::ToString(const cec_opcode opcode)
621{
004b8382
LOK
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 }
03ae897d
LOK
767}
768
769const char *CLibCEC::ToString(const cec_system_audio_status mode)
770{
004b8382
LOK
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 }
03ae897d
LOK
780}
781
004b8382 782const char *CLibCEC::ToString(const cec_audio_status UNUSED(status))
03ae897d 783{
004b8382
LOK
784 // TODO this is a mask
785 return "TODO";
03ae897d
LOK
786}
787
788const char *CLibCEC::ToString(const cec_vendor_id vendor)
789{
004b8382
LOK
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 }
03ae897d 813}
caca2d81
LOK
814
815const char *CLibCEC::ToString(const cec_client_version version)
816{
004b8382
LOK
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 }
caca2d81 838}
d40928b5 839
3efda01a
LOK
840const char *CLibCEC::ToString(const cec_server_version version)
841{
004b8382
LOK
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 }
3efda01a
LOK
863}
864
004b8382 865void CLibCEC::CheckKeypressTimeout(void)
a75e3a5a 866{
004b8382
LOK
867 // check all clients
868 for (vector<CCECClient *>::iterator it = m_clients.begin(); it != m_clients.end(); it++)
869 (*it)->CheckKeypressTimeout();
a75e3a5a
LOK
870}
871
004b8382 872void CLibCEC::AddLog(const cec_log_level level, const char *strFormat, ...)
d40928b5 873{
004b8382
LOK
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);
224ea877
LOK
889}
890
004b8382 891void CLibCEC::Alert(const libcec_alert type, const libcec_parameter &param)
30b4aac0 892{
004b8382
LOK
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);
30b4aac0
LOK
896}
897
004b8382 898bool CLibCEC::SetActiveView(void)
224ea877 899{
004b8382
LOK
900 AddLog(CEC_LOG_WARNING, "deprecated method %s called", __FUNCTION__);
901 return SetActiveSource();
224ea877
LOK
902}
903
004b8382 904bool CLibCEC::EnablePhysicalAddressDetection(void)
224ea877 905{
004b8382
LOK
906 AddLog(CEC_LOG_WARNING, "deprecated method %s called", __FUNCTION__);
907 return true;
224ea877 908}
3efda01a 909
004b8382 910CCECClient *CLibCEC::RegisterClient(libcec_configuration *configuration)
3efda01a 911{
004b8382
LOK
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;
3efda01a 927}
c9549d35 928
004b8382 929void CLibCEC::UnregisterClients(void)
c9549d35 930{
004b8382
LOK
931 m_clients.clear();
932 delete m_client;
933 m_client = NULL;
c9549d35 934}
9878069e 935
004b8382 936void * CECInitialise(libcec_configuration *configuration)
9878069e 937{
004b8382
LOK
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);
9878069e 946}
209b7a5c 947
004b8382 948void * CECInit(const char *strDeviceName, CEC::cec_device_type_list types, uint16_t iPhysicalAddress /* = 0 */)
209b7a5c 949{
004b8382
LOK
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);
209b7a5c
LOK
962}
963
004b8382 964bool CECStartBootloader(void)
209b7a5c 965{
004b8382
LOK
966 bool bReturn(false);
967 cec_adapter deviceList[1];
968 if (CUSBCECAdapterDetection::FindAdapters(deviceList, 1) > 0)
209b7a5c 969 {
004b8382
LOK
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)
209b7a5c 973 {
004b8382
LOK
974 comm.Close();
975 CEvent::Sleep(500);
209b7a5c 976 }
004b8382
LOK
977 if (comm.IsOpen())
978 bReturn = comm.StartBootloader();
209b7a5c 979 }
004b8382
LOK
980
981 return bReturn;
982}
983
984void CECDestroy(CEC::ICECAdapter *instance)
985{
986 delete instance;
209b7a5c 987}
f80cd208 988
b32ffd87 989bool CLibCEC::GetDeviceInformation(const char *strPort, libcec_configuration *config, uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */)
f80cd208
LOK
990{
991 if (m_cec->IsRunning())
992 return false;
004b8382 993
f80cd208 994 return m_cec->GetDeviceInformation(strPort, config, iTimeoutMs);
a75e3a5a 995}