diff options
45 files changed, 1175 insertions, 706 deletions
diff --git a/Navigation.py b/Navigation.py index 2ca87f6f..2437bbf5 100644 --- a/Navigation.py +++ b/Navigation.py @@ -50,9 +50,9 @@ class Navigation: for x in self.record_event: x(rec_service, event) - def playService(self, ref, checkParentalControl = True): + def playService(self, ref, checkParentalControl = True, forceRestart = False): oldref = self.currentlyPlayingServiceReference - if ref and oldref and ref == oldref: + if ref and oldref and ref == oldref and not forceRestart: print "ignore request to play already running service" return 0 print "playing", ref and ref.toString() diff --git a/data/defaults/Dream/userbouquet.favourites.tv b/data/defaults/Dream/userbouquet.favourites.tv index f1adaf9e..cc5e9fe9 100644 --- a/data/defaults/Dream/userbouquet.favourites.tv +++ b/data/defaults/Dream/userbouquet.favourites.tv @@ -10,7 +10,7 @@ #SERVICE 1:0:1:33:21:85:C00000:0:0:0:
#SERVICE 1:0:1:701:5:85:C00000:0:0:0:
#SERVICE 1:0:1:2F1C:441:1:C00000:0:0:0:
-#SERVICE 1:0:1:7005:436:1:C00000:0:0:0:
+#SERVICE 1:0:1:6D6E:437:1:C00000:0:0:0:
#SERVICE 1:0:1:2FC:5:85:C00000:0:0:0:
#SERVICE 1:0:1:F98:454:1:C00000:0:0:0:
#SERVICE 1:0:1:7034:41B:1:C00000:0:0:0:
@@ -26,7 +26,6 @@ #SERVICE 1:64:B:0:0:0:0:0:0:0::Doku/Wissen/Themen
#DESCRIPTION Doku/Wissen/Themen
#SERVICE 1:0:1:6DD0:44D:1:C00000:0:0:0:
-#SERVICE 1:0:1:6D6E:437:1:C00000:0:0:0:
#SERVICE 1:0:1:6D6B:437:1:C00000:0:0:0:
#SERVICE 1:0:1:2775:444:1:C00000:0:0:0:
#SERVICE 1:0:1:293:5:85:C00000:0:0:0:
@@ -77,8 +76,6 @@ #SERVICE 1:64:5:0:0:0:0:0:0:0::Reisen
#DESCRIPTION Reisen
#SERVICE 1:0:1:20:21:85:C00000:0:0:0:
-#SERVICE 1:0:1:3339:45B:1:C00000:0:0:0:
-#SERVICE 1:0:1:27B9:444:1:C00000:0:0:0:
#SERVICE 1:64:9:0:0:0:0:0:0:0::Beratung
#DESCRIPTION Beratung
#SERVICE 1:0:1:295:21:85:C00000:0:0:0:
@@ -92,7 +89,6 @@ #SERVICE 1:0:1:36:7:85:C00000:0:0:0:
#SERVICE 1:0:1:307:7:85:C00000:0:0:0:
#SERVICE 1:0:1:296:5:85:C00000:0:0:0:
-#SERVICE 1:0:1:2791:444:1:C00000:0:0:0:
#SERVICE 1:0:1:383:21:85:C00000:0:0:0:
#SERVICE 1:0:1:313C:459:1:C00000:0:0:0:
#SERVICE 1:0:1:3159:459:1:C00000:0:0:0:
@@ -104,9 +100,9 @@ #SERVICE 1:0:19:2B66:3F3:1:C00000:0:0:0:
#SERVICE 1:0:19:2B70:3F3:1:C00000:0:0:0:
#SERVICE 1:0:19:6EEC:4B1:1:C00000:0:0:0:
-#SERVICE 1:0:19:1324:3EF:1:C00000:0:0:0:
-#SERVICE 1:0:19:1325:3EF:1:C00000:0:0:0:
+#SERVICE 1:0:19:EF12:421:1:C00000:0:0:0:
#SERVICE 1:0:19:2B84:3F3:1:C00000:0:0:0:
+#SERVICE 1:0:19:EF13:421:1:C00000:0:0:0:
#SERVICE 1:64:0:0:0:0:0:0:0:0::Alternativen
#DESCRIPTION Alternativen
#SERVICE 1:0:1:6DCB:44D:1:C00000:0:0:0:
diff --git a/data/keymap.xml b/data/keymap.xml index 25538f87..9461d509 100755 --- a/data/keymap.xml +++ b/data/keymap.xml @@ -98,6 +98,10 @@ <key id="KEY_BLUE" mapto="extensions" flags="b" /> </map> + <map context="SatlistShortcutAction"> + <key id="KEY_BLUE" mapto="nothingconnected" flags="b" /> + </map> + <map context="InfobarChannelSelection"> <key id="KEY_LEFT" mapto="zapUp" flags="mr" /> <key id="KEY_RIGHT" mapto="zapDown" flags="mr" /> diff --git a/data/skin_default.xml b/data/skin_default.xml index 71f579cb..85c4016a 100755 --- a/data/skin_default.xml +++ b/data/skin_default.xml @@ -70,8 +70,8 @@ <widget name="menu" position="10,10" size="290,225" scrollbarMode="showOnDemand" /> </screen> <!-- Channel context menu --> - <screen name="ChannelContextMenu" position="center,center" size="300,255" title="Channellist menu"> - <widget name="menu" position="10,10" size="290,230" scrollbarMode="showOnDemand" /> + <screen name="ChannelContextMenu" position="center,center" size="350,255" title="Channellist menu"> + <widget name="menu" position="10,10" size="340,230" scrollbarMode="showOnDemand" /> </screen> <!-- Channel selection - TV --> <screen name="ChannelSelection" position="center,center" size="560,430" title="Channel Selection"> @@ -253,6 +253,10 @@ self.instance.move(ePoint((720-wsizex)/2, (576-wsizey)/(count > 7 and 2 or 3) <screen name="Dish" flags="wfNoBorder" position="300,100" size="130,160" title="Dish" zPosition="100" backgroundColor="transparent"> <widget name="Dishpixmap" pixmap="skin_default/icons/dish.png" position="0,0" size="130,160" alphatest="off" /> </screen> + <!-- unhandled key pressed --> + <screen name="UnhandledKey" flags="wfNoBorder" position="620,50" size="34,45" title="UnhandledKey" zPosition="100" backgroundColor="transparent"> + <widget name="UnhandledKeyPixmap" pixmap="skin_default/unhandled-key.png" position="0,0" size="34,45" alphatest="off" /> + </screen> <!-- EPG Selection - Single --> <screen name="EPGSelection" position="center,center" size="560,430" title="EPG Selection"> <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> diff --git a/data/skin_default/Makefile.am b/data/skin_default/Makefile.am index e2d2abcc..9e9b7cd4 100644..100755 --- a/data/skin_default/Makefile.am +++ b/data/skin_default/Makefile.am @@ -15,6 +15,7 @@ dist_install_DATA = \ border_eventinfo.png \ border_info.png \ border_menu_300.png \ + border_menu_350.png \ border_menu.png \ border_multiepg.png \ bottombar.png \ @@ -50,6 +51,7 @@ dist_install_DATA = \ sleeptimer.png \ timeline-now.png \ timeline.png \ + unhandled-key.png \ verticalline-plugins.png \ vkey_backspace.png \ vkey_bg.png \ diff --git a/data/skin_default/border_menu_350.png b/data/skin_default/border_menu_350.png Binary files differnew file mode 100755 index 00000000..4f6f49c2 --- /dev/null +++ b/data/skin_default/border_menu_350.png diff --git a/data/skin_default/div-h.png b/data/skin_default/div-h.png Binary files differindex d6fcc7fb..9ab4ff45 100644..100755 --- a/data/skin_default/div-h.png +++ b/data/skin_default/div-h.png diff --git a/data/skin_default/unhandled-key.png b/data/skin_default/unhandled-key.png Binary files differnew file mode 100644 index 00000000..8e543498 --- /dev/null +++ b/data/skin_default/unhandled-key.png diff --git a/lib/actions/action.cpp b/lib/actions/action.cpp index 0eb4cdb1..a2d85ffd 100644 --- a/lib/actions/action.cpp +++ b/lib/actions/action.cpp @@ -208,7 +208,7 @@ void eActionMap::keyPressed(const std::string &device, int key, int flags) } } else { - eDebug("wildcard."); +// eDebug("wildcard."); ePyObject pArgs = PyTuple_New(2); PyTuple_SET_ITEM(pArgs, 0, PyInt_FromLong(key)); PyTuple_SET_ITEM(pArgs, 1, PyInt_FromLong(flags)); diff --git a/lib/base/elock.h b/lib/base/elock.h index 51582e67..01757182 100644 --- a/lib/base/elock.h +++ b/lib/base/elock.h @@ -83,9 +83,18 @@ class eSingleLock pthread_mutex_t m_lock; eSingleLock(eSingleLock &); public: - eSingleLock() + eSingleLock(bool recursive=false) { - pthread_mutex_init(&m_lock, 0); + if (recursive) + { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_lock, &attr); + pthread_mutexattr_destroy(&attr); + } + else + pthread_mutex_init(&m_lock, 0); } ~eSingleLock() { diff --git a/lib/driver/rc.cpp b/lib/driver/rc.cpp index c7acd113..c56fde44 100644 --- a/lib/driver/rc.cpp +++ b/lib/driver/rc.cpp @@ -81,7 +81,6 @@ eRCShortDriver::eRCShortDriver(const char *filename): eRCDriver(eRCInput::getIns { sn=eSocketNotifier::create(eApp, handle, eSocketNotifier::Read); CONNECT(sn->activated, eRCShortDriver::keyPressed); - eRCInput::getInstance()->setFile(handle); } } @@ -115,7 +114,6 @@ eRCInputEventDriver::eRCInputEventDriver(const char *filename): eRCDriver(eRCInp { sn=eSocketNotifier::create(eApp, handle, eSocketNotifier::Read); CONNECT(sn->activated, eRCInputEventDriver::keyPressed); - eRCInput::getInstance()->setFile(handle); } } @@ -127,6 +125,16 @@ std::string eRCInputEventDriver::getDeviceName() return name; } +void eRCInputEventDriver::setExclusive(bool b) +{ + if (handle >= 0) + { + int grab = b; + if (::ioctl(handle, EVIOCGRAB, grab) < 0) + perror("EVIOCGRAB"); + } +} + eRCInputEventDriver::~eRCInputEventDriver() { if (handle>=0) @@ -165,7 +173,6 @@ eRCInput::eRCInput() { ASSERT( !instance); instance=this; - handle = -1; locked = 0; keyboardMode = kmNone; } @@ -183,21 +190,18 @@ bool eRCInput::open() return false; } -int eRCInput::lock() +void eRCInput::lock() { locked=1; - return handle; + for (std::map<std::string,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i) + i->second->setExclusive(false); } void eRCInput::unlock() { - if (locked) - locked=0; -} - -void eRCInput::setFile(int newh) -{ - handle=newh; + locked=0; + for (std::map<std::string,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i) + i->second->setExclusive(true); } void eRCInput::addDevice(const std::string &id, eRCDevice *dev) @@ -216,7 +220,7 @@ eRCDevice *eRCInput::getDevice(const std::string &id) if (i == devices.end()) { eDebug("failed, possible choices are:"); - for (std::map<std::string,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i) + for (std::map<std::string,eRCDevice*>::iterator i=devices.begin(); i != devices.end(); ++i) eDebug("%s", i->first.c_str()); return 0; } diff --git a/lib/driver/rc.h b/lib/driver/rc.h index 9708ea7b..52909468 100644 --- a/lib/driver/rc.h +++ b/lib/driver/rc.h @@ -53,6 +53,7 @@ public: * \param key The key to get the description for. * \result User readable description of given key. */ + virtual void setExclusive(bool b) { }; }; /** @@ -89,6 +90,7 @@ public: ~eRCDriver(); void enable(int en) { enabled=en; } + virtual void setExclusive(bool) { } }; class eRCShortDriver: public eRCDriver @@ -112,6 +114,7 @@ public: std::string getDeviceName(); eRCInputEventDriver(const char *filename); ~eRCInputEventDriver(); + void setExclusive(bool b); // in exclusive mode data is not carried to console device }; class eRCKey @@ -173,7 +176,6 @@ public: class eRCInput: public Object { int locked; - int handle; static eRCInput *instance; int keyboardMode; #ifdef SWIG @@ -199,8 +201,6 @@ public: void close(); bool open(); - void setFile(int handle); - /* This is only relevant for "keyboard"-styled input devices, i.e. not plain remote controls. It's up to the input device driver to decide wheter an input device is a keyboard or @@ -237,7 +237,7 @@ public: void setKeyboardMode(int mode) { keyboardMode = mode; } int getKeyboardMode() { return keyboardMode; } static eRCInput *getInstance() { return instance; } - int lock(); + void lock(); void unlock(); int islocked() { return locked; } }; diff --git a/lib/driver/rcconsole.cpp b/lib/driver/rcconsole.cpp index bcce5601..eb5aee3d 100644 --- a/lib/driver/rcconsole.cpp +++ b/lib/driver/rcconsole.cpp @@ -16,7 +16,6 @@ eRCConsoleDriver::eRCConsoleDriver(const char *filename): eRCDriver(eRCInput::ge { sn=eSocketNotifier::create(eApp, handle, eSocketNotifier::Read); CONNECT(sn->activated, eRCConsoleDriver::keyPressed); - eRCInput::getInstance()->setFile(handle); } /* set console mode */ diff --git a/lib/driver/rcinput.cpp b/lib/driver/rcinput.cpp index d10d94f3..e593087d 100644 --- a/lib/driver/rcinput.cpp +++ b/lib/driver/rcinput.cpp @@ -83,8 +83,13 @@ eRCDeviceInputDev::eRCDeviceInputDev(eRCInputEventDriver *driver) break; } } + setExclusive(true); eDebug("Input device \"%s\" is %sa keyboard.", id.c_str(), iskeyboard ? "" : "not "); +} +void eRCDeviceInputDev::setExclusive(bool b) +{ + driver->setExclusive(!iskeyboard && b); } const char *eRCDeviceInputDev::getDescription() const diff --git a/lib/driver/rcinput.h b/lib/driver/rcinput.h index c7f56975..3b4579c5 100644 --- a/lib/driver/rcinput.h +++ b/lib/driver/rcinput.h @@ -10,6 +10,7 @@ public: void handleCode(long code); eRCDeviceInputDev(eRCInputEventDriver *driver); const char *getDescription() const; + void setExclusive(bool); }; #endif diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index a8dfb193..6eaadb04 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -1766,6 +1766,8 @@ RESULT eDVBChannel::playFile(const char *file) m_pvr_thread->setStreamMode(1); m_pvr_thread->setScatterGather(this); + m_event(this, evtPreStart); + if (m_pvr_thread->start(file, m_pvr_fd_dst)) { delete m_pvr_thread; diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index cff4dbb9..4ef7efad 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -522,7 +522,7 @@ public: virtual RESULT getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> &)=0; enum { - evtEOF, evtSOF, evtFailed + evtPreStart, evtEOF, evtSOF, evtFailed }; virtual RESULT connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)=0; virtual RESULT connectEvent(const Slot2<void,iDVBChannel*,int> &eventChange, ePtr<eConnection> &connection)=0; diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 9bd065b3..ee89a3a4 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -75,6 +75,9 @@ void eDVBServicePMTHandler::channelEvent(iDVBChannel *channel, int event) { switch (event) { + case iDVBChannel::evtPreStart: + serviceEvent(eventPreStart); + break; case iDVBChannel::evtEOF: serviceEvent(eventEOF); break; diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h index a9ca23f2..483c06b1 100644 --- a/lib/dvb/pmt.h +++ b/lib/dvb/pmt.h @@ -123,6 +123,7 @@ public: eventNewProgramInfo, // we just received a PMT eventTuned, // a channel was sucessfully (re-)tuned in, you may start additional filters now + eventPreStart, // before start filepush thread eventSOF, // seek pre start eventEOF, // a file playback did end diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index b7ea945f..d5ad2494 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -7,6 +7,7 @@ #include <stdio.h> eDVBTSTools::eDVBTSTools() + :m_file_lock(true) { m_pid = -1; m_maxrange = 256*1024; @@ -47,6 +48,7 @@ int eDVBTSTools::openFile(const char *filename, int nostreaminfo) m_samples_taken = 0; + eSingleLocker l(m_file_lock); if (m_file.open(filename, 1) < 0) return -1; return 0; @@ -54,6 +56,7 @@ int eDVBTSTools::openFile(const char *filename, int nostreaminfo) void eDVBTSTools::closeFile() { + eSingleLocker l(m_file_lock); m_file.close(); } @@ -78,7 +81,8 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) return -1; offset -= offset % 188; - + + eSingleLocker l(m_file_lock); if (m_file.lseek(offset, SEEK_SET) < 0) { eDebug("lseek failed"); @@ -144,24 +148,83 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) } else payload = packet + 4; - /* if (m_pid >= 0) if (pid != m_pid) continue; */ if (!pusi) continue; - - + /* somehow not a startcode. (this is invalid, since pusi was set.) ignore it. */ if (payload[0] || payload[1] || (payload[2] != 1)) continue; - + + if (payload[3] == 0xFD) + { // stream use extension mechanism defined in ISO 13818-1 Amendment 2 + if (payload[7] & 1) // PES extension flag + { + int offs = 0; + if (payload[7] & 0x80) // pts avail + offs += 5; + if (payload[7] & 0x40) // dts avail + offs += 5; + if (payload[7] & 0x20) // escr avail + offs += 6; + if (payload[7] & 0x10) // es rate + offs += 3; + if (payload[7] & 0x8) // dsm trickmode + offs += 1; + if (payload[7] & 0x4) // additional copy info + offs += 1; + if (payload[7] & 0x2) // crc + offs += 2; + if (payload[8] < offs) + continue; + uint8_t pef = payload[9+offs++]; // pes extension field + if (pef & 1) // pes extension flag 2 + { + if (pef & 0x80) // private data flag + offs += 16; + if (pef & 0x40) // pack header field flag + offs += 1; + if (pef & 0x20) // program packet sequence counter flag + offs += 2; + if (pef & 0x10) // P-STD buffer flag + offs += 2; + if (payload[8] < offs) + continue; + uint8_t stream_id_extension_len = payload[9+offs++] & 0x7F; + if (stream_id_extension_len >= 1) + { + if (payload[8] < (offs + stream_id_extension_len) ) + continue; + if (payload[9+offs] & 0x80) // stream_id_extension_bit (should not set) + continue; + switch (payload[9+offs]) + { + case 0x55 ... 0x5f: // VC-1 + break; + case 0x71: // AC3 / DTS + break; + default: + eDebug("skip unknwn stream_id_extension %02x\n", payload[9+offs]); + continue; + } + } + else + continue; + } + else + continue; + } + else + continue; + } /* drop non-audio, non-video packets because other streams can be non-compliant.*/ - if (((payload[3] & 0xE0) != 0xC0) && // audio - ((payload[3] & 0xF0) != 0xE0)) // video + else if (((payload[3] & 0xE0) != 0xC0) && // audio + ((payload[3] & 0xF0) != 0xE0)) // video continue; - + if (payload[7] & 0x80) /* PTS */ { pts = ((unsigned long long)(payload[ 9]&0xE)) << 29; @@ -358,7 +421,8 @@ void eDVBTSTools::calcEnd() { if (!m_file.valid()) return; - + + eSingleLocker l(m_file_lock); off_t end = m_file.lseek(0, SEEK_END); if (llabs(end - m_last_filelength) > 1*1024*1024) @@ -515,6 +579,7 @@ int eDVBTSTools::findPMT(int &pmt_pid, int &service_id) return -1; } + eSingleLocker l(m_file_lock); if (m_file.lseek(0, SEEK_SET) < 0) { eDebug("seek failed"); diff --git a/lib/dvb/tstools.h b/lib/dvb/tstools.h index c230a341..ed8b9241 100644 --- a/lib/dvb/tstools.h +++ b/lib/dvb/tstools.h @@ -4,6 +4,7 @@ #include <sys/types.h> #include <lib/dvb/pvrparse.h> #include <lib/base/rawfile.h> +#include <lib/base/elock.h> /* * Note: we're interested in PTS values, not STC values. @@ -75,9 +76,10 @@ public: private: int m_pid; int m_maxrange; - + + eSingleLock m_file_lock; eRawFile m_file; - + int m_begin_valid, m_end_valid; pts_t m_pts_begin, m_pts_end; off_t m_offset_begin, m_offset_end; diff --git a/lib/python/Components/ChoiceList.py b/lib/python/Components/ChoiceList.py index 4700e9e6..33868d61 100755 --- a/lib/python/Components/ChoiceList.py +++ b/lib/python/Components/ChoiceList.py @@ -3,7 +3,7 @@ from Tools.Directories import SCOPE_CURRENT_SKIN, resolveFilename from enigma import RT_HALIGN_LEFT, eListboxPythonMultiContent, gFont from Tools.LoadPixmap import LoadPixmap -def ChoiceEntryComponent(key, text): +def ChoiceEntryComponent(key = "", text = ["--"]): res = [ text ] if text[0] == "--": res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 00, 800, 25, 0, RT_HALIGN_LEFT, "-"*200)) diff --git a/lib/python/Components/NimManager.py b/lib/python/Components/NimManager.py index 7d148f3c..00d06095 100644 --- a/lib/python/Components/NimManager.py +++ b/lib/python/Components/NimManager.py @@ -1213,10 +1213,21 @@ def InitNimManager(nimmgr): tmp.lnb = lnb nim.advanced.sat[x] = tmp + def toneAmplitudeChanged(configElement): + fe_id = configElement.fe_id + slot_id = configElement.slot_id + if nimmgr.nim_slots[slot_id].description == 'Alps BSBE2': + open("/proc/stb/frontend/%d/tone_amplitude" %(fe_id), "w").write(configElement.value) + + empty_slots = 0 for slot in nimmgr.nim_slots: x = slot.slot nim = config.Nims[x] if slot.isCompatible("DVB-S"): + nim.toneAmplitude = ConfigSelection([("9", "600mV"), ("8", "700mV"), ("7", "800mV"), ("6", "900mV"), ("5", "1100mV")], "7") + nim.toneAmplitude.fe_id = x - empty_slots + nim.toneAmplitude.slot_id = x + nim.toneAmplitude.addNotifier(toneAmplitudeChanged) nim.diseqc13V = ConfigYesNo(False) nim.diseqcMode = ConfigSelection(diseqc_mode_choices, "diseqc_a_b") nim.connectedTo = ConfigSelection([(str(id), nimmgr.getNimDescription(id)) for id in nimmgr.getNimListOfType("DVB-S") if id != x]) @@ -1306,6 +1317,7 @@ def InitNimManager(nimmgr): nim.terrestrial = ConfigSelection(choices = list) nim.terrestrial_5V = ConfigOnOff() else: + empty_slots += 1 nim.configMode = ConfigSelection(choices = { "nothing": _("disabled") }, default="nothing"); if slot.type is not None: print "pls add support for this frontend type!", slot.type diff --git a/lib/python/Plugins/Extensions/CutListEditor/plugin.py b/lib/python/Plugins/Extensions/CutListEditor/plugin.py index efe9f761..abd606d6 100644 --- a/lib/python/Plugins/Extensions/CutListEditor/plugin.py +++ b/lib/python/Plugins/Extensions/CutListEditor/plugin.py @@ -195,7 +195,7 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He self.onClose.append(self.__onClose) def __onClose(self): - self.session.nav.playService(self.old_service) + self.session.nav.playService(self.old_service, forceRestart=True) def updateStateLabel(self, state): self["SeekState"].setText(state[3].strip()) diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py index 44075d64..642a898d 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Process.py +++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py @@ -264,6 +264,7 @@ class WaitForResidentTasks(Task): def run(self, callback): print "waiting for %d resident task(s) %s to finish..." % (len(self.job.resident_tasks),str(self.job.resident_tasks)) + self.callback = callback if self.job.resident_tasks == 0: callback(self, []) diff --git a/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py b/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py index c4289cb0..a1c38842 100755 --- a/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py +++ b/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py @@ -8,7 +8,6 @@ from Components.Sources.List import List from Components.Sources.StaticText import StaticText from Components.Sources.Progress import Progress from Components.FileList import FileList -from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_FONTS, SCOPE_HDD from Components.config import config, getConfigListEntry from Components.ConfigList import ConfigListScreen @@ -235,7 +234,6 @@ class ProjectSettings(Screen,ConfigListScreen): self.session.open(MessageBox,self.project.error,MessageBox.TYPE_ERROR) elif scope == "project": if self.project.loadProject(path): - configRef.setValue(path) self.initConfigList() else: self.session.open(MessageBox,self.project.error,MessageBox.TYPE_ERROR) diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py index 928a8b82..dbc988b1 100755 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py @@ -10,7 +10,8 @@ from Components.ActionMap import HelpableActionMap, ActionMap from Components.Sources.List import List from Components.Sources.StaticText import StaticText from Components.Sources.Progress import Progress -from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT +from Components.MultiContent import MultiContentEntryText +from enigma import gFont, RT_HALIGN_LEFT, RT_HALIGN_RIGHT from Tools.Directories import resolveFilename, SCOPE_PLUGINS class TitleList(Screen, HelpableScreen): @@ -27,7 +28,18 @@ class TitleList(Screen, HelpableScreen): <widget source="title_label" render="Label" position="10,48" size="540,38" font="Regular;18" transparent="1" /> <widget source="error_label" render="Label" position="10,48" size="540,395" zPosition="3" font="Regular;20" transparent="1" /> <widget source="titles" render="Listbox" scrollbarMode="showOnDemand" position="10,86" size="540,312" zPosition="3" transparent="1" > - <convert type="StaticMultiList" /> + <convert type="TemplatedMultiContent"> + {"template": [ + MultiContentEntryText(pos = (0, 0), size = (420, 20), font = 0, flags = RT_HALIGN_LEFT, text = 1), # index 1 Title, + MultiContentEntryText(pos = (0, 20), size = (328, 17), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 description, + MultiContentEntryText(pos = (420, 6), size = (120, 20), font = 1, flags = RT_HALIGN_RIGHT, text = 3), # index 3 begin time, + MultiContentEntryText(pos = (328, 20), size = (154, 17), font = 1, flags = RT_HALIGN_RIGHT, text = 4), # index 4 channel, + MultiContentEntryText(pos = (482, 20), size = (58, 20), font = 1, flags = RT_HALIGN_RIGHT, text = 5), # index 4 channel, + ], + "fonts": [gFont("Regular", 20), gFont("Regular", 14)], + "itemHeight": 37 + } + </convert> </widget> <widget source="space_bar" render="Progress" position="10,410" size="540,26" borderWidth="1" backgroundColor="#254f7497" /> <widget source="space_label" render="Label" position="40,414" size="480,22" zPosition="2" font="Regular;18" halign="center" transparent="1" foregroundColor="#000000" /> @@ -71,7 +83,7 @@ class TitleList(Screen, HelpableScreen): else: self.newProject() - self["titles"] = List(list = [ ], enableWrapAround = True, item_height=30, fonts = [gFont("Regular", 20)]) + self["titles"] = List([]) self.updateTitleList() self.previous_size = 0 self.onLayoutFinish.append(self.layoutFinished) @@ -188,6 +200,9 @@ class TitleList(Screen, HelpableScreen): def selectedSource(self, source): if source is None: return None + if not source.getPath().endswith(".ts"): + self.session.open(MessageBox,text = _("You can only burn Dreambox recordings!"), type = MessageBox.TYPE_ERROR) + return None t = self.project.addService(source) try: editor = source.edit @@ -256,15 +271,14 @@ class TitleList(Screen, HelpableScreen): job = Process.DVDJob(self.project, menupreview=True) job_manager.in_background = False job_manager.AddJob(job) - + def updateTitleList(self): - res = [ ] + list = [ ] for title in self.project.titles: - a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 5, 500, 25, 0, RT_HALIGN_LEFT, title.properties.menutitle.getValue()) ] - res.append(a) - self["titles"].list = res + list.append((title, title.properties.menutitle.getValue(), title.properties.menusubtitle.getValue(), title.DVBchannel, title.formatDVDmenuText("$D.$M.$Y, $T", 0), title.formatDVDmenuText("$l", 0))) + self["titles"].list = list self.updateSize() - if len(res): + if len(list): self["key_red"].text = _("Remove title") self["key_yellow"].text = _("Title properties") else: diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py index 11601cc3..0a664eba 100755 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py @@ -9,7 +9,7 @@ from Components.Sources.StaticText import StaticText from Components.Sources.Progress import Progress from Components.FileList import FileList from Components.Pixmap import Pixmap -from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT, ePicLoad +from enigma import ePicLoad from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_FONTS, SCOPE_HDD from Components.config import config, getConfigListEntry, ConfigInteger, ConfigSubsection, ConfigSelection from Components.ConfigList import ConfigListScreen @@ -164,7 +164,8 @@ class LanguageChoices(): self.choices.sort() self.choices.insert(0,("nolang", ("unspecified"))) self.choices.insert(1,(syslang, self.langdict[syslang])) - self.choices.insert(2,("en", self.langdict["en"])) + if syslang != "en": + self.choices.insert(2,("en", self.langdict["en"])) def getLanguage(self, DVB_lang): DVB_lang = DVB_lang.lower() diff --git a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp index 94f2ee38..0372c497 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp +++ b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp @@ -696,7 +696,7 @@ RESULT eServiceDVD::setTrickmode(int /*trick*/) RESULT eServiceDVD::isCurrentlySeekable() { - return m_state == stRunning; + return m_state == stRunning ? 3 : 0; } RESULT eServiceDVD::keyPressed(int key) diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am b/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am index ee1e56de..2d5e3381 100644..100755 --- a/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am @@ -6,7 +6,8 @@ install_PYTHON = \ __init__.py \ plugin.py \ BackupRestore.py \ - ImageWizard.py + ImageWizard.py \ + SoftwareTools.py dist_install_DATA = \ imagewizard.xml \ diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py new file mode 100755 index 00000000..4e7591ef --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py @@ -0,0 +1,226 @@ +from enigma import eConsoleAppContainer +from Components.Console import Console +from Components.About import about +from Components.DreamInfoHandler import DreamInfoHandler +from Components.Language import language +from Components.Sources.List import List +from Components.Ipkg import IpkgComponent +from Components.Network import iNetwork +from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_METADIR + +from time import time + +class SoftwareTools(DreamInfoHandler): + lastDownloadDate = None + NetworkConnectionAvailable = None + list_updating = False + available_updates = 0 + available_updatelist = [] + available_packetlist = [] + installed_packetlist = {} + + + def __init__(self): + aboutInfo = about.getImageVersionString() + if aboutInfo.startswith("dev-"): + self.ImageVersion = 'Experimental' + else: + self.ImageVersion = 'Stable' + self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country" + DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language) + self.directory = resolveFilename(SCOPE_METADIR) + self.list = List([]) + self.NotifierCallback = None + self.Console = Console() + self.UpdateConsole = Console() + self.cmdList = [] + self.unwanted_extensions = ('-dbg', '-dev', '-doc') + self.ipkg = IpkgComponent() + self.ipkg.addCallback(self.ipkgCallback) + + def statusCallback(self, status, progress): + pass + + def startSoftwareTools(self, callback = None): + if callback is not None: + self.NotifierCallback = callback + iNetwork.checkNetworkState(self.checkNetworkCB) + + def checkNetworkCB(self,data): + if data is not None: + if data <= 2: + SoftwareTools.NetworkConnectionAvailable = True + self.getUpdates() + else: + SoftwareTools.NetworkConnectionAvailable = False + self.getUpdates() + + def getUpdates(self, callback = None): + if SoftwareTools.NetworkConnectionAvailable == True: + SoftwareTools.lastDownloadDate = time() + if SoftwareTools.list_updating is False and callback is None: + SoftwareTools.list_updating = True + self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) + elif SoftwareTools.list_updating is False and callback is not None: + SoftwareTools.list_updating = True + self.NotifierCallback = callback + self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) + elif SoftwareTools.list_updating is True and callback is not None: + #update info collecting already in progress + self.NotifierCallback = callback + else: + SoftwareTools.list_updating = False + if callback is not None: + callback(False) + elif self.NotifierCallback is not None: + self.NotifierCallback(False) + + def ipkgCallback(self, event, param): + if event == IpkgComponent.EVENT_ERROR: + SoftwareTools.list_updating = False + elif event == IpkgComponent.EVENT_DONE: + if SoftwareTools.list_updating: + self.startIpkgListAvailable() + pass + + def startIpkgListAvailable(self, callback = None): + if callback is not None: + SoftwareTools.list_updating = True + if SoftwareTools.list_updating: + if not self.UpdateConsole: + self.UpdateConsole = Console() + cmd = "ipkg list" + self.UpdateConsole.ePopen(cmd, self.IpkgListAvailableCB, callback) + + def IpkgListAvailableCB(self, result, retval, extra_args = None): + (callback) = extra_args + if len(result): + if SoftwareTools.list_updating: + SoftwareTools.available_packetlist = [] + for x in result.splitlines(): + split = x.split(' - ') + name = split[0].strip() + if not any(name.endswith(x) for x in self.unwanted_extensions): + SoftwareTools.available_packetlist.append([name, split[1].strip(), split[2].strip()]) + if callback is None: + self.startInstallMetaPackage() + else: + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + callback(True) + else: + SoftwareTools.list_updating = False + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + if callback is not None: + callback(False) + + def startInstallMetaPackage(self, callback = None): + if callback is not None: + SoftwareTools.list_updating = True + if SoftwareTools.list_updating: + if not self.UpdateConsole: + self.UpdateConsole = Console() + cmd = "ipkg install enigma2-meta enigma2-plugins-meta enigma2-skins-meta" + self.UpdateConsole.ePopen(cmd, self.InstallMetaPackageCB, callback) + + def InstallMetaPackageCB(self, result, retval, extra_args = None): + (callback) = extra_args + if len(result): + self.fillPackagesIndexList() + if callback is None: + self.startIpkgListInstalled() + else: + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + callback(True) + else: + SoftwareTools.list_updating = False + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + if callback is not None: + callback(False) + + def startIpkgListInstalled(self, callback = None): + if callback is not None: + SoftwareTools.list_updating = True + if SoftwareTools.list_updating: + if not self.UpdateConsole: + self.UpdateConsole = Console() + cmd = "ipkg list_installed" + self.UpdateConsole.ePopen(cmd, self.IpkgListInstalledCB, callback) + + def IpkgListInstalledCB(self, result, retval, extra_args = None): + (callback) = extra_args + if len(result): + SoftwareTools.installed_packetlist = {} + for x in result.splitlines(): + split = x.split(' - ') + name = split[0].strip() + if not any(name.endswith(x) for x in self.unwanted_extensions): + SoftwareTools.installed_packetlist[name] = split[1].strip() + if callback is None: + self.countUpdates() + else: + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + callback(True) + else: + SoftwareTools.list_updating = False + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + if callback is not None: + callback(False) + + def countUpdates(self, callback = None): + SoftwareTools.available_updates = 0 + SoftwareTools.available_updatelist = [] + for package in self.packagesIndexlist[:]: + attributes = package[0]["attributes"] + packagename = attributes["packagename"] + for x in SoftwareTools.available_packetlist: + if x[0] == packagename: + if SoftwareTools.installed_packetlist.has_key(packagename): + if SoftwareTools.installed_packetlist[packagename] != x[1]: + SoftwareTools.available_updates +=1 + SoftwareTools.available_updatelist.append([packagename]) + + SoftwareTools.list_updating = False + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + if callback is not None: + callback(True) + callback = None + elif self.NotifierCallback is not None: + self.NotifierCallback(True) + self.NotifierCallback = None + + def startIpkgUpdate(self, callback = None): + if not self.Console: + self.Console = Console() + cmd = "ipkg update" + self.Console.ePopen(cmd, self.IpkgUpdateCB, callback) + + def IpkgUpdateCB(self, result, retval, extra_args = None): + (callback) = extra_args + if len(result): + if self.Console: + if len(self.Console.appContainers) == 0: + if callback is not None: + callback(True) + callback = None + + def cleanupSoftwareTools(self): + if self.NotifierCallback is not None: + self.NotifierCallback = None + self.ipkg.stop() + if self.Console is not None: + if len(self.Console.appContainers): + for name in self.Console.appContainers.keys(): + self.Console.kill(name) + if self.UpdateConsole is not None: + if len(self.UpdateConsole.appContainers): + for name in self.UpdateConsole.appContainers.keys(): + self.UpdateConsole.kill(name) + +iSoftwareTools = SoftwareTools()
\ No newline at end of file diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py index c70201b3..f61ea53c 100755 --- a/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py @@ -23,6 +23,7 @@ from Components.About import about from Components.DreamInfoHandler import DreamInfoHandler from Components.Language import language from Components.AVSwitch import AVSwitch +from Components.Network import iNetwork from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN, SCOPE_METADIR from Tools.LoadPixmap import LoadPixmap from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad @@ -36,6 +37,7 @@ from twisted.internet import reactor from ImageWizard import ImageWizard from BackupRestore import BackupSelection, RestoreMenu, BackupScreen, RestoreScreen, getBackupPath, getBackupFilename +from SoftwareTools import iSoftwareTools config.plugins.configurationbackup = ConfigSubsection() config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False) @@ -74,30 +76,31 @@ def load_cache(cache_file): class UpdatePluginMenu(Screen): skin = """ - <screen name="UpdatePluginMenu" position="center,center" size="560,400" title="Software manager" > + <screen name="UpdatePluginMenu" position="center,center" size="610,410" title="Software management" > <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> - <ePixmap pixmap="skin_default/border_menu_300.png" position="5,50" zPosition="1" size="300,300" transparent="1" alphatest="on" /> - <widget source="menu" render="Listbox" position="10,60" size="290,260" scrollbarMode="showOnDemand"> + <ePixmap pixmap="skin_default/border_menu_350.png" position="5,50" zPosition="1" size="350,300" transparent="1" alphatest="on" /> + <widget source="menu" render="Listbox" position="15,60" size="330,290" scrollbarMode="showOnDemand"> <convert type="TemplatedMultiContent"> {"template": [ - MultiContentEntryText(pos = (2, 2), size = (290, 22), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText, + MultiContentEntryText(pos = (2, 2), size = (330, 24), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText, ], - "fonts": [gFont("Regular", 20)], + "fonts": [gFont("Regular", 22)], "itemHeight": 25 } </convert> </widget> - <widget source="menu" render="Listbox" position="310,50" size="240,300" scrollbarMode="showNever" selectionDisabled="1"> + <widget source="menu" render="Listbox" position="360,50" size="240,300" scrollbarMode="showNever" selectionDisabled="1"> <convert type="TemplatedMultiContent"> {"template": [ MultiContentEntryText(pos = (2, 2), size = (240, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description, ], - "fonts": [gFont("Regular", 20)], + "fonts": [gFont("Regular", 22)], "itemHeight": 300 } </convert> </widget> + <widget source="status" render="Label" position="5,360" zPosition="10" size="600,50" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" /> </screen>""" def __init__(self, session, args = 0): @@ -106,14 +109,15 @@ class UpdatePluginMenu(Screen): self.menu = args self.list = [] self.oktext = _("\nPress OK on your remote control to continue.") + self.text = "" self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value ) if self.menu == 0: + self.list.append(("install-extensions", _("Manage extensions"), _("\nManage extensions or plugins for your Dreambox" ) + self.oktext, None)) self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext, None)) - #self.list.append(("install-plugins", _("Install extensions"), _("\nInstall new Extensions or Plugins to your dreambox" ) + self.oktext, None)) self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext, None)) self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext, None)) self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext, None)) - self.list.append(("ipkg-install", _("Install local extension"), _("\nScan for local packages and install them." ) + self.oktext, None)) + self.list.append(("ipkg-install", _("Install local extension"), _("\nScan for local extensions and install them." ) + self.oktext, None)) for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER): if p.__call__.has_key("SoftwareSupported"): callFnc = p.__call__["SoftwareSupported"](None) @@ -133,8 +137,8 @@ class UpdatePluginMenu(Screen): self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext, None)) self.list.append(("backuplocation", _("Choose backup location"), _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext, None)) self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext, None)) - if config.usage.setup_level.index >= 2: # expert+ - self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext, None)) + #if config.usage.setup_level.index >= 2: # expert+ + # self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext, None)) self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext, None)) for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER): if p.__call__.has_key("AdvancedSoftwareSupported"): @@ -152,28 +156,54 @@ class UpdatePluginMenu(Screen): self["menu"] = List(self.list) self["key_red"] = StaticText(_("Close")) + self["status"] = StaticText("") - self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], + self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions"], { "ok": self.go, "back": self.close, "red": self.close, }, -1) - self.onLayoutFinish.append(self.layoutFinished) self.backuppath = getBackupPath() self.backupfile = getBackupFilename() self.fullbackupfilename = self.backuppath + "/" + self.backupfile self.onShown.append(self.setWindowTitle) + #self.onClose.append(self.cleanup) def layoutFinished(self): idx = 0 self["menu"].index = idx + #self.getUpdateInfos() def setWindowTitle(self): - self.setTitle(_("Software manager")) + self.setTitle(_("Software management")) + + def cleanup(self): + iNetwork.stopPingConsole() + iSoftwareTools.cleanupSoftwareTools() + + def getUpdateInfos(self): + self.text = "" + if iSoftwareTools.NetworkConnectionAvailable == True: + if iSoftwareTools.list_updating is False: + if iSoftwareTools.available_updates is not 0: + self.text = _("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.") + else: + self.text = "" #_("There are no updates available.") + else: + if iSoftwareTools.available_updates is not 0: + self.text = _("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.") + else: + self.text = "" #_("There are no updates available.") + self.text += "\n" + _("A search for available updates is currently in progress.") + else: + self.text = _("No network connection available.") + self["status"].setText(self.text) + def go(self): + #iNetwork.stopPingConsole() current = self["menu"].getCurrent() if current: currentEntry = current[0] @@ -182,7 +212,7 @@ class UpdatePluginMenu(Screen): self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!")) elif (currentEntry == "software-restore"): self.session.open(ImageWizard) - elif (currentEntry == "install-plugins"): + elif (currentEntry == "install-extensions"): self.session.open(PluginManager, self.skin_path) elif (currentEntry == "system-backup"): self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True) @@ -260,433 +290,11 @@ class UpdatePluginMenu(Screen): self.exe = True self.session.open(RestoreScreen, runRestore = True) -class IPKGMenu(Screen): - skin = """ - <screen name="IPKGMenu" position="center,center" size="560,400" title="Select upgrade source to edit." > - <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> - <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" /> - <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> - <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" /> - <widget name="filelist" position="5,50" size="550,340" scrollbarMode="showOnDemand" /> - </screen>""" - - def __init__(self, session, plugin_path): - Screen.__init__(self, session) - self.skin_path = plugin_path - - self["key_red"] = StaticText(_("Close")) - self["key_green"] = StaticText(_("Edit")) - - self.sel = [] - self.val = [] - self.entry = False - self.exe = False - - self.path = "" - - self["actions"] = NumberActionMap(["SetupActions"], - { - "ok": self.KeyOk, - "cancel": self.keyCancel - }, -1) - - self["shortcuts"] = ActionMap(["ShortcutActions"], - { - "red": self.keyCancel, - "green": self.KeyOk, - }) - self.flist = [] - self["filelist"] = MenuList(self.flist) - self.fill_list() - self.onLayoutFinish.append(self.layoutFinished) - - def layoutFinished(self): - self.setWindowTitle() - - def setWindowTitle(self): - self.setTitle(_("Select upgrade source to edit.")) - - def fill_list(self): - self.flist = [] - self.path = '/etc/ipkg/' - if (os_path.exists(self.path) == False): - self.entry = False - return - for file in listdir(self.path): - if (file.endswith(".conf")): - if file != 'arch.conf': - self.flist.append((file)) - self.entry = True - self["filelist"].l.setList(self.flist) - - def KeyOk(self): - if (self.exe == False) and (self.entry == True): - self.sel = self["filelist"].getCurrent() - self.val = self.path + self.sel - self.session.open(IPKGSource, self.val) - - def keyCancel(self): - self.close() - - def Exit(self): - self.close() - - -class IPKGSource(Screen): - skin = """ - <screen name="IPKGSource" position="center,center" size="560,80" title="Edit upgrade source url." > - <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> - <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" /> - <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> - <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" /> - <widget name="text" position="5,50" size="550,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" /> - </screen>""" - - def __init__(self, session, configfile = None): - Screen.__init__(self, session) - self.session = session - self.configfile = configfile - text = "" - if self.configfile: - try: - fp = file(configfile, 'r') - sources = fp.readlines() - if sources: - text = sources[0] - fp.close() - except IOError: - pass - - desk = getDesktop(0) - x= int(desk.size().width()) - y= int(desk.size().height()) - - self["key_red"] = StaticText(_("Cancel")) - self["key_green"] = StaticText(_("Save")) - - if (y>=720): - self["text"] = Input(text, maxSize=False, type=Input.TEXT) - else: - self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT) - - self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"], - { - "ok": self.go, - "back": self.close, - "red": self.close, - "green": self.go, - "left": self.keyLeft, - "right": self.keyRight, - "home": self.keyHome, - "end": self.keyEnd, - "deleteForward": self.keyDeleteForward, - "deleteBackward": self.keyDeleteBackward, - "1": self.keyNumberGlobal, - "2": self.keyNumberGlobal, - "3": self.keyNumberGlobal, - "4": self.keyNumberGlobal, - "5": self.keyNumberGlobal, - "6": self.keyNumberGlobal, - "7": self.keyNumberGlobal, - "8": self.keyNumberGlobal, - "9": self.keyNumberGlobal, - "0": self.keyNumberGlobal - }, -1) - - self.onLayoutFinish.append(self.layoutFinished) - - def layoutFinished(self): - self.setWindowTitle() - self["text"].right() - - def setWindowTitle(self): - self.setTitle(_("Edit upgrade source url.")) - - def go(self): - text = self["text"].getText() - if text: - fp = file(self.configfile, 'w') - fp.write(text) - fp.write("\n") - fp.close() - self.close() - - def keyLeft(self): - self["text"].left() - - def keyRight(self): - self["text"].right() - - def keyHome(self): - self["text"].home() - - def keyEnd(self): - self["text"].end() - - def keyDeleteForward(self): - self["text"].delete() - - def keyDeleteBackward(self): - self["text"].deleteBackward() - - def keyNumberGlobal(self, number): - self["text"].number(number) - - -class PacketManager(Screen): - skin = """ - <screen name="PacketManager" position="center,center" size="530,420" title="Packet manager" > - <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> - <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" /> - <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> - <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" /> - <widget source="list" render="Listbox" position="5,50" size="520,365" scrollbarMode="showOnDemand"> - <convert type="TemplatedMultiContent"> - {"template": [ - MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description - MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap - MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap - ], - "fonts": [gFont("Regular", 22),gFont("Regular", 14)], - "itemHeight": 52 - } - </convert> - </widget> - </screen>""" - - def __init__(self, session, plugin_path, args = None): - Screen.__init__(self, session) - self.session = session - self.skin_path = plugin_path - - self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], - { - "ok": self.go, - "back": self.exit, - "red": self.exit, - "green": self.reload, - }, -1) - - self.list = [] - self.statuslist = [] - self["list"] = List(self.list) - self["key_red"] = StaticText(_("Close")) - self["key_green"] = StaticText(_("Reload")) - - self.list_updating = True - self.packetlist = [] - self.installed_packetlist = {} - self.Console = Console() - self.cmdList = [] - self.cachelist = [] - self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs) - self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory - self.oktext = _("\nAfter pressing OK, please wait!") - self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox') - - self.ipkg = IpkgComponent() - self.ipkg.addCallback(self.ipkgCallback) - self.onShown.append(self.setWindowTitle) - self.onLayoutFinish.append(self.rebuildList) - - def exit(self): - self.ipkg.stop() - if self.Console is not None: - if len(self.Console.appContainers): - for name in self.Console.appContainers.keys(): - self.Console.kill(name) - self.close() - - def reload(self): - if (os_path.exists(self.cache_file) == True): - remove(self.cache_file) - self.list_updating = True - self.rebuildList() - - def setWindowTitle(self): - self.setTitle(_("Packet manager")) - - def setStatus(self,status = None): - if status: - self.statuslist = [] - divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) - if status == 'update': - statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) - self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng )) - self['list'].setList(self.statuslist) - elif status == 'error': - statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) - self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng )) - self['list'].setList(self.statuslist) - - def rebuildList(self): - self.setStatus('update') - self.inv_cache = 0 - self.vc = valid_cache(self.cache_file, self.cache_ttl) - if self.cache_ttl > 0 and self.vc != 0: - try: - self.buildPacketList() - except: - self.inv_cache = 1 - if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: - self.run = 0 - self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) - - def go(self, returnValue = None): - cur = self["list"].getCurrent() - if cur: - status = cur[3] - package = cur[0] - self.cmdList = [] - if status == 'installed': - self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package })) - if len(self.cmdList): - self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext) - elif status == 'upgradeable': - self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package })) - if len(self.cmdList): - self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext) - elif status == "installable": - self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package })) - if len(self.cmdList): - self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext) - - def runRemove(self, result): - if result: - self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList) - - def runRemoveFinished(self): - self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) - - def RemoveReboot(self, result): - if result is None: - return - if result is False: - cur = self["list"].getCurrent() - if cur: - item = self['list'].getIndex() - self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable') - self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable'] - self['list'].setList(self.list) - write_cache(self.cache_file, self.cachelist) - self.reloadPluginlist() - if result: - quitMainloop(3) - - def runUpgrade(self, result): - if result: - self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList) - - def runUpgradeFinished(self): - self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) - - def UpgradeReboot(self, result): - if result is None: - return - if result is False: - cur = self["list"].getCurrent() - if cur: - item = self['list'].getIndex() - self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed') - self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed'] - self['list'].setList(self.list) - write_cache(self.cache_file, self.cachelist) - self.reloadPluginlist() - if result: - quitMainloop(3) - - def ipkgCallback(self, event, param): - if event == IpkgComponent.EVENT_ERROR: - self.list_updating = False - self.setStatus('error') - elif event == IpkgComponent.EVENT_DONE: - if self.list_updating: - self.list_updating = False - if not self.Console: - self.Console = Console() - cmd = "ipkg list" - self.Console.ePopen(cmd, self.IpkgList_Finished) - #print event, "-", param - pass - - def IpkgList_Finished(self, result, retval, extra_args = None): - if len(result): - self.packetlist = [] - for x in result.splitlines(): - split = x.split(' - ') #self.blacklisted_packages - if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): - self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()]) - if not self.Console: - self.Console = Console() - cmd = "ipkg list_installed" - self.Console.ePopen(cmd, self.IpkgListInstalled_Finished) - - def IpkgListInstalled_Finished(self, result, retval, extra_args = None): - if len(result): - self.installed_packetlist = {} - for x in result.splitlines(): - split = x.split(' - ') - if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): - self.installed_packetlist[split[0].strip()] = split[1].strip() - self.buildPacketList() - - def buildEntryComponent(self, name, version, description, state): - divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) - if state == 'installed': - installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) - return((name, version, description, state, installedpng, divpng)) - elif state == 'upgradeable': - upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgradeable.png")) - return((name, version, description, state, upgradeablepng, divpng)) - else: - installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) - return((name, version, description, state, installablepng, divpng)) - - def buildPacketList(self): - self.list = [] - self.cachelist = [] - - if self.cache_ttl > 0 and self.vc != 0: - print 'Loading packagelist cache from ',self.cache_file - try: - self.cachelist = load_cache(self.cache_file) - if len(self.cachelist) > 0: - for x in self.cachelist: - self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3])) - self['list'].setList(self.list) - except: - self.inv_cache = 1 - - if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: - print 'rebuilding fresh package list' - for x in self.packetlist: - status = "" - if self.installed_packetlist.has_key(x[0].strip()): - if self.installed_packetlist[x[0].strip()] == x[1].strip(): - status = "installed" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) - else: - status = "upgradeable" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) - else: - status = "installable" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) - if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions): - self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status]) - write_cache(self.cache_file, self.cachelist) - self['list'].setList(self.list) - - def reloadPluginlist(self): - plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) - class PluginManager(Screen, DreamInfoHandler): - lastDownloadDate = None - skin = """ - <screen name="PluginManager" position="center,center" size="560,440" title="Plugin manager" > + <screen name="PluginManager" position="center,center" size="560,440" title="Extensions management" > <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" /> <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" /> @@ -700,17 +308,17 @@ class PluginManager(Screen, DreamInfoHandler): {"templates": {"default": (51,[ MultiContentEntryText(pos = (30, 1), size = (470, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (30, 25), size = (470, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description + MultiContentEntryText(pos = (30, 25), size = (470, 24), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description MultiContentEntryPixmapAlphaTest(pos = (475, 0), size = (48, 48), png = 5), # index 5 is the status pixmap MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 6), # index 6 is the div pixmap ]), "category": (40,[ MultiContentEntryText(pos = (30, 0), size = (500, 22), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (30, 22), size = (500, 16), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the description + MultiContentEntryText(pos = (30, 22), size = (500, 16), font=2, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the description MultiContentEntryPixmapAlphaTest(pos = (0, 38), size = (550, 2), png = 3), # index 3 is the div pixmap ]) }, - "fonts": [gFont("Regular", 22),gFont("Regular", 16)], + "fonts": [gFont("Regular", 22),gFont("Regular", 20),gFont("Regular", 16)], "itemHeight": 52 } </convert> @@ -722,15 +330,6 @@ class PluginManager(Screen, DreamInfoHandler): Screen.__init__(self, session) self.session = session self.skin_path = plugin_path - aboutInfo = about.getImageVersionString() - if aboutInfo.startswith("dev-"): - self.ImageVersion = 'Experimental' - else: - self.ImageVersion = 'Stable' - self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country" - - DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language) - self.directory = resolveFilename(SCOPE_METADIR) self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "HelpActions" ], { @@ -747,6 +346,7 @@ class PluginManager(Screen, DreamInfoHandler): self.statuslist = [] self.selectedFiles = [] self.categoryList = [] + self.packetlist = [] self["list"] = List(self.list) self["key_red"] = StaticText(_("Close")) self["key_green"] = StaticText("") @@ -754,30 +354,22 @@ class PluginManager(Screen, DreamInfoHandler): self["key_blue"] = StaticText("") self["status"] = StaticText("") - self.list_updating = True - self.packetlist = [] - self.installed_packetlist = {} - self.available_packetlist = [] - self.available_updates = 0 - self.Console = Console() self.cmdList = [] self.oktext = _("\nAfter pressing OK, please wait!") - self.unwanted_extensions = ('-dbg', '-dev', '-doc') - - self.ipkg = IpkgComponent() - self.ipkg.addCallback(self.ipkgCallback) if not self.selectionChanged in self["list"].onSelectionChanged: self["list"].onSelectionChanged.append(self.selectionChanged) self.currList = "" self.currentSelectedTag = None self.currentSelectedIndex = None - + self.currentSelectedPackage = None + self.saved_currentSelectedPackage = None + self.onShown.append(self.setWindowTitle) - self.onLayoutFinish.append(self.rebuildList) + self.onLayoutFinish.append(self.getUpdateInfos) def setWindowTitle(self): - self.setTitle(_("Plugin manager")) + self.setTitle(_("Extensions management")) def exit(self): if self.currList == "packages": @@ -789,11 +381,7 @@ class PluginManager(Screen, DreamInfoHandler): self["list"].updateList(self.categoryList) self.selectionChanged() else: - self.ipkg.stop() - if self.Console is not None: - if len(self.Console.appContainers): - for name in self.Console.appContainers.keys(): - self.Console.kill(name) + iSoftwareTools.cleanupSoftwareTools() self.prepareInstall() if len(self.cmdList): self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList) @@ -814,7 +402,7 @@ class PluginManager(Screen, DreamInfoHandler): divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) if status == 'update': statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) - self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'', '', statuspng, divpng, None, '' )) + self.statuslist.append(( _("Updating software catalog"), '', _("Searching for available updates. Please wait..." ),'', '', statuspng, divpng, None, '' )) self["list"].style = "default" self['list'].setList(self.statuslist) elif status == 'sync': @@ -828,8 +416,26 @@ class PluginManager(Screen, DreamInfoHandler): self["list"].style = "default" self['list'].setList(self.statuslist) - def statusCallback(self, status, progress): - pass + def getUpdateInfos(self): + self.setState('update') + iSoftwareTools.getUpdates(self.getUpdateInfosCB) + + def getUpdateInfosCB(self, retval = None): + if retval is not None: + if retval is True: + if iSoftwareTools.available_updates is not 0: + self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.")) + else: + self["status"].setText(_("There are no updates available.")) + elif retval is False: + self["status"].setText(_("No network connection available.")) + self.rebuildList() + + def rebuildList(self, retval = None): + if self.currentSelectedTag is None: + self.buildCategoryList() + else: + self.buildPacketList(self.currentSelectedTag) def selectionChanged(self): current = self["list"].getCurrent() @@ -838,34 +444,34 @@ class PluginManager(Screen, DreamInfoHandler): if self.currList == "packages": self["key_red"].setText(_("Back")) if current[4] == 'installed': - self["key_green"].setText(_("Remove")) + self["key_green"].setText(_("Uninstall")) elif current[4] == 'installable': self["key_green"].setText(_("Install")) elif current[4] == 'remove': - self["key_green"].setText(_("Undo\nRemove")) + self["key_green"].setText(_("Undo uninstall")) elif current[4] == 'install': - self["key_green"].setText(_("Undo\nInstall")) + self["key_green"].setText(_("Undo install")) self["key_yellow"].setText(_("View details")) self["key_blue"].setText("") - if len(self.selectedFiles) == 0 and self.available_updates is not 0: - self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available.")) + if len(self.selectedFiles) == 0 and iSoftwareTools.available_updates is not 0: + self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.")) elif len(self.selectedFiles) is not 0: self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected.")) else: - self["status"].setText(_("There is nothing to be done.")) + self["status"].setText(_("There are currently no outstanding actions.")) elif self.currList == "category": self["key_red"].setText(_("Close")) self["key_green"].setText("") self["key_yellow"].setText("") self["key_blue"].setText("") - if len(self.selectedFiles) == 0 and self.available_updates is not 0: - self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available.")) + if len(self.selectedFiles) == 0 and iSoftwareTools.available_updates is not 0: + self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.")) self["key_yellow"].setText(_("Update")) elif len(self.selectedFiles) is not 0: self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected.")) self["key_yellow"].setText(_("Process")) else: - self["status"].setText(_("There is nothing to be done.")) + self["status"].setText(_("There are currently no outstanding actions.")) def getSelectionState(self, detailsFile): for entry in self.selectedFiles: @@ -873,82 +479,6 @@ class PluginManager(Screen, DreamInfoHandler): return True return False - def rebuildList(self): - self.setState('update') - if not PluginManager.lastDownloadDate or (time() - PluginManager.lastDownloadDate) > 3600: - # Only update from internet once per hour - PluginManager.lastDownloadDate = time() - print "last update time > 1h" - self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) - else: - print "last update time < 1h" - self.startIpkgList() - - def ipkgCallback(self, event, param): - if event == IpkgComponent.EVENT_ERROR: - self.list_updating = False - self.setState('error') - elif event == IpkgComponent.EVENT_DONE: - self.startIpkgList() - pass - - def startIpkgList(self): - if self.list_updating: - if not self.Console: - self.Console = Console() - cmd = "ipkg list" - self.Console.ePopen(cmd, self.IpkgList_Finished) - - def IpkgList_Finished(self, result, retval, extra_args = None): - if len(result): - self.available_packetlist = [] - for x in result.splitlines(): - split = x.split(' - ') - if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): - self.available_packetlist.append([split[0].strip(), split[1].strip(), split[2].strip()]) - self.startInstallMetaPackage() - - def startInstallMetaPackage(self): - if self.list_updating: - self.list_updating = False - if not self.Console: - self.Console = Console() - cmd = "ipkg install enigma2-meta" #dummy,will change probably" - self.Console.ePopen(cmd, self.InstallMetaPackage_Finished) - - def InstallMetaPackage_Finished(self, result, retval, extra_args = None): - if len(result): - self.fillPackagesIndexList() - if not self.Console: - self.Console = Console() - self.setState('sync') - cmd = "ipkg list_installed" - self.Console.ePopen(cmd, self.IpkgListInstalled_Finished) - - def IpkgListInstalled_Finished(self, result, retval, extra_args = None): - if len(result): - self.installed_packetlist = {} - for x in result.splitlines(): - split = x.split(' - ') - if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): - self.installed_packetlist[split[0].strip()] = split[1].strip() - self.countUpdates() - if self.currentSelectedTag is None: - self.buildCategoryList() - else: - self.buildPacketList(self.currentSelectedTag) - - def countUpdates(self): - self.available_updates = 0 - for package in self.packagesIndexlist[:]: - attributes = package[0]["attributes"] - packagename = attributes["packagename"] - for x in self.available_packetlist: - if x[0].strip() == packagename: - if self.installed_packetlist.has_key(packagename): - if self.installed_packetlist[packagename] != x[1].strip(): - self.available_updates +=1 - def handleCurrent(self): current = self["list"].getCurrent() if current: @@ -971,6 +501,7 @@ class PluginManager(Screen, DreamInfoHandler): alreadyinList = True if not alreadyinList: self.selectedFiles.append((detailsFile,current[4],current[3])) + self.currentSelectedPackage = ((detailsFile,current[4],current[3])) if current[4] == 'installed': self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'remove', True) elif current[4] == 'installable': @@ -989,8 +520,9 @@ class PluginManager(Screen, DreamInfoHandler): if current: if self.currList == "packages": if current[7] is not '': - detailsfile = self.directory[0] + "/" + current[1] + detailsfile = iSoftwareTools.directory[0] + "/" + current[1] if (os_path.exists(detailsfile) == True): + self.saved_currentSelectedPackage = self.currentSelectedPackage self.session.openWithCallback(self.detailsClosed, PluginDetails, self.skin_path, current) else: self.session.open(MessageBox, _("Sorry, no Details available!"), MessageBox.TYPE_INFO, timeout = 10) @@ -999,29 +531,29 @@ class PluginManager(Screen, DreamInfoHandler): if len(self.cmdList): self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList) - def detailsClosed(self, result): - if result: - if not self.Console: - self.Console = Console() - self.setState('sync') - PluginManager.lastDownloadDate = time() - self.selectedFiles = [] - cmd = "ipkg update" - self.Console.ePopen(cmd, self.InstallMetaPackage_Finished) + def detailsClosed(self, result = None): + if result is not None: + if result is not False: + self.setState('sync') + iSoftwareTools.lastDownloadDate = time() + for entry in self.selectedFiles: + if entry == self.saved_currentSelectedPackage: + self.selectedFiles.remove(entry) + iSoftwareTools.startIpkgListInstalled(self.rebuildList) def buildEntryComponent(self, name, details, description, packagename, state, selected = False): divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) + installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) + installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) + removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) + installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png")) if state == 'installed': - installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) return((name, details, description, packagename, state, installedpng, divpng, selected)) elif state == 'installable': - installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) return((name, details, description, packagename, state, installablepng, divpng, selected)) elif state == 'remove': - removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) return((name, details, description, packagename, state, removepng, divpng, selected)) elif state == 'install': - installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png")) return((name, details, description, packagename, state, installpng, divpng, selected)) def buildPacketList(self, categorytag = None): @@ -1029,7 +561,7 @@ class PluginManager(Screen, DreamInfoHandler): self.currList = "packages" self.currentSelectedTag = categorytag self.packetlist = [] - for package in self.packagesIndexlist[:]: + for package in iSoftwareTools.packagesIndexlist[:]: prerequisites = package[0]["prerequisites"] if prerequisites.has_key("tag"): for foundtag in prerequisites["tag"]: @@ -1044,19 +576,23 @@ class PluginManager(Screen, DreamInfoHandler): self.list = [] for x in self.packetlist: status = "" - selectState = self.getSelectionState(x[1].strip()) - if self.installed_packetlist.has_key(x[3].strip()): + name = x[0].strip() + details = x[1].strip() + description = x[2].strip() + packagename = x[3].strip() + selectState = self.getSelectionState(details) + if iSoftwareTools.installed_packetlist.has_key(packagename): if selectState == True: status = "remove" else: status = "installed" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState)) + self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState)) else: if selectState == True: status = "install" else: status = "installable" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState)) + self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState)) if len(self.list): self.list.sort(key=lambda x: x[0]) self["list"].style = "default" @@ -1068,7 +604,7 @@ class PluginManager(Screen, DreamInfoHandler): self.currList = "category" self.categories = [] self.categoryList = [] - for package in self.packagesIndexlist[:]: + for package in iSoftwareTools.packagesIndexlist[:]: prerequisites = package[0]["prerequisites"] if prerequisites.has_key("tag"): for foundtag in prerequisites["tag"]: @@ -1114,14 +650,14 @@ class PluginManager(Screen, DreamInfoHandler): def prepareInstall(self): self.cmdList = [] - if self.available_updates > 0: + if iSoftwareTools.available_updates > 0: self.cmdList.append((IpkgComponent.CMD_UPGRADE, { "test_only": False })) if self.selectedFiles and len(self.selectedFiles): for plugin in self.selectedFiles: - detailsfile = self.directory[0] + "/" + plugin[0] + detailsfile = iSoftwareTools.directory[0] + "/" + plugin[0] if (os_path.exists(detailsfile) == True): - self.fillPackageDetails(plugin[0]) - self.package = self.packageDetails[0] + iSoftwareTools.fillPackageDetails(plugin[0]) + self.package = iSoftwareTools.packageDetails[0] if self.package[0].has_key("attributes"): self.attributes = self.package[0]["attributes"] if self.attributes.has_key("package"): @@ -1144,9 +680,13 @@ class PluginManager(Screen, DreamInfoHandler): else: self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] })) - def runExecute(self, result): - if result: - self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList) + def runExecute(self, result = None): + if result is not None: + if result[0] is True: + self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList) + elif result[0] is False: + self.cmdList = result[1] + self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList) else: self.close() @@ -1158,6 +698,7 @@ class PluginManager(Screen, DreamInfoHandler): return if result is False: self.reloadPluginlist() + self.selectedFiles = [] self.detailsClosed(True) if result: quitMainloop(3) @@ -1168,7 +709,7 @@ class PluginManager(Screen, DreamInfoHandler): class PluginManagerInfo(Screen): skin = """ - <screen name="PluginManagerInfo" position="center,center" size="560,440" title="Plugin manager activity information" > + <screen name="PluginManagerInfo" position="center,center" size="560,450" title="Plugin manager activity information" > <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" /> <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> @@ -1176,18 +717,18 @@ class PluginManagerInfo(Screen): <widget source="list" render="Listbox" position="5,50" size="550,350" scrollbarMode="showOnDemand" selectionDisabled="1"> <convert type="TemplatedMultiContent"> {"template": [ - MultiContentEntryText(pos = (50, 1), size = (150, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state + MultiContentEntryText(pos = (50, 0), size = (150, 26), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name + MultiContentEntryText(pos = (50, 27), size = (540, 23), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap - MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap + MultiContentEntryPixmapAlphaTest(pos = (0, 48), size = (550, 2), png = 3), # index 3 is the div pixmap ], - "fonts": [gFont("Regular", 22),gFont("Regular", 18)], - "itemHeight": 52 + "fonts": [gFont("Regular", 24),gFont("Regular", 22)], + "itemHeight": 50 } </convert> </widget> - <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="560,2" transparent="1" alphatest="on" /> - <widget source="status" render="Label" position="5,420" zPosition="10" size="550,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" /> + <ePixmap pixmap="skin_default/div-h.png" position="0,404" zPosition="10" size="560,2" transparent="1" alphatest="on" /> + <widget source="status" render="Label" position="5,408" zPosition="10" size="550,44" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" /> </screen>""" def __init__(self, session, plugin_path, cmdlist = None): @@ -1198,17 +739,17 @@ class PluginManagerInfo(Screen): self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], { - "ok": self.process, + "ok": self.process_all, "back": self.exit, "red": self.exit, - "green": self.process, + "green": self.process_extensions, }, -1) self.list = [] self["list"] = List(self.list) self["key_red"] = StaticText(_("Cancel")) - self["key_green"] = StaticText(_("Continue")) - self["status"] = StaticText(_("Following tasks will be done after you press continue!")) + self["key_green"] = StaticText(_("Only extensions.")) + self["status"] = StaticText(_("Following tasks will be done after you press OK!")) self.onShown.append(self.setWindowTitle) self.onLayoutFinish.append(self.rebuildList) @@ -1254,32 +795,41 @@ class PluginManagerInfo(Screen): return(( _('Upgrading'), info, upgradepng, divpng)) def exit(self): - self.close(False) + self.close() - def process(self): - self.close(True) + def process_all(self): + self.close((True,None)) + + def process_extensions(self): + self.list = [] + if self.cmdlist is not None: + for entry in self.cmdlist: + cmd = entry[0] + if entry[0] in (0,2): + self.list.append((entry)) + self.close((False,self.list)) class PluginManagerHelp(Screen): skin = """ - <screen name="PluginManagerHelp" position="center,center" size="560,440" title="Plugin manager help" > + <screen name="PluginManagerHelp" position="center,center" size="560,450" title="Plugin manager help" > <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> <widget source="list" render="Listbox" position="5,50" size="550,350" scrollbarMode="showOnDemand" selectionDisabled="1"> <convert type="TemplatedMultiContent"> {"template": [ - MultiContentEntryText(pos = (50, 1), size = (540, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state + MultiContentEntryText(pos = (50, 0), size = (150, 26), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name + MultiContentEntryText(pos = (50, 27), size = (540, 23), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap - MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap + MultiContentEntryPixmapAlphaTest(pos = (0, 48), size = (550, 2), png = 3), # index 3 is the div pixmap ], - "fonts": [gFont("Regular", 22),gFont("Regular", 18)], - "itemHeight": 52 + "fonts": [gFont("Regular", 24),gFont("Regular", 22)], + "itemHeight": 50 } </convert> </widget> - <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="550,2" transparent="1" alphatest="on" /> - <widget source="status" render="Label" position="5,420" zPosition="10" size="550,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" /> + <ePixmap pixmap="skin_default/div-h.png" position="0,404" zPosition="10" size="560,2" transparent="1" alphatest="on" /> + <widget source="status" render="Label" position="5,408" zPosition="10" size="550,44" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" /> </screen>""" def __init__(self, session, plugin_path): @@ -1401,7 +951,7 @@ class PluginDetails(Screen, DreamInfoHandler): self.onLayoutFinish.append(self.setInfos) def setWindowTitle(self): - self.setTitle(_("Package details for: " + self.pluginname)) + self.setTitle(_("Details for extension: " + self.pluginname)) def exit(self): self.close(False) @@ -1444,7 +994,7 @@ class PluginDetails(Screen, DreamInfoHandler): self["author"].setText(_("Author: ") + self.author) self["detailtext"].setText(self.description.strip()) - if self.pluginstate == 'installable': + if self.pluginstate in ('installable', 'install'): self["key_green"].setText(_("Install")) else: self["key_green"].setText(_("Remove")) @@ -1489,7 +1039,7 @@ class PluginDetails(Screen, DreamInfoHandler): if self.attributes.has_key("package"): self.packagefiles = self.attributes["package"] self.cmdList = [] - if self.pluginstate == 'installed': + if self.pluginstate in ('installed', 'remove'): if self.packagefiles: for package in self.packagefiles[:]: self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] })) @@ -1654,6 +1204,427 @@ class UpdatePlugin(Screen): self.close() + +class IPKGMenu(Screen): + skin = """ + <screen name="IPKGMenu" position="center,center" size="560,400" title="Select upgrade source to edit." > + <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> + <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" /> + <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> + <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" /> + <widget name="filelist" position="5,50" size="550,340" scrollbarMode="showOnDemand" /> + </screen>""" + + def __init__(self, session, plugin_path): + Screen.__init__(self, session) + self.skin_path = plugin_path + + self["key_red"] = StaticText(_("Close")) + self["key_green"] = StaticText(_("Edit")) + + self.sel = [] + self.val = [] + self.entry = False + self.exe = False + + self.path = "" + + self["actions"] = NumberActionMap(["SetupActions"], + { + "ok": self.KeyOk, + "cancel": self.keyCancel + }, -1) + + self["shortcuts"] = ActionMap(["ShortcutActions"], + { + "red": self.keyCancel, + "green": self.KeyOk, + }) + self.flist = [] + self["filelist"] = MenuList(self.flist) + self.fill_list() + self.onLayoutFinish.append(self.layoutFinished) + + def layoutFinished(self): + self.setWindowTitle() + + def setWindowTitle(self): + self.setTitle(_("Select upgrade source to edit.")) + + def fill_list(self): + self.flist = [] + self.path = '/etc/ipkg/' + if (os_path.exists(self.path) == False): + self.entry = False + return + for file in listdir(self.path): + if (file.endswith(".conf")): + if file != 'arch.conf': + self.flist.append((file)) + self.entry = True + self["filelist"].l.setList(self.flist) + + def KeyOk(self): + if (self.exe == False) and (self.entry == True): + self.sel = self["filelist"].getCurrent() + self.val = self.path + self.sel + self.session.open(IPKGSource, self.val) + + def keyCancel(self): + self.close() + + def Exit(self): + self.close() + + +class IPKGSource(Screen): + skin = """ + <screen name="IPKGSource" position="center,center" size="560,80" title="Edit upgrade source url." > + <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> + <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" /> + <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> + <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" /> + <widget name="text" position="5,50" size="550,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" /> + </screen>""" + + def __init__(self, session, configfile = None): + Screen.__init__(self, session) + self.session = session + self.configfile = configfile + text = "" + if self.configfile: + try: + fp = file(configfile, 'r') + sources = fp.readlines() + if sources: + text = sources[0] + fp.close() + except IOError: + pass + + desk = getDesktop(0) + x= int(desk.size().width()) + y= int(desk.size().height()) + + self["key_red"] = StaticText(_("Cancel")) + self["key_green"] = StaticText(_("Save")) + + if (y>=720): + self["text"] = Input(text, maxSize=False, type=Input.TEXT) + else: + self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT) + + self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"], + { + "ok": self.go, + "back": self.close, + "red": self.close, + "green": self.go, + "left": self.keyLeft, + "right": self.keyRight, + "home": self.keyHome, + "end": self.keyEnd, + "deleteForward": self.keyDeleteForward, + "deleteBackward": self.keyDeleteBackward, + "1": self.keyNumberGlobal, + "2": self.keyNumberGlobal, + "3": self.keyNumberGlobal, + "4": self.keyNumberGlobal, + "5": self.keyNumberGlobal, + "6": self.keyNumberGlobal, + "7": self.keyNumberGlobal, + "8": self.keyNumberGlobal, + "9": self.keyNumberGlobal, + "0": self.keyNumberGlobal + }, -1) + + self.onLayoutFinish.append(self.layoutFinished) + + def layoutFinished(self): + self.setWindowTitle() + self["text"].right() + + def setWindowTitle(self): + self.setTitle(_("Edit upgrade source url.")) + + def go(self): + text = self["text"].getText() + if text: + fp = file(self.configfile, 'w') + fp.write(text) + fp.write("\n") + fp.close() + self.close() + + def keyLeft(self): + self["text"].left() + + def keyRight(self): + self["text"].right() + + def keyHome(self): + self["text"].home() + + def keyEnd(self): + self["text"].end() + + def keyDeleteForward(self): + self["text"].delete() + + def keyDeleteBackward(self): + self["text"].deleteBackward() + + def keyNumberGlobal(self, number): + self["text"].number(number) + + +class PacketManager(Screen): + skin = """ + <screen name="PacketManager" position="center,center" size="530,420" title="Packet manager" > + <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> + <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" /> + <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> + <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" /> + <widget source="list" render="Listbox" position="5,50" size="520,365" scrollbarMode="showOnDemand"> + <convert type="TemplatedMultiContent"> + {"template": [ + MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name + MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description + MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap + MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap + ], + "fonts": [gFont("Regular", 22),gFont("Regular", 14)], + "itemHeight": 52 + } + </convert> + </widget> + </screen>""" + + def __init__(self, session, plugin_path, args = None): + Screen.__init__(self, session) + self.session = session + self.skin_path = plugin_path + + self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], + { + "ok": self.go, + "back": self.exit, + "red": self.exit, + "green": self.reload, + }, -1) + + self.list = [] + self.statuslist = [] + self["list"] = List(self.list) + self["key_red"] = StaticText(_("Close")) + self["key_green"] = StaticText(_("Reload")) + + self.list_updating = True + self.packetlist = [] + self.installed_packetlist = {} + self.Console = Console() + self.cmdList = [] + self.cachelist = [] + self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs) + self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory + self.oktext = _("\nAfter pressing OK, please wait!") + self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox') + + self.ipkg = IpkgComponent() + self.ipkg.addCallback(self.ipkgCallback) + self.onShown.append(self.setWindowTitle) + self.onLayoutFinish.append(self.rebuildList) + + def exit(self): + self.ipkg.stop() + if self.Console is not None: + if len(self.Console.appContainers): + for name in self.Console.appContainers.keys(): + self.Console.kill(name) + self.close() + + def reload(self): + if (os_path.exists(self.cache_file) == True): + remove(self.cache_file) + self.list_updating = True + self.rebuildList() + + def setWindowTitle(self): + self.setTitle(_("Packet manager")) + + def setStatus(self,status = None): + if status: + self.statuslist = [] + divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) + if status == 'update': + statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) + self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng )) + self['list'].setList(self.statuslist) + elif status == 'error': + statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) + self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng )) + self['list'].setList(self.statuslist) + + def rebuildList(self): + self.setStatus('update') + self.inv_cache = 0 + self.vc = valid_cache(self.cache_file, self.cache_ttl) + if self.cache_ttl > 0 and self.vc != 0: + try: + self.buildPacketList() + except: + self.inv_cache = 1 + if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: + self.run = 0 + self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) + + def go(self, returnValue = None): + cur = self["list"].getCurrent() + if cur: + status = cur[3] + package = cur[0] + self.cmdList = [] + if status == 'installed': + self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package })) + if len(self.cmdList): + self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext) + elif status == 'upgradeable': + self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package })) + if len(self.cmdList): + self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext) + elif status == "installable": + self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package })) + if len(self.cmdList): + self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext) + + def runRemove(self, result): + if result: + self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList) + + def runRemoveFinished(self): + self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) + + def RemoveReboot(self, result): + if result is None: + return + if result is False: + cur = self["list"].getCurrent() + if cur: + item = self['list'].getIndex() + self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable') + self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable'] + self['list'].setList(self.list) + write_cache(self.cache_file, self.cachelist) + self.reloadPluginlist() + if result: + quitMainloop(3) + + def runUpgrade(self, result): + if result: + self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList) + + def runUpgradeFinished(self): + self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) + + def UpgradeReboot(self, result): + if result is None: + return + if result is False: + cur = self["list"].getCurrent() + if cur: + item = self['list'].getIndex() + self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed') + self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed'] + self['list'].setList(self.list) + write_cache(self.cache_file, self.cachelist) + self.reloadPluginlist() + if result: + quitMainloop(3) + + def ipkgCallback(self, event, param): + if event == IpkgComponent.EVENT_ERROR: + self.list_updating = False + self.setStatus('error') + elif event == IpkgComponent.EVENT_DONE: + if self.list_updating: + self.list_updating = False + if not self.Console: + self.Console = Console() + cmd = "ipkg list" + self.Console.ePopen(cmd, self.IpkgList_Finished) + #print event, "-", param + pass + + def IpkgList_Finished(self, result, retval, extra_args = None): + if len(result): + self.packetlist = [] + for x in result.splitlines(): + split = x.split(' - ') #self.blacklisted_packages + if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): + self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()]) + if not self.Console: + self.Console = Console() + cmd = "ipkg list_installed" + self.Console.ePopen(cmd, self.IpkgListInstalled_Finished) + + def IpkgListInstalled_Finished(self, result, retval, extra_args = None): + if len(result): + self.installed_packetlist = {} + for x in result.splitlines(): + split = x.split(' - ') + if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): + self.installed_packetlist[split[0].strip()] = split[1].strip() + self.buildPacketList() + + def buildEntryComponent(self, name, version, description, state): + divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) + if state == 'installed': + installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) + return((name, version, description, state, installedpng, divpng)) + elif state == 'upgradeable': + upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgradeable.png")) + return((name, version, description, state, upgradeablepng, divpng)) + else: + installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) + return((name, version, description, state, installablepng, divpng)) + + def buildPacketList(self): + self.list = [] + self.cachelist = [] + + if self.cache_ttl > 0 and self.vc != 0: + print 'Loading packagelist cache from ',self.cache_file + try: + self.cachelist = load_cache(self.cache_file) + if len(self.cachelist) > 0: + for x in self.cachelist: + self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3])) + self['list'].setList(self.list) + except: + self.inv_cache = 1 + + if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: + print 'rebuilding fresh package list' + for x in self.packetlist: + status = "" + if self.installed_packetlist.has_key(x[0].strip()): + if self.installed_packetlist[x[0].strip()] == x[1].strip(): + status = "installed" + self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) + else: + status = "upgradeable" + self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) + else: + status = "installable" + self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) + if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions): + self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status]) + write_cache(self.cache_file, self.cachelist) + self['list'].setList(self.list) + + def reloadPluginlist(self): + plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) + class IpkgInstaller(Screen): skin = """ <screen name="IpkgInstaller" position="center,center" size="550,450" title="Install extensions" > @@ -1719,15 +1690,20 @@ def UpgradeMain(session, **kwargs): def startSetup(menuid): if menuid != "setup": return [ ] - return [(_("Software manager"), UpgradeMain, "software_manager", 50)] + return [(_("Software management"), UpgradeMain, "software_manager", 50)] + +def autostart(reason, **kwargs): + if reason is True: + iSoftwareTools.startSoftwareTools() def Plugins(path, **kwargs): global plugin_path plugin_path = path list = [ - PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup), + PluginDescriptor(where = [PluginDescriptor.WHERE_NETWORKCONFIG_READ], fnc = autostart), + PluginDescriptor(name=_("Software management"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup), PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan) ] if config.usage.setup_level.index >= 2: # expert+ - list.append(PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain)) + list.append(PluginDescriptor(name=_("Software management"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain)) return list diff --git a/lib/python/Plugins/SystemPlugins/Videomode/VideoWizard.py b/lib/python/Plugins/SystemPlugins/Videomode/VideoWizard.py index cd1529aa..512bcec3 100644 --- a/lib/python/Plugins/SystemPlugins/Videomode/VideoWizard.py +++ b/lib/python/Plugins/SystemPlugins/Videomode/VideoWizard.py @@ -131,8 +131,12 @@ class VideoWizard(WizardLanguage, Rc): def modeSelect(self, mode): ratesList = self.listRates(mode) print "ratesList:", ratesList - self.hw.setMode(port = self.port, mode = mode, rate = ratesList[0][0]) - + if self.port == "DVI" and mode in ("720p", "1080i"): + self.rate = "multi" + self.hw.setMode(port = self.port, mode = mode, rate = "multi") + else: + self.hw.setMode(port = self.port, mode = mode, rate = ratesList[0][0]) + def listRates(self, querymode = None): if querymode is None: querymode = self.mode diff --git a/lib/python/Plugins/SystemPlugins/Videomode/videowizard.xml b/lib/python/Plugins/SystemPlugins/Videomode/videowizard.xml index 29ac4297..5dea661d 100644 --- a/lib/python/Plugins/SystemPlugins/Videomode/videowizard.xml +++ b/lib/python/Plugins/SystemPlugins/Videomode/videowizard.xml @@ -20,7 +20,7 @@ self.selectKey("DOWN") self["portpic"].hide() </code> </step> - <step id="rateselection" nextstep="dvirateintroduction" timeout="20" timeoutaction="selectnext"> + <step id="rateselection" nextstep="end" timeout="20" timeoutaction="selectnext"> <condition> self.condition = (self.port != "DVI" or self.mode == "PC") </condition> @@ -33,7 +33,7 @@ self.selectKey("UP") self.selectKey("DOWN") </code> </step> - <step id="dvirateintroduction" nextstep="dvirateselection"> + <!--step id="dvirateintroduction" nextstep="dvirateselection"> <condition> self.condition = (self.port == "DVI" and self.mode in ["720p", "1080i"]) </condition> @@ -89,7 +89,7 @@ self.selectKey("UP") self.selectKey("DOWN") self.rateSelect("50Hz") </code> - </step> + </step--> <step id="end"> <code> self.hw.saveMode(self.port, self.mode, self.rate) diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py index 0432823b..5fbfd591 100644 --- a/lib/python/Screens/ChannelSelection.py +++ b/lib/python/Screens/ChannelSelection.py @@ -21,10 +21,13 @@ profile("ChannelSelection.py 2.3") from Components.Input import Input profile("ChannelSelection.py 3") from Components.ParentalControl import parentalControl +from Components.ChoiceList import ChoiceList, ChoiceEntryComponent +from Components.SystemInfo import SystemInfo from Screens.InputBox import InputBox, PinInput from Screens.MessageBox import MessageBox from Screens.ServiceInfo import ServiceInfo profile("ChannelSelection.py 4") +from Screens.PictureInPicture import PictureInPicture from Screens.RdsDisplay import RassInteractive from ServiceReference import ServiceReference from Tools.BoundFunction import boundFunction @@ -69,9 +72,9 @@ OFF = 0 EDIT_BOUQUET = 1 EDIT_ALTERNATIVES = 2 -def append_when_current_valid(current, menu, args, level = 0): +def append_when_current_valid(current, menu, args, level = 0, key = ""): if current and current.valid() and level <= config.usage.setup_level.index: - menu.append(args) + menu.append(ChoiceEntryComponent(key, args)) class ChannelContextMenu(Screen): def __init__(self, session, csel): @@ -80,13 +83,15 @@ class ChannelContextMenu(Screen): self.csel = csel self.bsel = None - self["actions"] = ActionMap(["OkCancelActions"], + self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "NumberActions"], { "ok": self.okbuttonClick, - "cancel": self.cancelClick + "cancel": self.cancelClick, + "blue": self.showServiceInPiP }) menu = [ ] + self.pipAvailable = False current = csel.getCurrentSelection() current_root = csel.getRoot() current_sel_path = current.getPath() @@ -122,8 +127,11 @@ class ChannelContextMenu(Screen): append_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService), level = 0) if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1: append_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag), level = 0) + if isPlayable and SystemInfo.get("NumVideoDecoders", 1) > 1: + append_when_current_valid(current, menu, (_("Activate Picture in Picture"), self.showServiceInPiP), level = 0, key = "blue") + self.pipAvailable = True else: - menu.append((_("add bouquet"), self.showBouquetInputBox)) + menu.append(ChoiceEntryComponent(text = (_("add bouquet"), self.showBouquetInputBox))) append_when_current_valid(current, menu, (_("remove entry"), self.removeBouquet), level = 0) if inBouquet: # current list is editable? @@ -131,7 +139,7 @@ class ChannelContextMenu(Screen): if not csel.movemode: append_when_current_valid(current, menu, (_("enable move mode"), self.toggleMoveMode), level = 1) if not inBouquetRootList and current_root and not (current_root.flags & eServiceReference.isGroup): - menu.append((_("add marker"), self.showMarkerInputBox)) + menu.append(ChoiceEntryComponent(text = (_("add marker"), self.showMarkerInputBox))) if haveBouquets: append_when_current_valid(current, menu, (_("enable bouquet edit"), self.bouquetMarkStart), level = 0) else: @@ -156,11 +164,11 @@ class ChannelContextMenu(Screen): append_when_current_valid(current, menu, (_("end alternatives edit"), self.bouquetMarkEnd), level = 0) append_when_current_valid(current, menu, (_("abort alternatives edit"), self.bouquetMarkAbort), level = 0) - menu.append((_("back"), self.cancelClick)) - self["menu"] = MenuList(menu) + menu.append(ChoiceEntryComponent(text = (_("back"), self.cancelClick))) + self["menu"] = ChoiceList(menu) def okbuttonClick(self): - self["menu"].getCurrent()[1]() + self["menu"].getCurrent()[0][1]() def cancelClick(self): self.close(False) @@ -189,6 +197,23 @@ class ChannelContextMenu(Screen): self.close() else: self.session.openWithCallback(self.close, MessageBox, _("The pin code you entered is wrong."), MessageBox.TYPE_ERROR) + + def showServiceInPiP(self): + if not self.pipAvailable: + return + if self.session.pipshown: + del self.session.pip + self.session.pip = self.session.instantiateDialog(PictureInPicture) + self.session.pip.show() + newservice = self.csel.servicelist.getCurrent() + if self.session.pip.playService(newservice): + self.session.pipshown = True + self.session.pip.servicePath = self.csel.getCurrentServicePath() + self.close(True) + else: + self.session.pipshown = False + del self.session.pip + self.session.openWithCallback(self.close, MessageBox, _("Could not open Picture in Picture"), MessageBox.TYPE_ERROR) def addServiceToBouquetSelected(self): bouquets = self.csel.getBouquetList() @@ -648,7 +673,11 @@ class ChannelSelectionEdit: self.entry_marked = True def doContext(self): - self.session.open(ChannelContextMenu, self) + self.session.openWithCallback(self.exitContext, ChannelContextMenu, self) + + def exitContext(self, close = False): + if close: + self.cancel() MODE_TV = 0 MODE_RADIO = 1 diff --git a/lib/python/Screens/InfoBar.py b/lib/python/Screens/InfoBar.py index a15c7ac1..5b061245 100644 --- a/lib/python/Screens/InfoBar.py +++ b/lib/python/Screens/InfoBar.py @@ -12,7 +12,7 @@ profile("LOAD:InfoBarGenerics") from Screens.InfoBarGenerics import InfoBarShowHide, \ InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarRdsDecoder, \ InfoBarEPG, InfoBarSeek, InfoBarInstantRecord, \ - InfoBarAudioSelection, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, \ + InfoBarAudioSelection, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, InfoBarUnhandledKey, \ InfoBarSubserviceSelection, InfoBarShowMovies, InfoBarTimeshift, \ InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarSimpleEventView, \ InfoBarSummarySupport, InfoBarMoviePlayerSummarySupport, InfoBarTimeshiftState, InfoBarTeletextPlugin, InfoBarExtensions, \ @@ -29,7 +29,7 @@ from Screens.HelpMenu import HelpableScreen class InfoBar(InfoBarBase, InfoBarShowHide, InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG, InfoBarRdsDecoder, InfoBarInstantRecord, InfoBarAudioSelection, - HelpableScreen, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, + HelpableScreen, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, InfoBarUnhandledKey, InfoBarSubserviceSelection, InfoBarTimeshift, InfoBarSeek, InfoBarSummarySupport, InfoBarTimeshiftState, InfoBarTeletextPlugin, InfoBarExtensions, InfoBarPiP, InfoBarPlugins, InfoBarSubtitleSupport, InfoBarServiceErrorPopupSupport, InfoBarJobman, @@ -52,7 +52,7 @@ class InfoBar(InfoBarBase, InfoBarShowHide, for x in HelpableScreen, \ InfoBarBase, InfoBarShowHide, \ InfoBarNumberZap, InfoBarChannelSelection, InfoBarMenu, InfoBarEPG, InfoBarRdsDecoder, \ - InfoBarInstantRecord, InfoBarAudioSelection, \ + InfoBarInstantRecord, InfoBarAudioSelection, InfoBarUnhandledKey, \ InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, InfoBarSubserviceSelection, \ InfoBarTimeshift, InfoBarSeek, InfoBarSummarySupport, InfoBarTimeshiftState, \ InfoBarTeletextPlugin, InfoBarExtensions, InfoBarPiP, InfoBarSubtitleSupport, InfoBarJobman, \ diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index a3e56a40..7ae0b123 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -26,13 +26,14 @@ from Screens.PictureInPicture import PictureInPicture from Screens.SubtitleDisplay import SubtitleDisplay from Screens.RdsDisplay import RdsInfoDisplay, RassInteractive from Screens.TimeDateInput import TimeDateInput +from Screens.UnhandledKey import UnhandledKey from ServiceReference import ServiceReference from Tools import Notifications from Tools.Directories import fileExists from enigma import eTimer, eServiceCenter, eDVBServicePMTHandler, iServiceInformation, \ - iPlayableService, eServiceReference, eEPGCache + iPlayableService, eServiceReference, eEPGCache, eActionMap from time import time, localtime, strftime from os import stat as os_stat @@ -47,6 +48,39 @@ class InfoBarDish: def __init__(self): self.dishDialog = self.session.instantiateDialog(Dish) +class InfoBarUnhandledKey: + def __init__(self): + self.unhandledKeyDialog = self.session.instantiateDialog(UnhandledKey) + self.hideUnhandledKeySymbolTimer = eTimer() + self.hideUnhandledKeySymbolTimer.callback.append(self.unhandledKeyDialog.hide) + self.checkUnusedTimer = eTimer() + self.checkUnusedTimer.callback.append(self.checkUnused) + self.onLayoutFinish.append(self.unhandledKeyDialog.hide) + eActionMap.getInstance().bindAction('', -0x7FFFFFFF, self.actionA) #highest prio + eActionMap.getInstance().bindAction('', 0x7FFFFFFF, self.actionB) #lowest prio + self.flags = (1<<1); + self.uflags = 0; + + #this function is called on every keypress! + def actionA(self, key, flag): + if flag != 4: + if self.flags & (1<<1): + self.flags = self.uflags = 0 + self.flags |= (1<<flag) + if flag == 1: # break + self.checkUnusedTimer.start(0, True) + return 0 + + #this function is only called when no other action has handled this key + def actionB(self, key, flag): + if flag != 4: + self.uflags |= (1<<flag) + + def checkUnused(self): + if self.flags == self.uflags: + self.unhandledKeyDialog.show() + self.hideUnhandledKeySymbolTimer.start(2000, True) + class InfoBarShowHide: """ InfoBar show/hide control, accepts toggleShow and hide actions, might start fancy animations. """ @@ -691,6 +725,7 @@ class InfoBarSeek: iPlayableService.evEOF: self.__evEOF, iPlayableService.evSOF: self.__evSOF, }) + self.fast_winding_hint_message_showed = False class InfoBarSeekActionMap(HelpableActionMap): def __init__(self, screen, *args, **kwargs): @@ -817,6 +852,7 @@ class InfoBarSeek: # print "seekable" def __serviceStarted(self): + self.fast_winding_hint_message_showed = False self.seekstate = self.SEEK_STATE_PLAY self.__seekableStatusChanged() @@ -907,6 +943,13 @@ class InfoBarSeek: self.showAfterSeek() def seekFwd(self): + seek = self.getSeek() + if seek and not (seek.isCurrentlySeekable() & 2): + if not self.fast_winding_hint_message_showed and (seek.isCurrentlySeekable() & 1): + self.session.open(MessageBox, _("No fast winding possible yet.. but you can use the number buttons to skip forward/backward!"), MessageBox.TYPE_INFO, timeout=10) + self.fast_winding_hint_message_showed = True + return + return 0 # trade as unhandled action if self.seekstate == self.SEEK_STATE_PLAY: self.setSeekState(self.makeStateForward(int(config.seek.enter_forward.value))) elif self.seekstate == self.SEEK_STATE_PAUSE: @@ -936,6 +979,13 @@ class InfoBarSeek: self.setSeekState(self.makeStateSlowMotion(speed)) def seekBack(self): + seek = self.getSeek() + if seek and not (seek.isCurrentlySeekable() & 2): + if not self.fast_winding_hint_message_showed and (seek.isCurrentlySeekable() & 1): + self.session.open(MessageBox, _("No fast winding possible yet.. but you can use the number buttons to skip forward/backward!"), MessageBox.TYPE_INFO, timeout=10) + self.fast_winding_hint_message_showed = True + return + return 0 # trade as unhandled action seekstate = self.seekstate if seekstate == self.SEEK_STATE_PLAY: self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value))) diff --git a/lib/python/Screens/Makefile.am b/lib/python/Screens/Makefile.am index 585983c2..5457bf64 100755 --- a/lib/python/Screens/Makefile.am +++ b/lib/python/Screens/Makefile.am @@ -14,5 +14,5 @@ install_PYTHON = \ SubtitleDisplay.py SubservicesQuickzap.py ParentalControlSetup.py NumericalTextInputHelpDialog.py \ SleepTimerEdit.py Ipkg.py RdsDisplay.py Globals.py DefaultWizard.py \ SessionGlobals.py LocationBox.py WizardLanguage.py TaskView.py Rc.py VirtualKeyBoard.py \ - TextBox.py FactoryReset.py RecordPaths.py + TextBox.py FactoryReset.py RecordPaths.py UnhandledKey.py diff --git a/lib/python/Screens/PluginBrowser.py b/lib/python/Screens/PluginBrowser.py index 61bb7d0a..cce08aed 100755 --- a/lib/python/Screens/PluginBrowser.py +++ b/lib/python/Screens/PluginBrowser.py @@ -9,7 +9,7 @@ from Components.Label import Label from Screens.MessageBox import MessageBox from Screens.Console import Console from Plugins.Plugin import PluginDescriptor -from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE +from Tools.Directories import resolveFilename, fileExists, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE from Tools.LoadPixmap import LoadPixmap from time import time @@ -22,19 +22,23 @@ class PluginBrowser(Screen): def __init__(self, session): Screen.__init__(self, session) - self["red"] = Label(_("Remove Plugins")) - self["green"] = Label(_("Download Plugins")) + self["red"] = Label() + self["green"] = Label() self.list = [] self["list"] = PluginList(self.list) - self["actions"] = ActionMap(["WizardActions", "ColorActions"], + self["actions"] = ActionMap(["WizardActions"], { "ok": self.save, "back": self.close, + }) + self["PluginDownloadActions"] = ActionMap(["ColorActions"], + { "red": self.delete, "green": self.download }) + self["PluginDownloadActions"].setEnabled(False) self.onFirstExecBegin.append(self.checkWarnings) self.onShown.append(self.updateList) @@ -47,7 +51,6 @@ class PluginBrowser(Screen): self.session.open(MessageBox, text = text, type = MessageBox.TYPE_WARNING) def save(self): - #self.close() self.run() def run(self): @@ -58,7 +61,15 @@ class PluginBrowser(Screen): self.pluginlist = plugins.getPlugins(PluginDescriptor.WHERE_PLUGINMENU) self.list = [PluginEntryComponent(plugin) for plugin in self.pluginlist] self["list"].l.setList(self.list) - + if fileExists(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/plugin.py")): + self["red"].setText("") + self["green"].setText("") + self["PluginDownloadActions"].setEnabled(False) + else: + self["red"].setText(_("Remove Plugins")) + self["green"].setText(_("Download Plugins")) + self["PluginDownloadActions"].setEnabled(True) + def delete(self): self.session.openWithCallback(self.PluginDownloadBrowserClosed, PluginDownloadBrowser, PluginDownloadBrowser.REMOVE) diff --git a/lib/python/Screens/Satconfig.py b/lib/python/Screens/Satconfig.py index e24e4636..d5249b99 100644 --- a/lib/python/Screens/Satconfig.py +++ b/lib/python/Screens/Satconfig.py @@ -5,7 +5,8 @@ from Components.ActionMap import ActionMap from Components.ConfigList import ConfigListScreen from Components.MenuList import MenuList from Components.NimManager import nimmanager -from Components.config import getConfigListEntry, config, ConfigNothing, ConfigSelection, updateConfigElement +from Components.config import getConfigListEntry, config, ConfigNothing, ConfigSelection, updateConfigElement,\ + ConfigSatlist from Components.Sources.List import List from Screens.MessageBox import MessageBox from Screens.ChoiceBox import ChoiceBox @@ -145,6 +146,8 @@ class NimSetup(Screen, ConfigListScreen): currSat = self.nimConfig.advanced.sat[cur_orb_pos] self.fillListWithAdvancedSatEntrys(currSat) self.have_advanced = True + if self.nim.description == "Alps BSBE2" and config.usage.setup_level.index >= 2: # expert + self.list.append(getConfigListEntry(_("Tone Amplitude"), self.nimConfig.toneAmplitude)) elif self.nim.isCompatible("DVB-C"): self.configMode = getConfigListEntry(_("Configuration Mode"), self.nimConfig.configMode) self.list.append(self.configMode) @@ -381,10 +384,11 @@ class NimSetup(Screen, ConfigListScreen): ConfigListScreen.__init__(self, self.list) - self["actions"] = ActionMap(["SetupActions"], + self["actions"] = ActionMap(["SetupActions", "SatlistShortcutAction"], { "ok": self.keySave, "cancel": self.keyCancel, + "nothingconnected": self.nothingConnectedShortcut }, -2) self.slotid = slotid @@ -421,6 +425,11 @@ class NimSetup(Screen, ConfigListScreen): # we need to call saveAll to reset the connectedTo choices self.saveAll() self.close() + + def nothingConnectedShortcut(self): + if type(self["config"].getCurrent()[1]) is ConfigSatlist: + self["config"].getCurrent()[1].setValue("3601") + self["config"].invalidateCurrent() class NimSelection(Screen): def __init__(self, session): diff --git a/lib/python/Screens/UnhandledKey.py b/lib/python/Screens/UnhandledKey.py new file mode 100644 index 00000000..63bfed5b --- /dev/null +++ b/lib/python/Screens/UnhandledKey.py @@ -0,0 +1,7 @@ +from Screen import Screen +from Components.Pixmap import Pixmap + +class UnhandledKey(Screen): + def __init__(self, session): + Screen.__init__(self, session) + self["UnhandledKeyPixmap"] = Pixmap() diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index a6b6cc6f..69329ce0 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1029,6 +1029,9 @@ void eDVBServicePlay::serviceEvent(int event) m_event((iPlayableService*)this, evUpdatedInfo); break; } + case eDVBServicePMTHandler::eventPreStart: + loadCuesheet(); + break; case eDVBServicePMTHandler::eventEOF: m_event((iPlayableService*)this, evEOF); break; @@ -1095,7 +1098,6 @@ RESULT eDVBServicePlay::start() m_event_handler.inject(event, 0); m_event_handler.inject(empty, 1); } - loadCuesheet(); m_event(this, evStart); } return 0; @@ -1385,7 +1387,14 @@ RESULT eDVBServicePlay::setTrickmode(int trick) RESULT eDVBServicePlay::isCurrentlySeekable() { - return m_is_pvr || m_timeshift_active; + int ret = 0; + if (m_decoder) + { + ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible + if (m_decoder->getVideoWidth() == -1) + ret &= ~2; + } + return ret; } RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr) diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 47511f78..2c84f7be 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -659,7 +659,31 @@ RESULT eServiceMP3::setTrickmode(int trick) RESULT eServiceMP3::isCurrentlySeekable() { - return 1; + int ret = 3; // seeking and fast/slow winding possible + GstElement *sink; + + if (!m_gst_playbin) + return 0; + if (m_state != stRunning) + return 0; + + g_object_get (G_OBJECT (m_gst_playbin), "video-sink", &sink, NULL); + + // disable fast winding yet when a dvbvideosink or dvbaudiosink is used + // for this we must do some changes on different places.. (gstreamer.. our sinks.. enigma2) + if (sink) { + ret &= ~2; // only seeking possible + gst_object_unref(sink); + } + else { + g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL); + if (sink) { + ret &= ~2; // only seeking possible + gst_object_unref(sink); + } + } + + return ret; } RESULT eServiceMP3::info(ePtr<iServiceInformation>&i) diff --git a/lib/service/servicexine.cpp b/lib/service/servicexine.cpp index 44e6a6e0..6b9adfb9 100644 --- a/lib/service/servicexine.cpp +++ b/lib/service/servicexine.cpp @@ -315,7 +315,7 @@ RESULT eServiceXine::setTrickmode(int trick) RESULT eServiceXine::isCurrentlySeekable() { - return 1; + return 3; } RESULT eServiceXine::info(ePtr<iServiceInformation>&i) diff --git a/tools/genmetaindex.py b/tools/genmetaindex.py index 82e79616..f7dc5b98 100755 --- a/tools/genmetaindex.py +++ b/tools/genmetaindex.py @@ -24,7 +24,7 @@ for file in sys.argv[2:]: assert info for i in info[:]: - if i.tag not in ["name", "packagename", "shortdescription"]: + if i.tag not in ["name", "packagename", "packagetype", "shortdescription"]: info.remove(i) for i in info[:]: |
