Merge commit 'origin/bug_202_networkconfig_cleanup' into experimental
[enigma2.git] / lib / service / servicexine.cpp
1 #define HAVE_XINE
2 #ifdef HAVE_XINE
3
4 /* yes, it's xine, not Xine. But eServicexine looks odd. */
5
6 #include <lib/base/eerror.h>
7 #include <lib/base/object.h>
8 #include <lib/base/ebase.h>
9 #include <string>
10 #include <lib/service/servicexine.h>
11 #include <lib/service/service.h>
12 #include <lib/base/init_num.h>
13 #include <lib/base/init.h>
14
15 static xine_t *xine; /* TODO: move this into a static class */
16
17 // eServiceFactoryXine
18
19 eServiceFactoryXine::eServiceFactoryXine()
20 {
21         ePtr<eServiceCenter> sc;
22         
23         eServiceCenter::getPrivInstance(sc);
24         if (sc)
25                 sc->addServiceFactory(eServiceFactoryXine::id, this);
26
27         m_service_info = new eStaticServiceXineInfo();
28 }
29
30 eServiceFactoryXine::~eServiceFactoryXine()
31 {
32         ePtr<eServiceCenter> sc;
33         
34         eServiceCenter::getPrivInstance(sc);
35         if (sc)
36                 sc->removeServiceFactory(eServiceFactoryXine::id);
37 }
38
39 DEFINE_REF(eServiceFactoryXine)
40
41         // iServiceHandler
42 RESULT eServiceFactoryXine::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
43 {
44                 // check resources...
45         ptr = new eServiceXine(ref.path.c_str());
46         return 0;
47 }
48
49 RESULT eServiceFactoryXine::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
50 {
51         ptr=0;
52         return -1;
53 }
54
55 RESULT eServiceFactoryXine::list(const eServiceReference &, ePtr<iListableService> &ptr)
56 {
57         ptr=0;
58         return -1;
59 }
60
61 RESULT eServiceFactoryXine::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
62 {
63         ptr = m_service_info;
64         return 0;
65 }
66
67 RESULT eServiceFactoryXine::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
68 {
69         ptr = 0;
70         return -1;
71 }
72
73
74 // eStaticServiceXineInfo
75
76
77 DEFINE_REF(eStaticServiceXineInfo)
78
79 eStaticServiceXineInfo::eStaticServiceXineInfo()
80 {
81 }
82
83 RESULT eStaticServiceXineInfo::getName(const eServiceReference &ref, std::string &name)
84 {
85         size_t last = ref.path.rfind('/');
86         if (last != std::string::npos)
87                 name = ref.path.substr(last+1);
88         else
89                 name = ref.path;
90         return 0;
91 }
92
93 int eStaticServiceXineInfo::getLength(const eServiceReference &ref)
94 {
95         return -1;
96 }
97
98 // eServiceXine
99
100 eServiceXine::eServiceXine(const char *filename): m_filename(filename), m_pump(eApp, 1)
101 {
102         m_state = stError;
103         stream = 0;
104         event_queue = 0;
105         ao_port = 0;
106         vo_port = 0;
107         
108         
109 //      if ((vo_port = xine_open_video_driver(xine, "fb", XINE_VISUAL_TYPE_FB, NULL)) == NULL)
110         if ((vo_port = xine_open_video_driver(xine, "none", XINE_VISUAL_TYPE_NONE, NULL)) == NULL)
111         {
112                 eWarning("cannot open xine video driver");
113         }
114
115         if ((ao_port = xine_open_audio_driver(xine , "alsa", NULL)) == NULL)
116         {
117                 eWarning("cannot open xine audio driver");
118         }
119         stream = xine_stream_new(xine, ao_port, vo_port);
120         event_queue = xine_event_new_queue(stream);
121         xine_event_create_listener_thread(event_queue, eventListenerWrap, this);
122
123 //      CONNECT(m_pump.recv_msg, eServiceXine::gstPoll);
124         m_state = stIdle;
125 }
126
127 eServiceXine::~eServiceXine()
128 {
129         if (m_state == stRunning)
130                 stop();
131
132         eDebug("close stream");
133         if (stream)
134                 xine_close(stream);
135         eDebug("dispose queue");
136         if (event_queue)
137                 xine_event_dispose_queue(event_queue);
138         eDebug("dispose stream");
139         if (stream)
140                 xine_dispose(stream);
141         eDebug("dispose ao_port");
142         if (ao_port)
143                 xine_close_audio_driver(xine, ao_port);
144         eDebug("dispose vo port");
145         if (vo_port)
146                 xine_close_video_driver(xine, vo_port); 
147         eDebug("done.");
148 }
149
150 DEFINE_REF(eServiceXine);       
151
152 void eServiceXine::eventListenerWrap(void *user_data, const xine_event_t *event)
153 {
154         eServiceXine *e = (eServiceXine*)user_data;
155         e->eventListener(event);
156 }
157
158 void eServiceXine::eventListener(const xine_event_t *event)
159 {
160         eDebug("handle %d", event->type);
161         switch(event->type) { 
162         case XINE_EVENT_UI_PLAYBACK_FINISHED:
163                 break;
164         }
165 }
166
167 RESULT eServiceXine::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
168 {
169         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
170         return 0;
171 }
172
173 RESULT eServiceXine::start()
174 {
175         if (m_state == stError)
176                 return -1;
177
178         ASSERT(m_state == stIdle);
179         ASSERT(stream);
180         
181         if (!xine_open(stream, m_filename.c_str()))
182         {
183                 eWarning("xine_open failed!");
184                 return -1;
185         }
186         
187         if (!xine_play(stream, 0, 0))
188         {
189                 eWarning("xine_play failed!");
190                 return -1;
191         }
192
193         m_state = stRunning;
194         
195         m_event(this, evStart);
196         return 0;
197 }
198
199 RESULT eServiceXine::stop()
200 {
201         if (m_state == stError)
202                 return -1;
203
204         ASSERT(m_state != stIdle);
205         ASSERT(stream);
206         if (m_state == stStopped)
207                 return -1;
208         printf("Xine: %s stop\n", m_filename.c_str());
209         xine_stop(stream);
210         // STOP
211         m_state = stStopped;
212         return 0;
213 }
214
215 RESULT eServiceXine::setTarget(int target)
216 {
217         return -1;
218 }
219
220 RESULT eServiceXine::pause(ePtr<iPauseableService> &ptr)
221 {
222         ptr=this;
223         return 0;
224 }
225
226 RESULT eServiceXine::setSlowMotion(int ratio)
227 {
228         return -1;
229 }
230
231 RESULT eServiceXine::setFastForward(int ratio)
232 {
233         return -1;
234 }
235   
236                 // iPausableService
237 RESULT eServiceXine::pause()
238 {
239         //SPEED_PAUSE
240         return 0;
241 }
242
243 RESULT eServiceXine::unpause()
244 {
245         //SPEED_NORMAL
246         // PLAY
247         return 0;
248 }
249
250         /* iSeekableService */
251 RESULT eServiceXine::seek(ePtr<iSeekableService> &ptr)
252 {
253         ptr = this;
254         return 0;
255 }
256
257 RESULT eServiceXine::getLength(pts_t &pts)
258 {
259         pts = -1;
260         if (m_state == stError)
261                 return 1;
262         ASSERT(stream);
263         
264         int pos_stream, pos_time, length_time;
265         
266         if (!xine_get_pos_length(stream, &pos_stream, &pos_time, &length_time))
267         {
268                 eDebug("xine_get_pos_length failed!");
269                 return 1;
270         }
271         
272         eDebug("length: %d ms", length_time);
273         
274         pts = length_time * 90;
275         
276         return 0;
277 }
278
279 RESULT eServiceXine::seekTo(pts_t to)
280 {
281                 // SEEK
282         return 0;
283 }
284
285 RESULT eServiceXine::seekRelative(int direction, pts_t to)
286 {
287                 // SEEK RELATIVE
288         return 0;
289 }
290
291 RESULT eServiceXine::getPlayPosition(pts_t &pts)
292 {
293         pts = -1;
294         if (m_state == stError)
295                 return 1;
296         ASSERT(stream);
297         
298         int pos_stream, pos_time, length_time;
299         
300         if (!xine_get_pos_length(stream, &pos_stream, &pos_time, &length_time))
301                 return 1;
302         
303         eDebug("pos_time: %d", pos_time);
304         pts = pos_time * 90;
305         
306                 // GET POSITION
307         return 0;
308 }
309
310 RESULT eServiceXine::setTrickmode(int trick)
311 {
312                 /* trickmode currently doesn't make any sense for us. */
313         return -1;
314 }
315
316 RESULT eServiceXine::isCurrentlySeekable()
317 {
318         return 3;
319 }
320
321 RESULT eServiceXine::info(ePtr<iServiceInformation>&i)
322 {
323         i = this;
324         return 0;
325 }
326
327 RESULT eServiceXine::getName(std::string &name)
328 {
329         name = "xine File: " + m_filename;
330         return 0;
331 }
332
333 int eServiceXine::getInfo(int w)
334 {
335         switch (w)
336         {
337         case sTitle:
338         case sArtist:
339         case sAlbum:
340         case sComment:
341         case sTracknumber:
342         case sGenre:
343                 return resIsString;
344
345         default:
346                 return resNA;
347         }
348 }
349
350 std::string eServiceXine::getInfoString(int w)
351 {
352         return "";
353 }
354
355 class eXine
356 {
357 public:
358         eXine()
359         {
360                         /* this should be done once. */
361
362                 if(!xine_check_version(1, 1, 0))
363                 {
364                         int major, minor, sub;
365                         xine_get_version (&major, &minor, &sub);
366                         eWarning("Require xine library version 1.1.0, found %d.%d.%d.\n",
367                                                 major, minor,sub);
368                         return;
369                 } else {
370                         int major, minor, sub;
371                         eDebug("Built with xine library %d.%d.%d (%s)\n",
372                                                  XINE_MAJOR_VERSION, XINE_MINOR_VERSION, XINE_SUB_VERSION, XINE_VERSION);
373                 
374                         xine_get_version (&major, &minor, &sub);
375
376                         eDebug("Found xine library version: %d.%d.%d (%s).\n", 
377                                                  major, minor, sub, xine_get_version_string());
378                 }
379         
380                 xine = xine_new();
381                 xine_engine_set_param(xine, XINE_ENGINE_PARAM_VERBOSITY, 1);
382                 xine_init(xine);
383         }
384         ~eXine()
385         {
386                 if (xine)
387                         xine_exit(xine);
388         }
389 };
390
391 eAutoInitP0<eXine> init_eXine(eAutoInitNumbers::service, "libxine");
392 eAutoInitPtr<eServiceFactoryXine> init_eServiceFactoryXine(eAutoInitNumbers::service+1, "eServiceFactoryXine");
393 #else
394 #warning xine not available
395 #endif