2 #include "servicedvd.h"
3 #include <lib/base/eerror.h>
4 #include <lib/base/object.h>
5 #include <lib/base/ebase.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>
15 #include <netinet/in.h>
17 #error no byte order defined!
22 #include <dreamdvd/ddvdlib.h>
27 eServiceFactoryDVD::eServiceFactoryDVD()
29 ePtr<eServiceCenter> sc;
31 eServiceCenter::getPrivInstance(sc);
34 std::list<std::string> extensions;
35 extensions.push_back("iso");
36 sc->addServiceFactory(eServiceFactoryDVD::id, this, extensions);
40 eServiceFactoryDVD::~eServiceFactoryDVD()
42 ePtr<eServiceCenter> sc;
44 eServiceCenter::getPrivInstance(sc);
46 sc->removeServiceFactory(eServiceFactoryDVD::id);
49 DEFINE_REF(eServiceFactoryDVD)
52 RESULT eServiceFactoryDVD::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
55 ptr = new eServiceDVD(ref.path.c_str());
59 RESULT eServiceFactoryDVD::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
65 RESULT eServiceFactoryDVD::list(const eServiceReference &, ePtr<iListableService> &ptr)
72 RESULT eServiceFactoryDVD::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
78 RESULT eServiceFactoryDVD::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
86 DEFINE_REF(eServiceDVD);
88 eServiceDVD::eServiceDVD(const char *filename):
90 m_ddvdconfig(ddvd_create()),
91 m_pixmap(new gPixmap(eSize(720, 576), 32)),
95 m_sn(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");
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,"");
115 void eServiceDVD::gotThreadMessage(const int &msg)
119 case 1: // thread stopped
121 m_event(this, evStopped);
126 void eServiceDVD::gotMessage(int what)
128 switch(ddvd_get_next_message(m_ddvdconfig,1))
130 case DDVD_COLORTABLE_UPDATE:
133 struct ddvd_color ctmp[4];
134 ddvd_get_last_colortable(ddvdconfig, ctmp);
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;
144 if(ioctl(fb, FBIOPUTCMAP, &colormap) == -1)
146 printf("Framebuffer: <FBIOPUTCMAP failed>\n");
150 eDebug("no support for 8bpp framebuffer in dvdplayer yet!");
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));
158 case DDVD_SHOWOSD_STATE_PLAY:
160 eDebug("DVD_SHOWOSD_STATE_PLAY!");
162 m_event(this, evUser+1);
165 case DDVD_SHOWOSD_STATE_PAUSE:
167 eDebug("DVD_SHOWOSD_STATE_PAUSE!");
168 m_event(this, evUser+2);
171 case DDVD_SHOWOSD_STATE_FFWD:
173 eDebug("DVD_SHOWOSD_STATE_FFWD!");
174 m_event(this, evUser+3);
177 case DDVD_SHOWOSD_STATE_FBWD:
179 eDebug("DVD_SHOWOSD_STATE_FBWD!");
180 m_event(this, evUser+4);
183 case DDVD_SHOWOSD_STRING:
185 eDebug("DVD_SHOWOSD_STRING!");
186 m_event(this, evUser+5);
189 case DDVD_SHOWOSD_AUDIO:
191 eDebug("DVD_SHOWOSD_STRING!");
192 m_event(this, evUser+6);
195 case DDVD_SHOWOSD_SUBTITLE:
197 eDebug("DVD_SHOWOSD_SUBTITLE!");
198 m_event((iPlayableService*)this, evUpdatedInfo);
199 m_event(this, evUser+7);
202 case DDVD_EOF_REACHED:
203 eDebug("DVD_EOF_REACHED!");
204 m_event(this, evEOF);
207 case DDVD_SOF_REACHED:
208 eDebug("DVD_SOF_REACHED!");
209 m_event(this, evSOF);
211 case DDVD_SHOWOSD_TIME:
213 static struct ddvd_time last_info;
214 struct ddvd_time info;
215 ddvd_get_last_time(m_ddvdconfig, &info);
218 ddvd_get_last_spu(m_ddvdconfig, &spu_id, &spu_lang);
219 if ( info.pos_chapter != last_info.pos_chapter )
221 eDebug("DVD_SHOWOSD_TIME!");
222 m_event(this, evUser+8); // chapterUpdated
224 if ( info.pos_title != last_info.pos_title )
226 m_event(this, evUser+9); // titleUpdated
228 if ( info.pos_title == m_seekTitle && m_doSeekTo )
230 seekRelative( +1, m_doSeekTo );
234 ddvd_get_last_time(m_ddvdconfig, &last_info);
237 case DDVD_SHOWOSD_TITLESTRING:
239 ddvd_get_title_string(m_ddvdconfig, m_ddvd_titlestring);
240 eDebug("DDVD_SHOWOSD_TITLESTRING: %s",m_ddvd_titlestring);
242 m_event(this, evStart);
243 // m_event((iPlayableService*)this, evUpdatedEventInfo);
244 // m_event(this, evUser+10);
247 case DDVD_MENU_OPENED:
248 eDebug("DVD_MENU_OPENED!");
249 m_event(this, evUser+11);
251 case DDVD_MENU_CLOSED:
252 eDebug("DVD_MENU_CLOSED!");
253 m_event(this, evUser+12);
260 eServiceDVD::~eServiceDVD()
262 eDebug("SERVICEDVD destruct!");
264 ddvd_close(m_ddvdconfig);
267 RESULT eServiceDVD::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
269 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
273 RESULT eServiceDVD::start()
275 assert(m_state == stIdle);
277 eDebug("eServiceDVD starting");
279 // m_event(this, evStart);
283 RESULT eServiceDVD::stop()
285 assert(m_state != stIdle);
286 if (m_state == stStopped)
288 eDebug("DVD: stop %s", m_filename.c_str());
290 ddvd_send_key(m_ddvdconfig, DDVD_KEY_EXIT);
292 struct ddvd_time info;
293 ddvd_get_last_time(m_ddvdconfig, &info);
294 if ( info.pos_chapter < info.end_chapter )
297 pos = info.pos_hours * 3600;
298 pos += info.pos_minutes * 60;
299 pos += info.pos_seconds;
303 else // last chapter - usually credits, don't save cue
310 RESULT eServiceDVD::setTarget(int target)
315 RESULT eServiceDVD::pause(ePtr<iPauseableService> &ptr)
321 RESULT eServiceDVD::seek(ePtr<iSeekableService> &ptr)
327 RESULT eServiceDVD::subtitle(ePtr<iSubtitleOutput> &ptr)
333 RESULT eServiceDVD::keys(ePtr<iServiceKeys> &ptr)
340 RESULT eServiceDVD::setSlowMotion(int ratio)
345 RESULT eServiceDVD::setFastForward(int trick)
347 eDebug("setTrickmode(%d)", trick);
348 while (m_current_trick > trick && m_current_trick != -64)
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)
355 m_current_trick /= 2;
356 if (abs(m_current_trick) == 1)
360 m_current_trick *= 2;
362 while (m_current_trick < trick && m_current_trick != 64)
364 ddvd_send_key(m_ddvdconfig, DDVD_KEY_FFWD);
365 if (m_current_trick == 0)
367 else if (m_current_trick < 0)
369 m_current_trick /= 2;
370 if (abs(m_current_trick) == 1)
374 m_current_trick *= 2;
379 RESULT eServiceDVD::pause()
381 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PAUSE);
385 RESULT eServiceDVD::unpause()
387 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PLAY);
391 void eServiceDVD::thread()
393 eDebug("eServiceDVD dvd thread started");
395 ddvd_run(m_ddvdconfig);
398 void eServiceDVD::thread_finished()
400 eDebug("eServiceDVD dvd thread finished");
401 m_pump.send(1); // inform main thread
404 RESULT eServiceDVD::info(ePtr<iServiceInformation>&i)
410 RESULT eServiceDVD::getName(std::string &name)
412 if ( m_ddvd_titlestring[0] != '\0' )
413 name = m_ddvd_titlestring;
419 int eServiceDVD::getInfo(int w)
426 return resIsPyObject; // then getInfoObject should be called
430 return resIsString; // then getInfoString should be called
433 struct ddvd_time info;
434 ddvd_get_last_time(m_ddvdconfig, &info);
435 return info.pos_chapter;
439 struct ddvd_time info;
440 ddvd_get_last_time(m_ddvdconfig, &info);
441 return info.end_chapter;
446 struct ddvd_time info;
447 ddvd_get_last_time(m_ddvdconfig, &info);
448 return info.pos_title;
452 struct ddvd_time info;
453 ddvd_get_last_time(m_ddvdconfig, &info);
454 return info.end_title;
457 case sTXTPID: // we abuse HAS_TELEXT icon in InfoBar to signalize subtitles status
461 ddvd_get_last_spu(m_ddvdconfig, &spu_id, &spu_lang);
469 std::string eServiceDVD::getInfoString(int w)
476 ddvd_get_last_spu(m_ddvdconfig, &spu_id, &spu_lang);
477 unsigned char spu_string[3]={spu_lang >> 8, spu_lang, 0};
482 sprintf(osd,"%d - %s",spu_id+1,spu_string);
488 int audio_id,audio_type;
490 ddvd_get_last_audio(m_ddvdconfig, &audio_id, &audio_lang, &audio_type);
491 char audio_string[3]={audio_lang >> 8, audio_lang, 0};
496 sprintf(audio_form,"MPEG");
499 sprintf(audio_form,"AC3");
502 sprintf(audio_form,"DTS");
505 sprintf(audio_form,"LPCM");
508 sprintf(audio_form,"-");
511 sprintf(osd,"%d - %s (%s)",audio_id+1,audio_string,audio_form);
515 eDebug("unhandled getInfoString(%d)", w);
520 PyObject *eServiceDVD::getInfoObject(int w)
525 eDebug("unhandled getInfoObject(%d)", w);
530 RESULT eServiceDVD::enableSubtitles(eWidget *parent, SWIG_PYOBJECT(ePyObject) entry)
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();
542 RESULT eServiceDVD::disableSubtitles(eWidget *parent)
544 delete m_subtitle_widget;
545 m_subtitle_widget = 0;
549 PyObject *eServiceDVD::getSubtitleList()
551 eDebug("eServiceDVD::getSubtitleList nyi");
555 PyObject *eServiceDVD::getCachedSubtitle()
557 eDebug("eServiceDVD::getCachedSubtitle nyi");
561 RESULT eServiceDVD::getLength(pts_t &len)
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;
573 // RESULT eServiceDVD::seekTo(pts_t to)
575 // struct ddvd_time info;
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);
587 RESULT eServiceDVD::seekTo(pts_t to)
590 eDebug("seekTo %lld", to);
591 ddvd_set_title(m_ddvdconfig, m_seekTitle);
596 RESULT eServiceDVD::seekRelative(int direction, pts_t to)
598 int seconds = to / 90000;
599 seconds *= direction;
600 eDebug("seekRelative %d %d", direction, seconds);
601 ddvd_skip_seconds(m_ddvdconfig, seconds);
605 RESULT eServiceDVD::getPlayPosition(pts_t &pos)
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);
617 RESULT eServiceDVD::seekChapter(int chapter)
619 eDebug("setChapter %d", chapter);
621 ddvd_set_chapter(m_ddvdconfig, chapter);
625 RESULT eServiceDVD::setTrickmode(int trick)
630 RESULT eServiceDVD::isCurrentlySeekable()
635 RESULT eServiceDVD::keyPressed(int key)
639 case iServiceKeys::keyLeft:
640 ddvd_send_key(m_ddvdconfig, DDVD_KEY_LEFT);
642 case iServiceKeys::keyRight:
643 ddvd_send_key(m_ddvdconfig, DDVD_KEY_RIGHT);
645 case iServiceKeys::keyUp:
646 ddvd_send_key(m_ddvdconfig, DDVD_KEY_UP);
648 case iServiceKeys::keyDown:
649 ddvd_send_key(m_ddvdconfig, DDVD_KEY_DOWN);
651 case iServiceKeys::keyOk:
652 ddvd_send_key(m_ddvdconfig, DDVD_KEY_OK);
654 case iServiceKeys::keyUser:
655 ddvd_send_key(m_ddvdconfig, DDVD_KEY_AUDIO);
657 case iServiceKeys::keyUser+1:
658 ddvd_send_key(m_ddvdconfig, DDVD_KEY_SUBTITLE);
660 case iServiceKeys::keyUser+2:
661 ddvd_send_key(m_ddvdconfig, DDVD_KEY_AUDIOMENU);
663 case iServiceKeys::keyUser+3:
664 ddvd_send_key(m_ddvdconfig, DDVD_KEY_NEXT_CHAPTER);
666 case iServiceKeys::keyUser+4:
667 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PREV_CHAPTER);
669 case iServiceKeys::keyUser+5:
670 ddvd_send_key(m_ddvdconfig, DDVD_KEY_NEXT_TITLE);
672 case iServiceKeys::keyUser+6:
673 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PREV_TITLE);
675 case iServiceKeys::keyUser+7:
676 ddvd_send_key(m_ddvdconfig, DDVD_KEY_MENU);
685 RESULT eServiceDVD::cueSheet(ePtr<iCueSheet> &ptr)
696 PyObject *eServiceDVD::getCutList()
698 ePyObject list = PyList_New(0);
700 // for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
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);
711 // eDebug("eServiceDVD::getCutList() pts=%lld",m_cue_pts);
716 void eServiceDVD::setCutList(ePyObject list)
718 eDebug("eServiceDVD::setCutList()");
720 if (!PyList_Check(list))
722 int size = PyList_Size(list);
725 // m_cue_entries.clear();
727 for (i=0; i<size; ++i)
729 ePyObject tuple = PyList_GET_ITEM(list, i);
730 if (!PyTuple_Check(tuple))
732 eDebug("non-tuple in cutlist");
735 if (PyTuple_Size(tuple) != 2)
737 eDebug("cutlist entries need to be a 2-tuple");
740 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
741 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
743 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
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);
752 m_cuesheet_changed = 1;
754 // cutlistToCuesheet();
755 m_event((iPlayableService*)this, evCuesheetChanged);
758 void eServiceDVD::setCutListEnable(int enable)
760 eDebug("eServiceDVD::setCutListEnable()");
761 m_cutlist_enabled = enable;
762 // cutlistToCuesheet();
766 void eServiceDVD::loadCuesheet()
768 eDebug("eServiceDVD::loadCuesheet()");
770 if ( m_ddvd_titlestring[0] != '\0' )
771 snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
773 eDebug("eServiceDVD::loadCuesheet() filename=%s",filename);
774 // m_cue_entries.clear();
776 FILE *f = fopen(filename, "rb");
780 eDebug("loading cuts..");
783 unsigned long long where;
786 if (!fread(&where, sizeof(where), 1, f))
788 if (!fread(&what, sizeof(what), 1, f))
791 #if BYTE_ORDER == LITTLE_ENDIAN
792 where = bswap_64(where);
801 // m_cue_entries.insert(cueEntry(where, what));
804 // eDebug("%d entries", m_cue_entries.size());
806 eDebug("cutfile not found!");
808 m_cuesheet_changed = 0;
809 // cutlistToCuesheet();
810 eDebug("eServiceDVD::loadCuesheet() pts=%lld",m_cue_pts);
813 m_event((iPlayableService*)this, evCuesheetChanged);
816 void eServiceDVD::saveCuesheet()
818 eDebug("eServiceDVD::saveCuesheet() pts=%lld",m_cue_pts);
820 if ( m_ddvd_titlestring[0] != '\0' )
821 snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
823 FILE *f = fopen(filename, "wb");
827 unsigned long long where;
830 // for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
832 #if BYTE_ORDER == BIG_ENDIAN
836 // where = bswap_64(i->where);
837 where = bswap_64(m_cue_pts);
839 // what = htonl(i->what);
841 fwrite(&where, sizeof(where), 1, f);
842 fwrite(&what, sizeof(what), 1, f);
848 m_cuesheet_changed = 0;
852 eAutoInitPtr<eServiceFactoryDVD> init_eServiceFactoryDVD(eAutoInitNumbers::service+1, "eServiceFactoryDVD");
857 Py_InitModule("servicedvd", NULL);