update dvbapp.
authorhschang <chang@dev3>
Thu, 15 Oct 2015 07:56:10 +0000 (16:56 +0900)
committerhschang <chang@dev3>
Mon, 19 Oct 2015 09:38:38 +0000 (18:38 +0900)
  - support FBC Tuner.
  - Add MiniTV, BoxModeConfig, FastZapSupport.
  - Fix wrong nim config when multi tuner changed.
  - Update harddisk, devicemanager.
  - Support gstreamer 1.X.
  - Support HEVC.
  - Support 2160P. (videomode)

59 files changed:
configure.ac
data/startwizard.xml
lib/base/eptrlist.h
lib/dvb/Makefile.am
lib/dvb/decoder.cpp
lib/dvb/decoder.h
lib/dvb/dvb.cpp
lib/dvb/dvb.h
lib/dvb/fbc.cpp [new file with mode: 0644]
lib/dvb/fbc.h [new file with mode: 0644]
lib/dvb/frontend.cpp
lib/dvb/frontend.h
lib/dvb/pmt.cpp
lib/dvb/pmt.h
lib/dvb/scan.cpp
lib/dvb/sec.cpp
lib/dvb/sec.h
lib/gdi/epng.cpp
lib/gdi/picload.cpp
lib/python/Components/Harddisk.py
lib/python/Components/NimManager.py
lib/python/Components/ServiceList.py
lib/python/Plugins/Extensions/DLNAServer/Makefile.am
lib/python/Plugins/Extensions/DLNAServer/dlnaserver [deleted file]
lib/python/Plugins/Extensions/Makefile.am
lib/python/Plugins/Extensions/MiniTV/Makefile.am [new file with mode: 0644]
lib/python/Plugins/Extensions/MiniTV/__init__.py [new file with mode: 0644]
lib/python/Plugins/Extensions/MiniTV/meta/Makefile.am [new file with mode: 0644]
lib/python/Plugins/Extensions/MiniTV/meta/plugin_minitv.xml [new file with mode: 0644]
lib/python/Plugins/Extensions/MiniTV/plugin.py [new file with mode: 0644]
lib/python/Plugins/Plugin.py
lib/python/Plugins/SystemPlugins/3GModemManager/3gcommand [deleted file]
lib/python/Plugins/SystemPlugins/3GModemManager/Makefile.am
lib/python/Plugins/SystemPlugins/Blindscan/plugin.py
lib/python/Plugins/SystemPlugins/BoxModeConfig/Makefile.am [new file with mode: 0755]
lib/python/Plugins/SystemPlugins/BoxModeConfig/__init__.py [new file with mode: 0755]
lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/Makefile.am [new file with mode: 0755]
lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/plugin_boxmodeconfig.xml [new file with mode: 0755]
lib/python/Plugins/SystemPlugins/BoxModeConfig/plugin.py [new file with mode: 0755]
lib/python/Plugins/SystemPlugins/DeviceManager/plugin.py
lib/python/Plugins/SystemPlugins/FastZapSupport/Makefile.am [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/FastZapSupport/__init__.py [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/FastZapSupport/meta/Makefile.am [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/FastZapSupport/meta/plugin_fastzapsupport.xml [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/FastZapSupport/plugin.py [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/Makefile.am
lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py
lib/python/Screens/About.py
lib/python/Screens/ChannelSelection.py
lib/python/Screens/InfoBarGenerics.py
lib/python/Screens/Satconfig.py
lib/python/Screens/ServiceInfo.py
lib/python/Screens/ServiceScan.py
lib/python/enigma_python.i
lib/service/listboxservice.cpp
lib/service/listboxservice.h
lib/service/servicedvbrecord.cpp
lib/service/servicemp3.cpp
lib/service/servicemp3.h

index d4071bb..bf4ad08 100644 (file)
@@ -30,7 +30,12 @@ TUXBOX_APPS_DVB
 AM_CONDITIONAL(HAVE_GIT_DIR, test -d "$srcdir/.git")
 AM_CONDITIONAL(HAVE_FAKE_GIT_DIR, test -f "$srcdir/.git/last_commit_info")
 
 AM_CONDITIONAL(HAVE_GIT_DIR, test -d "$srcdir/.git")
 AM_CONDITIONAL(HAVE_FAKE_GIT_DIR, test -f "$srcdir/.git/last_commit_info")
 
-PKG_CHECK_MODULES(BASE, [freetype2 fribidi gstreamer-0.10 gstreamer-pbutils-0.10 libdvbsi++ libpng libxml-2.0 sigc++-1.2 libssl libcrypto])
+dnl versions of gstreamer and plugins-base
+AC_ARG_WITH(gstversion,
+        AS_HELP_STRING([--with-gstversion],[use gstreamer version (major.minor)]),
+        [GST_MAJORMINOR=$withval],[GST_MAJORMINOR=0.10])
+
+PKG_CHECK_MODULES(BASE, [freetype2 fribidi gstreamer-$GST_MAJORMINOR gstreamer-pbutils-$GST_MAJORMINOR libdvbsi++ libpng libxml-2.0 sigc++-1.2 libssl libcrypto])
 PKG_CHECK_MODULES(LIBDDVD, libdreamdvd, HAVE_LIBDDVD="yes", HAVE_LIBDDVD="no")
 AM_CONDITIONAL(HAVE_LIBDDVD, test "$HAVE_LIBDDVD" = "yes")
 
 PKG_CHECK_MODULES(LIBDDVD, libdreamdvd, HAVE_LIBDDVD="yes", HAVE_LIBDDVD="no")
 AM_CONDITIONAL(HAVE_LIBDDVD, test "$HAVE_LIBDDVD" = "yes")
 
@@ -210,6 +215,8 @@ lib/python/Plugins/Extensions/BackupSuiteUSB/Makefile
 lib/python/Plugins/Extensions/BackupSuiteUSB/meta/Makefile
 lib/python/Plugins/Extensions/SatipClient/Makefile
 lib/python/Plugins/Extensions/SatipClient/meta/Makefile
 lib/python/Plugins/Extensions/BackupSuiteUSB/meta/Makefile
 lib/python/Plugins/Extensions/SatipClient/Makefile
 lib/python/Plugins/Extensions/SatipClient/meta/Makefile
+lib/python/Plugins/Extensions/MiniTV/Makefile
+lib/python/Plugins/Extensions/MiniTV/meta/Makefile
 lib/python/Plugins/SystemPlugins/CleanupWizard/Makefile
 lib/python/Plugins/SystemPlugins/CleanupWizard/meta/Makefile
 lib/python/Plugins/SystemPlugins/CommonInterfaceAssignment/Makefile
 lib/python/Plugins/SystemPlugins/CleanupWizard/Makefile
 lib/python/Plugins/SystemPlugins/CleanupWizard/meta/Makefile
 lib/python/Plugins/SystemPlugins/CommonInterfaceAssignment/Makefile
@@ -295,6 +302,10 @@ lib/python/Plugins/SystemPlugins/AudioEffect/Makefile
 lib/python/Plugins/SystemPlugins/AudioEffect/meta/Makefile
 lib/python/Plugins/SystemPlugins/AnimationSetup/Makefile
 lib/python/Plugins/SystemPlugins/AnimationSetup/meta/Makefile
 lib/python/Plugins/SystemPlugins/AudioEffect/meta/Makefile
 lib/python/Plugins/SystemPlugins/AnimationSetup/Makefile
 lib/python/Plugins/SystemPlugins/AnimationSetup/meta/Makefile
+lib/python/Plugins/SystemPlugins/FastZapSupport/Makefile
+lib/python/Plugins/SystemPlugins/FastZapSupport/meta/Makefile
+lib/python/Plugins/SystemPlugins/BoxModeConfig/Makefile
+lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/Makefile
 lib/python/Tools/Makefile
 lib/service/Makefile
 lib/components/Makefile
 lib/python/Tools/Makefile
 lib/service/Makefile
 lib/components/Makefile
index c13a502..db04392 100755 (executable)
@@ -48,7 +48,8 @@ self.selectKey("RIGHT")
                <step id="nimc">
                        <condition>
 from Components.NimManager import nimmanager
                <step id="nimc">
                        <condition>
 from Components.NimManager import nimmanager
-self.condition = len(nimmanager.nim_slots) > 2 and not nimmanager.nim_slots[2].empty and config.misc.startwizard.shownimconfig.value
+from Screens.Satconfig import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 2 and not nimmanager.nim_slots[2].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[2])
                        </condition>
                        <text value="Please set up tuner C" />
                        <config screen="NimSetup" module="Satconfig" args="2" type="ConfigList" />
                        </condition>
                        <text value="Please set up tuner C" />
                        <config screen="NimSetup" module="Satconfig" args="2" type="ConfigList" />
@@ -61,7 +62,8 @@ self.selectKey("RIGHT")
                <step id="nimd">
                        <condition>
 from Components.NimManager import nimmanager
                <step id="nimd">
                        <condition>
 from Components.NimManager import nimmanager
-self.condition = len(nimmanager.nim_slots) > 3 and not nimmanager.nim_slots[3].empty and config.misc.startwizard.shownimconfig.value
+from Screens.Satconfig import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 3 and not nimmanager.nim_slots[3].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[3])
                        </condition>
                        <text value="Please set up tuner D" />
                        <config screen="NimSetup" module="Satconfig" args="3" type="ConfigList" />
                        </condition>
                        <text value="Please set up tuner D" />
                        <config screen="NimSetup" module="Satconfig" args="3" type="ConfigList" />
@@ -71,6 +73,90 @@ self.selectKey("LEFT")
 self.selectKey("RIGHT")
                        </code>
                </step>
 self.selectKey("RIGHT")
                        </code>
                </step>
+               <step id="nime">
+                       <condition>
+from Components.NimManager import nimmanager
+from Screens.Satconfig import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 4 and not nimmanager.nim_slots[4].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[4])
+                       </condition>
+                       <text value="Please set up tuner E" />
+                       <config screen="NimSetup" module="Satconfig" args="4" type="ConfigList" />
+                       <code>
+self.clearSelectedKeys()
+self.selectKey("LEFT")
+self.selectKey("RIGHT")
+                       </code>
+               </step>
+               <step id="nimf">
+                       <condition>
+from Components.NimManager import nimmanager
+from Screens.Satconfig import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 5 and not nimmanager.nim_slots[5].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[5])
+                       </condition>
+                       <text value="Please set up tuner F" />
+                       <config screen="NimSetup" module="Satconfig" args="5" type="ConfigList" />
+                       <code>
+self.clearSelectedKeys()
+self.selectKey("LEFT")
+self.selectKey("RIGHT")
+                       </code>
+               </step>
+               <step id="nimg">
+                       <condition>
+from Components.NimManager import nimmanager
+from Screens.Satconfig import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 6 and not nimmanager.nim_slots[6].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[6])
+                       </condition>
+                       <text value="Please set up tuner G" />
+                       <config screen="NimSetup" module="Satconfig" args="6" type="ConfigList" />
+                       <code>
+self.clearSelectedKeys()
+self.selectKey("LEFT")
+self.selectKey("RIGHT")
+                       </code>
+               </step>
+               <step id="nimh">
+                       <condition>
+from Components.NimManager import nimmanager
+from Screens.Satconfig import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 7 and not nimmanager.nim_slots[7].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[7])
+                       </condition>
+                       <text value="Please set up tuner H" />
+                       <config screen="NimSetup" module="Satconfig" args="7" type="ConfigList" />
+                       <code>
+self.clearSelectedKeys()
+self.selectKey("LEFT")
+self.selectKey("RIGHT")
+                       </code>
+               </step>
+               <step id="nimi">
+                       <condition>
+from Components.NimManager import nimmanager
+from Screens.Satconfig import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 8 and not nimmanager.nim_slots[8].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[8])
+                       </condition>
+                       <text value="Please set up tuner I" />
+                       <config screen="NimSetup" module="Satconfig" args="8" type="ConfigList" />
+                       <code>
+self.clearSelectedKeys()
+self.selectKey("LEFT")
+self.selectKey("RIGHT")
+                       </code>
+               </step>
+               <step id="nimj">
+                       <condition>
+from Components.NimManager import nimmanager
+from Screens.Satconfig import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 9 and not nimmanager.nim_slots[9].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[9])
+                       </condition>
+                       <text value="Please set up tuner J" />
+                       <config screen="NimSetup" module="Satconfig" args="9" type="ConfigList" />
+                       <code>
+self.clearSelectedKeys()
+self.selectKey("LEFT")
+self.selectKey("RIGHT")
+                       </code>
+               </step>
                <step id="satlistsquestion">
                        <text value="Do you want to install default sat lists?" />
                        <condition>
                <step id="satlistsquestion">
                        <text value="Do you want to install default sat lists?" />
                        <condition>
index 0da46da..361323c 100644 (file)
@@ -174,7 +174,7 @@ public:
        {
                // added a new item to the list... in order
                // returns a iterator to the new item
        {
                // added a new item to the list... in order
                // returns a iterator to the new item
-               return insert( std::lower_bound( std::list<T*>::begin(), std::list<T*>::end(), e, less()), e );
+               return this->insert( std::lower_bound( std::list<T*>::begin(), std::list<T*>::end(), e, less()), e );
        }
 
 };
        }
 
 };
@@ -804,7 +804,7 @@ public:
        {
                // added a new item to the list... in order
                // returns a iterator to the new item
        {
                // added a new item to the list... in order
                // returns a iterator to the new item
-               return insert( std::lower_bound( std::list<ePtr<T> >::begin(), e, std::list<ePtr<T> >::end()), e );
+               return this->insert( std::lower_bound( std::list<ePtr<T> >::begin(), e, std::list<ePtr<T> >::end()), e );
        }
 
 };
        }
 
 };
index 9b33755..b185237 100644 (file)
@@ -30,7 +30,8 @@ libenigma_dvb_a_SOURCES = \
        subtitle.cpp \
        teletext.cpp \
        tstools.cpp \
        subtitle.cpp \
        teletext.cpp \
        tstools.cpp \
-       volume.cpp
+       volume.cpp \
+       fbc.cpp
 
 dvbincludedir = $(pkgincludedir)/lib/dvb
 dvbinclude_HEADERS = \
 
 dvbincludedir = $(pkgincludedir)/lib/dvb
 dvbinclude_HEADERS = \
@@ -61,4 +62,5 @@ dvbinclude_HEADERS = \
        subtitle.h \
        teletext.h \
        tstools.h \
        subtitle.h \
        teletext.h \
        tstools.h \
-       volume.h
+       volume.h \
+       fbc.h
index 97cb99d..8a4a82d 100644 (file)
@@ -344,6 +344,7 @@ eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev)
 #define VIDEO_STREAMTYPE_MPEG4_Part2 4
 #define VIDEO_STREAMTYPE_VC1_SM 5
 #define VIDEO_STREAMTYPE_MPEG1 6
 #define VIDEO_STREAMTYPE_MPEG4_Part2 4
 #define VIDEO_STREAMTYPE_VC1_SM 5
 #define VIDEO_STREAMTYPE_MPEG1 6
+#define VIDEO_STREAMTYPE_H265_HEVC 7
 
 #if HAVE_DVB_API_VERSION < 3
 int eDVBVideo::setPid(int pid)
 
 #if HAVE_DVB_API_VERSION < 3
 int eDVBVideo::setPid(int pid)
@@ -431,6 +432,9 @@ int eDVBVideo::startPid(int pid, int type)
        case VC1_SM:
                streamtype = VIDEO_STREAMTYPE_VC1_SM;
                break;
        case VC1_SM:
                streamtype = VIDEO_STREAMTYPE_VC1_SM;
                break;
+       case H265_HEVC:
+               streamtype = VIDEO_STREAMTYPE_H265_HEVC;
+               break;
        }
 
        eDebugNoNewLine("VIDEO_SET_STREAMTYPE %d - ", streamtype);
        }
 
        eDebugNoNewLine("VIDEO_SET_STREAMTYPE %d - ", streamtype);
index ed8b6c7..f0f8b2f 100644 (file)
@@ -49,7 +49,7 @@ private:
        Signal1<void, struct iTSMPEGDecoder::videoEvent> m_event;
        int m_width, m_height, m_framerate, m_aspect, m_progressive;
 public:
        Signal1<void, struct iTSMPEGDecoder::videoEvent> m_event;
        int m_width, m_height, m_framerate, m_aspect, m_progressive;
 public:
-       enum { MPEG2, MPEG4_H264, MPEG1, MPEG4_Part2, VC1, VC1_SM };
+       enum { MPEG2, MPEG4_H264, MPEG1, MPEG4_Part2, VC1, VC1_SM, H265_HEVC };
        eDVBVideo(eDVBDemux *demux, int dev);
        void stop();
 #if HAVE_DVB_API_VERSION < 3
        eDVBVideo(eDVBDemux *demux, int dev);
        void stop();
 #if HAVE_DVB_API_VERSION < 3
index 62b01d2..0a371f0 100755 (executable)
@@ -6,6 +6,8 @@
 #include <lib/dvb/sec.h>
 #include <lib/dvb/specs.h>
 
 #include <lib/dvb/sec.h>
 #include <lib/dvb/specs.h>
 
+#include <lib/dvb/fbc.h>
+
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -26,6 +28,14 @@ eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(f
 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
 {
        m_fe->dec_use();
 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
 {
        m_fe->dec_use();
+       if (m_fe->m_frontend->is_FBCTuner())
+       {
+               eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
+               if (fbcmng)
+               {
+                       fbcmng->unset(m_fe);
+               }
+       }
 }
 
 DEFINE_REF(eDVBAllocatedDemux);
 }
 
 DEFINE_REF(eDVBAllocatedDemux);
@@ -422,13 +432,31 @@ void eDVBResourceManager::setFrontendType(int index, const char *type)
 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
 {
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
 {
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
-       ePtr<eDVBRegisteredFrontend> best;
+//     ePtr<eDVBRegisteredFrontend> best;
+       eDVBRegisteredFrontend *best = NULL;
        int bestval = 0;
        int foundone = 0;
 
        int bestval = 0;
        int foundone = 0;
 
+       int check_fbc_linked = 0;
+       eDVBRegisteredFrontend *fbc_fe = NULL;
+       eDVBRegisteredFrontend *best_fbc_fe = NULL;
+       eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
+
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
        {
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
        {
-               int c = i->m_frontend->isCompatibleWith(feparm);
+               int c = 0;
+               fbc_fe = NULL;
+               if (!check_fbc_linked && i->m_frontend->is_FBCTuner() && fbcmng && fbcmng->canLink(*i))
+               {
+                       check_fbc_linked = 1;
+                       c = fbcmng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
+
+//                     eDebug("[eDVBResourceManager::allocateFrontend] fbcmng->isCompatibleWith slotid : %p (%d), fbc_fe : %p (%d), score : %d", (eDVBRegisteredFrontend *)*i,  i->m_frontend->getSlotID(), fbc_fe, fbc_fe?fbc_fe->m_frontend->getSlotID():-1, c);                     
+               }
+               else
+               {
+                       c = i->m_frontend->isCompatibleWith(feparm);
+               }
 
                if (c)  /* if we have at least one frontend which is compatible with the source, flag this. */
                        foundone = 1;
 
                if (c)  /* if we have at least one frontend which is compatible with the source, flag this. */
                        foundone = 1;
@@ -439,15 +467,26 @@ RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, eP
                        if (c > bestval)
                        {
                                bestval = c;
                        if (c > bestval)
                        {
                                bestval = c;
-                               best = i;
+//                             best = i;
+                               best = *i;
+                               best_fbc_fe = fbc_fe;
                        }
                }
                        }
                }
-//             else
+               else
+               {
 //                     eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
 //                     eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
+               }
+
+               eDVBRegisteredFrontend *tmp = *i;
        }
 
        if (best)
        {
        }
 
        if (best)
        {
+               if (fbcmng && best_fbc_fe)
+               {
+                       fbcmng->addLink(best, best_fbc_fe, simulate);
+               }
+
                fe = new eDVBAllocatedFrontend(best);
                return 0;
        }
                fe = new eDVBAllocatedFrontend(best);
                return 0;
        }
@@ -667,12 +706,6 @@ RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
                if (!simulate) \
                        eDebug(x); \
        } while(0)
                if (!simulate) \
                        eDebug(x); \
        } while(0)
-//             else \
-//             { \
-//                     eDebugNoNewLine("SIMULATE:"); \
-//                     eDebug(x); \
-//             } \
-
 
 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
 {
 
 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
 {
@@ -877,14 +910,27 @@ int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &fepar
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
        ePtr<eDVBRegisteredFrontend> best;
        int bestval = 0;
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
        ePtr<eDVBRegisteredFrontend> best;
        int bestval = 0;
+       int check_fbc_link = 0;
+       eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
 
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
 
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
+       {
                if (!i->m_inuse)
                {
                if (!i->m_inuse)
                {
-                       int c = i->m_frontend->isCompatibleWith(feparm);
+                       int c = 0;
+                       if(fbcmng && i->m_frontend->is_FBCTuner() && fbcmng->canLink(*i) && !check_fbc_link)
+                       {
+                               check_fbc_link = 1;
+                               c = fbcmng->isCompatibleWith(feparm, *i, simulate);
+                       }
+                       else
+                       {
+                               c = i->m_frontend->isCompatibleWith(feparm);
+                       }
                        if (c > bestval)
                                bestval = c;
                }
                        if (c > bestval)
                                bestval = c;
                }
+       }
        return bestval;
 }
 
        return bestval;
 }
 
index 10ad094..fa1e8a1 100644 (file)
@@ -12,6 +12,7 @@
 #include <lib/dvb/tstools.h>
 #include <lib/dvb/esection.h>
 #include <connection.h>
 #include <lib/dvb/tstools.h>
 #include <lib/dvb/esection.h>
 #include <connection.h>
+#include <lib/dvb/fbc.h>
 
 #include <dvbsi++/service_description_section.h>
 
 
 #include <dvbsi++/service_description_section.h>
 
@@ -158,8 +159,9 @@ class eDVBResourceManager: public iObject, public Object
        ePtr<iDVBChannelList> m_list;
        ePtr<iDVBSatelliteEquipmentControl> m_sec;
        static eDVBResourceManager *instance;
        ePtr<iDVBChannelList> m_list;
        ePtr<iDVBSatelliteEquipmentControl> m_sec;
        static eDVBResourceManager *instance;
-       
        friend class eDVBChannel;
        friend class eDVBChannel;
+       friend class eFBCTunerManager;
        RESULT addChannel(const eDVBChannelID &chid, eDVBChannel *ch);
        RESULT removeChannel(eDVBChannel *ch);
 
        RESULT addChannel(const eDVBChannelID &chid, eDVBChannel *ch);
        RESULT removeChannel(eDVBChannel *ch);
 
diff --git a/lib/dvb/fbc.cpp b/lib/dvb/fbc.cpp
new file mode 100644 (file)
index 0000000..dc70c05
--- /dev/null
@@ -0,0 +1,880 @@
+/* FBC Manager */
+#include <lib/dvb/fbc.h>
+#include <lib/dvb/dvb.h>
+#include <lib/dvb/sec.h>
+#include <lib/base/object.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#define FE_SLOT_ID(fe) fe->m_frontend->getSlotID()
+
+//#define FBC_DEBUG
+
+#ifdef FBC_DEBUG
+#define eFecDebug(arg...) eDebug(arg)
+#else
+#define eFecDebug(arg...)
+#endif
+
+
+DEFINE_REF(eFBCTunerManager);
+
+bool eFBCTunerManager::isDestroyed = false;
+
+eFBCTunerManager::eFBCTunerManager()
+{
+       ePtr<eDVBResourceManager> res_mgr;
+       eDVBResourceManager::getInstance(res_mgr);
+       m_res_mgr = res_mgr;
+
+       /* num of fbc tuner in one set */
+       m_fbc_tuner_num = getFBCTunerNum();
+       procInit();
+}
+
+eFBCTunerManager::~eFBCTunerManager()
+{
+       isDestroyed = true;
+}
+
+void eFBCTunerManager::procInit()
+{
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
+
+       /* 1 FBC set has 8 tuners. */
+       /* 1st set : 0, 1, 2, 3, 4, 5, 6, 7 */
+       /* 2nd set : 8, 9, 10, 11, 12, 13, 14, 15 */
+       /* 1st, 2nd frontend is top on a set */
+
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (!it->m_frontend->is_FBCTuner())
+                       continue;
+
+               if (isRootFe(*it))
+               {
+                       setProcFBCID(FE_SLOT_ID(it), getFBCID(FE_SLOT_ID(it)));
+               }
+       }
+}
+
+int eFBCTunerManager::getFBCTunerNum()
+{
+       char tmp[255];
+       int fbc_tuner_num = 2;
+       int fd = open("/proc/stb/info/chipset", O_RDONLY);
+       if(fd < 0) {
+               eDebug("open failed, /proc/stb/info/chipset!");
+               fbc_tuner_num = 2;
+       }
+       else
+       {
+               read(fd, tmp, 255);
+               close(fd);
+
+               if (!!strstr(tmp, "7376"))
+                       fbc_tuner_num = 2;
+       }
+       return fbc_tuner_num;
+}
+
+int eFBCTunerManager::setProcFBCID(int fe_id, int fbc_id)
+{
+       eFecDebug("[*][eFBCTunerManager::setProcFBCID] %d -> %d %s", fe_id, fbc_id, !isRootFeSlot(fe_id)?"(linked)":"");
+       char filename[128];
+       char data[4];
+       sprintf(filename, "/proc/stb/frontend/%d/fbc_id", fe_id);
+       int fd = open(filename, O_RDWR);
+       if(fd < 0) {
+               eDebug("[*][eFBCTunerManager::setProcFBCID] open failed, %s: %m", filename);
+               return -1;
+       }
+       else
+       {
+               if(isLinkedByIndex(fe_id))
+                       fbc_id += 0x10; // 0x10 : isLinked, 0x01 : fbc_id
+
+               sprintf(data, "%x", fbc_id);
+               write(fd, data, strlen(data));
+               close(fd);
+       }
+       return 0;
+}
+
+bool eFBCTunerManager::isRootFeSlot(int fe_slot_id)
+{
+       return (fe_slot_id%8 < m_fbc_tuner_num) ? true : false;
+}
+
+
+bool eFBCTunerManager::isRootFe(eDVBRegisteredFrontend *fe)
+{
+       return isRootFeSlot(FE_SLOT_ID(fe));
+}
+
+bool eFBCTunerManager::isSameFbcSet(int a, int b)
+{
+       return (a/8) == (b/8) ? true : false;
+}
+
+bool eFBCTunerManager::isSupportDVBS(eDVBRegisteredFrontend *fe)
+{
+       return (fe->m_frontend->supportsDeliverySystem(SYS_DVBS, true) || fe->m_frontend->supportsDeliverySystem(SYS_DVBS2, true)) ? true : false;
+}
+
+int eFBCTunerManager::getFBCID(int top_fe_id)
+{
+       return 2*top_fe_id/8 + top_fe_id%8; /* (0,1,8,9,16,17...) -> (0,1,2,3,4,5...)*/
+}
+
+int eFBCTunerManager::setDefaultFBCID(eDVBRegisteredFrontend *fe)
+{
+       if (!isRootFe(fe))
+               return -1;
+
+       return setProcFBCID(FE_SLOT_ID(fe), getFBCID(FE_SLOT_ID(fe)));
+}
+
+void eFBCTunerManager::updateFBCID(eDVBRegisteredFrontend *next_fe, eDVBRegisteredFrontend *prev_fe)
+{
+       eDVBRegisteredFrontend *top_fe = getTop(prev_fe);
+       setProcFBCID(FE_SLOT_ID(next_fe), getFBCID(FE_SLOT_ID(top_fe)));
+}
+
+eDVBRegisteredFrontend *eFBCTunerManager::getPrev(eDVBRegisteredFrontend *fe)
+{
+       eDVBRegisteredFrontend *prev_fe = NULL;
+       long linked_prev_ptr = -1;
+       fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
+       if (linked_prev_ptr != -1)
+               prev_fe = (eDVBRegisteredFrontend *)linked_prev_ptr;
+       return prev_fe;
+}
+
+eDVBRegisteredFrontend *eFBCTunerManager::getNext(eDVBRegisteredFrontend *fe)
+{
+       eDVBRegisteredFrontend *next_fe = NULL;
+       long linked_next_ptr = -1;
+       fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
+       if (linked_next_ptr != -1)
+               next_fe = (eDVBRegisteredFrontend *)linked_next_ptr;
+       return next_fe;
+}
+
+eDVBRegisteredFrontend *eFBCTunerManager::getTop(eDVBRegisteredFrontend *fe)
+{
+       eDVBRegisteredFrontend *prev_fe = fe;
+       long linked_prev_ptr = -1;
+       fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
+       while(linked_prev_ptr != -1)
+       {
+               prev_fe = (eDVBRegisteredFrontend *)linked_prev_ptr;
+               prev_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
+       }
+       return prev_fe;
+}
+
+eDVBRegisteredFrontend *eFBCTunerManager::getLast(eDVBRegisteredFrontend *fe)
+{
+       eDVBRegisteredFrontend *next_fe = fe;
+       long linked_next_ptr = -1;
+       fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
+       while(linked_next_ptr != -1)
+       {
+               next_fe = (eDVBRegisteredFrontend *)linked_next_ptr;
+               next_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
+       }
+       return next_fe;
+}
+
+bool eFBCTunerManager::isLinked(eDVBRegisteredFrontend *fe)
+{
+       return getPrev(fe) ? true:false;
+}
+
+bool eFBCTunerManager::isLinkedByIndex(int fe_idx)
+{
+       bool linked = false;
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
+
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (FE_SLOT_ID(it) == fe_idx)
+               {
+                       linked = isLinked(*it);
+                       break;
+               }
+       }
+       return linked;
+}
+
+bool eFBCTunerManager::checkTop(eDVBRegisteredFrontend *fe)
+{
+       return getPrev(fe) ? false:true;
+}
+
+int eFBCTunerManager::connectLinkByIndex(int link_fe_index, int prev_fe_index, int next_fe_index, bool simulate)
+{
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
+
+       eFecDebug("     [*][eFBCTunerManager::connectLinkByIndex] try to link %d->%d->%d %s", prev_fe_index, link_fe_index, next_fe_index, simulate?"(simulate)":"");
+
+       eDVBRegisteredFrontend *link_fe=NULL;
+       eDVBRegisteredFrontend *prev_fe=NULL;
+       eDVBRegisteredFrontend *next_fe=NULL;
+
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (FE_SLOT_ID(it) == prev_fe_index)
+               {
+                       prev_fe = *it;
+               }
+               else if (FE_SLOT_ID(it) == next_fe_index)
+               {
+                       next_fe = *it;
+               }
+               else if (FE_SLOT_ID(it) == link_fe_index)
+               {
+                       link_fe = *it;
+               }
+       }
+
+       if (prev_fe && next_fe && link_fe)
+       {
+               /* enable linked fe */
+               link_fe->m_frontend->setEnabled(true);
+
+               /* connect */
+               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
+
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
+               next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)link_fe);
+       }
+       else
+       {
+               eDebug("        [*][eFBCTunerManager::connectLinkByIndex] connect failed! (prev_fe : %p, next_fe : %p, link_fe : %p, %s)", prev_fe, next_fe, link_fe, simulate?"simulate":"");
+               return -1;
+       }
+
+       return 0;
+}
+
+int eFBCTunerManager::connectLinkByIndex(int link_fe_index, int prev_fe_index, bool simulate)
+{
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
+
+       eFecDebug("     [*][eFBCTunerManager::connectLinkByIndex] try to link %d->%d %s", prev_fe_index, link_fe_index, simulate?"(simulate)":"");
+
+       eDVBRegisteredFrontend *link_fe=NULL;
+       eDVBRegisteredFrontend *prev_fe=NULL;
+
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (FE_SLOT_ID(it) == prev_fe_index)
+               {
+                       prev_fe = *it;
+               }
+               else if (FE_SLOT_ID(it) == link_fe_index)
+               {
+                       link_fe = *it;
+               }
+       }
+
+       if (prev_fe && link_fe)
+       {
+               /* enable linked fe */
+               link_fe->m_frontend->setEnabled(true);
+
+               /* connect */
+               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
+       }
+       else
+       {
+               eDebug("        [*][eFBCTunerManager::connectLinkByIndex] connect failed! (prev_fe : %p, link_fe : %p, %s)", prev_fe, link_fe, simulate?"simulate":"");
+               return -1;
+       }
+
+       return 0;
+}
+
+int eFBCTunerManager::disconnectLinkByIndex(int link_fe_index, int prev_fe_index, int next_fe_index, bool simulate)
+{
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
+
+       eFecDebug("     [*][eFBCTunerManager::connectLinkByIndex] try to unlink %d->%d->%d %s", prev_fe_index, link_fe_index, next_fe_index, simulate?"(simulate)":"");
+
+       eDVBRegisteredFrontend *link_fe=NULL;
+       eDVBRegisteredFrontend *prev_fe=NULL;
+       eDVBRegisteredFrontend *next_fe=NULL;
+
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (FE_SLOT_ID(it) == prev_fe_index)
+               {
+                       prev_fe = *it;
+               }
+               else if (FE_SLOT_ID(it) == next_fe_index)
+               {
+                       next_fe = *it;
+               }
+               else if (FE_SLOT_ID(it) == link_fe_index)
+               {
+                       link_fe = *it;
+               }
+       }
+
+       if (prev_fe && next_fe && link_fe)
+       {
+               /* disconnect */
+               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
+               next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
+
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
+
+               /* enable linked fe */
+               link_fe->m_frontend->setEnabled(false);
+       }
+       else
+       {
+               eDebug("        [*][eFBCTunerManager::disconnectLinkByIndex] disconnect failed! (prev_fe : %p, next_fe : %p, link_fe : %p, %s)", prev_fe, next_fe, link_fe, simulate?"simulate":"");
+               return -1;
+       }
+
+       return 0;
+}
+int eFBCTunerManager::disconnectLinkByIndex(int link_fe_index, int prev_fe_index, bool simulate)
+{
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
+
+       eFecDebug("     [*][eFBCTunerManager::connectLinkByIndex] try to unlink %d->%d %s", prev_fe_index, link_fe_index, simulate?"(simulate)":"");
+
+       eDVBRegisteredFrontend *link_fe=NULL;
+       eDVBRegisteredFrontend *prev_fe=NULL;
+
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (FE_SLOT_ID(it) == prev_fe_index)
+               {
+                       prev_fe = *it;
+               }
+               else if (FE_SLOT_ID(it) == link_fe_index)
+               {
+                       link_fe = *it;
+               }
+       }
+
+       if (prev_fe && link_fe)
+       {
+               /* disconnect */
+               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
+
+               /* enable linked fe */
+               link_fe->m_frontend->setEnabled(false);
+       }
+       else
+       {
+               eDebug("        [*][eFBCTunerManager::disconnectLinkByIndex] disconnect failed! (prev_fe : %p, link_fe : %p, %s)", prev_fe, link_fe, simulate?"simulate":"");
+               return -1;
+       }
+
+       return 0;
+}
+
+int eFBCTunerManager::connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
+{
+       eFecDebug("     [*][eFBCTunerManager::connectLink] try to link %d->%d->%d %s", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), FE_SLOT_ID(next_fe), simulate?"(simulate)":"");
+       int ret = connectLinkByIndex(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), FE_SLOT_ID(next_fe), !simulate);
+       if(!ret)
+       {
+               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
+
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
+               next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)link_fe);
+
+               /* enable linked fe */
+               link_fe->m_frontend->setEnabled(true);  
+       }
+
+       return ret;
+}
+
+int eFBCTunerManager::connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, bool simulate)
+{
+       eFecDebug("     [*][eFBCTunerManager::connectLink] try to link %d->%d %s", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), simulate?"(simulate)":"");
+       int ret = connectLinkByIndex(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), !simulate);
+       if(!ret)
+       {
+               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
+
+               /* enable linked fe */
+               link_fe->m_frontend->setEnabled(true);
+       }
+
+       return ret;
+}
+
+int eFBCTunerManager::disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
+{
+       eFecDebug("     [*][eFBCTunerManager::disconnectLink] disconnect %d->%d->%d %s", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), FE_SLOT_ID(next_fe), simulate?"(simulate)":"");
+       int ret = disconnectLinkByIndex(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), FE_SLOT_ID(next_fe), !simulate);
+       if(!ret)
+       {
+               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
+               next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
+
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
+
+               link_fe->m_frontend->setEnabled(false);
+       }
+
+       return ret;
+}
+
+int eFBCTunerManager::disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, bool simulate)
+{
+       eFecDebug("     [*][eFBCTunerManager::disconnectLink] disconnect %d->%d %s", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), simulate?"(simulate)":"");
+       int ret = disconnectLinkByIndex(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), !simulate);
+       if(!ret)
+       {
+               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
+               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
+
+               link_fe->m_frontend->setEnabled(false);
+       }
+
+       return ret;
+}
+
+/* no set pair simulate fe */
+/* no set proc fbc_id */
+void eFBCTunerManager::connectLinkNoSimulate(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe)
+{
+       eDVBRegisteredFrontend *last_fe = getLast(top_fe);
+
+       last_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
+       link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)last_fe);
+
+       /* enable linked fe */
+       link_fe->m_frontend->setEnabled(true);
+
+       /* add slot mask*/
+       updateLNBSlotMask(FE_SLOT_ID(link_fe), FE_SLOT_ID(top_fe), false);
+}
+
+/* no set pair simulate fe */
+/* no set proc fbc_id */
+void eFBCTunerManager::disconnectLinkNoSimulate(eDVBRegisteredFrontend *link_fe)
+{
+       if(getNext(link_fe))
+       {
+               eFecDebug("[*][eFBCTunerManager::disconnectLinkNoSimulate] link fe is no last.");
+               return;
+       }
+
+       eDVBRegisteredFrontend *prev_fe = getPrev(link_fe);
+
+       if(!prev_fe)
+       {
+               eFecDebug("[*][eFBCTunerManager::disconnectLinkNoSimulate] can not found prev fe.");
+               return;
+       }
+
+       prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
+       link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
+               
+       /* enable linked fe */
+       link_fe->m_frontend->setEnabled(false);
+
+       /* add slot mask*/
+       updateLNBSlotMask(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), true);
+}
+
+bool eFBCTunerManager::checkUsed(eDVBRegisteredFrontend *fe, bool a_simulate)
+{
+       if (fe->m_inuse > 0)
+               return true;
+
+       bool simulate = !a_simulate;
+
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (FE_SLOT_ID(it) == FE_SLOT_ID(fe))
+               {
+                       return (it->m_inuse >0)?true:false;
+               }
+       }
+
+       eDebug("[*][eFBCTunerManager::checkUsed] ERROR! can not found fe ptr (feid : %d, simulate : %d)", FE_SLOT_ID(fe), simulate);
+       return false;
+}
+
+bool eFBCTunerManager::canLink(eDVBRegisteredFrontend *fe)
+{
+       if(isRootFe(fe))
+               return false;
+
+       if(getPrev(fe) || getNext(fe))
+               return false;
+
+       if(isUnicable(fe))
+               return false;
+
+       return true;
+}
+
+bool eFBCTunerManager::isUnicable(eDVBRegisteredFrontend *fe)
+{
+       int slot_idx = FE_SLOT_ID(fe);
+       bool is_unicable = false;
+
+       ePtr<eDVBSatelliteEquipmentControl> sec = eDVBSatelliteEquipmentControl::getInstance();
+       for (int idx=0; idx <= sec->m_lnbidx; ++idx )
+       {
+               eDVBSatelliteLNBParameters &lnb_param = sec->m_lnbs[idx];
+               if ( lnb_param.m_slot_mask & (1 << slot_idx) )
+               {
+                       is_unicable = lnb_param.SatCR_idx != -1;
+                       break;
+               }
+       }
+       return is_unicable;
+}
+
+int eFBCTunerManager::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, bool simulate)
+{
+       eDVBRegisteredFrontend *best_fbc_fe;
+       return isCompatibleWith(feparm, link_fe, best_fbc_fe, simulate);
+}
+
+int eFBCTunerManager::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *&fbc_fe, bool simulate)
+{
+       int best_score = 0;
+
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (!it->m_frontend->is_FBCTuner())
+                       continue;
+
+               if (!isRootFe(*it))
+                       continue;
+
+               if(!it->m_frontend->getEnabled())
+                       continue;
+
+               if(!isSameFbcSet(FE_SLOT_ID(link_fe), FE_SLOT_ID(it)))
+                       continue;
+
+               if(it->m_inuse == 0) // No link to a fe not in use.
+                       continue;
+
+               if(isLinked(*it)) // No link to a fe linked to another.
+                       continue;
+
+               if(isUnicable(*it))
+                       continue;
+
+               /* connect link */
+               connectLinkNoSimulate(link_fe, *it);
+
+               /* get score */
+               int c = link_fe->m_frontend->isCompatibleWith(feparm);
+               eFecDebug("[*][eFBCTunerManager::isCompatibleWith] score : %d (%d->%d)", c, FE_SLOT_ID(it), FE_SLOT_ID(link_fe));
+               if (c > best_score)
+               {
+                       best_score = c;
+                       fbc_fe = (eDVBRegisteredFrontend *)*it;
+               }
+
+               /* disconnect link */
+               disconnectLinkNoSimulate(link_fe);
+       }
+
+       eFecDebug("[*][eFBCTunerManager::isCompatibleWith] fe : %p(%d), score : %d %s", link_fe, FE_SLOT_ID(link_fe), best_score, simulate?"(simulate)":"");
+
+       return best_score;
+}
+
+void eFBCTunerManager::connectSortedLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate)
+{
+       int link_fe_id = FE_SLOT_ID(link_fe);
+       int top_fe_id = FE_SLOT_ID(top_fe);
+       int prev_fe_id = link_fe_id - 1;
+
+       eFecDebug("     [*][eFBCTunerManager::connectSortedLink] link_id : %d, top_id : %d %s", link_fe_id, top_fe_id, simulate?"(simulate)":"");
+
+       if (prev_fe_id < 0)
+       {
+               eFecDebug("     [*][eFBCTunerManager::connectSortedLink] link failed! link_id : %d, top_id : %d %s", link_fe_id, top_fe_id, simulate?"(simulate)":"");
+               return;
+       }
+
+       /* serach prev fe */
+       eDVBRegisteredFrontend *next_fe = top_fe;
+       long linked_next_ptr = -1;
+       top_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
+       while(linked_next_ptr != -1)
+       {
+               next_fe = (eDVBRegisteredFrontend *)linked_next_ptr;
+               next_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
+               if (FE_SLOT_ID(next_fe) == prev_fe_id)
+                       break;
+       }
+
+       eDVBRegisteredFrontend *prev_fe = next_fe;
+
+       /* get next fe */
+       next_fe = getNext(prev_fe);     
+
+       /* connect */
+       if (next_fe)
+       {
+               int res = connectLink(link_fe, prev_fe, next_fe, simulate);
+               if (res)
+               {
+                       eDebug("[*][eFBCTunerManager::connectSortedLink] ERROR! connect link failed! (%d->%d->%d)", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), FE_SLOT_ID(next_fe));
+                       return;
+               }
+       }
+       else
+       {
+               int res = connectLink(link_fe, prev_fe, simulate);
+               if (res)
+               {
+                       eDebug("[*][eFBCTunerManager::connectSortedLink] ERROR! connect link failed! (%d->%d)", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe));
+                       return;
+               }
+       }
+
+       /* set proc fbc_id */
+       setProcFBCID(link_fe_id, getFBCID(top_fe_id));
+
+       /* add slot mask*/
+       updateLNBSlotMask(link_fe_id, top_fe_id, false);
+}
+
+/* attach link_fe to tail of fe linked list */
+void eFBCTunerManager::addLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate)
+{
+       eFecDebug("     [*][eFBCTunerManager::addLink] addLink : %p(%d)->%p(%d) %s", top_fe, FE_SLOT_ID(top_fe), link_fe, FE_SLOT_ID(link_fe), simulate?"(simulate)":"");
+
+       if (!isRootFe(top_fe))
+               return;
+
+//     eDVBRegisteredFrontend *top_fe = a_top_fe;
+//     if (!checkTop(top_fe))
+//             top_fe = getTop(top_fe);
+
+//     printLinks(top_fe);
+       connectSortedLink(link_fe, top_fe, simulate);
+//     printLinks(top_fe);
+}
+
+/* if fe, fe_simulated is unused, unlink current frontend from linked things. */
+/* all unused linked fbc fe must be unlinked! */
+void eFBCTunerManager::unset(eDVBRegisteredFrontend *fe)
+{
+       bool simulate = fe->m_frontend->is_simulate();
+
+       if (isRootFe(fe))
+               return;
+
+       if(checkUsed(fe, simulate))
+               return;
+
+       if(isUnicable(fe))
+               return;
+
+       eFecDebug("     [*][eFBCTunerManager::unset] fe id : %p(%d) %s", fe, FE_SLOT_ID(fe), simulate?"(simulate)":"");
+
+       
+//     printLinks(fe);
+
+       eDVBRegisteredFrontend *linked_prev_fe = getPrev(fe);
+       eDVBRegisteredFrontend *linked_next_fe = getNext(fe);
+
+       if (!linked_prev_fe)
+       {
+               eDebug("[*][eFBCTunerManager::unset] ERROR! can not found prev linked frontend (fe_id : %d)", FE_SLOT_ID(fe));
+               return;
+       }
+
+       if (linked_next_fe)
+       {
+               int res = disconnectLink(fe, linked_prev_fe, linked_next_fe, simulate);
+               if (res)
+               {
+                       eDebug("[*][eFBCTunerManager::unset] ERROR! disconnect link failed! (%d->%d->%d)", FE_SLOT_ID(linked_prev_fe), FE_SLOT_ID(fe), FE_SLOT_ID(linked_next_fe));
+                       return;
+               }
+       }
+       else
+       {
+               int res = disconnectLink(fe, linked_prev_fe, simulate);
+               if (res)
+               {
+                       eDebug("[*][eFBCTunerManager::unset] ERROR! disconnect link failed! (%d->%d)", FE_SLOT_ID(linked_prev_fe), FE_SLOT_ID(fe));
+                       return;
+               }
+       }
+
+       /* set proc fbc_id (skip) */
+
+       /* remove slot mask*/
+       updateLNBSlotMask(FE_SLOT_ID(fe), FE_SLOT_ID(linked_prev_fe), true);
+
+//     printLinks(fe);
+}
+
+bool eFBCTunerManager::canAllocateLink(eDVBRegisteredFrontend *fe, bool simulate)
+{
+       if (!isRootFe(fe))
+               return false;
+
+       if (isLinked(fe))
+               return false;
+
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (it->m_frontend->is_FBCTuner() && !isRootFe(*it) && isSameFbcSet(FE_SLOT_ID(fe), FE_SLOT_ID(it)) && !it->m_frontend->getEnabled() && !isLinked(*it))
+                       return true;
+       }
+
+       return false;
+}
+
+int eFBCTunerManager::updateLNBSlotMask(int dest_slot, int src_slot, bool remove)
+{
+       ePtr<eDVBSatelliteEquipmentControl> sec = eDVBSatelliteEquipmentControl::getInstance();
+
+       int sec_lnbidx = sec->m_lnbidx;
+
+       int found = 0;
+       for (int idx=0; idx <= sec_lnbidx; ++idx )
+       {
+               eDVBSatelliteLNBParameters &lnb_param = sec->m_lnbs[idx];
+               if ( lnb_param.m_slot_mask & (1 << src_slot) )
+               {
+                       eFecDebug("[*][eFBCTunerManager::updateLNBSlotMask] m_slot_mask : %d", lnb_param.m_slot_mask);
+
+                       if (!remove)
+                               lnb_param.m_slot_mask |= (1 << dest_slot);
+                       else
+                               lnb_param.m_slot_mask &= ~(1 << dest_slot);
+
+                       eFecDebug("[*][eFBCTunerManager::updateLNBSlotMask] changed m_slot_mask : %d", lnb_param.m_slot_mask);
+                       found = 1;
+               }
+       }
+
+       if (!found)
+               eFecDebug("[*][eFBCTunerManager::updateLNBSlotMask] src %d not found", src_slot);
+
+       return 0;
+}
+
+int eFBCTunerManager::getLinkedSlotID(int fe_id)
+{
+       int link = -1;
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if(it->m_frontend->getSlotID() == fe_id)
+               {
+                       long prev_ptr = -1;
+                       it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, prev_ptr);
+                       if (prev_ptr != -1)
+                       {
+                               eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
+                               link = FE_SLOT_ID(prev_fe);
+                       }
+                       break;
+               }
+       }
+
+       eFecDebug(" [*][eFBCTunerManager::getLinkedSlotID] fe_id : %d, link : %d", fe_id, link);
+
+       return link;
+}
+
+void eFBCTunerManager::printLinks(eDVBRegisteredFrontend *fe)
+{
+       long linked_prev_ptr = -1;
+       eDVBRegisteredFrontend *linked_prev_fe = fe;
+       fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
+       while (linked_prev_ptr != -1)
+       {
+               linked_prev_fe = (eDVBRegisteredFrontend*) linked_prev_ptr;
+               linked_prev_fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, (long&)linked_prev_ptr);
+       }
+
+       long linked_next_ptr = -1;
+       eDVBRegisteredFrontend *linked_next_fe = linked_prev_fe;
+       eFecDebug("     [*][eFBCTunerManager::printLinks] fe id : %d (%p), inuse : %d, enabled : %d, fbc : %d", FE_SLOT_ID(linked_next_fe), linked_next_fe, linked_next_fe->m_inuse, linked_next_fe->m_frontend->getEnabled(), linked_next_fe->m_frontend->is_FBCTuner());
+       linked_prev_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
+       while (linked_next_ptr != -1)
+       {
+               linked_next_fe = (eDVBRegisteredFrontend*) linked_next_ptr;
+               eFecDebug("     [*][eFBCTunerManager::printLinks] fe id : %d (%p), inuse : %d, enabled : %d, fbc : %d", FE_SLOT_ID(linked_next_fe), linked_next_fe, linked_next_fe->m_inuse, linked_next_fe->m_frontend->getEnabled(), linked_next_fe->m_frontend->is_FBCTuner());
+               linked_next_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, (long&)linked_next_ptr);
+       }
+
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               int prev = -1;
+               int next = -1;
+               long prev_ptr = -1;
+               long next_ptr = -1;
+               it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, prev_ptr);
+               it->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, next_ptr);
+               if (prev_ptr != -1)
+               {
+                       eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
+                       prev = FE_SLOT_ID(prev_fe);
+               }
+
+               if (next_ptr != -1)
+               {
+                       eDVBRegisteredFrontend *next_fe = (eDVBRegisteredFrontend *)next_ptr;
+                       next = FE_SLOT_ID(next_fe);
+               }
+               
+               eFecDebug("     [*][eFBCTunerManager::printLinks] fe_id : %d, inuse : %d, enabled : %d, fbc : %d, prev : %d, next : %d", FE_SLOT_ID(it), it->m_inuse, it->m_frontend->getEnabled(), it->m_frontend->is_FBCTuner(), prev, next);
+       }
+
+       eSmartPtrList<eDVBRegisteredFrontend> &simulate_frontends = m_res_mgr->m_simulate_frontend;
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(simulate_frontends.begin()); it != simulate_frontends.end(); ++it)
+       {
+               int prev = -1;
+               int next = -1;
+               long prev_ptr = -1;
+               long next_ptr = -1;
+               it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, prev_ptr);
+               it->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, next_ptr);
+               if (prev_ptr != -1)
+               {
+                       eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
+                       prev = FE_SLOT_ID(prev_fe);
+               }
+
+               if (next_ptr != -1)
+               {
+                       eDVBRegisteredFrontend *next_fe = (eDVBRegisteredFrontend *)next_ptr;
+                       next = FE_SLOT_ID(next_fe);
+               }
+               
+               eFecDebug("     [*][eFBCTunerManager::printLinks] fe_id : %2d, inuse : %d, enabled : %d, fbc : %d, prev : %2d, cur : %2d, next : %2d (simulate)", FE_SLOT_ID(it), it->m_inuse, it->m_frontend->getEnabled(), it->m_frontend->is_FBCTuner(), prev, FE_SLOT_ID(it), next);
+       }
+}
+
diff --git a/lib/dvb/fbc.h b/lib/dvb/fbc.h
new file mode 100644 (file)
index 0000000..5f1afc1
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef __dvb_fbc_h
+#define __dvb_fbc_h
+
+/* FBC Manager */
+#include <lib/base/ebase.h>
+#include <lib/base/object.h>
+#include <lib/base/eptrlist.h>
+#include <lib/dvb/idvb.h>
+
+class eDVBResourceManager;
+class eDVBRegisteredFrontend;
+
+class eFBCTunerManager: public iObject, public Object
+{
+private:
+       DECLARE_REF(eFBCTunerManager);
+       ePtr<eDVBResourceManager> m_res_mgr;
+       int m_fbc_tuner_num;
+       static bool isDestroyed;
+
+       int getFBCTunerNum();
+       void procInit();
+       bool isSameFbcSet(int a, int b);
+       bool isSupportDVBS(eDVBRegisteredFrontend *fe);
+       int getFBCID(int root_fe_id);
+
+       eDVBRegisteredFrontend *getPrev(eDVBRegisteredFrontend *fe);
+       eDVBRegisteredFrontend *getNext(eDVBRegisteredFrontend *fe);
+       eDVBRegisteredFrontend *getTop(eDVBRegisteredFrontend *fe);
+       eDVBRegisteredFrontend *getLast(eDVBRegisteredFrontend *fe);
+       bool isLinked(eDVBRegisteredFrontend *fe);
+       bool isLinkedByIndex(int fe_idx);
+       bool checkTop(eDVBRegisteredFrontend *fe);
+       int connectLinkByIndex(int link_fe_index, int prev_fe_index, int next_fe_index, bool simulate);
+       int connectLinkByIndex(int link_fe_index, int prev_fe_index, bool simulate);
+       int disconnectLinkByIndex(int link_fe_index, int prev_fe_index, int next_fe_index, bool simulate);
+       int disconnectLinkByIndex(int link_fe_index, int prev_fe_index, bool simulate);
+       int connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate);
+       int connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, bool simulate);
+       int disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate);
+       int disconnectLink(eDVBRegisteredFrontend *linkable_fe, eDVBRegisteredFrontend *top_fe, bool simulate);
+       void connectLinkNoSimulate(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe);
+       void disconnectLinkNoSimulate(eDVBRegisteredFrontend *link_fe);
+
+       bool checkUsed(eDVBRegisteredFrontend *fe, bool a_simulate);
+       void connectSortedLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate);
+       int updateLNBSlotMask(int dest_slot, int src_slot, bool remove);
+       void printLinks(eDVBRegisteredFrontend *fe);
+
+public:
+       eFBCTunerManager();
+       virtual ~eFBCTunerManager();
+       int setProcFBCID(int fe_id, int fbc_id);
+       int setDefaultFBCID(eDVBRegisteredFrontend *fe);
+       void updateFBCID(eDVBRegisteredFrontend *next_fe, eDVBRegisteredFrontend *prev_fe);
+       bool isRootFeSlot(int fe_slot_id);
+       bool isRootFe(eDVBRegisteredFrontend *fe);
+       bool canLink(eDVBRegisteredFrontend *fe);
+       bool isUnicable(eDVBRegisteredFrontend *fe);
+       int isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, bool simulate);
+       int isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *&fbc_fe, bool simulate);
+       void addLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate);
+       void unset(eDVBRegisteredFrontend *fe);
+       bool canAllocateLink(eDVBRegisteredFrontend *fe, bool simulate);
+
+       static eFBCTunerManager* getInstance()
+       {
+               if (isDestroyed == true)
+               {
+                       eDebug("eFBCTunerManager is already destroyed!");
+                       return 0;
+               }
+               static eFBCTunerManager instance;
+               return &instance;
+       }
+
+       int getLinkedSlotID(int feid);
+};
+
+#endif /* __dvb_fbc_h */
\ No newline at end of file
index ae40483..1e7cb6b 100755 (executable)
@@ -502,7 +502,7 @@ int eDVBFrontend::PreferredFrontendIndex=-1;
 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate, eDVBFrontend *simulate_fe)
        :m_simulate(simulate), m_enabled(false), m_simulate_fe(simulate_fe), m_dvbid(fe), m_slotid(fe)
        ,m_fd(-1), m_rotor_mode(false), m_need_rotor_workaround(false)
 eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate, eDVBFrontend *simulate_fe)
        :m_simulate(simulate), m_enabled(false), m_simulate_fe(simulate_fe), m_dvbid(fe), m_slotid(fe)
        ,m_fd(-1), m_rotor_mode(false), m_need_rotor_workaround(false)
-       ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0)
+       ,m_state(stateClosed), m_timeout(0), m_tuneTimer(0), m_fbc(false)
 #if HAVE_DVB_API_VERSION < 3
        ,m_secfd(-1)
 #endif
 #if HAVE_DVB_API_VERSION < 3
        ,m_secfd(-1)
 #endif
@@ -525,6 +525,11 @@ eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate, eDVBFronten
 
        m_idleInputpower[0]=m_idleInputpower[1]=0;
 
 
        m_idleInputpower[0]=m_idleInputpower[1]=0;
 
+       char fileName[32] = {0};
+       sprintf(fileName, "/proc/stb/frontend/%d/fbc_id", m_slotid);
+       if (access(fileName, F_OK) == 0)
+               m_fbc = true;
+
        ok = !openFrontend();
        closeFrontend();
 }
        ok = !openFrontend();
        closeFrontend();
 }
@@ -2961,7 +2966,6 @@ RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateCh
 
 RESULT eDVBFrontend::setVoltage(int voltage)
 {
 
 RESULT eDVBFrontend::setVoltage(int voltage)
 {
-
 #if HAVE_DVB_API_VERSION < 3
        secVoltage vlt;
 #else
 #if HAVE_DVB_API_VERSION < 3
        secVoltage vlt;
 #else
@@ -3050,6 +3054,7 @@ RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc)
 {
        if (m_simulate)
                return 0;
 {
        if (m_simulate)
                return 0;
+
 #if HAVE_DVB_API_VERSION < 3
        struct secCommand cmd;
        cmd.type = SEC_CMDTYPE_DISEQC_RAW;
 #if HAVE_DVB_API_VERSION < 3
        struct secCommand cmd;
        cmd.type = SEC_CMDTYPE_DISEQC_RAW;
@@ -3269,7 +3274,7 @@ bool eDVBFrontend::setSlotInfo(ePyObject obj)
 //                     m_slotid, m_description);
                return false;
        }
 //                     m_slotid, m_description);
                return false;
        }
-       m_enabled = Enabled == Py_True;
+       m_enabled = (Enabled == Py_True);
        // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
        m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
                !!strstr(m_description, "Alps BSBE2") ||
        // HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
        m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
                !!strstr(m_description, "Alps BSBE2") ||
@@ -3285,8 +3290,9 @@ bool eDVBFrontend::setSlotInfo(ePyObject obj)
                /* HACK for legacy dvb api without DELSYS support */
                m_delsys[SYS_DVBT2] = true;
        }
                /* HACK for legacy dvb api without DELSYS support */
                m_delsys[SYS_DVBT2] = true;
        }
+
        eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s, DVB-T2 %s",
        eDebugNoSimulate("setSlotInfo for dvb frontend %d to slotid %d, descr %s, need rotorworkaround %s, enabled %s, DVB-S2 %s, DVB-T2 %s",
-               m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", m_enabled == Py_True ? "Yes" : "No", IsDVBS2 == Py_True ? "Yes" : "No", IsDVBT2 == Py_True ? "Yes" : "No" );
+               m_dvbid, m_slotid, m_description, m_need_rotor_workaround ? "Yes" : "No", Enabled == Py_True ? "Yes" : "No", IsDVBS2 == Py_True ? "Yes" : "No", IsDVBT2 == Py_True ? "Yes" : "No" );
        return true;
 arg_error:
        PyErr_SetString(PyExc_StandardError,
        return true;
 arg_error:
        PyErr_SetString(PyExc_StandardError,
index 11c5dfd..e6e3aea 100644 (file)
@@ -73,6 +73,7 @@ private:
        DECLARE_REF(eDVBFrontend);
        bool m_simulate;
        bool m_enabled;
        DECLARE_REF(eDVBFrontend);
        bool m_simulate;
        bool m_enabled;
+       bool m_fbc;
        eDVBFrontend *m_simulate_fe; // only used to set frontend type in dvb.cpp
        int m_dvbid;
        int m_slotid;
        eDVBFrontend *m_simulate_fe; // only used to set frontend type in dvb.cpp
        int m_dvbid;
        int m_slotid;
@@ -146,6 +147,7 @@ public:
        static int getTypePriorityOrder() { return PriorityOrder; }
        static void setPreferredFrontend(int index) { PreferredFrontendIndex = index; }
        static int getPreferredFrontend() { return PreferredFrontendIndex; }
        static int getTypePriorityOrder() { return PriorityOrder; }
        static void setPreferredFrontend(int index) { PreferredFrontendIndex = index; }
        static int getPreferredFrontend() { return PreferredFrontendIndex; }
+
        bool supportsDeliverySystem(const fe_delivery_system_t &sys, bool obeywhitelist);
        void setDeliverySystemWhitelist(const std::vector<fe_delivery_system_t> &whitelist);
 
        bool supportsDeliverySystem(const fe_delivery_system_t &sys, bool obeywhitelist);
        void setDeliverySystemWhitelist(const std::vector<fe_delivery_system_t> &whitelist);
 
@@ -154,6 +156,9 @@ public:
        int closeFrontend(bool force=false, bool no_delayed=false);
        const char *getDescription() const { return m_description; }
        bool is_simulate() const { return m_simulate; }
        int closeFrontend(bool force=false, bool no_delayed=false);
        const char *getDescription() const { return m_description; }
        bool is_simulate() const { return m_simulate; }
+       bool is_FBCTuner() { return m_fbc; }
+       bool getEnabled() { return m_enabled; }
+       void setEnabled(bool enable) { m_enabled = enable; }
 };
 
 #endif // SWIG
 };
 
 #endif // SWIG
index febfd78..6f0c9ee 100644 (file)
@@ -268,7 +268,7 @@ void eDVBServicePMTHandler::AITready(int error)
                                std::string boundaryExtension = "";
                                
                                int controlCode = (*i)->getApplicationControlCode();
                                std::string boundaryExtension = "";
                                
                                int controlCode = (*i)->getApplicationControlCode();
-                               ApplicationIdentifier * applicationIdentifier = (*i)->getApplicationIdentifier();
+                               const ApplicationIdentifier * applicationIdentifier = (*i)->getApplicationIdentifier();
                                profilecode = 0;
                                orgid = applicationIdentifier->getOrganisationId();
                                appid = applicationIdentifier->getApplicationId();
                                profilecode = 0;
                                orgid = applicationIdentifier->getOrganisationId();
                                appid = applicationIdentifier->getApplicationId();
@@ -285,7 +285,7 @@ void eDVBServicePMTHandler::AITready(int error)
                                                case APPLICATION_DESCRIPTOR:
                                                {
                                                        ApplicationDescriptor* applicationDescriptor = (ApplicationDescriptor*)(*desc);
                                                case APPLICATION_DESCRIPTOR:
                                                {
                                                        ApplicationDescriptor* applicationDescriptor = (ApplicationDescriptor*)(*desc);
-                                                       ApplicationProfileList* applicationProfiles = applicationDescriptor->getApplicationProfiles();
+                                                       const ApplicationProfileList* applicationProfiles = applicationDescriptor->getApplicationProfiles();
                                                        ApplicationProfileConstIterator interactionit = applicationProfiles->begin();
                                                        for(; interactionit != applicationProfiles->end(); ++interactionit)
                                                        {
                                                        ApplicationProfileConstIterator interactionit = applicationProfiles->begin();
                                                        for(; interactionit != applicationProfiles->end(); ++interactionit)
                                                        {
@@ -353,7 +353,7 @@ void eDVBServicePMTHandler::AITready(int error)
                                }
                                if(!hbbtvUrl.empty())
                                {
                                }
                                if(!hbbtvUrl.empty())
                                {
-                                       char* uu = hbbtvUrl.c_str();
+                                       const char* uu = hbbtvUrl.c_str();
                                        if(!strncmp(uu, "http://", 7) || !strncmp(uu, "dvb://", 6) || !strncmp(uu, "https://", 8))
                                        {
                                                if(controlCode == 1) m_HBBTVUrl = hbbtvUrl;
                                        if(!strncmp(uu, "http://", 7) || !strncmp(uu, "dvb://", 6) || !strncmp(uu, "https://", 8))
                                        {
                                                if(controlCode == 1) m_HBBTVUrl = hbbtvUrl;
@@ -420,7 +420,7 @@ void eDVBServicePMTHandler::OCready(int error)
        {
                for (std::vector<OCSection*>::const_iterator it = ptr->getSections().begin(); it != ptr->getSections().end(); ++it)
                {
        {
                for (std::vector<OCSection*>::const_iterator it = ptr->getSections().begin(); it != ptr->getSections().end(); ++it)
                {
-                       unsigned char* sectionData = (*it)->getData();
+                       unsigned char* sectionData = (unsigned char*)(*it)->getData();
                }
        }
        /* for now, do not keep listening for table updates */
                }
        }
        /* for now, do not keep listening for table updates */
@@ -571,6 +571,13 @@ int eDVBServicePMTHandler::getProgramInfo(program &program)
                                                video.type = videoStream::vtMPEG4_H264;
                                                isvideo = 1;
                                                //break; fall through !!!
                                                video.type = videoStream::vtMPEG4_H264;
                                                isvideo = 1;
                                                //break; fall through !!!
+                                       case 0x24: // H265 HEVC
+                                               if (!isvideo)
+                                               {
+                                                       video.type = videoStream::vtH265_HEVC;
+                                                       isvideo = 1;
+                                               }
+                                               //break; fall through !!!
                                        case 0x10: // MPEG 4 Part 2
                                                if (!isvideo)
                                                {
                                        case 0x10: // MPEG 4 Part 2
                                                if (!isvideo)
                                                {
index 98ace2b..b15c95b 100644 (file)
@@ -194,7 +194,7 @@ public:
        {
                int pid;
                int component_tag;
        {
                int pid;
                int component_tag;
-               enum { vtMPEG2, vtMPEG4_H264, vtMPEG1, vtMPEG4_Part2, vtVC1, vtVC1_SM };
+               enum { vtMPEG2, vtMPEG4_H264, vtMPEG1, vtMPEG4_Part2, vtVC1, vtVC1_SM, vtH265_HEVC };
                int type;
        };
        
                int type;
        };
        
index fb6f204..969ed9f 100644 (file)
@@ -381,6 +381,7 @@ void eDVBScan::PMTready(int err)
                                switch ((*es)->getType())
                                {
                                case 0x1b: // AVC Video Stream (MPEG4 H264)
                                switch ((*es)->getType())
                                {
                                case 0x1b: // AVC Video Stream (MPEG4 H264)
+                               case 0x24: // H265 HEVC
                                case 0x10: // MPEG 4 Part 2
                                case 0x01: // MPEG 1 video
                                case 0x02: // MPEG 2 video
                                case 0x10: // MPEG 4 Part 2
                                case 0x01: // MPEG 1 video
                                case 0x02: // MPEG 2 video
index 08976ef..d1567ba 100644 (file)
@@ -49,11 +49,6 @@ eDVBSatelliteEquipmentControl::eDVBSatelliteEquipmentControl(eSmartPtrList<eDVBR
                if (!simulate) \
                        eSecDebug(x); \
        } while(0)
                if (!simulate) \
                        eSecDebug(x); \
        } while(0)
-//             else \
-//             { \
-//                     eDebugNoNewLine("SIMULATE:"); \
-//                     eDebug(x); \
-//             } \
 
 int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite &sat, iDVBFrontend *fe, int slot_id, int *highest_score_lnb)
 {
 
 int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite &sat, iDVBFrontend *fe, int slot_id, int *highest_score_lnb)
 {
@@ -279,11 +274,6 @@ bool need_turn_fast(int turn_speed)
                if (!simulate) \
                        eDebug(x); \
        } while(0)
                if (!simulate) \
                        eDebug(x); \
        } while(0)
-//             else \
-//             { \
-//                     eDebugNoNewLine("SIMULATE:"); \
-//                     eDebug(x); \
-//             } \
 
 RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPARAMETERS &parm, const eDVBFrontendParametersSatellite &sat, int slot_id, unsigned int tunetimeout)
 {
 
 RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPARAMETERS &parm, const eDVBFrontendParametersSatellite &sat, int slot_id, unsigned int tunetimeout)
 {
@@ -1166,6 +1156,13 @@ RESULT eDVBSatelliteEquipmentControl::clear()
                it->m_frontend->setData(eDVBFrontend::ROTOR_POS, -1);
                it->m_frontend->setData(eDVBFrontend::ROTOR_CMD, -1);
                it->m_frontend->setData(eDVBFrontend::SATCR, -1);
                it->m_frontend->setData(eDVBFrontend::ROTOR_POS, -1);
                it->m_frontend->setData(eDVBFrontend::ROTOR_CMD, -1);
                it->m_frontend->setData(eDVBFrontend::SATCR, -1);
+
+               if (it->m_frontend->is_FBCTuner())
+               {
+                       eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
+                       if (fbcmng)
+                               fbcmng->setDefaultFBCID(*it);
+               }
        }
 
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_simulate_frontends.begin()); it != m_avail_simulate_frontends.end(); ++it)
        }
 
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_simulate_frontends.begin()); it != m_avail_simulate_frontends.end(); ++it)
@@ -1610,6 +1607,12 @@ RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
                        char c;
                        p1->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)p2);
                        p2->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)p1);
                        char c;
                        p1->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)p2);
                        p2->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)p1);
+
+                       eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
+                       if (p1->m_frontend->is_FBCTuner() && fbcmng)
+                       {
+                               fbcmng->updateFBCID(p1, p2);
+                       }
                }
 
                p1=p2=NULL;
                }
 
                p1=p2=NULL;
index ca3e7f2..d176498 100644 (file)
@@ -4,6 +4,8 @@
 #include <lib/dvb/idvb.h>
 #include <list>
 
 #include <lib/dvb/idvb.h>
 #include <list>
 
+#include <lib/dvb/fbc.h>
+
 #ifndef SWIG
 class eSecCommand
 {
 #ifndef SWIG
 class eSecCommand
 {
@@ -379,6 +381,8 @@ public:
        void setRotorMoving(int, bool); // called from the frontend's
        bool isRotorMoving();
        bool canMeasureInputPower() { return m_canMeasureInputPower; }
        void setRotorMoving(int, bool); // called from the frontend's
        bool isRotorMoving();
        bool canMeasureInputPower() { return m_canMeasureInputPower; }
+
+       friend class eFBCTunerManager;
 };
 
 #endif
 };
 
 #endif
index fd33298..e0da3eb 100644 (file)
@@ -1,4 +1,5 @@
 #define PNG_SKIP_SETJMP_CHECK
 #define PNG_SKIP_SETJMP_CHECK
+#include <zlib.h>
 #include <png.h>
 #include <stdio.h>
 #include <lib/gdi/epng.h>
 #include <png.h>
 #include <stdio.h>
 #include <lib/gdi/epng.h>
@@ -52,7 +53,7 @@ int loadPNG(ePtr<gPixmap> &result, const char *filename)
                fclose(fp);
                return 0;
         }
                fclose(fp);
                return 0;
         }
-       if (setjmp(png_ptr->jmpbuf))
+       if ( setjmp(png_jmpbuf(png_ptr)) )
        {
                eDebug("das war wohl nix");
                png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        {
                eDebug("das war wohl nix");
                png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
@@ -262,7 +263,7 @@ int savePNG(const char *filename, gPixmap *pixmap)
                PNG_COLOR_TYPE_RGB_ALPHA, 
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
 
                PNG_COLOR_TYPE_RGB_ALPHA, 
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
 
-       if (setjmp(png_ptr->jmpbuf))
+       if ( setjmp(png_jmpbuf(png_ptr)) )
        {
                eDebug("error :/");
                png_destroy_write_struct(&png_ptr, &info_ptr);
        {
                eDebug("error :/");
                png_destroy_write_struct(&png_ptr, &info_ptr);
index 2afebd5..ab7a0b5 100644 (file)
@@ -280,7 +280,7 @@ static unsigned char *png_load(const char *file, int *ox, int *oy, int *_bypp)
                return NULL;
        }
 
                return NULL;
        }
 
-       if (setjmp(png_ptr->jmpbuf))
+       if (setjmp(png_jmpbuf(png_ptr)))
        {
                png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
                fclose(fh);
        {
                png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
                fclose(fh);
index ca4ef9e..1221f8f 100755 (executable)
@@ -29,6 +29,33 @@ def getProcMounts():
                item[1] = item[1].replace('\\040', ' ')
        return result
 
                item[1] = item[1].replace('\\040', ' ')
        return result
 
+def CheckSfdiskVer():
+       cmd = 'sfdisk --version'
+       lines = popen(cmd).readlines()
+       for l in lines:
+               if l.find("sfdisk from util-linux") != -1:
+                       ver = l.split()[-1].strip()
+                       break
+       try:
+               vs = ver.split('.')
+               if len(vs) > 2:
+                       ver = '.'.join(vs[:2])
+
+               ver = float(ver)
+       except:
+               print "[CheckSfdiskVer] check parted version Failed!"
+               return 0
+       return ver
+
+def enableUdevEvent(enable = True):
+       if enable:
+               option = '--start-exec-queue'
+       else:
+               option = '--stop-exec-queue'
+       cmd = "udevadm control %s" % option
+       print "CMD : ", cmd
+       system(cmd)
+
 DEVTYPE_UDEV = 0
 DEVTYPE_DEVFS = 1
 
 DEVTYPE_UDEV = 0
 DEVTYPE_DEVFS = 1
 
@@ -225,6 +252,7 @@ class Harddisk:
                                pass
 
                res = system(cmd)
                                pass
 
                res = system(cmd)
+               print "CMD : ", cmd
                return (res >> 8)
 
         def checkPartionPath(self, path):
                return (res >> 8)
 
         def checkPartionPath(self, path):
@@ -235,6 +263,22 @@ class Harddisk:
                         time.sleep(1)
                 return False
 
                         time.sleep(1)
                 return False
 
+       def updatePartition(self):
+               sfdiskVer = CheckSfdiskVer()
+               if sfdiskVer < 2.26: # sfdisk -R option is deprecated at sfdiskVer >= 2.26
+                       cmd = 'sfdisk -R %s; sleep 5' % (self.disk_path)
+               elif path.exists('/usr/sbin/partprobe'):
+                       cmd = 'partprobe %s; sleep 5' % (self.disk_path)
+               elif path.exists('/usr/sbin/partx'):
+                       cmd = 'partx -u %s' % (self.disk_path)
+               else:
+                       return -1
+
+               print "CMD : ", cmd
+               res = system(cmd)
+
+               return (res >> 8)
+
        def createPartition(self):
                def CheckPartedVer():
                        cmd = 'parted --version'
        def createPartition(self):
                def CheckPartedVer():
                        cmd = 'parted --version'
@@ -260,9 +304,15 @@ class Harddisk:
                        cmd = 'parted %s %s --script mklabel gpt mkpart disk ext2 0%% 100%%' % ( setAlign, self.disk_path )
 
                else:
                        cmd = 'parted %s %s --script mklabel gpt mkpart disk ext2 0%% 100%%' % ( setAlign, self.disk_path )
 
                else:
-                       cmd = 'printf "8,\n;0,0\n;0,0\n;0,0\ny\n" | sfdisk -f -uS ' + self.disk_path
+                       sfdiskVer = CheckSfdiskVer()
+                       if sfdiskVer <= 2.21:
+                               cmd = 'printf "8,\n;0,0\n;0,0\n;0,0\ny\n" | sfdisk -f -uS ' + self.disk_path
+                       else:
+                               cmd = 'printf "8,\nquit\nY\n" | sfdisk -f -uS ' + self.disk_path
 
 
+               print "CMD : ", cmd
                res = system(cmd)
                res = system(cmd)
+
                if not self.checkPartionPath(self.partitionPath("1")):
                        print "no exist : ", self.partitionPath("1")
                        return 1
                if not self.checkPartionPath(self.partitionPath("1")):
                        print "no exist : ", self.partitionPath("1")
                        return 1
@@ -273,6 +323,7 @@ class Harddisk:
                if self.diskSize() > 4 * 1024:
                        cmd += "-T largefile "
                cmd += "-m0 -O dir_index " + self.partitionPath("1")
                if self.diskSize() > 4 * 1024:
                        cmd += "-T largefile "
                cmd += "-m0 -O dir_index " + self.partitionPath("1")
+               print "CMD : ", cmd
                res = system(cmd)
                return (res >> 8)
 
                res = system(cmd)
                return (res >> 8)
 
@@ -286,20 +337,33 @@ class Harddisk:
                fstab.close()
 
                res = -1
                fstab.close()
 
                res = -1
+               mount_point = None
                for line in lines:
                        parts = line.strip().split(" ")
                for line in lines:
                        parts = line.strip().split(" ")
-                        real_path = path.realpath(parts[0])                                                 
-                        if not real_path[-1].isdigit():                                                     
-                                continue                                                                    
-                        try:                                                                                
-                                if MajorMinor(real_path) == MajorMinor(self.partitionPath(real_path[-1])):
-                                       cmd = "mount -t ext3 " + parts[0]
-                                       res = system(cmd)
+                       real_path = path.realpath(parts[0])
+                       if not real_path[-1].isdigit():
+                               continue
+                       try:
+                               if MajorMinor(real_path) == MajorMinor(self.partitionPath(real_path[-1])):
+                                       mount_point = parts[0]
                                        break
                        except OSError:
                                pass
 
                                        break
                        except OSError:
                                pass
 
-               return (res >> 8)
+               if mount_point is None:
+                       return 0
+
+               cmd = "mount -t ext3 " + mount_point
+               print "CMD : ", cmd
+               res = system(cmd)
+
+               if (res >> 8) != 0:
+                       return -3
+
+               if self.createMovieFolder() != 0:
+                       return -4
+
+               return 0
 
        def createMovieFolder(self):
                try:
 
        def createMovieFolder(self):
                try:
@@ -324,15 +388,17 @@ class Harddisk:
 
                if access(part, 0):
                        cmd = 'dd bs=512 count=3 if=/dev/zero of=' + part
 
                if access(part, 0):
                        cmd = 'dd bs=512 count=3 if=/dev/zero of=' + part
+                       print "CMD : ", cmd
                        res = system(cmd)
                else:
                        res = 0
 
                return (res >> 8)
 
                        res = system(cmd)
                else:
                        res = 0
 
                return (res >> 8)
 
-       errorList = [ _("Everything is fine"), _("Creating partition failed"), _("Mkfs failed"), _("Mount failed"), _("Create movie folder failed"), _("Fsck failed"), _("Please Reboot"), _("Filesystem contains uncorrectable errors"), _("Unmount failed")]
+       errorList = [ _("Everything is fine"), _("Creating partition failed"), _("Mkfs failed"), _("Mount failed"), _("Create movie folder failed"), _("Fsck failed"), _("Please Reboot"), _("Filesystem contains uncorrectable errors"), _("Unmount failed"), _("partx failed")]
 
        def initialize(self):
 
        def initialize(self):
+               enableUdevEvent(False)
                self.unmount()
 
                # Udev tries to mount the partition immediately if there is an
                self.unmount()
 
                # Udev tries to mount the partition immediately if there is an
@@ -342,19 +408,23 @@ class Harddisk:
                # ext3 at least.
                self.killPartition("1")
 
                # ext3 at least.
                self.killPartition("1")
 
-               if self.createPartition() != 0:
-                       return -1
+               if self.updatePartition() != 0:
+                       res = -9
 
 
-               if self.mkfs() != 0:
-                       return -2
+               elif self.createPartition() != 0:
+                       res = -1
 
 
-               if self.mount() != 0:
-                       return -3
+               elif self.updatePartition() != 0:
+                       res = -9
 
 
-               if self.createMovieFolder() != 0:
-                       return -4
+               elif self.mkfs() != 0:
+                       res = -2
 
 
-               return 0
+               else:
+                       res = self.mount()
+
+               enableUdevEvent(True)
+               return res
 
        def check(self):
                self.unmount()
 
        def check(self):
                self.unmount()
@@ -571,7 +641,7 @@ class HarddiskManager:
                try:
                        removable = bool(int(readFile(devpath + "/removable")))
                        dev = int(readFile(devpath + "/dev").split(':')[0])
                try:
                        removable = bool(int(readFile(devpath + "/removable")))
                        dev = int(readFile(devpath + "/dev").split(':')[0])
-                       if dev in (7, 31): # loop, mtdblock
+                       if dev in (7, 31, 179): # loop, mtdblock, mmcblock
                                blacklisted = True
                        if blockdev[0:2] == 'sr':
                                is_cdrom = True
                                blacklisted = True
                        if blockdev[0:2] == 'sr':
                                is_cdrom = True
index ce063b4..2a40aed 100755 (executable)
@@ -59,10 +59,10 @@ class SecConfigure:
                sec.setLNBLOFL(9750000)
                sec.setLNBLOFH(10600000)
                sec.setLNBThreshold(11700000)
                sec.setLNBLOFL(9750000)
                sec.setLNBLOFH(10600000)
                sec.setLNBThreshold(11700000)
-               sec.setLNBIncreasedVoltage(lnbParam.OFF)
+               sec.setLNBIncreasedVoltage(False)
                sec.setRepeats(0)
                sec.setFastDiSEqC(fastDiSEqC)
                sec.setRepeats(0)
                sec.setFastDiSEqC(fastDiSEqC)
-               sec.setSeqRepeat(0)
+               sec.setSeqRepeat(False)
                sec.setCommandOrder(0)
 
                #user values
                sec.setCommandOrder(0)
 
                #user values
@@ -369,9 +369,9 @@ class SecConfigure:
 #                                      pass # nyi in drivers
 
                                if currLnb.increased_voltage.value:
 #                                      pass # nyi in drivers
 
                                if currLnb.increased_voltage.value:
-                                       sec.setLNBIncreasedVoltage(lnbParam.ON)
+                                       sec.setLNBIncreasedVoltage(True)
                                else:
                                else:
-                                       sec.setLNBIncreasedVoltage(lnbParam.OFF)
+                                       sec.setLNBIncreasedVoltage(False)
 
                                dm = currLnb.diseqcMode.value
                                if dm == "none":
 
                                dm = currLnb.diseqcMode.value
                                if dm == "none":
@@ -1116,7 +1116,7 @@ def InitSecParams():
 # the C(++) part should can handle this
 # the configElement should be only visible when diseqc 1.2 is disabled
 
 # the C(++) part should can handle this
 # the configElement should be only visible when diseqc 1.2 is disabled
 
-def InitNimManager(nimmgr):
+def InitNimManager(nimmgr, update_slots = []):
        hw = HardwareInfo()
        addNimConfig = False
        try:
        hw = HardwareInfo()
        addNimConfig = False
        try:
@@ -1646,6 +1646,9 @@ def InitNimManager(nimmgr):
                x = slot.slot
                nim = config.Nims[x]
 
                x = slot.slot
                nim = config.Nims[x]
 
+               if update_slots and (x not in update_slots):
+                       continue
+
                if slot.isCompatible("DVB-S"):
                        createSatConfig(nim, x, empty_slots)
                        config_mode_choices = [ ("nothing", _("nothing connected")),
                if slot.isCompatible("DVB-S"):
                        createSatConfig(nim, x, empty_slots)
                        config_mode_choices = [ ("nothing", _("nothing connected")),
index cd055a8..3930c07 100644 (file)
@@ -113,6 +113,16 @@ class ServiceList(HTMLComponent, GUIComponent):
                self.l.getCurrent(r)
                return r
 
                self.l.getCurrent(r)
                return r
 
+       def getPrev(self):
+               r = eServiceReference()
+               self.l.getPrev(r)
+               return r
+
+       def getNext(self):
+               r = eServiceReference()
+               self.l.getNext(r)
+               return r
+
        def atBegin(self):
                return self.instance.atBegin()
 
        def atBegin(self):
                return self.instance.atBegin()
 
index 8d8805f..821fe1d 100644 (file)
@@ -3,10 +3,6 @@ installdir = $(pkglibdir)/python/Plugins/Extensions/DLNAServer
 SUBDIRS = meta 
 
 install_PYTHON = \
 SUBDIRS = meta 
 
 install_PYTHON = \
-       dlnaserver \
        __init__.py \
        plugin.py 
 
        __init__.py \
        plugin.py 
 
-install-data-hook:
-       @chmod +x $(DESTDIR)$(installdir)/dlnaserver
-
diff --git a/lib/python/Plugins/Extensions/DLNAServer/dlnaserver b/lib/python/Plugins/Extensions/DLNAServer/dlnaserver
deleted file mode 100755 (executable)
index 4fad9ab..0000000
Binary files a/lib/python/Plugins/Extensions/DLNAServer/dlnaserver and /dev/null differ
index 9dd4299..d94b791 100755 (executable)
@@ -1,7 +1,7 @@
 installdir = $(pkglibdir)/python/Plugins/Extensions
 
 SUBDIRS = TuxboxPlugins CutListEditor PicturePlayer MediaScanner MediaPlayer GraphMultiEPG SocketMMI DVDBurn Modem WebBrowser \
 installdir = $(pkglibdir)/python/Plugins/Extensions
 
 SUBDIRS = TuxboxPlugins CutListEditor PicturePlayer MediaScanner MediaPlayer GraphMultiEPG SocketMMI DVDBurn Modem WebBrowser \
-       StreamTV DLNABrowser DLNAServer HbbTV BackupSuiteUSB BackupSuiteHDD SatipClient
+       StreamTV DLNABrowser DLNAServer HbbTV BackupSuiteUSB BackupSuiteHDD SatipClient MiniTV
 
 if HAVE_LIBDDVD
 SUBDIRS += DVDPlayer
 
 if HAVE_LIBDDVD
 SUBDIRS += DVDPlayer
diff --git a/lib/python/Plugins/Extensions/MiniTV/Makefile.am b/lib/python/Plugins/Extensions/MiniTV/Makefile.am
new file mode 100644 (file)
index 0000000..98f2931
--- /dev/null
@@ -0,0 +1,7 @@
+installdir = $(pkglibdir)/python/Plugins/Extensions/MiniTV
+
+SUBDIRS = meta
+
+install_PYTHON =       \
+       __init__.py \
+       plugin.py
diff --git a/lib/python/Plugins/Extensions/MiniTV/__init__.py b/lib/python/Plugins/Extensions/MiniTV/__init__.py
new file mode 100644 (file)
index 0000000..139597f
--- /dev/null
@@ -0,0 +1,2 @@
+
+
diff --git a/lib/python/Plugins/Extensions/MiniTV/meta/Makefile.am b/lib/python/Plugins/Extensions/MiniTV/meta/Makefile.am
new file mode 100644 (file)
index 0000000..2d31de6
--- /dev/null
@@ -0,0 +1,3 @@
+installdir = $(datadir)/meta
+
+dist_install_DATA = plugin_minitv.xml
diff --git a/lib/python/Plugins/Extensions/MiniTV/meta/plugin_minitv.xml b/lib/python/Plugins/Extensions/MiniTV/meta/plugin_minitv.xml
new file mode 100644 (file)
index 0000000..d7dbe58
--- /dev/null
@@ -0,0 +1,17 @@
+<default>
+         <prerequisites>
+                    <tag type="Display" />
+                    <tag type="System" />
+         </prerequisites>
+          <info>
+                    <author>hschang</author>
+                    <name>MiniTV</name>
+                    <packagename>enigma2-plugin-extensions-minitv</packagename>
+                    <shortdescription>Support MiniTV of your VU+</shortdescription>
+                    <description>Support MiniTV of your VU+</description>
+          </info>
+
+         <files type="package"> <!-- without version, without .ipk -->
+               <file type="package" name="enigma2-plugin-extensions-minitv" />
+       </files>
+</default>
diff --git a/lib/python/Plugins/Extensions/MiniTV/plugin.py b/lib/python/Plugins/Extensions/MiniTV/plugin.py
new file mode 100644 (file)
index 0000000..1bf8a4a
--- /dev/null
@@ -0,0 +1,66 @@
+from Plugins.Plugin import PluginDescriptor
+from Components.PluginComponent import plugins
+from Components.config import config, ConfigSubsection, ConfigSelection
+from enigma import eDBoxLCD
+
+config.plugins.minitv = ConfigSubsection()
+config.plugins.minitv.enable = ConfigSelection(default = "disable", choices = [ ("enable", "enable"), ("disable", "disable")])
+
+class MiniTV:
+       def __init__(self):
+               config.plugins.minitv.enable.addNotifier(self.miniTVChanged, initial_call = True)
+               config.misc.standbyCounter.addNotifier(self.standbyCounterChanged, initial_call = False)
+
+       def getExtensionName(self):
+               if config.plugins.minitv.enable.value == "enable":
+                       return _("Disable MiniTV")
+
+               return _("Enable MiniTV")
+
+       def showMiniTV(self):
+               old_value = config.plugins.minitv.enable.value
+               config.plugins.minitv.enable.value = (old_value == "enable") and "disable" or "enable"
+               config.plugins.minitv.enable.save()
+
+       def miniTVChanged(self, configElement):
+               self.setMiniTV(configElement.value)
+
+       def setMiniTV(self, value):
+               cur_value = open("/proc/stb/lcd/live_enable", "r").read().strip()
+               if cur_value != value:
+                       open("/proc/stb/lcd/live_enable", "w").write(value)
+
+       def standbyCounterChanged(self, configElement):
+               from Screens.Standby import inStandby
+               if self.leaveStandby not in inStandby.onClose:
+                       inStandby.onClose.append(self.leaveStandby)
+
+               self.setMiniTV("disable")
+
+       def leaveStandby(self):
+               self.setMiniTV(config.plugins.minitv.enable.value)
+
+minitv_instance = MiniTV()
+
+def addExtentions(infobarExtensions):
+       infobarExtensions.addExtension((minitv_instance.getExtensionName, minitv_instance.showMiniTV, lambda: True), None)
+
+def autoStart(reason, **kwargs):
+       if reason == 1:
+               minitv_instance.setMiniTV("standby")
+
+def Plugins(**kwargs):
+       list = []
+       list.append(
+               PluginDescriptor(name="MiniTV",
+               description="MiniTV",
+               where = [PluginDescriptor.WHERE_EXTENSIONSINGLE],
+               fnc = addExtentions))
+
+       list.append(
+               PluginDescriptor(
+               where = [PluginDescriptor.WHERE_AUTOSTART],
+               fnc = autoStart))
+
+       return list
+
index d87e6e9..2137d0e 100755 (executable)
@@ -60,6 +60,12 @@ class PluginDescriptor:
        # should be provided to name and describe the new menu entry.
        WHERE_SOFTWAREMANAGER = 14
 
        # should be provided to name and describe the new menu entry.
        WHERE_SOFTWAREMANAGER = 14
 
+       WHERE_SATCONFIGCHANGED = 15
+
+       WHERE_SERVICESCAN = 16
+
+       WHERE_EXTENSIONSINGLE = 17
+
 
        def __init__(self, name = "Plugin", where = [ ], description = "", icon = None, fnc = None, wakeupfnc = None, needsRestart = None, internal = False, weight = 0):
                self.name = name
 
        def __init__(self, name = "Plugin", where = [ ], description = "", icon = None, fnc = None, wakeupfnc = None, needsRestart = None, internal = False, weight = 0):
                self.name = name
diff --git a/lib/python/Plugins/SystemPlugins/3GModemManager/3gcommand b/lib/python/Plugins/SystemPlugins/3GModemManager/3gcommand
deleted file mode 100755 (executable)
index ae61799..0000000
Binary files a/lib/python/Plugins/SystemPlugins/3GModemManager/3gcommand and /dev/null differ
index 962f84c..0ac90e0 100644 (file)
@@ -5,9 +5,5 @@ SUBDIRS = meta script
 install_PYTHON = \
        __init__.py \
        plugin.py \
 install_PYTHON = \
        __init__.py \
        plugin.py \
-       apnlist.xml \
-       3gcommand 
-
-install-data-hook:
-       @chmod +x $(DESTDIR)$(installdir)/3gcommand
+       apnlist.xml
 
 
index 40a349e..82ce819 100644 (file)
@@ -149,9 +149,7 @@ class Blindscan(ConfigListScreen, Screen):
                else:   self.i2c_mapping_table = {0:2, 1:3, 2:1, 3:0}
 
        def getNimSocket(self, slot_number):
                else:   self.i2c_mapping_table = {0:2, 1:3, 2:1, 3:0}
 
        def getNimSocket(self, slot_number):
-               if slot_number < 0 or slot_number > 3:
-                       return -1
-               return self.i2c_mapping_table[slot_number]
+               return self.i2c_mapping_table.get(slot_number, -1)
 
        def keyNone(self):
                None
 
        def keyNone(self):
                None
diff --git a/lib/python/Plugins/SystemPlugins/BoxModeConfig/Makefile.am b/lib/python/Plugins/SystemPlugins/BoxModeConfig/Makefile.am
new file mode 100755 (executable)
index 0000000..a7c22ea
--- /dev/null
@@ -0,0 +1,7 @@
+installdir = $(pkglibdir)/python/Plugins/SystemPlugins/BoxModeConfig
+
+SUBDIRS = meta
+
+install_PYTHON = \
+       __init__.py \
+       plugin.py
diff --git a/lib/python/Plugins/SystemPlugins/BoxModeConfig/__init__.py b/lib/python/Plugins/SystemPlugins/BoxModeConfig/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/Makefile.am b/lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/Makefile.am
new file mode 100755 (executable)
index 0000000..8cd9a96
--- /dev/null
@@ -0,0 +1,3 @@
+installdir = $(datadir)/meta
+
+dist_install_DATA = plugin_boxmodeconfig.xml
diff --git a/lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/plugin_boxmodeconfig.xml b/lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/plugin_boxmodeconfig.xml
new file mode 100755 (executable)
index 0000000..67ce9d4
--- /dev/null
@@ -0,0 +1,16 @@
+<default>
+         <prerequisites>
+                    <tag type="System" />
+         </prerequisites>
+          <info>
+                    <author>hschang</author>
+                    <name>BoxModeConfig</name>
+                    <packagename>enigma2-plugin-systemplugins-boxmodeconfig</packagename>
+                    <shortdescription>configuration boxmode.</shortdescription>
+                    <description>configuration boxmode.</description>
+          </info>
+
+         <files type="package"> <!-- without version, without .ipk -->
+               <file type="package" name="enigma2-plugin-systemplugins-boxmodeconfig" />
+       </files>
+</default>
diff --git a/lib/python/Plugins/SystemPlugins/BoxModeConfig/plugin.py b/lib/python/Plugins/SystemPlugins/BoxModeConfig/plugin.py
new file mode 100755 (executable)
index 0000000..abda052
--- /dev/null
@@ -0,0 +1,121 @@
+from Screens.Screen import Screen
+from Components.ConfigList import ConfigListScreen
+from Components.config import ConfigSelection, getConfigListEntry
+from Components.Sources.StaticText import StaticText
+from Screens.MessageBox import MessageBox
+from Screens.Standby import TryQuitMainloop
+import os
+
+BOXMODE_BINNAME = "/usr/bin/nvram"
+
+description_list = {}
+description_list["1"] = "current box mode : 1"
+description_list["2"] = "current box mode : 2"
+description_list["3"] = "current box mode : 3"
+description_list["4"] = "current box mode : 4"
+description_list["5"] = "current box mode : 5"
+
+class BoxModeConfig(Screen, ConfigListScreen):
+       skin =  """
+               <screen position="center,center" size="400,190" title="BoxModeConfig" >
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="30,10" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="230,10" size="140,40" alphatest="on" />
+
+                       <widget source="key_red" render="Label" position="30,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_green" render="Label" position="230,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
+
+                       <widget name="config" zPosition="2" position="5,70" size="380,90" scrollbarMode="showOnDemand" transparent="1" />
+                       <widget source="description" render="Label" position="30,160" size="380,30" font="Regular;24" halign="center" valign="center" />
+               </screen>
+               """
+
+       def __init__(self, session):
+               self.skin = BoxModeConfig.skin
+               Screen.__init__(self, session)
+
+               from Components.ActionMap import ActionMap
+               from Components.Button import Button
+               self["key_red"] = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("Save"))
+               self["description"] = StaticText(_("starting..."))
+
+               self["actions"] = ActionMap(["SetupActions", "ColorActions"],
+               {
+                       "ok": self.keyOk,
+                       "save": self.keyOk,
+                       "cancel": self.keyCancel,
+                       "green": self.keyOk,
+                       "red": self.keyCancel,
+               }, -2)
+
+               self.list = []
+               ConfigListScreen.__init__(self, self.list, session = self.session)
+               setmodelist = [ ("1", "1 "), ("2", "2 "), ("3", "3 "), ("4", "4 "), ("5", "5 ") ]
+               self.oldconfig = self.getCurrentValue()
+               self.boxmode = ConfigSelection(choices = setmodelist, default = self.oldconfig)
+               self.list.append(getConfigListEntry(_("BoxMode : "), self.boxmode))
+               self["config"].list = self.list
+               self["config"].l.setList(self.list)
+
+               if not self.showDescription in self["config"].onSelectionChanged:
+                       self["config"].onSelectionChanged.append(self.showDescription)
+
+       def getCurrentValue(self):
+               global BOXMODE_BINNAME
+               cmd = "%s getenv BOXMODE" % (BOXMODE_BINNAME)
+               print "CMD : ", cmd
+               current_value = os.popen(cmd).read().strip()
+               try:
+                       if int(current_value) < 1:
+                               current_value = "1"
+                       elif int(current_value) > 5:
+                               current_value = "5"
+               except:
+                       print '%s -> failed, force to set "3"' % cmd
+                       current_value = "3"
+               return current_value
+
+       def showDescription(self):
+               global description_list
+               current_value = self["config"].getCurrent()[1].value
+               if current_value:
+                       text = description_list[current_value]
+                       self["description"].setText( _(text) )
+
+       def keyLeft(self):
+               ConfigListScreen.keyLeft(self)
+               self.showDescription()
+
+       def keyRight(self):
+               ConfigListScreen.keyRight(self)
+               self.showDescription()
+
+       def keyOk(self):
+               current_value = self["config"].getCurrent()[1].value
+               if self.oldconfig != current_value:             
+                       cmd = "%s setenv BOXMODE %s" % (BOXMODE_BINNAME, current_value)
+                       print "CMD : ", cmd
+                       os.system(cmd)
+
+                       msg = "You should reboot your STB now.\n Press OK Button."
+                       self.session.openWithCallback(self.doReboot, MessageBox, _(msg), type = MessageBox.TYPE_INFO)
+               else:
+                       self.close()
+
+       def doReboot(self, res = None):
+               self.session.open(TryQuitMainloop, 2)
+
+       def keyCancel(self):
+               self.close()
+
+def main(session, **kwargs):
+       session.open(BoxModeConfig)
+
+def Plugins(**kwargs):
+       descriptors = []
+       from os import path
+       global BOXMODE_BINNAME
+       if path.exists(BOXMODE_BINNAME):
+               from Plugins.Plugin import PluginDescriptor
+               descriptors.append(PluginDescriptor(name = "BoxModeConfig", description = _("BoxMode Configuration."), where = PluginDescriptor.WHERE_PLUGINMENU, fnc = main))
+       return descriptors
\ No newline at end of file
index 6d5860f..41c6905 100755 (executable)
@@ -4,7 +4,7 @@ from Components.config import config, ConfigSelection, getConfigListEntry, Confi
 from Components.ConfigList import ConfigListScreen
 from Components.Console import Console
 from Components.GUIComponent import GUIComponent
 from Components.ConfigList import ConfigListScreen
 from Components.Console import Console
 from Components.GUIComponent import GUIComponent
-from Components.Harddisk import harddiskmanager
+from Components.Harddisk import harddiskmanager, CheckSfdiskVer, enableUdevEvent
 from Components.MenuList import MenuList
 from Components.Pixmap import Pixmap, MultiPixmap
 from Components.Sources.List import List
 from Components.MenuList import MenuList
 from Components.Pixmap import Pixmap, MultiPixmap
 from Components.Sources.List import List
@@ -549,8 +549,10 @@ class DeviceInit(Screen):
                self.maxPartNum = 4
                self.inputbox_partitionSizeRemain = self.inputbox_partitionSizeTotal
                self.unit = "MB"
                self.maxPartNum = 4
                self.inputbox_partitionSizeRemain = self.inputbox_partitionSizeTotal
                self.unit = "MB"
+               self.onClose.append(enableUdevEvent)
 
        def timerStart(self):
 
        def timerStart(self):
+               enableUdevEvent(False)
                self.initStartTimer.start(100,True)
 
        def confirmMessage(self):
                self.initStartTimer.start(100,True)
 
        def confirmMessage(self):
@@ -680,62 +682,66 @@ class DeviceInit(Screen):
                        try:
                                ver = float(ver)
                        except:
                        try:
                                ver = float(ver)
                        except:
-                               print "[CheckPartedVer] check parted version Failed!"
+                               print "[DeviceManager] check parted version Failed!"
                                return 0
                        return ver
 
                partitions = len(self.inputbox_partitionSizeList) # get num of partition
                set = ""
                                return 0
                        return ver
 
                partitions = len(self.inputbox_partitionSizeList) # get num of partition
                set = ""
-               if self.partitionType == "MBR":
-                       if partitions == 1:
-                               cmd = 'printf "8,\n;0,0\n;0,0\n;0,0\ny\n" | sfdisk -f -uS /dev/' + self.device
+
+               setAlign = ""
+               partedVer = CheckPartedVer()
+               if partedVer >= 2.1: # align option is supported in version 2.1 or later
+                       setAlign = "--align optimal"
+                       if self.devicesize < 1024 * 1000 * 1000: # 1GB
+                               setAlign = "-a min"
                        else:
                        else:
-                               for p in range(4):
-                                       if partitions > p+1:
-                                               set += ",%s\n"%(self.inputbox_partitionSizeList[p])
-                                       else:
-                                               set +=";\n"
-                               set+="y\n"
-                               cmd = 'printf "%s" | sfdisk -f -uM /dev/%s'%(set,self.device)
-
-               elif self.partitionType == "GPT": # partition type is GPT
-                       setAlign = ""
-                       partedVer = CheckPartedVer()
-                       if partedVer >= 2.1: # align option is supported in version 2.1 or later
-                               setAlign = "--align optimal"
-
-                       if partitions == 1:
-                               cmd = 'parted %s /dev/%s --script mklabel gpt mkpart disk ext2 0%% 100%%' % (setAlign, self.device)
-                       else: # has multiple partitions
-                               p_current = 0
-                               for p in range(partitions):
-                                       if p == 0:
-                                               p_start = p_current
-                                               p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / 100 )
-                                               p_current = p_end
-                                       elif p > 0 and partitions > (p + 1):
-                                               p_start = p_current
-                                               p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / 100 )+ p_start
-                                               p_current = p_end
-                                       elif partitions == (p + 1):
-                                               p_start = p_current
-                                               p_end = 100
-                                       if p_start == p_end:
-                                               p_end +=1
-                                       if p_end > 100:
-                                               continue
-                                       set += 'mkpart disk%d ext2 %d%% %d%% ' % (p + 1, p_start, p_end)
-                               cmd = 'parted %s /dev/%s --script mklabel gpt %s' % (setAlign, self.device, set)
+                               setAlign = "-a opt"
+
+               if self.partitionType == "GPT": # partition type is GPT
+                       parttype = 'gpt'
                else:
                else:
-                       errorMsg = "Invalid partitioning type"
-                       self.msgWaiting.run_close(False, errorMsg)
-                       return
+                       parttype = 'msdos'
+
+               if partitions == 1:
+                       cmd = 'parted %s /dev/%s --script mklabel %s mkpart primary 0%% 100%%' % (setAlign, self.device, parttype)
+               else: # has multiple partitions
+                       p_current = 0
+                       for p in range(partitions):
+                               if p == 0:
+                                       p_start = p_current
+                                       p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / self.inputbox_partitionSizeTotal )
+                                       p_current = p_end
+                               elif p > 0 and partitions > (p + 1):
+                                       p_start = p_current
+                                       p_end = int( (long(self.inputbox_partitionSizeList[p]) * 100) / self.inputbox_partitionSizeTotal )+ p_start
+                                       p_current = p_end
+                               elif partitions == (p + 1):
+                                       p_start = p_current
+                                       p_end = 100
+
+                               if p_start == p_end:
+                                       p_end +=1
+                               if p_end > 100:
+                                       continue
+
+                               set += 'mkpart primary ext2 %d%% %d%% ' % (p_start, p_end)
+                       cmd = 'parted %s /dev/%s --script mklabel %s %s' % (setAlign, self.device, parttype, set)
+
                self.deviceInitConsole.ePopen(cmd, self.initInitializeFinished)
 
        def initInitializeFinished(self, result, retval, extra_args = None):
                if retval == 0:
                        if self.partitionType == "MBR":
                self.deviceInitConsole.ePopen(cmd, self.initInitializeFinished)
 
        def initInitializeFinished(self, result, retval, extra_args = None):
                if retval == 0:
                        if self.partitionType == "MBR":
-                               cmd = "sfdisk -R /dev/%s ; sleep 5" % (self.device)
+                               sfdiskVer = CheckSfdiskVer()
+                               if sfdiskVer < 2.26: # sfdisk -R option is deprecated at sfdiskVer >= 2.26
+                                       cmd = 'sfdisk -R /dev/%s; sleep 5' % (self.device)
+                               elif path.exists('/usr/sbin/partprobe'):
+                                       cmd = 'partprobe /dev/%s; sleep 5' % (self.device)
+                               elif path.exists('/usr/sbin/partx'):
+                                       cmd = 'partx -u /dev/%s; sleep 5' % (self.device)
+                               else:
+                                       cmd = 'sfdisk -R /dev/%s; sleep 5' % (self.device)
                        else: # is GPT
                                cmd = "sleep 5"
                        self.deviceInitConsole.ePopen(cmd, self.initInitializingRefreshFinished)
                        else: # is GPT
                                cmd = "sleep 5"
                        self.deviceInitConsole.ePopen(cmd, self.initInitializingRefreshFinished)
@@ -780,25 +786,25 @@ class DeviceInit(Screen):
                partitions.close()
 
                if self.fstype == "ext4":
                partitions.close()
 
                if self.fstype == "ext4":
-                       cmd = "/sbin/mkfs.ext4 -F "
+                       cmd = "mkfs.ext4 -F "
                        if partitionsize > 2 * 1024 * 1024: # 2GB
                                cmd += "-T largefile "
                        cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 " + fulldevicename
                elif self.fstype == "ext3":
                        if partitionsize > 2 * 1024 * 1024: # 2GB
                                cmd += "-T largefile "
                        cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 " + fulldevicename
                elif self.fstype == "ext3":
-                       cmd = "/sbin/mkfs.ext3 -F "
+                       cmd = "mkfs.ext3 -F "
                        if partitionsize > 2 * 1024 * 1024:
                                cmd += "-T largefile "
                        cmd += "-m0 " + fulldevicename
                elif self.fstype == "ext2":
                        if partitionsize > 2 * 1024 * 1024:
                                cmd += "-T largefile "
                        cmd += "-m0 " + fulldevicename
                elif self.fstype == "ext2":
-                       cmd = "/sbin/mkfs.ext2 -F "
+                       cmd = "mkfs.ext2 -F "
                        if partitionsize > 2 * 1024 * 1024:
                                cmd += "-T largefile "
                        cmd += "-m0 " + fulldevicename
                elif self.fstype == "vfat":
                        if partitionsize > 4 * 1024 * 1024 * 1024:
                        if partitionsize > 2 * 1024 * 1024:
                                cmd += "-T largefile "
                        cmd += "-m0 " + fulldevicename
                elif self.fstype == "vfat":
                        if partitionsize > 4 * 1024 * 1024 * 1024:
-                               cmd = "/usr/sbin/mkfs.vfat -I -S4096 " + fulldevicename
+                               cmd = "mkfs.vfat -I -S4096 " + fulldevicename
                        else:
                        else:
-                               cmd = "/usr/sbin/mkfs.vfat -I " + fulldevicename
+                               cmd = "mkfs.vfat -I " + fulldevicename
                                if partitionsize > 2 * 1024 * 1024: # if partiton size larger then 2GB, use FAT32
                                        cmd += " -F 32"
 
                                if partitionsize > 2 * 1024 * 1024: # if partiton size larger then 2GB, use FAT32
                                        cmd += " -F 32"
 
@@ -990,8 +996,10 @@ class DeviceFormat(Screen):
                self.setHotplugDisabled = False
                self.umountTimer = eTimer()
                self.umountTimer.callback.append(self.doUnmount)
                self.setHotplugDisabled = False
                self.umountTimer = eTimer()
                self.umountTimer.callback.append(self.doUnmount)
+               self.onClose.append(enableUdevEvent)
 
        def timerStart(self):
 
        def timerStart(self):
+               enableUdevEvent(False)
                self.formatStartTimer.start(100,True)
 
        def DeviceFormatStart(self):
                self.formatStartTimer.start(100,True)
 
        def DeviceFormatStart(self):
@@ -1041,7 +1049,12 @@ class DeviceFormat(Screen):
                        if oldfstype == newfstype:
                                self.changePartitionIDFinished("NORESULT", 0)
                        else:
                        if oldfstype == newfstype:
                                self.changePartitionIDFinished("NORESULT", 0)
                        else:
-                               cmd = "sfdisk --change-id /dev/%s %s" % (partition[:3], partition[3:])
+                               sfdiskVer = CheckSfdiskVer()
+                               if sfdiskVer >= 2.26:
+                                       cmd = "sfdisk --part-type /dev/%s %s" % (partition[:3], partition[3:])
+                               else:
+                                       cmd = "sfdisk --change-id /dev/%s %s" % (partition[:3], partition[3:])
+
                                if newfstype[:3] == "ext":
                                        cmd += " 83"
                                else:
                                if newfstype[:3] == "ext":
                                        cmd += " 83"
                                else:
@@ -1060,7 +1073,16 @@ class DeviceFormat(Screen):
                        if oldfstype == newfstype:
                                self.refreshPartitionFinished("NORESULT", 0)
                        else:
                        if oldfstype == newfstype:
                                self.refreshPartitionFinished("NORESULT", 0)
                        else:
-                               cmd = "sfdisk -R /dev/%s; sleep 5"%(device)
+                               sfdiskVer = CheckSfdiskVer()
+                               if sfdiskVer < 2.26: # sfdisk -R option is deprecated at sfdiskVer >= 2.26
+                                       cmd = "sfdisk -R /dev/%s; sleep 5" % (device)
+                               elif path.exists('/usr/sbin/partprobe'):
+                                       cmd = 'partprobe /dev/%s; sleep 5' % (device)
+                               elif path.exists('/usr/sbin/partx'):
+                                       cmd = 'partx -u /dev/%s; sleep 5' % (device)
+                               else:
+                                       cmd = "sfdisk -R /dev/%s; sleep 5" % (device)
+
                                self.deviceFormatConsole.ePopen(cmd, self.refreshPartitionFinished)
                else:
                        if result and result.find("Use GNU Parted") > 0:
                                self.deviceFormatConsole.ePopen(cmd, self.refreshPartitionFinished)
                else:
                        if result and result.find("Use GNU Parted") > 0:
@@ -1079,25 +1101,25 @@ class DeviceFormat(Screen):
                newfstype = self.newfstype
                if retval == 0:
                        if newfstype == "ext4":
                newfstype = self.newfstype
                if retval == 0:
                        if newfstype == "ext4":
-                               cmd = "/sbin/mkfs.ext4 -F "
+                               cmd = "mkfs.ext4 -F "
                                if size > 2 * 1024:
                                        cmd += "-T largefile "
                                cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 /dev/" + partition
                        elif newfstype == "ext3":
                                if size > 2 * 1024:
                                        cmd += "-T largefile "
                                cmd += "-O extent,flex_bg,large_file,uninit_bg -m1 /dev/" + partition
                        elif newfstype == "ext3":
-                               cmd = "/sbin/mkfs.ext3 -F "
+                               cmd = "mkfs.ext3 -F "
                                if size > 2 * 1024:
                                        cmd += "-T largefile "
                                cmd += "-m0 /dev/" + partition
                        elif newfstype == "ext2":
                                if size > 2 * 1024:
                                        cmd += "-T largefile "
                                cmd += "-m0 /dev/" + partition
                        elif newfstype == "ext2":
-                               cmd = "/sbin/mkfs.ext2 -F "
+                               cmd = "mkfs.ext2 -F "
                                if size > 2 * 1024:
                                        cmd += "-T largefile "
                                cmd += "-m0 /dev/" + partition
                        elif newfstype == "vfat":
                                if size > 4 * 1024 * 1024:
                                if size > 2 * 1024:
                                        cmd += "-T largefile "
                                cmd += "-m0 /dev/" + partition
                        elif newfstype == "vfat":
                                if size > 4 * 1024 * 1024:
-                                       cmd = "/usr/sbin/mkfs.vfat -I -S4096 /dev/" + partition
+                                       cmd = "mkfs.vfat -I -S4096 /dev/" + partition
                                else:
                                else:
-                                       cmd = "/usr/sbin/mkfs.vfat -I /dev/" + partition
+                                       cmd = "mkfs.vfat -I /dev/" + partition
                                        if size > 2 * 1024: # if partiton size larger then 2GB, use FAT32
                                                cmd += " -F 32"
                        self.deviceFormatConsole.ePopen(cmd, self.mkfsFinished)
                                        if size > 2 * 1024: # if partiton size larger then 2GB, use FAT32
                                                cmd += " -F 32"
                        self.deviceFormatConsole.ePopen(cmd, self.mkfsFinished)
@@ -1668,6 +1690,28 @@ class deviceManagerHotplug:
                        self.doMount(uuid, devpath, mountpoint, filesystem)
 
        def removeHotplugDevice(self, partition):
                        self.doMount(uuid, devpath, mountpoint, filesystem)
 
        def removeHotplugDevice(self, partition):
+               device = partition.device
+               devpath = "/dev/"+device
+# get BlkidInfo
+               (uuid, filesystem) = deviceinfo.getPartitionBlkidInfo(device)
+               if uuid == "":
+# retry..
+                       os.system("sleep 1")
+                       (uuid, filesystem) = deviceinfo.getPartitionBlkidInfo(device)
+               if uuid == "":
+                       print "[DeviceManagerHotplug] getBlkidInfo failed!"
+                       return
+# get configList
+               devicemanagerconfig.loadConfig()
+               configList = devicemanagerconfig.getConfigList()
+               mountpoint = None
+               for line in configList:
+                       if uuid == line[0].strip():
+                               mountpoint = line[1].strip()
+                               break
+               if mountpoint is None:
+                       return
+# do umount
                self.doUmount(partition.device, partition.mountpoint)
 
        def getHotplugAction(self, action, partition):
                self.doUmount(partition.device, partition.mountpoint)
 
        def getHotplugAction(self, action, partition):
diff --git a/lib/python/Plugins/SystemPlugins/FastZapSupport/Makefile.am b/lib/python/Plugins/SystemPlugins/FastZapSupport/Makefile.am
new file mode 100644 (file)
index 0000000..fd9599d
--- /dev/null
@@ -0,0 +1,7 @@
+installdir = $(pkglibdir)/python/Plugins/SystemPlugins/FastZapSupport
+
+SUBDIRS = meta
+
+install_PYTHON =       \
+       __init__.py \
+       plugin.py
diff --git a/lib/python/Plugins/SystemPlugins/FastZapSupport/__init__.py b/lib/python/Plugins/SystemPlugins/FastZapSupport/__init__.py
new file mode 100644 (file)
index 0000000..139597f
--- /dev/null
@@ -0,0 +1,2 @@
+
+
diff --git a/lib/python/Plugins/SystemPlugins/FastZapSupport/meta/Makefile.am b/lib/python/Plugins/SystemPlugins/FastZapSupport/meta/Makefile.am
new file mode 100644 (file)
index 0000000..78678fe
--- /dev/null
@@ -0,0 +1,3 @@
+installdir = $(datadir)/meta
+
+dist_install_DATA = plugin_fastzapsupport.xml
diff --git a/lib/python/Plugins/SystemPlugins/FastZapSupport/meta/plugin_fastzapsupport.xml b/lib/python/Plugins/SystemPlugins/FastZapSupport/meta/plugin_fastzapsupport.xml
new file mode 100644 (file)
index 0000000..064496e
--- /dev/null
@@ -0,0 +1,16 @@
+<default>
+         <prerequisites>
+                    <tag type="System" />
+         </prerequisites>
+          <info>
+                    <author>hschang</author>
+                    <name>FastZapSupport</name>
+                    <packagename>enigma2-plugin-systemplugins-fastzapsupport</packagename>
+                    <shortdescription>Support FastZapping of your VU+</shortdescription>
+                    <description>Support FastZapping of your VU+</description>
+          </info>
+
+         <files type="package"> <!-- without version, without .ipk -->
+               <file type="package" name="enigma2-plugin-systemplugins-fastzapsupport" />
+       </files>
+</default>
diff --git a/lib/python/Plugins/SystemPlugins/FastZapSupport/plugin.py b/lib/python/Plugins/SystemPlugins/FastZapSupport/plugin.py
new file mode 100644 (file)
index 0000000..542531e
--- /dev/null
@@ -0,0 +1,488 @@
+
+from Plugins.Plugin import PluginDescriptor
+import NavigationInstance
+
+from Tools import Notifications
+from Screens.MessageBox import MessageBox
+
+from enigma import iPlayableService, iServiceInformation, eEnv
+
+import struct
+import os
+import re
+
+from Components.NimManager import nimmanager
+from Components.config import ConfigNothing, config
+
+from Components.ServiceEventTracker import ServiceEventTracker
+
+from enigma import iPlayableService
+from Screens.InfoBar import InfoBar
+
+fast_zap_support = None
+
+LANEDB_PATH = eEnv.resolve("${sysconfdir}/enigma2/") + "lamedb"
+
+FAVOURITES_PATH = eEnv.resolve("${sysconfdir}/enigma2/") + "userbouquet.favourites.tv"
+
+PROC_FBC_PATH = "/proc/stb/frontend/fbc"
+
+#PROC_FBC_PATH = "/home/root/fbc"
+
+def strToHex(s):
+               return hex(int(s, 16))
+
+class FastZapSupport:
+       def __init__(self, session):
+               self.session = session
+               self.onClose = [ ] # hack
+
+               self.channelList = []
+#              self.srefList = []
+               self.channelData = []
+               self.procData = {}
+
+               self.parseChannelDB()
+               srefList = self.getSrefList()
+               self.channelData = self.makeChannelData(srefList)
+
+               self.parseNimConfiguration()
+               self.writeDataProc(self.channelData)
+
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+               {
+                       iPlayableService.evStart: self.serviceStarted,
+               })
+
+       def serviceStarted(self):
+               if InfoBar.instance:
+                       channelList = InfoBar.instance.servicelist
+
+                       prevService = channelList.servicelist.getPrev().toString()
+                       curService = channelList.servicelist.getCurrent().toString()
+                       nextService = channelList.servicelist.getNext().toString()
+                       
+#                      print "[FastZapSupport] PREV : ", prevService
+#                      print "[FastZapSupport] CUR : ", curService
+#                      print "[FastZapSupport] NEXT : ", nextService
+
+                       srefList = []
+                       srefList.append(prevService)
+                       srefList.append(nextService)
+
+                       # sref
+                       # type:flags:stype:sid:tsid:onid:namespace:psid:ptsid:
+
+                       channelData = self.makeChannelData(srefList)
+                       self.writeDataProc(channelData)
+
+       def python_scanf(self, my_str, pattern):
+               D = ('%d',      '(\d+?)')
+               F = ('%f', '(\d+\.\d+?)')
+               S = ('%s',       '(.+?)')
+               re_pattern = pattern.replace(*D).replace(*F).replace(*S)
+               match = re.match(re_pattern, my_str)
+               if match:
+                       return match.groups()
+               raise ValueError("String doesn't match pattern")
+
+       def parseChannelDB(self):
+               global LANEDB_PATH
+
+               if not os.access(LANEDB_PATH, os.R_OK):
+                       return
+
+               channelList = []
+               f = open(LANEDB_PATH, "r")
+               line = f.readline()
+
+               try:
+                       version = self.python_scanf(line, "eDVB services /%d/")
+                       if len(version)!=1 or version[0] != '4':
+#                              print "invalid version"
+                               return None
+               except Exception, ex:
+#                      print "[fastzapsupport] exception error : ", ex
+                       return None
+
+               line = f.readline()
+
+               if line != "transponders\n":
+#                      print "[FastZapSupport] no transponders"
+                       return None
+
+               channel_idx = 0
+
+               while 1:
+                       line = f.readline()
+                       if not line:
+                               break
+                       if line == "end\n":
+                               break
+                       tmp = line.strip('\n').split(':')
+                       if len(tmp) != 3:
+                               continue
+
+                       channelID = {}
+                       channelID["namespace"] = tmp[0]
+                       channelID["tsid"] = tmp[1]
+                       channelID["onid"] = tmp[2]
+
+                       feParms = {}
+                       feParms["frequency"] = None
+                       feParms["symbol_rate"] = None
+                       feParms["polarisation"] = None
+                       feParms["fec"] = None
+                       feParms["orbital_position"] = None
+                       feParms["inversion"] = None
+                       feParms["flags"] = None
+                       feParms["system"] = None
+                       feParms["modulation"] = None
+                       feParms["rolloff"] = None
+                       feParms["pilot"] = None
+
+                       while 1:
+                               line = f.readline()
+                               if line == "/\n":
+                                       break
+                               if line[1] == 's':
+                                       s = line[3:].strip('\n').split(':')
+                                       if len(s) >= 7:
+                                               ss = s[:7]
+                                               feParms["frequency"], feParms["symbol_rate"], feParms["polarisation"], feParms["fec"], feParms["orbital_position"], feParms["inversion"], feParms["flags"] = ss
+                                               if feParms["polarisation"] < 0:
+                                                       feParms["polarisation"] += 3600
+
+                                               feParms["system"] = '0' # DVB-S
+                                               feParms["modulation"] = '1' # QPSK
+                                               feParms["rolloff"] = '0' # 0.35
+                                               feParms["pilot"] = '2' # unknown
+
+                                       if len(s) >= 8:
+                                               ss = s[7:]
+                                               feParms["system"], feParms["modulation"], feParms["rolloff"], feParms["pilot"] = ss
+
+                       if feParms["frequency"] is None:
+                               continue
+
+                       channel = {}
+                       channel["channelID"] = channelID
+                       channel["feParms"] = feParms
+                       channel["idx"] = channel_idx
+                       channelList.append(channel)
+                       channel_idx += 1
+
+#              print "[FastZapSupport] %d transponders" % len(channelList)
+               self.channelList = channelList
+
+       def parseNimConfiguration(self):
+               self.diseqc_position = {}
+               for x in nimmanager.nim_slots:
+                       nimConfig = nimmanager.getNimConfig(x.slot)
+
+                       if x.isCompatible("DVB-S"):
+                               if nimConfig.configMode.value == "simple":
+#                                      print "[FastZapSupport] nimConfig.diseqcMode.value : ", nimConfig.diseqcMode.value
+                                       if nimConfig.diseqcMode.value == "single" and not nimConfig.simpleSingleSendDiSEqC.value:                                       
+                                               continue
+
+                                       elif nimConfig.diseqcMode.value == "diseqc_a_b" or nimConfig.diseqcMode.value == "diseqc_a_b_c_d":
+                                               pass
+
+                                       else:
+                                               continue
+
+                                       if nimConfig.diseqcA.orbital_position != 3601: # 3601: nothing connected
+                                               if not self.diseqc_position.has_key(nimConfig.diseqcA.orbital_position):
+                                                       self.diseqc_position[nimConfig.diseqcA.orbital_position] = {"pos" : "AA", "lofth" : 11700000}
+
+                                       if nimConfig.diseqcB.orbital_position != 3601:
+                                               if not self.diseqc_position.has_key(nimConfig.diseqcB.orbital_position):
+                                                       self.diseqc_position[nimConfig.diseqcB.orbital_position] = {"pos" : "AB", "lofth" : 11700000}
+
+                                       if nimConfig.diseqcC.orbital_position != 3601:
+                                               if not self.diseqc_position.has_key(nimConfig.diseqcC.orbital_position):
+                                                       self.diseqc_position[nimConfig.diseqcC.orbital_position] = {"pos" : "BA", "lofth" : 11700000}
+
+                                       if nimConfig.diseqcD.orbital_position != 3601:
+                                               if not self.diseqc_position.has_key(nimConfig.diseqcD.orbital_position):
+                                                       self.diseqc_position[nimConfig.diseqcD.orbital_position] = {"pos" : "BB", "lofth": 11700000}
+
+                               elif nimConfig.configMode.value == "advanced":
+                                       if nimConfig.advanced.sats.orbital_position is None:
+                                               continue
+
+                                       cur_orb_pos = nimConfig.advanced.sats.orbital_position
+                                       satlist = nimConfig.advanced.sat.keys()
+
+                                       if cur_orb_pos not in satlist:
+                                               cur_orb_pos = satlist[0]
+
+                                       currSat = nimConfig.advanced.sat[cur_orb_pos]
+                                       lnbnum = int(currSat.lnb.value)
+                                       currLnb = nimConfig.advanced.lnb[lnbnum]
+
+                                       if isinstance(currLnb, ConfigNothing):
+                                               continue
+
+                                       if currLnb.lof.value == "universal_lnb":
+                                               lofth = 11700000
+
+                                       elif currLnb.lof.value == "user_defined":
+                                               lofth = int(currLnb.threshold.value) * 1000
+                                       else:
+                                               continue
+
+                                       if currLnb.diseqcMode.value == "none":
+                                               continue
+
+                                       if currLnb.commitedDiseqcCommand.value == "none":
+                                               continue
+
+                                       if currLnb.commitedDiseqcCommand.value in ["AA", "AB", "BA", "BB"]:
+                                               position = currLnb.commitedDiseqcCommand.value
+
+                                       else:
+                                               position = "AA"
+
+                                       self.diseqc_position[cur_orb_pos] = {"pos" : position, "lofth" : lofth}
+
+       def getTone(self, frequency, orbital_position):
+               tone = "low"
+               lofth = 11700000
+
+               if self.diseqc_position.has_key(orbital_position):
+                       lofth = self.diseqc_position[orbital_position]["lofth"]
+
+               if frequency > lofth:
+                       tone = "high"
+
+               return tone
+
+       def getPosition(self, orbital_position):
+               if self.diseqc_position.has_key(orbital_position):
+                       return self.diseqc_position[orbital_position]["pos"]
+
+               return None
+
+       def getSrefList(self):
+               srefList = []
+
+               global FAVOURITES_PATH
+
+               if not os.access(FAVOURITES_PATH, os.R_OK):
+#                      print "[FastZapSupport] Error, %s not found." % FAVOURITES_PATH
+                       return
+
+               f = open(FAVOURITES_PATH, "r")
+               while 1:
+                       line = f.readline()
+                       if not line:
+                               break
+
+                       if not line.startswith("#SERVICE"):
+                               continue
+
+                       data = line.split(' ')
+                       if (len(data) != 2):
+                               continue
+
+                       res = re.search("\d+:\d+:\w+:\w+:\w+:\w+:\w+:\w+:\w+:\w+:", data[1])
+
+                       if res:
+                               sref = res.group()
+                               sref_split = sref.split(":")
+                               type = int(sref_split[0])
+                               flag = int(sref_split[1])
+                               stype = int(sref_split[2], 16) # hex to int
+                               if type != 1 or flag != 0:
+                                       continue
+
+                               # VIDEO : 1, 17, 22, 25, 134, 195
+                               # AUDIO : 2, 10
+                               # HEVC : 31
+                               if not stype in (1, 17, 22, 25, 134, 195, 2, 10, 31):
+                                       continue # unknown service type
+
+                               if sref not in srefList:
+                                       srefList.append(sref)
+
+#              print "[FastZapSupport] TOTAL %d Services" % len(srefList)
+
+               return srefList
+
+       def getChannel(self, sref):
+               sref_tsid = strToHex(sref.split(":")[4])
+               sref_onid = strToHex(sref.split(":")[5])
+               sref_namespace = strToHex(sref.split(":")[6])
+               for channel in self.channelList:
+                       channel_tsid = strToHex(channel["channelID"]["tsid"])
+                       channel_onid = strToHex(channel["channelID"]["onid"])
+                       channel_namespace = strToHex(channel["channelID"]["namespace"])
+                       if (sref_tsid == channel_tsid) and (sref_onid == channel_onid) and (sref_namespace == channel_namespace):
+                               return channel
+
+               return None
+
+       def makeChannelData(self, srefList):
+               channelData = []
+               for sref in srefList:
+                       channel = self.getChannel(sref)
+                       if channel is None:
+                               continue
+
+                       if channel not in channelData:
+                               channelData.append((channel, sref))
+
+#              print "[FastZapSupport] TOTAL %d channels" % len(channelData)
+
+               return channelData
+
+       def writeDataProc(self, channelData):
+               global PROC_FBC_PATH
+
+               if not os.access(PROC_FBC_PATH, os.F_OK):
+#                      print "[FastZapSupport] Error, %s not found!" % PROC_FBC_PATH
+                       return
+
+               fbc_proc_list = ["frequency", "symbolrate", "polarisation", "fec", "inv", "system", "modulation", "rolloff", "pilot", "tone", "position", "sid"]
+               procData = {}
+
+               for c in fbc_proc_list:
+                       procData[c] = []
+
+               pol_table = ["h", "v"]
+               fec_table = ["auto", "12", "23", "34", "56", "78", "89", "35", "45", "910", "none"]
+               inv_table = ["on", "off", "auto"]
+               system_table = ["dvbs", "dvbs2"]
+               modulation_table = ["auto", "qpsk", "8psk", "qam16"]
+               rolloff_table = ["0_35", "0_25", "0_20"]
+               pilot_table = ["off", "on", "auto"]
+               position_table = {"AA" : "a", "AB" : "b", "BA" : "c", "BB" : "d"}
+
+               for (channel, sref) in channelData:
+                       feParms = channel["feParms"]
+
+                       position = self.getPosition(int(feParms["orbital_position"]))
+                       if position is None:
+                               continue
+
+                       procData["position"].append(position_table[position]) # aa, ab, ba, bb
+
+                       procData["frequency"].append(str(feParms["frequency"]))
+                       procData["symbolrate"].append(str(feParms["symbol_rate"]))
+                       procData["polarisation"].append(pol_table[int(feParms["polarisation"])])
+                       procData["fec"].append(fec_table[int(feParms["fec"])])
+                       procData["inv"].append(inv_table[int(feParms["inversion"])])
+                       procData["system"].append(system_table[int(feParms["system"])])
+
+                       if system_table[int(feParms["system"])] == "dvbs2":
+                               procData["modulation"].append( modulation_table[int(feParms["modulation"])] )
+                               procData["rolloff"].append(  rolloff_table[int(feParms["rolloff"])] )
+                               procData["pilot"].append( pilot_table[int(feParms["pilot"])] )
+
+                       else:
+                               procData["modulation"].append("none")
+                               procData["rolloff"].append("none")
+                               procData["pilot"].append("none")
+
+                       procData["tone"].append(self.getTone(int(feParms["frequency"]), int(feParms["orbital_position"]))) # low or high
+
+                       sid = str(int(sref.split(":")[3], 16))
+                       procData["sid"].append(sid)
+
+               total = len(procData["position"])
+               for c in fbc_proc_list:
+                       if self.procData.get(c, []) != procData[c]:
+                               procPath = "%s/%s" % (PROC_FBC_PATH, c)
+
+                               data = str(total) + " " + ','.join(procData[c])
+                               if not os.access(procPath, os.W_OK):
+#                                      print "[FastZapSupport] %s not found, skip write (data : %s)" % (procPath, data)
+                                       continue
+
+#                              print "[FastZapSupport] %s data updated" % procPath
+
+                               open("%s/%s" % (PROC_FBC_PATH, c) , "w").write(data)
+
+                               self.procData[c] = procData[c]
+
+def FastZapSupportInit(reason, **kwargs):
+       if kwargs.has_key("session"):
+               session = kwargs["session"]
+               global fast_zap_support
+               fast_zap_support = FastZapSupport(session)
+
+def SatConfigChanged():
+       global fast_zap_support
+       fast_zap_support.parseNimConfiguration()
+       fast_zap_support.writeDataProc(fast_zap_support.channelData)
+
+def lamedbChanged():
+       global fast_zap_support
+       fast_zap_support.parseChannelDB()
+
+from Components.config import config, ConfigSubsection, ConfigBoolean
+config.plugins.fastzapsetup = ConfigSubsection()
+config.plugins.fastzapsetup.activate = ConfigBoolean(default = False)
+
+class FastZapSetup:
+       def __init__(self):
+               config.plugins.fastzapsetup.activate.addNotifier(self.updateProc)
+
+       def getExtensionName(self):
+               if config.plugins.fastzapsetup.activate.value:
+                       return _("Disable FastZapping")
+
+               return _("Enable FastZapping")
+
+       def updateToggle(self):
+               if config.plugins.fastzapsetup.activate.value:
+                       config.plugins.fastzapsetup.activate.value = False
+               else:
+                       config.plugins.fastzapsetup.activate.value = True
+
+       def updateProc(self, configElement):
+               val = configElement.value and "enable" or "disable"
+               try:
+                       global PROC_FBC_PATH
+                       procPath = "%s/fcc" % PROC_FBC_PATH
+                       print "[FastZapSetup] write %s to %s" % (val ,procPath)
+                       open(procPath, "w").write(val)
+
+               except Exception, ex:
+                       print "[FastZapSetup] exception error : ", ex
+
+               configElement.save()
+
+fastzapsetup_instance = FastZapSetup()
+def addExtentions(infobarExtensions):
+       infobarExtensions.addExtension((fastzapsetup_instance.getExtensionName, fastzapsetup_instance.updateToggle, lambda: True), None)
+
+def Plugins(**kwargs):
+       list = []
+       list.append(
+               PluginDescriptor(name="FastZapSupport",
+               description="FastZapSupport",
+               where = [PluginDescriptor.WHERE_SESSIONSTART],
+               fnc = FastZapSupportInit))
+
+       list.append(
+               PluginDescriptor(name="FastZapSupport",
+               description="FastZapSupport",
+               where = [PluginDescriptor.WHERE_SATCONFIGCHANGED],
+               fnc = SatConfigChanged))
+
+       list.append(
+               PluginDescriptor(name="FastZapSupport",
+               description="FastZapSupport",
+               where = [PluginDescriptor.WHERE_SERVICESCAN],
+               fnc = lamedbChanged))
+
+       list.append(
+               PluginDescriptor(name="FastZapSetup",
+               description="FastZapSetup",
+               where = [PluginDescriptor.WHERE_EXTENSIONSINGLE],
+               fnc = addExtentions))
+
+       return list
index cf3498b..72a7d0a 100755 (executable)
@@ -7,7 +7,8 @@ SUBDIRS = SoftwareManager FrontprocessorUpgrade PositionerSetup Satfinder \
        TempFanControl Fancontrol FPGAUpgrade WirelessLanSetup ManualFancontrol \
        Blindscan RemoteControlCode UI3DSetup UIPositionSetup HDMICEC LEDBrightnessSetup \
        FirmwareUpgrade CrashReport 3GModemManager WirelessAccessPoint ZappingModeSelection \
        TempFanControl Fancontrol FPGAUpgrade WirelessLanSetup ManualFancontrol \
        Blindscan RemoteControlCode UI3DSetup UIPositionSetup HDMICEC LEDBrightnessSetup \
        FirmwareUpgrade CrashReport 3GModemManager WirelessAccessPoint ZappingModeSelection \
-       DeviceManager TransCodingSetup WOLSetup NetDrive AudioEffect AnimationSetup
+       DeviceManager TransCodingSetup WOLSetup NetDrive AudioEffect AnimationSetup FastZapSupport \
+       BoxModeConfig
 
 install_PYTHON =       \
        __init__.py
 
 install_PYTHON =       \
        __init__.py
index 346c3b8..802c0b6 100644 (file)
@@ -38,6 +38,11 @@ class VideoHardware:
                        "60Hz" : {60: "1080p"},
                        "multi": {50: "1080p50", 60: "1080p"}
                },
                        "60Hz" : {60: "1080p"},
                        "multi": {50: "1080p50", 60: "1080p"}
                },
+               "2160p": {
+                       "50Hz" : {50: "2160p50"},
+                       "60Hz" : {60: "2160p"},
+                       "multi": {50: "2160p50", 60: "2160p"}
+               },
                "PC": {
                        "1024x768": {60: "1024x768"},
                        "800x600" : {60: "800x600"},
                "PC": {
                        "1024x768": {60: "1024x768"},
                        "800x600" : {60: "800x600"},
@@ -55,11 +60,11 @@ class VideoHardware:
                }
        }
 
                }
        }
 
-       widescreen_modes = set(["720p", "1080i", "1080p"])
-       hdmi_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero"])
-       hdmi_pc_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero"])
-       noscart_hw_types = set(["zero"])
-       noypbpr_hw_types = set(["solose", "zero"])
+       widescreen_modes = set(["720p", "1080i", "1080p", "2160p"])
+       hdmi_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k"])
+       hdmi_pc_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k"])
+       noscart_hw_types = set(["zero", "solo4k"])
+       noypbpr_hw_types = set(["solose", "zero", "solo4k"])
 
        def getDeviceName(self):
                device_name = "unknown"
 
        def getDeviceName(self):
                device_name = "unknown"
@@ -74,7 +79,10 @@ class VideoHardware:
                return device_name
 
        def isVumodel(self, hw_type):
                return device_name
 
        def isVumodel(self, hw_type):
-               return hw_type in set(["bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero"])
+               return hw_type in set(["bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k"])
+
+       def isVumodel4K(self, hw_type):
+               return hw_type in set(["solo4k"])
 
        # re-define AVSwitch.getOutputAspect
        def getOutputAspect(self):
 
        # re-define AVSwitch.getOutputAspect
        def getOutputAspect(self):
@@ -232,6 +240,9 @@ class VideoHardware:
                # vu+ support 1080p
                if self.isVumodel(hw_type):
                        self.modes["DVI"].insert(self.modes["DVI"].index("1080i")+1, "1080p")
                # vu+ support 1080p
                if self.isVumodel(hw_type):
                        self.modes["DVI"].insert(self.modes["DVI"].index("1080i")+1, "1080p")
+                       # 4K support 2160p
+                       if self.isVumodel4K(hw_type):
+                               self.modes["DVI"].insert(self.modes["DVI"].index("1080p")+1, "2160p")
 
                portlist = [ ]
                port_choices = self.getPortList()
 
                portlist = [ ]
                port_choices = self.getPortList()
index a274010..328d98d 100644 (file)
@@ -25,11 +25,37 @@ class About(Screen):
                self["FPVersion"] = StaticText(fp_version)
 
                nims = nimmanager.nimList()
                self["FPVersion"] = StaticText(fp_version)
 
                nims = nimmanager.nimList()
-               for count in (0, 1, 2, 3):
-                       if count < len(nims):
-                               self["Tuner" + str(count)] = StaticText(nims[count])
-                       else:
-                               self["Tuner" + str(count)] = StaticText("")
+               if len(nims) <= 4 :
+                       for count in (0, 1, 2, 3):
+                               if count < len(nims):
+                                       self["Tuner" + str(count)] = StaticText(nims[count])
+                               else:
+                                       self["Tuner" + str(count)] = StaticText("")
+               else:
+                       desc_list = []
+                       count = 0
+                       cur_idx = -1
+                       while count < len(nims):
+                               data = nims[count].split(":")
+                               idx = data[0].strip('Tuner').strip()
+                               desc = data[1].strip()
+                               if desc_list and desc_list[cur_idx]['desc'] == desc:
+                                       desc_list[cur_idx]['end'] = idx
+                               else:
+                                       desc_list.append({'desc' : desc, 'start' : idx, 'end' : idx})
+                                       cur_idx += 1
+                               count += 1
+
+                       for count in (0, 1, 2, 3):
+                               if count < len(desc_list):
+                                       if desc_list[count]['start'] == desc_list[count]['end']:
+                                               text = "Tuner %s: %s" % (desc_list[count]['start'], desc_list[count]['desc'])
+                                       else:
+                                               text = "Tuner %s-%s: %s" % (desc_list[count]['start'], desc_list[count]['end'], desc_list[count]['desc'])
+                               else:
+                                       text = ""
+
+                               self["Tuner" + str(count)] = StaticText(text)
 
                self["HDDHeader"] = StaticText(_("Detected HDD:"))
                hddlist = harddiskmanager.HDDList()
 
                self["HDDHeader"] = StaticText(_("Detected HDD:"))
                hddlist = harddiskmanager.HDDList()
index 6813381..fc176a7 100755 (executable)
@@ -719,8 +719,9 @@ MODE_RADIO = 1
 # type 27 = advanced codec HD NVOD reference service (NYI)
 # type 2 = digital radio sound service
 # type 10 = advanced codec digital radio sound service
 # type 27 = advanced codec HD NVOD reference service (NYI)
 # type 2 = digital radio sound service
 # type 10 = advanced codec digital radio sound service
+# type 31 = High Efficiency Video Coing digital television
 
 
-service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 22) || (type == 25) || (type == 134) || (type == 195)'
+service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 22) || (type == 25) || (type == 31) || (type == 134) || (type == 195)'
 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2) || (type == 10)'
 
 class ChannelSelectionBase(Screen):
 service_types_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2) || (type == 10)'
 
 class ChannelSelectionBase(Screen):
index 78d9984..c5f72e2 100755 (executable)
@@ -1322,6 +1322,9 @@ class InfoBarExtensions:
                                "extensions": (self.showExtensionSelection, _("view extensions...")),
                        }, 1) # lower priority
 
                                "extensions": (self.showExtensionSelection, _("view extensions...")),
                        }, 1) # lower priority
 
+               for p in plugins.getPlugins(PluginDescriptor.WHERE_EXTENSIONSINGLE):
+                       p(self)
+
        def addExtension(self, extension, key = None, type = EXTENSION_SINGLE):
                self.list.append((type, extension, key))
 
        def addExtension(self, extension, key = None, type = EXTENSION_SINGLE):
                self.list.append((type, extension, key))
 
index c5366f9..48b580c 100644 (file)
@@ -15,6 +15,24 @@ from Screens.ServiceStopScreen import ServiceStopScreen
 from time import mktime, localtime
 from datetime import datetime
 
 from time import mktime, localtime
 from datetime import datetime
 
+from Components.PluginComponent import plugins
+from Plugins.Plugin import PluginDescriptor
+
+def isFBCTuner(nim):
+       if nim.description.find("FBC") == -1:
+               return False
+       return True
+
+def isFBCRoot(nim):
+       if nim.slot %8 < 2:
+               return True
+       return False
+
+def isFBCLink(nim):
+       if isFBCTuner(nim) and not isFBCRoot(nim):
+               return True
+       return False
+
 class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
        def createSimpleSetup(self, list, mode):
                nim = self.nimConfig
 class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
        def createSimpleSetup(self, list, mode):
                nim = self.nimConfig
@@ -70,6 +88,9 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                                choices["satposdepends"] = _("second cable of motorized LNB")
                        if len(nimmanager.canConnectTo(self.slotid)) > 0:
                                choices["loopthrough"] = _("loopthrough to")
                                choices["satposdepends"] = _("second cable of motorized LNB")
                        if len(nimmanager.canConnectTo(self.slotid)) > 0:
                                choices["loopthrough"] = _("loopthrough to")
+                       if isFBCLink(self.nim):
+                               choices = { "nothing": _("not configured"),
+                                               "advanced": _("advanced")}
                        self.nimConfig.configMode.setChoices(choices, default = "nothing")
 
        def createSetup(self):
                        self.nimConfig.configMode.setChoices(choices, default = "nothing")
 
        def createSetup(self):
@@ -210,8 +231,9 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                        self.advancedType, self.advancedSCR, self.advancedDiction, self.advancedManufacturer, self.advancedUnicable, self.advancedConnected, \
                        self.uncommittedDiseqcCommand, self.cableScanType, self.multiType)
                if self["config"].getCurrent() == self.multiType:
                        self.advancedType, self.advancedSCR, self.advancedDiction, self.advancedManufacturer, self.advancedUnicable, self.advancedConnected, \
                        self.uncommittedDiseqcCommand, self.cableScanType, self.multiType)
                if self["config"].getCurrent() == self.multiType:
+                       update_slots = [self.slotid]
                        from Components.NimManager import InitNimManager
                        from Components.NimManager import InitNimManager
-                       InitNimManager(nimmanager)
+                       InitNimManager(nimmanager, update_slots)
                        self.nim = nimmanager.nim_slots[self.slotid]
                        self.nimConfig = self.nim.config
                        
                        self.nim = nimmanager.nim_slots[self.slotid]
                        self.nimConfig = self.nim.config
                        
@@ -246,6 +268,10 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                self.list.append(self.advancedLnbsEntry)
 
                if currLnb:
                self.list.append(self.advancedLnbsEntry)
 
                if currLnb:
+                       if isFBCLink(self.nim):
+                               if currLnb.lof.value != "unicable":
+                                       currLnb.lof.value = "unicable"
+
                        self.list.append(getConfigListEntry(_("Priority"), currLnb.prio))
                        self.advancedLof = getConfigListEntry(_("LOF"), currLnb.lof)
                        self.list.append(self.advancedLof)
                        self.list.append(getConfigListEntry(_("Priority"), currLnb.prio))
                        self.advancedLof = getConfigListEntry(_("LOF"), currLnb.lof)
                        self.list.append(self.advancedLof)
@@ -310,6 +336,10 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                                for id in connectable:
                                        choices.append((str(id), nimmanager.getNimDescription(id)))
                                if len(choices):
                                for id in connectable:
                                        choices.append((str(id), nimmanager.getNimDescription(id)))
                                if len(choices):
+                                       if isFBCLink(self.nim):
+                                               if self.nimConfig.advanced.unicableconnected.value != True:
+                                                       self.nimConfig.advanced.unicableconnected.value = True
+
                                        self.advancedConnected = getConfigListEntry(_("connected"), self.nimConfig.advanced.unicableconnected)
                                        self.list.append(self.advancedConnected)
                                        if self.nimConfig.advanced.unicableconnected.value == True:
                                        self.advancedConnected = getConfigListEntry(_("connected"), self.nimConfig.advanced.unicableconnected)
                                        self.list.append(self.advancedConnected)
                                        if self.nimConfig.advanced.unicableconnected.value == True:
@@ -479,10 +509,22 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                self.createSetup()
 
        def keyLeft(self):
                self.createSetup()
 
        def keyLeft(self):
+               if isFBCLink(self.nim):
+                       checkList = (self.advancedLof, self.advancedConnected)
+                       curEntry = self["config"].getCurrent()
+                       if curEntry in checkList:
+                               return
+
                ConfigListScreen.keyLeft(self)
                self.newConfig()
 
        def keyRight(self):
                ConfigListScreen.keyLeft(self)
                self.newConfig()
 
        def keyRight(self):
+               if isFBCLink(self.nim):
+                       checkList = (self.advancedLof, self.advancedConnected)
+                       curEntry = self["config"].getCurrent()
+                       if curEntry in checkList:
+                               return
+
                ConfigListScreen.keyRight(self)
                self.newConfig()
                
                ConfigListScreen.keyRight(self)
                self.newConfig()
                
@@ -502,6 +544,9 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                        self.nimConfig.connectedTo.setChoices(choices)
                for x in self["config"].list:
                        x[1].save()
                        self.nimConfig.connectedTo.setChoices(choices)
                for x in self["config"].list:
                        x[1].save()
+
+               for p in plugins.getPlugins(PluginDescriptor.WHERE_SATCONFIGCHANGED):
+                       p()
                        
        def cancelConfirm(self, result):
                if not result:
                        
        def cancelConfirm(self, result):
                if not result:
@@ -517,13 +562,14 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                if type(self["config"].getCurrent()[1]) is ConfigSatlist:
                        self["config"].getCurrent()[1].setValue("3601")
                        self["config"].invalidateCurrent()
                if type(self["config"].getCurrent()[1]) is ConfigSatlist:
                        self["config"].getCurrent()[1].setValue("3601")
                        self["config"].invalidateCurrent()
-                       
+
 class NimSelection(Screen):
        def __init__(self, session):
                Screen.__init__(self, session)
                
                self.list = [None] * nimmanager.getSlotCount()
                self["nimlist"] = List(self.list)
 class NimSelection(Screen):
        def __init__(self, session):
                Screen.__init__(self, session)
                
                self.list = [None] * nimmanager.getSlotCount()
                self["nimlist"] = List(self.list)
+               self.loadFBCLinks()
                self.updateList()
                
                self.setResultClass()
                self.updateList()
                
                self.setResultClass()
@@ -533,6 +579,23 @@ class NimSelection(Screen):
                        "ok": self.okbuttonClick ,
                        "cancel": self.close
                }, -2)
                        "ok": self.okbuttonClick ,
                        "cancel": self.close
                }, -2)
+
+       def loadFBCLinks(self):
+               for x in nimmanager.nim_slots:
+                       slotid = x.slot
+                       nimConfig = nimmanager.getNimConfig(x.slot)
+                       configMode = nimConfig.configMode.value
+                       if self.showNim(x):
+                               if x.isCompatible("DVB-S"):
+                                       if isFBCLink(x) and configMode != "advanced":
+                                               from enigma import getLinkedSlotID
+                                               link = getLinkedSlotID(x.slot)
+
+                                               if link == -1:
+                                                       nimConfig.configMode.value = "nothing"
+                                               else:
+                                                       nimConfig.configMode.value = "loopthrough"
+                                                       nimConfig.connectedTo.value = str(link)
                
        def setResultClass(self):
                self.resultclass = NimSetup
                
        def setResultClass(self):
                self.resultclass = NimSetup
@@ -540,8 +603,17 @@ class NimSelection(Screen):
        def okbuttonClick(self):
                nim = self["nimlist"].getCurrent()
                nim = nim and nim[3]
        def okbuttonClick(self):
                nim = self["nimlist"].getCurrent()
                nim = nim and nim[3]
+
+               nimConfig = nimmanager.getNimConfig(nim.slot)
+               if isFBCLink(nim) and nimConfig.configMode.value == "loopthrough":
+                       return
+
                if nim is not None and not nim.empty and nim.isSupported():
                if nim is not None and not nim.empty and nim.isSupported():
-                       self.session.openWithCallback(self.updateList, self.resultclass, nim.slot)
+                       self.session.openWithCallback(self.NimSetupCB, self.resultclass, nim.slot)
+
+       def NimSetupCB(self):
+               self.loadFBCLinks()
+               self.updateList()
                        
        def showNim(self, nim):
                return True
                        
        def showNim(self, nim):
                return True
@@ -558,7 +630,7 @@ class NimSelection(Screen):
                                                text = { "loopthrough": _("loopthrough to"),
                                                                 "equal": _("equal to"),
                                                                 "satposdepends": _("second cable of motorized LNB") } [nimConfig.configMode.value]
                                                text = { "loopthrough": _("loopthrough to"),
                                                                 "equal": _("equal to"),
                                                                 "satposdepends": _("second cable of motorized LNB") } [nimConfig.configMode.value]
-                                               text += " " + _("Tuner") + " " + ["A", "B", "C", "D"][int(nimConfig.connectedTo.value)]
+                                               text += " " + _("Tuner") + " " + chr(ord('A')+int(nimConfig.connectedTo.value))
                                        elif nimConfig.configMode.value == "nothing":
                                                text = _("not configured")
                                        elif nimConfig.configMode.value == "simple":
                                        elif nimConfig.configMode.value == "nothing":
                                                text = _("not configured")
                                        elif nimConfig.configMode.value == "simple":
@@ -592,6 +664,8 @@ class NimSelection(Screen):
                                                        text = _("simple")
                                        elif nimConfig.configMode.value == "advanced":
                                                text = _("advanced")
                                                        text = _("simple")
                                        elif nimConfig.configMode.value == "advanced":
                                                text = _("advanced")
+                                       if isFBCLink(x) and nimConfig.configMode.value != "advanced":
+                                               text += _("\n<This tuner is configured automatically>")
                                elif x.isCompatible("DVB-T") or x.isCompatible("DVB-C"):
                                        if nimConfig.configMode.value == "nothing":
                                                text = _("nothing connected")
                                elif x.isCompatible("DVB-T") or x.isCompatible("DVB-C"):
                                        if nimConfig.configMode.value == "nothing":
                                                text = _("nothing connected")
@@ -605,3 +679,4 @@ class NimSelection(Screen):
                                self.list.append((slotid, x.friendly_full_description, text, x))
                self["nimlist"].setList(self.list)
                self["nimlist"].updateList(self.list)
                                self.list.append((slotid, x.friendly_full_description, text, x))
                self["nimlist"].setList(self.list)
                self["nimlist"].updateList(self.list)
+
index bc0968e..da534ec 100644 (file)
@@ -182,7 +182,7 @@ class ServiceInfo(Screen):
                if frontendDataOrg and len(frontendDataOrg):
                        frontendData = ConvertToHumanReadable(frontendDataOrg)
                        if frontendDataOrg["tuner_type"] == "DVB-S":
                if frontendDataOrg and len(frontendDataOrg):
                        frontendData = ConvertToHumanReadable(frontendDataOrg)
                        if frontendDataOrg["tuner_type"] == "DVB-S":
-                               return ((_("NIM"), ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H')[frontendData["tuner_number"]], TYPE_TEXT),
+                               return ((_("NIM"), chr(ord('A')+int(frontendData["tuner_number"])), TYPE_TEXT),
                                                (_("Type"), frontendData["tuner_type"], TYPE_TEXT),
                                                (_("System"), frontendData["system"], TYPE_TEXT),
                                                (_("Modulation"), frontendData["modulation"], TYPE_TEXT),
                                                (_("Type"), frontendData["tuner_type"], TYPE_TEXT),
                                                (_("System"), frontendData["system"], TYPE_TEXT),
                                                (_("Modulation"), frontendData["modulation"], TYPE_TEXT),
@@ -195,7 +195,7 @@ class ServiceInfo(Screen):
                                                (_("Pilot"), frontendData.get("pilot", None), TYPE_TEXT),
                                                (_("Roll-off"), frontendData.get("rolloff", None), TYPE_TEXT))
                        elif frontendDataOrg["tuner_type"] == "DVB-C":
                                                (_("Pilot"), frontendData.get("pilot", None), TYPE_TEXT),
                                                (_("Roll-off"), frontendData.get("rolloff", None), TYPE_TEXT))
                        elif frontendDataOrg["tuner_type"] == "DVB-C":
-                               return ((_("NIM"), ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H')[frontendData["tuner_number"]], TYPE_TEXT),
+                               return ((_("NIM"), chr(ord('A')+int(frontendData["tuner_number"])), TYPE_TEXT),
                                                (_("Type"), frontendData["tuner_type"], TYPE_TEXT),
                                                (_("Modulation"), frontendData["modulation"], TYPE_TEXT),
                                                (_("Frequency"), frontendData["frequency"], TYPE_VALUE_DEC),
                                                (_("Type"), frontendData["tuner_type"], TYPE_TEXT),
                                                (_("Modulation"), frontendData["modulation"], TYPE_TEXT),
                                                (_("Frequency"), frontendData["frequency"], TYPE_VALUE_DEC),
@@ -203,7 +203,7 @@ class ServiceInfo(Screen):
                                                (_("Inversion"), frontendData["inversion"], TYPE_TEXT),
                                                (_("FEC"), frontendData["fec_inner"], TYPE_TEXT))
                        elif frontendDataOrg["tuner_type"] == "DVB-T":
                                                (_("Inversion"), frontendData["inversion"], TYPE_TEXT),
                                                (_("FEC"), frontendData["fec_inner"], TYPE_TEXT))
                        elif frontendDataOrg["tuner_type"] == "DVB-T":
-                               data = ((_("NIM"), ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H')[frontendData["tuner_number"]], TYPE_TEXT),
+                               data = ((_("NIM"), chr(ord('A')+int(frontendData["tuner_number"])), TYPE_TEXT),
                                                (_("Type"), frontendData["tuner_type"], TYPE_TEXT),
                                                (_("System"), frontendData["system"], TYPE_TEXT),
                                                (_("Frequency"), frontendData["frequency"], TYPE_VALUE_DEC),
                                                (_("Type"), frontendData["tuner_type"], TYPE_TEXT),
                                                (_("System"), frontendData["system"], TYPE_TEXT),
                                                (_("Frequency"), frontendData["frequency"], TYPE_VALUE_DEC),
index 6be08d4..efa218b 100644 (file)
@@ -5,6 +5,8 @@ from Components.Label import Label
 from Components.ActionMap import ActionMap
 from Components.FIFOList import FIFOList
 from Components.Sources.FrontendInfo import FrontendInfo
 from Components.ActionMap import ActionMap
 from Components.FIFOList import FIFOList
 from Components.Sources.FrontendInfo import FrontendInfo
+from Components.PluginComponent import plugins
+from Plugins.Plugin import PluginDescriptor
 
 class ServiceScanSummary(Screen):
        skin = """
 
 class ServiceScanSummary(Screen):
        skin = """
@@ -60,6 +62,11 @@ class ServiceScan(Screen):
                        })
 
                self.onFirstExecBegin.append(self.doServiceScan)
                        })
 
                self.onFirstExecBegin.append(self.doServiceScan)
+               self.onClose.append(self.doPluginCB)
+
+       def doPluginCB(self):
+               for p in plugins.getPlugins(PluginDescriptor.WHERE_SERVICESCAN):
+                       p()
 
        def doServiceScan(self):
                self["scan"] = CScan(self["scan_progress"], self["scan_state"], self["servicelist"], self["pass"], self.scanList, self["network"], self["transponder"], self["FrontendInfo"], self.session.summary)
 
        def doServiceScan(self):
                self["scan"] = CScan(self["scan_progress"], self["scan_state"], self["servicelist"], self["pass"], self.scanList, self["network"], self["transponder"], self["FrontendInfo"], self.session.summary)
index 9891fb3..6a25592 100755 (executable)
@@ -334,6 +334,16 @@ void setPreferredTuner(int index)
 }
 %}
 
 }
 %}
 
+int getLinkedSlotID(int);
+%{
+int getLinkedSlotID(int fe)
+{
+        eFBCTunerManager *mgr = eFBCTunerManager::getInstance();
+        if (mgr) return mgr->getLinkedSlotID(fe);
+        return -1;
+}
+%}
+
 /************** temp *****************/
 
        /* need a better place for this, i agree. */
 /************** temp *****************/
 
        /* need a better place for this, i agree. */
index cc8c32b..cd65f35 100644 (file)
@@ -99,6 +99,37 @@ void eListboxServiceContent::getCurrent(eServiceReference &ref)
                ref = eServiceReference();
 }
 
                ref = eServiceReference();
 }
 
+void eListboxServiceContent::getPrev(eServiceReference &ref)
+{
+       if (cursorValid())
+       {
+               list::iterator cursor(m_cursor);
+               if (cursor == m_list.begin())
+               {
+                       cursor = m_list.end();
+               }
+               ref = *(--cursor);
+       }
+       else
+               ref = eServiceReference();
+}
+
+void eListboxServiceContent::getNext(eServiceReference &ref)
+{
+       if (cursorValid())
+       {
+               list::iterator cursor(m_cursor);
+               cursor++;
+               if (cursor == m_list.end())
+               {
+                       cursor = m_list.begin();
+               }
+               ref = *(cursor);
+       }
+       else
+               ref = eServiceReference();
+}
+
 int eListboxServiceContent::getNextBeginningWithChar(char c)
 {
 //     printf("Char: %c\n", c);
 int eListboxServiceContent::getNextBeginningWithChar(char c)
 {
 //     printf("Char: %c\n", c);
index 589afba..ab5bd20 100644 (file)
@@ -19,6 +19,8 @@ public:
        void setIgnoreService( const eServiceReference &service );
        void setRoot(const eServiceReference &ref, bool justSet=false);
        void getCurrent(eServiceReference &ref);
        void setIgnoreService( const eServiceReference &service );
        void setRoot(const eServiceReference &ref, bool justSet=false);
        void getCurrent(eServiceReference &ref);
+       void getPrev(eServiceReference &ref);
+       void getNext(eServiceReference &ref);
        
        int getNextBeginningWithChar(char c);
        int getPrevMarkerPos();
        
        int getNextBeginningWithChar(char c);
        int getPrevMarkerPos();
index 0287acf..dc1b22e 100644 (file)
@@ -15,7 +15,7 @@
 
 DEFINE_REF(eDVBServiceRecord);
 
 
 DEFINE_REF(eDVBServiceRecord);
 
-eDVBServiceRecord::eDVBServiceRecord(const eServiceReferenceDVB &ref, bool isstreamclient = false):
+eDVBServiceRecord::eDVBServiceRecord(const eServiceReferenceDVB &ref, bool isstreamclient):
        m_ref(ref),m_is_stream_client(isstreamclient)
 {
        CONNECT(m_service_handler.serviceEvent, eDVBServiceRecord::serviceEvent);
        m_ref(ref),m_is_stream_client(isstreamclient)
 {
        CONNECT(m_service_handler.serviceEvent, eDVBServiceRecord::serviceEvent);
index e79be09..8e8f190 100755 (executable)
 #include <gst/pbutils/missing-plugins.h>
 #include <sys/stat.h>
 
 #include <gst/pbutils/missing-plugins.h>
 #include <sys/stat.h>
 
+#define GSTREAMER_SUBTITLE_SYNC_MODE_BUG
+
+#define SUBTITLE_DEBUG
+
 #define HTTP_TIMEOUT 10
 
 #define HTTP_TIMEOUT 10
 
+typedef enum
+{
+       GST_PLAY_FLAG_VIDEO         = 0x00000001,
+       GST_PLAY_FLAG_AUDIO         = 0x00000002,
+       GST_PLAY_FLAG_TEXT          = 0x00000004,
+       GST_PLAY_FLAG_VIS           = 0x00000008,
+       GST_PLAY_FLAG_SOFT_VOLUME   = 0x00000010,
+       GST_PLAY_FLAG_NATIVE_AUDIO  = 0x00000020,
+       GST_PLAY_FLAG_NATIVE_VIDEO  = 0x00000040,
+       GST_PLAY_FLAG_DOWNLOAD      = 0x00000080,
+       GST_PLAY_FLAG_BUFFERING     = 0x00000100
+} GstPlayFlags;
+
 // eServiceFactoryMP3
 
 eServiceFactoryMP3::eServiceFactoryMP3()
 // eServiceFactoryMP3
 
 eServiceFactoryMP3::eServiceFactoryMP3()
@@ -223,15 +240,13 @@ int eServiceMP3::ac3_delay,
 eServiceMP3::eServiceMP3(eServiceReference ref)
        :m_ref(ref), m_pump(eApp, 1)
 {
 eServiceMP3::eServiceMP3(eServiceReference ref)
        :m_ref(ref), m_pump(eApp, 1)
 {
-       m_seekTimeout = eTimer::create(eApp);
        m_subtitle_sync_timer = eTimer::create(eApp);
        m_streamingsrc_timeout = 0;
        m_stream_tags = 0;
        m_currentAudioStream = -1;
        m_subtitle_sync_timer = eTimer::create(eApp);
        m_streamingsrc_timeout = 0;
        m_stream_tags = 0;
        m_currentAudioStream = -1;
-       m_currentSubtitleStream = 0;
+       m_currentSubtitleStream = -1;
        m_subtitle_widget = 0;
        m_subtitle_widget = 0;
-       m_currentTrickRatio = 0;
-       m_subs_to_pull = 0;
+       m_currentTrickRatio = 1.0;
        m_buffer_size = 1*1024*1024;
        m_prev_decoder_time = -1;
        m_decoder_time_valid_state = 0;
        m_buffer_size = 1*1024*1024;
        m_prev_decoder_time = -1;
        m_decoder_time_valid_state = 0;
@@ -239,8 +254,6 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
        //vuplus
        m_is_hls_stream = 0;
        audioSink = videoSink = NULL;
        //vuplus
        m_is_hls_stream = 0;
        audioSink = videoSink = NULL;
-
-       CONNECT(m_seekTimeout->timeout, eServiceMP3::seekTimeoutCB);
        CONNECT(m_subtitle_sync_timer->timeout, eServiceMP3::pushSubtitles);
        CONNECT(m_pump.recv_msg, eServiceMP3::gstPoll);
        m_aspect = m_width = m_height = m_framerate = m_progressive = -1;
        CONNECT(m_subtitle_sync_timer->timeout, eServiceMP3::pushSubtitles);
        CONNECT(m_pump.recv_msg, eServiceMP3::gstPoll);
        m_aspect = m_width = m_height = m_framerate = m_progressive = -1;
@@ -251,7 +264,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
        const char *filename = m_ref.path.c_str();
        const char *ext = strrchr(filename, '.');
        if (!ext)
        const char *filename = m_ref.path.c_str();
        const char *ext = strrchr(filename, '.');
        if (!ext)
-               ext = filename;
+               ext = filename + strlen(filename);
 
        m_sourceinfo.is_video = FALSE;
        m_sourceinfo.audiotype = atUnknown;
 
        m_sourceinfo.is_video = FALSE;
        m_sourceinfo.audiotype = atUnknown;
@@ -312,7 +325,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
                                ePythonConfigQuery::getConfigValue("config.mediaplayer.alternateUserAgent", m_useragent);
                }
                if ( m_useragent.length() == 0 )
                                ePythonConfigQuery::getConfigValue("config.mediaplayer.alternateUserAgent", m_useragent);
                }
                if ( m_useragent.length() == 0 )
-                       m_useragent = "Dream Multimedia Dreambox Enigma2 Mediaplayer";
+                       m_useragent = "Enigma2 Mediaplayer";
        }
        else if ( m_sourceinfo.containertype == ctCDA )
        {
        }
        else if ( m_sourceinfo.containertype == ctCDA )
        {
@@ -334,38 +347,45 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
 
                uri = g_filename_to_uri(filename, NULL, NULL);
 
 
                uri = g_filename_to_uri(filename, NULL, NULL);
 
-       //eDebug("eServiceMP3::playbin2 uri=%s", uri);
-       eDebug("eServiceMP3::playbin2");
+       eDebug("eServiceMP3::playbin uri=%s", uri);
 
 
+#if GST_VERSION_MAJOR < 1
        m_gst_playbin = gst_element_factory_make("playbin2", "playbin");
        m_gst_playbin = gst_element_factory_make("playbin2", "playbin");
-       if (!m_gst_playbin)
-               m_errorInfo.error_message = "failed to create GStreamer pipeline!\n";
-
-       g_object_set (G_OBJECT (m_gst_playbin), "uri", uri, NULL);
-
-       int flags = 0x47; // ( GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_TEXT );
-       g_object_set (G_OBJECT (m_gst_playbin), "flags", flags, NULL);
-
-       g_free(uri);
-
-       GstElement *subsink = gst_element_factory_make("appsink", "subtitle_sink");
-       if (!subsink)
-               eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-appsink");
-       else
-       {
-               m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this);
-               g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-pango-markup; video/x-dvd-subpicture; subpicture/x-pgs"), NULL);
-               g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL);
-               
-       }
+#else
+       m_gst_playbin = gst_element_factory_make("playbin", "playbin");
+#endif 
 
        if ( m_gst_playbin )
        {
 
        if ( m_gst_playbin )
        {
-               gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), gstBusSyncHandler, this);
-               char srt_filename[strlen(filename)+1];
-               strncpy(srt_filename,filename,strlen(filename)-3);
-               srt_filename[strlen(filename)-3]='\0';
-               strcat(srt_filename, "srt");
+               int flags;
+               g_object_get(G_OBJECT (m_gst_playbin), "flags", &flags, NULL);
+               flags |= GST_PLAY_FLAG_NATIVE_VIDEO;
+               flags &= ~GST_PLAY_FLAG_SOFT_VOLUME;
+               g_object_set (G_OBJECT (m_gst_playbin), "flags", flags, NULL);
+               g_object_set (G_OBJECT (m_gst_playbin), "uri", uri, NULL);
+               g_free(uri);
+
+               GstElement *subsink = gst_element_factory_make("subsink", "subtitle_sink");
+               if (!subsink)
+                       eDebug("eServiceMP3::sorry, can't play: missing gst-plugin-subsink");
+               else
+               {
+                       m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this);
+                       g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-raw; text/x-pango-markup; video/x-dvd-subpicture; subpicture/x-pgs"), NULL);
+                       g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL);
+                       g_object_set (G_OBJECT (m_gst_playbin), "current-text", m_currentSubtitleStream, NULL);
+               }
+               GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin));
+#if GST_VERSION_MAJOR < 1
+               gst_bus_set_sync_handler(bus, gstBusSyncHandler, this);
+#else
+               gst_bus_set_sync_handler(bus, gstBusSyncHandler, this, NULL);
+#endif
+               gst_object_unref(bus);
+               char srt_filename[ext - filename + 5];
+               strncpy(srt_filename, filename, ext - filename);
+               srt_filename[ext - filename]='\0';
+               strcat(srt_filename, ".srt");
                struct stat buffer;
                if (stat(srt_filename, &buffer) == 0)
                {
                struct stat buffer;
                if (stat(srt_filename, &buffer) == 0)
                {
@@ -383,6 +403,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
                if (m_gst_playbin)
                        gst_object_unref(GST_OBJECT(m_gst_playbin));
 
                if (m_gst_playbin)
                        gst_object_unref(GST_OBJECT(m_gst_playbin));
 
+               m_errorInfo.error_message = "failed to create GStreamer pipeline!\n";
                eDebug("eServiceMP3::sorry, can't play: %s",m_errorInfo.error_message.c_str());
                m_gst_playbin = 0;
        }
                eDebug("eServiceMP3::sorry, can't play: %s",m_errorInfo.error_message.c_str());
                m_gst_playbin = 0;
        }
@@ -393,18 +414,28 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
 eServiceMP3::~eServiceMP3()
 {
        // disconnect subtitle callback
 eServiceMP3::~eServiceMP3()
 {
        // disconnect subtitle callback
-       GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink");
+       GstElement *subsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink");
 
 
-       if (appsink)
+       if (subsink)
        {
        {
-               g_signal_handler_disconnect (appsink, m_subs_to_pull_handler_id);
-               gst_object_unref(appsink);
+               g_signal_handler_disconnect (subsink, m_subs_to_pull_handler_id);
+               gst_object_unref(subsink);
        }
 
        }
 
-       delete m_subtitle_widget;
+       if (m_subtitle_widget)
+               delete m_subtitle_widget;
 
 
-       // disconnect sync handler callback
-       gst_bus_set_sync_handler(gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin)), NULL, NULL);
+       if (m_gst_playbin)
+       {
+               // disconnect sync handler callback
+               GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin));
+#if GST_VERSION_MAJOR < 1
+               gst_bus_set_sync_handler(bus, NULL, NULL);
+#else
+               gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
+#endif
+               gst_object_unref(bus);
+       }
 
        if (m_state == stRunning)
                stop();
 
        if (m_state == stRunning)
                stop();
@@ -470,7 +501,6 @@ RESULT eServiceMP3::stop()
        //GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_gst_playbin),GST_DEBUG_GRAPH_SHOW_ALL,"e2-playbin");
 
        //eDebug("eServiceMP3::stop %s", m_ref.path.c_str());
        //GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_gst_playbin),GST_DEBUG_GRAPH_SHOW_ALL,"e2-playbin");
 
        //eDebug("eServiceMP3::stop %s", m_ref.path.c_str());
-       eDebug("eServiceMP3::stop service..");
        gst_element_set_state(m_gst_playbin, GST_STATE_NULL);
        m_state = stStopped;
 
        gst_element_set_state(m_gst_playbin, GST_STATE_NULL);
        m_state = stStopped;
 
@@ -493,7 +523,7 @@ RESULT eServiceMP3::setSlowMotion(int ratio)
        if (!ratio)
                return 0;
        eDebug("eServiceMP3::setSlowMotion ratio=%f",1/(float)ratio);
        if (!ratio)
                return 0;
        eDebug("eServiceMP3::setSlowMotion ratio=%f",1/(float)ratio);
-       return trickSeek(1/(float)ratio);
+       return trickSeek(1.0/(gdouble)ratio);
 }
 
 RESULT eServiceMP3::setFastForward(int ratio)
 }
 
 RESULT eServiceMP3::setFastForward(int ratio)
@@ -502,28 +532,6 @@ RESULT eServiceMP3::setFastForward(int ratio)
        return trickSeek(ratio);
 }
 
        return trickSeek(ratio);
 }
 
-void eServiceMP3::seekTimeoutCB()
-{
-       pts_t ppos, len;
-       getPlayPosition(ppos);
-       getLength(len);
-       ppos += 90000*m_currentTrickRatio;
-       
-       if (ppos < 0)
-       {
-               ppos = 0;
-               m_seekTimeout->stop();
-       }
-       if (ppos > len)
-       {
-               ppos = 0;
-               stop();
-               m_seekTimeout->stop();
-               return;
-       }
-       seekTo(ppos);
-}
-
                // iPausableService
 RESULT eServiceMP3::pause()
 {
                // iPausableService
 RESULT eServiceMP3::pause()
 {
@@ -540,6 +548,9 @@ RESULT eServiceMP3::unpause()
        if (!m_gst_playbin || m_state != stRunning)
                return -1;
 
        if (!m_gst_playbin || m_state != stRunning)
                return -1;
 
+       if (m_currentTrickRatio != 1.0)
+               trickSeek(1.0);
+
        gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
 
        return 0;
        gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
 
        return 0;
@@ -562,12 +573,15 @@ RESULT eServiceMP3::getLength(pts_t &pts)
 
        GstFormat fmt = GST_FORMAT_TIME;
        gint64 len;
 
        GstFormat fmt = GST_FORMAT_TIME;
        gint64 len;
-       
+#if GST_VERSION_MAJOR < 1      
        if (!gst_element_query_duration(m_gst_playbin, &fmt, &len))
        if (!gst_element_query_duration(m_gst_playbin, &fmt, &len))
+#else
+       if (!gst_element_query_duration(m_gst_playbin, fmt, &len))
+#endif
                return -1;
                /* len is in nanoseconds. we have 90 000 pts per second. */
        
                return -1;
                /* len is in nanoseconds. we have 90 000 pts per second. */
        
-       pts = len / 11111;
+       pts = len / 11111LL;
        return 0;
 }
 
        return 0;
 }
 
@@ -575,9 +589,15 @@ RESULT eServiceMP3::seekToImpl(pts_t to)
 {
                /* convert pts to nanoseconds */
        gint64 time_nanoseconds = to * 11111LL;
 {
                /* convert pts to nanoseconds */
        gint64 time_nanoseconds = to * 11111LL;
-       if (!gst_element_seek (m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
+#if GST_VERSION_MAJOR < 1
+       if (!gst_element_seek (m_gst_playbin, m_currentTrickRatio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH),
                GST_SEEK_TYPE_SET, time_nanoseconds,
                GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
                GST_SEEK_TYPE_SET, time_nanoseconds,
                GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
+#else
+       if (!gst_element_seek (m_gst_playbin, m_currentTrickRatio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
+               GST_SEEK_TYPE_SET, time_nanoseconds,
+               GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
+#endif
        {
                eDebug("eServiceMP3::seekTo failed");
                return -1;
        {
                eDebug("eServiceMP3::seekTo failed");
                return -1;
@@ -591,14 +611,11 @@ RESULT eServiceMP3::seekTo(pts_t to)
        RESULT ret = -1;
 
        if (m_gst_playbin) {
        RESULT ret = -1;
 
        if (m_gst_playbin) {
-               eSingleLocker l(m_subs_to_pull_lock); // this is needed to dont handle incomming subtitles during seek!
-               if (!(ret = seekToImpl(to)))
-               {
-                       m_subtitle_pages.clear();
-                       m_prev_decoder_time = -1;
-                       m_decoder_time_valid_state = 0;
-                       m_subs_to_pull = 0;
-               }
+               m_subtitle_sync_timer->stop();
+               m_subtitle_pages.clear();
+               m_prev_decoder_time = -1;
+               m_decoder_time_valid_state = 0;
+               ret = seekToImpl(to);
        }
 
        return ret;
        }
 
        return ret;
@@ -616,33 +633,50 @@ RESULT eServiceMP3::trickSeek(gdouble ratio)
        int flags;
        flags = GST_SEEK_FLAG_NONE;
        flags |= GST_SEEK_FLAG_FLUSH;
        int flags;
        flags = GST_SEEK_FLAG_NONE;
        flags |= GST_SEEK_FLAG_FLUSH;
-//     flags |= GstSeekFlags (GST_SEEK_FLAG_ACCURATE);
+#if GST_VERSION_MAJOR >= 1
        flags |= GST_SEEK_FLAG_KEY_UNIT;
        flags |= GST_SEEK_FLAG_KEY_UNIT;
-//     flags |= GstSeekFlags (GST_SEEK_FLAG_SEGMENT);
-//     flags |= GstSeekFlags (GST_SEEK_FLAG_SKIP);
+#endif
 
        GstFormat fmt = GST_FORMAT_TIME;
 
        GstFormat fmt = GST_FORMAT_TIME;
-       gint64 pos, len;
+       bool validposition = false;
+       pts_t pos;
+       gint64 len;
+       
+#if GST_VERSION_MAJOR < 1
        gst_element_query_duration(m_gst_playbin, &fmt, &len);
        gst_element_query_duration(m_gst_playbin, &fmt, &len);
-       gst_element_query_position(m_gst_playbin, &fmt, &pos);
-
-       if ( ratio >= 0 )
-       {
-               s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, (GstSeekFlags)flags, GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, len);
+#else
+       gst_element_query_duration(m_gst_playbin, fmt, &len);
+#endif
 
 
-               eDebug("eServiceMP3::trickSeek with rate %lf to %" GST_TIME_FORMAT " ", ratio, GST_TIME_ARGS (pos));
-       }
-       else
+       if (getPlayPosition(pos) >= 0)
        {
        {
-               s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_SKIP|GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1);
+               validposition = true;
+               pos = pos * 11111LL;
        }
 
        }
 
-       if (!gst_element_send_event ( GST_ELEMENT (m_gst_playbin), s_event))
+       if ( validposition )
        {
        {
-               eDebug("eServiceMP3::trickSeek failed");
-               return -1;
-       }
+               if ( ratio >= 0.0 )
+               {
+                       s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, (GstSeekFlags)flags, GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, len);
 
 
+                       eDebug("eServiceMP3::trickSeek with rate %lf to %" GST_TIME_FORMAT " ", ratio, GST_TIME_ARGS (pos));
+               }
+               else
+               {
+                       s_event = gst_event_new_seek (ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_SKIP|GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1);
+               }
+
+               if (!gst_element_send_event ( GST_ELEMENT (m_gst_playbin), s_event))
+               {
+                       eDebug("eServiceMP3::trickSeek failed");
+                       return -1;
+               }
+       }
+       m_subtitle_pages.clear();
+       m_prev_decoder_time = -1;
+       m_decoder_time_valid_state = 0;
+       m_currentTrickRatio = ratio;
        return 0;
 }
 
        return 0;
 }
 
@@ -653,13 +687,15 @@ RESULT eServiceMP3::seekRelative(int direction, pts_t to)
                return -1;
 
        pts_t ppos;
                return -1;
 
        pts_t ppos;
-       getPlayPosition(ppos);
+
+       if (getPlayPosition(ppos) < 0 )
+               return -1;
+
        ppos += to * direction;
        if (ppos < 0)
                ppos = 0;
        ppos += to * direction;
        if (ppos < 0)
                ppos = 0;
-       seekTo(ppos);
        
        
-       return 0;
+       return seekTo(ppos);
 }
 
 RESULT eServiceMP3::getPlayPosition(pts_t &pts)
 }
 
 RESULT eServiceMP3::getPlayPosition(pts_t &pts)
@@ -681,7 +717,11 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts)
        }
        else
        {
        }
        else
        {
+#if GST_VERSION_MAJOR < 1
                if(!gst_element_query_position(m_gst_playbin, &fmt, &pos))
                if(!gst_element_query_position(m_gst_playbin, &fmt, &pos))
+#else
+               if(!gst_element_query_position(m_gst_playbin, fmt, &pos))
+#endif
                {
                        eDebug("gst_element_query_position failed in getPlayPosition");
                        return -1;
                {
                        eDebug("gst_element_query_position failed in getPlayPosition");
                        return -1;
@@ -689,8 +729,8 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts)
        }
 
        /* pos is in nanoseconds. we have 90 000 pts per second. */
        }
 
        /* pos is in nanoseconds. we have 90 000 pts per second. */
-       pts = pos / 11111;
-//     eDebug("gst_element_query_position %lld pts (%lld ms)", pts, pos/1000000);
+       pts = pos / 11111LL;
+//     eDebug("gst_element_query_position %lld pts (%lld ms)", pts, pos/1000000LL);
        return 0;
 }
 
        return 0;
 }
 
@@ -877,12 +917,28 @@ std::string eServiceMP3::getInfoString(int w)
                break;
        case sTagDate:
                GDate *date;
                break;
        case sTagDate:
                GDate *date;
+#if GST_VERSION_MAJOR >= 1
+               GstDateTime *date_time;
+#endif
                if (gst_tag_list_get_date(m_stream_tags, GST_TAG_DATE, &date))
                {
                        gchar res[5];
                        g_date_strftime (res, sizeof(res), "%Y-%M-%D", date); 
                        return (std::string)res;
                }
                if (gst_tag_list_get_date(m_stream_tags, GST_TAG_DATE, &date))
                {
                        gchar res[5];
                        g_date_strftime (res, sizeof(res), "%Y-%M-%D", date); 
                        return (std::string)res;
                }
+#if GST_VERSION_MAJOR >= 1
+               else if (gst_tag_list_get_date_time(m_stream_tags, GST_TAG_DATE_TIME, &date_time))
+               {
+                       if (gst_date_time_has_year(date_time))
+                       {
+                               gchar res[5];
+                               snprintf(res, sizeof(res), "%04d", gst_date_time_get_year(date_time));
+                               gst_date_time_unref(date_time);
+                               return (std::string)res;
+                       }
+                       gst_date_time_unref(date_time);
+               }
+#endif
                break;
        case sTagComposer:
                tag = GST_TAG_COMPOSER;
                break;
        case sTagComposer:
                tag = GST_TAG_COMPOSER;
@@ -1007,24 +1063,42 @@ PyObject *eServiceMP3::getInfoObject(int w)
                        break;
        }
 
                        break;
        }
 
-       if ( isBuffer )
+       if (m_stream_tags && tag)
        {
        {
-               const GValue *gv_buffer = gst_tag_list_get_value_index(m_stream_tags, tag, 0);
-               if ( gv_buffer )
+               if ( isBuffer )
                {
                {
-                       GstBuffer *buffer;
-                       buffer = gst_value_get_buffer (gv_buffer);
-                       return PyBuffer_FromMemory(GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
+                       const GValue *gv_buffer = gst_tag_list_get_value_index(m_stream_tags, tag, 0);
+                       if ( gv_buffer )
+                       {
+                               GstBuffer *buffer;
+                               unsigned char *bufferData;
+                               unsigned int bufferSize;
+                               buffer = gst_value_get_buffer (gv_buffer);
+#if GST_VERSION_MAJOR < 1
+                               bufferData = GST_BUFFER_DATA(buffer);
+                               bufferSize = GST_BUFFER_SIZE(buffer);
+#else
+                               GstMapInfo map;
+                               gst_buffer_map(buffer, &map, GST_MAP_READ);
+                               bufferData = map.data;
+                               bufferSize = map.size;
+#endif
+                               PyObject *ret = PyBuffer_FromMemory(bufferData, bufferSize);
+#if GST_VERSION_MAJOR >= 1
+                               gst_buffer_unmap(buffer, &map);
+#endif
+                               return ret;
+                       }
+               }
+               else
+               {
+                       gdouble value = 0.0;
+                       gst_tag_list_get_double(m_stream_tags, tag, &value);
+                       return PyFloat_FromDouble(value);
                }
                }
-       }
-       else
-       {
-               gdouble value = 0.0;
-               gst_tag_list_get_double(m_stream_tags, tag, &value);
-               return PyFloat_FromDouble(value);
        }
 
        }
 
-       return 0;
+       Py_RETURN_NONE;
 }
 
 RESULT eServiceMP3::audioChannel(ePtr<iAudioChannelSelection> &ptr)
 }
 
 RESULT eServiceMP3::audioChannel(ePtr<iAudioChannelSelection> &ptr)
@@ -1065,16 +1139,23 @@ int eServiceMP3::getCurrentTrack()
 
 RESULT eServiceMP3::selectTrack(unsigned int i)
 {
 
 RESULT eServiceMP3::selectTrack(unsigned int i)
 {
+       bool validposition = false;
        pts_t ppos;
        pts_t ppos;
-       getPlayPosition(ppos);
-       ppos -= 90000;
-       if (ppos < 0)
-               ppos = 0;
+       if (getPlayPosition(ppos) >= 0)
+       {
+               validposition = true;
+               ppos -= 90000;
+               if (ppos < 0)
+                       ppos = 0;
+       }
 
        int ret = selectAudioStream(i);
        if (!ret) {
 
        int ret = selectAudioStream(i);
        if (!ret) {
-               /* flush */
-               seekTo(ppos);
+               if (validposition)
+               {
+                       /* flush */
+                       seekTo(ppos);
+               }
        }
 
        return ret;
        }
 
        return ret;
@@ -1136,14 +1217,17 @@ RESULT eServiceMP3::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
 subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL)
 {
        subtype_t type = stUnknown;
 subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL)
 {
        subtype_t type = stUnknown;
+#if GST_VERSION_MAJOR < 1
        GstCaps* caps = gst_pad_get_negotiated_caps(pad);
        GstCaps* caps = gst_pad_get_negotiated_caps(pad);
-
+#else
+       GstCaps* caps = gst_pad_get_current_caps(pad);
+#endif
        if (!caps && !g_codec)
        {
                caps = gst_pad_get_allowed_caps(pad);
        }
 
        if (!caps && !g_codec)
        {
                caps = gst_pad_get_allowed_caps(pad);
        }
 
-       if ( caps )
+       if ( caps && !gst_caps_is_empty(caps))
        {
                GstStructure* str = gst_caps_get_structure(caps, 0);
                const gchar *g_type = gst_structure_get_name(str);
        {
                GstStructure* str = gst_caps_get_structure(caps, 0);
                const gchar *g_type = gst_structure_get_name(str);
@@ -1153,7 +1237,7 @@ subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL)
                        type = stVOB;
                else if ( !strcmp(g_type, "text/x-pango-markup") )
                        type = stSSA;
                        type = stVOB;
                else if ( !strcmp(g_type, "text/x-pango-markup") )
                        type = stSSA;
-               else if ( !strcmp(g_type, "text/plain") )
+               else if ( !strcmp(g_type, "text/plain") || !strcmp(g_type, "text/x-plain") || !strcmp(g_type, "text/x-raw"))
                        type = stPlainText;
                else if ( !strcmp(g_type, "subpicture/x-pgs") )
                        type = stPGS;
                        type = stPlainText;
                else if ( !strcmp(g_type, "subpicture/x-pgs") )
                        type = stPGS;
@@ -1180,10 +1264,18 @@ subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL)
        return type;
 }
 
        return type;
 }
 
+#if GST_VERSION_MAJOR < 1
 gint eServiceMP3::match_sinktype(GstElement *element, gpointer type)
 {
        return strcmp(g_type_name(G_OBJECT_TYPE(element)), (const char*)type);
 }
 gint eServiceMP3::match_sinktype(GstElement *element, gpointer type)
 {
        return strcmp(g_type_name(G_OBJECT_TYPE(element)), (const char*)type);
 }
+#else
+gint eServiceMP3::match_sinktype(const GValue *velement, const gchar *type)
+{
+       GstElement *element = GST_ELEMENT_CAST(g_value_get_object(velement));
+       return strcmp(g_type_name(G_OBJECT_TYPE(element)), type);
+}
+#endif
 
 void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
 {
 
 void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
 {
@@ -1239,15 +1331,17 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                                }       break;
                                case GST_STATE_CHANGE_READY_TO_PAUSED:
                                {
                                }       break;
                                case GST_STATE_CHANGE_READY_TO_PAUSED:
                                {
+#if GST_VERSION_MAJOR >= 1
+                                       GValue result = { 0, };
+#endif
                                        GstIterator *children;
                                        GstIterator *children;
-                                       GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink");
-                                       if (appsink)
+                                       GstElement *subsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink");
+                                       if (subsink)
                                        {
                                        {
-                                               g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL);
-                                               g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL);
-                                               g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL);
-                                               eDebug("eServiceMP3::appsink properties set!");
-                                               gst_object_unref(appsink);
+#ifdef GSTREAMER_SUBTITLE_SYNC_MODE_BUG
+                                               g_object_set (G_OBJECT (subsink), "sync", FALSE, NULL);
+#endif
+                                               gst_object_unref(subsink);
                                        }
 
                                        if (audioSink)
                                        }
 
                                        if (audioSink)
@@ -1262,11 +1356,27 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                                        }
 
                                        children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin));
                                        }
 
                                        children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin));
+#if GST_VERSION_MAJOR < 1
                                        audioSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBAudioSink"));
                                        audioSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBAudioSink"));
+#else
+                                       if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &result, (gpointer)"GstDVBAudioSink"))
+                                       {
+                                               audioSink = GST_ELEMENT_CAST(g_value_dup_object(&result));
+                                               g_value_unset(&result);
+                                       }
+#endif
                                        gst_iterator_free(children);
 
                                        children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin));
                                        gst_iterator_free(children);
 
                                        children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin));
+#if GST_VERSION_MAJOR < 1
                                        videoSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBVideoSink"));
                                        videoSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBVideoSink"));
+#else
+                                       if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &result, (gpointer)"GstDVBVideoSink"))
+                                       {
+                                               videoSink = GST_ELEMENT_CAST(g_value_dup_object(&result));
+                                               g_value_unset(&result);
+                                       }
+#endif
                                        gst_iterator_free(children);
 
                                        setAC3Delay(ac3_delay);
                                        gst_iterator_free(children);
 
                                        setAC3Delay(ac3_delay);
@@ -1356,11 +1466,35 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                        if ( gv_image )
                        {
                                GstBuffer *buf_image;
                        if ( gv_image )
                        {
                                GstBuffer *buf_image;
+#if GST_VERSION_MAJOR < 1
                                buf_image = gst_value_get_buffer (gv_image);
                                buf_image = gst_value_get_buffer (gv_image);
+#else
+                               GstSample *sample;
+                               sample = (GstSample *)g_value_get_boxed(gv_image);
+                               buf_image = gst_sample_get_buffer(sample);
+#endif
                                int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644);
                                int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644);
-                               int ret = write(fd, GST_BUFFER_DATA(buf_image), GST_BUFFER_SIZE(buf_image));
-                               close(fd);
-                               eDebug("eServiceMP3::/tmp/.id3coverart %d bytes written ", ret);
+                               if (fd >= 0)
+                               {
+                                       guint8 *data;
+                                       gsize size;
+                                       int ret;
+#if GST_VERSION_MAJOR < 1
+                                       data = GST_BUFFER_DATA(buf_image);
+                                       size = GST_BUFFER_SIZE(buf_image);
+#else
+                                       GstMapInfo map;
+                                       gst_buffer_map(buf_image, &map, GST_MAP_READ);
+                                       data = map.data;
+                                       size = map.size;
+#endif
+                                       ret = write(fd, data, size);
+#if GST_VERSION_MAJOR >= 1
+                                       gst_buffer_unmap(buf_image, &map);
+#endif
+                                       close(fd);
+                                       eDebug("eServiceMP3::/tmp/.id3coverart %d bytes written ", ret);
+                               }
                                m_event((iPlayableService*)this, evUser+13);
                        }
                        gst_tag_list_free(tags);
                                m_event((iPlayableService*)this, evUser+13);
                        }
                        gst_tag_list_free(tags);
@@ -1372,8 +1506,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                        if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
                                break;
 
                        if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
                                break;
 
-                       GstTagList *tags;
-                       gint i, active_idx, n_video = 0, n_audio = 0, n_text = 0;
+                       gint i, n_video = 0, n_audio = 0, n_text = 0;
 
                        g_object_get (m_gst_playbin, "n-video", &n_video, NULL);
                        g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL);
 
                        g_object_get (m_gst_playbin, "n-video", &n_video, NULL);
                        g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL);
@@ -1384,8 +1517,6 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                        if ( n_video + n_audio <= 0 )
                                stop();
 
                        if ( n_video + n_audio <= 0 )
                                stop();
 
-                       active_idx = 0;
-
                        m_audioStreams.clear();
                        m_subtitleStreams.clear();
 
                        m_audioStreams.clear();
                        m_subtitleStreams.clear();
 
@@ -1393,9 +1524,14 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                        {
                                audioStream audio;
                                gchar *g_codec, *g_lang;
                        {
                                audioStream audio;
                                gchar *g_codec, *g_lang;
+                               GstTagList *tags = NULL;
                                GstPad* pad = 0;
                                g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad);
                                GstPad* pad = 0;
                                g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad);
+#if GST_VERSION_MAJOR < 1
                                GstCaps* caps = gst_pad_get_negotiated_caps(pad);
                                GstCaps* caps = gst_pad_get_negotiated_caps(pad);
+#else
+                               GstCaps* caps = gst_pad_get_current_caps(pad);
+#endif
                                if (!caps)
                                        continue;
                                GstStructure* str = gst_caps_get_structure(caps, 0);
                                if (!caps)
                                        continue;
                                GstStructure* str = gst_caps_get_structure(caps, 0);
@@ -1404,7 +1540,11 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                                g_codec = g_strdup(g_type);
                                g_lang = g_strdup_printf ("und");
                                g_signal_emit_by_name (m_gst_playbin, "get-audio-tags", i, &tags);
                                g_codec = g_strdup(g_type);
                                g_lang = g_strdup_printf ("und");
                                g_signal_emit_by_name (m_gst_playbin, "get-audio-tags", i, &tags);
+#if GST_VERSION_MAJOR < 1
                                if ( tags && gst_is_tag_list(tags) )
                                if ( tags && gst_is_tag_list(tags) )
+#else
+                               if ( tags && GST_IS_TAG_LIST(tags) )
+#endif
                                {
                                        gst_tag_list_get_string(tags, GST_TAG_AUDIO_CODEC, &g_codec);
                                        gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
                                {
                                        gst_tag_list_get_string(tags, GST_TAG_AUDIO_CODEC, &g_codec);
                                        gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
@@ -1422,12 +1562,17 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                        for (i = 0; i < n_text; i++)
                        {
                                gchar *g_codec = NULL, *g_lang = NULL;
                        for (i = 0; i < n_text; i++)
                        {
                                gchar *g_codec = NULL, *g_lang = NULL;
+                               GstTagList *tags = NULL;
                                g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags);
                                subtitleStream subs;
 //                             int ret;
 
                                g_lang = g_strdup_printf ("und");
                                g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags);
                                subtitleStream subs;
 //                             int ret;
 
                                g_lang = g_strdup_printf ("und");
+#if GST_VERSION_MAJOR < 1
                                if ( tags && gst_is_tag_list(tags) )
                                if ( tags && gst_is_tag_list(tags) )
+#else
+                               if ( tags && GST_IS_TAG_LIST(tags) )
+#endif
                                {
                                        gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
                                        gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec);
                                {
                                        gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
                                        gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec);
@@ -1608,7 +1753,11 @@ audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure)
                return atAC3;
        else if ( gst_structure_has_name (structure, "audio/x-dts") || gst_structure_has_name (structure, "audio/dts") )
                return atDTS;
                return atAC3;
        else if ( gst_structure_has_name (structure, "audio/x-dts") || gst_structure_has_name (structure, "audio/dts") )
                return atDTS;
+#if GST_VERSION_MAJOR < 1
        else if ( gst_structure_has_name (structure, "audio/x-raw-int") )
        else if ( gst_structure_has_name (structure, "audio/x-raw-int") )
+#else
+       else if ( gst_structure_has_name (structure, "audio/x-raw") )
+#endif
                return atPCM;
 
        return atUnknown;
                return atPCM;
 
        return atUnknown;
@@ -1616,32 +1765,51 @@ audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure)
 
 void eServiceMP3::gstPoll(const Message &msg)
 {
 
 void eServiceMP3::gstPoll(const Message &msg)
 {
-       if (msg.type == 1)
+       switch(msg.type)
        {
        {
-               GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin));
-               GstMessage *message;
-               while ((message = gst_bus_pop(bus)))
+               case 1:
                {
                {
-                       gstBusCall(bus, message);
-                       gst_message_unref (message);
+                       GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin));
+                       GstMessage *message;
+                       while ((message = gst_bus_pop(bus)))
+                       {
+                               gstBusCall(bus, message);
+                               gst_message_unref (message);
+                       }
+                       gst_object_unref(bus);
+                       break;
+               }
+               case 2:
+               {
+                       pullSubtitle(msg.d.buffer);
+                       gst_buffer_unref(msg.d.buffer);
+                       break;
+               }
+               case 3:
+               {
+                       gstTextpadHasCAPS_synced(msg.d.pad);
+                       gst_object_unref(msg.d.pad);
+                       break;
+               }
+               default:
+               {
+                       eDebug("gstPoll unhandled Message %d\n", msg.type);
+                       break;
                }
        }
                }
        }
-       else if (msg.type == 2)
-               pullSubtitle();
-       else if (msg.type == 3)
-               gstTextpadHasCAPS_synced(msg.d.pad);
-       else
-               eDebug("gstPoll unhandled Message %d\n", msg.type);
 }
 
 eAutoInitPtr<eServiceFactoryMP3> init_eServiceFactoryMP3(eAutoInitNumbers::service+1, "eServiceFactoryMP3");
 
 }
 
 eAutoInitPtr<eServiceFactoryMP3> init_eServiceFactoryMP3(eAutoInitNumbers::service+1, "eServiceFactoryMP3");
 
-void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data)
+void eServiceMP3::gstCBsubtitleAvail(GstElement *subsink, GstBuffer *buffer, gpointer user_data)
 {
 {
-       eServiceMP3 *_this = (eServiceMP3*)user_data;   
-       eSingleLocker l(_this->m_subs_to_pull_lock);
-       ++_this->m_subs_to_pull;
-       _this->m_pump.send(Message(2));
+       eServiceMP3 *_this = (eServiceMP3*)user_data;
+       if (_this->m_currentSubtitleStream < 0)
+       {
+               if (buffer) gst_buffer_unref(buffer);
+               return;
+       }
+       _this->m_pump.send(Message(2, buffer));
 }
 
 void eServiceMP3::gstTextpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data)
 }
 
 void eServiceMP3::gstTextpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data)
@@ -1668,7 +1836,7 @@ void eServiceMP3::gstTextpadHasCAPS_synced(GstPad *pad)
 
 //             eDebug("gstGhostpadHasCAPS_synced %p %d", pad, m_subtitleStreams.size());
 
 
 //             eDebug("gstGhostpadHasCAPS_synced %p %d", pad, m_subtitleStreams.size());
 
-               if (!m_subtitleStreams.empty())
+               if (m_currentSubtitleStream >= 0 && m_currentSubtitleStream < (int)m_subtitleStreams.size())
                        subs = m_subtitleStreams[m_currentSubtitleStream];
                else {
                        subs.type = stUnknown;
                        subs = m_subtitleStreams[m_currentSubtitleStream];
                else {
                        subs.type = stUnknown;
@@ -1677,20 +1845,22 @@ void eServiceMP3::gstTextpadHasCAPS_synced(GstPad *pad)
 
                if ( subs.type == stUnknown )
                {
 
                if ( subs.type == stUnknown )
                {
-                       GstTagList *tags;
-//                     eDebug("gstGhostpadHasCAPS::m_subtitleStreams[%i].type == stUnknown...", m_currentSubtitleStream);
-
+                       GstTagList *tags = NULL;
                        gchar *g_lang;
                        g_signal_emit_by_name (m_gst_playbin, "get-text-tags", m_currentSubtitleStream, &tags);
 
                        g_lang = g_strdup_printf ("und");
                        gchar *g_lang;
                        g_signal_emit_by_name (m_gst_playbin, "get-text-tags", m_currentSubtitleStream, &tags);
 
                        g_lang = g_strdup_printf ("und");
+#if GST_VERSION_MAJOR < 1
                        if ( tags && gst_is_tag_list(tags) )
                        if ( tags && gst_is_tag_list(tags) )
+#else
+                       if ( tags && GST_IS_TAG_LIST(tags) )
+#endif
                                gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
 
                        subs.language_code = std::string(g_lang);
                        subs.type = getSubtitleType(pad);
 
                                gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
 
                        subs.language_code = std::string(g_lang);
                        subs.type = getSubtitleType(pad);
 
-                       if (!m_subtitleStreams.empty())
+                       if (m_currentSubtitleStream >= 0 && m_currentSubtitleStream < (int)m_subtitleStreams.size())
                                m_subtitleStreams[m_currentSubtitleStream] = subs;
                        else
                                m_subtitleStreams.push_back(subs);
                                m_subtitleStreams[m_currentSubtitleStream] = subs;
                        else
                                m_subtitleStreams.push_back(subs);
@@ -1702,74 +1872,77 @@ void eServiceMP3::gstTextpadHasCAPS_synced(GstPad *pad)
 
                gst_caps_unref (caps);
        }
 
                gst_caps_unref (caps);
        }
-
-       gst_object_unref (pad);
 }
 
 }
 
-void eServiceMP3::pullSubtitle()
+void eServiceMP3::pullSubtitle(GstBuffer *buffer)
 {
 {
-       GstElement *sink;
-       g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL);
-       
-       if (sink)
+       if (buffer && m_currentSubtitleStream >= 0 && m_currentSubtitleStream < (int)m_subtitleStreams.size())
        {
        {
-               while (m_subs_to_pull && m_subtitle_pages.size() < 2)
+#if GST_VERSION_MAJOR < 1
+               gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer);
+               size_t len = GST_BUFFER_SIZE(buffer);
+#else
+               GstMapInfo map;
+               if(!gst_buffer_map(buffer, &map, GST_MAP_READ))
+               {
+                       eDebug("eServiceMP3::pullSubtitle gst_buffer_map failed");
+                       gst_buffer_unref(buffer);
+                       return;
+               }
+               gint64 buf_pos = GST_BUFFER_PTS(buffer);
+               size_t len = map.size;
+//             eDebug("gst_buffer_get_size %zu map.size %zu", gst_buffer_get_size(buffer), len);
+#endif
+               gint64 duration_ns = GST_BUFFER_DURATION(buffer);
+               int subType = m_subtitleStreams[m_currentSubtitleStream].type;
+#ifdef SUBTITLE_DEBUG
+               eDebug("pullSubtitle type = %i" ,subType);
+#endif                         
+               if (subType)
                {
                {
-                       GstBuffer *buffer;
+                       if ( subType < stVOB )
                        {
                        {
-                               eSingleLocker l(m_subs_to_pull_lock);
-                               --m_subs_to_pull;
-                               g_signal_emit_by_name (sink, "pull-buffer", &buffer);
+                               unsigned char line[len+1];
+                               SubtitlePage page;
+#if GST_VERSION_MAJOR < 1
+                               memcpy(line, GST_BUFFER_DATA(buffer), len);
+#else
+                               memcpy(line, map.data, len);
+#endif
+                               line[len] = 0;
+#ifdef SUBTITLE_DEBUG
+                               eDebug("got new text subtitle @ buf_pos = %lld ns (in pts=%lld), dur=%lld: '%s' ", buf_pos, buf_pos/11111LL, duration_ns, line);
+#endif
+                               gRGB rgbcol(0xD0,0xD0,0xD0);
+                               page.type = SubtitlePage::Pango;
+                               page.pango_page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line));
+                               page.pango_page.m_show_pts = buf_pos / 11111LL;
+                               page.pango_page.m_timeout = duration_ns / 1000000;
+                               m_subtitle_pages.push_back(page);
+                               m_subtitle_sync_timer->start(1, true);
                        }
                        }
-                       if (buffer)
+                       else
                        {
                        {
-                               gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer);
-                               gint64 duration_ns = GST_BUFFER_DURATION(buffer);
-                               size_t len = GST_BUFFER_SIZE(buffer);
-                               eDebug("pullSubtitle m_subtitleStreams[m_currentSubtitleStream].type=%i",m_subtitleStreams[m_currentSubtitleStream].type);
-                               
-                               if ( m_subtitleStreams[m_currentSubtitleStream].type )
-                               {
-                                       if ( m_subtitleStreams[m_currentSubtitleStream].type < stVOB )
-                                       {
-                                               unsigned char line[len+1];
-                                               SubtitlePage page;
-                                               memcpy(line, GST_BUFFER_DATA(buffer), len);
-                                               line[len] = 0;
-                                               eDebug("got new text subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line);
-                                               gRGB rgbcol(0xD0,0xD0,0xD0);
-                                               page.type = SubtitlePage::Pango;
-                                               page.pango_page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line));
-                                               page.pango_page.m_show_pts = buf_pos / 11111L;
-                                               page.pango_page.m_timeout = duration_ns / 1000000;
-                                               m_subtitle_pages.push_back(page);
-                                               if (m_subtitle_pages.size()==1)
-                                                       pushSubtitles();
-                                       }
-                                       else
-                                       {
-                                               eDebug("unsupported subpicture... ignoring");
-                                       }
-                               }
-                               gst_buffer_unref(buffer);
+                               eDebug("unsupported subpicture... ignoring");
                        }
                }
                        }
                }
-               gst_object_unref(sink);
+#if GST_VERSION_MAJOR >= 1
+               gst_buffer_unmap(buffer, &map);
+#endif
        }
        }
-       else
-               eDebug("no subtitle sink!");
 }
 
 void eServiceMP3::pushSubtitles()
 {
 }
 
 void eServiceMP3::pushSubtitles()
 {
+       long next_timer = 0;
        while ( !m_subtitle_pages.empty() )
        {
        while ( !m_subtitle_pages.empty() )
        {
-               SubtitlePage &frontpage = m_subtitle_pages.front();
                pts_t running_pts;
                gint64 diff_ms = 0;
                gint64 show_pts = 0;
 
                pts_t running_pts;
                gint64 diff_ms = 0;
                gint64 show_pts = 0;
 
-               getPlayPosition(running_pts);
+               if (getPlayPosition(running_pts) < 0)
+                       m_decoder_time_valid_state = 0;
 
                if (m_decoder_time_valid_state < 4) {
                        ++m_decoder_time_valid_state;
 
                if (m_decoder_time_valid_state < 4) {
                        ++m_decoder_time_valid_state;
@@ -1780,34 +1953,54 @@ void eServiceMP3::pushSubtitles()
 //                                     eDebug("%d: decoder time not valid! prev %lld, now %lld\n", m_decoder_time_valid_state, m_prev_decoder_time/90, running_pts/90);
 //                             else
 //                                     eDebug("%d: decoder time not valid! now %lld\n", m_decoder_time_valid_state, running_pts/90);
 //                                     eDebug("%d: decoder time not valid! prev %lld, now %lld\n", m_decoder_time_valid_state, m_prev_decoder_time/90, running_pts/90);
 //                             else
 //                                     eDebug("%d: decoder time not valid! now %lld\n", m_decoder_time_valid_state, running_pts/90);
-                               m_subtitle_sync_timer->start(25, true);
+                               next_timer = 25;
                                m_prev_decoder_time = running_pts;
                                break;
                        }
                }
 
                                m_prev_decoder_time = running_pts;
                                break;
                        }
                }
 
+               SubtitlePage &frontpage = m_subtitle_pages.front();
                if (frontpage.type == SubtitlePage::Pango)
                        show_pts = frontpage.pango_page.m_show_pts;
 
                diff_ms = ( show_pts - running_pts ) / 90;
                if (frontpage.type == SubtitlePage::Pango)
                        show_pts = frontpage.pango_page.m_show_pts;
 
                diff_ms = ( show_pts - running_pts ) / 90;
-               eDebug("check subtitle: decoder: %lld, show_pts: %lld, diff: %lld ms", running_pts/90, show_pts/90, diff_ms);
+
+#ifdef SUBTITLE_DEBUG
+               int32_t decoder_ms, start_ms, end_ms, diff_start_ms, diff_end_ms;
+               ePangoSubtitlePageElement &element = frontpage.pango_page.m_elements[0];
+               std::string text = element.m_pango_line;
+               decoder_ms = running_pts / 90;
+               start_ms = show_pts/ 90;
+               end_ms = start_ms + frontpage.pango_page.m_timeout;
+               diff_start_ms = start_ms - decoder_ms;
+               diff_end_ms = end_ms - decoder_ms;
+
+               eDebug("*** next subtitle: decoder: %d, start: %d, end: %d, duration_ms: %d, diff_start: %d, diff_end: %d : %s",
+                       decoder_ms, start_ms, end_ms, end_ms - start_ms, diff_start_ms, diff_end_ms, text.c_str());
+#endif
 
                if ( diff_ms < -100 )
                {
 
                if ( diff_ms < -100 )
                {
+#ifdef SUBTITLE_DEBUG
                        eDebug("subtitle too late... drop");
                        eDebug("subtitle too late... drop");
+#endif
                        m_subtitle_pages.pop_front();
                }
                else if ( diff_ms > 20 )
                {
                        m_subtitle_pages.pop_front();
                }
                else if ( diff_ms > 20 )
                {
-                       eDebug("start timer");
-                       m_subtitle_sync_timer->start(diff_ms, true);
+#ifdef SUBTITLE_DEBUG
+                       eDebug("*** current sub in the future, start timer, %d\n", diff_start_ms);
+#endif
+                       next_timer = diff_ms;
                        break;
                }
                else // immediate show
                {
                        if ( m_subtitle_widget )
                        {
                        break;
                }
                else // immediate show
                {
                        if ( m_subtitle_widget )
                        {
-                               eDebug("show!\n");
+#ifdef SUBTITLE_DEBUG
+                               eDebug("*** current sub actual, show!");
+#endif
                                if ( frontpage.type == SubtitlePage::Pango)
                                        m_subtitle_widget->setPage(frontpage.pango_page);
                                m_subtitle_widget->show();
                                if ( frontpage.type == SubtitlePage::Pango)
                                        m_subtitle_widget->setPage(frontpage.pango_page);
                                m_subtitle_widget->show();
@@ -1815,8 +2008,11 @@ void eServiceMP3::pushSubtitles()
                        m_subtitle_pages.pop_front();
                }
        }
                        m_subtitle_pages.pop_front();
                }
        }
-       if (m_subtitle_pages.empty())
-               pullSubtitle();
+       if (!next_timer)
+       {
+               next_timer = 1000;
+       }
+       m_subtitle_sync_timer->start(next_timer, true);
 }
 
 
 }
 
 
@@ -1827,7 +2023,6 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple)
        int tuplesize = PyTuple_Size(tuple);
        int pid, type;
        gint text_pid = 0;
        int tuplesize = PyTuple_Size(tuple);
        int pid, type;
        gint text_pid = 0;
-       eSingleLocker l(m_subs_to_pull_lock);
 
 //     GstPad *pad = 0;
 //     g_signal_emit_by_name (m_gst_playbin, "get-text-pad", m_currentSubtitleStream, &pad);
 
 //     GstPad *pad = 0;
 //     g_signal_emit_by_name (m_gst_playbin, "get-text-pad", m_currentSubtitleStream, &pad);
@@ -1849,12 +2044,14 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple)
 
        if (m_currentSubtitleStream != pid)
        {
 
        if (m_currentSubtitleStream != pid)
        {
-               g_object_set (G_OBJECT (m_gst_playbin), "current-text", pid, NULL);
-               eDebug ("eServiceMP3::enableSubtitles g_object_set current-text = %i", pid);
-               m_currentSubtitleStream = pid;
-               m_subs_to_pull = 0;
-               m_prev_decoder_time = -1;
+               g_object_set (G_OBJECT (m_gst_playbin), "current-text", -1, NULL);
+               m_subtitle_sync_timer->stop();
                m_subtitle_pages.clear();
                m_subtitle_pages.clear();
+               m_prev_decoder_time = -1;
+               m_decoder_time_valid_state = 0;
+               m_currentSubtitleStream = pid;
+               g_object_set (G_OBJECT (m_gst_playbin), "current-text", m_currentSubtitleStream, NULL);
+               eDebug ("eServiceMP3::enableSubtitles g_object_set current-text = %i", pid);
        }
 
        m_subtitle_widget = 0;
        }
 
        m_subtitle_widget = 0;
@@ -1866,6 +2063,14 @@ RESULT eServiceMP3::enableSubtitles(eWidget *parent, ePyObject tuple)
        eDebug ("eServiceMP3::switched to subtitle stream %i", text_pid);
 //     gst_pad_remove_buffer_probe (pad, subprobe_handler_id);
 
        eDebug ("eServiceMP3::switched to subtitle stream %i", text_pid);
 //     gst_pad_remove_buffer_probe (pad, subprobe_handler_id);
 
+#ifdef GSTREAMER_SUBTITLE_SYNC_MODE_BUG
+                       /*
+                        * when we're running the subsink in sync=false mode,
+                        * we have to force a seek, before the new subtitle stream will start
+                        */
+                       seekRelative(-1, 90000);
+#endif
+
        m_event((iPlayableService*)this, evUpdatedInfo);
 
        return 0;
        m_event((iPlayableService*)this, evUpdatedInfo);
 
        return 0;
@@ -1878,9 +2083,15 @@ error_out:
 
 RESULT eServiceMP3::disableSubtitles(eWidget *parent)
 {
 
 RESULT eServiceMP3::disableSubtitles(eWidget *parent)
 {
+       m_currentSubtitleStream = -1;
+       g_object_set (G_OBJECT (m_gst_playbin), "current-text", m_currentSubtitleStream, NULL);
        eDebug("eServiceMP3::disableSubtitles");
        eDebug("eServiceMP3::disableSubtitles");
+       m_subtitle_sync_timer->stop();
        m_subtitle_pages.clear();
        m_subtitle_pages.clear();
-       delete m_subtitle_widget;
+       m_prev_decoder_time = -1;
+       m_decoder_time_valid_state = 0;
+       if (m_subtitle_widget)
+               delete m_subtitle_widget;
        m_subtitle_widget = 0;
        return 0;
 }
        m_subtitle_widget = 0;
        return 0;
 }
index 41aec13..156400d 100644 (file)
@@ -189,8 +189,6 @@ private:
        std::vector<subtitleStream> m_subtitleStreams;
        eSubtitleWidget *m_subtitle_widget;
        int m_currentTrickRatio;
        std::vector<subtitleStream> m_subtitleStreams;
        eSubtitleWidget *m_subtitle_widget;
        int m_currentTrickRatio;
-       ePtr<eTimer> m_seekTimeout;
-       void seekTimeoutCB();
        friend class eServiceFactoryMP3;
        eServiceReference m_ref;
        int m_buffer_size;
        friend class eServiceFactoryMP3;
        eServiceReference m_ref;
        int m_buffer_size;
@@ -222,9 +220,15 @@ private:
                 {
                         d.pad=pad;
                 }
                 {
                         d.pad=pad;
                 }
+                               Message(int type, GstBuffer *buffer)
+                        :type(type)
+                {
+                        d.buffer=buffer;
+                }
 
                 int type;
                 union {
 
                 int type;
                 union {
+                        GstBuffer *buffer; // for msg type 2
                         GstPad *pad; // for msg type 3
                 } d;
         };
                         GstPad *pad; // for msg type 3
                 } d;
         };
@@ -232,12 +236,16 @@ private:
         eFixedMessagePump<Message> m_pump;
 
         audiotype_t gstCheckAudioPad(GstStructure* structure);
         eFixedMessagePump<Message> m_pump;
 
         audiotype_t gstCheckAudioPad(GstStructure* structure);
+#if GST_VERSION_MAJOR < 1
         static gint match_sinktype(GstElement *element, gpointer type);
         static gint match_sinktype(GstElement *element, gpointer type);
+#else
+        static gint match_sinktype(const GValue *velement, const gchar *type);
+#endif
         void gstBusCall(GstBus *bus, GstMessage *msg);
         static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data);
        static void gstTextpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data);
        void gstTextpadHasCAPS_synced(GstPad *pad);
         void gstBusCall(GstBus *bus, GstMessage *msg);
         static GstBusSyncReply gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data);
        static void gstTextpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data);
        void gstTextpadHasCAPS_synced(GstPad *pad);
-        static void gstCBsubtitleAvail(GstElement *element, gpointer user_data);
+        static void gstCBsubtitleAvail(GstElement *element, GstBuffer *buffer, gpointer user_data);
         GstPad* gstCreateSubtitleSink(eServiceMP3* _this, subtype_t type);
        void gstPoll(const Message&);
         static void gstHTTPSourceSetAgent(GObject *source, GParamSpec *unused, gpointer user_data);
         GstPad* gstCreateSubtitleSink(eServiceMP3* _this, subtype_t type);
        void gstPoll(const Message&);
         static void gstHTTPSourceSetAgent(GObject *source, GParamSpec *unused, gpointer user_data);
@@ -257,11 +265,9 @@ private:
         int m_decoder_time_valid_state;
 
         void pushSubtitles();
         int m_decoder_time_valid_state;
 
         void pushSubtitles();
-        void pullSubtitle();
+        void pullSubtitle(GstBuffer *buffer);
         void sourceTimeout();
         void sourceTimeout();
-        int m_subs_to_pull;
         sourceStream m_sourceinfo;
         sourceStream m_sourceinfo;
-       eSingleLock m_subs_to_pull_lock;
        gulong m_subs_to_pull_handler_id;
 
        RESULT seekToImpl(pts_t to);
        gulong m_subs_to_pull_handler_id;
 
        RESULT seekToImpl(pts_t to);