Commit | Line | Data |
---|---|---|
004b8382 LOK |
1 | /* |
2 | * This file is part of the libCEC(R) library. | |
3 | * | |
4 | * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. | |
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 "CECClient.h" | |
34 | #include "CECProcessor.h" | |
35 | #include "LibCEC.h" | |
36 | #include "devices/CECPlaybackDevice.h" | |
37 | #include "devices/CECAudioSystem.h" | |
38 | #include "devices/CECTV.h" | |
39 | ||
40 | using namespace CEC; | |
41 | using namespace PLATFORM; | |
42 | ||
43 | #define LIB_CEC m_processor->GetLib() | |
44 | #define ToString(x) LIB_CEC->ToString(x) | |
45 | ||
46 | CCECClient::CCECClient(CCECProcessor *processor, const libcec_configuration *configuration) : | |
47 | m_processor(processor), | |
48 | m_bInitialised(false), | |
49 | m_bRegistered(false), | |
50 | m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN), | |
51 | m_buttontime(0) | |
52 | { | |
53 | SetConfiguration(configuration); | |
54 | } | |
55 | ||
56 | CCECClient::~CCECClient(void) | |
57 | { | |
58 | if (m_processor) | |
59 | m_processor->UnregisterClient(this); | |
60 | } | |
61 | ||
62 | bool CCECClient::IsInitialised(void) | |
63 | { | |
64 | CLockObject lock(m_mutex); | |
65 | return m_bInitialised && m_processor; | |
66 | } | |
67 | ||
68 | void CCECClient::SetInitialised(bool bSetTo) | |
69 | { | |
70 | CLockObject lock(m_mutex); | |
71 | m_bInitialised = bSetTo; | |
72 | } | |
73 | ||
74 | bool CCECClient::IsRegistered(void) | |
75 | { | |
76 | CLockObject lock(m_mutex); | |
77 | return m_bRegistered && m_processor; | |
78 | } | |
79 | ||
80 | void CCECClient::SetRegistered(bool bSetTo) | |
81 | { | |
82 | CLockObject lock(m_mutex); | |
83 | m_bRegistered = bSetTo; | |
84 | } | |
85 | ||
86 | bool CCECClient::Initialise(void) | |
87 | { | |
88 | if (IsInitialised()) | |
89 | return true; | |
90 | ||
91 | //TODO do the same for the other devices | |
92 | CCECBusDevice *primary = m_processor->GetDevice(m_configuration.logicalAddresses.primary); | |
93 | if (!primary) | |
94 | { | |
95 | LIB_CEC->AddLog(CEC_LOG_WARNING, "cannot find the primary device (logical address %x)", m_configuration.logicalAddresses.primary); | |
96 | return false; | |
97 | } | |
98 | ||
99 | /* only set our OSD name for the primary device */ | |
100 | primary->SetOSDName(m_configuration.strDeviceName); | |
101 | ||
102 | /* set the default menu language for devices we control */ | |
103 | primary->SetMenuLanguage(m_configuration.strDeviceLanguage); | |
104 | ||
105 | if (CLibCEC::IsValidPhysicalAddress(m_configuration.iPhysicalAddress)) | |
106 | { | |
107 | primary->SetPhysicalAddress(m_configuration.iPhysicalAddress); | |
108 | primary->TransmitPhysicalAddress(); | |
109 | } | |
110 | else | |
111 | { | |
112 | SetHDMIPort(m_configuration.baseDevice, m_configuration.iHDMIPort, true); | |
113 | } | |
114 | ||
115 | /* make the primary device the active source if the option is set */ | |
116 | if (m_configuration.bActivateSource == 1) | |
117 | primary->ActivateSource(); | |
118 | ||
119 | SetInitialised(true); | |
120 | return true; | |
121 | } | |
122 | ||
123 | bool CCECClient::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, bool bForce /* = false */) | |
124 | { | |
125 | bool bReturn(false); | |
126 | ||
127 | // limit the HDMI port range to 1-15 | |
128 | if (iPort < CEC_MIN_HDMI_PORTNUMBER || | |
129 | iPort > CEC_MAX_HDMI_PORTNUMBER) | |
130 | return bReturn; | |
131 | ||
132 | { | |
133 | CLockObject lock(m_mutex); | |
134 | m_configuration.baseDevice = iBaseDevice; | |
135 | m_configuration.iHDMIPort = iPort; | |
136 | } | |
137 | ||
138 | if (!m_processor->IsRunning() && !bForce) | |
139 | return true; | |
140 | ||
141 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting HDMI port to %d on device %s (%d)", iPort, ToString(iBaseDevice), (int)iBaseDevice); | |
142 | ||
143 | uint16_t iPhysicalAddress(CEC_INVALID_PHYSICAL_ADDRESS); | |
144 | CCECBusDevice *baseDevice = m_processor->GetDevice(iBaseDevice); | |
145 | if (baseDevice) | |
146 | iPhysicalAddress = baseDevice->GetPhysicalAddress(m_configuration.logicalAddresses.primary); | |
147 | ||
148 | if (iPhysicalAddress <= CEC_MAX_PHYSICAL_ADDRESS) | |
149 | { | |
150 | if (iPhysicalAddress == 0) | |
151 | iPhysicalAddress += 0x1000 * iPort; | |
152 | else if (iPhysicalAddress % 0x1000 == 0) | |
153 | iPhysicalAddress += 0x100 * iPort; | |
154 | else if (iPhysicalAddress % 0x100 == 0) | |
155 | iPhysicalAddress += 0x10 * iPort; | |
156 | else if (iPhysicalAddress % 0x10 == 0) | |
157 | iPhysicalAddress += iPort; | |
158 | ||
159 | bReturn = true; | |
160 | } | |
161 | ||
162 | if (!bReturn) | |
163 | { | |
164 | 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); | |
165 | iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS; | |
166 | } | |
167 | ||
168 | SetPhysicalAddress(iPhysicalAddress); | |
169 | ||
170 | return bReturn; | |
171 | } | |
172 | ||
173 | bool CCECClient::SetPhysicalAddress(uint16_t iPhysicalAddress) | |
174 | { | |
175 | bool bSendActiveView(false); | |
176 | bool bReturn(false); | |
177 | bool bSendUpdate = m_processor->CECInitialised(); | |
178 | ||
179 | CECDEVICEVEC sendUpdatesTo; | |
180 | { | |
181 | CLockObject lock(m_mutex); | |
182 | m_configuration.iPhysicalAddress = iPhysicalAddress; | |
183 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "setting physical address to '%04X'", iPhysicalAddress); | |
184 | ||
185 | bool bWasActiveSource(false); | |
186 | CECDEVICEVEC devices; | |
187 | // TODO | |
188 | m_processor->GetDevices()->GetLibCECControlled(devices); | |
189 | ||
190 | for (CECDEVICEVEC::iterator it = devices.begin(); it != devices.end(); it++) | |
191 | { | |
192 | bWasActiveSource |= (*it)->IsActiveSource(); | |
193 | (*it)->MarkAsInactiveSource(); | |
194 | (*it)->SetPhysicalAddress(iPhysicalAddress); | |
195 | if (bSendUpdate) | |
196 | sendUpdatesTo.push_back(*it); | |
197 | } | |
198 | ||
199 | bSendActiveView = bWasActiveSource && bSendUpdate; | |
200 | bReturn = true; | |
201 | } | |
202 | ||
203 | for (CECDEVICEVEC::iterator it = sendUpdatesTo.begin(); it != sendUpdatesTo.end(); it++) | |
204 | { | |
205 | (*it)->TransmitPhysicalAddress(); | |
206 | if (bSendActiveView && m_configuration.logicalAddresses.primary == (*it)->GetLogicalAddress()) | |
207 | { | |
208 | (*it)->MarkAsActiveSource(); | |
209 | if ((*it)->HasValidPhysicalAddress()) | |
210 | (*it)->ActivateSource(); | |
211 | } | |
212 | } | |
213 | ||
214 | if (bReturn) | |
215 | { | |
216 | m_processor->PersistConfiguration(&m_configuration); | |
217 | ConfigurationChanged(m_configuration); | |
218 | } | |
219 | ||
220 | return bReturn; | |
221 | } | |
222 | ||
223 | bool CCECClient::FindLogicalAddresses(void) | |
224 | { | |
225 | m_configuration.logicalAddresses.Clear(); | |
226 | ||
227 | if (m_configuration.deviceTypes.IsEmpty()) | |
228 | { | |
229 | LIB_CEC->AddLog(CEC_LOG_ERROR, "no device types given"); | |
230 | return false; | |
231 | } | |
232 | ||
233 | for (uint8_t iPtr = 0; iPtr < 5; iPtr++) | |
234 | { | |
235 | if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RESERVED) | |
236 | continue; | |
237 | ||
238 | cec_logical_address address(CECDEVICE_UNKNOWN); | |
239 | if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RECORDING_DEVICE) | |
240 | address = FindLogicalAddressRecordingDevice(); | |
241 | if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_TUNER) | |
242 | address = FindLogicalAddressTuner(); | |
243 | if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_PLAYBACK_DEVICE) | |
244 | address = FindLogicalAddressPlaybackDevice(); | |
245 | if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_AUDIO_SYSTEM) | |
246 | address = FindLogicalAddressAudioSystem(); | |
247 | ||
248 | if (address == CECDEVICE_UNKNOWN) | |
249 | { | |
250 | LIB_CEC->AddLog(CEC_LOG_ERROR, "%s - failed to allocate device '%d', type '%s'", __FUNCTION__, iPtr, ToString(m_configuration.deviceTypes.types[iPtr])); | |
251 | return false; | |
252 | } | |
253 | ||
254 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - device '%d', type '%s', LA '%X'", __FUNCTION__, iPtr, ToString(m_configuration.deviceTypes.types[iPtr]), address); | |
255 | m_configuration.logicalAddresses.Set(address); | |
256 | } | |
257 | ||
258 | return true; | |
259 | } | |
260 | ||
261 | cec_logical_address CCECClient::FindLogicalAddressRecordingDevice(void) | |
262 | { | |
263 | cec_logical_address retVal(CECDEVICE_UNKNOWN); | |
264 | ||
265 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'recording device'"); | |
266 | if (m_processor->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE1)) | |
267 | retVal = CECDEVICE_RECORDINGDEVICE1; | |
268 | else if (m_processor->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE2)) | |
269 | retVal = CECDEVICE_RECORDINGDEVICE2; | |
270 | else if (m_processor->TryLogicalAddress(CECDEVICE_RECORDINGDEVICE3)) | |
271 | retVal = CECDEVICE_RECORDINGDEVICE3; | |
272 | ||
273 | return retVal; | |
274 | } | |
275 | ||
276 | cec_logical_address CCECClient::FindLogicalAddressTuner(void) | |
277 | { | |
278 | cec_logical_address retVal(CECDEVICE_UNKNOWN); | |
279 | ||
280 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'tuner'"); | |
281 | if (m_processor->TryLogicalAddress(CECDEVICE_TUNER1)) | |
282 | retVal = CECDEVICE_TUNER1; | |
283 | else if (m_processor->TryLogicalAddress(CECDEVICE_TUNER2)) | |
284 | retVal = CECDEVICE_TUNER2; | |
285 | else if (m_processor->TryLogicalAddress(CECDEVICE_TUNER3)) | |
286 | retVal = CECDEVICE_TUNER3; | |
287 | else if (m_processor->TryLogicalAddress(CECDEVICE_TUNER4)) | |
288 | retVal = CECDEVICE_TUNER4; | |
289 | ||
290 | return retVal; | |
291 | } | |
292 | ||
293 | cec_logical_address CCECClient::FindLogicalAddressPlaybackDevice(void) | |
294 | { | |
295 | cec_logical_address retVal(CECDEVICE_UNKNOWN); | |
296 | ||
297 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'playback device'"); | |
298 | if (m_processor->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE1)) | |
299 | retVal = CECDEVICE_PLAYBACKDEVICE1; | |
300 | else if (m_processor->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE2)) | |
301 | retVal = CECDEVICE_PLAYBACKDEVICE2; | |
302 | else if (m_processor->TryLogicalAddress(CECDEVICE_PLAYBACKDEVICE3)) | |
303 | retVal = CECDEVICE_PLAYBACKDEVICE3; | |
304 | ||
305 | return retVal; | |
306 | } | |
307 | ||
308 | cec_logical_address CCECClient::FindLogicalAddressAudioSystem(void) | |
309 | { | |
310 | cec_logical_address retVal(CECDEVICE_UNKNOWN); | |
311 | ||
312 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "detecting logical address for type 'audiosystem'"); | |
313 | if (m_processor->TryLogicalAddress(CECDEVICE_AUDIOSYSTEM)) | |
314 | retVal = CECDEVICE_AUDIOSYSTEM; | |
315 | ||
316 | return retVal; | |
317 | } | |
318 | ||
319 | CCECBusDevice *CCECClient::GetDeviceByType(const cec_device_type type) const | |
320 | { | |
321 | // get all devices that match our logical addresses | |
322 | CECDEVICEVEC devices; | |
323 | m_processor->GetDevices()->GetByLogicalAddresses(devices, m_configuration.logicalAddresses); | |
324 | ||
325 | // filter the type we need | |
326 | CCECDeviceMap::FilterType(type, devices); | |
327 | ||
328 | return devices.empty() ? | |
329 | NULL : | |
330 | *devices.begin(); | |
331 | } | |
332 | ||
333 | bool CCECClient::ChangeDeviceType(cec_device_type from, cec_device_type to) | |
334 | { | |
335 | bool bChanged(false); | |
336 | ||
337 | LIB_CEC->AddLog(CEC_LOG_NOTICE, "changing device type '%s' into '%s'", ToString(from), ToString(to)); | |
338 | ||
339 | CLockObject lock(m_mutex); | |
340 | ||
341 | CCECBusDevice *previousDevice = GetDeviceByType(from); | |
342 | if (!previousDevice) | |
343 | return false; | |
344 | ||
345 | m_processor->UnregisterClient(this); | |
346 | ||
347 | m_configuration.logicalAddresses.primary = CECDEVICE_UNREGISTERED; | |
348 | ||
349 | for (uint8_t iPtr = 0; iPtr < 5; iPtr++) | |
350 | { | |
351 | if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RESERVED) | |
352 | continue; | |
353 | ||
354 | if (m_configuration.deviceTypes.types[iPtr] == from) | |
355 | { | |
356 | bChanged = true; | |
357 | m_configuration.deviceTypes.types[iPtr] = to; | |
358 | } | |
359 | else if (m_configuration.deviceTypes.types[iPtr] == to && bChanged) | |
360 | { | |
361 | m_configuration.deviceTypes.types[iPtr] = CEC_DEVICE_TYPE_RESERVED; | |
362 | } | |
363 | } | |
364 | ||
365 | if (bChanged) | |
366 | { | |
367 | // re-register the client to set the new ackmask | |
368 | if (!m_processor->RegisterClient(this)) | |
369 | return false; | |
370 | ||
371 | // copy the data from the previous device | |
372 | CCECBusDevice *newDevice = GetDeviceByType(to); | |
373 | if (previousDevice && newDevice) | |
374 | { | |
375 | newDevice->SetDeviceStatus(CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC); | |
376 | newDevice->SetCecVersion(previousDevice->GetCecVersion(m_configuration.logicalAddresses.primary, false)); | |
377 | newDevice->SetMenuLanguage(previousDevice->GetMenuLanguage(m_configuration.logicalAddresses.primary, false)); | |
378 | newDevice->SetMenuState(previousDevice->GetMenuState(m_configuration.logicalAddresses.primary)); | |
379 | newDevice->SetOSDName(previousDevice->GetOSDName(m_configuration.logicalAddresses.primary, false)); | |
380 | newDevice->SetPhysicalAddress(previousDevice->GetCurrentPhysicalAddress()); | |
381 | newDevice->SetPowerStatus(previousDevice->GetPowerStatus(m_configuration.logicalAddresses.primary, false)); | |
382 | newDevice->SetVendorId(previousDevice->GetVendorId(m_configuration.logicalAddresses.primary, false)); | |
383 | ||
384 | if ((from == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || from == CEC_DEVICE_TYPE_RECORDING_DEVICE) && | |
385 | (to == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || to == CEC_DEVICE_TYPE_RECORDING_DEVICE)) | |
386 | { | |
387 | newDevice->AsPlaybackDevice()->SetDeckControlMode(previousDevice->AsPlaybackDevice()->GetDeckControlMode(m_configuration.logicalAddresses.primary)); | |
388 | newDevice->AsPlaybackDevice()->SetDeckStatus(previousDevice->AsPlaybackDevice()->GetDeckStatus(m_configuration.logicalAddresses.primary)); | |
389 | } | |
390 | } | |
391 | ||
392 | // and reset the previous device to the initial state | |
393 | if (previousDevice) | |
394 | previousDevice->ResetDeviceStatus(); | |
395 | } | |
396 | ||
397 | return true; | |
398 | } | |
399 | ||
400 | bool CCECClient::SetLogicalAddress(cec_logical_address iLogicalAddress) | |
401 | { | |
402 | CLockObject lock(m_mutex); | |
403 | if (m_configuration.logicalAddresses.primary != iLogicalAddress) | |
404 | { | |
405 | LIB_CEC->AddLog(CEC_LOG_NOTICE, "<< setting primary logical address to %1x", iLogicalAddress); | |
406 | m_configuration.logicalAddresses.primary = iLogicalAddress; | |
407 | m_configuration.logicalAddresses.Set(iLogicalAddress); | |
408 | return m_processor->RegisterClient(this); | |
409 | } | |
410 | ||
411 | return true; | |
412 | } | |
413 | ||
414 | bool CCECClient::Transmit(const cec_command &data) | |
415 | { | |
416 | return m_processor ? m_processor->Transmit(data) : false; | |
417 | } | |
418 | ||
419 | bool CCECClient::SendPowerOnDevices(cec_logical_address address /* = CECDEVICE_TV */) | |
420 | { | |
421 | if (address == CECDEVICE_BROADCAST && m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0) | |
422 | { | |
423 | CECDEVICEVEC devices; | |
424 | m_processor->GetDevices()->GetWakeDevices(m_configuration, devices); | |
425 | return m_processor->PowerOnDevices(m_configuration.logicalAddresses.primary, devices); | |
426 | } | |
427 | ||
428 | return m_processor->PowerOnDevice(m_configuration.logicalAddresses.primary, address); | |
429 | } | |
430 | ||
431 | bool CCECClient::SendStandbyDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */) | |
432 | { | |
433 | if (address == CECDEVICE_BROADCAST && m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0) | |
434 | { | |
435 | CECDEVICEVEC devices; | |
436 | m_processor->GetDevices()->GetPowerOffDevices(m_configuration, devices); | |
437 | return m_processor->StandbyDevices(m_configuration.logicalAddresses.primary, devices); | |
438 | } | |
439 | ||
440 | return m_processor->StandbyDevice(m_configuration.logicalAddresses.primary, address); | |
441 | } | |
442 | ||
443 | bool CCECClient::SendSetActiveSource(cec_device_type type /* = CEC_DEVICE_TYPE_RESERVED */) | |
444 | { | |
445 | bool bReturn(false); | |
446 | ||
447 | CCECBusDevice *device(NULL); | |
448 | CECDEVICEVEC devices; | |
449 | m_processor->GetDevices()->GetByLogicalAddresses(devices, m_configuration.logicalAddresses); | |
450 | ||
451 | if (type != CEC_DEVICE_TYPE_RESERVED) | |
452 | CCECDeviceMap::FilterType(type, devices); | |
453 | ||
454 | // no devices left | |
455 | if (devices.empty()) | |
456 | m_processor->GetDevices()->GetByLogicalAddresses(devices, m_configuration.logicalAddresses); | |
457 | ||
458 | if (!devices.empty()) | |
459 | device = *devices.begin(); | |
460 | ||
461 | if (device) | |
462 | { | |
463 | bReturn = true; | |
464 | if (m_processor->IsRunning() && device->HasValidPhysicalAddress()) | |
465 | bReturn = device->ActivateSource(); | |
466 | } | |
467 | ||
468 | return bReturn; | |
469 | } | |
470 | ||
471 | CCECPlaybackDevice *CCECClient::GetPlaybackDevice(void) | |
472 | { | |
473 | CCECPlaybackDevice *device(NULL); | |
474 | CECDEVICEVEC devices; | |
475 | m_processor->GetDevices()->GetByLogicalAddresses(devices, m_configuration.logicalAddresses); | |
476 | CCECDeviceMap::FilterType(CEC_DEVICE_TYPE_PLAYBACK_DEVICE, devices); | |
477 | ||
478 | // no devices left | |
479 | if (devices.empty()) | |
480 | { | |
481 | m_processor->GetDevices()->GetByLogicalAddresses(devices, m_configuration.logicalAddresses); | |
482 | CCECDeviceMap::FilterType(CEC_DEVICE_TYPE_RECORDING_DEVICE, devices); | |
483 | } | |
484 | ||
485 | if (!devices.empty()) | |
486 | device = (*devices.begin())->AsPlaybackDevice(); | |
487 | ||
488 | return device; | |
489 | } | |
490 | ||
491 | CCECBusDevice *CCECClient::GetPrimaryDevice(void) | |
492 | { | |
493 | return m_processor->GetDevice(m_configuration.logicalAddresses.primary); | |
494 | } | |
495 | ||
496 | bool CCECClient::SendSetDeckControlMode(cec_deck_control_mode mode, bool bSendUpdate /* = true */) | |
497 | { | |
498 | bool bReturn(false); | |
499 | ||
500 | CCECBusDevice *device = GetPlaybackDevice(); | |
501 | if (device) | |
502 | { | |
503 | device->AsPlaybackDevice()->SetDeckControlMode(mode); | |
504 | if (bSendUpdate) | |
505 | bReturn = device->AsPlaybackDevice()->TransmitDeckStatus(CECDEVICE_TV); | |
506 | else | |
507 | bReturn = true; | |
508 | } | |
509 | ||
510 | return false; | |
511 | } | |
512 | ||
513 | bool CCECClient::SendSetDeckInfo(cec_deck_info info, bool bSendUpdate /* = true */) | |
514 | { | |
515 | bool bReturn(false); | |
516 | ||
517 | CCECBusDevice *device = GetPlaybackDevice(); | |
518 | if (device) | |
519 | { | |
520 | device->AsPlaybackDevice()->SetDeckStatus(info); | |
521 | if (bSendUpdate) | |
522 | bReturn = device->AsPlaybackDevice()->TransmitDeckStatus(CECDEVICE_TV); | |
523 | else | |
524 | bReturn = true; | |
525 | } | |
526 | ||
527 | return false; | |
528 | } | |
529 | ||
530 | bool CCECClient::SendSetMenuState(cec_menu_state state, bool bSendUpdate /* = true */) | |
531 | { | |
532 | CECDEVICEVEC devices; | |
533 | m_processor->GetDevices()->GetByLogicalAddresses(devices, m_configuration.logicalAddresses); | |
534 | ||
535 | for (CECDEVICEVEC::iterator it = devices.begin(); it != devices.end(); it++) | |
536 | { | |
537 | (*it)->SetMenuState(state); | |
538 | if (bSendUpdate) | |
539 | (*it)->TransmitMenuState(CECDEVICE_TV); | |
540 | } | |
541 | ||
542 | return true; | |
543 | } | |
544 | ||
545 | bool CCECClient::SendSetInactiveView(void) | |
546 | { | |
547 | CCECBusDevice *primary = GetPrimaryDevice(); | |
548 | if (primary) | |
549 | { | |
550 | primary->MarkAsInactiveSource(); | |
551 | return primary->TransmitInactiveSource(); | |
552 | } | |
553 | return false; | |
554 | } | |
555 | ||
556 | bool CCECClient::SendSetOSDString(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage) | |
557 | { | |
558 | CCECBusDevice *primary = GetPrimaryDevice(); | |
559 | if (primary) | |
560 | return primary->TransmitOSDString(iLogicalAddress, duration, strMessage); | |
561 | ||
562 | return false; | |
563 | } | |
564 | ||
565 | cec_version CCECClient::GetDeviceCecVersion(cec_logical_address iAddress) | |
566 | { | |
567 | CCECBusDevice *device = m_processor->GetDevice(iAddress); | |
568 | if (device) | |
569 | return device->GetCecVersion(m_configuration.logicalAddresses.primary); | |
570 | return CEC_VERSION_UNKNOWN; | |
571 | } | |
572 | ||
573 | bool CCECClient::GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language) | |
574 | { | |
575 | CCECBusDevice *device = m_processor->GetDevice(iAddress); | |
576 | if (device) | |
577 | { | |
578 | *language = device->GetMenuLanguage(m_configuration.logicalAddresses.primary); | |
579 | return (strcmp(language->language, "???") != 0); | |
580 | } | |
581 | return false; | |
582 | } | |
583 | ||
584 | cec_osd_name CCECClient::GetDeviceOSDName(cec_logical_address iAddress) | |
585 | { | |
586 | cec_osd_name retVal; | |
587 | retVal.device = iAddress; | |
588 | retVal.name[0] = 0; | |
589 | ||
590 | CCECBusDevice *device = m_processor->GetDevice(iAddress); | |
591 | if (device) | |
592 | { | |
593 | CStdString strOSDName = device->GetOSDName(m_configuration.logicalAddresses.primary); | |
594 | snprintf(retVal.name, sizeof(retVal.name), "%s", strOSDName.c_str()); | |
595 | retVal.device = iAddress; | |
596 | } | |
597 | ||
598 | return retVal; | |
599 | } | |
600 | ||
601 | uint16_t CCECClient::GetDevicePhysicalAddress(cec_logical_address iAddress) | |
602 | { | |
603 | CCECBusDevice *device = m_processor->GetDevice(iAddress); | |
604 | if (device) | |
605 | return device->GetPhysicalAddress(m_configuration.logicalAddresses.primary); | |
606 | return CEC_INVALID_PHYSICAL_ADDRESS; | |
607 | } | |
608 | ||
609 | cec_power_status CCECClient::GetDevicePowerStatus(cec_logical_address iAddress) | |
610 | { | |
611 | CCECBusDevice *device = m_processor->GetDevice(iAddress); | |
612 | if (device) | |
613 | return device->GetPowerStatus(m_configuration.logicalAddresses.primary); | |
614 | return CEC_POWER_STATUS_UNKNOWN; | |
615 | } | |
616 | ||
617 | uint64_t CCECClient::GetDeviceVendorId(cec_logical_address iAddress) | |
618 | { | |
619 | CCECBusDevice *device = m_processor->GetDevice(iAddress); | |
620 | if (device) | |
621 | return device->GetVendorId(m_configuration.logicalAddresses.primary); | |
622 | return CEC_VENDOR_UNKNOWN; | |
623 | } | |
624 | ||
625 | uint8_t CCECClient::SendVolumeUp(bool bSendRelease /* = true */) | |
626 | { | |
627 | CCECBusDevice *device = GetPrimaryDevice(); | |
628 | CCECAudioSystem *audio = m_processor->GetAudioSystem(); | |
629 | ||
630 | return device && audio && audio->IsPresent() ? | |
631 | audio->VolumeUp(device->GetLogicalAddress(), bSendRelease) : | |
632 | (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; | |
633 | } | |
634 | ||
635 | uint8_t CCECClient::SendVolumeDown(bool bSendRelease /* = true */) | |
636 | { | |
637 | CCECBusDevice *device = GetPrimaryDevice(); | |
638 | CCECAudioSystem *audio = m_processor->GetAudioSystem(); | |
639 | ||
640 | return device && audio && audio->IsPresent() ? | |
641 | audio->VolumeDown(device->GetLogicalAddress(), bSendRelease) : | |
642 | (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; | |
643 | } | |
644 | ||
645 | uint8_t CCECClient::SendMuteAudio(void) | |
646 | { | |
647 | CCECBusDevice *device = GetPrimaryDevice(); | |
648 | CCECAudioSystem *audio = m_processor->GetAudioSystem(); | |
649 | ||
650 | return device && audio && audio->IsPresent() ? | |
651 | audio->MuteAudio(device->GetLogicalAddress()) : | |
652 | (uint8_t)CEC_AUDIO_VOLUME_STATUS_UNKNOWN; | |
653 | } | |
654 | ||
655 | bool CCECClient::SendKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = true */) | |
656 | { | |
657 | CCECBusDevice *device = GetPrimaryDevice(); | |
658 | CCECBusDevice *dest = m_processor->GetDevice(iDestination); | |
659 | ||
660 | return device && dest ? | |
661 | device->TransmitKeypress(m_configuration.logicalAddresses.primary, key, bWait) : | |
662 | false; | |
663 | } | |
664 | ||
665 | bool CCECClient::SendKeyRelease(cec_logical_address iDestination, bool bWait /* = true */) | |
666 | { | |
667 | CCECBusDevice *device = GetPrimaryDevice(); | |
668 | CCECBusDevice *dest = m_processor->GetDevice(iDestination); | |
669 | ||
670 | return device && dest ? | |
671 | device->TransmitKeyRelease(m_configuration.logicalAddresses.primary, bWait) : | |
672 | false; | |
673 | } | |
674 | ||
675 | bool CCECClient::GetCurrentConfiguration(libcec_configuration *configuration) | |
676 | { | |
677 | // client version 1.5.0 | |
678 | snprintf(configuration->strDeviceName, 13, "%s", m_configuration.strDeviceName); | |
679 | configuration->deviceTypes = m_configuration.deviceTypes; | |
680 | configuration->bAutodetectAddress = m_configuration.bAutodetectAddress; | |
681 | configuration->iPhysicalAddress = m_configuration.iPhysicalAddress; | |
682 | configuration->baseDevice = m_configuration.baseDevice; | |
683 | configuration->iHDMIPort = m_configuration.iHDMIPort; | |
684 | configuration->clientVersion = m_configuration.clientVersion; | |
685 | configuration->serverVersion = m_configuration.serverVersion; | |
686 | configuration->tvVendor = m_configuration.tvVendor; | |
687 | ||
688 | configuration->bGetSettingsFromROM = m_configuration.bGetSettingsFromROM; | |
689 | configuration->bUseTVMenuLanguage = m_configuration.bUseTVMenuLanguage; | |
690 | configuration->bActivateSource = m_configuration.bActivateSource; | |
691 | configuration->wakeDevices = m_configuration.wakeDevices; | |
692 | configuration->powerOffDevices = m_configuration.powerOffDevices; | |
693 | configuration->bPowerOffScreensaver = m_configuration.bPowerOffScreensaver; | |
694 | configuration->bPowerOffOnStandby = m_configuration.bPowerOffOnStandby; | |
695 | ||
696 | // client version 1.5.1 | |
697 | if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_5_1) | |
698 | configuration->bSendInactiveSource = m_configuration.bSendInactiveSource; | |
699 | ||
700 | // client version 1.5.3 | |
701 | if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_5_3) | |
702 | configuration->logicalAddresses = m_configuration.logicalAddresses; | |
703 | ||
704 | // client version 1.6.0 | |
705 | if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_6_0) | |
706 | { | |
707 | configuration->iFirmwareVersion = m_configuration.iFirmwareVersion; | |
708 | configuration->bPowerOffDevicesOnStandby = m_configuration.bPowerOffDevicesOnStandby; | |
709 | configuration->bShutdownOnStandby = m_configuration.bShutdownOnStandby; | |
710 | } | |
711 | ||
712 | // client version 1.6.2 | |
713 | if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_6_2) | |
714 | { | |
715 | memcpy(configuration->strDeviceLanguage, m_configuration.strDeviceLanguage, 3); | |
716 | configuration->iFirmwareBuildDate = m_configuration.iFirmwareBuildDate; | |
717 | } | |
718 | return true; | |
719 | } | |
720 | ||
721 | bool CCECClient::SetConfiguration(const libcec_configuration *configuration) | |
722 | { | |
723 | bool bReinit(false); | |
724 | bool bIsRunning(m_processor && m_processor->IsRunning()); | |
725 | ||
726 | if (configuration->callbacks) | |
727 | { | |
728 | m_configuration.callbacks = configuration->callbacks; | |
729 | m_configuration.callbackParam = configuration->callbackParam; | |
730 | } | |
731 | ||
732 | //TODO | |
733 | CCECBusDevice *primary = bIsRunning ? GetPrimaryDevice() : NULL; | |
734 | cec_device_type oldPrimaryType = primary ? primary->GetType() : CEC_DEVICE_TYPE_RECORDING_DEVICE; | |
735 | ||
99aeafb9 | 736 | m_configuration.clientVersion = configuration->clientVersion; |
004b8382 LOK |
737 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - using client version '%s'", __FUNCTION__, ToString((cec_client_version)configuration->clientVersion)); |
738 | ||
739 | // client version 1.5.0 | |
740 | ||
741 | // device types | |
742 | bool bDeviceTypeChanged = bIsRunning && m_configuration.deviceTypes != configuration->deviceTypes; | |
743 | m_configuration.deviceTypes = configuration->deviceTypes; | |
744 | if (bDeviceTypeChanged) | |
745 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - using primary device type '%s'", __FUNCTION__, ToString(configuration->deviceTypes[0])); | |
746 | ||
747 | bool bPhysicalAddressChanged(false); | |
748 | ||
749 | // autodetect address | |
750 | bool bPhysicalAutodetected(false); | |
751 | if (bIsRunning && configuration->bAutodetectAddress == 1) | |
752 | { | |
753 | uint16_t iPhysicalAddress = m_processor->GetDetectedPhysicalAddress(); | |
754 | if (CLibCEC::IsValidPhysicalAddress(iPhysicalAddress)) | |
755 | { | |
756 | if (bIsRunning) | |
757 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - autodetected physical address '%04X'", __FUNCTION__, iPhysicalAddress); | |
758 | else | |
759 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - using physical address '%04X'", __FUNCTION__, iPhysicalAddress); | |
760 | bPhysicalAddressChanged = (m_configuration.iPhysicalAddress != iPhysicalAddress); | |
761 | m_configuration.iPhysicalAddress = iPhysicalAddress; | |
762 | m_configuration.iHDMIPort = CEC_HDMI_PORTNUMBER_NONE; | |
763 | m_configuration.baseDevice = CECDEVICE_UNKNOWN; | |
764 | bPhysicalAutodetected = true; | |
765 | } | |
766 | } | |
767 | ||
768 | // physical address | |
769 | if (!bPhysicalAutodetected) | |
770 | { | |
771 | uint16_t iPhysicalAddress(CLibCEC::IsValidPhysicalAddress(configuration->iPhysicalAddress) ? configuration->iPhysicalAddress : CEC_PHYSICAL_ADDRESS_TV); | |
772 | bPhysicalAddressChanged = bIsRunning && m_configuration.iPhysicalAddress != iPhysicalAddress; | |
773 | if (bPhysicalAddressChanged) | |
774 | { | |
775 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - physical address '%04X'", __FUNCTION__, iPhysicalAddress); | |
776 | m_configuration.iPhysicalAddress = iPhysicalAddress; | |
777 | } | |
778 | } | |
779 | ||
780 | bool bHdmiPortChanged(false); | |
781 | if (!bPhysicalAutodetected && !CLibCEC::IsValidPhysicalAddress(configuration->iPhysicalAddress)) | |
782 | { | |
783 | // base device | |
784 | bHdmiPortChanged = bIsRunning && m_configuration.baseDevice != configuration->baseDevice; | |
785 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - using base device '%x'", __FUNCTION__, (int)configuration->baseDevice); | |
786 | m_configuration.baseDevice = configuration->baseDevice; | |
787 | ||
788 | // hdmi port | |
789 | bHdmiPortChanged |= bIsRunning && m_configuration.iHDMIPort != configuration->iHDMIPort; | |
790 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - using HDMI port '%d'", __FUNCTION__, configuration->iHDMIPort); | |
791 | m_configuration.iHDMIPort = configuration->iHDMIPort; | |
792 | } | |
793 | else | |
794 | { | |
795 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - resetting HDMI port and base device to defaults", __FUNCTION__); | |
796 | m_configuration.baseDevice = CECDEVICE_UNKNOWN; | |
797 | m_configuration.iHDMIPort = CEC_HDMI_PORTNUMBER_NONE; | |
798 | } | |
799 | ||
800 | bReinit = bPhysicalAddressChanged || bHdmiPortChanged || bDeviceTypeChanged; | |
801 | ||
802 | // device name | |
803 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - using OSD name '%s'", __FUNCTION__, configuration->strDeviceName); | |
804 | snprintf(m_configuration.strDeviceName, 13, "%s", configuration->strDeviceName); | |
805 | if (primary && !primary->GetOSDName(m_configuration.logicalAddresses.primary, false).Equals(m_configuration.strDeviceName)) | |
806 | { | |
807 | primary->SetOSDName(m_configuration.strDeviceName); | |
808 | if (!bReinit && bIsRunning) | |
809 | primary->TransmitOSDName(CECDEVICE_TV); | |
810 | } | |
811 | ||
812 | // tv vendor id override | |
813 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - vendor id '%s'", __FUNCTION__, ToString((cec_vendor_id)configuration->tvVendor)); | |
814 | if (m_processor && m_configuration.tvVendor != configuration->tvVendor) | |
815 | { | |
816 | m_configuration.tvVendor= configuration->tvVendor; | |
817 | m_processor->GetTV()->SetVendorId((uint64_t)m_configuration.tvVendor); | |
818 | } | |
819 | ||
820 | // wake CEC devices | |
821 | if (m_configuration.wakeDevices != configuration->wakeDevices) | |
822 | { | |
823 | m_configuration.wakeDevices = configuration->wakeDevices; | |
824 | if (!bReinit && bIsRunning) | |
825 | SendPowerOnDevices(); | |
826 | } | |
827 | ||
828 | // just copy these | |
829 | m_configuration.bUseTVMenuLanguage = configuration->bUseTVMenuLanguage; | |
830 | m_configuration.bActivateSource = configuration->bActivateSource; | |
831 | m_configuration.bGetSettingsFromROM = configuration->bGetSettingsFromROM; | |
832 | m_configuration.powerOffDevices = configuration->powerOffDevices; | |
833 | m_configuration.bPowerOffScreensaver = configuration->bPowerOffScreensaver; | |
834 | m_configuration.bPowerOffOnStandby = configuration->bPowerOffOnStandby; | |
835 | ||
836 | // client version 1.5.1 | |
837 | if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_5_1) | |
838 | m_configuration.bSendInactiveSource = configuration->bSendInactiveSource; | |
839 | ||
840 | // client version 1.6.0 | |
841 | if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_6_0) | |
842 | { | |
843 | m_configuration.bPowerOffDevicesOnStandby = configuration->bPowerOffDevicesOnStandby; | |
844 | m_configuration.bShutdownOnStandby = configuration->bShutdownOnStandby; | |
845 | } | |
846 | ||
847 | // client version 1.6.2 | |
848 | if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_6_2) | |
849 | { | |
850 | memcpy(m_configuration.strDeviceLanguage, configuration->strDeviceLanguage, 3); | |
851 | } | |
852 | ||
853 | // ensure that there is at least 1 device type set | |
854 | if (m_configuration.deviceTypes.IsEmpty()) | |
855 | m_configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE); | |
856 | ||
857 | if (bIsRunning) | |
858 | m_processor->GetTV()->ReplaceHandler(false); | |
859 | ||
860 | bool bReturn(true); | |
861 | if (bReinit || m_configuration.logicalAddresses.IsEmpty()) | |
862 | { | |
863 | if (bDeviceTypeChanged) | |
864 | bReturn = ChangeDeviceType(oldPrimaryType, m_configuration.deviceTypes[0]); | |
865 | else if (CLibCEC::IsValidPhysicalAddress(m_configuration.iPhysicalAddress)) | |
866 | bReturn = SetPhysicalAddress(m_configuration.iPhysicalAddress); | |
867 | else if (m_configuration.baseDevice != CECDEVICE_UNKNOWN && m_configuration.iHDMIPort != CEC_HDMI_PORTNUMBER_NONE) | |
868 | bReturn = SetHDMIPort(m_configuration.baseDevice, m_configuration.iHDMIPort); | |
869 | } | |
870 | else if (m_configuration.bActivateSource == 1 && bIsRunning && !m_processor->IsActiveSource(m_configuration.logicalAddresses.primary)) | |
871 | { | |
872 | // activate the source if we're not already the active source | |
873 | m_processor->SetActiveSource(m_configuration.deviceTypes.types[0]); | |
874 | } | |
875 | ||
876 | // persist the configuration | |
877 | if (bIsRunning) | |
878 | m_processor->PersistConfiguration(&m_configuration); | |
879 | ||
880 | return bReturn; | |
881 | } | |
882 | ||
883 | void CCECClient::AddCommand(const cec_command &command) | |
884 | { | |
885 | CLockObject lock(m_mutex); | |
886 | ||
887 | 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); | |
888 | ||
889 | if (m_configuration.callbacks && m_configuration.callbacks->CBCecCommand) | |
890 | m_configuration.callbacks->CBCecCommand(m_configuration.callbackParam, command); | |
891 | else if (!m_commandBuffer.Push(command)) | |
892 | LIB_CEC->AddLog(CEC_LOG_WARNING, "command buffer is full"); | |
893 | } | |
894 | ||
895 | int CCECClient::MenuStateChanged(const cec_menu_state newState) | |
896 | { | |
897 | CLockObject lock(m_mutex); | |
898 | ||
899 | LIB_CEC->AddLog(CEC_LOG_NOTICE, ">> %s: %s", ToString(CEC_OPCODE_MENU_REQUEST), ToString(newState)); | |
900 | ||
901 | if (m_configuration.callbacks && | |
902 | m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_2 && | |
903 | m_configuration.callbacks->CBCecMenuStateChanged) | |
904 | return m_configuration.callbacks->CBCecMenuStateChanged(m_configuration.callbackParam, newState); | |
905 | ||
906 | return 0; | |
907 | } | |
908 | ||
909 | void CCECClient::Alert(const libcec_alert type, const libcec_parameter ¶m) | |
910 | { | |
911 | CLockObject lock(m_mutex); | |
912 | ||
913 | if (m_configuration.callbacks && | |
914 | m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_0 && | |
915 | m_configuration.callbacks->CBCecAlert) | |
916 | m_configuration.callbacks->CBCecAlert(m_configuration.callbackParam, type, param); | |
917 | } | |
918 | ||
919 | void CCECClient::AddLog(const cec_log_message &message) | |
920 | { | |
921 | CLockObject lock(m_logMutex); | |
922 | if (m_configuration.callbacks && m_configuration.callbacks->CBCecLogMessage) | |
923 | m_configuration.callbacks->CBCecLogMessage(m_configuration.callbackParam, message); | |
924 | else | |
925 | m_logBuffer.Push(message); | |
926 | } | |
927 | ||
928 | void CCECClient::AddKey(void) | |
929 | { | |
930 | CLockObject lock(m_mutex); | |
931 | ||
932 | if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN) | |
933 | { | |
934 | cec_keypress key; | |
935 | ||
936 | key.duration = (unsigned int) (GetTimeMs() - m_buttontime); | |
937 | key.keycode = m_iCurrentButton; | |
938 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "key released: %1x", key.keycode); | |
939 | ||
940 | if (m_configuration.callbacks && m_configuration.callbacks->CBCecKeyPress) | |
941 | m_configuration.callbacks->CBCecKeyPress(m_configuration.callbackParam, key); | |
942 | else | |
943 | m_keyBuffer.Push(key); | |
944 | m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN; | |
945 | } | |
946 | ||
947 | m_buttontime = 0; | |
948 | } | |
949 | ||
950 | void CCECClient::AddKey(const cec_keypress &key) | |
951 | { | |
952 | CLockObject lock(m_mutex); | |
953 | ||
954 | LIB_CEC->AddLog(CEC_LOG_DEBUG, "key pressed: %1x", key.keycode); | |
955 | ||
956 | if (m_configuration.callbacks && m_configuration.callbacks->CBCecKeyPress) | |
957 | m_configuration.callbacks->CBCecKeyPress(m_configuration.callbackParam, key); | |
958 | else | |
959 | m_keyBuffer.Push(key); | |
960 | ||
961 | m_iCurrentButton = key.duration > 0 ? CEC_USER_CONTROL_CODE_UNKNOWN : key.keycode; | |
962 | m_buttontime = key.duration > 0 ? 0 : GetTimeMs(); | |
963 | } | |
964 | ||
965 | void CCECClient::SetCurrentButton(cec_user_control_code iButtonCode) | |
966 | { | |
967 | /* push keypress to the keybuffer with 0 duration. | |
968 | push another press to the keybuffer with the duration set when the button is released */ | |
969 | cec_keypress key; | |
970 | key.duration = 0; | |
971 | key.keycode = iButtonCode; | |
972 | ||
973 | AddKey(key); | |
974 | } | |
975 | ||
976 | void CCECClient::CheckKeypressTimeout(void) | |
977 | { | |
978 | if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN && GetTimeMs() - m_buttontime > CEC_BUTTON_TIMEOUT) | |
979 | { | |
980 | AddKey(); | |
981 | m_iCurrentButton = CEC_USER_CONTROL_CODE_UNKNOWN; | |
982 | } | |
983 | } | |
984 | ||
985 | void CCECClient::ConfigurationChanged(const libcec_configuration &config) | |
986 | { | |
987 | CLockObject lock(m_mutex); | |
988 | ||
989 | if (m_configuration.callbacks && | |
990 | m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0 && | |
991 | m_configuration.callbacks->CBCecConfigurationChanged && | |
992 | m_processor->CECInitialised()) | |
993 | m_configuration.callbacks->CBCecConfigurationChanged(m_configuration.callbackParam, config); | |
994 | } | |
995 | ||
996 | bool CCECClient::EnableCallbacks(void *cbParam, ICECCallbacks *callbacks) | |
997 | { | |
998 | CLockObject lock(m_mutex); | |
999 | m_configuration.callbackParam = cbParam; | |
1000 | m_configuration.callbacks = callbacks; | |
1001 | return true; | |
1002 | } | |
1003 | ||
1004 | bool CCECClient::GetNextLogMessage(cec_log_message *message) | |
1005 | { | |
1006 | return (m_logBuffer.Pop(*message)); | |
1007 | } | |
1008 | ||
1009 | bool CCECClient::GetNextKeypress(cec_keypress *key) | |
1010 | { | |
1011 | return m_keyBuffer.Pop(*key); | |
1012 | } | |
1013 | ||
1014 | bool CCECClient::GetNextCommand(cec_command *command) | |
1015 | { | |
1016 | return m_commandBuffer.Pop(*command); | |
1017 | } |