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