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 return CUSBCECAdapterDetection::FindAdapters(deviceList
, iBufSize
, strDevicePath
);
120 bool CLibCEC::StartBootloader(void)
122 return m_cec
? m_cec
->StartBootloader() : false;
125 bool CLibCEC::PingAdapter(void)
127 return m_client
? m_client
->PingAdapter() : false;
130 bool CLibCEC::EnableCallbacks(void *cbParam
, ICECCallbacks
*callbacks
)
132 return m_client
? m_client
->EnableCallbacks(cbParam
, callbacks
) : false;
135 bool CLibCEC::GetCurrentConfiguration(libcec_configuration
*configuration
)
137 return m_client
? m_client
->GetCurrentConfiguration(*configuration
) : false;
140 bool CLibCEC::SetConfiguration(const libcec_configuration
*configuration
)
142 return m_client
? m_client
->SetConfiguration(*configuration
) : false;
145 bool CLibCEC::CanPersistConfiguration(void)
147 return m_client
? m_client
->CanPersistConfiguration() : false;
150 bool CLibCEC::PersistConfiguration(libcec_configuration
*configuration
)
152 return m_client
? m_client
->PersistConfiguration(*configuration
) : false;
155 void CLibCEC::RescanActiveDevices(void)
158 m_client
->RescanActiveDevices();
161 bool CLibCEC::IsLibCECActiveSource(void)
163 return m_client
? m_client
->IsLibCECActiveSource() : false;
166 bool CLibCEC::Transmit(const cec_command
&data
)
168 return m_client
? m_client
->Transmit(data
) : false;
171 bool CLibCEC::SetLogicalAddress(cec_logical_address iLogicalAddress
)
173 return m_client
? m_client
->SetLogicalAddress(iLogicalAddress
) : false;
176 bool CLibCEC::SetPhysicalAddress(uint16_t iPhysicalAddress
/* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
178 return m_client
? m_client
->SetPhysicalAddress(iPhysicalAddress
) : false;
181 bool CLibCEC::SetHDMIPort(cec_logical_address iBaseDevice
, uint8_t iPort
/* = CEC_DEFAULT_HDMI_PORT */)
183 return m_client
? m_client
->SetHDMIPort(iBaseDevice
, iPort
) : false;
186 bool CLibCEC::PowerOnDevices(cec_logical_address address
/* = CECDEVICE_TV */)
188 return m_client
? m_client
->SendPowerOnDevices(address
) : false;
191 bool CLibCEC::StandbyDevices(cec_logical_address address
/* = CECDEVICE_BROADCAST */)
193 return m_client
? m_client
->SendStandbyDevices(address
) : false;
196 bool CLibCEC::SetActiveSource(cec_device_type type
/* = CEC_DEVICE_TYPE_RESERVED */)
198 return m_client
? m_client
->SendSetActiveSource(type
) : false;
201 bool CLibCEC::SetDeckControlMode(cec_deck_control_mode mode
, bool bSendUpdate
/* = true */)
203 return m_client
? m_client
->SendSetDeckControlMode(mode
, bSendUpdate
) : false;
206 bool CLibCEC::SetDeckInfo(cec_deck_info info
, bool bSendUpdate
/* = true */)
208 return m_client
? m_client
->SendSetDeckInfo(info
, bSendUpdate
) : false;
211 bool CLibCEC::SetInactiveView(void)
213 return m_client
? m_client
->SendSetInactiveView() : false;
216 bool CLibCEC::SetMenuState(cec_menu_state state
, bool bSendUpdate
/* = true */)
218 return m_client
? m_client
->SendSetMenuState(state
, bSendUpdate
) : false;
221 bool CLibCEC::SetOSDString(cec_logical_address iLogicalAddress
, cec_display_control duration
, const char *strMessage
)
223 return m_client
? m_client
->SendSetOSDString(iLogicalAddress
, duration
, strMessage
) : false;
226 bool CLibCEC::SwitchMonitoring(bool bEnable
)
228 return m_client
? m_client
->SwitchMonitoring(bEnable
) : false;
231 cec_version
CLibCEC::GetDeviceCecVersion(cec_logical_address iAddress
)
233 return m_client
? m_client
->GetDeviceCecVersion(iAddress
) : CEC_VERSION_UNKNOWN
;
236 bool CLibCEC::GetDeviceMenuLanguage(cec_logical_address iAddress
, cec_menu_language
*language
)
238 return m_client
? m_client
->GetDeviceMenuLanguage(iAddress
, *language
) : false;
241 uint64_t CLibCEC::GetDeviceVendorId(cec_logical_address iAddress
)
243 return m_client
? m_client
->GetDeviceVendorId(iAddress
) : (uint64_t)CEC_VENDOR_UNKNOWN
;
246 uint16_t CLibCEC::GetDevicePhysicalAddress(cec_logical_address iAddress
)
248 return m_client
? m_client
->GetDevicePhysicalAddress(iAddress
) : CEC_INVALID_PHYSICAL_ADDRESS
;
251 cec_power_status
CLibCEC::GetDevicePowerStatus(cec_logical_address iAddress
)
253 return m_client
? m_client
->GetDevicePowerStatus(iAddress
) : CEC_POWER_STATUS_UNKNOWN
;
256 bool CLibCEC::PollDevice(cec_logical_address iAddress
)
258 return m_client
? m_client
->PollDevice(iAddress
) : false;
261 cec_logical_addresses
CLibCEC::GetActiveDevices(void)
263 cec_logical_addresses addresses
;
266 addresses
= m_client
->GetActiveDevices();
270 bool CLibCEC::IsActiveDevice(cec_logical_address iAddress
)
272 return m_client
? m_client
->IsActiveDevice(iAddress
) : false;
275 bool CLibCEC::IsActiveDeviceType(cec_device_type type
)
277 return m_client
? m_client
->IsActiveDeviceType(type
) : false;
280 uint8_t CLibCEC::VolumeUp(bool bSendRelease
/* = true */)
282 return m_client
? m_client
->SendVolumeUp(bSendRelease
) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
285 uint8_t CLibCEC::VolumeDown(bool bSendRelease
/* = true */)
287 return m_client
? m_client
->SendVolumeDown(bSendRelease
) : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
290 uint8_t CLibCEC::MuteAudio(bool UNUSED(bSendRelease
) /* = true */)
292 return m_client
? m_client
->SendMuteAudio() : (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
295 bool CLibCEC::SendKeypress(cec_logical_address iDestination
, cec_user_control_code key
, bool bWait
/* = true */)
297 return m_client
? m_client
->SendKeypress(iDestination
, key
, bWait
) : false;
300 bool CLibCEC::SendKeyRelease(cec_logical_address iDestination
, bool bWait
/* = true */)
302 return m_client
? m_client
->SendKeyRelease(iDestination
, bWait
) : false;
305 cec_osd_name
CLibCEC::GetDeviceOSDName(cec_logical_address iAddress
)
308 retVal
.device
= CECDEVICE_UNKNOWN
;
309 memset(retVal
.name
, 0, 14);
312 retVal
= m_client
->GetDeviceOSDName(iAddress
);
316 cec_logical_address
CLibCEC::GetActiveSource(void)
318 return m_client
? m_client
->GetActiveSource() : CECDEVICE_UNKNOWN
;
321 bool CLibCEC::IsActiveSource(cec_logical_address iAddress
)
323 return m_client
? m_client
->IsActiveSource(iAddress
) : false;
325 bool CLibCEC::SetStreamPath(cec_logical_address iAddress
)
327 return m_client
? m_client
->SetStreamPath(iAddress
) : false;
330 bool CLibCEC::SetStreamPath(uint16_t iPhysicalAddress
)
332 return m_client
? m_client
->SetStreamPath(iPhysicalAddress
) : false;
335 cec_logical_addresses
CLibCEC::GetLogicalAddresses(void)
337 cec_logical_addresses addresses
;
340 m_client
->GetLogicalAddresses();
344 bool CLibCEC::GetNextLogMessage(cec_log_message
*message
)
346 return m_client
? m_client
->GetNextLogMessage(message
) : false;
349 bool CLibCEC::GetNextKeypress(cec_keypress
*key
)
351 return m_client
? m_client
->GetNextKeypress(key
) : false;
354 bool CLibCEC::GetNextCommand(cec_command
*command
)
356 return m_client
? m_client
->GetNextCommand(command
) : false;
359 cec_device_type
CLibCEC::GetType(cec_logical_address address
)
361 return CCECTypeUtils::GetType(address
);
364 uint16_t CLibCEC::GetMaskForType(cec_logical_address address
)
366 return CCECTypeUtils::GetMaskForType(address
);
369 uint16_t CLibCEC::GetMaskForType(cec_device_type type
)
371 return CCECTypeUtils::GetMaskForType(type
);
374 bool CLibCEC::IsValidPhysicalAddress(uint16_t iPhysicalAddress
)
376 return iPhysicalAddress
>= CEC_MIN_PHYSICAL_ADDRESS
&&
377 iPhysicalAddress
<= CEC_MAX_PHYSICAL_ADDRESS
;
380 const char *CLibCEC::ToString(const cec_device_type type
)
382 return CCECTypeUtils::ToString(type
);
385 const char *CLibCEC::ToString(const cec_menu_state state
)
387 return CCECTypeUtils::ToString(state
);
390 const char *CLibCEC::ToString(const cec_version version
)
392 return CCECTypeUtils::ToString(version
);
395 const char *CLibCEC::ToString(const cec_power_status status
)
397 return CCECTypeUtils::ToString(status
);
400 const char *CLibCEC::ToString(const cec_logical_address address
)
402 return CCECTypeUtils::ToString(address
);
405 const char *CLibCEC::ToString(const cec_deck_control_mode mode
)
407 return CCECTypeUtils::ToString(mode
);
410 const char *CLibCEC::ToString(const cec_deck_info status
)
412 return CCECTypeUtils::ToString(status
);
415 const char *CLibCEC::ToString(const cec_opcode opcode
)
417 return CCECTypeUtils::ToString(opcode
);
420 const char *CLibCEC::ToString(const cec_system_audio_status mode
)
422 return CCECTypeUtils::ToString(mode
);
425 const char *CLibCEC::ToString(const cec_audio_status status
)
427 return CCECTypeUtils::ToString(status
);
430 const char *CLibCEC::ToString(const cec_vendor_id vendor
)
432 return CCECTypeUtils::ToString(vendor
);
435 const char *CLibCEC::ToString(const cec_client_version version
)
437 return CCECTypeUtils::ToString(version
);
440 const char *CLibCEC::ToString(const cec_server_version version
)
442 return CCECTypeUtils::ToString(version
);
445 void CLibCEC::CheckKeypressTimeout(void)
448 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
449 (*it
)->CheckKeypressTimeout();
452 void CLibCEC::AddLog(const cec_log_level level
, const char *strFormat
, ...)
456 // format the message
458 va_start(argList
, strFormat
);
459 strLog
.FormatV(strFormat
, argList
);
462 cec_log_message message
;
463 message
.level
= level
;
464 message
.time
= GetTimeMs() - m_iStartTime
;
465 snprintf(message
.message
, sizeof(message
.message
), "%s", strLog
.c_str());
467 // send the message to all clients
468 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
469 (*it
)->AddLog(message
);
472 void CLibCEC::Alert(const libcec_alert type
, const libcec_parameter
¶m
)
474 // send the alert to all clients
475 for (vector
<CCECClient
*>::iterator it
= m_clients
.begin(); it
!= m_clients
.end(); it
++)
476 (*it
)->Alert(type
, param
);
479 bool CLibCEC::SetActiveView(void)
481 AddLog(CEC_LOG_WARNING
, "deprecated method %s called", __FUNCTION__
);
482 return SetActiveSource();
485 bool CLibCEC::EnablePhysicalAddressDetection(void)
487 AddLog(CEC_LOG_WARNING
, "deprecated method %s called", __FUNCTION__
);
491 CCECClient
*CLibCEC::RegisterClient(libcec_configuration
&configuration
)
496 // create a new client instance
497 CCECClient
*newClient
= new CCECClient(m_cec
, configuration
);
500 m_clients
.push_back(newClient
);
502 // if the default client isn't set, set it
504 m_client
= newClient
;
506 // register the new client
507 if (m_cec
->CECInitialised())
508 m_cec
->RegisterClient(newClient
);
513 void CLibCEC::UnregisterClients(void)
516 m_cec
->UnregisterClients();
520 DELETE_AND_NULL(m_client
);
523 void * CECInitialise(libcec_configuration
*configuration
)
528 // create a new libCEC instance
529 CLibCEC
*lib
= new CLibCEC(NULL
);
531 // register a new client
532 CCECClient
*client(NULL
);
533 if (lib
&& configuration
)
534 client
= lib
->RegisterClient(*configuration
);
536 // update the current configuration
538 client
->GetCurrentConfiguration(*configuration
);
540 // ensure that the correct server version is set
541 configuration
->serverVersion
= LIBCEC_VERSION_CURRENT
;
543 return static_cast< void* > (lib
);
546 void * CECInit(const char *strDeviceName
, CEC::cec_device_type_list types
, uint16_t iPhysicalAddress
/* = 0 */)
548 libcec_configuration configuration
;
550 // client version < 1.5.0
551 snprintf(configuration
.strDeviceName
, 13, "%s", strDeviceName
);
552 configuration
.deviceTypes
= types
;
553 configuration
.iPhysicalAddress
= iPhysicalAddress
;
555 if (configuration
.deviceTypes
.IsEmpty())
556 configuration
.deviceTypes
.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE
);
558 return CECInitialise(&configuration
);
561 bool CECStartBootloader(void)
564 cec_adapter deviceList
[1];
565 if (CUSBCECAdapterDetection::FindAdapters(deviceList
, 1) > 0)
567 CUSBCECAdapterCommunication
comm(NULL
, deviceList
[0].comm
);
568 CTimeout
timeout(CEC_DEFAULT_CONNECT_TIMEOUT
);
569 while (timeout
.TimeLeft() > 0 && (bReturn
= comm
.Open(timeout
.TimeLeft() / CEC_CONNECT_TRIES
, true)) == false)
575 bReturn
= comm
.StartBootloader();
581 void CECDestroy(CEC::ICECAdapter
*instance
)
583 DELETE_AND_NULL(instance
);
586 bool CLibCEC::GetDeviceInformation(const char *strPort
, libcec_configuration
*config
, uint32_t iTimeoutMs
/* = CEC_DEFAULT_CONNECT_TIMEOUT */)
588 if (m_cec
->IsRunning())
591 return m_cec
->GetDeviceInformation(strPort
, config
, iTimeoutMs
);
594 // no longer being used
595 void CLibCEC::AddKey(const cec_keypress
&UNUSED(key
)) {}
596 void CLibCEC::AddCommand(const cec_command
&UNUSED(command
)) {}
597 void CLibCEC::ConfigurationChanged(const libcec_configuration
&UNUSED(config
)) {}
598 void CLibCEC::SetCurrentButton(cec_user_control_code
UNUSED(iButtonCode
)) {}
599 CLibCEC
*CLibCEC::GetInstance(void) { return NULL
; }
600 void CLibCEC::SetInstance(CLibCEC
*UNUSED(instance
)) {}