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)
108 // unregister all clients
109 m_cec
->UnregisterClients();
111 // close the connection
115 int8_t CLibCEC::FindAdapters(cec_adapter
*deviceList
, uint8_t iBufSize
, const char *strDevicePath
/* = NULL */)
117 if (!CUSBCECAdapterDetection::CanAutodetect())
119 AddLog(CEC_LOG_WARNING
, "libCEC has not been compiled with adapter detection code for this target, so the path to the COM port has to be provided to libCEC");
123 return CUSBCECAdapterDetection::FindAdapters(deviceList
, iBufSize
, strDevicePath
);
126 bool CLibCEC::StartBootloader(void)
128 return m_cec
? m_cec
->StartBootloader() : false;
131 bool CLibCEC::PingAdapter(void)
133 return m_client
? m_client
->PingAdapter() : false;
136 bool CLibCEC::EnableCallbacks(void *cbParam
, ICECCallbacks
*callbacks
)
138 return m_client
? m_client
->EnableCallbacks(cbParam
, callbacks
) : false;
141 bool CLibCEC::GetCurrentConfiguration(libcec_configuration
*configuration
)
143 return m_client
? m_client
->GetCurrentConfiguration(*configuration
) : false;
146 bool CLibCEC::SetConfiguration(const libcec_configuration
*configuration
)
148 return m_client
? m_client
->SetConfiguration(*configuration
) : false;
151 bool CLibCEC::CanPersistConfiguration(void)
153 return m_client
? m_client
->CanPersistConfiguration() : false;
156 bool CLibCEC::PersistConfiguration(libcec_configuration
*configuration
)
158 return m_client
? m_client
->PersistConfiguration(*configuration
) : false;
161 void CLibCEC::RescanActiveDevices(void)
164 m_client
->RescanActiveDevices();
167 bool CLibCEC::IsLibCECActiveSource(void)
169 return m_client
? m_client
->IsLibCECActiveSource() : false;
172 bool CLibCEC::Transmit(const cec_command
&data
)
174 return m_client
? m_client
->Transmit(data
) : false;
177 bool CLibCEC::SetLogicalAddress(cec_logical_address iLogicalAddress
)
179 return m_client
? m_client
->SetLogicalAddress(iLogicalAddress
) : false;
182 bool CLibCEC::SetPhysicalAddress(uint16_t iPhysicalAddress
/* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
184 return m_client
? m_client
->SetPhysicalAddress(iPhysicalAddress
) : false;
187 bool CLibCEC::SetHDMIPort(cec_logical_address iBaseDevice
, uint8_t iPort
/* = CEC_DEFAULT_HDMI_PORT */)
189 return m_client
? m_client
->SetHDMIPort(iBaseDevice
, iPort
) : false;
192 bool CLibCEC::PowerOnDevices(cec_logical_address address
/* = CECDEVICE_TV */)
194 return m_client
? m_client
->SendPowerOnDevices(address
) : false;
197 bool CLibCEC::StandbyDevices(cec_logical_address address
/* = CECDEVICE_BROADCAST */)
199 return m_client
? m_client
->SendStandbyDevices(address
) : false;
202 bool CLibCEC::SetActiveSource(cec_device_type type
/* = CEC_DEVICE_TYPE_RESERVED */)
204 return m_client
? m_client
->SendSetActiveSource(type
) : false;
207 bool CLibCEC::SetDeckControlMode(cec_deck_control_mode mode
, bool bSendUpdate
/* = true */)
209 return m_client
? m_client
->SendSetDeckControlMode(mode
, bSendUpdate
) : false;
212 bool CLibCEC::SetDeckInfo(cec_deck_info info
, bool bSendUpdate
/* = true */)
214 return m_client
? m_client
->SendSetDeckInfo(info
, bSendUpdate
) : false;
217 bool CLibCEC::SetInactiveView(void)
219 return m_client
? m_client
->SendSetInactiveView() : false;
222 bool CLibCEC::SetMenuState(cec_menu_state state
, bool bSendUpdate
/* = true */)
224 return m_client
? m_client
->SendSetMenuState(state
, bSendUpdate
) : false;
227 bool CLibCEC::SetOSDString(cec_logical_address iLogicalAddress
, cec_display_control duration
, const char *strMessage
)
229 return m_client
? m_client
->SendSetOSDString(iLogicalAddress
, duration
, strMessage
) : false;
232 bool CLibCEC::SwitchMonitoring(bool bEnable
)
234 return m_client
? m_client
->SwitchMonitoring(bEnable
) : false;
237 cec_version
CLibCEC::GetDeviceCecVersion(cec_logical_address iAddress
)
239 return m_client
? m_client
->GetDeviceCecVersion(iAddress
) : CEC_VERSION_UNKNOWN
;
242 bool CLibCEC::GetDeviceMenuLanguage(cec_logical_address iAddress
, cec_menu_language
*language
)
244 return m_client
? m_client
->GetDeviceMenuLanguage(iAddress
, *language
) : false;
247 uint64_t CLibCEC::GetDeviceVendorId(cec_logical_address iAddress
)
249 return m_client
? m_client
->GetDeviceVendorId(iAddress
) : (uint64_t)CEC_VENDOR_UNKNOWN
;
252 uint16_t CLibCEC::GetDevicePhysicalAddress(cec_logical_address iAddress
)
254 return m_client
? m_client
->GetDevicePhysicalAddress(iAddress
) : CEC_INVALID_PHYSICAL_ADDRESS
;
257 cec_power_status
CLibCEC::GetDevicePowerStatus(cec_logical_address iAddress
)
259 return m_client
? m_client
->GetDevicePowerStatus(iAddress
) : CEC_POWER_STATUS_UNKNOWN
;
262 bool CLibCEC::PollDevice(cec_logical_address iAddress
)
264 return m_client
? m_client
->PollDevice(iAddress
) : false;
267 cec_logical_addresses
CLibCEC::GetActiveDevices(void)
269 cec_logical_addresses addresses
;
272 addresses
= m_client
->GetActiveDevices();
276 bool CLibCEC::IsActiveDevice(cec_logical_address iAddress
)
278 return m_client
? m_client
->IsActiveDevice(iAddress
) : false;
281 bool CLibCEC::IsActiveDeviceType(cec_device_type type
)
283 return m_client
? m_client
->IsActiveDeviceType(type
) : false;
286 uint8_t CLibCEC::VolumeUp(bool bSendRelease
/* = true */)
288 return m_client
? m_client
->SendVolumeUp(bSendRelease
) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
291 uint8_t CLibCEC::VolumeDown(bool bSendRelease
/* = true */)
293 return m_client
? m_client
->SendVolumeDown(bSendRelease
) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
296 uint8_t CLibCEC::MuteAudio(bool UNUSED(bSendRelease
) /* = true */)
298 return m_client
? m_client
->SendMuteAudio() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
301 bool CLibCEC::SendKeypress(cec_logical_address iDestination
, cec_user_control_code key
, bool bWait
/* = true */)
303 return m_client
? m_client
->SendKeypress(iDestination
, key
, bWait
) : false;
306 bool CLibCEC::SendKeyRelease(cec_logical_address iDestination
, bool bWait
/* = true */)
308 return m_client
? m_client
->SendKeyRelease(iDestination
, bWait
) : false;
311 cec_osd_name
CLibCEC::GetDeviceOSDName(cec_logical_address iAddress
)
314 retVal
.device
= CECDEVICE_UNKNOWN
;
315 memset(retVal
.name
, 0, 14);
318 retVal
= m_client
->GetDeviceOSDName(iAddress
);
322 cec_logical_address
CLibCEC::GetActiveSource(void)
324 return m_client
? m_client
->GetActiveSource() : CECDEVICE_UNKNOWN
;
327 bool CLibCEC::IsActiveSource(cec_logical_address iAddress
)
329 return m_client
? m_client
->IsActiveSource(iAddress
) : false;
331 bool CLibCEC::SetStreamPath(cec_logical_address iAddress
)
333 return m_client
? m_client
->SetStreamPath(iAddress
) : false;
336 bool CLibCEC::SetStreamPath(uint16_t iPhysicalAddress
)
338 return m_client
? m_client
->SetStreamPath(iPhysicalAddress
) : false;
341 cec_logical_addresses
CLibCEC::GetLogicalAddresses(void)
343 cec_logical_addresses addresses
;
346 m_client
->GetLogicalAddresses();
350 bool CLibCEC::GetNextLogMessage(cec_log_message
*message
)
352 return m_client
? m_client
->GetNextLogMessage(message
) : false;
355 bool CLibCEC::GetNextKeypress(cec_keypress
*key
)
357 return m_client
? m_client
->GetNextKeypress(key
) : false;
360 bool CLibCEC::GetNextCommand(cec_command
*command
)
362 return m_client
? m_client
->GetNextCommand(command
) : false;
365 cec_device_type
CLibCEC::GetType(cec_logical_address address
)
367 return CCECTypeUtils::GetType(address
);
370 uint16_t CLibCEC::GetMaskForType(cec_logical_address address
)
372 return CCECTypeUtils::GetMaskForType(address
);
375 uint16_t CLibCEC::GetMaskForType(cec_device_type type
)
377 return CCECTypeUtils::GetMaskForType(type
);
380 bool CLibCEC::IsValidPhysicalAddress(uint16_t iPhysicalAddress
)
382 return iPhysicalAddress
>= CEC_MIN_PHYSICAL_ADDRESS
&&
383 iPhysicalAddress
<= CEC_MAX_PHYSICAL_ADDRESS
;
386 const char *CLibCEC::ToString(const cec_device_type type
)
388 return CCECTypeUtils::ToString(type
);
391 const char *CLibCEC::ToString(const cec_menu_state state
)
393 return CCECTypeUtils::ToString(state
);
396 const char *CLibCEC::ToString(const cec_version version
)
398 return CCECTypeUtils::ToString(version
);
401 const char *CLibCEC::ToString(const cec_power_status status
)
403 return CCECTypeUtils::ToString(status
);
406 const char *CLibCEC::ToString(const cec_logical_address address
)
408 return CCECTypeUtils::ToString(address
);
411 const char *CLibCEC::ToString(const cec_deck_control_mode mode
)
413 return CCECTypeUtils::ToString(mode
);
416 const char *CLibCEC::ToString(const cec_deck_info status
)
418 return CCECTypeUtils::ToString(status
);
421 const char *CLibCEC::ToString(const cec_opcode opcode
)
423 return CCECTypeUtils::ToString(opcode
);
426 const char *CLibCEC::ToString(const cec_system_audio_status mode
)
428 return CCECTypeUtils::ToString(mode
);
431 const char *CLibCEC::ToString(const cec_audio_status status
)
433 return CCECTypeUtils::ToString(status
);
436 const char *CLibCEC::ToString(const cec_vendor_id vendor
)
438 return CCECTypeUtils::ToString(vendor
);
441 const char *CLibCEC::ToString(const cec_client_version version
)
443 return CCECTypeUtils::ToString(version
);
446 const char *CLibCEC::ToString(const cec_server_version version
)
448 return CCECTypeUtils::ToString(version
);
451 void CLibCEC::CheckKeypressTimeout(void)
454 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
455 (*it
)->CheckKeypressTimeout();
458 void CLibCEC::AddLog(const cec_log_level level
, const char *strFormat
, ...)
462 // format the message
464 va_start(argList
, strFormat
);
465 strLog
.FormatV(strFormat
, argList
);
468 cec_log_message message
;
469 message
.level
= level
;
470 message
.time
= GetTimeMs() - m_iStartTime
;
471 snprintf(message
.message
, sizeof(message
.message
), "%s", strLog
.c_str());
473 // send the message to all clients
474 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
475 (*it
)->AddLog(message
);
478 void CLibCEC::Alert(const libcec_alert type
, const libcec_parameter
¶m
)
480 // send the alert to all clients
481 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
482 (*it
)->Alert(type
, param
);
485 bool CLibCEC::SetActiveView(void)
487 AddLog(CEC_LOG_WARNING
, "deprecated method %s called", __FUNCTION__
);
488 return SetActiveSource();
491 bool CLibCEC::EnablePhysicalAddressDetection(void)
493 AddLog(CEC_LOG_WARNING
, "deprecated method %s called", __FUNCTION__
);
497 CCECClient
*CLibCEC::RegisterClient(libcec_configuration
&configuration
)
502 // create a new client instance
503 CCECClient
*newClient
= new CCECClient(m_cec
, configuration
);
506 m_clients
.push_back(newClient
);
508 // if the default client isn't set, set it
510 m_client
= newClient
;
512 // register the new client
513 if (m_cec
->CECInitialised())
514 m_cec
->RegisterClient(newClient
);
519 void CLibCEC::UnregisterClients(void)
522 m_cec
->UnregisterClients();
526 DELETE_AND_NULL(m_client
);
529 void * CECInitialise(libcec_configuration
*configuration
)
534 // create a new libCEC instance
535 CLibCEC
*lib
= new CLibCEC(NULL
);
537 // register a new client
538 CCECClient
*client(NULL
);
539 if (lib
&& configuration
)
540 client
= lib
->RegisterClient(*configuration
);
542 // update the current configuration
544 client
->GetCurrentConfiguration(*configuration
);
546 // ensure that the correct server version is set
547 configuration
->serverVersion
= LIBCEC_VERSION_CURRENT
;
549 return static_cast< void* > (lib
);
552 void * CECInit(const char *strDeviceName
, CEC::cec_device_type_list types
, uint16_t iPhysicalAddress
/* = 0 */)
554 libcec_configuration configuration
;
556 // client version < 1.5.0
557 snprintf(configuration
.strDeviceName
, 13, "%s", strDeviceName
);
558 configuration
.deviceTypes
= types
;
559 configuration
.iPhysicalAddress
= iPhysicalAddress
;
561 if (configuration
.deviceTypes
.IsEmpty())
562 configuration
.deviceTypes
.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE
);
564 return CECInitialise(&configuration
);
567 bool CECStartBootloader(void)
570 cec_adapter deviceList
[1];
571 if (CUSBCECAdapterDetection::FindAdapters(deviceList
, 1) > 0)
573 CUSBCECAdapterCommunication
comm(NULL
, deviceList
[0].comm
);
574 CTimeout
timeout(CEC_DEFAULT_CONNECT_TIMEOUT
);
575 while (timeout
.TimeLeft() > 0 && (bReturn
= comm
.Open(timeout
.TimeLeft() / CEC_CONNECT_TRIES
, true)) == false)
581 bReturn
= comm
.StartBootloader();
587 void CECDestroy(CEC::ICECAdapter
*instance
)
589 DELETE_AND_NULL(instance
);
592 bool CLibCEC::GetDeviceInformation(const char *strPort
, libcec_configuration
*config
, uint32_t iTimeoutMs
/* = CEC_DEFAULT_CONNECT_TIMEOUT */)
594 if (m_cec
->IsRunning())
597 return m_cec
->GetDeviceInformation(strPort
, config
, iTimeoutMs
);
600 // no longer being used
601 void CLibCEC::AddKey(const cec_keypress
&UNUSED(key
)) {}
602 void CLibCEC::AddCommand(const cec_command
&UNUSED(command
)) {}
603 void CLibCEC::ConfigurationChanged(const libcec_configuration
&UNUSED(config
)) {}
604 void CLibCEC::SetCurrentButton(cec_user_control_code
UNUSED(iButtonCode
)) {}
605 CLibCEC
*CLibCEC::GetInstance(void) { return NULL
; }
606 void CLibCEC::SetInstance(CLibCEC
*UNUSED(instance
)) {}