summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorhschang <chang@dev3>2017-08-21 07:18:36 (GMT)
committerhschang <chang@dev3>2017-08-21 07:18:36 (GMT)
commit7963a66b2debe9cf6ae566cb88511fdfdc9dc216 (patch)
tree8ac4bb2338a409e8e62f71e5a4ceb5d94fba3b5a /lib
parentdd4c8249ef0b08234b6239da9bef26ed7e33ac78 (diff)
Add QuadPiP plugin.
Diffstat (limited to 'lib')
-rw-r--r--lib/dvb/decoder.cpp48
-rw-r--r--lib/gui/evideo.cpp27
-rw-r--r--lib/gui/evideo.h2
-rw-r--r--lib/python/Components/ServiceList.py4
-rw-r--r--lib/python/Components/SystemInfo.py2
-rw-r--r--lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h2
-rwxr-xr-xlib/python/Plugins/Extensions/Makefile.am2
-rw-r--r--lib/python/Plugins/Extensions/QuadPiP/Makefile.am9
-rw-r--r--lib/python/Plugins/Extensions/QuadPiP/__init__.py2
-rw-r--r--lib/python/Plugins/Extensions/QuadPiP/keymap.xml23
-rw-r--r--lib/python/Plugins/Extensions/QuadPiP/meta/Makefile.am3
-rw-r--r--lib/python/Plugins/Extensions/QuadPiP/meta/plugin_quadpip.xml17
-rw-r--r--lib/python/Plugins/Extensions/QuadPiP/plugin.py31
-rw-r--r--lib/python/Plugins/Extensions/QuadPiP/qpip.py1008
-rwxr-xr-xlib/python/Screens/Makefile.am2
-rw-r--r--lib/python/Screens/QuadPiP.py63
-rw-r--r--lib/service/iservice.h1
-rwxr-xr-xlib/service/servicedvb.cpp28
-rw-r--r--lib/service/servicedvb.h4
-rw-r--r--lib/service/servicehdmi.h2
-rw-r--r--lib/service/servicemp3.h2
21 files changed, 1266 insertions, 16 deletions
diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp
index 2c8044b..2091114 100644
--- a/lib/dvb/decoder.cpp
+++ b/lib/dvb/decoder.cpp
@@ -186,7 +186,21 @@ int eDVBAudio::startPid(int pid, int type)
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 */
+ switch (m_dev)
+ {
+ case 0:
+ pes.pes_type = DMX_PES_AUDIO0;
+ break;
+ case 1:
+ pes.pes_type = DMX_PES_AUDIO1;
+ break;
+ case 2:
+ pes.pes_type = DMX_PES_AUDIO2;
+ break;
+ case 3:
+ pes.pes_type = DMX_PES_AUDIO3;
+ break;
+ }
pes.flags = 0;
eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - audio - ", pid);
if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
@@ -500,7 +514,21 @@ int eDVBVideo::startPid(int pid, int type)
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 */
+ switch (m_dev)
+ {
+ case 0:
+ pes.pes_type = DMX_PES_VIDEO0;
+ break;
+ case 1:
+ pes.pes_type = DMX_PES_VIDEO1;
+ break;
+ case 2:
+ pes.pes_type = DMX_PES_VIDEO2;
+ break;
+ case 3:
+ pes.pes_type = DMX_PES_VIDEO3;
+ break;
+ }
pes.flags = 0;
eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - video - ", pid);
if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
@@ -829,7 +857,21 @@ int eDVBPCR::startPid(int pid)
pes.pid = pid;
pes.input = DMX_IN_FRONTEND;
pes.output = DMX_OUT_DECODER;
- pes.pes_type = m_dev ? DMX_PES_PCR1 : DMX_PES_PCR0; /* FIXME */
+ switch (m_dev)
+ {
+ case 0:
+ pes.pes_type = DMX_PES_PCR0;
+ break;
+ case 1:
+ pes.pes_type = DMX_PES_PCR1;
+ break;
+ case 2:
+ pes.pes_type = DMX_PES_PCR2;
+ break;
+ case 3:
+ pes.pes_type = DMX_PES_PCR3;
+ break;
+ }
pes.flags = 0;
eDebugNoNewLine("DMX_SET_PES_FILTER(0x%02x) - pcr - ", pid);
if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0)
diff --git a/lib/gui/evideo.cpp b/lib/gui/evideo.cpp
index 745571d..f5876e9 100644
--- a/lib/gui/evideo.cpp
+++ b/lib/gui/evideo.cpp
@@ -30,7 +30,7 @@ void setFullsize()
}
eVideoWidget::eVideoWidget(eWidget *parent)
- :eLabel(parent), m_fb_size(720, 576), m_state(0), m_decoder(1)
+ :eLabel(parent), m_fb_size(720, 576), m_state(0), m_decoder(1), m_adjust_position(true)
{
if (!fullsizeTimer)
{
@@ -118,14 +118,17 @@ void eVideoWidget::updatePosition(int disable)
int width = pos.width() * 720 / m_fb_size.width();
int height = pos.height() * 576 / m_fb_size.height();
- int tmp = left - (width * 4) / 100;
- left = tmp < 0 ? 0 : tmp;
- tmp = top - (height * 4) / 100;
- top = tmp < 0 ? 0 : tmp;
- tmp = (width * 108) / 100;
- width = left + tmp > 720 ? 720 - left : tmp;
- tmp = (height * 108) / 100;
- height = top + tmp > 576 ? 576 - top : tmp;
+ if (m_adjust_position)
+ {
+ int tmp = left - (width * 4) / 100;
+ left = tmp < 0 ? 0 : tmp;
+ tmp = top - (height * 4) / 100;
+ top = tmp < 0 ? 0 : tmp;
+ tmp = (width * 108) / 100;
+ width = left + tmp > 720 ? 720 - left : tmp;
+ tmp = (height * 108) / 100;
+ height = top + tmp > 576 ? 576 - top : tmp;
+ }
// eDebug("picture recalced %d %d -> %d %d", left, top, width, height);
@@ -172,3 +175,9 @@ void eVideoWidget::setDecoder(int decoder)
{
m_decoder = decoder;
}
+
+void eVideoWidget::setAdjustPosition(bool value)
+{
+ m_adjust_position = value;
+}
+
diff --git a/lib/gui/evideo.h b/lib/gui/evideo.h
index 2f1b91b..e6ff21d 100644
--- a/lib/gui/evideo.h
+++ b/lib/gui/evideo.h
@@ -9,11 +9,13 @@ class eVideoWidget: public eLabel
int m_state;
eRect m_user_rect;
int m_decoder;
+ bool m_adjust_position;
public:
eVideoWidget(eWidget *parent);
~eVideoWidget();
void setDecoder(int target);
void setFBSize(eSize size);
+ void setAdjustPosition(bool value);
protected:
int event(int event, void *data=0, void *data2=0);
void updatePosition(int disable = 0);
diff --git a/lib/python/Components/ServiceList.py b/lib/python/Components/ServiceList.py
index 6972d91..f99c7f0 100644
--- a/lib/python/Components/ServiceList.py
+++ b/lib/python/Components/ServiceList.py
@@ -265,3 +265,7 @@ class ServiceList(HTMLComponent, GUIComponent):
self.l.setElementPosition(self.l.celServiceName, eRect(60, 0, self.instance.size().width()-60, self.ItemHeight))
self.l.setElementFont(self.l.celServiceInfo, self.ServiceInfoFont)
+ def selectionEnabled(self, enabled):
+ if self.instance is not None:
+ self.instance.setSelectionEnable(enabled)
+
diff --git a/lib/python/Components/SystemInfo.py b/lib/python/Components/SystemInfo.py
index 6fcab1d..a1f0d6f 100644
--- a/lib/python/Components/SystemInfo.py
+++ b/lib/python/Components/SystemInfo.py
@@ -32,4 +32,6 @@ SystemInfo["DeepstandbySupport"] = HardwareInfo().get_device_name() != "dm800"
SystemInfo["HdmiInSupport"] = HardwareInfo().get_vu_device_name() == "ultimo4k"
SystemInfo["WOWLSupport"] = HardwareInfo().get_vu_device_name() == "ultimo4k"
SystemInfo["ScrambledPlayback"] = HardwareInfo().get_vu_device_name() in ("solo4k", "ultimo4k")
+SystemInfo["FastChannelChange"] = fileExists("/proc/stb/frontend/fbc/fcc")
+SystemInfo["MiniTV"] = fileExists("/proc/stb/lcd/live_enable")
diff --git a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h
index 80cfcf0..47e02d1 100644
--- a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h
+++ b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.h
@@ -45,6 +45,8 @@ public:
RESULT streamed(ePtr<iStreamedService> &ptr) { ptr = 0; return -1; }
RESULT cueSheet(ePtr<iCueSheet> &ptr);
+ void setQpipMode(bool value, bool audio) { }
+
// iPlayableService
RESULT connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection);
RESULT start();
diff --git a/lib/python/Plugins/Extensions/Makefile.am b/lib/python/Plugins/Extensions/Makefile.am
index d94b791..32b7e14 100755
--- a/lib/python/Plugins/Extensions/Makefile.am
+++ b/lib/python/Plugins/Extensions/Makefile.am
@@ -1,7 +1,7 @@
installdir = $(pkglibdir)/python/Plugins/Extensions
SUBDIRS = TuxboxPlugins CutListEditor PicturePlayer MediaScanner MediaPlayer GraphMultiEPG SocketMMI DVDBurn Modem WebBrowser \
- StreamTV DLNABrowser DLNAServer HbbTV BackupSuiteUSB BackupSuiteHDD SatipClient MiniTV
+ StreamTV DLNABrowser DLNAServer HbbTV BackupSuiteUSB BackupSuiteHDD SatipClient MiniTV QuadPiP
if HAVE_LIBDDVD
SUBDIRS += DVDPlayer
diff --git a/lib/python/Plugins/Extensions/QuadPiP/Makefile.am b/lib/python/Plugins/Extensions/QuadPiP/Makefile.am
new file mode 100644
index 0000000..9bd3320
--- /dev/null
+++ b/lib/python/Plugins/Extensions/QuadPiP/Makefile.am
@@ -0,0 +1,9 @@
+installdir = $(pkglibdir)/python/Plugins/Extensions/QuadPiP
+
+SUBDIRS = meta
+
+install_PYTHON = \
+ __init__.py \
+ plugin.py \
+ qpip.py \
+ keymap.xml
diff --git a/lib/python/Plugins/Extensions/QuadPiP/__init__.py b/lib/python/Plugins/Extensions/QuadPiP/__init__.py
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/lib/python/Plugins/Extensions/QuadPiP/__init__.py
@@ -0,0 +1,2 @@
+
+
diff --git a/lib/python/Plugins/Extensions/QuadPiP/keymap.xml b/lib/python/Plugins/Extensions/QuadPiP/keymap.xml
new file mode 100644
index 0000000..4361718
--- /dev/null
+++ b/lib/python/Plugins/Extensions/QuadPiP/keymap.xml
@@ -0,0 +1,23 @@
+<keymap>
+ <map context="QuadPipSetupActions">
+ <key id="KEY_OK" mapto="ok" flags="m" />
+ <key id="KEY_EXIT" mapto="cancel" flags="m" />
+ <key id="KEY_UP" mapto="up" flags="m" />
+ <key id="KEY_DOWN" mapto="down" flags="m" />
+ <key id="KEY_LEFT" mapto="left" flags="m" />
+ <key id="KEY_RIGHT" mapto="right" flags="m" />
+ <key id="KEY_RED" mapto="red" flags="m" />
+ <key id="KEY_GREEN" mapto="green" flags="m" />
+ <key id="KEY_YELLOW" mapto="yellow" flags="m" />
+ <key id="KEY_BLUE" mapto="blue" flags="m" />
+ <key id="KEY_MENU" mapto="menu" flags="m" />
+ <key id="KEY_CHANNELUP" mapto="channelup" flags="m" />
+ <key id="KEY_CHANNELDOWN" mapto="channeldown" flags="m" />
+ <key id="KEY_PREVIOUS" mapto="channelPrev" flags="m" />
+ <key id="KEY_NEXT" mapto="channelNext" flags="m" />
+ </map>
+ <map context="QuadPipChannelEditActions">
+ <key id="KEY_INFO" mapto="toggleList" flags="m" />
+ <key id="KEY_VIDEO" mapto="editName" flags="m" />
+ </map>
+</keymap>
diff --git a/lib/python/Plugins/Extensions/QuadPiP/meta/Makefile.am b/lib/python/Plugins/Extensions/QuadPiP/meta/Makefile.am
new file mode 100644
index 0000000..b29c526
--- /dev/null
+++ b/lib/python/Plugins/Extensions/QuadPiP/meta/Makefile.am
@@ -0,0 +1,3 @@
+installdir = $(datadir)/meta
+
+dist_install_DATA = plugin_quadpip.xml
diff --git a/lib/python/Plugins/Extensions/QuadPiP/meta/plugin_quadpip.xml b/lib/python/Plugins/Extensions/QuadPiP/meta/plugin_quadpip.xml
new file mode 100644
index 0000000..cec9642
--- /dev/null
+++ b/lib/python/Plugins/Extensions/QuadPiP/meta/plugin_quadpip.xml
@@ -0,0 +1,17 @@
+<default>
+ <prerequisites>
+ <tag type="Display" />
+ <tag type="System" />
+ </prerequisites>
+ <info>
+ <author>hschang</author>
+ <name>Quad PiP</name>
+ <packagename>enigma2-plugin-extensions-quadpip</packagename>
+ <shortdescription>Support Quad PiP of your VU+</shortdescription>
+ <description>Support Quad PiP of your VU+</description>
+ </info>
+
+ <files type="package"> <!-- without version, without .ipk -->
+ <file type="package" name="enigma2-plugin-extensions-quadpip" />
+ </files>
+</default>
diff --git a/lib/python/Plugins/Extensions/QuadPiP/plugin.py b/lib/python/Plugins/Extensions/QuadPiP/plugin.py
new file mode 100644
index 0000000..928de86
--- /dev/null
+++ b/lib/python/Plugins/Extensions/QuadPiP/plugin.py
@@ -0,0 +1,31 @@
+from Plugins.Plugin import PluginDescriptor
+from Components.PluginComponent import plugins
+from Components.config import config, ConfigSubsection, ConfigSelection
+from enigma import eDBoxLCD
+
+from qpip import QuadPipScreen, setDecoderMode
+
+def main(session, **kwargs):
+ session.open(QuadPipScreen)
+
+def autoStart(reason, **kwargs):
+ if reason == 0:
+ setDecoderMode("normal")
+ elif reason == 1:
+ pass
+
+def Plugins(**kwargs):
+ list = []
+ list.append(
+ PluginDescriptor(name=_("Enable Quad PIP"),
+ description="Quad Picture in Picture",
+ where = [PluginDescriptor.WHERE_EXTENSIONSMENU],
+ fnc = main))
+
+ list.append(
+ PluginDescriptor(
+ where = [PluginDescriptor.WHERE_AUTOSTART],
+ fnc = autoStart))
+
+ return list
+
diff --git a/lib/python/Plugins/Extensions/QuadPiP/qpip.py b/lib/python/Plugins/Extensions/QuadPiP/qpip.py
new file mode 100644
index 0000000..72a4819
--- /dev/null
+++ b/lib/python/Plugins/Extensions/QuadPiP/qpip.py
@@ -0,0 +1,1008 @@
+from Screens.Screen import Screen
+from Components.ConfigList import ConfigListScreen
+from Components.config import config, ConfigSubsection, ConfigSelection, getConfigListEntry
+from Components.ActionMap import ActionMap
+from Components.Pixmap import Pixmap, MovingPixmap
+from Screens.MessageBox import MessageBox
+from Components.Sources.StaticText import StaticText
+from Plugins.Plugin import PluginDescriptor
+from Tools.Directories import fileExists
+from Tools.Directories import resolveFilename, SCOPE_PLUGINS
+
+from Components.Sources.List import List
+from Components.Label import Label
+from Components.ActionMap import HelpableActionMap
+from Components.MenuList import MenuList
+
+from Screens.ChannelSelection import ChannelSelectionBase
+from enigma import eServiceReference
+from enigma import eListboxPythonMultiContent
+from enigma import eTimer
+from ServiceReference import ServiceReference
+from Components.FileList import FileList
+from Components.Button import Button
+from Screens.ChoiceBox import ChoiceBox
+from Screens.QuadPiP import QuadPiP
+
+from Screens.VirtualKeyBoard import VirtualKeyBoard
+from Screens.HelpMenu import HelpableScreen
+
+import pickle
+import os
+
+from Components.config import config, ConfigSubsection, ConfigNumber
+from Components.Slider import Slider
+
+from Components.SystemInfo import SystemInfo
+
+config.plugins.quadpip = ConfigSubsection()
+config.plugins.quadpip.lastchannel = ConfigNumber(default = 1)
+
+ENABLE_QPIP_PROCPATH = "/proc/stb/video/decodermode"
+
+def setDecoderMode(value):
+ if os.access(ENABLE_QPIP_PROCPATH, os.F_OK):
+ fd = open(ENABLE_QPIP_PROCPATH,"w")
+ fd.write(value)
+ fd.close()
+
+ # read to check
+ fd = open(ENABLE_QPIP_PROCPATH,"r")
+ data = fd.read()
+ fd.close()
+
+ return data.strip() == value
+
+class QuadPipChannelEntry:
+ def __init__(self, name, idx, ch1, ch2, ch3, ch4):
+ self.name = name
+ self.idx = idx
+ self.channel = {"1" : ch1, "2" : ch2, "3" : ch1, "4" : ch1,}
+
+ def __str__(self):
+ return "idx : %d, name : %s, ch0 : %s, ch1 : %s, ch2 : %s, ch3 : %s"\
+ % (self.idx, self.name, self.channel.get("1"), self.channel.get("2"), self.channel.get("3"), self.channel.get("4"))
+
+ def __cmp__(self, other):
+ return self.idx - other.idx
+
+ def getName(self):
+ return self.name
+
+ def getIndex(self):
+ return self.idx
+
+ def setChannel(self, idx, chName, sref):
+ if self.channel.has_key(idx):
+ self.channel[idx] = (chName, sref)
+ return True
+
+ return False
+
+ def deleteChannel(self, idx):
+ if self.channel.has_key(idx):
+ self.channel[idx] = None
+ return True
+
+ return False
+
+ def getChannel(self, idx):
+ return self.channel.get(idx, None)
+
+ def getChannelName(self, idx):
+ chName = None
+ ch = self.getChannel(idx)
+ if ch:
+ chName = ch[0]
+
+ if chName is None:
+ chName = " <No Channel>"
+
+ return chName
+
+ def getChannelSref(self, idx):
+ chSref = None
+ ch = self.getChannel(idx)
+ if ch:
+ chSref = ch[1]
+ return chSref
+
+ def setIndex(self, idx):
+ self.idx = idx
+
+ def setName(self, name):
+ self.name = name
+
+class QuadPipChannelData:
+ def __init__(self):
+ self.PipChannelList = []
+ self.pipChannelDataPath = "/etc/enigma2/quadPipChannels.dat"
+ self.dataLoad()
+
+ def dataSave(self):
+ fd = open(self.pipChannelDataPath, "w")
+ pickle.dump(self.PipChannelList, fd)
+ fd.close()
+ #print "[*] dataSave"
+
+ def dataLoad(self):
+ if not os.access(self.pipChannelDataPath, os.R_OK):
+ return
+
+ fd = open(self.pipChannelDataPath, "r")
+ self.PipChannelList = pickle.load(fd)
+ fd.close()
+ #print "[*] dataLoad"
+
+ def getPipChannels(self):
+ return self.PipChannelList
+
+ def length(self):
+ return len(self.PipChannelList)
+
+class QuadPipChannelList(QuadPipChannelData):
+ def __init__(self):
+ QuadPipChannelData.__init__(self)
+ self._curIdx = config.plugins.quadpip.lastchannel.value # starting from 1
+ self.defaultEntryPreName = "Quad PiP channel "
+
+ def saveAll(self):
+ self.dataSave()
+ config.plugins.quadpip.lastchannel.value = self._curIdx
+ config.plugins.quadpip.lastchannel.save()
+
+ def setIdx(self, value):
+ if self._curIdx != value:
+ self._curIdx = value
+ config.plugins.quadpip.lastchannel.value = self._curIdx
+ config.plugins.quadpip.lastchannel.save()
+
+ def getIdx(self):
+ return self._curIdx
+
+ def getCurrentChannel(self):
+ return self.getChannel(self._curIdx)
+
+ def getChannel(self, idx):
+ for ch in self.PipChannelList:
+ if idx == ch.getIndex():
+ return ch
+
+ return None
+
+ def addNewChannel(self, newChannel):
+ self.PipChannelList.append(newChannel)
+
+ def removeChannel(self, _channel):
+ if self.getIdx() == _channel.getIndex():
+ self.setIdx(0) # set invalid index
+
+ self.PipChannelList.remove(_channel)
+
+ def sortPipChannelList(self):
+ self.PipChannelList.sort()
+ newIdx = 1
+ for ch in self.PipChannelList:
+ ch.setIndex(newIdx)
+ chName = ch.getName()
+ if chName.startswith(self.defaultEntryPreName):
+ ch.setName("%s%d" % (self.defaultEntryPreName, ch.getIndex()))
+ newIdx += 1
+
+ def getDefaultPreName(self):
+ return self.defaultEntryPreName
+
+quad_pip_channel_list_instance = QuadPipChannelList()
+
+class CreateQuadPipChannelEntry(ChannelSelectionBase):
+ skin_default_1080p = """
+ <screen name="CreateQuadPipChannelEntry" position="center,center" size="1500,850" flags="wfNoBorder">
+ <widget source="Title" render="Label" position="100,60" size="1300,60" zPosition="3" font="Semiboldit;52" halign="left" valign="center" backgroundColor="#25062748" transparent="1" />
+ <ePixmap pixmap="skin_default/buttons/red.png" position="137,140" size="140,40" alphatest="blend" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="492,140" size="140,40" alphatest="blend" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="837,140" size="140,40" alphatest="blend" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="1192,140" size="140,40" alphatest="blend" />
+ <widget name="key_red" position="137,140" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
+ <widget name="key_green" position="492,140" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
+ <widget name="key_yellow" position="837,140" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" foregroundColor="#ffffff" transparent="1" />
+ <widget name="key_blue" position="1192,140" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
+ <widget name="list" position="100,200" size="1250,365" serviceItemHeight="40" serviceNumberFont="Regular;28" serviceNameFont="Regular;28" serviceInfoFont="Semibold;24" foregroundColorServiceNotAvail="#58595b" transparent="1" scrollbarMode="showOnDemand" />
+ <widget name="textChannels" position="100,580" size="1250,30" font="Regular;33" transparent="1" />
+ <widget name="selectedList" position="110,620" size="700,160" font="Regular;28" itemHeight="40" transparent="1" />
+ <widget name="description" position="860,630" size="650,160" font="Regular;28" halign="left" transparent="1" />
+ </screen>
+ """
+ skin_default_720p = """
+ <screen name="CreateQuadPipChannelEntry" position="center,center" size="1000,610" flags="wfNoBorder">
+ <widget source="Title" render="Label" position="40,40" size="910,40" zPosition="3" font="Semiboldit;32" backgroundColor="#25062748" transparent="1" />
+ <ePixmap pixmap="skin_default/buttons/red.png" position="75,80" size="140,40" alphatest="blend" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="325,80" size="140,40" alphatest="blend" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="575,80" size="140,40" alphatest="blend" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="825,80" size="140,40" alphatest="blend" />
+ <widget name="key_red" position="75,80" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
+ <widget name="key_green" position="325,80" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
+ <widget name="key_yellow" position="575,80" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" foregroundColor="#ffffff" transparent="1" />
+ <widget name="key_blue" position="825,80" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
+ <widget name="list" position="60,130" size="700,255" transparent="1" scrollbarMode="showOnDemand" foregroundColorServiceNotAvail="#58595b" />
+ <widget name="textChannels" position="60,400" size="850,20" font="Regular;24" transparent="1" />
+ <widget name="selectedList" position="70,430" size="480,150" font="Regular;22" itemHeight="25" transparent="1" />
+ <widget name="description" position="590,460" size="350,150" font="Regular;22" halign="left" transparent="1" />
+ </screen>
+ """
+ skin_default_576p = """
+ <screen name="CreateQuadPipChannelEntry" position="center,center" size="680,520" flags="wfNoBorder">
+ <widget source="Title" render="Label" position="30,20" size="600,30" zPosition="3" font="Regular;22" backgroundColor="#25062748" transparent="1" />
+ <ePixmap pixmap="skin_default/buttons/red.png" position="15,60" size="140,40" alphatest="blend" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="185,60" size="140,40" alphatest="blend" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="355,60" size="140,40" alphatest="blend" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="525,60" size="140,40" alphatest="blend" />
+ <widget name="key_red" position="15,60" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
+ <widget name="key_green" position="185,60" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
+ <widget name="key_yellow" position="355,60" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" foregroundColor="#ffffff" transparent="1" />
+ <widget name="key_blue" position="525,60" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
+ <widget name="list" position="50,115" size="580,230" transparent="1" scrollbarMode="showOnDemand" foregroundColorServiceNotAvail="#58595b" />
+ <widget name="textChannels" position="45,360" size="295,20" font="Regular;22" transparent="1" />
+ <widget name="selectedList" position="50,385" size="290,100" font="Regular;20" itemHeight="22" transparent="1" />
+ <widget name="description" position="360,390" size="310,140" font="Regular;20" halign="left" transparent="1" />
+ </screen>
+ """
+ def __init__(self, session, defaultEntryName, channel = None):
+ ChannelSelectionBase.__init__(self, session)
+
+ self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "QuadPipChannelEditActions"],
+ {
+ "cancel": self.Exit,
+ "ok": self.channelSelected,
+ "toggleList" : self.toggleCurrList,
+ "editName" : self.editEntryName,
+ "up": self.goUp,
+ "down": self.goDown,
+ }, -1)
+
+ self.session = session
+ dh = self.session.desktop.size().height()
+ self.skin = {1080:CreateQuadPipChannelEntry.skin_default_1080p, \
+ 720:CreateQuadPipChannelEntry.skin_default_720p, \
+ 576:CreateQuadPipChannelEntry.skin_default_576p}.get(dh, CreateQuadPipChannelEntry.skin_default_1080p)
+
+ self.defaultEntryName = defaultEntryName
+ self["textChannels"] = Label(_(" "))
+ self["description"] = Label(_(" "))
+
+ self.currList = None
+
+ self.newChannel = channel
+ self.descChannels = []
+ self.prepareChannels()
+ self["selectedList"] = MenuList(self.descChannels, True)
+ self.selectedList = self["selectedList"]
+
+ self.onLayoutFinish.append(self.layoutFinished)
+
+ def layoutFinished(self):
+ self.setTvMode()
+ self.showFavourites()
+ self.switchToServices()
+ self.updateEntryName()
+
+ def updateEntryName(self):
+ self["textChannels"].setText("%s :" % self.newChannel.getName())
+
+ def editEntryName(self):
+ self.session.openWithCallback(self.editEntryNameCB, VirtualKeyBoard, title = (_("Input channel name.")), text = self.newChannel.getName())
+
+ def editEntryNameCB(self, newName):
+ if newName:
+ self.newChannel.setName(newName)
+ self.updateEntryName()
+
+ def updateDescription(self):
+ if self.currList == "channelList":
+ desc = _("EPG key : Switch to quad PiP entry\nOk key : Add to new entry\nPVR key : Input channel name\nExit key : Finish channel edit")
+ else:
+ desc = _("EPG key : Switch to channel list\nOk key : Remove selected channel\nPVR key : Input channel name\nExit key : Finish channel edit")
+
+ self["description"].setText(desc)
+
+ def prepareChannels(self):
+ if self.newChannel is None:
+ self.newChannel = QuadPipChannelEntry(self.defaultEntryName, 99999, None, None, None, None)
+
+ self.updateDescChannels()
+
+ def updateDescChannels(self):
+ self.descChannels = []
+ for idx in range(1,5):
+ sIdx = str(idx)
+ _isEmpty = False
+ chName = self.newChannel.getChannelName(sIdx)
+ if chName is None:
+ chName = " <empty>"
+ _isEmpty = True
+ self.descChannels.append(("%d) %s" % (idx, chName), sIdx, _isEmpty))
+
+ def updateDescChannelList(self):
+ self["selectedList"].setList(self.descChannels)
+
+ def goUp(self):
+ if self.currList == "channelList":
+ self.servicelist.moveUp()
+ else:
+ self.selectedList.up()
+
+ def goDown(self):
+ if self.currList == "channelList":
+ self.servicelist.moveDown()
+ else:
+ self.selectedList.down()
+
+ def toggleCurrList(self):
+ if self.currList == "channelList":
+ self.switchToSelected()
+ else:
+ self.switchToServices()
+
+ def switchToServices(self):
+ self.servicelist.selectionEnabled(1)
+ self.selectedList.selectionEnabled(0)
+ self.currList = "channelList"
+ self.updateDescription()
+
+ def switchToSelected(self):
+ self.servicelist.selectionEnabled(0)
+ self.selectedList.selectionEnabled(1)
+ self.currList = "selectedList"
+ self.updateDescription()
+
+ def channelSelected(self): # just return selected service
+ if self.currList == "channelList":
+ ref = self.getCurrentSelection()
+ if (ref.flags & 7) == 7:
+ self.enterPath(ref)
+ elif not (ref.flags & eServiceReference.isMarker):
+ ref = self.getCurrentSelection()
+ serviceName = ServiceReference(ref).getServiceName()
+ sref = ref.toString()
+ #self.addChannel(serviceName, sref)
+ _title = _('Choice where to put "%s"') % serviceName
+ _list = []
+ for idx in range(1,5):
+ sIdx = str(idx)
+ _isEmpty = False
+ chName = self.newChannel.getChannelName(sIdx)
+ _list.append((chName, sIdx, serviceName, sref, _isEmpty))
+
+ self.session.openWithCallback(self.choiceIdxCallback, ChoiceBox, title=_title, list=tuple(_list))
+ else:
+ self.removeChannel()
+
+ def choiceIdxCallback(self, answer):
+ if answer is not None:
+ (desc, sIdx, serviceName, sref, _isEmpty) = answer
+ self.addChannel(sIdx, serviceName, sref)
+
+ def addChannel(self, sIdx, serviceName, sref):
+ if self.newChannel.setChannel(sIdx, serviceName, sref):
+ self.updateDescChannels()
+ self.updateDescChannelList()
+
+ def removeChannel(self):
+ cur = self.selectedList.getCurrent()
+ if cur:
+ sIdx = cur[1]
+ if self.newChannel.deleteChannel(sIdx):
+ self.updateDescChannels()
+ self.updateDescChannelList()
+
+ def getNewChannel(self):
+ for idx in range(1,5):
+ sIdx = str(idx)
+ ch = self.newChannel.getChannel(sIdx)
+ if ch is not None:
+ return self.newChannel
+
+ return None
+
+ def Exit(self):
+ self.close(self.getNewChannel())
+
+class QuadPiPChannelSelection(Screen, HelpableScreen):
+ skin = """
+ <screen position="%s,%s" size="%d,%d">
+ <ePixmap pixmap="skin_default/buttons/red.png" position="%d,%d" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="%d,%d" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="%d,%d" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="%d,%d" size="140,40" alphatest="on" />
+ <widget name="key_red" position="%d,%d" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#9f1313" transparent="1" />
+ <widget name="key_green" position="%d,%d" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#1f771f" transparent="1" />
+ <widget name="key_yellow" position="%d,%d" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#a08500" transparent="1" />
+ <widget name="key_blue" position="%d,%d" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" foregroundColor="#ffffff" backgroundColor="#18188b" transparent="1" />
+ <widget source="ChannelList" render="Listbox" position="%d,%d" size="%d,%d" scrollbarMode="showOnDemand">
+ <convert type="TemplatedMultiContent">
+ {"template":
+ [
+ MultiContentEntryText(pos = (%d, %d), size = (%d, %d), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 0),
+ MultiContentEntryText(pos = (%d, %d), size = (%d, %d), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 1),
+ MultiContentEntryText(pos = (%d, %d), size = (%d, %d), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2),
+ MultiContentEntryText(pos = (%d, %d), size = (%d, %d), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3),
+ MultiContentEntryText(pos = (%d, %d), size = (%d, %d), font=1, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 4),
+ ],
+ "fonts": [gFont("Regular", %d), gFont("Regular", %d)],
+ "itemHeight": %d
+ }
+ </convert>
+ </widget>
+ </screen>
+ """
+ def __init__(self, session):
+ self.session = session
+ Screen.__init__(self, session)
+ HelpableScreen.__init__(self)
+ self.setTitle(_("Quad PiP Channel Selection"))
+
+ dw = self.session.desktop.size().width()
+ dh = self.session.desktop.size().height()
+ pw, ph = {1080:("center", "center"), 720:("center", "center"), 576:("center", "20%")}.get(dh, ("center", "center"))
+ (sw, sh) = {1080:(dw/3, dh/2), 720:(int(dw/2), int(dh/1.5)), 576:(int(dw/1.3), int(dh/1.5))}.get(dh, (28, 24))
+ button_margin = 5
+ button_h = 40
+ list_y = 40+button_margin*3
+ self.fontSize = {1080:(28, 24), 720:(24,20), 576:(20,18)}.get(dh, (28, 24))
+ self.skin = QuadPiPChannelSelection.skin % (pw, ph, \
+ sw, sh+list_y, \
+ sw/8-70, button_margin, \
+ sw/8-70+sw/4, button_margin, \
+ sw/8-70+sw/4*2, button_margin, \
+ sw/8-70+sw/4*3, button_margin, \
+ sw/8-70, button_margin, \
+ sw/8-70+sw/4, button_margin, \
+ sw/8-70+sw/4*2, button_margin, \
+ sw/8-70+sw/4*3, button_margin, \
+ 0, list_y, sw, sh, \
+ sw/16, 1, sw-sw/16*2, sh/13, \
+ sw/11, 1+sh/13, sw-sw/16*2-sw/8, sh/18, \
+ sw/11, 1+sh/13+sh/18, sw-sw/16*2-sw/8, sh/18, \
+ sw/11, 1+sh/13+sh/18*2, sw-sw/16*2-sw/8, sh/18, \
+ sw/11, 1+sh/13+sh/18*3, sw-sw/16*2-sw/8, sh/18, \
+ self.fontSize[0], self.fontSize[1], \
+ sh/3)
+ self["key_red"] = Label(_("Select"))
+ self["key_green"] = Label(_("Add"))
+ self["key_yellow"] = Label(_("Remove"))
+ self["key_blue"] = Label(_("Edit"))
+
+ self.PipChannelListApply = []
+ self["ChannelList"] = List(self.PipChannelListApply)
+
+ self["qpipActions"] = HelpableActionMap(self, "QuadPipSetupActions",
+ {
+ "red": (self.keyRed, _("Select Quad Channels")),
+ "green": (self.keyGreen, _("Add New Quad Channel Entry")),
+ "yellow": (self.keyYellow, _("Remove Quad Channel Entry")),
+ "blue": (self.keyBlue, _("Edit Quad Channel Entry")),
+ }, -2)
+
+ self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
+ {
+ "ok": (self.keyOk, _("Select Quad Channels")),
+ "cancel": (self.keyCancel, _("Exit Quad Channel Selection")),
+ }, -2)
+
+ self.oldPosition = None
+
+ global quad_pip_channel_list_instance
+ self.qpipChannelList = quad_pip_channel_list_instance
+
+ self.oldPosition = self.qpipChannelList.getIdx()-1
+
+ self.onLayoutFinish.append(self.layoutFinishedCB)
+
+ def layoutFinishedCB(self):
+ self.updateDisplay()
+ self.updatePosition()
+
+ def keyOk(self):
+ idx = self.getCurrentIndex()
+ if idx != -1:
+ self.qpipChannelList.setIdx(idx)
+
+ self.close()
+
+ def keyCancel(self):
+ self.close()
+
+ def keyRed(self):
+ self.keyOk()
+
+ def keyGreen(self):
+ self.session.openWithCallback(self.CreateQuadPipChannelEntryCB, CreateQuadPipChannelEntry, self.getDefaultEntryName(), None)
+
+ def keyYellow(self):
+ curChannel = self.getSelectedChannel()
+ if curChannel:
+ self.oldPosition = self["ChannelList"].getIndex()
+ self.qpipChannelList.removeChannel(curChannel)
+ self.updateChannelList()
+
+ def keyBlue(self):
+ curChannel = self.getSelectedChannel()
+ if curChannel:
+ self.oldPosition = self["ChannelList"].getIndex()
+ self.qpipChannelList.removeChannel(curChannel)
+ self.session.openWithCallback(self.CreateQuadPipChannelEntryCB, CreateQuadPipChannelEntry, None, curChannel)
+
+ def getCurrentIndex(self):
+ idx = -1
+ cur = self["ChannelList"].getCurrent()
+ if cur:
+ idx = cur[5]
+
+ return idx
+
+ def getSelectedChannel(self):
+ selectedChannel = None
+ idx = self.getCurrentIndex()
+ if idx != -1:
+ selectedChannel = self.qpipChannelList.getChannel(idx)
+
+ return selectedChannel
+
+ def getDefaultEntryName(self):
+ return "%s%d" % (self.qpipChannelList.getDefaultPreName(), self.qpipChannelList.length() + 1)
+
+ def CreateQuadPipChannelEntryCB(self, newChannel):
+ if newChannel:
+ self.qpipChannelList.addNewChannel(newChannel)
+ self.qpipChannelList.sortPipChannelList()
+ self.oldPosition = newChannel.getIndex()-1
+ self.updateDisplay()
+ self.updatePosition()
+
+ def updateDisplay(self):
+ self.PipChannelListApply = []
+ for ch in self.getChannelList():
+ entry = []
+
+ entryName = ch.getName()
+ if not entryName:
+ entryName = "%s%d" % (self.qpipChannelList.getDefaultPreName(), ch.getIndex())
+
+ if self.qpipChannelList.getIdx() == ch.getIndex():
+ entryName += " (current channel)"
+
+ entry.append(entryName)
+ entry.append("1) " + ch.getChannelName("1"))
+ entry.append("2) " + ch.getChannelName("2"))
+ entry.append("3) " + ch.getChannelName("3"))
+ entry.append("4) " + ch.getChannelName("4"))
+ entry.append(ch.getIndex())
+ self.PipChannelListApply.append(tuple(entry))
+
+ self["ChannelList"].setList(self.PipChannelListApply)
+
+ def updatePosition(self):
+ if self.oldPosition:
+ if self["ChannelList"].count() > self.oldPosition:
+ self["ChannelList"].setIndex(self.oldPosition)
+ self.oldPosition = None
+
+ def updateChannelList(self):
+ self.qpipChannelList.sortPipChannelList()
+ self.updateDisplay()
+ self.updatePosition()
+
+ def getChannelList(self):
+ return self.qpipChannelList.getPipChannels()
+
+class FocusShowHide:
+ STATE_HIDDEN = 0
+ STATE_SHOWN = 1
+
+ def __init__(self):
+ self.__state = self.STATE_SHOWN
+ self.hideTimer = eTimer()
+ self.hideTimer.callback.append(self.hideTimerCB)
+ self.onLayoutFinish.append(self.startHideTimer)
+
+ def startHideTimer(self):
+ self.hideTimer.stop()
+ self.hideTimer.start(5000, True)
+
+ def hideTimerCB(self):
+ self.hideFocus()
+
+ def isShown(self):
+ return self.__state == self.STATE_SHOWN
+
+ def showFocus(self):
+ self.show()
+ self.__state = self.STATE_SHOWN
+ self.startHideTimer()
+
+ def hideFocus(self):
+ self.hideTimer.stop()
+ self.hide()
+ self.__state = self.STATE_HIDDEN
+
+ def toggleShow(self):
+ if self.__state == self.STATE_SHOWN:
+ self.hideFocus()
+ elif self.__state == self.STATE_HIDDEN:
+ self.showFocus()
+
+class QuadPipScreen(Screen, FocusShowHide, HelpableScreen):
+ skin = """
+ <screen position="0,0" size="%d,%d" backgroundColor="transparent" flags="wfNoBorder">
+ <widget name="ch1" position="240,240" zPosition="1" size="480,60" font="Regular; %d" halign="center" valign="center" foregroundColor="white" backgroundColor="#ffffffff" alphatest="on" />
+ <widget name="ch2" position="1200,240" zPosition="1" size="480,60" font="Regular; %d" halign="center" valign="center" foregroundColor="white" backgroundColor="#ffffffff" alphatest="on" />
+ <widget name="ch3" position="240,780" zPosition="1" size="480,60" font="Regular; %d" halign="center" valign="center" foregroundColor="white" backgroundColor="#ffffffff" alphatest="on" />
+ <widget name="ch4" position="1200,780" zPosition="1" size="480,60" font="Regular; %d" halign="center" valign="center" foregroundColor="white" backgroundColor="#ffffffff" alphatest="on" />
+ <widget name="text1" position="%d,%d" zPosition="2" size="%d,%d" font="Regular; %d" halign="left" valign="center" alphatest="on" />
+ <widget name="text2" position="%d,%d" zPosition="2" size="%d,%d" font="Regular; %d" halign="left" valign="center" alphatest="on" />
+ <widget name="focus" position="0,0" zPosition="-1" size="960,540" backgroundColor="#ffffffff" borderWidth="5" borderColor="#e61616" alphatest="on" />
+ </screen>
+ """
+ def __init__(self, session):
+ self.session = session
+ self.session.qPips = None
+ Screen.__init__(self, session)
+ FocusShowHide.__init__(self)
+ HelpableScreen.__init__(self)
+ self.setTitle(_("Quad PiP Screen"))
+
+ self["actions"] = HelpableActionMap(self, "QuadPipSetupActions",
+ {
+ "cancel": (self.keyExit, _("Exit quad PiP")),
+ "ok": (self.keyOk, _("Zap focused channel on full screen")),
+ "left": (self.keyLeft, _("Select channel audio")),
+ "right": (self.keyRight, _("Select channel audio")),
+ "up": (self.keyUp, _("Select channel audio")),
+ "down": (self.keyDown, _("Select channel audio")),
+ "channelup" : (self.KeyChannel, _("Show channel selection")),
+ "channeldown" : (self.KeyChannel, _("Show channel selection")),
+ "menu" : (self.KeyChannel, _("Show channel selection")),
+ "channelPrev" : (self.KeyPrev, _("Prev quad PiP channel")),
+ "channelNext" : (self.KeyNext, _("Next quad PiP channel")),
+ "red" : (self.KeyRed, _("Show/Hide focus bar")),
+ }, -1)
+
+ self["ch1"] = Label(_(" "))
+ self["ch2"] = Label(_(" "))
+ self["ch3"] = Label(_(" "))
+ self["ch4"] = Label(_(" "))
+ self["text1"] = Label(_(" Red key : Show/Hide channel name"))
+ self["text2"] = Label(_(" Menu key : Select quad channel"))
+ self["focus"] = Slider(-1, -1)
+
+ self.currentPosition = 1 # 1~4
+ self.updatePositionList()
+
+ self.skin = QuadPipScreen.skin % (self.session.desktop.size().width(), self.session.desktop.size().height(), \
+ self.fontSize, self.fontSize, self.fontSize, self.fontSize, \
+ self.text1Pos[0], self.text1Pos[1], self.text1Pos[2], self.text1Pos[3], self.fontSize, \
+ self.text2Pos[0], self.text2Pos[1], self.text2Pos[2], self.text2Pos[3], self.fontSize)
+ self.oldService = None
+ self.curChannel = None
+ self.curPlayAudio = -1
+
+ global quad_pip_channel_list_instance
+ self.qpipChannelList = quad_pip_channel_list_instance
+
+ self.oldFccEnable = False
+ self.oldMinitvEanble = False
+
+ self.onLayoutFinish.append(self.layoutFinishedCB)
+
+ self.notSupportTimer = eTimer()
+ self.notSupportTimer.callback.append(self.showNotSupport)
+
+ self.noChannelTimer = eTimer()
+ self.noChannelTimer.callback.append(self.noChannelTimerCB)
+
+ self.forceToExitTimer = eTimer()
+ self.forceToExitTimer.callback.append(self.forceToExitTimerCB)
+
+ def forceToExitTimerCB(self):
+ self.session.openWithCallback(self.close, MessageBox, _("Quad PiP is not available."), MessageBox.TYPE_ERROR)
+
+ def showNotSupport(self):
+ self.session.openWithCallback(self.close, MessageBox, _("Box or driver is not support Quad PiP."), MessageBox.TYPE_ERROR)
+
+ def noChannelTimerCB(self):
+ self.session.openWithCallback(self.ChannelSelectCB, QuadPiPChannelSelection)
+
+ def layoutFinishedCB(self):
+ if not os.access(ENABLE_QPIP_PROCPATH, os.F_OK):
+ self.notSupportTimer.start(100, True)
+ return
+
+ self.onClose.append(self.__onClose)
+
+ if self.session.pipshown: # try to disable pip
+ self.session.pipshown = False
+ del self.session.pip
+
+ self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
+ self.session.nav.stopService()
+
+ if SystemInfo.get("FastChannelChange", False):
+ self.disableFCC()
+
+ if SystemInfo.get("MiniTV", False):
+ self.disableMiniTV()
+
+ ret = setDecoderMode("mosaic")
+ if ret is not True:
+ self.forceToExitTimer.start(0, True)
+ return
+
+ self.moveLabel()
+
+ if self.qpipChannelList.length() == 0:
+ self.noChannelTimer.start(10, True)
+ else:
+ self.playLastChannel()
+
+ def __onClose(self):
+ self.disableQuadPip()
+ setDecoderMode("normal")
+
+ if SystemInfo.get("FastChannelChange", False):
+ self.enableFCC()
+
+ if SystemInfo.get("MiniTV", False):
+ self.enableMiniTV()
+
+ self.qpipChannelList.saveAll()
+ self.session.nav.playService(self.oldService)
+
+ def getChannelPosMap(self, w, h):
+ rectMap = {}
+ ch1 = (0, 0, int(w*0.5), int(h*0.5))
+ ch2 = (int(w*0.5), 0, int(w*0.5), int(h*0.5))
+ ch3 = (0, int(h*0.5), int(w*0.5), int(h*0.5))
+ ch4 = (int(w*0.5), int(h*0.5), int(w*0.5), int(h*0.5))
+ rectMap = (None, ch1, ch2, ch3, ch4)
+
+ return rectMap
+
+ def updatePositionList(self):
+ w = self.session.desktop.size().width()
+ h = self.session.desktop.size().height()
+ self.framePosMap = self.getChannelPosMap(w, h)
+ self.eVideoPosMap = self.getChannelPosMap(720, 576)
+
+ self.movePositionMap = {}
+ self.movePositionMap["left"] = [-1, 2, 1, 4, 3]
+ self.movePositionMap["right"] = [-1, 2, 1, 4, 3]
+ self.movePositionMap["up"] = [-1, 3, 4, 1, 2]
+ self.movePositionMap["down"] = [-1, 3, 4, 1, 2]
+
+ self.labelPositionMap = {}
+ self.labelPositionMap["ch1"] = (w/8, h/4-h/36, w/4, h/18)
+ self.labelPositionMap["ch2"] = (w/8+w/2, h/4-h/36, w/4, h/18)
+ self.labelPositionMap["ch3"] = (w/8, h/4-h/36+h/2, w/4, h/18)
+ self.labelPositionMap["ch4"] = (w/8+w/2, h/4-h/36+h/2, w/4, h/18)
+
+ self.decoderIdxMap = [None, 0, 1, 2, 3]
+
+ self.fontSize = {1080:40, 720:28, 576:18}.get(h, 40)
+ self.text1Pos = (w-w/3, h-h/18-h/18, w/3, h/18)
+ self.text2Pos = (w-w/3, h-h/18, w/3, h/18)
+
+ def moveFrame(self):
+ self.showFocus()
+ pos = self.framePosMap[self.currentPosition]
+ self["focus"].resize(int(pos[2]), int(pos[3]))
+ self["focus"].move(int(pos[0]), int(pos[1]))
+
+ def moveLabel(self):
+ posMap = self.labelPositionMap
+
+ ch1_posMap = posMap["ch1"]
+ self["ch1"].move(int(ch1_posMap[0]), int(ch1_posMap[1]))
+ self["ch1"].resize(int(ch1_posMap[2]), int(ch1_posMap[3]))
+
+ ch2_posMap = posMap["ch2"]
+ self["ch2"].move(int(ch2_posMap[0]), int(ch2_posMap[1]))
+ self["ch2"].resize(int(ch2_posMap[2]), int(ch2_posMap[3]))
+
+ ch3_posMap = posMap["ch3"]
+ self["ch3"].move(int(ch3_posMap[0]), int(ch3_posMap[1]))
+ self["ch3"].resize(int(ch3_posMap[2]), int(ch3_posMap[3]))
+
+ ch4_posMap = posMap["ch4"]
+ self["ch4"].move(int(ch4_posMap[0]), int(ch4_posMap[1]))
+ self["ch4"].resize(int(ch4_posMap[2]), int(ch4_posMap[3]))
+
+ def keyExit(self):
+ self.close()
+
+ def keyOk(self):
+ if self.isShown():
+ channel = self.qpipChannelList.getCurrentChannel()
+ if channel:
+ chInfo = channel.getChannel(str(self.currentPosition))
+ if chInfo:
+ (sname, sref) = chInfo
+ self.oldService = eServiceReference(sref)
+ self.close()
+ else:
+ self.showFocus()
+
+ def keyLeft(self):
+ newPosition = self.movePositionMap["left"][self.currentPosition]
+ self.selectPosition(newPosition)
+
+ def keyRight(self):
+ newPosition = self.movePositionMap["right"][self.currentPosition]
+ self.selectPosition(newPosition)
+
+ def keyUp(self):
+ newPosition = self.movePositionMap["up"][self.currentPosition]
+ self.selectPosition(newPosition)
+
+ def keyDown(self):
+ newPosition = self.movePositionMap["down"][self.currentPosition]
+ self.selectPosition(newPosition)
+
+ def KeyChannel(self):
+ self.session.openWithCallback(self.ChannelSelectCB, QuadPiPChannelSelection)
+
+ def KeyPrev(self):
+ curIdx = self.qpipChannelList.getIdx()
+ curIdx -= 1
+ if curIdx == 0:
+ curIdx = self.qpipChannelList.length()
+ self.qpipChannelList.setIdx(curIdx)
+ self.playLastChannel()
+
+ def KeyNext(self):
+ curIdx = self.qpipChannelList.getIdx()
+ curIdx += 1
+ if curIdx > self.qpipChannelList.length():
+ curIdx = 1
+ self.qpipChannelList.setIdx(curIdx)
+ self.playLastChannel()
+
+ def KeyRed(self):
+ self.toggleShow()
+
+ def selectPosition(self, pos):
+ self.currentPosition = pos
+ self.moveFrame()
+ self.selectAudio()
+
+ def selectAudio(self):
+ if self.curPlayAudio == -1:
+ return
+
+ if self.curPlayAudio != self.currentPosition:
+ if self.session.qPips and len(self.session.qPips) >= self.currentPosition:
+ self.playAudio(self.curPlayAudio, False)
+ self.playAudio(self.currentPosition, True)
+
+ def disableQuadPip(self):
+ if self.session.qPips is not None:
+ for qPip in self.session.qPips:
+ del qPip
+
+ self.session.qPips = None
+ self.curPlayAudio = -1
+
+ self.updateChannelName(None)
+
+ def ChannelSelectCB(self):
+ if self.qpipChannelList.length() == 0:
+ self.disableQuadPip()
+ else:
+ self.playLastChannel()
+
+ def playLastChannel(self, first=True):
+ if self.qpipChannelList.length() == 0:
+ return
+
+ channel = self.qpipChannelList.getCurrentChannel()
+ if channel:
+ self.playChannel(channel)
+ elif first:
+ self.qpipChannelList.setIdx(1)
+ self.playLastChannel(False)
+
+ return channel
+
+ def playChannel(self, channel):
+ print "[playChannel] channel : ", channel
+
+ if self.curChannel and self.curChannel == channel.channel:
+ return
+
+ self.disableQuadPip()
+ self.selectPosition(1)
+
+ self.curChannel = channel.channel.copy()
+
+ self.session.qPips = []
+ for idx in range(1,5):
+ chInfo = channel.getChannel(str(idx))
+ if chInfo is None:
+ continue
+
+ (sname, sref) = chInfo
+
+ qPipShown = False
+
+ decoderIdx = self.decoderIdxMap[idx]
+ pos = self.eVideoPosMap[idx]
+ #print "===================================================================="
+ #print "sname : ", sname
+ #print "sref : ", sref
+ #print "decoderIdx : " , decoderIdx
+ #print "pos : ", pos
+ #print "===================================================================="
+
+ qPipInstance = self.session.instantiateDialog(QuadPiP, decoderIdx, pos)
+ qPipInstance.setAnimationMode(0)
+ qPipInstance.show()
+
+ isPlayAudio = False
+ if self.currentPosition == idx:
+ isPlayAudio = True
+ self.curPlayAudio = idx
+
+ if qPipInstance.playService(eServiceReference(sref), isPlayAudio):
+ self.session.qPips.append(qPipInstance)
+ else:
+ print "play failed, ", sref
+ del qPipInstance
+
+ self.updateChannelName(channel)
+ self.showFocus()
+
+ def playAudio(self, idx, value):
+ qPipInstance = self.session.qPips[idx-1]
+ qPipInstance.setQpipMode(True, value)
+
+ if value:
+ self.curPlayAudio = idx
+ else:
+ self.curPlayAudio = -1
+
+ def updateChannelName(self, channel):
+ for idx in range(1,5):
+ self["ch%d" % idx].setText((channel and channel.getChannelName(str(idx))) or "No channel")
+
+ def disableFCC(self):
+ try:
+ self.oldFccEnable = config.plugins.fccsetup.activate.value
+ if self.oldFccEnable:
+ config.plugins.fccsetup.activate.value = False
+ from Plugins.SystemPlugins.FastChannelChange.plugin import FCCChanged
+ FCCChanged()
+ except:
+ self.oldFccEnable = False
+
+ def enableFCC(self):
+ if self.oldFccEnable:
+ try:
+ config.plugins.fccsetup.activate.value = self.oldFccEnable
+ from Plugins.SystemPlugins.FastChannelChange.plugin import FCCChanged
+ FCCChanged()
+ except:
+ pass
+
+ def disableMiniTV(self):
+ try:
+ self.oldMinitvEanble = config.plugins.minitv.enable.value
+ if self.oldMinitvEanble:
+ config.plugins.minitv.enable.value = False
+ except:
+ self.oldFccEnable = False
+
+ def enableMiniTV(self):
+ if self.oldMinitvEanble:
+ try:
+ config.plugins.minitv.enable.value = self.oldMinitvEanble
+ except:
+ pass
+
diff --git a/lib/python/Screens/Makefile.am b/lib/python/Screens/Makefile.am
index 4c4fa44..35e8510 100755
--- a/lib/python/Screens/Makefile.am
+++ b/lib/python/Screens/Makefile.am
@@ -15,5 +15,5 @@ install_PYTHON = \
SleepTimerEdit.py Ipkg.py RdsDisplay.py Globals.py DefaultWizard.py \
SessionGlobals.py LocationBox.py WizardLanguage.py TaskView.py Rc.py VirtualKeyBoard.py \
TextBox.py FactoryReset.py RecordPaths.py UnhandledKey.py ServiceStopScreen.py \
- InputDeviceSetup.py
+ InputDeviceSetup.py QuadPiP.py
diff --git a/lib/python/Screens/QuadPiP.py b/lib/python/Screens/QuadPiP.py
new file mode 100644
index 0000000..57dac06
--- /dev/null
+++ b/lib/python/Screens/QuadPiP.py
@@ -0,0 +1,63 @@
+from Screens.Screen import Screen
+from enigma import ePoint, eSize, eServiceCenter, getBestPlayableServiceReference, eServiceReference
+from Components.VideoWindow import VideoWindow
+from Components.config import config, ConfigPosition
+
+class QuadPiP(Screen):
+ def __init__(self, session, decoderIdx = 1, pos = None):
+ Screen.__init__(self, session)
+ self["video"] = VideoWindow(decoderIdx, 720, 576)
+ self.currentService = None
+ self.onLayoutFinish.append(self.LayoutFinished)
+ self.decoderIdx = decoderIdx
+ self.pos = pos
+ self.skinName = "PictureInPicture"
+
+ def LayoutFinished(self):
+ self["video"].instance.setAdjustPosition(False)
+ self.onLayoutFinish.remove(self.LayoutFinished)
+ x = self.pos[0]
+ y = self.pos[1]
+ w = self.pos[2]
+ h = self.pos[3]
+
+ if x != -1 and y != -1 and w != -1 and h != -1:
+ self.move(x, y)
+ self.resize(w, h)
+
+ def move(self, x, y):
+ self.instance.move(ePoint(x, y))
+
+ def resize(self, w, h):
+ self.instance.resize(eSize(*(w, h)))
+ self["video"].instance.resize(eSize(*(w, h)))
+
+ def getPosition(self):
+ return ((self.instance.position().x(), self.instance.position().y()))
+
+ def getSize(self):
+ return (self.instance.size().width(), self.instance.size().height())
+
+ def playService(self, service, playAudio):
+ if service and (service.flags & eServiceReference.isGroup):
+ ref = getBestPlayableServiceReference(service, eServiceReference())
+ else:
+ ref = service
+ if ref:
+ self.pipservice = eServiceCenter.getInstance().play(ref)
+ if self.pipservice and not self.pipservice.setTarget(self.decoderIdx):
+ self.setQpipMode(True, playAudio)
+ self.pipservice.start()
+ self.currentService = service
+ return True
+ else:
+ self.pipservice = None
+ return False
+
+ def setQpipMode(self, pipMode, playAudio):
+ if self.pipservice:
+ self.pipservice.setQpipMode(pipMode, playAudio)
+
+ def getCurrentService(self):
+ return self.currentService
+
diff --git a/lib/service/iservice.h b/lib/service/iservice.h
index 33ff66b..bc0f872 100644
--- a/lib/service/iservice.h
+++ b/lib/service/iservice.h
@@ -879,6 +879,7 @@ public:
virtual SWIG_VOID(RESULT) stream(ePtr<iStreamableService> &SWIG_OUTPUT)=0;
virtual SWIG_VOID(RESULT) streamed(ePtr<iStreamedService> &SWIG_OUTPUT)=0;
virtual SWIG_VOID(RESULT) keys(ePtr<iServiceKeys> &SWIG_OUTPUT)=0;
+ virtual void setQpipMode(bool value, bool audio)=0;
};
SWIG_TEMPLATE_TYPEDEF(ePtr<iPlayableService>, iPlayableServicePtr);
diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp
index 1494cc5..f740b47 100755
--- a/lib/service/servicedvb.cpp
+++ b/lib/service/servicedvb.cpp
@@ -959,6 +959,10 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv
m_current_video_pid_type = 0;
+ m_qpip_mode = false;
+
+ m_play_audio = true;
+
CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
}
@@ -1963,7 +1967,7 @@ int eDVBServicePlay::selectAudioStream(int i)
m_current_audio_pid = apid;
- if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
+ if ((m_is_primary || (m_qpip_mode && m_play_audio)) && m_decoder->setAudioPID(apid, apidtype))
{
eDebug("set audio pid failed");
return -4;
@@ -2665,7 +2669,9 @@ void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
m_decoder->setVideoPID(vpid, vpidtype);
m_current_video_pid_type = vpidtype;
- selectAudioStream();
+
+ if (!m_qpip_mode || m_play_audio) // 1) no qpip mode, 2) qpip mode & play audio
+ selectAudioStream();
//if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
if (!(m_is_pvr || m_is_stream || m_timeshift_active))
@@ -3305,6 +3311,24 @@ PyObject *eDVBServicePlay::getStreamingData()
return r;
}
+void eDVBServicePlay::setQpipMode(bool value, bool audio)
+{
+ m_qpip_mode = value;
+ m_play_audio = audio;
+
+ if(m_decoder)
+ {
+ if (m_play_audio)
+ {
+ selectAudioStream();
+ }
+ else
+ {
+ m_decoder->setAudioPID(-1, -1);
+ }
+ m_decoder->set();
+ }
+}
DEFINE_REF(eDVBServicePlay)
diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h
index eafc96d..6d2eaf9 100644
--- a/lib/service/servicedvb.h
+++ b/lib/service/servicedvb.h
@@ -184,6 +184,7 @@ public:
// iStreamableService
RESULT stream(ePtr<iStreamableService> &ptr);
PyObject *getStreamingData();
+ void setQpipMode(bool value, bool audio);
protected:
friend class eServiceFactoryDVB;
@@ -202,6 +203,9 @@ protected:
eDVBServiceEITHandler m_event_handler;
int m_current_audio_pid;
int m_current_video_pid_type;
+
+ bool m_qpip_mode;
+ bool m_play_audio;
eDVBServicePlay(const eServiceReference &ref, eDVBService *service, bool connect_event=true);
diff --git a/lib/service/servicehdmi.h b/lib/service/servicehdmi.h
index 1f8e664..0248f3d 100644
--- a/lib/service/servicehdmi.h
+++ b/lib/service/servicehdmi.h
@@ -75,6 +75,8 @@ public:
std::string getInfoString(int w);
PyObject *getInfoObject(int w);
+ void setQpipMode(bool value, bool audio) { }
+
private:
friend class eServiceFactoryHDMI;
eServiceHDMI(eServiceReference ref);
diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h
index 50957c4..8ada1b5 100644
--- a/lib/service/servicemp3.h
+++ b/lib/service/servicemp3.h
@@ -83,6 +83,8 @@ public:
RESULT keys(ePtr<iServiceKeys> &ptr) { ptr = 0; return -1; }
RESULT stream(ePtr<iStreamableService> &ptr) { ptr = 0; return -1; }
+ void setQpipMode(bool value, bool audio) { }
+
// iPausableService
RESULT pause();
RESULT unpause();