1280de6e2f43eb4db87376e7529000b0c9a42bcd
[deb_libcec.git] / src / lib / devices / CECDeviceMap.cpp
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 "env.h"
34 #include "CECDeviceMap.h"
35
36 #include "CECAudioSystem.h"
37 #include "CECPlaybackDevice.h"
38 #include "CECRecordingDevice.h"
39 #include "CECTuner.h"
40 #include "CECTV.h"
41 #include "lib/CECProcessor.h"
42 #include "lib/CECTypeUtils.h"
43
44 using namespace std;
45 using namespace CEC;
46
47 CCECDeviceMap::CCECDeviceMap(CCECProcessor *processor) :
48 m_processor(processor),
49 m_iActiveSource(CEC_INVALID_PHYSICAL_ADDRESS)
50 {
51 for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_BROADCAST; iPtr++)
52 {
53 switch(iPtr)
54 {
55 case CECDEVICE_AUDIOSYSTEM:
56 m_busDevices.insert(make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECAudioSystem(processor, (cec_logical_address) iPtr)));
57 break;
58 case CECDEVICE_PLAYBACKDEVICE1:
59 case CECDEVICE_PLAYBACKDEVICE2:
60 case CECDEVICE_PLAYBACKDEVICE3:
61 m_busDevices.insert(make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECPlaybackDevice(processor, (cec_logical_address) iPtr)));
62 break;
63 case CECDEVICE_RECORDINGDEVICE1:
64 case CECDEVICE_RECORDINGDEVICE2:
65 case CECDEVICE_RECORDINGDEVICE3:
66 m_busDevices.insert(make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECRecordingDevice(processor, (cec_logical_address) iPtr)));
67 break;
68 case CECDEVICE_TUNER1:
69 case CECDEVICE_TUNER2:
70 case CECDEVICE_TUNER3:
71 case CECDEVICE_TUNER4:
72 m_busDevices.insert(make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECTuner(processor, (cec_logical_address) iPtr)));
73 break;
74 case CECDEVICE_TV:
75 m_busDevices.insert(make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECTV(processor, (cec_logical_address) iPtr)));
76 break;
77 default:
78 m_busDevices.insert(make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECBusDevice(processor, (cec_logical_address) iPtr)));
79 break;
80 }
81 }
82 }
83 CCECDeviceMap::~CCECDeviceMap(void)
84 {
85 Clear();
86 }
87
88 CECDEVICEMAP::iterator CCECDeviceMap::Begin(void)
89 {
90 return m_busDevices.begin();
91 }
92
93 CECDEVICEMAP::iterator CCECDeviceMap::End(void)
94 {
95 return m_busDevices.end();
96 }
97
98 void CCECDeviceMap::ResetDeviceStatus(void)
99 {
100 for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
101 it->second->ResetDeviceStatus();
102 }
103
104 CCECBusDevice *CCECDeviceMap::operator[] (cec_logical_address iAddress) const
105 {
106 return At(iAddress);
107 }
108
109 CCECBusDevice *CCECDeviceMap::operator[] (uint8_t iAddress) const
110 {
111 return At(iAddress);
112 }
113
114 CCECBusDevice *CCECDeviceMap::At(cec_logical_address iAddress) const
115 {
116 return At((uint8_t) iAddress);
117 }
118
119 CCECBusDevice *CCECDeviceMap::At(uint8_t iAddress) const
120 {
121 CECDEVICEMAP::const_iterator it = m_busDevices.find((cec_logical_address)iAddress);
122 if (it != m_busDevices.end())
123 return it->second;
124 return NULL;
125 }
126
127 void CCECDeviceMap::Clear(void)
128 {
129 for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
130 delete it->second;
131 m_busDevices.clear();
132 }
133
134 CCECBusDevice *CCECDeviceMap::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress, bool bSuppressUpdate /* = true */)
135 {
136 CCECBusDevice *device(NULL);
137
138 // check each device until we found a match
139 for (CECDEVICEMAP::iterator it = m_busDevices.begin(); !device && it != m_busDevices.end(); it++)
140 {
141 if (it->second->GetPhysicalAddress(m_processor->GetLogicalAddress(), bSuppressUpdate) == iPhysicalAddress)
142 device = it->second;
143 }
144
145 return device;
146 }
147
148 void CCECDeviceMap::Get(CECDEVICEVEC &devices) const
149 {
150 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
151 devices.push_back(it->second);
152 }
153
154 void CCECDeviceMap::GetByLogicalAddresses(CECDEVICEVEC &devices, const cec_logical_addresses &addresses)
155 {
156 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
157 {
158 if (addresses.IsSet(it->first))
159 devices.push_back(it->second);
160 }
161 }
162
163 void CCECDeviceMap::GetByType(const cec_device_type type, CECDEVICEVEC &devices) const
164 {
165 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
166 if (it->second->GetType() == type)
167 devices.push_back(it->second);
168 }
169
170 void CCECDeviceMap::GetLibCECControlled(CECDEVICEVEC &devices) const
171 {
172 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
173 if (it->second->IsHandledByLibCEC())
174 devices.push_back(it->second);
175 }
176
177 void CCECDeviceMap::GetActive(CECDEVICEVEC &devices) const
178 {
179 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
180 {
181 cec_bus_device_status status = it->second->GetStatus();
182 if (status == CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC ||
183 status == CEC_DEVICE_STATUS_PRESENT)
184 devices.push_back(it->second);
185 }
186 }
187
188 void CCECDeviceMap::GetPowerOffDevices(const libcec_configuration &configuration, CECDEVICEVEC &devices) const
189 {
190 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
191 {
192 if (configuration.powerOffDevices[(uint8_t)it->first])
193 devices.push_back(it->second);
194 }
195 }
196
197 void CCECDeviceMap::GetWakeDevices(const libcec_configuration &configuration, CECDEVICEVEC &devices) const
198 {
199 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
200 {
201 if (configuration.wakeDevices[(uint8_t)it->first])
202 devices.push_back(it->second);
203 }
204 }
205
206 CCECBusDevice *CCECDeviceMap::GetActiveSource(void) const
207 {
208 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
209 {
210 if (m_iActiveSource != CEC_INVALID_PHYSICAL_ADDRESS && !it->second->IsActiveSource() &&
211 m_iActiveSource == it->second->GetCurrentPhysicalAddress())
212 it->second->MarkAsActiveSource();
213 if (it->second->IsActiveSource())
214 return it->second;
215 }
216 return NULL;
217 }
218
219 void CCECDeviceMap::FilterLibCECControlled(CECDEVICEVEC &devices)
220 {
221 CECDEVICEVEC newDevices;
222 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
223 {
224 if ((*it)->IsHandledByLibCEC())
225 newDevices.push_back(*it);
226 }
227 devices = newDevices;
228 }
229
230 void CCECDeviceMap::FilterActive(CECDEVICEVEC &devices)
231 {
232 CECDEVICEVEC newDevices;
233 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
234 {
235 cec_bus_device_status status = (*it)->GetCurrentStatus();
236 if (status == CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC ||
237 status == CEC_DEVICE_STATUS_PRESENT)
238 newDevices.push_back(*it);
239 }
240 devices = newDevices;
241 }
242
243 void CCECDeviceMap::FilterTypes(const cec_device_type_list &types, CECDEVICEVEC &devices)
244 {
245 cec_device_type_list t(types);//silly, but needed to retain abi
246 CECDEVICEVEC newDevices;
247 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
248 {
249 if (t.IsSet((*it)->GetType()))
250 newDevices.push_back(*it);
251 }
252 devices = newDevices;
253 }
254
255 void CCECDeviceMap::FilterType(const cec_device_type type, CECDEVICEVEC &devices)
256 {
257 CECDEVICEVEC newDevices;
258 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
259 {
260 if ((*it)->GetType() == type)
261 newDevices.push_back(*it);
262 }
263 devices = newDevices;
264 }
265
266 cec_logical_addresses CCECDeviceMap::ToLogicalAddresses(const CECDEVICEVEC &devices)
267 {
268 cec_logical_addresses addresses;
269 addresses.Clear();
270 for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
271 addresses.Set((*it)->GetLogicalAddress());
272 return addresses;
273 }
274
275 void CCECDeviceMap::GetChildrenOf(CECDEVICEVEC& devices, CCECBusDevice* device) const
276 {
277 devices.clear();
278 if (!device)
279 return;
280
281 uint16_t iPA = device->GetCurrentPhysicalAddress();
282
283 for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
284 {
285 uint16_t iCurrentPA = it->second->GetCurrentPhysicalAddress();
286 if (CCECTypeUtils::PhysicalAddressIsIncluded(iPA, iCurrentPA))
287 devices.push_back(it->second);
288 }
289 }
290
291 void CCECDeviceMap::SetActiveSource(uint16_t iPhysicalAddress)
292 {
293 m_iActiveSource = iPhysicalAddress;
294 }
295
296 uint16_t CCECDeviceMap::GetActiveSourceAddress(void) const
297 {
298 return m_iActiveSource;
299 }
300
301 void CCECDeviceMap::SignalAll(cec_opcode opcode)
302 {
303 for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
304 it->second->SignalOpcode(opcode);
305 }