2 * This file is part of the libCEC(R) library.
4 * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
5 * libCEC(R) is an original work, containing original code.
7 * libCEC(R) is a trademark of Pulse-Eight Limited.
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.
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.
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.
24 * Alternatively, you can license this library under a commercial license,
25 * please contact Pulse-Eight Licensing for more information.
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/
35 #include "adapter/USBCECAdapterDetection.h"
36 #include "adapter/USBCECAdapterCommunication.h"
37 #include "CECProcessor.h"
38 #include "CECTypeUtils.h"
39 #include "devices/CECAudioSystem.h"
40 #include "devices/CECBusDevice.h"
41 #include "devices/CECPlaybackDevice.h"
42 #include "devices/CECTV.h"
43 #include "platform/util/timeutils.h"
44 #include "platform/util/StdString.h"
45 #include "platform/util/util.h"
47 #include "CECClient.h"
51 using namespace PLATFORM
;
53 //TODO replace deprecated constructor in 2.0
54 CLibCEC::CLibCEC(const char *UNUSED(strDeviceName
), cec_device_type_list
UNUSED(types
), uint16_t UNUSED(iPhysicalAddress
) /* = 0 */) :
55 m_iStartTime(GetTimeMs()),
58 m_cec
= new CCECProcessor(this);
61 //TODO replace deprecated constructor in 2.0
62 CLibCEC::CLibCEC(libcec_configuration
*UNUSED(configuration
)) :
63 m_iStartTime(GetTimeMs()),
66 m_cec
= new CCECProcessor(this);
69 CLibCEC::~CLibCEC(void)
71 // unregister all clients client
74 // delete the adapter connection
75 DELETE_AND_NULL(m_cec
);
78 bool CLibCEC::Open(const char *strPort
, uint32_t iTimeoutMs
/* = CEC_DEFAULT_CONNECT_TIMEOUT */)
80 if (!m_cec
|| !strPort
)
83 // open a new connection
84 if (!m_cec
->Start(strPort
, CEC_SERIAL_DEFAULT_BAUDRATE
, iTimeoutMs
))
86 AddLog(CEC_LOG_ERROR
, "could not start CEC communications");
90 // register all clients
91 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
93 if (!m_cec
->RegisterClient(*it
))
95 AddLog(CEC_LOG_ERROR
, "failed to register a CEC client");
103 void CLibCEC::Close(void)
105 // unregister all clients
108 // close the connection
113 int8_t CLibCEC::FindAdapters(cec_adapter
*deviceList
, uint8_t iBufSize
, const char *strDevicePath
/* = NULL */)
115 return CUSBCECAdapterDetection::FindAdapters(deviceList
, iBufSize
, strDevicePath
);
118 bool CLibCEC::StartBootloader(void)
120 return m_cec
? m_cec
->StartBootloader() : false;
123 bool CLibCEC::PingAdapter(void)
125 return m_client
? m_client
->PingAdapter() : false;
128 bool CLibCEC::EnableCallbacks(void *cbParam
, ICECCallbacks
*callbacks
)
130 return m_client
? m_client
->EnableCallbacks(cbParam
, callbacks
) : false;
133 bool CLibCEC::GetCurrentConfiguration(libcec_configuration
*configuration
)
135 return m_client
? m_client
->GetCurrentConfiguration(*configuration
) : false;
138 bool CLibCEC::SetConfiguration(const libcec_configuration
*configuration
)
140 return m_client
? m_client
->SetConfiguration(*configuration
) : false;
143 bool CLibCEC::CanPersistConfiguration(void)
145 return m_client
? m_client
->CanPersistConfiguration() : false;
148 bool CLibCEC::PersistConfiguration(libcec_configuration
*configuration
)
150 return m_client
? m_client
->PersistConfiguration(*configuration
) : false;
153 void CLibCEC::RescanActiveDevices(void)
156 m_client
->RescanActiveDevices();
159 bool CLibCEC::IsLibCECActiveSource(void)
161 return m_client
? m_client
->IsLibCECActiveSource() : false;
164 bool CLibCEC::Transmit(const cec_command
&data
)
166 return m_client
? m_client
->Transmit(data
) : false;
169 bool CLibCEC::SetLogicalAddress(cec_logical_address iLogicalAddress
)
171 return m_client
? m_client
->SetLogicalAddress(iLogicalAddress
) : false;
174 bool CLibCEC::SetPhysicalAddress(uint16_t iPhysicalAddress
/* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
176 return m_client
? m_client
->SetPhysicalAddress(iPhysicalAddress
) : false;
179 bool CLibCEC::SetHDMIPort(cec_logical_address iBaseDevice
, uint8_t iPort
/* = CEC_DEFAULT_HDMI_PORT */)
181 return m_client
? m_client
->SetHDMIPort(iBaseDevice
, iPort
) : false;
184 bool CLibCEC::PowerOnDevices(cec_logical_address address
/* = CECDEVICE_TV */)
186 return m_client
? m_client
->SendPowerOnDevices(address
) : false;
189 bool CLibCEC::StandbyDevices(cec_logical_address address
/* = CECDEVICE_BROADCAST */)
191 return m_client
? m_client
->SendStandbyDevices(address
) : false;
194 bool CLibCEC::SetActiveSource(cec_device_type type
/* = CEC_DEVICE_TYPE_RESERVED */)
196 return m_client
? m_client
->SendSetActiveSource(type
) : false;
199 bool CLibCEC::SetDeckControlMode(cec_deck_control_mode mode
, bool bSendUpdate
/* = true */)
201 return m_client
? m_client
->SendSetDeckControlMode(mode
, bSendUpdate
) : false;
204 bool CLibCEC::SetDeckInfo(cec_deck_info info
, bool bSendUpdate
/* = true */)
206 return m_client
? m_client
->SendSetDeckInfo(info
, bSendUpdate
) : false;
209 bool CLibCEC::SetInactiveView(void)
211 return m_client
? m_client
->SendSetInactiveView() : false;
214 bool CLibCEC::SetMenuState(cec_menu_state state
, bool bSendUpdate
/* = true */)
216 return m_client
? m_client
->SendSetMenuState(state
, bSendUpdate
) : false;
219 bool CLibCEC::SetOSDString(cec_logical_address iLogicalAddress
, cec_display_control duration
, const char *strMessage
)
221 return m_client
? m_client
->SendSetOSDString(iLogicalAddress
, duration
, strMessage
) : false;
224 bool CLibCEC::SwitchMonitoring(bool bEnable
)
226 return m_client
? m_client
->SwitchMonitoring(bEnable
) : false;
229 cec_version
CLibCEC::GetDeviceCecVersion(cec_logical_address iAddress
)
231 return m_client
? m_client
->GetDeviceCecVersion(iAddress
) : CEC_VERSION_UNKNOWN
;
234 bool CLibCEC::GetDeviceMenuLanguage(cec_logical_address iAddress
, cec_menu_language
*language
)
236 return m_client
? m_client
->GetDeviceMenuLanguage(iAddress
, *language
) : false;
239 uint64_t CLibCEC::GetDeviceVendorId(cec_logical_address iAddress
)
241 return m_client
? m_client
->GetDeviceVendorId(iAddress
) : (uint64_t)CEC_VENDOR_UNKNOWN
;
244 uint16_t CLibCEC::GetDevicePhysicalAddress(cec_logical_address iAddress
)
246 return m_client
? m_client
->GetDevicePhysicalAddress(iAddress
) : CEC_INVALID_PHYSICAL_ADDRESS
;
249 cec_power_status
CLibCEC::GetDevicePowerStatus(cec_logical_address iAddress
)
251 return m_client
? m_client
->GetDevicePowerStatus(iAddress
) : CEC_POWER_STATUS_UNKNOWN
;
254 bool CLibCEC::PollDevice(cec_logical_address iAddress
)
256 return m_client
? m_client
->PollDevice(iAddress
) : false;
259 cec_logical_addresses
CLibCEC::GetActiveDevices(void)
261 cec_logical_addresses addresses
;
264 addresses
= m_client
->GetActiveDevices();
268 bool CLibCEC::IsActiveDevice(cec_logical_address iAddress
)
270 return m_client
? m_client
->IsActiveDevice(iAddress
) : false;
273 bool CLibCEC::IsActiveDeviceType(cec_device_type type
)
275 return m_client
? m_client
->IsActiveDeviceType(type
) : false;
278 uint8_t CLibCEC::VolumeUp(bool bSendRelease
/* = true */)
280 return m_client
? m_client
->SendVolumeUp(bSendRelease
) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
283 uint8_t CLibCEC::VolumeDown(bool bSendRelease
/* = true */)
285 return m_client
? m_client
->SendVolumeDown(bSendRelease
) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
288 uint8_t CLibCEC::MuteAudio(bool UNUSED(bSendRelease
) /* = true */)
290 return m_client
? m_client
->SendMuteAudio() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
293 bool CLibCEC::SendKeypress(cec_logical_address iDestination
, cec_user_control_code key
, bool bWait
/* = true */)
295 return m_client
? m_client
->SendKeypress(iDestination
, key
, bWait
) : false;
298 bool CLibCEC::SendKeyRelease(cec_logical_address iDestination
, bool bWait
/* = true */)
300 return m_client
? m_client
->SendKeyRelease(iDestination
, bWait
) : false;
303 cec_osd_name
CLibCEC::GetDeviceOSDName(cec_logical_address iAddress
)
306 retVal
.device
= CECDEVICE_UNKNOWN
;
307 memset(retVal
.name
, 0, 14);
310 retVal
= m_client
->GetDeviceOSDName(iAddress
);
314 cec_logical_address
CLibCEC::GetActiveSource(void)
316 return m_client
? m_client
->GetActiveSource() : CECDEVICE_UNKNOWN
;
319 bool CLibCEC::IsActiveSource(cec_logical_address iAddress
)
321 return m_client
? m_client
->IsActiveSource(iAddress
) : false;
323 bool CLibCEC::SetStreamPath(cec_logical_address iAddress
)
325 return m_client
? m_client
->SetStreamPath(iAddress
) : false;
328 bool CLibCEC::SetStreamPath(uint16_t iPhysicalAddress
)
330 return m_client
? m_client
->SetStreamPath(iPhysicalAddress
) : false;
333 cec_logical_addresses
CLibCEC::GetLogicalAddresses(void)
335 cec_logical_addresses addresses
;
338 m_client
->GetLogicalAddresses();
342 bool CLibCEC::GetNextLogMessage(cec_log_message
*message
)
344 return m_client
? m_client
->GetNextLogMessage(message
) : false;
347 bool CLibCEC::GetNextKeypress(cec_keypress
*key
)
349 return m_client
? m_client
->GetNextKeypress(key
) : false;
352 bool CLibCEC::GetNextCommand(cec_command
*command
)
354 return m_client
? m_client
->GetNextCommand(command
) : false;
357 cec_device_type
CLibCEC::GetType(cec_logical_address address
)
359 return CCECTypeUtils::GetType(address
);
362 uint16_t CLibCEC::GetMaskForType(cec_logical_address address
)
364 return CCECTypeUtils::GetMaskForType(address
);
367 uint16_t CLibCEC::GetMaskForType(cec_device_type type
)
369 return CCECTypeUtils::GetMaskForType(type
);
372 bool CLibCEC::IsValidPhysicalAddress(uint16_t iPhysicalAddress
)
374 return iPhysicalAddress
>= CEC_MIN_PHYSICAL_ADDRESS
&&
375 iPhysicalAddress
<= CEC_MAX_PHYSICAL_ADDRESS
;
378 const char *CLibCEC::ToString(const cec_device_type type
)
380 return CCECTypeUtils::ToString(type
);
383 const char *CLibCEC::ToString(const cec_menu_state state
)
385 return CCECTypeUtils::ToString(state
);
388 const char *CLibCEC::ToString(const cec_version version
)
390 return CCECTypeUtils::ToString(version
);
393 const char *CLibCEC::ToString(const cec_power_status status
)
395 return CCECTypeUtils::ToString(status
);
398 const char *CLibCEC::ToString(const cec_logical_address address
)
400 return CCECTypeUtils::ToString(address
);
403 const char *CLibCEC::ToString(const cec_deck_control_mode mode
)
405 return CCECTypeUtils::ToString(mode
);
408 const char *CLibCEC::ToString(const cec_deck_info status
)
410 return CCECTypeUtils::ToString(status
);
413 const char *CLibCEC::ToString(const cec_opcode opcode
)
415 return CCECTypeUtils::ToString(opcode
);
418 const char *CLibCEC::ToString(const cec_system_audio_status mode
)
420 return CCECTypeUtils::ToString(mode
);
423 const char *CLibCEC::ToString(const cec_audio_status status
)
425 return CCECTypeUtils::ToString(status
);
428 const char *CLibCEC::ToString(const cec_vendor_id vendor
)
430 return CCECTypeUtils::ToString(vendor
);
433 const char *CLibCEC::ToString(const cec_client_version version
)
435 return CCECTypeUtils::ToString(version
);
438 const char *CLibCEC::ToString(const cec_server_version version
)
440 return CCECTypeUtils::ToString(version
);
443 void CLibCEC::CheckKeypressTimeout(void)
446 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
447 (*it
)->CheckKeypressTimeout();
450 void CLibCEC::AddLog(const cec_log_level level
, const char *strFormat
, ...)
454 // format the message
456 va_start(argList
, strFormat
);
457 strLog
.FormatV(strFormat
, argList
);
460 cec_log_message message
;
461 message
.level
= level
;
462 message
.time
= GetTimeMs() - m_iStartTime
;
463 snprintf(message
.message
, sizeof(message
.message
), "%s", strLog
.c_str());
465 // send the message to all clients
466 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
467 (*it
)->AddLog(message
);
470 void CLibCEC::Alert(const libcec_alert type
, const libcec_parameter
¶m
)
472 // send the alert to all clients
473 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
474 (*it
)->Alert(type
, param
);
477 bool CLibCEC::SetActiveView(void)
479 AddLog(CEC_LOG_WARNING
, "deprecated method %s called", __FUNCTION__
);
480 return SetActiveSource();
483 bool CLibCEC::EnablePhysicalAddressDetection(void)
485 AddLog(CEC_LOG_WARNING
, "deprecated method %s called", __FUNCTION__
);
489 CCECClient
*CLibCEC::RegisterClient(libcec_configuration
&configuration
)
494 // create a new client instance
495 CCECClient
*newClient
= new CCECClient(m_cec
, configuration
);
498 m_clients
.push_back(newClient
);
500 // if the default client isn't set, set it
502 m_client
= newClient
;
504 // register the new client
505 if (m_cec
->CECInitialised())
506 m_cec
->RegisterClient(newClient
);
511 void CLibCEC::UnregisterClients(void)
514 m_cec
->UnregisterClients();
518 DELETE_AND_NULL(m_client
);
521 void * CECInitialise(libcec_configuration
*configuration
)
526 // create a new libCEC instance
527 CLibCEC
*lib
= new CLibCEC(NULL
);
529 // register a new client
530 CCECClient
*client(NULL
);
531 if (lib
&& configuration
)
532 client
= lib
->RegisterClient(*configuration
);
534 // update the current configuration
536 client
->GetCurrentConfiguration(*configuration
);
538 // ensure that the correct server version is set
539 configuration
->serverVersion
= LIBCEC_VERSION_CURRENT
;
541 return static_cast< void* > (lib
);
544 void * CECInit(const char *strDeviceName
, CEC::cec_device_type_list types
, uint16_t iPhysicalAddress
/* = 0 */)
546 libcec_configuration configuration
;
548 // client version < 1.5.0
549 snprintf(configuration
.strDeviceName
, 13, "%s", strDeviceName
);
550 configuration
.deviceTypes
= types
;
551 configuration
.iPhysicalAddress
= iPhysicalAddress
;
553 if (configuration
.deviceTypes
.IsEmpty())
554 configuration
.deviceTypes
.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE
);
556 return CECInitialise(&configuration
);
559 bool CECStartBootloader(void)
562 cec_adapter deviceList
[1];
563 if (CUSBCECAdapterDetection::FindAdapters(deviceList
, 1) > 0)
565 CUSBCECAdapterCommunication
comm(NULL
, deviceList
[0].comm
);
566 CTimeout
timeout(CEC_DEFAULT_CONNECT_TIMEOUT
);
567 while (timeout
.TimeLeft() > 0 && (bReturn
= comm
.Open(timeout
.TimeLeft() / CEC_CONNECT_TRIES
, true)) == false)
573 bReturn
= comm
.StartBootloader();
579 void CECDestroy(CEC::ICECAdapter
*instance
)
581 DELETE_AND_NULL(instance
);
584 bool CLibCEC::GetDeviceInformation(const char *strPort
, libcec_configuration
*config
, uint32_t iTimeoutMs
/* = CEC_DEFAULT_CONNECT_TIMEOUT */)
586 if (m_cec
->IsRunning())
589 return m_cec
->GetDeviceInformation(strPort
, config
, iTimeoutMs
);
592 // no longer being used
593 void CLibCEC::AddKey(const cec_keypress
&UNUSED(key
)) {}
594 void CLibCEC::AddCommand(const cec_command
&UNUSED(command
)) {}
595 void CLibCEC::ConfigurationChanged(const libcec_configuration
&UNUSED(config
)) {}
596 void CLibCEC::SetCurrentButton(cec_user_control_code
UNUSED(iButtonCode
)) {}
597 CLibCEC
*CLibCEC::GetInstance(void) { return NULL
; }
598 void CLibCEC::SetInstance(CLibCEC
*UNUSED(instance
)) {}