27679826aa40e24ae7db548926834b9f03dcd4cd
[vuplus_dvbapp] / lib / service / servicehdmi.cpp
1 #include <lib/base/ebase.h>
2 #include <lib/base/eerror.h>
3 #include <lib/base/init_num.h>
4 #include <lib/base/init.h>
5 #include <lib/base/nconfig.h>
6 #include <lib/base/object.h>
7 #include <lib/dvb/decoder.h>
8 #include <lib/service/servicehdmi.h>
9 #include <lib/service/service.h>
10
11 #include <string>
12
13 #define HDMI_IN_REC_ENCODER_INDEX 0
14 #define HDMI_IN_REC_DECODER_INDEX 2
15
16 eServiceFactoryHDMI::eServiceFactoryHDMI()
17 {
18         ePtr<eServiceCenter> sc;
19
20         eServiceCenter::getPrivInstance(sc);
21         if (sc)
22         {
23                 std::list<std::string> extensions;
24                 sc->addServiceFactory(eServiceFactoryHDMI::id, this, extensions);
25         }
26
27         m_service_info = new eStaticServiceHDMIInfo();
28 }
29
30 eServiceFactoryHDMI::~eServiceFactoryHDMI()
31 {
32         ePtr<eServiceCenter> sc;
33
34         eServiceCenter::getPrivInstance(sc);
35         if (sc)
36         {
37                 sc->removeServiceFactory(eServiceFactoryHDMI::id);
38         }
39 }
40
41 DEFINE_REF(eServiceFactoryHDMI)
42
43 RESULT eServiceFactoryHDMI::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
44 {
45         ptr = new eServiceHDMI(ref);
46         return 0;
47 }
48
49 RESULT eServiceFactoryHDMI::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
50 {
51         ePtr<eNavigation> nav_instance;
52         getNavInstance(nav_instance);
53         ptr = new eServiceHDMIRecord(ref, nav_instance);
54         return 0;
55 }
56
57 RESULT eServiceFactoryHDMI::list(const eServiceReference &, ePtr<iListableService> &ptr)
58 {
59         ptr = 0;
60         return -1;
61 }
62
63 RESULT eServiceFactoryHDMI::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
64 {
65         ptr = m_service_info;
66         return 0;
67 }
68
69 RESULT eServiceFactoryHDMI::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
70 {
71         ptr = 0;
72         return -1;
73 }
74
75 void eServiceFactoryHDMI::getNavInstance(ePtr<eNavigation> &nav_instance)
76 {
77         if (!m_nav_instance)
78         {
79                 ePtr<iServiceHandler> service_center;
80                 eServiceCenter::getInstance(service_center);
81                 m_nav_instance = new eNavigation(service_center, HDMI_IN_REC_DECODER_INDEX);
82         }
83         nav_instance = m_nav_instance;
84 }
85
86 DEFINE_REF(eStaticServiceHDMIInfo)
87
88 eStaticServiceHDMIInfo::eStaticServiceHDMIInfo()
89 {
90 }
91
92 RESULT eStaticServiceHDMIInfo::getName(const eServiceReference &ref, std::string &name)
93 {
94         if (ref.name.length())
95         {
96                 name = ref.name;
97         }
98         else
99         {
100                 name = "HDMI IN";
101         }
102         return 0;
103 }
104
105 int eStaticServiceHDMIInfo::getLength(const eServiceReference &ref)
106 {
107         return -1;
108 }
109
110 int eStaticServiceHDMIInfo::getInfo(const eServiceReference &ref, int w)
111 {
112         return iServiceInformation::resNA;
113 }
114
115 long long eStaticServiceHDMIInfo::getFileSize(const eServiceReference &ref)
116 {
117         return 0;
118 }
119
120 eServiceHDMI::eServiceHDMI(eServiceReference ref)
121  : m_ref(ref), m_decoder_index(0)
122 {
123
124 }
125
126 eServiceHDMI::~eServiceHDMI()
127 {
128 }
129
130 DEFINE_REF(eServiceHDMI);
131
132 RESULT eServiceHDMI::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
133 {
134         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
135         return 0;
136 }
137
138 RESULT eServiceHDMI::start()
139 {
140         m_decoder = new eTSMPEGDecoder(NULL, m_decoder_index);
141         m_decoder->setVideoPID(1, 0);
142         m_decoder->setAudioPID(1, 0);
143         m_decoder->play();
144         m_event(this, evStart);
145         return 0;
146 }
147
148 RESULT eServiceHDMI::stop()
149 {
150         m_decoder = NULL;
151         m_event(this, evStopped);
152         return 0;
153 }
154
155 RESULT eServiceHDMI::setTarget(int target)
156 {
157         m_decoder_index = target;
158         return 0;
159 }
160
161 RESULT eServiceHDMI::info(ePtr<iServiceInformation> &i)
162 {
163         i = this;
164         return 0;
165 }
166
167 RESULT eServiceHDMI::getName(std::string &name)
168 {
169         if (m_ref.name.length())
170         {
171                 name = m_ref.name;
172         }
173         else
174         {
175                 name = "HDMI IN";
176         }
177         return 0;
178 }
179
180 int eServiceHDMI::getInfo(int w)
181 {
182         return resNA;
183 }
184
185 std::string eServiceHDMI::getInfoString(int w)
186 {
187         return "";
188 }
189
190 PyObject* eServiceHDMI::getInfoObject(int w)
191 {
192         Py_RETURN_NONE;
193 }
194
195 DEFINE_REF(eServiceHDMIRecord);
196
197 eServiceHDMIRecord::eServiceHDMIRecord(const eServiceReference &ref, ePtr<eNavigation> &nav_instance)
198 {
199         m_ref = ref;
200         m_state = stateIdle;
201         m_target_fd = -1;
202         m_error = 0;
203         m_encoder_fd = -1;
204         m_thread = NULL;
205         m_nav_instance = nav_instance;
206 }
207
208 RESULT eServiceHDMIRecord::prepare(const char *filename, time_t begTime, time_t endTime, int eit_event_id, const char *name, const char *descr, const char *tags)
209 {
210         m_filename = filename;
211
212         if (m_state == stateIdle)
213         {
214                 return doPrepare();
215         }
216         return -1;
217 }
218
219 RESULT eServiceHDMIRecord::prepareStreaming()
220 {
221         return -1;
222 }
223
224 RESULT eServiceHDMIRecord::start(bool simulate)
225 {
226         m_simulate = simulate;
227         m_event((iRecordableService*)this, evStart);
228         return doRecord();
229 }
230
231 RESULT eServiceHDMIRecord::stop()
232 {
233         if (!m_simulate)
234                 eDebug("[eServiceHDMIRecord] stop recording!");
235         if (m_state == stateRecording)
236         {
237                 if (m_thread)
238                 {
239                         m_thread->stop();
240                         m_thread->stopSaveMetaInformation();
241                 }
242                 if (m_target_fd >= 0)
243                 {
244                         ::close(m_target_fd);
245                         m_target_fd = -1;
246                 }
247
248                 m_state = statePrepared;
249         } else if (!m_simulate)
250                 eDebug("[eServiceHDMIRecord] (was not recording)");
251         if (m_state == statePrepared)
252         {
253                 delete m_thread;
254                 m_thread = NULL;
255                 m_nav_instance->stopService();
256                 if (m_encoder_fd >= 0)
257                 {
258                         ::close(m_encoder_fd);
259                         m_encoder_fd = -1;
260                 }
261                 m_state = stateIdle;
262         }
263         m_event((iRecordableService*)this, evRecordStopped);
264         return 0;
265 }
266
267 int eServiceHDMIRecord::doPrepare()
268 {
269         if (!m_simulate && m_encoder_fd < 0)
270         {
271                 if (m_nav_instance->playService(m_ref) >= 0)
272                 {
273                         char filename[128];
274                         snprintf(filename, sizeof(filename), "/dev/encoder%d", HDMI_IN_REC_ENCODER_INDEX);
275                         m_encoder_fd = open(filename, O_RDONLY);
276                 }
277                 if (m_encoder_fd < 0)
278                         return -1;
279         }
280         m_state = statePrepared;
281         return 0;
282 }
283
284 int eServiceHDMIRecord::doRecord()
285 {
286         int err = doPrepare();
287         if (err)
288         {
289                 m_error = errTuneFailed;
290                 m_event((iRecordableService*)this, evRecordFailed);
291                 return err;
292         }
293
294         if (!m_thread && !m_simulate)
295         {
296                 eDebug("[eServiceHDMIRecord] Recording to %s...", m_filename.c_str());
297                 ::remove(m_filename.c_str());
298                 int fd = ::open(m_filename.c_str(), O_WRONLY | O_CREAT | O_LARGEFILE | O_CLOEXEC, 0666);
299                 if (fd < 0)
300                 {
301                         eDebug("[eServiceHDMIRecord] can't open recording file: %m");
302                         m_error = errOpenRecordFile;
303                         m_event((iRecordableService*)this, evRecordFailed);
304                         return errOpenRecordFile;
305                 }
306
307                 m_thread = new eDVBRecordFileThread();
308                 m_target_fd = fd;
309         }
310
311         eDebug("[eServiceHDMIRecord] start recording...");
312
313         if (m_state != stateRecording)
314         {
315                 if (m_thread && m_encoder_fd >= 0)
316                 {
317                         m_thread->startSaveMetaInformation(m_filename);
318                         m_thread->start(m_encoder_fd, m_target_fd);
319                 }
320                 m_state = stateRecording;
321         }
322
323         m_error = 0;
324         m_event((iRecordableService*)this, evRecordRunning);
325         return 0;
326 }
327
328 RESULT eServiceHDMIRecord::stream(ePtr<iStreamableService> &ptr)
329 {
330         ptr = NULL;
331         return -1;
332 }
333
334 RESULT eServiceHDMIRecord::subServices(ePtr<iSubserviceList> &ptr)
335 {
336         ptr = NULL;
337         return -1;
338 }
339
340 RESULT eServiceHDMIRecord::frontendInfo(ePtr<iFrontendInformation> &ptr)
341 {
342         ptr = this;
343         return 0;
344 }
345
346 RESULT eServiceHDMIRecord::connectEvent(const Slot2<void,iRecordableService*,int> &event, ePtr<eConnection> &connection)
347 {
348         connection = new eConnection((iRecordableService*)this, m_event.connect(event));
349         return 0;
350 }
351
352 eAutoInitPtr<eServiceFactoryHDMI> init_eServiceFactoryHDMI(eAutoInitNumbers::service + 1, "eServiceFactoryHDMI");