2 #include <lib/base/eerror.h>
3 #include <lib/base/object.h>
4 #include <lib/base/ebase.h>
5 #include <lib/base/nconfig.h>
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>
14 #include <netinet/in.h>
16 #error no byte order defined!
20 #include <dreamdvd/ddvdlib.h>
22 #include "servicedvd.h"
26 eServiceFactoryDVD::eServiceFactoryDVD()
28 ePtr<eServiceCenter> sc;
30 eServiceCenter::getPrivInstance(sc);
33 std::list<std::string> extensions;
34 extensions.push_back("iso");
35 sc->addServiceFactory(eServiceFactoryDVD::id, this, extensions);
39 eServiceFactoryDVD::~eServiceFactoryDVD()
41 ePtr<eServiceCenter> sc;
43 eServiceCenter::getPrivInstance(sc);
45 sc->removeServiceFactory(eServiceFactoryDVD::id);
48 DEFINE_REF(eServiceFactoryDVD)
51 RESULT eServiceFactoryDVD::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
54 ptr = new eServiceDVD(ref.path.c_str());
58 RESULT eServiceFactoryDVD::record(const eServiceReference &/*ref*/, ePtr<iRecordableService> &ptr)
64 RESULT eServiceFactoryDVD::list(const eServiceReference &, ePtr<iListableService> &ptr)
71 RESULT eServiceFactoryDVD::info(const eServiceReference &/*ref*/, ePtr<iStaticServiceInformation> &ptr)
77 RESULT eServiceFactoryDVD::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
85 DEFINE_REF(eServiceDVD);
87 eServiceDVD::eServiceDVD(const char *filename):
89 m_ddvdconfig(ddvd_create()),
90 m_pixmap(new gPixmap(eSize(720, 576), 32)),
96 m_sn = eSocketNotifier::create(eApp, ddvd_get_messagepipe_fd(m_ddvdconfig), eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Error|eSocketNotifier::Hungup);
98 eDebug("SERVICEDVD construct!");
100 ddvd_set_dvd_path(m_ddvdconfig, filename);
101 ddvd_set_ac3thru(m_ddvdconfig, 0);
102 ddvd_set_language(m_ddvdconfig, "de");
104 if (ePythonConfigQuery::getConfigValue("config.av.aspect", aspect) != 0)
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);
111 ddvd_set_video(m_ddvdconfig, DDVD_16_9, DDVD_PAL);
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,"");
121 void eServiceDVD::gotThreadMessage(const int &msg)
125 case 1: // thread stopped
127 m_event(this, evStopped);
132 void eServiceDVD::gotMessage(int /*what*/)
134 switch(ddvd_get_next_message(m_ddvdconfig,1))
136 case DDVD_COLORTABLE_UPDATE:
139 struct ddvd_color ctmp[4];
140 ddvd_get_last_colortable(ddvdconfig, ctmp);
144 rd1[252+i]=ctmp[i].red;
145 bl1[252+i]=ctmp[i].blue;
146 gn1[252+i]=ctmp[i].green;
147 tr1[252+i]=ctmp[i].trans;
150 if(ioctl(fb, FBIOPUTCMAP, &colormap) == -1)
152 printf("Framebuffer: <FBIOPUTCMAP failed>\n");
156 eDebug("no support for 8bpp framebuffer in dvdplayer yet!");
159 case DDVD_SCREEN_UPDATE:
160 eDebug("DVD_SCREEN_UPDATE!");
161 if (m_subtitle_widget)
162 m_subtitle_widget->setPixmap(m_pixmap, eRect(0, 0, 720, 576));
164 case DDVD_SHOWOSD_STATE_PLAY:
166 eDebug("DVD_SHOWOSD_STATE_PLAY!");
168 m_event(this, evUser+1);
171 case DDVD_SHOWOSD_STATE_PAUSE:
173 eDebug("DVD_SHOWOSD_STATE_PAUSE!");
174 m_event(this, evUser+2);
177 case DDVD_SHOWOSD_STATE_FFWD:
179 eDebug("DVD_SHOWOSD_STATE_FFWD!");
180 m_event(this, evUser+3);
183 case DDVD_SHOWOSD_STATE_FBWD:
185 eDebug("DVD_SHOWOSD_STATE_FBWD!");
186 m_event(this, evUser+4);
189 case DDVD_SHOWOSD_STRING:
191 eDebug("DVD_SHOWOSD_STRING!");
192 m_event(this, evUser+5);
195 case DDVD_SHOWOSD_AUDIO:
197 eDebug("DVD_SHOWOSD_STRING!");
198 m_event(this, evUser+6);
201 case DDVD_SHOWOSD_SUBTITLE:
203 eDebug("DVD_SHOWOSD_SUBTITLE!");
204 m_event((iPlayableService*)this, evUpdatedInfo);
205 m_event(this, evUser+7);
208 case DDVD_EOF_REACHED:
209 eDebug("DVD_EOF_REACHED!");
210 m_event(this, evEOF);
212 case DDVD_SOF_REACHED:
213 eDebug("DVD_SOF_REACHED!");
214 m_event(this, evSOF);
216 case DDVD_SHOWOSD_TIME:
218 static struct ddvd_time last_info;
219 struct ddvd_time info;
220 // eDebug("DVD_SHOWOSD_TIME!");
221 ddvd_get_last_time(m_ddvdconfig, &info);
222 if ( info.pos_chapter != last_info.pos_chapter )
223 m_event(this, evUser+8); // chapterUpdated
224 if ( info.pos_title != last_info.pos_title )
225 m_event(this, evUser+9); // titleUpdated
226 memcpy(&last_info, &info, sizeof(struct ddvd_time));
229 case DDVD_SHOWOSD_TITLESTRING:
231 ddvd_get_title_string(m_ddvdconfig, m_ddvd_titlestring);
232 eDebug("DDVD_SHOWOSD_TITLESTRING: %s",m_ddvd_titlestring);
236 m_event(this, evStart);
239 case DDVD_MENU_OPENED:
240 eDebug("DVD_MENU_OPENED!");
242 m_event(this, evSeekableStatusChanged);
243 m_event(this, evUser+11);
245 case DDVD_MENU_CLOSED:
246 eDebug("DVD_MENU_CLOSED!");
248 m_event(this, evSeekableStatusChanged);
249 m_event(this, evUser+12);
256 eServiceDVD::~eServiceDVD()
258 eDebug("SERVICEDVD destruct!");
261 ddvd_close(m_ddvdconfig);
264 RESULT eServiceDVD::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
266 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
270 RESULT eServiceDVD::start()
272 assert(m_state == stIdle);
274 eDebug("eServiceDVD starting");
276 // m_event(this, evStart);
280 RESULT eServiceDVD::stop()
282 assert(m_state != stIdle);
283 if (m_state == stStopped)
285 eDebug("DVD: stop %s", m_filename.c_str());
287 ddvd_send_key(m_ddvdconfig, DDVD_KEY_EXIT);
292 RESULT eServiceDVD::setTarget(int /*target*/)
297 RESULT eServiceDVD::pause(ePtr<iPauseableService> &ptr)
303 RESULT eServiceDVD::seek(ePtr<iSeekableService> &ptr)
309 RESULT eServiceDVD::subtitle(ePtr<iSubtitleOutput> &ptr)
315 RESULT eServiceDVD::keys(ePtr<iServiceKeys> &ptr)
322 RESULT eServiceDVD::setSlowMotion(int /*ratio*/)
327 RESULT eServiceDVD::setFastForward(int trick)
329 eDebug("setTrickmode(%d)", trick);
330 while (m_current_trick > trick && m_current_trick != -64)
332 ddvd_send_key(m_ddvdconfig, DDVD_KEY_FBWD);
333 if (m_current_trick == 0)
334 m_current_trick = -2;
335 else if (m_current_trick > 0)
337 m_current_trick /= 2;
338 if (abs(m_current_trick) == 1)
342 m_current_trick *= 2;
344 while (m_current_trick < trick && m_current_trick != 64)
346 ddvd_send_key(m_ddvdconfig, DDVD_KEY_FFWD);
347 if (m_current_trick == 0)
349 else if (m_current_trick < 0)
351 m_current_trick /= 2;
352 if (abs(m_current_trick) == 1)
356 m_current_trick *= 2;
361 RESULT eServiceDVD::pause()
363 eDebug("set pause!\n");
364 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PAUSE);
368 RESULT eServiceDVD::unpause()
370 eDebug("set unpause!\n");
371 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PLAY);
375 void eServiceDVD::thread()
377 eDebug("eServiceDVD dvd thread started");
379 ddvd_run(m_ddvdconfig);
382 void eServiceDVD::thread_finished()
384 eDebug("eServiceDVD dvd thread finished");
385 m_pump.send(1); // inform main thread
388 RESULT eServiceDVD::info(ePtr<iServiceInformation>&i)
394 RESULT eServiceDVD::getName(std::string &name)
396 if ( m_ddvd_titlestring[0] != '\0' )
397 name = m_ddvd_titlestring;
403 int eServiceDVD::getInfo(int w)
407 case sCurrentChapter:
409 struct ddvd_time info;
410 ddvd_get_last_time(m_ddvdconfig, &info);
411 return info.pos_chapter;
415 struct ddvd_time info;
416 ddvd_get_last_time(m_ddvdconfig, &info);
417 return info.end_chapter;
421 struct ddvd_time info;
422 ddvd_get_last_time(m_ddvdconfig, &info);
423 return info.pos_title;
427 struct ddvd_time info;
428 ddvd_get_last_time(m_ddvdconfig, &info);
429 return info.end_title;
431 case sTXTPID: // we abuse HAS_TELEXT icon in InfoBar to signalize subtitles status
435 ddvd_get_last_spu(m_ddvdconfig, &spu_id, &spu_lang);
440 return resIsPyObject;
446 std::string eServiceDVD::getInfoString(int w)
453 eDebug("unhandled getInfoString(%d)", w);
458 PyObject *eServiceDVD::getInfoObject(int w)
464 ePyObject tuple = PyTuple_New(3);
465 int audio_id,audio_type;
467 ddvd_get_last_audio(m_ddvdconfig, &audio_id, &audio_lang, &audio_type);
468 char audio_string[3]={audio_lang >> 8, audio_lang, 0};
469 PyTuple_SetItem(tuple, 0, PyInt_FromLong(audio_id+1));
470 PyTuple_SetItem(tuple, 1, PyString_FromString(audio_string));
474 PyTuple_SetItem(tuple, 2, PyString_FromString("MPEG"));
477 PyTuple_SetItem(tuple, 2, PyString_FromString("AC3"));
480 PyTuple_SetItem(tuple, 2, PyString_FromString("DTS"));
483 PyTuple_SetItem(tuple, 2, PyString_FromString("LPCM"));
486 PyTuple_SetItem(tuple, 2, PyString_FromString(""));
492 ePyObject tuple = PyTuple_New(2);
495 ddvd_get_last_spu(m_ddvdconfig, &spu_id, &spu_lang);
496 char spu_string[3]={spu_lang >> 8, spu_lang, 0};
499 PyTuple_SetItem(tuple, 0, PyInt_FromLong(0));
500 PyTuple_SetItem(tuple, 1, PyString_FromString(""));
504 PyTuple_SetItem(tuple, 0, PyInt_FromLong(spu_id+1));
505 PyTuple_SetItem(tuple, 1, PyString_FromString(spu_string));
510 eDebug("unhandled getInfoObject(%d)", w);
515 RESULT eServiceDVD::enableSubtitles(eWidget *parent, SWIG_PYOBJECT(ePyObject) /*entry*/)
517 if (m_subtitle_widget)
518 delete m_subtitle_widget;
519 m_subtitle_widget = new eSubtitleWidget(parent);
520 m_subtitle_widget->resize(parent->size());
521 m_subtitle_widget->setPixmap(m_pixmap, eRect(0, 0, 720, 576));
522 m_subtitle_widget->setZPosition(-1);
523 m_subtitle_widget->show();
527 RESULT eServiceDVD::disableSubtitles(eWidget */*parent*/)
529 delete m_subtitle_widget;
530 m_subtitle_widget = 0;
534 PyObject *eServiceDVD::getSubtitleList()
536 eDebug("eServiceDVD::getSubtitleList nyi");
540 PyObject *eServiceDVD::getCachedSubtitle()
542 eDebug("eServiceDVD::getCachedSubtitle nyi");
546 RESULT eServiceDVD::getLength(pts_t &len)
548 // eDebug("eServiceDVD::getLength");
549 struct ddvd_time info;
550 ddvd_get_last_time(m_ddvdconfig, &info);
551 len = info.end_hours * 3600;
552 len += info.end_minutes * 60;
553 len += info.end_seconds;
558 RESULT eServiceDVD::seekTo(pts_t to)
560 eDebug("eServiceDVD::seekTo(%lld)",to);
563 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);
564 ddvd_set_resume_pos(m_ddvdconfig, m_resume_info);
569 RESULT eServiceDVD::seekRelative(int direction, pts_t to)
571 int seconds = to / 90000;
572 seconds *= direction;
573 eDebug("seekRelative %d %d", direction, seconds);
574 ddvd_skip_seconds(m_ddvdconfig, seconds);
578 RESULT eServiceDVD::getPlayPosition(pts_t &pos)
580 struct ddvd_time info;
581 ddvd_get_last_time(m_ddvdconfig, &info);
582 pos = info.pos_hours * 3600;
583 pos += info.pos_minutes * 60;
584 pos += info.pos_seconds;
585 // eDebug("getPlayPosition %lld", pos);
590 RESULT eServiceDVD::seekTitle(int title)
592 eDebug("setTitle %d", title);
593 ddvd_set_title(m_ddvdconfig, title);
597 RESULT eServiceDVD::seekChapter(int chapter)
599 eDebug("setChapter %d", chapter);
601 ddvd_set_chapter(m_ddvdconfig, chapter);
605 RESULT eServiceDVD::setTrickmode(int /*trick*/)
610 RESULT eServiceDVD::isCurrentlySeekable()
612 return m_state == stRunning;
615 RESULT eServiceDVD::keyPressed(int key)
619 case iServiceKeys::keyLeft:
620 ddvd_send_key(m_ddvdconfig, DDVD_KEY_LEFT);
622 case iServiceKeys::keyRight:
623 ddvd_send_key(m_ddvdconfig, DDVD_KEY_RIGHT);
625 case iServiceKeys::keyUp:
626 ddvd_send_key(m_ddvdconfig, DDVD_KEY_UP);
628 case iServiceKeys::keyDown:
629 ddvd_send_key(m_ddvdconfig, DDVD_KEY_DOWN);
631 case iServiceKeys::keyOk:
632 ddvd_send_key(m_ddvdconfig, DDVD_KEY_OK);
634 case iServiceKeys::keyUser:
635 ddvd_send_key(m_ddvdconfig, DDVD_KEY_AUDIO);
637 case iServiceKeys::keyUser+1:
638 ddvd_send_key(m_ddvdconfig, DDVD_KEY_SUBTITLE);
640 case iServiceKeys::keyUser+2:
641 ddvd_send_key(m_ddvdconfig, DDVD_KEY_AUDIOMENU);
643 case iServiceKeys::keyUser+3:
644 ddvd_send_key(m_ddvdconfig, DDVD_KEY_NEXT_CHAPTER);
646 case iServiceKeys::keyUser+4:
647 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PREV_CHAPTER);
649 case iServiceKeys::keyUser+5:
650 ddvd_send_key(m_ddvdconfig, DDVD_KEY_NEXT_TITLE);
652 case iServiceKeys::keyUser+6:
653 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PREV_TITLE);
655 case iServiceKeys::keyUser+7:
656 ddvd_send_key(m_ddvdconfig, DDVD_KEY_MENU);
664 RESULT eServiceDVD::cueSheet(ePtr<iCueSheet> &ptr)
675 PyObject *eServiceDVD::getCutList()
677 ePyObject list = PyList_New(1);
678 ePyObject tuple = PyTuple_New(2);
679 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(m_cue_pts));
680 PyTuple_SetItem(tuple, 1, PyInt_FromLong(3));
681 PyList_SetItem(list, 0, tuple);
685 void eServiceDVD::setCutList(ePyObject /*list*/)
689 void eServiceDVD::setCutListEnable(int /*enable*/)
693 void eServiceDVD::loadCuesheet()
696 if ( m_ddvd_titlestring[0] != '\0' )
697 snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
699 snprintf(filename, 128, "%s/dvd.cuts", m_filename.c_str());
701 eDebug("eServiceDVD::loadCuesheet() filename=%s",filename);
703 FILE *f = fopen(filename, "rb");
707 unsigned long long where;
710 if (!fread(&where, sizeof(where), 1, f))
712 if (!fread(&what, sizeof(what), 1, f))
714 #if BYTE_ORDER == LITTLE_ENDIAN
715 where = bswap_64(where);
719 if (!fread(&m_resume_info, sizeof(struct ddvd_resume), 1, f))
721 if (!fread(&what, sizeof(what), 1, f))
732 eDebug("cutfile not found!");
736 m_event((iPlayableService*)this, evCuesheetChanged);
737 eDebug("eServiceDVD::loadCuesheet() pts=%lld",m_cue_pts);
741 void eServiceDVD::saveCuesheet()
743 eDebug("eServiceDVD::saveCuesheet()");
745 struct ddvd_resume resume_info;
746 ddvd_get_resume_pos(m_ddvdconfig, &resume_info);
748 if (resume_info.title)
750 struct ddvd_time info;
751 ddvd_get_last_time(m_ddvdconfig, &info);
753 pos = info.pos_hours * 3600;
754 pos += info.pos_minutes * 60;
755 pos += info.pos_seconds;
758 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);
762 eDebug("we're in a menu or somewhere else funny. so save cuesheet with pts=0");
767 if ( m_ddvd_titlestring[0] != '\0' )
768 snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
770 snprintf(filename, 128, "%s/dvd.cuts", m_filename.c_str());
772 FILE *f = fopen(filename, "wb");
776 unsigned long long where;
779 #if BYTE_ORDER == BIG_ENDIAN
782 where = bswap_64(m_cue_pts);
785 fwrite(&where, sizeof(where), 1, f);
786 fwrite(&what, sizeof(what), 1, f);
789 fwrite(&resume_info, sizeof(struct ddvd_resume), 1, f);
790 fwrite(&what, sizeof(what), 1, f);
796 eAutoInitPtr<eServiceFactoryDVD> init_eServiceFactoryDVD(eAutoInitNumbers::service+1, "eServiceFactoryDVD");
801 Py_InitModule("servicedvd", NULL);