From afa141eedd597d0468d33b97a79f738a9ebfd11f Mon Sep 17 00:00:00 2001 From: hschang Date: Thu, 15 Oct 2015 16:56:10 +0900 Subject: [PATCH] update dvbapp. - support FBC Tuner. - Add MiniTV, BoxModeConfig, FastZapSupport. - Fix wrong nim config when multi tuner changed. - Update harddisk, devicemanager. - Support gstreamer 1.X. - Support HEVC. - Support 2160P. (videomode) --- configure.ac | 13 +- data/startwizard.xml | 90 ++- lib/base/eptrlist.h | 4 +- lib/dvb/Makefile.am | 6 +- lib/dvb/decoder.cpp | 4 + lib/dvb/decoder.h | 2 +- lib/dvb/dvb.cpp | 68 +- lib/dvb/dvb.h | 4 +- lib/dvb/fbc.cpp | 880 +++++++++++++++++++++ lib/dvb/fbc.h | 80 ++ lib/dvb/frontend.cpp | 14 +- lib/dvb/frontend.h | 5 + lib/dvb/pmt.cpp | 15 +- lib/dvb/pmt.h | 2 +- lib/dvb/scan.cpp | 1 + lib/dvb/sec.cpp | 23 +- lib/dvb/sec.h | 4 + lib/gdi/epng.cpp | 5 +- lib/gdi/picload.cpp | 2 +- lib/python/Components/Harddisk.py | 110 ++- lib/python/Components/NimManager.py | 13 +- lib/python/Components/ServiceList.py | 10 + .../Plugins/Extensions/DLNAServer/Makefile.am | 4 - .../Plugins/Extensions/DLNAServer/dlnaserver | Bin 10848 -> 0 bytes lib/python/Plugins/Extensions/Makefile.am | 2 +- lib/python/Plugins/Extensions/MiniTV/Makefile.am | 7 + lib/python/Plugins/Extensions/MiniTV/__init__.py | 2 + .../Plugins/Extensions/MiniTV/meta/Makefile.am | 3 + .../Extensions/MiniTV/meta/plugin_minitv.xml | 17 + lib/python/Plugins/Extensions/MiniTV/plugin.py | 66 ++ lib/python/Plugins/Plugin.py | 6 + .../Plugins/SystemPlugins/3GModemManager/3gcommand | Bin 12032 -> 0 bytes .../SystemPlugins/3GModemManager/Makefile.am | 6 +- .../Plugins/SystemPlugins/Blindscan/plugin.py | 4 +- .../SystemPlugins/BoxModeConfig/Makefile.am | 7 + .../SystemPlugins/BoxModeConfig/__init__.py | 0 .../SystemPlugins/BoxModeConfig/meta/Makefile.am | 3 + .../BoxModeConfig/meta/plugin_boxmodeconfig.xml | 16 + .../Plugins/SystemPlugins/BoxModeConfig/plugin.py | 121 +++ .../Plugins/SystemPlugins/DeviceManager/plugin.py | 158 ++-- .../SystemPlugins/FastZapSupport/Makefile.am | 7 + .../SystemPlugins/FastZapSupport/__init__.py | 2 + .../SystemPlugins/FastZapSupport/meta/Makefile.am | 3 + .../FastZapSupport/meta/plugin_fastzapsupport.xml | 16 + .../Plugins/SystemPlugins/FastZapSupport/plugin.py | 488 ++++++++++++ lib/python/Plugins/SystemPlugins/Makefile.am | 3 +- .../SystemPlugins/Videomode/VideoHardware.py | 23 +- lib/python/Screens/About.py | 36 +- lib/python/Screens/ChannelSelection.py | 3 +- lib/python/Screens/InfoBarGenerics.py | 3 + lib/python/Screens/Satconfig.py | 83 +- lib/python/Screens/ServiceInfo.py | 6 +- lib/python/Screens/ServiceScan.py | 7 + lib/python/enigma_python.i | 10 + lib/service/listboxservice.cpp | 31 + lib/service/listboxservice.h | 2 + lib/service/servicedvbrecord.cpp | 2 +- lib/service/servicemp3.cpp | 647 ++++++++++----- lib/service/servicemp3.h | 18 +- 59 files changed, 2785 insertions(+), 382 deletions(-) create mode 100644 lib/dvb/fbc.cpp create mode 100644 lib/dvb/fbc.h delete mode 100755 lib/python/Plugins/Extensions/DLNAServer/dlnaserver create mode 100644 lib/python/Plugins/Extensions/MiniTV/Makefile.am create mode 100644 lib/python/Plugins/Extensions/MiniTV/__init__.py create mode 100644 lib/python/Plugins/Extensions/MiniTV/meta/Makefile.am create mode 100644 lib/python/Plugins/Extensions/MiniTV/meta/plugin_minitv.xml create mode 100644 lib/python/Plugins/Extensions/MiniTV/plugin.py delete mode 100755 lib/python/Plugins/SystemPlugins/3GModemManager/3gcommand create mode 100755 lib/python/Plugins/SystemPlugins/BoxModeConfig/Makefile.am create mode 100755 lib/python/Plugins/SystemPlugins/BoxModeConfig/__init__.py create mode 100755 lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/Makefile.am create mode 100755 lib/python/Plugins/SystemPlugins/BoxModeConfig/meta/plugin_boxmodeconfig.xml create mode 100755 lib/python/Plugins/SystemPlugins/BoxModeConfig/plugin.py create mode 100644 lib/python/Plugins/SystemPlugins/FastZapSupport/Makefile.am create mode 100644 lib/python/Plugins/SystemPlugins/FastZapSupport/__init__.py create mode 100644 lib/python/Plugins/SystemPlugins/FastZapSupport/meta/Makefile.am create mode 100644 lib/python/Plugins/SystemPlugins/FastZapSupport/meta/plugin_fastzapsupport.xml create mode 100644 lib/python/Plugins/SystemPlugins/FastZapSupport/plugin.py 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") 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]) @@ -61,7 +62,8 @@ self.selectKey("RIGHT") 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]) @@ -71,6 +73,90 @@ self.selectKey("LEFT") self.selectKey("RIGHT") + + +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]) + + + + +self.clearSelectedKeys() +self.selectKey("LEFT") +self.selectKey("RIGHT") + + + + +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]) + + + + +self.clearSelectedKeys() +self.selectKey("LEFT") +self.selectKey("RIGHT") + + + + +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]) + + + + +self.clearSelectedKeys() +self.selectKey("LEFT") +self.selectKey("RIGHT") + + + + +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]) + + + + +self.clearSelectedKeys() +self.selectKey("LEFT") +self.selectKey("RIGHT") + + + + +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]) + + + + +self.clearSelectedKeys() +self.selectKey("LEFT") +self.selectKey("RIGHT") + + + + +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]) + + + + +self.clearSelectedKeys() +self.selectKey("LEFT") +self.selectKey("RIGHT") + + 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::begin(), std::list::end(), e, less()), e ); + return this->insert( std::lower_bound( std::list::begin(), std::list::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 >::begin(), e, std::list >::end()), e ); + return this->insert( std::lower_bound( std::list >::begin(), e, std::list >::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 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 #include +#include + #include #include #include @@ -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 &fe, ePtr &feparm, bool simulate) { eSmartPtrList &frontends = simulate ? m_simulate_frontend : m_frontend; - ePtr best; +// ePtr 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::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 &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 &list) if (!simulate) \ eDebug(x); \ } while(0) -// else \ -// { \ -// eDebugNoNewLine("SIMULATE:"); \ -// eDebug(x); \ -// } \ - RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr &channel, bool simulate) { @@ -877,14 +910,27 @@ int eDVBResourceManager::canAllocateFrontend(ePtr &fepar eSmartPtrList &frontends = simulate ? m_simulate_frontend : m_frontend; ePtr best; int bestval = 0; + int check_fbc_link = 0; + eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance(); for (eSmartPtrList::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 #include #include +#include #include @@ -158,8 +159,9 @@ class eDVBResourceManager: public iObject, public Object ePtr m_list; ePtr 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 +#include +#include +#include + +#include +#include + +#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 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 &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::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 &frontends = m_res_mgr->m_frontend; + + for (eSmartPtrList::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 &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::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 &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::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 &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::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 &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::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 &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend; + for (eSmartPtrList::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 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 &feparm, eDVBRegisteredFrontend *link_fe, bool simulate) +{ + eDVBRegisteredFrontend *best_fbc_fe; + return isCompatibleWith(feparm, link_fe, best_fbc_fe, simulate); +} + +int eFBCTunerManager::isCompatibleWith(ePtr &feparm, eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *&fbc_fe, bool simulate) +{ + int best_score = 0; + + eSmartPtrList &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend; + for (eSmartPtrList::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 &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend; + for (eSmartPtrList::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 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 &frontends = m_res_mgr->m_frontend; + for (eSmartPtrList::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 &frontends = m_res_mgr->m_frontend; + for (eSmartPtrList::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 &simulate_frontends = m_res_mgr->m_simulate_frontend; + for (eSmartPtrList::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 +#include +#include +#include + +class eDVBResourceManager; +class eDVBRegisteredFrontend; + +class eFBCTunerManager: public iObject, public Object +{ +private: + DECLARE_REF(eFBCTunerManager); + ePtr 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 &feparm, eDVBRegisteredFrontend *link_fe, bool simulate); + int isCompatibleWith(ePtr &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 &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 &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::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(eSmartPtrListm_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::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 #include +#include + #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 #include #include #include @@ -52,7 +53,7 @@ int loadPNG(ePtr &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 4fad9abd9dd4110e1e13f8859308531ef751f7bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10848 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 wYPueIj2-y<^M4`_94~QQcaR2}S 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 @@ + + + + + + + hschang + MiniTV + enigma2-plugin-extensions-minitv + Support MiniTV of your VU+ + Support MiniTV of your VU+ + + + + + + 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 ae61799ed944ec7414572b9c407a7e87cb590e50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12032 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 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 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 @@ + + + + + + hschang + BoxModeConfig + enigma2-plugin-systemplugins-boxmodeconfig + configuration boxmode. + configuration boxmode. + + + + + + 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 = """ + + + + + + + + + + + """ + + 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 @@ + + + + + + hschang + FastZapSupport + enigma2-plugin-systemplugins-fastzapsupport + Support FastZapping of your VU+ + Support FastZapping of your VU+ + + + + + + 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") 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 #include +#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 &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 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 m_subtitleStreams; eSubtitleWidget *m_subtitle_widget; int m_currentTrickRatio; - ePtr 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 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); -- 2.7.4