Support Uno4k/Ultimo4k
authorhschang <chang@dev3>
Thu, 24 Nov 2016 03:50:07 +0000 (12:50 +0900)
committerhschang <chang@dev3>
Thu, 24 Nov 2016 03:50:07 +0000 (12:50 +0900)
  - Fix FCC for uno4k/ultimo4k
  - Fix APIs to support 1080p skin
  - Support HDMI colordepth (VideoMode)
  - Support TT2L08 automatic scan

58 files changed:
ServiceReference.py
configure.ac
data/startwizard.xml
lib/dvb/decoder.cpp
lib/dvb/demux.cpp
lib/dvb/demux.h
lib/dvb/dvb.cpp [changed mode: 0755->0644]
lib/dvb/dvb.h
lib/dvb/fbc.cpp
lib/dvb/fbc.h
lib/dvb/fcc.cpp
lib/dvb/frontend.cpp
lib/dvb/frontend.h
lib/gui/elistbox.cpp
lib/gui/elistbox.h
lib/gui/elistboxcontent.cpp
lib/nav/core.cpp
lib/nav/core.h
lib/python/Components/ChoiceList.py
lib/python/Components/ConfigList.py
lib/python/Components/EpgList.py
lib/python/Components/FileList.py
lib/python/Components/HelpMenuList.py
lib/python/Components/InputDevice.py
lib/python/Components/MediaPlayer.py
lib/python/Components/MovieList.py
lib/python/Components/ParentalControlList.py
lib/python/Components/PluginList.py
lib/python/Components/SelectionList.py
lib/python/Components/SystemInfo.py
lib/python/Components/TimerList.py
lib/python/Plugins/Extensions/GraphMultiEPG/GraphMultiEpg.py
lib/python/Plugins/SystemPlugins/Makefile.am
lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/Makefile.am [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/__init__.py [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/meta/Makefile.am [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/meta/plugin_ultimo4kmisccontrol.xml [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/plugin.py [new file with mode: 0644]
lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py
lib/python/Plugins/SystemPlugins/WOLSetup/plugin.py
lib/python/Plugins/SystemPlugins/WirelessAccessPoint/plugin.py
lib/python/Plugins/SystemPlugins/WirelessLanSetup/plugin.py
lib/python/Screens/InfoBar.py
lib/python/Screens/InfoBarGenerics.py
lib/python/Screens/PluginBrowser.py
lib/python/Screens/Satconfig.py
lib/python/Screens/ScanSetup.py
lib/python/Screens/ServiceInfo.py
lib/python/Screens/VirtualKeyBoard.py
lib/python/Tools/HardwareInfo.py
lib/python/enigma_python.i
lib/service/Makefile.am
lib/service/servicedvb.cpp
lib/service/servicedvb.h
lib/service/servicedvbfcc.cpp
lib/service/servicehdmi.cpp [new file with mode: 0644]
lib/service/servicehdmi.h [new file with mode: 0644]
skin.py

index 0a46992..401e47a 100644 (file)
@@ -32,4 +32,4 @@ class ServiceReference(eServiceReference):
 
        def isRecordable(self):
                ref = self.ref
-               return ref.flags & eServiceReference.isGroup or (ref.type == eServiceReference.idDVB)
\ No newline at end of file
+               return ref.flags & eServiceReference.isGroup or (ref.type == eServiceReference.idDVB) or (ref.type == 0x2000)
\ No newline at end of file
index 7c52d00..00a4bd2 100644 (file)
@@ -308,6 +308,8 @@ lib/python/Plugins/SystemPlugins/Solo4kMiscControl/Makefile
 lib/python/Plugins/SystemPlugins/Solo4kMiscControl/meta/Makefile
 lib/python/Plugins/SystemPlugins/FastChannelChange/Makefile
 lib/python/Plugins/SystemPlugins/FastChannelChange/meta/Makefile
+lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/Makefile
+lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/meta/Makefile
 lib/python/Tools/Makefile
 lib/service/Makefile
 lib/components/Makefile
index db04392..5ed6413 100755 (executable)
@@ -48,8 +48,8 @@ self.selectKey("RIGHT")
                <step id="nimc">
                        <condition>
 from Components.NimManager import nimmanager
-from Screens.Satconfig import isFBCLink
-self.condition = len(nimmanager.nim_slots) > 2 and not nimmanager.nim_slots[2].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[2])
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 2 and not nimmanager.nim_slots[2].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[2].slot)
                        </condition>
                        <text value="Please set up tuner C" />
                        <config screen="NimSetup" module="Satconfig" args="2" type="ConfigList" />
@@ -62,8 +62,8 @@ self.selectKey("RIGHT")
                <step id="nimd">
                        <condition>
 from Components.NimManager import nimmanager
-from Screens.Satconfig import isFBCLink
-self.condition = len(nimmanager.nim_slots) > 3 and not nimmanager.nim_slots[3].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[3])
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 3 and not nimmanager.nim_slots[3].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[3].slot)
                        </condition>
                        <text value="Please set up tuner D" />
                        <config screen="NimSetup" module="Satconfig" args="3" type="ConfigList" />
@@ -76,8 +76,8 @@ self.selectKey("RIGHT")
                <step id="nime">
                        <condition>
 from Components.NimManager import nimmanager
-from Screens.Satconfig import isFBCLink
-self.condition = len(nimmanager.nim_slots) > 4 and not nimmanager.nim_slots[4].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[4])
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 4 and not nimmanager.nim_slots[4].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[4].slot)
                        </condition>
                        <text value="Please set up tuner E" />
                        <config screen="NimSetup" module="Satconfig" args="4" type="ConfigList" />
@@ -90,8 +90,8 @@ self.selectKey("RIGHT")
                <step id="nimf">
                        <condition>
 from Components.NimManager import nimmanager
-from Screens.Satconfig import isFBCLink
-self.condition = len(nimmanager.nim_slots) > 5 and not nimmanager.nim_slots[5].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[5])
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 5 and not nimmanager.nim_slots[5].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[5].slot)
                        </condition>
                        <text value="Please set up tuner F" />
                        <config screen="NimSetup" module="Satconfig" args="5" type="ConfigList" />
@@ -104,8 +104,8 @@ self.selectKey("RIGHT")
                <step id="nimg">
                        <condition>
 from Components.NimManager import nimmanager
-from Screens.Satconfig import isFBCLink
-self.condition = len(nimmanager.nim_slots) > 6 and not nimmanager.nim_slots[6].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[6])
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 6 and not nimmanager.nim_slots[6].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[6].slot)
                        </condition>
                        <text value="Please set up tuner G" />
                        <config screen="NimSetup" module="Satconfig" args="6" type="ConfigList" />
@@ -118,8 +118,8 @@ self.selectKey("RIGHT")
                <step id="nimh">
                        <condition>
 from Components.NimManager import nimmanager
-from Screens.Satconfig import isFBCLink
-self.condition = len(nimmanager.nim_slots) > 7 and not nimmanager.nim_slots[7].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[7])
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 7 and not nimmanager.nim_slots[7].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[7].slot)
                        </condition>
                        <text value="Please set up tuner H" />
                        <config screen="NimSetup" module="Satconfig" args="7" type="ConfigList" />
@@ -132,8 +132,8 @@ self.selectKey("RIGHT")
                <step id="nimi">
                        <condition>
 from Components.NimManager import nimmanager
-from Screens.Satconfig import isFBCLink
-self.condition = len(nimmanager.nim_slots) > 8 and not nimmanager.nim_slots[8].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[8])
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 8 and not nimmanager.nim_slots[8].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[8].slot)
                        </condition>
                        <text value="Please set up tuner I" />
                        <config screen="NimSetup" module="Satconfig" args="8" type="ConfigList" />
@@ -146,8 +146,8 @@ self.selectKey("RIGHT")
                <step id="nimj">
                        <condition>
 from Components.NimManager import nimmanager
-from Screens.Satconfig import isFBCLink
-self.condition = len(nimmanager.nim_slots) > 9 and not nimmanager.nim_slots[9].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[9])
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 9 and not nimmanager.nim_slots[9].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[9].slot)
                        </condition>
                        <text value="Please set up tuner J" />
                        <config screen="NimSetup" module="Satconfig" args="9" type="ConfigList" />
@@ -157,6 +157,34 @@ self.selectKey("LEFT")
 self.selectKey("RIGHT")
                        </code>
                </step>
+               <step id="nimq">
+                       <condition>
+from Components.NimManager import nimmanager
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 16 and not nimmanager.nim_slots[16].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[16].slot)
+                       </condition>
+                       <text value="Please set up tuner Q" />
+                       <config screen="NimSetup" module="Satconfig" args="16" type="ConfigList" />
+                       <code>
+self.clearSelectedKeys()
+self.selectKey("LEFT")
+self.selectKey("RIGHT")
+                       </code>
+               </step>
+               <step id="nimr">
+                       <condition>
+from Components.NimManager import nimmanager
+from enigma import isFBCLink
+self.condition = len(nimmanager.nim_slots) > 17 and not nimmanager.nim_slots[17].empty and config.misc.startwizard.shownimconfig.value and not isFBCLink(nimmanager.nim_slots[17].slot)
+                       </condition>
+                       <text value="Please set up tuner R" />
+                       <config screen="NimSetup" module="Satconfig" args="17" type="ConfigList" />
+                       <code>
+self.clearSelectedKeys()
+self.selectKey("LEFT")
+self.selectKey("RIGHT")
+                       </code>
+               </step>
                <step id="satlistsquestion">
                        <text value="Do you want to install default sat lists?" />
                        <condition>
index e3d97af..2c8044b 100644 (file)
 #define VIDEO_GET_PTS              _IOR('o', 57, __u64)
 #endif
 
+#ifndef VIDEO_SOURCE_HDMI
+#define VIDEO_SOURCE_HDMI 2
+#endif
+#ifndef AUDIO_SOURCE_HDMI
+#define AUDIO_SOURCE_HDMI 2
+#endif
+
 DEFINE_REF(eDVBAudio);
 
 eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev)
@@ -51,19 +58,31 @@ eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev)
 #if HAVE_DVB_API_VERSION < 3
        sprintf(filename, "/dev/dvb/card%d/audio%d", demux->adapter, dev);
 #else
-       sprintf(filename, "/dev/dvb/adapter%d/audio%d", demux->adapter, dev);
+       sprintf(filename, "/dev/dvb/adapter%d/audio%d", demux ? demux->adapter : 0, dev);
 #endif
        m_fd = ::open(filename, O_RDWR);
        if (m_fd < 0)
                eWarning("%s: %m", filename);
+       if (demux)
+       {
 #if HAVE_DVB_API_VERSION < 3
-       sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
+               sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
 #else
-       sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
+               sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
 #endif
-       m_fd_demux = ::open(filename, O_RDWR);
-       if (m_fd_demux < 0)
-               eWarning("%s: %m", filename);
+               m_fd_demux = ::open(filename, O_RDWR);
+               if (m_fd_demux < 0)
+                       eWarning("%s: %m", filename);
+       }
+       else
+       {
+               m_fd_demux = -1;
+       }
+
+       if (m_fd >= 0)
+       {
+               ::ioctl(m_fd, AUDIO_SELECT_SOURCE, demux ? AUDIO_SOURCE_DEMUX : AUDIO_SOURCE_HDMI);
+       }
 }
 
 #if HAVE_DVB_API_VERSION < 3
@@ -160,89 +179,101 @@ int eDVBAudio::setAVSync(int val)
 #else
 int eDVBAudio::startPid(int pid, int type)
 {
-       if ((m_fd < 0) || (m_fd_demux < 0))
-               return -1;
-       dmx_pes_filter_params pes;
-
-       pes.pid      = pid;
-       pes.input    = DMX_IN_FRONTEND;
-       pes.output   = DMX_OUT_DECODER;
-       pes.pes_type = m_dev ? DMX_PES_AUDIO1 : DMX_PES_AUDIO0; /* FIXME */
-       pes.flags    = 0;
-       eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - audio - ", pid);
-       if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
-       {
-               eDebug("failed (%m)");
-               return -errno;
-       }
-       eDebug("ok");
-       eDebugNoNewLine("DEMUX_START - audio - ");
-       if (::ioctl(m_fd_demux, DMX_START) < 0)
+       if (m_fd_demux >= 0)
        {
-               eDebug("failed (%m)");
-               return -errno;
+               dmx_pes_filter_params pes;
+
+               pes.pid      = pid;
+               pes.input    = DMX_IN_FRONTEND;
+               pes.output   = DMX_OUT_DECODER;
+               pes.pes_type = m_dev ? DMX_PES_AUDIO1 : DMX_PES_AUDIO0; /* FIXME */
+               pes.flags    = 0;
+               eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - audio - ", pid);
+               if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
+               {
+                       eDebug("failed (%m)");
+                       return -errno;
+               }
+               eDebug("ok");
+               eDebugNoNewLine("DEMUX_START - audio - ");
+               if (::ioctl(m_fd_demux, DMX_START) < 0)
+               {
+                       eDebug("failed (%m)");
+                       return -errno;
+               }
+               eDebug("ok");
        }
-       eDebug("ok");
-       int bypass = 0;
 
-       switch (type)
+       if (m_fd >= 0)
        {
-       case aMPEG:
-               bypass = 1;
-               break;
-       case aAC3:
-               bypass = 0;
-               break;
-       case aDTS:
-               bypass = 2;
-               break;
-       case aAAC:
-               bypass = 8;
-               break;
-       case aAACHE:
-               bypass = 9;
-               break;
-       case aLPCM:
-               bypass = 6;
-               break;
-       case aDTSHD:
-               bypass = 0x10;
-               break;
-       case aDDP:
-               bypass = 0x22;
-               break;
+               int bypass = 0;
 
-       }
+               switch (type)
+               {
+               case aMPEG:
+                       bypass = 1;
+                       break;
+               case aAC3:
+                       bypass = 0;
+                       break;
+               case aDTS:
+                       bypass = 2;
+                       break;
+               case aAAC:
+                       bypass = 8;
+                       break;
+               case aAACHE:
+                       bypass = 9;
+                       break;
+               case aLPCM:
+                       bypass = 6;
+                       break;
+               case aDTSHD:
+                       bypass = 0x10;
+                       break;
+               case aDDP:
+                       bypass = 0x22;
+                       break;
 
-       eDebugNoNewLine("AUDIO_SET_BYPASS(%d) - ", bypass);
-       if (::ioctl(m_fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
-               eDebug("failed (%m)");
-       else
-               eDebug("ok");
-       freeze();  // why freeze here?!? this is a problem when only a pid change is requested... because of the unfreeze logic in Decoder::setState
-       eDebugNoNewLine("AUDIO_PLAY - ");
-       if (::ioctl(m_fd, AUDIO_PLAY) < 0)
-               eDebug("failed (%m)");
-       else
-               eDebug("ok");
+               }
+
+               eDebugNoNewLine("AUDIO_SET_BYPASS(%d) - ", bypass);
+               if (::ioctl(m_fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
+                       eDebug("failed (%m)");
+               else
+                       eDebug("ok");
+               freeze();  // why freeze here?!? this is a problem when only a pid change is requested... because of the unfreeze logic in Decoder::setState
+               eDebugNoNewLine("AUDIO_PLAY - ");
+               if (::ioctl(m_fd, AUDIO_PLAY) < 0)
+                       eDebug("failed (%m)");
+               else
+                       eDebug("ok");
+       }
        return 0;
 }
 #endif
 
 void eDVBAudio::stop()
 {
-       eDebugNoNewLine("AUDIO_STOP - ");
-       if (::ioctl(m_fd, AUDIO_STOP) < 0)
-               eDebug("failed (%m)");
-       else
-               eDebug("ok");
+       if (m_fd >= 0)
+       {
+               eDebugNoNewLine("AUDIO_STOP - ");
+               if (::ioctl(m_fd, AUDIO_STOP) < 0)
+                       eDebug("failed (%m)");
+               else
+                       eDebug("ok");
+       }
+
+       if (m_fd_demux >= 0)
+       {
 #if HAVE_DVB_API_VERSION > 2
-       eDebugNoNewLine("DEMUX_STOP - audio - ");
-       if (::ioctl(m_fd_demux, DMX_STOP) < 0)
-               eDebug("failed (%m)");
-       else
-               eDebug("ok");
+               eDebugNoNewLine("DEMUX_STOP - audio - ");
+               if (::ioctl(m_fd_demux, DMX_STOP) < 0)
+                       eDebug("failed (%m)");
+               else
+                       eDebug("ok");
 #endif
+       }
 }
 
 void eDVBAudio::flush()
@@ -317,7 +348,7 @@ eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev, bool fcc_enable)
        if (m_fd_video < 0)
                eWarning("/dev/video: %m");
 #else
-       sprintf(filename, "/dev/dvb/adapter%d/video%d", demux->adapter, dev);
+       sprintf(filename, "/dev/dvb/adapter%d/video%d", demux ? demux->adapter : 0, dev);
 #endif
        m_fd = ::open(filename, O_RDWR);
        if (m_fd < 0)
@@ -328,15 +359,30 @@ eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev, bool fcc_enable)
                CONNECT(m_sn->activated, eDVBVideo::video_event);
        }
        eDebug("Video Device: %s", filename);
+
+
+
+       if (demux)
+       {
 #if HAVE_DVB_API_VERSION < 3
-       sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
+               sprintf(filename, "/dev/dvb/card%d/demux%d", demux->adapter, demux->demux);
 #else
-       sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
+               sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux);
 #endif
-       m_fd_demux = ::open(filename, O_RDWR);
-       if (m_fd_demux < 0)
-               eWarning("%s: %m", filename);
-       eDebug("demux device: %s", filename);
+               m_fd_demux = ::open(filename, O_RDWR);
+               if (m_fd_demux < 0)
+                       eWarning("%s: %m", filename);
+               eDebug("demux device: %s", filename);
+       }
+       else
+       {
+               m_fd_demux = -1;
+       }
+
+       if (m_fd >= 0)
+       {
+               ::ioctl(m_fd, VIDEO_SELECT_SOURCE, demux ? VIDEO_SOURCE_DEMUX : VIDEO_SOURCE_HDMI);
+       }
 }
 
 // not finally values i think.. !!
@@ -408,71 +454,79 @@ int eDVBVideo::stopPid()
 #else
 int eDVBVideo::startPid(int pid, int type)
 {
-       int streamtype = VIDEO_STREAMTYPE_MPEG2;
-
        if (m_fcc_enable)
                return 0;
 
-       if ((m_fd < 0) || (m_fd_demux < 0))
-               return -1;
-       dmx_pes_filter_params pes;
-
-       switch(type)
+       if (m_fd >= 0)
        {
-       default:
-       case MPEG2:
-               break;
-       case MPEG4_H264:
-               streamtype = VIDEO_STREAMTYPE_MPEG4_H264;
-               break;
-       case MPEG1:
-               streamtype = VIDEO_STREAMTYPE_MPEG1;
-               break;
-       case MPEG4_Part2:
-               streamtype = VIDEO_STREAMTYPE_MPEG4_Part2;
-               break;
-       case VC1:
-               streamtype = VIDEO_STREAMTYPE_VC1;
-               break;
-       case VC1_SM:
-               streamtype = VIDEO_STREAMTYPE_VC1_SM;
-               break;
-       case H265_HEVC:
-               streamtype = VIDEO_STREAMTYPE_H265_HEVC;
-               break;
-       }
+               int streamtype = VIDEO_STREAMTYPE_MPEG2;
+               switch(type)
+               {
+                       default:
+                       case MPEG2:
+                               break;
+                       case MPEG4_H264:
+                               streamtype = VIDEO_STREAMTYPE_MPEG4_H264;
+                               break;
+                       case MPEG1:
+                               streamtype = VIDEO_STREAMTYPE_MPEG1;
+                               break;
+                       case MPEG4_Part2:
+                               streamtype = VIDEO_STREAMTYPE_MPEG4_Part2;
+                               break;
+                       case VC1:
+                               streamtype = VIDEO_STREAMTYPE_VC1;
+                               break;
+                       case VC1_SM:
+                               streamtype = VIDEO_STREAMTYPE_VC1_SM;
+                               break;
+                       case H265_HEVC:
+                               streamtype = VIDEO_STREAMTYPE_H265_HEVC;
+                               break;
+               }
 
-       eDebugNoNewLine("VIDEO_SET_STREAMTYPE %d - ", streamtype);
-       if (::ioctl(m_fd, VIDEO_SET_STREAMTYPE, streamtype) < 0)
-               eDebug("failed (%m)");
-       else
-               eDebug("ok");
+               eDebugNoNewLine("VIDEO_SET_STREAMTYPE %d - ", streamtype);
+               if (::ioctl(m_fd, VIDEO_SET_STREAMTYPE, streamtype) < 0)
+                       eDebug("failed (%m)");
+               else
+                       eDebug("ok");
+               
+       }
 
-       pes.pid      = pid;
-       pes.input    = DMX_IN_FRONTEND;
-       pes.output   = DMX_OUT_DECODER;
-       pes.pes_type = m_dev ? DMX_PES_VIDEO1 : DMX_PES_VIDEO0; /* FIXME */
-       pes.flags    = 0;
-       eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - video - ", pid);
-       if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
+       if (m_fd_demux >= 0)
        {
-               eDebug("failed (%m)");
-               return -errno;
+               dmx_pes_filter_params pes;
+
+               pes.pid      = pid;
+               pes.input    = DMX_IN_FRONTEND;
+               pes.output   = DMX_OUT_DECODER;
+               pes.pes_type = m_dev ? DMX_PES_VIDEO1 : DMX_PES_VIDEO0; /* FIXME */
+               pes.flags    = 0;
+               eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - video - ", pid);
+               if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
+               {
+                       eDebug("failed (%m)");
+                       return -errno;
+               }
+               eDebug("ok");
+               eDebugNoNewLine("DEMUX_START - video - ");
+               if (::ioctl(m_fd_demux, DMX_START) < 0)
+               {
+                       eDebug("failed (%m)");
+                       return -errno;
+               }
+               eDebug("ok");
        }
-       eDebug("ok");
-       eDebugNoNewLine("DEMUX_START - video - ");
-       if (::ioctl(m_fd_demux, DMX_START) < 0)
+
+       if (m_fd >= 0)
        {
-               eDebug("failed (%m)");
-               return -errno;
+               freeze();  // why freeze here?!? this is a problem when only a pid change is requested... because of the unfreeze logic in Decoder::setState
+               eDebugNoNewLine("VIDEO_PLAY - ");
+               if (::ioctl(m_fd, VIDEO_PLAY) < 0)
+                       eDebug("failed (%m)");
+               else
+                       eDebug("ok");
        }
-       eDebug("ok");
-       freeze();  // why freeze here?!? this is a problem when only a pid change is requested... because of the unfreeze logic in Decoder::setState
-       eDebugNoNewLine("VIDEO_PLAY - ");
-       if (::ioctl(m_fd, VIDEO_PLAY) < 0)
-               eDebug("failed (%m)");
-       else
-               eDebug("ok");
        return 0;
 }
 #endif
@@ -482,18 +536,25 @@ void eDVBVideo::stop()
        if (m_fcc_enable)
                return;
 
+       if (m_fd_demux >= 0)
+       {
 #if HAVE_DVB_API_VERSION > 2
-       eDebugNoNewLine("DEMUX_STOP - video - ");
-       if (::ioctl(m_fd_demux, DMX_STOP) < 0)
-               eDebug("failed (%m)");
-       else
-               eDebug("ok");
+               eDebugNoNewLine("DEMUX_STOP - video - ");
+               if (::ioctl(m_fd_demux, DMX_STOP) < 0)
+                       eDebug("failed (%m)");
+               else
+                       eDebug("ok");
 #endif
-       eDebugNoNewLine("VIDEO_STOP - ");
-       if (::ioctl(m_fd, VIDEO_STOP, 1) < 0)
-               eDebug("failed (%m)");
-       else
-               eDebug("ok");
+       }
+
+       if (m_fd >= 0)
+       {
+               eDebugNoNewLine("VIDEO_STOP - ");
+               if (::ioctl(m_fd, VIDEO_STOP, 1) < 0)
+                       eDebug("failed (%m)");
+               else
+                       eDebug("ok");
+       }
 }
 
 void eDVBVideo::flush()
@@ -1113,7 +1174,10 @@ eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder)
                m_changed(0), m_decoder(decoder), m_video_clip_fd(-1), m_showSinglePicTimer(eTimer::create(eApp)),
                m_fcc_fd(-1), m_fcc_enable(false), m_fcc_state(fcc_state_stop), m_fcc_feid(-1), m_fcc_vpid(-1), m_fcc_vtype(-1), m_fcc_pcrpid(-1)
 {
-       demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn);
+       if (m_demux)
+       {
+               demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn);
+       }
        CONNECT(m_showSinglePicTimer->timeout, eTSMPEGDecoder::finishShowSinglePic);
        m_state = stateStop;
 }
index b677275..1af2a10 100644 (file)
@@ -58,12 +58,10 @@ typedef enum {
 #include "crc32.h"
 
 #include <lib/base/eerror.h>
-#include <lib/base/filepush.h>
 #include <lib/dvb/idvb.h>
 #include <lib/dvb/demux.h>
 #include <lib/dvb/esection.h>
 #include <lib/dvb/decoder.h>
-#include <lib/dvb/pvrparse.h>
 
 eDVBDemux::eDVBDemux(int adapter, int demux): adapter(adapter), demux(demux)
 {
@@ -151,9 +149,9 @@ RESULT eDVBDemux::createTSRecorder(ePtr<iDVBTSRecorder> &recorder)
        return 0;
 }
 
-RESULT eDVBDemux::getMPEGDecoder(ePtr<iTSMPEGDecoder> &decoder, int primary)
+RESULT eDVBDemux::getMPEGDecoder(ePtr<iTSMPEGDecoder> &decoder, int index)
 {
-       decoder = new eTSMPEGDecoder(this, primary ? 0 : 1);
+       decoder = new eTSMPEGDecoder(this, index);
        return 0;
 }
 
@@ -447,26 +445,6 @@ RESULT eDVBPESReader::connectRead(const Slot2<void,const __u8*,int> &r, ePtr<eCo
        return 0;
 }
 
-class eDVBRecordFileThread: public eFilePushThread
-{
-public:
-       eDVBRecordFileThread();
-       void setTimingPID(int pid, int type);
-       
-       void startSaveMetaInformation(const std::string &filename);
-       void stopSaveMetaInformation();
-       void enableAccessPoints(bool enable);
-       int getLastPTS(pts_t &pts);
-protected:
-       int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
-private:
-       eMPEGStreamParserTS m_ts_parser;
-       eMPEGStreamInformation m_stream_info;
-       off_t m_current_offset;
-       pts_t m_last_pcr; /* very approximate.. */
-       int m_pid;
-};
-
 eDVBRecordFileThread::eDVBRecordFileThread()
        :eFilePushThread(IOPRIO_CLASS_RT, 7), m_ts_parser(m_stream_info)
 {
index b34ad27..015115a 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <lib/dvb/idvb.h>
 #include <lib/dvb/idemux.h>
+#include <lib/dvb/pvrparse.h>
+#include <lib/base/filepush.h>
 
 class eDVBDemux: public iDVBDemux
 {
@@ -83,7 +85,25 @@ public:
        RESULT connectRead(const Slot2<void,const __u8*, int> &read, ePtr<eConnection> &conn);
 };
 
-class eDVBRecordFileThread;
+class eDVBRecordFileThread: public eFilePushThread
+{
+public:
+       eDVBRecordFileThread();
+       void setTimingPID(int pid, int type);
+       
+       void startSaveMetaInformation(const std::string &filename);
+       void stopSaveMetaInformation();
+       void enableAccessPoints(bool enable);
+       int getLastPTS(pts_t &pts);
+protected:
+       int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
+private:
+       eMPEGStreamParserTS m_ts_parser;
+       eMPEGStreamInformation m_stream_info;
+       off_t m_current_offset;
+       pts_t m_last_pcr; /* very approximate.. */
+       int m_pid;
+};
 
 class eDVBTSRecorder: public iDVBTSRecorder, public Object
 {
old mode 100755 (executable)
new mode 100644 (file)
index 012a834..756c685
@@ -34,7 +34,7 @@ eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
                eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
                if (fbcmng)
                {
-                       fbcmng->unset(m_fe);
+                       fbcmng->unLink(m_fe);
                }
        }
 }
@@ -126,6 +126,8 @@ eDVBResourceManager::eDVBResourceManager()
 
        eDVBCAService::registerChannelCallback(this);
 
+       m_fbc_mng = new eFBCTunerManager(this);
+
        CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
 }
 
@@ -433,26 +435,34 @@ void eDVBResourceManager::setFrontendType(int index, const char *type)
 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
 {
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
-//     ePtr<eDVBRegisteredFrontend> best;
        eDVBRegisteredFrontend *best = NULL;
        int bestval = 0;
        int foundone = 0;
 
-       int check_fbc_linked = 0;
+       int check_fbc_leaf_linkable = 0;
+       int current_fbc_setid = -1;
        eDVBRegisteredFrontend *fbc_fe = NULL;
        eDVBRegisteredFrontend *best_fbc_fe = NULL;
-       eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
 
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
        {
                int c = 0;
                fbc_fe = NULL;
-               if (!check_fbc_linked && i->m_frontend->is_FBCTuner() && fbcmng && fbcmng->canLink(*i))
+               if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
                {
-                       check_fbc_linked = 1;
-                       c = fbcmng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
+                       int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
+                       if (fbc_setid != current_fbc_setid)
+                       {
+                               current_fbc_setid = fbc_setid;
+                               check_fbc_leaf_linkable = 0;
+                       }
 
-//                     eDebug("[eDVBResourceManager::allocateFrontend] fbcmng->isCompatibleWith slotid : %p (%d), fbc_fe : %p (%d), score : %d", (eDVBRegisteredFrontend *)*i,  i->m_frontend->getSlotID(), fbc_fe, fbc_fe?fbc_fe->m_frontend->getSlotID():-1, c);                     
+                       if (!check_fbc_leaf_linkable)
+                       {
+                               c = m_fbc_mng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
+                               check_fbc_leaf_linkable = 1;
+                               eDebug("[eDVBResourceManager::allocateFrontend] m_fbc_mng->isCompatibleWith slotid : %p (%d), fbc_fe : %p (%d), score : %d", (eDVBRegisteredFrontend *)*i,  i->m_frontend->getSlotID(), fbc_fe, fbc_fe?fbc_fe->m_frontend->getSlotID():-1, c);
+                       }
                }
                else
                {
@@ -464,18 +474,17 @@ RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, eP
 
                if (!i->m_inuse)
                {
-//                     eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
+                       eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
                        if (c > bestval)
                        {
                                bestval = c;
-//                             best = i;
                                best = *i;
                                best_fbc_fe = fbc_fe;
                        }
                }
                else
                {
-//                     eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
+                       eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
                }
 
                eDVBRegisteredFrontend *tmp = *i;
@@ -483,9 +492,9 @@ RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, eP
 
        if (best)
        {
-               if (fbcmng && best_fbc_fe)
+               if (best_fbc_fe)
                {
-                       fbcmng->addLink(best, best_fbc_fe, simulate);
+                       m_fbc_mng->addLink(best, best_fbc_fe, simulate);
                }
 
                fe = new eDVBAllocatedFrontend(best);
@@ -911,18 +920,29 @@ int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &fepar
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
        ePtr<eDVBRegisteredFrontend> best;
        int bestval = 0;
-       int check_fbc_link = 0;
-       eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
+       int check_fbc_leaf_linkable = 0;
+       int current_fbc_setid = -1;
 
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
        {
                if (!i->m_inuse)
                {
                        int c = 0;
-                       if(fbcmng && i->m_frontend->is_FBCTuner() && fbcmng->canLink(*i) && !check_fbc_link)
+                       if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
                        {
-                               check_fbc_link = 1;
-                               c = fbcmng->isCompatibleWith(feparm, *i, simulate);
+                               int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
+                               if (fbc_setid != current_fbc_setid)
+                               {
+                                       current_fbc_setid = fbc_setid;
+                                       check_fbc_leaf_linkable = 0;
+                               }
+
+                               if (!check_fbc_leaf_linkable)
+                               {
+                                       eDVBRegisteredFrontend *dummy;
+                                       c = m_fbc_mng->isCompatibleWith(feparm, *i, dummy, simulate);
+                                       check_fbc_leaf_linkable = 1;
+                               }
                        }
                        else
                        {
index fa1e8a1..c0acc4f 100644 (file)
@@ -159,6 +159,8 @@ class eDVBResourceManager: public iObject, public Object
        ePtr<iDVBChannelList> m_list;
        ePtr<iDVBSatelliteEquipmentControl> m_sec;
        static eDVBResourceManager *instance;
+
+       ePtr<eFBCTunerManager> m_fbc_mng;
  
        friend class eDVBChannel;
        friend class eFBCTunerManager;
index dc70c05..9dd66b0 100644 (file)
@@ -7,8 +7,6 @@
 #include <unistd.h>
 #include <fcntl.h>
 
-#define FE_SLOT_ID(fe) fe->m_frontend->getSlotID()
-
 //#define FBC_DEBUG
 
 #ifdef FBC_DEBUG
 #define eFecDebug(arg...)
 #endif
 
+static int getProcData(const char* filename)
+{
+       int res = -1;
+       FILE *fp = fopen(filename,"r");
+       if(fp)
+       {
+               fscanf(fp, "%d", &res);
+               fclose(fp);
+       }
+       else
+       {
+               eFecDebug("[*][eFBCTunerManager::getProcData] open failed, %s: %m", filename);
+       }
+       return res;
+}
 
-DEFINE_REF(eFBCTunerManager);
-
-bool eFBCTunerManager::isDestroyed = false;
-
-eFBCTunerManager::eFBCTunerManager()
+static void setProcData(const char* filename, int value)
 {
-       ePtr<eDVBResourceManager> res_mgr;
-       eDVBResourceManager::getInstance(res_mgr);
-       m_res_mgr = res_mgr;
+       eDebug("[*] setProcData %s -> %d", filename, value);
+       FILE *fp = fopen(filename, "w");
+       if(fp)
+       {
+               fprintf(fp, "%d", value);
+               fclose(fp);
+       }
+       else
+       {
+               eFecDebug("[*][eFBCTunerManager::setProcData] open failed, %s: %m", filename);
+       }
+}
 
-       /* num of fbc tuner in one set */
-       m_fbc_tuner_num = getFBCTunerNum();
-       procInit();
+static void loadConnectChoices(const char* filename, bool *connect_choices)
+{
+       FILE *fp = fopen(filename,"r");
+       if(fp)
+       {
+               int c;
+               while(EOF != (c = fgetc(fp)))
+               {
+                       if(isdigit(c))
+                               connect_choices[c - '0'] = true;
+               }
+               fclose(fp);
+       }
+       else
+       {
+               eFecDebug("[*][eFBCTunerManager::LoadFbcRootChoices] open failed, %s: %m", filename);
+       }
 }
 
-eFBCTunerManager::~eFBCTunerManager()
+
+DEFINE_REF(eFBCTunerManager);
+
+eFBCTunerManager* eFBCTunerManager::m_instance = (eFBCTunerManager*)0;
+
+eFBCTunerManager* eFBCTunerManager::getInstance()
 {
-       isDestroyed = true;
+       return m_instance;
 }
 
-void eFBCTunerManager::procInit()
+eFBCTunerManager::eFBCTunerManager(ePtr<eDVBResourceManager> res_mgr)
+       :m_res_mgr(res_mgr)
 {
+       if (!m_instance)
+               m_instance = this;
+
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
 
-       /* 1 FBC set has 8 tuners. */
-       /* 1st set : 0, 1, 2, 3, 4, 5, 6, 7 */
-       /* 2nd set : 8, 9, 10, 11, 12, 13, 14, 15 */
-       /* 1st, 2nd frontend is top on a set */
+       /* each FBC set has 8 tuners. */
+       /* first set : 0, 1, 2, 3, 4, 5, 6, 7 */
+       /* second set : 8, 9, 10, 11, 12, 13, 14, 15 */
+       /* first, second frontend is top on a set */
+
+       bool isRoot;
+       int fbcSetID = -1;
+       int fbcIndex = 0;
+       int initFbcId = -1;
+       int prevFbcSetID = -1;
+       char tmp[128];
+       std::string proc_fe;
+       bool connect_choices[32] = {false};
 
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
        {
-               if (!it->m_frontend->is_FBCTuner())
+               // continue for DVB-C FBC Tuner
+               if (!(it->m_frontend->supportsDeliverySystem(SYS_DVBS, false) || it->m_frontend->supportsDeliverySystem(SYS_DVBS2, false)))
                        continue;
 
-               if (isRootFe(*it))
+               int fe_id = feSlotID(it);
+               snprintf(tmp, sizeof(tmp), "/proc/stb/frontend/%d", fe_id);
+               proc_fe = tmp;
+               fbcSetID = getProcData(std::string(proc_fe + "/fbc_set_id").c_str());
+               if (fbcSetID != -1)
                {
-                       setProcFBCID(FE_SLOT_ID(it), getFBCID(FE_SLOT_ID(it)));
+                       if (prevFbcSetID != fbcSetID)
+                       {
+                               prevFbcSetID = fbcSetID;
+                               memset(connect_choices, 0, sizeof(connect_choices));
+                               loadConnectChoices(std::string(proc_fe + "/fbc_connect_choices").c_str(), connect_choices);
+                               fbcIndex =0; // reset
+                       }
+
+                       isRoot = false;
+                       if (fbcIndex < sizeof(connect_choices)/sizeof(connect_choices[0]))
+                       {
+                               isRoot = connect_choices[fbcIndex];
+                       }
+
+                       initFbcId = isRoot ? fbcIndex : 0;
+
+                       FBC_TUNER elem = {fbcSetID, fbcIndex, isRoot, initFbcId};
+                       m_fbc_tuners[fe_id] = elem;
+
+                       /* set default fbc ID */
+                       setProcFBCID(fe_id, initFbcId, false);
+
+                       /* enable fbc tuner */
+                       it->m_frontend->setFBCTuner(true);
+
+                       fbcIndex++;
                }
        }
 }
 
-int eFBCTunerManager::getFBCTunerNum()
+eFBCTunerManager::~eFBCTunerManager()
 {
-       char tmp[255];
-       int fbc_tuner_num = 2;
-       int fd = open("/proc/stb/info/chipset", O_RDONLY);
-       if(fd < 0) {
-               eDebug("open failed, /proc/stb/info/chipset!");
-               fbc_tuner_num = 2;
-       }
-       else
-       {
-               read(fd, tmp, 255);
-               close(fd);
-
-               if (!!strstr(tmp, "7376"))
-                       fbc_tuner_num = 2;
-       }
-       return fbc_tuner_num;
+       if (m_instance == this)
+               m_instance = 0;
 }
 
-int eFBCTunerManager::setProcFBCID(int fe_id, int fbc_id)
+int eFBCTunerManager::setProcFBCID(int fe_id, int fbc_connect, bool is_linked)
 {
-       eFecDebug("[*][eFBCTunerManager::setProcFBCID] %d -> %d %s", fe_id, fbc_id, !isRootFeSlot(fe_id)?"(linked)":"");
+       eFecDebug("[*][eFBCTunerManager::setProcFBCID] %d -> %d", fe_id, fbc_connect);
        char filename[128];
-       char data[4];
-       sprintf(filename, "/proc/stb/frontend/%d/fbc_id", fe_id);
-       int fd = open(filename, O_RDWR);
-       if(fd < 0) {
-               eDebug("[*][eFBCTunerManager::setProcFBCID] open failed, %s: %m", filename);
-               return -1;
-       }
-       else
-       {
-               if(isLinkedByIndex(fe_id))
-                       fbc_id += 0x10; // 0x10 : isLinked, 0x01 : fbc_id
 
-               sprintf(data, "%x", fbc_id);
-               write(fd, data, strlen(data));
-               close(fd);
-       }
+       /* set root */
+       sprintf(filename, "/proc/stb/frontend/%d/fbc_connect", fe_id);
+       setProcData(filename, fbc_connect);
+
+       /* set linked */
+       sprintf(filename, "/proc/stb/frontend/%d/fbc_link", fe_id);
+       setProcData(filename, (int)is_linked);
+
        return 0;
 }
 
-bool eFBCTunerManager::isRootFeSlot(int fe_slot_id)
+
+int eFBCTunerManager::feSlotID(const eDVBRegisteredFrontend *fe) const
 {
-       return (fe_slot_id%8 < m_fbc_tuner_num) ? true : false;
+       return fe->m_frontend->getSlotID();
 }
 
+void eFBCTunerManager::setDefaultFBCID(eDVBRegisteredFrontend *fe)
+{
+       int fe_id = feSlotID(fe);
+       setProcFBCID(fe_id, getDefaultFBCID(fe_id), isLinked(fe));
+}
 
-bool eFBCTunerManager::isRootFe(eDVBRegisteredFrontend *fe)
+void eFBCTunerManager::updateFBCID(eDVBRegisteredFrontend *next_fe, eDVBRegisteredFrontend *prev_fe)
+{
+       setProcFBCID(feSlotID(next_fe), getFBCID(feSlotID(getTop(prev_fe))), isLinked(next_fe));
+}
+
+bool eFBCTunerManager::isLinked(eDVBRegisteredFrontend *fe) const
 {
-       return isRootFeSlot(FE_SLOT_ID(fe));
+       long linked_prev_ptr = -1;
+       fe->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, linked_prev_ptr);
+       return (linked_prev_ptr != -1);
+}
+
+bool eFBCTunerManager::isUnicable(eDVBRegisteredFrontend *fe) const
+{
+       int slot_idx = feSlotID(fe);
+       bool is_unicable = false;
+
+       ePtr<eDVBSatelliteEquipmentControl> sec = eDVBSatelliteEquipmentControl::getInstance();
+       for (int idx=0; idx <= sec->m_lnbidx; ++idx )
+       {
+               eDVBSatelliteLNBParameters &lnb_param = sec->m_lnbs[idx];
+               if ( lnb_param.m_slot_mask & (1 << slot_idx) )
+               {
+                       is_unicable = lnb_param.SatCR_idx != -1;
+                       break;
+               }
+       }
+       return is_unicable;
 }
 
-bool eFBCTunerManager::isSameFbcSet(int a, int b)
+bool eFBCTunerManager::isFeUsed(eDVBRegisteredFrontend *fe, bool a_simulate) const
 {
-       return (a/8) == (b/8) ? true : false;
+       if (fe->m_inuse > 0)
+               return true;
+
+       bool simulate = !a_simulate;
+
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
+       {
+               if (feSlotID(it) == feSlotID(fe))
+               {
+                       return (it->m_inuse >0);
+               }
+       }
+
+       eDebug("[*][eFBCTunerManager::isFeUsed] ERROR! can not found fe ptr (feid : %d, simulate : %d)", feSlotID(fe), simulate);
+       return false;
 }
 
-bool eFBCTunerManager::isSupportDVBS(eDVBRegisteredFrontend *fe)
+bool eFBCTunerManager::isSameFbcSet(int fe_a, int fe_b)
 {
-       return (fe->m_frontend->supportsDeliverySystem(SYS_DVBS, true) || fe->m_frontend->supportsDeliverySystem(SYS_DVBS2, true)) ? true : false;
+       return m_fbc_tuners[fe_a].fbcSetID == m_fbc_tuners[fe_b].fbcSetID;
 }
 
-int eFBCTunerManager::getFBCID(int top_fe_id)
+bool eFBCTunerManager::isRootFe(eDVBRegisteredFrontend *fe)
 {
-       return 2*top_fe_id/8 + top_fe_id%8; /* (0,1,8,9,16,17...) -> (0,1,2,3,4,5...)*/
+       return m_fbc_tuners[feSlotID(fe)].isRoot;
 }
 
-int eFBCTunerManager::setDefaultFBCID(eDVBRegisteredFrontend *fe)
+int eFBCTunerManager::getFBCID(int fe_id)
 {
-       if (!isRootFe(fe))
-               return -1;
+       return m_fbc_tuners[fe_id].fbcIndex;
+}
 
-       return setProcFBCID(FE_SLOT_ID(fe), getFBCID(FE_SLOT_ID(fe)));
+int eFBCTunerManager::getDefaultFBCID(int fe_id)
+{
+       return m_fbc_tuners[fe_id].initFbcId;
 }
 
-void eFBCTunerManager::updateFBCID(eDVBRegisteredFrontend *next_fe, eDVBRegisteredFrontend *prev_fe)
+int eFBCTunerManager::getFBCSetID(int fe_id)
 {
-       eDVBRegisteredFrontend *top_fe = getTop(prev_fe);
-       setProcFBCID(FE_SLOT_ID(next_fe), getFBCID(FE_SLOT_ID(top_fe)));
+       return m_fbc_tuners[fe_id].fbcSetID;
 }
 
-eDVBRegisteredFrontend *eFBCTunerManager::getPrev(eDVBRegisteredFrontend *fe)
+eDVBRegisteredFrontend *eFBCTunerManager::getPrev(eDVBRegisteredFrontend *fe) const
 {
        eDVBRegisteredFrontend *prev_fe = NULL;
        long linked_prev_ptr = -1;
@@ -152,7 +259,7 @@ eDVBRegisteredFrontend *eFBCTunerManager::getPrev(eDVBRegisteredFrontend *fe)
        return prev_fe;
 }
 
-eDVBRegisteredFrontend *eFBCTunerManager::getNext(eDVBRegisteredFrontend *fe)
+eDVBRegisteredFrontend *eFBCTunerManager::getNext(eDVBRegisteredFrontend *fe) const
 {
        eDVBRegisteredFrontend *next_fe = NULL;
        long linked_next_ptr = -1;
@@ -162,7 +269,7 @@ eDVBRegisteredFrontend *eFBCTunerManager::getNext(eDVBRegisteredFrontend *fe)
        return next_fe;
 }
 
-eDVBRegisteredFrontend *eFBCTunerManager::getTop(eDVBRegisteredFrontend *fe)
+eDVBRegisteredFrontend *eFBCTunerManager::getTop(eDVBRegisteredFrontend *fe) const
 {
        eDVBRegisteredFrontend *prev_fe = fe;
        long linked_prev_ptr = -1;
@@ -175,7 +282,7 @@ eDVBRegisteredFrontend *eFBCTunerManager::getTop(eDVBRegisteredFrontend *fe)
        return prev_fe;
 }
 
-eDVBRegisteredFrontend *eFBCTunerManager::getLast(eDVBRegisteredFrontend *fe)
+eDVBRegisteredFrontend *eFBCTunerManager::getLast(eDVBRegisteredFrontend *fe) const
 {
        eDVBRegisteredFrontend *next_fe = fe;
        long linked_next_ptr = -1;
@@ -188,371 +295,53 @@ eDVBRegisteredFrontend *eFBCTunerManager::getLast(eDVBRegisteredFrontend *fe)
        return next_fe;
 }
 
-bool eFBCTunerManager::isLinked(eDVBRegisteredFrontend *fe)
+eDVBRegisteredFrontend *eFBCTunerManager::getSimulFe(eDVBRegisteredFrontend *fe) const
 {
-       return getPrev(fe) ? true:false;
-}
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_simulate_frontend;
 
-bool eFBCTunerManager::isLinkedByIndex(int fe_idx)
-{
-       bool linked = false;
-       eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); it++)
+               if (feSlotID(*it) == feSlotID(fe))
+                       return(*it);
 
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
-       {
-               if (FE_SLOT_ID(it) == fe_idx)
-               {
-                       linked = isLinked(*it);
-                       break;
-               }
-       }
-       return linked;
+       return((eDVBRegisteredFrontend *)0);
 }
 
-bool eFBCTunerManager::checkTop(eDVBRegisteredFrontend *fe)
+void eFBCTunerManager::connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
 {
-       return getPrev(fe) ? false:true;
-}
-
-int eFBCTunerManager::connectLinkByIndex(int link_fe_index, int prev_fe_index, int next_fe_index, bool simulate)
-{
-       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
-
-       eFecDebug("     [*][eFBCTunerManager::connectLinkByIndex] try to link %d->%d->%d %s", prev_fe_index, link_fe_index, next_fe_index, simulate?"(simulate)":"");
-
-       eDVBRegisteredFrontend *link_fe=NULL;
-       eDVBRegisteredFrontend *prev_fe=NULL;
-       eDVBRegisteredFrontend *next_fe=NULL;
-
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
-       {
-               if (FE_SLOT_ID(it) == prev_fe_index)
-               {
-                       prev_fe = *it;
-               }
-               else if (FE_SLOT_ID(it) == next_fe_index)
-               {
-                       next_fe = *it;
-               }
-               else if (FE_SLOT_ID(it) == link_fe_index)
-               {
-                       link_fe = *it;
-               }
-       }
+       if (next_fe)
+               eFecDebug("     [*][eFBCTunerManager::connectLink] connect %d->%d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), feSlotID(next_fe), simulate?"(simulate)":"");
+       else
+               eFecDebug("     [*][eFBCTunerManager::connectLink] connect %d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), simulate?"(simulate)":"");
 
-       if (prev_fe && next_fe && link_fe)
+       prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
+       link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
+       if (next_fe)
        {
-               /* enable linked fe */
-               link_fe->m_frontend->setEnabled(true);
-
-               /* connect */
-               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
-               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
-
                link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
                next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)link_fe);
        }
-       else
-       {
-               eDebug("        [*][eFBCTunerManager::connectLinkByIndex] connect failed! (prev_fe : %p, next_fe : %p, link_fe : %p, %s)", prev_fe, next_fe, link_fe, simulate?"simulate":"");
-               return -1;
-       }
-
-       return 0;
 }
 
-int eFBCTunerManager::connectLinkByIndex(int link_fe_index, int prev_fe_index, bool simulate)
+void eFBCTunerManager::disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
 {
-       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
-
-       eFecDebug("     [*][eFBCTunerManager::connectLinkByIndex] try to link %d->%d %s", prev_fe_index, link_fe_index, simulate?"(simulate)":"");
-
-       eDVBRegisteredFrontend *link_fe=NULL;
-       eDVBRegisteredFrontend *prev_fe=NULL;
-
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
-       {
-               if (FE_SLOT_ID(it) == prev_fe_index)
-               {
-                       prev_fe = *it;
-               }
-               else if (FE_SLOT_ID(it) == link_fe_index)
-               {
-                       link_fe = *it;
-               }
-       }
-
-       if (prev_fe && link_fe)
-       {
-               /* enable linked fe */
-               link_fe->m_frontend->setEnabled(true);
-
-               /* connect */
-               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
-               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
-       }
+       if (next_fe)
+               eFecDebug("     [*][eFBCTunerManager::disconnectLink] disconnect %d->%d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), feSlotID(next_fe), simulate?"(simulate)":"");
        else
-       {
-               eDebug("        [*][eFBCTunerManager::connectLinkByIndex] connect failed! (prev_fe : %p, link_fe : %p, %s)", prev_fe, link_fe, simulate?"simulate":"");
-               return -1;
-       }
-
-       return 0;
-}
-
-int eFBCTunerManager::disconnectLinkByIndex(int link_fe_index, int prev_fe_index, int next_fe_index, bool simulate)
-{
-       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
-
-       eFecDebug("     [*][eFBCTunerManager::connectLinkByIndex] try to unlink %d->%d->%d %s", prev_fe_index, link_fe_index, next_fe_index, simulate?"(simulate)":"");
-
-       eDVBRegisteredFrontend *link_fe=NULL;
-       eDVBRegisteredFrontend *prev_fe=NULL;
-       eDVBRegisteredFrontend *next_fe=NULL;
+               eFecDebug("     [*][eFBCTunerManager::disconnectLink] disconnect %d->%d %s", feSlotID(prev_fe), feSlotID(link_fe), simulate?"(simulate)":"");
 
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
-       {
-               if (FE_SLOT_ID(it) == prev_fe_index)
-               {
-                       prev_fe = *it;
-               }
-               else if (FE_SLOT_ID(it) == next_fe_index)
-               {
-                       next_fe = *it;
-               }
-               else if (FE_SLOT_ID(it) == link_fe_index)
-               {
-                       link_fe = *it;
-               }
-       }
-
-       if (prev_fe && next_fe && link_fe)
+       if (next_fe)
        {
-               /* disconnect */
                prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
                next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
 
                link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
                link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
-
-               /* enable linked fe */
-               link_fe->m_frontend->setEnabled(false);
-       }
-       else
-       {
-               eDebug("        [*][eFBCTunerManager::disconnectLinkByIndex] disconnect failed! (prev_fe : %p, next_fe : %p, link_fe : %p, %s)", prev_fe, next_fe, link_fe, simulate?"simulate":"");
-               return -1;
-       }
-
-       return 0;
-}
-int eFBCTunerManager::disconnectLinkByIndex(int link_fe_index, int prev_fe_index, bool simulate)
-{
-       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
-
-       eFecDebug("     [*][eFBCTunerManager::connectLinkByIndex] try to unlink %d->%d %s", prev_fe_index, link_fe_index, simulate?"(simulate)":"");
-
-       eDVBRegisteredFrontend *link_fe=NULL;
-       eDVBRegisteredFrontend *prev_fe=NULL;
-
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
-       {
-               if (FE_SLOT_ID(it) == prev_fe_index)
-               {
-                       prev_fe = *it;
-               }
-               else if (FE_SLOT_ID(it) == link_fe_index)
-               {
-                       link_fe = *it;
-               }
-       }
-
-       if (prev_fe && link_fe)
-       {
-               /* disconnect */
-               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
-               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
-
-               /* enable linked fe */
-               link_fe->m_frontend->setEnabled(false);
        }
        else
        {
-               eDebug("        [*][eFBCTunerManager::disconnectLinkByIndex] disconnect failed! (prev_fe : %p, link_fe : %p, %s)", prev_fe, link_fe, simulate?"simulate":"");
-               return -1;
-       }
-
-       return 0;
-}
-
-int eFBCTunerManager::connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
-{
-       eFecDebug("     [*][eFBCTunerManager::connectLink] try to link %d->%d->%d %s", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), FE_SLOT_ID(next_fe), simulate?"(simulate)":"");
-       int ret = connectLinkByIndex(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), FE_SLOT_ID(next_fe), !simulate);
-       if(!ret)
-       {
-               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
-               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
-
-               link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
-               next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)link_fe);
-
-               /* enable linked fe */
-               link_fe->m_frontend->setEnabled(true);  
-       }
-
-       return ret;
-}
-
-int eFBCTunerManager::connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, bool simulate)
-{
-       eFecDebug("     [*][eFBCTunerManager::connectLink] try to link %d->%d %s", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), simulate?"(simulate)":"");
-       int ret = connectLinkByIndex(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), !simulate);
-       if(!ret)
-       {
-               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
-               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
-
-               /* enable linked fe */
-               link_fe->m_frontend->setEnabled(true);
-       }
-
-       return ret;
-}
-
-int eFBCTunerManager::disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate)
-{
-       eFecDebug("     [*][eFBCTunerManager::disconnectLink] disconnect %d->%d->%d %s", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), FE_SLOT_ID(next_fe), simulate?"(simulate)":"");
-       int ret = disconnectLinkByIndex(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), FE_SLOT_ID(next_fe), !simulate);
-       if(!ret)
-       {
-               prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)next_fe);
-               next_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)prev_fe);
-
-               link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
-               link_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
-
-               link_fe->m_frontend->setEnabled(false);
-       }
-
-       return ret;
-}
-
-int eFBCTunerManager::disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, bool simulate)
-{
-       eFecDebug("     [*][eFBCTunerManager::disconnectLink] disconnect %d->%d %s", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), simulate?"(simulate)":"");
-       int ret = disconnectLinkByIndex(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), !simulate);
-       if(!ret)
-       {
                prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
                link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
-
-               link_fe->m_frontend->setEnabled(false);
-       }
-
-       return ret;
-}
-
-/* no set pair simulate fe */
-/* no set proc fbc_id */
-void eFBCTunerManager::connectLinkNoSimulate(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe)
-{
-       eDVBRegisteredFrontend *last_fe = getLast(top_fe);
-
-       last_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)link_fe);
-       link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)last_fe);
-
-       /* enable linked fe */
-       link_fe->m_frontend->setEnabled(true);
-
-       /* add slot mask*/
-       updateLNBSlotMask(FE_SLOT_ID(link_fe), FE_SLOT_ID(top_fe), false);
-}
-
-/* no set pair simulate fe */
-/* no set proc fbc_id */
-void eFBCTunerManager::disconnectLinkNoSimulate(eDVBRegisteredFrontend *link_fe)
-{
-       if(getNext(link_fe))
-       {
-               eFecDebug("[*][eFBCTunerManager::disconnectLinkNoSimulate] link fe is no last.");
-               return;
-       }
-
-       eDVBRegisteredFrontend *prev_fe = getPrev(link_fe);
-
-       if(!prev_fe)
-       {
-               eFecDebug("[*][eFBCTunerManager::disconnectLinkNoSimulate] can not found prev fe.");
-               return;
-       }
-
-       prev_fe->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)-1);
-       link_fe->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)-1);
-               
-       /* enable linked fe */
-       link_fe->m_frontend->setEnabled(false);
-
-       /* add slot mask*/
-       updateLNBSlotMask(FE_SLOT_ID(link_fe), FE_SLOT_ID(prev_fe), true);
-}
-
-bool eFBCTunerManager::checkUsed(eDVBRegisteredFrontend *fe, bool a_simulate)
-{
-       if (fe->m_inuse > 0)
-               return true;
-
-       bool simulate = !a_simulate;
-
-       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
-       {
-               if (FE_SLOT_ID(it) == FE_SLOT_ID(fe))
-               {
-                       return (it->m_inuse >0)?true:false;
-               }
        }
-
-       eDebug("[*][eFBCTunerManager::checkUsed] ERROR! can not found fe ptr (feid : %d, simulate : %d)", FE_SLOT_ID(fe), simulate);
-       return false;
-}
-
-bool eFBCTunerManager::canLink(eDVBRegisteredFrontend *fe)
-{
-       if(isRootFe(fe))
-               return false;
-
-       if(getPrev(fe) || getNext(fe))
-               return false;
-
-       if(isUnicable(fe))
-               return false;
-
-       return true;
-}
-
-bool eFBCTunerManager::isUnicable(eDVBRegisteredFrontend *fe)
-{
-       int slot_idx = FE_SLOT_ID(fe);
-       bool is_unicable = false;
-
-       ePtr<eDVBSatelliteEquipmentControl> sec = eDVBSatelliteEquipmentControl::getInstance();
-       for (int idx=0; idx <= sec->m_lnbidx; ++idx )
-       {
-               eDVBSatelliteLNBParameters &lnb_param = sec->m_lnbs[idx];
-               if ( lnb_param.m_slot_mask & (1 << slot_idx) )
-               {
-                       is_unicable = lnb_param.SatCR_idx != -1;
-                       break;
-               }
-       }
-       return is_unicable;
-}
-
-int eFBCTunerManager::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, bool simulate)
-{
-       eDVBRegisteredFrontend *best_fbc_fe;
-       return isCompatibleWith(feparm, link_fe, best_fbc_fe, simulate);
 }
 
 int eFBCTunerManager::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *&fbc_fe, bool simulate)
@@ -571,7 +360,7 @@ int eFBCTunerManager::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDV
                if(!it->m_frontend->getEnabled())
                        continue;
 
-               if(!isSameFbcSet(FE_SLOT_ID(link_fe), FE_SLOT_ID(it)))
+               if(!isSameFbcSet(feSlotID(link_fe), feSlotID(it)))
                        continue;
 
                if(it->m_inuse == 0) // No link to a fe not in use.
@@ -583,174 +372,158 @@ int eFBCTunerManager::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDV
                if(isUnicable(*it))
                        continue;
 
+               eDVBRegisteredFrontend *top_fe = *it;
+               eDVBRegisteredFrontend *prev_fe = getLast(top_fe);
+
                /* connect link */
-               connectLinkNoSimulate(link_fe, *it);
+               connectLink(link_fe, prev_fe, NULL, simulate);
+
+               /* enable linked fe */
+               link_fe->m_frontend->setEnabled(true);
+
+               /* add slot mask*/
+               updateLNBSlotMask(feSlotID(link_fe), feSlotID(*it), false);
 
                /* get score */
                int c = link_fe->m_frontend->isCompatibleWith(feparm);
-               eFecDebug("[*][eFBCTunerManager::isCompatibleWith] score : %d (%d->%d)", c, FE_SLOT_ID(it), FE_SLOT_ID(link_fe));
                if (c > best_score)
                {
                        best_score = c;
                        fbc_fe = (eDVBRegisteredFrontend *)*it;
                }
 
+               eFecDebug("[*][eFBCTunerManager::isCompatibleWith] score : %d (%d->%d)", c, feSlotID(it), feSlotID(link_fe));
+
+               ASSERT(!getNext(link_fe));
+               ASSERT(getPrev(link_fe));
+               ASSERT(getLast(top_fe) == link_fe);
+
                /* disconnect link */
-               disconnectLinkNoSimulate(link_fe);
+               disconnectLink(link_fe, prev_fe, NULL, simulate);
+
+               /* disable linked fe */
+               link_fe->m_frontend->setEnabled(false);
+
+               /* remove slot mask*/
+               updateLNBSlotMask(feSlotID(link_fe), feSlotID(top_fe), true);
        }
 
-       eFecDebug("[*][eFBCTunerManager::isCompatibleWith] fe : %p(%d), score : %d %s", link_fe, FE_SLOT_ID(link_fe), best_score, simulate?"(simulate)":"");
+       eFecDebug("[*][eFBCTunerManager::isCompatibleWith] fe : %p(%d), score : %d %s", link_fe, feSlotID(link_fe), best_score, simulate?"(simulate)":"");
 
        return best_score;
 }
 
-void eFBCTunerManager::connectSortedLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate)
+/* attach link_fe to tail of fe linked list */
+void eFBCTunerManager::addLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate)
 {
-       int link_fe_id = FE_SLOT_ID(link_fe);
-       int top_fe_id = FE_SLOT_ID(top_fe);
-       int prev_fe_id = link_fe_id - 1;
+       //printLinks(link_fe);
 
-       eFecDebug("     [*][eFBCTunerManager::connectSortedLink] link_id : %d, top_id : %d %s", link_fe_id, top_fe_id, simulate?"(simulate)":"");
+       eFecDebug("     [*][eFBCTunerManager::addLink] addLink : %p(%d)->%p(%d) %s", top_fe, feSlotID(top_fe), link_fe, feSlotID(link_fe), simulate?"(simulate)":"");
 
-       if (prev_fe_id < 0)
-       {
-               eFecDebug("     [*][eFBCTunerManager::connectSortedLink] link failed! link_id : %d, top_id : %d %s", link_fe_id, top_fe_id, simulate?"(simulate)":"");
+       eDVBRegisteredFrontend *next_fe = NULL;
+       eDVBRegisteredFrontend *prev_fe = NULL;
+
+       if(isRootFe(link_fe) || !isRootFe(top_fe))
                return;
-       }
 
-       /* serach prev fe */
-       eDVBRegisteredFrontend *next_fe = top_fe;
-       long linked_next_ptr = -1;
-       top_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
-       while(linked_next_ptr != -1)
+       /* search prev/next fe */
+       next_fe = top_fe;
+       while(true)
        {
-               next_fe = (eDVBRegisteredFrontend *)linked_next_ptr;
-               next_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
-               if (FE_SLOT_ID(next_fe) == prev_fe_id)
+               prev_fe = next_fe;
+               next_fe = getNext(prev_fe);
+               if ((next_fe == NULL) || (feSlotID(next_fe) > feSlotID(link_fe)))
                        break;
        }
 
-       eDVBRegisteredFrontend *prev_fe = next_fe;
+       /* connect */
+       connectLink(link_fe, prev_fe, next_fe, simulate);
 
-       /* get next fe */
-       next_fe = getNext(prev_fe);     
+       /* enable linked fe */
+       link_fe->m_frontend->setEnabled(true);
 
-       /* connect */
-       if (next_fe)
-       {
-               int res = connectLink(link_fe, prev_fe, next_fe, simulate);
-               if (res)
-               {
-                       eDebug("[*][eFBCTunerManager::connectSortedLink] ERROR! connect link failed! (%d->%d->%d)", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe), FE_SLOT_ID(next_fe));
-                       return;
-               }
-       }
-       else
+       /* simulate connect */
+       if (!simulate)
        {
-               int res = connectLink(link_fe, prev_fe, simulate);
-               if (res)
-               {
-                       eDebug("[*][eFBCTunerManager::connectSortedLink] ERROR! connect link failed! (%d->%d)", FE_SLOT_ID(prev_fe), FE_SLOT_ID(link_fe));
-                       return;
-               }
-       }
+               eDVBRegisteredFrontend *simulate_prev_fe = NULL;
+               eDVBRegisteredFrontend *simulate_link_fe = NULL;
+               eDVBRegisteredFrontend *simulate_next_fe = NULL;
 
-       /* set proc fbc_id */
-       setProcFBCID(link_fe_id, getFBCID(top_fe_id));
+               simulate_prev_fe = getSimulFe(prev_fe);
+               simulate_link_fe = getSimulFe(link_fe);
 
-       /* add slot mask*/
-       updateLNBSlotMask(link_fe_id, top_fe_id, false);
-}
+               if (next_fe) 
+                       simulate_next_fe = getSimulFe(next_fe);
 
-/* attach link_fe to tail of fe linked list */
-void eFBCTunerManager::addLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate)
-{
-       eFecDebug("     [*][eFBCTunerManager::addLink] addLink : %p(%d)->%p(%d) %s", top_fe, FE_SLOT_ID(top_fe), link_fe, FE_SLOT_ID(link_fe), simulate?"(simulate)":"");
+               eFecDebug("     [*][eFBCTunerManager::addLink] simulate fe : %p -> %p -> %p", simulate_prev_fe, simulate_link_fe, simulate_next_fe);
 
-       if (!isRootFe(top_fe))
-               return;
+               connectLink(simulate_link_fe, simulate_prev_fe, simulate_next_fe, !simulate);
 
-//     eDVBRegisteredFrontend *top_fe = a_top_fe;
-//     if (!checkTop(top_fe))
-//             top_fe = getTop(top_fe);
+               /* enable simulate linked fe */
+               simulate_link_fe->m_frontend->setEnabled(true);
+       }
+
+       /* set proc fbc_id */
+       if (!simulate)
+               setProcFBCID(feSlotID(link_fe), getFBCID(feSlotID(top_fe)), isLinked(link_fe));
 
-//     printLinks(top_fe);
-       connectSortedLink(link_fe, top_fe, simulate);
-//     printLinks(top_fe);
+       /* add slot mask*/
+       updateLNBSlotMask(feSlotID(link_fe), feSlotID(top_fe), false);
+
+       //printLinks(link_fe);
 }
 
 /* if fe, fe_simulated is unused, unlink current frontend from linked things. */
 /* all unused linked fbc fe must be unlinked! */
-void eFBCTunerManager::unset(eDVBRegisteredFrontend *fe)
+void eFBCTunerManager::unLink(eDVBRegisteredFrontend *link_fe)
 {
-       bool simulate = fe->m_frontend->is_simulate();
+       bool simulate = link_fe->m_frontend->is_simulate();
+       eFecDebug("     [*][eFBCTunerManager::unLink] fe id : %p(%d) %s", link_fe, feSlotID(link_fe), simulate?"(simulate)":"");
 
-       if (isRootFe(fe))
+       if (isRootFe(link_fe) || isFeUsed(link_fe, simulate) || isUnicable(link_fe) || !isLinked(link_fe))
+       {
+               eFecDebug("     [*][eFBCTunerManager::unLink] skip..");
                return;
+       }
 
-       if(checkUsed(fe, simulate))
-               return;
+       //printLinks(link_fe);
 
-       if(isUnicable(fe))
-               return;
+       eDVBRegisteredFrontend *prev_fe = getPrev(link_fe);
+       eDVBRegisteredFrontend *next_fe = getNext(link_fe);
 
-       eFecDebug("     [*][eFBCTunerManager::unset] fe id : %p(%d) %s", fe, FE_SLOT_ID(fe), simulate?"(simulate)":"");
+       ASSERT(prev_fe);
 
-       
-//     printLinks(fe);
+       disconnectLink(link_fe, prev_fe, next_fe, simulate);
 
-       eDVBRegisteredFrontend *linked_prev_fe = getPrev(fe);
-       eDVBRegisteredFrontend *linked_next_fe = getNext(fe);
+       /* disable linked fe */
+       link_fe->m_frontend->setEnabled(false);
 
-       if (!linked_prev_fe)
+       /* simulate disconnect */
+       if (!simulate)
        {
-               eDebug("[*][eFBCTunerManager::unset] ERROR! can not found prev linked frontend (fe_id : %d)", FE_SLOT_ID(fe));
-               return;
-       }
+               eDVBRegisteredFrontend *simulate_prev_fe = NULL;
+               eDVBRegisteredFrontend *simulate_link_fe = NULL;
+               eDVBRegisteredFrontend *simulate_next_fe = NULL;
 
-       if (linked_next_fe)
-       {
-               int res = disconnectLink(fe, linked_prev_fe, linked_next_fe, simulate);
-               if (res)
-               {
-                       eDebug("[*][eFBCTunerManager::unset] ERROR! disconnect link failed! (%d->%d->%d)", FE_SLOT_ID(linked_prev_fe), FE_SLOT_ID(fe), FE_SLOT_ID(linked_next_fe));
-                       return;
-               }
-       }
-       else
-       {
-               int res = disconnectLink(fe, linked_prev_fe, simulate);
-               if (res)
-               {
-                       eDebug("[*][eFBCTunerManager::unset] ERROR! disconnect link failed! (%d->%d)", FE_SLOT_ID(linked_prev_fe), FE_SLOT_ID(fe));
-                       return;
-               }
-       }
-
-       /* set proc fbc_id (skip) */
+               simulate_prev_fe = getSimulFe(prev_fe);
+               simulate_link_fe = getSimulFe(link_fe);
 
-       /* remove slot mask*/
-       updateLNBSlotMask(FE_SLOT_ID(fe), FE_SLOT_ID(linked_prev_fe), true);
+               if (next_fe) 
+                       simulate_next_fe = getSimulFe(next_fe);
 
-//     printLinks(fe);
-}
+               disconnectLink(simulate_link_fe, simulate_prev_fe, simulate_next_fe, !simulate);
 
-bool eFBCTunerManager::canAllocateLink(eDVBRegisteredFrontend *fe, bool simulate)
-{
-       if (!isRootFe(fe))
-               return false;
+               /* enable simulate linked fe */
+               simulate_link_fe->m_frontend->setEnabled(false);
+       }
 
-       if (isLinked(fe))
-               return false;
+       /* set default proc fbc_id */
+       //setDefaultFBCID(link_fe);
 
-       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_res_mgr->m_simulate_frontend : m_res_mgr->m_frontend;
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(frontends.begin()); it != frontends.end(); ++it)
-       {
-               if (it->m_frontend->is_FBCTuner() && !isRootFe(*it) && isSameFbcSet(FE_SLOT_ID(fe), FE_SLOT_ID(it)) && !it->m_frontend->getEnabled() && !isLinked(*it))
-                       return true;
-       }
+       /* remove slot mask*/
+       updateLNBSlotMask(feSlotID(link_fe), feSlotID(getTop(prev_fe)), true);
 
-       return false;
+       //printLinks(link_fe);
 }
 
 int eFBCTunerManager::updateLNBSlotMask(int dest_slot, int src_slot, bool remove)
@@ -783,7 +556,12 @@ int eFBCTunerManager::updateLNBSlotMask(int dest_slot, int src_slot, bool remove
        return 0;
 }
 
-int eFBCTunerManager::getLinkedSlotID(int fe_id)
+bool eFBCTunerManager::canLink(eDVBRegisteredFrontend *fe)
+{
+       return !(isRootFe(fe) || getPrev(fe) || getNext(fe) || isUnicable(fe));
+}
+
+int eFBCTunerManager::getLinkedSlotID(int fe_id) const
 {
        int link = -1;
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = m_res_mgr->m_frontend;
@@ -796,7 +574,7 @@ int eFBCTunerManager::getLinkedSlotID(int fe_id)
                        if (prev_ptr != -1)
                        {
                                eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
-                               link = FE_SLOT_ID(prev_fe);
+                               link = feSlotID(prev_fe);
                        }
                        break;
                }
@@ -807,7 +585,18 @@ int eFBCTunerManager::getLinkedSlotID(int fe_id)
        return link;
 }
 
-void eFBCTunerManager::printLinks(eDVBRegisteredFrontend *fe)
+bool eFBCTunerManager::isFBCLink(int fe_id)
+{
+       bool res = false;
+       std::map<int, FBC_TUNER>::iterator it = m_fbc_tuners.find(fe_id);
+       if (it != m_fbc_tuners.end())
+       {
+               res = !it->second.isRoot;
+       }
+       return res;
+}
+
+void eFBCTunerManager::printLinks(eDVBRegisteredFrontend *fe) const
 {
        long linked_prev_ptr = -1;
        eDVBRegisteredFrontend *linked_prev_fe = fe;
@@ -820,12 +609,12 @@ void eFBCTunerManager::printLinks(eDVBRegisteredFrontend *fe)
 
        long linked_next_ptr = -1;
        eDVBRegisteredFrontend *linked_next_fe = linked_prev_fe;
-       eFecDebug("     [*][eFBCTunerManager::printLinks] fe id : %d (%p), inuse : %d, enabled : %d, fbc : %d", FE_SLOT_ID(linked_next_fe), linked_next_fe, linked_next_fe->m_inuse, linked_next_fe->m_frontend->getEnabled(), linked_next_fe->m_frontend->is_FBCTuner());
+       eFecDebug("     [*][eFBCTunerManager::printLinks] fe id : %d (%p), inuse : %d, enabled : %d, fbc : %d", feSlotID(linked_next_fe), linked_next_fe, linked_next_fe->m_inuse, linked_next_fe->m_frontend->getEnabled(), linked_next_fe->m_frontend->is_FBCTuner());
        linked_prev_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, linked_next_ptr);
        while (linked_next_ptr != -1)
        {
                linked_next_fe = (eDVBRegisteredFrontend*) linked_next_ptr;
-               eFecDebug("     [*][eFBCTunerManager::printLinks] fe id : %d (%p), inuse : %d, enabled : %d, fbc : %d", FE_SLOT_ID(linked_next_fe), linked_next_fe, linked_next_fe->m_inuse, linked_next_fe->m_frontend->getEnabled(), linked_next_fe->m_frontend->is_FBCTuner());
+               eFecDebug("     [*][eFBCTunerManager::printLinks] fe id : %d (%p), inuse : %d, enabled : %d, fbc : %d", feSlotID(linked_next_fe), linked_next_fe, linked_next_fe->m_inuse, linked_next_fe->m_frontend->getEnabled(), linked_next_fe->m_frontend->is_FBCTuner());
                linked_next_fe->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, (long&)linked_next_ptr);
        }
 
@@ -841,16 +630,16 @@ void eFBCTunerManager::printLinks(eDVBRegisteredFrontend *fe)
                if (prev_ptr != -1)
                {
                        eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
-                       prev = FE_SLOT_ID(prev_fe);
+                       prev = feSlotID(prev_fe);
                }
 
                if (next_ptr != -1)
                {
                        eDVBRegisteredFrontend *next_fe = (eDVBRegisteredFrontend *)next_ptr;
-                       next = FE_SLOT_ID(next_fe);
+                       next = feSlotID(next_fe);
                }
                
-               eFecDebug("     [*][eFBCTunerManager::printLinks] fe_id : %d, inuse : %d, enabled : %d, fbc : %d, prev : %d, next : %d", FE_SLOT_ID(it), it->m_inuse, it->m_frontend->getEnabled(), it->m_frontend->is_FBCTuner(), prev, next);
+               eFecDebug("     [*][eFBCTunerManager::printLinks] fe_id : %2d, inuse : %d, enabled : %d, fbc : %d, prev : %2d, cur : %2d, next : %2d", feSlotID(it), it->m_inuse, it->m_frontend->getEnabled(), it->m_frontend->is_FBCTuner(), prev, feSlotID(it), next);
        }
 
        eSmartPtrList<eDVBRegisteredFrontend> &simulate_frontends = m_res_mgr->m_simulate_frontend;
@@ -865,16 +654,16 @@ void eFBCTunerManager::printLinks(eDVBRegisteredFrontend *fe)
                if (prev_ptr != -1)
                {
                        eDVBRegisteredFrontend *prev_fe = (eDVBRegisteredFrontend *)prev_ptr;
-                       prev = FE_SLOT_ID(prev_fe);
+                       prev = feSlotID(prev_fe);
                }
 
                if (next_ptr != -1)
                {
                        eDVBRegisteredFrontend *next_fe = (eDVBRegisteredFrontend *)next_ptr;
-                       next = FE_SLOT_ID(next_fe);
+                       next = feSlotID(next_fe);
                }
                
-               eFecDebug("     [*][eFBCTunerManager::printLinks] fe_id : %2d, inuse : %d, enabled : %d, fbc : %d, prev : %2d, cur : %2d, next : %2d (simulate)", FE_SLOT_ID(it), it->m_inuse, it->m_frontend->getEnabled(), it->m_frontend->is_FBCTuner(), prev, FE_SLOT_ID(it), next);
+               eFecDebug("     [*][eFBCTunerManager::printLinks] fe_id : %2d, inuse : %d, enabled : %d, fbc : %d, prev : %2d, cur : %2d, next : %2d (simulate)", feSlotID(it), it->m_inuse, it->m_frontend->getEnabled(), it->m_frontend->is_FBCTuner(), prev, feSlotID(it), next);
        }
 }
 
index 5f1afc1..f4899f0 100644 (file)
@@ -6,75 +6,63 @@
 #include <lib/base/object.h>
 #include <lib/base/eptrlist.h>
 #include <lib/dvb/idvb.h>
+#include <map>
 
 class eDVBResourceManager;
 class eDVBRegisteredFrontend;
 
+typedef struct fbc_tuner
+{
+       int fbcSetID;
+       int fbcIndex;
+       bool isRoot;
+       int initFbcId;
+}FBC_TUNER;
+
+
 class eFBCTunerManager: public iObject, public Object
 {
 private:
        DECLARE_REF(eFBCTunerManager);
        ePtr<eDVBResourceManager> m_res_mgr;
-       int m_fbc_tuner_num;
-       static bool isDestroyed;
+       static eFBCTunerManager *m_instance;
+       std::map<int, FBC_TUNER> m_fbc_tuners;
 
-       int getFBCTunerNum();
-       void procInit();
-       bool isSameFbcSet(int a, int b);
-       bool isSupportDVBS(eDVBRegisteredFrontend *fe);
-       int getFBCID(int root_fe_id);
+       int setProcFBCID(int fe_id, int root_idx, bool is_linked);
+       int feSlotID(const eDVBRegisteredFrontend *fe) const;
+       bool isLinked(eDVBRegisteredFrontend *fe) const;
+       bool isUnicable(eDVBRegisteredFrontend *fe) const;
+       bool isFeUsed(eDVBRegisteredFrontend *fe, bool a_simulate) const;
+       bool isSameFbcSet(int fe_id_a, int fe_id_b);
+       bool isRootFe(eDVBRegisteredFrontend *fe);
+       int getFBCID(int fe_id);
+       int getDefaultFBCID(int fe_id);
 
-       eDVBRegisteredFrontend *getPrev(eDVBRegisteredFrontend *fe);
-       eDVBRegisteredFrontend *getNext(eDVBRegisteredFrontend *fe);
-       eDVBRegisteredFrontend *getTop(eDVBRegisteredFrontend *fe);
-       eDVBRegisteredFrontend *getLast(eDVBRegisteredFrontend *fe);
-       bool isLinked(eDVBRegisteredFrontend *fe);
-       bool isLinkedByIndex(int fe_idx);
-       bool checkTop(eDVBRegisteredFrontend *fe);
-       int connectLinkByIndex(int link_fe_index, int prev_fe_index, int next_fe_index, bool simulate);
-       int connectLinkByIndex(int link_fe_index, int prev_fe_index, bool simulate);
-       int disconnectLinkByIndex(int link_fe_index, int prev_fe_index, int next_fe_index, bool simulate);
-       int disconnectLinkByIndex(int link_fe_index, int prev_fe_index, bool simulate);
-       int connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate);
-       int connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, bool simulate);
-       int disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate);
-       int disconnectLink(eDVBRegisteredFrontend *linkable_fe, eDVBRegisteredFrontend *top_fe, bool simulate);
-       void connectLinkNoSimulate(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe);
-       void disconnectLinkNoSimulate(eDVBRegisteredFrontend *link_fe);
+       eDVBRegisteredFrontend *getPrev(eDVBRegisteredFrontend *fe) const;
+       eDVBRegisteredFrontend *getNext(eDVBRegisteredFrontend *fe) const;
+       eDVBRegisteredFrontend *getTop(eDVBRegisteredFrontend *fe) const;
+       eDVBRegisteredFrontend *getLast(eDVBRegisteredFrontend *fe) const;
+       eDVBRegisteredFrontend *getSimulFe(eDVBRegisteredFrontend *fe) const;
 
-       bool checkUsed(eDVBRegisteredFrontend *fe, bool a_simulate);
-       void connectSortedLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate);
+       void connectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate);
+       void disconnectLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *prev_fe, eDVBRegisteredFrontend *next_fe, bool simulate);
        int updateLNBSlotMask(int dest_slot, int src_slot, bool remove);
-       void printLinks(eDVBRegisteredFrontend *fe);
+       void printLinks(eDVBRegisteredFrontend *fe) const;
 
 public:
-       eFBCTunerManager();
+       static eFBCTunerManager* getInstance();
+       eFBCTunerManager(ePtr<eDVBResourceManager> res_mgr);
        virtual ~eFBCTunerManager();
-       int setProcFBCID(int fe_id, int fbc_id);
-       int setDefaultFBCID(eDVBRegisteredFrontend *fe);
+       void setDefaultFBCID(eDVBRegisteredFrontend *fe);
        void updateFBCID(eDVBRegisteredFrontend *next_fe, eDVBRegisteredFrontend *prev_fe);
-       bool isRootFeSlot(int fe_slot_id);
-       bool isRootFe(eDVBRegisteredFrontend *fe);
-       bool canLink(eDVBRegisteredFrontend *fe);
-       bool isUnicable(eDVBRegisteredFrontend *fe);
-       int isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, bool simulate);
        int isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm, eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *&fbc_fe, bool simulate);
        void addLink(eDVBRegisteredFrontend *link_fe, eDVBRegisteredFrontend *top_fe, bool simulate);
-       void unset(eDVBRegisteredFrontend *fe);
-       bool canAllocateLink(eDVBRegisteredFrontend *fe, bool simulate);
-
-       static eFBCTunerManager* getInstance()
-       {
-               if (isDestroyed == true)
-               {
-                       eDebug("eFBCTunerManager is already destroyed!");
-                       return 0;
-               }
-               static eFBCTunerManager instance;
-               return &instance;
-       }
-
-       int getLinkedSlotID(int feid);
+       void unLink(eDVBRegisteredFrontend *link_fe);
+       bool canLink(eDVBRegisteredFrontend *fe);
+       int getLinkedSlotID(int feid) const;
+       int getFBCSetID(int fe_id);
+       bool isFBCLink(int fe_id);
 };
 
-#endif /* __dvb_fbc_h */
\ No newline at end of file
+#endif /* __dvb_fbc_h */
+
index 614340b..e83dbc8 100644 (file)
@@ -326,7 +326,7 @@ bool eFCCServiceManager::checkAvailable(const eServiceReference &ref)
        int serviceType = ref.getData(0);
        eFCCServiceManager *fcc_mng = eFCCServiceManager::getInstance();
 
-       if (ref.path.empty() && (serviceType != 2) && (serviceType != 10) && fcc_mng) // no PVR, streaming, radio channel..
+       if ((ref.type == 1) && ref.path.empty() && (serviceType != 2) && (serviceType != 10) && fcc_mng) // no PVR, streaming, radio channel..
                return fcc_mng->isEnable();
        return false;
 }
index fa36653..2892fe4 100755 (executable)
@@ -525,11 +525,6 @@ eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok, bool simulate, eDVBFronten
 
        m_idleInputpower[0]=m_idleInputpower[1]=0;
 
-       char fileName[32] = {0};
-       sprintf(fileName, "/proc/stb/frontend/%d/fbc_id", m_slotid);
-       if (access(fileName, F_OK) == 0)
-               m_fbc = true;
-
        ok = !openFrontend();
        closeFrontend();
 }
index aceb856..41dc311 100644 (file)
@@ -160,6 +160,7 @@ public:
        const char *getDescription() const { return m_description; }
        bool is_simulate() const { return m_simulate; }
        bool is_FBCTuner() { return m_fbc; }
+       void setFBCTuner(bool enable) { m_fbc = enable; }
        bool getEnabled() { return m_enabled; }
        void setEnabled(bool enable) { m_enabled = enable; }
        bool isLoopTimerActive() { return m_tuneTimer->isActive(); }
index c13114e..a73cfdb 100644 (file)
@@ -480,6 +480,11 @@ void eListbox::entryReset(bool selectionHome)
        invalidate();
 }
 
+void eListbox::setFont(gFont *font)
+{
+       m_style.m_font = font;
+}
+
 void eListbox::setBackgroundColor(gRGB &col)
 {
        m_style.m_background_color = col;
index 0073653..7334e48 100644 (file)
@@ -71,6 +71,7 @@ struct eListboxStyle
                        {1 x 0} use transparent background
                        {1 x p} use transparent background picture
                */
+       ePtr<gFont> m_font;
 };
 #endif
 
@@ -127,6 +128,7 @@ public:
        void setForegroundColorSelected(gRGB &col);
        void setBackgroundPicture(ePtr<gPixmap> &pixmap);
        void setSelectionPicture(ePtr<gPixmap> &pixmap);
+       void setFont(gFont *font);
 
 #ifndef SWIG
        struct eListboxStyle *getLocalStyle(void);
index ba0794e..3dcea7b 100644 (file)
@@ -138,7 +138,7 @@ void eListboxPythonStringContent::setSize(const eSize &size)
 
 void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
 {
-       ePtr<gFont> fnt = new gFont("Regular", 20);
+       ePtr<gFont> fnt;
        painter.clip(eRect(offset, m_itemsize));
        style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
 
@@ -151,6 +151,7 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style,
 
        if (local_style)
        {
+               fnt = local_style->m_font;
                if (selected)
                {
                        /* if we have a local background color set, use that. */
@@ -170,6 +171,7 @@ void eListboxPythonStringContent::paint(gPainter &painter, eWindowStyle &style,
                                painter.setForegroundColor(local_style->m_foreground_color);
                }
        }
+       if (!fnt) fnt = new gFont("Regular", 20);
 
        /* if we have no transparent background */
        if (!local_style || !local_style->m_transparent_background)
@@ -273,8 +275,8 @@ void eListboxPythonStringContent::invalidate()
 
 void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected)
 {
-       ePtr<gFont> fnt = new gFont("Regular", 20);
-       ePtr<gFont> fnt2 = new gFont("Regular", 16);
+       ePtr<gFont> fnt;
+       ePtr<gFont> fnt2;
        eRect itemrect(offset, m_itemsize);
        eListboxStyle *local_style = 0;
        bool cursorValid = this->cursorValid();
@@ -288,6 +290,7 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
 
        if (local_style)
        {
+               fnt = local_style->m_font;
                if (selected)
                {
                        /* if we have a local background color set, use that. */
@@ -308,6 +311,16 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
                }
        }
 
+       if (fnt)
+       {
+               fnt2 = new gFont(fnt->family, fnt->pointSize - fnt->pointSize/5);
+       }
+       else
+       {
+               fnt = new gFont("Regular", 20);
+               fnt2 = new gFont("Regular", 16);
+       }
+
        if (!local_style || !local_style->m_transparent_background)
                /* if we have no transparent background */
        {
index 2e54d87..cfb132f 100644 (file)
@@ -36,6 +36,7 @@ RESULT eNavigation::playService(const eServiceReference &service)
 
        if (m_runningService)
        {
+               m_runningService->setTarget(m_decoder);
                m_runningService->connectEvent(slot(*this, &eNavigation::serviceEvent), m_service_event_conn);
                res = m_runningService->start();
        }
@@ -154,10 +155,11 @@ RESULT eNavigation::pause(int dop)
                return p->unpause();
 }
 
-eNavigation::eNavigation(iServiceHandler *serviceHandler)
+eNavigation::eNavigation(iServiceHandler *serviceHandler, int decoder)
 {
        ASSERT(serviceHandler);
        m_servicehandler = serviceHandler;
+       m_decoder = decoder;
        m_fccmgr = new eFCCServiceManager(this);
 }
 
index a4906c1..b055bc8 100644 (file)
@@ -11,6 +11,7 @@
 class eNavigation: public iObject, public Object
 {
        DECLARE_REF(eNavigation);
+       int m_decoder;
        ePtr<iServiceHandler> m_servicehandler;
 
        ePtr<iPlayableService> m_runningService;
@@ -41,7 +42,7 @@ public:
        PyObject *getRecordings(bool simulate=false);
        
        RESULT pause(int p);
-       eNavigation(iServiceHandler *serviceHandler);
+       eNavigation(iServiceHandler *serviceHandler, int decoder = 0);
        virtual ~eNavigation();
 };
 
index 33868d6..af93399 100755 (executable)
@@ -2,25 +2,30 @@ from MenuList import MenuList
 from Tools.Directories import SCOPE_CURRENT_SKIN, resolveFilename
 from enigma import RT_HALIGN_LEFT, eListboxPythonMultiContent, gFont
 from Tools.LoadPixmap import LoadPixmap
+import skin
 
 def ChoiceEntryComponent(key = "", text = ["--"]):
        res = [ text ]
        if text[0] == "--":
-               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 00, 800, 25, 0, RT_HALIGN_LEFT, "-"*200))
+               x, y, w, h = skin.parameters.get("ChoicelistDash",(0, 0, 800, 25))
+               res.append((eListboxPythonMultiContent.TYPE_TEXT, x, y, w, h, 0, RT_HALIGN_LEFT, "-"*200))
        else:
-               res.append((eListboxPythonMultiContent.TYPE_TEXT, 45, 00, 800, 25, 0, RT_HALIGN_LEFT, text[0]))
+               x, y, w, h = skin.parameters.get("ChoicelistName",(45, 0, 800, 25))
+               res.append((eListboxPythonMultiContent.TYPE_TEXT, x, y, w, h, 0, RT_HALIGN_LEFT, text[0]))
        
                png = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/key_" + key + ".png"))
                if png is not None:
-                       res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 5, 0, 35, 25, png))
+                       x, y, w, h = skin.parameters.get("ChoicelistIcon",(5, 0, 35, 25))
+                       res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, x, y, w, h, png))
        
        return res
 
 class ChoiceList(MenuList):
        def __init__(self, list, selection = 0, enableWrapAround=False):
                MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
-               self.l.setFont(0, gFont("Regular", 20))
-               self.l.setItemHeight(25)
+               font = skin.fonts.get("ChoiceList", ("Regular", 20, 25))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               self.l.setItemHeight(font[2])
                self.selection = selection
 
        def postWidgetCreate(self, instance):
index 24f917f..fd638d7 100755 (executable)
@@ -4,12 +4,14 @@ from config import KEY_LEFT, KEY_RIGHT, KEY_HOME, KEY_END, KEY_0, KEY_DELETE, KE
 from Components.ActionMap import NumberActionMap, ActionMap
 from enigma import eListbox, eListboxPythonConfigContent, eRCInput, eTimer
 from Screens.MessageBox import MessageBox
+import skin
 
 class ConfigList(HTMLComponent, GUIComponent, object):
        def __init__(self, list, session = None):
                GUIComponent.__init__(self)
                self.l = eListboxPythonConfigContent()
-               self.l.setSeperation(200)
+               seperation, = skin.parameters.get("ConfigListSeperator", (200, ))
+               self.l.setSeperation(seperation)
                self.timer = eTimer()
                self.list = list
                self.onSelectionChanged = [ ]
index 41cd1b2..1440d60 100755 (executable)
@@ -9,6 +9,7 @@ from Tools.LoadPixmap import LoadPixmap
 from time import localtime, time
 from ServiceReference import ServiceReference
 from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN
+import skin
 
 EPG_TYPE_SINGLE = 0
 EPG_TYPE_MULTI = 1
@@ -43,8 +44,10 @@ class EPGList(HTMLComponent, GUIComponent):
                GUIComponent.__init__(self)
                self.type=type
                self.l = eListboxPythonMultiContent()
-               self.l.setFont(0, gFont("Regular", 22))
-               self.l.setFont(1, gFont("Regular", 16))
+               font = skin.fonts.get("EPGList0", ("Regular", 22))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               font = skin.fonts.get("EPGList1", ("Regular", 16))
+               self.l.setFont(1, gFont(font[0], font[1]))
                if type == EPG_TYPE_SINGLE:
                        self.l.setBuildFunc(self.buildSingleEntry)
                elif type == EPG_TYPE_MULTI:
index 4c5b98d..542a135 100755 (executable)
@@ -8,6 +8,7 @@ from Tools.Directories import SCOPE_CURRENT_SKIN, resolveFilename, fileExists
 from enigma import RT_HALIGN_LEFT, eListboxPythonMultiContent, \
        eServiceReference, eServiceCenter, gFont
 from Tools.LoadPixmap import LoadPixmap
+import skin
 
 EXTENSIONS = {
                "m4a": "music",
@@ -42,7 +43,8 @@ EXTENSIONS = {
 
 def FileEntryComponent(name, absolute = None, isDir = False):
        res = [ (absolute, isDir) ]
-       res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 470, 20, 0, RT_HALIGN_LEFT, name))
+       x, y, w, h = skin.parameters.get("FileListName",(35, 1, 470, 20))
+       res.append((eListboxPythonMultiContent.TYPE_TEXT, x, y, w, h, 0, RT_HALIGN_LEFT, name))
        if isDir:
                png = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "extensions/directory.png"))
        else:
@@ -53,7 +55,8 @@ def FileEntryComponent(name, absolute = None, isDir = False):
                else:
                        png = None
        if png is not None:
-               res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 10, 2, 20, 20, png))
+               x, y, w, h = skin.parameters.get("FileListIcon",(10, 2, 20, 20))
+               res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, x, y, w, h, png))
        
        return res
 
@@ -76,8 +79,9 @@ class FileList(MenuList):
 
                self.refreshMountpoints()
                self.changeDir(directory)
-               self.l.setFont(0, gFont("Regular", 18))
-               self.l.setItemHeight(23)
+               font = skin.fonts.get("FileList", ("Regular", 18, 23))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               self.l.setItemHeight(font[2])
                self.serviceHandler = eServiceCenter.getInstance()
 
        def refreshMountpoints(self):
@@ -269,7 +273,8 @@ class FileList(MenuList):
 
 def MultiFileSelectEntryComponent(name, absolute = None, isDir = False, selected = False):
        res = [ (absolute, isDir, selected, name) ]
-       res.append((eListboxPythonMultiContent.TYPE_TEXT, 55, 1, 470, 20, 0, RT_HALIGN_LEFT, name))
+       x, y, w, h = skin.parameters.get("FileListMultiName",(55, 0, 470, 25))
+       res.append((eListboxPythonMultiContent.TYPE_TEXT, x, y, w, h, 0, RT_HALIGN_LEFT, name))
        if isDir:
                png = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "extensions/directory.png"))
        else:
@@ -280,7 +285,8 @@ def MultiFileSelectEntryComponent(name, absolute = None, isDir = False, selected
                else:
                        png = None
        if png is not None:
-               res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 30, 2, 20, 20, png))
+               x, y, w, h = skin.parameters.get("FileListMultiIcon",(30, 2, 20, 20))
+               res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, x, y, w, h, png))
 
        if not name.startswith('<'):
                if selected is False:
@@ -288,7 +294,8 @@ def MultiFileSelectEntryComponent(name, absolute = None, isDir = False, selected
                        res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 2, 0, 25, 25, icon))
                else:
                        icon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/lock_on.png"))
-                       res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 2, 0, 25, 25, icon))
+                       x, y, w, h = skin.parameters.get("FileListMultiLock",(2, 0, 25, 25))
+                       res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, x, y, w, h, icon))
        
        return res
 
@@ -300,8 +307,9 @@ class MultiFileSelectList(FileList):
                        self.selectedFiles = []
                FileList.__init__(self, directory, showMountpoints = showMountpoints, matchingPattern = matchingPattern, showDirectories = showDirectories, showFiles = showFiles,  useServiceRef = useServiceRef, inhibitDirs = inhibitDirs, inhibitMounts = inhibitMounts, isTop = isTop, enableWrapAround = enableWrapAround, additionalExtensions = additionalExtensions)
                self.changeDir(directory)                       
-               self.l.setItemHeight(25)
-               self.l.setFont(0, gFont("Regular", 20))
+               font = skin.fonts.get("FileListMulti", ("Regular", 20, 25))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               self.l.setItemHeight(font[2])
                self.onSelectionChanged = [ ]
 
        def selectionChanged(self):
index 66139df..c997395 100755 (executable)
@@ -2,6 +2,7 @@ from GUIComponent import GUIComponent
 
 from enigma import eListboxPythonMultiContent, eListbox, gFont
 from Tools.KeyBindings import queryKeyBinding, getKeyDescription
+import skin
 #getKeyPositions
 
 # [ ( actionmap, context, [(action, help), (action, help), ...] ), (actionmap, ... ), ... ]
@@ -39,23 +40,30 @@ class HelpMenuList(GUIComponent):
                                if isinstance(help, list):
                                        self.extendedHelp = True
                                        print "extendedHelpEntry found"
+                                       x, y, w, h = skin.parameters.get("HelpMenuListExtHlp0",(0, 0, 400, 26))
+                                       x1, y1, w1, h1 = skin.parameters.get("HelpMenuListExtHlp1",(0, 28, 400, 20))
                                        entry.extend((
-                                               (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 400, 26, 0, 0, help[0]),
-                                               (eListboxPythonMultiContent.TYPE_TEXT, 0, 28, 400, 20, 1, 0, help[1])
+                                               (eListboxPythonMultiContent.TYPE_TEXT, x, y, w, h, 0, 0, help[0]),
+                                               (eListboxPythonMultiContent.TYPE_TEXT, x1, y1, w1, h1, 1, 0, help[1])
                                        ))
                                else:
-                                       entry.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 400, 28, 0, 0, help) )
+                                       x, y, w, h = skin.parameters.get("HelpMenuListHlp",(0, 0, 400, 28))
+                                       entry.append( (eListboxPythonMultiContent.TYPE_TEXT, x, y, w, h, 0, 0, help) )
                                        
                                l.append(entry)
 
                self.l.setList(l)
                if self.extendedHelp is True:
-                       self.l.setFont(0, gFont("Regular", 24))
-                       self.l.setFont(1, gFont("Regular", 18))
-                       self.l.setItemHeight(50)
+
+                       font = skin.fonts.get("HelpMenuListExt0", ("Regular", 24, 50))
+                       self.l.setFont(0, gFont(font[0], font[1]))
+                       self.l.setItemHeight(font[2])
+                       font = skin.fonts.get("HelpMenuListExt1", ("Regular", 18))
+                       self.l.setFont(1, gFont(font[0], font[1]))
                else:
-                       self.l.setFont(0, gFont("Regular", 24))
-                       self.l.setItemHeight(38)
+                       font = skin.fonts.get("HelpMenuList", ("Regular", 24, 38))
+                       self.l.setFont(0, gFont(font[0], font[1]))
+                       self.l.setItemHeight(font[2])
 
        def ok(self):
                # a list entry has a "private" tuple as first entry...
index d675ca3..965a27f 100755 (executable)
@@ -8,8 +8,8 @@ from os import path as os_path, listdir, open as os_open, close as os_close, wri
 # asm-generic/ioctl.h
 IOC_NRBITS = 8L
 IOC_TYPEBITS = 8L
-IOC_SIZEBITS = 13L
-IOC_DIRBITS = 3L
+IOC_SIZEBITS = 14L
+IOC_DIRBITS = 2L
 
 IOC_NRSHIFT = 0L
 IOC_TYPESHIFT = IOC_NRSHIFT+IOC_NRBITS
@@ -33,6 +33,9 @@ class inputDevices:
                devices = listdir("/dev/input/")
 
                for evdev in devices:
+                       if not evdev.startswith("event"):
+                               continue
+
                        try:
                                buffer = "\0"*512
                                self.fd = os_open("/dev/input/" + evdev, O_RDWR | O_NONBLOCK)
index 5583b22..35fdce1 100755 (executable)
@@ -6,6 +6,7 @@ from os import path
 from enigma import eListboxPythonMultiContent, RT_VALIGN_CENTER, gFont, eServiceCenter
 
 from Tools.LoadPixmap import LoadPixmap
+import skin
 
 STATE_PLAY = 0
 STATE_PAUSE = 1
@@ -25,7 +26,8 @@ def PlaylistEntryComponent(serviceref, state):
        text = serviceref.getName()
        if text is "":
                text = path.split(serviceref.getPath().split('/')[-1])[1]
-       res.append((eListboxPythonMultiContent.TYPE_TEXT,25, 1, 470, 22, 0, RT_VALIGN_CENTER, text))
+       x, y, w, h = skin.parameters.get("PlayListName",(25, 1, 470, 22))
+       res.append((eListboxPythonMultiContent.TYPE_TEXT,x, y, w, h, 0, RT_VALIGN_CENTER, text))
        png = None
        if state == STATE_PLAY:
                png = PlayIcon
@@ -39,15 +41,17 @@ def PlaylistEntryComponent(serviceref, state):
                png = ForwardIcon
 
        if png is not None:
-               res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 5, 3, 16, 16, png))
+               x, y, w, h = skin.parameters.get("PlayListIcon",(5, 3, 16, 16))
+               res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, x, y, w, h, png))
 
        return res
 
 class PlayList(MenuList):
        def __init__(self, enableWrapAround = False):
                MenuList.__init__(self, [], enableWrapAround, eListboxPythonMultiContent)
-               self.l.setFont(0, gFont("Regular", 18))
-               self.l.setItemHeight(23)
+               font = skin.fonts.get("PlayList", ("Regular", 18, 23))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               self.l.setItemHeight(font[2])
                self.currPlaying = -1
                self.oldCurrPlaying = -1
                self.serviceHandler = eServiceCenter.getInstance()
index 5c98e4b..3df3bf2 100644 (file)
@@ -25,6 +25,15 @@ class MovieList(GUIComponent):
                self.descr_state = descr_state or self.HIDE_DESCRIPTION
                self.sort_type = sort_type or self.SORT_RECORDED
 
+               self.fontName = "Regular"
+               self.fontSizesOriginal = (22,18,16)
+               self.fontSizesCompact = (20,14)
+               self.fontSizesMinimal = (20,16)
+               self.itemHeights = (75,37,25)
+               self.columnsOriginal = (180,200)
+               self.columnsCompactDescription = (120,154,58)
+               self.compactColumn = (75,200)
+
                self.l = eListboxPythonMultiContent()
                self.tags = set()
                
@@ -57,20 +66,63 @@ class MovieList(GUIComponent):
        def setSortType(self, type):
                self.sort_type = type
 
+       def applySkin(self, desktop, parent):
+               def warningWrongSkinParameter(string):
+                       print "[MovieList] wrong '%s' skin parameters" % string
+               def fontName(value):
+                       self.fontName = value
+               def fontSizesOriginal(value):
+                       self.fontSizesOriginal = map(int, value.split(","))
+                       if len(self.fontSizesOriginal) != 3:
+                               warningWrongSkinParameter(attrib)
+               def fontSizesCompact(value):
+                       self.fontSizesCompact = map(int, value.split(","))
+                       if len(self.fontSizesCompact) != 2:
+                               warningWrongSkinParameter(attrib)
+               def fontSizesMinimal(value):
+                       self.fontSizesMinimal = map(int, value.split(","))
+                       if len(self.fontSizesMinimal) != 2:
+                               warningWrongSkinParameter(attrib)
+               def itemHeights(value):
+                       self.itemHeights = map(int, value.split(","))
+                       if len(self.itemHeights) != 3:
+                               warningWrongSkinParameter(attrib)
+               def columnsOriginal(value):
+                       self.columnsOriginal = map(int, value.split(","))
+                       if len(self.columnsOriginal) != 2:
+                               warningWrongSkinParameter(attrib)
+               def columnsCompactDescription(value):
+                       self.columnsCompactDescription = map(int, value.split(","))
+                       if len(self.columnsCompactDescription) != 3:
+                               warningWrongSkinParameter(attrib)
+               def compactColumn(value):
+                       self.compactColumn = map(int, value.split(","))
+                       if len(self.compactColumn) != 2:
+                               warningWrongSkinParameter(attrib)
+               for (attrib, value) in self.skinAttributes[:]:
+                       try:
+                               locals().get(attrib)(value)
+                               self.skinAttributes.remove((attrib, value))
+                       except:
+                               pass
+               self.redrawList()
+               return GUIComponent.applySkin(self, desktop, parent)
+
        def redrawList(self):
                if self.list_type == MovieList.LISTTYPE_ORIGINAL:
-                       self.l.setFont(0, gFont("Regular", 22))
-                       self.l.setFont(1, gFont("Regular", 18))
-                       self.l.setFont(2, gFont("Regular", 16))
-                       self.l.setItemHeight(75)
+                       for i in range(3):
+                               self.l.setFont(i, gFont(self.fontName, self.fontSizesOriginal[i]))
+                       self.itemHeight = self.itemHeights[0]
                elif self.list_type == MovieList.LISTTYPE_COMPACT_DESCRIPTION or self.list_type == MovieList.LISTTYPE_COMPACT:
-                       self.l.setFont(0, gFont("Regular", 20))
-                       self.l.setFont(1, gFont("Regular", 14))
                        self.l.setItemHeight(37)
+                       for i in range(2):
+                               self.l.setFont(i, gFont(self.fontName, self.fontSizesCompact[i]))
+                       self.itemHeight = self.itemHeights[1]
                else:
-                       self.l.setFont(0, gFont("Regular", 20))
-                       self.l.setFont(1, gFont("Regular", 16))
-                       self.l.setItemHeight(25)
+                       for i in range(2):
+                               self.l.setFont(i, gFont(self.fontName, self.fontSizesMinimal[i]))
+                       self.itemHeight = self.itemHeights[2]
+               self.l.setItemHeight(self.itemHeight)
 
        #
        # | name of movie              |
@@ -106,45 +158,54 @@ class MovieList(GUIComponent):
                if begin > 0:
                        t = FuzzyTime(begin)
                        begin_string = t[0] + ", " + t[1]
-               
+               ih = self.itemHeight
                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))
+                       fc, sc = self.columnsOriginal[0], self.columnsOriginal[1]
+                       ih1 = (ih * 2) / 5 # 75 -> 30
+                       ih2 = (ih * 2) / 3 # 75 -> 50
+                       res.append(MultiContentEntryText(pos=(0, 0), size=(width-fc-2, ih1), font = 0, flags = RT_HALIGN_LEFT, text=txt))
                        if self.tags:
-                               res.append(MultiContentEntryText(pos=(width-180, 0), size=(180, 30), font = 2, flags = RT_HALIGN_RIGHT, text = tags))
+                               res.append(MultiContentEntryText(pos=(width-fc, 0), size=(fc, ih1), 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()))
+                                       res.append(MultiContentEntryText(pos=(sc, ih2), size=(sc, ih2-ih1), 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=(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))
+                                       res.append(MultiContentEntryText(pos=(width-fc, 0), size=(fc, ih1), font = 2, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
+                       res.append(MultiContentEntryText(pos=(0, ih1), size=(width, ih2-ih1), font=1, flags=RT_HALIGN_LEFT, text=description))
+                       res.append(MultiContentEntryText(pos=(0, ih2), size=(sc, ih2-ih1), font=1, flags=RT_HALIGN_LEFT, text=begin_string))
+                       res.append(MultiContentEntryText(pos=(width-sc, ih2), size=(sc-2, ih2-ih1), 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))
-                       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))
+                       ih1 = ((ih * 8) + 14) / 15 # 37 -> 20, round up
+                       fc, sc, lc = self.columnsCompactDescription[0], self.columnsCompactDescription[1], self.columnsCompactDescription[2]
+                       res.append(MultiContentEntryText(pos=(0, 0), size=(width-fc, ih1), font = 0, flags = RT_HALIGN_LEFT, text = txt))
+                       res.append(MultiContentEntryText(pos=(0, ih1), size=(width-sc-lc, ih-ih1), font=1, flags=RT_HALIGN_LEFT, text=description))
+                       res.append(MultiContentEntryText(pos=(width-fc, 6), size=(fc, ih1), 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))
+                               res.append(MultiContentEntryText(pos=(width-sc-lc, ih1), size=(sc, ih-ih1), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
+                       res.append(MultiContentEntryText(pos=(width-lc, ih1), size=(lc, ih1), 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))
+                       ih1 = ((ih * 8) + 14) / 15 # 37 -> 20, round up
+                       lc, col = self.compactColumn[0], self.compactColumn[1]
+                       res.append(MultiContentEntryText(pos=(0, 0), size=(width-lc-2, ih1), font = 0, flags = RT_HALIGN_LEFT, text = txt))
                        if self.tags:
-                               res.append(MultiContentEntryText(pos=(width-200, 20), size=(200, 17), font = 1, flags = RT_HALIGN_RIGHT, text = tags))
+                               res.append(MultiContentEntryText(pos=(width-col, ih1), size=(col, ih-ih1), 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()))
+                                       res.append(MultiContentEntryText(pos=(col, ih1), size=(col, ih-ih1), 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))
+                                       res.append(MultiContentEntryText(pos=(width-col, ih1), size=(col, ih-ih1), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
+                       res.append(MultiContentEntryText(pos=(0, ih1), size=(col, ih-ih1), font=1, flags=RT_HALIGN_LEFT, text=begin_string))
+                       res.append(MultiContentEntryText(pos=(width-lc, 0), size=(lc, ih1), font=0, flags=RT_HALIGN_RIGHT, text=len))
                else:
                        assert(self.list_type == MovieList.LISTTYPE_MINIMAL)
                        if self.descr_state == MovieList.SHOW_DESCRIPTION:
-                               res.append(MultiContentEntryText(pos=(0, 0), size=(width-146, 20), font = 0, flags = RT_HALIGN_LEFT, text = txt))
-                               res.append(MultiContentEntryText(pos=(width-145, 4), size=(145, 20), font=1, flags=RT_HALIGN_RIGHT, text=begin_string))
+                               dateSize = ih * 145 / 20   # 20 -> 145
+                               res.append(MultiContentEntryText(pos=(0, 0), size=(width-dateSize, ih), font = 0, flags = RT_HALIGN_LEFT, text = txt))
+                               res.append(MultiContentEntryText(pos=(width-dateSize, 4), size=(dateSize, ih), font=1, flags=RT_HALIGN_RIGHT, text=begin_string))
                        else:
-                               res.append(MultiContentEntryText(pos=(0, 0), size=(width-77, 20), font = 0, flags = RT_HALIGN_LEFT, text = txt))
-                               res.append(MultiContentEntryText(pos=(width-75, 0), size=(75, 20), font=0, flags=RT_HALIGN_RIGHT, text=len))
+                               lenSize = ih * 75 / 20 # 20 -> 75
+                               res.append(MultiContentEntryText(pos=(0, 0), size=(width-lenSize-2, ih), font = 0, flags = RT_HALIGN_LEFT, text = txt))
+                               res.append(MultiContentEntryText(pos=(width-lenSize, 0), size=(lenSize, ih), font=0, flags=RT_HALIGN_RIGHT, text=len))
                
                return res
 
index 0e65257..e6425b7 100644 (file)
@@ -4,6 +4,7 @@ from Tools.Directories import SCOPE_SKIN_IMAGE, resolveFilename
 
 from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT
 from Tools.LoadPixmap import LoadPixmap
+import skin
 
 #Now there is a list of pictures instead of one...
 entryPicture = {}
@@ -28,8 +29,9 @@ def ParentalControlEntryComponent(service, name, protectionType):
 class ParentalControlList(MenuList):
        def __init__(self, list, enableWrapAround = False):
                MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
-               self.l.setFont(0, gFont("Regular", 20))
-               self.l.setItemHeight(32)
+               font = skin.fonts.get("ParentalControlList", ("Regular", 20, 32))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               self.l.setItemHeight(font[2])
 
        def toggleSelectedLock(self):
                from Components.ParentalControl import parentalControl
index 39c60ff..fee11ef 100644 (file)
@@ -5,44 +5,55 @@ from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixm
 
 from enigma import eListboxPythonMultiContent, gFont
 from Tools.LoadPixmap import LoadPixmap
+import skin
 
-def PluginEntryComponent(plugin):
+def PluginEntryComponent(plugin, width=440):
        if plugin.icon is None:
                png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/plugin.png"))
        else:
                png = plugin.icon
 
+       nx, ny, nh = skin.parameters.get("PluginBrowserName",(120, 5, 25))
+       dx, dy, dh = skin.parameters.get("PluginBrowserDescr",(120, 26, 17))
+       ix, iy, iw, ih = skin.parameters.get("PluginBrowserIcon",(10, 5, 100, 40))
        return [
                plugin,
-               MultiContentEntryText(pos=(120, 5), size=(320, 25), font=0, text=plugin.name),
-               MultiContentEntryText(pos=(120, 26), size=(320, 17), font=1, text=plugin.description),
-               MultiContentEntryPixmapAlphaTest(pos=(10, 5), size=(100, 40), png = png)
+               MultiContentEntryText(pos=(nx, ny), size=(width-nx, nh), font=0, text=plugin.name),
+               MultiContentEntryText(pos=(dx, dy), size=(width-dx, dh), font=1, text=plugin.description),
+               MultiContentEntryPixmapAlphaTest(pos=(ix, iy), size=(iw, ih), png = png)
        ]
 
-def PluginCategoryComponent(name, png):
+def PluginCategoryComponent(name, png, width=440):
+       x, y, h = skin.parameters.get("PluginBrowserDownloadName",(120, 5, 25))
+       ix, iy, iw, ih = skin.parameters.get("PluginBrowserDownloadIcon",(10, 0, 100, 50))
        return [
                name,
-               MultiContentEntryText(pos=(120, 5), size=(320, 25), font=0, text=name),
-               MultiContentEntryPixmapAlphaTest(pos=(10, 0), size=(100, 50), png = png)
+               MultiContentEntryText(pos=(x, y), size=(width-x, h), font=0, text=name),
+               MultiContentEntryPixmapAlphaTest(pos=(ix, iy), size=(iw, ih), png = png)
        ]
 
-def PluginDownloadComponent(plugin, name):
+def PluginDownloadComponent(plugin, name, width=440):
        if plugin.icon is None:
                png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/plugin.png"))
        else:
                png = plugin.icon
 
+       x, y, h = skin.parameters.get("PluginBrowserDownloadName",(120, 5, 25))
+       dx, dy, dh = skin.parameters.get("PluginBrowserDownloadDescr",(120, 26, 17))
+       ix, iy, iw, ih = skin.parameters.get("PluginBrowserDownloadIcon",(10, 0, 100, 50))
        return [
                plugin,
-               MultiContentEntryText(pos=(120, 5), size=(320, 25), font=0, text=name),
-               MultiContentEntryText(pos=(120, 26), size=(320, 17), font=1, text=plugin.description),
-               MultiContentEntryPixmapAlphaTest(pos=(10, 0), size=(100, 50), png = png)
+               MultiContentEntryText(pos=(x, y), size=(width-x, h), font=0, text=name),
+               MultiContentEntryText(pos=(dx, dy), size=(width-dx, dh), font=1, text=plugin.description),
+               MultiContentEntryPixmapAlphaTest(pos=(ix, iy), size=(iw, ih), png = png)
        ]
        
 
 class PluginList(MenuList):
        def __init__(self, list, enableWrapAround=False):
                MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
-               self.l.setFont(0, gFont("Regular", 20))
-               self.l.setFont(1, gFont("Regular", 14))
-               self.l.setItemHeight(50)
+               font = skin.fonts.get("PluginBrowser0", ("Regular", 20, 50))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               self.l.setItemHeight(font[2])
+               font = skin.fonts.get("PluginBrowser1", ("Regular", 14))
+               self.l.setFont(1, gFont(font[0], font[1]))
index 1c5423f..030f7c5 100755 (executable)
@@ -2,6 +2,7 @@ from MenuList import MenuList
 from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN
 from enigma import eListboxPythonMultiContent, eListbox, gFont, RT_HALIGN_LEFT
 from Tools.LoadPixmap import LoadPixmap
+import skin
 
 selectionpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/selectioncross.png"))
 
@@ -17,8 +18,9 @@ def SelectionEntryComponent(description, value, index, selected):
 class SelectionList(MenuList):
        def __init__(self, list = None, enableWrapAround = False):
                MenuList.__init__(self, list or [], enableWrapAround, content = eListboxPythonMultiContent)
-               self.l.setFont(0, gFont("Regular", 20))
-               self.l.setItemHeight(30)
+               font = skin.fonts.get("SelectionList", ("Regular", 20, 30))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               self.l.setItemHeight(font[2])
 
        def addSelection(self, description, value, index, selected = True):
                self.list.append(SelectionEntryComponent(description, value, index, selected))
index f9c4065..67f2e75 100644 (file)
@@ -29,3 +29,6 @@ SystemInfo["NumFrontpanelLEDs"] = countFrontpanelLEDs()
 SystemInfo["FrontpanelDisplay"] = fileExists("/dev/dbox/oled0") or fileExists("/dev/dbox/lcd0")
 SystemInfo["FrontpanelDisplayGrayscale"] = fileExists("/dev/dbox/oled0")
 SystemInfo["DeepstandbySupport"] = HardwareInfo().get_device_name() != "dm800"
+SystemInfo["HdmiInSupport"] = HardwareInfo().get_vu_device_name() == "ultimo4k"
+SystemInfo["WOWLSupport"] = HardwareInfo().get_vu_device_name() == "ultimo4k"
+
index 30097c9..f895bd8 100755 (executable)
@@ -1,5 +1,6 @@
 from HTMLComponent import HTMLComponent
 from GUIComponent import GUIComponent
+from skin import parseFont
 
 from Tools.FuzzyDate import FuzzyTime
 
@@ -17,8 +18,14 @@ class TimerList(HTMLComponent, GUIComponent, object):
        def buildTimerEntry(self, timer, processed):
                width = self.l.getItemSize().width()
                res = [ None ]
-               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, timer.service_ref.getServiceName()))
-               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 30, width, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, timer.name))
+               print "timer.service_ref.getServiceName() : ", timer.service_ref.getServiceName()
+               print "timer.name : ", timer.name
+               ih = self.itemHeight
+               ih1 = ih * 30 / 70 # 70 -> 30
+               ih2 = ih * 20 / 70 # 70 -> 20
+               stateSize = ih * 150 / 70   # 20 -> 145
+               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width, ih1, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, timer.service_ref.getServiceName()))
+               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, ih1, width, ih2, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, timer.name))
 
                repeatedtext = ""
                days = ( _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") )
@@ -34,19 +41,19 @@ class TimerList(HTMLComponent, GUIComponent, object):
                                        flags = flags >> 1
                        if timer.justplay:
                                if timer.end - timer.begin < 4: # rounding differences
-                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s "+ _("(ZAP)")) % (FuzzyTime(timer.begin)[1]))))
+                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, ih1+ih2, width-stateSize, ih2, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s "+ _("(ZAP)")) % (FuzzyTime(timer.begin)[1]))))
                                else:
-                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s ... %s (%d " + _("mins") + ") ") % (FuzzyTime(timer.begin)[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60)) + _("(ZAP)")))
+                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, ih1+ih2, width-stateSize, ih2, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s ... %s (%d " + _("mins") + ") ") % (FuzzyTime(timer.begin)[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60)) + _("(ZAP)")))
                        else:
-                               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s ... %s (%d " + _("mins") + ")") % (FuzzyTime(timer.begin)[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60))))
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, ih1+ih2, width-stateSize, ih2, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s ... %s (%d " + _("mins") + ")") % (FuzzyTime(timer.begin)[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60))))
                else:
                        if timer.justplay:
                                if timer.end - timer.begin < 4:
-                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s " + _("(ZAP)")) % (FuzzyTime(timer.begin)))))
+                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, ih1+ih2, width-stateSize, ih2, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s " + _("(ZAP)")) % (FuzzyTime(timer.begin)))))
                                else:
-                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s ... %s (%d " + _("mins") + ") ") % (FuzzyTime(timer.begin) + FuzzyTime(timer.end)[1:] + ((timer.end - timer.begin) / 60,))) + _("(ZAP)")))
+                                       res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, ih1+ih2, width-stateSize, ih2, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s ... %s (%d " + _("mins") + ") ") % (FuzzyTime(timer.begin) + FuzzyTime(timer.end)[1:] + ((timer.end - timer.begin) / 60,))) + _("(ZAP)")))
                        else:
-                               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s ... %s (%d " + _("mins") + ")") % (FuzzyTime(timer.begin) + FuzzyTime(timer.end)[1:] + ((timer.end - timer.begin) / 60,)))))
+                               res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, ih1+ih2, width-stateSize, ih2, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s ... %s (%d " + _("mins") + ")") % (FuzzyTime(timer.begin) + FuzzyTime(timer.end)[1:] + ((timer.end - timer.begin) / 60,)))))
 
                if not processed:
                        if timer.state == TimerEntry.StateWaiting:
@@ -68,21 +75,41 @@ class TimerList(HTMLComponent, GUIComponent, object):
                if timer.disabled:
                        state = _("disabled")
 
-               res.append((eListboxPythonMultiContent.TYPE_TEXT, width-150, 50, 150, 20, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, state))
+               res.append((eListboxPythonMultiContent.TYPE_TEXT, width-stateSize, ih1+ih2, stateSize, ih2, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, state))
 
                if timer.disabled:
+                       iconPosX = width * 490 / 740
                        png = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/redx.png"))
-                       res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 490, 5, 40, 40, png))
+                       res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, iconPosX, 5, 40, 40, png))
                return res
 
        def __init__(self, list):
                GUIComponent.__init__(self)
                self.l = eListboxPythonMultiContent()
                self.l.setBuildFunc(self.buildTimerEntry)
-               self.l.setFont(0, gFont("Regular", 20))
-               self.l.setFont(1, gFont("Regular", 18))
-               self.l.setItemHeight(70)
+               self.serviceNameFont = gFont("Regular", 20)
+               self.font = gFont("Regular", 18)
+               self.itemHeight = 70
                self.l.setList(list)
+
+       def applySkin(self, desktop, parent):
+               def itemHeight(value):
+                       self.itemHeight = int(value)
+               def setServiceNameFont(value):
+                       self.serviceNameFont = parseFont(value, ((1,1),(1,1)))
+               def setFont(value):
+                       self.font = parseFont(value, ((1,1),(1,1)))
+
+               for (attrib, value) in list(self.skinAttributes):
+                       try:
+                               locals().get(attrib)(value)
+                               self.skinAttributes.remove((attrib, value))
+                       except:
+                               pass
+               self.l.setFont(0, self.serviceNameFont)
+               self.l.setFont(1, self.font)
+               self.l.setItemHeight(self.itemHeight)
+               return GUIComponent.applySkin(self, desktop, parent)
        
        def getCurrent(self):
                cur = self.l.getCurrentSelection()
index 1d621f4..1f081e6 100755 (executable)
@@ -1,4 +1,4 @@
-from skin import parseColor
+from skin import parseColor, parseFont, parseSize
 from Components.config import config, ConfigClock, ConfigInteger
 from Components.Pixmap import Pixmap
 from Components.Button import Button
@@ -36,7 +36,6 @@ class EPGList(HTMLComponent, GUIComponent):
                        self.onSelChanged.append(selChangedCB)
                GUIComponent.__init__(self)
                self.l = eListboxPythonMultiContent()
-               self.l.setItemHeight(54);
                self.l.setBuildFunc(self.buildEntry)
                if overjump_empty:
                        self.l.setSelectableFunc(self.isSelectable)
@@ -58,28 +57,41 @@ class EPGList(HTMLComponent, GUIComponent):
                self.backColorSelected = 0x808080
                self.foreColorService = None
                self.backColorService = None
+               self.serviceFont = gFont("Regular", 20)
+               self.entryFont = gFont("Regular", 14)
+               self.itemHeight = 54
 
        def applySkin(self, desktop, screen):
-               if self.skinAttributes is not None:
-                       attribs = [ ]
-                       for (attrib, value) in self.skinAttributes:
-                               if attrib == "EntryForegroundColor":
-                                       self.foreColor = parseColor(value).argb()
-                               elif attrib == "EntryForegroundColorSelected":
-                                       self.foreColorSelected = parseColor(value).argb()
-                               elif attrib == "EntryBorderColor":
-                                       self.borderColor = parseColor(value).argb()
-                               elif attrib == "EntryBackgroundColor":
-                                       self.backColor = parseColor(value).argb()
-                               elif attrib == "EntryBackgroundColorSelected":
-                                       self.backColorSelected = parseColor(value).argb()
-                               elif attrib == "ServiceNameForegroundColor":
-                                       self.foreColorService = parseColor(value).argb()
-                               elif attrib == "ServiceNameBackgroundColor":
-                                       self.backColorService = parseColor(value).argb()
-                               else:
-                                       attribs.append((attrib,value))
-                       self.skinAttributes = attribs
+               def EntryForegroundColor(value):
+                       self.foreColor = parseColor(value).argb()
+               def EntryForegroundColorSelected(value):
+                       self.foreColorSelected = parseColor(value).argb()
+               def EntryBackgroundColor(value):
+                       self.backColor = parseColor(value).argb()
+               def EntryBackgroundColorSelected(value):
+                       self.backColorSelected = parseColor(value).argb()
+               def EntryBorderColor(value):
+                       self.borderColor = parseColor(value).argb()
+               def EntryItemHeight(value):
+                       self.itemHeight = int(value)
+               def ServiceNameForegroundColor(value):
+                       self.foreColorService = parseColor(value).argb()                
+               def ServiceNameBackgroundColor(value):
+                       self.backColorService = parseColor(value).argb()
+               def ServiceFont(value):
+                       self.serviceFont = parseFont(value, ((1,1),(1,1)) )
+               def EntryFont(value):
+                       self.entryFont = parseFont(value, ((1,1),(1,1)) )
+
+               for (attrib, value) in list(self.skinAttributes):
+                       try:
+                               locals().get(attrib)(value)
+                               self.skinAttributes.remove((attrib, value))
+                       except:
+                               pass
+               self.l.setFont(0, self.serviceFont)
+               self.l.setFont(1, self.entryFont)
+               self.l.setItemHeight(self.itemHeight)
                return GUIComponent.applySkin(self, desktop, screen)
 
        def isSelectable(self, service, sname, event_list):
@@ -190,8 +202,6 @@ class EPGList(HTMLComponent, GUIComponent):
                instance.setWrapAround(True)
                instance.selectionChanged.get().append(self.serviceChanged)
                instance.setContent(self.l)
-               self.l.setFont(0, gFont("Regular", 20))
-               self.l.setFont(1, gFont("Regular", 14))
                self.l.setSelectionClip(eRect(0,0,0,0), False)
 
        def preWidgetRemove(self, instance):
@@ -382,21 +392,44 @@ class TimelineText(HTMLComponent, GUIComponent):
                GUIComponent.__init__(self)
                self.l = eListboxPythonMultiContent()
                self.l.setSelectionClip(eRect(0,0,0,0))
-               self.l.setItemHeight(25);
-               self.l.setFont(0, gFont("Regular", 20))
+               self.foreColor = 0xffc000
+               self.backColor = 0x000000
+               self.font = gFont("Regular", 20)
+               self.itemHeight = 25
 
        GUI_WIDGET = eListbox
 
+       def applySkin(self, desktop, screen):
+               def foregroundColor(value):
+                       self.foreColor = parseColor(value).argb()
+               def backgroundColor(value):
+                       self.backColor = parseColor(value).argb()
+               def font(value):
+                       self.font = parseFont(value,  ((1, 1), (1, 1)) )
+               def itemHeight(value):
+                       self.itemHeight = int(value)
+               for (attrib, value) in list(self.skinAttributes):
+                       try:
+                               locals().get(attrib)(value)
+                               self.skinAttributes.remove((attrib, value))
+                       except:
+                               pass
+               self.l.setFont(0, self.font)
+               self.l.setItemHeight(self.itemHeight);
+               return GUIComponent.applySkin(self, desktop, screen)
+
        def postWidgetCreate(self, instance):
                instance.setContent(self.l)
 
        def setEntries(self, entries):
+               ih = self.itemHeight
+               width = ih * 60 / 25
                res = [ None ] # no private data needed
                for x in entries:
                        tm = x[0]
                        xpos = x[1]
                        str = strftime("%H:%M", localtime(tm))
-                       res.append((eListboxPythonMultiContent.TYPE_TEXT, xpos-30, 0, 60, 25, 0, RT_HALIGN_CENTER|RT_VALIGN_CENTER, str))
+                       res.append((eListboxPythonMultiContent.TYPE_TEXT, xpos-30, 0, width, ih, 0, RT_HALIGN_CENTER|RT_VALIGN_CENTER, str))
                self.l.setList([res])
 
 config.misc.graph_mepg_prev_time=ConfigClock(default = time())
index 950b50e..a5c65be 100755 (executable)
@@ -8,7 +8,7 @@ SUBDIRS = SoftwareManager FrontprocessorUpgrade PositionerSetup Satfinder \
        Blindscan RemoteControlCode UI3DSetup UIPositionSetup HDMICEC LEDBrightnessSetup \
        FirmwareUpgrade CrashReport 3GModemManager WirelessAccessPoint ZappingModeSelection \
        DeviceManager TransCodingSetup WOLSetup NetDrive AudioEffect AnimationSetup \
-       BoxModeConfig Solo4kMiscControl FastChannelChange
+       BoxModeConfig Solo4kMiscControl FastChannelChange Ultimo4kMiscControl
 
 install_PYTHON =       \
        __init__.py
diff --git a/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/Makefile.am b/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/Makefile.am
new file mode 100644 (file)
index 0000000..c7cc202
--- /dev/null
@@ -0,0 +1,7 @@
+installdir = $(pkglibdir)/python/Plugins/SystemPlugins/Ultimo4kMiscControl
+
+SUBDIRS = meta
+
+install_PYTHON =  \
+       __init__.py \
+       plugin.py
diff --git a/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/__init__.py b/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/__init__.py
new file mode 100644 (file)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/meta/Makefile.am b/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/meta/Makefile.am
new file mode 100644 (file)
index 0000000..e23527e
--- /dev/null
@@ -0,0 +1,3 @@
+installdir = $(datadir)/meta
+
+dist_install_DATA = plugin_ultimo4kmisccontrol.xml
diff --git a/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/meta/plugin_ultimo4kmisccontrol.xml b/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/meta/plugin_ultimo4kmisccontrol.xml
new file mode 100644 (file)
index 0000000..7440ede
--- /dev/null
@@ -0,0 +1,16 @@
+<default>
+         <prerequisites>
+                    <tag type="System" />
+         </prerequisites>
+          <info>
+                    <author>hschang</author>
+                    <name>Ultimo4kMiscControl</name>
+                    <packagename>enigma2-plugin-systemplugins-ultimo4kmisccontrol</packagename>
+                    <shortdescription>set Ultimo4K LNB Power and etc..</shortdescription>
+                    <description>Control LNB Power and ToneBurst,CI delay for Ultimo4K.</description>
+          </info>
+
+         <files type="package"> <!-- without version, without .ipk -->
+               <file type="package" name="enigma2-plugin-systemplugins-ultimo4kmisccontrol" />
+       </files>
+</default>
diff --git a/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/plugin.py b/lib/python/Plugins/SystemPlugins/Ultimo4kMiscControl/plugin.py
new file mode 100644 (file)
index 0000000..d9cd261
--- /dev/null
@@ -0,0 +1,116 @@
+from Screens.Screen import Screen
+from Components.ConfigList import ConfigListScreen
+from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigSelection
+from Components.ActionMap import ActionMap
+from Screens.MessageBox import MessageBox
+from Components.Sources.StaticText import StaticText
+from Plugins.Plugin import PluginDescriptor
+from Tools.Directories import fileExists
+
+config.plugins.ultimo4kMiscControl = ConfigSubsection()
+config.plugins.ultimo4kMiscControl.forceLnbPower = ConfigSelection(default = "off", choices = [ ("on", _("Yes")), ("off", _("No"))] )
+config.plugins.ultimo4kMiscControl.forceToneBurst = ConfigSelection(default = "disable", choices = [ ("enable", _("Yes")), ("disable", _("No"))] )
+config.plugins.ultimo4kMiscControl.dvbCiDelay = ConfigSelection(default = "256", choices = [ ("16", _("16")), ("32", _("32")), ("64", _("64")), ("128", _("128")), ("256", _("256"))] )
+
+PROC_FORCE_LNBPOWER = "/proc/stb/frontend/fbc/force_lnbon"
+PROC_FORCE_TONEBURST = "/proc/stb/frontend/fbc/force_toneburst"
+PROC_DVB_CI_DELAY = "/proc/stb/tsmux/rmx_delay"
+
+def setProcValueOnOff(value, procPath):
+       try:
+               print "[ultimo4kMiscControl] set %s : %s" % (procPath, value)
+               fd = open(procPath,'w')
+               fd.write(value)
+               fd.close()
+               return 0
+       except Exception, e:
+               print "[ultimo4kMiscControl] proc write Error", e
+               return -1
+
+
+from enigma import eTimer
+class checkDriverSupport:
+       def __init__(self):
+               self.onLayoutFinish.append(self.procCheck)
+               self.dispErrorTimer = eTimer()
+               self.dispErrorTimer.callback.append(self.dispErrorMsg)
+
+       def procCheck(self):
+               if not (fileExists(PROC_FORCE_LNBPOWER) and fileExists(PROC_FORCE_TONEBURST) and fileExists(PROC_DVB_CI_DELAY)):
+                       self.dispErrorTimer.start(0, True)
+
+       def dispErrorMsg(self):
+               self.session.openWithCallback(self.close ,MessageBox, _("Driver is not supported."), MessageBox.TYPE_ERROR)
+
+class ultimo4kMiscControl(Screen, ConfigListScreen, checkDriverSupport):
+       skin =  """
+               <screen position="center,center" size="400,250" title="Ultimo4K Misc. Control" >
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="30,10" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="230,10" size="140,40" alphatest="on" />
+                       <widget source="key_red" render="Label" position="30,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_green" render="Label" position="230,10" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
+                       <widget name="config" zPosition="2" position="5,70" size="380,180" scrollbarMode="showOnDemand" transparent="1" />
+               </screen>
+               """
+
+       def __init__(self,session):
+               Screen.__init__(self,session)
+               self.session = session
+               self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
+               {
+                       "ok": self.keySave,
+                       "cancel": self.keyCancel,
+                       "red": self.keyCancel,
+                       "green": self.keySave,
+               }, -2)
+               self.list = []
+               ConfigListScreen.__init__(self, self.list,session = self.session)
+               self["key_red"] = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("Ok"))
+               self.createSetup()
+
+               checkDriverSupport.__init__(self)
+
+       def createSetup(self):
+               self.list = []
+               self.lnbPowerEntry = getConfigListEntry(_("Force LNB Power"), config.plugins.ultimo4kMiscControl.forceLnbPower)
+               self.toneBurstEntry = getConfigListEntry(_("Force ToneBurst"), config.plugins.ultimo4kMiscControl.forceToneBurst)
+               self.ciDelayEntry = getConfigListEntry(_("DVB CI Delay"), config.plugins.ultimo4kMiscControl.dvbCiDelay)
+               self.list.append( self.lnbPowerEntry )
+               self.list.append( self.toneBurstEntry )
+               self.list.append( self.ciDelayEntry )
+               self["config"].list = self.list
+               self["config"].l.setList(self.list)
+
+       def keySave(self):
+               res = setProcValueOnOff(config.plugins.ultimo4kMiscControl.forceLnbPower.value, PROC_FORCE_LNBPOWER)
+               if res == 0:
+                       res = setProcValueOnOff(config.plugins.ultimo4kMiscControl.forceToneBurst.value, PROC_FORCE_TONEBURST)
+               if res == 0:
+                       res = setProcValueOnOff(config.plugins.ultimo4kMiscControl.dvbCiDelay.value, PROC_DVB_CI_DELAY)
+
+               if res == -1:
+                       self.resetConfig()
+                       self.session.openWithCallback(self.close, MessageBox, _("SET FAILED!\n"), MessageBox.TYPE_ERROR)
+               else:
+                       self.saveAll()
+                       self.close()
+
+       def resetConfig(self):
+               for x in self["config"].list:
+                       x[1].cancel()
+
+def main(session, **kwargs):
+       session.open(ultimo4kMiscControl)
+
+def OnSessionStart(session, **kwargs):
+       setProcValueOnOff(config.plugins.ultimo4kMiscControl.forceLnbPower.value, PROC_FORCE_LNBPOWER)
+       setProcValueOnOff(config.plugins.ultimo4kMiscControl.forceToneBurst.value, PROC_FORCE_TONEBURST)
+       setProcValueOnOff(config.plugins.ultimo4kMiscControl.dvbCiDelay.value, PROC_DVB_CI_DELAY)
+
+def Plugins(**kwargs):
+       pList = []
+       pList.append( PluginDescriptor(where=PluginDescriptor.WHERE_SESSIONSTART, fnc=OnSessionStart) )
+       pList.append( PluginDescriptor(name=_("Ultimo4K Misc. Control"), description="set Ultimo4K LNB Power and etc..", where = PluginDescriptor.WHERE_PLUGINMENU, needsRestart = False, fnc=main) )
+       return pList
+
index 8781659..6b5d4d7 100644 (file)
@@ -62,10 +62,10 @@ class VideoHardware:
        }
 
        widescreen_modes = set(["720p", "1080i", "1080p", "2160p"])
-       hdmi_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k"])
-       hdmi_pc_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k"])
-       noscart_hw_types = set(["zero", "solo4k"])
-       noypbpr_hw_types = set(["solose", "zero", "solo4k"])
+       hdmi_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k", "ultimo4k", "uno4k"])
+       hdmi_pc_hw_types = set(["dm500", "dm800se", "dm7020hd", "bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k", "ultimo4k", "uno4k"])
+       noscart_hw_types = set(["zero", "solo4k", "ultimo4k", "uno4k"])
+       noypbpr_hw_types = set(["solose", "zero", "solo4k", "ultimo4k", "uno4k"])
 
        def getDeviceName(self):
                device_name = "unknown"
@@ -80,10 +80,10 @@ class VideoHardware:
                return device_name
 
        def isVumodel(self, hw_type):
-               return hw_type in set(["bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k"])
+               return hw_type in set(["bm750", "solo", "uno", "ultimo", "solo2", "duo2", "solose", "zero", "solo4k", "ultimo4k", "uno4k"])
 
        def isVumodel4K(self, hw_type):
-               return hw_type in set(["solo4k"])
+               return hw_type in set(["solo4k", "ultimo4k", "uno4k"])
 
        # re-define AVSwitch.getOutputAspect
        def getOutputAspect(self):
index bf29218..6d285fd 100644 (file)
@@ -9,10 +9,12 @@ from Screens.ChoiceBox import ChoiceBox
 from Screens.MessageBox import MessageBox
 from Screens.Standby import TryQuitMainloop
 
+from Components.SystemInfo import SystemInfo
 from Components.PluginComponent import plugins
 
 from Components.ConfigList import ConfigListScreen
 from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigYesNo, ConfigSelection
+from Components.Network import iNetwork
 
 import os
 
@@ -24,6 +26,8 @@ _flagSupportWol = _flagForceEnable and True or os.path.exists(_deviseWOL)
 _tryQuitTable = {"deepstandby":1, "reboot":2, "guirestart":3}
 
 _ethDevice = "eth0"
+if SystemInfo.get("WOWLSupport", False):
+       _ethDevice = "wlan3"
 
 config.plugins.wolconfig = ConfigSubsection()
 config.plugins.wolconfig.activate = ConfigYesNo(default = False)
@@ -46,7 +50,7 @@ class NetTool:
 
 class WOLSetup(ConfigListScreen, Screen):
        skin =  """
-               <screen name="WOLSetup" position="center,120" size="600,390" title="WakeOnLan Setup">
+               <screen name="WOLSetup" position="center,center" size="600,390" title="WakeOnLan Setup">
                        <ePixmap pixmap="skin_default/buttons/red.png" position="5,0" size="140,40" alphatest="on" />
                        <ePixmap pixmap="skin_default/buttons/green.png" position="155,0" size="140,40" alphatest="on" />
                        <ePixmap pixmap="skin_default/buttons/yellow.png" position="305,0" size="140,40" alphatest="on" />
@@ -98,7 +102,13 @@ class WOLSetup(ConfigListScreen, Screen):
                        self.configlist.append(getConfigListEntry(_("WakeOnLan Enable"), config.plugins.wolconfig.activate))
                        if config.plugins.wolconfig.activate.value:
                                self.configlist.append(getConfigListEntry(_("Location"), config.plugins.wolconfig.location))
-                               macaddr = "HWaddr of %s is %s" % (_ethDevice, NetTool.GetHardwareAddr(_ethDevice))
+                               if SystemInfo.get("WOWLSupport", False):
+                                       if iNetwork.getAdapterAttribute(_ethDevice, 'up'):
+                                               macaddr = "HWaddr of %s is %s" % (_ethDevice, NetTool.GetHardwareAddr(_ethDevice))
+                                       else:
+                                               macaddr = "Wireless lan is not activated."
+                               else:
+                                       macaddr = "HWaddr of %s is %s" % (_ethDevice, NetTool.GetHardwareAddr(_ethDevice))
                        else:   macaddr = "Wake on Lan disabled"
                        self["introduction"].setText(macaddr)
 
index f4dce00..5b34d8f 100755 (executable)
@@ -173,6 +173,8 @@ class WirelessAccessPoint(Screen,ConfigListScreen):
                for x in iNetwork.getInstalledAdapters():
                        if x.startswith('eth') or x.startswith('br') or x.startswith('mon'):
                                continue
+                       elif os_path.exists("/tmp/bcm/%s"%x):
+                               continue
                        wlanIfaces.append(x)
                        description=self.getAdapterDescription(x)
                        if description == "Unknown network adapter":
@@ -181,7 +183,7 @@ class WirelessAccessPoint(Screen,ConfigListScreen):
                                self.wlanDeviceList.append(( x, description + " (%s)"%x ))
 
                if len(self.wlanDeviceList) == 0:
-                       self.msg = "Wireless Lan Device is not detected."
+                       self.msg = "Can not find wireless lan devices that support AP mode."
                        return -1
 
                apModeConfig.wirelessdevice = ConfigSelection( choices = self.wlanDeviceList )
index 7f53647..0ff7c4f 100755 (executable)
@@ -136,6 +136,8 @@ class WlanSelection(Screen,HelpableScreen):
                                        return str(os_path.basename(os_path.realpath(driverdir))) + " " + _("WLAN adapter")
                        else:
                                return _("Unknown network adapter")
+               elif os_path.exists("/tmp/bcm/%s"%iface):
+                       return _("BroadCom WLAN adapter")
                else:
                        return _("Unknown network adapter")
 
@@ -300,20 +302,20 @@ class WlanSetup(Screen,HelpableScreen):
                        self.session.openWithCallback(self.checklist, WlanConfig, self.iface)
 
        def restartLan(self, ret = False):
-               if (ret == True):
+               if ret:
                        iNetwork.restartNetwork(self.restartLanDataAvail)
                        self.restartLanRef = self.session.openWithCallback(self.restartfinishedCB, MessageBox, _("Please wait while your network is restarting..."), type = MessageBox.TYPE_INFO, enable_input = False)
 
        def restartLanDataAvail(self, data):
-               if data is True:
+               if data:
                        iNetwork.getInterfaces(self.getInterfacesDataAvail)
 
        def getInterfacesDataAvail(self, data):
-               if data is True:
+               if data:
                        self.restartLanRef.close(True)
 
        def restartfinishedCB(self,data):
-               if data is True:
+               if data:
                        self.session.open(MessageBox, _("Finished restarting your network"), type = MessageBox.TYPE_INFO, timeout = 5, default = False)
 
        def cleanup(self):
@@ -383,6 +385,8 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
                self.updateInterfaces(self.updateInterfaceCB)
                self.onClose.append(self.cleanup)
 
+               self.useWlCommand = os_path.exists("/tmp/bcm/%s"%iface)
+
        def updateInterfaces(self,callback = None):
                iNetwork.config_ready = False
                iNetwork.msgPlugins()
@@ -395,6 +399,45 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
                self.createConfig()
                self.createSetup()
 
+       def getWlConfName(self, iface):
+               return "/etc/wl.conf.%s" % iface
+
+       def readWlConf(self):
+               wsconf = {}
+               wsconf["ssid"] = "Vuplus AP"
+               wsconf["hidden_ssid"] = False # not used
+               wsconf["encrypt_mothod"] = "wpa2"
+               wsconf["wep_keytype"] = "ascii" # not used
+               wsconf["key"] = "XXXXXXXX"
+
+               wlConfName = self.getWlConfName(self.iface)
+
+               if fileExists(wlConfName):
+                       fd = open(wlConfName, "r")
+                       lines = fd.readlines()
+                       fd.close()
+
+                       for line in lines:
+                               try:
+                                       (key, value) = line.strip().split('=',1)
+                               except:
+                                       continue
+
+                               if key == 'ssid':
+                                       wsconf["ssid"] = value.strip()
+                               if key == 'method':
+                                       wsconf["encrypt_mothod"] = value.strip()
+                               elif key == 'key':
+                                       wsconf["key"] = value.strip()
+                               else:
+                                       continue
+
+               print ""
+               for (k,v) in wsconf.items():
+                       print "[wsconf][%s] %s" % (k , v)
+
+               return wsconf
+
        def getWpaSupplicantName(self, iface):
                return "/etc/wpa_supplicant.conf.%s" % iface
 
@@ -527,11 +570,16 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
                self.displayIP("DNS1", self.primaryDNS)
                self.displayIP("DNS2", self.secondaryDNS)
 
-# readWPASupplicantConf
-               wsconf = self.readWpaSupplicantConf()
+# read old configuration
+               if self.useWlCommand:
+                       wsconf = self.readWlConf()
+               else:
+                       wsconf = self.readWpaSupplicantConf()
 
 # method setup
-               encryptionChoices = [("wep", _("WEP")), ("wpa", _("WPA")), ("wpa2", _("WPA2")), ("wpa/wpa2", _("WPA/WPA2")), ("None", _("No Encrypt"))  ]
+               encryptionChoices = [("wep", _("WEP")), ("wpa", _("WPA")), ("wpa2", _("WPA2")), ("None", _("No Encrypt"))  ]
+               if not self.useWlCommand:
+                       encryptionChoices.append( ("wpa/wpa2", _("WPA/WPA2")) )
                self.methodConfigEntry = NoSave(ConfigSelection(default = wsconf["encrypt_mothod"], choices = encryptionChoices))
 
 # key type setup
@@ -559,9 +607,11 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
                self.usedeviceEntry = getConfigListEntry(_("Use Device"), self.activateInterfaceEntry)
                self.usedhcpEntry = getConfigListEntry(_("Use DHCP"), self.usedhcpConfigEntry)
                self.essidEntry = getConfigListEntry(_("SSID"), self.ssidConfigEntry)
-               self.hiddenessidEntry = getConfigListEntry(_("Hidden Network"), self.hiddenssidConfigEntry)
+               if not self.useWlCommand:
+                       self.hiddenessidEntry = getConfigListEntry(_("Hidden Network"), self.hiddenssidConfigEntry)
                self.methodEntry = getConfigListEntry(_("Encrypt Method"), self.methodConfigEntry)
-               self.keytypeEntry = getConfigListEntry(_("Key Type"), self.keytypeConfigEntry)
+               if not self.useWlCommand:
+                       self.keytypeEntry = getConfigListEntry(_("Key Type"), self.keytypeConfigEntry)
                self.keyEntry = getConfigListEntry(_("KEY"), self.keyConfigEntry)
 
                self.ipEntry = getConfigListEntry(_("IP"), self.IPConfigEntry)
@@ -596,12 +646,16 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
                                self.configList.append(self.primaryDNSConfigEntry)
                                self.configList.append(self.secondaryDNSConfigEntry)
 
-                       self.configList.append( self.hiddenessidEntry )
+                       if not self.useWlCommand:
+                               self.configList.append( self.hiddenessidEntry )
+
                        self.configList.append( self.essidEntry )
                        self.configList.append( self.methodEntry )
 
                        if self.methodConfigEntry.value =="wep":
-                               self.configList.append( self.keytypeEntry )
+                               if not self.useWlCommand:
+                                       self.configList.append( self.keytypeEntry )
+
                        if self.methodConfigEntry.value != "None":
                                self.configList.append( self.keyEntry )
 
@@ -702,10 +756,47 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
                                iNetwork.setAdapterAttribute(interface, "up", False)
                                iNetwork.deactivateInterface(interface)
 
-               if not self.isWPAMethod(self.methodConfigEntry.value):
-                       self.writeWpasupplicantConf()
+               plainpwd = None
+               psk = None
+
+               if self.isWPAMethod(self.methodConfigEntry.value) and (not self.useWlCommand):
+                       (psk, plainpwd) = self.getWpaPhrase()
+
+               res = False
+               if self.useWlCommand:
+                       res = self.writeWlConf()
                else:
-                       self.getWpaPhrase()
+                       res = self.writeWpasupplicantConf(psk, plainpwd)
+
+               if res:
+                       self.writeNetConfig()
+
+       def writeWlConf(self):
+               wsconf = {}
+               wsconf["ssid"] = "Vuplus AP"
+               wsconf["hidden_ssid"] = False # not used
+               wsconf["encrypt_mothod"] = "None"
+               wsconf["wep_keytype"] = "ascii" # not used
+               wsconf["key"] = "XXXXXXXX"
+               
+               wlConfName = self.getWlConfName(self.iface)
+
+               try:
+                       fd = open(wlConfName, "w")
+               except:
+                       self.session.open(MessageBox, _("%s open error." % wlConfName ), type = MessageBox.TYPE_ERROR, timeout = 10)
+                       return False
+
+               contents = ""
+               contents += "ssid="+self.ssidConfigEntry.value+"\n"
+               contents += "method="+self.methodConfigEntry.value+"\n"
+               contents += "key="+self.keyConfigEntry.value+"\n"
+
+               print "content = \n"+contents
+               fd.write(contents)
+               fd.close()
+
+               return True
 
        def getWpaPhrase(self):
                cmd = "wpa_passphrase '%s' '%s'" % (self.ssidConfigEntry.value, self.keyConfigEntry.value)
@@ -724,7 +815,8 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
                                plainpwd = line
                        elif key == 'psk':
                                psk = line
-               self.writeWpasupplicantConf(psk, plainpwd)
+
+               return (psk, plainpwd)
 
        def writeWpasupplicantConf(self, passphrasekey=None, plainpwd=None):
                wpaSupplicantName = self.getWpaSupplicantName(self.iface)
@@ -732,7 +824,7 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
                        wpafd = open(wpaSupplicantName, "w")
                except:
                        self.session.open(MessageBox, _("%s open error." % wpaSupplicantName ), type = MessageBox.TYPE_ERROR, timeout = 10)
-                       return
+                       return False
 
                contents = "#WPA Supplicant Configuration by STB\n"
                contents += "ctrl_interface=/var/run/wpa_supplicant\n"
@@ -788,7 +880,8 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
 #              print "content = \n"+contents
                wpafd.write(contents)
                wpafd.close()
-               self.writeNetConfig()
+
+               return True
 
        def writeNetConfig(self):
                if self.activateInterfaceEntry.value is True:
@@ -812,9 +905,13 @@ class WlanConfig(Screen, ConfigListScreen, HelpableScreen):
                        iNetwork.setAdapterAttribute(self.iface, "up", False)
                        iNetwork.deactivateInterface(self.iface)
 
-               wpaSupplicantName = self.getWpaSupplicantName(self.iface)
-               contents = "\tpre-up wpa_supplicant -i"+self.iface+" -c%s -B -D" % (wpaSupplicantName)  +iNetwork.detectWlanModule(self.iface)+"\n"
-               contents += "\tpost-down wpa_cli terminate\n"
+               if self.useWlCommand:
+                       contents = '\tpre-up wl-config.sh -m %s -k %s -s "%s" \n' % (self.methodConfigEntry.value, self.keyConfigEntry.value, self.ssidConfigEntry.value)
+                       contents += '\tpost-down wl-down.sh\n'
+               else:
+                       wpaSupplicantName = self.getWpaSupplicantName(self.iface)
+                       contents = "\tpre-up wpa_supplicant -i"+self.iface+" -c%s -B -D" % (wpaSupplicantName)  +iNetwork.detectWlanModule(self.iface)+"\n"
+                       contents += "\tpost-down wpa_cli terminate\n"
                iNetwork.setAdapterAttribute(self.iface, "configStrings", contents)
                iNetwork.writeNetworkConfig()
                iNetwork.restartNetwork(self.updateCurrentInterfaces)
@@ -967,6 +1064,8 @@ class WlanScanAp(Screen,HelpableScreen):
                self.onClose.append(self.__onClose)
                self.onShown.append(lambda: self.startupTimer.start(10, True))
 
+               self.useWlCommand = os_path.exists("/tmp/bcm/%s"%iface)
+
        def startup(self):
                if self.oldInterfaceState is not True:
                        self["Status"].setText(("Please wait for activating interface..."))
@@ -977,6 +1076,10 @@ class WlanScanAp(Screen,HelpableScreen):
        def activateIface(self):
                os_system("ifconfig "+self.iface+" up")
                iNetwork.setAdapterAttribute(self.iface, "up", True)
+
+               if self.useWlCommand:
+                       os_system("wl up")
+
                self.updateStatusTimer.start(10, True)
                
 
@@ -1118,6 +1221,9 @@ class WlanScanAp(Screen,HelpableScreen):
                        os_system("ifconfig "+self.iface+" down")
                        iNetwork.setAdapterAttribute(self.iface, "up", False)
 
+                       if self.useWlCommand:
+                               os_system("wl down")
+
 class NetworkAdapterTest(Screen):
        def __init__(self, session,iface):
                Screen.__init__(self, session)
index 4145722..8fec85c 100755 (executable)
@@ -16,7 +16,8 @@ from Screens.InfoBarGenerics import InfoBarShowHide, \
        InfoBarSubserviceSelection, InfoBarShowMovies, InfoBarTimeshift,  \
        InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarSimpleEventView, \
        InfoBarSummarySupport, InfoBarMoviePlayerSummarySupport, InfoBarTimeshiftState, InfoBarTeletextPlugin, InfoBarExtensions, \
-       InfoBarSubtitleSupport, InfoBarPiP, InfoBarPlugins, InfoBarServiceErrorPopupSupport, InfoBarJobman
+       InfoBarSubtitleSupport, InfoBarPiP, InfoBarPlugins, InfoBarServiceErrorPopupSupport, InfoBarJobman, \
+       InfoBarHDMI
 
 profile("LOAD:InitBar_Components")
 from Components.ActionMap import HelpableActionMap
@@ -33,7 +34,7 @@ class InfoBar(InfoBarBase, InfoBarShowHide,
        InfoBarSubserviceSelection, InfoBarTimeshift, InfoBarSeek,
        InfoBarSummarySupport, InfoBarTimeshiftState, InfoBarTeletextPlugin, InfoBarExtensions,
        InfoBarPiP, InfoBarPlugins, InfoBarSubtitleSupport, InfoBarServiceErrorPopupSupport, InfoBarJobman,
-       Screen):
+       InfoBarHDMI, Screen):
        
        ALLOW_SUSPEND = True
        instance = None
@@ -57,7 +58,7 @@ class InfoBar(InfoBarBase, InfoBarShowHide,
                                InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, InfoBarSubserviceSelection, \
                                InfoBarTimeshift, InfoBarSeek, InfoBarSummarySupport, InfoBarTimeshiftState, \
                                InfoBarTeletextPlugin, InfoBarExtensions, InfoBarPiP, InfoBarSubtitleSupport, InfoBarJobman, \
-                               InfoBarPlugins, InfoBarServiceErrorPopupSupport:
+                               InfoBarPlugins, InfoBarServiceErrorPopupSupport, InfoBarHDMI:
                        x.__init__(self)
 
                self.helpList.append((self["actions"], "InfobarActions", [("showMovies", _("view recordings..."))]))
@@ -133,7 +134,7 @@ class MoviePlayer(InfoBarBase, InfoBarShowHide, \
                InfoBarSeek, InfoBarShowMovies, InfoBarAudioSelection, HelpableScreen, InfoBarNotifications,
                InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarSimpleEventView,
                InfoBarMoviePlayerSummarySupport, InfoBarSubtitleSupport, Screen, InfoBarTeletextPlugin,
-               InfoBarServiceErrorPopupSupport, InfoBarExtensions, InfoBarPlugins, InfoBarPiP):
+               InfoBarServiceErrorPopupSupport, InfoBarExtensions, InfoBarPlugins, InfoBarPiP, InfoBarHDMI):
 
        ENABLE_RESUME_SUPPORT = True
        ALLOW_SUSPEND = True
index a6d25d5..2bf91fd 100755 (executable)
@@ -2329,3 +2329,47 @@ class InfoBarServiceErrorPopupSupport:
                        Notifications.AddPopup(text = error, type = MessageBox.TYPE_ERROR, timeout = 5, id = "ZapError")
                else:
                        Notifications.RemovePopup(id = "ZapError")
+
+class InfoBarHDMI:
+       def __init__(self):
+               self.hdmiInServiceRef = eServiceReference('8192:0:1:0:0:0:0:0:0:0:')
+               if SystemInfo.get("HdmiInSupport", False):
+                       self.addExtension((self.getShowHdmiInName, self.HDMIIn, lambda: True), None)
+                       self.addExtension((self.getShowHdmiInPIPName, self.HDMIInPIP, self.pipShown), None)
+
+       def getShowHdmiInName(self):
+               curref = self.session.nav.getCurrentlyPlayingServiceReference()
+               if curref and curref.type == 8192:
+                       name = _("Disable HDMI-IN on Main Screen")
+               else:
+                       name = _("Enable HDMI-IN on Main Screen")
+
+               return name
+
+       def getShowHdmiInPIPName(self):
+               curref = self.session.pip.getCurrentService()
+               if curref and curref.type == 8192:
+                       name = _("Disable HDMI-IN on PIP")
+               else:
+                       name = _("Enable HDMI-IN on PIP")
+
+               return name
+
+       def getCurrentServiceRef(self):
+               slist = self.servicelist
+               currentServiceSref = slist.servicelist.getCurrent()
+               return currentServiceSref
+
+       def HDMIIn(self):
+               curref = self.session.nav.getCurrentlyPlayingServiceReference()
+               if curref and curref.type == 8192:
+                       self.session.nav.playService(self.getCurrentServiceRef())
+               else:
+                       self.session.nav.playService(self.hdmiInServiceRef)
+
+       def HDMIInPIP(self):
+               curref = self.session.pip.getCurrentService()
+               if curref and curref.type == 8192:
+                       self.session.pip.playService(self.getCurrentServiceRef())
+               else:
+                       self.session.pip.playService(self.hdmiInServiceRef)
\ No newline at end of file
index d423f46..0f7148a 100755 (executable)
@@ -46,6 +46,12 @@ class PluginBrowser(Screen):
                self["SoftwareActions"].setEnabled(False)
                self.onFirstExecBegin.append(self.checkWarnings)
                self.onShown.append(self.updateList)
+               self.onLayoutFinish.append(self.saveListsize)
+
+       def saveListsize(self):
+               listsize = self["list"].instance.size()
+               self.listWidth = listsize.width()
+               self.listHeight = listsize.height()
        
        def checkWarnings(self):
                if len(plugins.warnings):
@@ -64,7 +70,7 @@ class PluginBrowser(Screen):
                
        def updateList(self):
                self.pluginlist = plugins.getPlugins(PluginDescriptor.WHERE_PLUGINMENU)
-               self.list = [PluginEntryComponent(plugin) for plugin in self.pluginlist]
+               self.list = [PluginEntryComponent(plugin, self.listWidth) for plugin in self.pluginlist]
                self["list"].l.setList(self.list)
                if fileExists(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/plugin.py")):
                        self["red"].setText(_("Manage extensions"))
@@ -172,7 +178,10 @@ class PluginDownloadBrowser(Screen):
                self.container.execute("opkg list enigma2-plugin-*")
 
        def startRun(self):
+               listsize = self["list"].instance.size()
                self["list"].instance.hide()
+               self.listWidth = listsize.width()
+               self.listHeight = listsize.height()
                if self.type == self.DOWNLOAD:
                        if not PluginDownloadBrowser.lastDownloadDate or (time() - PluginDownloadBrowser.lastDownloadDate) > 3600:
                                # Only update from internet once per hour
@@ -256,10 +265,10 @@ class PluginDownloadBrowser(Screen):
                        
                for x in self.plugins.keys():
                        if x in self.expanded:
-                               list.append(PluginCategoryComponent(x, expandedIcon))
-                               list.extend([PluginDownloadComponent(plugin[0], plugin[1]) for plugin in self.plugins[x]])
+                               list.append(PluginCategoryComponent(x, expandedIcon, self.listWidth))
+                               list.extend([PluginDownloadComponent(plugin[0], plugin[1], self.listWidth) for plugin in self.plugins[x]])
                        else:
-                               list.append(PluginCategoryComponent(x, expandableIcon))
+                               list.append(PluginCategoryComponent(x, expandableIcon, self.listWidth))
                self.list = list
                self["list"].l.setList(list)
 
index 58f5494..564541b 100644 (file)
@@ -1,4 +1,4 @@
-from enigma import eDVBDB
+from enigma import eDVBDB, getLinkedSlotID, isFBCLink
 from Screen import Screen
 from Components.SystemInfo import SystemInfo
 from Components.ActionMap import ActionMap
@@ -18,21 +18,6 @@ from datetime import datetime
 from Components.PluginComponent import plugins
 from Plugins.Plugin import PluginDescriptor
 
-def isFBCTuner(nim):
-       if nim.description.find("FBC") == -1:
-               return False
-       return True
-
-def isFBCRoot(nim):
-       if nim.slot %8 < 2:
-               return True
-       return False
-
-def isFBCLink(nim):
-       if isFBCTuner(nim) and not isFBCRoot(nim):
-               return True
-       return False
-
 class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
        def createSimpleSetup(self, list, mode):
                nim = self.nimConfig
@@ -88,7 +73,7 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                                choices["satposdepends"] = _("second cable of motorized LNB")
                        if len(nimmanager.canConnectTo(self.slotid)) > 0:
                                choices["loopthrough"] = _("loopthrough to")
-                       if isFBCLink(self.nim):
+                       if isFBCLink(self.nim.slot):
                                choices = { "nothing": _("not configured"),
                                                "advanced": _("advanced")}
                        self.nimConfig.configMode.setChoices(choices, default = "nothing")
@@ -268,7 +253,7 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                self.list.append(self.advancedLnbsEntry)
 
                if currLnb:
-                       if isFBCLink(self.nim):
+                       if isFBCLink(self.nim.slot):
                                if currLnb.lof.value != "unicable":
                                        currLnb.lof.value = "unicable"
 
@@ -336,7 +321,7 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                                for id in connectable:
                                        choices.append((str(id), nimmanager.getNimDescription(id)))
                                if len(choices):
-                                       if isFBCLink(self.nim):
+                                       if isFBCLink(self.nim.slot):
                                                if self.nimConfig.advanced.unicableconnected.value != True:
                                                        self.nimConfig.advanced.unicableconnected.value = True
 
@@ -512,7 +497,7 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                self.createSetup()
 
        def keyLeft(self):
-               if isFBCLink(self.nim):
+               if isFBCLink(self.nim.slot):
                        checkList = (self.advancedLof, self.advancedConnected)
                        curEntry = self["config"].getCurrent()
                        if curEntry in checkList:
@@ -522,7 +507,7 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
                self.newConfig()
 
        def keyRight(self):
-               if isFBCLink(self.nim):
+               if isFBCLink(self.nim.slot):
                        checkList = (self.advancedLof, self.advancedConnected)
                        curEntry = self["config"].getCurrent()
                        if curEntry in checkList:
@@ -587,8 +572,7 @@ class NimSelection(Screen):
                        configMode = nimConfig.configMode.value
                        if self.showNim(x):
                                if x.isCompatible("DVB-S"):
-                                       if isFBCLink(x) and configMode != "advanced":
-                                               from enigma import getLinkedSlotID
+                                       if isFBCLink(x.slot) and configMode != "advanced":
                                                link = getLinkedSlotID(x.slot)
 
                                                if link == -1:
@@ -605,7 +589,7 @@ class NimSelection(Screen):
                nim = nim and nim[3]
 
                nimConfig = nimmanager.getNimConfig(nim.slot)
-               if isFBCLink(nim) and nimConfig.configMode.value == "loopthrough":
+               if isFBCLink(nim.slot) and nimConfig.configMode.value == "loopthrough":
                        return
 
                if nim is not None and not nim.empty and nim.isSupported():
@@ -664,7 +648,7 @@ class NimSelection(Screen):
                                                        text = _("simple")
                                        elif nimConfig.configMode.value == "advanced":
                                                text = _("advanced")
-                                       if isFBCLink(x) and nimConfig.configMode.value != "advanced":
+                                       if isFBCLink(x.slot) and nimConfig.configMode.value != "advanced":
                                                text += _("\n<This tuner is configured automatically>")
                                elif x.isCompatible("DVB-T") or x.isCompatible("DVB-C"):
                                        if nimConfig.configMode.value == "nothing":
index 6fdeb53..079bdef 100644 (file)
@@ -101,13 +101,16 @@ cable_bands = {
 cable_autoscan_nimtype = {
 'SSH108' : 'ssh108',
 'TT3L10' : 'tt3l10',
-'TURBO' : 'vuplus_turbo_c'
+'TURBO' : 'vuplus_turbo_c',
+'TT2L08' : 'tt2l08',
+'BCM3148' : 'bcm3148'
 }
 
 terrestrial_autoscan_nimtype = {
 'SSH108' : 'ssh108_t2_scan',
 'TT3L10' : 'tt3l10_t2_scan',
-'TURBO' : 'vuplus_turbo_t'
+'TURBO' : 'vuplus_turbo_t',
+'TT2L08' : 'tt2l08_t2_scan'
 }
 
 def GetDeviceId(filter, nim_idx):
index da534ec..ffd288f 100644 (file)
@@ -6,6 +6,7 @@ from Components.Label import Label
 from ServiceReference import ServiceReference
 from enigma import eListboxPythonMultiContent, eListbox, gFont, iServiceInformation, eServiceCenter
 from Tools.Transponder import ConvertToHumanReadable
+import skin
 
 RT_HALIGN_LEFT = 0
 
@@ -30,11 +31,14 @@ def ServiceInfoListEntry(a, b, valueType=TYPE_TEXT, param=4):
                else:
                        b = str(b)
 
+       x, y, w, h = skin.parameters.get("ServiceInfo",(0, 0, 200, 30))
+       xa, ya, wa, ha = skin.parameters.get("ServiceInfoLeft",(0, 0, 200, 25))
+       xb, yb, wb, hb = skin.parameters.get("ServiceInfoRight",(220, 0, 350, 25))
        return [
                #PyObject *type, *px, *py, *pwidth, *pheight, *pfnt, *pstring, *pflags;
-               (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 200, 30, 0, RT_HALIGN_LEFT, ""),
-               (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 200, 25, 0, RT_HALIGN_LEFT, a),
-               (eListboxPythonMultiContent.TYPE_TEXT, 220, 0, 350, 25, 0, RT_HALIGN_LEFT, b)
+               (eListboxPythonMultiContent.TYPE_TEXT, x, y, w, h, 0, RT_HALIGN_LEFT, ""),
+               (eListboxPythonMultiContent.TYPE_TEXT, xa, ya, wa, ha, 0, RT_HALIGN_LEFT, a),
+               (eListboxPythonMultiContent.TYPE_TEXT, xb, yb, wb, hb, 0, RT_HALIGN_LEFT, b)
        ]
 
 class ServiceInfoList(HTMLComponent, GUIComponent):
@@ -43,8 +47,9 @@ class ServiceInfoList(HTMLComponent, GUIComponent):
                self.l = eListboxPythonMultiContent()
                self.list = source
                self.l.setList(self.list)
-               self.l.setFont(0, gFont("Regular", 23))
-               self.l.setItemHeight(25)
+               font = skin.fonts.get("ServiceInfo", ("Regular", 23, 25))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               self.l.setItemHeight(font[2])
 
        GUI_WIDGET = eListbox
 
index 174ffdd..36d8e7c 100755 (executable)
@@ -10,12 +10,14 @@ from Components.MenuList import MenuList
 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
 from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN
 from Tools.LoadPixmap import LoadPixmap
+import skin
 
 class VirtualKeyBoardList(MenuList):
        def __init__(self, list, enableWrapAround=False):
                MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
-               self.l.setFont(0, gFont("Regular", 28))
-               self.l.setItemHeight(45)
+               font = skin.fonts.get("VirtualKeyboard", ("Regular", 28, 45))
+               self.l.setFont(0, gFont(font[0], font[1]))
+               self.l.setItemHeight(font[2])
 
 def VirtualKeyBoardEntryComponent(keys, selectedKey,shiftMode=False):
        key_backspace = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_backspace.png"))
index e72d291..da7b9db 100644 (file)
@@ -1,5 +1,8 @@
+import os
+
 class HardwareInfo:
        device_name = None
+       vu_device_name = None
 
        def __init__(self):
                if HardwareInfo.device_name is not None:
@@ -30,5 +33,13 @@ class HardwareInfo:
                        except:
                                pass
 
+               HardwareInfo.vu_device_name = "unknown"
+               vumodel_path = "/proc/stb/info/vumodel"
+               if os.access(vumodel_path, os.F_OK):
+                       HardwareInfo.vu_device_name = open(vumodel_path, "r").read().strip()
+
        def get_device_name(self):
                return HardwareInfo.device_name
+
+       def get_vu_device_name(self):
+               return HardwareInfo.vu_device_name
index 158c986..e9a8161 100755 (executable)
@@ -356,6 +356,16 @@ void setFCCEnable(int enable)
 }
 %}
 
+bool isFBCLink(int);
+%{
+bool isFBCLink(int fe)
+{
+        eFBCTunerManager *mgr = eFBCTunerManager::getInstance();
+        if (mgr) return mgr->isFBCLink(fe);
+        return false;
+}
+%}
+
 /************** temp *****************/
 
        /* need a better place for this, i agree. */
index 2df1dd9..07d69d0 100644 (file)
@@ -18,7 +18,8 @@ libenigma_service_a_SOURCES = \
        servicedvbfcc.cpp \
        servicefs.cpp \
        servicemp3.cpp \
-       servicem2ts.cpp
+       servicem2ts.cpp \
+       servicehdmi.cpp
 
 serviceincludedir = $(pkgincludedir)/lib/service
 serviceinclude_HEADERS = \
@@ -31,7 +32,8 @@ serviceinclude_HEADERS = \
        servicedvbfcc.h \
        servicefs.h \
        servicemp3.h \
-       servicem2ts.h
+       servicem2ts.h \
+       servicehdmi.h
 
 if HAVE_LIBXINE
 libenigma_service_a_SOURCES += \
index 086f595..acc998a 100755 (executable)
@@ -945,6 +945,7 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv
        m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
 {
        m_is_primary = 1;
+       m_decoder_index = 0;
        m_is_stream = m_reference.path.substr(0, 7) == "http://";
        m_is_pvr = (!m_reference.path.empty() && !m_is_stream);
 
@@ -1268,6 +1269,7 @@ RESULT eDVBServicePlay::stop()
 RESULT eDVBServicePlay::setTarget(int target)
 {
        m_is_primary = !target;
+       m_decoder_index = target;
        return 0;
 }
 
@@ -2577,7 +2579,7 @@ void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
                h.getDecodeDemux(m_decode_demux);
                if (m_decode_demux)
                {
-                       m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
+                       m_decode_demux->getMPEGDecoder(m_decoder, m_decoder_index);
                        if (m_decoder)
                                m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
                        if (m_is_primary)
index 7ded16a..eafc96d 100644 (file)
@@ -192,6 +192,7 @@ protected:
        ePtr<eDVBService> m_dvb_service;
        
        ePtr<iTSMPEGDecoder> m_decoder;
+       int m_decoder_index;
        int m_is_primary;
        int m_have_video_pid;
        int m_tune_state;
index 972e73e..7cabb03 100644 (file)
@@ -236,7 +236,7 @@ void eDVBServiceFCCPlay::updateFCCDecoder(bool sendSeekableStateChanged)
                h.getDecodeDemux(m_decode_demux);
                if (m_decode_demux)
                {
-                       m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
+                       m_decode_demux->getMPEGDecoder(m_decoder, m_decoder_index);
                        if (m_decoder)
                                m_decoder->connectVideoEvent(slot(*this, &eDVBServiceFCCPlay::video_event), m_video_event_connection);
                }
diff --git a/lib/service/servicehdmi.cpp b/lib/service/servicehdmi.cpp
new file mode 100644 (file)
index 0000000..2767982
--- /dev/null
@@ -0,0 +1,352 @@
+#include <lib/base/ebase.h>
+#include <lib/base/eerror.h>
+#include <lib/base/init_num.h>
+#include <lib/base/init.h>
+#include <lib/base/nconfig.h>
+#include <lib/base/object.h>
+#include <lib/dvb/decoder.h>
+#include <lib/service/servicehdmi.h>
+#include <lib/service/service.h>
+
+#include <string>
+
+#define HDMI_IN_REC_ENCODER_INDEX 0
+#define HDMI_IN_REC_DECODER_INDEX 2
+
+eServiceFactoryHDMI::eServiceFactoryHDMI()
+{
+       ePtr<eServiceCenter> sc;
+
+       eServiceCenter::getPrivInstance(sc);
+       if (sc)
+       {
+               std::list<std::string> extensions;
+               sc->addServiceFactory(eServiceFactoryHDMI::id, this, extensions);
+       }
+
+       m_service_info = new eStaticServiceHDMIInfo();
+}
+
+eServiceFactoryHDMI::~eServiceFactoryHDMI()
+{
+       ePtr<eServiceCenter> sc;
+
+       eServiceCenter::getPrivInstance(sc);
+       if (sc)
+       {
+               sc->removeServiceFactory(eServiceFactoryHDMI::id);
+       }
+}
+
+DEFINE_REF(eServiceFactoryHDMI)
+
+RESULT eServiceFactoryHDMI::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
+{
+       ptr = new eServiceHDMI(ref);
+       return 0;
+}
+
+RESULT eServiceFactoryHDMI::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
+{
+       ePtr<eNavigation> nav_instance;
+       getNavInstance(nav_instance);
+       ptr = new eServiceHDMIRecord(ref, nav_instance);
+       return 0;
+}
+
+RESULT eServiceFactoryHDMI::list(const eServiceReference &, ePtr<iListableService> &ptr)
+{
+       ptr = 0;
+       return -1;
+}
+
+RESULT eServiceFactoryHDMI::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
+{
+       ptr = m_service_info;
+       return 0;
+}
+
+RESULT eServiceFactoryHDMI::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
+{
+       ptr = 0;
+       return -1;
+}
+
+void eServiceFactoryHDMI::getNavInstance(ePtr<eNavigation> &nav_instance)
+{
+       if (!m_nav_instance)
+       {
+               ePtr<iServiceHandler> service_center;
+               eServiceCenter::getInstance(service_center);
+               m_nav_instance = new eNavigation(service_center, HDMI_IN_REC_DECODER_INDEX);
+       }
+       nav_instance = m_nav_instance;
+}
+
+DEFINE_REF(eStaticServiceHDMIInfo)
+
+eStaticServiceHDMIInfo::eStaticServiceHDMIInfo()
+{
+}
+
+RESULT eStaticServiceHDMIInfo::getName(const eServiceReference &ref, std::string &name)
+{
+       if (ref.name.length())
+       {
+               name = ref.name;
+       }
+       else
+       {
+               name = "HDMI IN";
+       }
+       return 0;
+}
+
+int eStaticServiceHDMIInfo::getLength(const eServiceReference &ref)
+{
+       return -1;
+}
+
+int eStaticServiceHDMIInfo::getInfo(const eServiceReference &ref, int w)
+{
+       return iServiceInformation::resNA;
+}
+
+long long eStaticServiceHDMIInfo::getFileSize(const eServiceReference &ref)
+{
+       return 0;
+}
+
+eServiceHDMI::eServiceHDMI(eServiceReference ref)
+ : m_ref(ref), m_decoder_index(0)
+{
+
+}
+
+eServiceHDMI::~eServiceHDMI()
+{
+}
+
+DEFINE_REF(eServiceHDMI);
+
+RESULT eServiceHDMI::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
+{
+       connection = new eConnection((iPlayableService*)this, m_event.connect(event));
+       return 0;
+}
+
+RESULT eServiceHDMI::start()
+{
+       m_decoder = new eTSMPEGDecoder(NULL, m_decoder_index);
+       m_decoder->setVideoPID(1, 0);
+       m_decoder->setAudioPID(1, 0);
+       m_decoder->play();
+       m_event(this, evStart);
+       return 0;
+}
+
+RESULT eServiceHDMI::stop()
+{
+       m_decoder = NULL;
+       m_event(this, evStopped);
+       return 0;
+}
+
+RESULT eServiceHDMI::setTarget(int target)
+{
+       m_decoder_index = target;
+       return 0;
+}
+
+RESULT eServiceHDMI::info(ePtr<iServiceInformation> &i)
+{
+       i = this;
+       return 0;
+}
+
+RESULT eServiceHDMI::getName(std::string &name)
+{
+       if (m_ref.name.length())
+       {
+               name = m_ref.name;
+       }
+       else
+       {
+               name = "HDMI IN";
+       }
+       return 0;
+}
+
+int eServiceHDMI::getInfo(int w)
+{
+       return resNA;
+}
+
+std::string eServiceHDMI::getInfoString(int w)
+{
+       return "";
+}
+
+PyObject* eServiceHDMI::getInfoObject(int w)
+{
+       Py_RETURN_NONE;
+}
+
+DEFINE_REF(eServiceHDMIRecord);
+
+eServiceHDMIRecord::eServiceHDMIRecord(const eServiceReference &ref, ePtr<eNavigation> &nav_instance)
+{
+       m_ref = ref;
+       m_state = stateIdle;
+       m_target_fd = -1;
+       m_error = 0;
+       m_encoder_fd = -1;
+       m_thread = NULL;
+       m_nav_instance = nav_instance;
+}
+
+RESULT eServiceHDMIRecord::prepare(const char *filename, time_t begTime, time_t endTime, int eit_event_id, const char *name, const char *descr, const char *tags)
+{
+       m_filename = filename;
+
+       if (m_state == stateIdle)
+       {
+               return doPrepare();
+       }
+       return -1;
+}
+
+RESULT eServiceHDMIRecord::prepareStreaming()
+{
+       return -1;
+}
+
+RESULT eServiceHDMIRecord::start(bool simulate)
+{
+       m_simulate = simulate;
+       m_event((iRecordableService*)this, evStart);
+       return doRecord();
+}
+
+RESULT eServiceHDMIRecord::stop()
+{
+       if (!m_simulate)
+               eDebug("[eServiceHDMIRecord] stop recording!");
+       if (m_state == stateRecording)
+       {
+               if (m_thread)
+               {
+                       m_thread->stop();
+                       m_thread->stopSaveMetaInformation();
+               }
+               if (m_target_fd >= 0)
+               {
+                       ::close(m_target_fd);
+                       m_target_fd = -1;
+               }
+
+               m_state = statePrepared;
+       } else if (!m_simulate)
+               eDebug("[eServiceHDMIRecord] (was not recording)");
+       if (m_state == statePrepared)
+       {
+               delete m_thread;
+               m_thread = NULL;
+               m_nav_instance->stopService();
+               if (m_encoder_fd >= 0)
+               {
+                       ::close(m_encoder_fd);
+                       m_encoder_fd = -1;
+               }
+               m_state = stateIdle;
+       }
+       m_event((iRecordableService*)this, evRecordStopped);
+       return 0;
+}
+
+int eServiceHDMIRecord::doPrepare()
+{
+       if (!m_simulate && m_encoder_fd < 0)
+       {
+               if (m_nav_instance->playService(m_ref) >= 0)
+               {
+                       char filename[128];
+                       snprintf(filename, sizeof(filename), "/dev/encoder%d", HDMI_IN_REC_ENCODER_INDEX);
+                       m_encoder_fd = open(filename, O_RDONLY);
+               }
+               if (m_encoder_fd < 0)
+                       return -1;
+       }
+       m_state = statePrepared;
+       return 0;
+}
+
+int eServiceHDMIRecord::doRecord()
+{
+       int err = doPrepare();
+       if (err)
+       {
+               m_error = errTuneFailed;
+               m_event((iRecordableService*)this, evRecordFailed);
+               return err;
+       }
+
+       if (!m_thread && !m_simulate)
+       {
+               eDebug("[eServiceHDMIRecord] Recording to %s...", m_filename.c_str());
+               ::remove(m_filename.c_str());
+               int fd = ::open(m_filename.c_str(), O_WRONLY | O_CREAT | O_LARGEFILE | O_CLOEXEC, 0666);
+               if (fd < 0)
+               {
+                       eDebug("[eServiceHDMIRecord] can't open recording file: %m");
+                       m_error = errOpenRecordFile;
+                       m_event((iRecordableService*)this, evRecordFailed);
+                       return errOpenRecordFile;
+               }
+
+               m_thread = new eDVBRecordFileThread();
+               m_target_fd = fd;
+       }
+
+       eDebug("[eServiceHDMIRecord] start recording...");
+
+       if (m_state != stateRecording)
+       {
+               if (m_thread && m_encoder_fd >= 0)
+               {
+                       m_thread->startSaveMetaInformation(m_filename);
+                       m_thread->start(m_encoder_fd, m_target_fd);
+               }
+               m_state = stateRecording;
+       }
+
+       m_error = 0;
+       m_event((iRecordableService*)this, evRecordRunning);
+       return 0;
+}
+
+RESULT eServiceHDMIRecord::stream(ePtr<iStreamableService> &ptr)
+{
+       ptr = NULL;
+       return -1;
+}
+
+RESULT eServiceHDMIRecord::subServices(ePtr<iSubserviceList> &ptr)
+{
+       ptr = NULL;
+       return -1;
+}
+
+RESULT eServiceHDMIRecord::frontendInfo(ePtr<iFrontendInformation> &ptr)
+{
+       ptr = this;
+       return 0;
+}
+
+RESULT eServiceHDMIRecord::connectEvent(const Slot2<void,iRecordableService*,int> &event, ePtr<eConnection> &connection)
+{
+       connection = new eConnection((iRecordableService*)this, m_event.connect(event));
+       return 0;
+}
+
+eAutoInitPtr<eServiceFactoryHDMI> init_eServiceFactoryHDMI(eAutoInitNumbers::service + 1, "eServiceFactoryHDMI");
diff --git a/lib/service/servicehdmi.h b/lib/service/servicehdmi.h
new file mode 100644 (file)
index 0000000..6db9c43
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef __servicehdmi_h
+#define __servicehdmi_h
+
+#include <lib/base/message.h>
+#include <lib/service/iservice.h>
+#include <lib/service/servicedvb.h>
+#include <lib/nav/core.h>
+
+class eStaticServiceHDMIInfo;
+
+class eServiceFactoryHDMI: public iServiceHandler
+{
+       DECLARE_REF(eServiceFactoryHDMI);
+public:
+       eServiceFactoryHDMI();
+       virtual ~eServiceFactoryHDMI();
+       enum { id = 0x2000 };
+
+       RESULT play(const eServiceReference &, ePtr<iPlayableService> &ptr);
+       RESULT record(const eServiceReference &, ePtr<iRecordableService> &ptr);
+       RESULT list(const eServiceReference &, ePtr<iListableService> &ptr);
+       RESULT info(const eServiceReference &, ePtr<iStaticServiceInformation> &ptr);
+       RESULT offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr);
+       void getNavInstance(ePtr<eNavigation> &nav_instance);
+private:
+       ePtr<eStaticServiceHDMIInfo> m_service_info;
+       ePtr<eNavigation> m_nav_instance;
+};
+
+class eStaticServiceHDMIInfo: public iStaticServiceInformation
+{
+       DECLARE_REF(eStaticServiceHDMIInfo);
+       friend class eServiceFactoryHDMI;
+       eStaticServiceHDMIInfo();
+public:
+       RESULT getName(const eServiceReference &ref, std::string &name);
+       int getLength(const eServiceReference &ref);
+       int getInfo(const eServiceReference &ref, int w);
+       int isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate) { return 1; }
+       long long getFileSize(const eServiceReference &ref);
+};
+
+class eServiceHDMI: public iPlayableService, public iServiceInformation, public Object
+{
+       DECLARE_REF(eServiceHDMI);
+public:
+       virtual ~eServiceHDMI();
+
+       RESULT connectEvent(const Slot2<void, iPlayableService*, int> &event, ePtr<eConnection> &connection);
+       RESULT start();
+       RESULT stop();
+       RESULT setTarget(int target);
+
+       RESULT pause(ePtr<iPauseableService> &ptr) { ptr = 0; return -1; }
+       RESULT seek(ePtr<iSeekableService> &ptr) { ptr = 0; return -1; }
+       RESULT audioTracks(ePtr<iAudioTrackSelection> &ptr) { ptr = 0; return -1; }
+       RESULT audioChannel(ePtr<iAudioChannelSelection> &ptr) { ptr = 0; return -1; }
+       RESULT subtitle(ePtr<iSubtitleOutput> &ptr) { ptr = 0; return -1; }
+       RESULT audioDelay(ePtr<iAudioDelay> &ptr) { ptr = 0; return -1; }
+
+       RESULT frontendInfo(ePtr<iFrontendInformation> &ptr) { ptr = 0; return -1; }
+       RESULT subServices(ePtr<iSubserviceList> &ptr) { ptr = 0; return -1; }
+       RESULT timeshift(ePtr<iTimeshiftService> &ptr) { ptr = 0; return -1; }
+       RESULT cueSheet(ePtr<iCueSheet> &ptr) { ptr = 0; return -1; }
+
+       RESULT rdsDecoder(ePtr<iRdsDecoder> &ptr) { ptr = 0; return -1; }
+       RESULT keys(ePtr<iServiceKeys> &ptr) { ptr = 0; return -1; }
+       RESULT stream(ePtr<iStreamableService> &ptr) { ptr = 0; return -1; }
+       RESULT streamed(ePtr<iStreamedService> &ptr) { ptr = 0; return -1; }
+
+       RESULT info(ePtr<iServiceInformation>&);
+
+       RESULT getName(std::string &name);
+       int getInfo(int w);
+       std::string getInfoString(int w);
+       PyObject *getInfoObject(int w);
+
+private:
+       friend class eServiceFactoryHDMI;
+       eServiceHDMI(eServiceReference ref);
+       Signal2<void,iPlayableService*, int> m_event;
+       eServiceReference m_ref;
+       int m_decoder_index;
+       ePtr<iTSMPEGDecoder> m_decoder;
+};
+
+class eServiceHDMIRecord: public eDVBServiceBase, public iRecordableService, public Object
+{
+       DECLARE_REF(eServiceHDMIRecord);
+public:
+       eServiceHDMIRecord(const eServiceReference &ref, ePtr<eNavigation> &nav_instance);
+       RESULT connectEvent(const Slot2<void,iRecordableService*,int> &event, ePtr<eConnection> &connection);
+       RESULT prepare(const char *filename, time_t begTime, time_t endTime, int eit_event_id, const char *name, const char *descr, const char *tags);
+       RESULT prepareStreaming();
+       RESULT start(bool simulate=false);
+       RESULT stop();
+       RESULT getError(int &error) { error = m_error; return 0; }
+       RESULT frontendInfo(ePtr<iFrontendInformation> &ptr);
+       RESULT stream(ePtr<iStreamableService> &ptr);
+       RESULT subServices(ePtr<iSubserviceList> &ptr);
+
+private:
+       enum { stateIdle, statePrepared, stateRecording };
+       bool m_simulate;
+       int m_state;
+       eDVBRecordFileThread *m_thread;
+       eServiceReference m_ref;
+
+       int m_recording, m_error;
+       std::string m_filename;
+
+       int m_target_fd;
+       int m_encoder_fd;
+       int m_decoder;
+       ePtr<eNavigation> m_nav_instance;
+
+       int doPrepare();
+       int doRecord();
+
+       /* events */
+       Signal2<void,iRecordableService*,int> m_event;
+
+       /* recorder events */
+       void recordEvent(int event);
+};
+
+#endif
diff --git a/skin.py b/skin.py
index a0190f1..f763dd0 100755 (executable)
--- a/skin.py
+++ b/skin.py
@@ -15,6 +15,13 @@ from Tools.LoadPixmap import LoadPixmap
 
 colorNames = dict()
 
+fonts = {
+       "Body": ("Regular", 18, 22, 16),
+       "ChoiceList": ("Regular", 20, 24, 18),
+}
+
+parameters = {}
+
 def dump(x, i=0):
        print " " * i + str(x)
        try:
@@ -70,6 +77,31 @@ profile("LoadSkinDefault")
 loadSkin('skin_default.xml')
 profile("LoadSkinDefaultDone")
 
+def parseCoordinate(str, e, size = 0):
+       str = str.strip()
+       if str == "center":
+               val = (e - size)/2
+       else:
+               sl = len(str)
+               l = 1
+
+               if str[0] is 'e':
+                       val = e
+               elif str[0] is 'c':
+                       val = e/2
+               else:
+                       val = 0;
+                       l = 0
+
+               if sl - l > 0:
+                       if str[sl-1] is '%':
+                               val += e * int(str[l:sl-1]) / 100
+                       else:
+                               val += int(str[l:sl])
+       if val < 0:
+               val = 0
+       return val
+
 def evalPos(pos, wsize, ssize, scale):
        if pos == "center":
                pos = (ssize - wsize) / 2
@@ -96,8 +128,13 @@ def parseSize(str, scale):
        x, y = str.split(',')
        return eSize(int(x) * scale[0][0] / scale[0][1], int(y) * scale[1][0] / scale[1][1])
 
-def parseFont(str, scale):
-       name, size = str.split(';')
+def parseFont(s, scale):
+       try:
+               f = fonts[s]
+               name = f[0]
+               size = f[1]
+       except:
+               name, size = s.split(';')
        return gFont(name, int(size) * scale[0][0] / scale[0][1])
 
 def parseColor(str):
@@ -108,18 +145,34 @@ def parseColor(str):
                        raise SkinError("color '%s' must be #aarrggbb or valid named color" % (str))
        return gRGB(int(str[1:], 0x10))
 
-def collectAttributes(skinAttributes, node, skin_path_prefix=None, ignore=[]):
+def collectAttributes(skinAttributes, node, context, skin_path_prefix=None, ignore=[]):
        # walk all attributes
-       for a in node.items():
-               #print a
-               attrib = a[0]
-               value = a[1]
-
-               if attrib in ("pixmap", "pointer", "seek_pointer", "backgroundPixmap", "selectionPixmap"):
-                       value = resolveFilename(SCOPE_SKIN_IMAGE, value, path_prefix=skin_path_prefix)
-
+       size = None
+       pos = None
+       for attrib, value in node.items():
                if attrib not in ignore:
-                       skinAttributes.append((attrib, value.encode("utf-8")))
+                       if attrib in ("pixmap", "pointer", "seek_pointer", "backgroundPixmap", "selectionPixmap"):
+                               value = resolveFilename(SCOPE_SKIN_IMAGE, value, path_prefix=skin_path_prefix)
+
+                       # Bit of a hack this, really. When a window has a flag (e.g. wfNoBorder)
+                       # it needs to be set at least before the size is set, in order for the
+                       # window dimensions to be calculated correctly in all situations.
+                       # If wfNoBorder is applied after the size has been set, the window will fail to clear the title area.
+                       # Similar situation for a scrollbar in a listbox; when the scrollbar setting is applied after
+                       # the size, a scrollbar will not be shown until the selection moves for the first time
+
+                       if attrib == 'size':
+                               size = value.encode("utf-8")
+                       elif attrib == 'position':
+                               pos = value.encode("utf-8")
+                       else:
+                               skinAttributes.append((attrib, value.encode("utf-8")))
+
+       if pos is not None:
+               pos, size = context.parse(pos, size)
+               skinAttributes.append(('position', pos))
+       if size is not None:
+               skinAttributes.append(('size', size))
 
 def loadPixmap(path, desktop):
        cached = False
@@ -133,136 +186,164 @@ def loadPixmap(path, desktop):
                raise SkinError("pixmap file %s not found!" % (path))
        return ptr
 
-def applySingleAttribute(guiObject, desktop, attrib, value, scale = ((1,1),(1,1))):
-       # and set attributes
-       try:
-               if attrib == 'position':
-                       guiObject.move(parsePosition(value, scale, desktop, guiObject.csize()))
-               elif attrib == 'size':
-                       guiObject.resize(parseSize(value, scale))
-               elif attrib == 'animationPaused':
-                       pass
-               elif attrib == 'animationMode':
-                       guiObject.setAnimationMode(
-                               { "disable": 0x00,
-                                       "off": 0x00,
-                                       "offshow": 0x10,
-                                       "offhide": 0x01,
-                                       "onshow": 0x01,
-                                       "onhide": 0x10,
+class AttributeParser:
+       def __init__(self, guiObject, desktop, scale = ((1,1),(1,1))):
+               self.guiObject = guiObject
+               self.desktop = desktop
+               self.scale = scale
+       def applyOne(self, attrib, value):
+               try:
+                       getattr(self, attrib)(value)
+               except AttributeError:
+                       print "[Skin] Attribute not implemented:", attrib, "value:", value
+               except SkinError, ex:
+                       print "[Skin] Error:", ex
+       def applyAll(self, attrs):
+               for attrib, value in attrs:
+                       try:
+                               getattr(self, attrib)(value)
+                       except AttributeError:
+                               print "[Skin] Attribute not implemented:", attrib, "value:", value
+                       except SkinError, ex:
+                               print "[Skin] Error:", ex
+       def position(self, value):
+               if isinstance(value, tuple):
+                       self.guiObject.move(ePoint(*value))
+               else:
+                       self.guiObject.move(parsePosition(value, self.scale, self.desktop, self.guiObject.csize()))
+       def size(self, value):
+               if isinstance(value, tuple):
+                       self.guiObject.resize(eSize(*value))
+               else:
+                       self.guiObject.resize(parseSize(value, self.scale))
+       def animationPaused(self, value):
+               pass
+       def animationPaused(self, value):
+               self.guiObject.setAnimationMode(
+                       { "disable": 0x00,
+                               "off": 0x00,
+                               "offshow": 0x10,
+                               "offhide": 0x01,
+                               "onshow": 0x01,
+                               "onhide": 0x10,
+                       }[value])
+       def title(self, value):
+               self.guiObject.setTitle(_(value))
+       def text(self, value):
+               self.guiObject.setText(_(value))
+       def font(self, value):
+               self.guiObject.setFont(parseFont(value, self.scale))
+       def zPosition(self, value):
+               self.guiObject.setZPosition(int(value))
+       def itemHeight(self, value):
+               self.guiObject.setItemHeight(int(value))
+       def pixmap(self, value):
+               ptr = loadPixmap(value, self.desktop)
+               self.guiObject.setPixmap(ptr)
+       def backgroundPixmap(self, value):
+               ptr = loadPixmap(value, self.desktop)
+               self.guiObject.setBackgroundPicture(ptr)
+       def selectionPixmap(self, value):
+               ptr = loadPixmap(value, self.desktop)
+               self.guiObject.setSelectionPicture(ptr)
+       def itemHeight(self, value):
+               self.guiObject.setItemHeight(int(value))
+       def alphatest(self, value):
+               self.guiObject.setAlphatest(
+                       { "on": 1,
+                         "off": 0,
+                         "blend": 2,
+                       }[value])
+       def scale(self, value):
+               self.guiObject.setScale(1)
+       def orientation(self, value):
+               try:
+                       self.guiObject.setOrientation(*
+                               { "orVertical": (self.guiObject.orVertical, False),
+                                       "orTopToBottom": (self.guiObject.orVertical, False),
+                                       "orBottomToTop": (self.guiObject.orVertical, True),
+                                       "orHorizontal": (self.guiObject.orHorizontal, False),
+                                       "orLeftToRight": (self.guiObject.orHorizontal, False),
+                                       "orRightToLeft": (self.guiObject.orHorizontal, True),
                                }[value])
-               elif attrib == 'title':
-                       guiObject.setTitle(_(value))
-               elif attrib == 'text':
-                       guiObject.setText(_(value))
-               elif attrib == 'font':
-                       guiObject.setFont(parseFont(value, scale))
-               elif attrib == 'zPosition':
-                       guiObject.setZPosition(int(value))
-               elif attrib == 'itemHeight':
-                       guiObject.setItemHeight(int(value))
-               elif attrib in ("pixmap", "backgroundPixmap", "selectionPixmap"):
-                       ptr = loadPixmap(value, desktop) # this should already have been filename-resolved.
-                       if attrib == "pixmap":
-                               guiObject.setPixmap(ptr)
-                       elif attrib == "backgroundPixmap":
-                               guiObject.setBackgroundPicture(ptr)
-                       elif attrib == "selectionPixmap":
-                               guiObject.setSelectionPicture(ptr)
-                       # guiObject.setPixmapFromFile(value)
-               elif attrib == "alphatest": # used by ePixmap
-                       guiObject.setAlphatest(
-                               { "on": 1,
-                                 "off": 0,
-                                 "blend": 2,
+               except KeyError:
+                       print "oprientation must be either orVertical or orHorizontal!"
+       def valign(self, value):
+               try:
+                       self.guiObject.setVAlign(
+                               { "top": self.guiObject.alignTop,
+                                       "center": self.guiObject.alignCenter,
+                                       "bottom": self.guiObject.alignBottom
                                }[value])
-               elif attrib == "scale":
-                       guiObject.setScale(1)
-               elif attrib == "orientation": # used by eSlider
-                       try:
-                               guiObject.setOrientation(*
-                                       { "orVertical": (guiObject.orVertical, False),
-                                               "orTopToBottom": (guiObject.orVertical, False),
-                                               "orBottomToTop": (guiObject.orVertical, True),
-                                               "orHorizontal": (guiObject.orHorizontal, False),
-                                               "orLeftToRight": (guiObject.orHorizontal, False),
-                                               "orRightToLeft": (guiObject.orHorizontal, True),
-                                       }[value])
-                       except KeyError:
-                               print "oprientation must be either orVertical or orHorizontal!"
-               elif attrib == "valign":
-                       try:
-                               guiObject.setVAlign(
-                                       { "top": guiObject.alignTop,
-                                               "center": guiObject.alignCenter,
-                                               "bottom": guiObject.alignBottom
-                                       }[value])
-                       except KeyError:
-                               print "valign must be either top, center or bottom!"
-               elif attrib == "halign":
+               except KeyError:
+                       print "valign must be either top, center or bottom!"
+       def halign(self, value):
+               try:
+                       self.guiObject.setHAlign(
+                               { "left": self.guiObject.alignLeft,
+                                       "center": self.guiObject.alignCenter,
+                                       "right": self.guiObject.alignRight,
+                                       "block": self.guiObject.alignBlock
+                               }[value])
+               except KeyError:
+                       print "halign must be either left, center, right or block!"
+       def flags(self, value):
+               flags = value.split(',')
+               for f in flags:
                        try:
-                               guiObject.setHAlign(
-                                       { "left": guiObject.alignLeft,
-                                               "center": guiObject.alignCenter,
-                                               "right": guiObject.alignRight,
-                                               "block": guiObject.alignBlock
-                                       }[value])
+                               fv = eWindow.__dict__[f]
+                               self.guiObject.setFlag(fv)
                        except KeyError:
-                               print "halign must be either left, center, right or block!"
-               elif attrib == "flags":
-                       flags = value.split(',')
-                       for f in flags:
-                               try:
-                                       fv = eWindow.__dict__[f]
-                                       guiObject.setFlag(fv)
-                               except KeyError:
-                                       print "illegal flag %s!" % f
-               elif attrib == "backgroundColor":
-                       guiObject.setBackgroundColor(parseColor(value))
-               elif attrib == "backgroundColorSelected":
-                       guiObject.setBackgroundColorSelected(parseColor(value))
-               elif attrib == "foregroundColor":
-                       guiObject.setForegroundColor(parseColor(value))
-               elif attrib == "foregroundColorSelected":
-                       guiObject.setForegroundColorSelected(parseColor(value))
-               elif attrib == "shadowColor":
-                       guiObject.setShadowColor(parseColor(value))
-               elif attrib == "selectionDisabled":
-                       guiObject.setSelectionEnable(0)
-               elif attrib == "transparent":
-                       guiObject.setTransparent(int(value))
-               elif attrib == "borderColor":
-                       guiObject.setBorderColor(parseColor(value))
-               elif attrib == "borderWidth":
-                       guiObject.setBorderWidth(int(value))
-               elif attrib == "scrollbarMode":
-                       guiObject.setScrollbarMode(
-                               { "showOnDemand": guiObject.showOnDemand,
-                                       "showAlways": guiObject.showAlways,
-                                       "showNever": guiObject.showNever
-                               }[value])
-               elif attrib == "enableWrapAround":
-                       guiObject.setWrapAround(True)
-               elif attrib == "pointer" or attrib == "seek_pointer":
-                       (name, pos) = value.split(':')
-                       pos = parsePosition(pos, scale)
-                       ptr = loadPixmap(name, desktop)
-                       guiObject.setPointer({"pointer": 0, "seek_pointer": 1}[attrib], ptr, pos)
-               elif attrib == 'shadowOffset':
-                       guiObject.setShadowOffset(parsePosition(value, scale))
-               elif attrib == 'noWrap':
-                       guiObject.setNoWrap(1)
-               elif attrib == 'id':
-                       pass
-               else:
-                       raise SkinError("unsupported attribute " + attrib + "=" + value)
-       except int:
-# AttributeError:
-               print "widget %s (%s) doesn't support attribute %s!" % ("", guiObject.__class__.__name__, attrib)
+                               print "illegal flag %s!" % f
+       def backgroundColor(self, value):
+               self.guiObject.setBackgroundColor(parseColor(value))
+       def backgroundColorSelected(self, value):
+               self.guiObject.setBackgroundColorSelected(parseColor(value))
+       def foregroundColor(self, value):
+               self.guiObject.setForegroundColor(parseColor(value))
+       def foregroundColorSelected(self, value):
+               self.guiObject.setForegroundColorSelected(parseColor(value))
+       def shadowColor(self, value):
+               self.guiObject.setShadowColor(parseColor(value))
+       def selectionDisabled(self, value):
+               self.guiObject.setSelectionEnable(0)
+       def transparent(self, value):
+               self.guiObject.setTransparent(int(value))
+       def borderColor(self, value):
+               self.guiObject.setBorderColor(parseColor(value))
+       def borderWidth(self, value):
+               self.guiObject.setBorderWidth(int(value))
+       def scrollbarMode(self, value):
+               self.guiObject.setScrollbarMode(
+                       { "showOnDemand": self.guiObject.showOnDemand,
+                               "showAlways": self.guiObject.showAlways,
+                               "showNever": self.guiObject.showNever
+                       }[value])
+       def enableWrapAround(self, value):
+               self.guiObject.setWrapAround(True)
+       def pointer(self, value):
+               (name, pos) = value.split(':')
+               pos = parsePosition(pos, self.scale)
+               ptr = loadPixmap(name, self.desktop)
+               self.guiObject.setPointer(0, ptr, pos)
+       def seek_pointer(self, value):
+               (name, pos) = value.split(':')
+               pos = parsePosition(pos, self.scale)
+               ptr = loadPixmap(name, self.desktop)
+               self.guiObject.setPointer(1, ptr, pos)
+       def shadowOffset(self, value):
+               self.guiObject.setShadowOffset(parsePosition(value, self.scale))
+       def noWrap(self, value):
+               self.guiObject.setNoWrap(1)
+       def id(self, value):
+               pass
+
+def applySingleAttribute(guiObject, desktop, attrib, value, scale = ((1,1),(1,1))):
+       # Someone still using applySingleAttribute?
+       AttributeParser(guiObject, desktop, scale).applyOne(attrib, value)
 
 def applyAllAttributes(guiObject, desktop, attributes, scale):
-       for (attrib, value) in attributes:
-               applySingleAttribute(guiObject, desktop, attrib, value, scale)
+       AttributeParser(guiObject, desktop, scale).applyAll(attributes)
 
 def loadSingleSkinData(desktop, skin, path_prefix):
        """loads skin data like colors, windowstyle etc."""
@@ -332,6 +413,29 @@ def loadSingleSkinData(desktop, skin, path_prefix):
                        addFont(resolved_font, name, scale, is_replacement)
                        #print "Font: ", resolved_font, name, scale, is_replacement
 
+               for alias in c.findall("alias"):
+                       get = alias.attrib.get
+                       try:
+                               name = get("name")
+                               font = get("font")
+                               size = int(get("size"))
+                               height = int(get("height", size)) # to be calculated some day
+                               width = int(get("width", size))
+                               global fonts
+                               fonts[name] = (font, size, height, width)
+                       except Exception, ex:
+                               print "[SKIN] bad font alias", ex
+
+       for c in skin.findall("parameters"):
+               for parameter in c.findall("parameter"):
+                       get = parameter.attrib.get
+                       try:
+                               name = get("name")
+                               value = get("value")
+                               parameters[name] = map(int, value.split(","))
+                       except Exception, ex:
+                               print "[SKIN] bad parameter", ex
+
        for c in skin.findall("subtitles"):
                from enigma import eWidget, eSubtitleWidget
                scale = ((1,1),(1,1))
@@ -402,27 +506,148 @@ def loadSingleSkinData(desktop, skin, path_prefix):
                x = eWindowStyleManager.getInstance()
                x.setStyle(id, style)
 
+display_skin_id = 1
+dom_screens = {}
+
 def loadSkinData(desktop):
+       global dom_skins, dom_screens, display_skin_id
        skins = dom_skins[:]
        skins.reverse()
        for (path, dom_skin) in skins:
                loadSingleSkinData(desktop, dom_skin, path)
 
+               for elem in dom_skin:
+                       if elem.tag == 'screen':
+                               name = elem.attrib.get('name', None)
+                               if name:
+                                       sid = elem.attrib.get('id', None)
+                                       if sid and (int(sid) != display_skin_id):
+                                               # not for this display
+                                               elem.clear()
+                                               continue
+                                       if name in dom_screens:
+                                               # Kill old versions, save memory
+                                               dom_screens[name][0].clear()
+                                       dom_screens[name] = (elem, path)
+                               else:
+                                       # without name, it's useless!
+                                       elem.clear()
+                       else:
+                               # non-screen element, no need for it any longer
+                               elem.clear()
+       # no longer needed, we know where the screens are now.
+       del dom_skins
+
 def lookupScreen(name, style_id):
-       for (path, skin) in dom_skins:
-               # first, find the corresponding screen element
-               for x in skin.findall("screen"):
-                       if x.attrib.get('name', '') == name:
-                               screen_style_id = x.attrib.get('id', '-1')
-                               if screen_style_id == '-1' and name.find('ummary') > 0:
-                                       screen_style_id = '1'
-                               if (style_id != 2 and int(screen_style_id) == -1) or int(screen_style_id) == style_id:
-                                       return x, path
+       if dom_screens.has_key(name):
+               elem, path = dom_screens[name]
+               screen_style_id = elem.attrib.get('id', '-1')
+               if screen_style_id == '-1' and name.find('ummary') > 0:
+                       screen_style_id = '1'
+               if (style_id != 2 and int(screen_style_id) == -1) or int(screen_style_id) == style_id:
+                       return elem, path
+
        return None, None
 
 class additionalWidget:
        pass
 
+# Class that makes a tuple look like something else. Some plugins just assume
+# that size is a string and try to parse it. This class makes that work.
+class SizeTuple(tuple):
+       def split(self, *args):
+               return (str(self[0]), str(self[1]))
+       def strip(self, *args):
+               return '%s,%s' % self
+       def __str__(self):
+               return '%s,%s' % self
+
+class SkinContext:
+       def __init__(self, parent=None, pos=None, size=None):
+               if parent is not None:
+                       if pos is not None:
+                               pos, size = parent.parse(pos, size)
+                               self.x, self.y = pos
+                               self.w, self.h = size
+                       else:
+                               self.x = None
+                               self.y = None
+                               self.w = None
+                               self.h = None
+       def __str__(self):
+               return "Context (%s,%s)+(%s,%s) " % (self.x, self.y, self.w, self.h)
+       def parse(self, pos, size):
+               if pos == "fill":
+                       pos = (self.x, self.y)
+                       size = (self.w, self.h)
+                       self.w = 0
+                       self.h = 0
+               elif pos == "bottom":
+                       w,h = size.split(',')
+                       h = int(h)
+                       pos = (self.x, self.y + self.h - h)
+                       size = (self.w, h)
+                       self.h -= h
+               elif pos == "top":
+                       w,h = size.split(',')
+                       h = int(h)
+                       pos = (self.x, self.y)
+                       size = (self.w, h)
+                       self.h -= h
+                       self.y += h
+               elif pos == "left":
+                       w,h = size.split(',')
+                       w = int(w)
+                       pos = (self.x, self.y)
+                       size = (w, self.h)
+                       self.x += w
+                       self.w -= w
+               elif pos == "right":
+                       w,h = size.split(',')
+                       w = int(w)
+                       pos = (self.x + self.w - w, self.y)
+                       size = (w, self.h)
+                       self.w -= w
+               else:
+                       size = size.split(',')
+                       size = (parseCoordinate(size[0], self.w), parseCoordinate(size[1], self.h)) 
+                       pos = pos.split(',')
+                       pos = (self.x + parseCoordinate(pos[0], self.w, size[0]), self.y + parseCoordinate(pos[1], self.h, size[1]))            
+               return (SizeTuple(pos), SizeTuple(size))
+
+class SkinContextStack(SkinContext):
+       # A context that stacks things instead of aligning them
+       def parse(self, pos, size):
+               if pos == "fill":
+                       pos = (self.x, self.y)
+                       size = (self.w, self.h)
+               elif pos == "bottom":
+                       w,h = size.split(',')
+                       h = int(h)
+                       pos = (self.x, self.y + self.h - h)
+                       size = (self.w, h)
+               elif pos == "top":
+                       w,h = size.split(',')
+                       h = int(h)
+                       pos = (self.x, self.y)
+                       size = (self.w, h)
+               elif pos == "left":
+                       w,h = size.split(',')
+                       w = int(w)
+                       pos = (self.x, self.y)
+                       size = (w, self.h)
+               elif pos == "right":
+                       w,h = size.split(',')
+                       w = int(w)
+                       pos = (self.x + self.w - w, self.y)
+                       size = (w, self.h)
+               else:
+                       size = size.split(',')
+                       size = (parseCoordinate(size[0], self.w), parseCoordinate(size[1], self.h))
+                       pos = pos.split(',')
+                       pos = (self.x + parseCoordinate(pos[0], self.w, size[0]), self.y + parseCoordinate(pos[1], self.h, size[1]))
+               return (SizeTuple(pos), SizeTuple(size))
+
 def readSkin(screen, skin, names, desktop):
        if not isinstance(names, list):
                names = [names]
@@ -466,15 +691,30 @@ def readSkin(screen, skin, names, desktop):
 
        skin_path_prefix = getattr(screen, "skin_path", path)
 
-       collectAttributes(screen.skinAttributes, myscreen, skin_path_prefix, ignore=["name"])
+#      collectAttributes(screen.skinAttributes, myscreen, skin_path_prefix, ignore=["name"])
+
+       context = SkinContext()
+       s = desktop.size()
+       context.x = 0
+       context.y = 0
+       context.w = s.width()
+       context.h = s.height()
+       del s
+       collectAttributes(screen.skinAttributes, myscreen, context, skin_path_prefix, ignore=("name",))
+       context = SkinContext(context, myscreen.attrib.get('position'), myscreen.attrib.get('size'))
+
+#
 
        screen.additionalWidgets = [ ]
        screen.renderer = [ ]
 
        visited_components = set()
 
-       # now walk all widgets
-       for widget in myscreen.findall("widget"):
+       # now walk all widgets and stuff
+       def process_none(widget, context):
+               pass
+
+       def process_widget(widget, context):
                get_attr = widget.attrib.get
                # ok, we either have 1:1-mapped widgets ('old style'), or 1:n-mapped
                # widgets (source->renderer).
@@ -484,7 +724,7 @@ def readSkin(screen, skin, names, desktop):
 
                if wname is None and wsource is None:
                        print "widget has no name and no source!"
-                       continue
+                       return
 
                if wname:
                        #print "Widget name=", wname
@@ -500,7 +740,7 @@ def readSkin(screen, skin, names, desktop):
 #                      assert screen[wname] is not Source
 
                        # and collect attributes for this
-                       collectAttributes(attributes, widget, skin_path_prefix, ignore=['name'])
+                       collectAttributes(attributes, widget, context, skin_path_prefix, ignore=['name'])
                elif wsource:
                        # get corresponding source
                        #print "Widget source=", wsource
@@ -575,55 +815,98 @@ def readSkin(screen, skin, names, desktop):
 
                        renderer.connect(source) # connect to source
                        attributes = renderer.skinAttributes = [ ]
-                       collectAttributes(attributes, widget, skin_path_prefix, ignore=['render', 'source'])
+                       collectAttributes(attributes, widget, context, skin_path_prefix, ignore=['render', 'source'])
 
                        screen.renderer.append(renderer)
 
-       from Components.GUIComponent import GUIComponent
-       nonvisited_components = [x for x in set(screen.keys()) - visited_components if isinstance(x, GUIComponent)]
-       assert not nonvisited_components, "the following components in %s don't have a skin entry: %s" % (name, ', '.join(nonvisited_components))
+       def process_applet(widget, context):
+               try:
+                       codeText = widget.text.strip()
+               except:
+                       codeText = ""
 
-       # now walk additional objects
-       for widget in myscreen.getchildren():
-               w_tag = widget.tag
+               #print "Found code:"
+               #print codeText
+               widgetType = widget.attrib.get('type')
 
-               if w_tag == "widget":
-                       continue
+               code = compile(codeText, "skin applet", "exec")
 
-               if w_tag == "applet":
-                       try:
-                               codeText = widget.text.strip()
-                       except:
-                               codeText = ""
+               if widgetType == "onLayoutFinish":
+                       screen.onLayoutFinish.append(code)
+                       #print "onLayoutFinish = ", codeText
+               else:
+                       raise SkinError("applet type '%s' unknown!" % widgetType)
+                       #print "applet type '%s' unknown!" % type
+
+       def process_elabel(widget, context):
+               w = additionalWidget()
+               w.widget = eLabel
+               w.skinAttributes = [ ]
+               collectAttributes(w.skinAttributes, widget, context, skin_path_prefix, ignore=['name'])
+               screen.additionalWidgets.append(w)
+
+       def process_epixmap(widget, context):
+               w = additionalWidget()
+               w.widget = ePixmap
+               w.skinAttributes = [ ]
+               collectAttributes(w.skinAttributes, widget, context, skin_path_prefix, ignore=['name'])
+               screen.additionalWidgets.append(w)
 
-                       #print "Found code:"
-                       #print codeText
-                       widgetType = widget.attrib.get('type')
+       def process_screen(widget, context):
+               for w in widget.findall("widget"):
+                       process_widget(w, context)
+       
+               for w in widget.getchildren():
+                       if w.tag == "widget":
+                               continue
 
-                       code = compile(codeText, "skin applet", "exec")
+                       p = processors.get(w.tag, process_none)
+                       p(w, context)
 
-                       if widgetType == "onLayoutFinish":
-                               screen.onLayoutFinish.append(code)
-                               #print "onLayoutFinish = ", codeText
+       def process_panel(widget, context):
+               n = widget.attrib.get('name')
+               if n:
+                       try:
+                               s = dom_screens.get(n, None)
+                       except KeyError:
+                               print "[SKIN] Unable to find screen '%s' referred in screen '%s'" % (n, name)
                        else:
-                               raise SkinError("applet type '%s' unknown!" % widgetType)
-                               #print "applet type '%s' unknown!" % type
+                               process_screen(s[0], context)
+
+               layout = widget.attrib.get('layout')
+               if layout == 'stack':
+                       cc = SkinContextStack
+               else:
+                       cc = SkinContext
+               try:
+                       c = cc(context, widget.attrib.get('position'), widget.attrib.get('size'))
+               except Exception, ex:
+                       raise SkinError("Failed to create skincontext (%s,%s) in %s: %s" % (widget.attrib.get('position'), widget.attrib.get('size'), context, ex) )
 
-                       continue
+               process_screen(widget, c)
 
-               w = additionalWidget()
+       processors = {
+               None: process_none,
+               "widget": process_widget,
+               "applet": process_applet,
+               "eLabel": process_elabel,
+               "ePixmap": process_epixmap,
+               "panel": process_panel
+       }
 
-               if w_tag == "eLabel":
-                       w.widget = eLabel
-               elif w_tag == "ePixmap":
-                       w.widget = ePixmap
-               else:
-                       raise SkinError("unsupported stuff : %s" % w_tag)
-                       #print "unsupported stuff : %s" % widget.tag
+       try:
+               context.x = 0 # reset offsets, all components are relative to screen
+               context.y = 0 # coordinates.
+               process_screen(myscreen, context)
+       except SkinError, e:
+                       print "[Skin] SKIN ERROR:", e
 
-               w.skinAttributes = [ ]
-               collectAttributes(w.skinAttributes, widget, skin_path_prefix, ignore=['name'])
+       from Components.GUIComponent import GUIComponent
+       nonvisited_components = [x for x in set(screen.keys()) - visited_components if isinstance(x, GUIComponent)]
+       assert not nonvisited_components, "the following components in %s don't have a skin entry: %s" % (name, ', '.join(nonvisited_components))
+       # This may look pointless, but it unbinds 'screen' from the nested scope. A better
+       # solution is to avoid the nested scope above and use the context object to pass
+       # things around.
+       screen = None
+       visited_components = None
 
-               # applyAttributes(guiObject, widget, desktop)
-               # guiObject.thisown = 0
-               screen.additionalWidgets.append(w)