summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac13
-rwxr-xr-xdata/startwizard.xml90
-rw-r--r--lib/base/eptrlist.h4
-rw-r--r--lib/dvb/Makefile.am6
-rw-r--r--lib/dvb/decoder.cpp4
-rw-r--r--lib/dvb/decoder.h2
-rwxr-xr-xlib/dvb/dvb.cpp68
-rw-r--r--lib/dvb/dvb.h4
-rw-r--r--lib/dvb/fbc.cpp880
-rw-r--r--lib/dvb/fbc.h80
-rwxr-xr-xlib/dvb/frontend.cpp14
-rw-r--r--lib/dvb/frontend.h5
-rw-r--r--lib/dvb/pmt.cpp15
-rw-r--r--lib/dvb/pmt.h2
-rw-r--r--lib/dvb/scan.cpp1
-rw-r--r--lib/dvb/sec.cpp23
-rw-r--r--lib/dvb/sec.h4
-rw-r--r--lib/gdi/epng.cpp5
-rw-r--r--lib/gdi/picload.cpp2
-rwxr-xr-xlib/python/Components/Harddisk.py110
-rwxr-xr-xlib/python/Components/NimManager.py13
-rw-r--r--lib/python/Components/ServiceList.py10
-rw-r--r--lib/python/Plugins/Extensions/DLNAServer/Makefile.am4
-rwxr-xr-xlib/python/Plugins/Extensions/DLNAServer/dlnaserverbin10848 -> 0 bytes
-rwxr-xr-xlib/python/Plugins/Extensions/Makefile.am2
-rw-r--r--lib/python/Plugins/Extensions/MiniTV/Makefile.am7
-rw-r--r--lib/python/Plugins/Extensions/MiniTV/__init__.py2
-rw-r--r--lib/python/Plugins/Extensions/MiniTV/meta/Makefile.am3
-rw-r--r--lib/python/Plugins/Extensions/MiniTV/meta/plugin_minitv.xml17
-rw-r--r--lib/python/Plugins/Extensions/MiniTV/plugin.py66
-rwxr-xr-xlib/python/Plugins/Plugin.py6
-rwxr-xr-xlib/python/Plugins/SystemPlugins/3GModemManager/3gcommandbin12032 -> 0 bytes
-rw-r--r--lib/python/Plugins/SystemPlugins/3GModemManager/Makefile.am6
-rw-r--r--lib/python/Plugins/SystemPlugins/Blindscan/plugin.py4
-rwxr-xr-xlib/python/Plugins/SystemPlugins/BoxModeConfig/Makefile.am7
-rwxr-xr-xlib/python/Plugins/SystemPlugins/BoxModeConfig/__init__.py0
-rwxr-xr-xlib/python/Plugins/SystemPlugins/BoxModeConfig/meta/Makefile.am3
-rwxr-xr-xlib/python/Plugins/SystemPlugins/BoxModeConfig/meta/plugin_boxmodeconfig.xml16
-rwxr-xr-xlib/python/Plugins/SystemPlugins/BoxModeConfig/plugin.py121
-rwxr-xr-xlib/python/Plugins/SystemPlugins/DeviceManager/plugin.py158
-rw-r--r--lib/python/Plugins/SystemPlugins/FastZapSupport/Makefile.am7
-rw-r--r--lib/python/Plugins/SystemPlugins/FastZapSupport/__init__.py2
-rw-r--r--lib/python/Plugins/SystemPlugins/FastZapSupport/meta/Makefile.am3
-rw-r--r--lib/python/Plugins/SystemPlugins/FastZapSupport/meta/plugin_fastzapsupport.xml16
-rw-r--r--lib/python/Plugins/SystemPlugins/FastZapSupport/plugin.py488
-rwxr-xr-xlib/python/Plugins/SystemPlugins/Makefile.am3
-rw-r--r--lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py23
-rw-r--r--lib/python/Screens/About.py36
-rwxr-xr-xlib/python/Screens/ChannelSelection.py3
-rwxr-xr-xlib/python/Screens/InfoBarGenerics.py3
-rw-r--r--lib/python/Screens/Satconfig.py83
-rw-r--r--lib/python/Screens/ServiceInfo.py6
-rw-r--r--lib/python/Screens/ServiceScan.py7
-rwxr-xr-xlib/python/enigma_python.i10
-rw-r--r--lib/service/listboxservice.cpp31
-rw-r--r--lib/service/listboxservice.h2
-rw-r--r--lib/service/servicedvbrecord.cpp2
-rwxr-xr-xlib/service/servicemp3.cpp647
-rw-r--r--lib/service/servicemp3.h18
59 files changed, 2785 insertions, 382 deletions
diff --git a/configure.ac b/configure.ac
index d4071bb..bf4ad08 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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")
-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")
@@ -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/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
@@ -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/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
diff --git a/data/startwizard.xml b/data/startwizard.xml
index c13a502..db04392 100755
--- a/data/startwizard.xml
+++ b/data/startwizard.xml
@@ -48,7 +48,8 @@ self.selectKey("RIGHT")
<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" />
@@ -61,7 +62,8 @@ self.selectKey("RIGHT")
<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" />
@@ -71,6 +73,90 @@ self.selectKey("LEFT")
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>
diff --git a/lib/base/eptrlist.h b/lib/base/eptrlist.h
index 0da46da..361323c 100644
--- a/lib/base/eptrlist.h
+++ b/lib/base/eptrlist.h
@@ -174,7 +174,7 @@ public:
{
// 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
- 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 );
}
};
diff --git a/lib/dvb/Makefile.am b/lib/dvb/Makefile.am
index 9b33755..b185237 100644
--- a/lib/dvb/Makefile.am
+++ b/lib/dvb/Makefile.am
@@ -30,7 +30,8 @@ libenigma_dvb_a_SOURCES = \
subtitle.cpp \
teletext.cpp \
tstools.cpp \
- volume.cpp
+ volume.cpp \
+ fbc.cpp
dvbincludedir = $(pkgincludedir)/lib/dvb
dvbinclude_HEADERS = \
@@ -61,4 +62,5 @@ dvbinclude_HEADERS = \
subtitle.h \
teletext.h \
tstools.h \
- volume.h
+ volume.h \
+ fbc.h
diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp
index 97cb99d..8a4a82d 100644
--- a/lib/dvb/decoder.cpp
+++ b/lib/dvb/decoder.cpp
@@ -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_H265_HEVC 7
#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 H265_HEVC:
+ streamtype = VIDEO_STREAMTYPE_H265_HEVC;
+ break;
}
eDebugNoNewLine("VIDEO_SET_STREAMTYPE %d - ", streamtype);
diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h
index ed8b6c7..f0f8b2f 100644
--- a/lib/dvb/decoder.h
+++ b/lib/dvb/decoder.h
@@ -49,7 +49,7 @@ private:
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
diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp
index 62b01d2..0a371f0 100755
--- a/lib/dvb/dvb.cpp
+++ b/lib/dvb/dvb.cpp
@@ -6,6 +6,8 @@
#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>
@@ -26,6 +28,14 @@ eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(f
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);
@@ -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;
- ePtr<eDVBRegisteredFrontend> best;
+// ePtr<eDVBRegisteredFrontend> best;
+ eDVBRegisteredFrontend *best = NULL;
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)
{
- 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;
@@ -439,15 +467,26 @@ RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, eP
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);
+ }
+
+ eDVBRegisteredFrontend *tmp = *i;
}
if (best)
{
+ if (fbcmng && best_fbc_fe)
+ {
+ fbcmng->addLink(best, best_fbc_fe, simulate);
+ }
+
fe = new eDVBAllocatedFrontend(best);
return 0;
}
@@ -667,12 +706,6 @@ RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
if (!simulate) \
eDebug(x); \
} while(0)
-// else \
-// { \
-// eDebugNoNewLine("SIMULATE:"); \
-// eDebug(x); \
-// } \
-
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;
+ int check_fbc_link = 0;
+ eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
+ {
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;
}
+ }
return bestval;
}
diff --git a/lib/dvb/dvb.h b/lib/dvb/dvb.h
index 10ad094..fa1e8a1 100644
--- a/lib/dvb/dvb.h
+++ b/lib/dvb/dvb.h
@@ -12,6 +12,7 @@
#include <lib/dvb/tstools.h>
#include <lib/dvb/esection.h>
#include <connection.h>
+#include <lib/dvb/fbc.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;
-
+
friend class eDVBChannel;
+ friend class eFBCTunerManager;
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
index 0000000..dc70c05
--- /dev/null
+++ b/lib/dvb/fbc.cpp
@@ -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
index 0000000..5f1afc1
--- /dev/null
+++ b/lib/dvb/fbc.h
@@ -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
diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp
index ae40483..1e7cb6b 100755
--- a/lib/dvb/frontend.cpp
+++ b/lib/dvb/frontend.cpp
@@ -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)
- ,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
@@ -525,6 +525,11 @@ eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate, eDVBFronten
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();
}
@@ -2961,7 +2966,6 @@ RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateCh
RESULT eDVBFrontend::setVoltage(int voltage)
{
-
#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 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_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") ||
@@ -3285,8 +3290,9 @@ bool eDVBFrontend::setSlotInfo(ePyObject obj)
/* 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",
- 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,
diff --git a/lib/dvb/frontend.h b/lib/dvb/frontend.h
index 11c5dfd..e6e3aea 100644
--- a/lib/dvb/frontend.h
+++ b/lib/dvb/frontend.h
@@ -73,6 +73,7 @@ private:
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;
@@ -146,6 +147,7 @@ public:
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);
@@ -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; }
+ bool is_FBCTuner() { return m_fbc; }
+ bool getEnabled() { return m_enabled; }
+ void setEnabled(bool enable) { m_enabled = enable; }
};
#endif // SWIG
diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp
index febfd78..6f0c9ee 100644
--- a/lib/dvb/pmt.cpp
+++ b/lib/dvb/pmt.cpp
@@ -268,7 +268,7 @@ void eDVBServicePMTHandler::AITready(int error)
std::string boundaryExtension = "";
int controlCode = (*i)->getApplicationControlCode();
- ApplicationIdentifier * applicationIdentifier = (*i)->getApplicationIdentifier();
+ const ApplicationIdentifier * applicationIdentifier = (*i)->getApplicationIdentifier();
profilecode = 0;
orgid = applicationIdentifier->getOrganisationId();
appid = applicationIdentifier->getApplicationId();
@@ -285,7 +285,7 @@ void eDVBServicePMTHandler::AITready(int error)
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)
{
@@ -353,7 +353,7 @@ void eDVBServicePMTHandler::AITready(int error)
}
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;
@@ -420,7 +420,7 @@ void eDVBServicePMTHandler::OCready(int error)
{
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 */
@@ -571,6 +571,13 @@ int eDVBServicePMTHandler::getProgramInfo(program &program)
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)
{
diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h
index 98ace2b..b15c95b 100644
--- a/lib/dvb/pmt.h
+++ b/lib/dvb/pmt.h
@@ -194,7 +194,7 @@ public:
{
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;
};
diff --git a/lib/dvb/scan.cpp b/lib/dvb/scan.cpp
index fb6f204..969ed9f 100644
--- a/lib/dvb/scan.cpp
+++ b/lib/dvb/scan.cpp
@@ -381,6 +381,7 @@ void eDVBScan::PMTready(int err)
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
diff --git a/lib/dvb/sec.cpp b/lib/dvb/sec.cpp
index 08976ef..d1567ba 100644
--- a/lib/dvb/sec.cpp
+++ b/lib/dvb/sec.cpp
@@ -49,11 +49,6 @@ eDVBSatelliteEquipmentControl::eDVBSatelliteEquipmentControl(eSmartPtrList<eDVBR
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)
{
@@ -279,11 +274,6 @@ bool need_turn_fast(int turn_speed)
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)
{
@@ -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);
+
+ 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)
@@ -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);
+
+ eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
+ if (p1->m_frontend->is_FBCTuner() && fbcmng)
+ {
+ fbcmng->updateFBCID(p1, p2);
+ }
}
p1=p2=NULL;
diff --git a/lib/dvb/sec.h b/lib/dvb/sec.h
index ca3e7f2..d176498 100644
--- a/lib/dvb/sec.h
+++ b/lib/dvb/sec.h
@@ -4,6 +4,8 @@
#include <lib/dvb/idvb.h>
#include <list>
+#include <lib/dvb/fbc.h>
+
#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; }
+
+ friend class eFBCTunerManager;
};
#endif
diff --git a/lib/gdi/epng.cpp b/lib/gdi/epng.cpp
index fd33298..e0da3eb 100644
--- a/lib/gdi/epng.cpp
+++ b/lib/gdi/epng.cpp
@@ -1,4 +1,5 @@
#define PNG_SKIP_SETJMP_CHECK
+#include <zlib.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;
}
- 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);
@@ -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);
- if (setjmp(png_ptr->jmpbuf))
+ if ( setjmp(png_jmpbuf(png_ptr)) )
{
eDebug("error :/");
png_destroy_write_struct(&png_ptr, &info_ptr);
diff --git a/lib/gdi/picload.cpp b/lib/gdi/picload.cpp
index 2afebd5..ab7a0b5 100644
--- a/lib/gdi/picload.cpp
+++ b/lib/gdi/picload.cpp
@@ -280,7 +280,7 @@ static unsigned char *png_load(const char *file, int *ox, int *oy, int *_bypp)
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);
diff --git a/lib/python/Components/Harddisk.py b/lib/python/Components/Harddisk.py
index ca4ef9e..1221f8f 100755
--- a/lib/python/Components/Harddisk.py
+++ b/lib/python/Components/Harddisk.py
@@ -29,6 +29,33 @@ def getProcMounts():
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
@@ -225,6 +252,7 @@ class Harddisk:
pass
res = system(cmd)
+ print "CMD : ", cmd
return (res >> 8)
def checkPartionPath(self, path):
@@ -235,6 +263,22 @@ class Harddisk:
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'
@@ -260,9 +304,15 @@ class Harddisk:
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)
+
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")
+ print "CMD : ", cmd
res = system(cmd)
return (res >> 8)
@@ -286,20 +337,33 @@ class Harddisk:
fstab.close()
res = -1
+ mount_point = None
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
- 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:
@@ -324,15 +388,17 @@ class Harddisk:
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)
- 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):
+ enableUdevEvent(False)
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")
- 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()
@@ -571,7 +641,7 @@ class HarddiskManager:
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
diff --git a/lib/python/Components/NimManager.py b/lib/python/Components/NimManager.py
index ce063b4..2a40aed 100755
--- a/lib/python/Components/NimManager.py
+++ b/lib/python/Components/NimManager.py
@@ -59,10 +59,10 @@ class SecConfigure:
sec.setLNBLOFL(9750000)
sec.setLNBLOFH(10600000)
sec.setLNBThreshold(11700000)
- sec.setLNBIncreasedVoltage(lnbParam.OFF)
+ sec.setLNBIncreasedVoltage(False)
sec.setRepeats(0)
sec.setFastDiSEqC(fastDiSEqC)
- sec.setSeqRepeat(0)
+ sec.setSeqRepeat(False)
sec.setCommandOrder(0)
#user values
@@ -369,9 +369,9 @@ class SecConfigure:
# pass # nyi in drivers
if currLnb.increased_voltage.value:
- sec.setLNBIncreasedVoltage(lnbParam.ON)
+ sec.setLNBIncreasedVoltage(True)
else:
- sec.setLNBIncreasedVoltage(lnbParam.OFF)
+ sec.setLNBIncreasedVoltage(False)
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
-def InitNimManager(nimmgr):
+def InitNimManager(nimmgr, update_slots = []):
hw = HardwareInfo()
addNimConfig = False
try:
@@ -1646,6 +1646,9 @@ def InitNimManager(nimmgr):
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")),
diff --git a/lib/python/Components/ServiceList.py b/lib/python/Components/ServiceList.py
index cd055a8..3930c07 100644
--- a/lib/python/Components/ServiceList.py
+++ b/lib/python/Components/ServiceList.py
@@ -113,6 +113,16 @@ class ServiceList(HTMLComponent, GUIComponent):
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()
diff --git a/lib/python/Plugins/Extensions/DLNAServer/Makefile.am b/lib/python/Plugins/Extensions/DLNAServer/Makefile.am
index 8d8805f..821fe1d 100644
--- a/lib/python/Plugins/Extensions/DLNAServer/Makefile.am
+++ b/lib/python/Plugins/Extensions/DLNAServer/Makefile.am
@@ -3,10 +3,6 @@ installdir = $(pkglibdir)/python/Plugins/Extensions/DLNAServer
SUBDIRS = meta
install_PYTHON = \
- dlnaserver \
__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
index 4fad9ab..0000000
--- a/lib/python/Plugins/Extensions/DLNAServer/dlnaserver
+++ /dev/null
Binary files differ
diff --git a/lib/python/Plugins/Extensions/Makefile.am b/lib/python/Plugins/Extensions/Makefile.am
index 9dd4299..d94b791 100755
--- a/lib/python/Plugins/Extensions/Makefile.am
+++ b/lib/python/Plugins/Extensions/Makefile.am
@@ -1,7 +1,7 @@
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
diff --git a/lib/python/Plugins/Extensions/MiniTV/Makefile.am b/lib/python/Plugins/Extensions/MiniTV/Makefile.am
new file mode 100644
index 0000000..98f2931
--- /dev/null
+++ b/lib/python/Plugins/Extensions/MiniTV/Makefile.am
@@ -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
index 0000000..139597f
--- /dev/null
+++ b/lib/python/Plugins/Extensions/MiniTV/__init__.py
@@ -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
index 0000000..2d31de6
--- /dev/null
+++ b/lib/python/Plugins/Extensions/MiniTV/meta/Makefile.am
@@ -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
index 0000000..d7dbe58
--- /dev/null
+++ b/lib/python/Plugins/Extensions/MiniTV/meta/plugin_minitv.xml
@@ -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
index 0000000..1bf8a4a
--- /dev/null
+++ b/lib/python/Plugins/Extensions/MiniTV/plugin.py
@@ -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
+
diff --git a/lib/python/Plugins/Plugin.py b/lib/python/Plugins/Plugin.py
index d87e6e9..2137d0e 100755
--- a/lib/python/Plugins/Plugin.py
+++ b/lib/python/Plugins/Plugin.py
@@ -60,6 +60,12 @@ class PluginDescriptor:
# 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
diff --git a/lib/python/Plugins/SystemPlugins/3GModemManager/3gcommand b/lib/python/Plugins/SystemPlugins/3GModemManager/3gcommand
deleted file mode 100755
index ae61799..0000000
--- a/lib/python/Plugins/SystemPlugins/3GModemManager/3gcommand
+++ /dev/null
Binary files differ
diff --git a/lib/python/Plugins/SystemPlugins/3GModemManager/Makefile.am b/lib/python/Plugins/SystemPlugins/3GModemManager/Makefile.am
index 962f84c..0ac90e0 100644
--- a/lib/python/Plugins/SystemPlugins/3GModemManager/Makefile.am
+++ b/lib/python/Plugins/SystemPlugins/3GModemManager/Makefile.am
@@ -5,9 +5,5 @@ SUBDIRS = meta script
install_PYTHON = \
__init__.py \
plugin.py \
- apnlist.xml \
- 3gcommand
-
-install-data-hook:
- @chmod +x $(DESTDIR)$(installdir)/3gcommand
+ apnlist.xml
diff --git a/lib/python/Plugins/SystemPlugins/Blindscan/plugin.py b/lib/python/Plugins/SystemPlugins/Blindscan/plugin.py
index 40a349e..82ce819 100644
--- a/lib/python/Plugins/SystemPlugins/Blindscan/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/Blindscan/plugin.py
@@ -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):
- 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
diff --git a/lib/python/Plugins/SystemPlugins/BoxModeConfig/Makefile.am b/lib/python/Plugins/SystemPlugins/BoxModeConfig/Makefile.am
new file mode 100755
index 0000000..a7c22ea
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/BoxModeConfig/Makefile.am
@@ -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
index 0000000..e69de29
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/BoxModeConfig/__init__.py
diff --git a/lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/Makefile.am b/lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/Makefile.am
new file mode 100755
index 0000000..8cd9a96
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/Makefile.am
@@ -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
index 0000000..67ce9d4
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/plugin_boxmodeconfig.xml
@@ -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
index 0000000..abda052
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/BoxModeConfig/plugin.py
@@ -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
diff --git a/lib/python/Plugins/SystemPlugins/DeviceManager/plugin.py b/lib/python/Plugins/SystemPlugins/DeviceManager/plugin.py
index 6d5860f..41c6905 100755
--- a/lib/python/Plugins/SystemPlugins/DeviceManager/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/DeviceManager/plugin.py
@@ -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.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
@@ -549,8 +549,10 @@ class DeviceInit(Screen):
self.maxPartNum = 4
self.inputbox_partitionSizeRemain = self.inputbox_partitionSizeTotal
self.unit = "MB"
+ self.onClose.append(enableUdevEvent)
def timerStart(self):
+ enableUdevEvent(False)
self.initStartTimer.start(100,True)
def confirmMessage(self):
@@ -680,62 +682,66 @@ class DeviceInit(Screen):
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 = ""
- 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:
- 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:
- 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":
- 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)
@@ -780,25 +786,25 @@ class DeviceInit(Screen):
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":
- cmd = "/sbin/mkfs.ext3 -F "
+ cmd = "mkfs.ext3 -F "
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:
- cmd = "/usr/sbin/mkfs.vfat -I -S4096 " + fulldevicename
+ cmd = "mkfs.vfat -I -S4096 " + fulldevicename
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"
@@ -990,8 +996,10 @@ class DeviceFormat(Screen):
self.setHotplugDisabled = False
self.umountTimer = eTimer()
self.umountTimer.callback.append(self.doUnmount)
+ self.onClose.append(enableUdevEvent)
def timerStart(self):
+ enableUdevEvent(False)
self.formatStartTimer.start(100,True)
def DeviceFormatStart(self):
@@ -1041,7 +1049,12 @@ class DeviceFormat(Screen):
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:
@@ -1060,7 +1073,16 @@ class DeviceFormat(Screen):
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:
@@ -1079,25 +1101,25 @@ class DeviceFormat(Screen):
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":
- cmd = "/sbin/mkfs.ext3 -F "
+ cmd = "mkfs.ext3 -F "
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:
- cmd = "/usr/sbin/mkfs.vfat -I -S4096 /dev/" + partition
+ cmd = "mkfs.vfat -I -S4096 /dev/" + partition
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)
@@ -1668,6 +1690,28 @@ class deviceManagerHotplug:
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):
diff --git a/lib/python/Plugins/SystemPlugins/FastZapSupport/Makefile.am b/lib/python/Plugins/SystemPlugins/FastZapSupport/Makefile.am
new file mode 100644
index 0000000..fd9599d
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/FastZapSupport/Makefile.am
@@ -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
index 0000000..139597f
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/FastZapSupport/__init__.py
@@ -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
index 0000000..78678fe
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/FastZapSupport/meta/Makefile.am
@@ -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
index 0000000..064496e
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/FastZapSupport/meta/plugin_fastzapsupport.xml
@@ -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
index 0000000..542531e
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/FastZapSupport/plugin.py
@@ -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
diff --git a/lib/python/Plugins/SystemPlugins/Makefile.am b/lib/python/Plugins/SystemPlugins/Makefile.am
index cf3498b..72a7d0a 100755
--- a/lib/python/Plugins/SystemPlugins/Makefile.am
+++ b/lib/python/Plugins/SystemPlugins/Makefile.am
@@ -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 \
- DeviceManager TransCodingSetup WOLSetup NetDrive AudioEffect AnimationSetup
+ DeviceManager TransCodingSetup WOLSetup NetDrive AudioEffect AnimationSetup FastZapSupport \
+ BoxModeConfig
install_PYTHON = \
__init__.py
diff --git a/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py b/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py
index 346c3b8..802c0b6 100644
--- a/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py
+++ b/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py
@@ -38,6 +38,11 @@ class VideoHardware:
"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"},
@@ -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"
@@ -74,7 +79,10 @@ class VideoHardware:
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):
@@ -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")
+ # 4K support 2160p
+ if self.isVumodel4K(hw_type):
+ self.modes["DVI"].insert(self.modes["DVI"].index("1080p")+1, "2160p")
portlist = [ ]
port_choices = self.getPortList()
diff --git a/lib/python/Screens/About.py b/lib/python/Screens/About.py
index a274010..328d98d 100644
--- a/lib/python/Screens/About.py
+++ b/lib/python/Screens/About.py
@@ -25,11 +25,37 @@ class About(Screen):
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()
diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py
index 6813381..fc176a7 100755
--- a/lib/python/Screens/ChannelSelection.py
+++ b/lib/python/Screens/ChannelSelection.py
@@ -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 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):
diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py
index 78d9984..c5f72e2 100755
--- a/lib/python/Screens/InfoBarGenerics.py
+++ b/lib/python/Screens/InfoBarGenerics.py
@@ -1322,6 +1322,9 @@ class InfoBarExtensions:
"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))
diff --git a/lib/python/Screens/Satconfig.py b/lib/python/Screens/Satconfig.py
index c5366f9..48b580c 100644
--- a/lib/python/Screens/Satconfig.py
+++ b/lib/python/Screens/Satconfig.py
@@ -15,6 +15,24 @@ from Screens.ServiceStopScreen import ServiceStopScreen
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
@@ -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")
+ if isFBCLink(self.nim):
+ choices = { "nothing": _("not configured"),
+ "advanced": _("advanced")}
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:
+ update_slots = [self.slotid]
from Components.NimManager import InitNimManager
- InitNimManager(nimmanager)
+ InitNimManager(nimmanager, update_slots)
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:
+ 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)
@@ -310,6 +336,10 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
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:
@@ -479,10 +509,22 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
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):
+ if isFBCLink(self.nim):
+ checkList = (self.advancedLof, self.advancedConnected)
+ curEntry = self["config"].getCurrent()
+ if curEntry in checkList:
+ return
+
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()
+
+ for p in plugins.getPlugins(PluginDescriptor.WHERE_SATCONFIGCHANGED):
+ p()
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()
-
+
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()
@@ -533,6 +579,23 @@ class NimSelection(Screen):
"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
@@ -540,8 +603,17 @@ class NimSelection(Screen):
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():
- 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
@@ -558,7 +630,7 @@ class NimSelection(Screen):
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":
@@ -592,6 +664,8 @@ class NimSelection(Screen):
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")
@@ -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)
+
diff --git a/lib/python/Screens/ServiceInfo.py b/lib/python/Screens/ServiceInfo.py
index bc0968e..da534ec 100644
--- a/lib/python/Screens/ServiceInfo.py
+++ b/lib/python/Screens/ServiceInfo.py
@@ -182,7 +182,7 @@ class ServiceInfo(Screen):
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),
@@ -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":
- 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),
@@ -203,7 +203,7 @@ class ServiceInfo(Screen):
(_("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),
diff --git a/lib/python/Screens/ServiceScan.py b/lib/python/Screens/ServiceScan.py
index 6be08d4..efa218b 100644
--- a/lib/python/Screens/ServiceScan.py
+++ b/lib/python/Screens/ServiceScan.py
@@ -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.PluginComponent import plugins
+from Plugins.Plugin import PluginDescriptor
class ServiceScanSummary(Screen):
skin = """
@@ -60,6 +62,11 @@ class ServiceScan(Screen):
})
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)
diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i
index 9891fb3..6a25592 100755
--- a/lib/python/enigma_python.i
+++ b/lib/python/enigma_python.i
@@ -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. */
diff --git a/lib/service/listboxservice.cpp b/lib/service/listboxservice.cpp
index cc8c32b..cd65f35 100644
--- a/lib/service/listboxservice.cpp
+++ b/lib/service/listboxservice.cpp
@@ -99,6 +99,37 @@ void eListboxServiceContent::getCurrent(eServiceReference &ref)
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);
diff --git a/lib/service/listboxservice.h b/lib/service/listboxservice.h
index 589afba..ab5bd20 100644
--- a/lib/service/listboxservice.h
+++ b/lib/service/listboxservice.h
@@ -19,6 +19,8 @@ public:
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();
diff --git a/lib/service/servicedvbrecord.cpp b/lib/service/servicedvbrecord.cpp
index 0287acf..dc1b22e 100644
--- a/lib/service/servicedvbrecord.cpp
+++ b/lib/service/servicedvbrecord.cpp
@@ -15,7 +15,7 @@
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);
diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp
index e79be09..8e8f190 100755
--- a/lib/service/servicemp3.cpp
+++ b/lib/service/servicemp3.cpp
@@ -19,8 +19,25 @@
#include <gst/pbutils/missing-plugins.h>
#include <sys/stat.h>
+#define GSTREAMER_SUBTITLE_SYNC_MODE_BUG
+
+#define SUBTITLE_DEBUG
+
#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()
@@ -223,15 +240,13 @@ int eServiceMP3::ac3_delay,
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_currentSubtitleStream = 0;
+ m_currentSubtitleStream = -1;
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;
@@ -239,8 +254,6 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
//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;
@@ -251,7 +264,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
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;
@@ -312,7 +325,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
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 )
{
@@ -334,38 +347,45 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
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");
- 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 )
{
- 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)
{
@@ -383,6 +403,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
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;
}
@@ -393,18 +414,28 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
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();
@@ -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());
- eDebug("eServiceMP3::stop service..");
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);
- return trickSeek(1/(float)ratio);
+ return trickSeek(1.0/(gdouble)ratio);
}
RESULT eServiceMP3::setFastForward(int ratio)
@@ -502,28 +532,6 @@ RESULT eServiceMP3::setFastForward(int 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()
{
@@ -540,6 +548,9 @@ RESULT eServiceMP3::unpause()
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;
@@ -562,12 +573,15 @@ RESULT eServiceMP3::getLength(pts_t &pts)
GstFormat fmt = GST_FORMAT_TIME;
gint64 len;
-
+#if GST_VERSION_MAJOR < 1
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. */
- pts = len / 11111;
+ pts = len / 11111LL;
return 0;
}
@@ -575,9 +589,15 @@ RESULT eServiceMP3::seekToImpl(pts_t to)
{
/* 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))
+#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;
@@ -591,14 +611,11 @@ RESULT eServiceMP3::seekTo(pts_t to)
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;
@@ -616,33 +633,50 @@ RESULT eServiceMP3::trickSeek(gdouble ratio)
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 |= GstSeekFlags (GST_SEEK_FLAG_SEGMENT);
-// flags |= GstSeekFlags (GST_SEEK_FLAG_SKIP);
+#endif
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_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;
}
@@ -653,13 +687,15 @@ RESULT eServiceMP3::seekRelative(int direction, pts_t to)
return -1;
pts_t ppos;
- getPlayPosition(ppos);
+
+ if (getPlayPosition(ppos) < 0 )
+ return -1;
+
ppos += to * direction;
if (ppos < 0)
ppos = 0;
- seekTo(ppos);
- return 0;
+ return seekTo(ppos);
}
RESULT eServiceMP3::getPlayPosition(pts_t &pts)
@@ -681,7 +717,11 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts)
}
else
{
+#if GST_VERSION_MAJOR < 1
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;
@@ -689,8 +729,8 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts)
}
/* 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;
}
@@ -877,12 +917,28 @@ std::string eServiceMP3::getInfoString(int w)
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_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;
@@ -1007,24 +1063,42 @@ PyObject *eServiceMP3::getInfoObject(int w)
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)
@@ -1065,16 +1139,23 @@ int eServiceMP3::getCurrentTrack()
RESULT eServiceMP3::selectTrack(unsigned int i)
{
+ bool validposition = false;
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) {
- /* flush */
- seekTo(ppos);
+ if (validposition)
+ {
+ /* flush */
+ seekTo(ppos);
+ }
}
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;
+#if GST_VERSION_MAJOR < 1
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 )
+ if ( caps && !gst_caps_is_empty(caps))
{
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;
- 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;
@@ -1180,10 +1264,18 @@ subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL)
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);
}
+#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)
{
@@ -1239,15 +1331,17 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
} break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
{
+#if GST_VERSION_MAJOR >= 1
+ GValue result = { 0, };
+#endif
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)
@@ -1262,11 +1356,27 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
}
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"));
+#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));
+#if GST_VERSION_MAJOR < 1
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);
@@ -1356,11 +1466,35 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
if ( gv_image )
{
GstBuffer *buf_image;
+#if GST_VERSION_MAJOR < 1
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 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);
@@ -1372,8 +1506,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
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);
@@ -1384,8 +1517,6 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
if ( n_video + n_audio <= 0 )
stop();
- active_idx = 0;
-
m_audioStreams.clear();
m_subtitleStreams.clear();
@@ -1393,9 +1524,14 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
{
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);
+#if GST_VERSION_MAJOR < 1
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);
@@ -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);
+#if GST_VERSION_MAJOR < 1
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);
@@ -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;
+ 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");
+#if GST_VERSION_MAJOR < 1
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);
@@ -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;
+#if GST_VERSION_MAJOR < 1
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;
@@ -1616,32 +1765,51 @@ audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure)
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");
-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)
@@ -1668,7 +1836,7 @@ void eServiceMP3::gstTextpadHasCAPS_synced(GstPad *pad)
// 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;
@@ -1677,20 +1845,22 @@ void eServiceMP3::gstTextpadHasCAPS_synced(GstPad *pad)
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");
+#if GST_VERSION_MAJOR < 1
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);
- 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);
@@ -1702,74 +1872,77 @@ void eServiceMP3::gstTextpadHasCAPS_synced(GstPad *pad)
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()
{
+ long next_timer = 0;
while ( !m_subtitle_pages.empty() )
{
- SubtitlePage &frontpage = m_subtitle_pages.front();
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;
@@ -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);
- m_subtitle_sync_timer->start(25, true);
+ next_timer = 25;
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;
- 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 )
{
+#ifdef SUBTITLE_DEBUG
eDebug("subtitle too late... drop");
+#endif
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 )
{
- 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();
@@ -1815,8 +2008,11 @@ void eServiceMP3::pushSubtitles()
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;
- eSingleLocker l(m_subs_to_pull_lock);
// 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)
{
- 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_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;
@@ -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);
+#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;
@@ -1878,9 +2083,15 @@ error_out:
RESULT eServiceMP3::disableSubtitles(eWidget *parent)
{
+ m_currentSubtitleStream = -1;
+ g_object_set (G_OBJECT (m_gst_playbin), "current-text", m_currentSubtitleStream, NULL);
eDebug("eServiceMP3::disableSubtitles");
+ m_subtitle_sync_timer->stop();
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;
}
diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h
index 41aec13..156400d 100644
--- a/lib/service/servicemp3.h
+++ b/lib/service/servicemp3.h
@@ -189,8 +189,6 @@ private:
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;
@@ -222,9 +220,15 @@ private:
{
d.pad=pad;
}
+ Message(int type, GstBuffer *buffer)
+ :type(type)
+ {
+ d.buffer=buffer;
+ }
int type;
union {
+ GstBuffer *buffer; // for msg type 2
GstPad *pad; // for msg type 3
} d;
};
@@ -232,12 +236,16 @@ private:
eFixedMessagePump<Message> m_pump;
audiotype_t gstCheckAudioPad(GstStructure* structure);
+#if GST_VERSION_MAJOR < 1
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);
- 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);
@@ -257,11 +265,9 @@ private:
int m_decoder_time_valid_state;
void pushSubtitles();
- void pullSubtitle();
+ void pullSubtitle(GstBuffer *buffer);
void sourceTimeout();
- int m_subs_to_pull;
sourceStream m_sourceinfo;
- eSingleLock m_subs_to_pull_lock;
gulong m_subs_to_pull_handler_id;
RESULT seekToImpl(pts_t to);