support new libdreamdvd, and do scaling in subtitle widget
[enigma2.git] / lib / python / Plugins / Extensions / DVDPlayer / src / servicedvd.cpp
1 /* yes, it's dvd  */
2 #include <lib/base/eerror.h>
3 #include <lib/base/object.h>
4 #include <lib/base/ebase.h>
5 #include <lib/base/nconfig.h>
6 #include <string>
7 #include <lib/service/service.h>
8 #include <lib/base/init_num.h>
9 #include <lib/base/init.h>
10 #include <lib/gui/esubtitle.h>
11 #include <lib/gdi/gpixmap.h>
12
13 #include <byteswap.h>
14 #include <netinet/in.h>
15 #ifndef BYTE_ORDER
16 #error no byte order defined!
17 #endif
18
19 extern "C" {
20 #include <dreamdvd/ddvdlib.h>
21 }
22 #include "servicedvd.h"
23
24 // eServiceFactoryDVD
25
26 eServiceFactoryDVD::eServiceFactoryDVD()
27 {
28         ePtr<eServiceCenter> sc;
29         
30         eServiceCenter::getPrivInstance(sc);
31         if (sc)
32         {
33                 std::list<std::string> extensions;
34                 extensions.push_back("iso");
35                 sc->addServiceFactory(eServiceFactoryDVD::id, this, extensions);
36         }
37 }
38
39 eServiceFactoryDVD::~eServiceFactoryDVD()
40 {
41         ePtr<eServiceCenter> sc;
42         
43         eServiceCenter::getPrivInstance(sc);
44         if (sc)
45                 sc->removeServiceFactory(eServiceFactoryDVD::id);
46 }
47
48 DEFINE_REF(eServiceFactoryDVD)
49
50         // iServiceHandler
51 RESULT eServiceFactoryDVD::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
52 {
53                 // check resources...
54         ptr = new eServiceDVD(ref.path.c_str());
55         return 0;
56 }
57
58 RESULT eServiceFactoryDVD::record(const eServiceReference &/*ref*/, ePtr<iRecordableService> &ptr)
59 {
60         ptr=0;
61         return -1;
62 }
63
64 RESULT eServiceFactoryDVD::list(const eServiceReference &, ePtr<iListableService> &ptr)
65 {
66         ptr=0;
67         return -1;
68 }
69
70
71 RESULT eServiceFactoryDVD::info(const eServiceReference &/*ref*/, ePtr<iStaticServiceInformation> &ptr)
72 {
73         ptr=0;
74         return -1;
75 }
76
77 RESULT eServiceFactoryDVD::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
78 {
79         ptr = 0;
80         return -1;
81 }
82
83 // eServiceDVD
84
85 DEFINE_REF(eServiceDVD);
86
87 eServiceDVD::eServiceDVD(const char *filename):
88         m_filename(filename),
89         m_ddvdconfig(ddvd_create()),
90         m_subtitle_widget(0),
91         m_state(stIdle),
92         m_current_trick(0),
93         m_pump(eApp, 1)
94 {
95         int aspect = DDVD_16_9; 
96         int policy = DDVD_PAN_SCAN;
97
98         char tmp[255];
99         ssize_t rd;
100
101         m_sn = eSocketNotifier::create(eApp, ddvd_get_messagepipe_fd(m_ddvdconfig), eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Error|eSocketNotifier::Hungup);
102         eDebug("SERVICEDVD construct!");
103         // create handle
104         ddvd_set_dvd_path(m_ddvdconfig, filename);
105         ddvd_set_ac3thru(m_ddvdconfig, 0);
106
107         std::string ddvd_language;
108         if (!ePythonConfigQuery::getConfigValue("config.osd.language", ddvd_language))
109                 ddvd_set_language(m_ddvdconfig, (ddvd_language.substr(0,2)).c_str());
110
111         int fd = open("/proc/stb/video/aspect", O_RDONLY);
112         if (fd > -1)
113         {
114                 rd = read(fd, tmp, 255);
115                 if (rd > 2 && !strncmp(tmp, "4:3", 3))
116                         aspect = DDVD_4_3;
117                 else if (rd > 4 && !strncmp(tmp, "16:10", 5))
118                         aspect = DDVD_16_10;
119                 close(fd);
120         }
121
122         fd = open("/proc/stb/video/policy", O_RDONLY);
123         if (fd > -1)
124         {
125                 rd = read(fd, tmp, 255);
126                 if (rd > 6 && !strncmp(tmp, "bestfit", 7))
127                         policy = DDVD_JUSTSCALE;
128                 else if (rd > 8 && !strncmp(tmp, "letterbox", 9))
129                         policy = DDVD_LETTERBOX;
130                 close(fd);
131         }
132
133         ddvd_set_video(m_ddvdconfig, aspect, policy, DDVD_PAL /*unused*/);
134
135         CONNECT(m_sn->activated, eServiceDVD::gotMessage);
136         CONNECT(m_pump.recv_msg, eServiceDVD::gotThreadMessage);
137         strcpy(m_ddvd_titlestring,"");
138         m_cue_pts = 0;
139         pause();
140 }
141
142 void eServiceDVD::gotThreadMessage(const int &msg)
143 {
144         switch(msg)
145         {
146         case 1: // thread stopped
147                 m_state = stStopped;
148                 m_event(this, evStopped);
149                 break;
150         }
151 }
152
153 void eServiceDVD::gotMessage(int /*what*/)
154 {
155         switch(ddvd_get_next_message(m_ddvdconfig,1))
156         {
157                 case DDVD_COLORTABLE_UPDATE:
158                 {
159 /*
160                         struct ddvd_color ctmp[4];
161                         ddvd_get_last_colortable(ddvdconfig, ctmp);
162                         int i=0;
163                         while (i < 4)
164                         {
165                                 rd1[252+i]=ctmp[i].red;
166                                 bl1[252+i]=ctmp[i].blue;
167                                 gn1[252+i]=ctmp[i].green;
168                                 tr1[252+i]=ctmp[i].trans;
169                                 i++;
170                         }
171                         if(ioctl(fb, FBIOPUTCMAP, &colormap) == -1)
172                         {
173                                 printf("Framebuffer: <FBIOPUTCMAP failed>\n");
174                                 return 1;
175                         }
176 */
177                         eDebug("no support for 8bpp framebuffer in dvdplayer yet!");
178                         break;
179                 }
180                 case DDVD_SCREEN_UPDATE:
181                         eDebug("DVD_SCREEN_UPDATE!");
182                         if (m_subtitle_widget) {
183                                 int x1,x2,y1,y2;
184                                 ddvd_get_last_blit_area(m_ddvdconfig, &x1, &x2, &y1, &y2);
185                                 
186                                 int x_offset = 0, y_offset = 0, width = 720, height = 576;
187
188 #ifdef DDVD_SUPPORTS_GET_BLIT_DESTINATION
189                                 ddvd_get_blit_destination(m_ddvdconfig, &x_offset, &y_offset, &width, &height);
190                                 eDebug("values got from ddvd: %d %d %d %d", x_offset, y_offset, width, height);
191                                 width -= x_offset * 2;
192                                 height -= y_offset * 2;
193 #endif
194                                 eRect dest(x_offset, y_offset, width, height);
195
196                                 if (dest.width() && dest.height())
197                                         m_subtitle_widget->setPixmap(m_pixmap, eRect(x1, y1, (x2-x1)+1, (y2-y1)+1), dest);
198                         }
199                         break;
200                 case DDVD_SHOWOSD_STATE_PLAY:
201                 {
202                         eDebug("DVD_SHOWOSD_STATE_PLAY!");
203                         m_current_trick = 0;
204                         m_event(this, evUser+1);
205                         break;
206                 }
207                 case DDVD_SHOWOSD_STATE_PAUSE:
208                 {
209                         eDebug("DVD_SHOWOSD_STATE_PAUSE!");
210                         m_event(this, evUser+2);
211                         break;
212                 }
213                 case DDVD_SHOWOSD_STATE_FFWD:
214                 {
215                         eDebug("DVD_SHOWOSD_STATE_FFWD!");
216                         m_event(this, evUser+3);
217                         break;
218                 }
219                 case DDVD_SHOWOSD_STATE_FBWD:
220                 {
221                         eDebug("DVD_SHOWOSD_STATE_FBWD!");
222                         m_event(this, evUser+4);
223                         break;
224                 }
225                 case DDVD_SHOWOSD_STRING:
226                 {
227                         eDebug("DVD_SHOWOSD_STRING!");
228                         m_event(this, evUser+5);
229                         break;
230                 }
231                 case DDVD_SHOWOSD_AUDIO:
232                 {
233                         eDebug("DVD_SHOWOSD_STRING!");
234                         m_event(this, evUser+6);
235                         break;
236                 }
237                 case DDVD_SHOWOSD_SUBTITLE:
238                 {
239                         eDebug("DVD_SHOWOSD_SUBTITLE!");
240                         m_event((iPlayableService*)this, evUpdatedInfo);
241                         m_event(this, evUser+7);
242                         break;
243                 }
244                 case DDVD_EOF_REACHED:
245                         eDebug("DVD_EOF_REACHED!");
246                         m_event(this, evEOF);
247                         break;
248                 case DDVD_SOF_REACHED:
249                         eDebug("DVD_SOF_REACHED!");
250                         m_event(this, evSOF);
251                         break;
252                 case DDVD_SHOWOSD_ANGLE:
253                 {
254                         int current, num;
255                         ddvd_get_angle_info(m_ddvdconfig, &current, &num);
256                         eDebug("DVD_ANGLE_INFO: %d / %d", current, num);
257                         m_event(this, evUser+13);
258                         break;
259                 }
260                 case DDVD_SHOWOSD_TIME:
261                 {
262                         static struct ddvd_time last_info;
263                         struct ddvd_time info;
264 //                      eDebug("DVD_SHOWOSD_TIME!");
265                         ddvd_get_last_time(m_ddvdconfig, &info);
266                         if ( info.pos_chapter != last_info.pos_chapter )
267                                 m_event(this, evUser+8); // chapterUpdated
268                         if ( info.pos_title != last_info.pos_title )
269                                 m_event(this, evUser+9); // titleUpdated
270                         memcpy(&last_info, &info, sizeof(struct ddvd_time));
271                         break;
272                 }
273                 case DDVD_SHOWOSD_TITLESTRING:
274                 {
275                         ddvd_get_title_string(m_ddvdconfig, m_ddvd_titlestring);
276                         eDebug("DDVD_SHOWOSD_TITLESTRING: %s",m_ddvd_titlestring);
277                         loadCuesheet();
278                         if (!m_cue_pts)
279                                 unpause();
280                         m_event(this, evStart);
281                         break;
282                 }
283                 case DDVD_MENU_OPENED:
284                         eDebug("DVD_MENU_OPENED!");
285                         m_state = stMenu;
286                         m_event(this, evSeekableStatusChanged);
287                         m_event(this, evUser+11);
288                         break;
289                 case DDVD_MENU_CLOSED:
290                         eDebug("DVD_MENU_CLOSED!");
291                         m_state = stRunning;
292                         m_event(this, evSeekableStatusChanged);
293                         m_event(this, evUser+12);
294                         break;
295                 default:
296                         break;
297         }
298 }
299
300 eServiceDVD::~eServiceDVD()
301 {
302         eDebug("SERVICEDVD destruct!");
303         kill();
304         saveCuesheet();
305         ddvd_close(m_ddvdconfig);
306         disableSubtitles(0);
307 }
308
309 RESULT eServiceDVD::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
310 {
311         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
312         return 0;
313 }
314
315 RESULT eServiceDVD::start()
316 {
317         ASSERT(m_state == stIdle);
318         m_state = stRunning;
319         eDebug("eServiceDVD starting");
320 //      m_event(this, evStart);
321         return 0;
322 }
323
324 RESULT eServiceDVD::stop()
325 {
326         ASSERT(m_state != stIdle);
327         if (m_state == stStopped)
328                 return -1;
329         eDebug("DVD: stop %s", m_filename.c_str());
330         m_state = stStopped;
331         ddvd_send_key(m_ddvdconfig, DDVD_KEY_EXIT);
332
333         return 0;
334 }
335
336 RESULT eServiceDVD::setTarget(int /*target*/)
337 {
338         return -1;
339 }
340
341 RESULT eServiceDVD::pause(ePtr<iPauseableService> &ptr)
342 {
343         ptr=this;
344         return 0;
345 }
346
347 RESULT eServiceDVD::seek(ePtr<iSeekableService> &ptr)
348 {
349         ptr=this;
350         return 0;
351 }
352
353 RESULT eServiceDVD::subtitle(ePtr<iSubtitleOutput> &ptr)
354 {
355         ptr=this;
356         return 0;
357 }
358
359 RESULT eServiceDVD::keys(ePtr<iServiceKeys> &ptr)
360 {
361         ptr=this;
362         return 0;
363 }
364
365         // iPausableService
366 RESULT eServiceDVD::setSlowMotion(int /*ratio*/)
367 {
368         return -1;
369 }
370
371 RESULT eServiceDVD::setFastForward(int trick)
372 {
373         eDebug("setTrickmode(%d)", trick);
374         while (m_current_trick > trick && m_current_trick != -64)
375         {
376                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_FBWD);
377                 if (m_current_trick == 0)
378                         m_current_trick = -2;
379                 else if (m_current_trick > 0)
380                 {
381                         m_current_trick /= 2;
382                         if (abs(m_current_trick) == 1)
383                                 m_current_trick=0;
384                 }
385                 else
386                         m_current_trick *= 2;
387         }
388         while (m_current_trick < trick && m_current_trick != 64)
389         {
390                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_FFWD);
391                 if (m_current_trick == 0)
392                         m_current_trick = 2;
393                 else if (m_current_trick < 0)
394                 {
395                         m_current_trick /= 2;
396                         if (abs(m_current_trick) == 1)
397                                 m_current_trick=0;
398                 }
399                 else
400                         m_current_trick *= 2;
401         }
402         return 0;
403 }
404
405 RESULT eServiceDVD::pause()
406 {
407         eDebug("set pause!\n");
408         ddvd_send_key(m_ddvdconfig, DDVD_KEY_PAUSE);
409         return 0;
410 }
411
412 RESULT eServiceDVD::unpause()
413 {
414         eDebug("set unpause!\n");
415         ddvd_send_key(m_ddvdconfig, DDVD_KEY_PLAY);
416         return 0;
417 }
418
419 void eServiceDVD::thread()
420 {
421         eDebug("eServiceDVD dvd thread started");
422         hasStarted();
423         ddvd_run(m_ddvdconfig);
424 }
425
426 void eServiceDVD::thread_finished()
427 {
428         eDebug("eServiceDVD dvd thread finished");
429         m_pump.send(1); // inform main thread
430 }
431
432 RESULT eServiceDVD::info(ePtr<iServiceInformation>&i)
433 {
434         i = this;
435         return 0;
436 }
437
438 RESULT eServiceDVD::getName(std::string &name)
439 {
440         if ( m_ddvd_titlestring[0] != '\0' )
441                 name = m_ddvd_titlestring;
442         else
443                 name = m_filename;
444         return 0;
445 }
446
447 int eServiceDVD::getInfo(int w)
448 {
449         switch (w)
450         {
451                 case sCurrentChapter:
452                 {
453                         struct ddvd_time info;
454                         ddvd_get_last_time(m_ddvdconfig, &info);
455                         return info.pos_chapter;
456                 }
457                 case sTotalChapters:
458                 {
459                         struct ddvd_time info;
460                         ddvd_get_last_time(m_ddvdconfig, &info);
461                         return info.end_chapter;
462                 }
463                 case sCurrentTitle:
464                 {
465                         struct ddvd_time info;
466                         ddvd_get_last_time(m_ddvdconfig, &info);
467                         return info.pos_title;
468                 }
469                 case sTotalTitles:
470                 {
471                         struct ddvd_time info;
472                         ddvd_get_last_time(m_ddvdconfig, &info);
473                         return info.end_title;
474                 }
475                 case sTXTPID:   // we abuse HAS_TELEXT icon in InfoBar to signalize subtitles status
476                 {
477                         int spu_id;
478                         uint16_t spu_lang;
479                         ddvd_get_last_spu(m_ddvdconfig, &spu_id, &spu_lang);
480                         return spu_id;
481                 }
482                 case sUser+6:
483                 case sUser+7:
484                 case sUser+8:
485                         return resIsPyObject;
486                 default:
487                         return resNA;
488         }
489 }
490
491 std::string eServiceDVD::getInfoString(int w)
492 {
493         switch(w)
494         {
495                 case sServiceref:
496                         break;
497                 default:
498                         eDebug("unhandled getInfoString(%d)", w);
499         }
500         return "";
501 }
502
503 PyObject *eServiceDVD::getInfoObject(int w)
504 {
505         switch(w)
506         {
507                 case sUser+6:
508                 {
509                         ePyObject tuple = PyTuple_New(3);
510                         int audio_id,audio_type;
511                         uint16_t audio_lang;
512                         ddvd_get_last_audio(m_ddvdconfig, &audio_id, &audio_lang, &audio_type);
513                         char audio_string[3]={audio_lang >> 8, audio_lang, 0};
514                         PyTuple_SetItem(tuple, 0, PyInt_FromLong(audio_id+1));
515                         PyTuple_SetItem(tuple, 1, PyString_FromString(audio_string));
516                         switch(audio_type)
517                         {
518                                 case DDVD_MPEG:
519                                         PyTuple_SetItem(tuple, 2, PyString_FromString("MPEG"));
520                                         break;
521                                 case DDVD_AC3:
522                                         PyTuple_SetItem(tuple, 2, PyString_FromString("AC3"));
523                                         break;
524                                 case DDVD_DTS:
525                                         PyTuple_SetItem(tuple, 2, PyString_FromString("DTS"));
526                                         break;
527                                 case DDVD_LPCM:
528                                         PyTuple_SetItem(tuple, 2, PyString_FromString("LPCM"));
529                                         break;
530                                 default:
531                                         PyTuple_SetItem(tuple, 2, PyString_FromString(""));
532                         }
533                         return tuple;
534                 }
535                 case sUser+7:
536                 {
537                         ePyObject tuple = PyTuple_New(2);
538                         int spu_id;
539                         uint16_t spu_lang;
540                         ddvd_get_last_spu(m_ddvdconfig, &spu_id, &spu_lang);
541                         char spu_string[3]={spu_lang >> 8, spu_lang, 0};
542                         if (spu_id == -1)
543                         {
544                                 PyTuple_SetItem(tuple, 0, PyInt_FromLong(0));
545                                 PyTuple_SetItem(tuple, 1, PyString_FromString(""));
546                         }
547                         else
548                         {
549                                 PyTuple_SetItem(tuple, 0, PyInt_FromLong(spu_id+1));
550                                 PyTuple_SetItem(tuple, 1, PyString_FromString(spu_string));
551                         }                               
552                         return tuple;
553                 }
554                 case sUser+8:
555                 {
556                         ePyObject tuple = PyTuple_New(2);
557                         int current, num;
558                         ddvd_get_angle_info(m_ddvdconfig, &current, &num);
559                         PyTuple_SetItem(tuple, 0, PyInt_FromLong(current));
560                         PyTuple_SetItem(tuple, 1, PyInt_FromLong(num));
561
562                         return tuple;
563                 }
564                 default:
565                         eDebug("unhandled getInfoObject(%d)", w);
566         }
567         Py_RETURN_NONE;
568 }
569
570 RESULT eServiceDVD::enableSubtitles(eWidget *parent, SWIG_PYOBJECT(ePyObject) /*entry*/)
571 {
572         delete m_subtitle_widget;
573
574         m_subtitle_widget = new eSubtitleWidget(parent);
575         m_subtitle_widget->resize(parent->size());
576
577         eSize size = eSize(720, 576);
578
579         if (!m_pixmap)
580         {
581                 m_pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */
582 #ifdef DDVD_SUPPORTS_GET_BLIT_DESTINATION
583                 ddvd_set_lfb_ex(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4, 1);
584 #else
585                 ddvd_set_lfb(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4);
586 #warning please update libdreamdvd for fast scaling
587 #endif
588                 run(); // start the thread
589         }
590
591         m_subtitle_widget->setZPosition(-1);
592         m_subtitle_widget->show();
593
594         return 0;
595 }
596
597 RESULT eServiceDVD::disableSubtitles(eWidget */*parent*/)
598 {
599         delete m_subtitle_widget;
600         m_subtitle_widget = 0;
601         return 0;
602 }
603
604 PyObject *eServiceDVD::getSubtitleList()
605 {
606         eDebug("eServiceDVD::getSubtitleList nyi");
607         Py_RETURN_NONE;
608 }
609
610 PyObject *eServiceDVD::getCachedSubtitle()
611 {
612         eDebug("eServiceDVD::getCachedSubtitle nyi");
613         Py_RETURN_NONE;
614 }
615
616 RESULT eServiceDVD::getLength(pts_t &len)
617 {
618 //      eDebug("eServiceDVD::getLength");
619         struct ddvd_time info;
620         ddvd_get_last_time(m_ddvdconfig, &info);
621         len = info.end_hours * 3600;
622         len += info.end_minutes * 60;
623         len += info.end_seconds;
624         len *= 90000;
625         return 0;
626 }
627
628 RESULT eServiceDVD::seekTo(pts_t to)
629 {
630         eDebug("eServiceDVD::seekTo(%lld)",to);
631         if ( to > 0 )
632         {
633                 eDebug("set_resume_pos: resume_info.title=%d, chapter=%d, block=%lu, audio_id=%d, audio_lock=%d, spu_id=%d, spu_lock=%d",m_resume_info.title,m_resume_info.chapter,m_resume_info.block,m_resume_info.audio_id, m_resume_info.audio_lock, m_resume_info.spu_id, m_resume_info.spu_lock);
634                 ddvd_set_resume_pos(m_ddvdconfig, m_resume_info);
635         }
636         return 0;
637 }
638
639 RESULT eServiceDVD::seekRelative(int direction, pts_t to)
640 {
641         int seconds = to / 90000;
642         seconds *= direction;
643         eDebug("seekRelative %d %d", direction, seconds);
644         ddvd_skip_seconds(m_ddvdconfig, seconds);
645         return 0;
646 }
647
648 RESULT eServiceDVD::getPlayPosition(pts_t &pos)
649 {
650         struct ddvd_time info;
651         ddvd_get_last_time(m_ddvdconfig, &info);
652         pos = info.pos_hours * 3600;
653         pos += info.pos_minutes * 60;
654         pos += info.pos_seconds;
655 //      eDebug("getPlayPosition %lld", pos);
656         pos *= 90000;
657         return 0;
658 }
659
660 RESULT eServiceDVD::seekTitle(int title)
661 {
662         eDebug("setTitle %d", title);
663         ddvd_set_title(m_ddvdconfig, title);
664         return 0;
665 }
666
667 RESULT eServiceDVD::seekChapter(int chapter)
668 {
669         eDebug("setChapter %d", chapter);
670         if ( chapter > 0 )
671                 ddvd_set_chapter(m_ddvdconfig, chapter);
672         return 0;
673 }
674
675 RESULT eServiceDVD::setTrickmode(int /*trick*/)
676 {
677         return -1;
678 }
679
680 RESULT eServiceDVD::isCurrentlySeekable()
681 {
682         return m_state == stRunning;
683 }
684
685 RESULT eServiceDVD::keyPressed(int key)
686 {
687         switch(key)
688         {
689         case iServiceKeys::keyLeft:
690                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_LEFT);
691                 break;
692         case iServiceKeys::keyRight:
693                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_RIGHT);
694                 break;
695         case iServiceKeys::keyUp:
696                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_UP);
697                 break;
698         case iServiceKeys::keyDown:
699                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_DOWN);
700                 break;
701         case iServiceKeys::keyOk:
702                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_OK);
703                 break;
704         case iServiceKeys::keyUser:
705                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_AUDIO);
706                 break;
707         case iServiceKeys::keyUser+1:
708                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_SUBTITLE);
709                 break;
710         case iServiceKeys::keyUser+2:
711                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_AUDIOMENU);
712                 break;
713         case iServiceKeys::keyUser+3:
714                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_NEXT_CHAPTER);
715                 break;
716         case iServiceKeys::keyUser+4:
717                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PREV_CHAPTER);
718                 break;
719         case iServiceKeys::keyUser+5:
720                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_NEXT_TITLE);
721                 break;
722         case iServiceKeys::keyUser+6:
723                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PREV_TITLE);
724                 break;
725         case iServiceKeys::keyUser+7:
726                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_MENU);
727                 break;
728         case iServiceKeys::keyUser+8:
729                 ddvd_send_key(m_ddvdconfig, DDVD_KEY_ANGLE);
730                 break;
731         default:
732                 return -1;
733         }
734         return 0;
735 }
736
737 RESULT eServiceDVD::cueSheet(ePtr<iCueSheet> &ptr)
738 {
739         if (m_cue_pts)
740         {
741                 ptr = this;
742                 return 0;
743         }
744         ptr = 0;
745         return -1;
746 }
747
748 PyObject *eServiceDVD::getCutList()
749 {
750         ePyObject list = PyList_New(1);
751         ePyObject tuple = PyTuple_New(2);
752         PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(m_cue_pts));
753         PyTuple_SetItem(tuple, 1, PyInt_FromLong(3));
754         PyList_SetItem(list, 0, tuple);
755         return list;
756 }
757
758 void eServiceDVD::setCutList(ePyObject /*list*/)
759 {
760 }
761
762 void eServiceDVD::setCutListEnable(int /*enable*/)
763 {
764 }
765
766 void eServiceDVD::loadCuesheet()
767 {
768         char filename[128];
769         if ( m_ddvd_titlestring[0] != '\0' )
770                 snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
771         else
772                 snprintf(filename, 128, "%s/dvd.cuts", m_filename.c_str());
773
774         eDebug("eServiceDVD::loadCuesheet() filename=%s",filename);
775
776         FILE *f = fopen(filename, "rb");
777
778         if (f)
779         {
780                 unsigned long long where;
781                 unsigned int what;
782
783                 if (!fread(&where, sizeof(where), 1, f))
784                         return;
785                 if (!fread(&what, sizeof(what), 1, f))
786                         return;
787 #if BYTE_ORDER == LITTLE_ENDIAN
788                 where = bswap_64(where);
789 #endif
790                 what = ntohl(what);
791
792                 if (!fread(&m_resume_info, sizeof(struct ddvd_resume), 1, f))
793                         return;
794                 if (!fread(&what, sizeof(what), 1, f))
795                         return;
796
797                 what = ntohl(what);
798                 if (what != 4 )
799                         return;
800
801                 m_cue_pts = where;
802
803                 fclose(f);
804         } else
805                 eDebug("cutfile not found!");
806
807         if (m_cue_pts)
808         {
809                 m_event((iPlayableService*)this, evCuesheetChanged);
810                 eDebug("eServiceDVD::loadCuesheet() pts=%lld",m_cue_pts);
811         }
812 }
813
814 void eServiceDVD::saveCuesheet()
815 {
816         eDebug("eServiceDVD::saveCuesheet()");
817
818         struct ddvd_resume resume_info;
819         ddvd_get_resume_pos(m_ddvdconfig, &resume_info);
820
821         if (resume_info.title)
822         {
823                 struct ddvd_time info;
824                 ddvd_get_last_time(m_ddvdconfig, &info);
825                 pts_t pos;
826                 pos = info.pos_hours * 3600;
827                 pos += info.pos_minutes * 60;
828                 pos += info.pos_seconds;
829                 pos *= 90000;
830                 m_cue_pts = pos;
831                 eDebug("ddvd_get_resume_pos resume_info.title=%d, chapter=%d, block=%lu, audio_id=%d, audio_lock=%d, spu_id=%d, spu_lock=%d  (pts=%llu)",resume_info.title,resume_info.chapter,resume_info.block,resume_info.audio_id, resume_info.audio_lock, resume_info.spu_id, resume_info.spu_lock,m_cue_pts);
832         }
833         else
834         {
835                 eDebug("we're in a menu or somewhere else funny. so save cuesheet with pts=0");
836                 m_cue_pts = 0;
837         }
838
839         char filename[128];
840         if ( m_ddvd_titlestring[0] != '\0' )
841                 snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
842         else
843                 snprintf(filename, 128, "%s/dvd.cuts", m_filename.c_str());
844         
845         FILE *f = fopen(filename, "wb");
846
847         if (f)
848         {
849                 unsigned long long where;
850                 int what;
851
852 #if BYTE_ORDER == BIG_ENDIAN
853                 where = m_cue_pts;
854 #else
855                 where = bswap_64(m_cue_pts);
856 #endif
857                 what = htonl(3);
858                 fwrite(&where, sizeof(where), 1, f);
859                 fwrite(&what, sizeof(what), 1, f);
860                 
861                 what = htonl(4);
862                 fwrite(&resume_info, sizeof(struct ddvd_resume), 1, f);
863                 fwrite(&what, sizeof(what), 1, f);
864
865                 fclose(f);
866         }
867 }
868
869 eAutoInitPtr<eServiceFactoryDVD> init_eServiceFactoryDVD(eAutoInitNumbers::service+1, "eServiceFactoryDVD");
870
871 PyMODINIT_FUNC
872 initservicedvd(void)
873 {
874         Py_InitModule("servicedvd", NULL);
875 }