lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h/cpp: add support for autores...
[enigma2.git] / lib / python / Plugins / Extensions / DVDPlayer / src / servicedvd.cpp
index a756e751736e67f613cc2e2e1d012b0a5b4afd43..2ba53927f6b62a89afd4cdf540aeb6bcea4db6b3 100644 (file)
@@ -51,7 +51,7 @@ DEFINE_REF(eServiceFactoryDVD)
 RESULT eServiceFactoryDVD::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
 {
                // check resources...
-       ptr = new eServiceDVD(ref.path.c_str());
+       ptr = new eServiceDVD(ref);
        return 0;
 }
 
@@ -84,37 +84,72 @@ RESULT eServiceFactoryDVD::offlineOperations(const eServiceReference &, ePtr<iSe
 
 DEFINE_REF(eServiceDVD);
 
-eServiceDVD::eServiceDVD(const char *filename):
-       m_filename(filename),
-       m_ddvdconfig(ddvd_create()),
-       m_pixmap(new gPixmap(eSize(720, 576), 32)),
-       m_subtitle_widget(0),
-       m_state(stIdle),
-       m_current_trick(0),
-       m_sn(eApp, ddvd_get_messagepipe_fd(m_ddvdconfig), eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Error|eSocketNotifier::Hungup),
-       m_pump(eApp, 1)
-{
-       std::string aspect;
+eServiceDVD::eServiceDVD(eServiceReference ref):
+       m_ref(ref), m_ddvdconfig(ddvd_create()), m_subtitle_widget(0), m_state(stIdle),
+       m_current_trick(0), m_pump(eApp, 1), m_width(-1), m_height(-1),
+       m_aspect(-1), m_framerate(-1), m_progressive(-1)
+{
+       int aspect = DDVD_16_9;
+       int policy = DDVD_PAN_SCAN;
+       int policy2 = DDVD_PAN_SCAN;
+
+       char tmp[255];
+       ssize_t rd;
+
+       m_sn = eSocketNotifier::create(eApp, ddvd_get_messagepipe_fd(m_ddvdconfig), eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Error|eSocketNotifier::Hungup);
        eDebug("SERVICEDVD construct!");
        // create handle
-       ddvd_set_dvd_path(m_ddvdconfig, filename);
+       ddvd_set_dvd_path(m_ddvdconfig, ref.path.c_str());
        ddvd_set_ac3thru(m_ddvdconfig, 0);
-       ddvd_set_language(m_ddvdconfig, "de");
-
-       if (ePythonConfigQuery::getConfigValue("config.av.aspect", aspect) != 0)
-               aspect = "16_9";
-       if (aspect == "4_3_letterbox")
-               ddvd_set_video(m_ddvdconfig, DDVD_4_3_LETTERBOX, DDVD_PAL);
-       else if (aspect == "4_3_panscan")
-               ddvd_set_video(m_ddvdconfig, DDVD_4_3_PAN_SCAN, DDVD_PAL);
-       else
-               ddvd_set_video(m_ddvdconfig, DDVD_16_9, DDVD_PAL);
 
-       ddvd_set_lfb(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, 720, 576, 4, 720*4);
-       CONNECT(m_sn.activated, eServiceDVD::gotMessage);
+       std::string ddvd_language;
+       if (!ePythonConfigQuery::getConfigValue("config.osd.language", ddvd_language))
+               ddvd_set_language(m_ddvdconfig, (ddvd_language.substr(0,2)).c_str());
+
+       int fd = open("/proc/stb/video/aspect", O_RDONLY);
+       if (fd > -1)
+       {
+               rd = read(fd, tmp, 255);
+               if (rd > 2 && !strncmp(tmp, "4:3", 3))
+                       aspect = DDVD_4_3;
+               else if (rd > 4 && !strncmp(tmp, "16:10", 5))
+                       aspect = DDVD_16_10;
+               close(fd);
+       }
+
+       fd = open("/proc/stb/video/policy", O_RDONLY);
+       if (fd > -1)
+       {
+               rd = read(fd, tmp, 255);
+               if (rd > 6 && !strncmp(tmp, "bestfit", 7))
+                       policy = DDVD_JUSTSCALE;
+               else if (rd > 8 && !strncmp(tmp, "letterbox", 9))
+                       policy = DDVD_LETTERBOX;
+               close(fd);
+       }
+
+#ifdef DDVD_SUPPORTS_16_10_SCALING
+       fd = open("/proc/stb/video/policy2", O_RDONLY);
+       if (fd > -1)
+       {
+               rd = read(fd, tmp, 255);
+               if (rd > 6 && !strncmp(tmp, "bestfit", 7))
+                       policy2 = DDVD_JUSTSCALE;
+               else if (rd > 8 && !strncmp(tmp, "letterbox", 9))
+                       policy2 = DDVD_LETTERBOX;
+               close(fd);
+       }
+       ddvd_set_video_ex(m_ddvdconfig, aspect, policy, policy2, DDVD_PAL /*unused*/);
+#else
+       ddvd_set_video(m_ddvdconfig, aspect, policy, DDVD_PAL /*unused*/);
+#warning please update libdreamdvd for 16:10 scaling support!
+#endif
+
+       CONNECT(m_sn->activated, eServiceDVD::gotMessage);
        CONNECT(m_pump.recv_msg, eServiceDVD::gotThreadMessage);
        strcpy(m_ddvd_titlestring,"");
        m_cue_pts = 0;
+       pause();
 }
 
 void eServiceDVD::gotThreadMessage(const int &msg)
@@ -157,8 +192,24 @@ void eServiceDVD::gotMessage(int /*what*/)
                }
                case DDVD_SCREEN_UPDATE:
                        eDebug("DVD_SCREEN_UPDATE!");
-                       if (m_subtitle_widget)
-                               m_subtitle_widget->setPixmap(m_pixmap, eRect(0, 0, 720, 576));
+                       if (m_subtitle_widget) {
+                               int x1,x2,y1,y2;
+                               ddvd_get_last_blit_area(m_ddvdconfig, &x1, &x2, &y1, &y2);
+                               
+                               int x_offset = 0, y_offset = 0, width = 720, height = 576;
+
+#ifdef DDVD_SUPPORTS_GET_BLIT_DESTINATION
+                               ddvd_get_blit_destination(m_ddvdconfig, &x_offset, &y_offset, &width, &height);
+                               eDebug("values got from ddvd: %d %d %d %d", x_offset, y_offset, width, height);
+                               y_offset = -y_offset;
+                               width -= x_offset * 2;
+                               height -= y_offset * 2;
+#endif
+                               eRect dest(x_offset, y_offset, width, height);
+
+                               if (dest.width() && dest.height())
+                                       m_subtitle_widget->setPixmap(m_pixmap, eRect(x1, y1, (x2-x1)+1, (y2-y1)+1), dest);
+                       }
                        break;
                case DDVD_SHOWOSD_STATE_PLAY:
                {
@@ -212,6 +263,14 @@ void eServiceDVD::gotMessage(int /*what*/)
                        eDebug("DVD_SOF_REACHED!");
                        m_event(this, evSOF);
                        break;
+               case DDVD_SHOWOSD_ANGLE:
+               {
+                       int current, num;
+                       ddvd_get_angle_info(m_ddvdconfig, &current, &num);
+                       eDebug("DVD_ANGLE_INFO: %d / %d", current, num);
+                       m_event(this, evUser+13);
+                       break;
+               }
                case DDVD_SHOWOSD_TIME:
                {
                        static struct ddvd_time last_info;
@@ -230,6 +289,8 @@ void eServiceDVD::gotMessage(int /*what*/)
                        ddvd_get_title_string(m_ddvdconfig, m_ddvd_titlestring);
                        eDebug("DDVD_SHOWOSD_TITLESTRING: %s",m_ddvd_titlestring);
                        loadCuesheet();
+                       if (!m_cue_pts)
+                               unpause();
                        m_event(this, evStart);
                        break;
                }
@@ -245,6 +306,32 @@ void eServiceDVD::gotMessage(int /*what*/)
                        m_event(this, evSeekableStatusChanged);
                        m_event(this, evUser+12);
                        break;
+#ifdef DDVD_SUPPORTS_PICTURE_INFO
+               case DDVD_SIZE_CHANGED:
+               {
+                       int changed = m_width != -1 && m_height != -1 && m_aspect != -1;
+                       ddvd_get_last_size(m_ddvdconfig, &m_width, &m_height, &m_aspect);
+                       if (changed)
+                               m_event((iPlayableService*)this, evVideoSizeChanged);
+                       break;
+               }
+               case DDVD_PROGRESSIVE_CHANGED:
+               {
+                       int changed = m_progressive != -1;
+                       ddvd_get_last_progressive(m_ddvdconfig, &m_progressive);
+                       if (changed)
+                               m_event((iPlayableService*)this, evVideoProgressiveChanged);
+                       break;
+               }
+               case DDVD_FRAMERATE_CHANGED:
+               {
+                       int changed = m_framerate != -1;
+                       ddvd_get_last_framerate(m_ddvdconfig, &m_framerate);
+                       if (changed)
+                               m_event((iPlayableService*)this, evVideoFramerateChanged);
+                       break;
+               }
+#endif
                default:
                        break;
        }
@@ -256,6 +343,7 @@ eServiceDVD::~eServiceDVD()
        kill();
        saveCuesheet();
        ddvd_close(m_ddvdconfig);
+       disableSubtitles(0);
 }
 
 RESULT eServiceDVD::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
@@ -266,20 +354,19 @@ RESULT eServiceDVD::connectEvent(const Slot2<void,iPlayableService*,int> &event,
 
 RESULT eServiceDVD::start()
 {
-       assert(m_state == stIdle);
+       ASSERT(m_state == stIdle);
        m_state = stRunning;
        eDebug("eServiceDVD starting");
-       run();
 //     m_event(this, evStart);
        return 0;
 }
 
 RESULT eServiceDVD::stop()
 {
-       assert(m_state != stIdle);
+       ASSERT(m_state != stIdle);
        if (m_state == stStopped)
                return -1;
-       eDebug("DVD: stop %s", m_filename.c_str());
+       eDebug("DVD: stop %s", m_ref.path.c_str());
        m_state = stStopped;
        ddvd_send_key(m_ddvdconfig, DDVD_KEY_EXIT);
 
@@ -393,7 +480,7 @@ RESULT eServiceDVD::getName(std::string &name)
        if ( m_ddvd_titlestring[0] != '\0' )
                name = m_ddvd_titlestring;
        else
-               name = m_filename;
+               name = m_ref.path;
        return 0;
 }
 
@@ -434,7 +521,20 @@ int eServiceDVD::getInfo(int w)
                }
                case sUser+6:
                case sUser+7:
+               case sUser+8:
                        return resIsPyObject;
+#ifdef DDVD_SUPPORTS_PICTURE_INFO
+               case sVideoWidth:
+                       return m_width;
+               case sVideoHeight:
+                       return m_height;
+               case sAspect:
+                       return m_aspect;
+               case sProgressive:
+                       return m_progressive;
+               case sFrameRate:
+                       return m_framerate;
+#endif
                default:
                        return resNA;
        }
@@ -445,7 +545,7 @@ std::string eServiceDVD::getInfoString(int w)
        switch(w)
        {
                case sServiceref:
-                       break;
+                       return m_ref.toString();
                default:
                        eDebug("unhandled getInfoString(%d)", w);
        }
@@ -503,6 +603,16 @@ PyObject *eServiceDVD::getInfoObject(int w)
                        }                               
                        return tuple;
                }
+               case sUser+8:
+               {
+                       ePyObject tuple = PyTuple_New(2);
+                       int current, num;
+                       ddvd_get_angle_info(m_ddvdconfig, &current, &num);
+                       PyTuple_SetItem(tuple, 0, PyInt_FromLong(current));
+                       PyTuple_SetItem(tuple, 1, PyInt_FromLong(num));
+
+                       return tuple;
+               }
                default:
                        eDebug("unhandled getInfoObject(%d)", w);
        }
@@ -511,13 +621,28 @@ PyObject *eServiceDVD::getInfoObject(int w)
 
 RESULT eServiceDVD::enableSubtitles(eWidget *parent, SWIG_PYOBJECT(ePyObject) /*entry*/)
 {
-       if (m_subtitle_widget)
-               delete m_subtitle_widget;
+       delete m_subtitle_widget;
+
        m_subtitle_widget = new eSubtitleWidget(parent);
        m_subtitle_widget->resize(parent->size());
-       m_subtitle_widget->setPixmap(m_pixmap, eRect(0, 0, 720, 576));
+
+       eSize size = eSize(720, 576);
+
+       if (!m_pixmap)
+       {
+               m_pixmap = new gPixmap(size, 32, 1); /* allocate accel surface (if possible) */
+#ifdef DDVD_SUPPORTS_GET_BLIT_DESTINATION
+               ddvd_set_lfb_ex(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4, 1);
+#else
+               ddvd_set_lfb(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4);
+#warning please update libdreamdvd for fast scaling
+#endif
+               run(); // start the thread
+       }
+
        m_subtitle_widget->setZPosition(-1);
        m_subtitle_widget->show();
+
        return 0;
 }
 
@@ -606,7 +731,7 @@ RESULT eServiceDVD::setTrickmode(int /*trick*/)
 
 RESULT eServiceDVD::isCurrentlySeekable()
 {
-       return m_state == stRunning;
+       return m_state == stRunning ? 3 : 0;
 }
 
 RESULT eServiceDVD::keyPressed(int key)
@@ -652,6 +777,9 @@ RESULT eServiceDVD::keyPressed(int key)
        case iServiceKeys::keyUser+7:
                ddvd_send_key(m_ddvdconfig, DDVD_KEY_MENU);
                break;
+       case iServiceKeys::keyUser+8:
+               ddvd_send_key(m_ddvdconfig, DDVD_KEY_ANGLE);
+               break;
        default:
                return -1;
        }
@@ -693,7 +821,7 @@ void eServiceDVD::loadCuesheet()
        if ( m_ddvd_titlestring[0] != '\0' )
                snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
        else
-               snprintf(filename, 128, "%s/dvd.cuts", m_filename.c_str());
+               snprintf(filename, 128, "%s/dvd.cuts", m_ref.path.c_str());
 
        eDebug("eServiceDVD::loadCuesheet() filename=%s",filename);
 
@@ -739,27 +867,32 @@ void eServiceDVD::saveCuesheet()
 {
        eDebug("eServiceDVD::saveCuesheet()");
 
-       struct ddvd_time info;
-       ddvd_get_last_time(m_ddvdconfig, &info);
-       if ( info.pos_chapter < info.end_chapter )
+       struct ddvd_resume resume_info;
+       ddvd_get_resume_pos(m_ddvdconfig, &resume_info);
+
+       if (resume_info.title)
        {
+               struct ddvd_time info;
+               ddvd_get_last_time(m_ddvdconfig, &info);
                pts_t pos;
                pos = info.pos_hours * 3600;
                pos += info.pos_minutes * 60;
                pos += info.pos_seconds;
                pos *= 90000;
                m_cue_pts = pos;
+               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);
+       }
+       else
+       {
+               eDebug("we're in a menu or somewhere else funny. so save cuesheet with pts=0");
+               m_cue_pts = 0;
        }
-
-       struct ddvd_resume resume_info;
-       ddvd_get_resume_pos(m_ddvdconfig, &resume_info);
-       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);
 
        char filename[128];
        if ( m_ddvd_titlestring[0] != '\0' )
                snprintf(filename, 128, "/home/root/dvd-%s.cuts", m_ddvd_titlestring);
        else
-               snprintf(filename, 128, "%s/dvd.cuts", m_filename.c_str());
+               snprintf(filename, 128, "%s/dvd.cuts", m_ref.path.c_str());
        
        FILE *f = fopen(filename, "wb");