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