1 /*
2 * This file is part of the libCEC(R) library.
3 *
4 * libCEC(R) is Copyright (C) 2011-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 *
24 *
25 * Alternatively, you can license this library under a commercial license,
26 * please contact Pulse-Eight Licensing for more information.
27 *
28 * For more information contact:
29 * Pulse-Eight Licensing <license@pulse-eight.com>
30 * http://www.pulse-eight.com/
31 * http://www.pulse-eight.net/
32 */
33
34 #include "env.h"
35 #include "CECDeviceMap.h"
36
37 #include "CECAudioSystem.h"
38 #include "CECPlaybackDevice.h"
39 #include "CECRecordingDevice.h"
40 #include "CECTuner.h"
41 #include "CECTV.h"
42 #include "CECProcessor.h"
43 #include "CECTypeUtils.h"
44
45 using namespace CEC;
46
CCECDeviceMap(CCECProcessor * processor)47 CCECDeviceMap::CCECDeviceMap(CCECProcessor *processor) :
48 m_processor(processor)
49 {
50 for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_BROADCAST; iPtr++)
51 {
52 switch(iPtr)
53 {
54 case CECDEVICE_AUDIOSYSTEM:
55 m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECAudioSystem(processor, (cec_logical_address) iPtr)));
56 break;
57 case CECDEVICE_PLAYBACKDEVICE1:
58 case CECDEVICE_PLAYBACKDEVICE2:
59 case CECDEVICE_PLAYBACKDEVICE3:
60 m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECPlaybackDevice(processor, (cec_logical_address) iPtr)));
61 break;
62 case CECDEVICE_RECORDINGDEVICE1:
63 case CECDEVICE_RECORDINGDEVICE2:
64 case CECDEVICE_RECORDINGDEVICE3:
65 m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECRecordingDevice(processor, (cec_logical_address) iPtr)));
66 break;
67 case CECDEVICE_TUNER1:
68 case CECDEVICE_TUNER2:
69 case CECDEVICE_TUNER3:
70 case CECDEVICE_TUNER4:
71 m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECTuner(processor, (cec_logical_address) iPtr)));
72 break;
73 case CECDEVICE_TV:
74 m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECTV(processor, (cec_logical_address) iPtr)));
75 break;
76 default:
77 m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECBusDevice(processor, (cec_logical_address) iPtr)));
78 break;
79 }
80 }
81 }
~CCECDeviceMap(void)82 CCECDeviceMap::~CCECDeviceMap(void)
83 {
84 Clear();
85 }
86
Begin(void)87 CECDEVICEMAP::iterator CCECDeviceMap::Begin(void)
88 {
89 return m_busDevices.begin();
90 }
91
End(void)92 CECDEVICEMAP::iterator CCECDeviceMap::End(void)
93 {
94 return m_busDevices.end();
95 }
96
ResetDeviceStatus(void)97 void CCECDeviceMap::ResetDeviceStatus(void)
98 {
99 for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
100 it->second->ResetDeviceStatus();
101 }
102
operator [](cec_logical_address iAddress) const103 CCECBusDevice *CCECDeviceMap::operator[] (cec_logical_address iAddress) const
104 {
105 return At(iAddress);
106 }
107
operator [](uint8_t iAddress) const108 CCECBusDevice *CCECDeviceMap::operator[] (uint8_t iAddress) const
109 {
110 return At(iAddress);
111 }
112
At(cec_logical_address iAddress) const113 CCECBusDevice *CCECDeviceMap::At(cec_logical_address iAddress) const
114 {
115 return At((uint8_t) iAddress);
116 }
117
At(uint8_t iAddress) const118 CCECBusDevice *CCECDeviceMap::At(uint8_t iAddress) const
119 {
120 CECDEVICEMAP::const_iterator it = m_busDevices.find((cec_logical_address)iAddress);
121 if (it != m_busDevices.end())
122 return it->second;
123 return NULL;
124 }
125
Clear(void)126 void CCECDeviceMap::Clear(void)
127 {
128 for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
129 delete it->second;
130 m_busDevices.clear();
131 }
132
GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress,bool bSuppressUpdate)133 CCECBusDevice *CCECDeviceMap::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress, bool bSuppressUpdate /* = true */)
134 {
135 CCECBusDevice *device(NULL);
136
137 // check each device until we found a match
138 for (CECDEVICEMAP::iterator it = m_busDevices.begin(); !device && it != m_busDevices.end(); it++)
139 {
140 if (it->second->GetPhysicalAddress(m_processor->GetLogicalAddress(), bSuppressUpdate) == iPhysicalAddress)
141 device = it->second;
142 }
143
144 return device;
145 }
146
Get(CECDEVICEVEC & devices) const147 void CCECDeviceMap::Get(CECDEVICEVEC &devices) const
148 {
149 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
150 devices.push_back(it->second);
151 }
152
GetByLogicalAddresses(CECDEVICEVEC & devices,const cec_logical_addresses & addresses)153 void CCECDeviceMap::GetByLogicalAddresses(CECDEVICEVEC &devices, const cec_logical_addresses &addresses)
154 {
155 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
156 {
157 if (addresses.IsSet(it->first))
158 devices.push_back(it->second);
159 }
160 }
161
GetByType(const cec_device_type type,CECDEVICEVEC & devices) const162 void CCECDeviceMap::GetByType(const cec_device_type type, CECDEVICEVEC &devices) const
163 {
164 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
165 if (it->second->GetType() == type)
166 devices.push_back(it->second);
167 }
168
GetLibCECControlled(CECDEVICEVEC & devices) const169 void CCECDeviceMap::GetLibCECControlled(CECDEVICEVEC &devices) const
170 {
171 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
172 if (it->second->IsHandledByLibCEC())
173 devices.push_back(it->second);
174 }
175
GetActive(CECDEVICEVEC & devices) const176 void CCECDeviceMap::GetActive(CECDEVICEVEC &devices) const
177 {
178 for (auto it = m_busDevices.begin(); it != m_busDevices.end(); ++it)
179 {
180 auto dev = it->second;
181 if (!!dev && dev->IsActive(false)) {
182 devices.push_back(it->second);
183 }
184 }
185 }
186
IsActiveType(const cec_device_type type,bool suppressPoll) const187 bool CCECDeviceMap::IsActiveType(const cec_device_type type, bool suppressPoll /* = true */) const
188 {
189 for (auto it = m_busDevices.begin(); it != m_busDevices.end(); ++it)
190 {
191 auto dev = it->second;
192 if (!!dev &&
193 (dev->GetType() == type) &&
194 (dev->IsActive(suppressPoll))) {
195 return true;
196 }
197 }
198 return false;
199 }
200
GetPowerOffDevices(const libcec_configuration & configuration,CECDEVICEVEC & devices) const201 void CCECDeviceMap::GetPowerOffDevices(const libcec_configuration &configuration, CECDEVICEVEC &devices) const
202 {
203 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
204 {
205 if (configuration.powerOffDevices[(uint8_t)it->first])
206 devices.push_back(it->second);
207 }
208 }
209
GetWakeDevices(const libcec_configuration & configuration,CECDEVICEVEC & devices) const210 void CCECDeviceMap::GetWakeDevices(const libcec_configuration &configuration, CECDEVICEVEC &devices) const
211 {
212 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
213 {
214 if (configuration.wakeDevices[(uint8_t)it->first])
215 devices.push_back(it->second);
216 }
217 }
218
GetActiveSource(void) const219 CCECBusDevice *CCECDeviceMap::GetActiveSource(void) const
220 {
221 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
222 {
223 if (it->second->IsActiveSource())
224 return it->second;
225 }
226 return NULL;
227 }
228
ResetActiveSourceSent(void)229 void CCECDeviceMap::ResetActiveSourceSent(void)
230 {
231 for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
232 it->second->SetActiveSourceSent(false);
233 }
234
FilterLibCECControlled(CECDEVICEVEC & devices)235 void CCECDeviceMap::FilterLibCECControlled(CECDEVICEVEC &devices)
236 {
237 CECDEVICEVEC newDevices;
238 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
239 {
240 if ((*it)->IsHandledByLibCEC())
241 newDevices.push_back(*it);
242 }
243 devices = newDevices;
244 }
245
FilterActive(CECDEVICEVEC & devices)246 void CCECDeviceMap::FilterActive(CECDEVICEVEC &devices)
247 {
248 CECDEVICEVEC newDevices;
249 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
250 {
251 cec_bus_device_status status = (*it)->GetCurrentStatus();
252 if (status == CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC ||
253 status == CEC_DEVICE_STATUS_PRESENT)
254 newDevices.push_back(*it);
255 }
256 devices = newDevices;
257 }
258
FilterTypes(const cec_device_type_list & types,CECDEVICEVEC & devices)259 void CCECDeviceMap::FilterTypes(const cec_device_type_list &types, CECDEVICEVEC &devices)
260 {
261 cec_device_type_list t(types);//silly, but needed to retain abi
262 CECDEVICEVEC newDevices;
263 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
264 {
265 if (t.IsSet((*it)->GetType()))
266 newDevices.push_back(*it);
267 }
268 devices = newDevices;
269 }
270
FilterType(const cec_device_type type,CECDEVICEVEC & devices)271 void CCECDeviceMap::FilterType(const cec_device_type type, CECDEVICEVEC &devices)
272 {
273 CECDEVICEVEC newDevices;
274 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
275 {
276 if ((*it)->GetType() == type)
277 newDevices.push_back(*it);
278 }
279 devices = newDevices;
280 }
281
ToLogicalAddresses(const CECDEVICEVEC & devices)282 cec_logical_addresses CCECDeviceMap::ToLogicalAddresses(const CECDEVICEVEC &devices)
283 {
284 cec_logical_addresses addresses;
285 addresses.Clear();
286 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
287 addresses.Set((*it)->GetLogicalAddress());
288 return addresses;
289 }
290
GetChildrenOf(CECDEVICEVEC & devices,CCECBusDevice * device) const291 void CCECDeviceMap::GetChildrenOf(CECDEVICEVEC& devices, CCECBusDevice* device) const
292 {
293 devices.clear();
294 if (!device)
295 return;
296
297 uint16_t iPA = device->GetCurrentPhysicalAddress();
298
299 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
300 {
301 uint16_t iCurrentPA = it->second->GetCurrentPhysicalAddress();
302 if (CCECTypeUtils::PhysicalAddressIsIncluded(iPA, iCurrentPA))
303 devices.push_back(it->second);
304 }
305 }
306
SignalAll(cec_opcode opcode)307 void CCECDeviceMap::SignalAll(cec_opcode opcode)
308 {
309 for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
310 it->second->SignalOpcode(opcode);
311 }
312