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