[FCC] Fix to perform normal decoding for usb tuner on FCC mode.
[vuplus_dvbapp] / lib / dvb / fcc.cpp
1 #include <lib/dvb/fcc.h>
2 #include <lib/nav/core.h>
3 #include <lib/base/nconfig.h>
4 #include <lib/base/eerror.h>
5 #include <lib/python/python.h>
6
7 //#define FCC_DEBUG
8
9 void FCCServiceChannels::addFCCService(const eServiceReference &service)
10 {
11         eDVBChannelID fcc_chid;
12
13         ((const eServiceReferenceDVB&)service).getChannelID(fcc_chid);
14
15         if (m_fcc_chids.find(fcc_chid) != m_fcc_chids.end())
16                 m_fcc_chids[fcc_chid] += 1;
17         else
18                 m_fcc_chids[fcc_chid] = 1;
19 }
20
21 void FCCServiceChannels::removeFCCService(const eServiceReference &service)
22 {
23         eDVBChannelID fcc_chid;
24         ((const eServiceReferenceDVB&)service).getChannelID(fcc_chid);
25
26         if (m_fcc_chids.find(fcc_chid) != m_fcc_chids.end())
27         {
28                 m_fcc_chids[fcc_chid] -= 1;
29
30                 if (m_fcc_chids[fcc_chid] == 0)
31                         m_fcc_chids.erase(fcc_chid);
32         }
33 }
34
35 int FCCServiceChannels::getFCCChannelID(std::map<eDVBChannelID, int> &fcc_chids)
36 {
37         if (!m_fcc_chids.size()) return -1;
38
39         fcc_chids = m_fcc_chids;
40         return 0;
41 }
42
43 eFCCServiceManager *eFCCServiceManager::m_instance = (eFCCServiceManager*)0;
44
45 eFCCServiceManager* eFCCServiceManager::getInstance()
46 {
47         return m_instance;
48 }
49
50 eFCCServiceManager::eFCCServiceManager(eNavigation *navptr)
51         :m_core(navptr), m_fcc_enable(false)
52 {
53         if (!m_instance)
54         {
55                 m_instance = this;
56         }
57 }
58
59 eFCCServiceManager::~eFCCServiceManager()
60 {
61         if (m_instance == this)
62         {
63                 m_instance = 0;
64         }
65 }
66
67 RESULT eFCCServiceManager::playFCCService(const eServiceReference &ref, ePtr<iPlayableService> &service)
68 {
69         std::map< ePtr<iPlayableService>, FCCServiceElem >::iterator it = m_FCCServices.begin();
70         for (;it != m_FCCServices.end();++it)
71         {
72                 ASSERT (ref != it->second.m_service_reference);
73         }
74
75         ASSERT(m_core->m_servicehandler);
76         RESULT res = m_core->m_servicehandler->play(ref, service);
77         if (res)
78                 service = 0;
79         else
80         {
81                 ePtr<eConnection> conn;
82                 service->connectEvent(slot(*this, &eFCCServiceManager::FCCEvent), conn);
83
84                 FCCServiceElem elem = {ref, conn, fcc_state_preparing, false};
85                 m_FCCServices[service] = elem;
86
87                 res = service->start();
88         }
89
90         printFCCServices();
91
92         return res;
93 }
94
95 void eFCCServiceManager::FCCEvent(iPlayableService* service, int event)
96 {
97         std::map<ePtr<iPlayableService>, FCCServiceElem >::iterator it = m_FCCServices.find(service);
98         if (it == m_FCCServices.end())
99         {
100                 eDebug("[eFCCServiceManager] event for non registered FCC service");
101                 return;
102         }
103
104         switch (event)
105         {
106                 case iPlayableService::evStart:
107                 {
108                         m_fccServiceChannels.addFCCService(it->second.m_service_reference);
109                         break;
110                 }
111                 case iPlayableService::evStopped:
112                 {
113                         m_fccServiceChannels.removeFCCService(it->second.m_service_reference);
114                         break;
115                 }
116                 case iPlayableService::evTuneFailed:
117                 case iPlayableService::evFccFailed:
118                 {
119                         eDebug("[eFCCServiceManager::FCCEvent][%s] set service to state failed.", it->second.m_service_reference.toString().c_str());
120                         it->second.m_state = fcc_state_failed;
121                         break;
122                 }
123         }
124         m_fcc_event(event);
125 }
126
127 RESULT eFCCServiceManager::cleanupFCCService()
128 {
129         if (m_FCCServices.size())
130         {
131                 std::map<ePtr<iPlayableService>, FCCServiceElem >::iterator it = m_FCCServices.begin();
132                 for (;it != m_FCCServices.end();++it)
133                 {
134                         eDebug("[eFCCServiceManager] stop FCC service sref : %s", it->second.m_service_reference.toString().c_str());
135                         it->first->stop();
136                 }
137
138                 m_FCCServices.clear();
139         }
140         return 0;
141 }
142
143 RESULT eFCCServiceManager::stopFCCService(const eServiceReference &sref)
144 {
145         if (m_FCCServices.size())
146         {
147                 std::map<ePtr<iPlayableService>, FCCServiceElem >::iterator it = m_FCCServices.begin();
148                 for (; it != m_FCCServices.end();)
149                 {
150                         if (it->second.m_service_reference == sref)
151                         {
152                                 eDebug("[eFCCServiceManager] stop FCC service sref : %s", it->second.m_service_reference.toString().c_str());
153                                 it->first->stop();
154                                 m_FCCServices.erase(it++);
155                         }
156                         else
157                         {
158                                 ++it;
159                         }
160                 }
161                 printFCCServices();
162         }
163         return 0;
164 }
165
166 RESULT eFCCServiceManager::stopFCCService()
167 {
168         if (m_FCCServices.size())
169         {
170                 std::map<ePtr<iPlayableService>, FCCServiceElem >::iterator it = m_FCCServices.begin();
171                 for (; it != m_FCCServices.end();)
172                 {
173                         if (it->second.m_state == fcc_state_failed)
174                         {
175                                 eDebug("[eFCCServiceManager] stop FCC service sref : %s", it->second.m_service_reference.toString().c_str());
176                                 it->first->stop();
177                                 m_FCCServices.erase(it++);
178                         }
179                         else
180                         {
181                                 ++it;
182                         }
183                 }
184
185                 printFCCServices();
186         }
187         return 0;
188 }
189
190 RESULT eFCCServiceManager::tryFCCService(const eServiceReference &sref, ePtr<iPlayableService> &service)
191 {
192         if (!isEnable())
193                 return -1;
194
195         ePtr<iPlayableService> new_service = 0;
196
197         printFCCServices();
198
199         int get_fcc_decoding = 0;
200
201         /* stop previous decoding service */
202         std::map< ePtr<iPlayableService>, FCCServiceElem >::iterator it;
203         for (it = m_FCCServices.begin();it != m_FCCServices.end();++it)
204         {
205                 if (it->second.m_state == fcc_state_decoding)
206                 {
207                         ASSERT(get_fcc_decoding == 0);
208                         get_fcc_decoding = 1;
209
210                         /* send end event */
211                         m_core->m_event(iPlayableService::evEnd);
212
213                         /* kill service and event */
214                         m_core->m_service_event_conn = 0;
215                         m_core->m_runningService = 0;
216
217                         if (it->second.m_useNormalDecode)
218                         {
219                                 /* stop service */
220                                 it->first->stop();
221                                 m_FCCServices.erase(it++);
222                         }
223                         else
224                         {
225                                 /* connect to fcc event */
226                                 ePtr<eConnection> conn;
227                                 it->first->connectEvent(slot(*this, &eFCCServiceManager::FCCEvent), conn);
228                                 it->second.m_service_event_conn = conn;
229                                 it->second.m_state = fcc_state_preparing;
230
231                                 /* switch to FCC prepare state */
232                                 it->first->start();
233
234                                 /* update FCCServiceChannels */
235                                 m_fccServiceChannels.addFCCService(it->second.m_service_reference);
236                         }
237                         break;
238                 }
239         }
240
241         /* search new service */
242         for (it = m_FCCServices.begin();it != m_FCCServices.end();++it)
243         {
244                 if (it->second.m_service_reference == sref)
245                 {
246                         eDebug("[eFCCServiceManager] use FCC service sref : %s", it->second.m_service_reference.toString().c_str());
247                         it->second.m_service_event_conn = 0; /* disconnect FCC event */
248                         it->second.m_state = fcc_state_decoding;
249                         new_service = it->first;
250                         m_fccServiceChannels.removeFCCService(it->second.m_service_reference);
251                         break;
252                 }
253         }
254
255         if (new_service)
256         {
257                 service = new_service;
258         }
259
260         else /* If new service is not found in FCC service list, cleanup all FCC prepared services and get new FCC service. */
261         {
262                 cleanupFCCService();
263                 m_core->stopService();
264                 if (eFCCServiceManager::checkAvailable(sref))
265                 {
266                         ASSERT(m_core->m_servicehandler);
267                         m_core->m_servicehandler->play(sref, service);
268
269                         if (service)
270                         {
271                                 FCCServiceElem elem = {sref, 0, fcc_state_decoding, false};
272                                 m_FCCServices[service] = elem;
273                                 service->start(); // do FCC preparing
274                         }
275                 }
276                 else
277                 {
278                         return -1;
279                 }
280         }
281
282         printFCCServices();
283
284         return 0;
285 }
286
287 int eFCCServiceManager::isLocked(ePtr<iPlayableService> service)
288 {
289         ePtr<iFrontendInformation> ptr;
290         service->frontendInfo(ptr);
291         return ptr->getFrontendInfo(iDVBFrontend_ENUMS::locked);
292 }
293
294 PyObject *eFCCServiceManager::getFCCServiceList()
295 {
296         ePyObject dest = PyDict_New();
297         if (dest)
298         {
299                 std::map< ePtr<iPlayableService>, FCCServiceElem >::iterator it = m_FCCServices.begin();
300                 for (;it != m_FCCServices.end();++it)
301                 {
302                         ePyObject tplist = PyList_New(0);
303                         PyList_Append(tplist, PyInt_FromLong((long)it->second.m_state));
304                         PyList_Append(tplist, PyInt_FromLong((long)isLocked(it->first)));
305                         PyDict_SetItemString(dest, it->second.m_service_reference.toString().c_str(), tplist);
306                         Py_DECREF(tplist);
307                 }
308         }
309
310         else
311                 Py_RETURN_NONE;
312         return dest;
313 }
314
315 void eFCCServiceManager::printFCCServices()
316 {
317 #ifdef FCC_DEBUG
318         eDebug("                                                [eFCCServiceManager::printFCCServices][*] total size : %d", m_FCCServices.size());
319
320         std::map< ePtr<iPlayableService>, FCCServiceElem >::iterator it = m_FCCServices.begin();
321         for (;it != m_FCCServices.end();++it)
322         {
323                 eDebug("                                                [eFCCServiceManager::printFCCServices][*] sref : %s, state : %d, tune : %d, useNormalDecode : %d", it->second.m_service_reference.toString().c_str(), it->second.m_state, isLocked(it->first), it->second.m_useNormalDecode);
324         }
325 #else
326         ;
327 #endif
328 }
329
330 int eFCCServiceManager::getFCCChannelID(std::map<eDVBChannelID, int> &fcc_chids)
331 {
332         eFCCServiceManager *fcc_mng = eFCCServiceManager::getInstance();
333         if (!fcc_mng) return -1;
334         return fcc_mng->m_fccServiceChannels.getFCCChannelID(fcc_chids);
335 }
336
337 bool eFCCServiceManager::checkAvailable(const eServiceReference &ref)
338 {
339         int serviceType = ref.getData(0);
340         eFCCServiceManager *fcc_mng = eFCCServiceManager::getInstance();
341
342         if ((ref.type == 1) && ref.path.empty() && (serviceType != 2) && (serviceType != 10) && fcc_mng) // no PVR, streaming, radio channel..
343                 return fcc_mng->isEnable();
344         return false;
345 }
346
347 bool eFCCServiceManager::isStateDecoding(iPlayableService* service)
348 {
349         std::map<ePtr<iPlayableService>, FCCServiceElem >::iterator it = m_FCCServices.find(service);
350         if (it != m_FCCServices.end())
351         {
352                 return (it->second.m_state == fcc_state_decoding);
353         }
354         else
355         {
356                 eDebug("[eFCCServiceManager] non registered FCC service");
357         }
358
359         return false;
360 }
361
362 void eFCCServiceManager::setNormalDecoding(iPlayableService* service)
363 {
364         std::map<ePtr<iPlayableService>, FCCServiceElem >::iterator it = m_FCCServices.find(service);
365         if (it != m_FCCServices.end())
366         {
367                 eDebug("[eFCCServiceManager::setNormalDecoding][%s] set to use normal decoding.", it->second.m_service_reference.toString().c_str());
368                 it->second.m_useNormalDecode = true;
369         }
370         else
371         {
372                 eDebug("[eFCCServiceManager] non registered FCC service");
373         }
374 }
375
376 DEFINE_REF(eFCCServiceManager);
377