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()),
95 int aspect = DDVD_16_9;
96 int policy = DDVD_PAN_SCAN;
101 m_sn = eSocketNotifier::create(eApp, ddvd_get_messagepipe_fd(m_ddvdconfig), eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Error|eSocketNotifier::Hungup);
102 eDebug("SERVICEDVD construct!");
104 ddvd_set_dvd_path(m_ddvdconfig, filename);
105 ddvd_set_ac3thru(m_ddvdconfig, 0);
106 ddvd_set_language(m_ddvdconfig, "de");
108 int fd = open("/proc/stb/video/aspect", O_RDONLY);
111 rd = read(fd, tmp, 255);
112 if (rd > 2 && !strncmp(tmp, "4:3", 3))
114 else if (rd > 4 && !strncmp(tmp, "16:10", 5))
119 fd = open("/proc/stb/video/policy", O_RDONLY);
122 rd = read(fd, tmp, 255);
123 if (rd > 6 && !strncmp(tmp, "bestfit", 7))
124 policy = DDVD_JUSTSCALE;
125 else if (rd > 8 && !strncmp(tmp, "letterbox", 9))
126 policy = DDVD_LETTERBOX;
130 ddvd_set_video(m_ddvdconfig, aspect, policy, DDVD_PAL /*unused*/);
132 CONNECT(m_sn->activated, eServiceDVD::gotMessage);
133 CONNECT(m_pump.recv_msg, eServiceDVD::gotThreadMessage);
134 strcpy(m_ddvd_titlestring,"");
139 void eServiceDVD::gotThreadMessage(const int &msg)
143 case 1: // thread stopped
145 m_event(this, evStopped);
150 void eServiceDVD::gotMessage(int /*what*/)
152 switch(ddvd_get_next_message(m_ddvdconfig,1))
154 case DDVD_COLORTABLE_UPDATE:
157 struct ddvd_color ctmp[4];
158 ddvd_get_last_colortable(ddvdconfig, ctmp);
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;
168 if(ioctl(fb, FBIOPUTCMAP, &colormap) == -1)
170 printf("Framebuffer: <FBIOPUTCMAP failed>\n");
174 eDebug("no support for 8bpp framebuffer in dvdplayer yet!");
177 case DDVD_SCREEN_UPDATE:
178 eDebug("DVD_SCREEN_UPDATE!");
179 if (m_subtitle_widget) {
181 ddvd_get_last_blit_area(m_ddvdconfig, &x1, &x2, &y1, &y2);
182 m_subtitle_widget->setPixmap(m_pixmap, eRect(x1, y1, (x2-x1)+1, (y2-y1)+1));
185 case DDVD_SHOWOSD_STATE_PLAY:
187 eDebug("DVD_SHOWOSD_STATE_PLAY!");
189 m_event(this, evUser+1);
192 case DDVD_SHOWOSD_STATE_PAUSE:
194 eDebug("DVD_SHOWOSD_STATE_PAUSE!");
195 m_event(this, evUser+2);
198 case DDVD_SHOWOSD_STATE_FFWD:
200 eDebug("DVD_SHOWOSD_STATE_FFWD!");
201 m_event(this, evUser+3);
204 case DDVD_SHOWOSD_STATE_FBWD:
206 eDebug("DVD_SHOWOSD_STATE_FBWD!");
207 m_event(this, evUser+4);
210 case DDVD_SHOWOSD_STRING:
212 eDebug("DVD_SHOWOSD_STRING!");
213 m_event(this, evUser+5);
216 case DDVD_SHOWOSD_AUDIO:
218 eDebug("DVD_SHOWOSD_STRING!");
219 m_event(this, evUser+6);
222 case DDVD_SHOWOSD_SUBTITLE:
224 eDebug("DVD_SHOWOSD_SUBTITLE!");
225 m_event((iPlayableService*)this, evUpdatedInfo);
226 m_event(this, evUser+7);
229 case DDVD_EOF_REACHED:
230 eDebug("DVD_EOF_REACHED!");
231 m_event(this, evEOF);
233 case DDVD_SOF_REACHED:
234 eDebug("DVD_SOF_REACHED!");
235 m_event(this, evSOF);
237 case DDVD_SHOWOSD_ANGLE:
240 ddvd_get_angle_info(m_ddvdconfig, ¤t, &num);
241 eDebug("DVD_ANGLE_INFO: %d / %d", current, num);
242 m_event(this, evUser+13);
245 case DDVD_SHOWOSD_TIME:
247 static struct ddvd_time last_info;
248 struct ddvd_time info;
249 // eDebug("DVD_SHOWOSD_TIME!");
250 ddvd_get_last_time(m_ddvdconfig, &info);
251 if ( info.pos_chapter != last_info.pos_chapter )
252 m_event(this, evUser+8); // chapterUpdated
253 if ( info.pos_title != last_info.pos_title )
254 m_event(this, evUser+9); // titleUpdated
255 memcpy(&last_info, &info, sizeof(struct ddvd_time));
258 case DDVD_SHOWOSD_TITLESTRING:
260 ddvd_get_title_string(m_ddvdconfig, m_ddvd_titlestring);
261 eDebug("DDVD_SHOWOSD_TITLESTRING: %s",m_ddvd_titlestring);
265 m_event(this, evStart);
268 case DDVD_MENU_OPENED:
269 eDebug("DVD_MENU_OPENED!");
271 m_event(this, evSeekableStatusChanged);
272 m_event(this, evUser+11);
274 case DDVD_MENU_CLOSED:
275 eDebug("DVD_MENU_CLOSED!");
277 m_event(this, evSeekableStatusChanged);
278 m_event(this, evUser+12);
285 eServiceDVD::~eServiceDVD()
287 eDebug("SERVICEDVD destruct!");
290 ddvd_close(m_ddvdconfig);
294 RESULT eServiceDVD::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
296 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
300 RESULT eServiceDVD::start()
302 assert(m_state == stIdle);
304 eDebug("eServiceDVD starting");
305 // m_event(this, evStart);
309 RESULT eServiceDVD::stop()
311 assert(m_state != stIdle);
312 if (m_state == stStopped)
314 eDebug("DVD: stop %s", m_filename.c_str());
316 ddvd_send_key(m_ddvdconfig, DDVD_KEY_EXIT);
321 RESULT eServiceDVD::setTarget(int /*target*/)
326 RESULT eServiceDVD::pause(ePtr<iPauseableService> &ptr)
332 RESULT eServiceDVD::seek(ePtr<iSeekableService> &ptr)
338 RESULT eServiceDVD::subtitle(ePtr<iSubtitleOutput> &ptr)
344 RESULT eServiceDVD::keys(ePtr<iServiceKeys> &ptr)
351 RESULT eServiceDVD::setSlowMotion(int /*ratio*/)
356 RESULT eServiceDVD::setFastForward(int trick)
358 eDebug("setTrickmode(%d)", trick);
359 while (m_current_trick > trick && m_current_trick != -64)
361 ddvd_send_key(m_ddvdconfig, DDVD_KEY_FBWD);
362 if (m_current_trick == 0)
363 m_current_trick = -2;
364 else if (m_current_trick > 0)
366 m_current_trick /= 2;
367 if (abs(m_current_trick) == 1)
371 m_current_trick *= 2;
373 while (m_current_trick < trick && m_current_trick != 64)
375 ddvd_send_key(m_ddvdconfig, DDVD_KEY_FFWD);
376 if (m_current_trick == 0)
378 else if (m_current_trick < 0)
380 m_current_trick /= 2;
381 if (abs(m_current_trick) == 1)
385 m_current_trick *= 2;
390 RESULT eServiceDVD::pause()
392 eDebug("set pause!\n");
393 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PAUSE);
397 RESULT eServiceDVD::unpause()
399 eDebug("set unpause!\n");
400 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PLAY);
404 void eServiceDVD::thread()
406 eDebug("eServiceDVD dvd thread started");
408 ddvd_run(m_ddvdconfig);
411 void eServiceDVD::thread_finished()
413 eDebug("eServiceDVD dvd thread finished");
414 m_pump.send(1); // inform main thread
417 RESULT eServiceDVD::info(ePtr<iServiceInformation>&i)
423 RESULT eServiceDVD::getName(std::string &name)
425 if ( m_ddvd_titlestring[0] != '\0' )
426 name = m_ddvd_titlestring;
432 int eServiceDVD::getInfo(int w)
436 case sCurrentChapter:
438 struct ddvd_time info;
439 ddvd_get_last_time(m_ddvdconfig, &info);
440 return info.pos_chapter;
444 struct ddvd_time info;
445 ddvd_get_last_time(m_ddvdconfig, &info);
446 return info.end_chapter;
450 struct ddvd_time info;
451 ddvd_get_last_time(m_ddvdconfig, &info);
452 return info.pos_title;
456 struct ddvd_time info;
457 ddvd_get_last_time(m_ddvdconfig, &info);
458 return info.end_title;
460 case sTXTPID: // we abuse HAS_TELEXT icon in InfoBar to signalize subtitles status
464 ddvd_get_last_spu(m_ddvdconfig, &spu_id, &spu_lang);
470 return resIsPyObject;
476 std::string eServiceDVD::getInfoString(int w)
483 eDebug("unhandled getInfoString(%d)", w);
488 PyObject *eServiceDVD::getInfoObject(int w)
494 ePyObject tuple = PyTuple_New(3);
495 int audio_id,audio_type;
497 ddvd_get_last_audio(m_ddvdconfig, &audio_id, &audio_lang, &audio_type);
498 char audio_string[3]={audio_lang >> 8, audio_lang, 0};
499 PyTuple_SetItem(tuple, 0, PyInt_FromLong(audio_id+1));
500 PyTuple_SetItem(tuple, 1, PyString_FromString(audio_string));
504 PyTuple_SetItem(tuple, 2, PyString_FromString("MPEG"));
507 PyTuple_SetItem(tuple, 2, PyString_FromString("AC3"));
510 PyTuple_SetItem(tuple, 2, PyString_FromString("DTS"));
513 PyTuple_SetItem(tuple, 2, PyString_FromString("LPCM"));
516 PyTuple_SetItem(tuple, 2, PyString_FromString(""));
522 ePyObject tuple = PyTuple_New(2);
525 ddvd_get_last_spu(m_ddvdconfig, &spu_id, &spu_lang);
526 char spu_string[3]={spu_lang >> 8, spu_lang, 0};
529 PyTuple_SetItem(tuple, 0, PyInt_FromLong(0));
530 PyTuple_SetItem(tuple, 1, PyString_FromString(""));
534 PyTuple_SetItem(tuple, 0, PyInt_FromLong(spu_id+1));
535 PyTuple_SetItem(tuple, 1, PyString_FromString(spu_string));
541 ePyObject tuple = PyTuple_New(2);
543 ddvd_get_angle_info(m_ddvdconfig, ¤t, &num);
544 PyTuple_SetItem(tuple, 0, PyInt_FromLong(current));
545 PyTuple_SetItem(tuple, 1, PyInt_FromLong(num));
550 eDebug("unhandled getInfoObject(%d)", w);
555 RESULT eServiceDVD::enableSubtitles(eWidget *parent, SWIG_PYOBJECT(ePyObject) /*entry*/)
557 delete m_subtitle_widget;
559 m_subtitle_widget = new eSubtitleWidget(parent);
560 m_subtitle_widget->resize(parent->size());
562 eSize size = parent->size();
566 m_pixmap = new gPixmap(size, 32);
567 ddvd_set_lfb(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4);
568 run(); // start the thread
571 m_subtitle_widget->setZPosition(-1);
572 m_subtitle_widget->show();
577 RESULT eServiceDVD::disableSubtitles(eWidget */*parent*/)
579 delete m_subtitle_widget;
580 m_subtitle_widget = 0;
584 PyObject *eServiceDVD::getSubtitleList()
586 eDebug("eServiceDVD::getSubtitleList nyi");
590 PyObject *eServiceDVD::getCachedSubtitle()
592 eDebug("eServiceDVD::getCachedSubtitle nyi");
596 RESULT eServiceDVD::getLength(pts_t &len)
598 // eDebug("eServiceDVD::getLength");
599 struct ddvd_time info;
600 ddvd_get_last_time(m_ddvdconfig, &info);
601 len = info.end_hours * 3600;
602 len += info.end_minutes * 60;
603 len += info.end_seconds;
608 RESULT eServiceDVD::seekTo(pts_t to)
610 eDebug("eServiceDVD::seekTo(%lld)",to);
613 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);
614 ddvd_set_resume_pos(m_ddvdconfig, m_resume_info);
619 RESULT eServiceDVD::seekRelative(int direction, pts_t to)
621 int seconds = to / 90000;
622 seconds *= direction;
623 eDebug("seekRelative %d %d", direction, seconds);
624 ddvd_skip_seconds(m_ddvdconfig, seconds);
628 RESULT eServiceDVD::getPlayPosition(pts_t &pos)
630 struct ddvd_time info;
631 ddvd_get_last_time(m_ddvdconfig, &info);
632 pos = info.pos_hours * 3600;
633 pos += info.pos_minutes * 60;
634 pos += info.pos_seconds;
635 // eDebug("getPlayPosition %lld", pos);
640 RESULT eServiceDVD::seekTitle(int title)
642 eDebug("setTitle %d", title);
643 ddvd_set_title(m_ddvdconfig, title);
647 RESULT eServiceDVD::seekChapter(int chapter)
649 eDebug("setChapter %d", chapter);
651 ddvd_set_chapter(m_ddvdconfig, chapter);
655 RESULT eServiceDVD::setTrickmode(int /*trick*/)
660 RESULT eServiceDVD::isCurrentlySeekable()
662 return m_state == stRunning;
665 RESULT eServiceDVD::keyPressed(int key)
669 case iServiceKeys::keyLeft:
670 ddvd_send_key(m_ddvdconfig, DDVD_KEY_LEFT);
672 case iServiceKeys::keyRight:
673 ddvd_send_key(m_ddvdconfig, DDVD_KEY_RIGHT);
675 case iServiceKeys::keyUp:
676 ddvd_send_key(m_ddvdconfig, DDVD_KEY_UP);
678 case iServiceKeys::keyDown:
679 ddvd_send_key(m_ddvdconfig, DDVD_KEY_DOWN);
681 case iServiceKeys::keyOk:
682 ddvd_send_key(m_ddvdconfig, DDVD_KEY_OK);
684 case iServiceKeys::keyUser:
685 ddvd_send_key(m_ddvdconfig, DDVD_KEY_AUDIO);
687 case iServiceKeys::keyUser+1:
688 ddvd_send_key(m_ddvdconfig, DDVD_KEY_SUBTITLE);
690 case iServiceKeys::keyUser+2:
691 ddvd_send_key(m_ddvdconfig, DDVD_KEY_AUDIOMENU);
693 case iServiceKeys::keyUser+3:
694 ddvd_send_key(m_ddvdconfig, DDVD_KEY_NEXT_CHAPTER);
696 case iServiceKeys::keyUser+4:
697 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PREV_CHAPTER);
699 case iServiceKeys::keyUser+5:
700 ddvd_send_key(m_ddvdconfig, DDVD_KEY_NEXT_TITLE);
702 case iServiceKeys::keyUser+6:
703 ddvd_send_key(m_ddvdconfig, DDVD_KEY_PREV_TITLE);
705 case iServiceKeys::keyUser+7:
706 ddvd_send_key(m_ddvdconfig, DDVD_KEY_MENU);
708 case iServiceKeys::keyUser+8:
709 ddvd_send_key(m_ddvdconfig, DDVD_KEY_ANGLE);
717 RESULT eServiceDVD::cueSheet(ePtr<iCueSheet> &ptr)
728 PyObject *eServiceDVD::getCutList()
730 ePyObject list = PyList_New(1);
731 ePyObject tuple = PyTuple_New(2);
732 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(m_cue_pts));
733 PyTuple_SetItem(tuple, 1, PyInt_FromLong(3));
734 PyList_SetItem(list, 0, tuple);
738 void eServiceDVD::setCutList(ePyObject /*list*/)
742 void eServiceDVD::setCutListEnable(int /*enable*/)
746 void eServiceDVD::loadCuesheet()
749 if ( m_ddvd_titlestring[0] != '\0' )
750 snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
752 snprintf(filename, 128, "%s/dvd.cuts", m_filename.c_str());
754 eDebug("eServiceDVD::loadCuesheet() filename=%s",filename);
756 FILE *f = fopen(filename, "rb");
760 unsigned long long where;
763 if (!fread(&where, sizeof(where), 1, f))
765 if (!fread(&what, sizeof(what), 1, f))
767 #if BYTE_ORDER == LITTLE_ENDIAN
768 where = bswap_64(where);
772 if (!fread(&m_resume_info, sizeof(struct ddvd_resume), 1, f))
774 if (!fread(&what, sizeof(what), 1, f))
785 eDebug("cutfile not found!");
789 m_event((iPlayableService*)this, evCuesheetChanged);
790 eDebug("eServiceDVD::loadCuesheet() pts=%lld",m_cue_pts);
794 void eServiceDVD::saveCuesheet()
796 eDebug("eServiceDVD::saveCuesheet()");
798 struct ddvd_resume resume_info;
799 ddvd_get_resume_pos(m_ddvdconfig, &resume_info);
801 if (resume_info.title)
803 struct ddvd_time info;
804 ddvd_get_last_time(m_ddvdconfig, &info);
806 pos = info.pos_hours * 3600;
807 pos += info.pos_minutes * 60;
808 pos += info.pos_seconds;
811 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);
815 eDebug("we're in a menu or somewhere else funny. so save cuesheet with pts=0");
820 if ( m_ddvd_titlestring[0] != '\0' )
821 snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
823 snprintf(filename, 128, "%s/dvd.cuts", m_filename.c_str());
825 FILE *f = fopen(filename, "wb");
829 unsigned long long where;
832 #if BYTE_ORDER == BIG_ENDIAN
835 where = bswap_64(m_cue_pts);
838 fwrite(&where, sizeof(where), 1, f);
839 fwrite(&what, sizeof(what), 1, f);
842 fwrite(&resume_info, sizeof(struct ddvd_resume), 1, f);
843 fwrite(&what, sizeof(what), 1, f);
849 eAutoInitPtr<eServiceFactoryDVD> init_eServiceFactoryDVD(eAutoInitNumbers::service+1, "eServiceFactoryDVD");
854 Py_InitModule("servicedvd", NULL);