Merge branch 'master' into tmbinc/FixTimingBugs
authorFelix Domke <tmbinc@elitedvb.net>
Mon, 17 Nov 2008 14:42:54 +0000 (15:42 +0100)
committerFelix Domke <tmbinc@elitedvb.net>
Mon, 17 Nov 2008 14:42:54 +0000 (15:42 +0100)
Conflicts:

lib/dvb/sec.cpp
lib/python/Components/Network.py
lib/python/Components/Playlist.py
lib/python/Plugins/Extensions/DVDBurn/Process.py
lib/python/Plugins/Extensions/MediaPlayer/plugin.py
lib/python/Screens/TimerEdit.py
po/lt.po
po/nl.po
po/tr.po

115 files changed:
Navigation.py
RecordTimer.py
data/countries/ua.png [new file with mode: 0644]
data/keymap.xml
data/menu.xml
data/skin_default.xml [changed mode: 0644->0755]
data/skin_default/vkey_backspace.png [new file with mode: 0755]
data/skin_default/vkey_bg.png [new file with mode: 0755]
data/skin_default/vkey_clr.png [new file with mode: 0755]
data/skin_default/vkey_esc.png [new file with mode: 0755]
data/skin_default/vkey_icon.png [new file with mode: 0755]
data/skin_default/vkey_left.png [new file with mode: 0755]
data/skin_default/vkey_ok.png [new file with mode: 0755]
data/skin_default/vkey_right.png [new file with mode: 0755]
data/skin_default/vkey_sel.png [new file with mode: 0755]
data/skin_default/vkey_shift.png [new file with mode: 0755]
data/skin_default/vkey_shift_sel.png [new file with mode: 0755]
data/skin_default/vkey_space.png [new file with mode: 0755]
data/skin_default/vkey_text.png [new file with mode: 0755]
e2reactor.py
lib/dvb/db.cpp
lib/dvb/decoder.cpp
lib/dvb/dvb.cpp
lib/dvb/dvb.h
lib/dvb/frontend.cpp
lib/dvb/idvb.h
lib/dvb/pmt.cpp
lib/dvb/pmt.h
lib/dvb/pvrparse.cpp
lib/dvb/scan.cpp
lib/dvb/sec.cpp
lib/dvb/sec.h
lib/gdi/lcd.cpp
lib/gdi/picload.cpp
lib/gdi/picload.h
lib/gui/epositiongauge.cpp
lib/python/Components/HelpMenuList.py [changed mode: 0644->0755]
lib/python/Components/Language.py
lib/python/Components/Lcd.py
lib/python/Components/MediaPlayer.py
lib/python/Components/MovieList.py
lib/python/Components/Network.py [changed mode: 0644->0755]
lib/python/Components/NimManager.py
lib/python/Components/Playlist.py
lib/python/Components/TimerSanityCheck.py
lib/python/Components/UsageConfig.py
lib/python/Components/config.py [changed mode: 0644->0755]
lib/python/Plugins/DemoPlugins/TestPlugin/Makefile.am
lib/python/Plugins/DemoPlugins/TestPlugin/maintainer.info [new file with mode: 0644]
lib/python/Plugins/DemoPlugins/TestPlugin/plugin.py
lib/python/Plugins/Extensions/DVDBurn/DVDProject.py
lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py
lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py
lib/python/Plugins/Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml
lib/python/Plugins/Extensions/DVDBurn/Makefile.am
lib/python/Plugins/Extensions/DVDBurn/Process.py
lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py
lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py
lib/python/Plugins/Extensions/DVDBurn/TitleList.py
lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py [new file with mode: 0644]
lib/python/Plugins/Extensions/DVDBurn/keymap.xml
lib/python/Plugins/Extensions/DVDBurn/plugin.py
lib/python/Plugins/Extensions/DVDPlayer/plugin.py
lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py
lib/python/Plugins/Extensions/MediaPlayer/Makefile.am
lib/python/Plugins/Extensions/MediaPlayer/plugin.py
lib/python/Plugins/Extensions/MediaPlayer/settings.py [new file with mode: 0644]
lib/python/Plugins/Extensions/PicturePlayer/plugin.py
lib/python/Plugins/Plugin.py
lib/python/Plugins/SystemPlugins/Hotplug/plugin.py
lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/plugin.py
lib/python/Screens/InfoBarGenerics.py
lib/python/Screens/InputBox.py
lib/python/Screens/LocationBox.py
lib/python/Screens/Makefile.am [changed mode: 0644->0755]
lib/python/Screens/MovieSelection.py
lib/python/Screens/NetworkSetup.py [changed mode: 0644->0755]
lib/python/Screens/Satconfig.py
lib/python/Screens/ScanSetup.py
lib/python/Screens/TimerEdit.py
lib/python/Screens/TimerEntry.py
lib/python/Screens/VirtualKeyBoard.py [new file with mode: 0755]
lib/python/Screens/Wizard.py
lib/python/enigma_python.i
lib/service/iservice.h
lib/service/service.cpp
lib/service/servicedvb.cpp
lib/service/servicedvb.h
main/bsod.cpp
mytest.py
po/Makefile.am
po/ar.po
po/ca.po
po/cs.po
po/da.po
po/de.po [changed mode: 0644->0755]
po/el.po
po/en.po
po/enigma2.pot
po/es.po
po/fi.po
po/fr.po
po/hr.po
po/hu.po
po/is.po [changed mode: 0755->0644]
po/it.po
po/lt.po
po/nl.po
po/no.po
po/pl.po
po/pt.po
po/ru.po
po/sv.po [changed mode: 0755->0644]
po/tr.po
po/uk.po [new file with mode: 0644]

index bda6f58..42733cb 100644 (file)
@@ -79,14 +79,14 @@ class Navigation:
        def getCurrentlyPlayingServiceReference(self):
                return self.currentlyPlayingServiceReference
        
-       def recordService(self, ref):
+       def recordService(self, ref, simulate=False):
                service = None
                print "recording service: %s" % (str(ref))
                if isinstance(ref, ServiceReference.ServiceReference):
                        ref = ref.ref
                if ref:
                        if ref.flags & eServiceReference.isGroup:
-                               ref = getBestPlayableServiceReference(ref, eServiceReference())
+                               ref = getBestPlayableServiceReference(ref, eServiceReference(), simulate)
                        service = ref and self.pnav and self.pnav.recordService(ref)
                        if service is None:
                                print "record returned non-zero"
index 397ff8a..28b878a 100644 (file)
@@ -91,7 +91,7 @@ class RecordTimerEntry(timer.TimerEntry, object):
                        Notifications.AddNotification(Screens.Standby.TryQuitMainloop, 1, onSessionOpenCallback=RecordTimerEntry.stopTryQuitMainloop, default_yes = default_yes)
 #################################################################
 
-       def __init__(self, serviceref, begin, end, name, description, eit, disabled = False, justplay = False, afterEvent = AFTEREVENT.NONE, checkOldTimers = False, dirname = None):
+       def __init__(self, serviceref, begin, end, name, description, eit, disabled = False, justplay = False, afterEvent = AFTEREVENT.NONE, checkOldTimers = False, dirname = None, tags = None):
                timer.TimerEntry.__init__(self, int(begin), int(end))
 
                if checkOldTimers == True:
@@ -117,6 +117,7 @@ class RecordTimerEntry(timer.TimerEntry, object):
                self.dirname = dirname
                self.dirnameHadToFallback = False
                self.autoincrease = False
+               self.tags = tags or []
 
                self.log_entries = []
                self.resetState()
@@ -192,6 +193,7 @@ class RecordTimerEntry(timer.TimerEntry, object):
                                f.write(self.name + "\n")
                                f.write(self.description + "\n")
                                f.write(str(self.begin) + "\n")
+                               f.write(' '.join(self.tags))
                                f.close()
                        except IOError:
                                self.log(4, "failed to write meta information")
@@ -368,10 +370,14 @@ def createTimer(xml):
                location = xml.getAttribute("location").encode("utf-8")
        else:
                location = None
+       if xml.hasAttribute("tags") and xml.getAttribute("tags"):
+               tags = xml.getAttribute("tags").encode("utf-8").split(' ')
+       else:
+               tags = None
 
        name = xml.getAttribute("name").encode("utf-8")
        #filename = xml.getAttribute("filename").encode("utf-8")
-       entry = RecordTimerEntry(serviceref, begin, end, name, description, eit, disabled, justplay, afterevent, dirname = location)
+       entry = RecordTimerEntry(serviceref, begin, end, name, description, eit, disabled, justplay, afterevent, dirname = location, tags = tags)
        entry.repeated = int(repeated)
        
        for l in elementsWithTag(xml.childNodes, "log"):
@@ -492,6 +498,8 @@ class RecordTimer(timer.Timer):
                                list.append(' eit="' + str(timer.eit) + '"')
                        if timer.dirname is not None:
                                list.append(' location="' + str(stringToXML(timer.dirname)) + '"')
+                       if timer.tags is not None:
+                               list.append(' tags="' + str(stringToXML(' '.join(timer.tags))) + '"')
                        list.append(' disabled="' + str(int(timer.disabled)) + '"')
                        list.append(' justplay="' + str(int(timer.justplay)) + '"')
                        list.append('>\n')
diff --git a/data/countries/ua.png b/data/countries/ua.png
new file mode 100644 (file)
index 0000000..fa8751e
Binary files /dev/null and b/data/countries/ua.png differ
index 5e73490..6b8b583 100644 (file)
@@ -77,8 +77,8 @@
        </map>
 
        <map context="InfobarEPGActions">
-               <key id="KEY_INFO" mapto="showEventInfo" flags="b" />
-               <key id="KEY_INFO" mapto="showSingleServiceEPG" flags="l" />
+               <key id="KEY_INFO" mapto="showEventView" flags="b" />
+               <key id="KEY_INFO" mapto="showEventInfoPlugin" flags="l" />
        </map>
        
        <map context="InfobarInstantRecord">
index 93455b2..369b20e 100644 (file)
@@ -70,6 +70,7 @@
                                        <item level="1" text="Device Setup..." entryID="device_setup"><screen module="NetworkSetup" screen="NetworkAdapterSelection"/></item>
                                        <item level="1" text="Nameserver Setup..." entryID="dns_setup"><screen module="NetworkSetup" screen="NameserverSetup"/></item>
                                </menu>-->
+                               <item level="2" text="Timeshift path..." entryId="timeshift_path"><screen module="LocationBox" screen="TimeshiftLocationBox" /></item>
                        </menu>
                        <item level="1" text="Common Interface" entryID="ci_setup" requires="CommonInterface"><screen module="Ci" screen="CiSelection" /></item>
                        <item level="0" text="Parental control" entryID="parental_setup"><screen module="ParentalControlSetup" screen="ParentalControlSetup" /></item>
old mode 100644 (file)
new mode 100755 (executable)
index 88cf8b4..993fd32
                <widget name="BottomBG" pixmap="skin_default/bottombar.png" position="5,310" size="540,120" zPosition="1" transparent="1" alphatest="on" />
                <widget name="Adaptertext" position="20,325" size="100,21" zPosition="10" font="Regular;19" transparent="1" />
                <widget name="Adapter" position="110,325" size="300,21" zPosition="10" font="Regular;19" transparent="1" />
-               <widget name="introduction2" position="110,360" size="300,20" zPosition="10" font="Regular;21" halign="center" transparent="1" />
+               <widget name="introduction2" position="90,360" size="300,20" zPosition="10" font="Regular;21" halign="center" transparent="1" />
                <widget name="ButtonRedtext" position="410,325" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
                <widget name="ButtonRed" pixmap="skin_default/buttons/button_red.png" position="390,325" zPosition="10" size="15,16" transparent="1" alphatest="on" />
                <widget name="ButtonBluetext" position="410,360" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
                <widget name="ButtonBlue" pixmap="skin_default/buttons/button_blue.png" position="390,360" zPosition="10" size="15,16" transparent="1" alphatest="on" />
+               <widget name="ButtonGreen" pixmap="skin_default/buttons/button_green.png" position="20,360" zPosition="10" size="15,16" transparent="1" alphatest="on" />
+               <widget name="VKeyIcon" pixmap="skin_default/vkey_icon.png" position="35,340" zPosition="10" size="60,48" transparent="1" alphatest="on" />
+               <widget name="HelpWindow" pixmap="skin_default/vkey_icon.png" position="120,245" zPosition="1" size="1,1" transparent="1" alphatest="on" />     
        </screen>
        <screen name="AdapterSetupConfiguration" position="90,100" size="550,400" title="Network Configuration..." >
                <ePixmap pixmap="skin_default/border_menu.png" position="10,10" zPosition="1" size="250,300" transparent="1" alphatest="on" />
@@ -568,7 +571,7 @@ self.instance.move(ePoint(orgpos.x() + (orgwidth - newwidth)/2, orgpos.y()))
                <widget name="ButtonRedtext" position="430,325" size="120,21" zPosition="10" font="Regular;21" transparent="1" />
                <ePixmap pixmap="skin_default/buttons/button_red.png" position="410,325" zPosition="10" size="15,16" transparent="1" alphatest="on" />
                <widget name="ButtonBluetext" position="60,325" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
-               <ePixmap pixmap="skin_default/buttons/button_blue.png" position="30,325" zPosition="10" size="15,16" transparent="1" alphatest="on" />
+               <widget name="ButtonBlue" pixmap="skin_default/buttons/button_blue.png" position="30,325" zPosition="10" size="15,16" transparent="1" alphatest="on" />
                <widget name="introduction" position="140,360" size="300,21" zPosition="10" font="Regular;21" halign="center" transparent="1" />
        </screen>
        <!-- Network adapter test Black = "#000000" Grey = "#8c8c93" Green = "#1cff1c" Red = #f23d21-->
@@ -1157,4 +1160,10 @@ self.instance.move(ePoint(orgpos.x() + (orgwidth - newwidth)/2, orgpos.y()))
                        <convert type="ProgressToText" />
                </widget>
        </screen>
+       <screen name="VirtualKeyBoard" position="80,150" size="560,350" zPosition="99" title="Virtual KeyBoard">
+               <ePixmap pixmap="skin_default/vkey_text.png" position="9,35" zPosition="-4" size="542,52" alphatest="on" />
+               <widget name="header" position="10,10" size="500,20" font="Regular;20" transparent="1" noWrap="1" />
+               <widget name="text" position="12,35" size="536,46" font="Regular;46" transparent="1" noWrap="1" halign="right" />
+               <widget name="list" position="10,100" size="540,225" selectionDisabled="1" transparent="1" />
+       </screen>
 </skin>
diff --git a/data/skin_default/vkey_backspace.png b/data/skin_default/vkey_backspace.png
new file mode 100755 (executable)
index 0000000..ed49159
Binary files /dev/null and b/data/skin_default/vkey_backspace.png differ
diff --git a/data/skin_default/vkey_bg.png b/data/skin_default/vkey_bg.png
new file mode 100755 (executable)
index 0000000..5151da4
Binary files /dev/null and b/data/skin_default/vkey_bg.png differ
diff --git a/data/skin_default/vkey_clr.png b/data/skin_default/vkey_clr.png
new file mode 100755 (executable)
index 0000000..0c7734b
Binary files /dev/null and b/data/skin_default/vkey_clr.png differ
diff --git a/data/skin_default/vkey_esc.png b/data/skin_default/vkey_esc.png
new file mode 100755 (executable)
index 0000000..56c52d3
Binary files /dev/null and b/data/skin_default/vkey_esc.png differ
diff --git a/data/skin_default/vkey_icon.png b/data/skin_default/vkey_icon.png
new file mode 100755 (executable)
index 0000000..f27b7f8
Binary files /dev/null and b/data/skin_default/vkey_icon.png differ
diff --git a/data/skin_default/vkey_left.png b/data/skin_default/vkey_left.png
new file mode 100755 (executable)
index 0000000..2e77e71
Binary files /dev/null and b/data/skin_default/vkey_left.png differ
diff --git a/data/skin_default/vkey_ok.png b/data/skin_default/vkey_ok.png
new file mode 100755 (executable)
index 0000000..2c0c7e8
Binary files /dev/null and b/data/skin_default/vkey_ok.png differ
diff --git a/data/skin_default/vkey_right.png b/data/skin_default/vkey_right.png
new file mode 100755 (executable)
index 0000000..fefb17c
Binary files /dev/null and b/data/skin_default/vkey_right.png differ
diff --git a/data/skin_default/vkey_sel.png b/data/skin_default/vkey_sel.png
new file mode 100755 (executable)
index 0000000..b612b94
Binary files /dev/null and b/data/skin_default/vkey_sel.png differ
diff --git a/data/skin_default/vkey_shift.png b/data/skin_default/vkey_shift.png
new file mode 100755 (executable)
index 0000000..477f8db
Binary files /dev/null and b/data/skin_default/vkey_shift.png differ
diff --git a/data/skin_default/vkey_shift_sel.png b/data/skin_default/vkey_shift_sel.png
new file mode 100755 (executable)
index 0000000..339ddb4
Binary files /dev/null and b/data/skin_default/vkey_shift_sel.png differ
diff --git a/data/skin_default/vkey_space.png b/data/skin_default/vkey_space.png
new file mode 100755 (executable)
index 0000000..5151da4
Binary files /dev/null and b/data/skin_default/vkey_space.png differ
diff --git a/data/skin_default/vkey_text.png b/data/skin_default/vkey_text.png
new file mode 100755 (executable)
index 0000000..6bdb8c8
Binary files /dev/null and b/data/skin_default/vkey_text.png differ
index a3d8ce1..cca2f35 100644 (file)
@@ -36,7 +36,10 @@ class E2SharedPoll:
                del self.dict[fd]
        
        def poll(self, timeout = None):
-               r = self.eApp.poll(timeout, self.dict)
+               try:
+                       r = self.eApp.poll(timeout, self.dict)
+               except KeyboardInterrupt:
+                       return None
                return r
 
 poller = E2SharedPoll()
index 02ecc1d..1c33203 100644 (file)
@@ -151,7 +151,7 @@ RESULT eDVBService::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &
        return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
 }
 
-int eDVBService::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
+int eDVBService::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
 {
        ePtr<eDVBResourceManager> res_mgr;
        if ( eDVBResourceManager::getInstance( res_mgr ) )
@@ -161,7 +161,7 @@ int eDVBService::isPlayable(const eServiceReference &ref, const eServiceReferenc
                eDVBChannelID chid, chid_ignore;
                ((const eServiceReferenceDVB&)ref).getChannelID(chid);
                ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
-               return res_mgr->canAllocateChannel(chid, chid_ignore);
+               return res_mgr->canAllocateChannel(chid, chid_ignore, simulate);
        }
        return 0;
 }
@@ -497,7 +497,7 @@ void eDVBDB::saveServicelist(const char *file)
                {
                        if (sat.system == eDVBFrontendParametersSatellite::System::DVB_S2)
                        {
-                               fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+                               fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
                                        sat.frequency, sat.symbol_rate,
                                        sat.polarisation, sat.fec,
                                        sat.orbital_position > 1800 ? sat.orbital_position - 3600 : sat.orbital_position,
@@ -505,11 +505,8 @@ void eDVBDB::saveServicelist(const char *file)
                                        flags,
                                        sat.system,
                                        sat.modulation,
-                                       sat.rolloff);
-                               if (sat.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK)
-                                       fprintf(f, ":%d\n", sat.pilot);
-                               else
-                                       fprintf(f, "\n");
+                                       sat.rolloff,
+                                       sat.pilot);
                        }
                        else
                        {
index 0ce59d0..6ad3922 100644 (file)
@@ -836,37 +836,40 @@ int eTSMPEGDecoder::setState()
                if (m_pcr)
                        m_pcr->stop();
                m_pcr = 0;
-               if ((m_pcrpid >= 0) && (m_pcrpid < 0x1FFF))
-               {
-                       m_pcr = new eDVBPCR(m_demux);
-                       if (m_pcr->startPid(m_pcrpid))
-                               res = -1;
-               }
-               m_changed &= ~changePCR;
        }
        if (m_changed & changeVideo)
        {
-               eDebug("VIDEO CHANGED (to %04x)", m_vpid);
                if (m_video)
                {
                        m_video->stop();
                        m_video = 0;
                        m_video_event_conn = 0;
                }
-               if ((m_vpid >= 0) && (m_vpid < 0x1FFF))
-               {
-                       m_video = new eDVBVideo(m_demux, m_decoder);
-                       m_video->connectEvent(slot(*this, &eTSMPEGDecoder::video_event), m_video_event_conn);
-                       if (m_video->startPid(m_vpid, m_vtype))
-                               res = -1;
-               }
-               m_changed &= ~changeVideo;
        }
        if (m_changed & changeAudio)
        {
                if (m_audio)
                        m_audio->stop();
                m_audio = 0;
+       }
+       if (m_changed & changeText)
+       {
+               if (m_text)
+                       m_text->stop();
+               m_text = 0;
+       }
+       if (m_changed & changePCR)
+       {
+               if ((m_pcrpid >= 0) && (m_pcrpid < 0x1FFF))
+               {
+                       m_pcr = new eDVBPCR(m_demux);
+                       if (m_pcr->startPid(m_pcrpid))
+                               res = -1;
+               }
+               m_changed &= ~changePCR;
+       }
+       if (m_changed & changeAudio)
+       {
                if ((m_apid >= 0) && (m_apid < 0x1FFF) && !noaudio)
                {
                        m_audio = new eDVBAudio(m_demux, m_decoder);
@@ -875,11 +878,19 @@ int eTSMPEGDecoder::setState()
                }
                m_changed &= ~changeAudio;
        }
+       if (m_changed & changeVideo)
+       {
+               if ((m_vpid >= 0) && (m_vpid < 0x1FFF))
+               {
+                       m_video = new eDVBVideo(m_demux, m_decoder);
+                       m_video->connectEvent(slot(*this, &eTSMPEGDecoder::video_event), m_video_event_conn);
+                       if (m_video->startPid(m_vpid, m_vtype))
+                               res = -1;
+               }
+               m_changed &= ~changeVideo;
+       }
        if (m_changed & changeText)
        {
-               if (m_text)
-                       m_text->stop();
-               m_text = 0;
                if ((m_textpid >= 0) && (m_textpid < 0x1FFF) && !nott)
                {
                        m_text = new eDVBTText(m_demux);
@@ -1069,6 +1080,7 @@ RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip)
        m_is_ff = frames_to_skip != 0;
 
        setState();
+       unfreeze(); // audio might be restarted and still in preroll (freezed) state.
 
        if (m_video)
                return m_video->setFastForward(frames_to_skip);
@@ -1081,6 +1093,7 @@ RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
        m_is_sm = repeat != 0;
 
        setState();
+       unfreeze(); // audio might be restarted and still in preroll (freezed) state.
 
        if (m_video)
                return m_video->setSlowMotion(repeat);
index 8afa70d..3ad086d 100644 (file)
@@ -713,12 +713,13 @@ RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &
        return 0;
 }
 
-int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
+int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
 {
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
        ePtr<eDVBRegisteredFrontend> best;
        int bestval = 0;
 
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
                if (!i->m_inuse)
                {
                        int c = i->m_frontend->isCompatibleWith(feparm);
@@ -755,10 +756,11 @@ int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBCha
        return 0;
 }
 
-int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
+int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, bool simulate)
 {
+       std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
        int ret=0;
-       if (m_cached_channel)
+       if (!simulate && m_cached_channel)
        {
                eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
                if(channelid==cache_chan->getChannelID())
@@ -767,7 +769,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
 
                /* first, check if a channel is already existing. */
 //     eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
-       for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
+       for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
        {
 //             eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
                if (i->m_channel_id == channelid)
@@ -780,8 +782,9 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
        int *decremented_cached_channel_fe_usecount=NULL,
                *decremented_fe_usecount=NULL;
 
-       for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
+       for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
        {
+               eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
 //             eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
                if (i->m_channel_id == ignore)
                {
@@ -795,7 +798,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
                                ePtr<iDVBFrontend> fe;
                                if (!i->m_channel->getFrontend(fe))
                                {
-                                       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
+                                       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
                                        {
                                                if ( &(*fe) == &(*ii->m_frontend) )
                                                {
@@ -822,7 +825,8 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
                                ePtr<iDVBFrontend> fe;
                                if (!channel->getFrontend(fe))
                                {
-                                       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
+                                       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
+                                       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
                                        {
                                                if ( &(*fe) == &(*ii->m_frontend) )
                                                {
@@ -852,7 +856,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
                goto error;
        }
 
-       ret = canAllocateFrontend(feparm);
+       ret = canAllocateFrontend(feparm, simulate);
 
 error:
        if (decremented_fe_usecount)
index 1a773ef..13556c2 100644 (file)
@@ -184,7 +184,7 @@ public:
        };
        
        RESULT connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection);
-       int canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID &ignore);
+       int canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID &ignore, bool simulate=false);
 
                /* allocate channel... */
        RESULT allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate=false);
@@ -206,7 +206,7 @@ public:
 #ifdef SWIG
 public:
 #endif
-       int canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm);
+       int canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate=false);
        bool canMeasureFrontendInputPower();
        PSignal1<void,int> frontendUseMaskChanged;
        SWIG_VOID(RESULT) allocateRawChannel(eUsePtr<iDVBChannel> &SWIG_OUTPUT, int slot_index);
index 635de8f..b0e92d3 100644 (file)
                if (!m_simulate) \
                        eDebug(x); \
        } while(0)
-//             else \
-//             { \
-//                     eDebugNoNewLine("SIMULATE:"); \
-//                     eDebug(x); \
-//             } \
+#if 0
+               else \
+               { \
+                       eDebugNoNewLine("SIMULATE:"); \
+                       eDebug(x); \
+               }
+#endif
 
 #define eDebugNoSimulateNoNewLine(x...) \
        do { \
                if (!m_simulate) \
                        eDebugNoNewLine(x); \
        } while(0)
-//             else \
-//             { \
-//                     eDebugNoNewLine("SIMULATE:"); \
-//                     eDebugNoNewLine(x); \
-//             } \
+#if 0
+               else \
+               { \
+                       eDebugNoNewLine("SIMULATE:"); \
+                       eDebugNoNewLine(x); \
+               }
+#endif
 
 void eDVBDiseqcCommand::setCommandString(const char *str)
 {
@@ -725,34 +729,58 @@ int eDVBFrontend::readFrontendData(int type)
                        if (!strcmp(m_description, "BCM4501 (internal)"))
                        {
                                unsigned int SDS_SNRE = snr << 16;
+                               float snr_in_db;
 
-                               static float SNR_COEFF[6] = {
-                                       100.0 / 4194304.0,
-                                       -7136.0 / 4194304.0,
-                                       197418.0 / 4194304.0,
-                                       -2602183.0 / 4194304.0,
-                                       20377212.0 / 4194304.0,
-                                       -37791203.0 / 4194304.0,
-                               };
-
-                               float fval1, fval2, snr_in_db;
-                               int i;
-                               fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0));
-                               fval2 = pow(10.0, fval1)-1;
-                               fval1 = 10.0 * log10(fval2);
-
-                               if (fval1 < 10.0)
+                               if (parm_u_qpsk_fec_inner <= FEC_AUTO) // DVB-S1 / QPSK
                                {
-                                       fval2 = SNR_COEFF[0];
-                                       for (i=0; i<6; ++i)
+                                       static float SNR_COEFF[6] = {
+                                               100.0 / 4194304.0,
+                                               -7136.0 / 4194304.0,
+                                               197418.0 / 4194304.0,
+                                               -2602183.0 / 4194304.0,
+                                               20377212.0 / 4194304.0,
+                                               -37791203.0 / 4194304.0,
+                                       };
+                                       float fval1 = 12.44714 - (2.0 * log10(SDS_SNRE / 256.0)),
+                                         fval2 = pow(10.0, fval1)-1;
+                                       fval1 = 10.0 * log10(fval2);
+
+                                       if (fval1 < 10.0)
                                        {
-                                               fval2 *= fval1;
-                                               fval2 += SNR_COEFF[i];
+                                               fval2 = SNR_COEFF[0];
+                                               for (int i=0; i<6; ++i)
+                                               {
+                                                       fval2 *= fval1;
+                                                       fval2 += SNR_COEFF[i];
+                                               }
+                                               fval1 = fval2;
                                        }
-                                       fval1 = fval2;
+                                       snr_in_db = fval1;
                                }
-                               snr_in_db = fval1;
+#if HAVE_DVB_API_VERSION >= 3
+                               else
+                               {
+                                       float fval1 = SDS_SNRE / 268435456.0,
+                                                 fval2, fval3, fval4;
 
+                                       if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
+                                       {
+                                               fval2 = 6.76;
+                                               fval3 = 4.35;
+                                       }
+                                       else // 8PSK
+                                       {
+                                               fval1 *= 0.5;
+                                               fval2 = 8.06;
+                                               fval3 = 6.18;
+                                       }
+                                       fval4 = -10.0 * log10(fval1);
+                                       fval1 = fval4;
+                                       for (int i=0; i < 5; ++i)
+                                               fval1 = fval4 - fval2 * log10(1.0+pow(10.0, (fval3-fval1)/fval2));
+                                       snr_in_db = fval1;
+                               }
+#endif
                                return (int)(snr_in_db * 100.0);
                        }
                        else if (strstr(m_description, "Alps BSBE1 C01A") ||
@@ -781,7 +809,6 @@ int eDVBFrontend::readFrontendData(int type)
                                                i;
                                        if(INRANGE(CN_lookup[Imin][REGVAL],regval,CN_lookup[Imax][REGVAL]))
                                        {
-                                               long val;
                                                while((Imax-Imin)>1)
                                                {
                                                        i=(Imax+Imin)/2;
@@ -987,22 +1014,19 @@ void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &parm, e
                        break;
                }
                PutToDict(dict, "rolloff", tmp);
-               if (parm_u_qpsk_fec_inner > FEC_S2_QPSK_9_10)
+               switch(parm_inversion & 0x30)
                {
-                       switch(parm_inversion & 0x30)
-                       {
-                       case 0: // pilot off
-                               tmp = "PILOT_OFF";
-                               break;
-                       case 0x10: // pilot on
-                               tmp = "PILOT_ON";
-                               break;
-                       case 0x20: // pilot auto
-                               tmp = "PILOT_AUTO";
-                               break;
-                       }
-                       PutToDict(dict, "pilot", tmp);
+               case 0: // pilot off
+                       tmp = "PILOT_OFF";
+                       break;
+               case 0x10: // pilot on
+                       tmp = "PILOT_ON";
+                       break;
+               case 0x20: // pilot auto
+                       tmp = "PILOT_AUTO";
+                       break;
                }
+               PutToDict(dict, "pilot", tmp);
                tmp = "DVB-S2";
        }
        else
@@ -1283,7 +1307,7 @@ void eDVBFrontend::getTransponderData(ePyObject dest, bool original)
                                {
                                        const FRONTENDPARAMETERS &parm = original || m_simulate ? this->parm : front;
                                        const char *tmp = "INVERSION_AUTO";
-                                       switch(parm_inversion)
+                                       switch(parm_inversion & 3)
                                        {
                                                case INVERSION_ON:
                                                        tmp = "INVERSION_ON";
@@ -1889,10 +1913,10 @@ RESULT eDVBFrontend::prepare_sat(const eDVBFrontendParametersSatellite &feparm,
                                        return -EINVAL;
                        }
                        parm_inversion |= (feparm.rolloff << 2); // Hack.. we use bit 2..3 of inversion param for rolloff
+                       parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
                        if (feparm.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) {
                                parm_u_qpsk_fec_inner = (fe_code_rate_t)((int)parm_u_qpsk_fec_inner+9);
                                // 8PSK fec driver values are decimal 9 bigger
-                               parm_inversion |= (feparm.pilot << 4); // Hack.. we use bit 4..5 of inversion param for pilot
                        }
                }
 #endif
index a2cce94..cda0589 100644 (file)
@@ -315,7 +315,7 @@ public:
        // iStaticServiceInformation
        RESULT getName(const eServiceReference &ref, std::string &name);
        RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time);
-       int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
+       int isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate=false);
        PyObject *getInfoObject(const eServiceReference &ref, int);  // implemented in lib/service/servicedvb.h
 
                /* for filtering: */
index 692428d..842d697 100644 (file)
@@ -1,3 +1,4 @@
+#include <lib/base/nconfig.h> // access to python config
 #include <lib/base/eerror.h>
 #include <lib/dvb/pmt.h>
 #include <lib/dvb/specs.h>
@@ -6,6 +7,7 @@
 #include <lib/dvb_ci/dvbci.h>
 #include <lib/dvb/epgcache.h>
 #include <lib/dvb/scan.h>
+#include <lib/dvb_ci/dvbci_session.h>
 #include <dvbsi++/ca_descriptor.h>
 #include <dvbsi++/ca_program_map_section.h>
 #include <dvbsi++/teletext_descriptor.h>
@@ -14,7 +16,6 @@
 #include <dvbsi++/stream_identifier_descriptor.h>
 #include <dvbsi++/subtitling_descriptor.h>
 #include <dvbsi++/teletext_descriptor.h>
-#include <lib/base/nconfig.h> // access to python config
 
 eDVBServicePMTHandler::eDVBServicePMTHandler()
        :m_ca_servicePtr(0), m_dvb_scan(0), m_decode_demux_num(0xFF)
@@ -677,7 +678,7 @@ ChannelMap eDVBCAService::exist_channels;
 ePtr<eConnection> eDVBCAService::m_chanAddedConn;
 
 eDVBCAService::eDVBCAService()
-       : m_prev_build_hash(0), m_sendstate(0), m_retryTimer(eTimer::create(eApp))
+       :m_buffer(512), m_prev_build_hash(0), m_sendstate(0), m_retryTimer(eTimer::create(eApp))
 {
        memset(m_used_demux, 0xFF, sizeof(m_used_demux));
        CONNECT(m_retryTimer->timeout, eDVBCAService::sendCAPMT);
@@ -864,19 +865,100 @@ channel_data *eDVBCAService::getChannelData(eDVBChannelID &chid)
 }
 // end static methods
 
+#define CA_REPLY_DEBUG
+#define MAX_LENGTH_BYTES 4
+#define MIN_LENGTH_BYTES 1
+
 void eDVBCAService::socketCB(int what)
 {
-       if (what & eSocketNotifier::Read)
-               /*eDebug("[eDVBCAService] data to read\n")*/;
-       if (what & eSocketNotifier::Priority)
-               /*eDebug("[eDVBCAService] priority data to read\n")*/;
+       if (what & (eSocketNotifier::Read | eSocketNotifier::Priority))
+       {
+               char msgbuffer[4096];
+               ssize_t length = read(m_sock, msgbuffer, sizeof(msgbuffer));
+               if (length == -1)
+               {
+                       if (errno != EAGAIN && errno != EINTR && errno != EBUSY)
+                       {
+                               eDebug("[eSocketMMIHandler] read (%m)");
+                               what |= eSocketNotifier::Error;
+                       }
+               } else if (length == 0)
+               {
+                       what |= eSocketNotifier::Hungup;
+               } else
+               {
+                       int len = length;
+                       unsigned char *data = (unsigned char*)msgbuffer;
+                       int clear = 1;
+       // If a new message starts, then the previous message
+       // should already have been processed. Otherwise the
+       // previous message was incomplete and should therefore
+       // be deleted.
+                       if ((len >= 1) && ((data[0] & 0xFF) != 0x9f))
+                               clear = 0;
+                       if ((len >= 2) && ((data[1] & 0x80) != 0x80))
+                               clear = 0;
+                       if ((len >= 3) && ((data[2] & 0x80) != 0x00))
+                               clear = 0;
+                       if (clear)
+                       {
+                               m_buffer.clear();
+#ifdef CA_REPLY_DEBUG
+                               eDebug("clear buffer");
+#endif
+                       }
+#ifdef CA_REPLY_DEBUG
+                       eDebug("Put to buffer:");
+                       for (int i=0; i < len; ++i)
+                               eDebugNoNewLine("%02x ", data[i]);
+                       eDebug("\n--------");
+#endif
+                       m_buffer.write( data, len );
+
+                       while ( m_buffer.size() >= (3 + MIN_LENGTH_BYTES) )
+                       {
+                               unsigned char tmp[3+MAX_LENGTH_BYTES];
+                               m_buffer.peek(tmp, 3+MIN_LENGTH_BYTES);
+                               if (((tmp[0] & 0xFF) != 0x9f) || ((tmp[1] & 0x80) != 0x80) || ((tmp[2] & 0x80) != 0x00))
+                               {
+                                       m_buffer.skip(1);
+#ifdef CA_REPLY_DEBUG
+                                       eDebug("skip %02x", tmp[0]);
+#endif
+                                       continue;
+                               }
+                               if (tmp[3] & 0x80)
+                               {
+                                       int peekLength = (tmp[3] & 0x7f) + 4;
+                                       if (m_buffer.size() < peekLength)
+                                               continue;
+                                       m_buffer.peek(tmp, peekLength);
+                               }
+                               int size=0;
+                               int LengthBytes=eDVBCISession::parseLengthField(tmp+3, size);
+                               int messageLength = 3+LengthBytes+size;
+                               if ( m_buffer.size() >= messageLength )
+                               {
+                                       unsigned char dest[messageLength];
+                                       m_buffer.read(dest, messageLength);
+#ifdef CA_REPLY_DEBUG
+                                       eDebug("dump ca reply:");
+                                       for (int i=0; i < messageLength; ++i)
+                                               eDebugNoNewLine("%02x ", dest[i]);
+                                       eDebug("\n--------");
+#endif
+//                                     /*emit*/ mmi_progress(0, dest, (const void*)(dest+3+LengthBytes), messageLength-3-LengthBytes);
+                               }
+                       }
+               }
+       }
        if (what & eSocketNotifier::Hungup) {
-               /*eDebug("[eDVBCAService] connection closed\n")*/;
+               /*eDebug("[eDVBCAService] connection closed")*/;
                m_sendstate=1;
                sendCAPMT();
        }
        if (what & eSocketNotifier::Error)
-               /*eDebug("[eDVBCAService] connection error\n")*/;
+               eDebug("[eDVBCAService] connection error");
 }
 
 void eDVBCAService::Connect()
index 107b071..ff0ef04 100644 (file)
@@ -3,6 +3,7 @@
 
 #ifndef SWIG
 #include <map>
+#include <lib/base/buffer.h>
 #include <lib/dvb/idvb.h>
 #include <lib/dvb/dvb.h>
 #include <lib/dvb/idemux.h>
@@ -35,6 +36,7 @@ typedef std::map<iDVBChannel*, channel_data*> ChannelMap;
 
 class eDVBCAService: public Object
 {
+       eIOBuffer m_buffer;
        ePtr<eSocketNotifier> m_sn;
        eServiceReferenceDVB m_service;
        uint8_t m_used_demux[32];
index dfc6224..c7a3746 100644 (file)
@@ -365,9 +365,9 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset)
                        if (ptsvalid)
                        {
                                m_streaminfo.m_access_points[offset] = pts;
-                               eDebug("Sequence header at %llx, pts %llx", offset, pts);
+//                             eDebug("Sequence header at %llx, pts %llx", offset, pts);
                        } else
-                               eDebug("Sequence header but no valid PTS value.");
+                               /*eDebug("Sequence header but no valid PTS value.")*/;
                }
 
                if (pkt[3] == 0x09 &&   /* MPEG4 AVC unit access delimiter */
@@ -376,9 +376,9 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset)
                        if (ptsvalid)
                        {
                                m_streaminfo.m_access_points[offset] = pts;
-                               eDebug("MPEG4 AVC UAD at %llx, pts %llx", offset, pts);
+//                             eDebug("MPEG4 AVC UAD at %llx, pts %llx", offset, pts);
                        } else
-                               eDebug("MPEG4 AVC UAD but no valid PTS value.");
+                               /*eDebug("MPEG4 AVC UAD but no valid PTS value.")*/;
                }
        }
        return 0;
index 2457763..71893f9 100644 (file)
@@ -758,7 +758,7 @@ void eDVBScan::channelDone()
                        SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
                        service->m_service_name = convertDVBUTF8(sname);
                        service->genSortName();
-                       service->m_provider_name = pname;
+                       service->m_provider_name = convertDVBUTF8(pname);
                }
 
                if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
index 35a8d04..2b7f717 100644 (file)
@@ -637,11 +637,11 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                                        diseqc.data[2] = 0;
                                                        // diseqc reset
                                                        sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_DISEQC_RESET_CMD]) );
                                                        diseqc.data[2] = 3;
                                                        // diseqc peripherial powersupply on
                                                        sec_sequence.push_back( eSecCommand(eSecCommand::SEND_DISEQC, diseqc) );
-                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 150) );
+                                                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_DISEQC_PERIPHERIAL_POWERON_CMD]) );
                                                }
 
                                                for (int seq_repeat = 0; seq_repeat < (di_param.m_seq_repeat?2:1); ++seq_repeat)
@@ -894,8 +894,8 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                csw = band;
                        }
 
-                       if (sendDiSEqC)
-                               sec_sequence.push_front( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
+//                     if (sendDiSEqC)
+                       sec_sequence.push_front( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeStatic) );
 
                        sec_fe->setData(eDVBFrontend::NEW_CSW, csw);
                        sec_fe->setData(eDVBFrontend::NEW_UCSW, ucsw);
@@ -923,8 +923,9 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
                                sec_sequence.push_back( eSecCommand(eSecCommand::SET_FRONTEND) );
                        }
 
-                       if (sendDiSEqC)
-                               sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
+//                     if (sendDiSEqC)
+                       sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, 50) );
+                       sec_sequence.push_back( eSecCommand(eSecCommand::SET_POWER_LIMITING_MODE, eSecCommand::modeDynamic) );
 
                        frontend.setSecSequence(sec_sequence);
 
index 42e53eb..e68ed16 100644 (file)
@@ -267,6 +267,8 @@ public:
                MOTOR_COMMAND_RETRIES, // max transmit tries of rotor command when the rotor dont start turning (with power measurement)
                MOTOR_RUNNING_TIMEOUT, // max motor running time before timeout
                DELAY_AFTER_VOLTAGE_CHANGE_BEFORE_SWITCH_CMDS, // delay after change voltage before transmit toneburst/diseqc
+               DELAY_AFTER_DISEQC_RESET_CMD,
+               DELAY_AFTER_DISEQC_PERIPHERIAL_POWERON_CMD,
                MAX_PARAMS
        };
 private:
index 3911719..ecc19b5 100644 (file)
@@ -166,8 +166,14 @@ void eDBoxLCD::update()
                memset(raw, 0, 64*64);
                for (y=0; y<64; y++)
                {
+                       int pix=0;
                        for (x=0; x<128 / 2; x++)
-                               raw[y*64+x] = (_buffer[y*132 + x * 2 + 2] & 0xF0) |(_buffer[y*132 + x * 2 + 1 + 2] >> 4);
+                       {
+                               pix = (_buffer[y*132 + x * 2 + 2] & 0xF0) |(_buffer[y*132 + x * 2 + 1 + 2] >> 4);
+                               if (inverted)
+                                       pix = 0xFF - pix;
+                               raw[y*64+x] = pix;
+                       }
                }
                if (lcdfd >= 0)
                        write(lcdfd, raw, 64*64);
index 94cb35b..1f9bed4 100644 (file)
@@ -10,6 +10,8 @@
 
 #include <epng.h>      // savePNG need it
 
+#define JDCT_DEFAULT JDCT_IFAST
+
 extern "C" {
 #include <jpeglib.h>
 #include <gif_lib.h>
@@ -163,6 +165,151 @@ static int jpeg_save(unsigned char *image_buffer, const char * filename, int qua
        return 0;
 }
 
+/* Expanded data source object for memory buffer input */
+typedef struct
+{
+       struct jpeg_source_mgr pub;     /* public fields */
+       FILE *infile;                   /* source stream */
+       JOCTET *buffer;         /* start of buffer */
+       boolean start_of_file;  /* have we gotten any data yet? */
+} mem_source_mgr;
+
+typedef mem_source_mgr *mem_src_ptr;
+
+static void init_source (j_decompress_ptr cinfo)
+{
+       mem_src_ptr src = (mem_src_ptr) cinfo->src;
+       src->start_of_file = TRUE;
+}
+
+static boolean fill_input_buffer (j_decompress_ptr cinfo)
+{
+       /* no-op */ (void)cinfo;
+       return TRUE;
+ }
+
+static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+       mem_src_ptr src = (mem_src_ptr) cinfo->src;
+       
+       if (num_bytes > 0)
+       {
+               src->pub.next_input_byte += (size_t) num_bytes;
+               src->pub.bytes_in_buffer -= (size_t) num_bytes;
+       }
+}
+
+static void term_source (j_decompress_ptr cinfo)
+{
+       /* no-op */ (void)cinfo;
+}
+
+static void jpeg_memory_src (j_decompress_ptr cinfo, unsigned char *inbfr, int len)
+{
+       mem_src_ptr src;
+       if (cinfo->src == NULL)
+       {
+               cinfo->src = (struct jpeg_source_mgr *)
+               (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, (size_t)sizeof(mem_source_mgr));
+               src = (mem_src_ptr) cinfo->src;
+               src->buffer = (JOCTET *) inbfr;
+       }
+       src = (mem_src_ptr) cinfo->src;
+       src->pub.init_source = init_source;
+       src->pub.fill_input_buffer = fill_input_buffer;
+       src->pub.skip_input_data = skip_input_data;
+       src->pub.resync_to_restart = jpeg_resync_to_restart;    /* use default method */
+       src->pub.term_source = term_source;
+       src->infile = 0L;
+       src->pub.bytes_in_buffer = len;                         /* sets to entire file len */
+       src->pub.next_input_byte = (JOCTET *)inbfr;             /* at start of buffer */
+}
+
+static int jpeg_load_thumb(const char *filename, int *x, int *y)
+{
+       struct jpeg_decompress_struct cinfo;
+       struct jpeg_decompress_struct *ciptr = &cinfo;
+       struct r_jpeg_error_mgr emgr;
+       FILE *fh;
+
+       if (!(fh = fopen(filename, "rb")))
+               return 0;
+
+       ciptr->err = jpeg_std_error(&emgr.pub);
+       emgr.pub.error_exit = jpeg_cb_error_exit;
+       if (setjmp(emgr.envbuffer) == 1)
+       {
+               jpeg_destroy_decompress(ciptr);
+               fclose(fh);
+               return 0;
+       }
+
+       jpeg_create_decompress(ciptr);
+       jpeg_stdio_src(ciptr, fh);
+
+       jpeg_save_markers (ciptr, JPEG_APP0 + 1, 0xffff);
+
+       jpeg_read_header(ciptr, TRUE);
+
+       struct jpeg_marker_struct *m = cinfo.marker_list;
+
+       unsigned char *thumb_buf = NULL;
+       size_t bufsize;
+       
+       if ( m )
+       {
+               unsigned char *p_data = m->data;
+               while ( p_data < m->data+m->data_length )
+               {
+                       if ( p_data[0] == 0xFF && p_data[1] == 0xD8 )
+                       {
+                               bufsize = (size_t) m->data_length - (size_t) (p_data-m->data);
+                               thumb_buf = new unsigned char[bufsize];
+                               bufsize = 0;
+                               do {
+                                       thumb_buf[bufsize++] = *p_data;
+                               } while ( !(*p_data++ == 0xFF && *p_data == 0xD9) && p_data < m->data+m->data_length );
+                               thumb_buf[bufsize++] = *p_data;
+                       }
+                       p_data++;
+               }
+       }
+
+       if ( thumb_buf != NULL )
+       {
+               jpeg_create_decompress(ciptr);
+               jpeg_memory_src(ciptr, thumb_buf, bufsize-2);
+               jpeg_read_header(ciptr, TRUE);
+       }
+       else
+               eDebug("no exif thumbnail found! loading actual image instead");
+
+       ciptr->out_color_space = JCS_RGB;
+       ciptr->scale_denom = 1;
+
+       jpeg_start_decompress(ciptr);
+       
+       *x=ciptr->output_width;
+       *y=ciptr->output_height;
+
+       if(ciptr->output_components == 3)
+       {
+               JSAMPLE *lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, ciptr->output_width * ciptr->output_components);
+               pic_buffer = new unsigned char[ciptr->output_height * ciptr->output_width * ciptr->output_components];
+               unsigned char *bp = pic_buffer;
+
+               while (ciptr->output_scanline < ciptr->output_height)
+               {
+                       jpeg_read_scanlines(ciptr, &lb, 1);
+                       memcpy(bp, lb, ciptr->output_width * ciptr->output_components);
+                       bp += ciptr->output_width * ciptr->output_components;
+               }
+       }
+       jpeg_finish_decompress(ciptr);
+       jpeg_destroy_decompress(ciptr);
+       fclose(fh);
+       return 1;
+}
 
 static int jpeg_load(const char *filename, int *x, int *y)
 {
@@ -410,7 +557,7 @@ static int png_load(const char *filename,  int *x, int *y)
 
        if (width * height > 1000000) // 1000x1000 or equiv.
        {
-               eDebug("[png_load] image size is %d x %d, which is \"too large\".", width, height);
+               eDebug("[png_load] image size is %d x %d, which is \"too large\".", (int)width, (int)height);
                png_read_end(png_ptr, info_ptr);
                png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
                fclose(fh);
@@ -632,7 +779,7 @@ static int pic_id(const char *name)
        return F_NONE;
 }
 
-int loadPic(ePtr<gPixmap> &result, std::string filename, int w, int h, int aspect, int resize_mode, int rotate, int background, std::string cachefile)
+int loadPic(ePtr<gPixmap> &result, std::string filename, int w, int h, int aspect, int resize_mode, int rotate, int background, std::string cachefile, int thumbnail)
 {
        result = 0;
        int ox=0, oy=0, imx, imy;
@@ -650,7 +797,13 @@ int loadPic(ePtr<gPixmap> &result, std::string filename, int w, int h, int aspec
                switch(pic_id(filename.c_str()))
                {
                        case F_PNG:     png_load(filename.c_str(), &ox, &oy);break;
-                       case F_JPEG:    jpeg_load(filename.c_str(), &ox, &oy);pic_buffer = conv24to32(pic_buffer, ox*oy, 1); break;
+                       case F_JPEG:    {
+                                       if (thumbnail)
+                                               jpeg_load_thumb(filename.c_str(), &ox, &oy);
+                                       else
+                                               jpeg_load(filename.c_str(), &ox, &oy);
+                                       pic_buffer = conv24to32(pic_buffer, ox*oy, 1);
+                                       break; }
                        case F_BMP:     bmp_load(filename.c_str(), &ox, &oy);pic_buffer = conv24to32(pic_buffer, ox*oy, 1); break;
                        case F_GIF:     gif_load(filename.c_str(), &ox, &oy);pic_buffer = conv24to32(pic_buffer, ox*oy, 1); break;
                        default:
index 7d5d8b2..7bb9adf 100644 (file)
@@ -5,7 +5,7 @@
 #include <lib/gdi/gpixmap.h>
 #include <lib/gdi/epng.h>
 
-SWIG_VOID(int) loadPic(ePtr<gPixmap> &SWIG_OUTPUT, std::string filename, int x, int y, int aspect, int resize_mode=0, int rotate=0, int background=0, std::string cachefile="");
+SWIG_VOID(int) loadPic(ePtr<gPixmap> &SWIG_OUTPUT, std::string filename, int x, int y, int aspect, int resize_mode=0, int rotate=0, int background=0, std::string cachefile="", int thumbnail=0);
 PyObject *getExif(const char *filename);
 
 #endif // __picload_h__
index 4785d7a..b3ee511 100644 (file)
@@ -126,13 +126,17 @@ int ePositionGauge::event(int event, void *data, void *data2)
                                        continue;
                                } else if (i->what == 1) /* out */
                                        out = i++->where;
-                               else /* mark */
+                               else if (i->what == 2) /* mark */
                                {
                                        int xm = scale(i->where);
                                        painter.setForegroundColor(gRGB(0xFF8080));
                                        painter.fill(eRect(xm - 2, 0, 4, s.height()));
                                        i++;
                                        continue;
+                               } else /* other marker, like last position */
+                               {
+                                       ++i;
+                                       continue;
                                }
                        }
                        
old mode 100644 (file)
new mode 100755 (executable)
index 25c9b8b..04815c8
@@ -1,7 +1,6 @@
 from GUIComponent import GUIComponent
 
 from enigma import eListboxPythonMultiContent, eListbox, gFont
-
 from Tools.KeyBindings import queryKeyBinding, getKeyDescription
 #getKeyPositions
 
@@ -13,6 +12,7 @@ class HelpMenuList(GUIComponent):
                self.onSelChanged = [ ]
                self.l = eListboxPythonMultiContent()
                self.callback = callback
+               self.extendedHelp = False
 
                l = [ ]
                for (actionmap, context, actions) in list:
@@ -36,17 +36,26 @@ class HelpMenuList(GUIComponent):
                                if flags & 8: # for long keypresses, prepend l_ into the key name.
                                        name = (name[0], "long")
                                        
-                               print "name:", name
-
                                entry.append( (actionmap, context, action, name ) )
-                               entry.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 400, 28, 0, 0, help) )
-
+                                       
+                               if type(help).__name__== 'list':
+                                       self.extendedHelp = True
+                                       print "extendedHelpEntry found"
+                                       entry.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 400, 26, 0, 0, help[0]) )
+                                       entry.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 28, 400, 20, 1, 0, help[1]) )
+                               else:
+                                       entry.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 400, 28, 0, 0, help) )
+                                       
                                l.append(entry)
 
                self.l.setList(l)
-
-               self.l.setFont(0, gFont("Regular", 24))
-               self.l.setItemHeight(38)
+               if self.extendedHelp is True:
+                       self.l.setFont(0, gFont("Regular", 24))
+                       self.l.setFont(1, gFont("Regular", 18))
+                       self.l.setItemHeight(50)
+               else:
+                       self.l.setFont(0, gFont("Regular", 24))
+                       self.l.setItemHeight(38)
 
        def ok(self):
                # a list entry has a "private" tuple as first entry...
index acb50e5..6d1e31f 100644 (file)
@@ -35,6 +35,7 @@ class Language:
                self.addLanguage(_("Spanish"), "es", "ES")
                self.addLanguage(_("Swedish"), "sv", "SE")
                self.addLanguage(_("Turkish"), "tr", "TR")
+               self.addLanguage(_("Ukrainian"), "uk", "UA")
 
                self.callbacks = []
 
index 0471843..0e50123 100644 (file)
@@ -44,9 +44,14 @@ def InitLcd():
 
                ilcd = LCD()
 
-               config.lcd.bright = ConfigSlider(default=10, limits=(0, 10))
+               config.lcd.standby = ConfigSlider(default=0, limits=(0, 10))
+               config.lcd.standby.addNotifier(setLCDbright);
+               config.lcd.standby.apply = lambda : setLCDbright(config.lcd.standby)
+
+               config.lcd.bright = ConfigSlider(default=5, limits=(0, 10))
                config.lcd.bright.addNotifier(setLCDbright);
                config.lcd.bright.apply = lambda : setLCDbright(config.lcd.bright)
+               config.lcd.bright.callNotifiersOnSaveAndCancel = True
 
                if not ilcd.isOled():
                        config.lcd.contrast = ConfigSlider(default=5, limits=(0, 20))
@@ -54,9 +59,6 @@ def InitLcd():
                else:
                        config.lcd.contrast = ConfigNothing()
 
-               config.lcd.standby = ConfigSlider(default=0, limits=(0, 10))
-               config.lcd.standby.apply = lambda : setLCDbright(config.lcd.standby)
-
                config.lcd.invert = ConfigYesNo(default=False)
                config.lcd.invert.addNotifier(setLCDinverted);
        else:
index 791274f..87ba977 100644 (file)
@@ -40,7 +40,7 @@ def PlaylistEntryComponent(serviceref, state):
 
        if png is not None:
                res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 5, 0, 16, 16, png))
-    
+
        return res
 
 class PlayList(MenuList):
@@ -76,6 +76,7 @@ class PlayList(MenuList):
        def setCurrentPlaying(self, index):
                self.oldCurrPlaying = self.currPlaying
                self.currPlaying = index
+               self.moveToIndex(index)
 
        def updateState(self, state):
                if len(self.list) > self.oldCurrPlaying and self.oldCurrPlaying != -1:
index ace3601..8568f3d 100644 (file)
@@ -103,7 +103,8 @@ class MovieList(GUIComponent):
                txt = info.getName(serviceref)
                service = ServiceReference(info.getInfoString(serviceref, iServiceInformation.sServiceref))
                description = info.getInfoString(serviceref, iServiceInformation.sDescription)
-               
+               tags = info.getInfoString(serviceref, iServiceInformation.sTags)
+
                begin_string = ""
                if begin > 0:
                        t = FuzzyTime(begin)
@@ -111,23 +112,33 @@ class MovieList(GUIComponent):
                
                if self.list_type == MovieList.LISTTYPE_ORIGINAL:
                        res.append(MultiContentEntryText(pos=(0, 0), size=(width-182, 30), font = 0, flags = RT_HALIGN_LEFT, text=txt))
-                       if service is not None:
-                               res.append(MultiContentEntryText(pos=(width-180, 0), size=(180, 30), font = 2, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
+                       if self.tags:
+                               res.append(MultiContentEntryText(pos=(width-180, 0), size=(180, 30), font = 2, flags = RT_HALIGN_RIGHT, text = tags))
+                               if service is not None:
+                                       res.append(MultiContentEntryText(pos=(200, 50), size=(200, 20), font = 1, flags = RT_HALIGN_LEFT, text = service.getServiceName()))
+                       else:
+                               if service is not None:
+                                       res.append(MultiContentEntryText(pos=(width-180, 0), size=(180, 30), font = 2, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
                        res.append(MultiContentEntryText(pos=(0, 30), size=(width, 20), font=1, flags=RT_HALIGN_LEFT, text=description))
-                       res.append(MultiContentEntryText(pos=(0, 50), size=(width-270, 20), font=1, flags=RT_HALIGN_LEFT, text=begin_string))
-                       res.append(MultiContentEntryText(pos=(width-200, 50), size=(200, 20), font=1, flags=RT_HALIGN_RIGHT, text=len))
+                       res.append(MultiContentEntryText(pos=(0, 50), size=(200, 20), font=1, flags=RT_HALIGN_LEFT, text=begin_string))
+                       res.append(MultiContentEntryText(pos=(width-200, 50), size=(198, 20), font=1, flags=RT_HALIGN_RIGHT, text=len))
                elif self.list_type == MovieList.LISTTYPE_COMPACT_DESCRIPTION:
                        res.append(MultiContentEntryText(pos=(0, 0), size=(width-120, 20), font = 0, flags = RT_HALIGN_LEFT, text = txt))
-                       if service is not None:
-                               res.append(MultiContentEntryText(pos=(width-212, 20), size=(154, 17), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
                        res.append(MultiContentEntryText(pos=(0, 20), size=(width-212, 17), font=1, flags=RT_HALIGN_LEFT, text=description))
                        res.append(MultiContentEntryText(pos=(width-120, 6), size=(120, 20), font=1, flags=RT_HALIGN_RIGHT, text=begin_string))
+                       if service is not None:
+                               res.append(MultiContentEntryText(pos=(width-212, 20), size=(154, 17), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
                        res.append(MultiContentEntryText(pos=(width-58, 20), size=(58, 20), font=1, flags=RT_HALIGN_RIGHT, text=len))
                elif self.list_type == MovieList.LISTTYPE_COMPACT:
                        res.append(MultiContentEntryText(pos=(0, 0), size=(width-77, 20), font = 0, flags = RT_HALIGN_LEFT, text = txt))
-                       if service is not None:
-                               res.append(MultiContentEntryText(pos=(width-200, 20), size=(200, 17), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
-                       res.append(MultiContentEntryText(pos=(0, 20), size=(width-200, 17), font=1, flags=RT_HALIGN_LEFT, text=begin_string))
+                       if self.tags:
+                               res.append(MultiContentEntryText(pos=(width-200, 20), size=(200, 17), font = 1, flags = RT_HALIGN_RIGHT, text = tags))
+                               if service is not None:
+                                       res.append(MultiContentEntryText(pos=(200, 20), size=(200, 17), font = 1, flags = RT_HALIGN_LEFT, text = service.getServiceName()))
+                       else:
+                               if service is not None:
+                                       res.append(MultiContentEntryText(pos=(width-200, 20), size=(200, 17), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
+                       res.append(MultiContentEntryText(pos=(0, 20), size=(200, 17), font=1, flags=RT_HALIGN_LEFT, text=begin_string))
                        res.append(MultiContentEntryText(pos=(width-75, 0), size=(75, 20), font=0, flags=RT_HALIGN_RIGHT, text=len))
                else:
                        assert(self.list_type == MovieList.LISTTYPE_MINIMAL)
@@ -212,6 +223,7 @@ class MovieList(GUIComponent):
                        if this_tags == ['']:
                                this_tags = []
                        this_tags = set(this_tags)
+                       tags |= this_tags
                
                        # filter_tags is either None (which means no filter at all), or 
                        # a set. In this case, all elements of filter_tags must be present,
@@ -219,7 +231,6 @@ class MovieList(GUIComponent):
                        if filter_tags is not None and not this_tags.issuperset(filter_tags):
                                continue
                
-                       tags |= this_tags
                        self.list.append((serviceref, info, begin, -1))
                
                if self.sort_type == MovieList.SORT_ALPHANUMERIC:
@@ -243,8 +254,9 @@ class MovieList(GUIComponent):
                for x in self.list:
                        if x[0] == serviceref:
                                self.instance.moveSelectionTo(count)
-                               break
+                               return True
                        count += 1
-
+               return False
+       
        def moveDown(self):
                self.instance.moveSelection(self.instance.moveDown)
old mode 100644 (file)
new mode 100755 (executable)
index bed9d95..64b3aa6
@@ -7,11 +7,21 @@ from Components.Console import Console
 class Network:
        def __init__(self):
                self.ifaces = {}
-               self.configuredInterfaces = []          
+               self.configuredInterfaces = []
+               self.configuredNetworkAdapters = []
+               self.NetworkState = 0
+               self.DnsState = 0
                self.nameservers = []
                self.ethtool_bin = "/usr/sbin/ethtool"
                self.container = eConsoleAppContainer()
                self.Console = Console()
+               self.LinkConsole = Console()
+               self.restartConsole = Console()
+               self.deactivateConsole = Console()
+               self.deactivateInterfaceConsole = Console()
+               self.activateConsole = Console()
+               self.resetNetworkConsole = Console()
+               self.DnsConsole = Console()
                self.getInterfaces()
 
        def getInterfaces(self, callback = None):
@@ -28,6 +38,11 @@ class Network:
                                self.getDataForInterface(device, callback)
                        except AttributeError:
                                pass
+               #print "self.ifaces:", self.ifaces
+               #self.writeNetworkConfig()
+               #print ord(' ')
+               #for line in result:
+               #       print ord(line[0])
 
        # helper function
        def regExpMatch(self, pattern, string):
@@ -46,66 +61,60 @@ class Network:
                        ip.append(int(x))
                return ip
 
+       def getDataForInterface(self, iface,callback):
+               #get ip out of ip addr, as avahi sometimes overrides it in ifconfig.
+               if not self.Console:
+                       self.Console = Console()
+               cmd = "ip -o addr"
+               self.Console.ePopen(cmd, self.IPaddrFinished, [iface,callback])
+
        def IPaddrFinished(self, result, retval, extra_args):
                (iface, callback ) = extra_args
                data = { 'up': False, 'dhcp': False, 'preup' : False, 'postdown' : False }
                globalIPpattern = re_compile("scope global")
                ipRegexp = '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
-               ipLinePattern = re_compile('inet ' + ipRegexp +'/')
+               netRegexp = '[0-9]{1,2}'
+               macRegexp = '[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}'
+               ipLinePattern = re_compile('inet ' + ipRegexp + '/')
                ipPattern = re_compile(ipRegexp)
-
+               netmaskLinePattern = re_compile('/' + netRegexp)
+               netmaskPattern = re_compile(netRegexp)
+               bcastLinePattern = re_compile(' brd ' + ipRegexp)
+               upPattern = re_compile('UP')
+               macPattern = re_compile('[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}')
+               macLinePattern = re_compile('link/ether ' + macRegexp)
+               
                for line in result.splitlines():
                        split = line.strip().split(' ',2)
+                       if (split[1][:-1] == iface):
+                               up = self.regExpMatch(upPattern, split[2])
+                               mac = self.regExpMatch(macPattern, self.regExpMatch(macLinePattern, split[2]))
+                               if up is not None:
+                                       data['up'] = True
+                                       if iface is not 'lo':
+                                               self.configuredInterfaces.append(iface)
+                               if mac is not None:
+                                       data['mac'] = mac
                        if (split[1] == iface):
                                if re_search(globalIPpattern, split[2]):
                                        ip = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, split[2]))
+                                       netmask = self.calc_netmask(self.regExpMatch(netmaskPattern, self.regExpMatch(netmaskLinePattern, split[2])))
+                                       bcast = self.regExpMatch(ipPattern, self.regExpMatch(bcastLinePattern, split[2]))
                                        if ip is not None:
                                                data['ip'] = self.convertIP(ip)
+                                       if netmask is not None:
+                                               data['netmask'] = self.convertIP(netmask)
+                                       if bcast is not None:
+                                               data['bcast'] = self.convertIP(bcast)
+                                               
                if not data.has_key('ip'):
                        data['dhcp'] = True
                        data['ip'] = [0, 0, 0, 0]
                        data['netmask'] = [0, 0, 0, 0]
                        data['gateway'] = [0, 0, 0, 0]
 
-               cmd = "ifconfig " + iface
-               self.Console.ePopen(cmd, self.ifconfigFinished, [iface, data, callback])
-
-       def getDataForInterface(self, iface,callback):
-               #get ip out of ip addr, as avahi sometimes overrides it in ifconfig.
-               cmd = "ip -o addr"
-               self.Console.ePopen(cmd, self.IPaddrFinished, [iface,callback])
-
-       def ifconfigFinished(self, result, retval, extra_args ):
-               (iface, data, callback ) = extra_args
-               ipRegexp = '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
-               ipLinePattern = re_compile('inet addr:' + ipRegexp)
-               netmaskLinePattern = re_compile('Mask:' + ipRegexp)
-               bcastLinePattern = re_compile('Bcast:' + ipRegexp)
-               ipPattern = re_compile(ipRegexp)
-               upPattern = re_compile('UP ')
-               macPattern = re_compile('[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[0-9]{2}')
-
-               for line in result.splitlines():
-                       #ip = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, line))
-                       netmask = self.regExpMatch(ipPattern, self.regExpMatch(netmaskLinePattern, line))
-                       bcast = self.regExpMatch(ipPattern, self.regExpMatch(bcastLinePattern, line))
-                       up = self.regExpMatch(upPattern, line)
-                       mac = self.regExpMatch(macPattern, line)
-                       #if ip is not None:
-                       #       data['ip'] = self.convertIP(ip)
-                       if netmask is not None:
-                               data['netmask'] = self.convertIP(netmask)
-                       if bcast is not None:
-                               data['bcast'] = self.convertIP(bcast)
-                       if up is not None:
-                               data['up'] = True
-                               if iface is not 'lo':
-                                       self.configuredInterfaces.append(iface)
-                       if mac is not None:
-                               data['mac'] = mac
-
                cmd = "route -n | grep  " + iface
-               self.Console.ePopen(cmd,self.routeFinished,[iface,data,callback])
+               self.Console.ePopen(cmd,self.routeFinished, [iface, data, callback])
 
        def routeFinished(self, result, retval, extra_args):
                (iface, data, callback) = extra_args
@@ -119,16 +128,7 @@ class Network:
                                gateway = self.regExpMatch(ipPattern, line[16:31])
                                if gateway is not None:
                                        data['gateway'] = self.convertIP(gateway)
-
-               for line in result.splitlines(): #get real netmask in case avahi has overridden ifconfig netmask
-                       split = line.strip().split('   ')
-                       if re_search(ipPattern, split[0]):
-                               foundip = self.convertIP(split[0])
-                               if (foundip[0] == data['ip'][0] and foundip[1] == data['ip'][1]):
-                                       if re_search(ipPattern, split[4]):
-                                               mask = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, split[4]))
-                                               if mask is not None:
-                                                       data['netmask'] = self.convertIP(mask)
+                                       
                self.ifaces[iface] = data
                self.loadNetworkConfig(iface,callback)
 
@@ -214,13 +214,16 @@ class Network:
                for ifacename, iface in ifaces.items():
                        if self.ifaces.has_key(ifacename):
                                self.ifaces[ifacename]["dhcp"] = iface["dhcp"]
-               if len(self.Console.appContainers) == 0:
-                       # load ns only once
-                       self.loadNameserverConfig()
-                       print "read configured interfac:", ifaces
-                       print "self.ifaces after loading:", self.ifaces
-                       if callback is not None:
-                               callback(True)
+               if self.Console:
+                       if len(self.Console.appContainers) == 0:
+                               # save configured interfacelist
+                               self.configuredNetworkAdapters = self.configuredInterfaces
+                               # load ns only once     
+                               self.loadNameserverConfig()
+                               print "read configured interfac:", ifaces
+                               print "self.ifaces after loading:", self.ifaces
+                               if callback is not None:
+                                       callback(True)
 
        def loadNameserverConfig(self):
                ipRegexp = "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
@@ -244,16 +247,39 @@ class Network:
 
                print "nameservers:", self.nameservers
 
-       def deactivateNetworkConfig(self):
+       def deactivateNetworkConfig(self, callback = None):
+               self.deactivateConsole = Console()
+               self.commands = []
+               self.commands.append("/etc/init.d/avahi-daemon stop")
                for iface in self.ifaces.keys():
-                       system("ip addr flush " + iface)
-               system("/etc/init.d/networking stop")
-               system("killall -9 udhcpc")
-               system("rm /var/run/udhcpc*")
+                       cmd = "ip addr flush " + iface
+                       self.commands.append(cmd)               
+               self.commands.append("/etc/init.d/networking stop")
+               self.commands.append("killall -9 udhcpc")
+               self.commands.append("rm /var/run/udhcpc*")
+               self.deactivateConsole.eBatch(self.commands, self.deactivateNetworkFinished, callback, debug=True)
+               
+       def deactivateNetworkFinished(self,extra_args):
+               callback = extra_args
+               if len(self.deactivateConsole.appContainers) == 0:
+                       if callback is not None:
+                               callback(True)
 
-       def activateNetworkConfig(self):
-               system("/etc/init.d/networking start")
-               self.getInterfaces()
+       def activateNetworkConfig(self, callback = None):
+               self.activateConsole = Console()
+               self.commands = []
+               self.commands.append("/etc/init.d/networking start")
+               self.commands.append("/etc/init.d/avahi-daemon start")
+               self.activateConsole.eBatch(self.commands, self.activateNetworkFinished, callback, debug=True)
+               
+       def activateNetworkFinished(self,extra_args):
+               callback = extra_args
+               if len(self.activateConsole.appContainers) == 0:
+                       if callback is not None:
+                               callback(True)
+
+       def getConfiguredAdapters(self):
+               return self.configuredNetworkAdapters
 
        def getNumberOfAdapters(self):
                return len(self.ifaces)
@@ -312,7 +338,24 @@ class Network:
                                if self.nameservers[i] == oldnameserver:
                                        self.nameservers[i] = newnameserver
 
-       def writeDefaultNetworkConfig(self,mode='lan'):
+       def resetNetworkConfig(self, mode='lan', callback = None):
+               self.resetNetworkConsole = Console()
+               self.commands = []
+               self.commands.append("/etc/init.d/avahi-daemon stop")
+               for iface in self.ifaces.keys():
+                       cmd = "ip addr flush " + iface
+                       self.commands.append(cmd)               
+               self.commands.append("/etc/init.d/networking stop")
+               self.commands.append("killall -9 udhcpc")
+               self.commands.append("rm /var/run/udhcpc*")
+               self.resetNetworkConsole.eBatch(self.commands, self.resetNetworkFinishedCB, [mode, callback], debug=True)
+
+       def resetNetworkFinishedCB(self, extra_args):
+               (mode, callback) = extra_args
+               if len(self.resetNetworkConsole.appContainers) == 0:
+                       self.writeDefaultNetworkConfig(mode, callback)
+
+       def writeDefaultNetworkConfig(self,mode='lan', callback = None):
                fp = file('/etc/network/interfaces', 'w')
                fp.write("# automatically generated by enigma 2\n# do NOT change manually!\n\n")
                fp.write("auto lo\n")
@@ -329,50 +372,100 @@ class Network:
                fp.write("\n")
                fp.close()
 
-       def resetNetworkConfig(self,mode='lan'):
-               self.deactivateNetworkConfig()
-               self.writeDefaultNetworkConfig(mode)
+               self.resetNetworkConsole = Console()
+               self.commands = []
                if mode == 'wlan':
-                       system("ifconfig eth0 down")
-                       system("ifconfig ath0 down")
-                       system("ifconfig wlan0 up")
+                       self.commands.append("ifconfig eth0 down")
+                       self.commands.append("ifconfig ath0 down")
+                       self.commands.append("ifconfig wlan0 up")
                if mode == 'wlan-mpci':
-                       system("ifconfig eth0 down")
-                       system("ifconfig wlan0 down")
-                       system("ifconfig ath0 up")              
+                       self.commands.append("ifconfig eth0 down")
+                       self.commands.append("ifconfig wlan0 down")
+                       self.commands.append("ifconfig ath0 up")                
                if mode == 'lan':                       
-                       system("ifconfig eth0 up")
-                       system("ifconfig wlan0 down")
-                       system("ifconfig ath0 down")
-               self.getInterfaces()    
-
-       def checkNetworkState(self):
-                # www.dream-multimedia-tv.de, www.heise.de, www.google.de
-               return system("ping -c 1 82.149.226.170") == 0 or \
-                       system("ping -c 1 193.99.144.85") == 0 or \
-                       system("ping -c 1 209.85.135.103") == 0
-
-       def restartNetwork(self):
-               iNetwork.deactivateNetworkConfig()
-               iNetwork.activateNetworkConfig()
+                       self.commands.append("ifconfig eth0 up")
+                       self.commands.append("ifconfig wlan0 down")
+                       self.commands.append("ifconfig ath0 down")
+               self.commands.append("/etc/init.d/avahi-daemon start")  
+               self.resetNetworkConsole.eBatch(self.commands, self.resetNetworkFinished, [mode,callback], debug=True)  
+
+       def resetNetworkFinished(self,extra_args):
+               (mode, callback) = extra_args
+               if len(self.resetNetworkConsole.appContainers) == 0:
+                       if callback is not None:
+                               callback(True,mode)
+
+       def checkNetworkState(self,statecallback):
+               # www.dream-multimedia-tv.de, www.heise.de, www.google.de
+               cmd1 = "ping -c 1 82.149.226.170"
+               cmd2 = "ping -c 1 193.99.144.85"
+               cmd3 = "ping -c 1 209.85.135.103"
+               self.PingConsole = Console()
+               self.PingConsole.ePopen(cmd1, self.checkNetworkStateFinished,statecallback)
+               self.PingConsole.ePopen(cmd2, self.checkNetworkStateFinished,statecallback)
+               self.PingConsole.ePopen(cmd3, self.checkNetworkStateFinished,statecallback)
+               
+       def checkNetworkStateFinished(self, result, retval,extra_args):
+               (statecallback) = extra_args
+               if self.PingConsole is not None:
+                       if retval == 0:
+                               self.PingConsole = None
+                               statecallback(self.NetworkState)
+                       else:
+                               self.NetworkState += 1
+                               if len(self.PingConsole.appContainers) == 0:
+                                       statecallback(self.NetworkState)
+               
+       def restartNetwork(self,callback = None):
+               self.restartConsole = Console()
+               self.commands = []
+               self.commands.append("/etc/init.d/avahi-daemon stop")
+               for iface in self.ifaces.keys():
+                       cmd = "ip addr flush " + iface
+                       self.commands.append(cmd)               
+               self.commands.append("/etc/init.d/networking stop")
+               self.commands.append("killall -9 udhcpc")
+               self.commands.append("rm /var/run/udhcpc*")
+               self.commands.append("/etc/init.d/networking start")
+               self.commands.append("/etc/init.d/avahi-daemon start")
+               self.restartConsole.eBatch(self.commands, self.restartNetworkFinished, callback, debug=True)
+       
+       def restartNetworkFinished(self,extra_args):
+               ( callback ) = extra_args
+               if callback is not None:
+                       callback(True)
 
        def getLinkState(self,iface,callback):
-               self.dataAvail = callback
                cmd = self.ethtool_bin + " " + iface
-               self.container.appClosed.append(self.cmdFinished)
-               self.container.dataAvail.append(callback)
-               self.container.execute(cmd)
-
-       def cmdFinished(self,retval):
-               self.container.appClosed.remove(self.cmdFinished)
-               self.container.dataAvail.remove(self.dataAvail)
-
-       def stopContainer(self):
-               self.container.kill()
-               
-       def ContainerRunning(self):
-               return self.container.running()
-
+               self.LinkConsole = Console()
+               self.LinkConsole.ePopen(cmd, self.getLinkStateFinished,callback)
+
+       def getLinkStateFinished(self, result, retval,extra_args):
+               (callback) = extra_args
+               if self.LinkConsole is not None:
+                       if len(self.LinkConsole.appContainers) == 0:
+                               callback(result)
+                       
+       def stopLinkStateConsole(self):
+               if self.LinkConsole is not None:
+                       self.LinkConsole = None
+
+       def stopDNSConsole(self):
+               if self.DnsConsole is not None:
+                       self.DnsConsole = None
+
+       def stopRestartConsole(self):
+               if self.restartConsole is not None:
+                       self.restartConsole = None
+                       
+       def stopGetInterfacesConsole(self):
+               if self.Console is not None:
+                       self.Console = None
+
+       def stopDeactivateInterfaceConsole(self):
+               if self.deactivateInterfaceConsole:
+                       self.deactivateInterfaceConsole = None
+                       
        def checkforInterface(self,iface):
                if self.getAdapterAttribute(iface, 'up') is True:
                        return True
@@ -384,13 +477,41 @@ class Network:
                        else:
                                return False
 
-       def checkDNSLookup(self):
-               return system("nslookup www.dream-multimedia-tv.de") == 0 or \
-                       system("nslookup www.heise.de") == 0 or \
-                       system("nslookup www.google.de")
-
-       def deactivateInterface(self,iface):
-               system("ifconfig " + iface + " down")
+       def checkDNSLookup(self,statecallback):
+               cmd1 = "nslookup www.dream-multimedia-tv.de"
+               cmd2 = "nslookup www.heise.de"
+               cmd3 = "nslookup www.google.de"
+               self.DnsConsole = Console()
+               self.DnsConsole.ePopen(cmd1, self.checkDNSLookupFinished,statecallback)
+               self.DnsConsole.ePopen(cmd2, self.checkDNSLookupFinished,statecallback)
+               self.DnsConsole.ePopen(cmd3, self.checkDNSLookupFinished,statecallback)
+               
+       def checkDNSLookupFinished(self, result, retval,extra_args):
+               (statecallback) = extra_args
+               if self.DnsConsole is not None:
+                       if retval == 0:
+                               self.DnsConsole = None
+                               statecallback(self.DnsState)
+                       else:
+                               self.DnsState += 1
+                               if len(self.DnsConsole.appContainers) == 0:
+                                       statecallback(self.DnsState)
+
+       def deactivateInterface(self,iface,callback = None):
+               self.deactivateInterfaceConsole = Console()
+               self.commands = []
+               cmd1 = "ip addr flush " + iface
+               cmd2 = "ifconfig " + iface + " down"
+               self.commands.append(cmd1)
+               self.commands.append(cmd2)
+               self.deactivateInterfaceConsole.eBatch(self.commands, self.deactivateInterfaceFinished, callback, debug=True)
+
+       def deactivateInterfaceFinished(self,extra_args):
+               callback = extra_args
+               if self.deactivateInterfaceConsole:
+                       if len(self.deactivateInterfaceConsole.appContainers) == 0:
+                               if callback is not None:
+                                       callback(True)
 
        def detectWlanModule(self):
                self.wlanmodule = None
@@ -411,6 +532,20 @@ class Network:
                                self.wlanmodule = 'zydas'
                return self.wlanmodule
        
+       def calc_netmask(self,nmask):
+               from struct import pack, unpack
+               from socket import inet_ntoa, inet_aton
+               mask = 1L<<31
+               xnet = (1L<<32)-1
+               cidr_range = range(0, 32)
+               cidr = long(nmask)
+               if cidr not in cidr_range:
+                       print 'cidr invalid: %d' % cidr
+                       return None
+               else:
+                       nm = ((1L<<cidr)-1)<<(32-cidr)
+                       netmask = str(inet_ntoa(pack('>L', nm)))
+                       return netmask
        
 iNetwork = Network()
 
index 3c7a147..f4e9108 100644 (file)
@@ -1,3 +1,5 @@
+from Tools.HardwareInfo import HardwareInfo
+
 from config import config, ConfigSubsection, ConfigSelection, ConfigFloat, \
        ConfigSatlist, ConfigYesNo, ConfigInteger, ConfigSubList, ConfigNothing, \
        ConfigSubDict, ConfigOnOff, ConfigDateTime
@@ -37,8 +39,8 @@ class SecConfigure:
                sec.addSatellite(orbpos)
                self.configuredSatellites.add(orbpos)
 
-       def addLNBSimple(self, sec, slotid, diseqcmode, toneburstmode = diseqcParam.NO, diseqcpos = diseqcParam.SENDNO, orbpos = 0, longitude = 0, latitude = 0, loDirection = 0, laDirection = 0, turningSpeed = rotorParam.FAST, useInputPower=True, inputPowerDelta=50):
-               if orbpos is None:
+       def addLNBSimple(self, sec, slotid, diseqcmode, toneburstmode = diseqcParam.NO, diseqcpos = diseqcParam.SENDNO, orbpos = 0, longitude = 0, latitude = 0, loDirection = 0, laDirection = 0, turningSpeed = rotorParam.FAST, useInputPower=True, inputPowerDelta=50, fastDiSEqC = False, setVoltageTone = True):
+               if orbpos is None or orbpos == 3601:
                        return
                #simple defaults
                sec.addLNB()
@@ -54,10 +56,8 @@ class SecConfigure:
                sec.setLNBThreshold(11700000)
                sec.setLNBIncreasedVoltage(lnbParam.OFF)
                sec.setRepeats(0)
-               sec.setFastDiSEqC(0)
+               sec.setFastDiSEqC(fastDiSEqC)
                sec.setSeqRepeat(0)
-               sec.setVoltageMode(switchParam.HV)
-               sec.setToneMode(switchParam.HILO)
                sec.setCommandOrder(0)
 
                #user values
@@ -69,6 +69,12 @@ class SecConfigure:
 
                if 0 <= diseqcmode < 3:
                        self.addSatellite(sec, orbpos)
+                       if setVoltageTone:
+                               sec.setVoltageMode(switchParam.HV)
+                               sec.setToneMode(switchParam.HILO)
+                       else:
+                               sec.setVoltageMode(switchParam._14V)
+                               sec.setToneMode(switchParam.OFF)
                elif (diseqcmode == 3): # diseqc 1.2
                        if self.satposdepends.has_key(slotid):
                                for slot in self.satposdepends[slotid]:
@@ -153,6 +159,7 @@ class SecConfigure:
                for slot in nim_slots:
                        x = slot.slot
                        nim = slot.config
+                       hw = HardwareInfo()
                        if slot.isCompatible("DVB-S"):
                                print "slot: " + str(x) + " configmode: " + str(nim.configMode.value)
                                if nim.configMode.value in [ "loopthrough", "satposdepends", "nothing" ]:
@@ -164,18 +171,25 @@ class SecConfigure:
                                        elif nim.configMode.value == "simple":          #simple config
                                                print "diseqcmode: ", nim.diseqcMode.value
                                                if nim.diseqcMode.value == "single":                    #single
-                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.NONE, diseqcpos = diseqcParam.SENDNO)
+                                                       if nim.simpleSingleSendDiSEqC.value:
+                                                               self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA)
+                                                       else:
+                                                               self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.NONE, diseqcpos = diseqcParam.SENDNO)
                                                elif nim.diseqcMode.value == "toneburst_a_b":           #Toneburst A/B
                                                        self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.A, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO)
                                                        self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.B, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO)
                                                elif nim.diseqcMode.value == "diseqc_a_b":              #DiSEqC A/B
-                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA)
-                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB)
+                                                       fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value
+                                                       setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value
+                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone)
+                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone)
                                                elif nim.diseqcMode.value == "diseqc_a_b_c_d":          #DiSEqC A/B/C/D
-                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA)
-                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB)
-                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcC.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BA)
-                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcD.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BB)
+                                                       fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value
+                                                       setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value
+                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone)
+                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone)
+                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcC.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone)
+                                                       self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcD.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone)
                                                elif nim.diseqcMode.value == "positioner":              #Positioner
                                                        if nim.latitudeOrientation.value == "north":
                                                                laValue = rotorParam.NORTH
@@ -185,12 +199,11 @@ class SecConfigure:
                                                                loValue = rotorParam.EAST
                                                        else:
                                                                loValue = rotorParam.WEST
-                                                       inputPowerDelta=50
+                                                       inputPowerDelta=nim.powerThreshold.value
                                                        useInputPower=False
                                                        turning_speed=0
                                                        if nim.powerMeasurement.value:
                                                                useInputPower=True
-                                                               inputPowerDelta=nim.powerThreshold.value
                                                                turn_speed_dict = { "fast": rotorParam.FAST, "slow": rotorParam.SLOW }
                                                                if turn_speed_dict.has_key(nim.turningSpeed.value):
                                                                        turning_speed = turn_speed_dict[nim.turningSpeed.value]
@@ -656,7 +669,7 @@ class NimManager:
        
        def canEqualTo(self, slotid):
                type = self.getNimType(slotid)
-               if self.getNimConfig(slotid) == "DVB-S2":
+               if type == "DVB-S2":
                        type = "DVB-S"
                nimList = self.getNimListOfType(type, slotid)
                for nim in nimList[:]:
@@ -664,10 +677,10 @@ class NimManager:
                        if mode.configMode.value == "loopthrough" or mode.configMode.value == "satposdepends":
                                nimList.remove(nim)
                return nimList
-       
+
        def canDependOn(self, slotid):
                type = self.getNimType(slotid)
-               if self.getNimConfig(slotid) == "DVB-S2":
+               if type == "DVB-S2":
                        type = "DVB-S"
                nimList = self.getNimListOfType(type, slotid)
                positionerList = []
@@ -680,6 +693,13 @@ class NimManager:
                                        if lnb != 0:
                                                nimHaveRotor = True
                                                break
+                               if not nimHaveRotor:
+                                       for sat in mode.advanced.sat.values():
+                                               lnb_num = int(sat.lnb.value)
+                                               diseqcmode = lnb_num and mode.advanced.lnb[lnb_num].diseqcMode.value or ""
+                                               if diseqcmode == "1_2":
+                                                       nimHaveRotor = True
+                                                       break
                        if nimHaveRotor:
                                alreadyConnected = False
                                for testnim in nimList:
@@ -725,12 +745,16 @@ class NimManager:
                        if configMode == "simple":
                                dm = nim.diseqcMode.value
                                if dm in ["single", "toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]:
-                                       list.append(self.satList[nim.diseqcA.index])
+                                       if nim.diseqcA.orbital_position != 3601:
+                                               list.append(self.satList[nim.diseqcA.index-1])
                                if dm in ["toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]:
-                                       list.append(self.satList[nim.diseqcB.index])
+                                       if nim.diseqcB.orbital_position != 3601:
+                                               list.append(self.satList[nim.diseqcB.index-1])
                                if dm == "diseqc_a_b_c_d":
-                                       list.append(self.satList[nim.diseqcC.index])
-                                       list.append(self.satList[nim.diseqcD.index])
+                                       if nim.diseqcC.orbital_position != 3601:
+                                               list.append(self.satList[nim.diseqcC.index-1])
+                                       if nim.diseqcD.orbital_position != 3601:
+                                               list.append(self.satList[nim.diseqcD.index-1])
                                if dm == "positioner":
                                        for x in self.satList:
                                                list.append(x)
@@ -834,6 +858,14 @@ def InitSecParams():
        x.addNotifier(lambda configElement: secClass.setParam(secClass.MOTOR_COMMAND_RETRIES, configElement.value))
        config.sec.motor_command_retries = x
 
+       x = ConfigInteger(default=50, limits = (0, 9999))
+       x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_RESET_CMD, configElement.value))
+       config.sec.delay_after_diseqc_reset_cmd = x
+
+       x = ConfigInteger(default=150, limits = (0, 9999))
+       x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_PERIPHERIAL_POWERON_CMD, configElement.value))
+       config.sec.delay_after_diseqc_peripherial_poweron_cmd = x
+
 # TODO add support for satpos depending nims to advanced nim configuration
 # so a second/third/fourth cable from a motorized lnb can used behind a
 # diseqc 1.0 / diseqc 1.1 / toneburst switch
@@ -842,6 +874,7 @@ def InitSecParams():
 
 def InitNimManager(nimmgr):
        InitSecParams()
+       hw = HardwareInfo()
 
        config.Nims = ConfigSubList()
        for x in range(len(nimmgr.nim_slots)):
@@ -883,10 +916,13 @@ def InitNimManager(nimmgr):
                                if id != x:
                                        choices.append((str(id), nimmgr.getNimDescription(id)))
                        nim.connectedTo = ConfigSelection(choices = choices)
-                       nim.diseqcA = getConfigSatlist(192, nimmgr.satList)
-                       nim.diseqcB = getConfigSatlist(130, nimmgr.satList)
-                       nim.diseqcC = ConfigSatlist(list = nimmgr.satList)
-                       nim.diseqcD = ConfigSatlist(list = nimmgr.satList)
+                       nim.simpleSingleSendDiSEqC = ConfigYesNo(default=False)
+                       nim.simpleDiSEqCSetVoltageTone = ConfigYesNo(default=True)
+                       nim.simpleDiSEqCOnlyOnSatChange = ConfigYesNo(default=False)
+                       nim.diseqcA = getConfigSatlist(192, [(3601, _('nothing connected'), 1)] + nimmgr.satList)
+                       nim.diseqcB = getConfigSatlist(130, [(3601, _('nothing connected'), 1)] + nimmgr.satList)
+                       nim.diseqcC = ConfigSatlist(list = [(3601, _('nothing connected'), 1)] + nimmgr.satList)
+                       nim.diseqcD = ConfigSatlist(list = [(3601, _('nothing connected'), 1)] + nimmgr.satList)
                        nim.positionerMode = ConfigSelection(
                                choices = [
                                        ("usals", _("USALS")),
@@ -897,7 +933,7 @@ def InitNimManager(nimmgr):
                        nim.latitude = ConfigFloat(default=[50,767], limits=[(0,359),(0,999)])
                        nim.latitudeOrientation = ConfigSelection(choices={"north": _("North"), "south": _("South")}, default="north")
                        nim.powerMeasurement = ConfigYesNo(default=True)
-                       nim.powerThreshold = ConfigInteger(default=50, limits=(0, 100))
+                       nim.powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm8000" and 15 or 50, limits=(0, 100))
                        nim.turningSpeed = ConfigSelection(choices = [("fast", _("Fast")), ("slow", _("Slow")), ("fast epoch", _("Fast epoch")) ], default = "fast")
                        btime = datetime(1970, 1, 1, 7, 0);
                        nim.fastTurningBegin = ConfigDateTime(default = mktime(btime.timetuple()), formatstring = _("%H:%M"), increment = 900)
@@ -972,7 +1008,7 @@ def InitNimManager(nimmgr):
                                nim.advanced.lnb[x].latitude = ConfigFloat(default = [50,767], limits = [(0,359),(0,999)])
                                nim.advanced.lnb[x].latitudeOrientation = ConfigSelection(choices = [("north", _("North")), ("south", _("South"))], default = "north")
                                nim.advanced.lnb[x].powerMeasurement = ConfigYesNo(default=True)
-                               nim.advanced.lnb[x].powerThreshold = ConfigInteger(default=50, limits=(0, 100))
+                               nim.advanced.lnb[x].powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm8000" and 15 or 50, limits=(0, 100))
                                nim.advanced.lnb[x].turningSpeed = ConfigSelection(choices = [("fast", _("Fast")), ("slow", _("Slow")), ("fast epoch", _("Fast epoch"))], default = "fast")
                                btime = datetime(1970, 1, 1, 7, 0);
                                nim.advanced.lnb[x].fastTurningBegin = ConfigDateTime(default=mktime(btime.timetuple()), formatstring = _("%H:%M"), increment = 600)
index 744ee3a..c9ebe47 100644 (file)
@@ -58,6 +58,7 @@ class PlaylistIOM3U(PlaylistIO):
        
        def open(self, filename):
                self.clear()
+               self.displayname = None
                try:
                        file = open(filename, "r")
                except IOError:
@@ -66,14 +67,22 @@ class PlaylistIOM3U(PlaylistIO):
                        entry = file.readline().strip()
                        if entry == "":
                                break
-                       if entry[0] != "#":
+                       if entry.startswith("#EXTINF:"):
+                               extinf = entry.split(',',1)
+                               if len(extinf) > 1:
+                                       self.displayname = extinf[1]
                                # TODO: use e2 facilities to create a service ref from file
+                       elif entry[0] != "#":
                                if entry[0] == "/":
-                                       self.addService(ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry))
+                                       sref = ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry)
                                elif entry.startswith("http"):
-                                       self.addService(ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry.replace(':',"%3a")))
+                                       sref = ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry.replace(':',"%3a"))
                                else:
-                                       self.addService(ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + os.path.dirname(filename) + "/" + entry))
+                                       sref = ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + os.path.dirname(filename) + "/" + entry)
+                               if self.displayname:
+                                       sref.ref.setName(self.displayname)
+                                       self.displayname = None
+                               self.addService(sref)
                file.close()
                return self.list
                
index e793cdc..031c9ca 100644 (file)
@@ -1,9 +1,7 @@
-import string
 import NavigationInstance
 from time import localtime
-from Components.NimManager import nimmanager
 from ServiceReference import ServiceReference
-from enigma import iServiceInformation, eServiceCenter
+from enigma import iServiceInformation, eServiceCenter, eServiceReference
 
 class TimerSanityCheck:
        def __init__(self, timerlist, newtimer=None):
@@ -54,6 +52,7 @@ class TimerSanityCheck:
                # index -1 for the new Timer, 0..n index of the existing timers
                # count of running timers
 
+               serviceHandler = eServiceCenter.getInstance()
                print "checkTimerlist"
 # create a list with all start and end times
 # split it into recurring and singleshot timers
@@ -149,9 +148,7 @@ class TimerSanityCheck:
                fakeRecList = []
                ConflictTimer = None
                ConflictTunerType = None
-               ConflictSlot = None
                newTimerTunerType = None
-               newTimerTunerSlot = None
                cnt = 0
                idx = 0
                overlaplist = []
@@ -162,24 +159,45 @@ class TimerSanityCheck:
                        else:
                                timer = self.timerlist[event[2]]
                        if event[1] == self.bflag:
-                               fakeRecService = NavigationInstance.instance.recordService(timer.service_ref)
-                               fakeRecResult = fakeRecService.start(True)
-                               feinfo = fakeRecService.frontendInfo().getFrontendData()
-                               tunerType = feinfo.get("tuner_type")
-                               tunerSlot = feinfo.get("tuner_number")
+                               tunerType = [ ]
+                               fakeRecService = NavigationInstance.instance.recordService(timer.service_ref, True)
+                               if fakeRecService:
+                                       fakeRecResult = fakeRecService.start(True)
+                               else:
+                                       fakeRecResult = -1
+                               if not fakeRecResult: # tune okay
+                                       feinfo = fakeRecService.frontendInfo().getFrontendData()
+                                       tunerType.append(feinfo.get("tuner_type"))
+                               else: # tune failed.. so we must go another way to get service type (DVB-S, DVB-T, DVB-C)
+
+                                       def getServiceType(ref): # helper function to get a service type of a service reference
+                                               serviceInfo = serviceHandler.info(ref)
+                                               serviceInfo = serviceInfo and serviceInfo.getInfoObject(ref, iServiceInformation.sTransponderData)
+                                               if serviceInfo:
+                                                       return { "Satellite" : "DVB-S", "Cable" : "DVB-C", "Terrestrial" : "DVB-T"}[serviceInfo["type"]]
+
+                                       ref = timer.service_ref.ref
+                                       if ref.flags & eServiceReference.isGroup: # service group ?
+                                               serviceList = serviceHandler.list(ref) # get all alternative services
+                                               if serviceList:
+                                                       for ref in serviceList.getContent("R"): # iterate over all group service references
+                                                               type = getServiceType(ref)
+                                                               if not type in tunerType: # just add single time
+                                                                       tunerType.append(type) 
+                                       else:
+                                               tunerType.append(getServiceType(ref))
+
                                if event[2] == -1: # new timer
                                        newTimerTunerType = tunerType
-                                       newTimerTunerSlot = tunerSlot
-                               overlaplist.append((fakeRecResult, timer, tunerType, tunerSlot))
+                               overlaplist.append((fakeRecResult, timer, tunerType))
                                fakeRecList.append((timer, fakeRecService))
                                if fakeRecResult:
                                        if ConflictTimer is None: # just take care of the first conflict
                                                ConflictTimer = timer
                                                ConflictTunerType = tunerType
-                                               ConflictTunerSlot = tunerSlot
                        elif event[1] == self.eflag:
                                for fakeRec in fakeRecList:
-                                       if timer == fakeRec[0]:
+                                       if timer == fakeRec[0] and fakeRec[1]:
                                                NavigationInstance.instance.stopRecordService(fakeRec[1])
                                                fakeRecList.remove(fakeRec)
                                del fakeRec
@@ -211,7 +229,6 @@ class TimerSanityCheck:
                                                if nt and kt:
                                                        ConflictTimer = self.newtimer
                                                        ConflictTunerType = newTimerTunerType
-                                                       ConflictSlot = newTimerTunerSlot
                                                        break
 
                self.simultimer = [ ConflictTimer ]
@@ -223,8 +240,11 @@ class TimerSanityCheck:
                                else:
                                        continue
                                for entry in event[4]:
-                                       if not self.simultimer.count(entry[1]) and (entry[2] == ConflictTunerType or entry[3] == ConflictTunerSlot):
-                                               self.simultimer.append(entry[1])
+                                       if not entry[1] in self.simultimer:
+                                               for x in entry[2]:
+                                                       if x in ConflictTunerType:
+                                                               self.simultimer.append(entry[1])
+                                                               break
 
                if len(self.simultimer) < 2:
                        print "Bug: unknown Conflict!"
index 714d366..6ed8784 100644 (file)
@@ -1,5 +1,5 @@
 from Components.Harddisk import harddiskmanager
-from config import ConfigSubsection, ConfigYesNo, config, ConfigSelection, ConfigText, ConfigNumber, ConfigSet
+from config import ConfigSubsection, ConfigYesNo, config, ConfigSelection, ConfigText, ConfigNumber, ConfigSet, ConfigLocations
 from enigma import Misc_Options, setTunerTypePriorityOrder;
 from SystemInfo import SystemInfo
 import os
@@ -30,6 +30,9 @@ def InitUsageConfig():
                ("standard", _("standard")), ("swap", _("swap PiP and main picture")),
                ("swapstop", _("move PiP to main picture")), ("stop", _("stop PiP")) ])
 
+       config.usage.allowed_timeshift_paths = ConfigLocations(default = ["/media/hdd/"])
+       config.usage.timeshift_path = ConfigText(default = "/media/hdd")
+
        config.usage.on_movie_start = ConfigSelection(default = "ask", choices = [
                ("ask", _("Ask user")), ("resume", _("Resume from last position")), ("beginning", _("Start from the beginning")) ])
        config.usage.on_movie_stop = ConfigSelection(default = "ask", choices = [
old mode 100644 (file)
new mode 100755 (executable)
index b448ca6..4d57bbb
@@ -34,6 +34,7 @@ class ConfigElement(object):
                self.save_disabled = False
                self.notifiers = []
                self.enabled = True
+               self.callNotifiersOnSaveAndCancel = False
 
        # you need to override this to do input validation
        def setValue(self, value):
@@ -66,9 +67,13 @@ class ConfigElement(object):
                        self.saved_value = None
                else:
                        self.saved_value = self.tostring(self.value)
+               if self.callNotifiersOnSaveAndCancel:
+                       self.changed()
 
        def cancel(self):
                self.load()
+               if self.callNotifiersOnSaveAndCancel:
+                       self.changed()
 
        def isChanged(self):
                sv = self.saved_value
@@ -513,6 +518,7 @@ class ConfigIP(ConfigSequence):
                self.auto_jump = auto_jump
 
        def handleKey(self, key):
+               
                if key == KEY_LEFT:
                        if self.marked_block > 0:
                                self.marked_block -= 1
@@ -531,8 +537,14 @@ class ConfigIP(ConfigSequence):
                        self.marked_block = len(self.limits)-1
                        self.overwrite = True
 
-               if key in KEY_NUMBERS:
-                       number = getKeyNumber(key)
+               if key in KEY_NUMBERS or key == KEY_ASCII:
+                       if key == KEY_ASCII:
+                               code = getPrevAsciiCode()
+                               if code < 48 or code > 57:
+                                       return
+                               number = code - 48
+                       else:   
+                               number = getKeyNumber(key)
                        oldvalue = self._value[self.marked_block]
                        
                        if self.overwrite:
@@ -770,12 +782,12 @@ class ConfigText(ConfigElement, NumericalTextInput):
 
        def getValue(self):
                return self.text.encode("utf-8")
-               
+
        def setValue(self, val):
                try:
                        self.text = val.decode("utf-8")
                except UnicodeDecodeError:
-                       self.text = val
+                       self.text = val.decode("utf-8", "ignore")
                        print "Broken UTF8!"
 
        value = property(getValue, setValue)
index 8173b37..2c52330 100644 (file)
@@ -4,3 +4,4 @@ install_PYTHON =        \
        __init__.py \
        plugin.py
  
+install_DATA = maintainer.info
diff --git a/lib/python/Plugins/DemoPlugins/TestPlugin/maintainer.info b/lib/python/Plugins/DemoPlugins/TestPlugin/maintainer.info
new file mode 100644 (file)
index 0000000..4f28561
--- /dev/null
@@ -0,0 +1,2 @@
+tmbinc@elitedvb.net
+Demo-Plugin
index 1f49a9e..a63562c 100644 (file)
@@ -50,6 +50,8 @@ class Test(Screen):
        
        def mycallback(self, answer):
                print "answer:", answer
+               if answer:
+                       raise "test-crash"
                self.close()
        
        def keyLeft(self):
index 8d02cb2..112a221 100644 (file)
@@ -1,5 +1,5 @@
 from Tools.Directories import fileExists
-from Components.config import config, ConfigSubsection, ConfigInteger, ConfigYesNo, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence
+from Components.config import config, ConfigSubsection, ConfigInteger, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence
 
 class ConfigColor(ConfigSequence):
        def __init__(self):
@@ -32,6 +32,7 @@ class DVDProject:
                self.settings = ConfigSubsection()
                self.settings.name = ConfigText(fixed_size = False, visible_width = 40)
                self.settings.authormode = ConfigSelection(choices = [("menu_linked", _("Linked titles with a DVD menu")), ("just_linked", _("Direct playback of linked titles without menu")), ("menu_seperate", _("Seperate titles with a main menu")), ("data_ts", _("Dreambox format data DVD (HDTV compatible)"))])
+               self.settings.titlesetmode = ConfigSelection(choices = [("single", _("Simple titleset (compatibility for legacy players)")), ("multi", _("Complex (allows mixing audio tracks and aspects)"))], default="multi")
                self.settings.output = ConfigSelection(choices = [("iso", _("Create DVD-ISO")), ("dvd", _("Burn DVD"))])
                self.settings.isopath = ConfigText(fixed_size = False, visible_width = 40)
                self.settings.dataformat = ConfigSelection(choices = [("iso9660_1", ("ISO9660 Level 1")), ("iso9660_4", ("ISO9660 version 2")), ("udf", ("UDF"))])                      
@@ -46,7 +47,6 @@ class DVDProject:
                self.settings.font_size = ConfigPixelvals()
                self.settings.space = ConfigPixelvals()
                self.settings.vmgm = ConfigFilename()
-               self.settings.autochapter = ConfigInteger(default = 0, limits = (0, 99))
                self.filekeys = ["vmgm", "menubg", "menuaudio", "font_face", "isopath"]
 
        def addService(self, service):
index 1bfb3d6..b1c627a 100644 (file)
@@ -1,17 +1,32 @@
+from Components.config import config, ConfigSubsection, ConfigSubList, ConfigInteger, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence, ConfigYesNo
+
+class ConfigFixedText(ConfigText):
+       def __init__(self, text, visible_width=60):
+               ConfigText.__init__(self, default = text, fixed_size = True, visible_width = visible_width)
+       def handleKey(self, key):
+               pass
+
 class DVDTitle:
        def __init__(self):
+               self.properties = ConfigSubsection()
+               self.properties.menutitle = ConfigText(fixed_size = False, visible_width = 80)
+               self.properties.menusubtitle = ConfigText(fixed_size = False, visible_width = 80)
+               self.DVBname = _("Title")
+               self.DVBdescr = _("Description")
+               self.DVBchannel = _("Channel")
+               self.properties.aspect = ConfigSelection(choices = [("4:3", _("4:3")), ("16:9", _("16:9"))])
+               self.properties.widescreen = ConfigSelection(choices = [("nopanscan", "nopanscan"), ("noletterbox", "noletterbox")])
+               self.properties.autochapter = ConfigInteger(default = 0, limits = (0, 60))
+               self.properties.audiotracks = ConfigSubList()
                self.cuesheet = [ ]
                self.source = None
-               self.name = ""
-               self.descr = ""
                self.filesize = 0
                self.estimatedDiskspace = 0
                self.inputfile = ""
                self.cutlist = [ ]
                self.chaptermarks = [ ]
-               self.audiotracks = [ ]
                self.timeCreate = None
-               self.sVideoType = -1
+               self.VideoType = -1
 
        def addService(self, service):
                from os import path
@@ -21,18 +36,61 @@ class DVDTitle:
                self.source = service
                serviceHandler = eServiceCenter.getInstance()
                info = serviceHandler.info(service)
-               self.descr = info and " " + info.getInfoString(service, iServiceInformation.sDescription) or ""
+               sDescr = info and " " + info.getInfoString(service, iServiceInformation.sDescription) or ""
+               self.DVBdescr = sDescr
                sTimeCreate = info.getInfo(service, iServiceInformation.sTimeCreate)
                if sTimeCreate > 1:
                        self.timeCreate = localtime(sTimeCreate)
                serviceref = ServiceReference(info.getInfoString(service, iServiceInformation.sServiceref))
-               self.name = info and info.getName(service) or "Title" + t.descr
-               self.channel = serviceref.getServiceName()
+               name = info and info.getName(service) or "Title" + sDescr
+               self.DVBname = name
+               self.DVBchannel = serviceref.getServiceName()
                self.inputfile = service.getPath()
                self.filesize = path.getsize(self.inputfile)
                self.estimatedDiskspace = self.filesize
                self.length = info.getLength(service)
 
+       def initDVDmenuText(self, project, track):
+               self.properties.menutitle.setValue(self.formatDVDmenuText(project.settings.titleformat.getValue(), track))
+               self.properties.menusubtitle.setValue(self.formatDVDmenuText(project.settings.subtitleformat.getValue(), track))
+
+       def formatDVDmenuText(self, template, track):
+               properties = self.properties
+               template = template.replace("$i", str(track))
+               template = template.replace("$t", self.DVBname)
+               template = template.replace("$d", self.DVBdescr)
+               template = template.replace("$c", str(len(self.chaptermarks)+1))
+               template = template.replace("$f", self.inputfile)
+               template = template.replace("$C", self.DVBchannel)
+               
+               #if template.find("$A") >= 0:
+               from TitleProperties import languageChoices
+               audiolist = [ ]
+               for audiotrack in self.properties.audiotracks:
+                       active = audiotrack.active.getValue()
+                       if active:
+                               trackstring = audiotrack.format.getValue()
+                               language = audiotrack.language.getValue()
+                               if languageChoices.langdict.has_key(language):
+                                       trackstring += ' (' + languageChoices.langdict[language] + ')'
+                               audiolist.append(trackstring)
+               audiostring = ', '.join(audiolist)
+               template = template.replace("$A", audiostring)
+               
+               if template.find("$l") >= 0:
+                       l = self.length
+                       lengthstring = "%d:%02d:%02d" % (l/3600, l%3600/60, l%60)
+                       template = template.replace("$l", lengthstring)
+               if self.timeCreate:
+                       template = template.replace("$Y", str(self.timeCreate[0]))
+                       template = template.replace("$M", str(self.timeCreate[1]))
+                       template = template.replace("$D", str(self.timeCreate[2]))
+                       timestring = "%d:%02d" % (self.timeCreate[3], self.timeCreate[4])
+                       template = template.replace("$T", timestring)
+               else:
+                       template = template.replace("$Y", "").replace("$M", "").replace("$D", "").replace("$T", "")
+               return template
+       
        def produceFinalCuesheet(self):
                CUT_TYPE_IN = 0
                CUT_TYPE_OUT = 1
@@ -78,9 +136,21 @@ class DVDTitle:
                        self.estimatedDiskspace = usedsize
                        self.length = accumulated_in / 90000
 
-       def produceAutoChapter(self, minutes):
-               if len(self.chaptermarks) < 1:
-                       chapterpts = self.cutlist[0]
-                       while chapterpts < self.length*90000:
+       def getChapterMarks(self, template="$h:$m:$s.$t"):
+               timestamps = [ ]
+               chapters = [ ]
+               minutes = self.properties.autochapter.getValue()
+               if len(self.chaptermarks) < 1 and minutes > 0:
+                       chapterpts = 0
+                       while chapterpts < (self.length-60*minutes)*90000:
                                chapterpts += 90000 * 60 * minutes
-                               self.chaptermarks.append(chapterpts)
+                               chapters.append(chapterpts)
+               else:
+                       chapters = self.chaptermarks
+               for p in chapters:
+                       timestring = template.replace("$h", str(p / (90000 * 3600)))
+                       timestring = timestring.replace("$m", ("%02d" % (p % (90000 * 3600) / (90000 * 60))))
+                       timestring = timestring.replace("$s", ("%02d" % (p % (90000 * 60) / 90000)))
+                       timestring = timestring.replace("$t", ("%03d" % ((p % 90000) / 90)))
+                       timestamps.append(timestring)
+               return timestamps
\ No newline at end of file
index d4e6a37..836c9fb 100644 (file)
@@ -9,6 +9,7 @@ from Components.Task import Task, Job, job_manager, Condition
 from Components.ScrollLabel import ScrollLabel
 from Components.Harddisk import harddiskmanager
 from Components.Console import Console
+from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
 
 class DVDToolbox(Screen):
        skin = """
@@ -54,6 +55,7 @@ class DVDToolbox(Screen):
                    "pageDown": self.pageDown
                })
                self.update()
+               hotplugNotifier.append(self.update)
                
        def pageUp(self):
                self["details"].pageUp()
@@ -61,7 +63,7 @@ class DVDToolbox(Screen):
        def pageDown(self):
                self["details"].pageDown()
 
-       def update(self):
+       def update(self, dev="", media_state=""):
                self["space_label"].text = _("Please wait... Loading list...")
                self["info"].text = ""
                self["details"].setText("")
@@ -141,6 +143,7 @@ class DVDToolbox(Screen):
 
        def exit(self):
                del self.Console
+               hotplugNotifier.remove(self.update)
                self.close()
 
 class DVDformatJob(Job):
index d9831e6..7d8de8c 100644 (file)
@@ -3,8 +3,9 @@
        <settings
                name="Dreambox DVD record"
                authormode="menu_linked"
+               titlesetmode="multi"
                titleformat="$i. $t"
-               subtitleformat="$D.$M.$Y, $T $C, $d ($c chapters)"
+               subtitleformat="$D.$M.$Y, $T $C, $d"
                vmgm="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/vmgmdream.mpg"
                menubg="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/dreamdvd_boat.jpg"
                menuaudio="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/silence.mp2"
index cb65f56..be89eba 100644 (file)
@@ -3,7 +3,7 @@ installdir = $(LIBDIR)/enigma2/python/Plugins/Extensions/DVDBurn
 install_PYTHON =       \
        __init__.py \
        plugin.py \
-       DVDProject.py DVDTitle.py TitleCutter.py TitleList.py Process.py ProjectSettings.py DVDToolbox.py
+       DVDProject.py DVDTitle.py TitleCutter.py TitleList.py TitleProperties.py Process.py ProjectSettings.py DVDToolbox.py
 
 install_DATA = *.xml *.jpg *.mpg *.mp2 *.png
 
index 4905459..89ca90f 100644 (file)
@@ -85,23 +85,34 @@ class DemuxTask(Task):
                title = job.project.titles[job.i]
                self.global_preconditions.append(DiskspacePrecondition(title.estimatedDiskspace))
                self.setTool("/usr/bin/projectx")
-               self.generated_files = [ ]
+               self.args += [inputfile, "-demux", "-out", self.job.workspace ]
                self.end = 300
                self.prog_state = 0
                self.weighting = 1000
                self.cutfile = self.job.workspace + "/cut_%d.Xcl" % (job.i+1)
                self.cutlist = title.cutlist
-               self.args += [inputfile, "-demux", "-out", self.job.workspace ]
+               self.currentPID = None
+               self.relevantAudioPIDs = [ ]
+               self.getRelevantAudioPIDs(title)
+               self.generated_files = [ ]
+               self.mplex_streamfiles = [ ]
                if len(self.cutlist) > 1:
                        self.args += [ "-cut", self.cutfile ]
 
        def prepare(self):
                self.writeCutfile()
 
+       def getRelevantAudioPIDs(self, title):
+               for audiotrack in title.properties.audiotracks:
+                       if audiotrack.active.getValue():
+                               self.relevantAudioPIDs.append(audiotrack.pid.getValue())
+
        def processOutputLine(self, line):
                line = line[:-1]
                MSG_NEW_FILE = "---> new File: "
                MSG_PROGRESS = "[PROGRESS] "
+               MSG_NEW_MP2 = "--> MPEG Audio (0x"
+               MSG_NEW_AC3 = "--> AC-3/DTS Audio on PID "
 
                if line.startswith(MSG_NEW_FILE):
                        file = line[len(MSG_NEW_FILE):]
@@ -111,10 +122,14 @@ class DemuxTask(Task):
                elif line.startswith(MSG_PROGRESS):
                        progress = line[len(MSG_PROGRESS):]
                        self.haveProgress(progress)
+               elif line.startswith(MSG_NEW_MP2) or line.startswith(MSG_NEW_AC3):
+                       self.currentPID = str(int(line.rstrip()[-6:].rsplit('0x',1)[-1],16))
 
        def haveNewFile(self, file):
-               print "PRODUCED FILE [%s]" % file
+               print "[DemuxTask] produced file:", file, self.currentPID
                self.generated_files.append(file)
+               if self.currentPID in self.relevantAudioPIDs or file.endswith("m2v"):
+                       self.mplex_streamfiles.append(file)
 
        def haveProgress(self, progress):
                #print "PROGRESS [%s]" % progress
@@ -131,7 +146,6 @@ class DemuxTask(Task):
                                if p > self.progress:
                                        self.progress = p
                        except ValueError:
-                               print "val error"
                                pass
 
        def writeCutfile(self):
@@ -151,8 +165,8 @@ class DemuxTask(Task):
        def cleanup(self, failed):
                if failed:
                        import os
-                       for f in self.generated_files:
-                               os.remove(f)
+                       for file in self.generated_files.itervalues():
+                               os.remove(file)
 
 class MplexTaskPostcondition(Condition):
        def check(self, task):
@@ -185,9 +199,9 @@ class MplexTask(Task):
                # we don't want the ReturncodePostcondition in this case because for right now we're just gonna ignore the fact that mplex fails with a buffer underrun error on some streams (this always at the very end)
 
        def prepare(self):
-               self.error = None                       
+               self.error = None
                if self.demux_task:
-                       self.args += self.demux_task.generated_files
+                       self.args += self.demux_task.mplex_streamfiles
 
        def processOutputLine(self, line):
                print "[MplexTask] ", line[:-1]
@@ -206,7 +220,7 @@ class RemoveESFiles(Task):
 
        def prepare(self):
                self.args += ["-f"]
-               self.args += self.demux_task.generated_files
+               self.args += self.demux_task.generated_files.values()
                self.args += [self.demux_task.cutfile]
 
 class DVDAuthorTask(Task):
@@ -411,27 +425,6 @@ class PreviewTaskPostcondition(Condition):
        def getErrorMessage(self, task):
                return "Cancel"
 
-def formatTitle(template, title, track):
-       template = template.replace("$i", str(track))
-       template = template.replace("$t", title.name)
-       template = template.replace("$d", title.descr)
-       template = template.replace("$c", str(len(title.chaptermarks)+1))
-       template = template.replace("$A", str(title.audiotracks))
-       template = template.replace("$f", title.inputfile)
-       template = template.replace("$C", title.channel)
-       l = title.length
-       lengthstring = "%d:%02d:%02d" % (l/3600, l%3600/60, l%60)
-       template = template.replace("$l", lengthstring)
-       if title.timeCreate:
-               template = template.replace("$Y", str(title.timeCreate[0]))
-               template = template.replace("$M", str(title.timeCreate[1]))
-               template = template.replace("$D", str(title.timeCreate[2]))
-               timestring = "%d:%02d" % (title.timeCreate[3], title.timeCreate[4])
-               template = template.replace("$T", timestring)
-       else:
-               template = template.replace("$Y", "").replace("$M", "").replace("$D", "").replace("$T", "")
-       return template.decode("utf-8")
-
 class ImagingPostcondition(Condition):
        def check(self, task):
                return task.returncode == 0
@@ -518,14 +511,13 @@ class MenuImageTask(Task):
                                menu_end_title = nr_titles+1
                        menu_i = 0
                        for title_no in range( menu_start_title , menu_end_title ):
-                               i = title_no-1
-                               top = s_top + ( menu_i * rowheight )
                                menu_i += 1
-                               title = self.job.project.titles[i]
-                               titleText = formatTitle(s.titleformat.getValue(), title, title_no)
+                               title = self.job.project.titles[title_no-1]
+                               top = s_top + ( menu_i * rowheight )
+                               titleText = title.formatDVDmenuText(s.titleformat.getValue(), title_no).decode("utf-8")
                                draw_bg.text((s_left,top), titleText, fill=self.Menus.color_button, font=fonts[1])
                                draw_high.text((s_left,top), titleText, fill=1, font=self.Menus.fonts[1])
-                               subtitleText = formatTitle(s.subtitleformat.getValue(), title, title_no)
+                               subtitleText = title.formatDVDmenuText(s.subtitleformat.getValue(), title_no).decode("utf-8")
                                draw_bg.text((s_left,top+36), subtitleText, fill=self.Menus.color_button, font=fonts[2])
                                bottom = top+rowheight
                                if bottom > self.Menus.imgheight:
@@ -607,7 +599,7 @@ class Menus:
                        menuoutputfilename = job.workspace+"/dvdmenu"+num+".mpg"
                        spumuxTask(job, spuxmlfilename, menubgmpgfilename, menuoutputfilename)
                
-def CreateAuthoringXML(job):
+def CreateAuthoringXML_singleset(job):
        nr_titles = len(job.project.titles)
        mode = job.project.settings.authormode.getValue()
        authorxml = []
@@ -649,9 +641,7 @@ def CreateAuthoringXML(job):
                authorxml.append('   </menus>\n')
        authorxml.append('   <titles>\n')
        for i in range( nr_titles ):
-               #for audiotrack in job.project.titles[i].audiotracks:
-                       #authorxml.append('    <audio lang="'+audiotrack[0][:2]+'" format="'+audiotrack[1]+'" />\n')
-               chapters = ','.join(["%d:%02d:%02d.%03d" % (p / (90000 * 3600), p % (90000 * 3600) / (90000 * 60), p % (90000 * 60) / 90000, (p % 90000) / 90) for p in job.project.titles[i].chaptermarks])
+               chapters = ','.join(job.project.titles[i].getChapterMarks())
                title_no = i+1
                title_filename = job.workspace + "/dvd_title_%d.mpg" % (title_no)
                if job.menupreview:
@@ -677,6 +667,84 @@ def CreateAuthoringXML(job):
                f.write(x)
        f.close()
 
+def CreateAuthoringXML_multiset(job):
+       nr_titles = len(job.project.titles)
+       mode = job.project.settings.authormode.getValue()
+       authorxml = []
+       authorxml.append('<?xml version="1.0" encoding="utf-8"?>\n')
+       authorxml.append(' <dvdauthor dest="' + (job.workspace+"/dvd") + '" jumppad="yes">\n')
+       authorxml.append('  <vmgm>\n')
+       authorxml.append('   <menus>\n')
+       authorxml.append('    <video aspect="4:3"/>\n')
+       if mode.startswith("menu"):
+               for menu_count in range(1 , job.nr_menus+1):
+                       authorxml.append('    <pgc>\n')
+                       menu_start_title = (menu_count-1)*job.titles_per_menu + 1
+                       menu_end_title = (menu_count)*job.titles_per_menu + 1
+                       if menu_end_title > nr_titles:
+                               menu_end_title = nr_titles+1
+                       for i in range( menu_start_title , menu_end_title ):
+                               authorxml.append('     <button name="button' + (str(i).zfill(2)) + '"> jump titleset ' + str(i) +' title 1; </button>\n')
+                       if menu_count > 1:
+                               authorxml.append('     <button name="button_prev"> jump menu ' + str(menu_count-1) + '; </button>\n')
+                       if menu_count < job.nr_menus:
+                               authorxml.append('     <button name="button_next"> jump menu ' + str(menu_count+1) + '; </button>\n')
+                       menuoutputfilename = job.workspace+"/dvdmenu"+str(menu_count)+".mpg"
+                       authorxml.append('     <vob file="' + menuoutputfilename + '" pause="inf"/>\n')
+                       authorxml.append('    </pgc>\n')
+       else:
+               authorxml.append('    <pgc>\n')
+               authorxml.append('     <vob file="' + job.project.settings.vmgm.getValue() + '" />\n' )
+               authorxml.append('     <post> jump titleset 1 title 1; </post>\n')
+               authorxml.append('    </pgc>\n')
+       authorxml.append('   </menus>\n')
+       authorxml.append('  </vmgm>\n')
+
+       for i in range( nr_titles ):
+               title = job.project.titles[i]
+               authorxml.append('  <titleset>\n')
+               authorxml.append('   <titles>\n')
+               for audiotrack in title.properties.audiotracks:
+                       active = audiotrack.active.getValue()
+                       if active:
+                               format = audiotrack.format.getValue()
+                               language = audiotrack.language.getValue()
+                               audio_tag = '    <audio format="%s"' % format
+                               if language != "nolang":
+                                       audio_tag += ' lang="%s"' % language
+                               audio_tag += ' />\n'
+                               authorxml.append(audio_tag)
+               aspect = title.properties.aspect.getValue()
+               video_tag = '    <video aspect="'+aspect+'"'
+               if title.properties.widescreen.getValue() == "4:3":
+                       video_tag += ' widescreen="'+title.properties.widescreen.getValue()+'"'
+               video_tag += ' />\n'
+               authorxml.append(video_tag)
+               chapters = ','.join(title.getChapterMarks())
+               title_no = i+1
+               title_filename = job.workspace + "/dvd_title_%d.mpg" % (title_no)
+               if job.menupreview:
+                       LinkTS(job, job.project.settings.vmgm.getValue(), title_filename)
+               else:
+                       MakeFifoNode(job, title_no)
+               if mode.endswith("linked") and title_no < nr_titles:
+                       post_tag = "jump titleset %d title 1;" % ( title_no+1 )
+               elif mode.startswith("menu"):
+                       post_tag = "call vmgm menu 1;"
+               else:   post_tag = ""
+
+               authorxml.append('    <pgc>\n')
+               authorxml.append('     <vob file="' + title_filename + '" chapters="' + chapters + '" />\n')
+               authorxml.append('     <post> ' + post_tag + ' </post>\n')
+               authorxml.append('    </pgc>\n')
+               authorxml.append('   </titles>\n')
+               authorxml.append('  </titleset>\n')
+       authorxml.append(' </dvdauthor>\n')
+       f = open(job.workspace+"/dvdauthor.xml", "w")
+       for x in authorxml:
+               f.write(x)
+       f.close()
+
 def getISOfilename(isopath, volName):
        from Tools.Directories import fileExists
        i = 0
@@ -703,7 +771,10 @@ class DVDJob(Job):
                CheckDiskspaceTask(self)
                if self.project.settings.authormode.getValue().startswith("menu") or self.menupreview:
                        Menus(self)
-               CreateAuthoringXML(self)
+               if self.project.settings.titlesetmode.getValue() == "multi":
+                       CreateAuthoringXML_multiset(self)
+               else:
+                       CreateAuthoringXML_singleset(self)
 
                DVDAuthorTask(self)
                
@@ -713,14 +784,14 @@ class DVDJob(Job):
                        PreviewTask(self, self.workspace + "/dvd/VIDEO_TS/")
                else:
                        for self.i in range(nr_titles):
-                               title = self.project.titles[self.i]
+                               self.title = self.project.titles[self.i]
                                link_name =  self.workspace + "/source_title_%d.ts" % (self.i+1)
                                title_filename = self.workspace + "/dvd_title_%d.mpg" % (self.i+1)
-                               LinkTS(self, title.inputfile, link_name)
+                               LinkTS(self, self.title.inputfile, link_name)
                                demux = DemuxTask(self, link_name)
                                self.mplextask = MplexTask(self, outputfile=title_filename, demux_task=demux)
                                self.mplextask.end = self.estimateddvdsize
-                               RemoveESFiles(self, demux)
+                               #RemoveESFiles(self, demux)
                        WaitForResidentTasks(self)
                        PreviewTask(self, self.workspace + "/dvd/VIDEO_TS/")
                        output = self.project.settings.output.getValue()
index 7491e04..b77383c 100644 (file)
@@ -148,8 +148,9 @@ class ProjectSettings(Screen,ConfigListScreen):
                        self.list.append(getConfigListEntry(_("Menu")+' '+_("spaces (top, between rows, left)"), self.settings.space))
                        self.list.append(getConfigListEntry(_("Menu")+' '+_("Audio"), self.settings.menuaudio))
                if authormode != "data_ts":
-                       self.list.append(getConfigListEntry(_("VMGM (intro trailer)"), self.settings.vmgm))
-                       self.list.append(getConfigListEntry(_("Auto chapter split every ? minutes (0=never)"), self.settings.autochapter))
+                       self.list.append(getConfigListEntry(_("Titleset mode"), self.settings.titlesetmode))
+                       if self.settings.titlesetmode.getValue() == "single" or authormode == "just_linked":
+                               self.list.append(getConfigListEntry(_("VMGM (intro trailer)"), self.settings.vmgm))
                else:
                        self.list.append(getConfigListEntry(("DVD data format"), self.settings.dataformat))
                
@@ -158,13 +159,13 @@ class ProjectSettings(Screen,ConfigListScreen):
        def keyLeft(self):
                ConfigListScreen.keyLeft(self)
                key = self.keydict[self["config"].getCurrent()[1]]
-               if key == "authormode" or key == "output":
+               if key == "authormode" or key == "output" or key=="titlesetmode":
                        self.initConfigList()
 
        def keyRight(self):
                ConfigListScreen.keyRight(self)
                key = self.keydict[self["config"].getCurrent()[1]]
-               if key == "authormode" or key == "output":
+               if key == "authormode" or key == "output" or key=="titlesetmode":
                        self.initConfigList()
 
        def exit(self):
index 163269c..210a3d5 100644 (file)
@@ -20,16 +20,31 @@ class TitleCutter(CutListEditor):
                audio = service and service.audioTracks()
                n = audio and audio.getNumberOfTracks() or 0
                if n > 0:
+                       from DVDTitle import ConfigFixedText
+                       from TitleProperties import languageChoices
+                       from Components.config import config, ConfigSubsection, ConfigSubList, ConfigSelection, ConfigYesNo
+                       self.t.properties.audiotracks = ConfigSubList()
                        for x in range(n):
                                i = audio.getTrackInfo(x)
-                               language = i.getLanguage()
+                               DVB_lang = i.getLanguage()
                                description = i.getDescription()
+                               pid = str(i.getPID())
                                if description == "MPEG":
                                        description = "MP2"
-                               self.t.audiotracks.append((language, description))
-               print "[DVDBurn getAudioTracks]", self.t.audiotracks
-               self.t.sVideoType = service.info().getInfo(iServiceInformation.sVideoType)
-               print "[DVDBurn getVideoType]", self.t.sVideoType
+                               print "[audiotrack] pid:", pid, "description:", description, "language:", DVB_lang
+                               self.t.properties.audiotracks.append(ConfigSubsection())
+                               self.t.properties.audiotracks[-1].active = ConfigYesNo(default = True)
+                               self.t.properties.audiotracks[-1].format = ConfigFixedText(description)
+                               self.t.properties.audiotracks[-1].language = ConfigSelection(choices = languageChoices.choices, default=languageChoices.getLanguage(DVB_lang))
+                               self.t.properties.audiotracks[-1].pid = ConfigFixedText(pid)
+                               self.t.properties.audiotracks[-1].DVB_lang = ConfigFixedText(DVB_lang)
+               sAspect = service.info().getInfo(iServiceInformation.sAspect)
+               if sAspect in ( 1, 2, 5, 6, 9, 0xA, 0xD, 0xE ):
+                       aspect = "4:3"
+               else:
+                       aspect = "16:9"
+               self.t.properties.aspect.setValue(aspect)
+               self.t.VideoType = service.info().getInfo(iServiceInformation.sVideoType)
 
        def exit(self):
                self.session.nav.stopService()
index 19380af..345af87 100644 (file)
@@ -1,4 +1,4 @@
-import DVDProject, TitleList, TitleCutter, ProjectSettings, DVDToolbox, Process
+import DVDProject, TitleList, TitleCutter, TitleProperties, ProjectSettings, DVDToolbox, Process
 from Screens.Screen import Screen
 from Screens.ChoiceBox import ChoiceBox
 from Screens.InputBox import InputBox
@@ -41,7 +41,7 @@ class TitleList(Screen, HelpableScreen):
                self["titleactions"] = HelpableActionMap(self, "DVDTitleList",
                        {
                                "addTitle": (self.addTitle, _("Add a new title"), _("Add title")),
-                               "editTitle": (self.editTitle, _("Edit chapters of current title"), _("Edit title")),
+                               "titleProperties": (self.titleProperties, _("Properties of current title"), _("Title properties")),
                                "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")),
                                "settings": (self.settings, _("Collection settings"), _("Settings")),
                                "burnProject": (self.burnProject, _("Burn DVD"), _("Burn DVD")),
@@ -59,7 +59,7 @@ class TitleList(Screen, HelpableScreen):
 
                self["key_red"] = StaticText(_("Remove title"))
                self["key_green"] = StaticText(_("Add title"))
-               self["key_yellow"] = StaticText(_("Edit title"))
+               self["key_yellow"] = StaticText(_("Title properties"))
                self["key_blue"] = StaticText(_("Settings"))
 
                self["title_label"] = StaticText()
@@ -78,40 +78,31 @@ class TitleList(Screen, HelpableScreen):
        def showMenu(self):
                menu = []
                if self.project.settings.output.getValue() == "dvd":
-                       menu.append((_("Burn DVD"), "burn"));
+                       menu.append((_("Burn DVD"), self.burnProject))
                elif self.project.settings.output.getValue() == "iso":
-                       menu.append((_("Create DVD-ISO"), "burn"));
-               menu.append((_("Preview menu"), "previewMenu"));
-               menu.append((_("DVD media toolbox"), "toolbox"));
-               menu.append((_("Collection settings"), "settings"));
-               menu.append((_("Add a new title"), "addtitle"));
-               menu.append((_("Remove title"), "removetitle"));
-               menu.append((_("Edit chapters of current title"), "edittitle"));
-               menu.append((_("Burn existing image to DVD"), "burniso"));
-               menu.append((_("Exit"), "exit"));
+                       menu.append((_("Create DVD-ISO"), self.burnProject))
+               menu.append((_("Burn existing image to DVD"), self.selectImage))
+               menu.append((_("DVD media toolbox"), self.toolbox))
+               menu.append((_("Preview menu"), self.previewMenu))
+               menu.append((_("Collection settings"), self.settings))
+               menu.append((_("Reset and renumerate title names"), self.resetTitles))
+               menu.append((_("Edit chapters of current title"), self.editTitle))
+               menu.append((_("Properties of current title"), self.titleProperties))
+               menu.append((_("Add a new title"), self.addTitle))
+               menu.append((_("Remove title"), self.removeCurrentTitle))
+               menu.append((_("Exit"), self.leave))
                self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
 
        def menuCallback(self, choice):
-               if choice is None:
-                       return
-               if choice[1] == "removetitle":
-                       self.removeCurrentTitle()
-               elif choice[1] == "addtitle":
-                       self.addTitle()
-               elif choice[1] == "edittitle":
-                       self.editTitle()
-               elif choice[1] == "toolbox":
-                       self.toolbox()
-               elif choice[1] == "settings":
-                       self.settings()
-               elif choice[1] == "previewMenu":
-                       self.previewMenu()
-               elif choice[1] == "burn":
-                       self.burnProject()
-               elif choice[1] == "burniso":
-                       self.session.openWithCallback(self.burnISO, ProjectSettings.FileBrowser, "image", self.project.settings)
-               elif choice[1] == "exit":
-                       self.leave()
+               if choice:
+                       choice[1]()
+
+       def titleProperties(self):
+               if self.getCurrentTitle():
+                       self.session.openWithCallback(self.updateTitleList, TitleProperties.TitleProperties, self, self.project, self["titles"].getIndex())
+
+       def selectImage(self):
+               self.session.openWithCallback(self.burnISO, ProjectSettings.FileBrowser, "image", self.project.settings)
 
        def newProject(self):
                self.project = DVDProject.DVDProject()
@@ -197,10 +188,6 @@ class TitleList(Screen, HelpableScreen):
                        job_manager.in_background = False
                        self.session.openWithCallback(self.JobViewCB, JobView, job)
                else:
-                       autochapter = self.project.settings.autochapter.getValue()
-                       if autochapter > 0:
-                               for title in self.project.titles:
-                                       title.produceAutoChapter(autochapter)
                        job = Process.DVDJob(self.project)
                        job_manager.AddJob(job)
                        job_manager.in_background = False
@@ -225,7 +212,7 @@ class TitleList(Screen, HelpableScreen):
                res = [ ]
                totalsize = 0
                for title in self.project.titles:
-                       a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 500, 50, 0, RT_HALIGN_LEFT, title.name)  ]
+                       a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 500, 50, 0, RT_HALIGN_LEFT, title.properties.menutitle.getValue())  ]
                        res.append(a)
                        totalsize += title.estimatedDiskspace
                self["titles"].list = res
@@ -263,13 +250,21 @@ class TitleList(Screen, HelpableScreen):
 
        def titleEditDone(self, cutlist):
                t = self.current_edit_title
+               t.initDVDmenuText(self.project,len(self.project.titles))
                t.cuesheet = cutlist
                t.produceFinalCuesheet()
-               if t.sVideoType != 0:
+               if t.VideoType != 0:
                        self.session.openWithCallback(self.DVDformatCB,MessageBox,text = _("The DVD standard doesn't support H.264 (HDTV) video streams. Do you want to create a Dreambox format data DVD (which will not play in stand-alone DVD players) instead?"), type = MessageBox.TYPE_YESNO)
                else:
                        self.updateTitleList()
 
+       def resetTitles(self):
+               count = 0
+               for title in self.project.titles:
+                       count += 1
+                       title.initDVDmenuText(self.project,count)
+               self.updateTitleList()
+
        def DVDformatCB(self, answer):
                t = self.current_edit_title
                if answer == True:
diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py
new file mode 100644 (file)
index 0000000..d5ba6c1
--- /dev/null
@@ -0,0 +1,169 @@
+from Screens.Screen import Screen
+from Screens.ChoiceBox import ChoiceBox
+from Screens.InputBox import InputBox
+from Screens.MessageBox import MessageBox
+from Screens.HelpMenu import HelpableScreen
+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 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, ConfigInteger, ConfigSubsection, ConfigSelection
+from Components.ConfigList import ConfigListScreen
+import DVDTitle
+
+class TitleProperties(Screen,ConfigListScreen):
+       skin = """
+               <screen position="90,83" size="560,445" title="Properties of current title" >
+                   <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/blue.png" position="420,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="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
+                   <widget name="config" position="10,50" size="540,300" scrollbarMode="showOnDemand" />
+                   <widget source="serviceinfo_headline" render="Label" position="20,360" size="520,20" font="Regular;20" />
+                   <widget source="serviceinfo" render="Label" position="20,382" size="520,66" font="Regular;16" />
+               </screen>"""
+
+       def __init__(self, session, parent, project, title_idx):
+               Screen.__init__(self, session)
+               self.parent = parent
+               self.project = project
+               self.title_idx = title_idx
+
+               self["key_red"] = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("OK"))
+               self["key_blue"] = StaticText(_("Edit Title"))
+               self["serviceinfo_headline"] = StaticText("DVB info:")
+               self["serviceinfo"] = StaticText()
+
+               self.properties = project.titles[title_idx].properties
+               ConfigListScreen.__init__(self, [])
+               self.properties.crop = DVDTitle.ConfigFixedText("crop")
+               self.properties.autochapter.addNotifier(self.initConfigList)
+               self.properties.aspect.addNotifier(self.initConfigList)
+               for audiotrack in self.properties.audiotracks:
+                       audiotrack.active.addNotifier(self.initConfigList)
+               
+               self.initConfigList()
+
+               self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
+               {
+                   "green": self.exit,
+                   "red": self.cancel,
+                   "blue": self.editTitle,
+                   "cancel": self.cancel,
+                   "ok": self.ok,
+               }, -2)
+
+       def initConfigList(self, element=None):
+               try:
+                       self.properties.position = ConfigInteger(default = self.title_idx+1, limits = (1, len(self.project.titles)))
+                       title = self.project.titles[self.title_idx]
+                       self.list = []
+                       self.list.append(getConfigListEntry("DVD " + _("Track"), self.properties.position))
+                       self.list.append(getConfigListEntry("DVD " + _("Title"), self.properties.menutitle))
+                       self.list.append(getConfigListEntry("DVD " + _("Description"), self.properties.menusubtitle))
+                       for audiotrack in self.properties.audiotracks:
+                               DVB_aud = audiotrack.DVB_lang.getValue() or audiotrack.pid.getValue()
+                               self.list.append(getConfigListEntry(_("burn audio track (%s)") % DVB_aud, audiotrack.active))
+                               if audiotrack.active.getValue():
+                                       self.list.append(getConfigListEntry(_("audio track (%s) format") % DVB_aud, audiotrack.format))
+                                       self.list.append(getConfigListEntry(_("audio track (%s) language") % DVB_aud, audiotrack.language))
+                                       
+                       self.list.append(getConfigListEntry("DVD " + _("Aspect Ratio"), self.properties.aspect))
+                       if self.properties.aspect.getValue() == "16:9":
+                               self.list.append(getConfigListEntry("DVD " + "widescreen", self.properties.widescreen))
+                       else:
+                               self.list.append(getConfigListEntry("DVD " + "widescreen", self.properties.crop))
+                       
+                       infotext = _("Available format variables") + ":\n$i=" + _("Track") + ", $t=" + _("Title") + ", $d=" + _("Description") + ", $l=" + _("length") + ", $c=" + _("chapters") + ",\n" + _("Record") + " $T=" + _("Begin time") + ", $Y=" + _("year") + ", $M=" + _("month") + ", $D=" + _("day") + ",\n$A=" + _("audio tracks") + ", $C=" + _("Channel") + ", $f=" + _("filename")
+                       self["info"] = StaticText(infotext)
+                       
+                       if len(title.chaptermarks) == 0:
+                               self.list.append(getConfigListEntry(_("Auto chapter split every ? minutes (0=never)"), self.properties.autochapter))
+                       infotext = _("Title") + ': ' + title.DVBname + "\n" + _("Description") + ': ' + title.DVBdescr + "\n" + _("Channel") + ': ' + title.DVBchannel
+                       chaptermarks = title.getChapterMarks(template="$h:$m:$s")
+                       chapters_count = len(chaptermarks)
+                       if chapters_count >= 1:
+                               infotext += ', ' + str(chapters_count+1) + ' ' + _("chapters") + ' ('
+                               infotext += ' / '.join(chaptermarks) + ')'
+                       self["serviceinfo"].setText(infotext)
+                       self["config"].setList(self.list)
+               except AttributeError:
+                       pass
+
+       def editTitle(self):
+               self.parent.editTitle()
+               self.initConfigList()
+
+       def changedConfigList(self):
+               self.initConfigList()
+
+       def exit(self):
+               self.applySettings()
+               self.close()
+
+       def applySettings(self):
+               for x in self["config"].list:
+                       x[1].save()
+               current_pos = self.title_idx+1
+               new_pos = self.properties.position.getValue()
+               if new_pos != current_pos:
+                       print "title got repositioned from ", current_pos, "to", new_pos
+                       swaptitle = self.project.titles.pop(current_pos-1)
+                       self.project.titles.insert(new_pos-1, swaptitle)
+
+       def ok(self):
+               #key = self.keydict[self["config"].getCurrent()[1]]
+               #if key in self.project.filekeys:
+                       #self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, key, self.settings)
+               pass
+
+       def cancel(self):
+               self.close()
+
+from Tools.ISO639 import LanguageCodes
+class LanguageChoices():
+       def __init__(self):
+               from Components.Language import language as syslanguage
+               syslang = syslanguage.getLanguage()[:2]
+               self.langdict = { }
+               self.choices = []
+               for key, val in LanguageCodes.iteritems():
+                       if len(key) == 2:
+                               self.langdict[key] = val[0]
+               for key, val in self.langdict.iteritems():
+                       if key not in [syslang, 'en']:
+                               self.langdict[key] = val
+                               self.choices.append((key, val))
+               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"]))
+
+       def getLanguage(self, DVB_lang):
+               DVB_lang = DVB_lang.lower()
+               stripwords = ["stereo", "audio", "description", "2ch", "dolby digital"]
+               for word in stripwords:
+                       DVB_lang = DVB_lang.replace(word,"").strip()
+               for key, val in LanguageCodes.iteritems():
+                       if DVB_lang.find(key.lower()) == 0:
+                               if len(key) == 2:
+                                       return key
+                               else:
+                                       DVB_lang = (LanguageCodes[key])[0]
+                       elif DVB_lang.find(val[0].lower()) > -1:
+                               if len(key) == 2:
+                                       return key
+                               else:
+                                       DVB_lang = (LanguageCodes[key])[0]
+               for key, val in self.langdict.iteritems():
+                       if val == DVB_lang:
+                               return key
+               return "nolang"
+
+languageChoices = LanguageChoices()
\ No newline at end of file
index 13fa3ee..e8bc104 100644 (file)
@@ -2,7 +2,7 @@
        <map context="DVDTitleList">
                <key id="KEY_RED" mapto="removeCurrentTitle" flags="m" />
                <key id="KEY_GREEN" mapto="addTitle" flags="m" />
-               <key id="KEY_YELLOW" mapto="editTitle" flags="m" />
+               <key id="KEY_YELLOW" mapto="titleProperties" flags="m" />
                <key id="KEY_BLUE" mapto="settings" flags="m" />
                <key id="KEY_RECORD" mapto="burnProject" flags="m" />
                <key id="KEY_0" mapto="burnProject" flags="m" />
index b658d80..29076ce 100644 (file)
@@ -12,5 +12,5 @@ def main_add(session, service, **kwargs):
        dvdburn.selectedSource(service)
 
 def Plugins(**kwargs):
-       return [PluginDescriptor(name="DVD Burn", description=_("Burn to DVD..."), where = PluginDescriptor.WHERE_MOVIELIST, fnc=main_add), 
-               PluginDescriptor(name="DVD Burn", description=_("Burn to DVD..."), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main) ]
+       return [PluginDescriptor(name="DVD Burn", description=_("Burn to DVD..."), where = PluginDescriptor.WHERE_MOVIELIST, fnc=main_add, icon="dvdburn.png"),
+               PluginDescriptor(name="DVD Burn", description=_("Burn to DVD..."), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main, icon="dvdburn.png") ]
index 4298642..cb5f0e0 100644 (file)
@@ -371,13 +371,25 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                if retval > 0:
                        self.zapToNumber(retval)
 
+       def getServiceInterface(self, iface):
+               service = self.service
+               if service:
+                       attr = getattr(service, iface, None)
+                       if callable(attr):
+                               return attr()
+               return None
+
        def __serviceStopped(self):
                self.dvdScreen.hide()
-               self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
+               subs = self.getServiceInterface("subtitle")
+               if subs:
+                       subs.disableSubtitles(self.session.current_dialog.instance)
 
        def serviceStarted(self): #override InfoBarShowHide function
                self.dvdScreen.show()
-               self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
+               subs = self.getServiceInterface("subtitle")
+               if subs:
+                       subs.enableSubtitles(self.dvdScreen.instance, None)
 
        def doEofInternal(self, playing):
                if self.in_menu:
@@ -435,17 +447,19 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                print "StringAvail"
 
        def __osdAudioInfoAvail(self):
-               audioTuple = self.service.info().getInfoObject(iServiceInformation.sUser+6)
+               info = self.getServiceInterface("info")
+               audioTuple = info and info.getInfoObject(iServiceInformation.sUser+6)
                print "AudioInfoAvail ", repr(audioTuple)
                if audioTuple:
                        audioString = "%d: %s (%s)" % (audioTuple[0],audioTuple[1],audioTuple[2])
                        self["audioLabel"].setText(audioString)
                        if audioTuple != self.last_audioTuple and not self.in_menu:
                                self.doShow()
-                       self.last_audioTuple = audioTuple
+               self.last_audioTuple = audioTuple
 
        def __osdSubtitleInfoAvail(self):
-               subtitleTuple = self.service.info().getInfoObject(iServiceInformation.sUser+7)
+               info = self.getServiceInterface("info")
+               subtitleTuple = info and info.getInfoObject(iServiceInformation.sUser+7)
                print "SubtitleInfoAvail ", repr(subtitleTuple)
                if subtitleTuple:
                        subtitleString = ""
@@ -454,21 +468,25 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                        self["subtitleLabel"].setText(subtitleString)
                        if subtitleTuple != self.last_subtitleTuple and not self.in_menu:
                                self.doShow()
-                       self.last_subtitleTuple = subtitleTuple
+               self.last_subtitleTuple = subtitleTuple
 
        def __chapterUpdated(self):
-               self.currentChapter = self.service.info().getInfo(iServiceInformation.sCurrentChapter)
-               self.totalChapters = self.service.info().getInfo(iServiceInformation.sTotalChapters)
-               self.setChapterLabel()
-               print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
+               info = self.getServiceInterface("info")
+               if info:
+                       self.currentChapter = info.getInfo(iServiceInformation.sCurrentChapter)
+                       self.totalChapters = info.getInfo(iServiceInformation.sTotalChapters)
+                       self.setChapterLabel()
+                       print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
 
        def __titleUpdated(self):
-               self.currentTitle = self.service.info().getInfo(iServiceInformation.sCurrentTitle)
-               self.totalTitles = self.service.info().getInfo(iServiceInformation.sTotalTitles)
-               self.setChapterLabel()
-               print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
-               if not self.in_menu:
-                       self.doShow()
+               info = self.getServiceInterface("info")
+               if info:
+                       self.currentTitle = info.getInfo(iServiceInformation.sCurrentTitle)
+                       self.totalTitles = info.getInfo(iServiceInformation.sTotalTitles)
+                       self.setChapterLabel()
+                       print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
+                       if not self.in_menu:
+                               self.doShow()
                
        def askLeavePlayer(self):
                choices = [(_("Continue playing"), "play"), (_("Exit"), "exit")]
@@ -476,73 +494,65 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                        choices.insert(1,(_("Return to file browser"), "browser"))                      
                self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list = choices)
 
+       def sendKey(self, key):
+               keys = self.getServiceInterface("keys")
+               if keys:
+                       keys.keyPressed(key)
+               return keys
+
        def nextAudioTrack(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyUser)
+               self.sendKey(iServiceKeys.keyUser)
 
        def nextSubtitleTrack(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyUser+1)
+               self.sendKey(iServiceKeys.keyUser+1)
 
        def enterDVDAudioMenu(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyUser+2)
+               self.sendKey(iServiceKeys.keyUser+2)
 
        def nextChapter(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyUser+3)
+               self.sendKey(iServiceKeys.keyUser+3)
 
        def prevChapter(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyUser+4)
+               self.sendKey(iServiceKeys.keyUser+4)
 
        def nextTitle(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyUser+5)
+               self.sendKey(iServiceKeys.keyUser+5)
 
        def prevTitle(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyUser+6)
+               self.sendKey(iServiceKeys.keyUser+6)
 
        def enterDVDMenu(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyUser+7)
+               self.sendKey(iServiceKeys.keyUser+7)
 
        def seekBeginning(self):
                if self.service:
                        seekable = self.getSeek()
-                       if seekable is not None:
+                       if seekable:
                                seekable.seekTo(0)
 
        def zapToNumber(self, number):
                if self.service:
                        seekable = self.getSeek()
-                       if seekable is not None:
+                       if seekable:
                                print "seek to chapter %d" % number
                                seekable.seekChapter(number)
 
 #      MENU ACTIONS
        def keyRight(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyRight)
+               self.sendKey(iServiceKeys.keyRight)
 
        def keyLeft(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyLeft)
+               self.sendKey(iServiceKeys.keyLeft)
 
        def keyUp(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyUp)
+               self.sendKey(iServiceKeys.keyUp)
 
        def keyDown(self):
-               if self.service:
-                       self.service.keys().keyPressed(iServiceKeys.keyDown)
+               self.sendKey(iServiceKeys.keyDown)
 
        def keyOk(self):
-               if self.service:
-                       if not self.in_menu:
-                               self.toggleInfo()
-                       self.service.keys().keyPressed(iServiceKeys.keyOk)
+               if self.sendKey(iServiceKeys.keyOk) and not self.in_menu:
+                       self.toggleInfo()
 
        def keyCancel(self):
                self.askLeavePlayer()
@@ -606,9 +616,10 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
        def playLastCB(self, answer): # overwrite infobar cuesheet function
                print "playLastCB", answer, self.resume_point
                if self.service:
-                       seek = self.service.seek()
                        if answer == True:
-                               seek.seekTo(self.resume_point)
+                               seekable = self.getSeek()
+                               if seekable:
+                                       seekable.seekTo(self.resume_point)
                        pause = self.service.pause()
                        pause.unpause()
                self.hideAfterResume()
index 7afbe14..21d1bfe 100644 (file)
@@ -93,4 +93,4 @@ def main(session, servicelist, **kwargs):
 def Plugins(**kwargs):
        name = _("Graphical Multi EPG")
        descr = _("A graphical EPG for all services of an specific bouquet")
-       return [ PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main) ]
+       return [ PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EVENTINFO, fnc=main) ]
index e4ec574..123df22 100644 (file)
@@ -1,5 +1,4 @@
 installdir = $(LIBDIR)/enigma2/python/Plugins/Extensions/MediaPlayer
 
 install_PYTHON = \
-       __init__.py \
-       plugin.py
+       __init__.py plugin.py settings.py
index ed1a887..0d5305d 100644 (file)
@@ -1,25 +1,27 @@
 from os import path as os_path, remove as os_remove, listdir as os_listdir
 from time import strftime
-from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation
+from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation, loadPic
+from ServiceReference import ServiceReference
 from Screens.Screen import Screen
+from Screens.HelpMenu import HelpableScreen
 from Screens.MessageBox import MessageBox
 from Screens.InputBox import InputBox
+from Screens.ChoiceBox import ChoiceBox
+from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport
 from Components.ActionMap import NumberActionMap, HelpableActionMap
 from Components.Label import Label
 from Components.Pixmap import Pixmap,MultiPixmap
-from Components.Label import Label
 from Components.FileList import FileList
 from Components.MediaPlayer import PlayList
-from Tools.Directories import resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE
 from Components.ServicePosition import ServicePositionGauge
 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
 from Components.Playlist import PlaylistIOInternal, PlaylistIOM3U, PlaylistIOPLS
-from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport
-from ServiceReference import ServiceReference
-from Screens.ChoiceBox import ChoiceBox
-from Screens.HelpMenu import HelpableScreen
+from Components.AVSwitch import AVSwitch
 from Components.Harddisk import harddiskmanager
-from Tools.Directories import fileExists, pathExists
+from Components.config import config
+from Tools.Directories import fileExists, pathExists, resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE
+from settings import MediaPlayerSettings
+from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
 import random
 
 class MyPlayList(PlayList):
@@ -42,6 +44,7 @@ class MediaPixmap(Pixmap):
                                        break
                if self.default_pixmap is None:
                        self.default_pixmap = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png")
+               self.coverFileNames = ["folder.png", "folder.jpg"]
                return Pixmap.applySkin(self, desktop, screen)
 
 class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport, HelpableScreen):
@@ -66,7 +69,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                self.addPlaylistParser(PlaylistIOInternal, "e2pls")
 
                # 'None' is magic to start at the list of mountpoints
-               self.filelist = FileList(None, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|mkv|mp4|dat|flac)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls")
+               defaultDir = config.mediaplayer.defaultDir.getValue()
+               self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|mkv|mp4|dat|flac)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls")
                self["filelist"] = self.filelist
 
                self.playlist = MyPlayList()
@@ -92,8 +96,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                self["coverArt"] = MediaPixmap()
                self["repeat"] = MultiPixmap()
 
-               self.repeat = False
                self.seek_target = None
+               hotplugNotifier.append(self.hotplugCB)
 
                class MoviePlayerActionMap(NumberActionMap):
                        def __init__(self, player, contexts = [ ], actions = { }, prio=0):
@@ -169,7 +173,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                self.coverArtFileName = ""
                self.isAudioCD = False
                self.AudioCD_albuminfo = {}
-               self.savePlaylistOnExit = True
+               self.cdAudioTrackFiles = []
+               self.applySettings()
 
                self.playlistIOInternal = PlaylistIOInternal()
                list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
@@ -192,16 +197,16 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                return MediaPlayerLCDScreen
 
        def exit(self):
-               self.session.openWithCallback(self.exitCB, MessageBox, _("Do you really want to exit?"), timeout=5)
-
-       def exitCB(self, answer):
-               if answer == True:
-                       self.playlistIOInternal.clear()
-                       for x in self.playlist.list:
-                               self.playlistIOInternal.addService(ServiceReference(x[0]))
-                       if self.savePlaylistOnExit:
-                               self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
-                       self.close()
+               self.playlistIOInternal.clear()
+               for x in self.playlist.list:
+                       self.playlistIOInternal.addService(ServiceReference(x[0]))
+               if self.savePlaylistOnExit:
+                       self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls"))
+               if config.mediaplayer.saveDirOnExit.getValue():
+                       config.mediaplayer.defaultDir.setValue(self.filelist.getCurrentDirectory())
+                       config.mediaplayer.defaultDir.save()
+               hotplugNotifier.remove(self.hotplugCB)
+               self.close()
 
        def checkSkipShowHideLock(self):
                self.updatedSeekState()
@@ -283,13 +288,15 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
        def updateCoverArtPixmap(self, path):
                while not path.endswith("/"):
                        path = path[:-1]
-               pngname = path + "folder.png"
-               
-               if not fileExists(pngname):
-                       pngname = self["coverArt"].default_pixmap
-               if self.coverArtFileName != pngname:
-                       self.coverArtFileName = pngname
-                       self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName)
+               new_coverArtFileName = self["coverArt"].default_pixmap
+               for filename in self["coverArt"].coverFileNames:
+                       if fileExists(path + filename):
+                               new_coverArtFileName = path + filename
+               if self.coverArtFileName != new_coverArtFileName:
+                       self.coverArtFileName = new_coverArtFileName
+                       pixmap = loadPic(self.coverArtFileName, 116, 116, AVSwitch().getAspectRatioSetting()/2,1,0,0)
+                       if pixmap is not None:
+                               self["coverArt"].instance.setPixmap(pixmap.__deref__())
 
        def leftDown(self):
                self.lefttimer = True
@@ -441,27 +448,25 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
 
        def showMenu(self):
                menu = []
+               if len(self.cdAudioTrackFiles):
+                       menu.insert(0,(_("Play Audio-CD..."), "audiocd"))
                if self.currList == "filelist":
                        if self.filelist.canDescent():
                                menu.append((_("add directory to playlist"), "copydir"))
                        else:
                                menu.append((_("add files to playlist"), "copyfiles"))
                        menu.append((_("switch to playlist"), "playlist"))
+                       menu.append((_("delete file"), "deletefile"))
                else:
                        menu.append((_("switch to filelist"), "filelist"))
-
                        menu.append((_("shuffle playlist"), "shuffle"))
-
-                       menu.append((_("delete"), "delete"))
+                       menu.append((_("Delete entry"), "deleteentry"))
                        menu.append((_("clear playlist"), "clear"))
                menu.append((_("hide player"), "hide"));
                menu.append((_("save playlist"), "saveplaylist"));
                menu.append((_("load playlist"), "loadplaylist"));
                menu.append((_("delete saved playlist"), "deleteplaylist"));
-               menu.append((_("repeat playlist"), "repeat"));
-               drivepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
-               if pathExists(drivepath):
-                       menu.insert(0,(_("Play Audio-CD..."), "audiocd"))
+               menu.append((_("Edit settings"), "settings"))
                self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
 
        def menuCallback(self, choice):
@@ -473,20 +478,19 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                elif choice[1] == "copyfiles":
                        self.stopEntry()
                        self.playlist.clear()
+                       self.isAudioCD = False
                        self.copyDirectory(os_path.dirname(self.filelist.getSelection()[0].getPath()) + "/", recursive = False)
                        self.playServiceRefEntry(self.filelist.getServiceRef())
                elif choice[1] == "playlist":
                        self.switchToPlayList()
                elif choice[1] == "filelist":
                        self.switchToFileList()
-               elif choice[1] == "delete":
+               elif choice[1] == "deleteentry":
                        if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex():
                                self.stopEntry()
                        self.deleteEntry()
                elif choice[1] == "clear":
-                       self.stopEntry()
-                       self.playlist.clear()
-                       self.switchToFileList()
+                       self.clear_playlist()
                elif choice[1] == "hide":
                        self.hide()
                elif choice[1] == "saveplaylist":
@@ -497,24 +501,11 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        self.delete_saved_playlist()
                elif choice[1] == "shuffle":
                        self.playlist.PlayListShuffle()
-               elif choice[1] == "repeat":
-                       if self.repeat == True:
-                               self.repeat = False
-                               self["repeat"].setPixmapNum(0)
-                       else:
-                               self.repeat = True
-                               self["repeat"].setPixmapNum(1)
+               elif choice[1] == "deletefile":
+                       self.deleteFile()
+               elif choice[1] == "settings":
+                       self.session.openWithCallback(self.applySettings, MediaPlayerSettings, self)
                elif choice[1] == "audiocd":
-                       from Components.Scanner import scanDevice
-                       drivepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
-                       self.cdAudioTrackFiles = []
-                       res = scanDevice(drivepath)
-                       list = [ (r.description, r, res[r], self.session) for r in res ]
-                       if list:
-                               (desc, scanner, files, session) = list[0]
-                               for file in files:
-                                       if file.mimetype == "audio/x-cda":
-                                               self.cdAudioTrackFiles.append(file.path)
                        self.playAudioCD()
 
        def playAudioCD(self):
@@ -533,6 +524,13 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        self.changeEntry(0)
                        self.switchToPlayList()
 
+       def applySettings(self):
+               self.savePlaylistOnExit = config.mediaplayer.savePlaylistOnExit.getValue()
+               if config.mediaplayer.repeat.getValue() == True:
+                       self["repeat"].setPixmapNum(1)
+               else:
+                       self["repeat"].setPixmapNum(0)
+
        def showEventInformation(self):
                from Screens.EventView import EventViewSimple
                from ServiceReference import ServiceReference
@@ -617,9 +615,14 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
 
        def deleteConfirmed(self, confirmed):
                if confirmed:
-                       os_remove(self.delname)
+                       try:
+                               os_remove(self.delname)
+                       except OSError,e:
+                               print "delete failed:", e
+                               self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
 
        def clear_playlist(self):
+               self.isAudioCD = False
                self.stopEntry()
                self.playlist.clear()
                self.switchToFileList()
@@ -632,20 +635,78 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                        if x[0][1] == True: #isDir
                                if recursive:
                                        self.copyDirectory(x[0][0])
-                       else:
+                       elif filelist.getServiceRef() and filelist.getServiceRef().type == 4097:
                                self.playlist.addFile(x[0][0])
                self.playlist.updateList()
 
+       def deleteFile(self):
+               if self.currList == "filelist":
+                       self.service = self.filelist.getServiceRef()
+               else:
+                       self.service = self.playlist.getSelection()
+               if self.service is None:
+                       return
+               if self.service.type != 4098 and self.session.nav.getCurrentlyPlayingServiceReference() is not None:
+                       if self.service == self.session.nav.getCurrentlyPlayingServiceReference():
+                               self.stopEntry()
+
+               serviceHandler = eServiceCenter.getInstance()
+               offline = serviceHandler.offlineOperations(self.service)
+               info = serviceHandler.info(self.service)
+               name = info and info.getName(self.service)
+               result = False
+               if offline is not None:
+                       # simulate first
+                       if not offline.deleteFromDisk(1):
+                               result = True
+               if result == True:
+                       self.session.openWithCallback(self.deleteConfirmed_offline, MessageBox, _("Do you really want to delete %s?") % (name))
+               else:
+                       self.session.openWithCallback(self.close, MessageBox, _("You cannot delete this!"), MessageBox.TYPE_ERROR)      
+
+       def deleteConfirmed_offline(self, confirmed):
+               if confirmed:
+                       serviceHandler = eServiceCenter.getInstance()
+                       offline = serviceHandler.offlineOperations(self.service)
+                       result = False
+                       if offline is not None:
+                               # really delete!
+                               if not offline.deleteFromDisk(0):
+                                       result = True
+                       if result == False:
+                               self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
+                       else:
+                               self.removeListEntry()
+
+       def removeListEntry(self):
+               currdir = self.filelist.getCurrentDirectory()
+               self.filelist.changeDir(currdir)
+               deleteend = False
+               while not deleteend:
+                       index = 0
+                       deleteend = True
+                       if len(self.playlist) > 0:
+                               for x in self.playlist.list:
+                                       if self.service == x[0]:
+                                               self.playlist.deleteFile(index)
+                                               deleteend = False
+                                               break
+                                       index += 1
+               self.playlist.updateList()
+               if self.currList == "playlist":
+                       if len(self.playlist) == 0:
+                               self.switchToFileList()
+
        def copyFile(self):
                if self.filelist.getServiceRef().type == 4098: # playlist
                        ServiceRef = self.filelist.getServiceRef()
                        extension = ServiceRef.getPath()[ServiceRef.getPath().rfind('.') + 1:]
-                       print "extension:", extension
                        if self.playlistparsers.has_key(extension):
                                playlist = self.playlistparsers[extension]()
                                list = playlist.open(ServiceRef.getPath())
                                for x in list:
                                        self.playlist.addFile(x.ref)
+                       self.playlist.updateList()
                else:
                        self.playlist.addFile(self.filelist.getServiceRef())
                        self.playlist.updateList()
@@ -659,7 +720,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                next = self.playlist.getCurrentIndex() + 1
                if next < len(self.playlist):
                        self.changeEntry(next)
-               elif ( len(self.playlist) > 0 ) and ( self.repeat == True ):
+               elif ( len(self.playlist) > 0 ) and ( config.mediaplayer.repeat.getValue() == True ):
                        self.stopEntry()
                        self.changeEntry(0)
 
@@ -700,6 +761,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                else:
                        self.stopEntry()
                        self.playlist.clear()
+                       self.isAudioCD = False
                        sel = self.filelist.getSelection()
                        if sel:
                                if sel[1]: # can descent
@@ -762,7 +824,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
 
                        self.unPauseService()
                        if needsInfoUpdate == True:
-                               self.updateCoverArtPixmap(currref.getPath())
+                               path = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getPath()
+                               self.updateCoverArtPixmap(path)
                        else:
                                pngname = self["coverArt"].default_pixmap
                                self.coverArtFileName = pngname
@@ -797,7 +860,20 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
                
        def subtitleSelection(self):
                from Screens.Subtitles import Subtitles
-               self.session.open(Subtitles)            
+               self.session.open(Subtitles)
+       
+       def hotplugCB(self, dev, media_state):
+               if dev == harddiskmanager.getCD():      
+                       from Components.Scanner import scanDevice
+                       devpath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
+                       self.cdAudioTrackFiles = []
+                       res = scanDevice(devpath)
+                       list = [ (r.description, r, res[r], self.session) for r in res ]
+                       if list:
+                               (desc, scanner, files, session) = list[0]
+                               for file in files:
+                                       if file.mimetype == "audio/x-cda":
+                                               self.cdAudioTrackFiles.append(file.path)
 
 class MediaPlayerLCDScreen(Screen):
        skin = """
@@ -814,7 +890,6 @@ class MediaPlayerLCDScreen(Screen):
                self["text4"] = Label("")
 
        def setText(self, text, line):
-               print "lcd set text:", text, line
                if len(text) > 10:
                        if text[-4:] == ".mp3":
                                text = text[:-4]
diff --git a/lib/python/Plugins/Extensions/MediaPlayer/settings.py b/lib/python/Plugins/Extensions/MediaPlayer/settings.py
new file mode 100644 (file)
index 0000000..c6d274b
--- /dev/null
@@ -0,0 +1,137 @@
+from Screens.Screen import Screen
+from Screens.HelpMenu import HelpableScreen
+from Components.Label import Label
+from Components.FileList import FileList
+from Components.MediaPlayer import PlayList
+from Components.config import config, getConfigListEntry, ConfigSubsection, configfile, ConfigText, ConfigYesNo
+from Components.ConfigList import ConfigListScreen
+from Components.ActionMap import ActionMap
+
+class ConfigDirectory(ConfigText):
+       def __init__(self, default="", visible_width=60):
+               ConfigText.__init__(self, default, fixed_size = True, visible_width = visible_width)
+       def handleKey(self, key):
+               pass
+       def getValue(self):
+               if self.text == "":
+                       return None
+               else:
+                       return ConfigText.getValue(self)
+       def setValue(self, val):
+               if val == None:
+                       val = ""
+               ConfigText.setValue(self, val)
+       def getMulti(self, selected):
+               if self.text == "":
+                       return ("mtext"[1-selected:], _("List of Storage Devices"), range(0))
+               else:
+                       return ConfigText.getMulti(self, selected)
+               
+config.mediaplayer = ConfigSubsection()
+config.mediaplayer.repeat = ConfigYesNo(default=False)
+config.mediaplayer.savePlaylistOnExit = ConfigYesNo(default=True)
+config.mediaplayer.saveDirOnExit = ConfigYesNo(default=False)
+config.mediaplayer.defaultDir = ConfigDirectory()
+
+class DirectoryBrowser(Screen, HelpableScreen):
+       skin = """
+               <screen name="DirectoryBrowser" position="160,62" size="450,376" title="Directory browser" >
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="10,0" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="300,0" size="140,40" alphatest="on" />
+                       <widget source="key_red" render="Label" position="10,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
+                       <widget source="key_green" render="Label" position="300,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
+                       <widget name="filelist" position="0,44" size="440,322" scrollbarMode="showOnDemand" />
+               </screen>"""
+       def __init__(self, session, currDir):
+               from Components.Sources.StaticText import StaticText
+               Screen.__init__(self, session)
+               HelpableScreen.__init__(self)
+               
+               self["key_red"] = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("Use"))
+
+               self.filelist = FileList(currDir, matchingPattern="")
+               self["filelist"] = self.filelist
+
+               self["FilelistActions"] = ActionMap(["SetupActions", "ColorActions"],
+                       {
+                               "green": self.use,
+                               "red": self.exit,
+                               "ok": self.ok,
+                               "cancel": self.exit
+                       })
+
+       def ok(self):
+               if self.filelist.canDescent():
+                       self.filelist.descent()
+
+       def use(self):
+               if self.filelist.canDescent() and len(self["filelist"].getFilename()) > len(self["filelist"].getCurrentDirectory()):
+                       self.filelist.descent()
+               self.close(self["filelist"].getCurrentDirectory())
+
+       def exit(self):
+               self.close(False)
+
+class MediaPlayerSettings(Screen,ConfigListScreen):
+       skin = """
+               <screen name="MediaPlayerSettings" position="160,150" size="450,200" title="Edit settings">
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="10,0" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="300,0" size="140,40" alphatest="on" />
+                       <widget source="key_red" render="Label" position="10,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
+                       <widget source="key_green" render="Label" position="300,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
+                       <widget name="config" position="10,44" size="430,146" />
+               </screen>"""
+
+       def __init__(self, session, parent):
+               from Components.Sources.StaticText import StaticText
+               Screen.__init__(self, session)
+               self["key_red"] = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("Save"))
+
+               ConfigListScreen.__init__(self, [])
+               self.parent = parent
+               self.initConfigList()
+               config.mediaplayer.saveDirOnExit.addNotifier(self.initConfigList)
+
+               self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
+               {
+                   "green": self.save,
+                   "red": self.cancel,
+                   "cancel": self.cancel,
+                   "ok": self.ok,
+               }, -2)
+
+       def initConfigList(self, element=None):
+               print "[initConfigList]", element
+               try:
+                       self.list = []
+                       self.list.append(getConfigListEntry(_("repeat playlist"), config.mediaplayer.repeat))
+                       self.list.append(getConfigListEntry(_("save playlist on exit"), config.mediaplayer.savePlaylistOnExit))
+                       self.list.append(getConfigListEntry(_("save last directory on exit"), config.mediaplayer.saveDirOnExit))
+                       if not config.mediaplayer.saveDirOnExit.getValue():
+                               self.list.append(getConfigListEntry(_("start directory"), config.mediaplayer.defaultDir))
+                       self["config"].setList(self.list)
+               except KeyError:
+                       print "keyError"
+
+       def changedConfigList(self):
+               self.initConfigList()
+
+       def ok(self):
+               if self["config"].getCurrent()[1] == config.mediaplayer.defaultDir:
+                       self.session.openWithCallback(self.DirectoryBrowserClosed, DirectoryBrowser, self.parent.filelist.getCurrentDirectory())
+
+       def DirectoryBrowserClosed(self, path):
+               print "PathBrowserClosed:" + str(path)
+               if path != False:
+                       config.mediaplayer.defaultDir.setValue(path)
+
+       def save(self):
+               for x in self["config"].list:
+                       x[1].save()
+               self.close()
+
+       def cancel(self):
+               self.close()
+
index a9d61ed..ea906f0 100644 (file)
@@ -155,7 +155,7 @@ class ThumbView(Screen):
                                        if not createDir(cachedir):
                                                cachefile = ""
 
-                       ptr = loadPic(self.path + self.thumblist[self.thumbindex], 180, 160, self.aspect, int(config.pic.resize.value), int(config.pic.rotate.value),1, cachefile)
+                       ptr = loadPic(self.path + self.thumblist[self.thumbindex], 180, 160, self.aspect, int(config.pic.resize.value), int(config.pic.rotate.value), 1, cachefile, 1)
                        if ptr != None:
                                self["thumb"+str(self.thumbindex)].show()
                                self["thumb"+str(self.thumbindex)].instance.setPixmap(ptr)
@@ -486,7 +486,7 @@ class picmain(Screen):
                                        if not createDir(cachedir):
                                                cachefile = ""
 
-                       ptr = loadPic(self.filelist.getCurrentDirectory() + self.filelist.getFilename(), 180, 160, self.aspect, int(config.pic.resize.value), 0, 0, cachefile)
+                       ptr = loadPic(self.filelist.getCurrentDirectory() + self.filelist.getFilename(), 180, 160, self.aspect, int(config.pic.resize.value), 0, 0, cachefile, 1)
                        if ptr != None:
                                self["thumbnail"].show()
                                self["thumbnail"].instance.setPixmap(ptr)
index a0db1d6..6df4fce 100644 (file)
@@ -45,6 +45,10 @@ class PluginDescriptor:
        # or return a function which is called with session and the interface name for extended setup of this interface
        WHERE_NETWORKSETUP = 10
        
+       # show up this plugin (or a choicebox with all of them) for long INFO keypress
+       # or return a function which is called with session and the interface name for extended setup of this interface
+       WHERE_EVENTINFO = 11
+
        def __init__(self, name = "Plugin", where = [ ], description = "", icon = None, fnc = None, wakeupfnc = None, internal = False):
                self.name = name
                self.internal = internal
index 469b1dd..97ddf4a 100644 (file)
@@ -8,6 +8,8 @@ DEVICEDB =  \
          "/devices/pci0000:00/0000:00:14.2/usb1/1-1/1-1:1.0/host0/target1:0:0/0:0:0:0": "SD Slot"
        }
 
+hotplugNotifier = [ ]
+
 class Hotplug(Protocol):
        def getUserfriendlyDeviceName(self, phys):
                return DEVICEDB.get(phys, "USB Storage")
@@ -48,6 +50,12 @@ class Hotplug(Protocol):
                                harddiskmanager.addHotplugPartition(dev, self.getUserfriendlyDeviceName(physdevpath))
                        elif media_state == '0':
                                harddiskmanager.removeHotplugPartition(dev)
+               
+               for callback in hotplugNotifier:
+                       try:
+                               callback(dev, media_state)
+                       except AttributeError:
+                               hotplugNotifier.remove(callback)
 
 def autostart(reason, **kwargs):
        if reason == 0:
index 7b3d08f..ec223d3 100644 (file)
@@ -23,6 +23,8 @@ class SecParameterSetup(Screen, ConfigListScreen):
 
                Screen.__init__(self, session)
                list = [
+                       ("Delay after diseqc reset command", config.sec.delay_after_diseqc_reset_cmd),
+                       ("Delay after diseqc peripherial poweron command", config.sec.delay_after_diseqc_peripherial_poweron_cmd),
                        ("Delay after continuous tone change", config.sec.delay_after_continuous_tone_change),
                        ("Delay after last voltage change", config.sec.delay_after_final_voltage_change),
                        ("Delay between diseqc commands", config.sec.delay_between_diseqc_repeats),
index aab2b64..cdaa2c1 100644 (file)
@@ -403,8 +403,8 @@ class InfoBarEPG:
                self.eventView = None
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
                        {
-                               "showEventInfo": (self.openEventView, _("show EPG...")),
-                               "showSingleServiceEPG": (self.openSingleServiceEPG, _("show single service EPG...")),
+                               "showEventView": (self.openEventView, _("show EPG...")),
+                               "showEventInfoPlugin": (self.showEventInfoPlugins, _("show single service EPG...")),
                                "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible,
                        })
 
@@ -489,6 +489,23 @@ class InfoBarEPG:
                ref=self.session.nav.getCurrentlyPlayingServiceReference()
                self.session.open(EPGSelection, ref)
 
+       def showEventInfoPlugins(self):
+               list = []
+               for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EVENTINFO):
+                       list.append((p.name, boundFunction(self.runPlugin, p)))
+               if len(list):
+                       list.append((_("show single service EPG..."), self.openSingleServiceEPG))
+                       self.session.openWithCallback(self.EventInfoPluginChosen, ChoiceBox, title=_("Please choose an extension..."), list = list)
+               else:
+                       self.openSingleServiceEPG()
+                       
+       def runPlugin(self, plugin):
+               plugin(session = self.session, servicelist = self.servicelist)
+               
+       def EventInfoPluginChosen(self, answer):
+               if answer is not None:
+                       answer[1]()
+
        def openSimilarList(self, eventid, refstr):
                self.session.open(EPGSelection, refstr, None, eventid)
 
@@ -1258,7 +1275,6 @@ class InfoBarExtensions:
 from Tools.BoundFunction import boundFunction
 
 # depends on InfoBarExtensions
-from Components.PluginComponent import plugins
 
 class InfoBarPlugins:
        def __init__(self):
index 43b8a8b..61ce356 100644 (file)
@@ -8,12 +8,14 @@ from Tools.BoundFunction import boundFunction
 from time import time
 
 class InputBox(Screen):
-       def __init__(self, session, title = "", windowTitle = _("Input"), **kwargs):
+       def __init__(self, session, title = "", windowTitle = _("Input"), useableChars = None, **kwargs):
                Screen.__init__(self, session)
 
                self["text"] = Label(title)
                self["input"] = Input(**kwargs)
                self.onShown.append(boundFunction(self.setTitle, windowTitle))
+               if useableChars is not None:
+                       self["input"].setUseableChars(useableChars)
 
                self["actions"] = NumberActionMap(["WizardActions", "InputBoxActions", "InputAsciiActions", "KeyboardInputActions"], 
                {
index 7cd6cbf..68d4f77 100644 (file)
@@ -503,3 +503,32 @@ class MovieLocationBox(LocationBox):
        def __init__(self, session, text, dir, minFree = None):
                inhibitDirs = ["/bin", "/boot", "/dev", "/etc", "/lib", "/proc", "/sbin", "/sys", "/usr", "/var"]
                LocationBox.__init__(self, session, text = text, currDir = dir, bookmarks = config.movielist.videodirs, autoAdd = True, editDir = True, inhibitDirs = inhibitDirs, minFree = minFree)
+
+class TimeshiftLocationBox(LocationBox):
+
+       skinName = "LocationBox" # XXX: though we could use a custom skin or inherit the hardcoded one we stick with the original :-)
+
+       def __init__(self, session):
+               inhibitDirs = ["/bin", "/boot", "/dev", "/etc", "/lib", "/proc", "/sbin", "/sys", "/usr", "/var"]
+               LocationBox.__init__(
+                               self,
+                               session,
+                               text = _("Where to save temporary timeshift recordings?"),
+                               currDir = config.usage.timeshift_path.value,
+                               bookmarks = config.usage.allowed_timeshift_paths,
+                               autoAdd = True,
+                               editDir = True,
+                               inhibitDirs = inhibitDirs,
+                               minFree = 1024 # XXX: the same requirement is hardcoded in servicedvb.cpp
+               )
+
+       def cancel(self):
+               config.usage.timeshift_path.cancel()
+               LocationBox.cancel(self)
+
+       def selectConfirmed(self, ret):
+               if ret:
+                       config.usage.timeshift_path.value = self.getPreferredFolder()
+                       config.usage.timeshift_path.save()
+                       LocationBox.selectConfirmed(self, ret)
+
old mode 100644 (file)
new mode 100755 (executable)
index 186c6f3..a3cf70b
@@ -13,5 +13,5 @@ install_PYTHON = \
        TimerSelection.py PictureInPicture.py TimeDateInput.py \
        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
+       SessionGlobals.py LocationBox.py WizardLanguage.py TaskView.py Rc.py VirtualKeyBoard.py
 
index c05f145..5951653 100644 (file)
@@ -29,6 +29,28 @@ config.movielist.description = ConfigInteger(default=MovieList.HIDE_DESCRIPTION)
 config.movielist.last_videodir = ConfigText(default=resolveFilename(SCOPE_HDD))
 config.movielist.last_timer_videodir = ConfigText(default=resolveFilename(SCOPE_HDD))
 config.movielist.videodirs = ConfigLocations(default=[resolveFilename(SCOPE_HDD)])
+config.movielist.first_tags = ConfigText(default="")
+config.movielist.second_tags = ConfigText(default="")
+
+
+def setPreferredTagEditor(te):
+       global preferredTagEditor
+       try:
+               if preferredTagEditor == None:
+                       preferredTagEditor = te
+                       print "Preferred tag editor changed to ", preferredTagEditor
+               else:
+                       print "Preferred tag editor already set to ", preferredTagEditor
+                       print "ignoring ", te
+       except:
+               preferredTagEditor = te
+               print "Preferred tag editor set to ", preferredTagEditor
+
+def getPreferredTagEditor():
+       global preferredTagEditor
+       return preferredTagEditor
+
+setPreferredTagEditor(None)
 
 class MovieContextMenu(Screen):
        def __init__(self, session, csel, service):
@@ -71,10 +93,8 @@ class MovieContextMenu(Screen):
 
        def sortBy(self, newType):
                config.movielist.moviesort.value = newType
-               self.csel.selectedmovie = self.csel.getCurrent()
                self.csel.setSortType(newType)
                self.csel.reloadList()
-               self.csel.moveTo()
                self.close()
 
        def listType(self, newType):
@@ -123,7 +143,7 @@ class MovieContextMenu(Screen):
                        self.session.openWithCallback(self.close, MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
                else:
                        self.csel["list"].removeService(self.service)
-                       self.csel["freeDiskSpace"].update()
+                       self.csel["freeDiskSpace"].update()
                        self.close()
 
 class SelectionEventInfo:
@@ -149,6 +169,7 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
 
                self.tags = [ ]
                self.selected_tags = None
+               self.selected_tags_ele = None
 
                self.movemode = False
                self.bouquet_mark_edit = False
@@ -178,7 +199,7 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
                # Need list for init
                SelectionEventInfo.__init__(self)
 
-               self["key_red"] = Button(_("All..."))
+               self["key_red"] = Button(_("All"))
                self["key_green"] = Button("")
                self["key_yellow"] = Button("")
                self["key_blue"] = Button("")
@@ -201,9 +222,9 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
                self["ColorActions"] = HelpableActionMap(self, "ColorActions",
                        {
                                "red": (self.showAll, _("show all")),
-                               "green": (self.showTagsFirst, _("show first tag")),
-                               "yellow": (self.showTagsSecond, _("show second tag")),
-                               "blue": (self.showTagsMenu, _("show tag menu")),
+                               "green": (self.showTagsFirst, _("show first selected tag")),
+                               "yellow": (self.showTagsSecond, _("show second selected tag")),
+                               "blue": (self.showTagsSelect, _("show tag menu")),
                        })
 
                self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
@@ -246,11 +267,8 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
                        self.updateDescription()
 
        def updateHDDData(self):
-               self.reloadList()
-               if self.selectedmovie is not None:
-                       self.moveTo()
+               self.reloadList(self.selectedmovie)
                self["waitingtext"].visible = False
-               self.updateTags()
 
        def moveTo(self):
                self["list"].moveTo(self.selectedmovie)
@@ -285,26 +303,29 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
        def updateTags(self):
                # get a list of tags available in this list
                self.tags = list(self["list"].tags)
-               
-               # by default, we do not display any filtering options
-               self.tag_first = ""
-               self.tag_second = ""
-               
-               # when tags are present, however, the first two are 
-               # directly mapped to the second, third ("green", "yellow") buttons
-               if len(self.tags) > 0:
-                       self.tag_first = self.getTagDescription(self.tags[0])
-               
-               if len(self.tags) > 1:
-                       self.tag_second = self.getTagDescription(self.tags[1])
-               
+
+               if not self.tags:
+                       # by default, we do not display any filtering options
+                       self.tag_first = ""
+                       self.tag_second = ""
+               else:
+                       tmp = config.movielist.first_tags.value
+                       if tmp in self.tags:
+                               self.tag_first = tmp
+                       else:
+                               self.tag_first = "<"+_("Tag 1")+">"
+                       tmp = config.movielist.second_tags.value
+                       if tmp in self.tags:
+                               self.tag_second = tmp
+                       else:
+                               self.tag_second = "<"+_("Tag 2")+">"
                self["key_green"].text = self.tag_first
                self["key_yellow"].text = self.tag_second
                
                # the rest is presented in a list, available on the
                # fourth ("blue") button
-               if len(self.tags) > 2:
-                       self["key_blue"].text = _("Other...")
+               if self.tags:
+                       self["key_blue"].text = _("Tags")+"..."
                else:
                        self["key_blue"].text = ""
 
@@ -317,20 +338,26 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
        def setSortType(self, type):
                self["list"].setSortType(type)
 
-       def reloadList(self):
+       def reloadList(self, sel = None, home = False):
                if not pathExists(config.movielist.last_videodir.value):
                        path = resolveFilename(SCOPE_HDD)
                        config.movielist.last_videodir.value = path
                        config.movielist.last_videodir.save()
                        self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + path)
                        self["freeDiskSpace"].path = path
+               if sel is None:
+                       sel = self.getCurrent()
                self["list"].reload(self.current_ref, self.selected_tags)
                title = _("Recorded files...")
-               if self.selected_tags is not None:
-                       title += " - " + ','.join(self.selected_tags)
                if config.usage.setup_level.index >= 2: # expert+
                        title += "  " + config.movielist.last_videodir.value
+               if self.selected_tags is not None:
+                       title += " - " + ','.join(self.selected_tags)
                self.setTitle(title)
+               if not (sel and self["list"].moveTo(sel)):
+                       if home:
+                               self["list"].moveToIndex(0)
+               self.updateTags()
                self["freeDiskSpace"].update()
 
        def doPathSelect(self):
@@ -348,7 +375,7 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
                                config.movielist.last_videodir.save()
                                self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + res)
                                self["freeDiskSpace"].path = res
-                               self.reloadList()
+                               self.reloadList(home = True)
                        else:
                                self.session.open(
                                        MessageBox,
@@ -358,35 +385,41 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
                                        )
 
        def showAll(self):
+               self.selected_tags_ele = None
                self.selected_tags = None
-               self.reloadList()
+               self.reloadList(home = True)
 
-       def showTagsN(self, n):
-               if len(self.tags) < n:
+       def showTagsN(self, tagele):
+               if not self.tags:
                        self.showTagWarning()
+               elif not tagele or self.selected_tags_ele == tagele or not tagele.value in self.tags:
+                       self.showTagsMenu(tagele)
                else:
-                       print "select tag #%d, %s, %s" % (n, self.tags[n - 1], ','.join(self.tags))
-                       self.selected_tags = set([self.tags[n - 1]])
-                       self.reloadList()
+                       self.selected_tags_ele = tagele
+                       self.selected_tags = set([tagele.value])
+                       self.reloadList(home = True)
 
        def showTagsFirst(self):
-               self.showTagsN(1)
+               self.showTagsN(config.movielist.first_tags)
 
        def showTagsSecond(self):
-               self.showTagsN(2)
+               self.showTagsN(config.movielist.second_tags)
+
+       def showTagsSelect(self):
+               self.showTagsN(None)
 
        def tagChosen(self, tag):
                if tag is not None:
                        self.selected_tags = set([tag[0]])
-                       self.reloadList()
+                       if self.selected_tags_ele:
+                               self.selected_tags_ele.value = tag[0]
+                               self.selected_tags_ele.save()
+                       self.reloadList(home = True)
 
-       def showTagsMenu(self):
-               if len(self.tags) < 3:
-                       self.showTagWarning()
-               else:
-                       list = [(tag, self.getTagDescription(tag)) for tag in self.tags ]
-                       self.session.openWithCallback(self.tagChosen, ChoiceBox, title=_("Please select keyword to filter..."), list = list)
+       def showTagsMenu(self, tagele):
+               self.selected_tags_ele = tagele
+               list = [(tag, self.getTagDescription(tag)) for tag in self.tags ]
+               self.session.openWithCallback(self.tagChosen, ChoiceBox, title=_("Please select tag to filter..."), list = list)
 
        def showTagWarning(self):
-               # TODO
-               self.session.open(MessageBox, _("You need to define some keywords first!\nPress the menu-key to define keywords.\nDo you want to define keywords now?"), MessageBox.TYPE_ERROR)
+               self.session.open(MessageBox, _("No tags are set on these movies."), MessageBox.TYPE_ERROR)
old mode 100644 (file)
new mode 100755 (executable)
index 862bce4..ea2d17e
@@ -1,25 +1,25 @@
 from Screen import Screen
-from Components.ActionMap import ActionMap,NumberActionMap
 from Screens.MessageBox import MessageBox
 from Screens.InputBox import InputBox
 from Screens.Standby import *
+from Screens.VirtualKeyBoard import VirtualKeyBoard
+from Screens.HelpMenu import HelpableScreen
 from Components.Network import iNetwork
 from Components.Label import Label,MultiColorLabel
 from Components.Pixmap import Pixmap,MultiPixmap
 from Components.MenuList import MenuList
-from Components.config import config, ConfigYesNo, ConfigIP, NoSave, ConfigText, ConfigSelection, getConfigListEntry, ConfigNothing
+from Components.config import config, ConfigYesNo, ConfigIP, NoSave, ConfigText, ConfigPassword, ConfigSelection, getConfigListEntry, ConfigNothing
 from Components.ConfigList import ConfigListScreen
 from Components.PluginComponent import plugins
 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
+from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
+from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
+from Tools.LoadPixmap import LoadPixmap
 from Plugins.Plugin import PluginDescriptor
-from enigma import eTimer
+from enigma import eTimer, ePoint, eSize, RT_HALIGN_LEFT, eListboxPythonMultiContent, gFont
 from os import path as os_path, system as os_system, unlink
 from re import compile as re_compile, search as re_search
-from Tools.Directories import resolveFilename, SCOPE_PLUGINS
 
-from Tools.Directories import SCOPE_SKIN_IMAGE,SCOPE_PLUGINS, resolveFilename
-from Tools.LoadPixmap import LoadPixmap
-from enigma import RT_HALIGN_LEFT, eListboxPythonMultiContent, gFont
 
 class InterfaceList(MenuList):
        def __init__(self, list, enableWrapAround=False):
@@ -30,11 +30,13 @@ class InterfaceList(MenuList):
 def InterfaceEntryComponent(index,name,default,active ):
        res = [ (index) ]
        res.append(MultiContentEntryText(pos=(80, 5), size=(430, 25), font=0, text=name))
-       if default is True:
-               png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/buttons/button_blue.png"))
-       if default is False:
-               png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/buttons/button_blue_off.png"))
-       res.append(MultiContentEntryPixmapAlphaTest(pos=(10, 5), size=(25, 25), png = png))
+       num_configured_if = len(iNetwork.getConfiguredAdapters())
+       if num_configured_if >= 2:
+               if default is True:
+                       png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/buttons/button_blue.png"))
+               if default is False:
+                       png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/buttons/button_blue_off.png"))
+               res.append(MultiContentEntryPixmapAlphaTest(pos=(10, 5), size=(25, 25), png = png))
        if active is True:
                png2 = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/lock_on.png"))
        if active is False:
@@ -43,41 +45,64 @@ def InterfaceEntryComponent(index,name,default,active ):
        return res
 
 
-class NetworkAdapterSelection(Screen):
+class NetworkAdapterSelection(Screen,HelpableScreen):
        def __init__(self, session):
                Screen.__init__(self, session)
-
-               self.wlan_errortext = _("No working wireless networkadapter found.\nPlease verify that you have attached a compatible WLAN USB Stick and your Network is configured correctly.")
-               self.lan_errortext = _("No working local networkadapter found.\nPlease verify that you have attached a network cable and your Network is configured correctly.")
+               HelpableScreen.__init__(self)
+               
+               self.wlan_errortext = _("No working wireless network adapter found.\nPlease verify that you have attached a compatible WLAN device and your network is configured correctly.")
+               self.lan_errortext = _("No working local network adapter found.\nPlease verify that you have attached a network cable and your network is configured correctly.")
+               self.oktext = _("Press OK on your remote control to continue.")
+               self.restartLanRef = None
                
                self["ButtonBluetext"] = Label(_("Set as default Interface"))
+               self["ButtonBlue"] = Pixmap()
                self["ButtonRedtext"] = Label(_("Close"))
                self["introduction"] = Label(_("Press OK to edit the settings."))
                
                self.adapters = [(iNetwork.getFriendlyAdapterName(x),x) for x in iNetwork.getAdapterList()]
-
+               
                if len(self.adapters) == 0:
                        self.onFirstExecBegin.append(self.NetworkFallback)
-
+                       
+               self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
+                       {
+                       "cancel": (self.close, _("exit network interface list")),
+                       "ok": (self.okbuttonClick, _("select interface")),
+                       })
+
+               self["ColorActions"] = HelpableActionMap(self, "ColorActions",
+                       {
+                       "red": (self.close, _("exit network interface list")),  
+                       })
+               
+               self["DefaultInterfaceAction"] = HelpableActionMap(self, "ColorActions",
+                       {
+                       "blue": (self.setDefaultInterface, [_("Set interface as default Interface"),_("* Only available if more than one interface is active.")] ),     
+                       })
+               
                self.list = []
                self["list"] = InterfaceList(self.list)
                self.updateList()
-               self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
-               {
-                       "ok": self.okbuttonClick,
-                       "cancel": self.close,
-                       "blue": self.setDefaultInterface,                       
-                       "red": self.close
-               }, -2)
-
+               
                if len(self.adapters) == 1:
                        self.onFirstExecBegin.append(self.okbuttonClick)
+               self.onClose.append(self.cleanup)
+
 
        def updateList(self):
-               iNetwork.getInterfaces()
                self.list = []
                default_gw = None
-               num_configured_if = len(iNetwork.configuredInterfaces)
+               num_configured_if = len(iNetwork.getConfiguredAdapters())
+               if num_configured_if >= 2:
+                       self["ButtonBlue"].show()
+                       self["ButtonBluetext"].show()
+                       self["DefaultInterfaceAction"].setEnabled(True)
+               else:
+                       self["ButtonBlue"].hide()
+                       self["ButtonBluetext"].hide()
+                       self["DefaultInterfaceAction"].setEnabled(False)
+
                if num_configured_if < 2 and os_path.exists("/etc/default_gw"):
                        unlink("/etc/default_gw")
                        
@@ -86,7 +111,7 @@ class NetworkAdapterSelection(Screen):
                        result = fp.read()
                        fp.close()
                        default_gw = result
-
+                                       
                if len(self.adapters) == 0: # no interface available => display only eth0
                        self.list.append(InterfaceEntryComponent("eth0",iNetwork.getFriendlyAdapterName('eth0'),True,True ))
                else:
@@ -106,24 +131,22 @@ class NetworkAdapterSelection(Screen):
                selection = self["list"].getCurrent()
                num_if = len(self.list)
                old_default_gw = None
+               num_configured_if = len(iNetwork.getConfiguredAdapters())
                if os_path.exists("/etc/default_gw"):
                        fp = open('/etc/default_gw', 'r')
                        old_default_gw = fp.read()
                        fp.close()
-               if num_if > 1 and (not old_default_gw or old_default_gw != selection[0]):
+               if num_configured_if > 1 and (not old_default_gw or old_default_gw != selection[0]):
                        fp = open('/etc/default_gw', 'w+')
                        fp.write(selection[0])
                        fp.close()
-                       iNetwork.restartNetwork()
-                       self.updateList()
-               elif old_default_gw and num_if < 2:
+                       self.restartLan()
+               elif old_default_gw and num_configured_if < 2:
                        unlink("/etc/default_gw")
-                       iNetwork.restartNetwork()
-                       self.updateList()
+                       self.restartLan()
 
        def okbuttonClick(self):
                selection = self["list"].getCurrent()
-               print "selection",selection
                if selection is not None:
                        self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetupConfiguration, selection[0])
 
@@ -134,25 +157,48 @@ class NetworkAdapterSelection(Screen):
                        self.updateList()
 
        def NetworkFallback(self):
-               if iNetwork.configuredInterfaces.has_key('wlan0') is True:
+               if iNetwork.configuredNetworkAdapters.has_key('wlan0') is True:
                        self.session.openWithCallback(self.ErrorMessageClosed, MessageBox, self.wlan_errortext, type = MessageBox.TYPE_INFO,timeout = 10)
-               if iNetwork.configuredInterfaces.has_key('ath0') is True:
+               if iNetwork.configuredNetworkAdapters.has_key('ath0') is True:
                        self.session.openWithCallback(self.ErrorMessageClosed, MessageBox, self.wlan_errortext, type = MessageBox.TYPE_INFO,timeout = 10)
                else:
                        self.session.openWithCallback(self.ErrorMessageClosed, MessageBox, self.lan_errortext, type = MessageBox.TYPE_INFO,timeout = 10)
 
        def ErrorMessageClosed(self, *ret):
-               if iNetwork.configuredInterfaces.has_key('wlan0') is True:
+               if iNetwork.configuredNetworkAdapters.has_key('wlan0') is True:
                        self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetupConfiguration, 'wlan0')
-               elif iNetwork.configuredInterfaces.has_key('ath0') is True:
+               elif iNetwork.configuredNetworkAdapters.has_key('ath0') is True:
                        self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetupConfiguration, 'ath0')
                else:
                        self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetupConfiguration, 'eth0')
 
-class NameserverSetup(Screen, ConfigListScreen):
+       def cleanup(self):
+               iNetwork.stopLinkStateConsole()
+               iNetwork.stopRestartConsole()
+               iNetwork.stopGetInterfacesConsole()
+
+       def restartLan(self):
+               iNetwork.restartNetwork(self.restartLanDataAvail)
+               self.restartLanRef = self.session.openWithCallback(self.restartfinishedCB, MessageBox, _("Please wait while we configure your network..."), type = MessageBox.TYPE_INFO, enable_input = False)
+                       
+       def restartLanDataAvail(self, data):
+               if data is True:
+                       iNetwork.getInterfaces(self.getInterfacesDataAvail)
+
+       def getInterfacesDataAvail(self, data):
+               if data is True:
+                       self.restartLanRef.close(True)
+
+       def restartfinishedCB(self,data):
+               if data is True:
+                       self.updateList()
+                       self.session.open(MessageBox, _("Finished configuring your network"), type = MessageBox.TYPE_INFO, timeout = 10, default = False)
+
+
+class NameserverSetup(Screen, ConfigListScreen, HelpableScreen):
        def __init__(self, session):
                Screen.__init__(self, session)
-               iNetwork.getInterfaces()
+               HelpableScreen.__init__(self)
                self.backupNameserverList = iNetwork.getNameserverList()[:]
                print "backup-list:", self.backupNameserverList
                
@@ -162,14 +208,23 @@ class NameserverSetup(Screen, ConfigListScreen):
                self["introduction"] = Label(_("Press OK to activate the settings."))
                self.createConfig()
                
-               self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
+               self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
+                       {
+                       "cancel": (self.cancel, _("exit nameserver configuration")),
+                       "ok": (self.ok, _("activate current configuration")),
+                       })
+               
+               self["ColorActions"] = HelpableActionMap(self, "ColorActions",
+                       {
+                       "red": (self.cancel, _("exit nameserver configuration")),
+                       "green": (self.add, _("add a nameserver entry")),
+                       "yellow": (self.remove, _("remove a nameserver entry")),
+                       })
+               
+               self["actions"] = NumberActionMap(["SetupActions"],
                {
                        "ok": self.ok,
-                       "cancel": self.cancel,
-                       "red": self.cancel,
-                       "green": self.add,
-                       "yellow": self.remove
-               }, -2)
+               }, -2)          
                
                self.list = []
                ConfigListScreen.__init__(self, self.list)
@@ -222,31 +277,55 @@ class NameserverSetup(Screen, ConfigListScreen):
                        self.createConfig()
                        self.createSetup()
        
-class AdapterSetup(Screen, ConfigListScreen):
-       def __init__(self, session, iface,essid=None, aplist=None):
+class AdapterSetup(Screen, ConfigListScreen, HelpableScreen):
+       def __init__(self, session, networkinfo, essid=None, aplist=None):
                Screen.__init__(self, session)
+               HelpableScreen.__init__(self)
                self.session = session
-               self.iface = iface
-               self.essid = essid
-               self.aplist = aplist
+               if isinstance(networkinfo, (list, tuple)):
+                       self.iface = networkinfo[0]
+                       self.essid = networkinfo[1]
+                       self.aplist = networkinfo[2]
+               else:
+                       self.iface = networkinfo
+                       self.essid = essid
+                       self.aplist = aplist
                self.extended = None
+               self.applyConfigRef = None
+               self.finished_cb = None
+               self.oktext = _("Press OK on your remote control to continue.")
                self.oldInterfaceState = iNetwork.getAdapterAttribute(self.iface, "up")
-               iNetwork.getInterfaces()
 
                self.createConfig()
-               
-               self["actions"] = NumberActionMap(["SetupActions", "ColorActions"],
+
+               self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
+                       {
+                       "cancel": (self.cancel, _("exit network adapter setup menu")),
+                       "ok": (self.ok, _("select menu entry")),
+                       })
+
+               self["ColorActions"] = HelpableActionMap(self, "ColorActions",
+                       {
+                       "red": (self.cancel, _("exit network adapter configuration")),
+                       "blue": (self.KeyBlue, _("open nameserver configuration")),
+                       })
+
+               self["VirtualKB"] = HelpableActionMap(self, "ColorActions",
+                       {
+                       "green": (self.KeyGreen, [_("open virtual keyboard input help"),_("* Only available when entering hidden SSID or network key")] ),                                      
+                       })
+
+               self["actions"] = NumberActionMap(["SetupActions"],
                {
                        "ok": self.ok,
-                       "cancel": self.cancel,
-                       "red": self.cancel,
-                       "blue": self.KeyBlue,
                }, -2)
                
+               
                self.list = []
                ConfigListScreen.__init__(self, self.list,session = self.session)
                self.createSetup()
                self.onLayoutFinish.append(self.layoutFinished)
+               self.onClose.append(self.cleanup)
                
                self["DNS1text"] = Label(_("Primary DNS"))
                self["DNS2text"] = Label(_("Secondary DNS"))
@@ -271,76 +350,105 @@ class AdapterSetup(Screen, ConfigListScreen):
                self["ButtonRedtext"] = Label(_("Close"))
                self["ButtonBlue"] = Pixmap()
                self["ButtonBluetext"] = Label(_("Edit DNS"))
+               self["ButtonGreen"] = Pixmap()
+               self["VKeyIcon"] = Pixmap()
+               self["HelpWindow"] = Pixmap()
 
        def layoutFinished(self):
                self["DNS1"].setText(self.primaryDNS.getText())
                self["DNS2"].setText(self.secondaryDNS.getText())
                if self.ipConfigEntry.getText() is not None:
-                       self["IP"].setText(self.ipConfigEntry.getText())
+                       if self.ipConfigEntry.getText() == "0.0.0.0":
+                               self["IP"].setText(_("N/A"))
+                       else:   
+                               self["IP"].setText(self.ipConfigEntry.getText())
+               else:
+                       self["IP"].setText(_("N/A"))
+               if self.netmaskConfigEntry.getText() is not None:
+                       if self.netmaskConfigEntry.getText() == "0.0.0.0":
+                                       self["Mask"].setText(_("N/A"))
+                       else:   
+                               self["Mask"].setText(self.netmaskConfigEntry.getText())
                else:
-                       self["IP"].setText([0,0,0,0])
-               self["Mask"].setText(self.netmaskConfigEntry.getText())
+                       self["IP"].setText(_("N/A"))                    
                if iNetwork.getAdapterAttribute(self.iface, "gateway"):
-                       self["Gateway"].setText(self.gatewayConfigEntry.getText())
+                       if self.gatewayConfigEntry.getText() == "0.0.0.0":
+                               self["Gateway"].setText(_("N/A"))
+                       else:
+                               self["Gateway"].setText(self.gatewayConfigEntry.getText())
                else:
                        self["Gateway"].hide()
                        self["Gatewaytext"].hide()
                self["Adapter"].setText(iNetwork.getFriendlyAdapterName(self.iface))
+               self["ButtonGreen"].hide()
+               self["VKeyIcon"].hide()
+               self["VirtualKB"].setEnabled(False)
+               self["HelpWindow"].hide()
 
        def createConfig(self):
                self.InterfaceEntry = None
                self.dhcpEntry = None
                self.gatewayEntry = None
-               self.SSIDscan = None
+               self.hiddenSSID = None
                self.wlanSSID = None
-               self.manualwlanSSID = None
                self.encryptionEnabled = None
                self.encryptionKey = None
+               self.encryptionType = None
                self.nwlist = None
+               self.encryptionlist = None
+               self.weplist = None
                self.wsconfig = None
                self.default = None
                
                if self.iface == "wlan0" or self.iface == "ath0" :
                        from Plugins.SystemPlugins.WirelessLan.Wlan import wpaSupplicant,Wlan
+                       self.w = Wlan(self.iface)
                        self.ws = wpaSupplicant()
-                       list = []
-                       list.append(_("WEP"))
-                       list.append(_("WPA"))
-                       list.append(_("WPA2"))
+                       self.encryptionlist = []
+                       self.encryptionlist.append(("WEP", _("WEP")))
+                       self.encryptionlist.append(("WPA", _("WPA")))
+                       self.encryptionlist.append(("WPA2", _("WPA2")))
+                       self.encryptionlist.append(("WPA/WPA2", _("WPA or WPA2")))
+                       self.weplist = []
+                       self.weplist.append("ASCII")
+                       self.weplist.append("HEX")
                        if self.aplist is not None:
                                self.nwlist&