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/
34 #include "CECClient.h"
36 #include "CECProcessor.h"
38 #include "CECTypeUtils.h"
39 #include "devices/CECPlaybackDevice.h"
40 #include "devices/CECAudioSystem.h"
41 #include "devices/CECTV.h"
42 #include "implementations/CECCommandHandler.h"
45 using namespace PLATFORM
;
47 #define LIB_CEC m_processor->GetLib()
48 #define ToString(x) CCECTypeUtils::ToString(x)
50 CCECClient::CCECClient(CCECProcessor
*processor
, const libcec_configuration
&configuration
) :
51 m_processor(processor
),
52 m_bInitialised(false),
54 m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN
),
56 m_iPreventForwardingPowerOffCommand(0)
58 m_configuration
.Clear();
59 // set the initial configuration
60 SetConfiguration(configuration
);
63 CCECClient::~CCECClient(void)
65 // unregister the client
66 if (m_processor
&& IsRegistered())
67 m_processor
->UnregisterClient(this);
70 bool CCECClient::IsInitialised(void)
72 CLockObject
lock(m_mutex
);
73 return m_bInitialised
&& m_processor
;
76 void CCECClient::SetInitialised(bool bSetTo
)
78 CLockObject
lock(m_mutex
);
79 m_bInitialised
= bSetTo
;
82 bool CCECClient::IsRegistered(void)
84 CLockObject
lock(m_mutex
);
85 return m_bRegistered
&& m_processor
;
88 void CCECClient::SetRegistered(bool bSetTo
)
90 CLockObject
lock(m_mutex
);
91 m_bRegistered
= bSetTo
;
94 bool CCECClient::OnRegister(void)
96 // return false if already initialised
100 // get all device we control
101 CECDEVICEVEC devices
;
102 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
104 // return false when no devices were found
107 LIB_CEC
->AddLog(CEC_LOG_WARNING
, "cannot find the primary device (logical address %x)", GetPrimaryLogicalAdddress());
111 // mark as initialised
112 SetInitialised(true);
114 // configure all devices
115 for (CECDEVICEVEC::iterator it
= devices
.begin(); it
!= devices
.end(); it
++)
117 // only set our OSD name for the primary device
118 if ((*it
)->GetLogicalAddress() == GetPrimaryLogicalAdddress())
119 (*it
)->SetOSDName(m_configuration
.strDeviceName
);
121 // set the default menu language for devices we control
122 (*it
)->SetMenuLanguage(m_configuration
.strDeviceLanguage
);
125 // set the physical address
126 SetPhysicalAddress(m_configuration
);
128 // make the primary device the active source if the option is set
129 if (m_configuration
.bActivateSource
== 1)
130 GetPrimaryDevice()->ActivateSource(500);
135 bool CCECClient::SetHDMIPort(const cec_logical_address iBaseDevice
, const uint8_t iPort
, bool bForce
/* = false */)
139 // limit the HDMI port range to 1-15
140 if (iPort
< CEC_MIN_HDMI_PORTNUMBER
||
141 iPort
> CEC_MAX_HDMI_PORTNUMBER
)
144 LIB_CEC
->AddLog(CEC_LOG_NOTICE
, "setting HDMI port to %d on device %s (%d)", iPort
, ToString(iBaseDevice
), (int)iBaseDevice
);
146 // update the configuration
148 CLockObject
lock(m_mutex
);
149 m_configuration
.baseDevice
= iBaseDevice
;
150 m_configuration
.iHDMIPort
= iPort
;
153 // don't continue if the connection isn't opened
154 if (!m_processor
->CECInitialised() && !bForce
)
157 // get the PA of the base device
158 uint16_t iPhysicalAddress(CEC_INVALID_PHYSICAL_ADDRESS
);
159 CCECBusDevice
*baseDevice
= m_processor
->GetDevice(iBaseDevice
);
161 iPhysicalAddress
= baseDevice
->GetPhysicalAddress(GetPrimaryLogicalAdddress());
163 // add our port number
164 if (iPhysicalAddress
<= CEC_MAX_PHYSICAL_ADDRESS
)
166 if (iPhysicalAddress
== 0)
167 iPhysicalAddress
+= 0x1000 * iPort
;
168 else if (iPhysicalAddress
% 0x1000 == 0)
169 iPhysicalAddress
+= 0x100 * iPort
;
170 else if (iPhysicalAddress
% 0x100 == 0)
171 iPhysicalAddress
+= 0x10 * iPort
;
172 else if (iPhysicalAddress
% 0x10 == 0)
173 iPhysicalAddress
+= iPort
;
178 // set the default address when something went wrong
181 LIB_CEC
->AddLog(CEC_LOG_WARNING
, "failed to set the physical address to %04X, setting it to the default value %04X", iPhysicalAddress
, CEC_DEFAULT_PHYSICAL_ADDRESS
);
182 iPhysicalAddress
= CEC_DEFAULT_PHYSICAL_ADDRESS
;
185 // and set the address
186 SetDevicePhysicalAddress(iPhysicalAddress
);
188 CallbackConfigurationChanged(m_configuration
);
193 void CCECClient::ResetPhysicalAddress(void)
195 SetPhysicalAddress(m_configuration
);
198 void CCECClient::SetPhysicalAddress(const libcec_configuration
&configuration
)
202 // override the physical address from configuration.iPhysicalAddress if it's set
203 if (!bPASet
&& CLibCEC::IsValidPhysicalAddress(configuration
.iPhysicalAddress
))
204 bPASet
= SetPhysicalAddress(configuration
.iPhysicalAddress
);
206 // try to autodetect the address
207 if (!bPASet
&& m_processor
->CECInitialised())
209 bPASet
= AutodetectPhysicalAddress();
210 m_configuration
.bAutodetectAddress
= bPASet
? 1 : 0;
213 // use the base device + hdmi port settings
215 bPASet
= SetHDMIPort(configuration
.baseDevice
, configuration
.iHDMIPort
);
217 // reset to defaults if something went wrong
220 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "%s - resetting HDMI port and base device to defaults", __FUNCTION__
);
221 m_configuration
.baseDevice
= CECDEVICE_UNKNOWN
;
222 m_configuration
.iHDMIPort
= CEC_HDMI_PORTNUMBER_NONE
;
226 bool CCECClient::SetPhysicalAddress(const uint16_t iPhysicalAddress
)
228 // update the configuration
231 CLockObject
lock(m_mutex
);
232 if (m_configuration
.iPhysicalAddress
== iPhysicalAddress
)
235 m_configuration
.iPhysicalAddress
= iPhysicalAddress
;
239 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "physical address unchanged (%04X)", iPhysicalAddress
);
243 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "setting physical address to '%04X'", iPhysicalAddress
);
245 // set the physical address for each device
246 SetDevicePhysicalAddress(iPhysicalAddress
);
248 // and send back the updated configuration
249 CallbackConfigurationChanged(m_configuration
);
254 void CCECClient::SetSupportedDeviceTypes(void)
256 cec_device_type_list types
;
259 // get the command handler for the tv
260 CCECCommandHandler
*tvHandler
= m_processor
->GetTV()->GetHandler();
264 // check all device types
265 for (uint8_t iPtr
= 0; iPtr
< 5; iPtr
++)
267 if (m_configuration
.deviceTypes
.types
[iPtr
] == CEC_DEVICE_TYPE_RESERVED
)
270 // get the supported device type. the handler will replace types it doesn't support by one it does support
271 cec_device_type type
= tvHandler
->GetReplacementDeviceType(m_configuration
.deviceTypes
.types
[iPtr
]);
272 if (!types
.IsSet(type
))
275 m_processor
->GetTV()->MarkHandlerReady();
277 // set the new type list
278 m_configuration
.deviceTypes
= types
;
280 // persist the new configuration
281 PersistConfiguration(m_configuration
);
284 bool CCECClient::AllocateLogicalAddresses(void)
286 // reset all previous LAs that were set
287 m_configuration
.logicalAddresses
.Clear();
289 // get the supported device types from the command handler of the TV
290 SetSupportedDeviceTypes();
292 // display an error if no device types are set
293 if (m_configuration
.deviceTypes
.IsEmpty())
295 LIB_CEC
->AddLog(CEC_LOG_ERROR
, "no device types given");
299 // check each entry of the list
300 for (uint8_t iPtr
= 0; iPtr
< 5; iPtr
++)
302 if (m_configuration
.deviceTypes
.types
[iPtr
] == CEC_DEVICE_TYPE_RESERVED
)
305 // find an LA for this type
306 cec_logical_address
address(CECDEVICE_UNKNOWN
);
307 if (m_configuration
.deviceTypes
.types
[iPtr
] == CEC_DEVICE_TYPE_RECORDING_DEVICE
)
308 address
= AllocateLogicalAddressRecordingDevice();
309 if (m_configuration
.deviceTypes
.types
[iPtr
] == CEC_DEVICE_TYPE_TUNER
)
310 address
= AllocateLogicalAddressTuner();
311 if (m_configuration
.deviceTypes
.types
[iPtr
] == CEC_DEVICE_TYPE_PLAYBACK_DEVICE
)
312 address
= AllocateLogicalAddressPlaybackDevice();
313 if (m_configuration
.deviceTypes
.types
[iPtr
] == CEC_DEVICE_TYPE_AUDIO_SYSTEM
)
314 address
= AllocateLogicalAddressAudioSystem();
316 // display an error if no LA could be allocated
317 if (address
== CECDEVICE_UNKNOWN
)
319 LIB_CEC
->AddLog(CEC_LOG_ERROR
, "%s - failed to allocate device '%d', type '%s'", __FUNCTION__
, iPtr
, ToString(m_configuration
.deviceTypes
.types
[iPtr
]));
323 // display the registered LA
324 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "%s - device '%d', type '%s', LA '%X'", __FUNCTION__
, iPtr
, ToString(m_configuration
.deviceTypes
.types
[iPtr
]), address
);
325 m_configuration
.logicalAddresses
.Set(address
);
328 // persist the new configuration
329 PersistConfiguration(m_configuration
);
334 cec_logical_address
CCECClient::AllocateLogicalAddressRecordingDevice(void)
336 cec_logical_address
retVal(CECDEVICE_UNKNOWN
);
338 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "detecting logical address for type 'recording device'");
339 if (m_processor
->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE1
, m_configuration
.cecVersion
))
340 retVal
= CECDEVICE_RECORDINGDEVICE1
;
341 else if (m_processor
->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE2
, m_configuration
.cecVersion
))
342 retVal
= CECDEVICE_RECORDINGDEVICE2
;
343 else if (m_processor
->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE3
, m_configuration
.cecVersion
))
344 retVal
= CECDEVICE_RECORDINGDEVICE3
;
349 cec_logical_address
CCECClient::AllocateLogicalAddressTuner(void)
351 cec_logical_address
retVal(CECDEVICE_UNKNOWN
);
353 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "detecting logical address for type 'tuner'");
354 if (m_processor
->TryLogicalAddress(CECDEVICE_TUNER1
, m_configuration
.cecVersion
))
355 retVal
= CECDEVICE_TUNER1
;
356 else if (m_processor
->TryLogicalAddress(CECDEVICE_TUNER2
, m_configuration
.cecVersion
))
357 retVal
= CECDEVICE_TUNER2
;
358 else if (m_processor
->TryLogicalAddress(CECDEVICE_TUNER3
, m_configuration
.cecVersion
))
359 retVal
= CECDEVICE_TUNER3
;
360 else if (m_processor
->TryLogicalAddress(CECDEVICE_TUNER4
, m_configuration
.cecVersion
))
361 retVal
= CECDEVICE_TUNER4
;
366 cec_logical_address
CCECClient::AllocateLogicalAddressPlaybackDevice(void)
368 cec_logical_address
retVal(CECDEVICE_UNKNOWN
);
370 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "detecting logical address for type 'playback device'");
371 if (m_processor
->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE1
, m_configuration
.cecVersion
))
372 retVal
= CECDEVICE_PLAYBACKDEVICE1
;
373 else if (m_processor
->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE2
, m_configuration
.cecVersion
))
374 retVal
= CECDEVICE_PLAYBACKDEVICE2
;
375 else if (m_processor
->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE3
, m_configuration
.cecVersion
))
376 retVal
= CECDEVICE_PLAYBACKDEVICE3
;
381 cec_logical_address
CCECClient::AllocateLogicalAddressAudioSystem(void)
383 cec_logical_address
retVal(CECDEVICE_UNKNOWN
);
385 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "detecting logical address for type 'audiosystem'");
386 if (m_processor
->TryLogicalAddress(CECDEVICE_AUDIOSYSTEM
, m_configuration
.cecVersion
))
387 retVal
= CECDEVICE_AUDIOSYSTEM
;
392 CCECBusDevice
*CCECClient::GetDeviceByType(const cec_device_type type
) const
394 // get all devices that match our logical addresses
395 CECDEVICEVEC devices
;
396 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
398 // filter the type we need
399 CCECDeviceMap::FilterType(type
, devices
);
401 return devices
.empty() ?
406 bool CCECClient::ChangeDeviceType(const cec_device_type from
, const cec_device_type to
)
411 LIB_CEC
->AddLog(CEC_LOG_NOTICE
, "changing device type '%s' into '%s'", ToString(from
), ToString(to
));
414 CLockObject
lock(m_mutex
);
416 // get the previous device that was allocated
417 CCECBusDevice
*previousDevice
= GetDeviceByType(from
);
421 // change the type in the device type list
422 bool bChanged(false);
423 for (uint8_t iPtr
= 0; iPtr
< 5; iPtr
++)
425 if (m_configuration
.deviceTypes
.types
[iPtr
] == CEC_DEVICE_TYPE_RESERVED
)
428 if (m_configuration
.deviceTypes
.types
[iPtr
] == from
)
431 m_configuration
.deviceTypes
.types
[iPtr
] = to
;
433 else if (m_configuration
.deviceTypes
.types
[iPtr
] == to
&& bChanged
)
435 // ensure that dupes are removed
436 m_configuration
.deviceTypes
.types
[iPtr
] = CEC_DEVICE_TYPE_RESERVED
;
441 // re-register the client to set the new ackmask
442 if (!m_processor
->RegisterClient(this))
445 // persist the new configuration
446 PersistConfiguration(m_configuration
);
451 bool CCECClient::SetLogicalAddress(const cec_logical_address iLogicalAddress
)
455 if (GetPrimaryLogicalAdddress() != iLogicalAddress
)
457 LIB_CEC
->AddLog(CEC_LOG_NOTICE
, "<< setting primary logical address to %1x", iLogicalAddress
);
459 CLockObject
lock(m_mutex
);
460 m_configuration
.logicalAddresses
.primary
= iLogicalAddress
;
461 m_configuration
.logicalAddresses
.Set(iLogicalAddress
);
464 bReturn
= m_processor
->RegisterClient(this);
466 // persist the new configuration
468 PersistConfiguration(m_configuration
);
474 bool CCECClient::Transmit(const cec_command
&data
, bool bIsReply
)
476 return m_processor
? m_processor
->Transmit(data
, bIsReply
) : false;
479 bool CCECClient::SendPowerOnDevices(const cec_logical_address address
/* = CECDEVICE_TV */)
481 // if the broadcast address if set as destination and the client version >=1.5.0, read the wakeDevices setting
482 if (address
== CECDEVICE_BROADCAST
&& m_configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_5_0
)
484 CECDEVICEVEC devices
;
485 m_processor
->GetDevices()->GetWakeDevices(m_configuration
, devices
);
486 return m_processor
->PowerOnDevices(GetPrimaryLogicalAdddress(), devices
);
489 return m_processor
->PowerOnDevice(GetPrimaryLogicalAdddress(), address
);
492 bool CCECClient::SendStandbyDevices(const cec_logical_address address
/* = CECDEVICE_BROADCAST */)
494 // if the broadcast address if set as destination and the client version >=1.5.0, read the standbyDevices setting
495 if (address
== CECDEVICE_BROADCAST
&& m_configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_5_0
)
497 CECDEVICEVEC devices
;
498 m_processor
->GetDevices()->GetPowerOffDevices(m_configuration
, devices
);
499 return m_processor
->StandbyDevices(GetPrimaryLogicalAdddress(), devices
);
502 return m_processor
->StandbyDevice(GetPrimaryLogicalAdddress(), address
);
505 bool CCECClient::SendSetActiveSource(const cec_device_type type
/* = CEC_DEVICE_TYPE_RESERVED */)
507 // get the devices that are controlled by us
508 CECDEVICEVEC devices
;
509 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
511 // filter out the device that matches the given type
512 if (type
!= CEC_DEVICE_TYPE_RESERVED
)
513 CCECDeviceMap::FilterType(type
, devices
);
515 // no devices left, re-fetch the list of devices that are controlled by us
517 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
519 if (!devices
.empty())
521 // get the first device from the list
522 CCECBusDevice
*device
= *devices
.begin();
525 if (!m_processor
->CECInitialised())
526 device
->MarkAsActiveSource();
527 else if (device
->HasValidPhysicalAddress())
528 return device
->ActivateSource();
534 CCECPlaybackDevice
*CCECClient::GetPlaybackDevice(void)
536 CCECPlaybackDevice
*device(NULL
);
537 CECDEVICEVEC devices
;
539 // get the playback devices
540 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
541 CCECDeviceMap::FilterType(CEC_DEVICE_TYPE_PLAYBACK_DEVICE
, devices
);
543 // no matches, get the recording devices
546 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
547 CCECDeviceMap::FilterType(CEC_DEVICE_TYPE_RECORDING_DEVICE
, devices
);
550 // get the first device that matches, and cast it to CCECPlaybackDevice
551 if (!devices
.empty())
552 device
= (*devices
.begin())->AsPlaybackDevice();
557 cec_logical_address
CCECClient::GetPrimaryLogicalAdddress(void)
559 CLockObject
lock(m_mutex
);
560 return m_configuration
.logicalAddresses
.primary
;
563 CCECBusDevice
*CCECClient::GetPrimaryDevice(void)
565 return m_processor
->GetDevice(GetPrimaryLogicalAdddress());
568 bool CCECClient::SendSetDeckControlMode(const cec_deck_control_mode mode
, bool bSendUpdate
/* = true */)
570 // find a playback device that we control
571 CCECPlaybackDevice
*device
= GetPlaybackDevice();
574 // and set the deck control mode if there is a match
575 device
->SetDeckControlMode(mode
);
577 return device
->TransmitDeckStatus(CECDEVICE_TV
, false);
585 bool CCECClient::SendSetDeckInfo(const cec_deck_info info
, bool bSendUpdate
/* = true */)
587 // find a playback device that we control
588 CCECPlaybackDevice
*device
= GetPlaybackDevice();
591 // and set the deck status if there is a match
592 device
->SetDeckStatus(info
);
594 return device
->AsPlaybackDevice()->TransmitDeckStatus(CECDEVICE_TV
, false);
602 bool CCECClient::SendSetMenuState(const cec_menu_state state
, bool bSendUpdate
/* = true */)
604 CECDEVICEVEC devices
;
606 // set the menu state for all devices that are controlled by us
607 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
608 for (CECDEVICEVEC::iterator it
= devices
.begin(); it
!= devices
.end(); it
++)
610 (*it
)->SetMenuState(state
);
612 (*it
)->TransmitMenuState(CECDEVICE_TV
, false);
618 bool CCECClient::SendSetInactiveView(void)
620 CECDEVICEVEC devices
;
622 // mark all devices that are controlled by us as inactive source
623 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
624 for (CECDEVICEVEC::iterator it
= devices
.begin(); it
!= devices
.end(); it
++)
626 if ((*it
)->IsActiveSource())
628 (*it
)->MarkAsInactiveSource();
629 return (*it
)->TransmitInactiveSource();
636 bool CCECClient::SendSetOSDString(const cec_logical_address iLogicalAddress
, const cec_display_control duration
, const char *strMessage
)
638 CCECBusDevice
*primary
= GetPrimaryDevice();
640 return primary
->TransmitOSDString(iLogicalAddress
, duration
, strMessage
, false);
645 cec_version
CCECClient::GetDeviceCecVersion(const cec_logical_address iAddress
)
647 CCECBusDevice
*device
= m_processor
->GetDevice(iAddress
);
649 return device
->GetCecVersion(GetPrimaryLogicalAdddress());
650 return CEC_VERSION_UNKNOWN
;
653 bool CCECClient::GetDeviceMenuLanguage(const cec_logical_address iAddress
, cec_menu_language
&language
)
655 CCECBusDevice
*device
= m_processor
->GetDevice(iAddress
);
658 language
= device
->GetMenuLanguage(GetPrimaryLogicalAdddress());
659 return (strcmp(language
.language
, "???") != 0);
664 cec_osd_name
CCECClient::GetDeviceOSDName(const cec_logical_address iAddress
)
667 retVal
.device
= iAddress
;
670 CCECBusDevice
*device
= m_processor
->GetDevice(iAddress
);
673 CStdString strOSDName
= device
->GetOSDName(GetPrimaryLogicalAdddress());
674 snprintf(retVal
.name
, sizeof(retVal
.name
), "%s", strOSDName
.c_str());
675 retVal
.device
= iAddress
;
681 uint16_t CCECClient::GetDevicePhysicalAddress(const cec_logical_address iAddress
)
683 CCECBusDevice
*device
= m_processor
->GetDevice(iAddress
);
685 return device
->GetPhysicalAddress(GetPrimaryLogicalAdddress());
686 return CEC_INVALID_PHYSICAL_ADDRESS
;
689 cec_power_status
CCECClient::GetDevicePowerStatus(const cec_logical_address iAddress
)
691 CCECBusDevice
*device
= m_processor
->GetDevice(iAddress
);
693 return device
->GetPowerStatus(GetPrimaryLogicalAdddress());
694 return CEC_POWER_STATUS_UNKNOWN
;
697 uint64_t CCECClient::GetDeviceVendorId(const cec_logical_address iAddress
)
699 CCECBusDevice
*device
= m_processor
->GetDevice(iAddress
);
701 return device
->GetVendorId(GetPrimaryLogicalAdddress());
702 return CEC_VENDOR_UNKNOWN
;
705 uint8_t CCECClient::SendVolumeUp(bool bSendRelease
/* = true */)
707 CCECBusDevice
*device
= GetPrimaryDevice();
708 CCECAudioSystem
*audio
= m_processor
->GetAudioSystem();
710 return device
&& audio
&& audio
->IsPresent() ?
711 audio
->VolumeUp(device
->GetLogicalAddress(), bSendRelease
) :
712 (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
715 uint8_t CCECClient::SendVolumeDown(bool bSendRelease
/* = true */)
717 CCECBusDevice
*device
= GetPrimaryDevice();
718 CCECAudioSystem
*audio
= m_processor
->GetAudioSystem();
720 return device
&& audio
&& audio
->IsPresent() ?
721 audio
->VolumeDown(device
->GetLogicalAddress(), bSendRelease
) :
722 (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
725 uint8_t CCECClient::SendMuteAudio(void)
727 CCECBusDevice
*device
= GetPrimaryDevice();
728 CCECAudioSystem
*audio
= m_processor
->GetAudioSystem();
730 return device
&& audio
&& audio
->IsPresent() ?
731 audio
->MuteAudio(device
->GetLogicalAddress()) :
732 (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN
;
735 bool CCECClient::SendKeypress(const cec_logical_address iDestination
, const cec_user_control_code key
, bool bWait
/* = true */)
737 CCECBusDevice
*dest
= m_processor
->GetDevice(iDestination
);
740 dest
->TransmitKeypress(GetPrimaryLogicalAdddress(), key
, bWait
) :
744 bool CCECClient::SendKeyRelease(const cec_logical_address iDestination
, bool bWait
/* = true */)
746 CCECBusDevice
*dest
= m_processor
->GetDevice(iDestination
);
749 dest
->TransmitKeyRelease(GetPrimaryLogicalAdddress(), bWait
) :
753 bool CCECClient::GetCurrentConfiguration(libcec_configuration
&configuration
)
755 CLockObject
lock(m_mutex
);
757 // client version 1.5.0
758 snprintf(configuration
.strDeviceName
, 13, "%s", m_configuration
.strDeviceName
);
759 configuration
.deviceTypes
= m_configuration
.deviceTypes
;
760 configuration
.bAutodetectAddress
= m_configuration
.bAutodetectAddress
;
761 configuration
.iPhysicalAddress
= m_configuration
.iPhysicalAddress
;
762 configuration
.baseDevice
= m_configuration
.baseDevice
;
763 configuration
.iHDMIPort
= m_configuration
.iHDMIPort
;
764 configuration
.clientVersion
= m_configuration
.clientVersion
;
765 configuration
.serverVersion
= m_configuration
.serverVersion
;
766 configuration
.tvVendor
= m_configuration
.tvVendor
;
768 configuration
.bGetSettingsFromROM
= m_configuration
.bGetSettingsFromROM
;
769 configuration
.bUseTVMenuLanguage
= m_configuration
.bUseTVMenuLanguage
;
770 configuration
.bActivateSource
= m_configuration
.bActivateSource
;
771 configuration
.wakeDevices
= m_configuration
.wakeDevices
;
772 configuration
.powerOffDevices
= m_configuration
.powerOffDevices
;
773 configuration
.bPowerOffScreensaver
= m_configuration
.bPowerOffScreensaver
;
774 configuration
.bPowerOffOnStandby
= m_configuration
.bPowerOffOnStandby
;
776 // client version 1.5.1
777 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_5_1
)
778 configuration
.bSendInactiveSource
= m_configuration
.bSendInactiveSource
;
780 // client version 1.5.3
781 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_5_3
)
782 configuration
.logicalAddresses
= m_configuration
.logicalAddresses
;
784 // client version 1.6.0
785 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_6_0
)
787 configuration
.iFirmwareVersion
= m_configuration
.iFirmwareVersion
;
788 configuration
.bPowerOffDevicesOnStandby
= m_configuration
.bPowerOffDevicesOnStandby
;
789 configuration
.bShutdownOnStandby
= m_configuration
.bShutdownOnStandby
;
792 // client version 1.6.2
793 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_6_2
)
795 memcpy(configuration
.strDeviceLanguage
, m_configuration
.strDeviceLanguage
, 3);
796 configuration
.iFirmwareBuildDate
= m_configuration
.iFirmwareBuildDate
;
799 // client version 1.6.3
800 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_6_3
)
802 configuration
.bMonitorOnly
= m_configuration
.bMonitorOnly
;
805 // client version 1.8.0
806 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_8_0
)
807 configuration
.cecVersion
= m_configuration
.cecVersion
;
809 // client version 1.8.2
810 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_8_2
)
811 configuration
.adapterType
= m_configuration
.adapterType
;
816 bool CCECClient::SetConfiguration(const libcec_configuration
&configuration
)
818 bool bIsRunning(m_processor
&& m_processor
->CECInitialised());
819 CCECBusDevice
*primary
= bIsRunning
? GetPrimaryDevice() : NULL
;
820 uint16_t iPA
= primary
? primary
->GetCurrentPhysicalAddress() : CEC_INVALID_PHYSICAL_ADDRESS
;
822 // update the callbacks
823 if (configuration
.callbacks
)
824 EnableCallbacks(configuration
.callbackParam
, configuration
.callbacks
);
826 // update the client version
827 SetClientVersion((cec_client_version
)configuration
.clientVersion
);
829 // update the OSD name
830 CStdString
strOSDName(configuration
.strDeviceName
);
831 SetOSDName(strOSDName
);
833 // update the TV vendor override
834 SetTVVendorOverride((cec_vendor_id
)configuration
.tvVendor
);
838 CLockObject
lock(m_mutex
);
839 m_configuration
.bUseTVMenuLanguage
= configuration
.bUseTVMenuLanguage
;
840 m_configuration
.bActivateSource
= configuration
.bActivateSource
;
841 m_configuration
.bGetSettingsFromROM
= configuration
.bGetSettingsFromROM
;
842 m_configuration
.wakeDevices
= configuration
.wakeDevices
;
843 m_configuration
.powerOffDevices
= configuration
.powerOffDevices
;
844 m_configuration
.bPowerOffScreensaver
= configuration
.bPowerOffScreensaver
;
845 m_configuration
.bPowerOffOnStandby
= configuration
.bPowerOffOnStandby
;
847 // client version 1.5.1
848 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_5_1
)
849 m_configuration
.bSendInactiveSource
= configuration
.bSendInactiveSource
;
851 // client version 1.6.0
852 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_6_0
)
854 m_configuration
.bPowerOffDevicesOnStandby
= configuration
.bPowerOffDevicesOnStandby
;
855 m_configuration
.bShutdownOnStandby
= configuration
.bShutdownOnStandby
;
858 // client version 1.6.2
859 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_6_2
)
861 memcpy(m_configuration
.strDeviceLanguage
, configuration
.strDeviceLanguage
, 3);
864 // client version 1.6.3
865 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_6_3
)
867 m_configuration
.bMonitorOnly
= configuration
.bMonitorOnly
;
870 // client version 1.8.0
871 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_8_0
)
872 m_configuration
.cecVersion
= configuration
.cecVersion
;
874 // client version 1.8.2
875 if (configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_8_2
)
876 m_configuration
.adapterType
= configuration
.adapterType
;
878 // ensure that there is at least 1 device type set
879 if (m_configuration
.deviceTypes
.IsEmpty())
880 m_configuration
.deviceTypes
.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE
);
883 bool bNeedReinit(false);
886 if (SetDeviceTypes(configuration
.deviceTypes
))
888 // the device type changed. just copy the rest, and re-register
890 CLockObject
lock(m_mutex
);
891 m_configuration
.iPhysicalAddress
= configuration
.iPhysicalAddress
;
892 m_configuration
.baseDevice
= configuration
.baseDevice
;
893 m_configuration
.iHDMIPort
= configuration
.iHDMIPort
;
899 // set the physical address
900 SetPhysicalAddress(configuration
);
903 // persist the new configuration
904 PersistConfiguration(m_configuration
);
907 primary
= GetPrimaryDevice();
909 if (bNeedReinit
|| !primary
|| primary
->GetCurrentPhysicalAddress() != iPA
)
911 // PA or device type changed
912 m_processor
->RegisterClient(this);
914 else if (primary
&& configuration
.bActivateSource
== 1 && bIsRunning
&& !primary
->IsActiveSource())
916 // activate the source if we're not already the active source
917 primary
->ActivateSource();
923 void CCECClient::AddCommand(const cec_command
&command
)
925 // don't forward the standby opcode more than once every 10 seconds
926 if (command
.opcode
== CEC_OPCODE_STANDBY
)
928 CLockObject
lock(m_mutex
);
929 if (m_iPreventForwardingPowerOffCommand
!= 0 &&
930 m_iPreventForwardingPowerOffCommand
> GetTimeMs())
933 m_iPreventForwardingPowerOffCommand
= GetTimeMs() + CEC_FORWARD_STANDBY_MIN_INTERVAL
;
936 if (command
.destination
== CECDEVICE_BROADCAST
|| GetLogicalAddresses().IsSet(command
.destination
))
938 LIB_CEC
->AddLog(CEC_LOG_NOTICE
, ">> %s (%X) -> %s (%X): %s (%2X)", ToString(command
.initiator
), command
.initiator
, ToString(command
.destination
), command
.destination
, ToString(command
.opcode
), command
.opcode
);
939 CallbackAddCommand(command
);
943 int CCECClient::MenuStateChanged(const cec_menu_state newState
)
945 LIB_CEC
->AddLog(CEC_LOG_NOTICE
, ">> %s: %s", ToString(CEC_OPCODE_MENU_REQUEST
), ToString(newState
));
946 return CallbackMenuStateChanged(newState
);
949 void CCECClient::AddKey(void)
952 key
.keycode
= CEC_USER_CONTROL_CODE_UNKNOWN
;
955 CLockObject
lock(m_mutex
);
956 if (m_iCurrentButton
!= CEC_USER_CONTROL_CODE_UNKNOWN
)
958 key
.duration
= (unsigned int) (GetTimeMs() - m_buttontime
);
959 key
.keycode
= m_iCurrentButton
;
961 m_iCurrentButton
= CEC_USER_CONTROL_CODE_UNKNOWN
;
966 if (key
.keycode
!= CEC_USER_CONTROL_CODE_UNKNOWN
)
968 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "key released: %s (%1x)", ToString(key
.keycode
), key
.keycode
);
973 void CCECClient::AddKey(const cec_keypress
&key
)
976 CLockObject
lock(m_mutex
);
977 m_iCurrentButton
= key
.duration
> 0 ? CEC_USER_CONTROL_CODE_UNKNOWN
: key
.keycode
;
978 m_buttontime
= key
.duration
> 0 ? 0 : GetTimeMs();
981 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "key pressed: %s (%1x)", ToString(key
.keycode
), key
.keycode
);
985 void CCECClient::SetCurrentButton(const cec_user_control_code iButtonCode
)
987 // push a keypress to the buffer with 0 duration and another with the duration set when released
990 key
.keycode
= iButtonCode
;
995 void CCECClient::CheckKeypressTimeout(void)
1000 CLockObject
lock(m_mutex
);
1001 uint64_t iNow
= GetTimeMs();
1003 if (m_iCurrentButton
!= CEC_USER_CONTROL_CODE_UNKNOWN
&&
1004 iNow
- m_buttontime
> CEC_BUTTON_TIMEOUT
)
1006 key
.duration
= (unsigned int) (iNow
- m_buttontime
);
1007 key
.keycode
= m_iCurrentButton
;
1009 m_iCurrentButton
= CEC_USER_CONTROL_CODE_UNKNOWN
;
1018 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "key auto-released: %s (%1x)", ToString(key
.keycode
), key
.keycode
);
1019 CallbackAddKey(key
);
1022 bool CCECClient::EnableCallbacks(void *cbParam
, ICECCallbacks
*callbacks
)
1024 CLockObject
lock(m_cbMutex
);
1025 m_configuration
.callbackParam
= cbParam
;
1026 m_configuration
.callbacks
= callbacks
;
1030 bool CCECClient::PingAdapter(void)
1032 return m_processor
? m_processor
->PingAdapter() : false;
1035 bool CCECClient::GetNextLogMessage(cec_log_message
*message
)
1037 return (m_logBuffer
.Pop(*message
));
1040 bool CCECClient::GetNextKeypress(cec_keypress
*key
)
1042 return m_keyBuffer
.Pop(*key
);
1045 bool CCECClient::GetNextCommand(cec_command
*command
)
1047 return m_commandBuffer
.Pop(*command
);
1050 std::string
CCECClient::GetConnectionInfo(void)
1053 strLog
.Format("libCEC version = %s, client version = %s, firmware version = %d", ToString((cec_server_version
)m_configuration
.serverVersion
), ToString((cec_client_version
)m_configuration
.clientVersion
), m_configuration
.iFirmwareVersion
);
1054 if (m_configuration
.iFirmwareBuildDate
!= CEC_FW_BUILD_UNKNOWN
)
1056 time_t buildTime
= (time_t)m_configuration
.iFirmwareBuildDate
;
1057 strLog
.AppendFormat(", firmware build date: %s", asctime(gmtime(&buildTime
)));
1058 strLog
= strLog
.Left((int)strLog
.length() - 1); // strip \n added by asctime
1059 strLog
.append(" +0000");
1062 // log the addresses that are being used
1063 if (!m_configuration
.logicalAddresses
.IsEmpty())
1065 strLog
.append(", logical address(es) = ");
1066 CECDEVICEVEC devices
;
1067 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
1068 for (CECDEVICEVEC::iterator it
= devices
.begin(); it
!= devices
.end(); it
++)
1069 strLog
.AppendFormat("%s (%X) ", (*it
)->GetLogicalAddressName(), (*it
)->GetLogicalAddress());
1072 if (!CLibCEC::IsValidPhysicalAddress(m_configuration
.iPhysicalAddress
))
1073 strLog
.AppendFormat(", base device: %s (%X), HDMI port number: %d", ToString(m_configuration
.baseDevice
), m_configuration
.baseDevice
, m_configuration
.iHDMIPort
);
1075 strLog
.AppendFormat(", physical address: %04x", m_configuration
.iPhysicalAddress
);
1077 strLog
.AppendFormat(", %s", LIB_CEC
->GetLibInfo());
1079 std::string
strReturn(strLog
.c_str());
1083 void CCECClient::SetTVVendorOverride(const cec_vendor_id id
)
1086 CLockObject
lock(m_mutex
);
1087 m_configuration
.tvVendor
= id
;
1090 if (id
!= CEC_VENDOR_UNKNOWN
)
1092 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "%s - vendor id '%s'", __FUNCTION__
, ToString(id
));
1094 CCECBusDevice
*tv
= m_processor
? m_processor
->GetTV() : NULL
;
1096 tv
->SetVendorId((uint64_t)id
);
1099 // persist the new configuration
1100 PersistConfiguration(m_configuration
);
1103 cec_vendor_id
CCECClient::GetTVVendorOverride(void)
1105 CLockObject
lock(m_mutex
);
1106 return (cec_vendor_id
)m_configuration
.tvVendor
;
1109 void CCECClient::SetOSDName(const std::string
&strDeviceName
)
1112 CLockObject
lock(m_mutex
);
1113 snprintf(m_configuration
.strDeviceName
, 13, "%s", strDeviceName
.c_str());
1116 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "%s - using OSD name '%s'", __FUNCTION__
, strDeviceName
.c_str());
1118 CCECBusDevice
*primary
= GetPrimaryDevice();
1119 if (primary
&& !primary
->GetCurrentOSDName().Equals(strDeviceName
.c_str()))
1121 primary
->SetOSDName(strDeviceName
);
1122 if (m_processor
&& m_processor
->CECInitialised())
1123 primary
->TransmitOSDName(CECDEVICE_TV
, false);
1126 // persist the new configuration
1127 PersistConfiguration(m_configuration
);
1130 std::string
CCECClient::GetOSDName(void)
1132 CLockObject
lock(m_mutex
);
1133 std::string
strOSDName(m_configuration
.strDeviceName
);
1137 void CCECClient::SetWakeDevices(const cec_logical_addresses
&addresses
)
1140 CLockObject
lock(m_mutex
);
1141 m_configuration
.wakeDevices
= addresses
;
1143 // persist the new configuration
1144 PersistConfiguration(m_configuration
);
1147 cec_logical_addresses
CCECClient::GetWakeDevices(void)
1149 CLockObject
lock(m_mutex
);
1150 return m_configuration
.wakeDevices
;
1153 bool CCECClient::AutodetectPhysicalAddress(void)
1155 bool bPhysicalAutodetected(false);
1156 uint16_t iPhysicalAddress
= m_processor
? m_processor
->GetDetectedPhysicalAddress() : CEC_INVALID_PHYSICAL_ADDRESS
;
1158 if (CLibCEC::IsValidPhysicalAddress(iPhysicalAddress
))
1160 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "%s - autodetected physical address '%04X'", __FUNCTION__
, iPhysicalAddress
);
1162 CLockObject
lock(m_mutex
);
1163 m_configuration
.iPhysicalAddress
= iPhysicalAddress
;
1164 m_configuration
.iHDMIPort
= CEC_HDMI_PORTNUMBER_NONE
;
1165 m_configuration
.baseDevice
= CECDEVICE_UNKNOWN
;
1166 bPhysicalAutodetected
= true;
1169 SetDevicePhysicalAddress(iPhysicalAddress
);
1171 return bPhysicalAutodetected
;
1174 void CCECClient::SetClientVersion(const cec_client_version version
)
1176 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "%s - using client version '%s'", __FUNCTION__
, ToString(version
));
1178 CLockObject
lock(m_mutex
);
1179 m_configuration
.clientVersion
= (uint32_t)version
;
1182 cec_client_version
CCECClient::GetClientVersion(void)
1184 CLockObject
lock(m_mutex
);
1185 return (cec_client_version
)m_configuration
.clientVersion
;
1188 bool CCECClient::SetDeviceTypes(const cec_device_type_list
&deviceTypes
)
1190 bool bNeedReinit(false);
1193 CLockObject
lock(m_mutex
);
1194 bNeedReinit
= m_processor
&& m_processor
->CECInitialised() &&
1195 (m_configuration
.deviceTypes
!= deviceTypes
);
1196 m_configuration
.deviceTypes
= deviceTypes
;
1199 // persist the new configuration
1200 PersistConfiguration(m_configuration
);
1203 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "%s - using primary device type '%s'", __FUNCTION__
, ToString(deviceTypes
[0]));
1208 cec_device_type_list
CCECClient::GetDeviceTypes(void)
1210 cec_device_type_list retVal
;
1211 CLockObject
lock(m_mutex
);
1212 retVal
= m_configuration
.deviceTypes
;
1216 bool CCECClient::SetDevicePhysicalAddress(const uint16_t iPhysicalAddress
)
1218 if (!CLibCEC::IsValidPhysicalAddress(iPhysicalAddress
))
1220 LIB_CEC
->AddLog(CEC_LOG_DEBUG
, "%s - not setting invalid physical address %04x", __FUNCTION__
, iPhysicalAddress
);
1224 // reconfigure all devices
1225 cec_logical_address
reactivateSource(CECDEVICE_UNKNOWN
);
1226 CECDEVICEVEC devices
;
1227 m_processor
->GetDevices()->GetByLogicalAddresses(devices
, m_configuration
.logicalAddresses
);
1228 for (CECDEVICEVEC::iterator it
= devices
.begin(); it
!= devices
.end(); it
++)
1230 // if this device was the active source, reactivate it afterwards
1231 if ((*it
)->IsActiveSource())
1232 reactivateSource
= (*it
)->GetLogicalAddress();
1234 // mark the device as inactive source
1235 if (IsInitialised())
1236 (*it
)->MarkAsInactiveSource();
1238 // set the new physical address
1239 (*it
)->SetPhysicalAddress(iPhysicalAddress
);
1242 if (IsInitialised())
1243 (*it
)->TransmitPhysicalAddress(false);
1246 // reactivate the previous active source
1247 if (reactivateSource
!= CECDEVICE_UNKNOWN
&&
1248 m_processor
->CECInitialised() &&
1251 CCECBusDevice
*device
= m_processor
->GetDevice(reactivateSource
);
1253 device
->ActivateSource();
1256 // persist the new configuration
1257 PersistConfiguration(m_configuration
);
1262 bool CCECClient::SwitchMonitoring(bool bEnable
)
1264 LIB_CEC
->AddLog(CEC_LOG_NOTICE
, "== %s monitoring mode ==", bEnable
? "enabling" : "disabling");
1268 m_processor
->SwitchMonitoring(bEnable
);
1269 m_configuration
.bMonitorOnly
= bEnable
;
1270 return bEnable
? true: m_processor
->RegisterClient(this);
1276 bool CCECClient::PollDevice(const cec_logical_address iAddress
)
1278 // try to find the primary device
1279 CCECBusDevice
*primary
= GetPrimaryDevice();
1280 // poll the destination, with the primary as source
1282 return primary
->TransmitPoll(iAddress
, false);
1284 return m_processor
? m_processor
->PollDevice(iAddress
) : false;
1287 cec_logical_addresses
CCECClient::GetActiveDevices(void)
1289 CECDEVICEVEC activeDevices
;
1291 m_processor
->GetDevices()->GetActive(activeDevices
);
1292 return CCECDeviceMap::ToLogicalAddresses(activeDevices
);
1295 bool CCECClient::IsActiveDevice(const cec_logical_address iAddress
)
1297 cec_logical_addresses activeDevices
= GetActiveDevices();
1298 return activeDevices
.IsSet(iAddress
);
1301 bool CCECClient::IsActiveDeviceType(const cec_device_type type
)
1303 CECDEVICEVEC activeDevices
;
1305 m_processor
->GetDevices()->GetActive(activeDevices
);
1306 CCECDeviceMap::FilterType(type
, activeDevices
);
1307 return !activeDevices
.empty();
1310 cec_logical_address
CCECClient::GetActiveSource(void)
1312 return m_processor
? m_processor
->GetActiveSource() : CECDEVICE_UNKNOWN
;
1315 bool CCECClient::IsActiveSource(const cec_logical_address iAddress
)
1317 return m_processor
? m_processor
->IsActiveSource(iAddress
) : false;
1320 bool CCECClient::SetStreamPath(const cec_logical_address iAddress
)
1322 uint16_t iPhysicalAddress
= GetDevicePhysicalAddress(iAddress
);
1323 if (iPhysicalAddress
!= CEC_INVALID_PHYSICAL_ADDRESS
)
1324 return SetStreamPath(iPhysicalAddress
);
1328 bool CCECClient::SetStreamPath(const uint16_t iPhysicalAddress
)
1330 bool bReturn(false);
1332 CCECBusDevice
*device
= GetDeviceByType(CEC_DEVICE_TYPE_TV
);
1335 device
->SetStreamPath(iPhysicalAddress
);
1336 bReturn
= device
->GetHandler()->TransmitSetStreamPath(iPhysicalAddress
, false);
1337 device
->MarkHandlerReady();
1341 LIB_CEC
->AddLog(CEC_LOG_ERROR
, "only the TV is allowed to send CEC_OPCODE_SET_STREAM_PATH");
1347 cec_logical_addresses
CCECClient::GetLogicalAddresses(void)
1349 cec_logical_addresses addresses
;
1350 CLockObject
lock(m_mutex
);
1351 addresses
= m_configuration
.logicalAddresses
;
1355 bool CCECClient::CanPersistConfiguration(void)
1357 return m_processor
? m_processor
->CanPersistConfiguration() : false;
1360 bool CCECClient::PersistConfiguration(const libcec_configuration
&configuration
)
1362 return m_processor
&& IsRegistered() ?
1363 m_processor
->PersistConfiguration(configuration
) :
1367 void CCECClient::RescanActiveDevices(void)
1370 m_processor
->RescanActiveDevices();
1373 bool CCECClient::IsLibCECActiveSource(void)
1375 bool bReturn(false);
1378 cec_logical_address activeSource
= m_processor
->GetActiveSource();
1379 CCECBusDevice
*device
= m_processor
->GetDevice(activeSource
);
1381 bReturn
= device
->IsHandledByLibCEC();
1386 void CCECClient::SourceActivated(const cec_logical_address logicalAddress
)
1388 LIB_CEC
->AddLog(CEC_LOG_NOTICE
, ">> source activated: %s (%x)", ToString(logicalAddress
), logicalAddress
);
1389 CallbackSourceActivated(true, logicalAddress
);
1392 void CCECClient::SourceDeactivated(const cec_logical_address logicalAddress
)
1394 LIB_CEC
->AddLog(CEC_LOG_NOTICE
, ">> source deactivated: %s (%x)", ToString(logicalAddress
), logicalAddress
);
1395 CallbackSourceActivated(false, logicalAddress
);
1398 void CCECClient::CallbackAddCommand(const cec_command
&command
)
1401 CLockObject
lock(m_cbMutex
);
1402 if (m_configuration
.callbacks
&& m_configuration
.callbacks
->CBCecCommand
)
1404 m_configuration
.callbacks
->CBCecCommand(m_configuration
.callbackParam
, command
);
1408 m_commandBuffer
.Push(command
);
1411 void CCECClient::CallbackAddKey(const cec_keypress
&key
)
1414 CLockObject
lock(m_cbMutex
);
1415 if (m_configuration
.callbacks
&& m_configuration
.callbacks
->CBCecKeyPress
)
1417 m_configuration
.callbacks
->CBCecKeyPress(m_configuration
.callbackParam
, key
);
1421 m_keyBuffer
.Push(key
);
1424 void CCECClient::CallbackAddLog(const cec_log_message
&message
)
1427 CLockObject
lock(m_cbMutex
);
1428 if (m_configuration
.callbacks
&& m_configuration
.callbacks
->CBCecLogMessage
)
1430 m_configuration
.callbacks
->CBCecLogMessage(m_configuration
.callbackParam
, message
);
1434 m_logBuffer
.Push(message
);
1437 void CCECClient::CallbackConfigurationChanged(const libcec_configuration
&config
)
1439 CLockObject
lock(m_cbMutex
);
1440 if (m_configuration
.callbacks
&&
1441 m_configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_5_0
&&
1442 m_configuration
.callbacks
->CBCecConfigurationChanged
&&
1443 m_processor
->CECInitialised())
1444 m_configuration
.callbacks
->CBCecConfigurationChanged(m_configuration
.callbackParam
, config
);
1447 void CCECClient::CallbackSourceActivated(bool bActivated
, const cec_logical_address logicalAddress
)
1449 CLockObject
lock(m_cbMutex
);
1450 if (m_configuration
.callbacks
&&
1451 m_configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_7_1
&&
1452 m_configuration
.callbacks
->CBCecSourceActivated
)
1453 m_configuration
.callbacks
->CBCecSourceActivated(m_configuration
.callbackParam
, logicalAddress
, bActivated
? 1 : 0);
1456 void CCECClient::CallbackAlert(const libcec_alert type
, const libcec_parameter
¶m
)
1458 CLockObject
lock(m_cbMutex
);
1459 if (m_configuration
.callbacks
&&
1460 m_configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_6_0
&&
1461 m_configuration
.callbacks
->CBCecAlert
)
1462 m_configuration
.callbacks
->CBCecAlert(m_configuration
.callbackParam
, type
, param
);
1465 int CCECClient::CallbackMenuStateChanged(const cec_menu_state newState
)
1467 CLockObject
lock(m_cbMutex
);
1468 if (m_configuration
.callbacks
&&
1469 m_configuration
.clientVersion
>= CEC_CLIENT_VERSION_1_6_2
&&
1470 m_configuration
.callbacks
->CBCecMenuStateChanged
)
1471 return m_configuration
.callbacks
->CBCecMenuStateChanged(m_configuration
.callbackParam
, newState
);