diff --git a/ChangeLog b/ChangeLog
index 5d1a7656f35..e3364097491 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1282,3 +1282,22 @@ openvix: developer 6.6.004.002
openvix: developer 6.6.004.003
openvix: developer 6.6.004.004
openvix: developer 6.6.004.005
+openvix: developer 6.6.004.006
+openvix: developer 6.6.004.007
+openvix: developer 6.6.004.008
+openvix: developer 6.6.004.009
+openvix: developer 6.6.004.010
+openvix: developer 6.6.004.011
+openvix: developer 6.6.004.012
+openvix: developer 6.6.004.013
+openvix: developer 6.6.004.014
+openvix: developer 6.6.005.001
+openvix: developer 6.6.005.002
+openvix: developer 6.6.005.003
+openvix: developer 6.6.006.001
+openvix: developer 6.6.006.002
+openvix: developer 6.6.006.003
+openvix: developer 6.6.006.004
+openvix: developer 6.6.006.005
+openvix: developer 6.6.006.006
+openvix: developer 6.6.007.001
diff --git a/README.md b/README.md
index 91e8f7552bd..2b3766fa3f7 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
## OpenViX buildserver requirements: ##
-> Ubuntu 22.04.1 LTS (Kernel 5.15.0) 64-bit
+>Ubuntu 24.04 LTS (GNU/Linux 6.8.0-39-generic x86_64)
## minimum hardware requirement for image build (building feeds may require more):
@@ -37,9 +37,7 @@
----------
3 - Set your shell to /bin/bash.
- sudo dpkg-reconfigure dash
- When asked: Install dash as /bin/sh?
- select "NO"
+ sudo ln -sf /bin/bash /bin/sh
----------
4 - modify max_user_watches
@@ -49,69 +47,83 @@
sudo sysctl -n -w fs.inotify.max_user_watches=524288
----------
-5 - Add user openvixbuilder
+5. Disable apparmor profile
+ Curently due to this Ubuntu/bitbake issue..https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2056555
+ This command nust be entered after every boot....
+
+ sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
+
+----------
+6 - Add user openvixbuilder
sudo adduser openvixbuilder
----------
-6 - Switch to user openvixbuilder
+7. Add your git user and email
+
+ git config --global user.email "you@example.com"
+
+ git config --global user.name "Your Name"
+
+----------
+8 - Switch to user openvixbuilder
su openvixbuilder
----------
-7 - Switch to home of openvixbuilder
+9 - Switch to home of openvixbuilder
cd ~
----------
-8 - Create folder openvix
+10 - Create folder openvix
mkdir -p ~/openvix
----------
-9 - Switch to folder openvix
+11 - Switch to folder openvix
cd openvix
----------
-10 - Clone oe-alliance git
+12 - Clone oe-alliance git
- git clone https://github.com/oe-alliance/build-enviroment.git -b 5.4
+ git clone https://github.com/oe-alliance/build-enviroment.git -b 5.3
----------
-11 - Switch to folder build-enviroment
+13 - Switch to folder build-enviroment
cd build-enviroment
----------
-12 - Update build-enviroment
+14 - Update build-enviroment
make update
----------
-13 - Initialise the first machine so site.conf gets created
+15 - Initialise the first machine so site.conf gets created
MACHINE=zgemmah9combo DISTRO=openvix DISTRO_TYPE=release make init
----------
-14 - Update site.conf
+16 - Update site.conf
- BB_NUMBER_THREADS, PARALLEL_MAKE set to number of threads supported by the CPU
- add/modify DL_DIR = " location for build sources " to point to a location where you can save derived build sources,
this will reduce build time in fetching these sources again.
----------
-15 - Building image with feeds e.g.:-
+17 - Building image with feeds e.g.:-
MACHINE=vuultimo4k DISTRO=openvix DISTRO_TYPE=release make image
----------
-16 - Building an image without feeds (Build time 1-2h)
+18 - Building an image without feeds (Build time 1-2h)
MACHINE=zgemmah9combo DISTRO=openvix DISTRO_TYPE=release make enigma2-image
----------
-17 - Building feeds only
+19 - Building feeds only
MACHINE=zgemmah9combo DISTRO=openvix DISTRO_TYPE=release make feeds
diff --git a/configure.ac b/configure.ac
index 05988050c51..25e07784205 100644
--- a/configure.ac
+++ b/configure.ac
@@ -420,6 +420,7 @@ if test "$BOXTYPE" == "dm900" -o "$BOXTYPE" == "dm920"; then
AC_DEFINE(HAVE_HDMIIN_DM, 1,[has hdmi in dm])
AC_DEFINE(LCD_DM900_Y_OFFSET, 4,[define LCD Y offset for dm900 and dm920])
AC_DEFINE(DREAMBOX_DUAL_TUNER, 1,[define it is dreambox dual tuner present])
+ AC_DEFINE(USE_ALTERNATE_CA_HANDLING, 1,[define it so to use additioanl ca device freeing])
AC_DEFINE(FORCE_NO_BLENDING_ACCELERATION, 1,[define when the framebuffer acceleration does not have alphablending support, though the autodetection might indicate that it does])
fi
@@ -474,6 +475,10 @@ if test "$BOXTYPE" == "sf8008" -o "$BOXTYPE" == "sf8008m" -o "$BOXTYPE" == "sx98
AC_DEFINE(FORCE_ALPHABLENDING_ACCELERATION, 1,[define when the framebuffer acceleration has alphablending support, but detection slow down all])
fi
+if test "$BOXTYPE" == "pulse4k" -o "$BOXTYPE" == "pulse4kmini"; then
+ AC_DEFINE(USE_ALTERNATE_CA_HANDLING, 1,[define it so to use additioanl ca device freeing])
+fi
+
if test "$BOXTYPE" == "u5" -o "$BOXTYPE" == "u5pvr" -o "$BOXTYPE" == "u51" -o "$BOXTYPE" == "u52" -o "$BOXTYPE" == "u53" -o "$BOXTYPE" == "u532" -o "$BOXTYPE" == "u533" -o "$BOXTYPE" == "u54" -o "$BOXTYPE" == "u55" -o "$BOXTYPE" == "u56" -o "$BOXTYPE" == "u57" -o "$BOXTYPE" == "u571" -o "$BOXTYPE" == "u41" -o "$BOXTYPE" == "u42" -o "$BOXTYPE" == "u43"; then
AC_DEFINE(HAVE_HISILICON, 1,[define add HISILICON chip])
fi
@@ -572,7 +577,7 @@ fi
AC_CHECK_HEADERS([sys/klog.h])
AC_CHECK_FUNCS([klogctl])
-ENIGMA2_CFLAGS="-fno-rtti -fno-exceptions -rdynamic -funwind-tables"
+ENIGMA2_CFLAGS="-fno-rtti -rdynamic -funwind-tables"
AC_SUBST(ENIGMA2_CFLAGS)
AX_CXX_COMPILE_STDCXX([17], [ext], [mandatory])
diff --git a/data/display400/skin_display.xml b/data/display400/skin_display.xml
index d5207a3372f..b956d15319e 100644
--- a/data/display400/skin_display.xml
+++ b/data/display400/skin_display.xml
@@ -27,6 +27,7 @@
+
diff --git a/data/display480/skin_display.xml b/data/display480/skin_display.xml
index 493f94cbd22..f0525256f8c 100644
--- a/data/display480/skin_display.xml
+++ b/data/display480/skin_display.xml
@@ -305,19 +305,19 @@
-
+
-
+
-
+
-
+
-
+
diff --git a/data/display800/Default_with_Picon_Fullscreen/skin_display.xml b/data/display800/Default_with_Picon_Fullscreen/skin_display.xml
index 1c6c832242e..d4bd12fd1ea 100644
--- a/data/display800/Default_with_Picon_Fullscreen/skin_display.xml
+++ b/data/display800/Default_with_Picon_Fullscreen/skin_display.xml
@@ -48,13 +48,16 @@
-
+
-
+
-
+
+
+
+
diff --git a/data/display800/skin_display.xml b/data/display800/skin_display.xml
index 14f4e6e9515..5dfca53c8d6 100644
--- a/data/display800/skin_display.xml
+++ b/data/display800/skin_display.xml
@@ -68,13 +68,16 @@
-
+
-
+
-
+
+
+
+
diff --git a/data/display800/skin_display_picon.xml b/data/display800/skin_display_picon.xml
index 47cb0074f92..d01e39661d7 100644
--- a/data/display800/skin_display_picon.xml
+++ b/data/display800/skin_display_picon.xml
@@ -61,13 +61,16 @@
-
+
-
+
-
+
+
+
+
diff --git a/data/setup.xml b/data/setup.xml
index 21f4c56664b..0c84719b2a1 100644
--- a/data/setup.xml
+++ b/data/setup.xml
@@ -27,6 +27,7 @@
- config.usage.wakeOnLAN
- config.misc.usegstplaybin3
- config.misc.RCSource
+ - config.skin.pixmap_force_alphablending
- config.misc.softcam_streamrelay_url
@@ -96,7 +97,9 @@
- config.usage.historymode
- config.usage.boolean_graphic
- config.usage.setupShowDefault
- - config.usage.fast_skin_reload
+
+
+ - config.usage.fast_skin_reload
- config.usage.alternative_number_mode
@@ -172,13 +175,13 @@
- config.subtitles.dvb_subtitles_original_position
- config.subtitles.subtitle_bad_timing_delay
- config.subtitles.dvb_subtitles_backtrans
+ - config.subtitles.pango_autoturnon
- config.subtitles.pango_subtitle_colors
- config.subtitles.pango_subtitle_fontswitch
- config.subtitles.colourise_dialogs
- config.subtitles.pango_subtitles_delay
- config.subtitles.pango_subtitles_fps
- config.subtitles.pango_subtitle_removehi
- - config.subtitles.pango_autoturnon
- config.autolanguage.audio_autoselect1
@@ -351,6 +354,7 @@
- config.crash.daysloglimit
- config.crash.sizeloglimit
- config.crash.logtimeformat
+ - config.crash.pystackonspinner
- config.crash.coredump
diff --git a/data/unicable.xml b/data/unicable.xml
index 83f4883e2e7..39fedb1f7c1 100644
--- a/data/unicable.xml
+++ b/data/unicable.xml
@@ -15,9 +15,10 @@ bootuptime: integer, delay to allow the device to boot up, in milliseconds (opti
lofl: integer, alternative LOF/L value (optional, default value is 9750)
lofh: integer, alternative LOF/H value (optional, defaultvalue is 10600)
-->
-
+
+
@@ -31,6 +32,7 @@ lofh: integer, alternative LOF/H value (optional, defaultvalue is 10600)
+
@@ -47,6 +49,7 @@ lofh: integer, alternative LOF/H value (optional, defaultvalue is 10600)
+
@@ -66,7 +69,7 @@ lofh: integer, alternative LOF/H value (optional, defaultvalue is 10600)
-
+
@@ -159,6 +162,7 @@ lofh: integer, alternative LOF/H value (optional, defaultvalue is 10600)
+
@@ -214,6 +218,7 @@ lofh: integer, alternative LOF/H value (optional, defaultvalue is 10600)
+
diff --git a/doc/ENIGMAINFOVALUES b/doc/ENIGMAINFOVALUES
new file mode 100644
index 00000000000..67c184976b9
--- /dev/null
+++ b/doc/ENIGMAINFOVALUES
@@ -0,0 +1,71 @@
+Based on enigma.info produced in oe-alliance branch 5.4 builds
+--------------------------------------------------------------
+
+architecture: string, from $DEFAULTTUNE, set in meta-brands/machine.conf, current oe-alliance choices: mips32el / cortexa15hf-neon-vfpv4 / cortexa7hf-vfp
+avjack: bool, from MACHINE_FEATURES
+blindscanbinary: string, from $BLINDSCAN_BINARY, set in meta-oe/conf/machine/box-hardware.inc
+brand: string, manufacturer, set in meta-brands, normally lower case
+ci: bool, from MACHINE_FEATURES
+compiledate: string, containing 8 digits, representing a date in format YYYYMMDD
+dboxlcd: bool, from MACHINE_FEATURES
+developername: string, distro name in lower case, from DEVELOPER_NAME ?= "${DISTRO_NAME}" in box-hardware.inc, $DISTRO_NAME, set in .conf
+displaybrand: string, manufacturer for display purposes, set in meta-brands
+displaydistro: string, free election of distro author, distro name for display purposes, set in .conf
+displaymodel: string, machine model name for display purposes, set in meta-brands
+displaytype: string, type of front panel display, from MACHINE_FEATURES
+distro: string, free election of distro author, should be lower case, from $DISTRO_NAME, set in .conf
+driversdate: string, containing 8 digits, representing a date in format YYYYMMDD or "N/A"
+dvi: bool, from MACHINE_FEATURES
+feedsurl: string, from $DISTRO_FEED_URI, set in .conf
+fhdskin: bool, has 'skins1080" in from MACHINE_FEATURES
+fpu: string, set in openembedded-core/meta/conf/machine/include/arm/arch-arm
+friendlyfamily: string, set in box-hardware.inc, FRIENDLY_FAMILY ?= "${MACHINE} ${BUILDMACHINE}"
+hdmi: bool, from MACHINE_FEATURES
+hdmifhdin: bool, from MACHINE_FEATURES
+hdmihdin: bool, from MACHINE_FEATURES
+hdmistandbymode: int, 0 or 1, from MACHINE_FEATURES, set in box-hardware.inc
+imagebuild: string, free election of distro author, from $BUILD_VERSION, set in .conf
+imagedevbuild: string, free election of distro author, from $DEVELOPER_BUILD_VERSION, set in .conf (default '001' set in layer-conf)
+imagedir: string, set in meta-brands, e.g. 'vuplus/ultimo4k'
+imagefs: string, set in meta-brands, e.g. 'tar.bz2 '
+imagetype: string, free election of distro author, from $DISTRO_TYPE, set on the command line, e.g. 'MACHINE=$machine DISTRO=$distro DISTRO_TYPE=$distro_type make image'
+imageversion: string, free election of distro author, from DISTRO_VERSION, set in .conf
+imglanguage: string, from $LANGUAGECHECK, based on flash size, set in meta-oe/conf/machine/box-hardware.inc
+imgrevision: string, default is the same as 'imagebuild'
+imgversion=: string, default is the same as 'imageversion'
+kernel: string, from $KERNEL_VERSION, set in meta-brands
+kexecmb: bool, from MACHINE_FEATURES
+kernelfile: string, from $KERNEL_FILE, set in meta-brands
+machinebuild: string, from $MACHINEBUILD, from env data.py [inheritFromOS]
+mediaservice: string, from MACHINE_FEATURES, set in set in meta-oe/conf/machine/box-hardware.inc, "${@bb.utils.contains("MACHINE_FEATURES", "himedia", "servicehisilicon" , "servicegstreamer", d)}"
+middleflash: bool, from MACHINE_FEATURES
+mkubifs: string, from $MKUBIFS_ARGS, set in meta-brands
+model: string, from $MACHINE, from env data.py [inheritFromOS]
+mtdbootfs: string, from $MTD_BOOTFS, set in meta-brands
+mtdkernel: string, from $MTD_KERNEL, set in meta-brands
+mtdrootfs: string, from $MTD_ROOTFS, set in meta-brands
+multilib: bool, from MACHINE_FEATURES
+multitranscoding: bool, from MACHINE_FEATURES
+oe: string, from $OE_VER, set in layer.conf, e.g. 'OE-Alliance 5.4'
+platform: string, from $STB_PLATFORM, set in meta-oe/conf/machine/box-hardware.inc, default: STB_PLATFORM ?= "${MACHINE}"
+python: string, from $PYTHON_BASEVERSION, e.g. '3.12'
+rca: bool, from MACHINE_FEATURES
+rcidnum: int, from $RCIDNUM, set in meta-oe/conf/machine/box-hardware.inc
+rcname: string, from $RCNAME, set in meta-brands, default from meta-oe/conf/machine/box-hardware.inc, RCNAME ??= "dmm1"
+rctype: int, from $RCTYPE, set in meta-brands, default from meta-oe/conf/machine/box-hardware.inc, RCTYPE ??= "0"
+rootfile: string, from $ROOTFS_FILE, set in meta-brands
+scart: bool, from MACHINE_FEATURES
+noscartswitch: bool, from MACHINE_FEATURES
+scartyuv: bool, from MACHINE_FEATURES
+smallflash: bool, from MACHINE_FEATURES
+socfamily='bcm7376'
+svideo: bool, from MACHINE_FEATURES
+timerwakeupmode: int, from MACHINE_FEATURES, set in meta-oe/conf/machine/box-hardware.inc, "${@bb.utils.contains_any("MACHINE_FEATURES", "TIMERWAKEUP", "1", "0", d)}"
+transcoding: bool, from MACHINE_FEATURES
+ubinize: string, from $UBINIZE_ARGS, set in meta-brands
+vfdsymbol: bool, from MACHINE_FEATURES
+wol: bool, from MACHINE_FEATURES
+wwol: bool, from MACHINE_FEATURES
+yocto: string, e.g '4.1', from openembedded-core git, git describe --match=yocto* | cut -d '-' -f 2
+yuv: bool, from MACHINE_FEATURES
+checksum: checksum of the above items in this file
diff --git a/lib/base/estring.cpp b/lib/base/estring.cpp
index 969bda63d35..1cd37c7ca34 100644
--- a/lib/base/estring.cpp
+++ b/lib/base/estring.cpp
@@ -649,13 +649,13 @@ std::string convertDVBUTF8(const unsigned char *data, int len, int table, int ts
if (table != 11)
table = data[i] + 4;
++i;
- eTrace("[convertDVBUTF8] (1..11)text encoded in ISO-8859-%d", table);
+/* eTrace("[convertDVBUTF8] (1..11)text encoded in ISO-8859-%d", table); */
break;
case ISO8859_xx:
{
int n = data[++i] << 8;
n |= (data[++i]);
- eTrace("[convertDVBUTF8] (0x10)text encoded in ISO-8859-%d", n);
+/* eTrace("[convertDVBUTF8] (0x10)text encoded in ISO-8859-%d", n); */
++i;
switch(n)
{
diff --git a/lib/driver/hdmi_cec.cpp b/lib/driver/hdmi_cec.cpp
index e0113da99a9..e71e46e7b66 100644
--- a/lib/driver/hdmi_cec.cpp
+++ b/lib/driver/hdmi_cec.cpp
@@ -11,8 +11,7 @@
#include
#include
#include
-/* NOTE: this header will move to linux uapi, once the cec framework is out of staging */
-#include
+#define CEC_LOG_ADDR_TYPE_TUNER 2
eHdmiCEC *eHdmiCEC::instance = NULL;
@@ -53,113 +52,35 @@ eHdmiCEC::eHdmiCEC()
{
ASSERT(!instance);
instance = this;
- linuxCEC = false;
fixedAddress = false;
physicalAddress[0] = 0x10;
physicalAddress[1] = 0x00;
logicalAddress = 1;
- deviceType = 1; /* default: recorder */
-
- hdmiFd = ::open("/dev/cec0", O_RDWR | O_CLOEXEC);
- if (hdmiFd >= 0)
- {
- __u32 monitor = CEC_MODE_INITIATOR | CEC_MODE_FOLLOWER;
- struct cec_caps caps = {};
-
- ::ioctl(hdmiFd, CEC_ADAP_G_CAPS, &caps);
-
- if (caps.capabilities & CEC_CAP_LOG_ADDRS)
- {
- struct cec_log_addrs laddrs = {};
-
- ::ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs);
- memset(&laddrs, 0, sizeof(laddrs));
-
- /*
- * NOTE: cec_version, osd_name and deviceType should be made configurable,
- * CEC_ADAP_S_LOG_ADDRS delayed till the desired values are available
- * (saves us some startup speed as well, polling for a free logical address
- * takes some time)
- */
- laddrs.cec_version = CEC_OP_CEC_VERSION_2_0;
- strcpy(laddrs.osd_name, "enigma2");
- laddrs.vendor_id = CEC_VENDOR_ID_NONE;
-
- switch (deviceType)
- {
- case CEC_LOG_ADDR_TV:
- laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TV;
- laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TV;
- laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TV;
- break;
- case CEC_LOG_ADDR_RECORD_1:
- laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_RECORD;
- laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_RECORD;
- laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_RECORD;
- break;
- case CEC_LOG_ADDR_TUNER_1:
- laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TUNER;
- laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TUNER;
- laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TUNER;
- break;
- case CEC_LOG_ADDR_PLAYBACK_1:
- laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_PLAYBACK;
- laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
- laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_PLAYBACK;
- break;
- case CEC_LOG_ADDR_AUDIOSYSTEM:
- laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM;
- laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
- laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
- break;
- default:
- laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
- laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_SWITCH;
- laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_SWITCH;
- break;
- }
- laddrs.num_log_addrs++;
-
- ::ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs);
- }
-
- ::ioctl(hdmiFd, CEC_S_MODE, &monitor);
-
- linuxCEC = true;
- }
-
- if (!linuxCEC)
- {
+ deviceType = CEC_LOG_ADDR_TYPE_TUNER; /* default: tuner */
#ifdef DREAMBOX
#define HDMIDEV "/dev/misc/hdmi_cec0"
#else
#define HDMIDEV "/dev/hdmi_cec"
#endif
- hdmiFd = ::open(HDMIDEV, O_RDWR | O_NONBLOCK | O_CLOEXEC);
- if (hdmiFd >= 0)
- {
-
+ hdmiFd = ::open(HDMIDEV, O_RDWR | O_NONBLOCK | O_CLOEXEC);
+ eTrace("[eHdmiCEC] ****** open HDMIDEV: %s hdmiFd: %d", HDMIDEV, hdmiFd);
+ if (hdmiFd >= 0)
+ {
#ifdef DREAMBOX
- unsigned int val = 0;
- ::ioctl(hdmiFd, 4, &val);
+ unsigned int val = 0;
+ ::ioctl(hdmiFd, 4, &val);
#else
- ::ioctl(hdmiFd, 0); /* flush old messages */
+ ::ioctl(hdmiFd, 0); /* flush old messages */
#endif
- }
- }
-
- if (hdmiFd >= 0)
- {
messageNotifier = eSocketNotifier::create(eApp, hdmiFd, eSocketNotifier::Read | eSocketNotifier::Priority);
CONNECT(messageNotifier->activated, eHdmiCEC::hdmiEvent);
+ getAddressInfo();
}
else
{
- eDebug("[eHdmiCEC] cannot open %s: %m", HDMIDEV);
+ eLog(1, "[eHdmiCEC] cannot open %s: %m", HDMIDEV); /* Error - should not happen */
}
-
- getAddressInfo();
}
eHdmiCEC::~eHdmiCEC()
@@ -191,71 +112,31 @@ void eHdmiCEC::getAddressInfo()
{
bool hasdata = false;
struct addressinfo addressinfo = {};
-
- if (linuxCEC)
+ if (::ioctl(hdmiFd, 1, &addressinfo) >= 0)
{
- __u16 phys_addr;
- struct cec_log_addrs laddrs = {};
-
- ::ioctl(hdmiFd, CEC_ADAP_G_PHYS_ADDR, &phys_addr);
- addressinfo.physical[0] = (phys_addr >> 8) & 0xff;
- addressinfo.physical[1] = phys_addr & 0xff;
-
- ::ioctl(hdmiFd, CEC_ADAP_G_LOG_ADDRS, &laddrs);
- addressinfo.logical = laddrs.log_addr[0];
-
- switch (laddrs.log_addr_type[0])
+ hasdata = true;
+#if DREAMBOX
+ /* we do not get the device type, check the logical address to determine the type */
+ switch (addressinfo.logical)
{
- case CEC_LOG_ADDR_TYPE_TV:
- addressinfo.type = CEC_LOG_ADDR_TV;
- break;
- case CEC_LOG_ADDR_TYPE_RECORD:
- addressinfo.type = CEC_LOG_ADDR_RECORD_1;
- break;
- case CEC_LOG_ADDR_TYPE_TUNER:
- addressinfo.type = CEC_LOG_ADDR_TUNER_1;
- break;
- case CEC_LOG_ADDR_TYPE_PLAYBACK:
- addressinfo.type = CEC_LOG_ADDR_PLAYBACK_1;
+ case 0x1:
+ case 0x2:
+ case 0x9:
+ addressinfo.type = 1; /* recorder */
break;
- case CEC_LOG_ADDR_TYPE_AUDIOSYSTEM:
- addressinfo.type = CEC_LOG_ADDR_AUDIOSYSTEM;
+ case 0x3:
+ case 0x6:
+ case 0x7:
+ case 0xa:
+ addressinfo.type = 3; /* tuner */
break;
- case CEC_LOG_ADDR_TYPE_UNREGISTERED:
- default:
- addressinfo.type = CEC_LOG_ADDR_UNREGISTERED;
+ case 0x4:
+ case 0x8:
+ case 0xb:
+ addressinfo.type = 4; /* playback */
break;
}
- hasdata = true;
- }
- else
- {
- if (::ioctl(hdmiFd, 1, &addressinfo) >= 0)
- {
- hasdata = true;
-#if DREAMBOX
- /* we do not get the device type, check the logical address to determine the type */
- switch (addressinfo.logical)
- {
- case 0x1:
- case 0x2:
- case 0x9:
- addressinfo.type = 1; /* recorder */
- break;
- case 0x3:
- case 0x6:
- case 0x7:
- case 0xa:
- addressinfo.type = 3; /* tuner */
- break;
- case 0x4:
- case 0x8:
- case 0xb:
- addressinfo.type = 4; /* playback */
- break;
- }
#endif
- }
}
if (hasdata)
{
@@ -265,7 +146,7 @@ void eHdmiCEC::getAddressInfo()
{
if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress)))
{
- eDebug("[eHdmiCEC] detected physical address change: %02X%02X --> %02X%02X", physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]);
+ eTrace("[eHdmiCEC] detected physical address change: %02X%02X --> %02X%02X", physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]);
memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress));
reportPhysicalAddress();
/* emit */ addressChanged((physicalAddress[0] << 8) | physicalAddress[1]);
@@ -292,11 +173,6 @@ void eHdmiCEC::setFixedPhysicalAddress(int address)
fixedAddress = true;
physicalAddress[0] = (address >> 8) & 0xff;
physicalAddress[1] = address & 0xff;
- if (linuxCEC)
- {
- __u16 phys_addr = address & 0xffff;
- ::ioctl(hdmiFd, CEC_ADAP_S_PHYS_ADDR, &phys_addr);
- }
/* report our (possibly new) address */
reportPhysicalAddress();
}
@@ -325,15 +201,6 @@ void eHdmiCEC::hdmiEvent(int what)
{
if (what & eSocketNotifier::Priority)
{
- if (linuxCEC)
- {
- struct cec_event cecevent;
- ::ioctl(hdmiFd, CEC_DQEVENT, &cecevent);
- if (cecevent.event == CEC_EVENT_STATE_CHANGE)
- {
- /* do not bother decoding the new address, just get the address in getAddressInfo */
- }
- }
getAddressInfo();
}
@@ -341,48 +208,35 @@ void eHdmiCEC::hdmiEvent(int what)
{
bool hasdata = false;
struct cec_rx_message rxmessage;
- if (linuxCEC)
+#ifdef DREAMBOX
+ if (::ioctl(hdmiFd, 2, &rxmessage) >= 0)
{
- struct cec_msg msg;
- if (::ioctl(hdmiFd, CEC_RECEIVE, &msg) >= 0)
- {
- rxmessage.length = msg.len - 1;
- memcpy(&rxmessage.data, &msg.msg[1], rxmessage.length);
- hasdata = true;
- }
+ hasdata = true;
}
- else
+ unsigned int val = 0;
+ ::ioctl(hdmiFd, 4, &val);
+#else
+ if (::read(hdmiFd, &rxmessage, 2) == 2)
{
-#ifdef DREAMBOX
- if (::ioctl(hdmiFd, 2, &rxmessage) >= 0)
+ if (::read(hdmiFd, &rxmessage.data, rxmessage.length) == rxmessage.length)
{
hasdata = true;
}
- unsigned int val = 0;
- ::ioctl(hdmiFd, 4, &val);
-#else
- if (::read(hdmiFd, &rxmessage, 2) == 2)
- {
- if (::read(hdmiFd, &rxmessage.data, rxmessage.length) == rxmessage.length)
- {
- hasdata = true;
- }
- }
-#endif
}
+#endif
bool hdmicec_enabled = eConfigManager::getConfigBoolValue("config.hdmicec.enabled", false);
if (hasdata && hdmicec_enabled)
{
bool keypressed = false;
static unsigned char pressedkey = 0;
- eDebugNoNewLineStart("[eHdmiCEC] received message");
- eDebugNoNewLine(" %02X", rxmessage.address);
+ eTraceNoNewLineStart("[eHdmiCEC] received message");
+ eTraceNoNewLine(" %02X", rxmessage.address);
for (int i = 0; i < rxmessage.length; i++)
{
- eDebugNoNewLine(" %02X", rxmessage.data[i]);
+ eTraceNoNewLine(" %02X", rxmessage.data[i]);
}
- eDebugNoNewLine("\n");
+ eTraceNoNewLine("\n");
bool hdmicec_report_active_menu = eConfigManager::getConfigBoolValue("config.hdmicec.report_active_menu", false);
if (hdmicec_report_active_menu)
{
@@ -522,7 +376,7 @@ long eHdmiCEC::translateKey(unsigned char code)
break;
default:
key = 0x8b;
- eDebug("eHdmiCEC: unknown code 0x%02X", (unsigned int)(code & 0xFF));
+ eTrace("eHdmiCEC: unknown code 0x%02X", (unsigned int)(code & 0xFF));
break;
}
return key;
@@ -532,31 +386,19 @@ void eHdmiCEC::sendMessage(struct cec_message &message)
{
if (hdmiFd >= 0)
{
- eDebugNoNewLineStart("[eHdmiCEC] send message");
- eDebugNoNewLine(" %02X", message.address);
+ eTraceNoNewLineStart("[eHdmiCEC] send message");
+ eTraceNoNewLine(" %02X", message.address);
for (int i = 0; i < message.length; i++)
{
- eDebugNoNewLine(" %02X", message.data[i]);
+ eTraceNoNewLine(" %02X", message.data[i]);
}
- eDebugNoNewLine("\n");
- if (linuxCEC)
- {
- struct cec_msg msg;
- cec_msg_init(&msg, logicalAddress, message.address);
- memcpy(&msg.msg[1], message.data, message.length);
- msg.len = message.length + 1;
- ::ioctl(hdmiFd, CEC_TRANSMIT, &msg);
- }
- else
- {
+ eTraceNoNewLine("\n");
#ifdef DREAMBOX
- message.flag = 1;
- ::ioctl(hdmiFd, 3, &message);
+ message.flag = 1;
+ ::ioctl(hdmiFd, 3, &message);
#else
- ssize_t ret = ::write(hdmiFd, &message, 2 + message.length);
- if (ret < 0) eDebug("[eHdmiCEC] write failed: %m");
+ ::write(hdmiFd, &message, 2 + message.length);
#endif
- }
}
}
diff --git a/lib/driver/hdmi_cec.h b/lib/driver/hdmi_cec.h
index e840ba62ddd..e1a0211e241 100644
--- a/lib/driver/hdmi_cec.h
+++ b/lib/driver/hdmi_cec.h
@@ -104,7 +104,6 @@ class eHdmiCEC : public eRCDriver
#endif
protected:
static eHdmiCEC *instance;
- bool linuxCEC;
unsigned char physicalAddress[2];
bool fixedAddress;
unsigned char deviceType, logicalAddress;
diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp
index f349e820937..6cce169b66b 100644
--- a/lib/dvb/db.cpp
+++ b/lib/dvb/db.cpp
@@ -19,6 +19,8 @@
#include
#include
#include
+#include
+#include
/*
* Copyright (C) 2017 Marcus Metzler
@@ -140,9 +142,18 @@ RESULT eBouquet::flushChanges()
std::string str = tmp.path;
if ( fprintf(f, "#SERVICE %s\r\n", tmp.toString().c_str()) < 0 )
goto err;
- if ( i->name.length() )
- if ( fprintf(f, "#DESCRIPTION %s\r\n", i->name.c_str()) < 0 )
+ if ( i->name.length() ) {
+ std::string fullName = i->name;
+ std::string provPart = "•";
+ if (i->prov.length())
+ {
+ provPart += i->prov;
+ if (fullName.find(provPart) == std::string::npos)
+ fullName += provPart;
+ }
+ if ( fprintf(f, "#DESCRIPTION %s\r\n", fullName.c_str()) < 0 )
goto err;
+ }
}
f.sync();
}
@@ -800,6 +811,65 @@ void eDVBDB::loadServiceListV5(FILE * f)
eDebug("[eDVBDB] loaded %d channels/transponders and %d services", tcount, scount);
}
+void eDVBDB::resetLcnDB()
+{
+ m_lcnmap.clear();
+ FILE *m_lcn_file = fopen(eEnv::resolve("${sysconfdir}/enigma2/lcndb").c_str(), "w");
+ if (m_lcn_file)
+ fclose(m_lcn_file);
+}
+
+void eDVBDB::saveLcnDB()
+{
+ std::string lfname = eEnv::resolve("${sysconfdir}/enigma2/lcndb");
+ CFile lf(lfname, "w");
+ if (lf)
+ {
+ for (auto &[key, value] : m_lcnmap)
+ {
+ value.write(lf, key);
+ }
+ }
+}
+
+void eDVBDB::addLcnToDB(int ns, int onid, int tsid, int sid, uint16_t lcn, uint32_t signal)
+{
+ eServiceReferenceDVB s = eServiceReferenceDVB(eDVBNamespace(ns), eTransportStreamID(tsid), eOriginalNetworkID(onid), eServiceID(sid), 0);
+ std::map::iterator it = m_lcnmap.find(s);
+ if (it != m_lcnmap.end())
+ {
+ it->second.Update(lcn, signal);
+ }
+ else
+ {
+ LCNData lcndata;
+ lcndata.Update(lcn, signal);
+ m_lcnmap.insert(std::pair(s, lcndata));
+ }
+}
+
+void eDVBDB::readLcnDBFile()
+{
+ char line[256];
+ m_lcnmap.clear();
+ std::string lfname = eEnv::resolve("${sysconfdir}/enigma2/lcndb");
+ CFile lf(lfname, "rt");
+ if(lf)
+ {
+ while (!feof(lf))
+ {
+ if (!fgets(line, sizeof(line), lf))
+ break;
+
+ LCNData lcndata;
+ eServiceReferenceDVB s = lcndata.parse(line);
+ if (s)
+ m_lcnmap.insert(std::pair(s, lcndata));
+
+ }
+ }
+}
+
void eDVBDB::loadServicelist(const char *file)
{
eDebug("[eDVBDB] ---- opening lame channel db");
@@ -828,6 +898,8 @@ void eDVBDB::loadServicelist(const char *file)
eDebug("[eDVBDB] services invalid, no transponders");
return;
}
+
+ readLcnDBFile();
// clear all transponders
int tcount = 0;
while (!feof(f))
@@ -1109,6 +1181,7 @@ void eDVBDB::saveServicelist(const char *file)
void eDVBDB::saveServicelist()
{
saveServicelist(eEnv::resolve("${sysconfdir}/enigma2/lamedb").c_str());
+ saveLcnDB();
}
void eDVBDB::saveIptvServicelist()
@@ -1124,6 +1197,29 @@ void eDVBDB::saveIptvServicelist()
outputFile.close();
}
+void eDVBDB::deleteBouquet(const std::string filename)
+{
+ std::string p = eEnv::resolve("${sysconfdir}/enigma2/");
+ DIR *dir = opendir(p.c_str());
+ if (!dir)
+ {
+ eDebug("[eDVBDB] Cannot open directory where the userbouquets should be expected..");
+ return;
+ }
+ dirent *entry;
+ while((entry = readdir(dir)) != NULL)
+ if (entry->d_type == DT_REG)
+ {
+ std::string path = entry->d_name;
+ if (path.find(filename) != std::string::npos)
+ {
+ std::remove(path.c_str());
+ m_bouquets.erase(filename);
+ }
+ }
+ closedir(dir);
+}
+
void eDVBDB::loadBouquet(const char *path)
{
std::vector userbouquetsfiles;
@@ -1300,7 +1396,7 @@ void eDVBDB::loadBouquet(const char *path)
{
for(unsigned int i=0; i 0)
{
eDebug("[eDVBDB] Adding additional userbouquet %s", userbouquetsfiles[i].c_str());
char buf[256];
@@ -1310,7 +1406,7 @@ void eDVBDB::loadBouquet(const char *path)
snprintf(buf, sizeof(buf), "1:7:2:0:0:0:0:0:0:0:FROM BOUQUET \"%s\" ORDER BY bouquet", userbouquetsfiles[i].c_str());
eServiceReference tmp(buf);
loadBouquet(userbouquetsfiles[i].c_str());
- if (!strcmp(userbouquetsfiles[i].c_str(), "userbouquet.LastScanned.tv"))
+ if (!strcmp(userbouquetsfiles[i].c_str(), "userbouquet.LastScanned.tv") || m_load_unlinked_userbouquets == 2)
list.push_back(tmp);
else
list.push_front(tmp);
@@ -1422,7 +1518,7 @@ int eDVBDB::renumberBouquet(eBouquet &bouquet, int startChannelNum)
eDVBDB *eDVBDB::instance;
eDVBDB::eDVBDB()
- : m_numbering_mode(false), m_load_unlinked_userbouquets(true)
+ : m_numbering_mode(false), m_load_unlinked_userbouquets(1)
{
instance = this;
@@ -2120,6 +2216,30 @@ PyObject *eDVBDB::readATSC(ePyObject atsc_list, ePyObject tp_dict)
return Py_True;
}
+PyObject *eDVBDB::getLcnDBData()
+{
+ ePyObject dest = PyList_New(0);
+ if (dest)
+ {
+ std::map::iterator it = m_lcnmap.begin();
+ for (;it != m_lcnmap.end();++it)
+ {
+ ePyObject tuple = PyTuple_New(6);
+ PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong((unsigned long)it->second.NS));
+ PyTuple_SET_ITEM(tuple, 1, PyLong_FromLongLong((unsigned long)it->second.ONID));
+ PyTuple_SET_ITEM(tuple, 2, PyLong_FromLongLong((unsigned long)it->second.TSID));
+ PyTuple_SET_ITEM(tuple, 3, PyLong_FromLongLong((unsigned long)it->second.SID));
+ PyTuple_SET_ITEM(tuple, 4, PyLong_FromLongLong((unsigned long)it->second.LCN));
+ PyTuple_SET_ITEM(tuple, 5, PyLong_FromLongLong((unsigned long)it->second.SIGNAL));
+ PyList_Append(dest, tuple);
+ Py_DECREF(tuple);
+ }
+ }
+ else
+ Py_RETURN_NONE;
+ return dest;
+}
+
eDVBDB::~eDVBDB()
{
instance=NULL;
@@ -2417,6 +2537,227 @@ RESULT eDVBDB::removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned i
return 0;
}
+RESULT eDVBDB::addOrUpdateBouquet(const std::string &name, ePyObject services, const int type, bool isAddedFirst)
+{
+ std::string ext = ".tv";
+ if (type == 2) {
+ ext = ".radio";
+ }
+ std::string filename = "userbouquet." + name + ext;
+ return addOrUpdateBouquet(name, filename, services, isAddedFirst);
+}
+
+RESULT eDVBDB::addOrUpdateBouquet(const std::string &name, const std::string &filename, ePyObject services, bool isAddedFirst)
+{
+ std::string ext = ".tv";
+ int type = 1;
+ if (filename.find(".radio") != std::string::npos) {
+ ext = ".radio";
+ type = 2;
+ }
+ ePtr db;
+ ePtr res;
+ eDVBResourceManager::getInstance(res);
+ res->getChannelList(db);
+ std::string bouquetquery = "FROM BOUQUET \"" + filename + "\" ORDER BY bouquet";
+ eServiceReference bouquetref(eServiceReference::idDVB, eServiceReference::flagDirectory, bouquetquery);
+ bouquetref.setData(0, type);
+ eBouquet *bouquet = NULL;
+ eServiceReference rootref(eServiceReference::idDVB, eServiceReference::flagDirectory, "FROM BOUQUET \"bouquets" + ext + "\" ORDER BY bouquet");
+ if (!db->getBouquet(bouquetref, bouquet) && bouquet)
+ {
+ bouquet->m_services.clear();
+ }
+ else
+ {
+ /* bouquet doesn't yet exist, create a new one */
+ if (!db->getBouquet(rootref, bouquet) && bouquet)
+ {
+ if (isAddedFirst)
+ bouquet->m_services.push_front(bouquetref);
+ else
+ bouquet->m_services.push_back(bouquetref);
+ bouquet->flushChanges();
+ }
+ /* loading the bouquet seems to be the only way to add it to the bouquet list */
+ loadBouquet(filename.c_str());
+ /* and now that it has been added to the list, we can find it */
+ db->getBouquet(bouquetref, bouquet);
+ bouquet->setListName(name);
+ }
+ if (!PyList_Check(services)) {
+ const char *errstr = "eDVBDB::appendServicesToBouquet second parameter is not a python list!!!";
+ PyErr_SetString(PyExc_TypeError, errstr);
+ return -1;
+ }
+ int size = PyList_Size(services);
+ while(size)
+ {
+ --size;
+ ePyObject refstr = PyList_GET_ITEM(services, size);
+ if (!PyUnicode_Check(refstr))
+ {
+ char buf[255];
+ snprintf(buf, 255, "eDVBDB::appendServicesToBouquet entry in service list is not a string.. it is '%s'!!", PyObject_Type(refstr));
+ PyErr_SetString(PyExc_TypeError, buf);
+ return -1;
+ }
+ const char *tmpstr = PyUnicode_AsUTF8(refstr);
+ eDebug("[eDVBDB] ParsedReference: %s", tmpstr);
+ eServiceReference ref(tmpstr);
+ if (ref.valid())
+ {
+ eDebug("eDVBDB::appendServicesToBouquet push ref %s", tmpstr);
+ bouquet->m_services.push_front(ref);
+ }
+ else
+ eDebug("[DB] eDVBDB::appendServicesToBouquet '%s' is not a valid service reference... ignore!!", tmpstr);
+ }
+
+ bouquet->flushChanges();
+ renumberBouquet();
+ return 0;
+}
+
+RESULT eDVBDB::appendServicesToBouquet(const std::string &filename, ePyObject services)
+{
+ std::string ext = ".tv";
+ int type = 1;
+ if (filename.find(".radio") != std::string::npos) {
+ ext = ".radio";
+ type = 2;
+ }
+ ePtr db;
+ ePtr res;
+ eDVBResourceManager::getInstance(res);
+ res->getChannelList(db);
+ std::string bouquetquery = "FROM BOUQUET \"" + filename + "\" ORDER BY bouquet";
+ eServiceReference bouquetref(eServiceReference::idDVB, eServiceReference::flagDirectory, bouquetquery);
+ bouquetref.setData(0, type);
+ eBouquet *bouquet = NULL;
+ if (!db->getBouquet(bouquetref, bouquet) && bouquet)
+ {
+
+ if (!PyList_Check(services)) {
+ const char *errstr = "eDVBDB::appendServicesToBouquet second parameter is not a python list!!!";
+ PyErr_SetString(PyExc_TypeError, errstr);
+ return -1;
+ }
+ int size = PyList_Size(services);
+ while(size)
+ {
+ --size;
+ ePyObject refstr = PyList_GET_ITEM(services, size);
+ if (!PyUnicode_Check(refstr))
+ {
+ char buf[255];
+ snprintf(buf, 255, "eDVBDB::appendServicesToBouquet entry in service list is not a string.. it is '%s'!!", PyObject_Type(refstr));
+ PyErr_SetString(PyExc_TypeError, buf);
+ return -1;
+ }
+ const char *tmpstr = PyUnicode_AsUTF8(refstr);
+ //eDebug("[eDVBDB] ParsedReference: %s", tmpstr);
+ eServiceReference ref(tmpstr);
+ if (ref.valid())
+ {
+ eDebug("eDVBDB::appendServicesToBouquet push ref %s", tmpstr);
+ bouquet->m_services.push_front(ref);
+ }
+ else
+ eDebug("[DB] eDVBDB::appendServicesToBouquet '%s' is not a valid service reference... ignore!!", tmpstr);
+ }
+ bouquet->flushChanges();
+ renumberBouquet();
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+RESULT eDVBDB::removeBouquet(const std::string &filename)
+{
+ std::string ext = ".tv";
+ int type = 1;
+ if (filename.find(".radio") != std::string::npos) {
+ ext = ".radio";
+ type = 2;
+ }
+ ePtr db;
+ ePtr res;
+ eDVBResourceManager::getInstance(res);
+ res->getChannelList(db);
+ std::string bouquetquery = "FROM BOUQUET \"" + filename + "\" ORDER BY bouquet";
+ eServiceReference bouquetref(eServiceReference::idDVB, eServiceReference::flagDirectory, bouquetquery);
+ bouquetref.setData(0, type);
+ eBouquet *bouquet = NULL;
+ eServiceReference rootref(eServiceReference::idDVB, eServiceReference::flagDirectory, "FROM BOUQUET \"bouquets" + ext + "\" ORDER BY bouquet");
+ if (!db->getBouquet(bouquetref, bouquet) && bouquet)
+ {
+ if (!db->getBouquet(rootref, bouquet) && bouquet)
+ {
+ bouquet->m_services.remove(bouquetref);
+ bouquet->flushChanges();
+ deleteBouquet(filename);
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ return 0;
+}
+
+RESULT eDVBDB::addChannelToDB(const eServiceReference &service, const eDVBFrontendParameters &feparam, SWIG_PYOBJECT(ePyObject) cachedPids, SWIG_PYOBJECT(ePyObject) caPids, const int serviceFlags)
+{
+ const eServiceReferenceDVB &sref = (const eServiceReferenceDVB&)service;
+ eDVBFrontendParameters *feparam_ptr = const_cast(&feparam);
+ eDVBChannelID chid;
+ sref.getChannelID(chid);
+ addChannelToList(chid, feparam_ptr);
+ ePtr s = new eDVBService;
+ s->m_service_name = service.getName();
+ s->m_provider_name = service.getProvider();
+ s->genSortName();
+ s->m_flags = serviceFlags;
+ if (PyList_Check(cachedPids)) {
+ int size = PyList_Size(cachedPids);
+ while(size)
+ {
+ --size;
+ ePyObject cachedPidTupleObj = PyList_GET_ITEM(cachedPids, size);
+ if (PyTuple_Check(cachedPidTupleObj) && PyTuple_Size(cachedPidTupleObj) == 2)
+ {
+ ePyObject cIDObj = PyTuple_GET_ITEM(cachedPidTupleObj, 0);
+ ePyObject cachedPidValObj = PyTuple_GET_ITEM(cachedPidTupleObj, 1);
+ if (PyLong_Check(cIDObj) && PyLong_Check(cachedPidValObj))
+ {
+ int cID = PyLong_AsLong(cIDObj);
+ int cPid = PyLong_AsLong(cachedPidValObj);
+ s->setCacheEntry((eDVBService::cacheID)cID, cPid);
+ }
+ }
+ }
+ }
+ CAID_LIST m_ca;
+ if (PyList_Check(caPids)) {
+ int size = PyList_Size(caPids);
+ while(size)
+ {
+ --size;
+ ePyObject caPidObj = PyList_GET_ITEM(caPids, size);
+ if (PyLong_Check(caPidObj))
+ {
+ int caPid = PyLong_AsLong(caPidObj);
+ m_ca.push_back((uint16_t)caPid);
+ }
+ }
+ }
+ s->m_ca = m_ca;
+ addOrUpdateService(sref, s);
+ return 0;
+}
+
RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm)
{
channel ch;
@@ -2456,6 +2797,16 @@ RESULT eDVBDB::addService(const eServiceReferenceDVB &serviceref, eDVBService *s
return 0;
}
+RESULT eDVBDB::addOrUpdateService(const eServiceReferenceDVB &serviceref, eDVBService *service)
+{
+ std::map >::iterator it(m_services.find(serviceref));
+ if (it == m_services.end())
+ m_services.insert(std::pair >(serviceref, service));
+ else
+ it->second = service;
+ return 0;
+}
+
RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr &service)
{
std::map >::iterator i;
@@ -2469,6 +2820,12 @@ RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr &data)
+{
+ data = m_lcnmap;
+ return 0;
+}
+
RESULT eDVBDB::flush()
{
saveServicelist();
diff --git a/lib/dvb/db.h b/lib/dvb/db.h
index 8501ea3be78..62ae8264823 100644
--- a/lib/dvb/db.h
+++ b/lib/dvb/db.h
@@ -7,8 +7,75 @@
#include
#include
#include
+#include
class ServiceDescriptionSection;
+struct LCNData
+{
+private:
+ bool FOUND;
+
+ std::vector split_str(std::string s)
+ {
+ std::vector tokens;
+ std::string token;
+ std::stringstream str(s);
+ while (getline(str, token, ':')) {
+ tokens.push_back(token);
+ }
+ return tokens;
+ }
+
+public:
+ int NS;
+ int ONID;
+ int TSID;
+ int SID;
+ int SIGNAL;
+ int LCN;
+ LCNData()
+ {
+ LCN = 0;
+ SIGNAL = -1;
+ FOUND = true;
+ }
+
+ eServiceReferenceDVB parse(const char *line)
+ {
+
+ if (sscanf(line, "%x:%x:%x:%x:%d:%d", &NS, &ONID, &TSID, &SID, &LCN, &SIGNAL) == 6)
+ return eServiceReferenceDVB(eDVBNamespace(NS), eTransportStreamID(TSID), eOriginalNetworkID(ONID), eServiceID(SID), 0);
+ else
+ return eServiceReferenceDVB();
+
+ }
+
+ void Update(uint16_t lcn, uint32_t signal)
+ {
+ LCN = lcn;
+ SIGNAL = signal;
+ FOUND = true;
+ }
+
+ void write(FILE *lf, const eServiceReferenceDVB &key)
+ {
+ if (FOUND)
+ {
+ int sid = key.getServiceID().get();
+ int tsid = key.getTransportStreamID().get();
+ int onid = key.getOriginalNetworkID().get();
+ int ns = key.getDVBNamespace().get();
+ fprintf(lf, "%x:%x:%x:%x:%d:%d\n", ns, onid, tsid, sid, LCN, SIGNAL);
+ }
+ }
+
+ void resetFound()
+ {
+ FOUND = false;
+ }
+
+};
+
class eIPTVDBItem
{
public:
@@ -58,13 +125,15 @@ class eDVBDB: public iDVBChannelList
std::map m_bouquets;
- bool m_numbering_mode, m_load_unlinked_userbouquets;
+ bool m_numbering_mode;
+ int m_load_unlinked_userbouquets;
#ifdef SWIG
eDVBDB();
~eDVBDB();
#endif
private:
void loadServiceListV5(FILE * f);
+ std::map m_lcnmap;
public:
std::vector iptv_services;
// iDVBChannelList
@@ -78,11 +147,17 @@ class eDVBDB: public iDVBChannelList
RESULT addCAID(const eServiceReference &service, unsigned int caid);
RESULT addFlag(const eServiceReference &service, unsigned int flagmask);
RESULT removeFlag(const eServiceReference &service, unsigned int flagmask);
+ RESULT addOrUpdateBouquet(const std::string &name, const std::string &filename, SWIG_PYOBJECT(ePyObject) services, bool isAddedFirst = false);
+ RESULT addOrUpdateBouquet(const std::string &name, SWIG_PYOBJECT(ePyObject) services, const int type, bool isAddedFirst = false);
+ RESULT appendServicesToBouquet(const std::string &filename, SWIG_PYOBJECT(ePyObject) services);
+ RESULT removeBouquet(const std::string &filename);
+ RESULT addChannelToDB(const eServiceReference &service, const eDVBFrontendParameters &feparam, SWIG_PYOBJECT(ePyObject) cachedPids, SWIG_PYOBJECT(ePyObject) caPids, const int serviceFlags);
void removeServicesFlag(unsigned int flagmask);
PyObject *readSatellites(SWIG_PYOBJECT(ePyObject) sat_list, SWIG_PYOBJECT(ePyObject) sat_dict, SWIG_PYOBJECT(ePyObject) tp_dict);
PyObject *readTerrestrials(SWIG_PYOBJECT(ePyObject) ter_list, SWIG_PYOBJECT(ePyObject) tp_dict);
PyObject *readCables(SWIG_PYOBJECT(ePyObject) cab_list, SWIG_PYOBJECT(ePyObject) tp_dict);
PyObject *readATSC(SWIG_PYOBJECT(ePyObject) atsc_list, SWIG_PYOBJECT(ePyObject) tp_dict);
+ PyObject *getLcnDBData();
#ifndef SWIG
RESULT removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned int orb_pos);
RESULT removeServices(eDVBChannelID chid, unsigned int orb_pos);
@@ -94,7 +169,9 @@ class eDVBDB: public iDVBChannelList
RESULT getChannelFrontendData(const eDVBChannelID &id, ePtr &parm);
RESULT addService(const eServiceReferenceDVB &referenc, eDVBService *service);
+ RESULT addOrUpdateService(const eServiceReferenceDVB &referenc, eDVBService *service);
RESULT getService(const eServiceReferenceDVB &reference, ePtr &service);
+ RESULT getLcnDBData(std::map &data);
RESULT flush();
RESULT startQuery(ePtr &query, eDVBChannelQuery *q, const eServiceReference &source);
@@ -102,14 +179,18 @@ class eDVBDB: public iDVBChannelList
RESULT getBouquet(const eServiceReference &ref, eBouquet* &bouquet);
//////
void loadBouquet(const char *path);
+ void deleteBouquet(const std::string filename);
void searchAllReferences(std::vector &result, int tsid, int onid, int sid);
eDVBDB();
virtual ~eDVBDB();
int renumberBouquet(eBouquet &bouquet, int startChannelNum = 1);
+ void addLcnToDB(int ns, int onid, int tsid, int sid, uint16_t lcn, uint32_t signal);
+ void resetLcnDB();
+ void readLcnDBFile();
#endif
eServiceReference searchReference(int tsid, int onid, int sid);
void setNumberingMode(bool numberingMode);
- void setLoadUnlinkedUserbouquets(bool value) { m_load_unlinked_userbouquets=value; }
+ void setLoadUnlinkedUserbouquets(int value) { m_load_unlinked_userbouquets=value; }
void renumberBouquet();
void loadServicelist(const char *filename);
static eDVBDB *getInstance() { return instance; }
@@ -117,6 +198,7 @@ class eDVBDB: public iDVBChannelList
void saveServicelist();
void saveIptvServicelist();
void saveServicelist(const char *file);
+ void saveLcnDB();
void reloadBouquets();
void parseServiceData(ePtr s, std::string str);
};
diff --git a/lib/dvb/epgcache.h b/lib/dvb/epgcache.h
index ecabba4d6fd..11b6860d548 100644
--- a/lib/dvb/epgcache.h
+++ b/lib/dvb/epgcache.h
@@ -187,6 +187,10 @@ class eEPGCache: public eMainloop, private eThread, public sigc::trackable
void timeUpdated();
void flushEPG(const uniqueEPGKey & s=uniqueEPGKey(), bool lock = true);
void reloadEITConfig(int listType);
+
+ /* Only used by servicedvbrecord.cpp to write the EIT file and Components.Timeshift.py*/
+ RESULT saveEventToFile(const char* filename, const eServiceReference &service, int eit_event_id, time_t begTime, time_t endTime);
+
#ifndef SWIG
eEPGCache();
~eEPGCache();
@@ -205,9 +209,6 @@ class eEPGCache: public eMainloop, private eThread, public sigc::trackable
RESULT lookupEventTime(const eServiceReference &service, time_t, const eventData *&, int direction=0);
public:
- /* Only used by servicedvbrecord.cpp to write the EIT file */
- RESULT saveEventToFile(const char* filename, const eServiceReference &service, int eit_event_id, time_t begTime, time_t endTime);
-
// Events are parsed epg events.. it's safe to use them after cache unlock
// after use the Event pointer must be released using "delete".
RESULT lookupEventId(const eServiceReference &service, int event_id, Event* &);
diff --git a/lib/dvb/scan.cpp b/lib/dvb/scan.cpp
index 86ebfe874f6..e4fde496eaa 100644
--- a/lib/dvb/scan.cpp
+++ b/lib/dvb/scan.cpp
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -23,6 +24,7 @@
#include
#include
#include
+#include
#include
#include "absdiff.h"
@@ -762,6 +764,9 @@ void eDVBScan::channelDone()
(*tsinfo)->getOriginalNetworkId());
bool T2 = false;
eDVBFrontendParametersTerrestrial t2transponder;
+ eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
+ eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
+ eDVBNamespace ns(0);
for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
desc != (*tsinfo)->getDescriptors()->end(); ++desc)
@@ -778,6 +783,10 @@ void eDVBScan::channelDone()
cable.set(d);
feparm->setDVBC(cable);
+ unsigned long hash=0;
+ feparm->getHash(hash);
+ ns = buildNamespace(onid, tsid, hash);
+
addChannelToScan(feparm);
break;
}
@@ -790,10 +799,19 @@ void eDVBScan::channelDone()
eDVBFrontendParametersTerrestrial terr;
terr.set(d);
feparm->setDVBT(terr);
+
+ unsigned long hash=0;
+ feparm->getHash(hash);
+ ns = buildNamespace(onid, tsid, hash);
addChannelToScan(feparm);
break;
}
+ case LOGICAL_CHANNEL_DESCRIPTOR:
+ {
+ // we handle it later
+ break;
+ }
case S2_SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
{
eDebug("[eDVBScan] S2_SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR found");
@@ -863,6 +881,18 @@ void eDVBScan::channelDone()
T2DeliverySystemDescriptor &d = (T2DeliverySystemDescriptor&)**desc;
t2transponder.set(d);
+ // fetch T2 namespace for LCN output, where frequency data may not be in SI table
+ ePtr fe;
+ ePtr trdata;
+ if (!m_channel->getFrontend(fe))
+ {
+ fe->getTransponderData(trdata, true);
+ int freq = trdata->getFrequency();
+ long hash = 0xEEEE0000;
+ hash |= (freq/1000000)&0xFFFF;
+ ns = buildNamespace(onid, tsid, hash); // used in case LOGICAL_CHANNEL_DESCRIPTOR
+ } // end fetch T2 namespace
+
for (T2CellConstIterator cell = d.getCells()->begin();
cell != d.getCells()->end(); ++cell)
{
@@ -904,6 +934,42 @@ void eDVBScan::channelDone()
break;
}
}
+ // we do this after the main loop because we absolutely need the namespace
+ for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
+ desc != (*tsinfo)->getDescriptors()->end(); ++desc)
+ {
+ switch ((*desc)->getTag())
+ {
+ case LOGICAL_CHANNEL_DESCRIPTOR:
+ {
+ if (!(system == iDVBFrontend::feTerrestrial || system == iDVBFrontend::feCable))
+ break; // when current locked transponder is not terrestrial or cable ignore this descriptor
+
+ if (ns.get() == 0)
+ break; // invalid namespace
+
+ int signal = 0;
+ ePtr fe;
+
+ if (!m_channel->getFrontend(fe))
+ signal = fe->readFrontendData(iFrontendInformation_ENUMS::signalQuality);
+
+ LogicalChannelDescriptor &d = (LogicalChannelDescriptor&)**desc;
+ for (LogicalChannelListConstIterator it = d.getChannelList()->begin(); it != d.getChannelList()->end(); it++)
+ {
+ LogicalChannel *ch = *it;
+ if (ch->getVisibleServiceFlag())
+ {
+ eDVBDB::getInstance()->addLcnToDB(ns.get(), onid.get(), tsid.get(), eServiceID(ch->getServiceId()).get(), ch->getLogicalChannelNumber(), signal);
+ SCAN_eDebug("NAMESPACE: %08x ONID: %04x TSID: %04x SID: %04x LCN: %05d SIGNAL: %08d", ns.get(), onid.get(), tsid.get(), ch->getServiceId(), ch->getLogicalChannelNumber(), signal);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
}
}
@@ -1168,6 +1234,12 @@ void eDVBScan::start(const eSmartPtrList &known_transpon
transponderlist = &m_ch_blindscan;
}
+ if (m_flags & scanRemoveServices)
+ {
+ eDVBDB::getInstance()->resetLcnDB();
+ }
+
+
for (eSmartPtrList::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
{
bool exist=false;
diff --git a/lib/dvb/sec.cpp b/lib/dvb/sec.cpp
index 8d64f946403..adb85d29ac9 100644
--- a/lib/dvb/sec.cpp
+++ b/lib/dvb/sec.cpp
@@ -1153,7 +1153,7 @@ void eDVBSatelliteEquipmentControl::prepareTurnOffSatCR(iDVBFrontend &frontend)
sec_sequence.push_back( eSecCommand(eSecCommand::IF_VOLTAGE_GOTO, compare) );
sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage13) );
- sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS]) );
+ sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, m_params[UNICABLE_DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS] > m_lnbs[m_lnbidx].boot_up_time ? m_params[UNICABLE_DELAY_AFTER_ENABLE_VOLTAGE_BEFORE_SWITCH_CMDS] : m_lnbs[m_lnbidx].boot_up_time ) );
sec_sequence.push_back( eSecCommand(eSecCommand::SET_VOLTAGE, iDVBFrontend::voltage18_5) );
sec_sequence.push_back( eSecCommand(eSecCommand::SET_TONE, iDVBFrontend::toneOff) );
@@ -1171,7 +1171,7 @@ void eDVBSatelliteEquipmentControl::prepareTurnOffSatCR(iDVBFrontend &frontend)
// data[3] "data1": data[3][7..5]: user band, data[3][4..2]: bank, data[3][1..0]: T[9..8]
// data[4] "data2": data[4][7..0]: T[7..0]
- unsigned int ub = userband & 0x01;
+ unsigned int ub = userband & 0x07;
unsigned int encoded_frequency_T = 0;
unsigned int mode = 0;
unsigned int position = 0;
diff --git a/lib/dvb/volume.cpp b/lib/dvb/volume.cpp
index 380751c2bc6..78d9292371a 100644
--- a/lib/dvb/volume.cpp
+++ b/lib/dvb/volume.cpp
@@ -38,6 +38,7 @@ eDVBVolumecontrol* eDVBVolumecontrol::getInstance()
}
eDVBVolumecontrol::eDVBVolumecontrol()
+:m_volsteps(5)
{
#ifdef HAVE_ALSA
mainVolume = NULL;
@@ -110,14 +111,19 @@ void eDVBVolumecontrol::closeMixer(int fd)
#endif
}
+void eDVBVolumecontrol::setVolumeSteps(int steps)
+{
+ m_volsteps = steps;
+}
+
void eDVBVolumecontrol::volumeUp(int left, int right)
{
- setVolume(leftVol + left, rightVol + right);
+ setVolume(leftVol + (left ? left : m_volsteps), rightVol + (right ? right : m_volsteps));
}
void eDVBVolumecontrol::volumeDown(int left, int right)
{
- setVolume(leftVol - left, rightVol - right);
+ setVolume(leftVol - (left ? left : m_volsteps), rightVol - (right ? right : m_volsteps));
}
int eDVBVolumecontrol::checkVolume(int vol)
diff --git a/lib/dvb/volume.h b/lib/dvb/volume.h
index 7e4f364512e..a574edb8b73 100644
--- a/lib/dvb/volume.h
+++ b/lib/dvb/volume.h
@@ -24,14 +24,16 @@ class eDVBVolumecontrol
bool muted;
int leftVol, rightVol;
+ int m_volsteps;
int checkVolume(int vol);
public:
static eDVBVolumecontrol* getInstance();
- void volumeUp(int left = 5, int right = 5);
- void volumeDown(int left = 5, int right = 5);
+ void setVolumeSteps(int steps);
+ void volumeUp(int left = 0, int right = 0);
+ void volumeDown(int left = 0, int right = 0);
void setVolume(int left, int right);
diff --git a/lib/dvb_ci/dvbci.cpp b/lib/dvb_ci/dvbci.cpp
index a744ae6a70b..68be817c347 100644
--- a/lib/dvb_ci/dvbci.cpp
+++ b/lib/dvb_ci/dvbci.cpp
@@ -1386,10 +1386,6 @@ eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
snprintf(config_key_operator_profile, 255, "config.ci.%d.disable_operator_profile", slotid);
bool operator_profile_disabled = eSimpleConfig::getBool(config_key_operator_profile, false);
m_operator_profiles_disabled = operator_profile_disabled;
- char config_key_ca0_excluded[255];
- snprintf(config_key_ca0_excluded, 255, "config.ci.%d.exclude_ca0_device", slotid);
- bool ca0_excluded = eSimpleConfig::getBool(config_key_ca0_excluded, false);
- m_ca0_excluded = ca0_excluded;
if (enabled)
openDevice();
else
diff --git a/lib/dvb_ci/dvbci.h b/lib/dvb_ci/dvbci.h
index 5d11f624b45..b940cf6ab7e 100644
--- a/lib/dvb_ci/dvbci.h
+++ b/lib/dvb_ci/dvbci.h
@@ -78,7 +78,6 @@ class eDVBCISlot: public iObject, public sigc::trackable
eMainloop *m_context;
int m_ciplus_routing_tunernum;
bool m_operator_profiles_disabled;
- bool m_ca0_excluded;
std::string m_ciplus_routing_input;
std::string m_ciplus_routing_ci_input;
@@ -131,7 +130,6 @@ class eDVBCISlot: public iObject, public sigc::trackable
int getNumOfServices();
int getVersion();
bool getIsOperatorProfileDisabled() { return m_operator_profiles_disabled; };
- bool getIsCA0Excluded() { return m_ca0_excluded; };
int16_t getCADemuxID() { return m_ca_demux_id; };
int getTunerNum() { return m_tunernum; };
int getUseCount() { return use_count; };
diff --git a/lib/dvb_ci/dvbci_appmgr.cpp b/lib/dvb_ci/dvbci_appmgr.cpp
index 482ebdd08aa..b45f6b3c040 100644
--- a/lib/dvb_ci/dvbci_appmgr.cpp
+++ b/lib/dvb_ci/dvbci_appmgr.cpp
@@ -4,6 +4,8 @@
#include
#include
#include
+#include
+#include
eDVBCIApplicationManagerSession::eDVBCIApplicationManagerSession(eDVBCISlot *tslot)
{
@@ -30,35 +32,42 @@ int eDVBCIApplicationManagerSession::receivedAPDU(const unsigned char *tag,const
{
case 0x21:
{
- int dl;
- eDebug("[CI%d AM] application info:", slot->getSlotID());
- eDebug("[CI%d AM] len: %d", slot->getSlotID(), len);
- eDebug("[CI%d AM] application_type: %d", slot->getSlotID(), ((unsigned char*)data)[0]);
- eDebug("[CI%d AM] application_manufacturer: %02x %02x", slot->getSlotID(), ((unsigned char*)data)[2], ((unsigned char*)data)[1]);
- eDebug("[CI%d AM] manufacturer_code: %02x %02x", slot->getSlotID(), ((unsigned char*)data)[4],((unsigned char*)data)[3]);
- dl=((unsigned char*)data)[5];
- if ((dl + 6) > len)
+ try
{
- eDebug("[CI%d AM] warning, invalid length (%d vs %d)", slot->getSlotID(), dl+6, len);
- dl=len-6;
- }
- char str[dl + 1];
- memcpy(str, ((char*)data) + 6, dl);
- str[dl] = '\0';
+ int dl;
+ eDebug("[CI%d AM] application info:", slot->getSlotID());
+ eDebug("[CI%d AM] len: %d", slot->getSlotID(), len);
+ eDebug("[CI%d AM] application_type: %d", slot->getSlotID(), ((unsigned char*)data)[0]);
+ eDebug("[CI%d AM] application_manufacturer: %02x %02x", slot->getSlotID(), ((unsigned char*)data)[2], ((unsigned char*)data)[1]);
+ eDebug("[CI%d AM] manufacturer_code: %02x %02x", slot->getSlotID(), ((unsigned char*)data)[4],((unsigned char*)data)[3]);
+ dl=((unsigned char*)data)[5];
+ if ((dl + 6) > len)
+ {
+ eDebug("[CI%d AM] warning, invalid length (%d vs %d)", slot->getSlotID(), dl+6, len);
+ dl=len-6;
+ }
+ char str[dl + 1];
+ memcpy(str, ((char*)data) + 6, dl);
+ str[dl] = '\0';
- m_app_name = str;
- if(m_app_name.size() > 0 && !isUTF8(m_app_name)) {
- eDebug("[CI%d AM] menu string is not UTF8 hex output:%s\nstr output:%s\n",slot->getSlotID(),string_to_hex(m_app_name).c_str(),m_app_name.c_str());
- m_app_name = convertLatin1UTF8(m_app_name);
- eDebug("[CI%d AM] fixed menu string: %s", slot->getSlotID(), m_app_name.c_str());
- }
- else {
- eDebug("[CI%d AM] menu string: %s", slot->getSlotID(), m_app_name.c_str());
- }
- /* emit */ eDVBCI_UI::getInstance()->m_messagepump.send(eDVBCIInterfaces::Message(eDVBCIInterfaces::Message::appNameChanged, slot->getSlotID(), m_app_name.c_str()));
+ m_app_name = str;
+ if(m_app_name.size() > 0 && !isUTF8(m_app_name)) {
+ eDebug("[CI%d AM] menu string is not UTF8 hex output:%s\nstr output:%s\n",slot->getSlotID(),string_to_hex(m_app_name).c_str(),m_app_name.c_str());
+ m_app_name = convertLatin1UTF8(m_app_name);
+ eDebug("[CI%d AM] fixed menu string: %s", slot->getSlotID(), m_app_name.c_str());
+ }
+ else {
+ eDebug("[CI%d AM] menu string: %s", slot->getSlotID(), m_app_name.c_str());
+ }
+ /* emit */ eDVBCI_UI::getInstance()->m_messagepump.send(eDVBCIInterfaces::Message(eDVBCIInterfaces::Message::appNameChanged, slot->getSlotID(), m_app_name.c_str()));
- /* emit */ eDVBCI_UI::getInstance()->m_messagepump.send(eDVBCIInterfaces::Message(eDVBCIInterfaces::Message::slotStateChanged, slot->getSlotID(), 2));
- break;
+ /* emit */ eDVBCI_UI::getInstance()->m_messagepump.send(eDVBCIInterfaces::Message(eDVBCIInterfaces::Message::slotStateChanged, slot->getSlotID(), 2));
+ break;
+ }
+ catch(std::exception ex)
+ {
+ eDebug("[CI%d AM] catch in AM for utf-8 %s", slot->getSlotID(), ex.what());
+ }
}
default:
eWarning("[CI%d AM] unknown APDU tag 9F 80 %02x", slot->getSlotID(), tag[2]);
diff --git a/lib/dvb_ci/dvbci_ccmgr.cpp b/lib/dvb_ci/dvbci_ccmgr.cpp
index 846ed032925..0c1899a1599 100644
--- a/lib/dvb_ci/dvbci_ccmgr.cpp
+++ b/lib/dvb_ci/dvbci_ccmgr.cpp
@@ -147,6 +147,10 @@ void eDVBCICcSession::removeProgram(uint16_t program_number, std::vector::iterator it = pids.begin(); it != pids.end(); ++it)
descrambler_set_pid(m_descrambler_fd, m_slot->getSlotID(), 0, *it);
+#ifdef USE_ALTERNATE_CA_HANDLING
+ descrambler_deinit(m_descrambler_fd);
+#endif
+
// removing program means probably decoding on this slot is ending. So mark this slot as not descrambling
eDVBCI_UI::getInstance()->setDecodingState(m_slot->getSlotID(), 0);
}
@@ -792,13 +796,13 @@ void eDVBCICcSession::set_descrambler_key()
if (m_descrambler_fd != -1 && m_current_ca_demux_id != m_slot->getCADemuxID())
{
descrambler_deinit(m_descrambler_fd);
- m_descrambler_fd = descrambler_init(m_slot->getSlotID(), m_slot->getCADemuxID() + (m_slot->getIsCA0Excluded() ? 1 : 0));
+ m_descrambler_fd = descrambler_init(m_slot->getSlotID(), m_slot->getCADemuxID());
m_current_ca_demux_id = m_slot->getCADemuxID();
}
if (m_descrambler_fd == -1 && m_slot->getCADemuxID() > -1)
{
- m_descrambler_fd = descrambler_init(m_slot->getSlotID(), m_slot->getCADemuxID() + (m_slot->getIsCA0Excluded() ? 1 : 0));
+ m_descrambler_fd = descrambler_init(m_slot->getSlotID(), m_slot->getCADemuxID());
m_current_ca_demux_id = m_slot->getCADemuxID();
}
diff --git a/lib/gdi/epng.cpp b/lib/gdi/epng.cpp
index 8745975b723..4fad34ad56c 100644
--- a/lib/gdi/epng.cpp
+++ b/lib/gdi/epng.cpp
@@ -127,6 +127,7 @@ int loadPNG(ePtr &result, const char *filename, int accel, int cached)
channels = png_get_channels(png_ptr, info_ptr);
result = new gPixmap(width, height, bit_depth * channels, cached ? PixmapCache::PixmapDisposed : NULL, accel);
+ result->isPNG = true;
gUnmanagedSurface *surface = result->surface;
png_bytep *rowptr = new png_bytep[height];
diff --git a/lib/gdi/gpixmap.h b/lib/gdi/gpixmap.h
index 112ce2e3e48..71c317c4897 100644
--- a/lib/gdi/gpixmap.h
+++ b/lib/gdi/gpixmap.h
@@ -225,6 +225,7 @@ class gPixmap: public iObject
gPixmap(int width, int height, int bpp, gPixmapDisposeCallback on_dispose, int accel = accelAuto);
gUnmanagedSurface *surface;
+ bool isPNG = false;
inline bool needClut() const { return surface && surface->bpp <= 8; }
#endif
diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp
index 977e8a7663f..e2892f0335e 100644
--- a/lib/gui/elistboxcontent.cpp
+++ b/lib/gui/elistboxcontent.cpp
@@ -493,6 +493,8 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
// Draw frame here so to be drawn under icons
if (selected && (!local_style || !local_style->m_selection) && (!local_style || !local_style->m_border_set))
style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
+
+ bool sep = false;
if (m_list && cursorValid)
{
@@ -523,201 +525,210 @@ void eListboxPythonConfigContent::paint(gPainter &painter, eWindowStyle &style,
text = PyTuple_GET_ITEM(item, 0);
text = PyObject_Str(text); /* creates a new object - old object was borrowed! */
const char *string = (text && PyUnicode_Check(text)) ? PyUnicode_AsUTF8(text) : "";
- painter.renderText(eRect(ePoint(offset.x()+15, offset.y()), m_itemsize), string,
- gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
+ if (!strcmp(string,"---") && PyTuple_Size(item) == 1) {
+ sep = true;
+ if (m_sepline_color_set) {
+ painter.setForegroundColor(m_sepline_color);
+ }
+ //eDebug("[CONFIGCONTENT] Go to step 1 fill line thick: %d; at pos x: %d, y: %d, w: %d, h: %d", m_sepline_thickness, offset.x() + 15, offset.y() + (m_itemsize.height() - m_sepline_thickness)/2, m_itemsize.width() - 30, m_sepline_thickness);
+ painter.fill(eRect(offset.x()+15, offset.y() + (m_itemsize.height() - m_sepline_thickness)/2, m_itemsize.width() - 30, m_sepline_thickness));
+ } else {
+ painter.renderText(eRect(ePoint(offset.x()+15, offset.y()), m_itemsize), string, gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
+ }
Py_XDECREF(text);
+ if (!sep) {
+ /* when we have no label, align value to the left. (FIXME:
+ don't we want to specifiy this individually?) */
+ int value_alignment_left = !*string;
- /* when we have no label, align value to the left. (FIXME:
- don't we want to specifiy this individually?) */
- int value_alignment_left = !*string;
-
- /* now, handle the value. get 2nd part from tuple*/
- if (PyTuple_Size(item) >= 2) // when no 2nd entry is in tuple this is a non selectable entry without config part
- value = PyTuple_GET_ITEM(item, 1);
+ /* now, handle the value. get 2nd part from tuple*/
+ if (PyTuple_Size(item) >= 2) // when no 2nd entry is in tuple this is a non selectable entry without config part
+ value = PyTuple_GET_ITEM(item, 1);
- if (value)
- {
- ePyObject args = PyTuple_New(1);
- PyTuple_SET_ITEM(args, 0, PyLong_FromLong(selected));
-
- /* CallObject will call __call__ which should return the value tuple */
- value = PyObject_CallObject(value, args);
+ if (value)
+ {
+ ePyObject args = PyTuple_New(1);
+ PyTuple_SET_ITEM(args, 0, PyLong_FromLong(selected));
- if (PyErr_Occurred())
- PyErr_Print();
+ /* CallObject will call __call__ which should return the value tuple */
+ value = PyObject_CallObject(value, args);
- Py_DECREF(args);
- /* the PyInt was stolen. */
- }
+ if (PyErr_Occurred())
+ PyErr_Print();
- /* check if this is really a tuple */
- if (value && PyTuple_Check(value))
- {
- /* convert type to string */
- ePyObject type = PyTuple_GET_ITEM(value, 0);
- const char *atype = (type && PyUnicode_Check(type)) ? PyUnicode_AsUTF8(type) : 0;
+ Py_DECREF(args);
+ /* the PyInt was stolen. */
+ }
- if (atype)
+ /* check if this is really a tuple */
+ if (value && PyTuple_Check(value))
{
- if (!strcmp(atype, "text"))
- {
- ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
- const char *value = (pvalue && PyUnicode_Check(pvalue)) ? PyUnicode_AsUTF8(pvalue) : "";
- painter.setFont(fnt2);
- if (value_alignment_left)
- painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
- else
- painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_RIGHT| gPainter::RT_VALIGN_CENTER, border_color, border_size);
-
- /* pvalue is borrowed */
- } else if (!strcmp(atype, "slider"))
+ /* convert type to string */
+ ePyObject type = PyTuple_GET_ITEM(value, 0);
+ const char *atype = (type && PyUnicode_Check(type)) ? PyUnicode_AsUTF8(type) : 0;
+
+ if (atype)
{
- ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
- ePyObject psize = PyTuple_GET_ITEM(value, 2);
-
- /* convert value to Long. fallback to -1 on error. */
- int value = (pvalue && PyLong_Check(pvalue)) ? PyLong_AsLong(pvalue) : -1;
- int size = (pvalue && PyLong_Check(psize)) ? PyLong_AsLong(psize) : 100;
-
- /* calc. slider length */
- int width = (m_itemsize.width() - m_seperation - 15) * value / size;
- int height = m_itemsize.height();
-
-
- /* draw slider */
- //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
- if (m_slider_height % 2 != height % 2)
- m_slider_height -= 1;
- if(m_slider_height + 2*m_slider_space >= height) // frame out of selector = without frame
- m_slider_space = 0;
- int slider_y_offset = (height - m_slider_height) / 2;
- if (m_slider_space)
+ if (!strcmp(atype, "text"))
{
- ePoint tl(offset.x() + m_seperation, offset.y() + slider_y_offset - m_slider_space - 1);
- ePoint tr(offset.x() + m_itemsize.width() - 15 - 1, tl.y());
- ePoint bl(tl.x(), offset.y() + slider_y_offset + m_slider_height + m_slider_space);
- ePoint br(tr.x(), bl.y());
- painter.line(tl, tr);
- painter.line(tr, br);
- painter.line(br, bl);
- painter.line(bl, tl);
- painter.fill(eRect(offset.x() + m_seperation + m_slider_space + 1, offset.y() + slider_y_offset, width - 2*(m_slider_space + 1), m_slider_height));
- }
- else
- {
- painter.fill(eRect(offset.x() + m_seperation, offset.y() + slider_y_offset, width, m_slider_height));
- }
+ ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
+ const char *value = (pvalue && PyUnicode_Check(pvalue)) ? PyUnicode_AsUTF8(pvalue) : "";
+ painter.setFont(fnt2);
+ if (value_alignment_left)
+ painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
+ else
+ painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_RIGHT| gPainter::RT_VALIGN_CENTER, border_color, border_size);
- /* pvalue is borrowed */
- } else if (!strcmp(atype, "mtext"))
- {
- ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
- const char *text = (pvalue && PyUnicode_Check(pvalue)) ? PyUnicode_AsUTF8(pvalue) : "";
- ePtr para = new eTextPara(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize));
- para->setFont(fnt2);
- para->renderString(text, 0);
+ /* pvalue is borrowed */
+ } else if (!strcmp(atype, "slider"))
+ {
+ ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
+ ePyObject psize = PyTuple_GET_ITEM(value, 2);
+
+ /* convert value to Long. fallback to -1 on error. */
+ int value = (pvalue && PyLong_Check(pvalue)) ? PyLong_AsLong(pvalue) : -1;
+ int size = (pvalue && PyLong_Check(psize)) ? PyLong_AsLong(psize) : 100;
+
+ /* calc. slider length */
+ int width = (m_itemsize.width() - m_seperation - 15) * value / size;
+ int height = m_itemsize.height();
+
+
+ /* draw slider */
+ //painter.fill(eRect(offset.x() + m_seperation, offset.y(), width, height));
+ if (m_slider_height % 2 != height % 2)
+ m_slider_height -= 1;
+ if(m_slider_height + 2*m_slider_space >= height) // frame out of selector = without frame
+ m_slider_space = 0;
+ int slider_y_offset = (height - m_slider_height) / 2;
+ if (m_slider_space)
+ {
+ ePoint tl(offset.x() + m_seperation, offset.y() + slider_y_offset - m_slider_space - 1);
+ ePoint tr(offset.x() + m_itemsize.width() - 15 - 1, tl.y());
+ ePoint bl(tl.x(), offset.y() + slider_y_offset + m_slider_height + m_slider_space);
+ ePoint br(tr.x(), bl.y());
+ painter.line(tl, tr);
+ painter.line(tr, br);
+ painter.line(br, bl);
+ painter.line(bl, tl);
+ painter.fill(eRect(offset.x() + m_seperation + m_slider_space + 1, offset.y() + slider_y_offset, width - 2*(m_slider_space + 1), m_slider_height));
+ }
+ else
+ {
+ painter.fill(eRect(offset.x() + m_seperation, offset.y() + slider_y_offset, width, m_slider_height));
+ }
- if (value_alignment_left)
- para->realign(eTextPara::dirLeft);
- else
- para->realign(eTextPara::dirRight);
+ /* pvalue is borrowed */
+ } else if (!strcmp(atype, "mtext"))
+ {
+ ePyObject pvalue = PyTuple_GET_ITEM(value, 1);
+ const char *text = (pvalue && PyUnicode_Check(pvalue)) ? PyUnicode_AsUTF8(pvalue) : "";
+ ePtr para = new eTextPara(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize));
+ para->setFont(fnt2);
+ para->renderString(text, 0);
- int glyphs = para->size();
+ if (value_alignment_left)
+ para->realign(eTextPara::dirLeft);
+ else
+ para->realign(eTextPara::dirRight);
- ePyObject plist;
+ int glyphs = para->size();
- if (PyTuple_Size(value) >= 3)
- plist = PyTuple_GET_ITEM(value, 2);
+ ePyObject plist;
- int entries = 0;
+ if (PyTuple_Size(value) >= 3)
+ plist = PyTuple_GET_ITEM(value, 2);
- if (plist && PyList_Check(plist))
- entries = PyList_Size(plist);
+ int entries = 0;
- int left=0, right=0, last=-1, top=0, bottom=0;
- bool isVertLB = m_listbox && m_listbox->getOrientation() == 1;
- eRect bbox;
- eRect pbox = para->getBoundBox();
- for (int i = 0; i < entries; ++i)
- {
- ePyObject entry = PyList_GET_ITEM(plist, i);
- int num = PyLong_Check(entry) ? PyLong_AsLong(entry) : -1;
+ if (plist && PyList_Check(plist))
+ entries = PyList_Size(plist);
- if ((num < 0) || (num >= glyphs))
- eWarning("[eListboxPythonMultiContent] glyph index %d in PythonConfigList out of bounds!", num);
- else
+ int left=0, right=0, last=-1, top=0, bottom=0;
+ bool isVertLB = m_listbox && m_listbox->getOrientation() == 1;
+ eRect bbox;
+ eRect pbox = para->getBoundBox();
+ for (int i = 0; i < entries; ++i)
{
- if (last+1 != num && last != -1) {
- if (isVertLB)
- bbox = eRect(left, offset.y(), right-left, (m_itemsize.height() - pbox.height()) / 2);
- else
- bbox = eRect(offset.x(), top, bottom-top, (m_itemsize.width() - pbox.width()) / 2);
- painter.fill(bbox);
- }
- para->setGlyphFlag(num, GS_INVERT);
- bbox = para->getGlyphBBox(num);
- if (last+1 != num || last == -1){
+ ePyObject entry = PyList_GET_ITEM(plist, i);
+ int num = PyLong_Check(entry) ? PyLong_AsLong(entry) : -1;
+
+ if ((num < 0) || (num >= glyphs))
+ eWarning("[eListboxPythonMultiContent] glyph index %d in PythonConfigList out of bounds!", num);
+ else
+ {
+ if (last+1 != num && last != -1) {
+ if (isVertLB)
+ bbox = eRect(left, offset.y(), right-left, (m_itemsize.height() - pbox.height()) / 2);
+ else
+ bbox = eRect(offset.x(), top, bottom-top, (m_itemsize.width() - pbox.width()) / 2);
+ painter.fill(bbox);
+ }
+ para->setGlyphFlag(num, GS_INVERT);
+ bbox = para->getGlyphBBox(num);
+ if (last+1 != num || last == -1){
+ if (isVertLB)
+ left = bbox.left();
+ else
+ top = bbox.top();
+ }
if (isVertLB)
- left = bbox.left();
+ right = bbox.left() + bbox.width();
else
- top = bbox.top();
+ bottom = bbox.top() + bbox.height();
+ last = num;
}
+ /* entry is borrowed */
+ }
+ if (last != -1) {
if (isVertLB)
- right = bbox.left() + bbox.width();
+ bbox = eRect(left, offset.y() + (m_itemsize.height() - pbox.height()) / 2, right - left, pbox.height());
else
- bottom = bbox.top() + bbox.height();
- last = num;
+ bbox = eRect(offset.x() + (m_itemsize.width() - pbox.width()) / 2, top , bottom - top, pbox.width());
+ painter.fill(bbox);
}
- /* entry is borrowed */
- }
- if (last != -1) {
if (isVertLB)
- bbox = eRect(left, offset.y() + (m_itemsize.height() - pbox.height()) / 2, right - left, pbox.height());
+ painter.renderPara(para, ePoint(0, m_itemsize.height() - pbox.height()) / 2);
else
- bbox = eRect(offset.x() + (m_itemsize.width() - pbox.width()) / 2, top , bottom - top, pbox.width());
- painter.fill(bbox);
- }
- if (isVertLB)
- painter.renderPara(para, ePoint(0, m_itemsize.height() - pbox.height()) / 2);
- else
- painter.renderPara(para, ePoint(m_itemsize.width() - pbox.width(), 0) / 2);
+ painter.renderPara(para, ePoint(m_itemsize.width() - pbox.width(), 0) / 2);
/* pvalue is borrowed */
- /* plist is 0 or borrowed */
- }
- else if (!strcmp(atype, "pixmap"))
- {
- ePyObject data;
- ePyObject ppixmap = PyTuple_GET_ITEM(value, 1);
+ /* plist is 0 or borrowed */
+ }
+ else if (!strcmp(atype, "pixmap"))
+ {
+ ePyObject data;
+ ePyObject ppixmap = PyTuple_GET_ITEM(value, 1);
- if (PyLong_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
- ppixmap = PyTuple_GetItem(data, PyLong_AsLong(ppixmap));
+ if (PyLong_Check(ppixmap) && data) /* if the pixemap is in fact a number, it refers to the 'data' list. */
+ ppixmap = PyTuple_GetItem(data, PyLong_AsLong(ppixmap));
- ePtr pixmap;
- if (SwigFromPython(pixmap, ppixmap))
- {
- eDebug("[eListboxPythonMultiContent] (Pixmap) get pixmap failed");
- const char *value = (ppixmap && PyUnicode_Check(ppixmap)) ? PyUnicode_AsUTF8(ppixmap) : "";
- painter.setFont(fnt2);
- if (value_alignment_left)
- painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
+ ePtr pixmap;
+ if (SwigFromPython(pixmap, ppixmap))
+ {
+ eDebug("[eListboxPythonMultiContent] (Pixmap) get pixmap failed");
+ const char *value = (ppixmap && PyUnicode_Check(ppixmap)) ? PyUnicode_AsUTF8(ppixmap) : "";
+ painter.setFont(fnt2);
+ if (value_alignment_left)
+ painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_LEFT | gPainter::RT_VALIGN_CENTER, border_color, border_size);
+ else
+ painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_RIGHT| gPainter::RT_VALIGN_CENTER, border_color, border_size);
+ }
else
- painter.renderText(eRect(ePoint(offset.x()-15, offset.y()), m_itemsize), value, gPainter::RT_HALIGN_RIGHT| gPainter::RT_VALIGN_CENTER, border_color, border_size);
- }
- else
- {
- eRect rect(ePoint(m_itemsize.width() - pixmap->size().width() - 15, offset.y() + (m_itemsize.height() - pixmap->size().height()) / 2), pixmap->size());
- painter.clip(rect);
- /* painter.blit(pixmap, rect.topLeft(), rect, 0); */
- painter.blit(pixmap, rect.topLeft(), rect, gPainter::BT_ALPHABLEND);
- painter.clippop();
+ {
+ eRect rect(ePoint(m_itemsize.width() - pixmap->size().width() - 15, offset.y() + (m_itemsize.height() - pixmap->size().height()) / 2), pixmap->size());
+ painter.clip(rect);
+ /* painter.blit(pixmap, rect.topLeft(), rect, 0); */
+ painter.blit(pixmap, rect.topLeft(), rect, gPainter::BT_ALPHABLEND);
+ painter.clippop();
+ }
}
}
- }
- /* type is borrowed */
- } else if (value)
- eWarning("[eListboxPythonConfigContent] second value of tuple is not a tuple.");
- if (value)
- Py_DECREF(value);
+ /* type is borrowed */
+ } else if (value)
+ eWarning("[eListboxPythonConfigContent] second value of tuple is not a tuple.");
+ if (value)
+ Py_DECREF(value);
+ }
}
}
diff --git a/lib/gui/elistboxcontent.h b/lib/gui/elistboxcontent.h
index 25f0031bc7e..7e3fa7c8ea5 100644
--- a/lib/gui/elistboxcontent.h
+++ b/lib/gui/elistboxcontent.h
@@ -21,6 +21,11 @@ class eListboxPythonStringContent: public virtual iListboxContent
void invalidate();
eSize getItemSize() { return m_itemsize; }
int getMaxItemTextWidth();
+ void setSeparatorLineColor(const gRGB &col) {
+ m_sepline_color = col;
+ m_sepline_color_set = 1;
+ }
+ void setSepLineThickness(int value) { m_sepline_thickness = value; }
#ifndef SWIG
protected:
void cursorHome();
@@ -56,6 +61,9 @@ class eListboxPythonStringContent: public virtual iListboxContent
int m_itemwidth;
int m_max_text_width;
int m_orientation;
+ gRGB m_sepline_color;
+ int m_sepline_color_set;
+ int m_sepline_thickness;
#endif
};
@@ -66,6 +74,11 @@ class eListboxPythonConfigContent: public eListboxPythonStringContent
void setSeperation(int sep) { m_seperation = sep; }
int currentCursorSelectable();
void setSlider(int height, int space) { m_slider_height = height; m_slider_space = space; }
+ void setSeparatorLineColor(const gRGB &col) {
+ m_sepline_color = col;
+ m_sepline_color_set = 1;
+ }
+ void setSepLineThickness(int value) { m_sepline_thickness = value; }
private:
int m_seperation, m_slider_height, m_slider_space;
};
diff --git a/lib/gui/epixmap.cpp b/lib/gui/epixmap.cpp
index 8963ca83ed6..b8ccc59175a 100644
--- a/lib/gui/epixmap.cpp
+++ b/lib/gui/epixmap.cpp
@@ -10,12 +10,21 @@ ePixmap::ePixmap(eWidget *parent)
void ePixmap::setAlphatest(int alphatest)
{
- m_alphatest = alphatest;
- setTransparent(alphatest);
+ if (m_force_blending > 0 && m_pixmap && m_pixmap->isPNG) {
+ if (m_force_blending == 2 || (m_force_blending == 1 && alphatest == 1))
+ m_alphatest = gPainter::BT_ALPHABLEND;
+ } else {
+ m_alphatest = alphatest;
+ }
+
+ setTransparent(m_alphatest);
}
void ePixmap::setScale(int scale)
{
+ // support old python code beacause the old code will only support BT_SCALE
+ scale = (scale) ? gPainter::BT_SCALE : 0;
+
if (m_scale != scale)
{
m_scale = scale;
@@ -23,6 +32,15 @@ void ePixmap::setScale(int scale)
}
}
+void ePixmap::setPixmapScale(int flags)
+{
+ if (m_scale != flags)
+ {
+ m_scale = flags;
+ invalidate();
+ }
+}
+
void ePixmap::setPixmap(gPixmap *pixmap)
{
m_pixmap = pixmap;
@@ -102,9 +120,8 @@ int ePixmap::event(int event, void *data, void *data2)
flags = gPainter::BT_ALPHATEST;
else if (m_alphatest == 2)
flags = gPainter::BT_ALPHABLEND;
- if (m_scale)
- flags |= gPainter::BT_SCALE;
-
+
+ flags |= m_scale;
painter.setRadius(cornerRadius, getCornerRadiusEdges());
painter.blit(m_pixmap, eRect(ePoint(0, 0), s), eRect(), flags);
}
@@ -125,6 +142,9 @@ int ePixmap::event(int event, void *data, void *data2)
return 0;
}
case evtChangedPixmap:
+ if (m_force_blending == 2){
+ setAlphatest(m_alphatest);
+ }
checkSize();
invalidate();
return 0;
diff --git a/lib/gui/epixmap.h b/lib/gui/epixmap.h
index 2db26f25128..99ef9bc162a 100644
--- a/lib/gui/epixmap.h
+++ b/lib/gui/epixmap.h
@@ -2,6 +2,7 @@
#define __lib_gui_epixmap_h
#include
+#include // access to python config
class ePixmap: public eWidget
{
@@ -15,6 +16,8 @@ class ePixmap: public eWidget
void setPixmapFromFile(const char *filename);
void setAlphatest(int alphatest); /* 1 for alphatest, 2 for alphablend */
void setScale(int scale);
+ void setPixmapScale(int flags);
+ void setPixmapScaleFlags(int flags) { setPixmapScale(flags); } // DEPRECATED
void setBorderWidth(int pixel);
void setBorderColor(const gRGB &color);
protected:
@@ -27,6 +30,7 @@ class ePixmap: public eWidget
evtChangedPixmap = evtUserWidget,
};
bool m_have_border_color;
+ int m_force_blending = eConfigManager::getConfigIntValue("config.skin.pixmap_force_alphablending", 0);
int m_border_width;
gRGB m_border_color;
};
diff --git a/lib/python/Components/AVSwitch.py b/lib/python/Components/AVSwitch.py
index 18a40f551fc..31dee1a933b 100644
--- a/lib/python/Components/AVSwitch.py
+++ b/lib/python/Components/AVSwitch.py
@@ -1,6 +1,6 @@
from os import path
-from enigma import eAVSwitch, getDesktop
+from enigma import eAVSwitch, eDVBVolumecontrol, getDesktop
from Components.config import ConfigBoolean, ConfigEnableDisable, ConfigNothing, ConfigSelection, ConfigSelectionNumber, ConfigSlider, ConfigSubDict, ConfigSubsection, ConfigYesNo, NoSave, config
from Components.SystemInfo import SystemInfo
@@ -400,6 +400,7 @@ def InitAVSwitch():
config.av.wss = ConfigEnableDisable(default=True)
config.av.generalAC3delay = ConfigSelectionNumber(-1000, 1000, 5, default=0)
config.av.generalPCMdelay = ConfigSelectionNumber(-1000, 1000, 5, default=0)
+ config.av.volume_hide_mute = ConfigYesNo(default=True)
config.av.vcrswitch = ConfigEnableDisable(default=False)
config.av.aspect.setValue("16:9")
config.av.aspect.addNotifier(iAVSwitch.setAspect)
@@ -649,6 +650,11 @@ def setPCMMultichannel(configElement):
config.av.pcm_multichannel = ConfigYesNo(default=False)
config.av.pcm_multichannel.addNotifier(setPCMMultichannel)
+ def setVolumeStepsize(configElement):
+ eDVBVolumecontrol.getInstance().setVolumeSteps(int(configElement.value))
+ config.av.volume_stepsize = ConfigSelectionNumber(1, 10, 1, default=5)
+ config.av.volume_stepsize.addNotifier(setVolumeStepsize)
+
if SystemInfo["CanDownmixAC3"]:
def setAC3Downmix(configElement):
open("/proc/stb/audio/ac3", "w").write(configElement.value)
diff --git a/lib/python/Components/About.py b/lib/python/Components/About.py
index a81a96484a3..712c6ecfc86 100644
--- a/lib/python/Components/About.py
+++ b/lib/python/Components/About.py
@@ -3,12 +3,11 @@
import struct
from os import path as ospath
-from os.path import join as pathjoin
from sys import modules, version_info
from time import time
-from Tools.Directories import fileExists, resolveFilename, SCOPE_LIBDIR
+from Tools.Directories import fileExists
-from enigma import getEnigmaVersionString
+from enigma import getEnigmaLastCommitDate, getEnigmaLastCommitHash
def getVersionString():
@@ -29,8 +28,12 @@ def driversDate():
return _formatDate(SystemInfo["driversdate"])
-def getLastUpdate():
- return _formatDate(getEnigmaVersionString().replace("-", ""))
+def getLastCommitDate():
+ return _formatDate(getEnigmaLastCommitDate().replace("-", ""))
+
+
+def getLastCommitHash():
+ return getEnigmaLastCommitHash()[:7]
def _formatDate(Date):
diff --git a/lib/python/Components/Addons/ScreenHeader.py b/lib/python/Components/Addons/ScreenHeader.py
index 18bcfe575cd..fa5f504f0a5 100644
--- a/lib/python/Components/Addons/ScreenHeader.py
+++ b/lib/python/Components/Addons/ScreenHeader.py
@@ -58,7 +58,7 @@ def buildEntry(self, sequence):
itemHeight = self.instance.size().height()
for idx, x in enumerate(sequence):
- if not isinstance(x, StaticText): # assume it is Pixmap
+ if not isinstance(x, StaticText): # assume it is Pixmap
if x.pixmap:
itemHeight = self.instance.size().height()
pix_size = x.pixmap.size()
diff --git a/lib/python/Components/ConfigList.py b/lib/python/Components/ConfigList.py
index 0396168fa41..d0dbf72ae45 100644
--- a/lib/python/Components/ConfigList.py
+++ b/lib/python/Components/ConfigList.py
@@ -1,5 +1,5 @@
-from enigma import eListbox, eListboxPythonConfigContent, ePoint, eRCInput, eTimer
-from skin import parameters, applySkinFactor
+from enigma import eListbox, eListboxPythonConfigContent, ePoint, eRCInput, eTimer, gRGB
+from skin import parameters, applySkinFactor, parseColor
from Components.ActionMap import HelpableActionMap, HelpableNumberActionMap
from Components.config import ConfigBoolean, ConfigElement, ConfigInteger, ConfigMacText, ConfigNothing, ConfigNumber, ConfigSelection, ConfigSequence, ConfigText, ACTIONKEY_0, ACTIONKEY_ASCII, ACTIONKEY_BACKSPACE, ACTIONKEY_DELETE, ACTIONKEY_ERASE, ACTIONKEY_FIRST, ACTIONKEY_LAST, ACTIONKEY_LEFT, ACTIONKEY_NUMBERS, ACTIONKEY_RIGHT, ACTIONKEY_SELECT, ACTIONKEY_TIMEOUT, ACTIONKEY_TOGGLE, configfile
@@ -26,6 +26,10 @@ def __init__(self, list, session=None):
self.onSelectionChanged = []
self.current = None
self.session = session
+ self.sepLineColor = 0xFFFFFF
+ self.sepLineThickness = 1
+ self.l.setSeparatorLineColor(gRGB(self.sepLineColor))
+ self.l.setSepLineThickness(self.sepLineThickness)
def execBegin(self):
rcinput = eRCInput.getInstance()
@@ -141,6 +145,22 @@ def pageDown(self):
def moveBottom(self):
if self.instance is not None:
self.instance.moveSelection(self.instance.moveEnd)
+
+ def applySkin(self, desktop, screen):
+ if self.skinAttributes is not None:
+ attribs = []
+ for (attrib, value) in self.skinAttributes:
+ if attrib == "sepLineColor":
+ self.sepLineColor = parseColor(value).argb()
+ elif attrib == "sepLineThickness":
+ self.sepLineThickness = int(value)
+ else:
+ attribs.append((attrib, value))
+ self.skinAttributes = attribs
+ rc = GUIComponent.applySkin(self, desktop, screen)
+ self.l.setSeparatorLineColor(gRGB(self.sepLineColor))
+ self.l.setSepLineThickness(self.sepLineThickness)
+ return rc
class ConfigListScreen:
@@ -462,7 +482,6 @@ def dummyConfigActions(self, value): # Temporary support for legacy code and pl
self["configActions"].setEnabled(value)
self["navigationActions"].setEnabled(value)
self["menuConfigActions"].setEnabled(value)
- self["charConfigActions"].setEnabled(value)
self["editConfigActions"].setEnabled(value)
def dummyVKBActions(self, value): # Temporary support for legacy code and plugins that hasn't yet been updated.
diff --git a/lib/python/Components/Converter/MovieInfo.py b/lib/python/Components/Converter/MovieInfo.py
index 8ccc3683551..b73c5cd53c9 100644
--- a/lib/python/Components/Converter/MovieInfo.py
+++ b/lib/python/Components/Converter/MovieInfo.py
@@ -143,21 +143,18 @@ def getText(self):
elif self.type == self.MOVIE_REC_FILESIZE:
return self.getFileSize(service, info)
elif self.type == self.FORMAT_STRING:
- timeCreate = strftime("%A %d %b %Y", localtime(info.getInfo(service, iServiceInformation.sTimeCreate)))
- duration = "%d min" % (info.getLength(service) / 60)
- filesize = "%d MB" % (info.getInfoObject(service, iServiceInformation.sFileSize) / (1024 * 1024))
- rec_ref_str = info.getInfoString(service, iServiceInformation.sServiceref)
- rec_service_name = eServiceReference(rec_ref_str).getServiceName()
+ timeCreate = localtime(info.getInfo(service, iServiceInformation.sTimeCreate))
+ duration = info.getLength(service)
+ filesize = info.getInfoObject(service, iServiceInformation.sFileSize)
res_str = ""
for x in self.parts[1:]:
- if x == "TIMECREATED" and timeCreate:
- res_str = self.appendToStringWithSeparator(res_str, timeCreate)
- if x == "DURATION" and duration:
- res_str = self.appendToStringWithSeparator(res_str, duration)
+ x = x.upper()
+ if x == "TIMECREATED" and timeCreate and timeCreate.tm_year > 1970:
+ res_str = self.appendToStringWithSeparator(res_str, strftime("%A %d %b %Y", timeCreate))
+ if x == "DURATION" and duration and duration > 0:
+ res_str = self.appendToStringWithSeparator(res_str, "%d min" % (duration / 60))
if x == "FILESIZE" and filesize:
- res_str = self.appendToStringWithSeparator(res_str, filesize)
- if x == "RECSERVICE" and rec_service_name:
- res_str = self.appendToStringWithSeparator(res_str, rec_service_name)
+ res_str = self.appendToStringWithSeparator(res_str, self.getFriendlyFilesize(filesize))
return res_str
return ""
diff --git a/lib/python/Components/Converter/ServiceName.py b/lib/python/Components/Converter/ServiceName.py
index aaf5102666c..8b64ac162d2 100644
--- a/lib/python/Components/Converter/ServiceName.py
+++ b/lib/python/Components/Converter/ServiceName.py
@@ -122,7 +122,10 @@ def getName(self, ref, info):
if not name:
name = ref and hasattr(self.source, "serviceref") and self.source.serviceref and info.getName(self.source.serviceref)
if not name:
- name = info.getName()
+ if not ref:
+ name = info.getName()
+ else:
+ name = info.getName(ref) or ref.getName()
return name.replace('\xc2\x86', '').replace('\xc2\x87', '').replace('_', ' ')
def getNumber(self):
diff --git a/lib/python/Components/EpgListGrid.py b/lib/python/Components/EpgListGrid.py
index 5ba00e05006..b87ac7ece69 100644
--- a/lib/python/Components/EpgListGrid.py
+++ b/lib/python/Components/EpgListGrid.py
@@ -386,7 +386,7 @@ def buildEntry(self, service, serviceName, events, picon, channel):
else:
res.append(MultiContentEntryText(
pos=(r1.left(), r1.top()),
- size=(r1.width(), r1.height()),
+ size=(r1.width() + self.serviceBorderWidth, r1.height() + self.serviceBorderWidth),
font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER,
text="",
color=serviceForeColor, color_sel=serviceForeColor,
@@ -514,7 +514,7 @@ def buildEntry(self, service, serviceName, events, picon, channel):
flags=BT_SCALE))
else:
res.append(MultiContentEntryText(
- pos=(left, top), size=(width, height),
+ pos=(left, top), size=(width + self.eventBorderWidth, height + self.eventBorderWidth),
font=1, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER,
text="", color=None, color_sel=None,
backcolor=self.backColor, backcolor_sel=self.backColorSelected,
@@ -602,7 +602,7 @@ def buildEntry(self, service, serviceName, events, picon, channel):
flags=BT_SCALE))
else:
res.append(MultiContentEntryText(
- pos=(left + xpos, top), size=(ewidth, height),
+ pos=(left + xpos, top), size=(ewidth + self.eventBorderWidth, height + self.eventBorderWidth),
font=1, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER,
text="", color=None, color_sel=None,
backcolor=backColor, backcolor_sel=backColorSel,
@@ -882,6 +882,7 @@ def __init__(self, epgConfig, graphic):
self.timelineFontName = "Regular"
self.timelineFontSize = 20
self.datefmt = ""
+ self.fullBorder = True
GUI_WIDGET = eListbox
@@ -903,6 +904,8 @@ def applySkin(self, desktop, screen):
self.timelineFontSize = font.pointSize
elif attrib == "itemHeight":
self.itemHeight = parseScale(value)
+ elif attrib == "fullBorder":
+ self.fullBorder = value == "1"
else:
attribs.append((attrib, value))
self.skinAttributes = attribs
@@ -979,12 +982,13 @@ def setEntries(self, list, timelineNow, timeLines, force):
png=bgpng,
flags=BT_SCALE))
else:
- res.append(MultiContentEntryText(
- pos=(0, 0),
- size=(serviceRect.width(), self.listHeight),
- color=foreColor,
- backcolor=backColor,
- border_width=self.borderWidth, border_color=self.borderColor))
+ if self.fullBorder:
+ res.append(MultiContentEntryText(
+ pos=(0, 0),
+ size=(serviceRect.width(), self.listHeight),
+ color=foreColor,
+ backcolor=backColor,
+ border_width=self.borderWidth, border_color=self.borderColor))
res.append(MultiContentEntryText(
pos=(5, 0),
@@ -994,6 +998,15 @@ def setEntries(self, list, timelineNow, timeLines, force):
color=foreColor,
backcolor=backColor))
+ if not self.fullBorder:
+ res.append(MultiContentEntryText(
+ pos=(serviceRect.width() - self.borderWidth * 2, 0),
+ size=(self.borderWidth, self.listHeight + self.borderWidth * 2),
+ text=" ",
+ color=foreColor,
+ backcolor=self.borderColor,
+ border_width=self.borderWidth, border_color=self.borderColor))
+
bgpng = self.timelineTime
xpos = 0
if bgpng is not None and self.graphic:
@@ -1005,12 +1018,13 @@ def setEntries(self, list, timelineNow, timeLines, force):
png=bgpng,
flags=BT_SCALE))
else:
- res.append(MultiContentEntryText(
- pos=(serviceRect.width(), 0),
- size=(eventRect.width(), self.listHeight),
- color=foreColor,
- backcolor=backColor,
- border_width=self.borderWidth, border_color=self.borderColor))
+ if self.fullBorder:
+ res.append(MultiContentEntryText(
+ pos=(serviceRect.width(), 0),
+ size=(eventRect.width(), self.listHeight),
+ color=foreColor,
+ backcolor=backColor,
+ border_width=self.borderWidth, border_color=self.borderColor))
for x in range(0, numLines):
ttime = localtime(timeBase + (x * timeStepsCalc))
@@ -1025,7 +1039,7 @@ def setEntries(self, list, timelineNow, timeLines, force):
else:
timetext = strftime("%-I:%M", ttime) + _("am")
res.append(MultiContentEntryText(
- pos=(serviceRect.width() + xpos, 0),
+ pos=(serviceRect.width() + xpos + 5, 0),
size=(incWidth, self.listHeight),
font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER,
text=timetext,
diff --git a/lib/python/Components/Harddisk.py b/lib/python/Components/Harddisk.py
index 9836825bcf3..5e567d8a248 100644
--- a/lib/python/Components/Harddisk.py
+++ b/lib/python/Components/Harddisk.py
@@ -666,7 +666,7 @@ def enumerateBlockDevices(self):
description = self.getUserfriendlyDeviceName(device, physicalDevice)
isCdrom = devMajor in opticalDisks or device.startswith("sr")
if isCdrom:
- self.cd = devicePath
+ self.cd = ospath.join("/dev", device) if device.startswith("sr") else devicePath
self.partitions.append(Partition(mountpoint=self.getMountpoint(device), description=description, force_mounted=True, device=device))
# print("[Harddisk] DEBUG: Partition(mountpoint=%s, description=%s, force_mounted=True, device=%s)" % (self.getMountpoint(device), description, device))
# print("[Harddisk] Found optical disk '%s' (%s)." % (device, physicalDevice))
@@ -760,18 +760,18 @@ def getUserfriendlyDeviceName(self, device, physicalDevice):
def splitDeviceName(self, devName):
devNameLen = len(devName)
- device = devName.rstrip("0123456789")
- deviceLen = len(device)
- if devName.startswith("mmcblk"): # This works for devices in the form: mmcblk0pX
- if device.endswith("p") and deviceLen < devNameLen:
+ device = devName
+ partition = 0
+ pdevice = devName.rstrip("0123456789")
+ deviceLen = len(pdevice)
+ if devName.startswith("mmcblk"):
+ if pdevice.endswith("p") and deviceLen < devNameLen: # This works for devices in the form: mmcblk0pX
device = devName[0:deviceLen - 1]
partition = int(devName[deviceLen:])
- else:
- device = devName
- partition = 0
- else: # This works for devices in the form: sdaX, hdaX, srX or any device that has a numeric suffix.
+ elif devName[:2] != "sr": # this works for: sr0 (which is in fact dev="sr0", part="")
+ device = pdevice # This works for other devices in the form: sdaX, hdaX, or any device that has a numeric suffix.
partition = int(devName[deviceLen:]) if deviceLen < devNameLen else 0
- # print("[Harddisk] splitDeviceName DEBUG: devName = '%s', device = '%s', partition = '%d'" % (devName, device, partition))
+ print(f"[Harddisk] splitDeviceName DEBUG: devName = '{devName}', device = '{device}', partition = '{partition}'")
return device, partition
def getAutofsMountpoint(self, device):
@@ -813,8 +813,11 @@ def addHotplugPartition(self, device, physDevice=None):
isCdrom = devMajor in opticalDisks or device.startswith("sr")
if isCdrom:
print("[Harddisk] Found optical disk '%s' (%s)." % (device, physicalDevice))
- self.cd = devicePath
- self.partitions.append(Partition(mountpoint=self.getMountpoint(hddDev), description=description, force_mounted=True, device=hddDev))
+ self.cd = ospath.join("/dev", device) if device.startswith("sr") else devicePath
+ part = Partition(mountpoint=self.getMountpoint(hddDev), description=description, force_mounted=True, device=hddDev)
+ self.partitions.append(part)
+ if part.mountpoint: # Plugins won't expect unmounted devices.
+ self.on_partition_list_change("add", part)
else: # Lets get to work on real HDD.
data = readFile(ospath.join(devicePath, "removable"))
removable = False if data is None else bool(int(data))
diff --git a/lib/python/Components/NimManager.py b/lib/python/Components/NimManager.py
index 221e3aa0396..66c58604138 100644
--- a/lib/python/Components/NimManager.py
+++ b/lib/python/Components/NimManager.py
@@ -1192,6 +1192,21 @@ def getSatListForNim(self, slotid):
def getNimListForSat(self, orb_pos):
return [nim.slot for nim in self.nim_slots if nim.isCompatible("DVB-S") and not nim.isFBCLink() and orb_pos in [sat[0] for sat in self.getSatListForNim(nim.slot)]]
+ def getTunableReferences(self):
+ referenceList = []
+ for nim in self.nim_slots:
+ if nim.isCompatible("DVB-S") and not nim.isFBCLink():
+ for reference in [f"{satellite[0]:04x}" for satellite in self.getSatListForNim(nim.slot)]:
+ if reference not in referenceList:
+ referenceList.append(reference)
+ elif nim.isCompatible("DVB-C") and not nim.isFBCLink() and 'ffff' not in reflist:
+ referenceList.append('ffff')
+ elif nim.isCompatible("DVB-T") and not nim.isFBCLink() and 'eeee' not in reflist:
+ referenceList.append('eeee')
+ elif nim.isCompatible("ATSC") and not nim.isFBCLink() and 'dddd' not in reflist:
+ referenceList.append('dddd')
+ return referenceList
+
def rotorLastPositionForNim(self, slotid, number=True):
available_slot = False
for slot in self.nim_slots:
diff --git a/lib/python/Components/OnlineUpdateCheck.py b/lib/python/Components/OnlineUpdateCheck.py
index 48c5768dbe5..be098aae822 100644
--- a/lib/python/Components/OnlineUpdateCheck.py
+++ b/lib/python/Components/OnlineUpdateCheck.py
@@ -46,6 +46,8 @@ def adapterAvailable(self): # Box has an adapter configured and active
return False
def NetworkUp(self, host="8.8.8.8", port=53, timeout=2): # Box can access outside the local network
+ return True # bypass this function
+
# Avoids DNS resolution
# Avoids application layer (HTTP/FTP/IMAP)
# Avoids calls to external utilities
@@ -84,7 +86,7 @@ def getFeedStatus(self):
try:
print("[OnlineUpdateCheck][getFeedStatus] checking feeds state")
req = Request("http://openvix.co.uk/TrafficLightState.php")
- d = urlopen(req)
+ d = urlopen(req, timeout=3)
trafficLight = d.read().decode()
if trafficLight == "stable":
status = 0
diff --git a/lib/python/Components/ServiceList.py b/lib/python/Components/ServiceList.py
index dc17ca9e4f2..f9f71e13932 100644
--- a/lib/python/Components/ServiceList.py
+++ b/lib/python/Components/ServiceList.py
@@ -388,19 +388,18 @@ def getCurrentIndex(self):
def setItemsPerPage(self):
numberOfRows = config.usage.serviceitems_per_page.value
- two_lines_val = int(config.usage.servicelist_twolines.value)
- if two_lines_val:
+ self.two_lines_val = int(config.usage.servicelist_twolines.value)
+ if self.two_lines_val:
numberOfRows = int(numberOfRows / ((self.ItemHeightTwoLineSkin / self.ItemHeightSkin)) if self.ItemHeightSkin and self.ItemHeightTwoLineSkin else 2)
- itemHeight = self.ItemHeightSkin if not two_lines_val else self.ItemHeightTwoLineSkin
+ itemHeight = self.ItemHeightTwoLineSkin if self.two_lines_val else self.ItemHeightSkin
if numberOfRows > 0:
itemHeight = self.listHeight // numberOfRows
- if two_lines_val:
+ if self.two_lines_val:
self.ItemHeightTwoLine = itemHeight
else:
self.ItemHeight = itemHeight
- self.l.setItemHeight(itemHeight)
- if self.listHeight and itemHeight:
- self.instance.resize(eSize(self.listWidth, self.listHeightOrig // itemHeight * itemHeight))
+ self.instance.resize(eSize(self.listWidth, self.listHeightOrig // self.ItemHeight * self.ItemHeight))
+ self.l.setItemHeight(self.ItemHeightTwoLine if self.two_lines_val else self.ItemHeight)
def getSelectionPosition(self):
# Adjust absolute index to index in displayed view
@@ -509,19 +508,17 @@ def setCurrentMarked(self, state):
def setMode(self, mode):
self.mode = mode
self.setItemsPerPage()
- two_lines_val = int(config.usage.servicelist_twolines.value)
- self.l.setItemHeight(self.ItemHeight if not two_lines_val else self.ItemHeightTwoLine)
- self.l.setVisualMode(eListboxServiceContent.visModeComplex if not two_lines_val else eListboxServiceContent.visSkinDefined)
+ self.l.setVisualMode(eListboxServiceContent.visModeComplex if not self.two_lines_val else eListboxServiceContent.visSkinDefined)
- if two_lines_val:
+ if self.two_lines_val:
timeText = _("%d min")
self.l.setTextTime(timeText)
- if two_lines_val > 1:
+ if self.two_lines_val > 1:
nextTitle = _("NEXT") + ": "
self.l.setNextTitle(nextTitle)
- self.l.setHasNextEvent(two_lines_val > 1)
+ self.l.setHasNextEvent(self.two_lines_val > 1)
if config.usage.service_icon_enable.value:
self.l.setGetPiconNameFunc(getPiconName)
@@ -540,7 +537,7 @@ def setMode(self, mode):
self.l.setServiceTypeIconMode(int(config.usage.servicetype_icon_mode.value))
self.l.setCryptoIconMode(int(config.usage.crypto_icon_mode.value))
self.l.setRecordIndicatorMode(int(config.usage.record_indicator_mode.value))
- self.l.setColumnWidth(-1 if two_lines_val else int(config.usage.servicelist_column.value))
+ self.l.setColumnWidth(-1 if self.two_lines_val else int(config.usage.servicelist_column.value))
self.l.setProgressBarMode(config.usage.show_event_progress_in_servicelist.value)
self.l.setChannelNumbersVisible(config.usage.show_channel_numbers_in_servicelist.value)
self.l.setAlternativeNumberingMode(config.usage.alternative_number_mode.value)
diff --git a/lib/python/Components/SystemInfo.py b/lib/python/Components/SystemInfo.py
index f3ff95d3f09..a03708b2d88 100644
--- a/lib/python/Components/SystemInfo.py
+++ b/lib/python/Components/SystemInfo.py
@@ -168,6 +168,7 @@ def setRCFile(source):
SystemInfo["RecoveryMode"] = False # This needs to be here so it can be reset by getMultibootslots!
SystemInfo["AndroidMode"] = False # This needs to be here so it can be reset by getMultibootslots!
SystemInfo["HasMultibootMTD"] = False # This needs to be here so it can be reset by getMultibootslots!
+SystemInfo["resetMBoot"] = False # Kexec kernel issue-this needs to be here so it can be reset by getMultibootslots if required!
SystemInfo["HasKexecUSB"] = False # This needs to be here so it can be reset by getMultibootslots!
SystemInfo["HasKexecMultiboot"] = fileHas("/proc/cmdline", "kexec=1") # This needs to be here so it can be tested by getMultibootslots!
from Tools.Multiboot import getMultibootslots # noqa: E402 # This import needs to be here to avoid a SystemInfo load loop!
diff --git a/lib/python/Components/Timeshift.py b/lib/python/Components/Timeshift.py
index 5547421ed04..c2bad169571 100644
--- a/lib/python/Components/Timeshift.py
+++ b/lib/python/Components/Timeshift.py
@@ -172,6 +172,14 @@ def __init__(self):
# Init PTS Infobar
+ self.onClose.append(self.__infoBarTimeshiftOnClose)
+
+ def __infoBarTimeshiftOnClose(self):
+ # on close remove Record Event Tracker from RecordTimer.on_state_change (otherwise callback will persist for destroyed instance after calling skin reloader)
+ print("[InfoBarTimeshift] __infoBarTimeshiftOnClose, remove Record Event Tracker from RecordTimer.on_state_change")
+ if self.ptsTimerEntryStateChange in self.session.nav.RecordTimer.on_state_change:
+ self.session.nav.RecordTimer.on_state_change.remove(self.ptsTimerEntryStateChange)
+
def __seekableStatusChanged(self):
# print("[Timeshift]__seekableStatusChanged")
self["TimeshiftActivateActions"].setEnabled(not self.isSeekable() and self.timeshiftEnabled() and int(config.timeshift.startdelay.value))
diff --git a/lib/python/Components/UsageConfig.py b/lib/python/Components/UsageConfig.py
index 81d4568a93f..83ca4e4763d 100644
--- a/lib/python/Components/UsageConfig.py
+++ b/lib/python/Components/UsageConfig.py
@@ -58,11 +58,11 @@ def alternativeNumberModeChange(configElement):
config.usage.hide_number_markers = ConfigYesNo(default=True)
config.usage.hide_number_markers.addNotifier(refreshServiceList, initial_call=False, immediate_feedback=False)
- config.usage.servicetype_icon_mode = ConfigSelection(default="0", choices=[("0", _("None")), ("1", _("Left from servicename (only available in single line mode)")), ("2", _("Right from servicename"))])
+ config.usage.servicetype_icon_mode = ConfigSelection(default="0", choices=[("0", _("None")), ("1", _("Left from servicename")), ("2", _("Right from servicename"))])
config.usage.servicetype_icon_mode.addNotifier(refreshServiceList, initial_call=False, immediate_feedback=False)
- config.usage.crypto_icon_mode = ConfigSelection(default="0", choices=[("0", _("None")), ("1", _("Left from servicename (only available in single line mode)")), ("2", _("Right from servicename"))])
+ config.usage.crypto_icon_mode = ConfigSelection(default="0", choices=[("0", _("None")), ("1", _("Left from servicename")), ("2", _("Right from servicename"))])
config.usage.crypto_icon_mode.addNotifier(refreshServiceList, initial_call=False, immediate_feedback=False)
- config.usage.record_indicator_mode = ConfigSelection(default="3", choices=[("0", _("None")), ("1", _("Left from servicename (only available in single line mode)")), ("2", _("Right from servicename")), ("3", _("Red colored"))])
+ config.usage.record_indicator_mode = ConfigSelection(default="3", choices=[("0", _("None")), ("1", _("Left from servicename")), ("2", _("Right from servicename")), ("3", _("Red colored"))])
config.usage.record_indicator_mode.addNotifier(refreshServiceList, initial_call=False, immediate_feedback=False)
choicelist = [("-1", _("Disable"))]
@@ -316,9 +316,9 @@ def showsecondinfobarChanged(configElement):
config.usage.show_bouquetalways = ConfigYesNo(default=False)
config.usage.show_event_progress_in_servicelist = ConfigSelection(default='barright', choices=[
('barleft', _("Progress bar left")),
- ('barright', _("Progress bar right (only available in single line mode)")),
+ ('barright', _("Progress bar right")),
('percleft', _("Percentage left")),
- ('percright', _("Percentage right (only available in single line mode)")),
+ ('percright', _("Percentage right")),
('no', _("No"))])
config.usage.show_channel_numbers_in_servicelist = ConfigYesNo(default=True)
config.usage.show_channel_jump_in_servicelist = ConfigSelection(default="alpha", choices=[
@@ -726,8 +726,6 @@ def setTimeDisplayStyles(configElement):
config.usage.boolean_graphic = ConfigSelection(default="no", choices={"no": _("no"), "yes": _("yes"), "only_bool": _("yes, but not in multi selections")})
config.usage.fast_skin_reload = ConfigYesNo(default=False)
- if not SystemInfo["DeveloperImage"]:
- config.usage.fast_skin_reload.value = False
if SystemInfo["hasXcoreVFD"]:
def set12to8characterVFD(configElement):
diff --git a/lib/python/Components/VolumeControl.py b/lib/python/Components/VolumeControl.py
index 17422a8d357..4e76fc0071a 100644
--- a/lib/python/Components/VolumeControl.py
+++ b/lib/python/Components/VolumeControl.py
@@ -33,12 +33,15 @@ def __init__(self, session):
vol = config.audio.volume.value
self.volctrl = eDVBVolumecontrol.getInstance()
self.volctrl.setVolume(vol, vol)
+ self.last_vol = vol
self.openDialogs()
self.hideVolTimer = eTimer()
self.hideVolTimer.callback.append(self.volHide)
+ self.stepVolTimer = eTimer()
+
def openDialogs(self):
self.volumeDialog = self.session.instantiateDialog(Volume)
self.volumeDialog.setAnimationMode(0)
@@ -85,7 +88,14 @@ def setVolume(self, direction):
def volHide(self):
self.volumeDialog.hide()
- self.muteDialog.hide()
+ #//set volume on if muted and volume is changed in webif
+ vol = self.volctrl.getVolume()
+ if self.volctrl.isMuted() and self.last_vol != vol:
+ self.volctrl.volumeUnMute()
+ self.last_vol = vol
+ #//
+ if not self.volctrl.isMuted() or config.av.volume_hide_mute.value:
+ self.muteDialog.hide()
def showMute(self):
if self.volctrl.isMuted():
@@ -106,3 +116,12 @@ def volMute(self, showMuteSymbol=True, force=False):
self.volumeDialog.setValue(vol)
self.volumeDialog.show()
self.hideVolTimer.start(3000, True)
+
+ def stepVolume(self):
+ if self.stepVolTimer.isActive():
+ step = config.av.volume_stepsize_fastmode.value
+ else:
+ self.getInputConfig()
+ step = config.av.volume_stepsize.value
+ self.stepVolTimer.start(self.repeat, True)
+ return step
\ No newline at end of file
diff --git a/lib/python/Components/config.py b/lib/python/Components/config.py
index 8638cd75bed..6c4f72ba97b 100644
--- a/lib/python/Components/config.py
+++ b/lib/python/Components/config.py
@@ -588,6 +588,12 @@ def trueValues(self):
# This should be set in the __init__() but has been done this way as a workaround for a stupid broken plugin that fails to call ConfigBoolean.__init__().
return ("1", "enable", "on", "true", "yes")
+ def isChanged(self):
+ # Make booleans checks with saved value non case sensitive
+ sv = self.saved_value or self.tostring(self.default)
+ strv = self.tostring(self.value)
+ return strv.lower() != sv.lower()
+
class ConfigEnableDisable(ConfigBoolean):
def __init__(self, default=False, graphic=True):
diff --git a/lib/python/Plugins/SystemPlugins/CableScan/plugin.py b/lib/python/Plugins/SystemPlugins/CableScan/plugin.py
index 27b324bb8e6..7ed1a876013 100644
--- a/lib/python/Plugins/SystemPlugins/CableScan/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/CableScan/plugin.py
@@ -8,7 +8,6 @@
from Components.ActionMap import ActionMap
from Components.NimManager import nimmanager
from Components.config import config, ConfigSubsection, ConfigSelection, ConfigYesNo, ConfigInteger, ConfigFloat
-from Components.Sources.StaticText import StaticText
from Components.ProgressBar import ProgressBar
from Components.Pixmap import Pixmap
from Components.ServiceList import refreshServiceList
diff --git a/lib/python/Plugins/SystemPlugins/FastChannelChange/plugin.py b/lib/python/Plugins/SystemPlugins/FastChannelChange/plugin.py
index 83fa70a0806..0dfeb644bfc 100644
--- a/lib/python/Plugins/SystemPlugins/FastChannelChange/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/FastChannelChange/plugin.py
@@ -527,7 +527,7 @@ def FCCStart(session, **kwargs):
def main(menuid, **kwargs):
if menuid == "scan":
- return [(_("Fast Channel Change"), FCCStart, "FCCSetup", 5)]
+ return [(_("Fast Channel Change"), FCCStart, "FCCSetup", None)]
else:
return []
diff --git a/lib/python/Plugins/SystemPlugins/FastScan/plugin.py b/lib/python/Plugins/SystemPlugins/FastScan/plugin.py
index 4764a4e5e5a..c2132451fbe 100644
--- a/lib/python/Plugins/SystemPlugins/FastScan/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/FastScan/plugin.py
@@ -5,7 +5,6 @@
from Screens.Setup import Setup
from Screens.MessageBox import MessageBox
from Components.config import config, ConfigSelection, ConfigYesNo, ConfigSubsection, ConfigText
-from Components.ConfigList import ConfigListScreen
from Components.NimManager import nimmanager
from Components.Label import Label
from Components.Pixmap import Pixmap
diff --git a/lib/python/Plugins/SystemPlugins/OpentvZapper/opentv_zapper.py b/lib/python/Plugins/SystemPlugins/OpentvZapper/opentv_zapper.py
index f0d3d29ed66..ce494874485 100644
--- a/lib/python/Plugins/SystemPlugins/OpentvZapper/opentv_zapper.py
+++ b/lib/python/Plugins/SystemPlugins/OpentvZapper/opentv_zapper.py
@@ -1,6 +1,3 @@
-import codecs
-import re
-
from Components.config import config, configfile
from Components.NimManager import nimmanager
@@ -12,7 +9,7 @@
# from this plugin
from .providers import providers
-from enigma import eDVBDB, eServiceReference, eTimer, eDVBFrontendParametersSatellite
+from enigma import eDVBDB, eServiceReference, eTimer, eDVBFrontendParametersSatellite, eDVBFrontendParameters
from time import localtime, time, strftime, mktime
@@ -23,7 +20,6 @@
from enigma import ePoint, eSize
debug_name = "opentv_zapper"
-lamedb_path = "/etc/enigma2"
download_interval = config.plugins.opentvzapper.update_interval.value * 60 * 60 # 6 hours
download_duration = 3 * 60 # stay tuned for 3 minutes
start_first_download = 5 * 60 # 5 minutes after booting
@@ -58,7 +54,7 @@ def play(self, service):
return True
def stop(self):
- if self.currentService == (self.navcore and self.navcore.getCurrentlyPlayingServiceReference()): # check the user hasn't zapped in the mean time
+ if isinstance(self.currentService, eServiceReference) and isinstance(playingref := self.navcore and self.navcore.getCurrentlyPlayingServiceReference(), eServiceReference) and self.currentService == playingref: # check the user hasn't zapped in the mean time
if self.currentBouquet is not None:
ChannelSelection.instance.setRoot(self.currentBouquet)
self.navcore.playService(self.previousService)
@@ -123,582 +119,6 @@ def stop(self):
self.session.pipshown = False
-class LamedbReader():
- def readLamedb(self, path):
- # print("[%s-LamedbReader] Reading lamedb..." % (debug_name))
-
- transponders = {}
-
- try:
- lamedb = open(path + "/lamedb", "r")
- except Exception:
- return transponders
-
- content = lamedb.read()
- lamedb.close()
-
- lamedb_ver = 4
- result = re.match('eDVB services /([45])/', content)
- if result:
- lamedb_ver = int(result.group(1))
- # print("[%s-LamedbReader] lamedb ver" % (debug_name), lamedb_ver)
- if lamedb_ver == 4:
- transponders = self.parseLamedbV4Content(content)
- elif lamedb_ver == 5:
- transponders = self.parseLamedbV5Content(content)
- return transponders
-
- def parseLamedbV4Content(self, content):
- transponders = {}
- transponders_count = 0
- services_count = 0
-
- tp_start = content.find("transponders\n")
- tp_stop = content.find("end\n")
-
- tp_blocks = content[tp_start + 13:tp_stop].strip().split("/")
- content = content[tp_stop + 4:]
-
- for block in tp_blocks:
- rows = block.strip().split("\n")
- if len(rows) != 2:
- continue
-
- first_row = rows[0].strip().split(":")
- if len(first_row) != 3:
- continue
-
- transponder = {}
- transponder["services"] = {}
- transponder["namespace"] = int(first_row[0], 16)
- transponder["transport_stream_id"] = int(first_row[1], 16)
- transponder["original_network_id"] = int(first_row[2], 16)
-
- # print("%x:%x:%x" % (namespace, transport_stream_id, original_network_id))
- second_row = rows[1].strip()
- transponder["dvb_type"] = 'dvb' + second_row[0]
- if transponder["dvb_type"] not in ["dvbs", "dvbt", "dvbc"]:
- continue
-
- second_row = second_row[2:].split(":")
-
- if transponder["dvb_type"] == "dvbs" and len(second_row) not in (7, 11, 14, 16):
- continue
- if transponder["dvb_type"] == "dvbt" and len(second_row) != 12:
- continue
- if transponder["dvb_type"] == "dvbc" and len(second_row) != 7:
- continue
-
- if transponder["dvb_type"] == "dvbs":
- transponder["frequency"] = int(second_row[0])
- transponder["symbol_rate"] = int(second_row[1])
- transponder["polarization"] = int(second_row[2])
- transponder["fec_inner"] = int(second_row[3])
- orbital_position = int(second_row[4])
- if orbital_position < 0:
- transponder["orbital_position"] = orbital_position + 3600
- else:
- transponder["orbital_position"] = orbital_position
-
- transponder["inversion"] = int(second_row[5])
- transponder["flags"] = int(second_row[6])
- if len(second_row) == 7: # DVB-S
- transponder["system"] = 0
- else: # DVB-S2
- transponder["system"] = int(second_row[7])
- transponder["modulation"] = int(second_row[8])
- transponder["roll_off"] = int(second_row[9])
- transponder["pilot"] = int(second_row[10])
- if len(second_row) > 13: # Multistream
- transponder["is_id"] = int(second_row[11])
- transponder["pls_code"] = int(second_row[12])
- transponder["pls_mode"] = int(second_row[13])
- if len(second_row) > 15: # T2MI
- transponder["t2mi_plp_id"] = int(second_row[14])
- transponder["t2mi_pid"] = int(second_row[15])
- elif transponder["dvb_type"] == "dvbt":
- transponder["frequency"] = int(second_row[0])
- transponder["bandwidth"] = int(second_row[1])
- transponder["code_rate_hp"] = int(second_row[2])
- transponder["code_rate_lp"] = int(second_row[3])
- transponder["modulation"] = int(second_row[4])
- transponder["transmission_mode"] = int(second_row[5])
- transponder["guard_interval"] = int(second_row[6])
- transponder["hierarchy"] = int(second_row[7])
- transponder["inversion"] = int(second_row[8])
- transponder["flags"] = int(second_row[9])
- transponder["system"] = int(second_row[10])
- transponder["plpid"] = int(second_row[11])
- elif transponder["dvb_type"] == "dvbc":
- transponder["frequency"] = int(second_row[0])
- transponder["symbol_rate"] = int(second_row[1])
- transponder["inversion"] = int(second_row[2])
- transponder["modulation"] = int(second_row[3])
- transponder["fec_inner"] = int(second_row[4])
- transponder["flags"] = int(second_row[5])
- transponder["system"] = int(second_row[6])
-
- key = "%x:%x:%x" % (transponder["namespace"], transponder["transport_stream_id"], transponder["original_network_id"])
- transponders[key] = transponder
- transponders_count += 1
-
- srv_start = content.find("services\n")
- srv_stop = content.rfind("end\n")
-
- srv_blocks = content[srv_start + 9:srv_stop].strip().split("\n")
-
- for i in range(0, len(srv_blocks) // 3):
- service_reference = srv_blocks[i * 3].strip()
- service_name = srv_blocks[(i * 3) + 1].strip()
- service_provider = srv_blocks[(i * 3) + 2].strip()
- service_reference = service_reference.split(":")
-
- if len(service_reference) not in (6, 7):
- continue
-
- service = {}
- service["service_name"] = service_name
- service["service_line"] = service_provider
- service["service_id"] = int(service_reference[0], 16)
- service["namespace"] = int(service_reference[1], 16)
- service["transport_stream_id"] = int(service_reference[2], 16)
- service["original_network_id"] = int(service_reference[3], 16)
- service["service_type"] = int(service_reference[4])
- service["flags"] = int(service_reference[5])
- if len(service_reference) == 7 and int(service_reference[6], 16) != 0:
- service["ATSC_source_id"] = int(service_reference[6], 16)
-
- key = "%x:%x:%x" % (service["namespace"], service["transport_stream_id"], service["original_network_id"])
- if key not in transponders:
- continue
-
- # The original (correct) code
- # transponders[key]["services"][service["service_id"]] = service
-
- # Dirty hack to work around the (well known) service type bug in lamedb/enigma2
- transponders[key]["services"]["%x:%x" % (service["service_type"], service["service_id"])] = service
-
- services_count += 1
-
- # print("[%s-LamedbReader] Read %d transponders and %d services" % (debug_name, transponders_count, services_count))
- return transponders
-
- def parseLamedbV5Content(self, content):
- transponders = {}
- transponders_count = 0
- services_count = 0
-
- lines = content.splitlines()
- for line in lines:
- if line.startswith("t:"):
- first_part = line.strip().split(",")[0][2:].split(":")
- if len(first_part) != 3:
- continue
-
- transponder = {}
- transponder["services"] = {}
- transponder["namespace"] = int(first_part[0], 16)
- transponder["transport_stream_id"] = int(first_part[1], 16)
- transponder["original_network_id"] = int(first_part[2], 16)
-
- second_part = line.strip().split(",")[1]
- transponder["dvb_type"] = 'dvb' + second_part[0]
- if transponder["dvb_type"] not in ["dvbs", "dvbt", "dvbc"]:
- continue
-
- second_part = second_part[2:].split(":")
-
- if transponder["dvb_type"] == "dvbs" and len(second_part) not in (7, 11):
- continue
- if transponder["dvb_type"] == "dvbt" and len(second_part) != 12:
- continue
- if transponder["dvb_type"] == "dvbc" and len(second_part) != 7:
- continue
-
- if transponder["dvb_type"] == "dvbs":
- transponder["frequency"] = int(second_part[0])
- transponder["symbol_rate"] = int(second_part[1])
- transponder["polarization"] = int(second_part[2])
- transponder["fec_inner"] = int(second_part[3])
- orbital_position = int(second_part[4])
- if orbital_position < 0:
- transponder["orbital_position"] = orbital_position + 3600
- else:
- transponder["orbital_position"] = orbital_position
-
- transponder["inversion"] = int(second_part[5])
- transponder["flags"] = int(second_part[6])
- if len(second_part) == 7: # DVB-S
- transponder["system"] = 0
- else: # DVB-S2
- transponder["system"] = int(second_part[7])
- transponder["modulation"] = int(second_part[8])
- transponder["roll_off"] = int(second_part[9])
- transponder["pilot"] = int(second_part[10])
- for part in line.strip().split(",")[2:]: # Multistream/T2MI
- if part.startswith("MIS/PLS:") and len(part[8:].split(":")) == 3:
- transponder["is_id"] = int(part[8:].split(":")[0])
- transponder["pls_code"] = int(part[8:].split(":")[1])
- transponder["pls_mode"] = int(part[8:].split(":")[2])
- elif part.startswith("T2MI:") and len(part[5:].split(":")) == 2:
- transponder["t2mi_plp_id"] = int(part[5:].split(":")[0])
- transponder["t2mi_pid"] = int(part[5:].split(":")[1])
- elif transponder["dvb_type"] == "dvbt":
- transponder["frequency"] = int(second_part[0])
- transponder["bandwidth"] = int(second_part[1])
- transponder["code_rate_hp"] = int(second_part[2])
- transponder["code_rate_lp"] = int(second_part[3])
- transponder["modulation"] = int(second_part[4])
- transponder["transmission_mode"] = int(second_part[5])
- transponder["guard_interval"] = int(second_part[6])
- transponder["hierarchy"] = int(second_part[7])
- transponder["inversion"] = int(second_part[8])
- transponder["flags"] = int(second_part[9])
- transponder["system"] = int(second_part[10])
- transponder["plpid"] = int(second_part[11])
- elif transponder["dvb_type"] == "dvbc":
- transponder["frequency"] = int(second_part[0])
- transponder["symbol_rate"] = int(second_part[1])
- transponder["inversion"] = int(second_part[2])
- transponder["modulation"] = int(second_part[3])
- transponder["fec_inner"] = int(second_part[4])
- transponder["flags"] = int(second_part[5])
- transponder["system"] = int(second_part[6])
-
- key = "%x:%x:%x" % (transponder["namespace"], transponder["transport_stream_id"], transponder["original_network_id"])
- transponders[key] = transponder
- transponders_count += 1
- elif line.startswith("s:"):
- service_reference = line.strip().split(",")[0][2:]
- service_name = line.strip().split('"', 1)[1].split('"')[0]
- third_part = line.strip().split('"', 2)[2]
- service_provider = ""
- if len(third_part):
- service_provider = third_part[1:]
- service_reference = service_reference.split(":")
- if len(service_reference) != 6 and len(service_reference) != 7:
- continue
-
- service = {}
- service["service_name"] = service_name
- service["service_line"] = service_provider
- service["service_id"] = int(service_reference[0], 16)
- service["namespace"] = int(service_reference[1], 16)
- service["transport_stream_id"] = int(service_reference[2], 16)
- service["original_network_id"] = int(service_reference[3], 16)
- service["service_type"] = int(service_reference[4])
- service["flags"] = int(service_reference[5])
- if len(service_reference) == 7 and int(service_reference[6], 16) != 0:
- service["ATSC_source_id"] = int(service_reference[6], 16)
-
- key = "%x:%x:%x" % (service["namespace"], service["transport_stream_id"], service["original_network_id"])
- if key not in transponders:
- continue
-
- # The original (correct) code
- # transponders[key]["services"][service["service_id"]] = service
-
- # Dirty hack to work around the (well known) service type bug in lamedb/enigma2
- transponders[key]["services"]["%x:%x" % (service["service_type"], service["service_id"])] = service
-
- services_count += 1
-
- # print("[%s-LamedbReader] Read %d transponders and %d services" % (debug_name, transponders_count, services_count))
- return transponders
-
-
-class LamedbWriter():
- def writeLamedb(self, path, transponders, filename="lamedb"):
- # print("[%s-LamedbWriter] Writing lamedb..." % (debug_name))
-
- transponders_count = 0
- services_count = 0
-
- lamedblist = []
- lamedblist.append("eDVB services /4/\n")
- lamedblist.append("transponders\n")
-
- for key in transponders.keys():
- transponder = transponders[key]
- if "services" not in transponder.keys() or len(transponder["services"]) < 1:
- continue
- lamedblist.append("%08x:%04x:%04x\n" %
- (transponder["namespace"],
- transponder["transport_stream_id"],
- transponder["original_network_id"]))
-
- if transponder["dvb_type"] == "dvbs":
- if transponder["orbital_position"] > 1800:
- orbital_position = transponder["orbital_position"] - 3600
- else:
- orbital_position = transponder["orbital_position"]
-
- if transponder["system"] == 0: # DVB-S
- lamedblist.append("\ts %d:%d:%d:%d:%d:%d:%d\n" %
- (transponder["frequency"],
- transponder["symbol_rate"],
- transponder["polarization"],
- transponder["fec_inner"],
- orbital_position,
- transponder["inversion"],
- transponder["flags"]))
- else: # DVB-S2
- multistream = ''
- t2mi = ''
- if "t2mi_plp_id" in transponder and "t2mi_pid" in transponder:
- t2mi = ':%d:%d' % (
- transponder["t2mi_plp_id"],
- transponder["t2mi_pid"])
- if "is_id" in transponder and "pls_code" in transponder and "pls_mode" in transponder:
- multistream = ':%d:%d:%d' % (
- transponder["is_id"],
- transponder["pls_code"],
- transponder["pls_mode"])
- if t2mi and not multistream: # this is to pad t2mi values if necessary.
- try: # some images are still not multistream aware after all this time
- multistream = ':%d:%d:%d' % (
- eDVBFrontendParametersSatellite.No_Stream_Id_Filter,
- eDVBFrontendParametersSatellite.PLS_Gold,
- eDVBFrontendParametersSatellite.PLS_Default_Gold_Code)
- except AttributeError:
- pass
- lamedblist.append("\ts %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d%s%s\n" %
- (transponder["frequency"],
- transponder["symbol_rate"],
- transponder["polarization"],
- transponder["fec_inner"],
- orbital_position,
- transponder["inversion"],
- transponder["flags"],
- transponder["system"],
- transponder["modulation"],
- transponder["roll_off"],
- transponder["pilot"],
- multistream,
- t2mi))
- elif transponder["dvb_type"] == "dvbt":
- lamedblist.append("\tt %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n" %
- (transponder["frequency"],
- transponder["bandwidth"],
- transponder["code_rate_hp"],
- transponder["code_rate_lp"],
- transponder["modulation"],
- transponder["transmission_mode"],
- transponder["guard_interval"],
- transponder["hierarchy"],
- transponder["inversion"],
- transponder["flags"],
- transponder["system"],
- transponder["plpid"]))
- elif transponder["dvb_type"] == "dvbc":
- lamedblist.append("\tc %d:%d:%d:%d:%d:%d:%d\n" %
- (transponder["frequency"],
- transponder["symbol_rate"],
- transponder["inversion"],
- transponder["modulation"],
- transponder["fec_inner"],
- transponder["flags"],
- transponder["system"]))
- lamedblist.append("/\n")
- transponders_count += 1
-
- lamedblist.append("end\nservices\n")
- for key in transponders.keys():
- transponder = transponders[key]
- if "services" not in transponder.keys():
- continue
-
- for key2 in transponder["services"].keys():
- service = transponder["services"][key2]
-
- lamedblist.append("%04x:%08x:%04x:%04x:%d:%d%s\n" %
- (service["service_id"],
- service["namespace"],
- service["transport_stream_id"],
- service["original_network_id"],
- service["service_type"],
- service["flags"],
- ":%x" % service["ATSC_source_id"] if "ATSC_source_id" in service else ""))
-
- control_chars = ''.join(list(map(chr, list(range(0, 32)) + list(range(127, 160)))))
- control_char_re = re.compile('[%s]' % re.escape(control_chars))
- if 'provider_name' in service.keys():
- service_name = control_char_re.sub('', service["service_name"])
- provider_name = control_char_re.sub('', service["provider_name"])
- else:
- service_name = service["service_name"]
-
- lamedblist.append("%s\n" % service_name)
-
- service_ca = ""
- if "free_ca" in service.keys() and service["free_ca"] != 0:
- service_ca = ",C:0000"
-
- service_flags = ""
- if "service_flags" in service.keys() and service["service_flags"] > 0:
- service_flags = ",f:%x" % service["service_flags"]
-
- if 'service_line' in service.keys():
- lamedblist.append("%s\n" % service["service_line"])
- else:
- lamedblist.append("p:%s%s%s\n" % (provider_name, service_ca, service_flags))
- services_count += 1
-
- lamedblist.append("end\nHave a lot of bugs!\n")
- lamedb = codecs.open(path + "/" + filename, "w", encoding="utf-8", errors="ignore")
- lamedb.write(''.join(lamedblist))
- lamedb.close()
- del lamedblist
-
- # print("[%s-LamedbWriter] Wrote %d transponders and %d services" % (debug_name, transponders_count, services_count))
-
- def writeLamedb5(self, path, transponders, filename="lamedb5"):
- # print("[%s-LamedbWriter] Writing lamedb V5..." % (debug_name))
-
- transponders_count = 0
- services_count = 0
-
- lamedblist = []
- lamedblist.append("eDVB services /5/\n")
- lamedblist.append("# Transponders: t:dvb_namespace:transport_stream_id:original_network_id,FEPARMS\n")
- lamedblist.append("# DVBS FEPARMS: s:frequency:symbol_rate:polarisation:fec:orbital_position:inversion:flags\n")
- lamedblist.append("# DVBS2 FEPARMS: s:frequency:symbol_rate:polarisation:fec:orbital_position:inversion:flags:system:modulation:rolloff:pilot[,MIS/PLS:is_id:pls_code:pls_mode][,T2MI:t2mi_plp_id:t2mi_pid]\n")
- lamedblist.append("# DVBT FEPARMS: t:frequency:bandwidth:code_rate_HP:code_rate_LP:modulation:transmission_mode:guard_interval:hierarchy:inversion:flags:system:plp_id\n")
- lamedblist.append("# DVBC FEPARMS: c:frequency:symbol_rate:inversion:modulation:fec_inner:flags:system\n")
- lamedblist.append('# Services: s:service_id:dvb_namespace:transport_stream_id:original_network_id:service_type:service_number:source_id,"service_name"[,p:provider_name][,c:cached_pid]*[,C:cached_capid]*[,f:flags]\n')
-
- for key in transponders.keys():
- transponder = transponders[key]
- if "services" not in transponder.keys() or len(transponder["services"]) < 1:
- continue
- lamedblist.append("t:%08x:%04x:%04x," %
- (transponder["namespace"],
- transponder["transport_stream_id"],
- transponder["original_network_id"]))
-
- if transponder["dvb_type"] == "dvbs":
- if transponder["orbital_position"] > 1800:
- orbital_position = transponder["orbital_position"] - 3600
- else:
- orbital_position = transponder["orbital_position"]
-
- if transponder["system"] == 0: # DVB-S
- lamedblist.append("s:%d:%d:%d:%d:%d:%d:%d\n" %
- (transponder["frequency"],
- transponder["symbol_rate"],
- transponder["polarization"],
- transponder["fec_inner"],
- orbital_position,
- transponder["inversion"],
- transponder["flags"]))
- else: # DVB-S2
- multistream = ''
- t2mi = ''
- if "is_id" in transponder and "pls_code" in transponder and "pls_mode" in transponder:
- try: # some images are still not multistream aware after all this time
- # don't write default values
- if not (transponder["is_id"] == eDVBFrontendParametersSatellite.No_Stream_Id_Filter and transponder["pls_code"] == eDVBFrontendParametersSatellite.PLS_Gold and transponder["pls_mode"] == eDVBFrontendParametersSatellite.PLS_Default_Gold_Code):
- multistream = ',MIS/PLS:%d:%d:%d' % (
- transponder["is_id"],
- transponder["pls_code"],
- transponder["pls_mode"])
- except AttributeError:
- pass
- if "t2mi_plp_id" in transponder and "t2mi_pid" in transponder:
- t2mi = ',T2MI:%d:%d' % (
- transponder["t2mi_plp_id"],
- transponder["t2mi_pid"])
- lamedblist.append("s:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d%s%s\n" %
- (transponder["frequency"],
- transponder["symbol_rate"],
- transponder["polarization"],
- transponder["fec_inner"],
- orbital_position,
- transponder["inversion"],
- transponder["flags"],
- transponder["system"],
- transponder["modulation"],
- transponder["roll_off"],
- transponder["pilot"],
- multistream,
- t2mi))
- elif transponder["dvb_type"] == "dvbt":
- lamedblist.append("t:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n" %
- (transponder["frequency"],
- transponder["bandwidth"],
- transponder["code_rate_hp"],
- transponder["code_rate_lp"],
- transponder["modulation"],
- transponder["transmission_mode"],
- transponder["guard_interval"],
- transponder["hierarchy"],
- transponder["inversion"],
- transponder["flags"],
- transponder["system"],
- transponder["plpid"]))
- elif transponder["dvb_type"] == "dvbc":
- lamedblist.append("c:%d:%d:%d:%d:%d:%d:%d\n" %
- (transponder["frequency"],
- transponder["symbol_rate"],
- transponder["inversion"],
- transponder["modulation"],
- transponder["fec_inner"],
- transponder["flags"],
- transponder["system"]))
- transponders_count += 1
-
- for key in transponders.keys():
- transponder = transponders[key]
- if "services" not in transponder.keys():
- continue
-
- for key2 in transponder["services"].keys():
- service = transponder["services"][key2]
-
- lamedblist.append("s:%04x:%08x:%04x:%04x:%d:%d%s," %
- (service["service_id"],
- service["namespace"],
- service["transport_stream_id"],
- service["original_network_id"],
- service["service_type"],
- service["flags"],
- ":%x" % service["ATSC_source_id"] if "ATSC_source_id" in service else ":0"))
-
- control_chars = ''.join(list(map(chr, list(range(0, 32)) + list(range(127, 160)))))
- control_char_re = re.compile('[%s]' % re.escape(control_chars))
- if 'provider_name' in service.keys():
- service_name = control_char_re.sub('', service["service_name"])
- provider_name = control_char_re.sub('', service["provider_name"])
- else:
- service_name = service["service_name"]
-
- lamedblist.append('"%s"' % service_name)
-
- service_ca = ""
- if "free_ca" in service.keys() and service["free_ca"] != 0:
- service_ca = ",C:0000"
-
- service_flags = ""
- if "service_flags" in service.keys() and service["service_flags"] > 0:
- service_flags = ",f:%x" % service["service_flags"]
-
- if 'service_line' in service.keys(): # from lamedb
- if len(service["service_line"]):
- lamedblist.append(",%s\n" % service["service_line"])
- else:
- lamedblist.append("\n")
- else: # from scanner
- lamedblist.append(",p:%s%s%s\n" % (provider_name, service_ca, service_flags))
- services_count += 1
-
- lamedb = codecs.open(path + "/" + filename, "w", encoding="utf-8", errors="ignore")
- lamedb.write(''.join(lamedblist))
- lamedb.close()
- del lamedblist
-
- # print("[%s-LamedbWriter] Wrote %d transponders and %d services" % (debug_name, transponders_count, services_count))
-
-
class Opentv_Zapper():
def __init__(self):
self.session = None
@@ -723,24 +143,41 @@ def checkAvailableTuners(self):
self.num_tuners = len(self.tuners)
return bool(self.num_tuners)
+ def setParams(self):
+ params = eDVBFrontendParametersSatellite()
+ params.frequency = self.transponder["frequency"]
+ params.symbol_rate = self.transponder["symbol_rate"]
+ params.polarisation = self.transponder["polarization"]
+ params.fec = self.transponder["fec_inner"]
+ params.inversion = eDVBFrontendParametersSatellite.Inversion_Unknown
+ params.orbital_position = self.transponder["orbital_position"]
+ params.system = self.transponder["system"]
+ params.modulation = self.transponder["modulation"]
+ params.rolloff = eDVBFrontendParametersSatellite.RollOff_auto
+ params.pilot = eDVBFrontendParametersSatellite.Pilot_Unknown
+ if hasattr(eDVBFrontendParametersSatellite, "No_Stream_Id_Filter"):
+ params.is_id = eDVBFrontendParametersSatellite.No_Stream_Id_Filter
+ if hasattr(eDVBFrontendParametersSatellite, "PLS_Gold"):
+ params.pls_mode = eDVBFrontendParametersSatellite.PLS_Gold
+ if hasattr(eDVBFrontendParametersSatellite, "PLS_Default_Gold_Code"):
+ params.pls_code = eDVBFrontendParametersSatellite.PLS_Default_Gold_Code
+ if hasattr(eDVBFrontendParametersSatellite, "No_T2MI_PLP_Id"):
+ params.t2mi_plp_id = eDVBFrontendParametersSatellite.No_T2MI_PLP_Id
+ if hasattr(eDVBFrontendParametersSatellite, "T2MI_Default_Pid"):
+ params.t2mi_pid = eDVBFrontendParametersSatellite.T2MI_Default_Pid
+ return params
+
def initialize(self):
provider = config.plugins.opentvzapper.providers.value
if not self.checkAvailableTuners() or self.initialized == provider: # if no tuner is available for this provider or we are already initialized, abort.
return
self.service = providers[provider]["service"]
self.sref = make_sref(self.service)
- transponder_key = "%x:%x:%x" % (self.transponder["namespace"], self.transponder["transport_stream_id"], self.transponder["original_network_id"])
- service_key = "%x:%x" % (self.service["service_type"], self.service["service_id"])
- transponders = LamedbReader().readLamedb(lamedb_path)
- if transponder_key not in transponders:
- transponders[transponder_key] = self.transponder
- if service_key not in transponders[transponder_key]["services"]:
- transponders[transponder_key]["services"][service_key] = self.service
- print("[%s] download service missing from lamedb. Adding now." % (debug_name))
- writer = LamedbWriter()
- writer.writeLamedb(lamedb_path, transponders)
- writer.writeLamedb5(lamedb_path, transponders)
- eDVBDB.getInstance().reloadServicelist()
+ self.sref.setName(self.service["service_name"])
+ self.sref.setProvider(self.service["service_provider"])
+ params_fe = eDVBFrontendParameters()
+ params_fe.setDVBS(self.setParams(), False)
+ eDVBDB.getInstance().addChannelToDB(self.sref, params_fe, self.service["service_cachedpids"], self.service["service_capids"], self.service["flags"])
self.initialized = provider
print("[%s] initialize completed." % (debug_name))
diff --git a/lib/python/Plugins/SystemPlugins/OpentvZapper/providers.py b/lib/python/Plugins/SystemPlugins/OpentvZapper/providers.py
index b1abcd6000a..bf7e2ee76a6 100644
--- a/lib/python/Plugins/SystemPlugins/OpentvZapper/providers.py
+++ b/lib/python/Plugins/SystemPlugins/OpentvZapper/providers.py
@@ -1,3 +1,6 @@
+from enigma import eDVBFrontendParametersSatellite
+
+
providers = {
"Astra 28.2": {
"transponder": {
@@ -12,19 +15,20 @@
'frequency': 11778000,
'flags': 0,
'transport_stream_id': 2004,
- 'dvb_type': 'dvbs',
- 'services': {},
+ 'modulation': eDVBFrontendParametersSatellite.Modulation_QPSK,
},
"service": {
'service_name': 'IEPG data 1',
'namespace': 18481152,
- 'service_line': 'p:BSkyB,c:010288,c:031ffe',
'original_network_id': 2,
'flags': 0,
'service_id': 4189,
'service_type': 1,
'transport_stream_id': 2004,
+ 'service_provider': 'BSkyB',
+ 'service_cachedpids': [(1, 0x0288), (3, 0x1ffe)],
+ 'service_capids': None,
},
}
}
diff --git a/lib/python/Plugins/SystemPlugins/ViX/BackupManager.py b/lib/python/Plugins/SystemPlugins/ViX/BackupManager.py
index 2d87b5e4923..243fa4ba45c 100644
--- a/lib/python/Plugins/SystemPlugins/ViX/BackupManager.py
+++ b/lib/python/Plugins/SystemPlugins/ViX/BackupManager.py
@@ -11,7 +11,7 @@
from Components.config import configfile, config, ConfigSubsection, ConfigYesNo, ConfigSelection, ConfigText, ConfigNumber, ConfigLocations, NoSave, ConfigClock, ConfigDirectory
from Components.Console import Console
from Components.FileList import MultiFileSelectList, FileList
-from Components.Harddisk import harddiskmanager
+from Components.Harddisk import harddiskmanager, bytesToHumanReadable
from Components.Label import Label
from Components.MenuList import MenuList
from Components.Sources.StaticText import StaticText
@@ -265,7 +265,8 @@ def populate_List(self):
self["lab1"].setText(_("The chosen location does not exist, using /media/hdd.") + "\n" + _("Select a backup to restore:"))
else:
self.BackupDirectory = config.backupmanager.backuplocation.value + "backup/"
- self["lab1"].setText(_("Device: ") + config.backupmanager.backuplocation.value + "\n" + _("Select a backup to restore:"))
+ s = statvfs(config.imagemanager.backuplocation.value)
+ self["lab1"].setText(_("Device: ") + config.backupmanager.backuplocation.value + " " + _("Free space:") + " " + bytesToHumanReadable(s.f_bsize * s.f_bavail) + "\n" + _("Select a backup to restore:"))
try:
if not path.exists(self.BackupDirectory):
mkdir(self.BackupDirectory, 0o755)
@@ -303,12 +304,6 @@ def showLog(self):
self.session.open(VIXBackupManagerLogView, filename)
def setupDone(self, test=None):
- if config.backupmanager.folderprefix.value == "":
- config.backupmanager.folderprefix.value = defaultprefix
- config.backupmanager.folderprefix.save()
- if not config.backupmanager.folderprefix.value.startswith(defaultprefix): # If the prefix doesn't start with the defaultprefix it is a tag...
- config.backupmanager.folderprefix.value = defaultprefix + "-" + config.backupmanager.folderprefix.value
- config.backupmanager.folderprefix.save()
self.populate_List()
self.doneConfiguring()
@@ -946,6 +941,15 @@ def backupfiles_choosen(self, ret):
config.backupmanager.save()
config.save()
+ def keySave(self):
+ if " " in config.backupmanager.folderprefix.value:
+ config.backupmanager.folderprefix.value = config.backupmanager.folderprefix.value.replace(" ", "")
+ if config.backupmanager.folderprefix.value == "":
+ config.backupmanager.folderprefix.value = defaultprefix
+ if not config.backupmanager.folderprefix.value.startswith(defaultprefix): # If the prefix doesn't start with the defaultprefix it is a tag...
+ config.backupmanager.folderprefix.value = defaultprefix + "-" + config.backupmanager.folderprefix.value
+ Setup.keySave(self)
+
class VIXBackupManagerLogView(TextBox):
skin = ["""
diff --git a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py
index d88c8437f7f..51a1109f74a 100644
--- a/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py
+++ b/lib/python/Plugins/SystemPlugins/ViX/ImageManager.py
@@ -11,9 +11,9 @@
from Components.ActionMap import ActionMap
from Components.Button import Button
from Components.ChoiceList import ChoiceList, ChoiceEntryComponent
-from Components.config import config, ConfigSubsection, ConfigYesNo, ConfigSelection, ConfigText, ConfigNumber, NoSave, ConfigClock, configfile
+from Components.config import config, ConfigSubsection, ConfigYesNo, ConfigSelection, ConfigText, ConfigNumber, NoSave, ConfigClock
from Components.Console import Console
-from Components.Harddisk import harddiskmanager, getProcMounts
+from Components.Harddisk import harddiskmanager, getProcMounts, bytesToHumanReadable
from Components.Label import Label
from Components.MenuList import MenuList
from Components.Sources.StaticText import StaticText
@@ -311,8 +311,7 @@ def populate_List(self):
else:
self.BackupDirectory = config.imagemanager.backuplocation.value + "imagebackups/"
s = statvfs(config.imagemanager.backuplocation.value)
- free = (s.f_bsize * s.f_bavail) // (1024 * 1024)
- self["lab1"].setText(_("Device: ") + config.imagemanager.backuplocation.value + " " + _("Free space:") + " " + str(free) + _("MB") + "\n" + _("Select an image to flash."))
+ self["lab1"].setText(_("Device: ") + config.imagemanager.backuplocation.value + " " + _("Free space:") + " " + bytesToHumanReadable(s.f_bsize * s.f_bavail) + "\n" + _("Select an image to flash."))
try:
if not path.exists(self.BackupDirectory):
mkdir(self.BackupDirectory, 0o755)
@@ -1736,16 +1735,15 @@ def __init__(self, session):
Setup.__init__(self, session=session, setup="viximagemanager", plugin="SystemPlugins/ViX")
def keySave(self):
+ if " " in config.imagemanager.folderprefix.value:
+ config.imagemanager.folderprefix.value = config.imagemanager.folderprefix.value.replace(" ", "")
if config.imagemanager.folderprefix.value == "":
config.imagemanager.folderprefix.value = defaultprefix
for configElement in (config.imagemanager.developer_username, config.imagemanager.developer_password):
if not configElement.value:
configElement.value = configElement.default
self.check_URL_format(config.imagemanager.imagefeed_MyBuild)
- for x in self["config"].list:
- x[1].save()
- configfile.save()
- self.close()
+ Setup.keySave(self)
def check_URL_format(self, configElement):
if configElement.value:
@@ -1753,3 +1751,19 @@ def check_URL_format(self, configElement):
configElement.value = configElement.value.strip("/") # remove any trailing slash
else:
configElement.value = configElement.default
+
+
+class KexecWarning(TextBox):
+ def __init__(self, session):
+ TextBox.__init__(self, session, text=self.warningText(), title="Kexec warning title")
+
+ def warningText(self):
+ return "\n\n".join([
+ _("Alert - the system has found an issue with the Vu+ Kexec Multiboot images - read the following information carefully"),
+ _("1. Try to reboot the box and check if this warning disappears"),
+ _("2. Try to re install Vu+ Multiboot as usual"),
+ _("3. If you wish to try and recover your Multiboot system then proceed as follows......."),
+ _("4. Login into the Recovery image using SSH or telnet."),
+ _("5. If you wish to backup eMMC slots 1,2,3 then enter 'tar -cvzf /media/hdd/linuxrootfsX.tar.gz /linuxrootfsX' where X is the slot number and repeat the command for each installed image slot in flash (so you have backup of installed flash images)"),
+ _("6. Then enter '/etc/init.d/kexec-multiboot-recovery start' "),
+ _("7. The script will copy the required files and then will automatically reboot the box"),])
diff --git a/lib/python/Plugins/SystemPlugins/ViX/menu.xml b/lib/python/Plugins/SystemPlugins/ViX/menu.xml
new file mode 100644
index 00000000000..a622bff2439
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/ViX/menu.xml
@@ -0,0 +1,44 @@
+
\ No newline at end of file
diff --git a/lib/python/Plugins/SystemPlugins/ViX/plugin.py b/lib/python/Plugins/SystemPlugins/ViX/plugin.py
index 5d815ccf885..304a9e3e547 100644
--- a/lib/python/Plugins/SystemPlugins/ViX/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/ViX/plugin.py
@@ -1,8 +1,12 @@
from os import listdir, path, stat
+from sys import modules
+import xml.etree.cElementTree
from Plugins.Plugin import PluginDescriptor
from Components.config import config
from Components.SystemInfo import SystemInfo
+from Screens.Menu import Menu
+from Tools.BoundFunction import boundFunction
from .BackupManager import BackupManagerautostart
from .ImageManager import ImageManagerautostart
@@ -65,19 +69,24 @@ def checkConfigBackup():
setLanguageFromBackup(backupAvailable)
-def VIXMenu(session):
- from .import ui
- return ui.VIXMenu(session)
+file = open("%s/menu.xml" % path.dirname(modules[__name__].__file__), 'r')
+mdom = xml.etree.cElementTree.parse(file)
+file.close()
-def UpgradeMain(session, **kwargs):
- session.open(VIXMenu)
+def VIXMenu(session, close=None, **kwargs):
+ session.openWithCallback(boundFunction(VIXMenuCallback, close), Menu, mdom.getroot())
+
+
+def VIXMenuCallback(close, answer=None):
+ if close and answer:
+ close(True)
def startSetup(menuid):
if menuid != "setup":
return []
- return [(_("ViX"), UpgradeMain, "vix_menu", 1010)]
+ return [(_("ViX"), VIXMenu, "vix_menu", 1010)]
def RestoreWizard(*args, **kwargs):
@@ -125,6 +134,11 @@ def BackupManagerMenu(session, **kwargs):
session.open(BackupManager)
+def KexecWarning(session):
+ from .ImageManager import KexecWarning
+ return KexecWarning(session)
+
+
def ImageManager(session):
from .ImageManager import VIXImageManager
return VIXImageManager(session)
@@ -195,15 +209,19 @@ def filescan(**kwargs):
def Plugins(**kwargs):
+ plist = []
+ if SystemInfo.get("resetMBoot"):
+ plist.append(PluginDescriptor(name=_("Kexec warning"), where=PluginDescriptor.WHERE_WIZARD, needsRestart=False, fnc=(20, KexecWarning)))
+
if SystemInfo["MultiBootSlot"] == 0: # only in recovery image
- plist = [PluginDescriptor(name=_("Image Manager"), where=PluginDescriptor.WHERE_MENU, needsRestart=False, fnc=ImageManagerStart)]
+ plist.append(PluginDescriptor(name=_("Image Manager"), where=PluginDescriptor.WHERE_MENU, needsRestart=False, fnc=ImageManagerStart))
if not config.misc.firstrun.value:
plist.append(PluginDescriptor(name=_("Vu+ ImageManager wizard"), where=PluginDescriptor.WHERE_WIZARD, needsRestart=False, fnc=(30, ImageManager)))
return plist
- plist = [
+ plist += [
PluginDescriptor(where=PluginDescriptor.WHERE_MENU, needsRestart=False, fnc=startSetup),
- PluginDescriptor(name=_("ViX Image Management"), where=PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain),
+ PluginDescriptor(name=_("ViX Image Management"), where=PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=VIXMenu),
PluginDescriptor(where=PluginDescriptor.WHERE_MENU, fnc=SoftcamSetup),
PluginDescriptor(where=PluginDescriptor.WHERE_MENU, fnc=PackageManagerSetup)]
if config.softcammanager.showinextensions.value:
diff --git a/lib/python/Plugins/SystemPlugins/ViX/ui.py b/lib/python/Plugins/SystemPlugins/ViX/ui.py
deleted file mode 100644
index 15ef978c7e9..00000000000
--- a/lib/python/Plugins/SystemPlugins/ViX/ui.py
+++ /dev/null
@@ -1,141 +0,0 @@
-from Components.ActionMap import NumberActionMap
-from Components.config import config
-from Components.Sources.StaticText import StaticText
-from Components.Sources.List import List
-from Components.SystemInfo import SystemInfo
-from Screens.ParentalControlSetup import ProtectedScreen
-from Screens.Screen import Screen
-
-
-class VIXMenu(Screen, ProtectedScreen):
- skin = ["""
-
-
-
-
- {"template": [
- MultiContentEntryText(pos = (%d,%d), size = (%d,%d), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
- ],
- "fonts": [gFont("Regular",%d)],
- "itemHeight":%d
- }
-
-
-
-
- {"template": [
- MultiContentEntryText(pos = (%d,%d), size = (%d,%d), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description,
- ],
- "fonts": [gFont("Regular",%d)],
- "itemHeight":%d
- }
-
-
-
- """,
- 610, 410, # screen
- 15, 60, 330, 286, # first menu Listbox
- 2, 0, 330, 26, # template one
- 22, # fonts
- 26, # ItemHeight
- 360, 50, 240, 300, # second menu Listbox
- 2, 2, 240, 300, # template two
- 22, # fonts
- 300, # itemHeight
- 5, 360, 600, 50, 22, # status
- ] # noqa: E124
-
- def __init__(self, session, args=0):
- Screen.__init__(self, session)
- ProtectedScreen.__init__(self)
- self.setTitle(_("ViX"))
- self.menu = args
- self.list = []
- if self.menu == 0:
- self.list.append(("backup-manager", _("Backup manager"), _("Manage settings backup."), None))
- self.list.append(("image-manager", _("Image manager"), _("Backup/Flash/ReBoot system image."), None))
- self.list.append(("ipkg-install", _("Install local extension"), _("Install IPK's from your tmp folder."), None))
- self.list.append(("mount-manager", _("Mount manager"), _("Manage your devices mount points."), None))
- self.list.append(("script-runner", _("Script runner"), _("Run your shell scripts."), None))
- self.list.append(("swap-manager", _("SWAP manager"), _("Create and Manage your SWAP files."), None))
- if SystemInfo["HasH9SD"]:
- self.list.append(("H9SDcard manager", _("H9SDcard Manager"), _("Move Nand root to SD card"), None))
- self["menu"] = List(self.list)
- self["key_red"] = StaticText(_("Close"))
-
- self["shortcuts"] = NumberActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "MenuActions", "NumberActions"],
- {
- "ok": self.go,
- "back": self.close,
- "red": self.close,
- "menu": self.closeRecursive,
- "1": self.go,
- "2": self.go,
- "3": self.go,
- "4": self.go,
- "5": self.go,
- "6": self.go,
- "7": self.go,
- "8": self.go,
- "9": self.go,
- }, -1) # noqa: E123
- self.onLayoutFinish.append(self.layoutFinished)
- self.onChangedEntry = []
- self["menu"].onSelectionChanged.append(self.selectionChanged)
-
- def isProtected(self):
- return config.ParentalControl.setuppinactive.value and config.ParentalControl.config_sections.vixmenu.value
-
- def createSummary(self):
- from Screens.PluginBrowser import PluginBrowserSummary
- return PluginBrowserSummary
-
- def selectionChanged(self):
- item = self["menu"].getCurrent()
- if item:
- name = item[1]
- desc = item[2]
- else:
- name = "-"
- desc = ""
- for cb in self.onChangedEntry:
- cb(name, desc)
-
- def layoutFinished(self):
- idx = 0
- self["menu"].index = idx
-
- def go(self, num=None):
- if num is not None:
- num -= 1
- if not num < self["menu"].count():
- return
- self["menu"].setIndex(num)
- current = self["menu"].getCurrent()
- if current:
- currentEntry = current[0]
- if self.menu == 0:
- if currentEntry == "backup-manager":
- from .BackupManager import VIXBackupManager
- self.session.open(VIXBackupManager)
- elif currentEntry == "image-manager":
- from .ImageManager import VIXImageManager
- self.session.open(VIXImageManager)
- elif currentEntry == "H9SDcard manager":
- from .H9SDmanager import H9SDmanager
- self.session.open(H9SDmanager)
- elif currentEntry == "ipkg-install":
- from .IPKInstaller import VIXIPKInstaller
- self.session.open(VIXIPKInstaller)
- elif currentEntry == "mount-manager":
- from .MountManager import VIXDevicesPanel
- self.session.open(VIXDevicesPanel)
- elif currentEntry == "script-runner":
- from .ScriptRunner import VIXScriptRunner
- self.session.open(VIXScriptRunner, None)
- elif currentEntry == "swap-manager":
- from .SwapManager import VIXSwap
- self.session.open(VIXSwap)
-
- def closeRecursive(self):
- self.close(True)
diff --git a/lib/python/Screens/About.py b/lib/python/Screens/About.py
index fc784da1d25..de401ea8fff 100644
--- a/lib/python/Screens/About.py
+++ b/lib/python/Screens/About.py
@@ -105,6 +105,8 @@ def populate(self):
imageSubBuild = ".%s" % SystemInfo["imagedevbuild"]
AboutText += _("Image:\t%s.%s%s (%s)\n") % (SystemInfo["imageversion"], SystemInfo["imagebuild"], imageSubBuild, SystemInfo["imagetype"].title())
+ AboutText += _("Installed:\t%s\n") % about.getFlashDateString()
+
VuPlustxt = "Vu+ Multiboot - " if SystemInfo["HasKexecMultiboot"] else ""
if fileHas("/proc/cmdline", "rootsubdir=linuxrootfs0"):
AboutText += _("Boot Device: \tRecovery Slot\n")
@@ -147,10 +149,7 @@ def populate(self):
else:
AboutText += _("4097 iptv player:\tDefault player\n")
AboutText += _("Python:\t%s\n") % about.getPythonVersionString()
- flashDate = about.getFlashDateString()
- AboutText += _("Installed:\t%s\n") % flashDate
- lastUpdate = about.getLastUpdate()
- AboutText += _("Last update:\t%s\n") % lastUpdate
+ AboutText += _("Last E2 update:\t%s (%s)\n") % (about.getLastCommitHash(), about.getLastCommitDate())
AboutText += _("E2 (re)starts:\t%s\n") % config.misc.startCounter.value
uptime = about.getBoxUptime()
if uptime:
@@ -623,7 +622,7 @@ def __init__(self, session, parent):
self["AboutText"] = StaticText()
self.aboutText.append(_("OpenViX: %s") % SystemInfo["imageversion"] + "." + SystemInfo["imagebuild"] + "\n")
self.aboutText.append(_("Model: %s %s\n") % (SystemInfo["MachineBrand"], SystemInfo["MachineName"]))
- self.aboutText.append(_("Updated: %s") % about.getLastUpdate() + "\n")
+ self.aboutText.append(_("Updated: %s") % about.getLastCommitDate() + "\n")
tempinfo = ""
if path.exists("/proc/stb/sensors/temp0/value"):
with open("/proc/stb/sensors/temp0/value", "r") as f:
diff --git a/lib/python/Screens/AudioSelection.py b/lib/python/Screens/AudioSelection.py
index cfb11969ef9..d739b951f29 100644
--- a/lib/python/Screens/AudioSelection.py
+++ b/lib/python/Screens/AudioSelection.py
@@ -588,7 +588,7 @@ def keyNumberGlobal(self, number):
def keyOk(self):
if self.focus == FOCUS_STREAMS and self["streams"].list:
cur = self["streams"].getCurrent()
- service = self.session.nav.getCurrentService()
+ service = self.session.nav.getCurrentService() # noqa: F841
ref = self.session.nav.getCurrentServiceRef()
ref = ref and eServiceReference(ref)
if self.settings.menupage.value == PAGE_AUDIO and cur[0] is not None:
diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py
index 7868ae68083..92150f1f635 100644
--- a/lib/python/Screens/ChannelSelection.py
+++ b/lib/python/Screens/ChannelSelection.py
@@ -446,9 +446,9 @@ def restoreDeletedBouquets(self):
print("[ChannelSelection] restore file ", file[:-4])
rename(file, file[:-4])
eDVBDBInstance = eDVBDB.getInstance()
- eDVBDBInstance.setLoadUnlinkedUserbouquets(True)
+ eDVBDBInstance.setLoadUnlinkedUserbouquets(1)
eDVBDBInstance.reloadBouquets()
- eDVBDBInstance.setLoadUnlinkedUserbouquets(config.misc.load_unlinked_userbouquets.value)
+ eDVBDBInstance.setLoadUnlinkedUserbouquets(int(config.misc.load_unlinked_userbouquets.value))
refreshServiceList()
self.csel.showFavourites()
self.close()
diff --git a/lib/python/Screens/ChoiceBox.py b/lib/python/Screens/ChoiceBox.py
index 4de0be623fe..80b25aaf7da 100644
--- a/lib/python/Screens/ChoiceBox.py
+++ b/lib/python/Screens/ChoiceBox.py
@@ -15,7 +15,7 @@
class ChoiceBox(Screen):
- def __init__(self, session, title="", list=None, keys=None, selection=0, skin_name=None, text="", reorderConfig="", windowTitle=None, var="", callbackList=None):
+ def __init__(self, session, title="", list=None, keys=None, selection=0, skin_name=None, text="", reorderConfig="", windowTitle=None, var="", callbackList=None, *args, **kwargs):
# list is in the format (, [,])
# callbackList is in the format (, , [,])
self.isCallbackList = bool(callbackList)
diff --git a/lib/python/Screens/Ci.py b/lib/python/Screens/Ci.py
index 8da9f536e7b..9b54d03813b 100644
--- a/lib/python/Screens/Ci.py
+++ b/lib/python/Screens/Ci.py
@@ -46,7 +46,6 @@ def InitCiConfig():
config.ci[slot].static_pin = ConfigPIN(default=0)
config.ci[slot].show_ci_messages = ConfigYesNo(default=True)
config.ci[slot].disable_operator_profile = ConfigYesNo(default=False)
- config.ci[slot].exclude_ca0_device = ConfigYesNo(default=False)
if SystemInfo["CI%dSupportsHighBitrates" % slot]:
with open("/proc/stb/tsmux/ci%d_tsclk_choices" % slot) as fd:
procChoices = fd.read().strip()
@@ -455,7 +454,7 @@ def appendEntries(self, slot, state):
self.state[slot] = state
if self.slot > 1:
self.list.append(("**************************", ConfigNothing(), 3, slot))
- self.list.append((_("CI %s enabled" % (slot)), config.ci[slot].enabled, -1, slot))
+ self.list.append((_("CI %s enabled") % slot, config.ci[slot].enabled, -1, slot))
self.list.append((_("Reset"), ConfigNothing(), 0, slot))
self.list.append((_("Init"), ConfigNothing(), 1, slot))
@@ -476,7 +475,6 @@ def appendEntries(self, slot, state):
self.list.append(getConfigListEntry(_("Show CI messages"), config.ci[slot].show_ci_messages, 3, slot))
self.list.append(getConfigListEntry(_("Disable operator profiles"), config.ci[slot].disable_operator_profile, 3, slot))
self.list.append(getConfigListEntry(_("Multiple service support"), config.ci[slot].canDescrambleMultipleServices, 3, slot))
- self.list.append(getConfigListEntry(_("Exclude first CA device"), config.ci[slot].exclude_ca0_device, 3, slot))
if SystemInfo["CI%dSupportsHighBitrates" % slot]:
self.list.append(getConfigListEntry(_("High bitrate support"), config.ci[slot].highBitrate))
if SystemInfo["CI%dRelevantPidsRoutingSupport" % slot]:
diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py
index 863831e2d75..ce03732a866 100644
--- a/lib/python/Screens/InfoBarGenerics.py
+++ b/lib/python/Screens/InfoBarGenerics.py
@@ -1364,7 +1364,7 @@ def historyNext(self):
self.servicelist.historyZap(+1)
def switchChannelUp(self, servicelist=None):
- if not self.secondInfoBarScreen.shown:
+# if not self.secondInfoBarScreen.shown:
servicelist = servicelist or self.servicelist
self.keyHide()
if not config.usage.show_bouquetalways.value:
@@ -1378,7 +1378,7 @@ def switchChannelUpLong(self):
self.switchChannelUp(self.servicelist2 if SystemInfo.get("NumVideoDecoders", 1) > 1 else None)
def switchChannelDown(self, servicelist=None):
- if not self.secondInfoBarScreen.shown:
+# if not self.secondInfoBarScreen.shown:
servicelist = servicelist or self.servicelist
self.keyHide()
if not config.usage.show_bouquetalways.value:
diff --git a/lib/python/Screens/InputDeviceSetup.py b/lib/python/Screens/InputDeviceSetup.py
index c3f0e1b4cda..7dd41e6db7d 100644
--- a/lib/python/Screens/InputDeviceSetup.py
+++ b/lib/python/Screens/InputDeviceSetup.py
@@ -6,7 +6,7 @@
from Components.Sources.List import List
from Components.config import config, ConfigYesNo, getConfigListEntry, ConfigSelection
from Components.ConfigList import ConfigListScreen
-from Components.ActionMap import ActionMap, HelpableActionMap
+from Components.ActionMap import HelpableActionMap
from Components.SystemInfo import SystemInfo
from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN
from Tools.LoadPixmap import LoadPixmap
diff --git a/lib/python/Screens/Menu.py b/lib/python/Screens/Menu.py
index c6efc3876b5..21d4fd7bf9f 100644
--- a/lib/python/Screens/Menu.py
+++ b/lib/python/Screens/Menu.py
@@ -3,7 +3,6 @@
from Components.ActionMap import HelpableNumberActionMap, HelpableActionMap
from Components.config import config, ConfigDictionarySet, configfile, NoSave
from Components.NimManager import nimmanager # noqa: F401 # used in menu.xml conditionals
-from Components.Pixmap import Pixmap
from Components.PluginComponent import plugins
from Components.Sources.List import List
from Components.Sources.StaticText import StaticText
@@ -249,12 +248,20 @@ def __init__(self, session, parent):
if self.layoutFinished not in self.onLayoutFinish:
self.onLayoutFinish.append(self.layoutFinished)
+ self["description"] = StaticText("")
+ if self.updateDescription not in self["menu"].onSelectionChanged:
+ self["menu"].onSelectionChanged.append(self.updateDescription)
+
+ def updateDescription(self):
+ self["description"].text = self["menu"].getCurrent() and len(self["menu"].getCurrent()) > 4 and self["menu"].getCurrent()[4] or ""
+
def __onExecBegin(self):
self.onExecBegin.remove(self.__onExecBegin)
self.okbuttonClick()
def layoutFinished(self):
self.screenContentChanged()
+ self.updateDescription()
def createMenuList(self):
if self.__class__.__name__ != "MenuSort":
diff --git a/lib/python/Screens/MessageBox.py b/lib/python/Screens/MessageBox.py
index ff6323d3dd2..5e685a1fc87 100644
--- a/lib/python/Screens/MessageBox.py
+++ b/lib/python/Screens/MessageBox.py
@@ -174,13 +174,13 @@ def getListItemHeight(self):
return itemHeight if itemHeight else defaultItemHeight
return defaultItemHeight # if itemHeight not in skinAttributes
- def getPixmapWidth(self):
- defaultPixmapWidth = 53
+ def getPixmapSize(self):
+ defaultPixmapWidth = (53, 53)
try: # protect from skin errors
- return self["ErrorPixmap"].visible and hasattr(self["ErrorPixmap"], 'getSize') and isinstance(self["ErrorPixmap"].getSize(), tuple) and len(self["ErrorPixmap"].getSize()) and self["ErrorPixmap"].getSize()[0] or \
- self["QuestionPixmap"].visible and hasattr(self["QuestionPixmap"], 'getSize') and isinstance(self["QuestionPixmap"].getSize(), tuple) and len(self["QuestionPixmap"].getSize()) and self["QuestionPixmap"].getSize()[0] or \
- self["InfoPixmap"].visible and hasattr(self["InfoPixmap"], 'getSize') and isinstance(self["InfoPixmap"].getSize(), tuple) and len(self["InfoPixmap"].getSize()) and self["InfoPixmap"].getSize()[0] or \
- self["WarningPixmap"].visible and hasattr(self["WarningPixmap"], 'getSize') and isinstance(self["WarningPixmap"].getSize(), tuple) and len(self["WarningPixmap"].getSize()) and self["WarningPixmap"].getSize()[0] or \
+ return self["ErrorPixmap"].visible and hasattr(self["ErrorPixmap"], 'getSize') and isinstance(self["ErrorPixmap"].getSize(), tuple) and len(self["ErrorPixmap"].getSize()) and self["ErrorPixmap"].getSize() or \
+ self["QuestionPixmap"].visible and hasattr(self["QuestionPixmap"], 'getSize') and isinstance(self["QuestionPixmap"].getSize(), tuple) and len(self["QuestionPixmap"].getSize()) and self["QuestionPixmap"].getSize() or \
+ self["InfoPixmap"].visible and hasattr(self["InfoPixmap"], 'getSize') and isinstance(self["InfoPixmap"].getSize(), tuple) and len(self["InfoPixmap"].getSize()) and self["InfoPixmap"].getSize() or \
+ self["WarningPixmap"].visible and hasattr(self["WarningPixmap"], 'getSize') and isinstance(self["WarningPixmap"].getSize(), tuple) and len(self["WarningPixmap"].getSize()) and self["WarningPixmap"].getSize() or \
defaultPixmapWidth
except Exception as err:
print("[MessageBox] defaultPixmapWidth, %s: '%s'" % (type(err).__name__, err))
@@ -192,9 +192,10 @@ def autoResize(self):
desktop_w = getDesktop(0).size().width()
desktop_h = getDesktop(0).size().height()
pixmapWidth = 0
+ pixmapHeight = 0
pixmapMargin = 0
if self.picon:
- pixmapWidth = self.getPixmapWidth()
+ pixmapWidth, pixmapHeight = self.getPixmapSize()
pixmapMargin = applySkinFactor(4)
textsize = (0, 0)
if self["text"].text:
@@ -222,7 +223,7 @@ def autoResize(self):
self["list"].instance.move(ePoint(margin + pixmapWidth + pixmapMargin, listPos))
wsizex = margin * 2 + width + pixmapWidth + pixmapMargin
- wsizey = listPos + (count * itemheight) + margin
+ wsizey = max(listPos + (count * itemheight) + margin, pixmapMargin * 2 + pixmapHeight)
wsize = (wsizex, wsizey)
self.instance.resize(eSize(*wsize))
diff --git a/lib/python/Screens/MinuteInput.py b/lib/python/Screens/MinuteInput.py
index 1c362170d0a..5e0befd3c76 100644
--- a/lib/python/Screens/MinuteInput.py
+++ b/lib/python/Screens/MinuteInput.py
@@ -5,7 +5,7 @@
class MinuteInput(Screen):
- def __init__(self, session, basemins=5, maxValue=False):
+ def __init__(self, session, basemins=5, maxValue=False, windowTitle=None):
Screen.__init__(self, session)
self["minutes"] = Input(str(basemins), type=Input.NUMBER, maxValue=maxValue)
@@ -34,9 +34,11 @@ def __init__(self, session, basemins=5, maxValue=False):
"cancel": self.cancel
})
+ if windowTitle is not None:
+ self.setTitle(windowTitle, showPath=False)
+
def keyNumberGlobal(self, number):
self["minutes"].number(number)
- pass
def left(self):
self["minutes"].left()
diff --git a/lib/python/Screens/OScamInfo.py b/lib/python/Screens/OScamInfo.py
index 76a7743a078..ec41725119e 100644
--- a/lib/python/Screens/OScamInfo.py
+++ b/lib/python/Screens/OScamInfo.py
@@ -417,7 +417,7 @@ class OscamInfoMenu(Screen):
def __init__(self, session):
Screen.__init__(self, session)
NAMEBIN2 = check_NAMEBIN2()
- self.setTitle(_("%s Info - Main Menu" % NAMEBIN2))
+ self.setTitle(_("%s Info - Main Menu") % NAMEBIN2)
self.menu = [_("Show Ecm info"), _("Show Clients"), _("Show Readers/Proxies"), _("Show Log"), _("Card info (CCcam-Reader)"), _("Ecm Statistics"), _("Setup")]
self.osc = OscamInfo()
self["mainmenu"] = oscMenuList([])
diff --git a/lib/python/Screens/PluginBrowser.py b/lib/python/Screens/PluginBrowser.py
index fcecb1fd0a9..ed1a474c84b 100644
--- a/lib/python/Screens/PluginBrowser.py
+++ b/lib/python/Screens/PluginBrowser.py
@@ -23,22 +23,12 @@
from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_SKIN
from Tools.LoadPixmap import LoadPixmap
+categories = ("bootlogos", "display", "drivers", "extensions", "kernel", "picons", "po", "security", "settings", "skin", "softcams", "systemplugins")
+# Note: "config.pluginbrowser" is also used in this module, it set in Components.UsageConfig and accessible via setup.xml.
config.misc.pluginbrowser = ConfigSubsection()
-config.misc.pluginbrowser.bootlogos = ConfigYesNo(default=True)
-config.misc.pluginbrowser.display = ConfigYesNo(default=True)
-config.misc.pluginbrowser.drivers = ConfigYesNo(default=True)
-config.misc.pluginbrowser.extensions = ConfigYesNo(default=True)
-config.misc.pluginbrowser.kernel = ConfigYesNo(default=False)
-config.misc.pluginbrowser.m2k = ConfigYesNo(default=True)
-config.misc.pluginbrowser.picons = ConfigYesNo(default=True)
-config.misc.pluginbrowser.po = ConfigYesNo(default=True)
-config.misc.pluginbrowser.security = ConfigYesNo(default=True)
-config.misc.pluginbrowser.settings = ConfigYesNo(default=True)
-config.misc.pluginbrowser.skin = ConfigYesNo(default=True)
-config.misc.pluginbrowser.softcams = ConfigYesNo(default=True)
-config.misc.pluginbrowser.systemplugins = ConfigYesNo(default=True)
-config.misc.pluginbrowser.weblinks = ConfigYesNo(default=True)
+for category in categories: # why do we need these configs if they can't be adjusted anywhere?
+ setattr(config.misc.pluginbrowser, category, ConfigYesNo(default=category not in ("kernel",))) # all defaults will be True except "kernel"
config.misc.pluginbrowser.plugin_order = ConfigText(default="")
@@ -269,7 +259,6 @@ class PluginDownloadBrowser(Screen):
REMOVE = 1
UPDATE = 2
PLUGIN_PREFIX = 'enigma2-plugin-'
- PLUGIN_PREFIX2 = []
lastDownloadDate = None
def __init__(self, session, type=0, needupdate=True, skin_name=None):
@@ -286,7 +275,14 @@ def __init__(self, session, type=0, needupdate=True, skin_name=None):
elif self.type == self.REMOVE:
config.misc.pluginbrowser.po.value = False
self.setTitle(_("Remove Plugins"))
- self.createPluginFilter()
+
+ self.plugin_prefix_whitelist = tuple([self.PLUGIN_PREFIX + x for x in set(categories).difference({"kernel", "po"}) if getattr(config.misc.pluginbrowser, x).value] + [y for x, y in (("kernel", "kernel-module-"), ("po", "enigma2-locale-")) if getattr(config.misc.pluginbrowser, x).value])
+ self.plugin_suffix_blacklist = tuple(["-dev", "-staticdev", "-dbg", "-doc", "-common", "-meta"] + [f"-{x}" for x in ("src", "po") if not getattr(config.pluginbrowser, x).value])
+
+ self.expandableIcon = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "icons/expandable-plugins.png"))
+ self.expandedIcon = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "icons/expanded-plugins.png"))
+ self.verticallineIcon = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "icons/verticalline-plugins.png"))
+
self.LanguageList = language.getLanguageListSelection()
self.container = eConsoleAppContainer()
self.container.appClosed.append(self.runFinished)
@@ -350,38 +346,6 @@ def selectionChanged(self):
for cb in self.onChangedEntry:
cb(name, desc)
- def createPluginFilter(self):
- # Create Plugin Filter
- self.PLUGIN_PREFIX2 = []
- if config.misc.pluginbrowser.bootlogos.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'bootlogos')
- if config.misc.pluginbrowser.drivers.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'drivers')
- if config.misc.pluginbrowser.extensions.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'extensions')
- if config.misc.pluginbrowser.m2k.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'm2k')
- if config.misc.pluginbrowser.picons.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'picons')
- if config.misc.pluginbrowser.security.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'security')
- if config.misc.pluginbrowser.settings.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'settings')
- if config.misc.pluginbrowser.skin.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'skin')
- if config.misc.pluginbrowser.display.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'display')
- if config.misc.pluginbrowser.softcams.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'softcams')
- if config.misc.pluginbrowser.systemplugins.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'systemplugins')
- if config.misc.pluginbrowser.weblinks.value:
- self.PLUGIN_PREFIX2.append(self.PLUGIN_PREFIX + 'weblinks')
- if config.misc.pluginbrowser.kernel.value:
- self.PLUGIN_PREFIX2.append('kernel-module-')
- if config.misc.pluginbrowser.po.value:
- self.PLUGIN_PREFIX2.append('enigma2-locale-')
-
def go(self):
sel = self["list"].l.getCurrentSelection()
@@ -611,35 +575,25 @@ def dataAvail(self, str):
for x in lines:
plugin = x.split(" - ", 2)
- # 'opkg list_installed' only returns name + version, no description field
- if len(plugin) >= 1:
- if not plugin[0].endswith('-dev') and not plugin[0].endswith('-staticdev') and not plugin[0].endswith('-dbg') and not plugin[0].endswith('-doc') and not plugin[0].endswith('-common') and not plugin[0].endswith('-meta') and plugin[0] not in self.installedplugins and ((not config.pluginbrowser.po.value and not plugin[0].endswith('-po')) or config.pluginbrowser.po.value) and ((not config.pluginbrowser.src.value and not plugin[0].endswith('-src')) or config.pluginbrowser.src.value):
- # Plugin filter
- for s in self.PLUGIN_PREFIX2:
- if plugin[0].startswith(s):
- if self.run == 1 and self.type == self.DOWNLOAD:
- self.installedplugins.append(plugin[0])
+ if plugin[0] and plugin[0] not in self.installedplugins and plugin[0].startswith(self.plugin_prefix_whitelist) and not plugin[0].endswith(self.plugin_suffix_blacklist):
+ if self.run == 1 and self.type == self.DOWNLOAD:
+ self.installedplugins.append(plugin[0])
+ else:
+ if len(plugin) == 2:
+ if plugin[0].startswith('enigma2-locale-'):
+ lang = plugin[0].split('-')
+ if len(lang) > 3:
+ plugin.append(lang[2] + '-' + lang[3])
else:
- if len(plugin) == 2:
- # 'opkg list_installed' does not return descriptions, append empty description
- if plugin[0].startswith('enigma2-locale-'):
- lang = plugin[0].split('-')
- if len(lang) > 3:
- plugin.append(lang[2] + '-' + lang[3])
- else:
- plugin.append(lang[2])
- else:
- plugin.append('')
- plugin.append(plugin[0][15:])
- self.pluginlist.append(plugin)
+ plugin.append(lang[2])
+ else: # 'opkg list_installed' only returns name + version, no description field, so append an empty description
+ plugin.append('')
+ plugin.append(plugin[0][15:])
+ self.pluginlist.append(plugin)
self.pluginlist.sort()
def updateList(self):
updatedlist = []
- expandableIcon = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "icons/expandable-plugins.png"))
- expandedIcon = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "icons/expanded-plugins.png"))
- verticallineIcon = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "icons/verticalline-plugins.png"))
-
self.plugins = {}
if self.type == self.UPDATE:
@@ -658,7 +612,7 @@ def updateList(self):
self.plugins[split[0]] = []
if split[0] == "kernel modules":
- self.plugins[split[0]].append((PluginDescriptor(name=x[0], description=x[2], icon=verticallineIcon), x[0][14:], x[1]))
+ self.plugins[split[0]].append((PluginDescriptor(name=x[0], description=x[2], icon=self.verticallineIcon), x[0][14:], x[1]))
elif split[0] == "languages":
for t in self.LanguageList:
if len(x[2]) > 2:
@@ -681,17 +635,17 @@ def updateList(self):
else:
if len(split) < 2:
continue
- self.plugins[split[0]].append((PluginDescriptor(name=x[3], description=x[2], icon=verticallineIcon), split[1], x[1]))
+ self.plugins[split[0]].append((PluginDescriptor(name=x[3], description=x[2], icon=self.verticallineIcon), split[1], x[1]))
temp = list(self.plugins.keys())
if config.usage.sort_pluginlist.value:
temp.sort()
for x in temp:
if x in self.expanded:
- updatedlist.append(PluginCategoryComponent(x, expandedIcon, self.listWidth))
+ updatedlist.append(PluginCategoryComponent(x, self.expandedIcon, self.listWidth))
updatedlist.extend([PluginDownloadComponent(plugin[0], plugin[1], plugin[2], self.listWidth) for plugin in self.plugins[x]])
else:
- updatedlist.append(PluginCategoryComponent(x, expandableIcon, self.listWidth))
+ updatedlist.append(PluginCategoryComponent(x, self.expandableIcon, self.listWidth))
self.list = updatedlist
self["list"].setList(updatedlist)
diff --git a/lib/python/Screens/RdsDisplay.py b/lib/python/Screens/RdsDisplay.py
index 63da0f39c68..996f9d523fd 100644
--- a/lib/python/Screens/RdsDisplay.py
+++ b/lib/python/Screens/RdsDisplay.py
@@ -10,6 +10,11 @@
class RdsInfoDisplaySummary(Screen):
+ skin = """
+
+
+ """
+
def __init__(self, session, parent):
Screen.__init__(self, session, parent=parent)
self["message"] = StaticText("")
diff --git a/lib/python/Screens/Satconfig.py b/lib/python/Screens/Satconfig.py
index b64ffc2da21..40d1dafef00 100644
--- a/lib/python/Screens/Satconfig.py
+++ b/lib/python/Screens/Satconfig.py
@@ -27,10 +27,8 @@ def __init__(self, session, slotid):
self.slotid = slotid
self.nim = nimmanager.nim_slots[slotid]
self.nimConfig = self.nim.config
- Setup.__init__(self, session, yellow_button={'function': self.key_yellow, 'helptext': _("Toggle Configuration Mode or AutoDisqc")},
- blue_button={'function': self.key_blue, 'helptext': _("Set all the settings back as they were")})
+ Setup.__init__(self, session, yellow_button={'function': self.key_yellow, 'helptext': _("Toggle Configuration Mode or AutoDisqc")}, blue_button={'function': self.key_blue, 'helptext': _("Set all the settings back as they were")})
ServiceStopScreen.__init__(self)
- self.createSetup()
self.setTitle(_("Setup") + " " + self.nim.friendly_full_description)
def createSimpleSetup(self, list, mode):
@@ -343,7 +341,7 @@ def newConfig(self):
self.advancedUnicable, self.advancedConnected, self.toneburst, self.committedDiseqcCommand, self.uncommittedDiseqcCommand, self.singleSatEntry, self.commandOrder,
self.showAdditionalMotorOptions, self.cableScanType, self.multiType, self.cableConfigScanDetails, self.terrestrialCountriesEntry, self.cableCountriesEntry,
self.toneamplitude, self.scpc, self.t2mirawmode, self.forcelnbpower, self.forcetoneburst, self.externallyPowered):
- self.createSetup()
+ self.createSetup()
def run(self):
if self.nimConfig.configMode.value == "simple" and self.nimConfig.diseqcMode.value in ("single", "diseqc_a_b", "diseqc_a_b_c_d") and (not self.nim.isCombined() or self.nimConfig.configModeDVBS.value):
diff --git a/lib/python/Screens/ScanSetup.py b/lib/python/Screens/ScanSetup.py
index 54a8ec3bb6c..02b06d519bd 100644
--- a/lib/python/Screens/ScanSetup.py
+++ b/lib/python/Screens/ScanSetup.py
@@ -199,7 +199,7 @@ def cableTransponderSearchClosed(self, retval):
self.cable_search_session.close(True)
def getCableTransponderData(self, dataString):
- dataString = str(dataString)
+ dataString = dataString.decode()
print("[getCableTransponderData] ", dataString)
# prepend any remaining data from the previous call
dataString = self.remainingdata + dataString
@@ -409,7 +409,7 @@ def terrestrialTransponderSearchClosed(self, retval):
self.terrestrialTransponderSearch(freq, bandWidth)
def getTerrestrialTransponderData(self, dataString):
- dataString = str(dataString)
+ dataString = dataString.decode()
print("[getTerrestrialTransponderData] ", dataString)
if self.terrestrial_tunerName.startswith("Sundtek"):
dataString = self.remaining_data + dataString
@@ -445,7 +445,7 @@ def getTerrestrialTransponderData(self, dataString):
tmpstr += title
self.terrestrial_search_session["text"].setText(tmpstr)
else:
- self.terrestrial_search_data += str
+ self.terrestrial_search_data += dataString
def setTerrestrialTransponderData(self):
data = self.terrestrial_search_data.split()
diff --git a/lib/python/Screens/Screen.py b/lib/python/Screens/Screen.py
index d799875c782..a9522b9fffa 100644
--- a/lib/python/Screens/Screen.py
+++ b/lib/python/Screens/Screen.py
@@ -2,7 +2,7 @@
from enigma import eRCInput, eTimer, eWindow # , getDesktop
-from skin import GUI_SKIN_ID, applyAllAttributes, menus, screens, setups
+from skin import GUI_SKIN_ID, applyAllAttributes, menus, screens, setups # noqa: F401
from Components.config import config
from Components.GUIComponent import GUIComponent
from Components.Pixmap import Pixmap
diff --git a/lib/python/Screens/Setup.py b/lib/python/Screens/Setup.py
index 20f53bbc315..b454e85c7a3 100644
--- a/lib/python/Screens/Setup.py
+++ b/lib/python/Screens/Setup.py
@@ -7,7 +7,6 @@
from Components.config import ConfigBoolean, ConfigNothing, ConfigSelection, config
from Components.ConfigList import ConfigListScreen
from Components.Label import Label
-from Components.Pixmap import Pixmap
from Components.SystemInfo import SystemInfo
from Components.Sources.StaticText import StaticText
from Screens.HelpMenu import HelpableScreen
diff --git a/lib/python/Screens/SkinSelector.py b/lib/python/Screens/SkinSelector.py
index a2a475a0af2..73889bc6bd9 100644
--- a/lib/python/Screens/SkinSelector.py
+++ b/lib/python/Screens/SkinSelector.py
@@ -13,6 +13,7 @@
from Screens.HelpMenu import HelpableScreen
from Screens.MessageBox import MessageBox
from Screens.Screen import Screen, ScreenSummary
+from Screens.Setup import Setup
from Screens.Standby import TryQuitMainloop, QUIT_RESTART
from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN, SCOPE_LCDSKIN, SCOPE_SKIN
@@ -36,8 +37,9 @@ def __init__(self, session, screenTitle=_("GUI Skin"), skin_name=None):
self["preview"] = Pixmap()
self["key_red"] = StaticText(_("Cancel"))
self["key_green"] = StaticText(_("Save"))
+ self["key_menu"] = StaticText(_("MENU"))
self["description"] = StaticText(_("Please wait... Loading list..."))
- self["skinActions"] = HelpableActionMap(self, ["CancelSaveActions", "OkActions", "NavigationActions"], {
+ self["skinActions"] = HelpableActionMap(self, ["CancelSaveActions", "OkActions", "NavigationActions", "MenuActions"], {
"cancel": (self.keyCancel, _("Cancel any changes to the currently active skin")),
"close": (self.closeRecursive, _("Cancel any changes to the currently active skin and exit all menus")),
"save": (self.keySave, _("Save and activate the currently selected skin")),
@@ -51,7 +53,8 @@ def __init__(self, session, screenTitle=_("GUI Skin"), skin_name=None):
"last": (self.keyPageDown, _("Move down a screen")),
"down": (self.keyDown, _("Move down a line")),
"pageDown": (self.keyPageDown, _("Move down a screen")),
- "bottom": (self.keyPageDown, _("Move down a screen"))
+ "bottom": (self.keyPageDown, _("Move down a screen")),
+ "menu": (self.keyMenu, _("Open menu"))
}, prio=-1, description=_("Skin Selection Actions"))
self.picload = ePicLoad()
self.picload.PictureData.get().append(self.showPic)
@@ -164,8 +167,7 @@ def keySave(self):
self.close()
else:
print("[SkinSelector] Selected skin: '%s' (Trying to restart again!)" % pathjoin(self.rootDir, skin))
- restartBox = self.session.openWithCallback(self.restartGUI, MessageBox, _("To apply the selected '%s' skin the GUI needs to restart. Would you like to restart the GUI now?") % label, MessageBox.TYPE_YESNO)
- restartBox.setTitle(_("SkinSelector: Restart GUI"))
+ self.showRestartMessage(_("To apply the selected '%s' skin the GUI needs to restart. Would you like to restart the GUI now?") % label)
elif skin == self.currentSkin:
print("[SkinSelector] Selected skin: '%s' (Pending skin '%s' cancelled!)" % (pathjoin(self.rootDir, skin), pathjoin(self.rootDir, self.config.value)))
self.config.value = skin
@@ -173,12 +175,15 @@ def keySave(self):
self.close()
else:
print("[SkinSelector] Selected skin: '%s'" % pathjoin(self.rootDir, skin))
- if config.usage.fast_skin_reload.value:
- self.saveConfig()
- self.session.reloadSkin()
- else:
- restartBox = self.session.openWithCallback(self.restartGUI, MessageBox, _("To save and apply the selected '%s' skin the GUI needs to restart. Would you like to save the selection and restart the GUI now?") % label, MessageBox.TYPE_YESNO)
- restartBox.setTitle(_("SkinSelector: Restart GUI"))
+ self.showRestartMessage(_("To save and apply the selected '%s' skin the GUI needs to restart. Would you like to save the selection and restart the GUI now?") % label)
+
+ def showRestartMessage(self, msg):
+ if config.usage.fast_skin_reload.value:
+ self.saveConfig()
+ self.session.reloadSkin()
+ else:
+ restartBox = self.session.openWithCallback(self.restartGUI, MessageBox, msg, MessageBox.TYPE_YESNO)
+ restartBox.setTitle(_("SkinSelector: Restart GUI"))
def restartGUI(self, answer):
if answer is True:
@@ -214,6 +219,9 @@ def keyBottom(self):
self["skins"].moveEnd()
self.loadPreview()
+ def keyMenu(self):
+ self.session.open(Setup, setup="skinselection")
+
def changedEntry(self):
for x in self.onChangedEntry:
x()
diff --git a/lib/python/Screens/TextBox.py b/lib/python/Screens/TextBox.py
index f9c0a3a354f..544524d6aa0 100644
--- a/lib/python/Screens/TextBox.py
+++ b/lib/python/Screens/TextBox.py
@@ -7,8 +7,12 @@
class TextBox(Screen):
def __init__(self, session, text="", title=None, skin_name=None, label=None):
Screen.__init__(self, session)
+ if isinstance(self.skinName, str):
+ self.skinName = [self.skinName]
+ if "TextBox" not in self.skinName:
+ self.skinName.append("TextBox")
if isinstance(skin_name, str):
- self.skinName = [skin_name, "TextBox"]
+ self.skinName.insert(0, skin_name)
self.text = text
self.label = "text"
if isinstance(label, str):
diff --git a/lib/python/Screens/VideoMode.py b/lib/python/Screens/VideoMode.py
index 0dc75f05da5..755979490ce 100644
--- a/lib/python/Screens/VideoMode.py
+++ b/lib/python/Screens/VideoMode.py
@@ -96,6 +96,8 @@ def createSetup(self):
self.list.append(getConfigListEntry(_("3D Surround"), config.av.surround_3d, _("This option allows you to enable 3D Surround Sound for an output.")))
if SystemInfo["Can3DSpeaker"] and config.av.surround_3d.value != "none":
self.list.append(getConfigListEntry(_("3D Surround Speaker Position"), config.av.surround_3d_speaker, _("This option allows you to change the virtual loudspeaker position.")))
+ self.list.append((_("Audio volume step size"), config.av.volume_stepsize, _("Configure the general audio volume step size (limit 1-10).")))
+ self.list.append((_("Hide mute icon"), config.av.volume_hide_mute, _("If volume muted, hide mute icon or mute information after few seconds.")))
if SystemInfo["CanAutoVolume"]:
self.list.append(getConfigListEntry(_("Auto Volume Level"), config.av.autovolume, _("This option configures output for Auto Volume Level.")))
if SystemInfo["Canedidchecking"]:
diff --git a/lib/python/ServiceReference.py b/lib/python/ServiceReference.py
index 7f8f025f1b4..b18074f6707 100644
--- a/lib/python/ServiceReference.py
+++ b/lib/python/ServiceReference.py
@@ -42,7 +42,7 @@ def __fromDirectory(path):
# Apply ServiceReference method proxies to the eServiceReference object so the two classes can be used interchangeably
# These are required for ServiceReference backwards compatibility
-eServiceReference.isRecordable = lambda serviceref: serviceref.flags & eServiceReference.isGroup or (serviceref.type == eServiceReference.idDVB or serviceref.type == eServiceReference.idDVB + 0x100 or serviceref.type == 0x2000 or serviceref.type == eServiceReference.idServiceMP3)
+eServiceReference.isRecordable = lambda serviceref: serviceref.flags & eServiceReference.isGroup or (serviceref.type == eServiceReference.idDVB or serviceref.type == eServiceReference.idDVB + 0x100 or serviceref.type == 0x2000 or serviceref.type == 0x1001 or serviceref.type == eServiceReference.idServiceMP3)
def __repr(serviceref):
diff --git a/lib/python/StartEnigma.py b/lib/python/StartEnigma.py
index b890f310ea1..f81621c3baa 100644
--- a/lib/python/StartEnigma.py
+++ b/lib/python/StartEnigma.py
@@ -476,10 +476,12 @@ def runNextScreen(session, screensToRun, *result):
if not VuRecovery:
profile("Bouquets")
print("[StartEnigma] Initialising Bouquets.")
- config.misc.load_unlinked_userbouquets = ConfigYesNo(default=False)
+ config.misc.load_unlinked_userbouquets = ConfigSelection(default="0", choices=[("0", _("Off")), ("1", _("Top")), ("2", _("Bottom"))])
+ if config.misc.load_unlinked_userbouquets.value.lower() in ("true", "false"):
+ config.misc.load_unlinked_userbouquets.value = "1" if config.misc.load_unlinked_userbouquets.value.lower() == "true" else "0"
def setLoadUnlinkedUserbouquets(configElement):
- enigma.eDVBDB.getInstance().setLoadUnlinkedUserbouquets(configElement.value)
+ enigma.eDVBDB.getInstance().setLoadUnlinkedUserbouquets(int(configElement.value))
config.misc.load_unlinked_userbouquets.addNotifier(setLoadUnlinkedUserbouquets)
if config.clientmode.enabled.value is False:
@@ -643,6 +645,7 @@ def RCSelectionChanged(configelement):
StackTracePrinterInst = StackTracePrinter()
profile("Init:skin")
+config.skin.pixmap_force_alphablending = ConfigSelection(default="0", choices=[("2", _("Always")), ("1", _("Only alpha test to alpha blend")), ("0", _("Use skin setting"))])
print("[StartEnigma] Initialising Skins.")
from skin import InitSkins # noqa: E402
InitSkins()
diff --git a/lib/python/Tools/Multiboot.py b/lib/python/Tools/Multiboot.py
index 11697dd4061..297635c4a45 100644
--- a/lib/python/Tools/Multiboot.py
+++ b/lib/python/Tools/Multiboot.py
@@ -6,7 +6,7 @@
from Components.Console import Console
from Components.SystemInfo import SystemInfo, BoxInfo as BoxInfoRunningInstance, BoxInformation
-from Tools.Directories import fileExists
+from Tools.Directories import copyfile, fileExists
if SystemInfo["HasKexecMultiboot"]:
from PIL import Image, ImageDraw, ImageFont
@@ -34,60 +34,73 @@ def getMultibootslots():
break
if path.exists(device):
Console(binary=True).ePopen(f"mount {device} {tmpname}")
- if path.isfile(path.join(tmpname, "STARTUP")):
+ if path.isfile(path.join(tmpname, "STARTUP")): # Multiboot receiver
+ if SystemInfo["HasKexecMultiboot"] and not path.isfile(dest := path.join(tmpname, "etc/init.d/kexec-multiboot-recovery")) and path.isfile("/etc/init.d/kexec-multiboot-recovery"): # check Recovery & slot image for recovery script
+ if path.isfile(etc_issue := path.join(tmpname, "etc/issue")):
+ try:
+ Creator = open(etc_issue).readlines()[-2].lower().split(maxsplit=1)[0]
+ except IndexError: # /etc/issue non standard file content
+ Creator = ""
+ if Creator in ("openvix", "openbh"):
+ copyfile("/etc/init.d/kexec-multiboot-recovery", dest)
SystemInfo["MBbootdevice"] = device
device2 = device.rsplit("/", 1)[1]
print(f"[Multiboot][[getMultibootslots]1 *** Bootdevice found: {device2}")
SystemInfo["BootDevice"] = device2
- for file in glob.glob(path.join(tmpname, "STARTUP_*")):
- slotnumber = file.rsplit("_", 3 if "BOXMODE" in file else 1)[1]
- slotname = file.rsplit("_", 3 if "BOXMODE" in file else 1)[0]
- slotname = file.rsplit("/", 1)[1]
- slotname = slotname if len(slotname) > 1 else ""
- slotname = "" # nullify for current moment
- if "STARTUP_ANDROID" in file:
- SystemInfo["AndroidMode"] = True
- continue
- if "STARTUP_RECOVERY" in file:
- SystemInfo["RecoveryMode"] = True
- slotnumber = "0"
- if slotnumber.isdigit() and slotnumber not in bootslots:
- line = open(file).read().replace("'", "").replace('"', "").replace("\n", " ").replace("ubi.mtd", "mtd").replace("bootargs=", "")
- slot = dict([(x.split("=", 1)[0].strip(), x.split("=", 1)[1].strip()) for x in line.strip().split(" ") if "=" in x])
- if slotnumber == "0":
- slot["slotType"] = ""
- slot["startupfile"] = path.basename(file)
- else:
- slot["slotType"] = "eMMC" if "mmc" in slot["root"] else "USB"
- if SystemInfo["HasKexecMultiboot"] and int(slotnumber) > 3:
- SystemInfo["HasKexecUSB"] = True
- if "root" in slot.keys():
- if "UUID=" in slot["root"]:
- slotx = getUUIDtoSD(slot["root"])
- UUID = slot["root"]
- UUIDnum += 1
- if slotx is not None:
- slot["root"] = slotx
- slot["kernel"] = f"/linuxrootfs{slotnumber}/zImage"
- if path.exists(slot["root"]) or slot["root"] == "ubi0:ubifs":
+ if path.exists("/sys/firmware/devicetree/base/chosen/bootargs"): # check no kernel corruption
+ for file in glob.glob(path.join(tmpname, "STARTUP_*")):
+ slotnumber = file.rsplit("_", 3 if "BOXMODE" in file else 1)[1]
+ slotname = file.rsplit("_", 3 if "BOXMODE" in file else 1)[0]
+ slotname = file.rsplit("/", 1)[1]
+ slotname = slotname if len(slotname) > 1 else ""
+ slotname = "" # nullify for current moment
+ if "STARTUP_ANDROID" in file:
+ SystemInfo["AndroidMode"] = True
+ continue
+ if "STARTUP_RECOVERY" in file:
+ SystemInfo["RecoveryMode"] = True
+ slotnumber = "0"
+ if slotnumber.isdigit() and slotnumber not in bootslots:
+ line = open(file).read().replace("'", "").replace('"', "").replace("\n", " ").replace("ubi.mtd", "mtd").replace("bootargs=", "")
+ slot = dict([(x.split("=", 1)[0].strip(), x.split("=", 1)[1].strip()) for x in line.strip().split(" ") if "=" in x])
+ if slotnumber == "0":
+ slot["slotType"] = ""
slot["startupfile"] = path.basename(file)
- slot["slotname"] = slotname
- SystemInfo["HasMultibootMTD"] = slot.get("mtd")
- if not SystemInfo["HasKexecMultiboot"] and "sda" in slot["root"]: # Not Kexec Vu+ receiver -- sf8008 type receiver with sd card, reset value as SD card slot has no rootsubdir
- slot["rootsubdir"] = None
- slot["slotType"] = "SDCARD"
- else:
- SystemInfo["HasRootSubdir"] = slot.get("rootsubdir")
+ else:
+ slot["slotType"] = "eMMC" if "mmc" in slot["root"] else "USB"
+ if SystemInfo["HasKexecMultiboot"] and int(slotnumber) > 3:
+ SystemInfo["HasKexecUSB"] = True
+ if "root" in slot.keys():
+ if "UUID=" in slot["root"]:
+ slotx = getUUIDtoSD(slot["root"])
+ UUID = slot["root"]
+ UUIDnum += 1
+ if slotx is not None:
+ slot["root"] = slotx
+ slot["kernel"] = f"/linuxrootfs{slotnumber}/zImage"
+ if path.exists(slot["root"]) or slot["root"] == "ubi0:ubifs":
+ slot["startupfile"] = path.basename(file)
+ slot["slotname"] = slotname
+ SystemInfo["HasMultibootMTD"] = slot.get("mtd")
+ if not SystemInfo["HasKexecMultiboot"] and "sda" in slot["root"]: # Not Kexec Vu+ receiver -- sf8008 type receiver with sd card, reset value as SD card slot has no rootsubdir
+ slot["rootsubdir"] = None
+ slot["slotType"] = "SDCARD"
+ else:
+ SystemInfo["HasRootSubdir"] = slot.get("rootsubdir")
- if "kernel" not in slot.keys():
- slot["kernel"] = f"{slot['root'].split('p')[0]}p{int(slot['root'].split('p')[1]) - 1}" # oldstyle MB kernel = root-1
+ if "kernel" not in slot.keys():
+ slot["kernel"] = f"{slot['root'].split('p')[0]}p{int(slot['root'].split('p')[1]) - 1}" # oldstyle MB kernel = root-1
+ else:
+ continue
+ bootslots[int(slotnumber)] = slot
+ elif slotnumber == "0":
+ bootslots[int(slotnumber)] = slot
else:
continue
- bootslots[int(slotnumber)] = slot
- elif slotnumber == "0":
- bootslots[int(slotnumber)] = slot
- else:
- continue
+ else: # kernel corruption set corruption flag
+ print(f"[multiboot][getMultibootslots]3 bootargs?: {path.exists("/sys/firmware/devicetree/base/chosen/bootargs")}")
+ SystemInfo["resetMBoot"] = True
+ bootslots = {}
Console(binary=True).ePopen(f"umount {tmpname}")
if not path.ismount(tmp.dir):
rmdir(tmp.dir)
@@ -156,16 +169,18 @@ def GetImagelist(Recovery=None):
print("[multiboot] [GetImagelist] using enigma.info")
BuildVersion = createInfo(slot, imagedir=imagedir)
else:
- print("[multiboot] [GetImagelist] using BoxInfo")
- Creator = open(f"{imagedir}/etc/issue").readlines()[-2].capitalize().strip()[:-6]
+ print("[multiboot] [GetImagelist] using etc/issue")
+ date = VerDate(imagedir)
+ try:
+ Creator = open(f"{imagedir}/etc/issue").readlines()[-2].capitalize().strip()[:-6]
+ except IndexError: # /etc/issue no standard file content
+ Creator = _("Unknown image")
if SystemInfo["HasKexecMultiboot"] and path.isfile(path.join(imagedir, "etc/vtiversion.info")):
Vti = open(path.join(imagedir, "etc/vtiversion.info")).read()
- date = VerDate(imagedir)
Creator = Vti[0:3]
Build = Vti[-8:-1]
BuildVersion = f"{Creator} {Build} ({date}) "
else:
- date = VerDate(imagedir)
Creator = Creator.replace("-release", " ")
BuildVersion = f"{Creator} ({date})"
if SystemInfo["HasKexecMultiboot"] and Recovery and config.usage.bootlogo_identify.value:
@@ -184,25 +199,43 @@ def GetImagelist(Recovery=None):
def createInfo(slot, imagedir="/"):
BoxInfo = BoxInformation(root=imagedir) if SystemInfo["MultiBootSlot"] != slot else BoxInfoRunningInstance
- Creator = BoxInfo.getItem("distro", " ").capitalize()
- BuildImgVersion = BoxInfo.getItem("imgversion")
- BuildType = BoxInfo.getItem("imagetype", " ")[0:3]
- BuildVer = BoxInfo.getItem("imagebuild")
- BuildDate = VerDate(imagedir)
- BuildDev = str(BoxInfo.getItem("imagedevbuild")).zfill(3) if BuildType != "rel" else ""
- return " ".join([str(x) for x in (Creator, BuildImgVersion, BuildType, BuildVer, BuildDev, "(%s)" % BuildDate) if x])
+ Creator = (distro := str(BoxInfo.getItem("displaydistro", ""))) and (distro := distro.split()[0]) and distro[:1].upper() + distro[1:] or str(BoxInfo.getItem("distro", "")).capitalize()
+ BuildImgVersion = str(BoxInfo.getItem("imgversion", "")).replace("-release", "") # replace("-release", "") for PLi 9.0
+ BuildType = str(BoxInfo.getItem("imagetype", "rel"))
+ if BuildType.lower().startswith("dev"):
+ BuildType = BuildType[:3]
+ BuildDev = str(idb).zfill(3) if Creator.lower().startswith(("openvix", "openpli")) and BuildType and not BuildType.lower().startswith("rel") and (idb := BoxInfo.getItem("imagedevbuild")) else ""
+ if BuildType.lower().startswith("rel"):
+ BuildType = "" # don't bother displaying "release" in the interface as this is the default image type
+ BuildVer = str(BoxInfo.getItem("imagebuild", ""))
+ CompileDate = str(BoxInfo.getItem("compiledate", ""))
+
+ try: # checking for valid YYYYMMDD format date in BuildVer, if so, don't display it
+ if BuildVer and (CompileDate == BuildVer or len(BuildVer) == 8 and BuildVer.startswith("20") and BuildVer.isnumeric() and datetime.strptime(BuildVer, '%Y%m%d')):
+ BuildVer = ""
+ except (TypeError, ValueError):
+ pass
+
+ if BuildVer and len(BuildVer) == 3 and BuildVer.isnumeric():
+ BuildImgVersion = BuildImgVersion + "." + BuildVer
+ BuildVer = ""
+
+ if BuildDev and len(BuildDev) == 3 and BuildDev.isnumeric():
+ BuildImgVersion = BuildImgVersion + "." + BuildDev
+ BuildDev = ""
+
+ try:
+ BuildDate = datetime.strptime(CompileDate, '%Y%m%d').strftime("%d-%m-%Y")
+ except (TypeError, ValueError): # sanity for enigma.info containing bad/no entry
+ BuildDate = VerDate(imagedir)
+
+ return " ".join([str(x).strip() for x in (Creator, BuildImgVersion, BuildType, BuildVer, BuildDev, f"({BuildDate})") if x and str(x).strip()])
def VerDate(imagedir):
- date1 = date2 = date3 = "00000000"
- if fileExists(path.join(imagedir, "var/lib/opkg/status")):
- date1 = datetime.fromtimestamp(stat(path.join(imagedir, "var/lib/opkg/status")).st_mtime).strftime("%Y-%m-%d")
- date2 = datetime.fromtimestamp(stat(path.join(imagedir, "usr/bin/enigma2")).st_mtime).strftime("%Y-%m-%d")
- if fileExists(path.join(imagedir, "usr/share/bootlogo.mvi")):
- date3 = datetime.fromtimestamp(stat(path.join(imagedir, "usr/share/bootlogo.mvi")).st_mtime).strftime("%Y-%m-%d")
- date = max(date1, date2, date3) # this is comparing strings
- date = datetime.strptime(date, '%Y-%m-%d').strftime("%d-%m-%Y")
- return date
+ def mtime(fpath):
+ return fileExists(file := path.join(imagedir, fpath)) and int(stat(file).st_mtime) or 0
+ return datetime.fromtimestamp(max(mtime("var/lib/opkg/status"), mtime("usr/bin/enigma2"), mtime("usr/share/bootlogo.mvi"))).strftime("%d-%m-%Y")
def emptySlot(slot):
diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i
index fa520bfd31c..38b82c7183d 100644
--- a/lib/python/enigma_python.i
+++ b/lib/python/enigma_python.i
@@ -461,6 +461,8 @@ extern eApplication *getApplication();
extern int getPrevAsciiCode();
extern void addFont(const char *filename, const char *alias, int scale_factor, int is_replacement, int renderflags = 0);
extern const char *getEnigmaVersionString();
+extern const char *getEnigmaLastCommitDate();
+extern const char *getEnigmaLastCommitHash();
extern const char *getGStreamerVersionString();
extern void dump_malloc_stats(void);
extern void pauseInit(void);
@@ -477,6 +479,8 @@ extern void runMainloop();
extern void quitMainloop(int exit_code);
extern eApplication *getApplication();
extern const char *getEnigmaVersionString();
+extern const char *getEnigmaLastCommitDate();
+extern const char *getEnigmaLastCommitHash();
extern const char *getGStreamerVersionString();
extern void dump_malloc_stats(void);
extern void pauseInit(void);
diff --git a/lib/python/skin.py b/lib/python/skin.py
index ce77768c964..3a18a7a4a3e 100644
--- a/lib/python/skin.py
+++ b/lib/python/skin.py
@@ -48,6 +48,7 @@
currentPrimarySkin = None
currentDisplaySkin = None
currentLoadingSkin = None
+currentScreenName = None
onLoadCallbacks = []
# Skins are loaded in order of priority. Skin with highest priority is
@@ -198,7 +199,7 @@ def __init__(self, message):
self.msg = message
def __str__(self):
- return "[Skin] {%s}: %s! Please contact the skin's author!" % (currentLoadingSkin or config.skin.primary_skin.value, self.msg)
+ return "[Skin] {%s}: %s! Please contact the skin's author!" % (currentLoadingSkin or (currentDisplaySkin if currentScreenName and currentScreenName.lower().endswith("summary") else currentPrimarySkin), self.msg)
# Convert a coordinate string into a number. Used to convert object position and
# size attributes into a number.
@@ -430,8 +431,8 @@ def collectAttributes(skinAttributes, node, context, skinPath=None, ignore=(), f
if attrib in filenames:
# DEBUG: Why does a SCOPE_CURRENT_LCDSKIN image replace the GUI image?!?!?!
pngfile = resolveFilename(SCOPE_CURRENT_SKIN, value, path_prefix=skinPath)
- if not isfile(pngfile) and isfile(resolveFilename(SCOPE_CURRENT_LCDSKIN, value, path_prefix=skinPath)):
- pngfile = resolveFilename(SCOPE_CURRENT_LCDSKIN, value, path_prefix=skinPath)
+ if not isfile(pngfile) and isfile(resolved := resolveFilename(SCOPE_CURRENT_LCDSKIN, value, path_prefix=skinPath)):
+ pngfile = resolved
value = pngfile
# 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
@@ -1198,6 +1199,8 @@ def readSkin(screen, skin, names, desktop):
myScreen = None
else:
name = "" % screen.__class__.__name__
+ global currentScreenName
+ currentScreenName = name
if myScreen is None: # Otherwise try embedded skin.
myScreen = getattr(screen, "parsedSkin", None)
if myScreen is None and getattr(screen, "skin", None): # Try uncompiled embedded skin.
@@ -1451,6 +1454,7 @@ def processPanel(widget, context):
# things around.
screen = None
usedComponents = None
+ currentScreenName = None
def findWidgets(name):
diff --git a/lib/service/iservice.h b/lib/service/iservice.h
index fee36e0ae6d..34a36b31367 100644
--- a/lib/service/iservice.h
+++ b/lib/service/iservice.h
@@ -103,7 +103,8 @@ class eServiceReference
return name;
}
std::string getProvider() const { return prov; }
- void setName( const std::string &n ) { name=n; }
+ void setName( const std::string &s ) { name=s; }
+ void setProvider( const std::string &s ) { prov=s; }
int getChannelNum() const { return number; }
void setChannelNum(const int n) { number = n; }
diff --git a/lib/service/service.cpp b/lib/service/service.cpp
index 3543bf03aba..c05d9de43af 100644
--- a/lib/service/service.cpp
+++ b/lib/service/service.cpp
@@ -172,6 +172,9 @@ std::string eServiceReference::toString() const
ret += ':';
ret += encode(name);
}
+ if (!prov.empty()) {
+ ret += "•" + prov;
+ }
return ret;
}
diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp
index 9f8d40716e3..c430dd79f30 100644
--- a/lib/service/servicemp3.cpp
+++ b/lib/service/servicemp3.cpp
@@ -253,7 +253,7 @@ eStaticServiceMP3Info::eStaticServiceMP3Info()
RESULT eStaticServiceMP3Info::getName(const eServiceReference &ref, std::string &name)
{
- if ( ref.name.length() )
+ if (ref.name.length())
name = ref.name;
else
{
@@ -283,7 +283,7 @@ int eStaticServiceMP3Info::getInfo(const eServiceReference &ref, int w)
{
case iServiceInformation::sTimeCreate:
{
- struct stat s;
+ struct stat s = {};
if (stat(ref.path.c_str(), &s) == 0)
{
return s.st_mtime;
@@ -292,7 +292,7 @@ int eStaticServiceMP3Info::getInfo(const eServiceReference &ref, int w)
break;
case iServiceInformation::sFileSize:
{
- struct stat s;
+ struct stat s = {};
if (stat(ref.path.c_str(), &s) == 0)
{
return s.st_size;
@@ -305,7 +305,7 @@ int eStaticServiceMP3Info::getInfo(const eServiceReference &ref, int w)
long long eStaticServiceMP3Info::getFileSize(const eServiceReference &ref)
{
- struct stat s;
+ struct stat s = {};
if (stat(ref.path.c_str(), &s) == 0)
{
return s.st_size;
@@ -438,6 +438,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref):
m_currentAudioStream = -1;
m_currentSubtitleStream = -1;
m_cachedSubtitleStream = -2; /* report subtitle stream to be 'cached'. TODO: use an actual cache. */
+ m_autoturnon = eConfigManager::getConfigBoolValue("config.subtitles.pango_autoturnon", true);
m_subtitle_widget = 0;
m_currentTrickRatio = 1.0;
m_buffer_size = 5 * 1024 * 1024;
@@ -459,17 +460,27 @@ eServiceMP3::eServiceMP3(eServiceReference ref):
m_decoder = NULL;
std::string sref = ref.toString();
- if (!sref.empty()) {
- std::vector &iptv_services = eDVBDB::getInstance()->iptv_services;
- for(std::vector::iterator it = iptv_services.begin(); it != iptv_services.end(); ++it) {
- if (sref.find(it->s_ref) != std::string::npos) {
- m_currentAudioStream = it->ampeg_pid;
- m_currentSubtitleStream = it->subtitle_pid;
- m_cachedSubtitleStream = m_currentSubtitleStream;
+ eDebug("[eServiceMP3] Init start %s", ref.toString().c_str());
+ size_t pos = m_ref.path.find('media');
+ size_t pos2 = m_ref.path.find('mkv');
+ if (pos == std::string::npos && pos2 == std::string::npos)
+ {
+ if (!sref.empty())
+ {
+ eDebug("[eServiceMP3] Init start !sref.empty()");
+ std::vector &iptv_services = eDVBDB::getInstance()->iptv_services;
+ for(std::vector::iterator it = iptv_services.begin(); it != iptv_services.end(); ++it)
+ {
+ if (sref.find(it->s_ref) != std::string::npos)
+ {
+ m_currentAudioStream = it->ampeg_pid;
+ m_currentSubtitleStream = it->subtitle_pid;
+ m_cachedSubtitleStream = m_currentSubtitleStream;
+ eDebug("[eServiceMP3] Init start iptv_service use sref pid's");
+ }
}
}
}
-
CONNECT(m_subtitle_sync_timer->timeout, eServiceMP3::pushSubtitles);
CONNECT(m_pump.recv_msg, eServiceMP3::gstPoll);
CONNECT(m_nownext_timer->timeout, eServiceMP3::updateEpgCacheNowNext);
@@ -481,7 +492,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref):
const char *filename;
std::string filename_str;
- size_t pos = m_ref.path.find('#');
+ pos = m_ref.path.find('#');
if (pos != std::string::npos && (m_ref.path.compare(0, 4, "http") == 0 || m_ref.path.compare(0, 4, "rtsp") == 0))
{
filename_str = m_ref.path.substr(0, pos);
@@ -2068,7 +2079,7 @@ void eServiceMP3::gstBusCall(GstMessage *msg)
for (i = 0; i < n_audio; i++)
{
- audioStream audio;
+ audioStream audio = {};
gchar *g_codec, *g_lang;
GstTagList *tags = NULL;
GstPad* pad = 0;
@@ -2222,7 +2233,7 @@ void eServiceMP3::gstBusCall(GstMessage *msg)
{
GstBufferingMode mode;
gst_message_parse_buffering(msg, &(m_bufferInfo.bufferPercent));
- eLog(6, "[eServiceMP3] Buffering %u percent done", m_bufferInfo.bufferPercent);
+ eTrace("[eServiceMP3] Buffering %u percent done", m_bufferInfo.bufferPercent);
gst_message_parse_buffering_stats(msg, &mode, &(m_bufferInfo.avgInRate), &(m_bufferInfo.avgOutRate), &(m_bufferInfo.bufferingLeft));
m_event((iPlayableService*)this, evBuffering);
/*
@@ -2308,7 +2319,7 @@ void eServiceMP3::HandleTocEntry(GstMessage *msg)
if (gst_toc_entry_get_entry_type (entry) == GST_TOC_ENTRY_TYPE_EDITION)
{
/* extra debug info for testing purposes CVR should_be_removed later on */
- eLog(5, "[eServiceMP3] toc_type %s", gst_toc_entry_type_get_nick(gst_toc_entry_get_entry_type (entry)));
+ eTrace("[eServiceMP3] toc_type %s", gst_toc_entry_type_get_nick(gst_toc_entry_get_entry_type (entry)));
gint y = 0;
for (GList* x = gst_toc_entry_get_sub_entries (entry); x; x = x->next)
{
@@ -2337,7 +2348,7 @@ void eServiceMP3::HandleTocEntry(GstMessage *msg)
{
m_cue_entries.insert(cueEntry(pts, type));
/* extra debug info for testing purposes CVR should_be_removed later on */
- eLog(5, "[eServiceMP3] toc_subtype %s,Nr = %d, start= %#" G_GINT64_MODIFIER "x",
+ eTrace("[eServiceMP3] toc_subtype %s,Nr = %d, start= %#" G_GINT64_MODIFIER "x",
gst_toc_entry_type_get_nick(gst_toc_entry_get_entry_type (sub_entry)), y + 1, pts);
}
}
@@ -2623,10 +2634,10 @@ void eServiceMP3::pullSubtitle(GstBuffer *buffer)
}
gint64 buf_pos = GST_BUFFER_PTS(buffer);
size_t len = map.size;
- eLog(6, "[eServiceMP3] gst_buffer_get_size %zu map.size %zu", gst_buffer_get_size(buffer), len);
+ eTrace("[eServiceMP3] gst_buffer_get_size %zu map.size %zu", gst_buffer_get_size(buffer), len);
gint64 duration_ns = GST_BUFFER_DURATION(buffer);
int subType = m_subtitleStreams[m_currentSubtitleStream].type;
- eLog(6, "[eServiceMP3] pullSubtitle type=%d size=%zu", subType, len);
+ eTrace("[eServiceMP3] pullSubtitle type=%d size=%zu", subType, len);
if ( subType )
{
if ( subType < stVOB )
@@ -2643,7 +2654,7 @@ void eServiceMP3::pullSubtitle(GstBuffer *buffer)
if (!line.empty() && line[line.length()-1] == '\n')
line.erase(line.length()-1);
- eLog(6, "[eServiceMP3] got new text subtitle @ buf_pos = %lld ns (in pts=%lld), dur=%lld: '%s' ", buf_pos, buf_pos/11111, duration_ns, line.c_str());
+ eTrace("[eServiceMP3] got new text subtitle @ buf_pos = %lld ns (in pts=%lld), dur=%lld: '%s' ", buf_pos, buf_pos/11111, duration_ns, line.c_str());
uint32_t start_ms = ((buf_pos / 1000000ULL) * convert_fps) + (delay / 90);
uint32_t end_ms = start_ms + (duration_ns / 1000000ULL);
@@ -2765,8 +2776,10 @@ void eServiceMP3::pushSubtitles()
RESULT eServiceMP3::enableSubtitles(iSubtitleUser *user, struct SubtitleTrack &track)
{
- if (m_currentSubtitleStream != track.pid)
+ eDebug ("[eServiceMP3][enableSubtitles] entered: subtitle stream %i track.pid %i", m_currentSubtitleStream, track.pid);
+ if (m_currentSubtitleStream != track.pid || m_autoturnon)
{
+ eDebug ("[eServiceMP3][enableSubtitles] m_currentSubtitleStream != track.pid)");
g_object_set (G_OBJECT (m_gst_playbin), "current-text", -1, NULL);
m_subtitle_sync_timer->stop();
m_subtitle_pages.clear();
@@ -2811,14 +2824,16 @@ RESULT eServiceMP3::disableSubtitles()
RESULT eServiceMP3::getCachedSubtitle(struct SubtitleTrack &track)
{
-
- bool autoturnon = eConfigManager::getConfigBoolValue("config.subtitles.pango_autoturnon", true);
int m_subtitleStreams_size = (int)m_subtitleStreams.size();
- if (!autoturnon)
+ if (!m_autoturnon)
+ {
+ eDebug("[eServiceMP3][getCachedSubtitle] autorun subtitles not set");
return -1;
-
+ }
+ eDebug("[eServiceMP3][getCachedSubtitle] autorun subtitles set");
if (m_cachedSubtitleStream == -2 && m_subtitleStreams_size)
{
+ eDebug("[eServiceMP3][getCachedSubtitle] m_cachedSubtitleStream == -2 && m_subtitleStreams_size)");
m_cachedSubtitleStream = 0;
int autosub_level = 5;
std::string configvalue;
@@ -2855,6 +2870,7 @@ RESULT eServiceMP3::getCachedSubtitle(struct SubtitleTrack &track)
if (m_cachedSubtitleStream >= 0 && m_cachedSubtitleStream < m_subtitleStreams_size)
{
+ eDebug("[eServiceMP3][getCachedSubtitle] (m_cachedSubtitleStream >= 0 && m_cachedSubtitleStream < m_subtitleStreams_size)");
track.type = 2;
track.pid = m_cachedSubtitleStream;
track.page_number = int(m_subtitleStreams[m_cachedSubtitleStream].type);
@@ -2880,7 +2896,7 @@ RESULT eServiceMP3::getSubtitleList(std::vector &subtitlel
break;
default:
{
- struct SubtitleTrack track;
+ struct SubtitleTrack track = {};
track.type = 2;
track.pid = stream_idx;
track.page_number = int(type);
diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h
index 149492c2a7d..adcb0553b61 100644
--- a/lib/service/servicemp3.h
+++ b/lib/service/servicemp3.h
@@ -305,6 +305,7 @@ class eServiceMP3: public iPlayableService, public iPauseableService,
bool m_use_prefillbuffer;
bool m_paused;
bool m_seek_paused;
+ bool m_autoturnon;
/* cuesheet load check */
bool m_cuesheet_loaded;
/* servicemMP3 chapter TOC support CVR */
diff --git a/main/Makefile.am b/main/Makefile.am
index 0fbd04f5f36..b4688955f98 100644
--- a/main/Makefile.am
+++ b/main/Makefile.am
@@ -59,6 +59,7 @@ else
ENIGMA2_COMMIT_DATE = `$(GIT) log --no-color -n 1 --pretty=format:%cd --date=short`
ENIGMA2_BRANCH = `$(GIT) branch --no-color 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'`
ENIGMA2_REV = `$(GIT) describe --abbrev=7 --always --long --tags`
+ENIGMA2_COMMIT_HASH = `$(GIT) rev-parse --verify HEAD`
endif
endif
@@ -70,6 +71,7 @@ version-intermediate.h:
-$(AM_V_at)[ -n "$(ENIGMA2_COMMIT_DATE)" ] && echo "#define ENIGMA2_COMMIT_DATE \"$(ENIGMA2_COMMIT_DATE)\"" >> $@
-$(AM_V_at)[ -n "$(ENIGMA2_BRANCH)" ] && echo "#define ENIGMA2_BRANCH \"$(ENIGMA2_BRANCH)\"" >> $@
-$(AM_V_at)[ -n "$(ENIGMA2_REV)" ] && echo "#define ENIGMA2_REV \"$(ENIGMA2_REV)\"" >> $@
+ -$(AM_V_at)[ -n "$(ENIGMA2_COMMIT_HASH)" ] && echo "#define ENIGMA2_COMMIT_HASH \"$(ENIGMA2_COMMIT_HASH)\"" >> $@
$(AM_V_at)([ -f version.h ] && diff -q version.h $@ >/dev/null) || $(INSTALL_HEADER) $@ version.h
enigma2$(EXEEXT): $(enigma2_OBJECTS) $(enigma2_DEPENDENCIES) $(enigma2_LDADD_WHOLE)
diff --git a/main/enigma.cpp b/main/enigma.cpp
index 800cb975a24..dd7a955ff84 100644
--- a/main/enigma.cpp
+++ b/main/enigma.cpp
@@ -400,10 +400,20 @@ void runMainloop()
}
const char *getEnigmaVersionString()
+{
+ return enigma2_version;
+}
+
+const char *getEnigmaLastCommitDate()
{
return enigma2_date;
}
+const char *getEnigmaLastCommitHash()
+{
+ return enigma2_hash;
+}
+
const char *getGStreamerVersionString()
{
return gst_version_string();
diff --git a/main/version_info.cpp b/main/version_info.cpp
index 5dcdbd7af5e..1c8105f574d 100644
--- a/main/version_info.cpp
+++ b/main/version_info.cpp
@@ -16,4 +16,9 @@ const char *enigma2_branch = ENIGMA2_BRANCH;
#endif
const char *enigma2_rev = ENIGMA2_REV;
+#ifndef ENIGMA2_COMMIT_HASH
+#define ENIGMA2_COMMIT_HASH ""
+#endif
+const char *enigma2_hash = ENIGMA2_COMMIT_HASH;
+
const char *enigma2_version = (ENIGMA2_COMMIT_DATE "-" ENIGMA2_BRANCH);
diff --git a/main/version_info.h b/main/version_info.h
index 63187e1c243..5d5a35ffa9a 100644
--- a/main/version_info.h
+++ b/main/version_info.h
@@ -4,6 +4,7 @@
extern const char *enigma2_date;
extern const char *enigma2_branch;
extern const char *enigma2_rev;
+extern const char *enigma2_hash;
extern const char *enigma2_version;
#endif
diff --git a/po/fi.po b/po/fi.po
index 88089f37916..320e334d0d9 100644
--- a/po/fi.po
+++ b/po/fi.po
@@ -5,7 +5,7 @@ msgstr ""
"Project-Id-Version: enigma2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-12-27 23:35+0000\n"
-"PO-Revision-Date: 2024-06-13 19:17+0300\n"
+"PO-Revision-Date: 2024-08-25 18:44+0300\n"
"Last-Translator: Orlandox\n"
"Language-Team: timoj/Kojo/Samzam/Orlandox\n"
"Language: fi\n"
@@ -1477,7 +1477,7 @@ msgid "5"
msgstr "5"
msgid "5001 + 5002"
-msgstr ""
+msgstr "5001 + 5002"
msgid "5001 only"
msgstr "vain 5001"
@@ -2670,7 +2670,7 @@ msgid "Belarus"
msgstr "Valko-Venäjä"
msgid "Belgian"
-msgstr "Belgialainen"
+msgstr "Belgia"
msgid "Belgium"
msgstr "Belgia"
@@ -2845,7 +2845,7 @@ msgid "Bulgaria"
msgstr "Bulgaria"
msgid "Bulgarian"
-msgstr "Bulgarialainen"
+msgstr "Bulgaria"
msgid "Burkina Faso"
msgstr "Burkina Faso"
@@ -3320,6 +3320,9 @@ msgstr "Piirisarja:\tHiSilicon %s\n"
msgid "Chipset: %s"
msgstr "Piirisarja: %s"
+msgid "Chinese"
+msgstr "Kiina"
+
msgid "Choose Bouquet"
msgstr "Valitse suosikkilista"
@@ -3627,10 +3630,10 @@ msgid "Configure alignment of the timeline date."
msgstr "Muuta aikajanan päivämäärän sijainnin asetuksia."
msgid "Configure an additional delay to improve external subtitle synchronisation."
-msgstr "Määritä ylimääräinen viive parantaaksesi ulkoisten tekstitysten ajoitusta."
+msgstr "Määrittää ylimääräisen viiveen parantamaan ulkoisen tekstityksen ajoitusta."
msgid "Configure an additional delay to improve subtitle synchronisation."
-msgstr "Määritä ylimääräinen viive parantaaksesi tekstitysten ajoitusta."
+msgstr "Määrittää ylimääräisen viiveen parantamaan tekstitysten ajoitusta."
msgid "Configure duration of inactivity before the hard disk drive goes to standby"
msgstr "Määritä joutoaika, jonka jälkeen kiintolevy siirtyy valmiustilaan"
@@ -3654,7 +3657,7 @@ msgid "Configure if and how wide the service name column will be shown in the ch
msgstr "Määrittää kuinka leveänä kanavanimet näytetään kanavalistassa."
msgid "Configure if behind the subtitles a background is shown."
-msgstr "Valitse näytetäänkö tekstityksen tausta."
+msgstr "Määrittää näkyykö tekstityksen takana tausta."
msgid "Configure if picons will be shown in the service list."
msgstr "Määrittää näytetäänkö kanavalogot kanavalistassa."
@@ -3666,7 +3669,7 @@ msgid "Configure if service picons will be shown in the channel selection list."
msgstr "Määrittää näytetäänkö kanavalogot kanavalistassa."
msgid "Configure if the subtitle should switch between normal, italic, bold and bolditalic"
-msgstr "Muokkaa ulkoisen tekstityksen fonttia, vaihtoehtoina: normaali, kursivoitu, lihavoitu ja lihavoitu kursiivi"
+msgstr "Määrittää pitääkö tekstityksen vaihtaa normaalin, kursivoidun, lihavoidun ja lihavoidun kursiivin välillä"
msgid "Configure interface"
msgstr "Määritä verkkosovitin"
@@ -3696,7 +3699,7 @@ msgid "Configure the behavior when reaching the end of a movie, during movie pla
msgstr "Määritä toiminto, kun saavutetaan tallenteen loppu toiston aikana."
msgid "Configure the border width of the subtitles. The dark border makes the subtitles easier to read on a light background."
-msgstr "Määritä tekstityksen reunuksen leveys. Tumma reunus helpottaa tekstityksen lukemista vaalealla taustalla."
+msgstr "Määrittää tekstityksen reunuksen leveyden. Tumma reunus helpottaa tekstityksen lukemista vaalealla taustalla."
msgid "Configure the brightness level of the front panel display for dimmed operation."
msgstr "Määritä etupaneelin näytön kirkkaus himmennetyssä tilassa."
@@ -3729,7 +3732,7 @@ msgid "Configure the first subtitle language (highest priority)."
msgstr "Määrittää ensisijaisen tekstityksen kielen (korkein prioriteetti)."
msgid "Configure the font size of the subtitles."
-msgstr "Määrittää tekstityksen koon."
+msgstr "Määrittää tekstityksen fonttikoon."
msgid "Configure the font size relative to skin size, so 1 increases by 1 point size, and -1 decreases by 1 point size."
msgstr "Määritä tekstin koko suhteessa teeman määritykseen, joten 1 suurentaa kokoa yhdellä merkkikoolla ja -1 pienentää yhdellä"
@@ -3747,7 +3750,7 @@ msgid "Configure the gateway."
msgstr "Määritä verkon yhdyskäytävä."
msgid "Configure the horizontal alignment of the subtitles."
-msgstr "Määrittää tekstityksen vaakasijainnin."
+msgstr "Määrittää tekstitysten vaakasuoran kohdistuksen."
msgid "Configure the infobar fading speed"
msgstr "Määritä tietopalkin häivytysnopeus"
@@ -3837,13 +3840,13 @@ msgid "Configure the third subtitle language."
msgstr "Määrittää kolmannen tekstityskielen."
msgid "Configure the transparency of the black background of graphical DVB subtitles."
-msgstr "Määrittää DVB-tekstityksen mustan taustavärin läpinäkyvyyden."
+msgstr "Määrittää DVB-tekstityksen mustan taustan läpinäkyvyyden."
msgid "Configure the tuner mode."
msgstr "Määrittää virittimen toimintatilan."
msgid "Configure the vertical position of the subtitles, measured from the bottom of the screen."
-msgstr "Määrittää tekstityksen kohdan pystysuunnassa, mitattuna kuvaruudun alareunasta."
+msgstr "Määrittää tekstityksen pystysuoran sijainnin näytön alareunasta mitattuna."
msgid "Configure the width allocated to the picon."
msgstr "Määritä kanavalogolle varattu leveys."
@@ -4236,7 +4239,7 @@ msgid "Czech"
msgstr "Tšekki"
msgid "Czechia"
-msgstr "Czechia"
+msgstr "Tšekki"
msgid "DAC"
msgstr "DAC"
@@ -4291,7 +4294,7 @@ msgid "DVB CI Delay"
msgstr "DVB CI-viive"
msgid "DVB subtitle black transparency"
-msgstr "DVB-tekstin mustan reunan läpinäkyvyys"
+msgstr "DVB-tekstityksen mustan läpinäkyvyys"
msgid "DVB type"
msgstr "DVB tyyppi"
@@ -4339,7 +4342,7 @@ msgid "Dance"
msgstr "Tanssi"
msgid "Danish"
-msgstr "Tanskalainen"
+msgstr "Tanska"
msgid "Darts"
msgstr "Tikanheitto"
@@ -6695,7 +6698,7 @@ msgid "Heard Island and McDonald Islands"
msgstr "Heard Island and McDonald Islands"
msgid "Hebrew"
-msgstr "Hebrea"
+msgstr "Heprea"
msgid "Height"
msgstr "Korkeus"
@@ -7662,8 +7665,8 @@ msgid "Last speed"
msgstr "Aikaisempi nopeus"
#, python-format
-msgid "Last update:\t%s\n"
-msgstr "Päivitys:\t%s\n"
+msgid "Last E2 update:\t%s (%s)\n"
+msgstr "Viimeisin E2 päivitys:\t%s (%s)\n"
#, python-format
msgid "Last update: %s"
@@ -7703,8 +7706,8 @@ msgstr "Libanon"
msgid "Left"
msgstr "Vasen"
-msgid "Left from servicename (only available in single line mode)"
-msgstr "Kanavanimestä vasemmalle (käytössä vain 1-rivisessä tilassa)"
+msgid "Left from servicename"
+msgstr "Kanavanimestä vasemmalle"
msgid "Left long"
msgstr "Pitkä vasemmalle"
@@ -9465,8 +9468,8 @@ msgstr "Prosenttia"
msgid "Percentage left"
msgstr "Prosentit vasemmalla"
-msgid "Percentage right (only available in single line mode)"
-msgstr "Prosentit oikealla (käytössä vain 1-rivisessä tilassa)"
+msgid "Percentage right"
+msgstr "Prosentit oikealla"
msgid "Perform a complete image backup before updating."
msgstr "Suorita täydellinen image-varmuuskopiointi ennen päivitystä."
@@ -10225,8 +10228,8 @@ msgstr "Etenemispalkki"
msgid "Progress bar left"
msgstr "Etenemispalkki vasemmalla"
-msgid "Progress bar right (only available in single line mode)"
-msgstr "Etenemispalkki oikealla (käytössä vain 1-rivisessä tilassa)"
+msgid "Progress bar right"
+msgstr "Etenemispalkki oikealla"
msgid "Prominent"
msgstr "Kuuluisa"
@@ -12348,7 +12351,7 @@ msgid "Show crypto info in infobar"
msgstr "Näytä salaustyyppi tietopalkissa"
msgid "Show default after description"
-msgstr "Näytä oletukset ohjelmakuvauksen jälkeen"
+msgstr "Näytä oletus kuvauksen jälkeen"
msgid "Show default on new line"
msgstr "Näytä oletus uudella rivillä"
@@ -13315,7 +13318,7 @@ msgid "Subtitle alignment"
msgstr "Tekstityksen keskitys"
msgid "Subtitle border width"
-msgstr "Tekstin reunan leveys"
+msgstr "Tekstityksen reunan leveys"
msgid "Subtitle delay when timing is bad"
msgstr "Tekstityksen viive ajoituksen ollessa huono"
@@ -13546,7 +13549,7 @@ msgstr ""
"Suomenkielinen käännös: timoj, Kojo, Samzam, Orlandox\n"
"\n"
"Ylläpito : Orlandox\n"
-"--- 13.06.2024 ---\n"
+"--- 25.08.2024 ---\n"
"\n"
"http://www.huoltovalikko.com"
@@ -13672,7 +13675,7 @@ msgid "Text color"
msgstr "Tekstin väri"
msgid "Thai"
-msgstr "Thai"
+msgstr "Thaimaa"
msgid "Thailand"
msgstr "Thaimaa"
@@ -14893,7 +14896,7 @@ msgid "Use original DVB subtitle position"
msgstr "Käytä alkuperäisen DVB-tekstityksen paikkaa"
msgid "Use original teletext position"
-msgstr "Käytä alkuperäistä teksti-TV tekstin paikkaa"
+msgstr "Käytä alkuperäistä teksti-TV tekstityksen paikkaa"
msgid "Use piconlcd directory for picons on color LCD"
msgstr "Käytä picon_lcd hakemistoa värinäytön kanavalogoille"
@@ -15478,14 +15481,14 @@ msgstr "Mikä viikonpäivä?"
msgid "What do you want to scan?"
msgstr "Mitä haluat hakea?"
-msgid "When changing skins this allows the skin to load without requiring an enigma restart."
-msgstr "Tämä sallii teeman vaihdon ilman enigman uudelleenkäynnistystä."
+msgid "This feature is for skin developers. It allows the skin to load without requiring an enigma restart."
+msgstr "Tämä ominaisuus on teemankehittäjille. Sen avulla teema latautuu ilman enigman uudelleenkäynnistystä."
msgid "When enabled a forced download will be possible from the extensions menu (blue button). Shows after next restart."
msgstr "Kun sallittu, pakotettu lataus on mahdollista laajennusvalikosta (sininen näppäin). Näkyy seuraavan uudelleenkäynnistyksen jälkeen."
msgid "When enabled enigma2 will load unlinked userbouquets. This means that userbouquets that are available, but not included in the bouquets.tv or bouquets.radio files, will still be loaded. This allows you for example to keep your own user bouquet while installed settings are upgraded"
-msgstr "Kun päällä, Enigma2 näyttää piilotetut suosikkilistat. Suosikkilistat jotka ovat saatavilla, mutta eivät ole bouquets.tv tai bouquets.radio tiedostoissa, ladataan silti. Tämä antaa sinun pitää omat suosikkilistasi samalla kun asennettuja päivitetään"
+msgstr "Kun päällä, Enigma2 näyttää piilotetut suosikkilistat. Suosikkilistat jotka ovat saatavilla, mutta eivät ole bouquets.tv tai bouquets.radio tiedostoissa, näytetään silti. Tämä antaa sinun pitää omat suosikkilistasi samalla kun asennettuja päivitetään"
msgid "When enabled the online checker will also check for experimental versions"
msgstr "Kun päällä, päivitys etsii myös kokeiluversioita"
@@ -15569,7 +15572,7 @@ msgid "When enabled, recordings are grouped by name into collections automatical
msgstr "Kun päällä, tallenteet ryhmitetään nimen mukaan kokoelmiksi automaattisesti."
msgid "When enabled, reformat subtitles to match the width of the screen."
-msgstr "Kun päällä, tekstityksen leveys sovitetaan ruudun leveyteen."
+msgstr "Kun päällä, tekstityksen leveys sovitetaan näytön leveyteen."
msgid "When enabled, show channel numbers in the channel selection screen."
msgstr "Kun päällä, näytä kanavanvalinnassa kanavanumerot."
@@ -15776,7 +15779,7 @@ msgid "Yellow"
msgstr "Keltainen"
msgid "Yellow DVB subtitles"
-msgstr "Keltaiset DVB-tekstit"
+msgstr "Keltainen DVB-tekstitys"
msgid "Yellow button (long)"
msgstr "Keltainen näppäin (pitkä)"
@@ -18790,7 +18793,7 @@ msgstr "Suorita komentorivin käskyjonoja (scripts)."
msgid "SWAP file not found. You have to create the file before you try to activate it."
msgstr "SWAP-tiedostoa ei löytynyt. Luo se ensin, ennen kuin yrität aktivoida sitä."
-msgid "SWAP manager"
+msgid "Swap manager"
msgstr "SWAP-tiedoston hallinnointi"
msgid "SWAP place:"
@@ -19195,7 +19198,7 @@ msgid "Homebuild URL"
msgstr "Itse luodun imagen URL"
msgid "If you are running your own build server and want to download your own images directly into ImageManager you can link to the URL of your JSON index. Don't forget to add '%s' where the box name should be inserted into the url. If you need help with implementing this please ask on the forum."
-msgstr "Jos käytät omaa koontipalvelinta ja haluat ladata omat imagesi suoraan Imagen Hallinnointiin, voit linkittää JSON-hakemistosi URL-osoitteeseen. Älä unohda lisätä '%s', johon boksin nimi tulee lisätä URL-osoitteeseen. Jos tarvitset apua tämän toteuttamisessa, kysy foorumilta."
+msgstr "Jos käytät omaa koontipalvelinta ja haluat ladata omat imagesi suoraan Imagen Hallinnointiin, voit linkittää JSON-hakemistosi URL-osoitteeseen. Älä unohda lisätä '%s', johon laitteen nimi tulee lisätä URL-osoitteeseen. Jos tarvitset apua tämän toteuttamisessa, kysy foorumilta."
msgid "slot%s %s - %s (current image)"
msgstr "paikka%s %s - %s (nykyinen image)"
@@ -19219,7 +19222,7 @@ msgid "The backup creates a snapshot of the image exactly as it is at the curren
msgstr "Varmuuskopio luo tilannekuvan imagesta täsmälleen sellaisena kuin se on kyseisellä hetkellä."
msgid "It allows making changes to the box with the knowledge that the box can be safely reverted back to a previous known working state."
-msgstr "Se mahdollistaa muutosten tekemisen boksiin tietäen, että boksi voidaan turvallisesti palauttaa aiempaan tunnetusti toimivaan tilaan."
+msgstr "Se mahdollistaa muutosten tekemisen laitteeseen tietäen, että laite voidaan turvallisesti palauttaa aiempaan tunnetusti toimivaan tilaan."
msgid "To make an image backup select GREEN from Image Manager main screen."
msgstr "Jos haluat tehdä imagen varmuuskopion, valitse Imagen hallinnoinnin päänäytöstä VIHREÄ."
@@ -19468,3 +19471,87 @@ msgstr "Aloita kaapeliverkon haku"
msgid "Start Fastscan"
msgstr "Aloita pikahaku"
+
+msgid "Always"
+msgstr "Aina"
+
+msgid "Alpha blending is the process of combining an image with a background to create the appearance of partial or full transparency. 'Always' may cause receivers that don't support hardware acceleration to render images more slowly. Also some skins may show strange side effects."
+msgstr "Alfasekoitus on prosessi, jossa kuva yhdistetään taustaan osittaisen tai täydellisen läpinäkyvyyden luomiseksi. 'Aina' saattaa saada vastaanottimet, jotka eivät tue laitteistokiihdytystä, renderöimään kuvia hitaammin. Myös jotkin teemat voivat näyttää outoja sivuvaikutuksia."
+
+msgid "Use skin setting"
+msgstr "Käytä teeman asetusta"
+
+msgid "Force alpha blending"
+msgstr "Pakota alfasekoitus"
+
+msgid "Subtitles always enabled for movie playback by servicemp3/servicehisilicon."
+msgstr "Tekstitykset ovat aina käytössä tallenteen toistoa varten servicemp3/servicehisiconin avulla."
+
+msgid "Only alpha test to alpha blend"
+msgstr "Vain alfatesti alfasekoitukseen"
+
+msgid "Alert - the system has found an issue with the Vu+ Kexec Multiboot images - read the following information carefully"
+msgstr "Varoitus - järjestelmä on löytänyt ongelman Vu+ Kexec Multiboot -imageista - lue seuraavat tiedot huolellisesti"
+
+msgid "1. Try to reboot the box and check if this warning disappears"
+msgstr "1. Yritä käynnistää laite uudelleen ja tarkista, katoaako tämä varoitus"
+
+msgid "2. Try to re install Vu+ Multiboot as usual"
+msgstr "2. Yritä asentaa Vu+ Multiboot uudelleen tavalliseen tapaan"
+
+msgid "3. If you wish to try and recover your Multiboot system then proceed as follows......."
+msgstr "3. Jos haluat yrittää palauttaa Multiboot-järjestelmän, toimi seuraavasti......."
+
+msgid "4. Login into the Recovery image using SSH or telnet."
+msgstr "4. Kirjaudu Palautustilaan SSH:n tai telnetin avulla."
+
+msgid "5. If you wish to backup eMMC slots 1,2,3 then enter 'tar -cvzf /media/hdd/linuxrootfsX.tar.gz /linuxrootfsX' where X is the slot number and repeat the command for each installed image slot in flash (so you have backup of installed flash images)"
+msgstr "5. Jos haluat varmuuskopioida eMMC-paikat 1,2,3, kirjoita 'tar -cvzf /media/hdd/linuxrootfsX.tar.gz /linuxrootfsX', jossa X on paikan numero, ja toista komento jokaiselle asennetulle imagepaikalle flash-muistissa (jolloin sinulla on varmuuskopio asennetuista flash-imageista)"
+
+msgid "6. Then enter '/etc/init.d/kexec-multiboot-recovery start' "
+msgstr "6. Kirjoita sitten '/etc/init.d/kexec-multiboot-recovery start' "
+
+msgid "7. The script will copy the required files and then will automatically reboot the box"
+msgstr "7. Scripti kopioi tarvittavat tiedostot ja käynnistää sitten laitteen automaattisesti uudelleen"
+
+msgid "Kexec warning"
+msgstr "Kexec-varoitus"
+
+msgid "Vu+ ImageManager wizard"
+msgstr "Vu+ Imagen hallinnoinnin avustaja"
+
+msgid "Use non blocking CA device access"
+msgstr "Käytä estotonta CA-laitteen käyttöoikeutta"
+
+msgid "When enabled, the CA device is not blocked when accessed."
+msgstr "Kun tämä on käytössä, CA-laitetta ei estetä, kun sitä käytetään."
+
+msgid "Unknown image"
+msgstr "Tuntematon image"
+
+msgid "Log python stack trace on spinner"
+msgstr "Lokita python-pinon jäljitys spinnerissä"
+
+msgid "Set to yes for debugging the root cause of a spinner."
+msgstr "Aseta kyllä, jos haluat selvittää spinnerin perimmäisen syyn."
+
+msgid "Skin selection"
+msgstr "Teeman valinta"
+
+msgid "Audio volume step size"
+msgstr "Äänenvoimakkuuden askelkoko"
+
+msgid "Configure the general audio volume step size (limit 1-10)."
+msgstr "Määrittele yleinen äänenvoimakkuuden askelkoko (rajoitus 1-10)."
+
+msgid "Hide mute icon"
+msgstr "Piilota mykistyskuvake"
+
+msgid "If volume muted, hide mute icon or mute information after few seconds."
+msgstr "Jos äänenvoimakkuus on mykistetty, piilota mykistyskuvake tai mykistystiedot muutaman sekunnin kuluttua."
+
+msgid "Top"
+msgstr "Ylinpänä"
+
+msgid "Bottom"
+msgstr "Alinpana"