aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/base/Makefile.am2
-rw-r--r--lib/base/console.cpp23
-rw-r--r--lib/base/etpm.cpp172
-rw-r--r--lib/base/etpm.h44
-rw-r--r--lib/dvb/demux.cpp61
-rw-r--r--lib/dvb/demux.h4
-rw-r--r--lib/dvb/dvb.cpp51
-rw-r--r--lib/dvb/dvb.h3
-rw-r--r--lib/dvb/epgcache.cpp224
-rw-r--r--lib/dvb/epgcache.h8
-rw-r--r--lib/dvb/frontend.cpp40
-rw-r--r--lib/dvb/idemux.h3
-rw-r--r--lib/dvb/idvb.h1
-rw-r--r--lib/dvb/pmt.cpp4
-rw-r--r--lib/dvb/sec.cpp29
-rw-r--r--lib/gdi/font.cpp149
-rw-r--r--lib/gdi/font.h13
-rw-r--r--lib/gdi/glcddc.cpp8
-rw-r--r--lib/gdi/gpixmap.cpp194
-rw-r--r--lib/gdi/lcd.cpp107
-rw-r--r--lib/gdi/lcd.h6
-rw-r--r--lib/gui/elistboxcontent.cpp98
-rw-r--r--lib/gui/elistboxcontent.h2
-rw-r--r--lib/gui/epixmap.cpp32
-rw-r--r--lib/gui/epixmap.h5
-rw-r--r--lib/gui/ewindowstyle.cpp4
-rwxr-xr-x[-rw-r--r--]lib/python/Components/About.py11
-rwxr-xr-xlib/python/Components/ConfigList.py13
-rwxr-xr-x[-rw-r--r--]lib/python/Components/Converter/TemplatedMultiContent.py4
-rwxr-xr-xlib/python/Components/DreamInfoHandler.py88
-rwxr-xr-xlib/python/Components/FileList.py3
-rw-r--r--[-rwxr-xr-x]lib/python/Components/Harddisk.py47
-rwxr-xr-x[-rw-r--r--]lib/python/Components/InputDevice.py225
-rwxr-xr-xlib/python/Components/Ipkg.py8
-rwxr-xr-xlib/python/Components/Network.py103
-rw-r--r--lib/python/Components/NimManager.py86
-rw-r--r--lib/python/Components/ParentalControl.py14
-rw-r--r--lib/python/Components/ParentalControlList.py5
-rwxr-xr-x[-rw-r--r--]lib/python/Components/RecordingConfig.py6
-rwxr-xr-x[-rw-r--r--]lib/python/Components/Renderer/Listbox.py15
-rw-r--r--[-rwxr-xr-x]lib/python/Components/ServiceList.py33
-rw-r--r--lib/python/Components/Task.py5
-rw-r--r--lib/python/Components/TimerSanityCheck.py4
-rw-r--r--lib/python/Components/UsageConfig.py11
-rw-r--r--lib/python/Components/VolumeControl.py4
-rwxr-xr-xlib/python/Components/config.py20
-rwxr-xr-xlib/python/Plugins/DemoPlugins/Makefile.am6
-rw-r--r--lib/python/Plugins/DemoPlugins/TPMDemo/Makefile.am5
-rw-r--r--lib/python/Plugins/DemoPlugins/TPMDemo/README1
-rw-r--r--lib/python/Plugins/DemoPlugins/TPMDemo/__init__.py0
-rw-r--r--lib/python/Plugins/DemoPlugins/TPMDemo/plugin.py87
-rwxr-xr-xlib/python/Plugins/Extensions/CutListEditor/meta/plugin_cutlisteditor.xml13
-rwxr-xr-xlib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py4
-rw-r--r--lib/python/Plugins/Extensions/DVDBurn/Process.py14
-rw-r--r--lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py4
-rwxr-xr-xlib/python/Plugins/Extensions/DVDBurn/meta/plugin_dvdburn.xml17
-rwxr-xr-xlib/python/Plugins/Extensions/DVDPlayer/meta/plugin_dvdplayer.xml13
-rwxr-xr-xlib/python/Plugins/Extensions/DVDPlayer/plugin.py19
-rwxr-xr-xlib/python/Plugins/Extensions/GraphMultiEPG/meta/plugin_graphmultiepg.xml15
-rwxr-xr-xlib/python/Plugins/Extensions/MediaPlayer/meta/plugin_mediaplayer.xml13
-rwxr-xr-xlib/python/Plugins/Extensions/MediaPlayer/plugin.py19
-rwxr-xr-xlib/python/Plugins/Extensions/MediaPlayer/settings.py2
-rwxr-xr-xlib/python/Plugins/Extensions/MediaScanner/meta/plugin_mediascanner.xml14
-rwxr-xr-xlib/python/Plugins/Extensions/PicturePlayer/meta/plugin_pictureplayer.xml13
-rwxr-xr-x[-rw-r--r--]lib/python/Plugins/Extensions/SocketMMI/meta/plugin_socketmmi.xml11
-rwxr-xr-x[-rw-r--r--]lib/python/Plugins/Extensions/TuxboxPlugins/meta/plugin_tuxboxplugins.xml11
-rw-r--r--lib/python/Plugins/Makefile.am1
-rwxr-xr-xlib/python/Plugins/SystemPlugins/CleanupWizard/meta/plugin_cleanupwizard.xml18
-rwxr-xr-xlib/python/Plugins/SystemPlugins/CommonInterfaceAssignment/meta/plugin_commoninterfaceassignment.xml23
-rwxr-xr-xlib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/__init__.py40
-rwxr-xr-xlib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/meta/plugin_crashlogautosubmit.xml17
-rwxr-xr-xlib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/plugin.py38
-rwxr-xr-xlib/python/Plugins/SystemPlugins/DefaultServicesScanner/meta/plugin_defaultservicesscanner.xml16
-rwxr-xr-xlib/python/Plugins/SystemPlugins/DiseqcTester/meta/plugin_diseqctester.xml16
-rwxr-xr-x[-rw-r--r--]lib/python/Plugins/SystemPlugins/FrontprocessorUpgrade/meta/plugin_frontprocessorupgrade.xml14
-rwxr-xr-x[-rw-r--r--]lib/python/Plugins/SystemPlugins/Hotplug/meta/plugin_hotplug.xml15
-rwxr-xr-xlib/python/Plugins/SystemPlugins/NFIFlash/dm8000_writenandbin71669 -> 0 bytes
-rw-r--r--lib/python/Plugins/SystemPlugins/NFIFlash/downloader.py1277
-rwxr-xr-x[-rw-r--r--]lib/python/Plugins/SystemPlugins/NFIFlash/flasher.py346
-rwxr-xr-xlib/python/Plugins/SystemPlugins/NFIFlash/meta/plugin_nfiflash.xml18
-rwxr-xr-xlib/python/Plugins/SystemPlugins/NFIFlash/mywritenandbin71626 -> 0 bytes
-rwxr-xr-xlib/python/Plugins/SystemPlugins/NFIFlash/plugin.py23
-rwxr-xr-xlib/python/Plugins/SystemPlugins/NetworkWizard/NetworkWizard.py3
-rwxr-xr-xlib/python/Plugins/SystemPlugins/NetworkWizard/meta/plugin_networkwizard.xml16
-rwxr-xr-xlib/python/Plugins/SystemPlugins/PositionerSetup/meta/plugin_positionersetup.xml17
-rwxr-xr-xlib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/meta/plugin_satelliteequipmentcontrol.xml16
-rwxr-xr-xlib/python/Plugins/SystemPlugins/Satfinder/meta/plugin_satfinder.xml18
-rwxr-xr-xlib/python/Plugins/SystemPlugins/SkinSelector/meta/plugin_skinselector.xml15
-rwxr-xr-xlib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py10
-rwxr-xr-xlib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py215
-rwxr-xr-xlib/python/Plugins/SystemPlugins/SoftwareManager/meta/plugin_softwaremanager.xml18
-rwxr-xr-xlib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py472
-rwxr-xr-xlib/python/Plugins/SystemPlugins/TempFanControl/LICENSE12
-rwxr-xr-x[-rw-r--r--]lib/python/Plugins/SystemPlugins/TempFanControl/Makefile.am4
-rwxr-xr-xlib/python/Plugins/SystemPlugins/TempFanControl/meta/Makefile.am3
-rwxr-xr-xlib/python/Plugins/SystemPlugins/TempFanControl/meta/plugin_tempfancontrol.xml20
-rwxr-xr-x[-rw-r--r--]lib/python/Plugins/SystemPlugins/TempFanControl/plugin.py1
-rwxr-xr-xlib/python/Plugins/SystemPlugins/VideoEnhancement/meta/plugin_videoenhancement.xml16
-rwxr-xr-xlib/python/Plugins/SystemPlugins/VideoTune/meta/plugin_videotune.xml13
-rw-r--r--lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py4
-rwxr-xr-x[-rw-r--r--]lib/python/Plugins/SystemPlugins/Videomode/VideoWizard.py18
-rwxr-xr-xlib/python/Plugins/SystemPlugins/Videomode/meta/plugin_videomode.xml14
-rwxr-xr-xlib/python/Plugins/SystemPlugins/WirelessLan/Makefile.am2
-rwxr-xr-xlib/python/Plugins/SystemPlugins/WirelessLan/Wlan.py179
-rwxr-xr-xlib/python/Plugins/SystemPlugins/WirelessLan/flags.py104
-rwxr-xr-xlib/python/Plugins/SystemPlugins/WirelessLan/iwlibs.py1114
-rwxr-xr-xlib/python/Plugins/SystemPlugins/WirelessLan/meta/plugin_wirelesslan.xml12
-rwxr-xr-xlib/python/Plugins/SystemPlugins/WirelessLan/plugin.py74
-rw-r--r--lib/python/Screens/AudioSelection.py314
-rw-r--r--lib/python/Screens/ChannelSelection.py30
-rw-r--r--lib/python/Screens/InfoBarGenerics.py126
-rwxr-xr-xlib/python/Screens/InputDeviceSetup.py280
-rwxr-xr-xlib/python/Screens/Ipkg.py21
-rwxr-xr-xlib/python/Screens/Makefile.am9
-rwxr-xr-xlib/python/Screens/NetworkSetup.py158
-rw-r--r--lib/python/Screens/ParentalControlSetup.py34
-rw-r--r--lib/python/Screens/Satconfig.py9
-rw-r--r--lib/python/Screens/ScanSetup.py48
-rw-r--r--lib/python/Screens/ServiceScan.py19
-rw-r--r--lib/python/Screens/Standby.py4
-rw-r--r--lib/python/Screens/Subtitles.py103
-rw-r--r--lib/python/Screens/TaskView.py18
-rw-r--r--lib/python/Screens/TimerEntry.py22
-rwxr-xr-xlib/python/Screens/Wizard.py4
-rw-r--r--lib/python/Tools/NumericalTextInput.py8
-rw-r--r--lib/python/enigma_python.i2
-rw-r--r--lib/service/listboxservice.cpp78
-rw-r--r--lib/service/listboxservice.h8
-rw-r--r--lib/service/servicedvb.cpp4
-rw-r--r--lib/service/servicemp3.cpp115
-rw-r--r--lib/service/servicemp3.h6
131 files changed, 4460 insertions, 3485 deletions
diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am
index 6ea9d03f..05085632 100644
--- a/lib/base/Makefile.am
+++ b/lib/base/Makefile.am
@@ -8,5 +8,5 @@ libenigma_base_a_SOURCES = \
init.cpp message.cpp thread.cpp \
smartptr.cpp estring.cpp connection.cpp \
filepush.cpp encoding.cpp console.cpp rawfile.cpp \
- nconfig.cpp ioprio.cpp
+ nconfig.cpp ioprio.cpp etpm.cpp
diff --git a/lib/base/console.cpp b/lib/base/console.cpp
index add87066..43f9f61e 100644
--- a/lib/base/console.cpp
+++ b/lib/base/console.cpp
@@ -516,18 +516,15 @@ eConsolePy_write(eConsolePy* self, PyObject *args)
{
int len;
char *data;
- if (PyArg_ParseTuple(args, "si", &data, &len))
- ;
- else
+ int ret = -1;
+ Py_ssize_t argc = PyTuple_Size(args);
+ if (argc > 1)
+ ret = PyArg_ParseTuple(args, "si", &data, &len);
+ else if (argc == 1)
{
PyObject *ob;
- if (!PyArg_ParseTuple(args, "O", &ob) || !PyString_Check(ob))
- {
- PyErr_SetString(PyExc_TypeError,
- "1st arg must be a string, optionaly 2nd arg can be the string length");
- return NULL;
- }
- else
+ ret = !PyArg_ParseTuple(args, "O", &ob) || !PyString_Check(ob);
+ if (!ret)
{
Py_ssize_t length;
if (!PyString_AsStringAndSize(ob, &data, &length))
@@ -536,6 +533,12 @@ eConsolePy_write(eConsolePy* self, PyObject *args)
len = 0;
}
}
+ if (ret)
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "1st arg must be a string, optionaly 2nd arg can be the string length");
+ return NULL;
+ }
self->cont->write(data, len);
Py_RETURN_NONE;
}
diff --git a/lib/base/etpm.cpp b/lib/base/etpm.cpp
new file mode 100644
index 00000000..9a443e0a
--- /dev/null
+++ b/lib/base/etpm.cpp
@@ -0,0 +1,172 @@
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <openssl/bn.h>
+#include <openssl/sha.h>
+#include <lib/base/eerror.h>
+
+#include "etpm.h"
+
+eTPM::eTPM()
+{
+ struct sockaddr_un addr;
+ unsigned char buf[8];
+ unsigned int tag;
+ size_t len;
+ unsigned char *val;
+
+ level2_cert_read = level3_cert_read = false;
+
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, TPMD_SOCKET);
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0)
+ {
+ eDebug("[eTPM] socket error");
+ return;
+ }
+
+ if (connect(fd, (const struct sockaddr *)&addr, SUN_LEN(&addr)) < 0)
+ {
+ eDebug("[eTPM] connect error");
+ return;
+ }
+
+ buf[0] = TPMD_DT_LEVEL2_CERT;
+ buf[1] = TPMD_DT_LEVEL3_CERT;
+ if (!send_cmd(TPMD_CMD_GET_DATA, buf, 2))
+ {
+ return;
+ }
+
+ val = (unsigned char*)recv_cmd(&tag, &len);
+ if (val == NULL)
+ {
+ return;
+ }
+
+ parse_data(val, len);
+ free(val);
+}
+
+eTPM::~eTPM()
+{
+
+}
+
+bool eTPM::send_cmd(enum tpmd_cmd cmd, const void *data, size_t len)
+{
+ unsigned char buf[len + 4];
+
+ buf[0] = (cmd >> 8) & 0xff;
+ buf[1] = (cmd >> 0) & 0xff;
+ buf[2] = (len >> 8) & 0xff;
+ buf[3] = (len >> 0) & 0xff;
+ memcpy(&buf[4], data, len);
+
+ if (write(fd, buf, sizeof(buf)) != (ssize_t)sizeof(buf))
+ {
+ fprintf(stderr, "%s: incomplete write\n", __func__);
+ return false;
+ }
+
+ return true;
+}
+
+void* eTPM::recv_cmd(unsigned int *tag, size_t *len)
+{
+ unsigned char buf[4];
+ void *val;
+
+ if (read(fd, buf, 4) != 4)
+ {
+ fprintf(stderr, "%s: incomplete read\n", __func__);
+ return NULL;
+ }
+
+ *tag = (buf[0] << 8) | buf[1];
+ *len = (buf[2] << 8) | buf[3];
+
+ val = malloc(*len);
+ if (val == NULL)
+ return NULL;
+
+ ssize_t rd = read(fd, val, *len);
+ if (rd < 0)
+ {
+ perror("eTPM::recv_cmd read");
+ free(val);
+ }
+ else if ((size_t)rd != *len) {
+ fprintf(stderr, "%s: incomplete read\n", __func__);
+ free(val);
+ return NULL;
+ }
+
+ return val;
+}
+
+void eTPM::parse_data(const unsigned char *data, size_t datalen)
+{
+ unsigned int i;
+ unsigned int tag;
+ unsigned int len;
+ const unsigned char *val;
+
+ for (i = 0; i < datalen; i += len) {
+ tag = data[i++];
+ len = data[i++];
+ val = &data[i];
+
+ switch (tag) {
+ case TPMD_DT_LEVEL2_CERT:
+ if (len != 210)
+ break;
+ memcpy(level2_cert, val, 210);
+ level2_cert_read = true;
+ break;
+ case TPMD_DT_LEVEL3_CERT:
+ if (len != 210)
+ break;
+ memcpy(level3_cert, val, 210);
+ level3_cert_read = true;
+ break;
+ }
+ }
+}
+
+std::string eTPM::getCert(cert_type type)
+{
+ if (type == TPMD_DT_LEVEL2_CERT && level2_cert_read)
+ return std::string((char*)level2_cert, 210);
+ else if (type == TPMD_DT_LEVEL3_CERT && level3_cert_read)
+ return std::string((char*)level3_cert, 210);
+ return "";
+}
+
+std::string eTPM::challenge(std::string rnd)
+{
+ if (rnd.length() == 8)
+ {
+ if (!send_cmd(TPMD_CMD_COMPUTE_SIGNATURE, rnd.c_str(), 8))
+ return "";
+
+ unsigned int tag;
+ size_t len;
+ unsigned char *val = (unsigned char*)recv_cmd(&tag, &len);
+
+ if (tag != TPMD_CMD_COMPUTE_SIGNATURE)
+ return "";
+
+ std::string ret((char*)val, len);
+ free(val);
+ return ret;
+ }
+ return "";
+}
diff --git a/lib/base/etpm.h b/lib/base/etpm.h
new file mode 100644
index 00000000..c9e52140
--- /dev/null
+++ b/lib/base/etpm.h
@@ -0,0 +1,44 @@
+#ifndef __lib_base_etpm_h
+#define __lib_base_etpm_h
+
+#ifndef SWIG
+#define TPMD_SOCKET "/var/run/tpmd_socket"
+#endif
+
+#include <string>
+
+class eTPM
+{
+#ifndef SWIG
+ int fd;
+ unsigned char level2_cert[210];
+ unsigned char level3_cert[210];
+ bool level2_cert_read;
+ bool level3_cert_read;
+
+ enum tpmd_cmd {
+ TPMD_CMD_RESERVED = 0x0000,
+ TPMD_CMD_GET_DATA = 0x0001,
+ TPMD_CMD_APDU = 0x0002,
+ TPMD_CMD_COMPUTE_SIGNATURE = 0x0003,
+ TPMD_CMD_APP_CERT = 0x0004,
+ };
+
+ bool send_cmd(enum tpmd_cmd cmd, const void *data, size_t len);
+ void *recv_cmd(unsigned int *tag, size_t *len);
+ void parse_data(const unsigned char *data, size_t datalen);
+
+#endif
+public:
+ eTPM();
+ ~eTPM();
+
+ enum cert_type {
+ TPMD_DT_LEVEL2_CERT = 0x04,
+ TPMD_DT_LEVEL3_CERT = 0x05
+ };
+ std::string getCert(cert_type type);
+ std::string challenge(std::string rnd);
+};
+
+#endif // __lib_base_etpm_h
diff --git a/lib/dvb/demux.cpp b/lib/dvb/demux.cpp
index 4fba8fa8..0c736c55 100644
--- a/lib/dvb/demux.cpp
+++ b/lib/dvb/demux.cpp
@@ -247,6 +247,14 @@ eDVBSectionReader::~eDVBSectionReader()
::close(fd);
}
+RESULT eDVBSectionReader::setBufferSize(int size)
+{
+ int res=::ioctl(fd, DMX_SET_BUFFER_SIZE, size);
+ if (res < 0)
+ eDebug("eDVBSectionReader DMX_SET_BUFFER_SIZE failed(%m)");
+ return res;
+}
+
RESULT eDVBSectionReader::start(const eDVBSectionFilterMask &mask)
{
RESULT res;
@@ -279,8 +287,7 @@ RESULT eDVBSectionReader::start(const eDVBSectionFilterMask &mask)
memcpy(sct.filter.mask, mask.mask, DMX_FILTER_SIZE);
#if HAVE_DVB_API_VERSION >= 3
memcpy(sct.filter.mode, mask.mode, DMX_FILTER_SIZE);
- if (::ioctl(fd, DMX_SET_BUFFER_SIZE, 8192*8) < 0)
- eDebug("DMX_SET_BUFFER_SIZE failed(%m)");
+ setBufferSize(8192*8);
#endif
res = ::ioctl(fd, DMX_SET_FILTER, &sct);
@@ -352,7 +359,7 @@ eDVBPESReader::eDVBPESReader(eDVBDemux *demux, eMainloop *context, RESULT &res):
if (m_fd >= 0)
{
- ::ioctl(m_fd, DMX_SET_BUFFER_SIZE, 64*1024);
+ setBufferSize(64*1024);
::fcntl(m_fd, F_SETFL, O_NONBLOCK);
m_notifier = eSocketNotifier::create(context, m_fd, eSocketNotifier::Read, false);
CONNECT(m_notifier->activated, eDVBPESReader::data);
@@ -364,6 +371,14 @@ eDVBPESReader::eDVBPESReader(eDVBDemux *demux, eMainloop *context, RESULT &res):
}
}
+RESULT eDVBPESReader::setBufferSize(int size)
+{
+ int res = ::ioctl(m_fd, DMX_SET_BUFFER_SIZE, size);
+ if (res < 0)
+ eDebug("eDVBPESReader DMX_SET_BUFFER_SIZE failed(%m)");
+ return res;
+}
+
DEFINE_REF(eDVBPESReader)
eDVBPESReader::~eDVBPESReader()
@@ -484,7 +499,7 @@ eDVBTSRecorder::eDVBTSRecorder(eDVBDemux *demux): m_demux(demux)
m_running = 0;
m_target_fd = -1;
m_thread = new eDVBRecordFileThread();
- CONNECT(m_thread->m_event, eDVBTSRecorder::filepushEvent);
+ CONNECT(m_thread->m_event, eDVBTSRecorder::filepushEvent);
#ifndef HAVE_ADD_PID
m_demux->m_dvr_busy = 1;
#endif
@@ -536,8 +551,8 @@ RESULT eDVBTSRecorder::start()
eDebug("FAILED to open demux (%s) in ts recoder (%m)", filename);
return -3;
}
-
- ::ioctl(m_source_fd, DMX_SET_BUFFER_SIZE, 1024*1024);
+
+ setBufferSize(1024*1024);
dmx_pes_filter_params flt;
#if HAVE_DVB_API_VERSION > 3
@@ -577,6 +592,14 @@ RESULT eDVBTSRecorder::start()
return 0;
}
+RESULT eDVBTSRecorder::setBufferSize(int size)
+{
+ int res = ::ioctl(m_source_fd, DMX_SET_BUFFER_SIZE, size);
+ if (res < 0)
+ eDebug("eDVBTSRecorder DMX_SET_BUFFER_SIZE failed(%m)");
+ return res;
+}
+
RESULT eDVBTSRecorder::addPID(int pid)
{
if (m_pids.find(pid) != m_pids.end())
@@ -625,18 +648,36 @@ RESULT eDVBTSRecorder::setBoundary(off_t max)
RESULT eDVBTSRecorder::stop()
{
+ int state=3;
+
for (std::map<int,int>::iterator i(m_pids.begin()); i != m_pids.end(); ++i)
stopPID(i->first);
if (!m_running)
return -1;
+
+#if HAVE_DVB_API_VERSION >= 5
+ /* workaround for record thread stop */
+ if (::ioctl(m_source_fd, DMX_STOP) < 0)
+ perror("DMX_STOP");
+ else
+ state &= ~1;
+
+ if (::close(m_source_fd) < 0)
+ perror("close");
+ else
+ state &= ~2;
+#endif
+
m_thread->stop();
-
- close(m_source_fd);
+
+ if (state & 3)
+ ::close(m_source_fd);
+
+ m_running = 0;
m_source_fd = -1;
-
+
m_thread->stopSaveMetaInformation();
-
return 0;
}
diff --git a/lib/dvb/demux.h b/lib/dvb/demux.h
index 7a697d49..d43c41bb 100644
--- a/lib/dvb/demux.h
+++ b/lib/dvb/demux.h
@@ -56,9 +56,9 @@ class eDVBSectionReader: public iDVBSectionReader, public Object
void data(int);
ePtr<eSocketNotifier> notifier;
public:
-
eDVBSectionReader(eDVBDemux *demux, eMainloop *context, RESULT &res);
virtual ~eDVBSectionReader();
+ RESULT setBufferSize(int size);
RESULT start(const eDVBSectionFilterMask &mask);
RESULT stop();
RESULT connectRead(const Slot1<void,const __u8*> &read, ePtr<eConnection> &conn);
@@ -76,6 +76,7 @@ class eDVBPESReader: public iDVBPESReader, public Object
public:
eDVBPESReader(eDVBDemux *demux, eMainloop *context, RESULT &res);
virtual ~eDVBPESReader();
+ RESULT setBufferSize(int size);
RESULT start(int pid);
RESULT stop();
RESULT connectRead(const Slot2<void,const __u8*, int> &read, ePtr<eConnection> &conn);
@@ -90,6 +91,7 @@ public:
eDVBTSRecorder(eDVBDemux *demux);
~eDVBTSRecorder();
+ RESULT setBufferSize(int size);
RESULT start();
RESULT addPID(int pid);
RESULT removePID(int pid);
diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp
index 17712dde..51629452 100644
--- a/lib/dvb/dvb.cpp
+++ b/lib/dvb/dvb.cpp
@@ -96,6 +96,8 @@ eDVBResourceManager::eDVBResourceManager()
m_boxtype = DM800;
else if (!strncmp(tmp, "dm500hd\n", rd))
m_boxtype = DM500HD;
+ else if (!strncmp(tmp, "dm800se\n", rd))
+ m_boxtype = DM800SE;
else {
eDebug("boxtype detection via /proc/stb/info not possible... use fallback via demux count!\n");
if (m_demux.size() == 3)
@@ -318,27 +320,34 @@ PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
return NULL;
}
- if ((unsigned int)PyList_Size(list) != m_frontend.size())
+ unsigned int assigned=0;
+ for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
{
+ int pos=0;
+ while (pos < PyList_Size(list)) {
+ ePyObject obj = PyList_GET_ITEM(list, pos++);
+ if (!i->m_frontend->setSlotInfo(obj))
+ continue;
+ ++assigned;
+ break;
+ }
+ }
+ if (assigned != m_frontend.size()) {
char blasel[256];
- sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations list size incorrect %d frontends avail, but %d entries in slotlist",
- m_frontend.size(), PyList_Size(list));
+ sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %d socket informations, but %d registered frontends!",
+ m_frontend.size(), assigned);
PyErr_SetString(PyExc_StandardError, blasel);
return NULL;
}
- int pos=0;
- for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
- {
- ePyObject obj = PyList_GET_ITEM(list, pos++);
- if (!i->m_frontend->setSlotInfo(obj))
- return NULL;
- }
- pos=0;
for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
{
- ePyObject obj = PyList_GET_ITEM(list, pos++);
- if (!i->m_frontend->setSlotInfo(obj))
- return NULL;
+ int pos=0;
+ while (pos < PyList_Size(list)) {
+ ePyObject obj = PyList_GET_ITEM(list, pos++);
+ if (!i->m_frontend->setSlotInfo(obj))
+ continue;
+ break;
+ }
}
Py_RETURN_NONE;
}
@@ -455,7 +464,7 @@ RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBA
ePtr<eDVBRegisteredDemux> unused;
- if (m_boxtype == DM800 || m_boxtype == DM500HD) // dm800 / 500hd
+ if (m_boxtype == DM800 || m_boxtype == DM500HD || m_boxtype == DM800SE) // dm800 / 500hd
{
cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
for (; i != m_demux.end(); ++i, ++n)
@@ -1657,6 +1666,18 @@ void eDVBChannel::SDTready(int result)
m_SDT = 0;
}
+int eDVBChannel::reserveDemux()
+{
+ ePtr<iDVBDemux> dmx;
+ if (!getDemux(dmx, 0))
+ {
+ uint8_t id;
+ if (!dmx->getCADemuxID(id))
+ return id;
+ }
+ return -1;
+}
+
RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
{
if (PyCallable_Check(callback))
diff --git a/lib/dvb/dvb.h b/lib/dvb/dvb.h
index 7b320006..fb925807 100644
--- a/lib/dvb/dvb.h
+++ b/lib/dvb/dvb.h
@@ -135,7 +135,7 @@ class eDVBResourceManager: public iObject, public Object
DECLARE_REF(eDVBResourceManager);
int avail, busy;
- enum { DM7025, DM800, DM500HD, DM8000 };
+ enum { DM7025, DM800, DM500HD, DM800SE, DM8000 };
int m_boxtype;
@@ -268,6 +268,7 @@ public:
int getUseCount() { return m_use_count; }
RESULT requestTsidOnid(ePyObject callback);
+ int reserveDemux();
private:
ePtr<eDVBAllocatedFrontend> m_frontend;
ePtr<eDVBAllocatedDemux> m_demux, m_decoder_demux;
diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp
index 119223a3..8ac0c718 100644
--- a/lib/dvb/epgcache.cpp
+++ b/lib/dvb/epgcache.cpp
@@ -213,9 +213,9 @@ pthread_mutex_t eEPGCache::channel_map_lock=
DEFINE_REF(eEPGCache)
eEPGCache::eEPGCache()
- :messages(this,1), cleanTimer(eTimer::create(this))//, paused(0)
+ :messages(this,1), cleanTimer(eTimer::create(this)), m_running(0)//, paused(0)
{
- eDebug("[EPGC] Initialized EPGCache");
+ eDebug("[EPGC] Initialized EPGCache (wait for setCacheFile call now)");
CONNECT(messages.recv_msg, eEPGCache::gotMessage);
CONNECT(eDVBLocalTimeHandler::getInstance()->m_timeUpdated, eEPGCache::timeUpdated);
@@ -226,22 +226,46 @@ eEPGCache::eEPGCache()
if (!res_mgr)
eDebug("[eEPGCache] no resource manager !!!!!!!");
else
- {
res_mgr->connectChannelAdded(slot(*this,&eEPGCache::DVBChannelAdded), m_chanAddedConn);
+
+ instance=this;
+ memset(m_filename, 0, sizeof(m_filename));
+}
+
+void eEPGCache::setCacheFile(const char *path)
+{
+ bool inited = !!strlen(m_filename);
+ strncpy(m_filename, path, 1024);
+ if (!inited)
+ {
+ eDebug("[EPGC] setCacheFile read/write epg data from/to '%s'", m_filename);
if (eDVBLocalTimeHandler::getInstance()->ready())
timeUpdated();
}
- instance=this;
}
void eEPGCache::timeUpdated()
{
- if (!sync())
+ if (strlen(m_filename))
{
- eDebug("[EPGC] time updated.. start EPG Mainloop");
- run();
- } else
- messages.send(Message(Message::timeChanged));
+ if (!sync())
+ {
+ eDebug("[EPGC] time updated.. start EPG Mainloop");
+ run();
+ singleLock s(channel_map_lock);
+ channelMapIterator it = m_knownChannels.begin();
+ for (; it != m_knownChannels.end(); ++it)
+ {
+ if (it->second->state == -1) {
+ it->second->state=0;
+ messages.send(Message(Message::startChannel, it->second));
+ }
+ }
+ } else
+ messages.send(Message(Message::timeChanged));
+ }
+ else
+ eDebug("[EPGC] time updated.. but cache file not set yet.. dont start epg!!");
}
void eEPGCache::DVBChannelAdded(eDVBChannel *chan)
@@ -337,8 +361,11 @@ void eEPGCache::DVBChannelRunning(iDVBChannel *chan)
return;
}
#endif
- messages.send(Message(Message::startChannel, chan));
- // -> gotMessage -> changedService
+ if (m_running) {
+ data.state=0;
+ messages.send(Message(Message::startChannel, chan));
+ // -> gotMessage -> changedService
+ }
}
}
}
@@ -365,7 +392,8 @@ void eEPGCache::DVBChannelStateChanged(iDVBChannel *chan)
case iDVBChannel::state_release:
{
eDebug("[eEPGCache] remove channel %p", chan);
- messages.send(Message(Message::leaveChannel, chan));
+ if (it->second->state >= 0)
+ messages.send(Message(Message::leaveChannel, chan));
pthread_mutex_lock(&it->second->channel_active);
singleLock s(channel_map_lock);
m_knownChannels.erase(it);
@@ -953,39 +981,24 @@ void eEPGCache::gotMessage( const Message &msg )
void eEPGCache::thread()
{
hasStarted();
+ m_running=1;
nice(4);
load();
cleanLoop();
runLoop();
save();
+ m_running=0;
}
void eEPGCache::load()
{
- FILE *f = fopen("/hdd/epg.dat", "r");
+ FILE *f = fopen(m_filename, "r");
if (f)
{
- unlink("/hdd/epg.dat");
+ unlink(m_filename);
int size=0;
int cnt=0;
-#if 0
- unsigned char md5_saved[16];
- unsigned char md5[16];
- bool md5ok=false;
- if (!md5_file("/hdd/epg.dat", 1, md5))
- {
- FILE *f = fopen("/hdd/epg.dat.md5", "r");
- if (f)
- {
- fread( md5_saved, 16, 1, f);
- fclose(f);
- if ( !memcmp(md5_saved, md5, 16) )
- md5ok=true;
- }
- }
- if ( md5ok )
-#endif
{
unsigned int magic=0;
fread( &magic, sizeof(int), 1, f);
@@ -1027,7 +1040,7 @@ void eEPGCache::load()
eventDB[key]=std::pair<eventMap,timeMap>(evMap,tmMap);
}
eventData::load(f);
- eDebug("[EPGC] %d events read from /hdd/epg.dat", cnt);
+ eDebug("[EPGC] %d events read from %s", cnt, m_filename);
#ifdef ENABLE_PRIVATE_EPG
char text2[11];
fread( text2, 11, 1, f);
@@ -1075,103 +1088,106 @@ void eEPGCache::load()
void eEPGCache::save()
{
- struct statfs s;
- off64_t tmp;
- if (statfs("/hdd", &s)<0)
- tmp=0;
- else
+ /* create empty file */
+ FILE *f = fopen(m_filename, "w");
+
+ if (!f)
+ {
+ eDebug("[EPGC] couldn't save epg data to '%s'(%m)", m_filename);
+ return;
+ }
+
+ char *buf = realpath(m_filename, NULL);
+ if (!buf)
{
- tmp=s.f_blocks;
- tmp*=s.f_bsize;
+ eDebug("[EPGC] realpath to '%s' failed in save (%m)", m_filename);
+ fclose(f);
+ return;
}
- // prevent writes to builtin flash
- if ( tmp < 1024*1024*50 ) // storage size < 50MB
+ eDebug("[EPGC] store epg to realpath '%s'", buf);
+
+ struct statfs s;
+ off64_t tmp;
+ if (statfs(buf, &s) < 0) {
+ eDebug("[EPGC] statfs '%s' failed in save (%m)", buf);
+ fclose(f);
return;
+ }
+
+ free(buf);
// check for enough free space on storage
tmp=s.f_bfree;
tmp*=s.f_bsize;
if ( tmp < (eventData::CacheSize*12)/10 ) // 20% overhead
+ {
+ eDebug("[EPGC] not enough free space at path '%s' %lld bytes availd but %d needed", buf, tmp, (eventData::CacheSize*12)/10);
+ fclose(f);
return;
+ }
- FILE *f = fopen("/hdd/epg.dat", "w");
int cnt=0;
- if ( f )
- {
- unsigned int magic = 0x98765432;
- fwrite( &magic, sizeof(int), 1, f);
- const char *text = "UNFINISHED_V7";
- fwrite( text, 13, 1, f );
- int size = eventDB.size();
- fwrite( &size, sizeof(int), 1, f );
- for (eventCache::iterator service_it(eventDB.begin()); service_it != eventDB.end(); ++service_it)
- {
- timeMap &timemap = service_it->second.second;
- fwrite( &service_it->first, sizeof(uniqueEPGKey), 1, f);
- size = timemap.size();
- fwrite( &size, sizeof(int), 1, f);
- for (timeMap::iterator time_it(timemap.begin()); time_it != timemap.end(); ++time_it)
- {
- __u8 len = time_it->second->ByteSize;
- fwrite( &time_it->second->type, sizeof(__u8), 1, f );
- fwrite( &len, sizeof(__u8), 1, f);
- fwrite( time_it->second->EITdata, len, 1, f);
- ++cnt;
- }
+ unsigned int magic = 0x98765432;
+ fwrite( &magic, sizeof(int), 1, f);
+ const char *text = "UNFINISHED_V7";
+ fwrite( text, 13, 1, f );
+ int size = eventDB.size();
+ fwrite( &size, sizeof(int), 1, f );
+ for (eventCache::iterator service_it(eventDB.begin()); service_it != eventDB.end(); ++service_it)
+ {
+ timeMap &timemap = service_it->second.second;
+ fwrite( &service_it->first, sizeof(uniqueEPGKey), 1, f);
+ size = timemap.size();
+ fwrite( &size, sizeof(int), 1, f);
+ for (timeMap::iterator time_it(timemap.begin()); time_it != timemap.end(); ++time_it)
+ {
+ __u8 len = time_it->second->ByteSize;
+ fwrite( &time_it->second->type, sizeof(__u8), 1, f );
+ fwrite( &len, sizeof(__u8), 1, f);
+ fwrite( time_it->second->EITdata, len, 1, f);
+ ++cnt;
}
- eDebug("[EPGC] %d events written to /hdd/epg.dat", cnt);
- eventData::save(f);
+ }
+ eDebug("[EPGC] %d events written to %s", cnt, m_filename);
+ eventData::save(f);
#ifdef ENABLE_PRIVATE_EPG
- const char* text3 = "PRIVATE_EPG";
- fwrite( text3, 11, 1, f );
- size = content_time_tables.size();
+ const char* text3 = "PRIVATE_EPG";
+ fwrite( text3, 11, 1, f );
+ size = content_time_tables.size();
+ fwrite( &size, sizeof(int), 1, f);
+ for (contentMaps::iterator a = content_time_tables.begin(); a != content_time_tables.end(); ++a)
+ {
+ contentMap &content_time_table = a->second;
+ fwrite( &a->first, sizeof(uniqueEPGKey), 1, f);
+ int size = content_time_table.size();
fwrite( &size, sizeof(int), 1, f);
- for (contentMaps::iterator a = content_time_tables.begin(); a != content_time_tables.end(); ++a)
+ for (contentMap::iterator i = content_time_table.begin(); i != content_time_table.end(); ++i )
{
- contentMap &content_time_table = a->second;
- fwrite( &a->first, sizeof(uniqueEPGKey), 1, f);
- int size = content_time_table.size();
+ int size = i->second.size();
+ fwrite( &i->first, sizeof(int), 1, f);
fwrite( &size, sizeof(int), 1, f);
- for (contentMap::iterator i = content_time_table.begin(); i != content_time_table.end(); ++i )
- {
- int size = i->second.size();
- fwrite( &i->first, sizeof(int), 1, f);
- fwrite( &size, sizeof(int), 1, f);
- for ( contentTimeMap::iterator it(i->second.begin());
- it != i->second.end(); ++it )
- {
- fwrite( &it->first, sizeof(time_t), 1, f);
- fwrite( &it->second.first, sizeof(time_t), 1, f);
- fwrite( &it->second.second, sizeof(__u16), 1, f);
- }
- }
- }
-#endif
- // write version string after binary data
- // has been written to disk.
- fsync(fileno(f));
- fseek(f, sizeof(int), SEEK_SET);
- fwrite("ENIGMA_EPG_V7", 13, 1, f);
- fclose(f);
-#if 0
- unsigned char md5[16];
- if (!md5_file("/hdd/epg.dat", 1, md5))
- {
- FILE *f = fopen("/hdd/epg.dat.md5", "w");
- if (f)
+ for ( contentTimeMap::iterator it(i->second.begin());
+ it != i->second.end(); ++it )
{
- fwrite( md5, 16, 1, f);
- fclose(f);
+ fwrite( &it->first, sizeof(time_t), 1, f);
+ fwrite( &it->second.first, sizeof(time_t), 1, f);
+ fwrite( &it->second.second, sizeof(__u16), 1, f);
}
}
-#endif
}
+#endif
+ // write version string after binary data
+ // has been written to disk.
+ fsync(fileno(f));
+ fseek(f, sizeof(int), SEEK_SET);
+ fwrite("ENIGMA_EPG_V7", 13, 1, f);
+ fclose(f);
}
eEPGCache::channel_data::channel_data(eEPGCache *ml)
:cache(ml)
- ,abortTimer(eTimer::create(ml)), zapTimer(eTimer::create(ml)), state(0)
+ ,abortTimer(eTimer::create(ml)), zapTimer(eTimer::create(ml)), state(-1)
,isRunning(0), haveData(0)
#ifdef ENABLE_PRIVATE_EPG
,startPrivateTimer(eTimer::create(ml))
diff --git a/lib/dvb/epgcache.h b/lib/dvb/epgcache.h
index 4d45d87e..90aff6c6 100644
--- a/lib/dvb/epgcache.h
+++ b/lib/dvb/epgcache.h
@@ -177,7 +177,8 @@ class eEPGCache: public eMainloop, private eThread, public Object
eEPGCache *cache;
ePtr<eTimer> abortTimer, zapTimer;
int prevChannelState;
- __u8 state, isRunning, haveData;
+ int state;
+ __u8 isRunning, haveData;
ePtr<eDVBChannel> channel;
ePtr<eConnection> m_stateChangedConn, m_NowNextConn, m_ScheduleConn, m_ScheduleOtherConn, m_ViasatConn;
ePtr<iDVBSectionReader> m_NowNextReader, m_ScheduleReader, m_ScheduleOtherReader, m_ViasatReader;
@@ -290,6 +291,8 @@ private:
void thread(); // thread function
// called from epgcache thread
+ int m_running;
+ char m_filename[1024];
void save();
void load();
#ifdef ENABLE_PRIVATE_EPG
@@ -325,6 +328,9 @@ public:
#endif
#endif
+ // must be called once!
+ void setCacheFile(const char *filename);
+
// called from main thread
inline void Lock();
inline void Unlock();
diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp
index bd8f0028..ebdad8a7 100644
--- a/lib/dvb/frontend.cpp
+++ b/lib/dvb/frontend.cpp
@@ -813,7 +813,7 @@ int eDVBFrontend::readFrontendData(int type)
float fval1 = SDS_SNRE / 268435456.0,
fval2, fval3, fval4;
- if (parm_u_qpsk_fec_inner <= FEC_S2_QPSK_9_10) // DVB-S2 QPSK
+ if (oparm.sat.modulation == eDVBFrontendParametersSatellite::Modulation_QPSK)
{
fval2 = 6.76;
fval3 = 4.35;
@@ -906,6 +906,19 @@ int eDVBFrontend::readFrontendData(int type)
}
else if (strstr(m_description, "BCM4506") || strstr(m_description, "BCM4505"))
ret = (snr * 100) >> 8;
+ else if (!strcmp(m_description, "CXD1981"))
+ {
+ int mse = (~snr) & 0xFF;
+ switch (parm_u_qam_modulation) {
+ case QAM_16:
+ case QAM_64:
+ case QAM_256: ret = (int)(-950 * log(((double)mse) / 760)); break;
+ case QAM_32:
+ case QAM_128: ret = (int)(-875 * log(((double)mse) / 650)); break;
+
+ default: break;
+ }
+ }
if (type == signalQuality)
{
@@ -1076,6 +1089,7 @@ static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &
case FEC_AUTO: tmp = eDVBFrontendParametersSatellite::FEC_Auto; break;
default: eDebug("got unsupported FEC from frontend! report as FEC_AUTO!\n");
}
+ PutToDict(dict, "fec_inner", tmp);
switch (p[0].u.data)
{
@@ -1124,7 +1138,7 @@ static void fillDictWithSatelliteData(ePyObject dict, const FRONTENDPARAMETERS &
PutToDict(dict, "orbital_position", orb_pos);
PutToDict(dict, "polarization", polarization);
- switch(parm_u_qpsk_fec_inner)
+ switch((int)parm_u_qpsk_fec_inner)
{
case FEC_1_2: tmp = eDVBFrontendParametersSatellite::FEC_1_2; break;
case FEC_2_3: tmp = eDVBFrontendParametersSatellite::FEC_2_3; break;
@@ -1458,9 +1472,11 @@ int eDVBFrontend::readInputpower()
return 0;
int power=m_slotid; // this is needed for read inputpower from the correct tuner !
char proc_name[64];
- sprintf(proc_name, "/proc/stb/fp/lnb_sense%d", m_slotid);
- FILE *f=fopen(proc_name, "r");
- if (f)
+ char proc_name2[64];
+ sprintf(proc_name, "/proc/stb/frontend/%d/lnb_sense", m_slotid);
+ sprintf(proc_name2, "/proc/stb/fp/lnb_sense%d", m_slotid);
+ FILE *f;
+ if ((f=fopen(proc_name, "r")) || (f=fopen(proc_name2, "r")))
{
if (fscanf(f, "%d", &power) != 1)
eDebug("read %s failed!! (%m)", proc_name);
@@ -2684,17 +2700,23 @@ int eDVBFrontend::isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm)
bool eDVBFrontend::setSlotInfo(ePyObject obj)
{
- ePyObject Id, Descr, Enabled, IsDVBS2;
- if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 4)
+ ePyObject Id, Descr, Enabled, IsDVBS2, frontendId;
+ if (!PyTuple_Check(obj) || PyTuple_Size(obj) != 5)
goto arg_error;
Id = PyTuple_GET_ITEM(obj, 0);
Descr = PyTuple_GET_ITEM(obj, 1);
Enabled = PyTuple_GET_ITEM(obj, 2);
IsDVBS2 = PyTuple_GET_ITEM(obj, 3);
- if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2))
+ frontendId = PyTuple_GET_ITEM(obj, 4);
+ m_slotid = PyInt_AsLong(Id);
+ if (!PyInt_Check(Id) || !PyString_Check(Descr) || !PyBool_Check(Enabled) || !PyBool_Check(IsDVBS2) || !PyInt_Check(frontendId))
goto arg_error;
strcpy(m_description, PyString_AS_STRING(Descr));
- m_slotid = PyInt_AsLong(Id);
+ if (PyInt_AsLong(frontendId) == -1 || PyInt_AsLong(frontendId) != m_dvbid) {
+// eDebugNoSimulate("skip slotinfo for slotid %d, descr %s",
+// m_slotid, m_description);
+ return false;
+ }
m_enabled = Enabled == Py_True;
// HACK.. the rotor workaround is neede for all NIMs with LNBP21 voltage regulator...
m_need_rotor_workaround = !!strstr(m_description, "Alps BSBE1") ||
diff --git a/lib/dvb/idemux.h b/lib/dvb/idemux.h
index e92b1e75..86b35fdb 100644
--- a/lib/dvb/idemux.h
+++ b/lib/dvb/idemux.h
@@ -6,6 +6,7 @@
class iDVBSectionReader: public iObject
{
public:
+ virtual RESULT setBufferSize(int size)=0;
virtual RESULT start(const eDVBSectionFilterMask &mask)=0;
virtual RESULT stop()=0;
virtual RESULT connectRead(const Slot1<void,const __u8*> &read, ePtr<eConnection> &conn)=0;
@@ -15,6 +16,7 @@ public:
class iDVBPESReader: public iObject
{
public:
+ virtual RESULT setBufferSize(int size)=0;
virtual RESULT start(int pid)=0;
virtual RESULT stop()=0;
virtual RESULT connectRead(const Slot2<void,const __u8*, int> &read, ePtr<eConnection> &conn)=0;
@@ -26,6 +28,7 @@ public:
class iDVBTSRecorder: public iObject
{
public:
+ virtual RESULT setBufferSize(int size) = 0;
virtual RESULT start() = 0;
virtual RESULT addPID(int pid) = 0;
virtual RESULT removePID(int pid) = 0;
diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h
index d00d1fc8..f1217a6a 100644
--- a/lib/dvb/idvb.h
+++ b/lib/dvb/idvb.h
@@ -509,6 +509,7 @@ public:
/* direct frontend access for raw channels and/or status inquiries. */
virtual SWIG_VOID(RESULT) getFrontend(ePtr<iDVBFrontend> &SWIG_OUTPUT)=0;
virtual RESULT requestTsidOnid(SWIG_PYOBJECT(ePyObject) callback) { return -1; }
+ virtual int reserveDemux() { return -1; }
#ifndef SWIG
enum
{
diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp
index ee89a3a4..ea4b96c5 100644
--- a/lib/dvb/pmt.cpp
+++ b/lib/dvb/pmt.cpp
@@ -133,11 +133,11 @@ void eDVBServicePMTHandler::PATready(int)
{
int pmtpid = -1;
std::vector<ProgramAssociationSection*>::const_iterator i;
- for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i)
+ for (i = ptr->getSections().begin(); pmtpid == -1 && i != ptr->getSections().end(); ++i)
{
const ProgramAssociationSection &pat = **i;
ProgramAssociationConstIterator program;
- for (program = pat.getPrograms()->begin(); program != pat.getPrograms()->end(); ++program)
+ for (program = pat.getPrograms()->begin(); pmtpid == -1 && program != pat.getPrograms()->end(); ++program)
if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID())
pmtpid = (*program)->getProgramMapPid();
}
diff --git a/lib/dvb/sec.cpp b/lib/dvb/sec.cpp
index 9ca0f734..a2bc8869 100644
--- a/lib/dvb/sec.cpp
+++ b/lib/dvb/sec.cpp
@@ -548,6 +548,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
if ( send_mask )
{
+ int diseqc_repeats = diseqc_mode > eDVBSatelliteDiseqcParameters::V1_0 ? di_param.m_repeats : 0;
int vlt = iDVBFrontend::voltageOff;
eSecCommand::pair compare;
compare.steps = +3;
@@ -620,7 +621,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
if ( send_mask & 2 )
++loops;
- loops <<= di_param.m_repeats;
+ loops <<= diseqc_repeats;
for ( int i = 0; i < loops;) // fill commands...
{
@@ -657,7 +658,7 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
int tmp = m_params[DELAY_BETWEEN_DISEQC_REPEATS];
if (cmd)
{
- int delay = di_param.m_repeats ? (tmp - 54) / 2 : tmp; // standard says 100msek between two repeated commands
+ int delay = diseqc_repeats ? (tmp - 54) / 2 : tmp; // standard says 100msek between two repeated commands
sec_sequence.push_back( eSecCommand(eSecCommand::SLEEP, delay) );
diseqc.data[2]=cmd;
diseqc.data[3]=(cmd==0x38) ? csw : ucsw;
@@ -1001,19 +1002,6 @@ RESULT eDVBSatelliteEquipmentControl::clear()
//reset some tuner configuration
for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
{
- long tmp;
- char c;
- if (sscanf(it->m_frontend->getDescription(), "BCM450%c (internal)", &c) == 1 && !it->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp) && tmp != -1)
- {
- FILE *f=fopen("/proc/stb/tsmux/lnb_b_input", "w");
- if (!f || fwrite("B", 1, 1, f) != 1)
- eDebug("set /proc/stb/tsmux/lnb_b_input to B failed!! (%m)");
- else
- {
- eDebug("set /proc/stb/tsmux/lnb_b_input to B OK");
- fclose(f);
- }
- }
it->m_frontend->setData(eDVBFrontend::SATPOS_DEPENDS_PTR, -1);
it->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, -1);
it->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, -1);
@@ -1445,17 +1433,6 @@ RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
char c;
p1->m_frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)p2);
p2->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)p1);
- if (!strcmp(p1->m_frontend->getDescription(), p2->m_frontend->getDescription()) && sscanf(p1->m_frontend->getDescription(), "BCM450%c (internal)", &c) == 1)
- {
- FILE *f=fopen("/proc/stb/tsmux/lnb_b_input", "w");
- if (!f || fwrite("A", 1, 1, f) != 1)
- eDebug("set /proc/stb/tsmux/lnb_b_input to A failed!! (%m)");
- else
- {
- eDebug("set /proc/stb/tsmux/lnb_b_input to A OK");
- fclose(f);
- }
- }
}
p1=p2=NULL;
diff --git a/lib/gdi/font.cpp b/lib/gdi/font.cpp
index b7d3c1db..a5db43a9 100644
--- a/lib/gdi/font.cpp
+++ b/lib/gdi/font.cpp
@@ -6,6 +6,11 @@
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
+#include <byteswap.h>
+
+#ifndef BYTE_ORDER
+#error "no BYTE_ORDER defined!"
+#endif
// use this for init Freetype...
#include <ft2build.h>
@@ -341,6 +346,8 @@ int eTextPara::appendGlyph(Font *current_font, FT_Face current_face, FT_UInt gly
i->x-=offset.x();
i->y-=offset.y();
i->bbox.moveBy(-offset.x(), -offset.y());
+ --lineChars.back();
+ ++charCount;
} while (i-- != glyphs.rbegin()); // rearrange them into the next line
cursor+=ePoint(linelength, 0); // put the cursor after that line
} else
@@ -378,6 +385,7 @@ int eTextPara::appendGlyph(Font *current_font, FT_Face current_face, FT_UInt gly
ng.glyph_index = glyphIndex;
ng.flags = flags;
glyphs.push_back(ng);
+ ++charCount;
/* when we have a SHY, don't xadvance. It will either be the last in the line (when used for breaking), or not displayed. */
if (!(flags & GS_SOFTHYPHEN))
@@ -425,7 +433,13 @@ void eTextPara::newLine(int flags)
cursor.setX(left);
previous=0;
int linegap=current_face->size->metrics.height-(current_face->size->metrics.ascender+current_face->size->metrics.descender);
+
+ lineOffsets.push_back(cursor.y());
+ lineChars.push_back(charCount);
+ charCount=0;
+
cursor+=ePoint(0, (current_face->size->metrics.ascender+current_face->size->metrics.descender+linegap)>>6);
+
if (maximum.height()<cursor.y())
maximum.setHeight(cursor.y());
previous=0;
@@ -595,22 +609,20 @@ int eTextPara::renderString(const char *string, int rflags)
shape(uc_shape, uc_string);
// now do the usual logical->visual reordering
-#ifdef HAVE_FRIBIDI
+ int size=uc_shape.size();
+#ifdef HAVE_FRIBIDI
FriBidiCharType dir=FRIBIDI_TYPE_ON;
- {
- int size=uc_shape.size();
- uc_visual.resize(size);
- // gaaanz lahm, aber anders geht das leider nicht, sorry.
- FriBidiChar array[size], target[size];
- std::copy(uc_shape.begin(), uc_shape.end(), array);
- fribidi_log2vis(array, size, &dir, target, 0, 0, 0);
- uc_visual.assign(target, target+size);
- }
+ uc_visual.resize(size);
+ // gaaanz lahm, aber anders geht das leider nicht, sorry.
+ FriBidiChar array[size], target[size];
+ std::copy(uc_shape.begin(), uc_shape.end(), array);
+ fribidi_log2vis(array, size, &dir, target, 0, 0, 0);
+ uc_visual.assign(target, target+size);
#else
uc_visual=uc_shape;
#endif
- glyphs.reserve(uc_visual.size());
+ glyphs.reserve(size);
int nextflags = 0;
@@ -704,8 +716,19 @@ nprint: isprintable=0;
calc_bbox();
#ifdef HAVE_FRIBIDI
if (dir & FRIBIDI_MASK_RTL)
+ {
realign(dirRight);
+ doTopBottomReordering=true;
+ }
#endif
+
+ if (charCount)
+ {
+ lineOffsets.push_back(cursor.y());
+ lineChars.push_back(charCount);
+ charCount=0;
+ }
+
return 0;
}
@@ -748,8 +771,9 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
gColor *lookup8, lookup8_invert[16];
gColor *lookup8_normal=0;
+ __u16 lookup16_normal[16], lookup16_invert[16], *lookup16;
__u32 lookup32_normal[16], lookup32_invert[16], *lookup32;
-
+
if (surface->bpp == 8)
{
if (surface->clut.data)
@@ -763,10 +787,33 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
opcode=0;
} else
opcode=1;
+ } else if (surface->bpp == 16)
+ {
+ opcode=2;
+ for (int i=0; i<16; ++i)
+ {
+#define BLEND(y, x, a) (y + (((x-y) * a)>>8))
+ unsigned char da = background.a, dr = background.r, dg = background.g, db = background.b;
+ int sa = i * 16;
+ if (sa < 256)
+ {
+ dr = BLEND(background.r, foreground.r, sa) & 0xFF;
+ dg = BLEND(background.g, foreground.g, sa) & 0xFF;
+ db = BLEND(background.b, foreground.b, sa) & 0xFF;
+ }
+#undef BLEND
+#if BYTE_ORDER == LITTLE_ENDIAN
+ lookup16_normal[i] = bswap_16(((db >> 3) << 11) | ((dg >> 2) << 5) | (dr >> 3));
+#else
+ lookup16_normal[i] = ((db >> 3) << 11) | ((dg >> 2) << 5) | (dr >> 3);
+#endif
+ da ^= 0xFF;
+ }
+ for (int i=0; i<16; ++i)
+ lookup16_invert[i]=lookup16_normal[i^0xF];
} else if (surface->bpp == 32)
{
opcode=3;
-
for (int i=0; i<16; ++i)
{
#define BLEND(y, x, a) (y + (((x-y) * a)>>8))
@@ -791,35 +838,47 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
eWarning("can't render to %dbpp", surface->bpp);
return;
}
-
+
gRegion area(eRect(0, 0, surface->x, surface->y));
gRegion clip = dc.getClip() & area;
int buffer_stride=surface->stride;
-
+
for (unsigned int c = 0; c < clip.rects.size(); ++c)
{
- for (glyphString::iterator i(glyphs.begin()); i != glyphs.end(); ++i)
+ std::list<int>::reverse_iterator line_offs_it(lineOffsets.rbegin());
+ std::list<int>::iterator line_chars_it(lineChars.begin());
+ int line_offs=0;
+ int line_chars=0;
+ for (glyphString::iterator i(glyphs.begin()); i != glyphs.end(); ++i, --line_chars)
{
+ while(!line_chars)
+ {
+ line_offs = *(line_offs_it++);
+ line_chars = *(line_chars_it++);
+ }
+
if (i->flags & GS_SOFTHYPHEN)
continue;
if (!(i->flags & GS_INVERT))
{
lookup8 = lookup8_normal;
+ lookup16 = lookup16_normal;
lookup32 = lookup32_normal;
} else
{
lookup8 = lookup8_invert;
+ lookup16 = lookup16_invert;
lookup32 = lookup32_invert;
}
-
+
static FTC_SBit glyph_bitmap;
if (fontRenderClass::instance->getGlyphBitmap(&i->font->font, i->glyph_index, &glyph_bitmap))
continue;
int rx=i->x+glyph_bitmap->left + offset.x();
- int ry=i->y-glyph_bitmap->top + offset.y();
-
+ int ry=(doTopBottomReordering ? line_offs : i->y) - glyph_bitmap->top + offset.y();
+
__u8 *d=(__u8*)(surface->data)+buffer_stride*ry+rx*surface->bypp;
__u8 *s=glyph_bitmap->buffer;
register int sx=glyph_bitmap->width;
@@ -845,46 +904,76 @@ void eTextPara::blit(gDC &dc, const ePoint &offset, const gRGB &background, cons
d+=diff*buffer_stride;
}
if (sx>0)
- for (int ay=0; ay<sy; ay++)
- {
- if (!opcode) // 4bit lookup to 8bit
+ {
+ switch(opcode) {
+ case 0: // 4bit lookup to 8bit
+ for (int ay=0; ay<sy; ay++)
{
register __u8 *td=d;
register int ax;
-
for (ax=0; ax<sx; ax++)
- {
+ {
register int b=(*s++)>>4;
if(b)
*td++=lookup8[b];
else
td++;
}
- } else if (opcode == 1) // 8bit direct
+ s+=glyph_bitmap->pitch-sx;
+ d+=buffer_stride;
+ }
+ break;
+ case 1: // 8bit direct
+ for (int ay=0; ay<sy; ay++)
{
register __u8 *td=d;
register int ax;
for (ax=0; ax<sx; ax++)
- {
+ {
register int b=*s++;
*td++^=b;
}
- } else
+ s+=glyph_bitmap->pitch-sx;
+ d+=buffer_stride;
+ }
+ break;
+ case 2: // 16bit
+ for (int ay=0; ay<sy; ay++)
+ {
+ register __u16 *td=(__u16*)d;
+ register int ax;
+ for (ax=0; ax<sx; ax++)
+ {
+ register int b=(*s++)>>4;
+ if(b)
+ *td++=lookup16[b];
+ else
+ td++;
+ }
+ s+=glyph_bitmap->pitch-sx;
+ d+=buffer_stride;
+ }
+ break;
+ case 3: // 32bit
+ for (int ay=0; ay<sy; ay++)
{
register __u32 *td=(__u32*)d;
register int ax;
for (ax=0; ax<sx; ax++)
- {
+ {
register int b=(*s++)>>4;
if(b)
*td++=lookup32[b];
else
td++;
}
+ s+=glyph_bitmap->pitch-sx;
+ d+=buffer_stride;
}
- s+=glyph_bitmap->pitch-sx;
- d+=buffer_stride;
+ default:
+ break;
}
+ }
}
}
}
diff --git a/lib/gdi/font.h b/lib/gdi/font.h
index 2643fda2..7dd9f89a 100644
--- a/lib/gdi/font.h
+++ b/lib/gdi/font.h
@@ -14,6 +14,7 @@ typedef FTC_ImageTypeRec FTC_Image_Desc;
typedef FTC_SBitCache FTC_SBit_Cache;
#endif
#include <vector>
+#include <list>
#include <lib/gdi/fb.h>
#include <lib/gdi/esize.h>
@@ -113,6 +114,10 @@ class eTextPara: public iObject
eSize maximum;
int left;
glyphString glyphs;
+ std::list<int> lineOffsets;
+ std::list<int> lineChars;
+ int charCount;
+ bool doTopBottomReordering;
int appendGlyph(Font *current_font, FT_Face current_face, FT_UInt glyphIndex, int flags, int rflags);
void newLine(int flags);
@@ -120,10 +125,12 @@ class eTextPara: public iObject
eRect boundBox;
void calc_bbox();
int bboxValid;
+ void clear();
public:
eTextPara(eRect area, ePoint start=ePoint(-1, -1))
- : current_font(0), replacement_font(0), current_face(0), replacement_face(0),
- area(area), cursor(start), maximum(0, 0), left(start.x()), bboxValid(0)
+ :current_font(0), replacement_font(0), current_face(0), replacement_face(0)
+ ,area(area), cursor(start), maximum(0, 0), left(start.x()), charCount(0)
+ ,doTopBottomReordering(false), bboxValid(0)
{
}
virtual ~eTextPara();
@@ -134,7 +141,7 @@ public:
void setFont(const gFont *font);
int renderString(const char *string, int flags=0);
- void clear();
+
void blit(gDC &dc, const ePoint &offset, const gRGB &background, const gRGB &foreground);
diff --git a/lib/gdi/glcddc.cpp b/lib/gdi/glcddc.cpp
index 8612c70b..a593cfa3 100644
--- a/lib/gdi/glcddc.cpp
+++ b/lib/gdi/glcddc.cpp
@@ -14,13 +14,13 @@ gLCDDC::gLCDDC()
surface.x=lcd->size().width();
surface.y=lcd->size().height();
- surface.bpp=8;
- surface.bypp=1;
surface.stride=lcd->stride();
+ surface.bypp=surface.stride / surface.x;
+ surface.bpp=surface.bypp*8;
surface.data=lcd->buffer();
-
- surface.clut.colors=256;
+ surface.clut.colors=0;
surface.clut.data=0;
+
m_pixmap = new gPixmap(&surface);
}
diff --git a/lib/gdi/gpixmap.cpp b/lib/gdi/gpixmap.cpp
index 3e643108..0e8d39ec 100644
--- a/lib/gdi/gpixmap.cpp
+++ b/lib/gdi/gpixmap.cpp
@@ -3,6 +3,11 @@
#include <lib/gdi/gpixmap.h>
#include <lib/gdi/region.h>
#include <lib/gdi/accel.h>
+#include <byteswap.h>
+
+#ifndef BYTE_ORDER
+#error "no BYTE_ORDER defined!"
+#endif
gLookup::gLookup()
:size(0), lookup(0)
@@ -154,6 +159,26 @@ void gPixmap::fill(const gRegion &region, const gColor &color)
{
for (int y=area.top(); y<area.bottom(); y++)
memset(((__u8*)surface->data)+y*surface->stride+area.left(), color.color, area.width());
+ } else if (surface->bpp == 16)
+ {
+ __u32 icol;
+
+ if (surface->clut.data && color < surface->clut.colors)
+ icol=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
+ else
+ icol=0x10101*color;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ __u16 col = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
+#else
+ __u16 col = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
+#endif
+ for (int y=area.top(); y<area.bottom(); y++)
+ {
+ __u16 *dst=(__u16*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
+ int x=area.width();
+ while (x--)
+ *dst++=col;
+ }
} else if (surface->bpp == 32)
{
__u32 col;
@@ -208,18 +233,33 @@ void gPixmap::fill(const gRegion &region, const gRGB &color)
while (x--)
*dst++=col;
}
+ } else if (surface->bpp == 16)
+ {
+ __u32 icol = color.argb();
+#if BYTE_ORDER == LITTLE_ENDIAN
+ __u16 col = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
+#else
+ __u16 col = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
+#endif
+ for (int y=area.top(); y<area.bottom(); y++)
+ {
+ __u16 *dst=(__u16*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
+ int x=area.width();
+ while (x--)
+ *dst++=col;
+ }
} else
eWarning("couldn't rgbfill %d bpp", surface->bpp);
}
}
-static void blit_8i_to_32(__u32 *dst, __u8 *src, __u32 *pal, int width)
+static inline void blit_8i_to_32(__u32 *dst, __u8 *src, __u32 *pal, int width)
{
while (width--)
*dst++=pal[*src++];
}
-static void blit_8i_to_32_at(__u32 *dst, __u8 *src, __u32 *pal, int width)
+static inline void blit_8i_to_32_at(__u32 *dst, __u8 *src, __u32 *pal, int width)
{
while (width--)
{
@@ -232,6 +272,25 @@ static void blit_8i_to_32_at(__u32 *dst, __u8 *src, __u32 *pal, int width)
}
}
+static inline void blit_8i_to_16(__u16 *dst, __u8 *src, __u32 *pal, int width)
+{
+ while (width--)
+ *dst++=pal[*src++] & 0xFFFF;
+}
+
+static inline void blit_8i_to_16_at(__u16 *dst, __u8 *src, __u32 *pal, int width)
+{
+ while (width--)
+ {
+ if (!(pal[*src]&0x80000000))
+ {
+ src++;
+ dst++;
+ } else
+ *dst++=pal[*src++] & 0xFFFF;
+ }
+}
+
/* WARNING, this function is not endian safe! */
static void blit_8i_to_32_ab(__u32 *dst, __u8 *src, __u32 *pal, int width)
{
@@ -441,6 +500,95 @@ void gPixmap::blit(const gPixmap &src, const eRect &_pos, const gRegion &clip, i
srcptr+=src.surface->stride;
dstptr+=surface->stride;
}
+ } else if ((surface->bpp == 16) && (src.surface->bpp==8))
+ {
+ __u8 *srcptr=(__u8*)src.surface->data;
+ __u8 *dstptr=(__u8*)surface->data; // !!
+ __u32 pal[256];
+
+ for (int i=0; i<256; ++i)
+ {
+ __u32 icol;
+ if (src.surface->clut.data && (i<src.surface->clut.colors))
+ icol=(src.surface->clut.data[i].a<<24)|(src.surface->clut.data[i].r<<16)|(src.surface->clut.data[i].g<<8)|(src.surface->clut.data[i].b);
+ else
+ icol=0x010101*i;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ pal[i] = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
+#else
+ pal[i] = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
+#endif
+ pal[i]^=0xFF000000;
+ }
+
+ srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
+ dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
+
+ if (flag & blitAlphaBlend)
+ eWarning("ignore unsupported 8bpp -> 16bpp alphablend!");
+
+ for (int y=0; y<area.height(); y++)
+ {
+ int width=area.width();
+ unsigned char *psrc=(unsigned char*)srcptr;
+ __u16 *dst=(__u16*)dstptr;
+ if (flag & blitAlphaTest)
+ blit_8i_to_16_at(dst, psrc, pal, width);
+ else
+ blit_8i_to_16(dst, psrc, pal, width);
+ srcptr+=src.surface->stride;
+ dstptr+=surface->stride;
+ }
+ } else if ((surface->bpp == 16) && (src.surface->bpp==32))
+ {
+ __u8 *srcptr=(__u8*)src.surface->data;
+ __u8 *dstptr=(__u8*)surface->data;
+
+ srcptr+=srcarea.left()+srcarea.top()*src.surface->stride;
+ dstptr+=area.left()+area.top()*surface->stride;
+
+ if (flag & blitAlphaBlend)
+ eWarning("ignore unsupported 32bpp -> 16bpp alphablend!");
+
+ for (int y=0; y<area.height(); y++)
+ {
+ int width=area.width();
+ __u32 *srcp=(__u32*)srcptr;
+ __u16 *dstp=(__u16*)dstptr;
+
+ if (flag & blitAlphaTest)
+ {
+ while (width--)
+ {
+ if (!((*srcp)&0xFF000000))
+ {
+ srcp++;
+ dstp++;
+ } else
+ {
+ __u32 icol = *srcp++;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ *dstp++ = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
+#else
+ *dstp++ = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
+#endif
+ }
+ }
+ } else
+ {
+ while (width--)
+ {
+ __u32 icol = *srcp++;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ *dstp++ = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
+#else
+ *dstp++ = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
+#endif
+ }
+ }
+ srcptr+=src.surface->stride;
+ dstptr+=surface->stride;
+ }
} else
eWarning("cannot blit %dbpp from %dbpp", surface->bpp, src.surface->bpp);
}
@@ -488,27 +636,34 @@ static inline int sgn(int a)
void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color)
{
__u8 *srf8 = 0;
- __u32 *srf32 = 0;
+ __u16 *srf16 = 0;
+ __u32 *srf32 = 0;
int stride = surface->stride;
-
+
if (clip.rects.empty())
return;
-
+
+ __u16 col16;
__u32 col = 0;
if (surface->bpp == 8)
- {
srf8 = (__u8*)surface->data;
- } else if (surface->bpp == 32)
+ else
{
srf32 = (__u32*)surface->data;
-
if (surface->clut.data && color < surface->clut.colors)
col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
else
col=0x10101*color;
- col^=0xFF000000;
+ col^=0xFF000000;
}
-
+
+ if (surface->bpp == 16)
+#if BYTE_ORDER == LITTLE_ENDIAN
+ col16=bswap_16(((col & 0xFF) >> 3) << 11 | ((col & 0xFF00) >> 10) << 5 | (col & 0xFF0000) >> 19);
+#else
+ col16=((col & 0xFF) >> 3) << 11 | ((col & 0xFF00) >> 10) << 5 | (col & 0xFF0000) >> 19;
+#endif
+
int xa = start.x(), ya = start.y(), xb = dst.x(), yb = dst.y();
int dx, dy, x, y, s1, s2, e, temp, swap, i;
dy=abs(yb-ya);
@@ -526,7 +681,7 @@ void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color)
} else
swap=0;
e = 2*dy-dx;
-
+
int lasthit = 0;
for(i=1; i<=dx; i++)
{
@@ -563,20 +718,25 @@ void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color)
} while (!clip.rects[a].contains(x, y));
lasthit = a;
}
-
+
if (srf8)
srf8[y * stride + x] = color;
- if (srf32)
+ else if (srf16)
+ srf16[y * stride/2 + x] = col16;
+ else
srf32[y * stride/4 + x] = col;
fail:
while (e>=0)
{
- if (swap==1) x+=s1;
- else y+=s2;
+ if (swap==1)
+ x+=s1;
+ else
+ y+=s2;
e-=2*dx;
}
- if (swap==1)
- y+=s2;
+
+ if (swap==1)
+ y+=s2;
else
x+=s1;
e+=2*dy;
diff --git a/lib/gdi/lcd.cpp b/lib/gdi/lcd.cpp
index ecc19b53..a7dc22db 100644
--- a/lib/gdi/lcd.cpp
+++ b/lib/gdi/lcd.cpp
@@ -14,13 +14,19 @@
eDBoxLCD *eDBoxLCD::instance;
-eLCD::eLCD(eSize size): res(size)
+eLCD::eLCD()
{
lcdfd = -1;
locked=0;
- _buffer=new unsigned char[res.height()*res.width()];
- memset(_buffer, 0, res.height()*res.width());
- _stride=res.width();
+}
+
+void eLCD::setSize(int xres, int yres, int bpp)
+{
+ res = eSize(xres, yres);
+ _buffer=new unsigned char[xres * yres * bpp/8];
+ memset(_buffer, 0, res.height()*res.width()*bpp/8);
+ _stride=res.width()*bpp/8;
+ eDebug("lcd buffer %p %d bytes, stride %d", _buffer, xres*yres*bpp/8, _stride);
}
eLCD::~eLCD()
@@ -42,14 +48,17 @@ void eLCD::unlock()
locked=0;
}
-eDBoxLCD::eDBoxLCD(): eLCD(eSize(132, 64))
+eDBoxLCD::eDBoxLCD()
{
+ int xres=132, yres=64, bpp=8;
is_oled = 0;
#ifndef NO_LCD
lcdfd = open("/dev/dbox/oled0", O_RDWR);
if (lcdfd < 0)
{
- FILE *f=fopen("/proc/stb/fp/oled_brightness", "w");
+ FILE *f=fopen("/proc/stb/lcd/oled_brightness", "w");
+ if (!f)
+ f = fopen("/proc/stb/fp/oled_brightness", "w");
if (f)
{
is_oled = 2;
@@ -73,13 +82,37 @@ eDBoxLCD::eDBoxLCD(): eLCD(eSize(132, 64))
int i=LCD_MODE_BIN;
ioctl(lcdfd, LCD_IOCTL_ASC_MODE, &i);
inverted=0;
+ FILE *f = fopen("/proc/stb/lcd/xres", "r");
+ if (f)
+ {
+ int tmp;
+ if (fscanf(f, "%x", &tmp) == 1)
+ xres = tmp;
+ fclose(f);
+ f = fopen("/proc/stb/lcd/yres", "r");
+ if (f)
+ {
+ if (fscanf(f, "%x", &tmp) == 1)
+ yres = tmp;
+ fclose(f);
+ f = fopen("/proc/stb/lcd/bpp", "r");
+ if (f)
+ {
+ if (fscanf(f, "%x", &tmp) == 1)
+ bpp = tmp;
+ fclose(f);
+ }
+ }
+ is_oled = 3;
+ }
}
+ setSize(xres, yres, bpp);
}
void eDBoxLCD::setInverted(unsigned char inv)
{
inverted=inv;
- update();
+ update();
}
int eDBoxLCD::setLCDContrast(int contrast)
@@ -102,11 +135,13 @@ int eDBoxLCD::setLCDContrast(int contrast)
int eDBoxLCD::setLCDBrightness(int brightness)
{
eDebug("setLCDBrightness %d", brightness);
- FILE *f=fopen("/proc/stb/fp/oled_brightness", "w");
+ FILE *f=fopen("/proc/stb/lcd/oled_brightness", "w");
+ if (!f)
+ f = fopen("/proc/stb/fp/oled_brightness", "w");
if (f)
{
if (fprintf(f, "%d", brightness) == 0)
- eDebug("write /proc/stb/fp/oled_brightness failed!! (%m)");
+ eDebug("write /proc/stb/lcd/oled_brightness failed!! (%m)");
fclose(f);
}
else
@@ -141,42 +176,46 @@ eDBoxLCD *eDBoxLCD::getInstance()
void eDBoxLCD::update()
{
- if (!is_oled || is_oled == 2)
+ if (lcdfd >= 0)
{
- unsigned char raw[132*8];
- int x, y, yy;
- for (y=0; y<8; y++)
+ if (!is_oled || is_oled == 2)
{
- for (x=0; x<132; x++)
+ unsigned char raw[132*8];
+ int x, y, yy;
+ for (y=0; y<8; y++)
{
- int pix=0;
- for (yy=0; yy<8; yy++)
+ for (x=0; x<132; x++)
{
- pix|=(_buffer[(y*8+yy)*132+x]>=108)<<yy;
+ int pix=0;
+ for (yy=0; yy<8; yy++)
+ {
+ pix|=(_buffer[(y*8+yy)*132+x]>=108)<<yy;
+ }
+ raw[y*132+x]=(pix^inverted);
}
- raw[y*132+x]=(pix^inverted);
}
- }
- if (lcdfd >= 0)
write(lcdfd, raw, 132*8);
- } else
- {
- unsigned char raw[64*64];
- int x, y;
- memset(raw, 0, 64*64);
- for (y=0; y<64; y++)
+ }
+ else if (is_oled == 3)
+ write(lcdfd, _buffer, _stride * res.height());
+ else
{
- int pix=0;
- for (x=0; x<128 / 2; x++)
+ unsigned char raw[64*64];
+ int x, y;
+ memset(raw, 0, 64*64);
+ for (y=0; y<64; y++)
{
- pix = (_buffer[y*132 + x * 2 + 2] & 0xF0) |(_buffer[y*132 + x * 2 + 1 + 2] >> 4);
- if (inverted)
- pix = 0xFF - pix;
- raw[y*64+x] = pix;
+ int pix=0;
+ for (x=0; x<128 / 2; x++)
+ {
+ pix = (_buffer[y*132 + x * 2 + 2] & 0xF0) |(_buffer[y*132 + x * 2 + 1 + 2] >> 4);
+ if (inverted)
+ pix = 0xFF - pix;
+ raw[y*64+x] = pix;
+ }
}
- }
- if (lcdfd >= 0)
write(lcdfd, raw, 64*64);
+ }
}
}
diff --git a/lib/gdi/lcd.h b/lib/gdi/lcd.h
index 99f921b5..e7b4c2c4 100644
--- a/lib/gdi/lcd.h
+++ b/lib/gdi/lcd.h
@@ -13,10 +13,11 @@
class eLCD
{
#ifdef SWIG
- eLCD(eSize size);
+ eLCD();
~eLCD();
#else
protected:
+ void setSize(int xres, int yres, int bpp);
eSize res;
unsigned char *_buffer;
int lcdfd;
@@ -29,12 +30,11 @@ public:
int islocked() { return locked; }
bool detected() { return lcdfd >= 0; }
#ifndef SWIG
- eLCD(eSize size);
+ eLCD();
virtual ~eLCD();
__u8 *buffer() { return (__u8*)_buffer; }
int stride() { return _stride; }
eSize size() { return res; }
-
virtual void update()=0;
#endif
};
diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp
index 1d0323cf..97e2cc67 100644
--- a/lib/gui/elistboxcontent.cpp
+++ b/lib/gui/elistboxcontent.cpp
@@ -516,7 +516,7 @@ void eListboxPythonMultiContent::setSelectionClip(eRect &rect, bool update)
m_listbox->entryChanged(m_cursor);
}
-static void clearRegionHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColor, bool cursorValid)
+static void clearRegionHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColor, bool cursorValid, bool clear=true)
{
if (pbackColor)
{
@@ -538,10 +538,11 @@ static void clearRegionHelper(gPainter &painter, eListboxStyle *local_style, con
else if (local_style->m_transparent_background)
return;
}
- painter.clear();
+ if (clear)
+ painter.clear();
}
-static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid)
+static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_style, const ePoint &offset, ePyObject &pbackColorSelected, bool cursorValid, bool clear=true)
{
if (pbackColorSelected)
{
@@ -561,10 +562,11 @@ static void clearRegionSelectedHelper(gPainter &painter, eListboxStyle *local_st
return;
}
}
- painter.clear();
+ if (clear)
+ painter.clear();
}
-static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *local_style, ePyObject pforeColor, ePyObject pforeColorSelected, ePyObject pbackColor, ePyObject pbackColorSelected, int selected, gRegion &rc, eRect &sel_clip, const ePoint &offset, bool cursorValid)
+static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *local_style, ePyObject pforeColor, ePyObject pforeColorSelected, ePyObject pbackColor, ePyObject pbackColorSelected, int selected, gRegion &rc, eRect &sel_clip, const ePoint &offset, bool cursorValid, bool clear=true)
{
if (selected && sel_clip.valid())
{
@@ -573,7 +575,7 @@ static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *l
{
painter.clip(part);
style.setStyle(painter, eWindowStyle::styleListboxNormal);
- clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
+ clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid, clear);
painter.clippop();
selected = 0;
}
@@ -582,7 +584,7 @@ static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *l
{
painter.clip(part);
style.setStyle(painter, eWindowStyle::styleListboxSelected);
- clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
+ clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid, clear);
painter.clippop();
selected = 1;
}
@@ -590,14 +592,14 @@ static void clearRegion(gPainter &painter, eWindowStyle &style, eListboxStyle *l
else if (selected)
{
style.setStyle(painter, eWindowStyle::styleListboxSelected);
- clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid);
+ clearRegionSelectedHelper(painter, local_style, offset, pbackColorSelected, cursorValid, clear);
if (local_style && local_style->m_selection)
painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
}
else
{
style.setStyle(painter, eWindowStyle::styleListboxNormal);
- clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid);
+ clearRegionHelper(painter, local_style, offset, pbackColor, cursorValid, clear);
}
if (selected)
@@ -820,7 +822,8 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
{
gRegion rc(rect);
- clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
+ bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
+ clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
}
painter.setFont(m_font[fnt]);
@@ -854,6 +857,10 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
}
break;
}
+ case TYPE_PROGRESS_PIXMAP: // Progress
+ /*
+ (1, x, y, width, height, filled_percent, pixmap [, borderWidth, foreColor, backColor, backColorSelected] )
+ */
case TYPE_PROGRESS: // Progress
{
/*
@@ -864,41 +871,55 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
pwidth = PyTuple_GET_ITEM(item, 3),
pheight = PyTuple_GET_ITEM(item, 4),
pfilled_perc = PyTuple_GET_ITEM(item, 5),
- pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
-
- if (!(px && py && pwidth && pheight && pfilled_perc))
+ ppixmap, pborderWidth, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected;
+ int idx = 6;
+ if (type == TYPE_PROGRESS)
{
- eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
- goto error_out;
+ if (!(px && py && pwidth && pheight && pfilled_perc))
+ {
+ eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS, x, y, width, height, filled percent [,border width, foreColor, backColor, backColorSelected]))");
+ goto error_out;
+ }
+ }
+ else
+ {
+ ppixmap = PyTuple_GET_ITEM(item, idx++);
+ if (ppixmap == Py_None)
+ continue;
+ if (!(px && py && pwidth && pheight && pfilled_perc, ppixmap))
+ {
+ eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PROGRESS_PIXMAP, x, y, width, height, filled percent, pixmap, [,border width, foreColor, backColor, backColorSelected]))");
+ goto error_out;
+ }
}
- if (size > 6)
+ if (size > idx)
{
- pborderWidth = PyTuple_GET_ITEM(item, 6);
+ pborderWidth = PyTuple_GET_ITEM(item, idx++);
if (pborderWidth == Py_None)
pborderWidth = ePyObject();
}
- if (size > 7)
+ if (size > idx)
{
- pforeColor = PyTuple_GET_ITEM(item, 7);
+ pforeColor = PyTuple_GET_ITEM(item, idx++);
if (pforeColor == Py_None)
pforeColor = ePyObject();
}
- if (size > 8)
+ if (size > idx)
{
- pforeColorSelected = PyTuple_GET_ITEM(item, 8);
+ pforeColorSelected = PyTuple_GET_ITEM(item, idx++);
if (pforeColorSelected == Py_None)
pforeColorSelected=ePyObject();
}
- if (size > 9)
+ if (size > idx)
{
- pbackColor = PyTuple_GET_ITEM(item, 9);
+ pbackColor = PyTuple_GET_ITEM(item, idx++);
if (pbackColor == Py_None)
pbackColor=ePyObject();
}
- if (size > 10)
+ if (size > idx)
{
- pbackColorSelected = PyTuple_GET_ITEM(item, 10);
+ pbackColorSelected = PyTuple_GET_ITEM(item, idx++);
if (pbackColorSelected == Py_None)
pbackColorSelected=ePyObject();
}
@@ -923,7 +944,8 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
{
gRegion rc(rect);
- clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
+ bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
+ clearRegion(painter, style, local_style, pforeColor, pforeColorSelected, pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
}
// border
@@ -939,12 +961,27 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
rect.setRect(x+width-bwidth, y+bwidth, bwidth, height-bwidth);
painter.fill(rect);
- // progress
rect.setRect(x+bwidth, y+bwidth, (width-bwidth*2) * filled / 100, height-bwidth*2);
- painter.fill(rect);
- painter.clippop();
+ // progress
+ if (ppixmap)
+ {
+ ePtr<gPixmap> pixmap;
+ if (PyInt_Check(ppixmap) && data) /* if the pixmap is in fact a number, it refers to the data list */
+ ppixmap = PyTuple_GetItem(data, PyInt_AsLong(ppixmap));
+ if (SwigFromPython(pixmap, ppixmap))
+ {
+ eDebug("eListboxPythonMultiContent (Pixmap) get pixmap failed");
+ painter.clippop();
+ continue;
+ }
+ painter.blit(pixmap, rect.topLeft(), rect, 0);
+ }
+ else
+ painter.fill(rect);
+
+ painter.clippop();
break;
}
case TYPE_PIXMAP_ALPHABLEND:
@@ -997,7 +1034,8 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
{
gRegion rc(rect);
- clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid);
+ bool mustClear = (selected && pbackColorSelected) || (!selected && pbackColor);
+ clearRegion(painter, style, local_style, ePyObject(), ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip, offset, cursorValid, mustClear);
}
painter.blit(pixmap, rect.topLeft(), rect, (type == TYPE_PIXMAP_ALPHATEST) ? gPainter::BT_ALPHATEST : (type == TYPE_PIXMAP_ALPHABLEND) ? gPainter::BT_ALPHABLEND : 0);
diff --git a/lib/gui/elistboxcontent.h b/lib/gui/elistboxcontent.h
index d3d2a089..2649c097 100644
--- a/lib/gui/elistboxcontent.h
+++ b/lib/gui/elistboxcontent.h
@@ -69,7 +69,7 @@ class eListboxPythonMultiContent: public eListboxPythonStringContent
public:
eListboxPythonMultiContent();
~eListboxPythonMultiContent();
- enum { TYPE_TEXT, TYPE_PROGRESS, TYPE_PIXMAP, TYPE_PIXMAP_ALPHATEST, TYPE_PIXMAP_ALPHABLEND };
+ enum { TYPE_TEXT, TYPE_PROGRESS, TYPE_PIXMAP, TYPE_PIXMAP_ALPHATEST, TYPE_PIXMAP_ALPHABLEND, TYPE_PROGRESS_PIXMAP };
void paint(gPainter &painter, eWindowStyle &style, const ePoint &offset, int selected);
int currentCursorSelectable();
void setList(SWIG_PYOBJECT(ePyObject) list);
diff --git a/lib/gui/epixmap.cpp b/lib/gui/epixmap.cpp
index f20c1a9f..bc0d42df 100644
--- a/lib/gui/epixmap.cpp
+++ b/lib/gui/epixmap.cpp
@@ -3,7 +3,7 @@
#include <lib/gui/ewidgetdesktop.h>
ePixmap::ePixmap(eWidget *parent)
- :eWidget(parent), m_alphatest(false), m_scale(false)
+ :eWidget(parent), m_alphatest(false), m_scale(false), m_have_border_color(false), m_border_width(0)
{
}
@@ -49,9 +49,22 @@ void ePixmap::setPixmapFromFile(const char *filename)
event(evtChangedPixmap);
}
+void ePixmap::setBorderWidth(int pixel)
+{
+ m_border_width=pixel;
+ invalidate();
+}
+
+void ePixmap::setBorderColor(const gRGB &color)
+{
+ m_border_color=color;
+ m_have_border_color=true;
+ invalidate();
+}
+
void ePixmap::checkSize()
{
- /* when we have no pixmap, or a pixmap of different size, we need
+ /* when we have no pixmap, or a pixmap of different size, we need
to enable transparency in any case. */
if (m_pixmap && m_pixmap->size() == size() && !m_alphatest)
setTransparent(0);
@@ -67,13 +80,14 @@ int ePixmap::event(int event, void *data, void *data2)
case evtPaint:
{
ePtr<eWindowStyle> style;
-
+
+ eSize s(size());
getStyle(style);
// we don't clear the background before because of performance reasons.
// when the pixmap is too small to fit the whole widget area, the widget is
// transparent anyway, so the background is already painted.
-// eWidget::event(event, data, data2);
+// eWidget::event(event, data, data2);
gPainter &painter = *(gPainter*)data2;
if (m_pixmap)
@@ -91,6 +105,16 @@ int ePixmap::event(int event, void *data, void *data2)
painter.blit(m_pixmap, ePoint(0, 0), eRect(), flags);
}
+ if (m_have_border_color)
+ painter.setForegroundColor(m_border_color);
+
+ if (m_border_width) {
+ painter.fill(eRect(0, 0, s.width(), m_border_width));
+ painter.fill(eRect(0, m_border_width, m_border_width, s.height()-m_border_width));
+ painter.fill(eRect(m_border_width, s.height()-m_border_width, s.width()-m_border_width, m_border_width));
+ painter.fill(eRect(s.width()-m_border_width, m_border_width, m_border_width, s.height()-m_border_width));
+ }
+
return 0;
}
case evtChangedPixmap:
diff --git a/lib/gui/epixmap.h b/lib/gui/epixmap.h
index 6280fb34..2db26f25 100644
--- a/lib/gui/epixmap.h
+++ b/lib/gui/epixmap.h
@@ -15,6 +15,8 @@ public:
void setPixmapFromFile(const char *filename);
void setAlphatest(int alphatest); /* 1 for alphatest, 2 for alphablend */
void setScale(int scale);
+ void setBorderWidth(int pixel);
+ void setBorderColor(const gRGB &color);
protected:
ePtr<gPixmap> m_pixmap;
int event(int event, void *data=0, void *data2=0);
@@ -24,6 +26,9 @@ private:
{
evtChangedPixmap = evtUserWidget,
};
+ bool m_have_border_color;
+ int m_border_width;
+ gRGB m_border_color;
};
#endif
diff --git a/lib/gui/ewindowstyle.cpp b/lib/gui/ewindowstyle.cpp
index 68a74e0c..0ecdc2a2 100644
--- a/lib/gui/ewindowstyle.cpp
+++ b/lib/gui/ewindowstyle.cpp
@@ -28,7 +28,9 @@ eWindowStyleManager::~eWindowStyleManager()
void eWindowStyleManager::getStyle(int style_id, ePtr<eWindowStyle> &style)
{
- style = m_current_style[style_id];
+ std::map<int, ePtr<eWindowStyle> >::iterator it = m_current_style.find(style_id);
+ ASSERT(it != m_current_style.end());
+ style = it->second;
}
void eWindowStyleManager::setStyle(int style_id, eWindowStyle *style)
diff --git a/lib/python/Components/About.py b/lib/python/Components/About.py
index 8e332e33..6b322c9d 100644..100755
--- a/lib/python/Components/About.py
+++ b/lib/python/Components/About.py
@@ -1,5 +1,6 @@
from Tools.Directories import resolveFilename, SCOPE_SYSETC
from enigma import getEnigmaVersionString
+from os import popen
class About:
def __init__(self):
@@ -43,4 +44,14 @@ class About:
def getEnigmaVersionString(self):
return getEnigmaVersionString()
+ def getKernelVersionString(self):
+ try:
+ result = popen("uname -r","r").read().strip("\n").split('-')
+ kernel_version = result[0]
+ return kernel_version
+ except:
+ pass
+
+ return "unknown"
+
about = About()
diff --git a/lib/python/Components/ConfigList.py b/lib/python/Components/ConfigList.py
index 418a1b67..24f917f7 100755
--- a/lib/python/Components/ConfigList.py
+++ b/lib/python/Components/ConfigList.py
@@ -61,12 +61,13 @@ class ConfigList(HTMLComponent, GUIComponent, object):
GUI_WIDGET = eListbox
def selectionChanged(self):
- if self.current:
+ if isinstance(self.current,tuple) and len(self.current) == 2:
self.current[1].onDeselect(self.session)
self.current = self.getCurrent()
- if self.current:
+ if isinstance(self.current,tuple) and len(self.current) == 2:
self.current[1].onSelect(self.session)
-
+ else:
+ return
for x in self.onSelectionChanged:
x()
@@ -75,11 +76,11 @@ class ConfigList(HTMLComponent, GUIComponent, object):
instance.setContent(self.l)
def preWidgetRemove(self, instance):
- if self.current:
+ if isinstance(self.current,tuple) and len(self.current) == 2:
self.current[1].onDeselect(self.session)
instance.selectionChanged.get().remove(self.selectionChanged)
instance.setContent(None)
-
+
def setList(self, l):
self.timer.stop()
self.__list = l
@@ -87,7 +88,7 @@ class ConfigList(HTMLComponent, GUIComponent, object):
if l is not None:
for x in l:
- assert isinstance(x[1], ConfigElement), "entry in ConfigList " + str(x[1]) + " must be a ConfigElement"
+ assert len(x) < 2 or isinstance(x[1], ConfigElement), "entry in ConfigList " + str(x[1]) + " must be a ConfigElement"
def getList(self):
return self.__list
diff --git a/lib/python/Components/Converter/TemplatedMultiContent.py b/lib/python/Components/Converter/TemplatedMultiContent.py
index b5a98449..b1d89f55 100644..100755
--- a/lib/python/Components/Converter/TemplatedMultiContent.py
+++ b/lib/python/Components/Converter/TemplatedMultiContent.py
@@ -53,14 +53,18 @@ class TemplatedMultiContent(StringList):
template = self.template.get("template")
itemheight = self.template["itemHeight"]
selectionEnabled = self.template.get("selectionEnabled", True)
+ scrollbarMode = self.template.get("scrollbarMode", "showOnDemand")
if templates and style and style in templates: # if we have a custom style defined in the source, and different templates in the skin, look it up
template = templates[style][1]
itemheight = templates[style][0]
if len(templates[style]) > 2:
selectionEnabled = templates[style][2]
+ if len(templates[style]) > 3:
+ scrollbarMode = templates[style][3]
self.content.setTemplate(template)
self.content.setItemHeight(itemheight)
self.selectionEnabled = selectionEnabled
+ self.scrollbarMode = scrollbarMode
self.active_style = style
diff --git a/lib/python/Components/DreamInfoHandler.py b/lib/python/Components/DreamInfoHandler.py
index 85e2b533..03d52157 100755
--- a/lib/python/Components/DreamInfoHandler.py
+++ b/lib/python/Components/DreamInfoHandler.py
@@ -16,7 +16,7 @@ class InfoHandlerParseError(Exception):
return repr(self.value)
class InfoHandler(xml.sax.ContentHandler):
- def __init__(self, prerequisiteMet, directory, language = None):
+ def __init__(self, prerequisiteMet, directory):
self.attributes = {}
self.directory = directory
self.list = []
@@ -26,9 +26,6 @@ class InfoHandler(xml.sax.ContentHandler):
self.validFileTypes = ["skin", "config", "services", "favourites", "package"]
self.prerequisitesMet = prerequisiteMet
self.data = ""
- self.language = language
- self.translatedPackageInfos = {}
- self.foundTranslation = None
def printError(self, error):
print "Error in defaults xml files:", error
@@ -52,15 +49,6 @@ class InfoHandler(xml.sax.ContentHandler):
if name == "info":
self.foundTranslation = None
self.data = ""
- if not attrs.has_key("language"):
- print "info tag with no language attribute"
- else:
- if attrs["language"] == 'en': # read default translations
- self.foundTranslation = False
- self.data = ""
- elif attrs["language"] == self.language:
- self.foundTranslation = True
- self.data = ""
if name == "files":
if attrs.has_key("type"):
@@ -91,20 +79,17 @@ class InfoHandler(xml.sax.ContentHandler):
if attrs.has_key("details"):
self.attributes["details"] = str(attrs["details"])
if attrs.has_key("name"):
- self.attributes["name"] = str(attrs["name"].encode("utf-8"))
+ self.attributes["name"] = str(attrs["name"])
if attrs.has_key("packagename"):
- self.attributes["packagename"] = str(attrs["packagename"].encode("utf-8"))
+ self.attributes["packagename"] = str(attrs["packagename"])
if attrs.has_key("packagetype"):
- self.attributes["packagetype"] = str(attrs["packagetype"].encode("utf-8"))
+ self.attributes["packagetype"] = str(attrs["packagetype"])
if attrs.has_key("shortdescription"):
- self.attributes["shortdescription"] = str(attrs["shortdescription"].encode("utf-8"))
+ self.attributes["shortdescription"] = str(attrs["shortdescription"])
if name == "screenshot":
if attrs.has_key("src"):
- if self.foundTranslation is False:
- self.attributes["screenshot"] = str(attrs["src"])
- elif self.foundTranslation is True:
- self.translatedPackageInfos["screenshot"] = str(attrs["src"])
+ self.attributes["screenshot"] = str(attrs["src"])
def endElement(self, name):
#print "endElement", name
@@ -124,7 +109,7 @@ class InfoHandler(xml.sax.ContentHandler):
self.attributes[self.filetype].append({ "name": str(self.fileattrs["name"]), "directory": directory })
if name in ( "default", "package" ):
- self.list.append({"attributes": self.attributes, 'prerequisites': self.globalprerequisites ,"translation": self.translatedPackageInfos})
+ self.list.append({"attributes": self.attributes, 'prerequisites': self.globalprerequisites})
self.attributes = {}
self.globalprerequisites = {}
@@ -133,30 +118,13 @@ class InfoHandler(xml.sax.ContentHandler):
self.attributes["author"] = str(data)
if self.elements[-1] == "name":
self.attributes["name"] = str(data)
- if self.foundTranslation is False:
- if self.elements[-1] == "author":
- self.attributes["author"] = str(data)
- if self.elements[-1] == "name":
- self.attributes["name"] = str(data)
- if self.elements[-1] == "packagename":
- self.attributes["packagename"] = str(data.encode("utf-8"))
- if self.elements[-1] == "shortdescription":
- self.attributes["shortdescription"] = str(data.encode("utf-8"))
- if self.elements[-1] == "description":
- self.data += data.strip()
- self.attributes["description"] = str(self.data.encode("utf-8"))
- elif self.foundTranslation is True:
- if self.elements[-1] == "author":
- self.translatedPackageInfos["author"] = str(data)
- if self.elements[-1] == "name":
- self.translatedPackageInfos["name"] = str(data)
- if self.elements[-1] == "description":
- self.data += data.strip()
- self.translatedPackageInfos["description"] = str(self.data.encode("utf-8"))
- if self.elements[-1] == "name":
- self.translatedPackageInfos["name"] = str(data.encode("utf-8"))
- if self.elements[-1] == "shortdescription":
- self.translatedPackageInfos["shortdescription"] = str(data.encode("utf-8"))
+ if self.elements[-1] == "packagename":
+ self.attributes["packagename"] = str(data)
+ if self.elements[-1] == "shortdescription":
+ self.attributes["shortdescription"] = str(data)
+ if self.elements[-1] == "description":
+ self.data += data.strip()
+ self.attributes["description"] = str(self.data)
#print "characters", data
@@ -166,13 +134,12 @@ class DreamInfoHandler:
STATUS_ERROR = 2
STATUS_INIT = 4
- def __init__(self, statusCallback, blocking = False, neededTag = None, neededFlag = None, language = None):
+ def __init__(self, statusCallback, blocking = False, neededTag = None, neededFlag = None):
self.hardware_info = HardwareInfo()
self.directory = "/"
self.neededTag = neededTag
self.neededFlag = neededFlag
- self.language = language
# caution: blocking should only be used, if further execution in enigma2 depends on the outcome of
# the installer!
@@ -203,8 +170,8 @@ class DreamInfoHandler:
#print handler.list
def readIndex(self, directory, file):
- print "Reading .xml meta index file", file
- handler = InfoHandler(self.prerequisiteMet, directory, self.language)
+ print "Reading .xml meta index file", directory, file
+ handler = InfoHandler(self.prerequisiteMet, directory)
try:
xml.sax.parse(file, handler)
for entry in handler.list:
@@ -216,7 +183,7 @@ class DreamInfoHandler:
def readDetails(self, directory, file):
self.packageDetails = []
print "Reading .xml meta details file", file
- handler = InfoHandler(self.prerequisiteMet, directory, self.language)
+ handler = InfoHandler(self.prerequisiteMet, directory)
try:
xml.sax.parse(file, handler)
for entry in handler.list:
@@ -225,7 +192,6 @@ class DreamInfoHandler:
print "file", file, "ignored due to errors in the file"
#print handler.list
-
# prerequisites = True: give only packages matching the prerequisites
def fillPackagesList(self, prerequisites = True):
self.packageslist = []
@@ -254,20 +220,16 @@ class DreamInfoHandler:
self.directory = [self.directory]
for indexfile in os.listdir(self.directory[0]):
- if indexfile.startswith("index"):
- if indexfile.endswith("_en.xml"): #we first catch all english indexfiles
- indexfileList.append(os.path.splitext(indexfile)[0][:-3])
-
+ if indexfile.startswith("index-"):
+ if indexfile.endswith(".xml"):
+ if indexfile[-7:-6] == "_":
+ continue
+ indexfileList.append(indexfile)
if len(indexfileList):
for file in indexfileList:
neededFile = self.directory[0] + "/" + file
- if self.language is not None:
- if os.path.exists(neededFile + '_' + self.language + '.xml' ):
- #print "translated index file found",neededFile + '_' + self.language + '.xml'
- self.readIndex(self.directory[0] + "/", neededFile + '_' + self.language + '.xml')
- else:
- #print "reading original index file"
- self.readIndex(self.directory[0] + "/", neededFile + '_en.xml')
+ if os.path.isfile(neededFile):
+ self.readIndex(self.directory[0] + "/" , neededFile)
if prerequisites:
for package in self.packagesIndexlist[:]:
diff --git a/lib/python/Components/FileList.py b/lib/python/Components/FileList.py
index 841a2fe5..1d71514b 100755
--- a/lib/python/Components/FileList.py
+++ b/lib/python/Components/FileList.py
@@ -196,6 +196,9 @@ class FileList(MenuList):
if (self.matchingPattern is None) or re_compile(self.matchingPattern).search(path):
self.list.append(FileEntryComponent(name = name, absolute = x , isDir = False))
+ if self.showMountpoints and len(self.list) == 0:
+ self.list.append(FileEntryComponent(name = _("nothing connected"), absolute = None, isDir = False))
+
self.l.setList(self.list)
if select is not None:
diff --git a/lib/python/Components/Harddisk.py b/lib/python/Components/Harddisk.py
index e8e612a4..7f837565 100755..100644
--- a/lib/python/Components/Harddisk.py
+++ b/lib/python/Components/Harddisk.py
@@ -5,6 +5,10 @@ from SystemInfo import SystemInfo
import time
from Components.Console import Console
+def MajorMinor(path):
+ rdev = stat(path).st_rdev
+ return (major(rdev),minor(rdev))
+
def readFile(filename):
file = open(filename)
data = file.read().strip()
@@ -125,13 +129,15 @@ class Harddisk:
for line in lines:
parts = line.strip().split(" ")
- if path.realpath(parts[0]).startswith(self.dev_path):
- try:
+ real_path = path.realpath(parts[0])
+ if not real_path[-1].isdigit():
+ continue
+ try:
+ if MajorMinor(real_path) == MajorMinor(self.partitionPath(real_path[-1])):
stat = statvfs(parts[1])
- except OSError:
- continue
- return stat.f_bfree/1000 * stat.f_bsize/1000
-
+ return stat.f_bfree/1000 * stat.f_bsize/1000
+ except OSError:
+ pass
return -1
def numPartitions(self):
@@ -168,10 +174,17 @@ class Harddisk:
cmd = "umount"
- for line in lines:
- parts = line.strip().split(" ")
- if path.realpath(parts[0]).startswith(self.dev_path):
- cmd = ' ' . join([cmd, parts[1]])
+ for line in lines:
+ parts = line.strip().split(" ")
+ real_path = path.realpath(parts[0])
+ if not real_path[-1].isdigit():
+ continue
+ try:
+ if MajorMinor(real_path) == MajorMinor(self.partitionPath(real_path[-1])):
+ cmd = ' ' . join([cmd, parts[1]])
+ break
+ except OSError:
+ pass
res = system(cmd)
return (res >> 8)
@@ -201,10 +214,16 @@ class Harddisk:
res = -1
for line in lines:
parts = line.strip().split(" ")
- if path.realpath(parts[0]) == self.partitionPath("1"):
- cmd = "mount -t ext3 " + parts[0]
- res = system(cmd)
- break
+ real_path = path.realpath(parts[0])
+ if not real_path[-1].isdigit():
+ continue
+ try:
+ if MajorMinor(real_path) == MajorMinor(self.partitionPath(real_path[-1])):
+ cmd = "mount -t ext3 " + parts[0]
+ res = system(cmd)
+ break
+ except OSError:
+ pass
return (res >> 8)
diff --git a/lib/python/Components/InputDevice.py b/lib/python/Components/InputDevice.py
index 3c3bd7a1..d675ca3a 100644..100755
--- a/lib/python/Components/InputDevice.py
+++ b/lib/python/Components/InputDevice.py
@@ -1,29 +1,208 @@
-from config import config, ConfigSlider, ConfigSubsection
+# coding: utf-8
+from config import config, configfile, ConfigSlider, ConfigSubsection, ConfigYesNo, ConfigText
+
+import struct, sys, time, errno
+from fcntl import ioctl
+from os import path as os_path, listdir, open as os_open, close as os_close, write as os_write, read as os_read, O_RDWR, O_NONBLOCK
+
+# asm-generic/ioctl.h
+IOC_NRBITS = 8L
+IOC_TYPEBITS = 8L
+IOC_SIZEBITS = 13L
+IOC_DIRBITS = 3L
+
+IOC_NRSHIFT = 0L
+IOC_TYPESHIFT = IOC_NRSHIFT+IOC_NRBITS
+IOC_SIZESHIFT = IOC_TYPESHIFT+IOC_TYPEBITS
+IOC_DIRSHIFT = IOC_SIZESHIFT+IOC_SIZEBITS
+
+IOC_READ = 2L
+
+def EVIOCGNAME(length):
+ return (IOC_READ<<IOC_DIRSHIFT)|(length<<IOC_SIZESHIFT)|(0x45<<IOC_TYPESHIFT)|(0x06<<IOC_NRSHIFT)
+
class inputDevices:
+
+ def __init__(self):
+ self.Devices = {}
+ self.currentDevice = ""
+ self.getInputDevices()
+
+ def getInputDevices(self):
+ devices = listdir("/dev/input/")
+
+ for evdev in devices:
+ try:
+ buffer = "\0"*512
+ self.fd = os_open("/dev/input/" + evdev, O_RDWR | O_NONBLOCK)
+ self.name = ioctl(self.fd, EVIOCGNAME(256), buffer)
+ self.name = self.name[:self.name.find("\0")]
+ os_close(self.fd)
+ except (IOError,OSError), err:
+ print '[iInputDevices] getInputDevices <ERROR: ioctl(EVIOCGNAME): ' + str(err) + ' >'
+ self.name = None
+
+ if self.name:
+ if self.name == 'dreambox front panel':
+ continue
+ if self.name == "dreambox advanced remote control (native)" and config.misc.rcused.value != 0:
+ continue
+ if self.name == "dreambox remote control (native)" and config.misc.rcused.value == 0:
+ continue
+ self.Devices[evdev] = {'name': self.name, 'type': self.getInputDeviceType(self.name),'enabled': False, 'configuredName': None }
+
+
+ def getInputDeviceType(self,name):
+ if name.find("remote control") != -1:
+ return "remote"
+ elif name.find("keyboard") != -1:
+ return "keyboard"
+ elif name.find("mouse") != -1:
+ return "mouse"
+ else:
+ print "Unknown device type:",name
+ return None
+
+ def getDeviceName(self, x):
+ if x in self.Devices.keys():
+ return self.Devices[x].get("name", x)
+ else:
+ return "Unknown device name"
+
+ def getDeviceList(self):
+ return sorted(self.Devices.iterkeys())
+
+ def getDefaultRCdeviceName(self):
+ if config.misc.rcused.value == 0:
+ for device in self.Devices.iterkeys():
+ if self.Devices[device]["name"] == "dreambox advanced remote control (native)":
+ return device
+ else:
+ for device in self.Devices.iterkeys():
+ if self.Devices[device]["name"] == "dreambox remote control (native)":
+ return device
+
+ def setDeviceAttribute(self, device, attribute, value):
+ #print "[iInputDevices] setting for device", device, "attribute", attribute, " to value", value
+ if self.Devices.has_key(device):
+ self.Devices[device][attribute] = value
+
+ def getDeviceAttribute(self, device, attribute):
+ if self.Devices.has_key(device):
+ if self.Devices[device].has_key(attribute):
+ return self.Devices[device][attribute]
+ return None
+
+ def setEnabled(self, device, value):
+ oldval = self.getDeviceAttribute(device, 'enabled')
+ #print "[iInputDevices] setEnabled for device %s to %s from %s" % (device,value,oldval)
+ self.setDeviceAttribute(device, 'enabled', value)
+ if oldval is True and value is False:
+ self.setDefaults(device)
+
+ def setName(self, device, value):
+ #print "[iInputDevices] setName for device %s to %s" % (device,value)
+ self.setDeviceAttribute(device, 'configuredName', value)
+
+ #struct input_event {
+ # struct timeval time; -> ignored
+ # __u16 type; -> EV_REP (0x14)
+ # __u16 code; -> REP_DELAY (0x00) or REP_PERIOD (0x01)
+ # __s32 value; -> DEFAULTS: 700(REP_DELAY) or 100(REP_PERIOD)
+ #}; -> size = 16
+
+ def setDefaults(self, device):
+ print "[iInputDevices] setDefaults for device %s" % (device)
+ self.setDeviceAttribute(device, 'configuredName', None)
+ event_repeat = struct.pack('iihhi', 0, 0, 0x14, 0x01, 100)
+ event_delay = struct.pack('iihhi', 0, 0, 0x14, 0x00, 700)
+ fd = os_open("/dev/input/" + device, O_RDWR)
+ os_write(fd, event_repeat)
+ os_write(fd, event_delay)
+ os_close(fd)
+
+ def setRepeat(self, device, value): #REP_PERIOD
+ if self.getDeviceAttribute(device, 'enabled') == True:
+ print "[iInputDevices] setRepeat for device %s to %d ms" % (device,value)
+ event = struct.pack('iihhi', 0, 0, 0x14, 0x01, int(value))
+ fd = os_open("/dev/input/" + device, O_RDWR)
+ os_write(fd, event)
+ os_close(fd)
+
+ def setDelay(self, device, value): #REP_DELAY
+ if self.getDeviceAttribute(device, 'enabled') == True:
+ print "[iInputDevices] setDelay for device %s to %d ms" % (device,value)
+ event = struct.pack('iihhi', 0, 0, 0x14, 0x00, int(value))
+ fd = os_open("/dev/input/" + device, O_RDWR)
+ os_write(fd, event)
+ os_close(fd)
+
+
+class InitInputDevices:
+
def __init__(self):
- pass
- def setRepeat(self, value):
- #print "setup rc repeat"
- pass
- def setDelay(self, value):
- #print "setup rc delay"
- pass
-
-def InitInputDevices():
- config.inputDevices = ConfigSubsection();
- config.inputDevices.repeat = ConfigSlider(default=5, limits=(1, 10))
- config.inputDevices.delay = ConfigSlider(default=4, limits=(1, 10))
-
- #this instance anywhere else needed?
- iDevices = inputDevices();
+ self.currentDevice = ""
+ self.createConfig()
- def inputDevicesRepeatChanged(configElement):
- iDevices.setRepeat(configElement.value);
+ def createConfig(self, *args):
+ config.inputDevices = ConfigSubsection()
+ for device in sorted(iInputDevices.Devices.iterkeys()):
+ self.currentDevice = device
+ #print "[InitInputDevices] -> creating config entry for device: %s -> %s " % (self.currentDevice, iInputDevices.Devices[device]["name"])
+ self.setupConfigEntries(self.currentDevice)
+ self.currentDevice = ""
+
+ def inputDevicesEnabledChanged(self,configElement):
+ if self.currentDevice != "" and iInputDevices.currentDevice == "":
+ iInputDevices.setEnabled(self.currentDevice, configElement.value)
+ elif iInputDevices.currentDevice != "":
+ iInputDevices.setEnabled(iInputDevices.currentDevice, configElement.value)
+
+ def inputDevicesNameChanged(self,configElement):
+ if self.currentDevice != "" and iInputDevices.currentDevice == "":
+ iInputDevices.setName(self.currentDevice, configElement.value)
+ if configElement.value != "":
+ devname = iInputDevices.getDeviceAttribute(self.currentDevice, 'name')
+ if devname != configElement.value:
+ cmd = "config.inputDevices." + self.currentDevice + ".enabled.value = False"
+ exec (cmd)
+ cmd = "config.inputDevices." + self.currentDevice + ".enabled.save()"
+ exec (cmd)
+ elif iInputDevices.currentDevice != "":
+ iInputDevices.setName(iInputDevices.currentDevice, configElement.value)
+
+ def inputDevicesRepeatChanged(self,configElement):
+ if self.currentDevice != "" and iInputDevices.currentDevice == "":
+ iInputDevices.setRepeat(self.currentDevice, configElement.value)
+ elif iInputDevices.currentDevice != "":
+ iInputDevices.setRepeat(iInputDevices.currentDevice, configElement.value)
+
+ def inputDevicesDelayChanged(self,configElement):
+ if self.currentDevice != "" and iInputDevices.currentDevice == "":
+ iInputDevices.setDelay(self.currentDevice, configElement.value)
+ elif iInputDevices.currentDevice != "":
+ iInputDevices.setDelay(iInputDevices.currentDevice, configElement.value)
+
+ def setupConfigEntries(self,device):
+ cmd = "config.inputDevices." + device + " = ConfigSubsection()"
+ exec (cmd)
+ cmd = "config.inputDevices." + device + ".enabled = ConfigYesNo(default = False)"
+ exec (cmd)
+ cmd = "config.inputDevices." + device + ".enabled.addNotifier(self.inputDevicesEnabledChanged,config.inputDevices." + device + ".enabled)"
+ exec (cmd)
+ cmd = "config.inputDevices." + device + '.name = ConfigText(default="")'
+ exec (cmd)
+ cmd = "config.inputDevices." + device + ".name.addNotifier(self.inputDevicesNameChanged,config.inputDevices." + device + ".name)"
+ exec (cmd)
+ cmd = "config.inputDevices." + device + ".repeat = ConfigSlider(default=100, increment = 10, limits=(0, 500))"
+ exec (cmd)
+ cmd = "config.inputDevices." + device + ".repeat.addNotifier(self.inputDevicesRepeatChanged,config.inputDevices." + device + ".repeat)"
+ exec (cmd)
+ cmd = "config.inputDevices." + device + ".delay = ConfigSlider(default=700, increment = 100, limits=(0, 5000))"
+ exec (cmd)
+ cmd = "config.inputDevices." + device + ".delay.addNotifier(self.inputDevicesDelayChanged,config.inputDevices." + device + ".delay)"
+ exec (cmd)
- def inputDevicesDelayChanged(configElement):
- iDevices.setDelay(configElement.value);
- # this will call the "setup-val" initial
- config.inputDevices.repeat.addNotifier(inputDevicesRepeatChanged);
- config.inputDevices.delay.addNotifier(inputDevicesDelayChanged);
+iInputDevices = inputDevices()
diff --git a/lib/python/Components/Ipkg.py b/lib/python/Components/Ipkg.py
index 0ba1165c..71447775 100755
--- a/lib/python/Components/Ipkg.py
+++ b/lib/python/Components/Ipkg.py
@@ -1,4 +1,5 @@
from enigma import eConsoleAppContainer
+from Tools.Directories import fileExists
class IpkgComponent:
EVENT_INSTALL = 0
@@ -20,7 +21,7 @@ class IpkgComponent:
def __init__(self, ipkg = '/usr/bin/ipkg'):
self.ipkg = ipkg
-
+ self.opkgAvail = fileExists('/usr/bin/opkg')
self.cmd = eConsoleAppContainer()
self.cache = None
self.callbackList = []
@@ -89,7 +90,10 @@ class IpkgComponent:
if data.find('Downloading') == 0:
self.callCallbacks(self.EVENT_DOWNLOAD, data.split(' ', 5)[1].strip())
elif data.find('Upgrading') == 0:
- self.callCallbacks(self.EVENT_UPGRADE, data.split(' ', 1)[1].split(' ')[0])
+ if self.opkgAvail:
+ self.callCallbacks(self.EVENT_UPGRADE, data.split(' ', 1)[1].split(' ')[0])
+ else:
+ self.callCallbacks(self.EVENT_UPGRADE, data.split(' ', 1)[1].split(' ')[0])
elif data.find('Installing') == 0:
self.callCallbacks(self.EVENT_INSTALL, data.split(' ', 1)[1].split(' ')[0])
elif data.find('Removing') == 0:
diff --git a/lib/python/Components/Network.py b/lib/python/Components/Network.py
index b9da48d8..e980cb8c 100755
--- a/lib/python/Components/Network.py
+++ b/lib/python/Components/Network.py
@@ -4,6 +4,7 @@ from socket import *
from enigma import eConsoleAppContainer
from Components.Console import Console
from Components.PluginComponent import plugins
+from Components.About import about
from Plugins.Plugin import PluginDescriptor
class Network:
@@ -26,6 +27,9 @@ class Network:
self.DnsConsole = Console()
self.PingConsole = Console()
self.config_ready = None
+ self.friendlyNames = {}
+ self.lan_interfaces = []
+ self.wlan_interfaces = []
self.getInterfaces()
def onRemoteRootFS(self):
@@ -309,13 +313,49 @@ class Network:
return len(self.ifaces)
def getFriendlyAdapterName(self, x):
- # maybe this needs to be replaced by an external list.
- friendlyNames = {
- "eth0": _("Integrated Ethernet"),
- "wlan0": _("Wireless"),
- "ath0": _("Integrated Wireless")
- }
- return friendlyNames.get(x, x) # when we have no friendly name, use adapter name
+ if x in self.friendlyNames.keys():
+ return self.friendlyNames.get(x, x)
+ else:
+ self.friendlyNames[x] = self.getFriendlyAdapterNaming(x)
+ return self.friendlyNames.get(x, x) # when we have no friendly name, use adapter name
+
+ def getFriendlyAdapterNaming(self, iface):
+ if iface.startswith('eth'):
+ if iface not in self.lan_interfaces and len(self.lan_interfaces) == 0:
+ self.lan_interfaces.append(iface)
+ return _("LAN connection")
+ elif iface not in self.lan_interfaces and len(self.lan_interfaces) >= 1:
+ self.lan_interfaces.append(iface)
+ return _("LAN connection") + " " + str(len(self.lan_interfaces))
+ else:
+ if iface not in self.wlan_interfaces and len(self.wlan_interfaces) == 0:
+ self.wlan_interfaces.append(iface)
+ return _("WLAN connection")
+ elif iface not in self.wlan_interfaces and len(self.wlan_interfaces) >= 1:
+ self.wlan_interfaces.append(iface)
+ return _("WLAN connection") + " " + str(len(self.wlan_interfaces))
+
+ def getFriendlyAdapterDescription(self, iface):
+ if iface == 'eth0':
+ return _("Internal LAN adapter.")
+ else:
+ classdir = "/sys/class/net/" + iface + "/device/"
+ driverdir = "/sys/class/net/" + iface + "/device/driver/"
+ if os_path.exists(classdir):
+ files = listdir(classdir)
+ if 'driver' in files:
+ if os_path.realpath(driverdir).endswith('ath_pci'):
+ return _("Atheros")+ " " + str(os_path.basename(os_path.realpath(driverdir))) + " " + _("WLAN adapter.")
+ elif os_path.realpath(driverdir).endswith('zd1211b'):
+ return _("Zydas")+ " " + str(os_path.basename(os_path.realpath(driverdir))) + " " + _("WLAN adapter.")
+ elif os_path.realpath(driverdir).endswith('rt73'):
+ return _("Ralink")+ " " + str(os_path.basename(os_path.realpath(driverdir))) + " " + _("WLAN adapter.")
+ elif os_path.realpath(driverdir).endswith('rt73usb'):
+ return _("Ralink")+ " " + str(os_path.basename(os_path.realpath(driverdir))) + " " + _("WLAN adapter.")
+ else:
+ return str(os_path.basename(os_path.realpath(driverdir))) + " " + _("WLAN adapter.")
+ else:
+ return _("Unknown network adapter.")
def getAdapterName(self, iface):
return iface
@@ -569,24 +609,39 @@ class Network:
if callback is not None:
callback(True)
- def detectWlanModule(self):
+ def detectWlanModule(self, iface = None):
self.wlanmodule = None
- rt73_dir = "/sys/bus/usb/drivers/rt73/"
- zd1211b_dir = "/sys/bus/usb/drivers/zd1211b/"
- madwifi_dir = "/sys/bus/pci/drivers/ath_pci/"
- if os_path.exists(madwifi_dir):
- files = listdir(madwifi_dir)
- if len(files) >= 1:
- self.wlanmodule = 'madwifi'
- if os_path.exists(rt73_dir):
- rtfiles = listdir(rt73_dir)
- if len(rtfiles) == 2 or len(rtfiles) == 5:
- self.wlanmodule = 'ralink'
- if os_path.exists(zd1211b_dir):
- zdfiles = listdir(zd1211b_dir)
- if len(zdfiles) == 1 or len(zdfiles) == 5:
- self.wlanmodule = 'zydas'
- return self.wlanmodule
+ classdir = "/sys/class/net/" + iface + "/device/"
+ driverdir = "/sys/class/net/" + iface + "/device/driver/"
+ if os_path.exists(classdir):
+ classfiles = listdir(classdir)
+ driver_found = False
+ nl80211_found = False
+ for x in classfiles:
+ if x == 'driver':
+ driver_found = True
+ if x.startswith('ieee80211:'):
+ nl80211_found = True
+
+ if driver_found and nl80211_found:
+ #print about.getKernelVersionString()
+ self.wlanmodule = "nl80211"
+ else:
+ if driver_found and not nl80211_found:
+ driverfiles = listdir(driverdir)
+ if os_path.realpath(driverdir).endswith('ath_pci'):
+ if len(driverfiles) >= 1:
+ self.wlanmodule = 'madwifi'
+ if os_path.realpath(driverdir).endswith('rt73'):
+ if len(driverfiles) == 2 or len(driverfiles) == 5:
+ self.wlanmodule = 'ralink'
+ if os_path.realpath(driverdir).endswith('zd1211b'):
+ if len(driverfiles) == 1 or len(driverfiles) == 5:
+ self.wlanmodule = 'zydas'
+ if self.wlanmodule is None:
+ self.wlanmodule = "wext"
+ print 'Using "%s" as wpa-supplicant driver' % (self.wlanmodule)
+ return self.wlanmodule
def calc_netmask(self,nmask):
from struct import pack, unpack
diff --git a/lib/python/Components/NimManager.py b/lib/python/Components/NimManager.py
index 553de9c9..94f73a6a 100644
--- a/lib/python/Components/NimManager.py
+++ b/lib/python/Components/NimManager.py
@@ -110,9 +110,16 @@ class SecConfigure:
def setSatposDepends(self, sec, nim1, nim2):
print "tuner", nim1, "depends on satpos of", nim2
sec.setTunerDepends(nim1, nim2)
+
+ def linkInternally(self, slotid):
+ nim = self.NimManager.getNim(slotid)
+ if nim.internallyConnectableTo is not None:
+ nim.setInternalLink()
def linkNIMs(self, sec, nim1, nim2):
print "link tuner", nim1, "to tuner", nim2
+ if nim2 == (nim1 - 1):
+ self.linkInternally(nim1)
sec.setTunerLinked(nim1, nim2)
def getRoot(self, slotid, connto):
@@ -127,6 +134,9 @@ class SecConfigure:
def update(self):
sec = secClass.getInstance()
self.configuredSatellites = set()
+ for slotid in self.NimManager.getNimListOfType("DVB-S"):
+ if self.NimManager.nimInternallyConnectableTo(slotid) is not None:
+ self.NimManager.nimRemoveInternalLink(slotid)
sec.clear() ## this do unlinking NIMs too !!
print "sec config cleared"
@@ -140,7 +150,7 @@ class SecConfigure:
for slot in nim_slots:
if slot.type is not None:
- used_nim_slots.append((slot.slot, slot.description, slot.config.configMode.value != "nothing" and True or False, slot.isCompatible("DVB-S2")))
+ used_nim_slots.append((slot.slot, slot.description, slot.config.configMode.value != "nothing" and True or False, slot.isCompatible("DVB-S2"), slot.frontend_id is None and -1 or slot.frontend_id))
eDVBResourceManager.getInstance().setFrontendSlotInformations(used_nim_slots)
for slot in nim_slots:
@@ -380,6 +390,7 @@ class SecConfigure:
if currLnb.diseqcMode.value == "1_0":
currCO = currLnb.commandOrder1_0.value
+ sec.setRepeats(0)
else:
currCO = currLnb.commandOrder.value
@@ -471,7 +482,7 @@ class SecConfigure:
self.update()
class NIM(object):
- def __init__(self, slot, type, description, has_outputs = True, internally_connectable = None, multi_type = {}):
+ def __init__(self, slot, type, description, has_outputs = True, internally_connectable = None, multi_type = {}, frontend_id = None, i2c = None, is_empty = False):
self.slot = slot
if type not in ("DVB-S", "DVB-C", "DVB-T", "DVB-S2", None):
@@ -483,8 +494,13 @@ class NIM(object):
self.has_outputs = has_outputs
self.internally_connectable = internally_connectable
self.multi_type = multi_type
+ self.i2c = i2c
+ self.frontend_id = frontend_id
+ self.__is_empty = is_empty
def isCompatible(self, what):
+ if not self.isSupported():
+ return False
compatible = {
None: (None,),
"DVB-S": ("DVB-S", None),
@@ -517,15 +533,35 @@ class NIM(object):
def getSlotID(self):
return chr(ord('A') + self.slot)
+ def getI2C(self):
+ return self.i2c
+
def hasOutputs(self):
return self.has_outputs
def internallyConnectableTo(self):
return self.internally_connectable
+ def setInternalLink(self):
+ if self.internally_connectable is not None:
+ print "setting internal link on frontend id", self.frontend_id
+ open("/proc/stb/frontend/%d/rf_switch" % self.frontend_id, "w").write("internal")
+
+ def removeInternalLink(self):
+ if self.internally_connectable is not None:
+ print "removing internal link on frontend id", self.frontend_id
+ open("/proc/stb/frontend/%d/rf_switch" % self.frontend_id, "w").write("external")
+
def isMultiType(self):
return (len(self.multi_type) > 0)
+ def isEmpty(self):
+ return self.__is_empty
+
+ # empty tuners are supported!
+ def isSupported(self):
+ return (self.frontend_id is not None) or self.__is_empty
+
# returns dict {<slotid>: <type>}
def getMultiTypeList(self):
return self.multi_type
@@ -548,8 +584,10 @@ class NIM(object):
if self.empty:
nim_text += _("(empty)")
+ elif not self.isSupported():
+ nim_text += self.description + " (" + _("not supported") + ")"
else:
- nim_text += self.description + " (" + self.friendly_type + ")"
+ nim_text += self.description + " (" + self.friendly_type + ")"
return nim_text
@@ -667,14 +705,19 @@ class NimManager:
entries[current_slot] = {}
elif line.strip().startswith("Type:"):
entries[current_slot]["type"] = str(line.strip()[6:])
+ entries[current_slot]["isempty"] = False
elif line.strip().startswith("Name:"):
entries[current_slot]["name"] = str(line.strip()[6:])
+ entries[current_slot]["isempty"] = False
elif line.strip().startswith("Has_Outputs:"):
input = str(line.strip()[len("Has_Outputs:") + 1:])
entries[current_slot]["has_outputs"] = (input == "yes")
elif line.strip().startswith("Internally_Connectable:"):
input = int(line.strip()[len("Internally_Connectable:") + 1:])
entries[current_slot]["internally_connectable"] = input
+ elif line.strip().startswith("Frontend_Device:"):
+ input = int(line.strip()[len("Frontend_Device:") + 1:])
+ entries[current_slot]["frontend_device"] = input
elif line.strip().startswith("Mode"):
# "Mode 0: DVB-T" -> ["Mode 0", " DVB-T"]
split = line.strip().split(":")
@@ -683,22 +726,35 @@ class NimManager:
modes = entries[current_slot].get("multi_type", {})
modes[split2[1]] = split[1].strip()
entries[current_slot]["multi_type"] = modes
+ elif line.strip().startswith("I2C_Device:"):
+ input = int(line.strip()[len("I2C_Device:") + 1:])
+ entries[current_slot]["i2c"] = input
elif line.strip().startswith("empty"):
entries[current_slot]["type"] = None
entries[current_slot]["name"] = _("N/A")
+ entries[current_slot]["isempty"] = True
nimfile.close()
+ from os import path
+
for id, entry in entries.items():
if not (entry.has_key("name") and entry.has_key("type")):
entry["name"] = _("N/A")
entry["type"] = None
+ if not (entry.has_key("i2c")):
+ entry["i2c"] = None
if not (entry.has_key("has_outputs")):
entry["has_outputs"] = True
- if not (entry.has_key("internally_connectable")):
- entry["internally_connectable"] = None
+ if entry.has_key("frontend_device"): # check if internally connectable
+ if path.exists("/proc/stb/frontend/%d/rf_switch" % entry["frontend_device"]):
+ entry["internally_connectable"] = entry["frontend_device"] - 1
+ else:
+ entry["internally_connectable"] = None
+ else:
+ entry["frontend_device"] = entry["internally_connectable"] = None
if not (entry.has_key("multi_type")):
entry["multi_type"] = {}
- self.nim_slots.append(NIM(slot = id, description = entry["name"], type = entry["type"], has_outputs = entry["has_outputs"], internally_connectable = entry["internally_connectable"], multi_type = entry["multi_type"]))
+ self.nim_slots.append(NIM(slot = id, description = entry["name"], type = entry["type"], has_outputs = entry["has_outputs"], internally_connectable = entry["internally_connectable"], multi_type = entry["multi_type"], frontend_id = entry["frontend_device"], i2c = entry["i2c"], is_empty = entry["isempty"]))
def hasNimType(self, chktype):
for slot in self.nim_slots:
@@ -717,6 +773,12 @@ class NimManager:
def getNimName(self, slotid):
return self.nim_slots[slotid].description
+
+ def getNim(self, slotid):
+ return self.nim_slots[slotid]
+
+ def getI2CDevice(self, slotid):
+ return self.nim_slots[slotid].getI2C()
def getNimListOfType(self, type, exception = -1):
# returns a list of indexes for NIMs compatible to the given type, except for 'exception'
@@ -747,6 +809,12 @@ class NimManager:
def hasOutputs(self, slotid):
return self.nim_slots[slotid].hasOutputs()
+ def nimInternallyConnectableTo(self, slotid):
+ return self.nim_slots[slotid].internallyConnectableTo()
+
+ def nimRemoveInternalLink(self, slotid):
+ self.nim_slots[slotid].removeInternalLink()
+
def canConnectTo(self, slotid):
slots = []
if self.nim_slots[slotid].internallyConnectableTo() is not None:
@@ -1007,7 +1075,7 @@ def InitNimManager(nimmgr):
lnb_choices = {
"universal_lnb": _("Universal LNB"),
-# "unicable": _("Unicable"),
+ "unicable": _("Unicable"),
"c_band": _("C-Band"),
"user_defined": _("User defined")}
@@ -1208,7 +1276,7 @@ def InitNimManager(nimmgr):
section.latitude = ConfigFloat(default = [50,767], limits = [(0,359),(0,999)])
section.latitudeOrientation = ConfigSelection(latitude_orientation_choices, "north")
section.powerMeasurement = ConfigYesNo(default=True)
- section.powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm8000" and 15 or 50, limits=(0, 100))
+ section.powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm7025" and 50 or 15, limits=(0, 100))
section.turningSpeed = ConfigSelection(turning_speed_choices, "fast")
section.fastTurningBegin = ConfigDateTime(default=advanced_lnb_fast_turning_btime, formatstring = _("%H:%M"), increment = 600)
section.fastTurningEnd = ConfigDateTime(default=advanced_lnb_fast_turning_etime, formatstring = _("%H:%M"), increment = 600)
@@ -1337,7 +1405,7 @@ def InitNimManager(nimmgr):
nim = config.Nims[x]
if slot.isCompatible("DVB-S"):
- nim.toneAmplitude = ConfigSelection([("9", "600mV"), ("8", "700mV"), ("7", "800mV"), ("6", "900mV"), ("5", "1100mV")], "7")
+ nim.toneAmplitude = ConfigSelection([("11", "340mV"), ("10", "360mV"), ("9", "600mV"), ("8", "700mV"), ("7", "800mV"), ("6", "900mV"), ("5", "1100mV")], "7")
nim.toneAmplitude.fe_id = x - empty_slots
nim.toneAmplitude.slot_id = x
nim.toneAmplitude.addNotifier(toneAmplitudeChanged)
diff --git a/lib/python/Components/ParentalControl.py b/lib/python/Components/ParentalControl.py
index 9942bca7..0ea65cd2 100644
--- a/lib/python/Components/ParentalControl.py
+++ b/lib/python/Components/ParentalControl.py
@@ -21,6 +21,8 @@ IMG_BLACKSERVICE = LIST_BLACKLIST + "-" + TYPE_SERVICE
IMG_BLACKBOUQUET = LIST_BLACKLIST + "-" + TYPE_BOUQUET
def InitParentalControl():
+ global parentalControl
+ parentalControl = ParentalControl()
config.ParentalControl = ConfigSubsection()
config.ParentalControl.configured = ConfigYesNo(default = False)
config.ParentalControl.mode = ConfigSelection(default = "simple", choices = [("simple", _("simple")), ("complex", _("complex"))])
@@ -55,11 +57,10 @@ def InitParentalControl():
class ParentalControl:
def __init__(self):
#Do not call open on init, because bouquets are not ready at that moment
-# self.open()
+ self.open()
self.serviceLevel = {}
#Instead: Use Flags to see, if we already initialized config and called open
self.configInitialized = False
- self.filesOpened = False
#This is the timer that is used to see, if the time for caching the pin is over
#Of course we could also work without a timer and compare the times every
#time we call isServicePlayable. But this might probably slow down zapping,
@@ -89,9 +90,6 @@ class ParentalControl:
def isServicePlayable(self, ref, callback):
if not config.ParentalControl.configured.value or not config.ParentalControl.servicepinactive.value:
return True
- #Check if we already read the whitelists and blacklists. If not: call open
- if self.filesOpened == False:
- self.open()
#Check if configuration has already been read or if the significant values have changed.
#If true: read the configuration
if self.configInitialized == False or self.storeServicePin != config.ParentalControl.storeservicepin.value or self.storeServicePinCancel != config.ParentalControl.storeservicepincancel.value:
@@ -153,8 +151,6 @@ class ParentalControl:
def getProtectionType(self, service):
#New method used in ParentalControlList: This method does not only return
#if a service is protected or not, it also returns, why (whitelist or blacklist, service or bouquet)
- if self.filesOpened == False:
- self.open()
sImage = ""
if (config.ParentalControl.type.value == LIST_WHITELIST):
if self.whitelist.has_key(service):
@@ -319,14 +315,10 @@ class ParentalControl:
def save(self):
# we need to open the files in case we havent's read them yet
- if not self.filesOpened:
- self.open()
self.saveListToFile(LIST_BLACKLIST)
self.saveListToFile(LIST_WHITELIST)
def open(self):
self.openListFromFile(LIST_BLACKLIST)
self.openListFromFile(LIST_WHITELIST)
- self.filesOpened = True
-parentalControl = ParentalControl()
diff --git a/lib/python/Components/ParentalControlList.py b/lib/python/Components/ParentalControlList.py
index 797ea391..0e65257d 100644
--- a/lib/python/Components/ParentalControlList.py
+++ b/lib/python/Components/ParentalControlList.py
@@ -1,5 +1,5 @@
from MenuList import MenuList
-from Components.ParentalControl import parentalControl, IMG_WHITESERVICE, IMG_WHITEBOUQUET, IMG_BLACKSERVICE, IMG_BLACKBOUQUET
+from Components.ParentalControl import IMG_WHITESERVICE, IMG_WHITEBOUQUET, IMG_BLACKSERVICE, IMG_BLACKBOUQUET
from Tools.Directories import SCOPE_SKIN_IMAGE, resolveFilename
from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT
@@ -32,13 +32,14 @@ class ParentalControlList(MenuList):
self.l.setItemHeight(32)
def toggleSelectedLock(self):
+ from Components.ParentalControl import parentalControl
print "self.l.getCurrentSelection():", self.l.getCurrentSelection()
print "self.l.getCurrentSelectionIndex():", self.l.getCurrentSelectionIndex()
curSel = self.l.getCurrentSelection()
if curSel[0][2]:
parentalControl.unProtectService(self.l.getCurrentSelection()[0][0])
else:
- parentalControl.protectService(self.l.getCurrentSelection()[0][0])
+ parentalControl.protectService(self.l.getCurrentSelection()[0][0])
#Instead of just negating the locked- flag, now I call the getProtectionType every time...
self.list[self.l.getCurrentSelectionIndex()] = ParentalControlEntryComponent(curSel[0][0], curSel[0][1], parentalControl.getProtectionType(curSel[0][0]))
self.l.setList(self.list)
diff --git a/lib/python/Components/RecordingConfig.py b/lib/python/Components/RecordingConfig.py
index fe9284d9..40dfb2ca 100644..100755
--- a/lib/python/Components/RecordingConfig.py
+++ b/lib/python/Components/RecordingConfig.py
@@ -1,4 +1,4 @@
-from config import ConfigNumber, ConfigYesNo, ConfigSubsection, config
+from config import ConfigNumber, ConfigYesNo, ConfigSubsection, ConfigSelection, config
def InitRecordingConfig():
config.recording = ConfigSubsection();
@@ -8,3 +8,7 @@ def InitRecordingConfig():
config.recording.margin_after = ConfigNumber(default=0)
config.recording.debug = ConfigYesNo(default = False)
config.recording.ascii_filenames = ConfigYesNo(default = False)
+ config.recording.filename_composition = ConfigSelection(default = "standard", choices = [
+ ("standard", _("standard")),
+ ("short", _("Short filenames")),
+ ("long", _("Long filenames")) ] ) \ No newline at end of file
diff --git a/lib/python/Components/Renderer/Listbox.py b/lib/python/Components/Renderer/Listbox.py
index 640121e1..716fe445 100644..100755
--- a/lib/python/Components/Renderer/Listbox.py
+++ b/lib/python/Components/Renderer/Listbox.py
@@ -19,6 +19,7 @@ class Listbox(Renderer, object):
self.__content = None
self.__wrap_around = False
self.__selection_enabled = True
+ self.__scrollbarMode = "showOnDemand"
GUI_WIDGET = eListbox
@@ -38,6 +39,7 @@ class Listbox(Renderer, object):
instance.selectionChanged.get().append(self.selectionChanged)
self.wrap_around = self.wrap_around # trigger
self.selection_enabled = self.selection_enabled # trigger
+ self.scrollbarMode = self.scrollbarMode # trigger
def preWidgetRemove(self, instance):
instance.setContent(None)
@@ -76,9 +78,22 @@ class Listbox(Renderer, object):
selection_enabled = property(lambda self: self.__selection_enabled, setSelectionEnabled)
+ def setScrollbarMode(self, mode):
+ self.__scrollbarMode = mode
+ if self.instance is not None:
+ self.instance.setScrollbarMode(int(
+ { "showOnDemand": 0,
+ "showAlways": 1,
+ "showNever": 2,
+ }[mode]))
+
+ scrollbarMode = property(lambda self: self.__scrollbarMode, setScrollbarMode)
+
def changed(self, what):
if hasattr(self.source, "selectionEnabled"):
self.selection_enabled = self.source.selectionEnabled
+ if hasattr(self.source, "scrollbarMode"):
+ self.scrollbarMode = self.source.scrollbarMode
if len(what) > 1 and isinstance(what[1], str) and what[1] == "style":
return
self.content = self.source.content
diff --git a/lib/python/Components/ServiceList.py b/lib/python/Components/ServiceList.py
index 6095812a..cd055a82 100755..100644
--- a/lib/python/Components/ServiceList.py
+++ b/lib/python/Components/ServiceList.py
@@ -7,6 +7,8 @@ from Tools.LoadPixmap import LoadPixmap
from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN
+from Components.config import config
+
class ServiceList(HTMLComponent, GUIComponent):
MODE_NORMAL = 0
MODE_FAVOURITES = 1
@@ -62,6 +64,22 @@ class ServiceList(HTMLComponent, GUIComponent):
self.l.setColor(eListboxServiceContent.markedBackgroundSelected, parseColor(value))
elif attrib == "foregroundColorServiceNotAvail":
self.l.setColor(eListboxServiceContent.serviceNotAvail, parseColor(value))
+ elif attrib == "colorEventProgressbar":
+ self.l.setColor(eListboxServiceContent.serviceEventProgressbarColor, parseColor(value))
+ elif attrib == "colorEventProgressbarSelected":
+ self.l.setColor(eListboxServiceContent.serviceEventProgressbarColorSelected, parseColor(value))
+ elif attrib == "colorEventProgressbarBorder":
+ self.l.setColor(eListboxServiceContent.serviceEventProgressbarBorderColor, parseColor(value))
+ elif attrib == "colorEventProgressbarBorderSelected":
+ self.l.setColor(eListboxServiceContent.serviceEventProgressbarBorderColorSelected, parseColor(value))
+ elif attrib == "colorServiceDescription":
+ self.l.setColor(eListboxServiceContent.serviceDescriptionColor, parseColor(value))
+ elif attrib == "colorServiceDescriptionSelected":
+ self.l.setColor(eListboxServiceContent.serviceDescriptionColorSelected, parseColor(value))
+ elif attrib == "picServiceEventProgressbar":
+ pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value))
+ if pic:
+ self.l.setPixmap(self.l.picServiceEventProgressbar, pic)
elif attrib == "serviceItemHeight":
self.ItemHeight = int(value)
elif attrib == "serviceNameFont":
@@ -213,17 +231,24 @@ class ServiceList(HTMLComponent, GUIComponent):
def setMode(self, mode):
self.mode = mode
+ self.l.setItemHeight(self.ItemHeight)
+ self.l.setVisualMode(eListboxServiceContent.visModeComplex)
if mode == self.MODE_NORMAL:
- self.l.setItemHeight(self.ItemHeight)
- self.l.setVisualMode(eListboxServiceContent.visModeComplex)
+ if config.usage.show_event_progress_in_servicelist.value:
+ self.l.setElementPosition(self.l.celServiceEventProgressbar, eRect(0, 0, 52, self.ItemHeight))
+ else:
+ self.l.setElementPosition(self.l.celServiceEventProgressbar, eRect(0, 0, 0, 0))
self.l.setElementFont(self.l.celServiceName, self.ServiceNameFont)
self.l.setElementPosition(self.l.celServiceName, eRect(0, 0, self.instance.size().width(), self.ItemHeight))
self.l.setElementFont(self.l.celServiceInfo, self.ServiceInfoFont)
else:
- self.l.setItemHeight(self.ItemHeight)
- self.l.setVisualMode(eListboxServiceContent.visModeComplex)
+ if config.usage.show_event_progress_in_servicelist.value:
+ self.l.setElementPosition(self.l.celServiceEventProgressbar, eRect(60, 0, 52, self.ItemHeight))
+ else:
+ self.l.setElementPosition(self.l.celServiceEventProgressbar, eRect(60, 0, 0, 0))
self.l.setElementFont(self.l.celServiceNumber, self.ServiceNumberFont)
self.l.setElementPosition(self.l.celServiceNumber, eRect(0, 0, 50, self.ItemHeight))
self.l.setElementFont(self.l.celServiceName, self.ServiceNameFont)
self.l.setElementPosition(self.l.celServiceName, eRect(60, 0, self.instance.size().width()-60, self.ItemHeight))
self.l.setElementFont(self.l.celServiceInfo, self.ServiceInfoFont)
+
diff --git a/lib/python/Components/Task.py b/lib/python/Components/Task.py
index 2e4e757d..3a755405 100644
--- a/lib/python/Components/Task.py
+++ b/lib/python/Components/Task.py
@@ -64,11 +64,10 @@ class Job(object):
def runNext(self):
if self.current_task == len(self.tasks):
if len(self.resident_tasks) == 0:
- cb = self.callback
- self.callback = None
self.status = self.FINISHED
self.state_changed()
- cb(self, None, [])
+ self.callback(self, None, [])
+ self.callback = None
else:
print "still waiting for %d resident task(s) %s to finish" % (len(self.resident_tasks), str(self.resident_tasks))
else:
diff --git a/lib/python/Components/TimerSanityCheck.py b/lib/python/Components/TimerSanityCheck.py
index 8f48d1ec..b472a19e 100644
--- a/lib/python/Components/TimerSanityCheck.py
+++ b/lib/python/Components/TimerSanityCheck.py
@@ -12,8 +12,8 @@ class TimerSanityCheck:
self.simultimer = []
self.rep_eventlist = []
self.nrep_eventlist = []
- self.bflag = 1
- self.eflag = -1
+ self.bflag = -1
+ self.eflag = 1
def check(self, ext_timer=1):
print "check"
diff --git a/lib/python/Components/UsageConfig.py b/lib/python/Components/UsageConfig.py
index 60827107..b86c1a13 100644
--- a/lib/python/Components/UsageConfig.py
+++ b/lib/python/Components/UsageConfig.py
@@ -51,7 +51,14 @@ def InitUsageConfig():
config.usage.on_long_powerpress = ConfigSelection(default = "show_menu", choices = [
("show_menu", _("show shutdown menu")),
- ("shutdown", _("immediate shutdown")) ] )
+ ("shutdown", _("immediate shutdown")),
+ ("standby", _("Standby")) ] )
+
+ config.usage.on_short_powerpress = ConfigSelection(default = "standby", choices = [
+ ("show_menu", _("show shutdown menu")),
+ ("shutdown", _("immediate shutdown")),
+ ("standby", _("Standby")) ] )
+
config.usage.alternatives_priority = ConfigSelection(default = "0", choices = [
("0", "DVB-S/-C/-T"),
@@ -61,6 +68,8 @@ def InitUsageConfig():
("4", "DVB-T/-C/-S"),
("5", "DVB-T/-S/-C") ])
+ config.usage.show_event_progress_in_servicelist = ConfigYesNo(default = False)
+
config.usage.blinking_display_clock_during_recording = ConfigYesNo(default = False)
config.usage.show_message_when_recording_starts = ConfigYesNo(default = True)
diff --git a/lib/python/Components/VolumeControl.py b/lib/python/Components/VolumeControl.py
index 19fb90d7..38102926 100644
--- a/lib/python/Components/VolumeControl.py
+++ b/lib/python/Components/VolumeControl.py
@@ -8,6 +8,7 @@ from config import config, ConfigSubsection, ConfigInteger
profile("VolumeControl")
#TODO .. move this to a own .py file
class VolumeControl:
+ instance = None
"""Volume control, handles volUp, volDown, volMute actions and display
a corresponding dialog"""
def __init__(self, session):
@@ -16,6 +17,9 @@ class VolumeControl:
globalActionMap.actions["volumeDown"]=self.volDown
globalActionMap.actions["volumeMute"]=self.volMute
+ assert not VolumeControl.instance, "only one VolumeControl instance is allowed!"
+ VolumeControl.instance = self
+
config.audio = ConfigSubsection()
config.audio.volume = ConfigInteger(default = 100, limits = (0, 100))
diff --git a/lib/python/Components/config.py b/lib/python/Components/config.py
index d7506e31..6e560857 100755
--- a/lib/python/Components/config.py
+++ b/lib/python/Components/config.py
@@ -1624,16 +1624,17 @@ class Config(ConfigSubsection):
self.pickle_this("config", self.saved_value, result)
return ''.join(result)
- def unpickle(self, lines):
+ def unpickle(self, lines, base_file=True):
tree = { }
for l in lines:
if not l or l[0] == '#':
continue
n = l.find('=')
+ name = l[:n]
val = l[n+1:].strip()
- names = l[:n].split('.')
+ names = name.split('.')
# if val.find(' ') != -1:
# val = val[:val.find(' ')]
@@ -1644,6 +1645,15 @@ class Config(ConfigSubsection):
base[names[-1]] = val
+ if not base_file: # not the initial config file..
+ #update config.x.y.value when exist
+ try:
+ configEntry = eval(name)
+ if configEntry is not None:
+ configEntry.value = val
+ except (SyntaxError, KeyError):
+ pass
+
# we inherit from ConfigSubsection, so ...
#object.__setattr__(self, "saved_value", tree["config"])
if "config" in tree:
@@ -1655,9 +1665,9 @@ class Config(ConfigSubsection):
f.write(text)
f.close()
- def loadFromFile(self, filename):
+ def loadFromFile(self, filename, base_file=False):
f = open(filename, "r")
- self.unpickle(f.readlines())
+ self.unpickle(f.readlines(), base_file)
f.close()
config = Config()
@@ -1668,7 +1678,7 @@ class ConfigFile:
def load(self):
try:
- config.loadFromFile(self.CONFIG_FILE)
+ config.loadFromFile(self.CONFIG_FILE, True)
except IOError, e:
print "unable to load config (%s), assuming defaults..." % str(e)
diff --git a/lib/python/Plugins/DemoPlugins/Makefile.am b/lib/python/Plugins/DemoPlugins/Makefile.am
index aace17cc..9e16bfc1 100755
--- a/lib/python/Plugins/DemoPlugins/Makefile.am
+++ b/lib/python/Plugins/DemoPlugins/Makefile.am
@@ -1,6 +1,8 @@
installdir = $(pkglibdir)/python/Plugins/DemoPlugins
-SUBDIRS = TestPlugin
+SUBDIRS = TestPlugin TPMDemo
install_PYTHON = \
- __init__.py \ No newline at end of file
+ __init__.py
+
+ \ No newline at end of file
diff --git a/lib/python/Plugins/DemoPlugins/TPMDemo/Makefile.am b/lib/python/Plugins/DemoPlugins/TPMDemo/Makefile.am
new file mode 100644
index 00000000..3ccca98e
--- /dev/null
+++ b/lib/python/Plugins/DemoPlugins/TPMDemo/Makefile.am
@@ -0,0 +1,5 @@
+installdir = $(LIBDIR)/enigma2/python/Plugins/DemoPlugins/TPMDemo
+
+install_PYTHON = \
+ __init__.py \
+ plugin.py
diff --git a/lib/python/Plugins/DemoPlugins/TPMDemo/README b/lib/python/Plugins/DemoPlugins/TPMDemo/README
new file mode 100644
index 00000000..89a972aa
--- /dev/null
+++ b/lib/python/Plugins/DemoPlugins/TPMDemo/README
@@ -0,0 +1 @@
+Please read enigma2/doc/TPM for further instructions on how to integrate this into your own plugins. \ No newline at end of file
diff --git a/lib/python/Plugins/DemoPlugins/TPMDemo/__init__.py b/lib/python/Plugins/DemoPlugins/TPMDemo/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/lib/python/Plugins/DemoPlugins/TPMDemo/__init__.py
diff --git a/lib/python/Plugins/DemoPlugins/TPMDemo/plugin.py b/lib/python/Plugins/DemoPlugins/TPMDemo/plugin.py
new file mode 100644
index 00000000..2c078d35
--- /dev/null
+++ b/lib/python/Plugins/DemoPlugins/TPMDemo/plugin.py
@@ -0,0 +1,87 @@
+from Screens.Screen import Screen
+from Plugins.Plugin import PluginDescriptor
+from enigma import eTPM
+import sha
+
+def bin2long(s):
+ return reduce( lambda x,y:(x<<8L)+y, map(ord, s))
+
+def long2bin(l):
+ res = ""
+ for byte in range(128):
+ res += chr((l >> (1024 - (byte + 1) * 8)) & 0xff)
+ return res
+
+def rsa_pub1024(src, mod):
+ return long2bin(pow(bin2long(src), 65537, bin2long(mod)))
+
+def decrypt_block(src, mod):
+ if len(src) != 128 and len(src) != 202:
+ return None
+ dest = rsa_pub1024(src[:128], mod)
+ hash = sha.new(dest[1:107])
+ if len(src) == 202:
+ hash.update(src[131:192])
+ result = hash.digest()
+ if result == dest[107:127]:
+ return dest
+ return None
+
+def validate_cert(cert, key):
+ buf = decrypt_block(cert[8:], key)
+ if buf is None:
+ return None
+ return buf[36:107] + cert[139:196]
+
+def read_random():
+ try:
+ fd = open("/dev/urandom", "r")
+ buf = fd.read(8)
+ fd.close()
+ return buf
+ except:
+ return None
+
+def main(session, **kwargs):
+ try:
+ device = open("/proc/stb/info/model", "r").readline().strip()
+ except:
+ device = ""
+ if device != "dm7025":
+ rootkey = ['\x9f', '|', '\xe4', 'G', '\xc9', '\xb4', '\xf4', '#', '&', '\xce', '\xb3', '\xfe', '\xda', '\xc9', 'U', '`', '\xd8', '\x8c', 's', 'o', '\x90', '\x9b', '\\', 'b', '\xc0', '\x89', '\xd1', '\x8c', '\x9e', 'J', 'T', '\xc5', 'X', '\xa1', '\xb8', '\x13', '5', 'E', '\x02', '\xc9', '\xb2', '\xe6', 't', '\x89', '\xde', '\xcd', '\x9d', '\x11', '\xdd', '\xc7', '\xf4', '\xe4', '\xe4', '\xbc', '\xdb', '\x9c', '\xea', '}', '\xad', '\xda', 't', 'r', '\x9b', '\xdc', '\xbc', '\x18', '3', '\xe7', '\xaf', '|', '\xae', '\x0c', '\xe3', '\xb5', '\x84', '\x8d', '\r', '\x8d', '\x9d', '2', '\xd0', '\xce', '\xd5', 'q', '\t', '\x84', 'c', '\xa8', ')', '\x99', '\xdc', '<', '"', 'x', '\xe8', '\x87', '\x8f', '\x02', ';', 'S', 'm', '\xd5', '\xf0', '\xa3', '_', '\xb7', 'T', '\t', '\xde', '\xa7', '\xf1', '\xc9', '\xae', '\x8a', '\xd7', '\xd2', '\xcf', '\xb2', '.', '\x13', '\xfb', '\xac', 'j', '\xdf', '\xb1', '\x1d', ':', '?']
+
+ etpm = eTPM()
+ l2cert = etpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
+ if l2cert is None:
+ print "l2cert not found"
+ return
+
+ l2key = validate_cert(l2cert, rootkey)
+ if l2key is None:
+ print "l2cert invalid"
+ return
+
+ l3cert = etpm.getCert(eTPM.TPMD_DT_LEVEL3_CERT)
+ if l3cert is None:
+ print "l3cert not found (can be fixed by running the genuine dreambox plugin and running the offered update)"
+ return
+
+ l3key = validate_cert(l3cert, l2key)
+ if l3key is None:
+ print "l3cert invalid"
+ return
+
+ rnd = read_random()
+ if rnd is None:
+ print "random error"
+ return
+ val = etpm.challenge(rnd)
+ result = decrypt_block(val, l3key)
+ if device == "dm7025" or result[80:88] == rnd:
+ print "successfully finished the tpm test"
+ # would start your plugin here
+
+def Plugins(**kwargs):
+ return [PluginDescriptor(name = "TPM Demo", description = _("A demo plugin for TPM usage."), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = main),
+ PluginDescriptor(name = "TPM Demo", description = _("A demo plugin for TPM usage."), icon = "plugin.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc = main)]
+ \ No newline at end of file
diff --git a/lib/python/Plugins/Extensions/CutListEditor/meta/plugin_cutlisteditor.xml b/lib/python/Plugins/Extensions/CutListEditor/meta/plugin_cutlisteditor.xml
index 1431caf4..7132ba02 100755
--- a/lib/python/Plugins/Extensions/CutListEditor/meta/plugin_cutlisteditor.xml
+++ b/lib/python/Plugins/Extensions/CutListEditor/meta/plugin_cutlisteditor.xml
@@ -2,23 +2,14 @@
<prerequisites>
<tag type="Recording" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>CutListEditor</name>
<packagename>enigma2-plugin-extensions-cutlisteditor</packagename>
- <shortdescription>CutListEditor allows you to edit your movies.</shortdescription>
+ <shortdescription>CutListEditor allows you to edit your movies</shortdescription>
<description>CutListEditor allows you to edit your movies.\nSeek to the start of the stuff you want to cut away. Press OK, select 'start cut'.\nThen seek to the end, press OK, select 'end cut'. That's it.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_cutlisteditor.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>Schnitteditor</name>
- <packagename>enigma2-plugin-extensions-cutlisteditor</packagename>
- <shortdescription>Mit dem Schnitteditor können Sie Ihre Aufnahmen schneiden.</shortdescription>
- <description>Mit dem Schnitteditor können Sie Ihre Aufnahmen schneiden.\nSpulen Sie zum Anfang des zu schneidenden Teils der Aufnahme. Drücken Sie dann OK und wählen Sie: 'start cut'.\nDann spulen Sie zum Ende, drücken OK und wählen 'end cut'. Das ist alles.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_cutlisteditor.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-extensions-cutlisteditor" />
</files>
diff --git a/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py b/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py
index 53287a36..0b81cfdf 100755
--- a/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py
+++ b/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py
@@ -68,7 +68,7 @@ class DVDToolbox(Screen):
self["info"].text = ""
self["details"].setText("")
self.Console = Console()
- cmd = "/bin/dvd+rw-mediainfo /dev/" + harddiskmanager.getCD()
+ cmd = "dvd+rw-mediainfo /dev/" + harddiskmanager.getCD()
self.Console.ePopen(cmd, self.mediainfoCB)
def format(self):
@@ -186,7 +186,7 @@ class DVDformatTask(Task):
Task.__init__(self, job, ("RW medium format"))
self.toolbox = job.toolbox
self.postconditions.append(DVDformatTaskPostcondition())
- self.setTool("/bin/dvd+rw-format")
+ self.setTool("dvd+rw-format")
self.args += [ "/dev/" + harddiskmanager.getCD() ]
self.end = 1100
self.retryargs = [ ]
diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py
index b64541b6..e00dedd9 100644
--- a/lib/python/Plugins/Extensions/DVDBurn/Process.py
+++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py
@@ -95,6 +95,8 @@ class DemuxTask(Task):
self.relevantAudioPIDs = [ ]
self.getRelevantAudioPIDs(title)
self.generated_files = [ ]
+ self.mplex_audiofiles = { }
+ self.mplex_videofile = ""
self.mplex_streamfiles = [ ]
if len(self.cutlist) > 1:
self.args += [ "-cut", self.cutfile ]
@@ -132,8 +134,10 @@ class DemuxTask(Task):
def haveNewFile(self, file):
print "[DemuxTask] produced file:", file, self.currentPID
self.generated_files.append(file)
- if self.currentPID in self.relevantAudioPIDs or file.endswith("m2v"):
- self.mplex_streamfiles.append(file)
+ if self.currentPID in self.relevantAudioPIDs:
+ self.mplex_audiofiles[self.currentPID] = file
+ elif file.endswith("m2v"):
+ self.mplex_videofile = file
def haveProgress(self, progress):
#print "PROGRESS [%s]" % progress
@@ -167,6 +171,12 @@ class DemuxTask(Task):
f.close()
def cleanup(self, failed):
+ print "[DemuxTask::cleanup]"
+ self.mplex_streamfiles = [ self.mplex_videofile ]
+ for pid in self.relevantAudioPIDs:
+ self.mplex_streamfiles.append(self.mplex_audiofiles[pid])
+ print self.mplex_streamfiles
+
if failed:
import os
for file in self.generated_files:
diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py b/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py
index a52fad9f..71a7f239 100644
--- a/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py
+++ b/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py
@@ -32,9 +32,9 @@ class TitleCutter(CutListEditor):
pid = str(i.getPID())
if description == "MPEG":
description = "MP2"
- print "[audiotrack] pid:", pid, "description:", description, "language:", DVB_lang
+ print "[audiotrack] pid:", pid, "description:", description, "language:", DVB_lang, "count:", x, "active:", (x < 8)
self.t.properties.audiotracks.append(ConfigSubsection())
- self.t.properties.audiotracks[-1].active = ConfigYesNo(default = True)
+ self.t.properties.audiotracks[-1].active = ConfigYesNo(default = (x < 8))
self.t.properties.audiotracks[-1].format = ConfigFixedText(description)
self.t.properties.audiotracks[-1].language = ConfigSelection(choices = languageChoices.choices, default=languageChoices.getLanguage(DVB_lang))
self.t.properties.audiotracks[-1].pid = ConfigFixedText(pid)
diff --git a/lib/python/Plugins/Extensions/DVDBurn/meta/plugin_dvdburn.xml b/lib/python/Plugins/Extensions/DVDBurn/meta/plugin_dvdburn.xml
index 647d1cfd..c1e202a9 100755
--- a/lib/python/Plugins/Extensions/DVDBurn/meta/plugin_dvdburn.xml
+++ b/lib/python/Plugins/Extensions/DVDBurn/meta/plugin_dvdburn.xml
@@ -3,22 +3,17 @@
<tag type="Recording" />
<tag type="Software" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>DVDBurn</name>
<packagename>enigma2-plugin-extensions-dvdburn</packagename>
- <shortdescription>With DVDBurn you can burn your recordings to a dvd.</shortdescription>
- <description>With DVDBurn you can burn your recordings to a dvd.\nArchive all your favorite movies to recordable dvds with menus if wanted.</description>
+ <shortdescription>Burn your recordings to DVD</shortdescription>
+ <description>With DVDBurn you can make compilations of records from your Dreambox hard drive.\n
+ Optionally you can add customizable menus. You can record the compilation to a standard-compliant DVD that can be played on conventinal DVD players.\n
+ HDTV recordings can only be burned in proprietary dreambox format.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_dvdburn_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>DVDBurn</name>
- <packagename>enigma2-plugin-extensions-dvdburn</packagename>
- <shortdescription>Mit DVDBurn brennen Sie ihre Aufnahmen auf DVD.</shortdescription>
- <description>Mit DVDBurn brennen Sie ihre Aufnahmen auf DVD.\nArchivieren Sie Ihre Liblingsfilme auf DVD mit Menus wenn Sie es wünschen.</description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_dvdburn_de.jpg" />
- </info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-extensions-dvdburn" />
</files>
diff --git a/lib/python/Plugins/Extensions/DVDPlayer/meta/plugin_dvdplayer.xml b/lib/python/Plugins/Extensions/DVDPlayer/meta/plugin_dvdplayer.xml
index 1353f7d2..6fc5a6f1 100755
--- a/lib/python/Plugins/Extensions/DVDPlayer/meta/plugin_dvdplayer.xml
+++ b/lib/python/Plugins/Extensions/DVDPlayer/meta/plugin_dvdplayer.xml
@@ -2,23 +2,14 @@
<prerequisites>
<tag type="Multimedia" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>DVDPlayer</name>
<packagename>enigma2-plugin-extensions-dvdplayer</packagename>
- <shortdescription>DVDPlayer plays your DVDs on your Dreambox.</shortdescription>
+ <shortdescription>DVDPlayer plays your DVDs on your Dreambox</shortdescription>
<description>DVDPlayer plays your DVDs on your Dreambox.\nWith the DVDPlayer you can play your DVDs on your Dreambox from a DVD or even from an iso file or video_ts folder on your harddisc or network.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_dvdplayer.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>DVDPlayer</name>
- <packagename>enigma2-plugin-extensions-dvdplayer</packagename>
- <shortdescription>Spielen Sie Ihre DVDs mit dem DVDPlayer auf Ihrer Dreambox ab.</shortdescription>
- <description>Spielen Sie Ihre DVDs mit dem DVDPlayer auf Ihrer Dreambox ab.\nMit dem DVDPlayer können Sie Ihre DVDs auf Ihrer Dreambox abspielen. Dabei ist es egal ob Sie von DVD, iso-Datei oder sogar direkt von einer video_ts Ordnerstruktur von Ihrer Festplatte oder dem Netzwerk abspielen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_dvdplayer.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-extensions-dvdplayer" />
</files>
diff --git a/lib/python/Plugins/Extensions/DVDPlayer/plugin.py b/lib/python/Plugins/Extensions/DVDPlayer/plugin.py
index e092e82f..64b4ae50 100755
--- a/lib/python/Plugins/Extensions/DVDPlayer/plugin.py
+++ b/lib/python/Plugins/Extensions/DVDPlayer/plugin.py
@@ -88,8 +88,8 @@ class FileBrowser(Screen):
self.close(None)
class DVDSummary(Screen):
- skin = """
- <screen position="0,0" size="132,64">
+ skin = (
+ """<screen name="DVDSummary" position="0,0" size="132,64" id="1">
<widget source="session.CurrentService" render="Label" position="5,4" size="120,28" font="Regular;12" transparent="1" >
<convert type="ServiceName">Name</convert>
</widget>
@@ -101,7 +101,20 @@ class DVDSummary(Screen):
<widget source="session.CurrentService" render="Progress" position="6,46" size="60,18" borderWidth="1" >
<convert type="ServicePosition">Position</convert>
</widget>
- </screen>"""
+ </screen>""",
+ """<screen name="DVDSummary" position="0,0" size="96,64" id="2">
+ <widget source="session.CurrentService" render="Label" position="0,0" size="96,25" font="Regular;12" transparent="1" >
+ <convert type="ServiceName">Name</convert>
+ </widget>
+ <widget name="DVDPlayer" position="0,26" size="96,12" font="Regular;10" transparent="1" />
+ <widget name="Chapter" position="0,40" size="66,12" font="Regular;10" transparent="1" halign="left" />
+ <widget source="session.CurrentService" render="Label" position="66,40" size="30,12" font="Regular;10" transparent="1" halign="right" >
+ <convert type="ServicePosition">Position</convert>
+ </widget>
+ <widget source="session.CurrentService" render="Progress" position="0,52" size="96,12" borderWidth="1" >
+ <convert type="ServicePosition">Position</convert>
+ </widget>
+ </screen>""")
def __init__(self, session, parent):
Screen.__init__(self, session, parent)
diff --git a/lib/python/Plugins/Extensions/GraphMultiEPG/meta/plugin_graphmultiepg.xml b/lib/python/Plugins/Extensions/GraphMultiEPG/meta/plugin_graphmultiepg.xml
index a10840da..d3a2edf8 100755
--- a/lib/python/Plugins/Extensions/GraphMultiEPG/meta/plugin_graphmultiepg.xml
+++ b/lib/python/Plugins/Extensions/GraphMultiEPG/meta/plugin_graphmultiepg.xml
@@ -3,23 +3,14 @@
<tag type="EPG" />
<tag type="Recording" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>GraphMultiEPG</name>
- <packagename>eenigma2-plugin-extensions-graphmultiepg</packagename>
- <shortdescription>GraphMultiEPG shows a graphical timeline EPG.</shortdescription>
+ <packagename>enigma2-plugin-extensions-graphmultiepg</packagename>
+ <shortdescription>GraphMultiEPG shows a graphical timeline EPG</shortdescription>
<description>GraphMultiEPG shows a graphical timeline EPG.\nShows a nice overview of all running und upcoming tv shows.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_graphmultiepg_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>GraphMultiEPG</name>
- <packagename>enigma2-plugin-extensions-graphmultiepg</packagename>
- <shortdescription>Zeigt ein grafisches Zeitlinien-EPG.</shortdescription>
- <description>Zeigt ein grafisches Zeitlinien-EPG.\nZeigt eine grafische Übersicht aller laufenden und kommenden Sendungen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_graphmultiepg_de.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-extensions-graphmultiepg" />
</files>
diff --git a/lib/python/Plugins/Extensions/MediaPlayer/meta/plugin_mediaplayer.xml b/lib/python/Plugins/Extensions/MediaPlayer/meta/plugin_mediaplayer.xml
index 2f9f22bf..ffbb8e89 100755
--- a/lib/python/Plugins/Extensions/MediaPlayer/meta/plugin_mediaplayer.xml
+++ b/lib/python/Plugins/Extensions/MediaPlayer/meta/plugin_mediaplayer.xml
@@ -2,23 +2,14 @@
<prerequisites>
<tag type="Multimedia" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>MediaPlayer</name>
<packagename>enigma2-plugin-extensions-mediaplayer</packagename>
- <shortdescription>Mediaplayer plays your favorite music and videos.</shortdescription>
+ <shortdescription>Plays your favorite music and videos</shortdescription>
<description>Mediaplayer plays your favorite music and videos.\nPlay all your favorite music and video files, organize them in playlists, view cover and album information.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_mediaplayer_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>MediaPlayer</name>
- <packagename>enigma2-plugin-extensions-mediaplayer</packagename>
- <shortdescription>Mediaplayer spielt Ihre Musik und Videos.</shortdescription>
- <description>Mediaplayer spielt Ihre Musik und Videos.\nSie können all Ihre Musik- und Videodateien abspielen, in Playlisten organisieren, Cover und Albuminformationen abrufen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_mediaplayer_de.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-extensions-mediaplayer" />
</files>
diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py
index 036bbbb9..9ae886fc 100755
--- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py
+++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py
@@ -901,11 +901,11 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
def unPauseService(self):
self.setSeekState(self.SEEK_STATE_PLAY)
-
+
def subtitleSelection(self):
- from Screens.Subtitles import Subtitles
- self.session.open(Subtitles, self)
-
+ from Screens.AudioSelection import SubtitleSelection
+ self.session.open(SubtitleSelection, self)
+
def hotplugCB(self, dev, media_state):
if dev == harddiskmanager.getCD():
if media_state == "1":
@@ -925,12 +925,17 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
self.clear_playlist()
class MediaPlayerLCDScreen(Screen):
- skin = """
- <screen position="0,0" size="132,64" title="LCD Text">
+ skin = (
+ """<screen name="MediaPlayerLCDScreen" position="0,0" size="132,64" id="1">
<widget name="text1" position="4,0" size="132,35" font="Regular;16"/>
<widget name="text3" position="4,36" size="132,14" font="Regular;10"/>
<widget name="text4" position="4,49" size="132,14" font="Regular;10"/>
- </screen>"""
+ </screen>""",
+ """<screen name="MediaPlayerLCDScreen" position="0,0" size="96,64" id="2">
+ <widget name="text1" position="0,0" size="96,35" font="Regular;14"/>
+ <widget name="text3" position="0,36" size="96,14" font="Regular;10"/>
+ <widget name="text4" position="0,49" size="96,14" font="Regular;10"/>
+ </screen>""")
def __init__(self, session, parent):
Screen.__init__(self, session)
diff --git a/lib/python/Plugins/Extensions/MediaPlayer/settings.py b/lib/python/Plugins/Extensions/MediaPlayer/settings.py
index 0b95812f..7f42677d 100755
--- a/lib/python/Plugins/Extensions/MediaPlayer/settings.py
+++ b/lib/python/Plugins/Extensions/MediaPlayer/settings.py
@@ -12,6 +12,8 @@ config.mediaplayer.repeat = ConfigYesNo(default=False)
config.mediaplayer.savePlaylistOnExit = ConfigYesNo(default=True)
config.mediaplayer.saveDirOnExit = ConfigYesNo(default=False)
config.mediaplayer.defaultDir = ConfigDirectory()
+config.mediaplayer.useAlternateUserAgent = ConfigYesNo(default=False)
+config.mediaplayer.alternateUserAgent = ConfigText(default="")
class DirectoryBrowser(Screen, HelpableScreen):
diff --git a/lib/python/Plugins/Extensions/MediaScanner/meta/plugin_mediascanner.xml b/lib/python/Plugins/Extensions/MediaScanner/meta/plugin_mediascanner.xml
index eced924f..eb9de1b6 100755
--- a/lib/python/Plugins/Extensions/MediaScanner/meta/plugin_mediascanner.xml
+++ b/lib/python/Plugins/Extensions/MediaScanner/meta/plugin_mediascanner.xml
@@ -1,25 +1,15 @@
<default>
<prerequisites>
- <tag type="Multimedia" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>MediaScanner</name>
<packagename>enigma2-plugin-extensions-mediascanner</packagename>
- <shortdescription>MediaScanner scans devices for playable media files.</shortdescription>
+ <shortdescription>Scan devices for playable media files</shortdescription>
<description>MediaScanner scans devices for playable media files and displays a menu with possible actions like viewing pictures or playing movies.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_mediascanner_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>MediaScanner</name>
- <packagename>enigma2-plugin-extensions-mediascanner</packagename>
- <shortdescription>MediaScanner durchsucht Geräte nach Mediendateien.</shortdescription>
- <description>MediaScanner durchsucht Geräte nach Mediendateien und bietet Ihnen die dazu passenden Aktionen an wie z.B. Bilder betrachten oder Videos abspielen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_mediascanner_en.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-extensions-mediascanner" />
</files>
diff --git a/lib/python/Plugins/Extensions/PicturePlayer/meta/plugin_pictureplayer.xml b/lib/python/Plugins/Extensions/PicturePlayer/meta/plugin_pictureplayer.xml
index faff9785..16e2ec90 100755
--- a/lib/python/Plugins/Extensions/PicturePlayer/meta/plugin_pictureplayer.xml
+++ b/lib/python/Plugins/Extensions/PicturePlayer/meta/plugin_pictureplayer.xml
@@ -2,23 +2,14 @@
<prerequisites>
<tag type="Multimedia" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>PicturePlayer</name>
<packagename>enigma2-plugin-extensions-pictureplayer</packagename>
- <shortdescription>PicturePlayer displays your photos on the TV.</shortdescription>
+ <shortdescription>Display your photos on the TV</shortdescription>
<description>The PicturePlayer displays your photos on the TV.\nYou can view them as thumbnails or slideshow.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_pictureplayer.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>Bildbetrachter</name>
- <packagename>enigma2-plugin-extensions-pictureplayer</packagename>
- <shortdescription>Der Bildbetrachter zeigt Ihre Bilder auf dem Fernseher an.</shortdescription>
- <description>Der Bildbetrachter zeigt Ihre Bilder auf dem Fernseher an.\nSie können sich Ihre Bilder als Thumbnails, einzeln oder als Slideshow anzeigen lassen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_pictureplayer.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-extensions-pictureplayer" />
</files>
diff --git a/lib/python/Plugins/Extensions/SocketMMI/meta/plugin_socketmmi.xml b/lib/python/Plugins/Extensions/SocketMMI/meta/plugin_socketmmi.xml
index acf8374d..3eaf8fc5 100644..100755
--- a/lib/python/Plugins/Extensions/SocketMMI/meta/plugin_socketmmi.xml
+++ b/lib/python/Plugins/Extensions/SocketMMI/meta/plugin_socketmmi.xml
@@ -2,20 +2,13 @@
<prerequisites>
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>SocketMMI</name>
<packagename>enigma2-plugin-extensions-socketmmi</packagename>
- <shortdescription>Python frontend for /tmp/mmi.socket.</shortdescription>
+ <shortdescription>Frontend for /tmp/mmi.socket</shortdescription>
<description>Python frontend for /tmp/mmi.socket.</description>
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>SocketMMI</name>
- <packagename>enigma2-plugin-extensions-socketmmi</packagename>
- <shortdescription>Python frontend für /tmp/mmi.socket.</shortdescription>
- <description>Python frontend für /tmp/mmi.socket.</description>
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-extensions-socketmmi" />
</files>
diff --git a/lib/python/Plugins/Extensions/TuxboxPlugins/meta/plugin_tuxboxplugins.xml b/lib/python/Plugins/Extensions/TuxboxPlugins/meta/plugin_tuxboxplugins.xml
index 734c48f1..7ca10826 100644..100755
--- a/lib/python/Plugins/Extensions/TuxboxPlugins/meta/plugin_tuxboxplugins.xml
+++ b/lib/python/Plugins/Extensions/TuxboxPlugins/meta/plugin_tuxboxplugins.xml
@@ -2,20 +2,13 @@
<prerequisites>
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>TuxboxPlugins</name>
<packagename>TuxboxPlugins</packagename>
- <shortdescription>Allows the execution of TuxboxPlugins.</shortdescription>
+ <shortdescription>Execute TuxboxPlugins</shortdescription>
<description>Allows the execution of TuxboxPlugins.</description>
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>TuxboxPlugins</name>
- <packagename>enigma2-plugin-extensions-tuxboxplugins</packagename>
- <shortdescription>Erlaubt das Ausführen von TuxboxPlugins.</shortdescription>
- <description>Erlaubt das Ausführen von TuxboxPlugins.</description>
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-extensions-tuxboxplugins" />
</files>
diff --git a/lib/python/Plugins/Makefile.am b/lib/python/Plugins/Makefile.am
index f0435036..79d2b0b6 100644
--- a/lib/python/Plugins/Makefile.am
+++ b/lib/python/Plugins/Makefile.am
@@ -4,3 +4,4 @@ SUBDIRS = Extensions SystemPlugins DemoPlugins
install_PYTHON = \
__init__.py Plugin.py
+
diff --git a/lib/python/Plugins/SystemPlugins/CleanupWizard/meta/plugin_cleanupwizard.xml b/lib/python/Plugins/SystemPlugins/CleanupWizard/meta/plugin_cleanupwizard.xml
index 99add3d3..d0781af4 100755
--- a/lib/python/Plugins/SystemPlugins/CleanupWizard/meta/plugin_cleanupwizard.xml
+++ b/lib/python/Plugins/SystemPlugins/CleanupWizard/meta/plugin_cleanupwizard.xml
@@ -2,26 +2,16 @@
<prerequisites>
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>CleanupWizard</name>
<packagename>enigma2-plugin-systemplugins-cleanupwizard</packagename>
<shortdescription>Automatically informs you on low internal memory</shortdescription>
- <description>The CleanupWizard informs you when your internal free memory of your dreambox has droppen under 2MB.
- You can use this wizard to remove some extensions.
- </description>
+ <description>The CleanupWizard informs you when the internal free memory of your dreambox has dropped below a definable threshold.
+ You can use this wizard to remove some plugins. </description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_cleanupwizard_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>CleanupWizard</name>
- <packagename>enigma2-plugin-systemplugins-cleanupwizard</packagename>
- <shortdescription>Informiert Sie automatisch wenn der interne Speicher Ihrer Dreambox voll wird.</shortdescription>
- <description>Der CleanupWizard informiert Sie, wenn der interne freie Speicher Ihrer Dreambox unter 2MB fällt.
- Sie können dann einige Erweiterungen deinstallieren um wieder Platz zu schaffen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_cleanupwizard_de.jpg" />
- </info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-cleanupwizard" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/CommonInterfaceAssignment/meta/plugin_commoninterfaceassignment.xml b/lib/python/Plugins/SystemPlugins/CommonInterfaceAssignment/meta/plugin_commoninterfaceassignment.xml
index 9abc5986..f34f0a3c 100755
--- a/lib/python/Plugins/SystemPlugins/CommonInterfaceAssignment/meta/plugin_commoninterfaceassignment.xml
+++ b/lib/python/Plugins/SystemPlugins/CommonInterfaceAssignment/meta/plugin_commoninterfaceassignment.xml
@@ -4,28 +4,17 @@
<tag type="CI" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>CommonInterfaceAssignment</name>
<packagename>enigma2-plugin-systemplugins-commoninterfaceassignment</packagename>
- <shortdescription>Assigning providers/services/caids to a dedicated CI module</shortdescription>
- <description>With the CommonInterfaceAssignment extension it is possible to use different CI modules
- in your Dreambox and assign to each of them dedicated providers/services or caids.\n
- So it is then possible to watch a scrambled service while recording another one.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_ciassignment.jpg" />
- </info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>CommonInterfaceAssignment</name>
- <packagename>enigma2-plugin-systemplugins-commoninterfaceassignment</packagename>
- <shortdescription>Zuweisen von Providern/Services/CAIDs an ein CI Modul</shortdescription>
- <description>Mit der CommonInterfaceAssignment Erweiterung ist es möglich jedem CI Modul bestimmte Provider/Services/CAIDs zuzuweisen.\n
- So ist es möglich mit einem CI einen Sender aufzunehmen\n
- und mit einem anderen einen Sender zu schauen.
- </description>
+ <shortdescription>Assigning providers/services/caids to a CI module</shortdescription>
+ <description>With the CommonInterfaceAssignment plugin it is possible to use different
+ CI modules in your Dreambox and assign dedicated providers/services or caids to each of them.\n
+ This allows watching a scrambled service while recording another one.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_ciassignment.jpg" />
</info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-commoninterfaceassignment" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/__init__.py b/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/__init__.py
index e69de29b..7933e4cd 100755
--- a/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/__init__.py
+++ b/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/__init__.py
@@ -0,0 +1,40 @@
+import sha
+
+def bin2long(s):
+ return reduce( lambda x,y:(x<<8L)+y, map(ord, s))
+
+def long2bin(l):
+ res = ""
+ for byte in range(128):
+ res += chr((l >> (1024 - (byte + 1) * 8)) & 0xff)
+ return res
+
+def rsa_pub1024(src, mod):
+ return long2bin(pow(bin2long(src), 65537, bin2long(mod)))
+
+def decrypt_block(src, mod):
+ if len(src) != 128 and len(src) != 202:
+ return None
+ dest = rsa_pub1024(src[:128], mod)
+ hash = sha.new(dest[1:107])
+ if len(src) == 202:
+ hash.update(src[131:192])
+ result = hash.digest()
+ if result == dest[107:127]:
+ return dest
+ return None
+
+def validate_cert(cert, key):
+ buf = decrypt_block(cert[8:], key)
+ if buf is None:
+ return None
+ return buf[36:107] + cert[139:196]
+
+def read_random():
+ try:
+ fd = open("/dev/urandom", "r")
+ buf = fd.read(8)
+ fd.close()
+ return buf
+ except:
+ return None \ No newline at end of file
diff --git a/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/meta/plugin_crashlogautosubmit.xml b/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/meta/plugin_crashlogautosubmit.xml
index a118ed7f..3140b15f 100755
--- a/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/meta/plugin_crashlogautosubmit.xml
+++ b/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/meta/plugin_crashlogautosubmit.xml
@@ -2,26 +2,17 @@
<prerequisites>
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>CrashlogAutoSubmit</name>
<packagename>enigma2-plugin-systemplugins-crashlogautosubmit</packagename>
<shortdescription>Automatically send crashlogs to Dream Multimedia</shortdescription>
- <description>With the CrashlogAutoSubmit extension it is possible to automatically send crashlogs
- found on your Harddrive to Dream Multimedia
+ <description>With the CrashlogAutoSubmit plugin it is possible to automatically
+ mail crashlogs found on your hard drive to Dream Multimedia.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_crashlogautosubmit_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>CrashlogAutoSubmit</name>
- <packagename>enigma2-plugin-systemplugins-crashlogautosubmit</packagename>
- <shortdescription>Automatisches versenden von Crashlogs an Dream Multimedia</shortdescription>
- <description>Mit dem CrashlogAutoSubmit Plugin ist es möglich auf Ihrer Festplatte
- gefundene Crashlogs automatisch an Dream Multimedia zu versenden.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_crashlogautosubmit_de.jpg" />
- </info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-crashlogautosubmit" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/plugin.py b/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/plugin.py
index 25639818..92c16289 100755
--- a/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/CrashlogAutoSubmit/plugin.py
@@ -8,12 +8,13 @@ from Screens.Screen import Screen
from Screens.VirtualKeyBoard import VirtualKeyBoard
from Screens.ChoiceBox import ChoiceBox
from Screens.MessageBox import MessageBox
-from enigma import ePoint
+from enigma import ePoint, eTPM
from Tools import Notifications
import os
from twisted.mail import smtp, relaymanager
import MimeWriter, mimetools, StringIO
+from __init__ import bin2long, long2bin, rsa_pub1024, decrypt_block, validate_cert, read_random
config.plugins.crashlogautosubmit = ConfigSubsection()
config.plugins.crashlogautosubmit.sendmail = ConfigSelection(default = "send", choices = [
@@ -376,11 +377,36 @@ def callCrashMailer(result,session):
def autostart(reason, **kwargs):
print "[CrashlogAutoSubmit] - autostart"
- if "session" in kwargs:
- try:
- startMailer(kwargs["session"])
- except ImportError, e:
- print "[CrashlogAutoSubmit] Twisted-mail not available, not starting CrashlogAutoSubmitter", e
+ try:
+ device = open("/proc/stb/info/model", "r").readline().strip()
+ except:
+ device = ""
+ if device != "dm7025":
+ rootkey = ['\x9f', '|', '\xe4', 'G', '\xc9', '\xb4', '\xf4', '#', '&', '\xce', '\xb3', '\xfe', '\xda', '\xc9', 'U', '`', '\xd8', '\x8c', 's', 'o', '\x90', '\x9b', '\\', 'b', '\xc0', '\x89', '\xd1', '\x8c', '\x9e', 'J', 'T', '\xc5', 'X', '\xa1', '\xb8', '\x13', '5', 'E', '\x02', '\xc9', '\xb2', '\xe6', 't', '\x89', '\xde', '\xcd', '\x9d', '\x11', '\xdd', '\xc7', '\xf4', '\xe4', '\xe4', '\xbc', '\xdb', '\x9c', '\xea', '}', '\xad', '\xda', 't', 'r', '\x9b', '\xdc', '\xbc', '\x18', '3', '\xe7', '\xaf', '|', '\xae', '\x0c', '\xe3', '\xb5', '\x84', '\x8d', '\r', '\x8d', '\x9d', '2', '\xd0', '\xce', '\xd5', 'q', '\t', '\x84', 'c', '\xa8', ')', '\x99', '\xdc', '<', '"', 'x', '\xe8', '\x87', '\x8f', '\x02', ';', 'S', 'm', '\xd5', '\xf0', '\xa3', '_', '\xb7', 'T', '\t', '\xde', '\xa7', '\xf1', '\xc9', '\xae', '\x8a', '\xd7', '\xd2', '\xcf', '\xb2', '.', '\x13', '\xfb', '\xac', 'j', '\xdf', '\xb1', '\x1d', ':', '?']
+ etpm = eTPM()
+ l2cert = etpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
+ if l2cert is None:
+ return
+ l2key = validate_cert(l2cert, rootkey)
+ if l2key is None:
+ return
+ l3cert = etpm.getCert(eTPM.TPMD_DT_LEVEL3_CERT)
+ if l3cert is None:
+ return
+ l3key = validate_cert(l3cert, l2key)
+ if l3key is None:
+ return
+ rnd = read_random()
+ if rnd is None:
+ return
+ val = etpm.challenge(rnd)
+ result = decrypt_block(val, l3key)
+ if device == "dm7025" or result[80:88] == rnd:
+ if "session" in kwargs:
+ try:
+ startMailer(kwargs["session"])
+ except ImportError, e:
+ print "[CrashlogAutoSubmit] Twisted-mail not available, not starting CrashlogAutoSubmitter", e
def openconfig(session, **kwargs):
diff --git a/lib/python/Plugins/SystemPlugins/DefaultServicesScanner/meta/plugin_defaultservicesscanner.xml b/lib/python/Plugins/SystemPlugins/DefaultServicesScanner/meta/plugin_defaultservicesscanner.xml
index 41d41ed6..74b7886f 100755
--- a/lib/python/Plugins/SystemPlugins/DefaultServicesScanner/meta/plugin_defaultservicesscanner.xml
+++ b/lib/python/Plugins/SystemPlugins/DefaultServicesScanner/meta/plugin_defaultservicesscanner.xml
@@ -1,26 +1,18 @@
<default>
<prerequisites>
<tag type="SAT" />
- <tag type="System" />
+ <tag type="Default" />
</prerequisites>
<info language="en">
<author>Dream Multimedia</author>
<name>DefaultServicesScanner</name>
<packagename>enigma2-plugin-systemplugins-defaultservicesscanner</packagename>
- <shortdescription>Scans default lamedbs sorted by satellite with a connected dish positioner.</shortdescription>
- <description>With the DefaultServicesScanner extension you can scan default lamedbs sorted by satellite with a connected dish positioner.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_defaultservicescanner.jpg" />
- </info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>DefaultServicesScanner</name>
- <packagename>enigma2-plugin-systemplugins-defaultservicesscanner</packagename>
- <shortdescription>Standard Sendersuche nach Satellit mit einem Rotor.</shortdescription>
- <description>Mit der DefaultServicesScanner Erweiterung können Sie eine standard Sendersuche nach Satellit mit einem angeschlossenen Rotor durchführen.
+ <shortdescription>Scans default lamedbs sorted by satellite</shortdescription>
+ <description>With the DefaultServicesScanner plugin you can scan default lamedbs sorted by satellite with a connected dish positioner.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_defaultservicescanner.jpg" />
</info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-defaultservicesscanner" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/DiseqcTester/meta/plugin_diseqctester.xml b/lib/python/Plugins/SystemPlugins/DiseqcTester/meta/plugin_diseqctester.xml
index 33808b3e..567618b2 100755
--- a/lib/python/Plugins/SystemPlugins/DiseqcTester/meta/plugin_diseqctester.xml
+++ b/lib/python/Plugins/SystemPlugins/DiseqcTester/meta/plugin_diseqctester.xml
@@ -3,24 +3,16 @@
<tag type="SAT" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>DiseqcTester</name>
<packagename>enigma2-plugin-systemplugins-diseqctester</packagename>
- <shortdescription>Test your Diseqc equipment.</shortdescription>
- <description>With the DiseqcTester extension you can test your satellite equipment for Diseqc compatibility and errors.
+ <shortdescription>Test your DiSEqC equipment</shortdescription>
+ <description>With the DiseqcTester plugin you can test your satellite equipment for DiSEqC compatibility and errors.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_diseqctester_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>DiseqcTester</name>
- <packagename>enigma2-plugin-systemplugins-diseqctester</packagename>
- <shortdescription>Testet Ihr Diseqc Equipment.</shortdescription>
- <description>Mit der DiseqcTester Erweiterung können Sie Ihr Satelliten-Equipment nach Diseqc-Kompatibilität und Fehlern überprüfen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_diseqctester_de.jpg" />
- </info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-diseqctester" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/FrontprocessorUpgrade/meta/plugin_frontprocessorupgrade.xml b/lib/python/Plugins/SystemPlugins/FrontprocessorUpgrade/meta/plugin_frontprocessorupgrade.xml
index 1763f67f..7b6fdca7 100644..100755
--- a/lib/python/Plugins/SystemPlugins/FrontprocessorUpgrade/meta/plugin_frontprocessorupgrade.xml
+++ b/lib/python/Plugins/SystemPlugins/FrontprocessorUpgrade/meta/plugin_frontprocessorupgrade.xml
@@ -3,24 +3,16 @@
<hardware type="dm8000" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>FrontprocessorUpgrade</name>
<packagename>enigma2-plugin-systemplugins-frontprocessorupgrade</packagename>
<packagetype>internal</packagetype> <!-- internal/public , public is default, internal metas are not displayed inside plugin manager -->
- <shortdescription>Internal firmware updater.</shortdescription>
+ <shortdescription>Internal firmware updater</shortdescription>
<description>This system tool is internally used to program the hardware with firmware updates.
</description>
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>FrontprocessorUpgrade</name>
- <packagename>enigma2-plugin-systemplugins-frontprocessorupgrade</packagename>
- <packagetype>internal</packagetype> <!-- internal/public , public is default, internal metas are not displayed inside plugin manager -->
- <shortdescription>Interner Firmware-Upgrader.</shortdescription>
- <description>Dieses Systemtool wird intern benutzt um Firmware-Upgrades für die Hardware aufzuspielen.
- </description>
- </info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-frontprocessorupgrade" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/Hotplug/meta/plugin_hotplug.xml b/lib/python/Plugins/SystemPlugins/Hotplug/meta/plugin_hotplug.xml
index 6c2824ca..610dfee6 100644..100755
--- a/lib/python/Plugins/SystemPlugins/Hotplug/meta/plugin_hotplug.xml
+++ b/lib/python/Plugins/SystemPlugins/Hotplug/meta/plugin_hotplug.xml
@@ -2,22 +2,15 @@
<prerequisites>
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>Hotplug</name>
<packagename>enigma2-plugin-systemplugins-hotplug</packagename>
- <shortdescription>Hotplugging for removeable devices.</shortdescription>
- <description>The Hotplug extension notifies your system of newly added or removed devices.
- </description>
- </info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>Hotplug</name>
- <packagename>enigma2-plugin-systemplugins-hotplug</packagename>
- <shortdescription>Hotplugging für entfernbare Geräte.</shortdescription>
- <description>Mit der Hotplug-Erweiterung wird Ihr System über neu angeschlossene oder entfernte Geräte informiert.
+ <shortdescription>Hotplugging for removeable devices</shortdescription>
+ <description>The Hotplug plugin notifies your system of newly added or removed devices.
</description>
</info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-hotplug" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/NFIFlash/dm8000_writenand b/lib/python/Plugins/SystemPlugins/NFIFlash/dm8000_writenand
deleted file mode 100755
index bd02d8fe..00000000
--- a/lib/python/Plugins/SystemPlugins/NFIFlash/dm8000_writenand
+++ /dev/null
Binary files differ
diff --git a/lib/python/Plugins/SystemPlugins/NFIFlash/downloader.py b/lib/python/Plugins/SystemPlugins/NFIFlash/downloader.py
index 6463f179..296d3bca 100644
--- a/lib/python/Plugins/SystemPlugins/NFIFlash/downloader.py
+++ b/lib/python/Plugins/SystemPlugins/NFIFlash/downloader.py
@@ -1,72 +1,222 @@
# -*- coding: utf-8 -*-
-from Components.MenuList import MenuList
+from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
from Screens.Screen import Screen
from Screens.MessageBox import MessageBox
from Screens.ChoiceBox import ChoiceBox
+from Screens.HelpMenu import HelpableScreen
+from Screens.TaskView import JobView
+from Components.About import about
from Components.ActionMap import ActionMap
from Components.Sources.StaticText import StaticText
-from Components.Sources.Progress import Progress
+from Components.Sources.List import List
from Components.Label import Label
from Components.FileList import FileList
+from Components.MenuList import MenuList
from Components.MultiContent import MultiContentEntryText
from Components.ScrollLabel import ScrollLabel
-from Tools.Directories import fileExists
+from Components.Harddisk import harddiskmanager
+from Components.Task import Task, Job, job_manager, Condition
+from Tools.Directories import fileExists, isMount
from Tools.HardwareInfo import HardwareInfo
-from enigma import eConsoleAppContainer, eListbox, gFont, eListboxPythonMultiContent, \
- RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, RT_WRAP, eRect, eTimer
-from os import system, remove
-import re
-import urllib
from Tools.Downloader import downloadWithProgress
+from enigma import eConsoleAppContainer, gFont, RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, RT_WRAP, eTimer
+from os import system, path, access, stat, remove, W_OK, R_OK
from twisted.web import client
from twisted.internet import reactor, defer
from twisted.python import failure
-from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
-
-class UserRequestedCancel(Exception):
- pass
-
-class Feedlist(MenuList):
- def __init__(self, list=[], enableWrapAround = False):
- MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
- self.l.setFont(0, gFont("Regular", 16))
- self.l.setItemHeight(22)
+import re
- def clear(self):
- del self.list[:]
- self.l.setList(self.list)
+class ImageDownloadJob(Job):
+ def __init__(self, url, filename, device=None, mountpoint="/"):
+ Job.__init__(self, _("Download .NFI-Files for USB-Flasher"))
+ if device:
+ if isMount(mountpoint):
+ UmountTask(self, mountpoint)
+ MountTask(self, device, mountpoint)
+ ImageDownloadTask(self, url, mountpoint+filename)
+ ImageDownloadTask(self, url[:-4]+".nfo", mountpoint+filename[:-4]+".nfo")
+ #if device:
+ #UmountTask(self, mountpoint)
+
+ def retry(self):
+ self.tasks[0].args += self.tasks[0].retryargs
+ Job.retry(self)
+
+class MountTask(Task):
+ def __init__(self, job, device, mountpoint):
+ Task.__init__(self, job, ("mount"))
+ self.setTool("mount")
+ options = "rw,sync"
+ self.mountpoint = mountpoint
+ self.args += [ device, mountpoint, "-o"+options ]
+ self.weighting = 1
+
+ def processOutput(self, data):
+ print "[MountTask] output:", data
+
+class UmountTask(Task):
+ def __init__(self, job, mountpoint):
+ Task.__init__(self, job, ("mount"))
+ self.setTool("umount")
+ self.args += [mountpoint]
+ self.weighting = 1
+
+class DownloaderPostcondition(Condition):
+ def check(self, task):
+ return task.returncode == 0
+
+ def getErrorMessage(self, task):
+ return self.error_message
+
+class ImageDownloadTask(Task):
+ def __init__(self, job, url, path):
+ Task.__init__(self, job, _("Downloading"))
+ self.postconditions.append(DownloaderPostcondition())
+ self.job = job
+ self.url = url
+ self.path = path
+ self.error_message = ""
+ self.last_recvbytes = 0
+ self.error_message = None
+ self.download = None
+ self.aborted = False
- def getNFIname(self):
- l = self.l.getCurrentSelection()
- return l and l[0][0]
+ def run(self, callback):
+ self.callback = callback
+ self.download = downloadWithProgress(self.url,self.path)
+ self.download.addProgress(self.download_progress)
+ self.download.start().addCallback(self.download_finished).addErrback(self.download_failed)
+ print "[ImageDownloadTask] downloading", self.url, "to", self.path
- def getNFIurl(self):
- l = self.l.getCurrentSelection()
- return l and l[0][1]
+ def abort(self):
+ print "[ImageDownloadTask] aborting", self.url
+ if self.download:
+ self.download.stop()
+ self.aborted = True
- def getNFOname(self):
- l = self.l.getCurrentSelection()
- return l and l[0][0][:-3]+"nfo"
+ def download_progress(self, recvbytes, totalbytes):
+ #print "[update_progress] recvbytes=%d, totalbytes=%d" % (recvbytes, totalbytes)
+ if ( recvbytes - self.last_recvbytes ) > 10000: # anti-flicker
+ self.progress = int(100*(float(recvbytes)/float(totalbytes)))
+ self.name = _("Downloading") + ' ' + "%d of %d kBytes" % (recvbytes/1024, totalbytes/1024)
+ self.last_recvbytes = recvbytes
- def getNFOurl(self):
- l = self.l.getCurrentSelection()
- return l and l[0][1][:-3]+"nfo"
+ def download_failed(self, failure_instance=None, error_message=""):
+ self.error_message = error_message
+ if error_message == "" and failure_instance is not None:
+ self.error_message = failure_instance.getErrorMessage()
+ Task.processFinished(self, 1)
- def isValid(self):
- l = self.l.getCurrentSelection()
- if not l or l[0] == 0:
- return False
+ def download_finished(self, string=""):
+ if self.aborted:
+ self.finish(aborted = True)
+ else:
+ Task.processFinished(self, 0)
+
+class StickWizardJob(Job):
+ def __init__(self, path):
+ Job.__init__(self, _("USB stick wizard"))
+ self.path = path
+ self.device = path
+ while self.device[-1:] == "/" or self.device[-1:].isdigit():
+ self.device = self.device[:-1]
+
+ box = HardwareInfo().get_device_name()
+ url = "http://www.dreamboxupdate.com/download/opendreambox/dreambox-nfiflasher-%s.tar.bz2" % box
+ self.downloadfilename = "/tmp/dreambox-nfiflasher-%s.tar.bz2" % box
+ self.imagefilename = "/tmp/nfiflash_%s.img" % box
+ #UmountTask(self, device)
+ PartitionTask(self)
+ ImageDownloadTask(self, url, self.downloadfilename)
+ UnpackTask(self)
+ CopyTask(self)
+
+class PartitionTaskPostcondition(Condition):
+ def check(self, task):
+ return task.returncode == 0
+
+ def getErrorMessage(self, task):
+ return {
+ task.ERROR_BLKRRPART: ("Device or resource busy"),
+ task.ERROR_UNKNOWN: (task.errormsg)
+ }[task.error]
+
+class PartitionTask(Task):
+ ERROR_UNKNOWN, ERROR_BLKRRPART = range(2)
+ def __init__(self, job):
+ Task.__init__(self, job, ("partitioning"))
+ self.postconditions.append(PartitionTaskPostcondition())
+ self.job = job
+ self.setTool("sfdisk")
+ self.args += [self.job.device]
+ self.weighting = 10
+ self.initial_input = "0 - 0x6 *\n;\n;\n;\ny"
+ self.errormsg = ""
+
+ def run(self, callback):
+ Task.run(self, callback)
+
+ def processOutput(self, data):
+ print "[PartitionTask] output:", data
+ if data.startswith("BLKRRPART:"):
+ self.error = self.ERROR_BLKRRPART
else:
- return True
+ self.error = self.ERROR_UNKNOWN
+ self.errormsg = data
+
+class UnpackTask(Task):
+ def __init__(self, job):
+ Task.__init__(self, job, ("Unpacking USB flasher image..."))
+ self.job = job
+ self.setTool("tar")
+ self.args += ["-xjvf", self.job.downloadfilename]
+ self.weighting = 80
+ self.end = 80
+ self.delayTimer = eTimer()
+ self.delayTimer.callback.append(self.progress_increment)
+
+ def run(self, callback):
+ Task.run(self, callback)
+ self.delayTimer.start(950, False)
+
+ def progress_increment(self):
+ self.progress += 1
+
+ def processOutput(self, data):
+ print "[UnpackTask] output: \'%s\'" % data
+ self.job.imagefilename = data
+
+ def afterRun(self):
+ self.delayTimer.callback.remove(self.progress_increment)
+
+class CopyTask(Task):
+ def __init__(self, job):
+ Task.__init__(self, job, ("Copying USB flasher boot image to stick..."))
+ self.job = job
+ self.setTool("dd")
+ self.args += ["if=%s" % self.job.imagefilename, "of=%s1" % self.job.device]
+ self.weighting = 20
+ self.end = 20
+ self.delayTimer = eTimer()
+ self.delayTimer.callback.append(self.progress_increment)
+
+ def run(self, callback):
+ Task.run(self, callback)
+ self.delayTimer.start(100, False)
+
+ def progress_increment(self):
+ self.progress += 1
+
+ def processOutput(self, data):
+ print "[CopyTask] output:", data
- def moveSelection(self,idx=0):
- if self.instance is not None:
- self.instance.moveSelectionTo(idx)
+ def afterRun(self):
+ self.delayTimer.callback.remove(self.progress_increment)
class NFOViewer(Screen):
skin = """
- <screen name="NFOViewer" position="110,115" size="540,400" title="Changelog viewer" >
- <widget name="changelog" position="10,10" size="520,380" font="Regular;16" />
+ <screen name="NFOViewer" position="center,center" size="610,410" title="Changelog" >
+ <widget name="changelog" position="10,10" size="590,380" font="Regular;16" />
</screen>"""
def __init__(self, session, nfo):
@@ -80,206 +230,37 @@ class NFOViewer(Screen):
"ok": self.exit,
"cancel": self.exit,
"down": self.pageDown,
- "up": self.pageUp
+ "up": self.pageUp
})
def pageUp(self):
self["changelog"].pageUp()
def pageDown(self):
self["changelog"].pageDown()
-
+
def exit(self):
self.close(False)
-class NFIDownload(Screen):
- LIST_SOURCE = 1
- LIST_DEST = 2
- skin = """
- <screen name="NFIDownload" position="90,95" size="560,420" title="Image download utility">
- <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
- <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
- <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
- <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
- <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#9f1313" transparent="1" />
- <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
- <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#a08500" transparent="1" />
- <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#18188b" transparent="1" />
-
- <widget source="label_top" render="Label" position="10,44" size="240,20" font="Regular;16" />
- <widget name="feedlist" position="10,66" size="250,222" scrollbarMode="showOnDemand" />
- <widget name="destlist" position="0,66" size="260,222" scrollbarMode="showOnDemand" />
-
- <widget source="label_bottom" render="Label" position="10,312" size="240,18" font="Regular;16"/>
- <widget source="path_bottom" render="Label" position="10,330" size="250,42" font="Regular;18" />
-
- <widget source="infolabel" render="Label" position="270,44" size="280,284" font="Regular;16" />
- <widget source="job_progressbar" render="Progress" position="10,374" size="540,26" borderWidth="1" backgroundColor="#254f7497" />
- <widget source="job_progresslabel" render="Label" position="130,378" zPosition="2" font="Regular;18" halign="center" transparent="1" size="300,22" foregroundColor="#000000" />
- <widget source="statusbar" render="Label" position="10,404" size="540,16" font="Regular;16" foregroundColor="#cccccc" />
- </screen>"""
-
- def __init__(self, session, destdir="/tmp/"):
- self.skin = NFIDownload.skin
- Screen.__init__(self, session)
-
- self["job_progressbar"] = Progress()
- self["job_progresslabel"] = StaticText()
-
- self["infolabel"] = StaticText()
- self["statusbar"] = StaticText()
- self["label_top"] = StaticText()
- self["label_bottom"] = StaticText()
- self["path_bottom"] = StaticText()
-
- self["key_green"] = StaticText()
- self["key_yellow"] = StaticText()
- self["key_blue"] = StaticText()
-
- self["key_red"] = StaticText()
-
- self["feedlist"] = Feedlist([0,(eListboxPythonMultiContent.TYPE_TEXT, 0, 0,250, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, "feed not available")])
- self["destlist"] = FileList(destdir, showDirectories = True, showFiles = False)
- self["destlist"].hide()
-
- self.download_container = eConsoleAppContainer()
- self.nfo = ""
- self.nfofile = ""
- self.feedhtml = ""
- self.focus = None
- self.download = None
- self.box = HardwareInfo().get_device_name()
- self.feed_base = "http://www.dreamboxupdate.com/opendreambox/1.5/%s/images/" % self.box
- self.nfi_filter = "" # "release" # only show NFIs containing this string, or all if ""
- self.wizard_mode = False
-
- self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "EPGSelectActions"],
- {
- "cancel": self.closeCB,
- "red": self.closeCB,
- "green": self.nfi_download,
- "yellow": self.switchList,
- "blue": self.askCreateUSBstick,
- "prevBouquet": self.switchList,
- "nextBouquet": self.switchList,
- "ok": self.ok,
- "left": self.left,
- "right": self.right,
- "up": self.up,
- "upRepeated": self.up,
- "downRepeated": self.down,
- "down": self.down
- }, -1)
-
- self.feed_download()
-
- def downloading(self, state=True):
- if state is True:
- self["key_red"].text = _("Cancel")
- self["key_green"].text = ""
- self["key_yellow"].text = ""
- self["key_blue"].text = ""
- else:
- self.download = None
- self["key_red"].text = _("Exit")
- if self["feedlist"].isValid():
- self["key_green"].text = (_("Download"))
- if self.focus is self.LIST_SOURCE:
- self["key_yellow"].text = (_("Change dir."))
- else:
- self["key_yellow"].text = (_("Select image"))
- self["key_blue"].text = (_("USB stick wizard"))
-
- def switchList(self,to_where=None):
- if self.download or not self["feedlist"].isValid():
- return
-
- self["job_progressbar"].value = 0
- self["job_progresslabel"].text = ""
-
- if to_where is None:
- if self.focus is self.LIST_SOURCE:
- to_where = self.LIST_DEST
- if self.focus is self.LIST_DEST:
- to_where = self.LIST_SOURCE
-
- if to_where is self.LIST_DEST:
- self.focus = self.LIST_DEST
- self["statusbar"].text = _("Please select target directory or medium")
- self["label_top"].text = _("choose destination directory")+":"
- self["feedlist"].hide()
- self["destlist"].show()
- self["label_bottom"].text = _("Selected source image")+":"
- self["path_bottom"].text = str(self["feedlist"].getNFIname())
- self["key_yellow"].text = (_("Select image"))
-
- elif to_where is self.LIST_SOURCE:
- self.focus = self.LIST_SOURCE
- self["statusbar"].text = _("Please choose .NFI image file from feed server to download")
- self["label_top"].text = _("select image from server")+":"
- self["feedlist"].show()
- self["destlist"].hide()
- self["label_bottom"].text = _("Destination directory")+":"
- self["path_bottom"].text = str(self["destlist"].getCurrentDirectory())
- self["key_yellow"].text = (_("Change dir."))
-
- def up(self):
- if self.download:
- return
- if self.focus is self.LIST_SOURCE:
- self["feedlist"].up()
- self.nfo_download()
- if self.focus is self.LIST_DEST:
- self["destlist"].up()
-
- def down(self):
- if self.download:
- return
- if self.focus is self.LIST_SOURCE:
- self["feedlist"].down()
- self.nfo_download()
- if self.focus is self.LIST_DEST:
- self["destlist"].down()
-
- def left(self):
- if self.download:
- return
- if self.focus is self.LIST_SOURCE:
- self["feedlist"].pageUp()
- self.nfo_download()
- if self.focus is self.LIST_DEST:
- self["destlist"].pageUp()
-
- def right(self):
- if self.download:
- return
- if self.focus is self.LIST_SOURCE:
- self["feedlist"].pageDown()
- self.nfo_download()
- if self.focus is self.LIST_DEST:
- self["destlist"].pageDown()
-
- def ok(self):
- if self.focus is self.LIST_SOURCE and self.nfo:
- self.session.open(NFOViewer, self.nfo)
- if self.download:
- return
- if self.focus is self.LIST_DEST:
- if self["destlist"].canDescent():
- self["destlist"].descent()
-
- def feed_download(self):
- self.downloading(True)
- self.download = self.feed_download
- client.getPage(self.feed_base).addCallback(self.feed_finished).addErrback(self.feed_failed)
+class feedDownloader:
+ def __init__(self, feed_base, box, OE_vers):
+ print "[feedDownloader::init] feed_base=%s, box=%s" % (feed_base, box)
+ self.feed_base = feed_base
+ self.OE_vers = OE_vers
+ self.box = box
+
+ def getList(self, callback, errback):
+ self.urlbase = "%s/%s/%s/images/" % (self.feed_base, self.OE_vers, self.box)
+ print "[getList]", self.urlbase
+ self.callback = callback
+ self.errback = errback
+ client.getPage(self.urlbase).addCallback(self.feed_finished).addErrback(self.feed_failed)
def feed_failed(self, failure_instance):
- print "[feed_failed] " + str(failure_instance)
- self["infolabel"].text = _("Could not connect to Dreambox .NFI Image Feed Server:") + "\n" + failure_instance.getErrorMessage() + "\n\n" + _("Please check your network settings!")
- self.downloading(False)
+ print "[feed_failed]", str(failure_instance)
+ self.errback(failure_instance.getErrorMessage())
def feed_finished(self, feedhtml):
- print "[feed_finished] " + str(feedhtml)
- self.downloading(False)
+ print "[feed_finished]"
fileresultmask = re.compile("<a class=[\'\"]nfi[\'\"] href=[\'\"](?P<url>.*?)[\'\"]>(?P<name>.*?.nfi)</a>", re.DOTALL)
searchresults = fileresultmask.finditer(feedhtml)
fileresultlist = []
@@ -287,378 +268,528 @@ class NFIDownload(Screen):
for x in searchresults:
url = x.group("url")
if url[0:7] != "http://":
- url = self.feed_base + x.group("url")
+ url = self.urlbase + x.group("url")
name = x.group("name")
- if name.find(self.nfi_filter) > -1:
- entry = [[name, url],(eListboxPythonMultiContent.TYPE_TEXT, 0, 0,250, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, name)]
- print "adding to feedlist: " + str(entry)
- fileresultlist.append(entry)
- else:
- print "NOT adding to feedlist: " + name
- self["feedlist"].l.setList(fileresultlist)
- self["feedlist"].moveSelection(0)
+ entry = (name, url)
+ fileresultlist.append(entry)
+ self.callback(fileresultlist, self.OE_vers)
- if len(fileresultlist) > 0:
- self.switchList(self.LIST_SOURCE)
- self.nfo_download()
- else:
- self["infolabel"].text = _("Cannot parse feed directory")
-
- def nfo_download(self):
- print "[check_for_NFO]"
- if self["feedlist"].isValid():
- print "nfiname: " + self["feedlist"].getNFIname()
- self["job_progressbar"].value = 0
- self["job_progresslabel"].text = ""
- if self["feedlist"].getNFIurl() is None:
- self["key_green"].text = ""
- return
- self["key_green"].text = _("Download")
- nfourl = self["feedlist"].getNFOurl()
- print "downloading " + nfourl
- self.download = self.nfo_download
- self.downloading(True)
- client.getPage(nfourl).addCallback(self.nfo_finished).addErrback(self.nfo_failed)
- self["statusbar"].text = ("Downloading image description...")
+class DeviceBrowser(Screen, HelpableScreen):
+ skin = """
+ <screen name="DeviceBrowser" position="center,center" size="520,430" title="Please select target medium" >
+ <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
+ <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
+ <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
+ <widget source="message" render="Label" position="5,50" size="510,150" font="Regular;16" />
+ <widget name="filelist" position="5,210" size="510,220" scrollbarMode="showOnDemand" />
+ </screen>"""
- def nfo_failed(self, failure_instance):
- print "[nfo_failed] " + str(failure_instance)
- self["infolabel"].text = _("No details for this image file") + "\n" + self["feedlist"].getNFIname()
- self["statusbar"].text = ""
- self.nfofilename = ""
- self.nfo = ""
- self.downloading(False)
+ def __init__(self, session, startdir, message="", showDirectories = True, showFiles = True, showMountpoints = True, matchingPattern = "", useServiceRef = False, inhibitDirs = False, inhibitMounts = False, isTop = False, enableWrapAround = False, additionalExtensions = None):
+ Screen.__init__(self, session)
- def nfo_finished(self,nfodata=""):
- print "[nfo_finished] " + str(nfodata)
- self.downloading(False)
- self.nfo = nfodata
- if self.nfo != "":
- self.nfofilename = self["destlist"].getCurrentDirectory() + '/' + self["feedlist"].getNFOname()
- self["infolabel"].text = self.nfo
- else:
- self.nfofilename = ""
- self["infolabel"].text = _("No details for this image file")
- self["statusbar"].text = _("Press OK to view full changelog")
-
- def nfi_download(self):
- if self["destlist"].getCurrentDirectory() is None:
- self.switchList(self.LIST_TARGET)
- if self["feedlist"].isValid():
- url = self["feedlist"].getNFIurl()
- self.nfilocal = self["destlist"].getCurrentDirectory()+'/'+self["feedlist"].getNFIname()
- print "[nfi_download] downloading %s to %s" % (url, self.nfilocal)
- self.download = downloadWithProgress(url,self.nfilocal)
- self.download.addProgress(self.nfi_progress)
- self["job_progressbar"].range = 1000
- self.download.start().addCallback(self.nfi_finished).addErrback(self.nfi_failed)
- self.downloading(True)
-
- def nfi_progress(self, recvbytes, totalbytes):
- #print "[update_progress] recvbytes=%d, totalbytes=%d" % (recvbytes, totalbytes)
- self["job_progressbar"].value = int(1000*recvbytes/float(totalbytes))
- self["job_progresslabel"].text = "%d of %d kBytes (%.2f%%)" % (recvbytes/1024, totalbytes/1024, 100*recvbytes/float(totalbytes))
+ HelpableScreen.__init__(self)
- def nfi_failed(self, failure_instance=None, error_message=""):
- if error_message == "" and failure_instance is not None:
- error_message = failure_instance.getErrorMessage()
- print "[nfi_failed] " + error_message
- if fileExists(self["destlist"].getCurrentDirectory()+'/'+self["feedlist"].getNFIname()):
- message = "%s %s\n%s" % (_(".NFI Download failed:"), error_message, _("Remove the incomplete .NFI file?"))
- self.session.openWithCallback(self.nfi_remove, MessageBox, message, MessageBox.TYPE_YESNO)
+ self["key_red"] = StaticText(_("Cancel"))
+ self["key_green"] = StaticText()
+ self["message"] = StaticText(message)
+
+ self.filelist = FileList(startdir, showDirectories = showDirectories, showFiles = showFiles, showMountpoints = showMountpoints, matchingPattern = matchingPattern, useServiceRef = useServiceRef, inhibitDirs = inhibitDirs, inhibitMounts = inhibitMounts, isTop = isTop, enableWrapAround = enableWrapAround, additionalExtensions = additionalExtensions)
+ self["filelist"] = self.filelist
+
+ self["FilelistActions"] = ActionMap(["SetupActions", "ColorActions"],
+ {
+ "green": self.use,
+ "red": self.exit,
+ "ok": self.ok,
+ "cancel": self.exit
+ })
+
+ hotplugNotifier.append(self.hotplugCB)
+ self.onShown.append(self.updateButton)
+ self.onClose.append(self.removeHotplug)
+
+ def hotplugCB(self, dev, action):
+ print "[hotplugCB]", dev, action
+ self.updateButton()
+
+ def updateButton(self):
+
+ if self["filelist"].getFilename() or self["filelist"].getCurrentDirectory():
+ self["key_green"].text = _("Use")
else:
- message = "%s %s" % (_(".NFI Download failed:"),error_message)
- self.session.open(MessageBox, message, MessageBox.TYPE_ERROR)
- self.downloading(False)
+ self["key_green"].text = ""
+
+ def removeHotplug(self):
+ print "[removeHotplug]"
+ hotplugNotifier.remove(self.hotplugCB)
- def nfi_finished(self, string=""):
- print "[nfi_finished] " + str(string)
- if self.nfo != "":
- self.nfofilename = self["destlist"].getCurrentDirectory() + '/' + self["feedlist"].getNFOname()
- nfofd = open(self.nfofilename, "w")
- if nfofd:
- nfofd.write(self.nfo)
- nfofd.close()
- else:
- print "couldn't save nfo file " + self.nfofilename
-
- pos = self.nfo.find("MD5:")
- if pos > 0 and len(self.nfo) >= pos+5+32:
- self["statusbar"].text = ("Please wait for md5 signature verification...")
- cmd = "md5sum -c -"
- md5 = self.nfo[pos+5:pos+5+32] + " " + self.nfilocal
- print cmd, md5
- self.download_container.setCWD(self["destlist"].getCurrentDirectory())
- self.download_container.appClosed.append(self.md5finished)
- self.download_container.execute(cmd)
- self.download_container.write(md5)
- self.download_container.dataSent.append(self.md5ready)
+ def ok(self):
+ if self.filelist.canDescent():
+ if self["filelist"].showMountpoints == True and self["filelist"].showDirectories == False:
+ self.use()
else:
- self["statusbar"].text = "Download completed."
- self.downloading(False)
- else:
- self["statusbar"].text = "Download completed."
- self.downloading(False)
- if self.wizard_mode:
- self.configBackup()
+ self.filelist.descent()
- def md5ready(self, retval):
- self.download_container.sendEOF()
+ def use(self):
+ print "[use]", self["filelist"].getCurrentDirectory(), self["filelist"].getFilename()
+ if self["filelist"].getCurrentDirectory() is not None:
+ if self.filelist.canDescent() and self["filelist"].getFilename() and len(self["filelist"].getFilename()) > len(self["filelist"].getCurrentDirectory()):
+ self.filelist.descent()
+ self.close(self["filelist"].getCurrentDirectory())
+ elif self["filelist"].getFilename():
+ self.close(self["filelist"].getFilename())
- def md5finished(self, retval):
- print "[md5finished]: " + str(retval)
- self.download_container.appClosed.remove(self.md5finished)
- if retval==0:
- self.downloading(False)
- if self.wizard_mode:
- self.configBackup()
- else:
- self["statusbar"].text = _(".NFI file passed md5sum signature check. You can safely flash this image!")
- self.switchList(self.LIST_SOURCE)
- else:
- self.session.openWithCallback(self.nfi_remove, MessageBox, (_("The md5sum validation failed, the file may be downloaded incompletely or be corrupted!") + "\n" + _("Remove the broken .NFI file?")), MessageBox.TYPE_YESNO)
-
- def nfi_remove(self, answer):
- self.downloading(False)
- if answer == True:
- nfifilename = self["destlist"].getCurrentDirectory()+'/'+self["feedlist"].getNFIname()
- if fileExists(self.nfofilename):
- remove(self.nfofilename)
- if fileExists(nfifilename):
- remove(nfifilename)
- self.switchList(self.LIST_SOURCE)
-
- def askCreateUSBstick(self):
- self.downloading()
- self.imagefilename = "/tmp/nfiflash_" + self.box + ".img"
- message = _("You have chosen to create a new .NFI flasher bootable USB stick. This will repartition the USB stick and therefore all data on it will be erased.")
- self.session.openWithCallback(self.flasherdownload_query, MessageBox, (message + '\n' + _("First we need to download the latest boot environment for the USB flasher.")), MessageBox.TYPE_YESNO)
-
- def flasherdownload_query(self, answer):
- if answer is False:
- self.downloading(False)
- self.switchList(self.LIST_SOURCE)
- return
- #url = self.feed_base + "/nfiflasher_" + self.box + ".tar.bz2"
- url = "http://www.dreamboxupdate.com/download/opendreambox/dreambox-nfiflasher-%s.tar.bz2" % self.box
- localfile = "/tmp/nfiflasher_image.tar.bz2"
- print "[flasherdownload_query] downloading %s to %s" % (url, localfile)
- self["statusbar"].text = ("Downloading %s..." % url)
- self.download = downloadWithProgress(url,localfile)
- self.download.addProgress(self.nfi_progress)
- self["job_progressbar"].range = 1000
- self.download.start().addCallback(self.flasherdownload_finished).addErrback(self.flasherdownload_failed)
-
- def flasherdownload_failed(self, failure_instance=None, error_message=""):
- if error_message == "" and failure_instance is not None:
- error_message = failure_instance.getErrorMessage()
- print "[flasherdownload_failed] " + error_message
- message = "%s %s" % (_("Download of USB flasher boot image failed: "),error_message)
- self.session.open(MessageBox, message, MessageBox.TYPE_ERROR)
- self.remove_img(True)
-
- def flasherdownload_finished(self, string=""):
- print "[flasherdownload_finished] " + str(string)
+ def exit(self):
+ self.close(False)
+
+(ALLIMAGES, RELEASE, EXPERIMENTAL, STICK_WIZARD, START) = range(5)
+
+class NFIDownload(Screen):
+ skin = """
+ <screen name="NFIDownload" position="center,center" size="610,410" title="NFIDownload" >
+ <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
+ <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#9f1313" transparent="1" />
+ <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
+ <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#a08500" transparent="1" />
+ <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#18188b" transparent="1" />
+ <ePixmap pixmap="skin_default/border_menu_350.png" position="5,50" zPosition="1" size="350,300" transparent="1" alphatest="on" />
+ <widget source="menu" render="Listbox" position="15,60" size="330,290" scrollbarMode="showOnDemand">
+ <convert type="TemplatedMultiContent">
+ {"templates":
+ {"default": (25, [
+ MultiContentEntryText(pos = (2, 2), size = (330, 24), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
+ ], True, "showOnDemand")
+ },
+ "fonts": [gFont("Regular", 22)],
+ "itemHeight": 25
+ }
+ </convert>
+ </widget>
+ <widget source="menu" render="Listbox" position="360,50" size="240,300" scrollbarMode="showNever" selectionDisabled="1">
+ <convert type="TemplatedMultiContent">
+ {"templates":
+ {"default": (300, [
+ MultiContentEntryText(pos = (2, 2), size = (240, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description,
+ ], False, "showNever")
+ },
+ "fonts": [gFont("Regular", 22)],
+ "itemHeight": 300
+ }
+ </convert>
+ </widget>
+ <widget source="status" render="Label" position="5,360" zPosition="10" size="600,50" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
+ </screen>"""
+
+ def __init__(self, session, destdir=None):
+ Screen.__init__(self, session)
+ #self.skin_path = plugin_path
+ #self.menu = args
+
+ self.box = HardwareInfo().get_device_name()
+ self.feed_base = "http://www.dreamboxupdate.com/opendreambox" #/1.5/%s/images/" % self.box
+ self.usbmountpoint = "/mnt/usb/"
+
+ self.menulist = []
+
+ self["menu"] = List(self.menulist)
+ self["key_red"] = StaticText(_("Close"))
+ self["key_green"] = StaticText()
+ self["key_yellow"] = StaticText()
+ self["key_blue"] = StaticText()
+
+ self["status"] = StaticText(_("Please wait... Loading list..."))
+
+ self["shortcuts"] = ActionMap(["OkCancelActions", "ColorActions", "ShortcutActions", "DirectionActions"],
+ {
+ "ok": self.keyOk,
+ "green": self.keyOk,
+ "red": self.keyRed,
+ "blue": self.keyBlue,
+ "up": self.keyUp,
+ "upRepeated": self.keyUp,
+ "downRepeated": self.keyDown,
+ "down": self.keyDown,
+ "cancel": self.close,
+ }, -1)
+ self.onShown.append(self.go)
+ self.feedlists = [[],[],[]]
+ self.branch = START
self.container = eConsoleAppContainer()
- self.container.appClosed.append(self.umount_finished)
self.container.dataAvail.append(self.tool_avail)
self.taskstring = ""
- umountdevs = ""
- from os import listdir
- for device in listdir("/dev"):
- if device[:2] == "sd" and device[-1:].isdigit():
- umountdevs += "/dev/"+device
- self.cmd = "umount " + umountdevs
- print "executing " + self.cmd
- self.container.execute(self.cmd)
+ self.image_idx = 0
+ self.nfofilename = ""
+ self.nfo = ""
+ self.target_dir = None
def tool_avail(self, string):
print "[tool_avail]" + string
self.taskstring += string
- def umount_finished(self, retval):
- self.container.appClosed.remove(self.umount_finished)
- self.container.appClosed.append(self.dmesg_cleared)
- self.taskstring = ""
- self.cmd = "dmesg -c"
- print "executing " + self.cmd
- self.container.execute(self.cmd)
+ def go(self):
+ self.onShown.remove(self.go)
+ self.umountCallback = self.getMD5
+ self.umount()
+
+ def getMD5(self):
+ url = "http://www.dreamboxupdate.com/download/opendreambox/dreambox-nfiflasher-%s-md5sums" % self.box
+ client.getPage(url).addCallback(self.md5sums_finished).addErrback(self.feed_failed)
+
+ def md5sums_finished(self, data):
+ print "[md5sums_finished]", data
+ self.stickimage_md5 = data
+ self.checkUSBStick()
+
+ def keyRed(self):
+ if self.branch == START:
+ self.close()
+ else:
+ self.branch = START
+ self["menu"].setList(self.menulist)
+ #elif self.branch == ALLIMAGES or self.branch == STICK_WIZARD:
- def dmesg_cleared(self, answer):
- self.container.appClosed.remove(self.dmesg_cleared)
- self.msgbox = self.session.open(MessageBox, _("Please disconnect all USB devices from your Dreambox and (re-)attach the target USB stick (minimum size is 64 MB) now!"), MessageBox.TYPE_INFO)
- hotplugNotifier.append(self.hotplugCB)
+ def keyBlue(self):
+ if self.nfo != "":
+ self.session.open(NFOViewer, self.nfo)
- def hotplugCB(self, dev, action):
- print "[hotplugCB]", dev, action
- if dev.startswith("sd") and action == "add":
- self.msgbox.close()
- hotplugNotifier.remove(self.hotplugCB)
- self.container.appClosed.append(self.dmesg_scanned)
- self.taskstring = ""
- self.cmd = "dmesg"
- print "executing " + self.cmd
- self.container.execute(self.cmd)
-
- def dmesg_scanned(self, retval):
- self.container.appClosed.remove(self.dmesg_scanned)
- dmesg_lines = self.taskstring.splitlines()
- self.devicetext = None
- self.stickdevice = None
- for i, line in enumerate(dmesg_lines):
- if line.find("usb-storage: waiting for device") != -1 and len(dmesg_lines) > i+3:
- self.devicetext = dmesg_lines[i+1].lstrip()+"\n"+dmesg_lines[i+3]
- elif line.find("/dev/scsi/host") != -1:
- self.stickdevice = line.split(":",1)[0].lstrip()
-
- if retval != 0 or self.devicetext is None or self.stickdevice is None:
- self.session.openWithCallback(self.remove_img, MessageBox, _("No useable USB stick found"), MessageBox.TYPE_ERROR)
+ def keyOk(self):
+ print "[keyOk]", self["menu"].getCurrent()
+ current = self["menu"].getCurrent()
+ if current:
+ if self.branch == START:
+ currentEntry = current[0]
+ if currentEntry == RELEASE:
+ self.image_idx = 0
+ self.branch = RELEASE
+ self.askDestination()
+ elif currentEntry == EXPERIMENTAL:
+ self.image_idx = 0
+ self.branch = EXPERIMENTAL
+ self.askDestination()
+ elif currentEntry == ALLIMAGES:
+ self.branch = ALLIMAGES
+ self.listImages()
+ elif currentEntry == STICK_WIZARD:
+ self.askStartWizard()
+ elif self.branch == ALLIMAGES:
+ self.image_idx = self["menu"].getIndex()
+ self.askDestination()
+ self.updateButtons()
+
+ def keyUp(self):
+ self["menu"].selectPrevious()
+ self.updateButtons()
+
+ def keyDown(self):
+ self["menu"].selectNext()
+ self.updateButtons()
+
+ def updateButtons(self):
+ current = self["menu"].getCurrent()
+ if current:
+ if self.branch == START:
+ self["key_red"].text = _("Close")
+ currentEntry = current[0]
+ if currentEntry in (RELEASE, EXPERIMENTAL):
+ self.nfo_download(currentEntry, 0)
+ self["key_green"].text = _("Download")
+ else:
+ self.nfofilename = ""
+ self.nfo = ""
+ self["key_blue"].text = ""
+ self["key_green"].text = _("continue")
+
+ elif self.branch == ALLIMAGES:
+ self["key_red"].text = _("Back")
+ self["key_green"].text = _("Download")
+ self.nfo_download(ALLIMAGES, self["menu"].getIndex())
+
+ def listImages(self):
+ print "[listImages]"
+ imagelist = []
+ mask = re.compile("%s/(?P<OE_vers>1\.\d)/%s/images/(?P<branch>.*?)-%s_(?P<version>.*?).nfi" % (self.feed_base, self.box, self.box), re.DOTALL)
+ for name, url in self.feedlists[ALLIMAGES]:
+ result = mask.match(url)
+ if result:
+ if result.group("version").startswith("20"):
+ version = ( result.group("version")[:4]+'-'+result.group("version")[4:6]+'-'+result.group("version")[6:8] )
+ else:
+ version = result.group("version")
+ description = "\nOpendreambox %s\n%s image\n%s\n" % (result.group("OE_vers"), result.group("branch"), version)
+ imagelist.append((url, name, _("Download %s from Server" ) % description, None))
+ self["menu"].setList(imagelist)
+
+ def getUSBPartitions(self):
+ allpartitions = [ (r.description, r.mountpoint) for r in harddiskmanager.getMountedPartitions(onlyhotplug = True)]
+ print "[getUSBPartitions]", allpartitions
+ usbpartition = []
+ for x in allpartitions:
+ print x, x[1] == '/', x[0].find("USB"), access(x[1], R_OK)
+ if x[1] != '/' and x[0].find("USB") > -1: # and access(x[1], R_OK) is True:
+ usbpartition.append(x)
+ return usbpartition
+
+ def askDestination(self):
+ usbpartition = self.getUSBPartitions()
+ if len(usbpartition) == 1:
+ self.target_dir = usbpartition[0][1]
+ self.ackDestinationDevice(device_description=usbpartition[0][0])
+ else:
+ self.openDeviceBrowser()
+
+ def openDeviceBrowser(self):
+ self.session.openWithCallback(self.DeviceBrowserClosed, DeviceBrowser, None, showDirectories=True, showMountpoints=True, inhibitMounts=["/autofs/sr0/"])
+
+ def DeviceBrowserClosed(self, path):
+ print "[DeviceBrowserClosed]", str(path)
+ self.target_dir = path
+ if path:
+ self.ackDestinationDevice()
+ else:
+ self.keyRed()
+
+ def ackDestinationDevice(self, device_description=None):
+ if device_description == None:
+ dev = self.target_dir
else:
- self.session.openWithCallback(self.fdisk_query, MessageBox, (_("The following device was found:\n\n%s\n\nDo you want to write the USB flasher to this stick?") % self.devicetext), MessageBox.TYPE_YESNO)
-
- def fdisk_query(self, answer):
- if answer == True and self.stickdevice:
- self["statusbar"].text = ("Partitioning USB stick...")
- self["job_progressbar"].range = 1000
- self["job_progressbar"].value = 100
- self["job_progresslabel"].text = "5.00%"
- self.taskstring = ""
- self.container.appClosed.append(self.fdisk_finished)
- self.container.execute("fdisk " + self.stickdevice + "/disc")
- self.container.write("d\n4\nd\n3\nd\n2\nd\nn\np\n1\n\n\nt\n6\nw\n")
- self.delayTimer = eTimer()
- self.delayTimer.callback.append(self.progress_increment)
- self.delayTimer.start(105, False)
+ dev = device_description
+ message = _("Do you want to download the image to %s ?") % (dev)
+ choices = [(_("Yes"), self.ackedDestination), (_("List of Storage Devices"),self.openDeviceBrowser), (_("Cancel"),self.keyRed)]
+ self.session.openWithCallback(self.ackDestination_query, ChoiceBox, title=message, list=choices)
+
+ def ackDestination_query(self, choice):
+ print "[ackDestination_query]", choice
+ if isinstance(choice, tuple):
+ choice[1]()
else:
- self.remove_img(True)
-
- def fdisk_finished(self, retval):
- self.container.appClosed.remove(self.fdisk_finished)
- self.delayTimer.stop()
- if retval == 0:
- if fileExists(self.imagefilename):
- self.tar_finished(0)
- self["job_progressbar"].value = 700
+ self.keyRed()
+
+ def ackedDestination(self):
+ print "[ackedDestination]", self.branch, self.target_dir
+ self.container.setCWD("/mnt")
+ if self.target_dir[:8] == "/autofs/":
+ self.target_dir = "/dev/" + self.target_dir[8:-1]
+
+ if self.branch == STICK_WIZARD:
+ job = StickWizardJob(self.target_dir)
+ job.afterEvent = "close"
+ job_manager.AddJob(job)
+ job_manager.failed_jobs = []
+ self.session.openWithCallback(self.StickWizardCB, JobView, job, afterEventChangeable = False)
+
+ elif self.branch != STICK_WIZARD:
+ url = self.feedlists[self.branch][self.image_idx][1]
+ filename = self.feedlists[self.branch][self.image_idx][0]
+ print "[getImage] start downloading %s to %s" % (url, filename)
+ if self.target_dir.startswith("/dev/"):
+ job = ImageDownloadJob(url, filename, self.target_dir, self.usbmountpoint)
else:
- self["statusbar"].text = ("Decompressing USB stick flasher boot image...")
- self.taskstring = ""
- self.container.appClosed.append(self.tar_finished)
- self.container.setCWD("/tmp")
- self.cmd = "tar -xjvf nfiflasher_image.tar.bz2"
- self.container.execute(self.cmd)
- print "executing " + self.cmd
- self.delayTimer = eTimer()
- self.delayTimer.callback.append(self.progress_increment)
- self.delayTimer.start(105, False)
+ job = ImageDownloadJob(url, filename, None, self.target_dir)
+ job.afterEvent = "close"
+ job_manager.AddJob(job)
+ job_manager.failed_jobs = []
+ self.session.openWithCallback(self.ImageDownloadCB, JobView, job, afterEventChangeable = False)
+
+ def StickWizardCB(self, ret=None):
+ print "[StickWizardCB]", ret
+# print job_manager.active_jobs, job_manager.failed_jobs, job_manager.job_classes, job_manager.in_background, job_manager.active_job
+ if len(job_manager.failed_jobs) == 0:
+ self.session.open(MessageBox, _("The USB stick was prepared to be bootable.\nNow you can download an NFI image file!"), type = MessageBox.TYPE_INFO)
+ if len(self.feedlists[ALLIMAGES]) == 0:
+ self.getFeed()
+ else:
+ self.setMenu()
else:
- print "fdisk failed: " + str(retval)
- self.session.openWithCallback(self.remove_img, MessageBox, ("fdisk " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR)
-
- def progress_increment(self):
- newval = int(self["job_progressbar"].value) + 1
- if newval < 950:
- self["job_progressbar"].value = newval
- self["job_progresslabel"].text = "%.2f%%" % (newval/10.0)
-
- def tar_finished(self, retval):
- self.delayTimer.stop()
- if len(self.container.appClosed) > 0:
- self.container.appClosed.remove(self.tar_finished)
- if retval == 0:
- self.imagefilename = "/tmp/nfiflash_" + self.box + ".img"
- self["statusbar"].text = ("Copying USB flasher boot image to stick...")
- self.taskstring = ""
- self.container.appClosed.append(self.dd_finished)
- self.cmd = "dd if=%s of=%s" % (self.imagefilename,self.stickdevice+"/part1")
- self.container.execute(self.cmd)
- print "executing " + self.cmd
- self.delayTimer = eTimer()
- self.delayTimer.callback.append(self.progress_increment)
- self.delayTimer.start(105, False)
+ self.umountCallback = self.checkUSBStick
+ self.umount()
+
+ def ImageDownloadCB(self, ret):
+ print "[ImageDownloadCB]", ret
+# print job_manager.active_jobs, job_manager.failed_jobs, job_manager.job_classes, job_manager.in_background, job_manager.active_job
+ if len(job_manager.failed_jobs) == 0:
+ self.session.openWithCallback(self.askBackupCB, MessageBox, _("The wizard can backup your current settings. Do you want to do a backup now?"), MessageBox.TYPE_YESNO)
else:
- self.session.openWithCallback(self.remove_img, MessageBox, (self.cmd + " " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR)
-
- def dd_finished(self, retval):
- self.delayTimer.stop()
- self.container.appClosed.remove(self.dd_finished)
- self.downloading(False)
- if retval == 0:
- self["job_progressbar"].value = 950
- self["job_progresslabel"].text = "95.00%"
- self["statusbar"].text = ("Remounting stick partition...")
- self.taskstring = ""
- self.container.appClosed.append(self.mount_finished)
- self.cmd = "mount %s /mnt/usb -o rw,sync" % (self.stickdevice+"/part1")
- self.container.execute(self.cmd)
- print "executing " + self.cmd
+ self.umountCallback = self.keyRed
+ self.umount()
+
+ def askBackupCB(self, ret):
+ if ret:
+ from Plugins.SystemPlugins.SoftwareManager.BackupRestore import BackupScreen
+
+ class USBBackupScreen(BackupScreen):
+ def __init__(self, session, usbmountpoint):
+ BackupScreen.__init__(self, session, runBackup = True)
+ self.backuppath = usbmountpoint
+ self.fullbackupfilename = self.backuppath + "/" + self.backupfile
+
+ self.session.openWithCallback(self.showHint, USBBackupScreen, self.usbmountpoint)
else:
- self.session.openWithCallback(self.remove_img, MessageBox, (self.cmd + " " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR)
-
- def mount_finished(self, retval):
- self.container.dataAvail.remove(self.tool_avail)
- self.container.appClosed.remove(self.mount_finished)
- if retval == 0:
- self["job_progressbar"].value = 1000
- self["job_progresslabel"].text = "100.00%"
- self["statusbar"].text = (".NFI Flasher bootable USB stick successfully created.")
- self.session.openWithCallback(self.flasherFinishedCB, MessageBox, _("The USB stick is now bootable. Do you want to download the latest image from the feed server and save it on the stick?"), type = MessageBox.TYPE_YESNO)
- self["destlist"].changeDir("/mnt/usb")
+ self.showHint()
+
+ def showHint(self, ret=None):
+ self.session.open(MessageBox, _("To update your Dreambox firmware, please follow these steps:\n1) Turn off your box with the rear power switch and make sure the bootable USB stick is plugged in.\n2) Turn mains back on and hold the DOWN button on the front panel pressed for 10 seconds.\n3) Wait for bootup and follow instructions of the wizard."), type = MessageBox.TYPE_INFO)
+ self.umountCallback = self.keyRed
+ self.umount()
+
+ def getFeed(self):
+ self.feedDownloader15 = feedDownloader(self.feed_base, self.box, OE_vers="1.5")
+ self.feedDownloader16 = feedDownloader(self.feed_base, self.box, OE_vers="1.6")
+ self.feedlists = [[],[],[]]
+ self.feedDownloader15.getList(self.gotFeed, self.feed_failed)
+ self.feedDownloader16.getList(self.gotFeed, self.feed_failed)
+
+ def feed_failed(self, message=""):
+ self["status"].text = _("Could not connect to Dreambox .NFI Image Feed Server:") + "\n" + str(message) + "\n" + _("Please check your network settings!")
+
+ def gotFeed(self, feedlist, OE_vers):
+ print "[gotFeed]", OE_vers
+ releaselist = []
+ experimentallist = []
+
+ for name, url in feedlist:
+ if name.find("release") > -1:
+ releaselist.append((name, url))
+ if name.find("experimental") > -1:
+ experimentallist.append((name, url))
+ self.feedlists[ALLIMAGES].append((name, url))
+
+ if OE_vers == "1.6":
+ self.feedlists[RELEASE] = releaselist + self.feedlists[RELEASE]
+ self.feedlists[EXPERIMENTAL] = experimentallist + self.feedlists[RELEASE]
+ elif OE_vers == "1.5":
+ self.feedlists[RELEASE] = self.feedlists[RELEASE] + releaselist
+ self.feedlists[EXPERIMENTAL] = self.feedlists[EXPERIMENTAL] + experimentallist
+
+ self.setMenu()
+
+ def checkUSBStick(self):
+ self.target_dir = None
+ allpartitions = [ (r.description, r.mountpoint) for r in harddiskmanager.getMountedPartitions(onlyhotplug = True)]
+ print "[checkUSBStick] found partitions:", allpartitions
+ usbpartition = []
+ for x in allpartitions:
+ print x, x[1] == '/', x[0].find("USB"), access(x[1], R_OK)
+ if x[1] != '/' and x[0].find("USB") > -1: # and access(x[1], R_OK) is True:
+ usbpartition.append(x)
+
+ print usbpartition
+ if len(usbpartition) == 1:
+ self.target_dir = usbpartition[0][1]
+ self.md5_passback = self.getFeed
+ self.md5_failback = self.askStartWizard
+ self.md5verify(self.stickimage_md5, self.target_dir)
+ elif usbpartition == []:
+ print "[NFIFlash] needs to create usb flasher stick first!"
+ self.askStartWizard()
else:
- self.session.openWithCallback(self.flasherFinishedCB, MessageBox, (self.cmd + " " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR)
- self.remove_img(True)
-
- def remove_img(self, answer):
- if fileExists("/tmp/nfiflasher_image.tar.bz2"):
- remove("/tmp/nfiflasher_image.tar.bz2")
- if fileExists(self.imagefilename):
- remove(self.imagefilename)
- self.downloading(False)
- self.switchList(self.LIST_SOURCE)
-
- def flasherFinishedCB(self, answer):
- if answer == True:
- self.wizard_mode = True
- self["feedlist"].moveSelection(0)
- self["path_bottom"].text = str(self["destlist"].getCurrentDirectory())
- self.nfo_download()
- self.nfi_download()
-
- def configBackup(self):
- self.session.openWithCallback(self.runBackup, MessageBox, _("The wizard can backup your current settings. Do you want to do a backup now?"))
-
- def runBackup(self, result=None):
- from Tools.Directories import createDir, isMount, pathExists
- from time import localtime
- from datetime import date
- from Screens.Console import Console
- if result:
- if isMount("/mnt/usb/"):
- if (pathExists("/mnt/usb/backup") == False):
- createDir("/mnt/usb/backup", True)
- d = localtime()
- dt = date(d.tm_year, d.tm_mon, d.tm_mday)
- self.backup_file = "backup/" + str(dt) + "_settings_backup.tar.gz"
- self.session.open(Console, title = "Backup running", cmdlist = ["tar -czvf " + "/mnt/usb/" + self.backup_file + " /etc/enigma2/ /etc/network/interfaces /etc/wpa_supplicant.conf"], finishedCallback = self.backup_finished, closeOnSuccess = True)
+ self.askStartWizard()
+
+ def askStartWizard(self):
+ self.branch = STICK_WIZARD
+ message = _("""This plugin creates a USB stick which can be used to update the firmware of your Dreambox without the need for a network or WLAN connection.
+First, a USB stick needs to be prepared so that it becomes bootable.
+In the next step, an NFI image file can be downloaded from the update server and saved on the USB stick.
+If you already have a prepared bootable USB stick, please insert it now. Otherwise plug in a USB stick with a minimum size of 64 MB!""")
+ self.session.openWithCallback(self.wizardDeviceBrowserClosed, DeviceBrowser, None, message, showDirectories=True, showMountpoints=True, inhibitMounts=["/","/autofs/sr0/","/autofs/sda1/","/media/hdd/","/media/net/",self.usbmountpoint,"/media/dvd/"])
+
+ def wizardDeviceBrowserClosed(self, path):
+ print "[wizardDeviceBrowserClosed]", path
+ self.target_dir = path
+ if path:
+ self.md5_passback = self.getFeed
+ self.md5_failback = self.wizardQuery
+ self.md5verify(self.stickimage_md5, self.target_dir)
else:
- self.backup_file = None
- self.backup_finished(skipped=True)
-
- def backup_finished(self, skipped=False):
- if not skipped:
- wizardfd = open("/mnt/usb/wizard.nfo", "w")
- if wizardfd:
- wizardfd.write("image: "+self["feedlist"].getNFIname()+'\n')
- wizardfd.write("configuration: "+self.backup_file+'\n')
- wizardfd.close()
- self.session.open(MessageBox, _("To update your Dreambox firmware, please follow these steps:\n1) Turn off your box with the rear power switch and plug in the bootable USB stick.\n2) Turn mains back on and hold the DOWN button on the front panel pressed for 10 seconds.\n3) Wait for bootup and follow instructions of the wizard."), type = MessageBox.TYPE_INFO)
-
- def closeCB(self):
- try:
- self.download.stop()
- #self.nfi_failed(None, "Cancelled by user request")
- self.downloading(False)
- except AttributeError:
self.close()
+
+ def wizardQuery(self):
+ print "[wizardQuery]"
+ description = self.target_dir
+ for name, dev in self.getUSBPartitions():
+ if dev == self.target_dir:
+ description = name
+ message = _("You have chosen to create a new .NFI flasher bootable USB stick. This will repartition the USB stick and therefore all data on it will be erased.") + "\n"
+ message += _("The following device was found:\n\n%s\n\nDo you want to write the USB flasher to this stick?") % description
+ choices = [(_("Yes"), self.ackedDestination), (_("List of Storage Devices"),self.askStartWizard), (_("Cancel"),self.close)]
+ self.session.openWithCallback(self.ackDestination_query, ChoiceBox, title=message, list=choices)
+
+ def setMenu(self):
+ self.menulist = []
+ try:
+ latest_release = "Release %s (Opendreambox 1.5)" % self.feedlists[RELEASE][0][0][-9:-4]
+ self.menulist.append((RELEASE, _("Get latest release image"), _("Download %s from Server" ) % latest_release, None))
+ except IndexError:
+ pass
+
+ try:
+ dat = self.feedlists[EXPERIMENTAL][0][0][-12:-4]
+ latest_experimental = "Experimental %s-%s-%s (Opendreambox 1.6)" % (dat[:4], dat[4:6], dat[6:])
+ self.menulist.append((EXPERIMENTAL, _("Get latest experimental image"), _("Download %s from Server") % latest_experimental, None))
+ except IndexError:
+ pass
+
+ self.menulist.append((ALLIMAGES, _("Choose image to download"), _("Select desired image from feed list" ), None))
+ self.menulist.append((STICK_WIZARD, _("USB stick wizard"), _("Prepare another USB stick for image flashing" ), None))
+ self["menu"].setList(self.menulist)
+ self["status"].text = _("Currently installed image") + ": %s" % (about.getImageVersionString())
+ self.branch = START
+ self.updateButtons()
+
+ def nfo_download(self, branch, idx):
+ nfourl = (self.feedlists[branch][idx][1])[:-4]+".nfo"
+ self.nfofilename = (self.feedlists[branch][idx][0])[:-4]+".nfo"
+ print "[check_for_NFO]", nfourl
+ client.getPage(nfourl).addCallback(self.nfo_finished).addErrback(self.nfo_failed)
+
+ def nfo_failed(self, failure_instance):
+ print "[nfo_failed] " + str(failure_instance)
+ self["key_blue"].text = ""
+ self.nfofilename = ""
+ self.nfo = ""
+
+ def nfo_finished(self,nfodata=""):
+ print "[nfo_finished] " + str(nfodata)
+ self["key_blue"].text = _("Changelog")
+ self.nfo = nfodata
+
+ def md5verify(self, md5, path):
+ cmd = "md5sum -c -s"
+ print "[verify_md5]", md5, path, cmd
+ self.container.setCWD(path)
+ self.container.appClosed.append(self.md5finished)
+ self.container.execute(cmd)
+ self.container.write(md5)
+ self.container.dataSent.append(self.md5ready)
+
+ def md5ready(self, retval):
+ self.container.sendEOF()
+
+ def md5finished(self, retval):
+ print "[md5finished]", str(retval)
+ self.container.appClosed.remove(self.md5finished)
+ self.container.dataSent.remove(self.md5ready)
+ if retval==0:
+ print "check passed! calling", repr(self.md5_passback)
+ self.md5_passback()
+ else:
+ print "check failed! calling", repr(self.md5_failback)
+ self.md5_failback()
+
+ def umount(self):
+ cmd = "umount " + self.usbmountpoint
+ print "[umount]", cmd
+ self.container.setCWD('/')
+ self.container.appClosed.append(self.umountFinished)
+ self.container.execute(cmd)
+
+ def umountFinished(self, retval):
+ print "[umountFinished]", str(retval)
+ self.container.appClosed.remove(self.umountFinished)
+ self.umountCallback()
def main(session, **kwargs):
session.open(NFIDownload,"/home/root")
diff --git a/lib/python/Plugins/SystemPlugins/NFIFlash/flasher.py b/lib/python/Plugins/SystemPlugins/NFIFlash/flasher.py
index 8986560b..ba96c071 100644..100755
--- a/lib/python/Plugins/SystemPlugins/NFIFlash/flasher.py
+++ b/lib/python/Plugins/SystemPlugins/NFIFlash/flasher.py
@@ -2,31 +2,62 @@ from Screens.Screen import Screen
from Screens.MessageBox import MessageBox
from Screens.ChoiceBox import ChoiceBox
from Screens.Standby import TryQuitMainloop
+from Screens.Console import Console
from Components.ActionMap import ActionMap
from Components.Sources.StaticText import StaticText
from Components.Sources.Progress import Progress
from Components.Sources.Boolean import Boolean
from Components.Label import Label
from Components.FileList import FileList
-from Components.Task import Task, Job, JobManager
+from Components.Task import Task, Job, job_manager, Condition
+from Screens.TaskView import JobView
from Tools.Directories import fileExists
from Tools.HardwareInfo import HardwareInfo
from os import system
-from enigma import eConsoleAppContainer
-import re
+from enigma import eConsoleAppContainer, quitMainloop
+from Components.About import about
+
+class md5Postcondition(Condition):
+ def check(self, task):
+ print "md5Postcondition::check", task.returncode
+ return task.returncode == 0
+
+ def getErrorMessage(self, task):
+ if task.returncode == 1:
+ return _("The md5sum validation failed, the file may be corrupted!")
+ return "md5 error"
+
+class md5verify(Task):
+ def __init__(self, job, path, md5):
+ Task.__init__(self, job, "md5sum")
+ self.postconditions.append(md5Postcondition())
+ self.weighting = 5
+ self.cwd = path
+ self.setTool("md5sum")
+ self.args += ["-c", "-s"]
+ self.initial_input = md5
+
+ def writeInput(self, input):
+ self.container.dataSent.append(self.md5ready)
+ print "[writeInput]", input
+ Task.writeInput(self, input)
+
+ def md5ready(self, retval):
+ self.container.sendEOF()
+
+ def processOutput(self, data):
+ print "[md5sum]",
class writeNAND(Task):
- def __init__(self,job,param,box):
+ def __init__(self, job, param, box):
Task.__init__(self,job, ("Writing image file to NAND Flash"))
- self.setTool("/usr/lib/enigma2/python/Plugins/SystemPlugins/NFIFlash/mywritenand")
+ self.setTool("/usr/lib/enigma2/python/Plugins/SystemPlugins/NFIFlash/writenfi-mipsel-2.6.18-r1")
if box == "dm7025":
self.end = 256
elif box[:5] == "dm800":
self.end = 512
- if box == "dm8000":
- self.setTool("/usr/lib/enigma2/python/Plugins/SystemPlugins/NFIFlash/dm8000_writenand")
self.args += param
- self.weighting = 1
+ self.weighting = 95
def processOutput(self, data):
print "[writeNand] " + data
@@ -38,143 +69,93 @@ class writeNAND(Task):
else:
self.output_line = data
-class NFISummary(Screen):
- skin = """
- <screen position="0,0" size="132,64">
- <widget source="title" render="Label" position="2,0" size="120,14" valign="center" font="Regular;12" />
- <widget source="content" render="Label" position="2,14" size="120,34" font="Regular;12" transparent="1" zPosition="1" />
- <widget source="job_progresslabel" render="Label" position="66,50" size="60,14" font="Regular;12" transparent="1" halign="right" zPosition="0" />
- <widget source="job_progressbar" render="Progress" position="2,50" size="66,14" borderWidth="1" />
- </screen>"""
-
- def __init__(self, session, parent):
- Screen.__init__(self, session, parent)
- self["title"] = StaticText(_("Image flash utility"))
- self["content"] = StaticText(_("Please select .NFI flash image file from medium"))
- self["job_progressbar"] = Progress()
- self["job_progresslabel"] = StaticText("")
-
- def setText(self, text):
- self["content"].setText(text)
-
class NFIFlash(Screen):
skin = """
- <screen name="NFIFlash" position="90,95" size="560,420" title="Image flash utility">
- <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
- <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
- <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" />
- <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
- <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#a08500" transparent="1" />
- <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#18188b" transparent="1" />
- <widget source="listlabel" render="Label" position="10,44" size="250,20" font="Regular;16" />
- <widget name="filelist" position="0,68" size="260,260" scrollbarMode="showOnDemand" />
- <widget source="infolabel" render="Label" position="270,44" size="280,284" font="Regular;16" />
- <widget source="job_progressbar" render="Progress" position="10,374" size="540,26" borderWidth="1" backgroundColor="#254f7497" />
- <widget source="job_progresslabel" render="Label" position="180,378" zPosition="2" font="Regular;18" halign="center" transparent="1" size="200,22" foregroundColor="#000000" />
- <widget source="statusbar" render="Label" position="10,404" size="540,16" font="Regular;16" foregroundColor="#cccccc" />
- </screen>"""
+ <screen name="NFIFlash" position="center,center" size="610,410" title="Image flash utility" >
+ <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
+ <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#9f1313" transparent="1" />
+ <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
+ <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#a08500" transparent="1" />
+ <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#18188b" transparent="1" />
+ <ePixmap pixmap="skin_default/border_menu_350.png" position="5,50" zPosition="1" size="350,300" transparent="1" alphatest="on" />
+ <widget name="filelist" position="15,60" size="330,284" scrollbarMode="showOnDemand" />
+ <widget source="infolabel" render="Label" position="360,50" size="240,300" font="Regular;13" />
+ <widget source="status" render="Label" position="5,360" zPosition="10" size="600,50" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
+ </screen>"""
- def __init__(self, session, cancelable = True, close_on_finish = False):
- self.skin = NFIFlash.skin
+ def __init__(self, session, destdir=None):
Screen.__init__(self, session)
- self["job_progressbar"] = Progress()
- self["job_progresslabel"] = StaticText("")
-
- self["finished"] = Boolean()
+ self.box = HardwareInfo().get_device_name()
+ self.usbmountpoint = "/mnt/usb/"
- self["infolabel"] = StaticText("")
- self["statusbar"] = StaticText(_("Please select .NFI flash image file from medium"))
- self["listlabel"] = StaticText(_("select .NFI flash file")+":")
-
+ self["key_red"] = StaticText()
self["key_green"] = StaticText()
self["key_yellow"] = StaticText()
self["key_blue"] = StaticText()
+ self.filelist = FileList(self.usbmountpoint, matchingPattern = "^.*\.(nfi|NFI)", showDirectories = False, showMountpoints = False)
+ self["filelist"] = self.filelist
+ self["infolabel"] = StaticText()
- self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions"],
+ self["status"] = StaticText(_("Please select an NFI file and press green key to flash!") + '\n' + _("currently installed image: %s") % (about.getImageVersionString()))
+ self.job = None
+
+ self["shortcuts"] = ActionMap(["OkCancelActions", "ColorActions", "ShortcutActions", "DirectionActions"],
{
- "green": self.ok,
+ "ok": self.keyOk,
+ "green": self.keyOk,
+ "up": self.keyUp,
+ "upRepeated": self.keyUp,
+ "downRepeated": self.keyDown,
+ "down": self.keyDown,
+ "left": self.keyLeft,
"yellow": self.reboot,
- "blue": self.runWizard,
- "ok": self.ok,
- "left": self.left,
- "right": self.right,
- "up": self.up,
- "down": self.down
+ "right": self.keyRight
}, -1)
-
- currDir = "/media/usb/"
- self.filelist = FileList(currDir, matchingPattern = "^.*\.(nfi|NFI)")
- self["filelist"] = self.filelist
- self.nfifile = ""
self.md5sum = ""
- self.job = None
- self.box = HardwareInfo().get_device_name()
- self.configuration_restorable = None
- self.wizard_mode = False
- from enigma import eTimer
- self.delayTimer = eTimer()
- self.delayTimer.callback.append(self.runWizard)
- self.delayTimer.start(50,1)
-
- def check_for_wizard(self):
- if self["filelist"].getCurrentDirectory() is not None and fileExists(self["filelist"].getCurrentDirectory()+"wizard.nfo"):
- self["key_blue"].text = _("USB stick wizard")
- return True
- else:
- self["key_blue"].text = ""
- return False
+ self.onShown.append(self.autostart)
- def runWizard(self):
- if not self.check_for_wizard():
- self.wizard_mode = False
- return
- wizardcontent = open(self["filelist"].getCurrentDirectory()+"/wizard.nfo", "r").readlines()
- nfifile = None
- for line in wizardcontent:
- line = line.strip()
- if line.startswith("image: "):
- nfifile = self["filelist"].getCurrentDirectory()+line[7:]
- if line.startswith("configuration: "):
- backupfile = self["filelist"].getCurrentDirectory()+line[15:]
- if fileExists(backupfile):
- print "wizard configuration:", backupfile
- self.configuration_restorable = backupfile
- else:
- self.configuration_restorable = None
- if nfifile and fileExists(nfifile):
- self.wizard_mode = True
- print "wizard image:", nfifile
- self.check_for_NFO(nfifile)
- self.queryFlash()
-
- def closeCB(self):
- if ( self.job is None or self.job.status is not self.job.IN_PROGRESS ) and not self.no_autostart:
- self.close()
- #else:
- #if self.cancelable:
- #self.cancel()
+ def autostart(self):
+ self.onShown.remove(self.autostart)
+ self.check_for_NFO()
+ print "[[layoutFinished]]", len(self["filelist"].getFileList())
+ if len(self["filelist"].getFileList()) == 1:
+ print "==1"
+ self.keyOk()
- def up(self):
+ def keyUp(self):
self["filelist"].up()
self.check_for_NFO()
- def down(self):
+ def keyDown(self):
self["filelist"].down()
self.check_for_NFO()
- def right(self):
+ def keyRight(self):
self["filelist"].pageDown()
self.check_for_NFO()
- def left(self):
+ def keyLeft(self):
self["filelist"].pageUp()
self.check_for_NFO()
+ def keyOk(self):
+ if self.job is None or self.job.status is not self.job.IN_PROGRESS:
+ if self["filelist"].canDescent(): # isDir
+ self["filelist"].descent()
+ self.check_for_NFO()
+ elif self["filelist"].getFilename():
+ self.session.openWithCallback(self.queryCB, MessageBox, _("Shall the USB stick wizard proceed and program the image file %s into flash memory?" % self.nfifile.rsplit('/',1)[-1]), MessageBox.TYPE_YESNO)
+
def check_for_NFO(self, nfifile=None):
- self.session.summary.setText(self["filelist"].getFilename())
+ print "check_for_NFO", self["filelist"].getFilename(), self["filelist"].getCurrentDirectory()
+ self["infolabel"].text = ""
+ self["key_green"].text = ""
+
if nfifile is None:
- self.session.summary.setText(self["filelist"].getFilename())
if self["filelist"].getFilename() is None:
return
if self["filelist"].getCurrentDirectory() is not None:
@@ -185,8 +166,10 @@ class NFIFlash(Screen):
if self.nfifile.upper().endswith(".NFI"):
self["key_green"].text = _("Flash")
nfofilename = self.nfifile[0:-3]+"nfo"
+ print nfofilename, fileExists(nfofilename)
if fileExists(nfofilename):
nfocontent = open(nfofilename, "r").read()
+ print "nfocontent:", nfocontent
self["infolabel"].text = nfocontent
pos = nfocontent.find("MD5:")
if pos > 0:
@@ -196,122 +179,51 @@ class NFIFlash(Screen):
else:
self["infolabel"].text = _("No details for this image file") + (self["filelist"].getFilename() or "")
self.md5sum = ""
- else:
- self["infolabel"].text = ""
- self["key_green"].text = ""
-
- def ok(self):
- if self.job is None or self.job.status is not self.job.IN_PROGRESS:
- if self["filelist"].canDescent(): # isDir
- self["filelist"].descent()
- self.session.summary.setText(self["filelist"].getFilename())
- self.check_for_NFO()
- self.check_for_wizard()
- else:
- self.queryFlash()
-
- def queryFlash(self):
- fd = open(self.nfifile, 'r')
- print fd
- sign = fd.read(11)
- print sign
- if sign.find("NFI1" + self.box + "\0") == 0:
- if self.md5sum != "":
- self["statusbar"].text = ("Please wait for md5 signature verification...")
- self.session.summary.setText(("Please wait for md5 signature verification..."))
- self.container = eConsoleAppContainer()
- self.container.setCWD(self["filelist"].getCurrentDirectory())
- self.container.appClosed.append(self.md5finished)
- self.container.dataSent.append(self.md5ready)
- self.container.execute("md5sum -cw -")
- self.container.write(self.md5sum)
- else:
- self.session.openWithCallback(self.queryCB, MessageBox, _("This .NFI file does not have a md5sum signature and is not guaranteed to work. Do you really want to burn this image to flash memory?"), MessageBox.TYPE_YESNO)
- else:
- self.session.open(MessageBox, (_("This .NFI file does not contain a valid %s image!") % (self.box.upper())), MessageBox.TYPE_ERROR)
-
- def md5ready(self, retval):
- self.container.sendEOF()
-
- def md5finished(self, retval):
- if retval==0:
- if self.wizard_mode:
- self.session.openWithCallback(self.queryCB, MessageBox, _("Shall the USB stick wizard proceed and program the image file %s into flash memory?" % self.nfifile.rsplit('/',1)[-1]), MessageBox.TYPE_YESNO)
- else:
- self.session.openWithCallback(self.queryCB, MessageBox, _("This .NFI file has a valid md5 signature. Continue programming this image to flash memory?"), MessageBox.TYPE_YESNO)
- else:
- self.session.openWithCallback(self.queryCB, MessageBox, _("The md5sum validation failed, the file may be corrupted! Are you sure that you want to burn this image to flash memory? You are doing this at your own risk!"), MessageBox.TYPE_YESNO)
def queryCB(self, answer):
if answer == True:
self.createJob()
- else:
- self["statusbar"].text = _("Please select .NFI flash image file from medium")
- self.wizard_mode = False
def createJob(self):
self.job = Job("Image flashing job")
- param = [self.nfifile]
- writeNAND(self.job,param,self.box)
- #writeNAND2(self.job,param)
- #writeNAND3(self.job,param)
- self.job.state_changed.append(self.update_job)
- self.job.end = 540
- self.cwd = self["filelist"].getCurrentDirectory()
- self["job_progressbar"].range = self.job.end
- self.startJob()
-
- def startJob(self):
+ self.job.afterEvent = "close"
+ cwd = self["filelist"].getCurrentDirectory()
+ md5verify(self.job, cwd, self.md5sum)
+ writeNAND(self.job, [self.nfifile], self.box)
self["key_blue"].text = ""
self["key_yellow"].text = ""
self["key_green"].text = ""
- #self["progress0"].show()
- #self["progress1"].show()
+ job_manager.AddJob(self.job)
+ self.session.openWithCallback(self.flashed, JobView, self.job, cancelable = False, backgroundable = False, afterEventChangeable = False)
- self.job.start(self.jobcb)
+ def flashed(self, bg):
+ print "[flashed]"
+ if self.job.status == self.job.FINISHED:
+ self["status"].text = _("NFI image flashing completed. Press Yellow to Reboot!")
+ filename = self.usbmountpoint+'enigma2settingsbackup.tar.gz'
+ if fileExists(filename):
+ import os.path, time
+ date = time.ctime(os.path.getmtime(filename))
+ self.session.openWithCallback(self.askRestoreCB, MessageBox, _("The wizard found a configuration backup. Do you want to restore your old settings from %s?") % date, MessageBox.TYPE_YESNO)
+ else:
+ self.unlockRebootButton()
+ else:
+ self["status"].text = _("Flashing failed")
- def update_job(self):
- j = self.job
- #print "[job state_changed]"
- if j.status == j.IN_PROGRESS:
- self.session.summary["job_progressbar"].value = j.progress
- self.session.summary["job_progressbar"].range = j.end
- self.session.summary["job_progresslabel"].text = "%.2f%%" % (100*j.progress/float(j.end))
- self["job_progressbar"].range = j.end
- self["job_progressbar"].value = j.progress
- #print "[update_job] j.progress=%f, j.getProgress()=%f, j.end=%d, text=%f" % (j.progress, j.getProgress(), j.end, (100*j.progress/float(j.end)))
- self["job_progresslabel"].text = "%.2f%%" % (100*j.progress/float(j.end))
- self.session.summary.setText(j.tasks[j.current_task].name)
- self["statusbar"].text = (j.tasks[j.current_task].name)
+ def askRestoreCB(self, ret):
+ if ret:
+ from Plugins.SystemPlugins.SoftwareManager.BackupRestore import getBackupFilename
+ restorecmd = ["tar -xzvf " + self.usbmountpoint + getBackupFilename() + " -C /"]
+ self.session.openWithCallback(self.unlockRebootButton, Console, title = _("Restore is running..."), cmdlist = restorecmd, closeOnSuccess = True)
+ else:
+ self.unlockRebootButton()
- elif j.status == j.FINISHED:
- self["statusbar"].text = _("Writing NFI image file to flash completed")
- self.session.summary.setText(_("NFI image flashing completed. Press Yellow to Reboot!"))
- if self.wizard_mode:
- self.restoreConfiguration()
+ def unlockRebootButton(self, retval = None):
+ if self.job.status == self.job.FINISHED:
self["key_yellow"].text = _("Reboot")
- elif j.status == j.FAILED:
- self["statusbar"].text = j.tasks[j.current_task].name + " " + _("failed")
- self.session.open(MessageBox, (_("Flashing failed") + ":\n" + j.tasks[j.current_task].name + ":\n" + j.tasks[j.current_task].output_line), MessageBox.TYPE_ERROR)
-
- def jobcb(self, jobref, fasel, blubber):
- print "[jobcb] %s %s %s" % (jobref, fasel, blubber)
- self["key_green"].text = _("Flash")
-
def reboot(self, ret=None):
if self.job.status == self.job.FINISHED:
- self["statusbar"].text = ("rebooting...")
- TryQuitMainloop(self.session,2)
-
- def restoreConfiguration(self):
- if self.configuration_restorable:
- from Screens.Console import Console
- cmdlist = [ "mount /dev/mtdblock/3 /mnt/realroot -t jffs2", "tar -xzvf " + self.configuration_restorable + " -C /mnt/realroot/" ]
- self.session.open(Console, title = "Restore running", cmdlist = cmdlist, finishedCallback = self.restore_finished, closeOnSuccess = True)
-
- def restore_finished(self):
- self.session.openWithCallback(self.reboot, MessageBox, _("USB stick wizard finished. Your dreambox will now restart with your new image!"), MessageBox.TYPE_INFO)
-
- def createSummary(self):
- return NFISummary
+ self["status"].text = ("rebooting...")
+ from os import system
+ system("/usr/lib/enigma2/python/Plugins/SystemPlugins/NFIFlash/kill_e2_reboot.sh")
diff --git a/lib/python/Plugins/SystemPlugins/NFIFlash/meta/plugin_nfiflash.xml b/lib/python/Plugins/SystemPlugins/NFIFlash/meta/plugin_nfiflash.xml
index c81f4ca5..f93f5c5a 100755
--- a/lib/python/Plugins/SystemPlugins/NFIFlash/meta/plugin_nfiflash.xml
+++ b/lib/python/Plugins/SystemPlugins/NFIFlash/meta/plugin_nfiflash.xml
@@ -2,28 +2,18 @@
<prerequisites>
<hardware type="dm8000" />
<tag type="System" />
- <tag type="Software" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>NFIFlash</name>
<packagename>enigma2-plugin-systemplugins-nfiflash</packagename>
- <shortdescription>Restore your Dreambox with a USB stick.</shortdescription>
- <description>With the NFIFlash extension it is possible to prepare a USB stick with an Dreambox image.\n
+ <shortdescription>Restore your Dreambox with a USB stick</shortdescription>
+ <description>With the NFIFlash plugin it is possible to prepare a USB stick with an Dreambox image.\n
It is then possible to flash your Dreambox with the image on that stick.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_nfiflash_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>NFIFlash</name>
- <packagename>enigma2-plugin-systemplugins-nfiflash</packagename>
- <shortdescription>Wiederherstellen Ihrer Dreambox mittels USB-Stick.</shortdescription>
- <description>Mit der NFIFlash Erweiterung können Sie ein Dreambox Image auf einen USB-Stick laden.\
- Mit diesem USB-Stick ist es dann möglich Ihre Dreambox zu flashen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_nfiflash_de.jpg" />
- </info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-nfiflash" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/NFIFlash/mywritenand b/lib/python/Plugins/SystemPlugins/NFIFlash/mywritenand
deleted file mode 100755
index 073a204f..00000000
--- a/lib/python/Plugins/SystemPlugins/NFIFlash/mywritenand
+++ /dev/null
Binary files differ
diff --git a/lib/python/Plugins/SystemPlugins/NFIFlash/plugin.py b/lib/python/Plugins/SystemPlugins/NFIFlash/plugin.py
index 28b33305..1eba1dd4 100755
--- a/lib/python/Plugins/SystemPlugins/NFIFlash/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/NFIFlash/plugin.py
@@ -2,6 +2,7 @@ from Plugins.Plugin import PluginDescriptor
from Tools.HardwareInfo import HardwareInfo
from Tools.Directories import fileExists
from downloader import NFIDownload, filescan
+from flasher import NFIFlash
def NFIFlasherMain(session, tmp = None, **kwargs):
session.open(NFIDownload, "/home/root" )
@@ -13,16 +14,12 @@ def Plugins(**kwargs):
# currently only available for DM8000
if HardwareInfo().get_device_name() != "dm8000":
return [PluginDescriptor()]
- if fileExists("/usr/share/bootlogo-flasher.mvi"):
- import flasher
- # started from usb stick # don't try to be intelligent and trick this - it's not possible to rewrite the flash memory with a system currently booted from it
- return [PluginDescriptor(where = PluginDescriptor.WHERE_WIZARD, fnc = (9,flasher.NFIFlash))]
- else:
- # started on real enigma2
- return [PluginDescriptor(name=_("NFI Image Flashing"),
- description=_("Download .NFI-Files for USB-Flasher"),
- icon = "flash.png",
- where = PluginDescriptor.WHERE_SOFTWAREMANAGER,
- fnc={"SoftwareSupported": NFICallFnc, "menuEntryName": lambda x: _("NFI Image Flashing"),
- "menuEntryDescription": lambda x: _("Download .NFI-Files for USB-Flasher")}),
- PluginDescriptor(name="nfi", where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]
+ #return [PluginDescriptor(where = PluginDescriptor.WHERE_WIZARD, fnc = (9,NFIFlash))]
+ # it's not possible to rewrite the flash memory with a system currently booted from it
+ return [PluginDescriptor(name=_("NFI Image Flashing"),
+ description=_("Download .NFI-Files for USB-Flasher"),
+ icon = "flash.png",
+ where = PluginDescriptor.WHERE_SOFTWAREMANAGER,
+ fnc={"SoftwareSupported": NFICallFnc, "menuEntryName": lambda x: _("NFI Image Flashing"),
+ "menuEntryDescription": lambda x: _("Download .NFI-Files for USB-Flasher")}),
+ PluginDescriptor(name="nfi", where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]
diff --git a/lib/python/Plugins/SystemPlugins/NetworkWizard/NetworkWizard.py b/lib/python/Plugins/SystemPlugins/NetworkWizard/NetworkWizard.py
index 6096ca8b..d7e83072 100755
--- a/lib/python/Plugins/SystemPlugins/NetworkWizard/NetworkWizard.py
+++ b/lib/python/Plugins/SystemPlugins/NetworkWizard/NetworkWizard.py
@@ -257,7 +257,7 @@ class NetworkWizard(WizardLanguage, Rc):
text1 = _("Your Dreambox is now ready to use.\n\nYour internet connection is working now.\n\n")
text2 = _('Accesspoint:') + "\t" + str(status[self.selectedInterface]["acesspoint"]) + "\n"
text3 = _('SSID:') + "\t" + str(status[self.selectedInterface]["essid"]) + "\n"
- text4 = _('Link Quality:') + "\t" + str(status[self.selectedInterface]["quality"])+"%" + "\n"
+ text4 = _('Link Quality:') + "\t" + str(status[self.selectedInterface]["quality"])+ "\n"
text5 = _('Signal Strength:') + "\t" + str(status[self.selectedInterface]["signal"]) + "\n"
text6 = _('Bitrate:') + "\t" + str(status[self.selectedInterface]["bitrate"]) + "\n"
text7 = _('Encryption:') + " " + str(status[self.selectedInterface]["encryption"]) + "\n"
@@ -421,3 +421,4 @@ class NetworkWizard(WizardLanguage, Rc):
def ChoicesSelectionMoved(self):
pass
+
diff --git a/lib/python/Plugins/SystemPlugins/NetworkWizard/meta/plugin_networkwizard.xml b/lib/python/Plugins/SystemPlugins/NetworkWizard/meta/plugin_networkwizard.xml
index 4d3adcbd..423365f1 100755
--- a/lib/python/Plugins/SystemPlugins/NetworkWizard/meta/plugin_networkwizard.xml
+++ b/lib/python/Plugins/SystemPlugins/NetworkWizard/meta/plugin_networkwizard.xml
@@ -1,26 +1,18 @@
<default>
<prerequisites>
+ <tag type="Network" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>NetworkWizard</name>
<packagename>enigma2-plugin-systemplugins-networkwizard</packagename>
<shortdescription>Step by step network configuration</shortdescription>
- <description>With the NetworkWizard you can easy configure your network step by step.
+ <description>With the NetworkWizard you can easily configure your network step by step.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_networkwizard_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>NetzwerkWizard</name>
- <packagename>enigma2-plugin-systemplugins-networkwizard</packagename>
- <shortdescription>Schritt für Schritt Netzwerk konfiguration</shortdescription>
- <description>Mit dem NetzwerkWizard können Sie Ihr Netzwerk konfigurieren. Sie werden Schritt
- für Schritt durch die Konfiguration geleitet.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_networkwizard_de.jpg" />
- </info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-networkwizard" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/PositionerSetup/meta/plugin_positionersetup.xml b/lib/python/Plugins/SystemPlugins/PositionerSetup/meta/plugin_positionersetup.xml
index 2cb47c07..5e1db7ba 100755
--- a/lib/python/Plugins/SystemPlugins/PositionerSetup/meta/plugin_positionersetup.xml
+++ b/lib/python/Plugins/SystemPlugins/PositionerSetup/meta/plugin_positionersetup.xml
@@ -3,25 +3,16 @@
<tag type="SAT" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>PositionerSetup</name>
<packagename>enigma2-plugin-systemplugins-positionersetup</packagename>
- <shortdescription>PositionerSetup helps you installing a motorized dish.</shortdescription>
- <description>With the PositionerSetup extension it is easy to install and configure a motorized dish.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_positionersetup.jpg" />
- </info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>PositionerSetup</name>
- <packagename>enigma2-plugin-systemplugins-positionersetup</packagename>
- <shortdescription>Unterstützt Sie beim installieren eines Rotors.</shortdescription>
- <description>Die PositionerSetup Erweiterung unterstützt Sie beim einrichten
- und konfigurieren einer motorgesteuerten Satellitenantenne.
+ <shortdescription>PositionerSetup helps you installing a motorized dish</shortdescription>
+ <description>With the PositionerSetup plugin it is easy to install and configure a motorized dish.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_positionersetup.jpg" />
</info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-positionersetup" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/meta/plugin_satelliteequipmentcontrol.xml b/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/meta/plugin_satelliteequipmentcontrol.xml
index 4c0c7af7..904f9a2e 100755
--- a/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/meta/plugin_satelliteequipmentcontrol.xml
+++ b/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/meta/plugin_satelliteequipmentcontrol.xml
@@ -3,25 +3,17 @@
<tag type="SAT" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>SatelliteEquipmentControl</name>
<name_de>SatelliteEquipmentControl</name_de>
<packagename>enigma2-plugin-systemplugins-satelliteequipmentcontrol</packagename>
- <shortdescription>SatelliteEquipmentControl allows you to fine-tune DiSEqC-settings.</shortdescription>
- <description>With the SatelliteEquipmentControl extension it is possible to fine-tune DiSEqC-settings.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_satcontrol.jpg" />
- </info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>SatelliteEquipmentControl</name>
- <packagename>enigma2-plugin-systemplugins-satelliteequipmentcontrol</packagename>
- <shortdescription>Fein-Einstellungen für DiSEqC</shortdescription>
- <description>Die SatelliteEquipmentControl-Erweiterung unterstützt Sie beim Feintuning der DiSEqC Einstellungen.
+ <shortdescription>SatelliteEquipmentControl allows you to fine-tune DiSEqC-settings</shortdescription>
+ <description>With the SatelliteEquipmentControl plugin it is possible to fine-tune DiSEqC-settings.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_satcontrol.jpg" />
</info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-satelliteequipmentcontrol" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/Satfinder/meta/plugin_satfinder.xml b/lib/python/Plugins/SystemPlugins/Satfinder/meta/plugin_satfinder.xml
index e9453deb..fe0c901e 100755
--- a/lib/python/Plugins/SystemPlugins/Satfinder/meta/plugin_satfinder.xml
+++ b/lib/python/Plugins/SystemPlugins/Satfinder/meta/plugin_satfinder.xml
@@ -1,28 +1,18 @@
<default>
<prerequisites>
<tag type="SAT" />
- <tag type="Software" />
+ <tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>Satfinder</name>
<packagename>enigma2-plugin-systemplugins-satfinder</packagename>
- <shortdescription>Satfinder helps you to align your dish.</shortdescription>
- <description>The Satfinder extension helps you to align your dish.\n
+ <shortdescription>Satfinder helps you to align your dish</shortdescription>
+ <description>The Satfinder plugin helps you to align your dish.\n
It shows you informations about signal rate and errors.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_satfinder.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>Satfinder</name>
- <packagename>enigma2-plugin-systemplugins-satfinder</packagename>
- <shortdescription>Satfinder unterstützt Sie beim ausrichten ihrer Satellitenanlage.</shortdescription>
- <description>Die Satfinder-Erweiterung unterstützt Sie beim Ausrichten ihrer Satellitenanlage.\n
- Es zeigt Ihnen Daten wie Signalstärke und Fehlerrate an.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_satfinder.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-satfinder" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/SkinSelector/meta/plugin_skinselector.xml b/lib/python/Plugins/SystemPlugins/SkinSelector/meta/plugin_skinselector.xml
index 717f732b..73544a56 100755
--- a/lib/python/Plugins/SystemPlugins/SkinSelector/meta/plugin_skinselector.xml
+++ b/lib/python/Plugins/SystemPlugins/SkinSelector/meta/plugin_skinselector.xml
@@ -1,28 +1,19 @@
<default>
<prerequisites>
<tag type="Display" />
- <tag type="System" />
+ <tag type="Skin" />
</prerequisites>
<info language="en">
<author>Dream Multimedia</author>
<name>SkinSelector</name>
<packagename>enigma2-plugin-systemplugins-skinselector</packagename>
- <shortdescription>SkinSelector shows a menu with selectable skins.</shortdescription>
+ <shortdescription>SkinSelector shows a menu with selectable skins</shortdescription>
<description>The SkinSelector shows a menu with selectable skins.\n
It's now easy to change the look and feel of your Dreambox.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_skinselector_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>SkinSelector</name>
- <packagename>enigma2-plugin-systemplugins-skinselector</packagename>
- <shortdescription>Der SkinSelector zeigt Ihnen ein Menu mit auswählbaren Skins.</shortdescription>
- <description>Die SkinSelector Erweiterung zeigt Ihnen ein Menu mit auswählbaren Skins.\n
- Sie können nun einfach das Aussehen der grafischen Oberfläche Ihrer Dreambox verändern.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_skinselector_de.jpg" />
- </info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-skinselector" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py
index dcff3ca2..7bd7d7a2 100755
--- a/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py
+++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/BackupRestore.py
@@ -251,8 +251,9 @@ class RestoreMenu(Screen):
def KeyOk(self):
if (self.exe == False) and (self.entry == True):
self.sel = self["filelist"].getCurrent()
- self.val = self.path + "/" + self.sel
- self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore\nfollowing backup:\n") + self.sel + _("\nSystem will restart after the restore!"))
+ if self.sel:
+ self.val = self.path + "/" + self.sel
+ self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore\nfollowing backup:\n") + self.sel + _("\nSystem will restart after the restore!"))
def keyCancel(self):
self.close()
@@ -265,8 +266,9 @@ class RestoreMenu(Screen):
def deleteFile(self):
if (self.exe == False) and (self.entry == True):
self.sel = self["filelist"].getCurrent()
- self.val = self.path + "/" + self.sel
- self.session.openWithCallback(self.startDelete, MessageBox, _("Are you sure you want to delete\nfollowing backup:\n" + self.sel ))
+ if self.sel:
+ self.val = self.path + "/" + self.sel
+ self.session.openWithCallback(self.startDelete, MessageBox, _("Are you sure you want to delete\nfollowing backup:\n" + self.sel ))
def startDelete(self, ret = False):
if (ret == True):
diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py
index d4653cca..ee0bec74 100755
--- a/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py
+++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py
@@ -1,4 +1,5 @@
-from enigma import eConsoleAppContainer
+# -*- coding: iso-8859-1 -*-
+from enigma import eConsoleAppContainer,eTPM
from Components.Console import Console
from Components.About import about
from Components.DreamInfoHandler import DreamInfoHandler
@@ -8,8 +9,49 @@ from Components.Ipkg import IpkgComponent
from Components.Network import iNetwork
from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_METADIR
from Tools.HardwareInfo import HardwareInfo
+import sha
from time import time
+rootkey = ['\x9f', '|', '\xe4', 'G', '\xc9', '\xb4', '\xf4', '#', '&', '\xce', '\xb3', '\xfe', '\xda', '\xc9', 'U', '`', '\xd8', '\x8c', 's', 'o', '\x90', '\x9b', '\\', 'b', '\xc0', '\x89', '\xd1', '\x8c', '\x9e', 'J', 'T', '\xc5', 'X', '\xa1', '\xb8', '\x13', '5', 'E', '\x02', '\xc9', '\xb2', '\xe6', 't', '\x89', '\xde', '\xcd', '\x9d', '\x11', '\xdd', '\xc7', '\xf4', '\xe4', '\xe4', '\xbc', '\xdb', '\x9c', '\xea', '}', '\xad', '\xda', 't', 'r', '\x9b', '\xdc', '\xbc', '\x18', '3', '\xe7', '\xaf', '|', '\xae', '\x0c', '\xe3', '\xb5', '\x84', '\x8d', '\r', '\x8d', '\x9d', '2', '\xd0', '\xce', '\xd5', 'q', '\t', '\x84', 'c', '\xa8', ')', '\x99', '\xdc', '<', '"', 'x', '\xe8', '\x87', '\x8f', '\x02', ';', 'S', 'm', '\xd5', '\xf0', '\xa3', '_', '\xb7', 'T', '\t', '\xde', '\xa7', '\xf1', '\xc9', '\xae', '\x8a', '\xd7', '\xd2', '\xcf', '\xb2', '.', '\x13', '\xfb', '\xac', 'j', '\xdf', '\xb1', '\x1d', ':', '?']
+
+def bin2long(s):
+ return reduce( lambda x,y:(x<<8L)+y, map(ord, s))
+
+def long2bin(l):
+ res = ""
+ for byte in range(128):
+ res += chr((l >> (1024 - (byte + 1) * 8)) & 0xff)
+ return res
+
+def rsa_pub1024(src, mod):
+ return long2bin(pow(bin2long(src), 65537, bin2long(mod)))
+
+def decrypt_block(src, mod):
+ if len(src) != 128 and len(src) != 202:
+ return None
+ dest = rsa_pub1024(src[:128], mod)
+ hash = sha.new(dest[1:107])
+ if len(src) == 202:
+ hash.update(src[131:192])
+ result = hash.digest()
+ if result == dest[107:127]:
+ return dest
+ return None
+
+def validate_cert(cert, key):
+ buf = decrypt_block(cert[8:], key)
+ if buf is None:
+ return None
+ return buf[36:107] + cert[139:196]
+
+def read_random():
+ try:
+ fd = open("/dev/urandom", "r")
+ buf = fd.read(8)
+ fd.close()
+ return buf
+ except:
+ return None
class SoftwareTools(DreamInfoHandler):
lastDownloadDate = None
@@ -28,7 +70,7 @@ class SoftwareTools(DreamInfoHandler):
else:
self.ImageVersion = 'Stable'
self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
- DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language)
+ DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion)
self.directory = resolveFilename(SCOPE_METADIR)
self.hardware_info = HardwareInfo()
self.list = List([])
@@ -51,47 +93,116 @@ class SoftwareTools(DreamInfoHandler):
def checkNetworkCB(self,data):
if data is not None:
if data <= 2:
- SoftwareTools.NetworkConnectionAvailable = True
+ self.NetworkConnectionAvailable = True
self.getUpdates()
else:
- SoftwareTools.NetworkConnectionAvailable = False
+ self.NetworkConnectionAvailable = False
self.getUpdates()
def getUpdates(self, callback = None):
- if SoftwareTools.NetworkConnectionAvailable == True:
- SoftwareTools.lastDownloadDate = time()
- if SoftwareTools.list_updating is False and callback is None:
- SoftwareTools.list_updating = True
- self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
- elif SoftwareTools.list_updating is False and callback is not None:
- SoftwareTools.list_updating = True
- self.NotifierCallback = callback
- self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
- elif SoftwareTools.list_updating is True and callback is not None:
- #update info collecting already in progress
- self.NotifierCallback = callback
+ if self.lastDownloadDate is None:
+ if self.hardware_info.device_name != "dm7025":
+ etpm = eTPM()
+ l2cert = etpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
+ if l2cert is None:
+ return
+ l2key = validate_cert(l2cert, rootkey)
+ if l2key is None:
+ return
+ l3cert = etpm.getCert(eTPM.TPMD_DT_LEVEL3_CERT)
+ if l3cert is None:
+ return
+ l3key = validate_cert(l3cert, l2key)
+ if l3key is None:
+ return
+ rnd = read_random()
+ if rnd is None:
+ return
+ val = etpm.challenge(rnd)
+ result = decrypt_block(val, l3key)
+ if self.hardware_info.device_name == "dm7025" or result[80:88] == rnd:
+ if self.NetworkConnectionAvailable == True:
+ self.lastDownloadDate = time()
+ if self.list_updating is False and callback is None:
+ self.list_updating = True
+ self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
+ elif self.list_updating is False and callback is not None:
+ self.list_updating = True
+ self.NotifierCallback = callback
+ self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
+ elif self.list_updating is True and callback is not None:
+ self.NotifierCallback = callback
+ else:
+ self.list_updating = False
+ if callback is not None:
+ callback(False)
+ elif self.NotifierCallback is not None:
+ self.NotifierCallback(False)
+ else:
+ self.NetworkConnectionAvailable = False
+ self.list_updating = False
+ if callback is not None:
+ callback(False)
+ elif self.NotifierCallback is not None:
+ self.NotifierCallback(False)
else:
- SoftwareTools.list_updating = False
- if callback is not None:
- callback(False)
- elif self.NotifierCallback is not None:
- self.NotifierCallback(False)
+ if self.NetworkConnectionAvailable == True:
+ self.lastDownloadDate = time()
+ if self.list_updating is False and callback is None:
+ self.list_updating = True
+ self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
+ elif self.list_updating is False and callback is not None:
+ self.list_updating = True
+ self.NotifierCallback = callback
+ self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
+ elif self.list_updating is True and callback is not None:
+ self.NotifierCallback = callback
+ else:
+ if self.list_updating and callback is not None:
+ if self.hardware_info.device_name != "dm7025":
+ etpm = eTPM()
+ l2cert = etpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
+ if l2cert is None:
+ return
+ l2key = validate_cert(l2cert, rootkey)
+ if l2key is None:
+ return
+ l3cert = etpm.getCert(eTPM.TPMD_DT_LEVEL3_CERT)
+ if l3cert is None:
+ return
+ l3key = validate_cert(l3cert, l2key)
+ if l3key is None:
+ return
+ rnd = read_random()
+ if rnd is None:
+ return
+ val = etpm.challenge(rnd)
+ result = decrypt_block(val, l3key)
+ if self.hardware_info.device_name == "dm7025" or result[80:88] == rnd:
+ self.NotifierCallback = callback
+ self.startIpkgListAvailable()
+ else:
+ self.list_updating = False
+ if callback is not None:
+ callback(False)
+ elif self.NotifierCallback is not None:
+ self.NotifierCallback(False)
def ipkgCallback(self, event, param):
if event == IpkgComponent.EVENT_ERROR:
- SoftwareTools.list_updating = False
+ self.list_updating = False
if self.NotifierCallback is not None:
self.NotifierCallback(False)
elif event == IpkgComponent.EVENT_DONE:
- if SoftwareTools.list_updating:
+ if self.list_updating:
self.startIpkgListAvailable()
#print event, "-", param
pass
def startIpkgListAvailable(self, callback = None):
if callback is not None:
- SoftwareTools.list_updating = True
- if SoftwareTools.list_updating:
+ self.list_updating = True
+ if self.list_updating:
if not self.UpdateConsole:
self.UpdateConsole = Console()
cmd = "ipkg list"
@@ -100,8 +211,8 @@ class SoftwareTools(DreamInfoHandler):
def IpkgListAvailableCB(self, result, retval, extra_args = None):
(callback) = extra_args
if result:
- if SoftwareTools.list_updating:
- SoftwareTools.available_packetlist = []
+ if self.list_updating:
+ self.available_packetlist = []
for x in result.splitlines():
tokens = x.split(' - ')
name = tokens[0].strip()
@@ -109,7 +220,7 @@ class SoftwareTools(DreamInfoHandler):
l = len(tokens)
version = l > 1 and tokens[1].strip() or ""
descr = l > 2 and tokens[2].strip() or ""
- SoftwareTools.available_packetlist.append([name, version, descr])
+ self.available_packetlist.append([name, version, descr])
if callback is None:
self.startInstallMetaPackage()
else:
@@ -117,7 +228,7 @@ class SoftwareTools(DreamInfoHandler):
if len(self.UpdateConsole.appContainers) == 0:
callback(True)
else:
- SoftwareTools.list_updating = False
+ self.list_updating = False
if self.UpdateConsole:
if len(self.UpdateConsole.appContainers) == 0:
if callback is not None:
@@ -125,14 +236,17 @@ class SoftwareTools(DreamInfoHandler):
def startInstallMetaPackage(self, callback = None):
if callback is not None:
- SoftwareTools.list_updating = True
- if SoftwareTools.list_updating:
- if not self.UpdateConsole:
- self.UpdateConsole = Console()
- cmd = "ipkg install enigma2-meta enigma2-plugins-meta enigma2-skins-meta"
- self.UpdateConsole.ePopen(cmd, self.InstallMetaPackageCB, callback)
+ self.list_updating = True
+ if self.list_updating:
+ if self.NetworkConnectionAvailable == True:
+ if not self.UpdateConsole:
+ self.UpdateConsole = Console()
+ cmd = "ipkg install enigma2-meta enigma2-plugins-meta enigma2-skins-meta"
+ self.UpdateConsole.ePopen(cmd, self.InstallMetaPackageCB, callback)
+ else:
+ self.InstallMetaPackageCB(True)
- def InstallMetaPackageCB(self, result, retval, extra_args = None):
+ def InstallMetaPackageCB(self, result, retval = None, extra_args = None):
(callback) = extra_args
if result:
self.fillPackagesIndexList()
@@ -143,16 +257,17 @@ class SoftwareTools(DreamInfoHandler):
if len(self.UpdateConsole.appContainers) == 0:
callback(True)
else:
- SoftwareTools.list_updating = False
+ self.list_updating = False
if self.UpdateConsole:
if len(self.UpdateConsole.appContainers) == 0:
if callback is not None:
callback(False)
def startIpkgListInstalled(self, callback = None):
+ print "STARTIPKGLISTINSTALLED"
if callback is not None:
- SoftwareTools.list_updating = True
- if SoftwareTools.list_updating:
+ self.list_updating = True
+ if self.list_updating:
if not self.UpdateConsole:
self.UpdateConsole = Console()
cmd = "ipkg list_installed"
@@ -161,14 +276,14 @@ class SoftwareTools(DreamInfoHandler):
def IpkgListInstalledCB(self, result, retval, extra_args = None):
(callback) = extra_args
if result:
- SoftwareTools.installed_packetlist = {}
+ self.installed_packetlist = {}
for x in result.splitlines():
tokens = x.split(' - ')
name = tokens[0].strip()
if not any(name.endswith(x) for x in self.unwanted_extensions):
l = len(tokens)
version = l > 1 and tokens[1].strip() or ""
- SoftwareTools.installed_packetlist[name] = version
+ self.installed_packetlist[name] = version
for package in self.packagesIndexlist[:]:
if not self.verifyPrerequisites(package[0]["prerequisites"]):
self.packagesIndexlist.remove(package)
@@ -184,26 +299,26 @@ class SoftwareTools(DreamInfoHandler):
if len(self.UpdateConsole.appContainers) == 0:
callback(True)
else:
- SoftwareTools.list_updating = False
+ self.list_updating = False
if self.UpdateConsole:
if len(self.UpdateConsole.appContainers) == 0:
if callback is not None:
callback(False)
def countUpdates(self, callback = None):
- SoftwareTools.available_updates = 0
- SoftwareTools.available_updatelist = []
+ self.available_updates = 0
+ self.available_updatelist = []
for package in self.packagesIndexlist[:]:
attributes = package[0]["attributes"]
packagename = attributes["packagename"]
- for x in SoftwareTools.available_packetlist:
+ for x in self.available_packetlist:
if x[0] == packagename:
- if SoftwareTools.installed_packetlist.has_key(packagename):
- if SoftwareTools.installed_packetlist[packagename] != x[1]:
- SoftwareTools.available_updates +=1
- SoftwareTools.available_updatelist.append([packagename])
+ if self.installed_packetlist.has_key(packagename):
+ if self.installed_packetlist[packagename] != x[1]:
+ self.available_updates +=1
+ self.available_updatelist.append([packagename])
- SoftwareTools.list_updating = False
+ self.list_updating = False
if self.UpdateConsole:
if len(self.UpdateConsole.appContainers) == 0:
if callback is not None:
diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/meta/plugin_softwaremanager.xml b/lib/python/Plugins/SystemPlugins/SoftwareManager/meta/plugin_softwaremanager.xml
index cd425c33..4135a212 100755
--- a/lib/python/Plugins/SystemPlugins/SoftwareManager/meta/plugin_softwaremanager.xml
+++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/meta/plugin_softwaremanager.xml
@@ -3,27 +3,17 @@
<tag type="Software" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>SoftwareManager</name>
<packagename>enigma2-plugin-systemplugins-softwaremanager</packagename>
- <shortdescription>SoftwareManager manages your Dreambox software.</shortdescription>
+ <shortdescription>SoftwareManager manages your Dreambox software</shortdescription>
<description>The SoftwareManager manages your Dreambox software.\n
- It's easy to update your receiver's software, install or remove extensions or even backup and restore your system settings.
+ It's easy to update your receiver's software, install or remove plugins or even backup and restore your system settings.
</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_softwaremanager_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>SoftwareManager</name>
- <packagename>enigma2-plugin-systemplugins-softwaremanager</packagename>
- <shortdescription>Der SoftwareManager verwaltet Ihre Dreambox Software.</shortdescription>
- <description>Der SoftwareManager verwaltet Ihre Dreambox Software.\n
- Sie können nun einfach Ihre Dreambox-Software aktualisieren, neue Erweiterungen installieren oder entfernen,
- oder ihre Einstellungen sichern und wiederherstellen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_softwaremanager_de.jpg" />
- </info>
+
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-softwaremanager" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py
index 1e0ed4d5..707663a0 100755
--- a/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py
@@ -14,7 +14,8 @@ from Components.MenuList import MenuList
from Components.Sources.List import List
from Components.Slider import Slider
from Components.Harddisk import harddiskmanager
-from Components.config import config,getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations
+from Components.config import config,getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations, ConfigYesNo, ConfigSelection
+from Components.ConfigList import ConfigListScreen
from Components.Console import Console
from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
from Components.SelectionList import SelectionList
@@ -26,7 +27,8 @@ from Components.AVSwitch import AVSwitch
from Components.Network import iNetwork
from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN, SCOPE_METADIR
from Tools.LoadPixmap import LoadPixmap
-from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad
+from Tools.NumericalTextInput import NumericalTextInput
+from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad, eRCInput, getPrevAsciiCode
from cPickle import dump, load
from os import path as os_path, system as os_system, unlink, stat, mkdir, popen, makedirs, listdir, access, rename, remove, W_OK, R_OK, F_OK
from time import time, gmtime, strftime, localtime
@@ -43,6 +45,14 @@ config.plugins.configurationbackup = ConfigSubsection()
config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf', '/etc/resolv.conf', '/etc/default_gw', '/etc/hostname'])
+config.plugins.SoftwareManager = ConfigSubsection()
+config.plugins.SoftwareManager.overwriteConfigFiles = ConfigSelection(
+ [
+ ("Y", _("Yes, always")),
+ ("N", _("No, never")),
+ ("ask", _("Always ask"))
+ ], "Y")
+
def write_cache(cache_file, cache_data):
#Does a cPickle dump
if not os_path.isdir( os_path.dirname(cache_file) ):
@@ -109,13 +119,16 @@ class UpdatePluginMenu(Screen):
self.menu = args
self.list = []
self.oktext = _("\nPress OK on your remote control to continue.")
+ self.menutext = _("Press MENU on your remote control for additional options.")
+ self.infotext = _("Press INFO on your remote control for additional information.")
self.text = ""
self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
if self.menu == 0:
+ print "building menu entries"
self.list.append(("install-extensions", _("Manage extensions"), _("\nManage extensions or plugins for your Dreambox" ) + self.oktext, None))
self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext, None))
self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext, None))
- self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext, None))
+ self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext + "\n\n" + self.infotext, None))
self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext, None))
self.list.append(("ipkg-install", _("Install local extension"), _("\nScan for local extensions and install them." ) + self.oktext, None))
for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER):
@@ -136,7 +149,7 @@ class UpdatePluginMenu(Screen):
elif self.menu == 1:
self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext, None))
self.list.append(("backuplocation", _("Choose backup location"), _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext, None))
- self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext, None))
+ self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup.") + self.oktext + "\n\n" + self.infotext, None))
if config.usage.setup_level.index >= 2: # expert+
self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext, None))
self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext, None))
@@ -156,25 +169,25 @@ class UpdatePluginMenu(Screen):
self["menu"] = List(self.list)
self["key_red"] = StaticText(_("Close"))
- self["status"] = StaticText("")
+ self["status"] = StaticText(self.menutext)
- self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions"],
+ self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "MenuActions"],
{
"ok": self.go,
"back": self.close,
"red": self.close,
+ "menu": self.handleMenu,
+ "showEventInfo": self.handleInfo,
}, -1)
self.onLayoutFinish.append(self.layoutFinished)
self.backuppath = getBackupPath()
self.backupfile = getBackupFilename()
self.fullbackupfilename = self.backuppath + "/" + self.backupfile
self.onShown.append(self.setWindowTitle)
- #self.onClose.append(self.cleanup)
def layoutFinished(self):
idx = 0
self["menu"].index = idx
- #self.getUpdateInfos()
def setWindowTitle(self):
self.setTitle(_("Software management"))
@@ -201,9 +214,17 @@ class UpdatePluginMenu(Screen):
self.text = _("No network connection available.")
self["status"].setText(self.text)
+ def handleMenu(self):
+ self.session.open(SoftwareManagerSetup)
+
+ def handleInfo(self):
+ current = self["menu"].getCurrent()
+ if current:
+ currentEntry = current[0]
+ if currentEntry in ("system-backup","backupfiles"):
+ self.session.open(SoftwareManagerInfo, mode = "backupinfo")
def go(self):
- #iNetwork.stopPingConsole()
current = self["menu"].getCurrent()
if current:
currentEntry = current[0]
@@ -290,6 +311,185 @@ class UpdatePluginMenu(Screen):
self.exe = True
self.session.open(RestoreScreen, runRestore = True)
+class SoftwareManagerSetup(Screen, ConfigListScreen):
+
+ skin = """
+ <screen name="SoftwareManagerSetup" position="center,center" size="560,440" title="SoftwareManager setup">
+ <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
+ <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
+ <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
+ <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
+ <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
+ <widget name="config" position="5,50" size="550,350" scrollbarMode="showOnDemand" />
+ <ePixmap pixmap="skin_default/div-h.png" position="0,400" zPosition="1" size="560,2" />
+ <widget source="introduction" render="Label" position="5,410" size="550,30" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
+ </screen>"""
+
+ def __init__(self, session, skin_path = None):
+ Screen.__init__(self, session)
+ self.session = session
+ self.skin_path = skin_path
+ if self.skin_path == None:
+ self.skin_path = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager")
+
+ self.onChangedEntry = [ ]
+ self.setup_title = _("Software manager setup")
+ self.overwriteConfigfilesEntry = None
+
+ self.list = [ ]
+ ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changedEntry)
+
+ self["actions"] = ActionMap(["SetupActions"],
+ {
+ "cancel": self.keyCancel,
+ "save": self.apply,
+ }, -2)
+
+ self["key_red"] = StaticText(_("Cancel"))
+ self["key_green"] = StaticText(_("OK"))
+ self["key_yellow"] = StaticText()
+ self["key_blue"] = StaticText()
+ self["introduction"] = StaticText()
+
+ self.createSetup()
+ self.onLayoutFinish.append(self.layoutFinished)
+
+ def layoutFinished(self):
+ self.setTitle(self.setup_title)
+
+ def createSetup(self):
+ self.list = [ ]
+ self.overwriteConfigfilesEntry = getConfigListEntry(_("Overwrite configuration files ?"), config.plugins.SoftwareManager.overwriteConfigFiles)
+ self.list.append(self.overwriteConfigfilesEntry)
+ self["config"].list = self.list
+ self["config"].l.setSeperation(400)
+ self["config"].l.setList(self.list)
+ if not self.selectionChanged in self["config"].onSelectionChanged:
+ self["config"].onSelectionChanged.append(self.selectionChanged)
+ self.selectionChanged()
+
+ def selectionChanged(self):
+ if self["config"].getCurrent() == self.overwriteConfigfilesEntry:
+ self["introduction"].setText(_("Overwrite configuration files during software upgrade?"))
+ else:
+ self["introduction"].setText("")
+
+ def newConfig(self):
+ pass
+
+ def keyLeft(self):
+ ConfigListScreen.keyLeft(self)
+
+ def keyRight(self):
+ ConfigListScreen.keyRight(self)
+
+ def confirm(self, confirmed):
+ if not confirmed:
+ print "not confirmed"
+ return
+ else:
+ self.keySave()
+
+ def apply(self):
+ self.session.openWithCallback(self.confirm, MessageBox, _("Use this settings?"), MessageBox.TYPE_YESNO, timeout = 20, default = True)
+
+ def cancelConfirm(self, result):
+ if not result:
+ return
+ for x in self["config"].list:
+ x[1].cancel()
+ self.close()
+
+ def keyCancel(self):
+ if self["config"].isChanged():
+ self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"), MessageBox.TYPE_YESNO, timeout = 20, default = True)
+ else:
+ self.close()
+
+ # for summary:
+ def changedEntry(self):
+ for x in self.onChangedEntry:
+ x()
+ self.selectionChanged()
+
+ def getCurrentEntry(self):
+ return self["config"].getCurrent()[0]
+
+ def getCurrentValue(self):
+ return str(self["config"].getCurrent()[1].value)
+
+ def createSummary(self):
+ from Screens.Setup import SetupSummary
+ return SetupSummary
+
+
+class SoftwareManagerInfo(Screen):
+ skin = """
+ <screen name="SoftwareManagerInfo" position="center,center" size="560,440" title="SoftwareManager information">
+ <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
+ <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
+ <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
+ <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
+ <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
+ <widget source="list" render="Listbox" position="5,50" size="550,340" scrollbarMode="showOnDemand" selectionDisabled="0">
+ <convert type="TemplatedMultiContent">
+ {"template": [
+ MultiContentEntryText(pos = (5, 0), size = (540, 26), font=0, flags = RT_HALIGN_LEFT | RT_HALIGN_CENTER, text = 0), # index 0 is the name
+ ],
+ "fonts": [gFont("Regular", 24),gFont("Regular", 22)],
+ "itemHeight": 26
+ }
+ </convert>
+ </widget>
+ <ePixmap pixmap="skin_default/div-h.png" position="0,400" zPosition="1" size="560,2" />
+ <widget source="introduction" render="Label" position="5,410" size="550,30" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
+ </screen>"""
+
+ def __init__(self, session, skin_path = None, mode = None):
+ Screen.__init__(self, session)
+ self.session = session
+ self.mode = mode
+ self.skin_path = skin_path
+ if self.skin_path == None:
+ self.skin_path = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager")
+
+ self["actions"] = ActionMap(["ShortcutActions", "WizardActions"],
+ {
+ "back": self.close,
+ "red": self.close,
+ }, -2)
+
+ self.list = []
+ self["list"] = List(self.list)
+
+ self["key_red"] = StaticText(_("Close"))
+ self["key_green"] = StaticText()
+ self["key_yellow"] = StaticText()
+ self["key_blue"] = StaticText()
+ self["introduction"] = StaticText()
+
+ self.onLayoutFinish.append(self.layoutFinished)
+
+ def layoutFinished(self):
+ self.setTitle(_("Softwaremanager information"))
+ if self.mode is not None:
+ self.showInfos()
+
+ def showInfos(self):
+ if self.mode == "backupinfo":
+ self.list = []
+ backupfiles = config.plugins.configurationbackup.backupdirs.value
+ for entry in backupfiles:
+ print entry
+ self.list.append((entry,))
+ self['list'].setList(self.list)
+
class PluginManager(Screen, DreamInfoHandler):
@@ -409,6 +609,7 @@ class PluginManager(Screen, DreamInfoHandler):
statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' ))
elif status == 'error':
+ self["key_green"].setText(_("Continue"))
statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' ))
self["list"].style = "default"
@@ -416,8 +617,11 @@ class PluginManager(Screen, DreamInfoHandler):
def getUpdateInfos(self):
- self.setState('update')
- iSoftwareTools.startSoftwareTools(self.getUpdateInfosCB)
+ if (iSoftwareTools.lastDownloadDate is not None and iSoftwareTools.NetworkConnectionAvailable is False):
+ self.rebuildList()
+ else:
+ self.setState('update')
+ iSoftwareTools.startSoftwareTools(self.getUpdateInfosCB)
def getUpdateInfosCB(self, retval = None):
if retval is not None:
@@ -428,11 +632,17 @@ class PluginManager(Screen, DreamInfoHandler):
self["status"].setText(_("There are no updates available."))
self.rebuildList()
elif retval is False:
- self.setState('error')
- if iSoftwareTools.NetworkConnectionAvailable:
- self["status"].setText(_("Updatefeed not available."))
+ if iSoftwareTools.lastDownloadDate is None:
+ self.setState('error')
+ if iSoftwareTools.NetworkConnectionAvailable:
+ self["status"].setText(_("Updatefeed not available."))
+ else:
+ self["status"].setText(_("No network connection available."))
else:
- self["status"].setText(_("No network connection available."))
+ iSoftwareTools.lastDownloadDate = time()
+ iSoftwareTools.list_updating = True
+ self.setState('update')
+ iSoftwareTools.getUpdates(self.getUpdateInfosCB)
def rebuildList(self, retval = None):
if self.currentSelectedTag is None:
@@ -450,10 +660,14 @@ class PluginManager(Screen, DreamInfoHandler):
self["key_green"].setText(_("Uninstall"))
elif current[4] == 'installable':
self["key_green"].setText(_("Install"))
+ if iSoftwareTools.NetworkConnectionAvailable is False:
+ self["key_green"].setText("")
elif current[4] == 'remove':
self["key_green"].setText(_("Undo uninstall"))
elif current[4] == 'install':
self["key_green"].setText(_("Undo install"))
+ if iSoftwareTools.NetworkConnectionAvailable is False:
+ self["key_green"].setText("")
self["key_yellow"].setText(_("View details"))
self["key_blue"].setText("")
if len(self.selectedFiles) == 0 and iSoftwareTools.available_updates is not 0:
@@ -503,21 +717,31 @@ class PluginManager(Screen, DreamInfoHandler):
if entry[0] == detailsFile:
alreadyinList = True
if not alreadyinList:
- self.selectedFiles.append((detailsFile,current[4],current[3]))
- self.currentSelectedPackage = ((detailsFile,current[4],current[3]))
+ if (iSoftwareTools.NetworkConnectionAvailable is False and current[4] in ('installable','install')):
+ pass
+ else:
+ self.selectedFiles.append((detailsFile,current[4],current[3]))
+ self.currentSelectedPackage = ((detailsFile,current[4],current[3]))
if current[4] == 'installed':
self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'remove', True)
elif current[4] == 'installable':
- self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'install', True)
+ if iSoftwareTools.NetworkConnectionAvailable:
+ self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'install', True)
elif current[4] == 'remove':
self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installed', False)
elif current[4] == 'install':
- self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installable',False)
+ if iSoftwareTools.NetworkConnectionAvailable:
+ self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installable',False)
self["list"].setList(self.list)
self["list"].setIndex(idx)
self["list"].updateList(self.list)
self.selectionChanged()
-
+ elif self.currList == "status":
+ iSoftwareTools.lastDownloadDate = time()
+ iSoftwareTools.list_updating = True
+ self.setState('update')
+ iSoftwareTools.getUpdates(self.getUpdateInfosCB)
+
def handleSelected(self):
current = self["list"].getCurrent()
if current:
@@ -589,13 +813,13 @@ class PluginManager(Screen, DreamInfoHandler):
status = "remove"
else:
status = "installed"
- self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState))
+ self.list.append(self.buildEntryComponent(name, _(details), _(description), packagename, status, selected = selectState))
else:
if selectState == True:
status = "install"
else:
status = "installable"
- self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState))
+ self.list.append(self.buildEntryComponent(name, _(details), _(description), packagename, status, selected = selectState))
if len(self.list):
self.list.sort(key=lambda x: x[0])
self["list"].style = "default"
@@ -904,8 +1128,7 @@ class PluginDetails(Screen, DreamInfoHandler):
self.skin_path = plugin_path
self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
self.attributes = None
- self.translatedAttributes = None
- DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language)
+ DreamInfoHandler.__init__(self, self.statusCallback, blocking = False)
self.directory = resolveFilename(SCOPE_METADIR)
if packagedata:
self.pluginname = packagedata[0]
@@ -943,8 +1166,6 @@ class PluginDetails(Screen, DreamInfoHandler):
self.package = self.packageDetails[0]
if self.package[0].has_key("attributes"):
self.attributes = self.package[0]["attributes"]
- if self.package[0].has_key("translation"):
- self.translatedAttributes = self.package[0]["translation"]
self.cmdList = []
self.oktext = _("\nAfter pressing OK, please wait!")
@@ -954,7 +1175,7 @@ class PluginDetails(Screen, DreamInfoHandler):
self.onLayoutFinish.append(self.setInfos)
def setWindowTitle(self):
- self.setTitle(_("Details for extension: " + self.pluginname))
+ self.setTitle(_("Details for plugin: ") + self.pluginname )
def exit(self):
self.close(False)
@@ -969,36 +1190,31 @@ class PluginDetails(Screen, DreamInfoHandler):
pass
def setInfos(self):
- if self.translatedAttributes.has_key("name"):
- self.pluginname = self.translatedAttributes["name"]
- elif self.attributes.has_key("name"):
+ if self.attributes.has_key("screenshot"):
+ self.loadThumbnail(self.attributes)
+
+ if self.attributes.has_key("name"):
self.pluginname = self.attributes["name"]
else:
self.pluginname = _("unknown")
- if self.translatedAttributes.has_key("author"):
- self.author = self.translatedAttributes["author"]
- elif self.attributes.has_key("author"):
+ if self.attributes.has_key("author"):
self.author = self.attributes["author"]
else:
self.author = _("unknown")
- if self.translatedAttributes.has_key("description"):
- self.description = self.translatedAttributes["description"]
- elif self.attributes.has_key("description"):
- self.description = self.attributes["description"]
+ if self.attributes.has_key("description"):
+ self.description = _(self.attributes["description"].replace("\\n", "\n"))
else:
self.description = _("No description available.")
- if self.translatedAttributes.has_key("screenshot"):
- self.loadThumbnail(self.translatedAttributes)
- else:
- self.loadThumbnail(self.attributes)
-
self["author"].setText(_("Author: ") + self.author)
- self["detailtext"].setText(self.description.strip())
+ self["detailtext"].setText(_(self.description))
if self.pluginstate in ('installable', 'install'):
- self["key_green"].setText(_("Install"))
+ if iSoftwareTools.NetworkConnectionAvailable:
+ self["key_green"].setText(_("Install"))
+ else:
+ self["key_green"].setText("")
else:
self["key_green"].setText(_("Remove"))
@@ -1006,10 +1222,17 @@ class PluginDetails(Screen, DreamInfoHandler):
thumbnailUrl = None
if entry.has_key("screenshot"):
thumbnailUrl = entry["screenshot"]
+ if self.language == "de":
+ if thumbnailUrl[-7:] == "_en.jpg":
+ thumbnailUrl = thumbnailUrl[:-7] + "_de.jpg"
+
if thumbnailUrl is not None:
self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1]
print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail
- client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
+ if iSoftwareTools.NetworkConnectionAvailable:
+ client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
+ else:
+ self.setThumbnail(noScreenshot = True)
else:
self.setThumbnail(noScreenshot = True)
@@ -1049,11 +1272,12 @@ class PluginDetails(Screen, DreamInfoHandler):
if len(self.cmdList):
self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext)
else:
- if self.packagefiles:
- for package in self.packagefiles[:]:
- self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
- if len(self.cmdList):
- self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext)
+ if iSoftwareTools.NetworkConnectionAvailable:
+ if self.packagefiles:
+ for package in self.packagefiles[:]:
+ self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
+ if len(self.cmdList):
+ self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext)
def runUpgrade(self, result):
if result:
@@ -1095,11 +1319,11 @@ class PluginDetails(Screen, DreamInfoHandler):
class UpdatePlugin(Screen):
skin = """
- <screen name="UpdatePlugin" position="center,center" size="550,200" title="Software update" >
+ <screen name="UpdatePlugin" position="center,center" size="550,300" title="Software update" >
<widget name="activityslider" position="0,0" size="550,5" />
<widget name="slider" position="0,150" size="550,30" />
<widget source="package" render="Label" position="10,30" size="540,20" font="Regular;18" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
- <widget source="status" render="Label" position="10,60" size="540,45" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
+ <widget source="status" render="Label" position="10,180" size="540,100" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
</screen>"""
def __init__(self, session, args = None):
@@ -1115,9 +1339,11 @@ class UpdatePlugin(Screen):
self["status"] = self.status
self.package = StaticText()
self["package"] = self.package
+ self.oktext = _("Press OK on your remote control to continue.")
self.packages = 0
self.error = 0
+ self.processed_packages = []
self.activity = 0
self.activityTimer = eTimer()
@@ -1151,20 +1377,34 @@ class UpdatePlugin(Screen):
self.slider.setValue(self.sliderPackages[param])
self.package.setText(param)
self.status.setText(_("Upgrading"))
- self.packages += 1
+ if not param in self.processed_packages:
+ self.processed_packages.append(param)
+ self.packages += 1
elif event == IpkgComponent.EVENT_INSTALL:
self.package.setText(param)
self.status.setText(_("Installing"))
- self.packages += 1
+ if not param in self.processed_packages:
+ self.processed_packages.append(param)
+ self.packages += 1
+ elif event == IpkgComponent.EVENT_REMOVE:
+ self.package.setText(param)
+ self.status.setText(_("Removing"))
+ if not param in self.processed_packages:
+ self.processed_packages.append(param)
+ self.packages += 1
elif event == IpkgComponent.EVENT_CONFIGURING:
self.package.setText(param)
self.status.setText(_("Configuring"))
+
elif event == IpkgComponent.EVENT_MODIFIED:
- self.session.openWithCallback(
- self.modificationCallback,
- MessageBox,
- _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
- )
+ if config.plugins.SoftwareManager.overwriteConfigFiles.value in ("N", "Y"):
+ self.ipkg.write(True and config.plugins.SoftwareManager.overwriteConfigFiles.value)
+ else:
+ self.session.openWithCallback(
+ self.modificationCallback,
+ MessageBox,
+ _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
+ )
elif event == IpkgComponent.EVENT_ERROR:
self.error += 1
elif event == IpkgComponent.EVENT_DONE:
@@ -1177,8 +1417,8 @@ class UpdatePlugin(Screen):
self.activityTimer.stop()
self.activityslider.setValue(0)
- self.package.setText("")
- self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
+ self.package.setText(_("Done - Installed or upgraded %d packages") % self.packages)
+ self.status.setText(self.oktext)
else:
self.activityTimer.stop()
self.activityslider.setValue(0)
@@ -1381,7 +1621,7 @@ class IPKGSource(Screen):
self["text"].number(number)
-class PacketManager(Screen):
+class PacketManager(Screen, NumericalTextInput):
skin = """
<screen name="PacketManager" position="center,center" size="530,420" title="Packet manager" >
<ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
@@ -1405,15 +1645,29 @@ class PacketManager(Screen):
def __init__(self, session, plugin_path, args = None):
Screen.__init__(self, session)
+ NumericalTextInput.__init__(self)
self.session = session
self.skin_path = plugin_path
- self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
+ self.setUseableChars(u'1234567890abcdefghijklmnopqrstuvwxyz')
+
+ self["shortcuts"] = NumberActionMap(["ShortcutActions", "WizardActions", "NumberActions", "InputActions", "InputAsciiActions", "KeyboardInputActions" ],
{
"ok": self.go,
"back": self.exit,
"red": self.exit,
"green": self.reload,
+ "gotAsciiCode": self.keyGotAscii,
+ "1": self.keyNumberGlobal,
+ "2": self.keyNumberGlobal,
+ "3": self.keyNumberGlobal,
+ "4": self.keyNumberGlobal,
+ "5": self.keyNumberGlobal,
+ "6": self.keyNumberGlobal,
+ "7": self.keyNumberGlobal,
+ "8": self.keyNumberGlobal,
+ "9": self.keyNumberGlobal,
+ "0": self.keyNumberGlobal
}, -1)
self.list = []
@@ -1425,6 +1679,7 @@ class PacketManager(Screen):
self.list_updating = True
self.packetlist = []
self.installed_packetlist = {}
+ self.upgradeable_packages = {}
self.Console = Console()
self.cmdList = []
self.cachelist = []
@@ -1432,18 +1687,51 @@ class PacketManager(Screen):
self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
self.oktext = _("\nAfter pressing OK, please wait!")
self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox')
+ self.opkgAvail = fileExists('/usr/bin/opkg')
self.ipkg = IpkgComponent()
self.ipkg.addCallback(self.ipkgCallback)
self.onShown.append(self.setWindowTitle)
self.onLayoutFinish.append(self.rebuildList)
+ rcinput = eRCInput.getInstance()
+ rcinput.setKeyboardMode(rcinput.kmAscii)
+
+ def keyNumberGlobal(self, val):
+ key = self.getKey(val)
+ if key is not None:
+ keyvalue = key.encode("utf-8")
+ if len(keyvalue) == 1:
+ self.setNextIdx(keyvalue[0])
+
+ def keyGotAscii(self):
+ keyvalue = unichr(getPrevAsciiCode()).encode("utf-8")
+ if len(keyvalue) == 1:
+ self.setNextIdx(keyvalue[0])
+
+ def setNextIdx(self,char):
+ if char in ("0", "1", "a"):
+ self["list"].setIndex(0)
+ else:
+ idx = self.getNextIdx(char)
+ if idx and idx <= self["list"].count:
+ self["list"].setIndex(idx)
+
+ def getNextIdx(self,char):
+ idx = 0
+ for i in self["list"].list:
+ if i[0][0] == char:
+ return idx
+ idx += 1
+
def exit(self):
self.ipkg.stop()
if self.Console is not None:
if len(self.Console.appContainers):
for name in self.Console.appContainers.keys():
self.Console.kill(name)
+ rcinput = eRCInput.getInstance()
+ rcinput.setKeyboardMode(rcinput.kmNone)
self.close()
def reload(self):
@@ -1561,14 +1849,19 @@ class PacketManager(Screen):
def IpkgList_Finished(self, result, retval, extra_args = None):
if result:
self.packetlist = []
+ last_name = ""
for x in result.splitlines():
- tokens = x.split(' - ') #self.blacklisted_packages
+ tokens = x.split(' - ')
name = tokens[0].strip()
if not any(name.endswith(x) for x in self.unwanted_extensions):
l = len(tokens)
version = l > 1 and tokens[1].strip() or ""
descr = l > 2 and tokens[2].strip() or ""
+ if name == last_name:
+ continue
+ last_name = name
self.packetlist.append([name, version, descr])
+
if not self.Console:
self.Console = Console()
cmd = "ipkg list_installed"
@@ -1578,30 +1871,47 @@ class PacketManager(Screen):
if result:
self.installed_packetlist = {}
for x in result.splitlines():
- tokens = x.split(' - ') #self.blacklisted_packages
+ tokens = x.split(' - ')
name = tokens[0].strip()
if not any(name.endswith(x) for x in self.unwanted_extensions):
l = len(tokens)
version = l > 1 and tokens[1].strip() or ""
self.installed_packetlist[name] = version
- self.buildPacketList()
+ if self.opkgAvail:
+ if not self.Console:
+ self.Console = Console()
+ cmd = "opkg list-upgradable"
+ self.Console.ePopen(cmd, self.OpkgListUpgradeable_Finished)
+ else:
+ self.buildPacketList()
+ def OpkgListUpgradeable_Finished(self, result, retval, extra_args = None):
+ if result:
+ self.upgradeable_packages = {}
+ for x in result.splitlines():
+ tokens = x.split(' - ')
+ name = tokens[0].strip()
+ if not any(name.endswith(x) for x in self.unwanted_extensions):
+ l = len(tokens)
+ version = l > 2 and tokens[2].strip() or ""
+ self.upgradeable_packages[name] = version
+ self.buildPacketList()
+
def buildEntryComponent(self, name, version, description, state):
divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
if state == 'installed':
installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
- return((name, version, description, state, installedpng, divpng))
+ return((name, version, _(description), state, installedpng, divpng))
elif state == 'upgradeable':
upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgradeable.png"))
- return((name, version, description, state, upgradeablepng, divpng))
+ return((name, version, _(description), state, upgradeablepng, divpng))
else:
installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
- return((name, version, description, state, installablepng, divpng))
+ return((name, version, _(description), state, installablepng, divpng))
def buildPacketList(self):
self.list = []
self.cachelist = []
-
if self.cache_ttl > 0 and self.vc != 0:
print 'Loading packagelist cache from ',self.cache_file
try:
@@ -1617,24 +1927,28 @@ class PacketManager(Screen):
print 'rebuilding fresh package list'
for x in self.packetlist:
status = ""
- if self.installed_packetlist.has_key(x[0].strip()):
- if self.installed_packetlist[x[0].strip()] == x[1].strip():
- status = "installed"
- self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
+ if self.installed_packetlist.has_key(x[0]):
+ if self.opkgAvail:
+ if self.upgradeable_packages.has_key(x[0]):
+ status = "upgradeable"
+ else:
+ status = "installed"
else:
- status = "upgradeable"
- self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
+ if self.installed_packetlist[x[0]] == x[1]:
+ status = "installed"
+ else:
+ status = "upgradeable"
else:
status = "installable"
- self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
- if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions):
- self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
+ self.list.append(self.buildEntryComponent(x[0], x[1], x[2], status))
+ self.cachelist.append([x[0], x[1], x[2], status])
write_cache(self.cache_file, self.cachelist)
self['list'].setList(self.list)
def reloadPluginlist(self):
plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
+
class IpkgInstaller(Screen):
skin = """
<screen name="IpkgInstaller" position="center,center" size="550,450" title="Install extensions" >
diff --git a/lib/python/Plugins/SystemPlugins/TempFanControl/LICENSE b/lib/python/Plugins/SystemPlugins/TempFanControl/LICENSE
new file mode 100755
index 00000000..99700593
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/TempFanControl/LICENSE
@@ -0,0 +1,12 @@
+This plugin is licensed under the Creative Commons
+Attribution-NonCommercial-ShareAlike 3.0 Unported
+License. To view a copy of this license, visit
+http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative
+Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
+
+Alternatively, this plugin may be distributed and executed on hardware which
+is licensed by Dream Multimedia GmbH.
+
+This plugin is NOT free software. It is open source, you are allowed to
+modify it (if you keep the license), but it may not be commercially
+distributed other than under the conditions noted above.
diff --git a/lib/python/Plugins/SystemPlugins/TempFanControl/Makefile.am b/lib/python/Plugins/SystemPlugins/TempFanControl/Makefile.am
index 78ff11c3..cfdeb654 100644..100755
--- a/lib/python/Plugins/SystemPlugins/TempFanControl/Makefile.am
+++ b/lib/python/Plugins/SystemPlugins/TempFanControl/Makefile.am
@@ -1,5 +1,9 @@
installdir = $(LIBDIR)/enigma2/python/Plugins/SystemPlugins/TempFanControl
+SUBDIRS = meta
+
install_PYTHON = \
__init__.py \
plugin.py
+
+dist_install_DATA = LICENSE \ No newline at end of file
diff --git a/lib/python/Plugins/SystemPlugins/TempFanControl/meta/Makefile.am b/lib/python/Plugins/SystemPlugins/TempFanControl/meta/Makefile.am
new file mode 100755
index 00000000..da7be245
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/TempFanControl/meta/Makefile.am
@@ -0,0 +1,3 @@
+installdir = $(datadir)/meta
+
+dist_install_DATA = plugin_tempfancontrol.xml
diff --git a/lib/python/Plugins/SystemPlugins/TempFanControl/meta/plugin_tempfancontrol.xml b/lib/python/Plugins/SystemPlugins/TempFanControl/meta/plugin_tempfancontrol.xml
new file mode 100755
index 00000000..5c6565a9
--- /dev/null
+++ b/lib/python/Plugins/SystemPlugins/TempFanControl/meta/plugin_tempfancontrol.xml
@@ -0,0 +1,20 @@
+<default>
+ <prerequisites>
+ <hardware type="dm8000" />
+ <hardware type="dm500hd" />
+ <hardware type="dm800se" />
+ <hardware type="dm7020hd" />
+ <tag type="System" />
+ </prerequisites>
+ <info>
+ <author>Dream Multimedia</author>
+ <name>TempFanControl</name>
+ <packagename>enigma2-plugin-systemplugins-tempfancontrol</packagename>
+ <shortdescription>Control your system fan</shortdescription>
+ <description>Control your internal system fan.</description>
+ </info>
+
+ <files type="package"> <!-- without version, without .ipk -->
+ <file type="package" name="enigma2-plugin-systemplugins-tempfancontrol" />
+ </files>
+</default>
diff --git a/lib/python/Plugins/SystemPlugins/TempFanControl/plugin.py b/lib/python/Plugins/SystemPlugins/TempFanControl/plugin.py
index c8af9cdd..42fe82da 100644..100755
--- a/lib/python/Plugins/SystemPlugins/TempFanControl/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/TempFanControl/plugin.py
@@ -131,6 +131,7 @@ class TempFanControl(Screen, ConfigListScreen):
ConfigListScreen.__init__(self, self.list, session = self.session)
#self["config"].list = self.list
#self["config"].setList(self.list)
+ self["config"].l.setSeperation(300)
self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
{
diff --git a/lib/python/Plugins/SystemPlugins/VideoEnhancement/meta/plugin_videoenhancement.xml b/lib/python/Plugins/SystemPlugins/VideoEnhancement/meta/plugin_videoenhancement.xml
index 208c7e0c..f52b4dab 100755
--- a/lib/python/Plugins/SystemPlugins/VideoEnhancement/meta/plugin_videoenhancement.xml
+++ b/lib/python/Plugins/SystemPlugins/VideoEnhancement/meta/plugin_videoenhancement.xml
@@ -3,25 +3,19 @@
<hardware type="dm8000" />
<hardware type="dm800" />
<hardware type="dm500hd" />
+ <hardware type="dm800se" />
+ <hardware type="dm7020hd" />
<tag type="Display" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>VideoEnhancement</name>
<packagename>enigma2-plugin-systemplugins-videoenhancement</packagename>
- <shortdescription>VideoEnhancement provides advanced video enhancement settings.</shortdescription>
- <description>The VideoEnhancement extension provides advanced video enhancement settings.</description>
+ <shortdescription>VideoEnhancement provides advanced video enhancement settings</shortdescription>
+ <description>The VideoEnhancement plugin provides advanced video enhancement settings.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_videoenhancement_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>Erweiterte A/V Einstellungen</name>
- <packagename>enigma2-plugin-systemplugins-videoenhancement</packagename>
- <shortdescription>Erweiterte A/V Einstellungen für Ihre Dreambox.</shortdescription>
- <description>Erweiterte A/V Einstellungen für Ihre Dreambox.</description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_videoenhancement_de.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-videoenhancement" />
diff --git a/lib/python/Plugins/SystemPlugins/VideoTune/meta/plugin_videotune.xml b/lib/python/Plugins/SystemPlugins/VideoTune/meta/plugin_videotune.xml
index c4609433..78b170ac 100755
--- a/lib/python/Plugins/SystemPlugins/VideoTune/meta/plugin_videotune.xml
+++ b/lib/python/Plugins/SystemPlugins/VideoTune/meta/plugin_videotune.xml
@@ -3,23 +3,14 @@
<tag type="Display" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>VideoTune</name>
<packagename>enigma2-plugin-systemplugins-videotune</packagename>
- <shortdescription>VideoTune helps fine-tuning your tv display.</shortdescription>
+ <shortdescription>VideoTune helps fine-tuning your tv display</shortdescription>
<description>The VideoTune helps fine-tuning your tv display.\nYou can control brightness and contrast of your tv.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_videotune.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia - DE</author>
- <name>VideoTune - DE </name>
- <packagename>enigma2-plugin-systemplugins-videotune</packagename>
- <shortdescription>VideoTune hilft beim fein-einstellen des Fernsehers.</shortdescription>
- <description>VideoTune hilf beim fein-einstellen des Fernsehers.\nSie können Kontrast und Helligkeit fein-einstellen.
- </description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_videotune.jpg" />
- </info>
<files type="package"> <!-- ohne versionsnummer, ohne .ipkg -->
<file type="package" name="enigma2-plugin-systemplugins-videotune" />
</files>
diff --git a/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py b/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py
index e3b902f0..dc4e8c56 100644
--- a/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py
+++ b/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py
@@ -239,9 +239,9 @@ class VideoHardware:
portlist = self.getPortList()
for port in portlist:
descr = port
- if descr == 'DVI' and hw_type == 'dm500hd':
+ if descr == 'DVI' and hw_type in ('dm500hd', 'dm800se', 'dm7020hd'):
descr = 'HDMI'
- elif descr == 'DVI-PC' and hw_type == 'dm500hd':
+ elif descr == 'DVI-PC' and hw_type in ('dm500hd', 'dm800se', 'dm7020hd'):
descr = 'HDMI-PC'
lst.append((port, descr))
diff --git a/lib/python/Plugins/SystemPlugins/Videomode/VideoWizard.py b/lib/python/Plugins/SystemPlugins/Videomode/VideoWizard.py
index 15f4d516..18e81764 100644..100755
--- a/lib/python/Plugins/SystemPlugins/Videomode/VideoWizard.py
+++ b/lib/python/Plugins/SystemPlugins/Videomode/VideoWizard.py
@@ -12,14 +12,22 @@ from Tools.HardwareInfo import HardwareInfo
config.misc.showtestcard = ConfigBoolean(default = False)
class VideoWizardSummary(WizardSummary):
- skin = """
- <screen position="0,0" size="132,64">
+ skin = (
+ """<screen name="VideoWizardSummary" position="0,0" size="132,64" id="1">
<widget name="text" position="6,4" size="120,40" font="Regular;12" transparent="1" />
<widget source="parent.list" render="Label" position="6,40" size="120,21" font="Regular;14">
<convert type="StringListSelection" />
</widget>
<!--widget name="pic" pixmap="%s" position="6,22" zPosition="10" size="64,64" transparent="1" alphatest="on"/-->
- </screen>""" #% (resolveFilename(SCOPE_PLUGINS, "SystemPlugins/Videomode/lcd_Scart.png"))
+ </screen>""",
+ """<screen name="VideoWizardSummary" position="0,0" size="96,64" id="2">
+ <widget name="text" position="0,4" size="96,40" font="Regular;12" transparent="1" />
+ <widget source="parent.list" render="Label" position="0,40" size="96,21" font="Regular;14">
+ <convert type="StringListSelection" />
+ </widget>
+ <!--widget name="pic" pixmap="%s" position="0,22" zPosition="10" size="64,64" transparent="1" alphatest="on"/-->
+ </screen>""")
+ #% (resolveFilename(SCOPE_PLUGINS, "SystemPlugins/Videomode/lcd_Scart.png"))
def __init__(self, session, parent):
WizardSummary.__init__(self, session, parent)
@@ -82,7 +90,7 @@ class VideoWizard(WizardLanguage, Rc):
for port in self.hw.getPortList():
if self.hw.isPortUsed(port):
descr = port
- if descr == 'DVI' and hw_type == 'dm500hd':
+ if descr == 'DVI' and hw_type in ('dm500hd', 'dm800se', 'dm7020hd'):
descr = 'HDMI'
if port != "DVI-PC":
list.append((descr,port))
@@ -100,7 +108,7 @@ class VideoWizard(WizardLanguage, Rc):
self.inputSelect(self.selection)
if self["portpic"].instance is not None:
picname = self.selection
- if picname == "DVI" and HardwareInfo().get_device_name() == "dm500hd":
+ if picname == "DVI" and HardwareInfo().get_device_name() in ("dm500hd", "dm800se", "dm7020hd"):
picname = "HDMI"
self["portpic"].instance.setPixmapFromFile(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/Videomode/" + picname + ".png"))
diff --git a/lib/python/Plugins/SystemPlugins/Videomode/meta/plugin_videomode.xml b/lib/python/Plugins/SystemPlugins/Videomode/meta/plugin_videomode.xml
index fbb6e3f4..e16a7dc8 100755
--- a/lib/python/Plugins/SystemPlugins/Videomode/meta/plugin_videomode.xml
+++ b/lib/python/Plugins/SystemPlugins/Videomode/meta/plugin_videomode.xml
@@ -3,22 +3,14 @@
<tag type="Display" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>Videomode</name>
<packagename>enigma2-plugin-systemplugins-videomode</packagename>
- <shortdescription>Videomode provides advanced video modes.</shortdescription>
- <description>The Videomode extension provides advanced video modes.</description>
+ <shortdescription>Videomode provides advanced video mode settings</shortdescription>
+ <description>The Videomode plugin provides advanced video mode settings.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_videomode_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>Videomode</name>
- <packagename>enigma2-plugin-systemplugins-videomode</packagename>
- <shortdescription>Videomode bietet erweiterte Video Einstellungen.</shortdescription>
- <description>Die Videomode-Erweiterung bietet erweiterte Video-Einstellungen.</description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_videomode_de.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-videomode" />
diff --git a/lib/python/Plugins/SystemPlugins/WirelessLan/Makefile.am b/lib/python/Plugins/SystemPlugins/WirelessLan/Makefile.am
index 2f362379..bdc1a884 100755
--- a/lib/python/Plugins/SystemPlugins/WirelessLan/Makefile.am
+++ b/lib/python/Plugins/SystemPlugins/WirelessLan/Makefile.am
@@ -4,8 +4,6 @@ SUBDIRS = meta
install_PYTHON = \
__init__.py \
- flags.py \
- iwlibs.py \
plugin.py \
Wlan.py
diff --git a/lib/python/Plugins/SystemPlugins/WirelessLan/Wlan.py b/lib/python/Plugins/SystemPlugins/WirelessLan/Wlan.py
index 1c1471ce..baefd435 100755
--- a/lib/python/Plugins/SystemPlugins/WirelessLan/Wlan.py
+++ b/lib/python/Plugins/SystemPlugins/WirelessLan/Wlan.py
@@ -1,7 +1,3 @@
-#from enigma import eListboxPythonMultiContent, eListbox, gFont, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_HALIGN_CENTER
-#from Components.MultiContent import MultiContentEntryText
-#from Components.GUIComponent import GUIComponent
-#from Components.HTMLComponent import HTMLComponent
from Components.config import config, ConfigYesNo, NoSave, ConfigSubsection, ConfigText, ConfigSelection, ConfigPassword
from Components.Console import Console
@@ -10,7 +6,8 @@ from string import maketrans, strip
import sys
import types
from re import compile as re_compile, search as re_search
-from iwlibs import getNICnames, Wireless, Iwfreq
+from pythonwifi.iwlibs import getNICnames, Wireless, Iwfreq, getWNICnames
+from pythonwifi import flags as wififlags
list = []
list.append("WEP")
@@ -65,38 +62,42 @@ class Wlan:
print "self.iface im iwconfigFinished",self.iface
callback = extra_args
data = { 'essid': False, 'frequency': False, 'acesspoint': False, 'bitrate': False, 'encryption': False, 'quality': False, 'signal': False }
- #print "result im iwconfigFinished",result
for line in result.splitlines():
- #print "line",line
line = line.strip()
if "ESSID" in line:
if "off/any" in line:
ssid = _("No Connection")
else:
- tmpssid=(line[line.index('ESSID')+7:len(line)-1])
- if tmpssid == '':
- ssid = _("Hidden networkname")
- elif tmpssid ==' ':
- ssid = _("Hidden networkname")
+ if "Nickname" in line:
+ tmpssid=(line[line.index('ESSID')+7:line.index('" Nickname')])
+ if tmpssid == '':
+ ssid = _("Hidden networkname")
+ elif tmpssid ==' ':
+ ssid = _("Hidden networkname")
+ else:
+ ssid = tmpssid
else:
- ssid = tmpssid
- #print "SSID->",ssid
+ tmpssid=(line[line.index('ESSID')+7:len(line)-1])
+ if tmpssid == '':
+ ssid = _("Hidden networkname")
+ elif tmpssid ==' ':
+ ssid = _("Hidden networkname")
+ else:
+ ssid = tmpssid
+
if ssid is not None:
data['essid'] = ssid
if 'Frequency' in line:
frequency = line[line.index('Frequency')+10 :line.index(' GHz')]
- #print "Frequency",frequency
if frequency is not None:
data['frequency'] = frequency
if "Access Point" in line:
ap=line[line.index('Access Point')+14:len(line)-1]
- #print "AP",ap
if ap is not None:
data['acesspoint'] = ap
if "Bit Rate" in line:
br = line[line.index('Bit Rate')+9 :line.index(' Mb/s')]
- #print "Bitrate",br
if br is not None:
data['bitrate'] = br
if 'Encryption key' in line:
@@ -104,7 +105,6 @@ class Wlan:
enc = _("Disabled")
else:
enc = line[line.index('Encryption key')+15 :line.index(' Security')]
- #print "Encryption key",enc
if enc is not None:
data['encryption'] = _("Enabled")
if 'Quality' in line:
@@ -112,12 +112,10 @@ class Wlan:
qual = line[line.index('Quality')+8:line.index('/100')]
else:
qual = line[line.index('Quality')+8:line.index('Sig')]
- #print "Quality",qual
if qual is not None:
data['quality'] = qual
if 'Signal level' in line:
- signal = line[line.index('Signal level')+14 :line.index(' dBm')]
- #print "Signal level",signal
+ signal = line[line.index('Signal level')+13 :line.index(' dBm')]
if signal is not None:
data['signal'] = signal
@@ -130,7 +128,6 @@ class Wlan:
callback(True,self.wlaniface)
def getAdapterAttribute(self, attribute):
- print "im getAdapterAttribute"
if self.wlaniface.has_key(self.iface):
print "self.wlaniface.has_key",self.iface
if self.wlaniface[self.iface].has_key(attribute):
@@ -142,13 +139,17 @@ class Wlan:
def getWirelessInterfaces(self):
- iwifaces = None
- try:
- iwifaces = getNICnames()
- except:
- print "[Wlan.py] No Wireless Networkcards could be found"
-
- return iwifaces
+ device = re_compile('[a-z]{2,}[0-9]*:')
+ ifnames = []
+
+ fp = open('/proc/net/wireless', 'r')
+ for line in fp:
+ try:
+ # append matching pattern, without the trailing colon
+ ifnames.append(device.search(line).group()[:-1])
+ except AttributeError:
+ pass
+ return ifnames
def getNetworkList(self):
@@ -156,8 +157,8 @@ class Wlan:
ifobj = Wireless(self.iface) # a Wireless NIC Object
#Association mappings
- stats, quality, discard, missed_beacon = ifobj.getStatistics()
- snr = quality.signallevel - quality.noiselevel
+ #stats, quality, discard, missed_beacon = ifobj.getStatistics()
+ #snr = quality.signallevel - quality.noiselevel
try:
scanresults = ifobj.scan()
@@ -167,55 +168,47 @@ class Wlan:
if scanresults is not None:
aps = {}
+ (num_channels, frequencies) = ifobj.getChannelInfo()
+ index = 1
for result in scanresults:
-
bssid = result.bssid
-
- encryption = map(lambda x: hex(ord(x)), result.encode)
-
- if encryption[-1] == "0x8":
+
+ if result.encode.flags & wififlags.IW_ENCODE_DISABLED > 0:
+ encryption = False
+ elif result.encode.flags & wififlags.IW_ENCODE_NOKEY > 0:
encryption = True
else:
- encryption = False
-
+ encryption = None
+
+ signal = str(result.quality.siglevel-0x100) + " dBm"
+ quality = "%s/%s" % (result.quality.quality,ifobj.getQualityMax().quality)
+
extra = []
for element in result.custom:
element = element.encode()
extra.append( strip(self.asciify(element)) )
-
- if result.quality.sl is 0 and len(extra) > 0:
- begin = extra[0].find('SignalStrength=')+15
-
- done = False
- end = begin+1
-
- while not done:
- if extra[0][begin:end].isdigit():
- end += 1
- else:
- done = True
- end -= 1
-
- signal = extra[0][begin:end]
- #print "[Wlan.py] signal is:" + str(signal)
+ for element in extra:
+ print element
+ if 'SignalStrength' in element:
+ signal = element[element.index('SignalStrength')+15:element.index(',L')]
+ if 'LinkQuality' in element:
+ quality = element[element.index('LinkQuality')+12:len(element)]
- else:
- signal = str(result.quality.sl)
-
aps[bssid] = {
'active' : True,
'bssid': result.bssid,
- 'channel': result.frequency.getChannel(result.frequency.getFrequency()),
+ 'channel': frequencies.index(ifobj._formatFrequency(result.frequency.getFrequency())) + 1,
'encrypted': encryption,
'essid': strip(self.asciify(result.essid)),
'iface': self.iface,
- 'maxrate' : result.rate[-1],
- 'noise' : result.quality.getNoiselevel(),
- 'quality' : str(result.quality.quality),
- 'signal' : signal,
+ 'maxrate' : ifobj._formatBitrate(result.rate[-1][-1]),
+ 'noise' : '',#result.quality.nlevel-0x100,
+ 'quality' : str(quality),
+ 'signal' : str(signal),
'custom' : extra,
}
- print aps[bssid]
+ #print "GOT APS ENTRY:",aps[bssid]
+ index = index + 1
return aps
@@ -226,12 +219,11 @@ class Wlan:
self.channel = str(fq.getChannel(str(ifobj.getFrequency()[0:-3])))
except:
self.channel = 0
- #print ifobj.getStatistics()
status = {
- 'BSSID': str(ifobj.getAPaddr()),
+ 'BSSID': str(ifobj.getAPaddr()), #ifobj.getStatistics()
'ESSID': str(ifobj.getEssid()),
- 'quality': str(ifobj.getStatistics()[1].quality),
- 'signal': str(ifobj.getStatistics()[1].sl),
+ 'quality': "%s/%s" % (ifobj.getStatistics()[1].quality,ifobj.getQualityMax().quality),
+ 'signal': str(ifobj.getStatistics()[1].siglevel-0x100) + " dBm",
'bitrate': str(ifobj.getBitrate()),
'channel': str(self.channel),
#'channel': str(fq.getChannel(str(ifobj.getFrequency()[0:-3]))),
@@ -326,7 +318,6 @@ class wpaSupplicant:
essid = split[1][1:-1]
elif split[0] == 'proto':
- print "split[1]",split[1]
config.plugins.wlan.encryption.enabled.value = True
if split[1] == "WPA" :
mode = 'WPA'
@@ -354,12 +345,9 @@ class wpaSupplicant:
else:
config.plugins.wlan.encryption.wepkeytype.value = 'HEX'
config.plugins.wlan.encryption.psk.value = split[1]
- print "[Wlan.py] Got Encryption: WEP - keytype is: "+config.plugins.wlan.encryption.wepkeytype.value
- print "[Wlan.py] Got Encryption: WEP - key0 is: "+config.plugins.wlan.encryption.psk.value
elif split[0] == 'psk':
config.plugins.wlan.encryption.psk.value = split[1][1:-1]
- print "[Wlan.py] Got PSK: "+split[1][1:-1]
else:
pass
@@ -436,24 +424,30 @@ class Status:
if "off/any" in line:
ssid = _("No Connection")
else:
- tmpssid=(line[line.index('ESSID')+7:len(line)-1])
- if tmpssid == '':
- ssid = _("Hidden networkname")
- elif tmpssid ==' ':
- ssid = _("Hidden networkname")
+ if "Nickname" in line:
+ tmpssid=(line[line.index('ESSID')+7:line.index('" Nickname')])
+ if tmpssid == '':
+ ssid = _("Hidden networkname")
+ elif tmpssid ==' ':
+ ssid = _("Hidden networkname")
+ else:
+ ssid = tmpssid
else:
- ssid = tmpssid
- #print "SSID->",ssid
+ tmpssid=(line[line.index('ESSID')+7:len(line)-1])
+ if tmpssid == '':
+ ssid = _("Hidden networkname")
+ elif tmpssid ==' ':
+ ssid = _("Hidden networkname")
+ else:
+ ssid = tmpssid
if ssid is not None:
data['essid'] = ssid
if 'Frequency' in line:
frequency = line[line.index('Frequency')+10 :line.index(' GHz')]
- #print "Frequency",frequency
if frequency is not None:
data['frequency'] = frequency
if "Access Point" in line:
ap=line[line.index('Access Point')+14:len(line)]
- #print "AP",ap
if ap is not None:
data['acesspoint'] = ap
if ap == "Not-Associated":
@@ -467,7 +461,6 @@ class Status:
br += " Mb/s"
else:
br = line[line.index('Bit Rate')+9 :line.index(' Mb/s')] + " Mb/s"
- #print "Bitrate",br
if br is not None:
data['bitrate'] = br
if 'Encryption key' in line:
@@ -480,28 +473,30 @@ class Status:
enc = line[line.index('Encryption key')+15 :line.index(' Security')]
if enc is not None:
enc = _("Enabled")
- #print "Encryption key",enc
if enc is not None:
data['encryption'] = enc
if 'Quality' in line:
if "/100" in line:
- qual = line[line.index('Quality')+8:line.index('/100')]
+ #qual = line[line.index('Quality')+8:line.index('/100')]
+ qual = line[line.index('Quality')+8:line.index(' Signal')]
else:
qual = line[line.index('Quality')+8:line.index('Sig')]
- #print "Quality",qual
if qual is not None:
data['quality'] = qual
if 'Signal level' in line:
if "dBm" in line:
- signal = line[line.index('Signal level')+14 :line.index(' dBm')]
+ signal = line[line.index('Signal level')+13 :line.index(' dBm')]
signal += " dBm"
elif "/100" in line:
- signal = line[line.index('Signal level')+13:line.index('/100 Noise')]
- signal += "%"
+ if "Noise" in line:
+ signal = line[line.index('Signal level')+13:line.index(' Noise')]
+ else:
+ signal = line[line.index('Signal level')+13:len(line)]
else:
- signal = line[line.index('Signal level')+13:line.index(' Noise')]
- signal += "%"
- #print "Signal level",signal
+ if "Noise" in line:
+ signal = line[line.index('Signal level')+13:line.index(' Noise')]
+ else:
+ signal = line[line.index('Signal level')+13:len(line)]
if signal is not None:
data['signal'] = signal
@@ -515,12 +510,10 @@ class Status:
callback(True,self.wlaniface)
def getAdapterAttribute(self, iface, attribute):
- print "im getAdapterAttribute"
self.iface = iface
if self.wlaniface.has_key(self.iface):
- print "self.wlaniface.has_key",self.iface
if self.wlaniface[self.iface].has_key(attribute):
return self.wlaniface[self.iface][attribute]
return None
-iStatus = Status() \ No newline at end of file
+iStatus = Status()
diff --git a/lib/python/Plugins/SystemPlugins/WirelessLan/flags.py b/lib/python/Plugins/SystemPlugins/WirelessLan/flags.py
deleted file mode 100755
index 4435f845..00000000
--- a/lib/python/Plugins/SystemPlugins/WirelessLan/flags.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# -*- coding: ISO-8859-1 -*-
-# python-wifi -- a wireless library to access wireless cards via python
-# Copyright (C) 2004, 2005, 2006 Rman Joost
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1 of
-# the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA
-
-modes = ['Auto',
- 'Ad-Hoc',
- 'Managed',
- 'Master',
- 'Repeat',
- 'Second',
- 'Monitor']
-
-IFNAMSIZE = 16
-IW_ESSID_MAX_SIZE = 16
-
-KILO = 10**3
-MEGA = 10**6
-GIGA = 10**9
-
-# ioctl calls for the Linux/i386 kernel
-SIOCIWFIRST = 0x8B00 # FIRST ioctl identifier
-SIOCGIFCONF = 0x8912 # ifconf struct
-SIOCGIWNAME = 0x8B01 # get name == wireless protocol
-SIOCGIWFREQ = 0x8B05 # get channel/frequency
-SIOCSIWMODE = 0x8B06 # set the operation mode
-SIOCGIWMODE = 0x8B07 # get operation mode
-SIOCGIWSENS = 0x8B09 # get sensitivity
-SIOCGIWAP = 0x8B15 # get AP MAC address
-SIOCSIWSCAN = 0x8B18 # set scanning off
-SIOCGIWSCAN = 0x8B19 # get scanning results
-SIOCGIWRATE = 0x8B21 # get default bit rate
-SIOCGIWRTS = 0x8B23 # get rts/cts threshold
-SIOCGIWFRAG = 0x8B25 # get fragmention thrh
-SIOCGIWTXPOW = 0x8B27 # get transmit power (dBm)
-SIOCGIWRETRY = 0x8B29 # get retry limit
-SIOCGIWRANGE = 0x8B0B # range
-SIOCGIWSTATS = 0x8B0F # get wireless statistics
-SIOCSIWESSID = 0x8B1A # set essid
-SIOCGIWESSID = 0x8B1B # get essid
-SIOCGIWPOWER = 0x8B2D # get power managment settings
-SIOCGIWENCODE = 0x8B2B # get encryption information
-SIOCIWLAST = 0x8BFF # LAST ioctl identifier
-
-# Power management flags
-IW_POWER_ON = 0x0000 # No details ...
-IW_POWER_TYPE = 0xF000 # Type of parameter
-IW_POWER_PERIOD = 0x1000 # Value is a period/duration of
-IW_POWER_TIMEOUT = 0x2000 # Value is a timeout
-IW_POWER_MODE = 0x0F00 # Power management mode
-IW_POWER_MIN = 0x0001 # Value is a minimum
-IW_POWER_MAX = 0x0002 # Value is a maximum
-IW_POWER_RELATIVE = 0x0004 # Value is not in seconds/ms/us
-
-# Retry limits
-IW_RETRY_TYPE = 0xF000 # Type of parameter
-
-# encoding stuff
-IW_ENCODE_DISABLED = 0x8000 # encoding is disabled
-IW_ENCODE_NOKEY = 0x0800 # key is write only, not present
-
-# constants responsible for scanning
-IW_SCAN_MAX_DATA = 4096
-
-IW_EV_LCP_LEN = 4
-IW_EV_CHAR_LEN = IW_EV_LCP_LEN + IFNAMSIZE
-IW_EV_UINT_LEN = IW_EV_LCP_LEN + 4
-IW_EV_FREQ_LEN = IW_EV_LCP_LEN + 8
-IW_EV_ADDR_LEN = IW_EV_LCP_LEN + 16
-IW_EV_POINT_LEN = IW_EV_LCP_LEN + 4
-IW_EV_PARAM_LEN = IW_EV_LCP_LEN + 8
-IW_EV_QUAL_LEN = IW_EV_LCP_LEN + 4
-
-EPERM = 1
-E2BIG = 7
-EAGAIN = 11
-
-IWHT_NULL = 0
-IWHT_CHAR = 2
-IWHT_UINT = 4
-IWHT_FREQ = 5
-IWHT_ADDR = 6
-IWHT_POINT = 8
-IWHT_PARAM = 9
-IWHT_QUAL = 10
-
-IWEVFIRST = 0x8C00 # FIRST event identifier
-IWEVQUAL = 0x8C01 # Quality statistics from scan
-IWEVCUSTOM = 0x8C02 # Custom Ascii string from Driver
-IWEVLAST = 0x8C0A # LAST event identifier
diff --git a/lib/python/Plugins/SystemPlugins/WirelessLan/iwlibs.py b/lib/python/Plugins/SystemPlugins/WirelessLan/iwlibs.py
deleted file mode 100755
index c5f9c6d2..00000000
--- a/lib/python/Plugins/SystemPlugins/WirelessLan/iwlibs.py
+++ /dev/null
@@ -1,1114 +0,0 @@
-# -*- coding: ISO-8859-1 -*-
-# python-wifi -- a wireless library to access wireless cards via python
-# Copyright (C) 2004, 2005, 2006 Rman Joost
-#
-# Contributions from:
-# Mike Auty <m.auty@softhome.net> (Iwscanresult, Iwscan)
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1 of
-# the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA
-
-from struct import pack as struct_pack, \
- unpack as struct_unpack, \
- calcsize as struct_calcsize
-
-from array import array
-from math import ceil, log10
-from fcntl import ioctl
-from socket import AF_INET, SOCK_DGRAM, socket
-from time import sleep
-from re import compile
-
-from flags import *
-
-def getNICnames():
- """ extract wireless device names of /proc/net/wireless
-
- returns empty list if no devices are present
-
- >>> getNICnames()
- ['eth1', 'wifi0']
- """
- device = compile('[a-z]+[0-9]+')
- ifnames = []
-
- f = open('/proc/net/wireless', 'r')
- data = f.readlines()
- for line in data:
- try:
- ifnames.append(device.search(line).group())
- except AttributeError:
- pass
- # if we couldn't lookup the devices, try to ask the kernel
- if ifnames == []:
- ifnames = getConfiguredNICnames()
-
- return ifnames
-
-def getConfiguredNICnames():
- """get the *configured* ifnames by a systemcall
-
- >>> getConfiguredNICnames()
- []
- """
- iwstruct = Iwstruct()
- ifnames = []
- buff = array('c', '\0'*1024)
- caddr_t, length = buff.buffer_info()
- s = iwstruct.pack('iP', length, caddr_t)
- try:
- result = iwstruct._fcntl(SIOCGIFCONF, s)
- except IOError, (i, e):
- return i, e
-
- # get the interface names out of the buffer
- for i in range(0, 1024, 32):
- ifname = buff.tostring()[i:i+32]
- ifname = struct_unpack('32s', ifname)[0]
- ifname = ifname.split('\0', 1)[0]
- if ifname:
- # verify if ifnames are really wifi devices
- wifi = Wireless(ifname)
- result = wifi.getAPaddr()
- if result[0] == 0:
- ifnames.append(ifname)
-
- return ifnames
-
-def makedict(**kwargs):
- return kwargs
-
-
-class Wireless(object):
- """Access to wireless interfaces"""
-
- def __init__(self, ifname):
- self.sockfd = socket(AF_INET, SOCK_DGRAM)
- self.ifname = ifname
- self.iwstruct = Iwstruct()
-
- def getAPaddr(self):
- """ returns accesspoint mac address
-
- >>> from iwlibs import Wireless, getNICnames
- >>> ifnames = getNICnames()
- >>> ifnames
- ['eth1', 'wifi0']
- >>> wifi = Wireless(ifnames[0])
- >>> wifi.getAPaddr()
- '00:0D:88:8E:4E:93'
-
- Test with non-wifi card:
- >>> wifi = Wireless('eth0')
- >>> wifi.getAPaddr()
- (95, 'Operation not supported')
-
- Test with non-existant card:
- >>> wifi = Wireless('eth2')
- >>> wifi.getAPaddr()
- (19, 'No such device')
- """
- buff, s = self.iwstruct.pack_wrq(32)
- i, result = self.iwstruct.iw_get_ext(self.ifname,
- SIOCGIWAP,
- data=s)
- if i > 0:
- return result
-
- return self.iwstruct.getMAC(result)
-
- def getBitrate(self):
- """returns device currently set bit rate
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getBitrate()
- '11 Mb/s'
- """
- i, result = self.iwstruct.iw_get_ext(self.ifname,
- SIOCGIWRATE)
- if i > 0:
- return result
- iwfreq = Iwfreq(result)
- return iwfreq.getBitrate()
-
- def getBitrates(self):
- """returns the number of available bitrates for the device
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> num, rates = wifi.getBitrates()
- >>> num == len(rates)
- True
- """
- range = Iwrange(self.ifname)
- if range.errorflag:
- return (range.errorflag, range.error)
- return (range.num_bitrates, range.bitrates)
-
- def getChannelInfo(self):
- """returns the number of channels and available frequency for
- the device
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> num, rates = wifi.getChannelInfo()
- >>> num == len(rates)
- True
- """
- range = Iwrange(self.ifname)
- if range.errorflag:
- return (range.errorflag, range.error)
- return (range.num_channels, range.frequencies)
-
- def getEssid(self):
- """get essid information
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getEssid()
- 'romanofski'
- """
- essid = ""
- buff, s = self.iwstruct.pack_wrq(32)
- i, result = self.iwstruct.iw_get_ext(self.ifname,
- SIOCGIWESSID,
- data=s)
- if i > 0:
- return result
- str = buff.tostring()
- return str.strip('\x00')
-
- def setEssid(self, essid):
- """set essid """
- raise NotImplementedError
- if len(essid) > IW_ESSID_MAX_SIZE:
- return "essid to big"
- buff, s = self.iwstruct.pack_test(essid, 32)
- i, result = self.iwstruct.iw_get_ext(self.ifname,
- SIOCSIWESSID,
- data=s)
- if i > 0:
- return result
-
- def getEncryption(self):
- """get encryption information which is probably a string of '*',
- 'open', 'private'
-
- as a normal user, you will get a 'Operation not permitted'
- error:
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getEncryption()
- (1, 'Operation not permitted')
- """
- iwpoint = Iwpoint(self.ifname)
- if iwpoint.errorflag:
- return (iwpoint.errorflag, iwpoint.error)
- return iwpoint.getEncryptionKey()
-
- def getFragmentation(self):
- """returns fragmentation threshold
-
- It depends on what the driver says. If you have fragmentation
- threshold turned on, you'll get an int. If it's turned of
- you'll get a string: 'off'.
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getFragmentation()
- 'off'
- """
- iwparam = Iwparam(self.ifname, SIOCGIWFRAG)
- if iwparam.errorflag:
- return (iwparam.errorflag, iwparam.error)
- return iwparam.getValue()
-
- def getFrequency(self):
- """returns currently set frequency of the card
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getFrequency()
- '2.417GHz'
- """
- i, r = self.iwstruct.iw_get_ext(self.ifname,
- SIOCGIWFREQ)
- if i > 0:
- return (i, r)
- iwfreq = Iwfreq(r)
- return iwfreq.getFrequency()
-
-
- def getMode(self):
- """returns currently set operation mode
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getMode()
- 'Managed'
- """
- i, result = self.iwstruct.iw_get_ext(self.ifname,
- SIOCGIWMODE)
- if i > 0:
- return result
- mode = self.iwstruct.unpack('i', result[:4])[0]
- return modes[mode]
-
- def setMode(self, mode):
- """sets the operation mode """
- try:
- this_modes = [x.lower() for x in modes]
- mode = mode.lower()
- wifimode = this_modes.index(mode)
- except ValueError:
- return "Invalid operation mode!"
-
- s = self.iwstruct.pack('I', wifimode)
- i, result = self.iwstruct.iw_get_ext(self.ifname,
- SIOCSIWMODE,
- data=s)
- if i > 0:
- return result
-
- def getWirelessName(self):
- """ returns wireless name
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getWirelessName()
- 'IEEE 802.11-DS'
- """
- i, result = self.iwstruct.iw_get_ext(self.ifname,
- SIOCGIWNAME)
- if i > 0:
- return result
- return result.split('\0')[0]
-
- def getPowermanagement(self):
- """returns power management settings
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getPowermanagement()
- 'off'
- """
- iwparam = Iwparam(self.ifname, SIOCGIWPOWER)
- if iwparam.errorflag:
- return (iwparam.errorflag, iwparam.error)
- return iwparam.getValue()
-
-
- def getRetrylimit(self):
- """returns limit retry/lifetime
-
- man iwconfig:
- Most cards have MAC retransmissions, and some allow to set
- the behaviour of the retry mechanism.
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getRetrylimit()
- 16
- """
- iwparam = Iwparam(self.ifname, SIOCGIWRETRY)
- if iwparam.errorflag:
- return (iwparam.errorflag, iwparam.error)
- return iwparam.getValue()
-
- def getRTS(self):
- """returns rts threshold
-
- returns int, 'auto', 'fixed', 'off'
-
- man iwconfig:
- RTS/CTS adds a handshake before each packet transmission to
- make sure that the channel is clear. This adds overhead, but
- increases performance in case of hidden nodes or a large
- number of active nodes. This parameter sets the size of the
- smallest packet for which the node sends RTS; a value equal
- to the maximum packet size disable the mechanism.
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getRTS()
- 'off'
- """
- iwparam = Iwparam(self.ifname, SIOCGIWRTS)
- if iwparam.errorflag:
- return (iwparam.errorflag, iwparam.error)
- return iwparam.getValue()
-
- def getSensitivity(self):
- """returns sensitivity information
-
- man iwconfig:
- This is the lowest signal level for which the hardware
- attempt packet reception, signals weaker than this are
- ignored. This is used to avoid receiving background noise,
- so you should set it according to the average noise
- level. Positive values are assumed to be the raw value used
- by the hardware or a percentage, negative values are
- assumed to be dBm.
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getSensitivity()
- 'off'
-
- """
- iwparam = Iwparam(self.ifname, SIOCGIWSENS)
- if iwparam.errorflag:
- return (iwparam.errorflag, iwparam.error)
- return iwparam.getValue()
-
- def getTXPower(self):
- """returns transmit power in dBm
-
- >>> from iwlibs import Wireless
- >>> wifi = Wireless('eth1')
- >>> wifi.getTXPower()
- '17 dBm'
- """
- i, r = self.iwstruct.iw_get_ext(self.ifname,
- SIOCGIWTXPOW)
- if i > 0:
- return (i, r)
- iwfreq = Iwfreq(r)
- return iwfreq.getTransmitPower()
-
- def getStatistics(self):
- """returns statistics information which can also be found in
- /proc/net/wireless
- """
- iwstats = Iwstats(self.ifname)
- if iwstats.errorflag > 0:
- return (iwstats.errorflag, iwstats.error)
- return [iwstats.status, iwstats.qual, iwstats.discard,
- iwstats.missed_beacon]
-
- def scan(self):
- """returns Iwscanresult objects, after a successful scan"""
- iwscan = Iwscan(self.ifname)
- return iwscan.scan()
-
-
-class Iwstruct(object):
- """basic class to handle iwstruct data """
-
- def __init__(self):
- self.idx = 0
- self.sockfd = socket(AF_INET, SOCK_DGRAM)
-
- def parse_data(self, fmt, data):
- """ unpacks raw C data """
- size = struct_calcsize(fmt)
- idx = self.idx
-
- str = data[idx:idx + size]
- self.idx = idx+size
- value = struct_unpack(fmt, str)
-
- # take care of a tuple like (int, )
- if len(value) == 1:
- return value[0]
- else:
- return value
-
- def pack(self, fmt, *args):
- """ calls struct_pack and returns the result """
- return struct_pack(fmt, *args)
-
- def pack_wrq(self, buffsize):
- """ packs wireless request data for sending it to the kernel """
- # Prepare a buffer
- # We need the address of our buffer and the size for it. The
- # ioctl itself looks for the pointer to the address in our
- # memory and the size of it.
- # Dont change the order how the structure is packed!!!
- buff = array('c', '\0'*buffsize)
- caddr_t, length = buff.buffer_info()
- s = struct_pack('Pi', caddr_t, length)
- return buff, s
-
- def pack_test(self, string, buffsize):
- """ packs wireless request data for sending it to the kernel """
- buffsize = buffsize - len(string)
- buff = array('c', string+'\0'*buffsize)
- caddr_t, length = buff.buffer_info()
- s = struct_pack('Pii', caddr_t, length, 1)
- return buff, s
-
- def unpack(self, fmt, packed_data):
- """ unpacks data with given format """
- return struct_unpack(fmt, packed_data)
-
- def _fcntl(self, request, args):
- return ioctl(self.sockfd.fileno(), request, args)
-
- def iw_get_ext(self, ifname, request, data=None):
- """ read information from ifname """
- # put some additional data behind the interface name
- if data is not None:
- buff = IFNAMSIZE-len(ifname)
- ifreq = ifname + '\0'*buff
- ifreq = ifreq + data
- else:
- ifreq = (ifname + '\0'*32)
-
- try:
- result = self._fcntl(request, ifreq)
- except IOError, (i, e):
- return i, e
-
- return (0, result[16:])
-
- def getMAC(self, packed_data):
- """ extracts mac addr from packed data and returns it as str """
- mac_addr = struct_unpack('xxBBBBBB', packed_data[:8])
- return "%02X:%02X:%02X:%02X:%02X:%02X" % mac_addr
-
-class Iwparam(object):
- """class to hold iwparam data """
-
- def __init__(self, ifname, ioctl):
- # (i) value, (b) fixed, (b) disabled, (b) flags
- self.fmt = "ibbH"
- self.value = 0
- self.fixed = 0
- self.disabled = 0
- self.flags = 0
- self.errorflag = 0
- self.error = ""
- self.ioctl = ioctl
- self.ifname = ifname
- self.update()
-
- def getValue(self):
- """returns the value if not disabled """
-
- if self.disabled:
- return 'off'
- if self.flags & IW_RETRY_TYPE == 0:
- return self.getRLAttributes()
- else:
- return self.getPMAttributes()
-
- def getRLAttributes(self):
- """returns a string with attributes determined by self.flags
- """
- return self.value
-
- def getPMAttributes(self):
- """returns a string with attributes determined by self.flags
- and IW_POWER*
- """
- result = ""
-
- # Modifiers
- if self.flags & IW_POWER_MIN == 0:
- result = " min"
- if self.flags & IW_POWER_MAX == 0:
- result = " max"
-
- # Type
- if self.flags & IW_POWER_TIMEOUT == 0:
- result = " period:"
- else:
- result = " timeout:"
- # Value with or without units
- # IW_POWER_RELATIVE - value is *not* in s/ms/us
- if self.flags & IW_POWER_RELATIVE:
- result += "%f" %(float(self.value)/MEGA)
- else:
- if self.value >= MEGA:
- result += "%fs" %(float(self.value)/MEGA)
- elif self.value >= KILO:
- result += "%fms" %(float(self.value)/KILO)
- else:
- result += "%dus" % self.value
-
- return result
-
- def update(self):
- iwstruct = Iwstruct()
- i, r = iwstruct.iw_get_ext(self.ifname,
- self.ioctl)
- if i > 0:
- self.errorflag = i
- self.error = r
- self._parse(r)
-
- def _parse(self, data):
- """ unpacks iwparam data """
- iwstruct = Iwstruct()
- self.value, self.fixed, self.disabled, self.flags =\
- iwstruct.parse_data(self.fmt, data)
-
-class Iwfreq(object):
- """ class to hold iwfreq data
- delegates to Iwstruct class
- """
-
- def __init__(self, data=None):
- self.fmt = "ihbb"
- if data is not None:
- self.frequency = self.parse(data)
- else:
- self.frequency = 0
- self.iwstruct = Iwstruct()
-
- def __getattr__(self, attr):
- return getattr(self.iwstruct, attr)
-
- def parse(self, data):
- """ unpacks iwparam"""
-
- size = struct_calcsize(self.fmt)
- m, e, i, pad = struct_unpack(self.fmt, data[:size])
- # XXX well, its not *the* frequency - we need a better name
- if e == 0:
- return m
- else:
- return float(m)*10**e
-
- def getFrequency(self):
- """returns Frequency (str)
-
- data - binary data returned by systemcall (iw_get_ext())
- """
- freq = self.frequency
-
- if freq >= GIGA:
- return "%0.3fGHz" %(freq/GIGA)
-
- if freq >= MEGA:
- return "%0.3fMHZ" %(freq/MEGA)
-
- if freq >= KILO:
- return "%0.3fKHz" %(freq/KILO)
-
- def getBitrate(self):
- """ returns Bitrate in Mbit
-
- data - binary data returned by systemcall (iw_get_ext())
- """
- bitrate = self.frequency
-
- if bitrate >= GIGA:
- return "%i Gb/s" %(bitrate/GIGA)
-
- if bitrate >= MEGA:
- return "%i Mb/s" %(bitrate/MEGA)
-
- if bitrate >= KILO:
- return "%i Kb/s" %(bitrate/KILO)
-
- def getTransmitPower(self):
- """ returns transmit power in dbm """
- # XXX something flaky is going on with m and e
- # eg. m = 50 and e should than be 0, because the number is stored in
- # m and don't needs to be recalculated
- return "%i dBm" %self.mw2dbm(self.frequency/10)
-
- def getChannel(self, freq):
- """returns channel information given by frequency
-
- returns None if frequency can't be converted
- freq = frequency to convert (int)
- iwrange = Iwrange object
- """
-
- try:
- freq = float(freq)
- except:
- return None
-
- lut = {}
- #13 Channels beginning at 2.412GHz and inreasing by 0,005 GHz steps
- for i in range(0,12):
- cur = float( 2.412 + ( i * 0.005 ) )
- lut[str(cur)] = i+1
- # Channel 14 need special actions ;)
- lut['2.484'] = 14
-
-
- if str(freq) in lut.keys():
- return lut[str(freq)]
-
- return None
-
-
- def mw2dbm(self, mwatt):
- """ converts mw to dbm(float) """
- return ceil(10.0 * log10(mwatt))
-
- def _setFrequency(self, list):
- """sets self.frequency by given list
-
- currently only used by Iwrange
- """
- assert len(list) == 4
- m, e, i, pad = list
- if e == 0:
- self.frequency = m
- else:
- self.frequency = m #float(m)*10**e
-
-class Iwstats(object):
- """ class to hold iwstat data """
-
- def __init__(self, ifname):
- # (2B) status, 4B iw_quality, 6i iw_discarded
- self.fmt = "2B4B6i"
- self.status = 0
- self.qual = Iwquality()
- self.discard = {}
- self.missed_beacon = 0
- self.ifname = ifname
- self.errorflag = 0
- self.error = ""
- self.update()
-
- def update(self):
- iwstruct = Iwstruct()
- buff, s = iwstruct.pack_wrq(32)
- i, result = iwstruct.iw_get_ext(self.ifname,
- SIOCGIWSTATS,
- data=s)
- if i > 0:
- self.error = result
- self.errorflag = i
- self._parse(buff.tostring())
-
- def _parse(self, data):
- """ unpacks iwstruct data """
- struct = Iwstruct()
- iwqual = Iwquality()
- iwstats_data = struct.parse_data(self.fmt, data)
-
- self.status = iwstats_data[0:2]
- self.qual.quality, self.qual.sl, self.qual.nl,\
- self.qual.flags = iwstats_data[2:6]
- nwid, code, frag, retries, flags = iwstats_data[6:11]
- self.missed_beacon = iwstats_data[11:12][0]
- self.discard = makedict(nwid=nwid, code=code,
- fragment=frag, retries=retries, misc=flags)
-
-class Iwquality(object):
- """ class to hold iwquality data """
-
- def __init__(self):
- self.quality = 0
- self.sl = 0
- self.nl = 0
- self.updated = 0
- self.fmt = "4B"
-
- def parse(self, data):
- """ unpacks iwquality data """
- struct = Iwstruct()
- qual, sl, nl, flags = struct.parse_data(self.fmt, data)
-
- # compute signal and noise level
- self.signal_level = sl
- self.noise_level = nl
-
- # asign the other values
- self.quality = qual
- self.updated = flags
-
- def setValues(self, list):
- """ assigns values given by a list to our attributes """
- attributes = ["quality", "signallevel", "noise_level",
- "updated"]
- assert len(list) == 4
-
- for i in range(len(list)):
- setattr(self, attributes[i], list[i])
-
- def getSignallevel(self):
- """ returns signal level """
- return self.sl-0x100
-
- def setSignallevel(self, sl):
- """ sets signal level """
- self.sl = sl
- signallevel = property(getSignallevel, setSignallevel)
-
- def getNoiselevel(self):
- """ returns noise level """
- return self.nl - 0x100
-
- def setNoiselevel(self):
- raise NotImplementedError
- self.nl = nl
- noiselevel = property(getNoiselevel, setNoiselevel)
-
-class Iwpoint(object):
- """ class to hold iwpoint data """
-
- def __init__(self, ifname):
- self.key = [0,0,0,0]
- self.fields = 0
- self.flags = 0
- # (4B) pointer to data, H length, H flags
- self.fmt = "4BHH"
- self.errorflag = 0
- self.error = ""
- self.ifname = ifname
- self.update()
-
- def __getattr__(self, attr):
- return getattr(self.iwstruct, attr)
-
- def update(self):
- iwstruct = Iwstruct()
- buff, s = iwstruct.pack_wrq(32)
- i, result = iwstruct.iw_get_ext(self.ifname,
- SIOCGIWENCODE,
- data=s)
- if i > 0:
- self.errorflag = i
- self.error = result
- self._parse(result)
-
- def getEncryptionKey(self):
- """ returns encryption key as '**' or 'off' as str """
- if self.flags & IW_ENCODE_DISABLED != 0:
- return 'off'
- elif self.flags & IW_ENCODE_NOKEY != 0:
- # a key is set, so print it
- return '**' * self.fields
-
- def _parse(self, data):
- """ unpacks iwpoint data
- """
- iwstruct = Iwstruct()
- ptr, ptr, ptr, ptr, self.fields, self.flags =\
- iwstruct.parse_data(self.fmt, data)
- self.key = [ptr, ptr, ptr, ptr]
-
-class Iwrange(object):
- """holds iwrange struct """
- IW_MAX_FREQUENCIES = 32
-
- def __init__(self, ifname):
- self.fmt = "iiihb6ii4B4Bi32i2i2i2i2i3h8h2b2bhi8i2b3h2i2ihB17x"\
- + self.IW_MAX_FREQUENCIES*"ihbb"
-
- self.ifname = ifname
- self.errorflag = 0
- self.error = ""
-
- # informative stuff
- self.throughput = 0
-
- # nwid (or domain id)
- self.min_nwid = self.max_nwid = 0
-
- # frequency for backward compatibility
- self.old_num_channels = self.old_num_frequency = self.old_freq = 0
-
- # signal level threshold
- self.sensitivity = 0
-
- # link quality
- self.max_qual = Iwquality()
- self.avg_qual = Iwquality()
-
- # rates
- self.num_bitrates = 0
- self.bitrates = []
-
- # rts threshold
- self.min_rts = self.max_rts = 0
-
- # fragmention threshold
- self.min_frag = self.max_frag = 0
-
- # power managment
- self.min_pmp = self.max_pmp = 0
- self.min_pmt = self.max_pmt = 0
- self.pmp_flags = self.pmt_flags = self.pm_capa = 0
-
- # encoder stuff
- self.encoding_size = 0
- self.num_encoding_sizes = self.max_encoding_tokens = 0
- self.encoding_login_index = 0
-
- # transmit power
- self.txpower_capa = self.num_txpower = self.txpower = 0
-
- # wireless extension version info
- self.we_vers_compiled = self.we_vers_src = 0
-
- # retry limits and lifetime
- self.retry_capa = self.retry_flags = self.r_time_flags = 0
- self.min_retry = self.max_retry = 0
- self.min_r_time = self.max_r_time = 0
-
- # frequency
- self.num_channels = self.num_frequency = 0
- self.frequencies = []
- self.update()
-
- def update(self):
- """updates Iwrange object by a system call to the kernel
- and updates internal attributes
- """
- iwstruct = Iwstruct()
- buff, s = iwstruct.pack_wrq(640)
- i, result = iwstruct.iw_get_ext(self.ifname,
- SIOCGIWRANGE,
- data=s)
- if i > 0:
- self.errorflag = i
- self.error = result
- data = buff.tostring()
- self._parse(data)
-
- def _parse(self, data):
- struct = Iwstruct()
- result = struct.parse_data(self.fmt, data)
-
- # XXX there is maybe a much more elegant way to do this
- self.throughput, self.min_nwid, self.max_nwid = result[0:3]
- self.old_num_channels, self.old_num_frequency = result[3:5]
- self.old_freq = result[5:11]
- self.sensitivity = result[11]
- self.max_qual.setValues(result[12:16])
- self.avg_qual.setValues(result[16:20])
- self.num_bitrates = result[20] # <- XXX
- raw_bitrates = result[21:53]
- for rate in raw_bitrates:
- iwfreq = Iwfreq()
- iwfreq.frequency = rate
- br = iwfreq.getBitrate()
- if br is not None:
- self.bitrates.append(br)
-
- self.min_rts, self.max_rts = result[53:55]
- self.min_frag, self.max_frag = result[55:57]
- self.min_pmp, self.max_pmp = result[57:59]
- self.min_pmt, self.max_pmt = result[59:61]
- self.pmp_flags, self.pmt_flags, self.pm_capa = result[61:64]
- self.encoding_size = result[64:72]
- self.num_encoding_sizes, self.max_encoding_tokens = result[72:74]
- self.encoding_login_index = result[74:76]
- self.txpower_capa, self.num_txpower = result[76:78]
- self.txpower = result[78:86]
- self.we_vers_compiled, self.we_vers_src = result[86:88]
- self.retry_capa, self.retry_flags, self.r_time_flags = result[88:91]
- self.min_retry, self.max_retry = result[91:93]
- self.min_r_time, self.max_r_time = result[93:95]
- self.num_channels = result[95]
- self.num_frequency = result[96]
- freq = result[97:]
-
- i = self.num_frequency
- for x in range(0, len(freq), 4):
- iwfreq = Iwfreq()
- iwfreq._setFrequency(freq[x:x+4])
- fq = iwfreq.getFrequency()
- if fq is not None:
- self.frequencies.append(fq)
- i -= 1
- if i <= 0:
- break
-
-class Iwscan(object):
- """class to handle AP scanning"""
-
- def __init__(self, ifname):
- self.ifname = ifname
- self.range = Iwrange(ifname)
- self.errorflag = 0
- self.error = ""
- self.stream = None
- self.aplist = None
-
- def scan(self, fullscan=True):
- """Completes a scan for available access points,
- and returns them in Iwscanresult format
-
- fullscan: If False, data is read from a cache of the last scan
- If True, a scan is conducted, and then the data is read
- """
- # By default everything is fine, do not wait
- result = 1
- if fullscan:
- self.setScan()
- if self.errorflag > EPERM:
- raise RuntimeError, 'setScan failure ' + str(self.errorflag) + " " + str(self.error)
- return None
- elif self.errorflag < EPERM:
- # Permission was NOT denied, therefore we must WAIT to get results
- result = 250
-
- while (result > 0):
- sleep(result/1000)
- result = self.getScan()
-
- if result < 0 or self.errorflag != 0:
- raise RuntimeError, 'getScan failure ' + str(self.errorflag) + " " + str(self.error)
-
- return self.aplist
-
-
- def setScan(self):
- """Triggers the scan, if we have permission
- """
- iwstruct = Iwstruct()
- s = iwstruct.pack('Pii', 0, 0, 0)
- i, result = iwstruct.iw_get_ext(self.ifname,
- SIOCSIWSCAN,s)
- if i > 0:
- self.errorflag = i
- self.error = result
- return result
-
- def getScan(self):
- """Retreives results, stored from the most recent scan
- Returns 0 if successful, a delay if the data isn't ready yet
- or -1 if something really nasty happened
- """
- iwstruct = Iwstruct()
- i = E2BIG
- bufflen = IW_SCAN_MAX_DATA
-
- # Keep resizing the buffer until it's large enough to hold the scan
- while (i == E2BIG):
- buff, s = iwstruct.pack_wrq(bufflen)
- i, result = iwstruct.iw_get_ext(self.ifname,
- SIOCGIWSCAN,
- data=s)
- if i == E2BIG:
- pbuff, newlen = iwstruct.unpack('Pi', s)
- if bufflen < newlen:
- bufflen = newlen
- else:
- bufflen = bufflen * 2
-
- if i == EAGAIN:
- return 100
- if i > 0:
- self.errorflag = i
- self.error = result
- return -1
-
- pbuff, reslen = iwstruct.unpack('Pi', s)
- if reslen > 0:
- # Initialize the stream, and turn it into an enumerator
- self.aplist = self._parse(buff.tostring())
- return 0
-
- def _parse(self, data):
- """Parse the event stream, and return a list of Iwscanresult objects
- """
- iwstruct = Iwstruct()
- scanresult = None
- aplist = []
-
- # Run through the stream, until broken
- while 1:
- # If we're the stream doesn't have enough space left for a header, break
- if len(data) < IW_EV_LCP_LEN:
- break;
-
- # Unpack the header
- length, cmd = iwstruct.unpack('HH', data[:4])
- # If the header says the following data is shorter than the header, then break
- if length < IW_EV_LCP_LEN:
- break;
-
- # Put the events into their respective result data
- if cmd == SIOCGIWAP:
- if scanresult is not None:
- aplist.append(scanresult)
- scanresult = Iwscanresult(data[IW_EV_LCP_LEN:length], self.range)
- elif scanresult is None:
- raise RuntimeError, 'Attempting to add an event without AP data'
- else:
- scanresult.addEvent(cmd, data[IW_EV_LCP_LEN:length])
-
- # We're finished with the preveious event
- data = data[length:]
-
- # Don't forgset the final result
- if scanresult.bssid != "00:00:00:00:00:00":
- aplist.append(scanresult)
- else:
- raise RuntimeError, 'Attempting to add an AP without a bssid'
- return aplist
-
-class Iwscanresult(object):
- """An object to contain all the events associated with a single scanned AP
- """
-
- def __init__(self, data, range):
- """Initialize the scan result with the access point data"""
- self.iwstruct = Iwstruct()
- self.range = range
- self.bssid = "%02X:%02X:%02X:%02X:%02X:%02X" % struct_unpack('BBBBBB', data[2:8])
- self.essid = None
- self.mode = None
- self.rate = []
- self.quality = Iwquality()
- self.frequency = None
- self.encode = None
- self.custom = []
- self.protocol = None
-
- def addEvent(self, cmd, data):
- """Attempts to add the data from an event to a scanresult
- Only certain data is accept, in which case the result is True
- If the event data is invalid, None is returned
- If the data is valid but unused, False is returned
- """
- if cmd <= SIOCIWLAST:
- if cmd < SIOCIWFIRST:
- return None
- elif cmd >= IWEVFIRST:
- if cmd > IWEVLAST:
- return None
- else:
- return None
-
- if cmd == SIOCGIWESSID:
- self.essid = data[4:]
- elif cmd == SIOCGIWMODE:
- self.mode = modes[self.iwstruct.unpack('i', data[:4])[0]]
- elif cmd == SIOCGIWRATE:
- # TODO, deal with multiple rates, or at least the highest rate
- freqsize = struct_calcsize("ihbb")
- while len(data) >= freqsize:
- iwfreq = Iwfreq(data)
- self.rate.append(iwfreq.getBitrate())
- data = data[freqsize:]
- elif cmd == IWEVQUAL:
- self.quality.parse(data)
- elif cmd == SIOCGIWFREQ:
- self.frequency = Iwfreq(data)
- elif cmd == SIOCGIWENCODE:
- self.encode = data
- elif cmd == IWEVCUSTOM:
- self.custom.append(data[1:])
- elif cmd == SIOCGIWNAME:
- self.protocol = data[:len(data)-2]
- else:
- #print "Cmd:", cmd
- return False
- return True \ No newline at end of file
diff --git a/lib/python/Plugins/SystemPlugins/WirelessLan/meta/plugin_wirelesslan.xml b/lib/python/Plugins/SystemPlugins/WirelessLan/meta/plugin_wirelesslan.xml
index 1f882b32..eca6c0f9 100755
--- a/lib/python/Plugins/SystemPlugins/WirelessLan/meta/plugin_wirelesslan.xml
+++ b/lib/python/Plugins/SystemPlugins/WirelessLan/meta/plugin_wirelesslan.xml
@@ -3,22 +3,14 @@
<tag type="Network" />
<tag type="System" />
</prerequisites>
- <info language="en">
+ <info>
<author>Dream Multimedia</author>
<name>WirelessLan</name>
<packagename>enigma2-plugin-systemplugins-wirelesslan</packagename>
<shortdescription>Configure your WLAN network interface</shortdescription>
- <description>The WirelessLan extensions helps you configuring your WLAN network interface.</description>
+ <description>The WirelessLan plugin helps you configuring your WLAN network interface.</description>
<screenshot src="http://www.dreamboxupdate.com/preview/plugin_wirelesslan_en.jpg" />
</info>
- <info language="de">
- <author>Dream Multimedia</author>
- <name>WirelessLan</name>
- <packagename>enigma2-plugin-systemplugins-wirelesslan</packagename>
- <shortdescription>Konfigurieren Sie Ihr WLAN Netzwerk.</shortdescription>
- <description>Die WirelessLan Erweiterung hilft Ihnen beim konfigurieren Ihres WLAN Netzwerkes..</description>
- <screenshot src="http://www.dreamboxupdate.com/preview/plugin_wirelesslan_de.jpg" />
- </info>
<files type="package"> <!-- without version, without .ipk -->
<file type="package" name="enigma2-plugin-systemplugins-wirelesslan" />
diff --git a/lib/python/Plugins/SystemPlugins/WirelessLan/plugin.py b/lib/python/Plugins/SystemPlugins/WirelessLan/plugin.py
index a687714d..28ee363e 100755
--- a/lib/python/Plugins/SystemPlugins/WirelessLan/plugin.py
+++ b/lib/python/Plugins/SystemPlugins/WirelessLan/plugin.py
@@ -1,4 +1,4 @@
-from enigma import eTimer
+from enigma import eTimer, eTPM
from Screens.Screen import Screen
from Components.ActionMap import ActionMap, NumberActionMap
from Components.Pixmap import Pixmap,MultiPixmap
@@ -14,7 +14,9 @@ from Plugins.Plugin import PluginDescriptor
from os import system, path as os_path, listdir
from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
from Tools.LoadPixmap import LoadPixmap
+from Tools.HardwareInfo import HardwareInfo
from Wlan import Wlan, wpaSupplicant, iStatus
+import sha
plugin_path = "/usr/lib/enigma2/python/Plugins/SystemPlugins/WirelessLan"
@@ -122,7 +124,7 @@ class WlanStatus(Screen):
if status is not None:
self["BSSID"].setText(status[self.iface]["acesspoint"])
self["ESSID"].setText(status[self.iface]["essid"])
- self["quality"].setText(status[self.iface]["quality"]+"%")
+ self["quality"].setText(status[self.iface]["quality"])
self["signal"].setText(status[self.iface]["signal"])
self["bitrate"].setText(status[self.iface]["bitrate"])
self["enc"].setText(status[self.iface]["encryption"])
@@ -373,6 +375,45 @@ class WlanScan(Screen):
return self.WlanList
+def bin2long(s):
+ return reduce( lambda x,y:(x<<8L)+y, map(ord, s))
+
+def long2bin(l):
+ res = ""
+ for byte in range(128):
+ res += chr((l >> (1024 - (byte + 1) * 8)) & 0xff)
+ return res
+
+def rsa_pub1024(src, mod):
+ return long2bin(pow(bin2long(src), 65537, bin2long(mod)))
+
+def decrypt_block(src, mod):
+ if len(src) != 128 and len(src) != 202:
+ return None
+ dest = rsa_pub1024(src[:128], mod)
+ hash = sha.new(dest[1:107])
+ if len(src) == 202:
+ hash.update(src[131:192])
+ result = hash.digest()
+ if result == dest[107:127]:
+ return dest
+ return None
+
+def validate_cert(cert, key):
+ buf = decrypt_block(cert[8:], key)
+ if buf is None:
+ return None
+ return buf[36:107] + cert[139:196]
+
+def read_random():
+ try:
+ fd = open("/dev/urandom", "r")
+ buf = fd.read(8)
+ fd.close()
+ return buf
+ except:
+ return None
+
def WlanStatusScreenMain(session, iface):
session.open(WlanStatus, iface)
@@ -387,8 +428,32 @@ def callFunction(iface):
def configStrings(iface):
- driver = iNetwork.detectWlanModule()
- print "Found WLAN-Driver:",driver
+ hardware_info = HardwareInfo()
+ if hardware_info.device_name != "dm7025":
+ rootkey = ['\x9f', '|', '\xe4', 'G', '\xc9', '\xb4', '\xf4', '#', '&', '\xce', '\xb3', '\xfe', '\xda', '\xc9', 'U', '`', '\xd8', '\x8c', 's', 'o', '\x90', '\x9b', '\\', 'b', '\xc0', '\x89', '\xd1', '\x8c', '\x9e', 'J', 'T', '\xc5', 'X', '\xa1', '\xb8', '\x13', '5', 'E', '\x02', '\xc9', '\xb2', '\xe6', 't', '\x89', '\xde', '\xcd', '\x9d', '\x11', '\xdd', '\xc7', '\xf4', '\xe4', '\xe4', '\xbc', '\xdb', '\x9c', '\xea', '}', '\xad', '\xda', 't', 'r', '\x9b', '\xdc', '\xbc', '\x18', '3', '\xe7', '\xaf', '|', '\xae', '\x0c', '\xe3', '\xb5', '\x84', '\x8d', '\r', '\x8d', '\x9d', '2', '\xd0', '\xce', '\xd5', 'q', '\t', '\x84', 'c', '\xa8', ')', '\x99', '\xdc', '<', '"', 'x', '\xe8', '\x87', '\x8f', '\x02', ';', 'S', 'm', '\xd5', '\xf0', '\xa3', '_', '\xb7', 'T', '\t', '\xde', '\xa7', '\xf1', '\xc9', '\xae', '\x8a', '\xd7', '\xd2', '\xcf', '\xb2', '.', '\x13', '\xfb', '\xac', 'j', '\xdf', '\xb1', '\x1d', ':', '?']
+ etpm = eTPM()
+ l2cert = etpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
+ if l2cert is None:
+ return
+ l2key = validate_cert(l2cert, rootkey)
+ if l2key is None:
+ return
+ l3cert = etpm.getCert(eTPM.TPMD_DT_LEVEL3_CERT)
+ if l3cert is None:
+ print "better run the genuine dreambox plugin"
+ return
+ l3key = validate_cert(l3cert, l2key)
+ if l3key is None:
+ return
+ rnd = read_random()
+ if rnd is None:
+ return
+ val = etpm.challenge(rnd)
+ result = decrypt_block(val, l3key)
+ if hardware_info.device_name == "dm7025" or result[80:88] == rnd:
+ driver = iNetwork.detectWlanModule(iface)
+ else:
+ driver = 'dreambox'
if driver in ('ralink', 'zydas'):
return " pre-up /usr/sbin/wpa_supplicant -i"+iface+" -c/etc/wpa_supplicant.conf -B -D"+driver+"\n post-down wpa_cli terminate"
else:
@@ -399,4 +464,3 @@ def configStrings(iface):
def Plugins(**kwargs):
return PluginDescriptor(name=_("Wireless LAN"), description=_("Connect to a Wireless Network"), where = PluginDescriptor.WHERE_NETWORKSETUP, fnc={"ifaceSupported": callFunction, "configStrings": configStrings, "WlanPluginEntry": lambda x: "Wireless Network Configuartion..."})
- \ No newline at end of file
diff --git a/lib/python/Screens/AudioSelection.py b/lib/python/Screens/AudioSelection.py
new file mode 100644
index 00000000..a0bfcab9
--- /dev/null
+++ b/lib/python/Screens/AudioSelection.py
@@ -0,0 +1,314 @@
+from Screen import Screen
+from Components.ServiceEventTracker import ServiceEventTracker
+from Components.ActionMap import ActionMap
+from Components.ConfigList import ConfigListScreen
+from Components.ChoiceList import ChoiceList, ChoiceEntryComponent
+from Components.config import config, ConfigSubsection, getConfigListEntry, ConfigNothing, ConfigSelection, ConfigOnOff
+from Components.MultiContent import MultiContentEntryText
+from Components.Sources.List import List
+from Components.Sources.Boolean import Boolean
+from Components.SystemInfo import SystemInfo
+
+from enigma import iPlayableService
+
+from Tools.ISO639 import LanguageCodes
+from Tools.BoundFunction import boundFunction
+FOCUS_CONFIG, FOCUS_STREAMS = range(2)
+[PAGE_AUDIO, PAGE_SUBTITLES] = ["audio", "subtitles"]
+
+class AudioSelection(Screen, ConfigListScreen):
+ def __init__(self, session, infobar=None, page=PAGE_AUDIO):
+ Screen.__init__(self, session)
+
+ self["streams"] = List([])
+ self["key_red"] = Boolean(False)
+ self["key_green"] = Boolean(False)
+ self["key_yellow"] = Boolean(True)
+ self["key_blue"] = Boolean(False)
+
+ ConfigListScreen.__init__(self, [])
+ self.infobar = infobar or self.session.infobar
+
+ self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+ {
+ iPlayableService.evUpdatedInfo: self.__updatedInfo
+ })
+ self.cached_subtitle_checked = False
+ self.__selected_subtitle = None
+
+ self["actions"] = ActionMap(["ColorActions", "SetupActions", "DirectionActions"],
+ {
+ "red": self.keyRed,
+ "green": self.keyGreen,
+ "yellow": self.keyYellow,
+ "blue": self.keyBlue,
+ "ok": self.keyOk,
+ "cancel": self.cancel,
+ "up": self.keyUp,
+ "down": self.keyDown,
+ }, -3)
+
+ self.settings = ConfigSubsection()
+ choicelist = [(PAGE_AUDIO,_("audio tracks")), (PAGE_SUBTITLES,_("Subtitles"))]
+ self.settings.menupage = ConfigSelection(choices = choicelist, default=page)
+ self.onLayoutFinish.append(self.__layoutFinished)
+
+ def __layoutFinished(self):
+ self["config"].instance.setSelectionEnable(False)
+ self.focus = FOCUS_STREAMS
+ self.settings.menupage.addNotifier(self.fillList)
+
+ def fillList(self, arg=None):
+ streams = []
+ conflist = []
+ selectedidx = 0
+
+ service = self.session.nav.getCurrentService()
+ self.audioTracks = audio = service and service.audioTracks()
+ n = audio and audio.getNumberOfTracks() or 0
+
+ if self.settings.menupage.getValue() == PAGE_AUDIO:
+ self.setTitle(_("Select audio track"))
+ if SystemInfo["CanDownmixAC3"]:
+ self.settings.downmix = ConfigOnOff(default=config.av.downmix_ac3.value)
+ self.settings.downmix.addNotifier(self.changeAC3Downmix, initial_call = False)
+ conflist.append(getConfigListEntry(_("AC3 downmix"), self.settings.downmix))
+ self["key_red"].setBoolean(True)
+
+ if n > 0:
+ self.audioChannel = service.audioChannel()
+ choicelist = [("0",_("left")), ("1",_("stereo")), ("2", _("right"))]
+ self.settings.channelmode = ConfigSelection(choices = choicelist, default = str(self.audioChannel.getCurrentChannel()))
+ self.settings.channelmode.addNotifier(self.changeMode, initial_call = False)
+ conflist.append(getConfigListEntry(_("Channel"), self.settings.channelmode))
+ self["key_green"].setBoolean(True)
+ selectedAudio = self.audioTracks.getCurrentTrack()
+ for x in range(n):
+ number = str(x)
+ i = audio.getTrackInfo(x)
+ languages = i.getLanguage().split('/')
+ description = i.getDescription() or _("<unknown>")
+ selected = ""
+ language = ""
+
+ if selectedAudio == x:
+ selected = _("Running")
+ selectedidx = x
+
+ cnt = 0
+ for lang in languages:
+ if cnt:
+ language += ' / '
+ if LanguageCodes.has_key(lang):
+ language += LanguageCodes[lang][0]
+ elif lang == "und":
+ _("<unknown>")
+ else:
+ language += lang
+ cnt += 1
+
+ streams.append((x, "", number, description, language, selected))
+
+ else:
+ streams = []
+ conflist.append(('',))
+ self["key_green"].setBoolean(False)
+
+ elif self.settings.menupage.getValue() == PAGE_SUBTITLES:
+ self.setTitle(_("Subtitle selection"))
+ conflist.append(('',))
+ conflist.append(('',))
+ self["key_red"].setBoolean(False)
+ self["key_green"].setBoolean(False)
+
+ if self.subtitlesEnabled():
+ sel = self.infobar.selected_subtitle
+ else:
+ sel = None
+
+ idx = 0
+
+ subtitlelist = self.getSubtitleList()
+
+ if len(subtitlelist):
+ for x in subtitlelist:
+ number = str(x[1])
+ description = "?"
+ language = _("<unknown>")
+ selected = ""
+
+ if sel and x[:4] == sel[:4]:
+ selected = _("Running")
+ selectedidx = idx
+
+ if x[4] != "und":
+ if LanguageCodes.has_key(x[4]):
+ language = LanguageCodes[x[4]][0]
+ else:
+ language = x[4]
+
+ if x[0] == 0:
+ description = "DVB"
+ number = "%x" % (x[1])
+
+ elif x[0] == 1:
+ description = "TTX"
+ number = "%x%02x" % (x[3],x[2])
+
+ elif x[0] == 2:
+ types = ("UTF-8 text","SSA / AAS",".SRT file")
+ description = types[x[2]]
+
+ streams.append((x, "", number, description, language, selected))
+ idx += 1
+
+ else:
+ streams = []
+
+ conflist.append(getConfigListEntry(_("Menu"), self.settings.menupage))
+
+ from Components.PluginComponent import plugins
+ from Plugins.Plugin import PluginDescriptor
+
+ if hasattr(self.infobar, "runPlugin"):
+ class PluginCaller:
+ def __init__(self, fnc, *args):
+ self.fnc = fnc
+ self.args = args
+ def __call__(self, *args, **kwargs):
+ self.fnc(*self.args)
+
+ Plugins = [ (p.name, PluginCaller(self.infobar.runPlugin, p)) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_AUDIOMENU) ]
+
+ if len(Plugins):
+ self["key_blue"].setBoolean(True)
+ conflist.append(getConfigListEntry(Plugins[0][0], ConfigNothing()))
+ self.plugincallfunc = Plugins[0][1]
+ if len(Plugins) > 1:
+ print "these plugins are installed but not displayed in the dialog box:", Plugins[1:]
+
+ self["config"].list = conflist
+ self["config"].l.setList(conflist)
+
+ self["streams"].list = streams
+ self["streams"].setIndex(selectedidx)
+
+ def __updatedInfo(self):
+ self.fillList()
+
+ def getSubtitleList(self):
+ s = self.infobar and self.infobar.getCurrentServiceSubtitle()
+ l = s and s.getSubtitleList() or [ ]
+ return l
+
+ def subtitlesEnabled(self):
+ return self.infobar.subtitles_enabled
+
+ def enableSubtitle(self, subtitles):
+ if self.infobar.selected_subtitle != subtitles:
+ self.infobar.subtitles_enabled = False
+ self.infobar.selected_subtitle = subtitles
+ if subtitles:
+ self.infobar.subtitles_enabled = True
+
+ def changeAC3Downmix(self, downmix):
+ if downmix.getValue() == True:
+ config.av.downmix_ac3.value = True
+ else:
+ config.av.downmix_ac3.value = False
+ config.av.downmix_ac3.save()
+
+ def changeMode(self, mode):
+ if mode is not None:
+ self.audioChannel.selectChannel(int(mode.getValue()))
+
+ def changeAudio(self, audio):
+ track = int(audio)
+ if isinstance(track, int):
+ if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > track:
+ self.audioTracks.selectTrack(track)
+
+ def keyLeft(self):
+ if self.focus == FOCUS_CONFIG:
+ ConfigListScreen.keyLeft(self)
+ elif self.focus == FOCUS_STREAMS:
+ self["streams"].setIndex(0)
+
+ def keyRight(self, config = False):
+ if config or self.focus == FOCUS_CONFIG:
+ if self["config"].getCurrentIndex() < 3:
+ ConfigListScreen.keyRight(self)
+ elif hasattr(self, "plugincallfunc"):
+ self.plugincallfunc()
+ if self.focus == FOCUS_STREAMS and self["streams"].count() and config == False:
+ self["streams"].setIndex(self["streams"].count()-1)
+
+ def keyRed(self):
+ if self["key_red"].getBoolean():
+ self.colorkey(0)
+
+ def keyGreen(self):
+ if self["key_green"].getBoolean():
+ self.colorkey(1)
+
+ def keyYellow(self):
+ if self["key_yellow"].getBoolean():
+ self.colorkey(2)
+
+ def keyBlue(self):
+ if self["key_blue"].getBoolean():
+ self.colorkey(3)
+
+ def colorkey(self, idx):
+ self["config"].setCurrentIndex(idx)
+ self.keyRight(True)
+
+ def keyUp(self):
+ if self.focus == FOCUS_CONFIG:
+ self["config"].instance.moveSelection(self["config"].instance.moveUp)
+ elif self.focus == FOCUS_STREAMS:
+ if self["streams"].getIndex() == 0:
+ self["config"].instance.setSelectionEnable(True)
+ self["streams"].style = "notselected"
+ self["config"].setCurrentIndex(len(self["config"].getList())-1)
+ self.focus = FOCUS_CONFIG
+ else:
+ self["streams"].selectPrevious()
+
+ def keyDown(self):
+ if self.focus == FOCUS_CONFIG:
+ if self["config"].getCurrentIndex() < len(self["config"].getList())-1:
+ self["config"].instance.moveSelection(self["config"].instance.moveDown)
+ else:
+ self["config"].instance.setSelectionEnable(False)
+ self["streams"].style = "default"
+ self.focus = FOCUS_STREAMS
+ elif self.focus == FOCUS_STREAMS:
+ self["streams"].selectNext()
+
+ def keyOk(self):
+ if self.focus == FOCUS_STREAMS and self["streams"].list:
+ cur = self["streams"].getCurrent()
+ if self.settings.menupage.getValue() == PAGE_AUDIO and cur[0] is not None:
+ self.changeAudio(cur[2])
+ self.__updatedInfo()
+ if self.settings.menupage.getValue() == PAGE_SUBTITLES and cur[0] is not None:
+ if self.infobar.selected_subtitle == cur[0]:
+ self.enableSubtitle(None)
+ selectedidx = self["streams"].getIndex()
+ self.__updatedInfo()
+ self["streams"].setIndex(selectedidx)
+ else:
+ self.enableSubtitle(cur[0])
+ self.__updatedInfo()
+ self.close(0)
+ elif self.focus == FOCUS_CONFIG:
+ self.keyRight()
+
+ def cancel(self):
+ self.close(0)
+
+class SubtitleSelection(AudioSelection):
+ def __init__(self, session, infobar=None):
+ AudioSelection.__init__(self, session, infobar, page=PAGE_SUBTITLES)
+ self.skinName = ["AudioSelection"]
diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py
index 0895c9c2..34316f01 100644
--- a/lib/python/Screens/ChannelSelection.py
+++ b/lib/python/Screens/ChannelSelection.py
@@ -20,7 +20,6 @@ from Components.Sources.ServiceEvent import ServiceEvent
profile("ChannelSelection.py 2.3")
from Components.Input import Input
profile("ChannelSelection.py 3")
-from Components.ParentalControl import parentalControl
from Components.ChoiceList import ChoiceList, ChoiceEntryComponent
from Components.SystemInfo import SystemInfo
from Screens.InputBox import InputBox, PinInput
@@ -77,6 +76,7 @@ def append_when_current_valid(current, menu, args, level = 0, key = ""):
class ChannelContextMenu(Screen):
def __init__(self, session, csel):
+
Screen.__init__(self, session)
#raise Exception("we need a better summary screen here")
self.csel = csel
@@ -106,14 +106,22 @@ class ChannelContextMenu(Screen):
isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
if isPlayable:
if config.ParentalControl.configured.value:
+ from Components.ParentalControl import parentalControl
if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
append_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())), level = 0)
else:
append_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())), level = 0)
if haveBouquets:
- append_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected), level = 0)
+ bouquets = self.csel.getBouquetList()
+ if bouquets is None:
+ bouquetCnt = 0
+ else:
+ bouquetCnt = len(bouquets)
+ if not inBouquet or bouquetCnt > 1:
+ append_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected), level = 0)
else:
- append_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected), level = 0)
+ if not inBouquet:
+ append_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected), level = 0)
else:
if current_root.getPath().find('FROM SATELLITES') != -1:
append_when_current_valid(current, menu, (_("remove selected satellite"), self.removeSatelliteServices), level = 0)
@@ -184,6 +192,7 @@ class ChannelContextMenu(Screen):
self.close()
def addParentalProtection(self, service):
+ from Components.ParentalControl import parentalControl
parentalControl.protectService(service.toCompareString())
self.close()
@@ -192,6 +201,7 @@ class ChannelContextMenu(Screen):
def pinEntered(self, service, result):
if result:
+ from Components.ParentalControl import parentalControl
parentalControl.unProtectService(service)
self.close()
else:
@@ -223,7 +233,7 @@ class ChannelContextMenu(Screen):
if cnt > 1: # show bouquet list
self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
elif cnt == 1: # add to only one existing bouquet
- self.addCurrentServiceToBouquet(bouquets[0][1])
+ self.addCurrentServiceToBouquet(bouquets[0][1], closeBouquetSelection = False)
def bouquetSelClosed(self, recursive):
self.bsel = None
@@ -257,12 +267,12 @@ class ChannelContextMenu(Screen):
self.csel.addMarker(marker)
self.close()
- def addCurrentServiceToBouquet(self, dest):
+ def addCurrentServiceToBouquet(self, dest, closeBouquetSelection = True):
self.csel.addServiceToBouquet(dest)
if self.bsel is not None:
self.bsel.close(True)
else:
- self.close(True) # close bouquet selection
+ self.close(closeBouquetSelection) # close bouquet selection
def removeCurrentService(self):
self.csel.removeCurrentService()
@@ -1400,9 +1410,9 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
{
- "keyTV": self.closeRadio,
- "keyRadio": self.closeRadio,
- "cancel": self.closeRadio,
+ "keyTV": self.cancel,
+ "keyRadio": self.cancel,
+ "cancel": self.cancel,
"ok": self.channelSelected,
})
@@ -1440,7 +1450,7 @@ class ChannelSelectionRadio(ChannelSelectionBase, ChannelSelectionEdit, ChannelS
self["RdsActions"].setEnabled(state)
########## RDS Radiotext / Rass Support END
- def closeRadio(self):
+ def cancel(self):
self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
self.info.hide()
#set previous tv service
diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py
index f98d4c33..6fa89112 100644
--- a/lib/python/Screens/InfoBarGenerics.py
+++ b/lib/python/Screens/InfoBarGenerics.py
@@ -598,6 +598,7 @@ class InfoBarEPG:
if list:
list.append((_("show single service EPG..."), self.openSingleServiceEPG))
+ list.append((_("Multi EPG"), self.openMultiServiceEPG))
self.session.openWithCallback(self.EventInfoPluginChosen, ChoiceBox, title=_("Please choose an extension..."), list = list, skin_name = "EPGExtensionsList")
else:
self.openSingleServiceEPG()
@@ -1672,126 +1673,11 @@ class InfoBarAudioSelection:
})
def audioSelection(self):
- service = self.session.nav.getCurrentService()
- self.audioTracks = audio = service and service.audioTracks()
- n = audio and audio.getNumberOfTracks() or 0
- tlist = []
- if n > 0:
- self.audioChannel = service.audioChannel()
-
- idx = 0
- while idx < n:
- cnt = 0
- i = audio.getTrackInfo(idx)
- languages = i.getLanguage().split('/')
- description = i.getDescription()
- language = ""
-
- for lang in languages:
- if cnt:
- language += ' / '
- if LanguageCodes.has_key(lang):
- language += LanguageCodes[lang][0]
- else:
- language += lang
- cnt += 1
-
- if len(description):
- description += " (" + language + ")"
- else:
- description = language
-
- tlist.append((description, idx))
- idx += 1
-
- tlist.sort(key=lambda x: x[0])
-
- selectedAudio = self.audioTracks.getCurrentTrack()
-
- selection = 0
-
- for x in tlist:
- if x[1] != selectedAudio:
- selection += 1
- else:
- break
-
- availableKeys = []
- usedKeys = []
-
- if SystemInfo["CanDownmixAC3"]:
- flist = [(_("AC3 downmix") + " - " +(_("Off"), _("On"))[config.av.downmix_ac3.value and 1 or 0], "CALLFUNC", self.changeAC3Downmix),
- ((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode")]
- usedKeys.extend(["red", "green"])
- availableKeys.extend(["yellow", "blue"])
- selection += 2
- else:
- flist = [((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode")]
- usedKeys.extend(["red"])
- availableKeys.extend(["green", "yellow", "blue"])
- selection += 1
-
- if hasattr(self, "runPlugin"):
- class PluginCaller:
- def __init__(self, fnc, *args):
- self.fnc = fnc
- self.args = args
- def __call__(self, *args, **kwargs):
- self.fnc(*self.args)
-
- Plugins = [ (p.name, PluginCaller(self.runPlugin, p)) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_AUDIOMENU) ]
-
- for p in Plugins:
- selection += 1
- flist.append((p[0], "CALLFUNC", p[1]))
- if availableKeys:
- usedKeys.append(availableKeys[0])
- del availableKeys[0]
- else:
- usedKeys.append("")
-
- flist.append(("--", ""))
- usedKeys.append("")
- selection += 1
-
- keys = usedKeys + [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" ] + [""] * n
- self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = flist + tlist, selection = selection, keys = keys, skin_name = "AudioTrackSelection")
- else:
- del self.audioTracks
-
- def changeAC3Downmix(self, arg):
- choicelist = self.session.current_dialog["list"]
- list = choicelist.list
- t = list[0][1]
- list[0][1]=(t[0], t[1], t[2], t[3], t[4], t[5], t[6],
- _("AC3 downmix") + " - " + (_("On"), _("Off"))[config.av.downmix_ac3.value and 1 or 0])
- choicelist.setList(list)
- if config.av.downmix_ac3.value:
- config.av.downmix_ac3.value = False
- else:
- config.av.downmix_ac3.value = True
- config.av.downmix_ac3.save()
-
- def audioSelected(self, audio):
- if audio is not None:
- if isinstance(audio[1], str):
- if audio[1] == "mode":
- keys = ["red", "green", "yellow"]
- selection = self.audioChannel.getCurrentChannel()
- tlist = ((_("left"), 0), (_("stereo"), 1), (_("right"), 2))
- self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys, skin_name ="AudioModeSelection")
- else:
- del self.audioChannel
- if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
- self.audioTracks.selectTrack(audio[1])
- else:
- del self.audioChannel
- del self.audioTracks
-
- def modeSelected(self, mode):
- if mode is not None:
- self.audioChannel.selectChannel(mode[1])
- del self.audioChannel
+ from Screens.AudioSelection import AudioSelection
+ self.session.openWithCallback(self.audioSelected, AudioSelection, infobar=self)
+
+ def audioSelected(self, ret=None):
+ print "[infobar::audioSelected]", ret
class InfoBarSubserviceSelection:
def __init__(self):
diff --git a/lib/python/Screens/InputDeviceSetup.py b/lib/python/Screens/InputDeviceSetup.py
new file mode 100755
index 00000000..bd8550b8
--- /dev/null
+++ b/lib/python/Screens/InputDeviceSetup.py
@@ -0,0 +1,280 @@
+from Screen import Screen
+from Screens.HelpMenu import HelpableScreen
+from Screens.MessageBox import MessageBox
+from Components.InputDevice import iInputDevices
+from Components.Sources.StaticText import StaticText
+from Components.Sources.Boolean import Boolean
+from Components.Sources.List import List
+from Components.config import config, ConfigSlider, ConfigSubsection, ConfigYesNo, ConfigText, getConfigListEntry, ConfigNothing
+from Components.ConfigList import ConfigListScreen
+from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
+from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN
+from Tools.LoadPixmap import LoadPixmap
+
+class InputDeviceSelection(Screen,HelpableScreen):
+ skin = """
+ <screen name="InputDeviceSelection" position="center,center" size="560,400" title="Select input device">
+ <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on"/>
+ <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on"/>
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on"/>
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on"/>
+ <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1"/>
+ <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1"/>
+ <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1"/>
+ <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1"/>
+ <widget source="list" render="Listbox" position="5,50" size="550,280" zPosition="10" scrollbarMode="showOnDemand">
+ <convert type="TemplatedMultiContent">
+ <!-- device, description, devicepng, divpng -->
+ {"template": [
+ MultiContentEntryPixmapAlphaTest(pos = (2, 8), size = (54, 54), png = 2), # index 3 is the interface pixmap
+ MultiContentEntryText(pos = (65, 6), size = (450, 54), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER|RT_WRAP, text = 1), # index 1 is the interfacename
+ ],
+ "fonts": [gFont("Regular", 28),gFont("Regular", 20)],
+ "itemHeight": 70
+ }
+
+ </convert>
+ </widget>
+ <ePixmap pixmap="skin_default/div-h.png" position="0,340" zPosition="1" size="560,2"/>
+ <widget source="introduction" render="Label" position="0,350" size="560,50" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1"/>
+ </screen>"""
+
+
+ def __init__(self, session):
+ Screen.__init__(self, session)
+ HelpableScreen.__init__(self)
+
+ self.edittext = _("Press OK to edit the settings.")
+
+ self["key_red"] = StaticText(_("Close"))
+ self["key_green"] = StaticText(_("Select"))
+ self["key_yellow"] = StaticText("")
+ self["key_blue"] = StaticText("")
+ self["introduction"] = StaticText(self.edittext)
+
+ self.devices = [(iInputDevices.getDeviceName(x),x) for x in iInputDevices.getDeviceList()]
+ print "[InputDeviceSelection] found devices :->", len(self.devices),self.devices
+
+ self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
+ {
+ "cancel": (self.close, _("Exit input device selection.")),
+ "ok": (self.okbuttonClick, _("Select input device.")),
+ }, -2)
+
+ self["ColorActions"] = HelpableActionMap(self, "ColorActions",
+ {
+ "red": (self.close, _("Exit input device selection.")),
+ "green": (self.okbuttonClick, _("Select input device.")),
+ }, -2)
+
+ self.currentIndex = 0
+ self.list = []
+ self["list"] = List(self.list)
+ self.updateList()
+ self.onLayoutFinish.append(self.layoutFinished)
+ self.onClose.append(self.cleanup)
+
+ def layoutFinished(self):
+ self.setTitle(_("Select input device"))
+
+ def cleanup(self):
+ self.currentIndex = 0
+
+ def buildInterfaceList(self,device,description,type ):
+ divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
+ activepng = None
+ devicepng = None
+ enabled = iInputDevices.getDeviceAttribute(device, 'enabled')
+
+ if type == 'remote':
+ if config.misc.rcused.value == 0:
+ if enabled:
+ devicepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/input_rcnew-configured.png"))
+ else:
+ devicepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/input_rcnew.png"))
+ else:
+ if enabled:
+ devicepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/input_rcold-configured.png"))
+ else:
+ devicepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/input_rcold.png"))
+ elif type == 'keyboard':
+ if enabled:
+ devicepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/input_keyboard-configured.png"))
+ else:
+ devicepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/input_keyboard.png"))
+ elif type == 'mouse':
+ if enabled:
+ devicepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/input_mouse-configured.png"))
+ else:
+ devicepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/input_mouse.png"))
+ else:
+ devicepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/input_rcnew.png"))
+ return((device, description, devicepng, divpng))
+
+ def updateList(self):
+ self.list = []
+ for x in self.devices:
+ dev_type = iInputDevices.getDeviceAttribute(x[1], 'type')
+ self.list.append(self.buildInterfaceList(x[1],_(x[0]), dev_type ))
+ self["list"].setList(self.list)
+ self["list"].setIndex(self.currentIndex)
+
+ def okbuttonClick(self):
+ selection = self["list"].getCurrent()
+ self.currentIndex = self["list"].getIndex()
+ if selection is not None:
+ self.session.openWithCallback(self.DeviceSetupClosed, InputDeviceSetup, selection[0])
+
+ def DeviceSetupClosed(self, *ret):
+ self.updateList()
+
+
+class InputDeviceSetup(Screen, ConfigListScreen):
+
+ skin = """
+ <screen name="InputDeviceSetup" position="center,center" size="560,440" title="Input device setup">
+ <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
+ <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
+ <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
+ <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
+ <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
+ <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
+ <widget name="config" position="5,50" size="550,350" scrollbarMode="showOnDemand" />
+ <ePixmap pixmap="skin_default/div-h.png" position="0,400" zPosition="1" size="560,2" />
+ <widget source="introduction" render="Label" position="5,410" size="550,30" zPosition="10" font="Regular;21" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
+ </screen>"""
+
+ def __init__(self, session, device):
+ Screen.__init__(self, session)
+ self.inputDevice = device
+ iInputDevices.currentDevice = self.inputDevice
+ self.onChangedEntry = [ ]
+ self.setup_title = _("Input device setup")
+ self.isStepSlider = None
+ self.enableEntry = None
+ self.repeatEntry = None
+ self.delayEntry = None
+ self.nameEntry = None
+ self.enableConfigEntry = None
+
+ self.list = [ ]
+ ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changedEntry)
+
+ self["actions"] = ActionMap(["SetupActions"],
+ {
+ "cancel": self.keyCancel,
+ "save": self.apply,
+ }, -2)
+
+ self["key_red"] = StaticText(_("Cancel"))
+ self["key_green"] = StaticText(_("OK"))
+ self["key_yellow"] = StaticText()
+ self["key_blue"] = StaticText()
+ self["introduction"] = StaticText()
+
+ self.createSetup()
+ self.onLayoutFinish.append(self.layoutFinished)
+ self.onClose.append(self.cleanup)
+
+ def layoutFinished(self):
+ self.setTitle(self.setup_title)
+
+ def cleanup(self):
+ iInputDevices.currentDevice = ""
+
+ def createSetup(self):
+ self.list = [ ]
+ cmd = "self.enableEntry = getConfigListEntry(_('"'Change repeat and delay settings?'"'), config.inputDevices." + self.inputDevice + ".enabled)"
+ exec (cmd)
+ cmd = "self.repeatEntry = getConfigListEntry(_('"'Interval between keys when repeating:'"'), config.inputDevices." + self.inputDevice + ".repeat)"
+ exec (cmd)
+ cmd = "self.delayEntry = getConfigListEntry(_('"'Delay before key repeat starts:'"'), config.inputDevices." + self.inputDevice + ".delay)"
+ exec (cmd)
+ cmd = "self.nameEntry = getConfigListEntry(_('"'Devicename:'"'), config.inputDevices." + self.inputDevice + ".name)"
+ exec (cmd)
+ if self.enableEntry:
+ if isinstance(self.enableEntry[1], ConfigYesNo):
+ self.enableConfigEntry = self.enableEntry[1]
+
+ self.list.append(self.enableEntry)
+ if self.enableConfigEntry:
+ if self.enableConfigEntry.value is True:
+ self.list.append(self.repeatEntry)
+ self.list.append(self.delayEntry)
+ else:
+ self.repeatEntry[1].setValue(self.repeatEntry[1].default)
+ self["config"].invalidate(self.repeatEntry)
+ self.delayEntry[1].setValue(self.delayEntry[1].default)
+ self["config"].invalidate(self.delayEntry)
+ self.nameEntry[1].setValue(self.nameEntry[1].default)
+ self["config"].invalidate(self.nameEntry)
+
+ self["config"].list = self.list
+ self["config"].l.setSeperation(400)
+ self["config"].l.setList(self.list)
+ if not self.selectionChanged in self["config"].onSelectionChanged:
+ self["config"].onSelectionChanged.append(self.selectionChanged)
+ self.selectionChanged()
+
+ def selectionChanged(self):
+ if self["config"].getCurrent() == self.enableEntry:
+ self["introduction"].setText(_("Current device: ") + str(iInputDevices.getDeviceAttribute(self.inputDevice, 'name')) )
+ else:
+ self["introduction"].setText(_("Current value: ") + self.getCurrentValue() + _(" ms"))
+
+ def newConfig(self):
+ current = self["config"].getCurrent()
+ if current:
+ if current == self.enableEntry:
+ self.createSetup()
+
+ def keyLeft(self):
+ ConfigListScreen.keyLeft(self)
+ self.newConfig()
+
+ def keyRight(self):
+ ConfigListScreen.keyRight(self)
+ self.newConfig()
+
+ def confirm(self, confirmed):
+ if not confirmed:
+ print "not confirmed"
+ return
+ else:
+ self.nameEntry[1].setValue(iInputDevices.getDeviceAttribute(self.inputDevice, 'name'))
+ cmd = "config.inputDevices." + self.inputDevice + ".name.save()"
+ exec (cmd)
+ self.keySave()
+
+ def apply(self):
+ self.session.openWithCallback(self.confirm, MessageBox, _("Use this input device settings?"), MessageBox.TYPE_YESNO, timeout = 20, default = True)
+
+ def cancelConfirm(self, result):
+ if not result:
+ return
+ for x in self["config"].list:
+ x[1].cancel()
+ self.close()
+
+ def keyCancel(self):
+ if self["config"].isChanged():
+ self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"), MessageBox.TYPE_YESNO, timeout = 20, default = True)
+ else:
+ self.close()
+ # for summary:
+ def changedEntry(self):
+ for x in self.onChangedEntry:
+ x()
+ self.selectionChanged()
+
+ def getCurrentEntry(self):
+ return self["config"].getCurrent()[0]
+
+ def getCurrentValue(self):
+ return str(self["config"].getCurrent()[1].value)
+
+ def createSummary(self):
+ from Screens.Setup import SetupSummary
+ return SetupSummary
diff --git a/lib/python/Screens/Ipkg.py b/lib/python/Screens/Ipkg.py
index 96876336..7f98f3df 100755
--- a/lib/python/Screens/Ipkg.py
+++ b/lib/python/Screens/Ipkg.py
@@ -25,6 +25,7 @@ class Ipkg(Screen):
self.packages = 0
self.error = 0
+ self.processed_packages = []
self.activity = 0
self.activityTimer = eTimer()
@@ -85,15 +86,21 @@ class Ipkg(Screen):
self.slider.setValue(self.sliderPackages[param])
self.package.setText(param)
self.status.setText(_("Upgrading"))
- self.packages += 1
+ if not param in self.processed_packages:
+ self.processed_packages.append(param)
+ self.packages += 1
elif event == IpkgComponent.EVENT_INSTALL:
self.package.setText(param)
self.status.setText(_("Installing"))
- self.packages += 1
+ if not param in self.processed_packages:
+ self.processed_packages.append(param)
+ self.packages += 1
elif event == IpkgComponent.EVENT_REMOVE:
self.package.setText(param)
self.status.setText(_("Removing"))
- self.packages += 1
+ if not param in self.processed_packages:
+ self.processed_packages.append(param)
+ self.packages += 1
elif event == IpkgComponent.EVENT_CONFIGURING:
self.package.setText(param)
self.status.setText(_("Configuring"))
@@ -103,10 +110,10 @@ class Ipkg(Screen):
self.runNextCmd()
elif event == IpkgComponent.EVENT_MODIFIED:
self.session.openWithCallback(
- self.modificationCallback,
- MessageBox,
- _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
- )
+ self.modificationCallback,
+ MessageBox,
+ _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
+ )
def modificationCallback(self, res):
self.ipkg.write(res and "N" or "Y")
diff --git a/lib/python/Screens/Makefile.am b/lib/python/Screens/Makefile.am
index d96b491e..69600f01 100755
--- a/lib/python/Screens/Makefile.am
+++ b/lib/python/Screens/Makefile.am
@@ -1,18 +1,19 @@
installdir = $(pkglibdir)/python/Screens
install_PYTHON = \
- ChannelSelection.py ClockDisplay.py ConfigMenu.py InfoBar.py Menu.py \
- MessageBox.py Screen.py ServiceScan.py TimerEdit.py \
+ AudioSelection.py ChannelSelection.py ClockDisplay.py ConfigMenu.py InfoBar.py \
+ Menu.py MessageBox.py Screen.py ServiceScan.py TimerEdit.py \
MovieSelection.py Setup.py About.py HarddiskSetup.py FixedMenu.py \
Satconfig.py ScanSetup.py NetworkSetup.py Ci.py TimerEntry.py Volume.py \
EpgSelection.py EventView.py Mute.py Standby.py ServiceInfo.py \
InfoBarGenerics.py HelpMenu.py Wizard.py __init__.py \
- Dish.py LanguageSelection.py StartWizard.py PiPSetup.py Subtitles.py \
+ Dish.py LanguageSelection.py StartWizard.py PiPSetup.py \
TutorialWizard.py PluginBrowser.py MinuteInput.py Scart.py PVRState.py \
Console.py InputBox.py ChoiceBox.py SimpleSummary.py \
TimerSelection.py PictureInPicture.py TimeDateInput.py \
SubtitleDisplay.py SubservicesQuickzap.py ParentalControlSetup.py NumericalTextInputHelpDialog.py \
SleepTimerEdit.py Ipkg.py RdsDisplay.py Globals.py DefaultWizard.py \
SessionGlobals.py LocationBox.py WizardLanguage.py TaskView.py Rc.py VirtualKeyBoard.py \
- TextBox.py FactoryReset.py RecordPaths.py UnhandledKey.py ServiceStopScreen.py
+ TextBox.py FactoryReset.py RecordPaths.py UnhandledKey.py ServiceStopScreen.py \
+ InputDeviceSetup.py
diff --git a/lib/python/Screens/NetworkSetup.py b/lib/python/Screens/NetworkSetup.py
index c0037f81..de2fa993 100755
--- a/lib/python/Screens/NetworkSetup.py
+++ b/lib/python/Screens/NetworkSetup.py
@@ -7,6 +7,7 @@ from Screens.HelpMenu import HelpableScreen
from Components.Network import iNetwork
from Components.Sources.StaticText import StaticText
from Components.Sources.Boolean import Boolean
+from Components.Sources.List import List
from Components.Label import Label,MultiColorLabel
from Components.Pixmap import Pixmap,MultiPixmap
from Components.MenuList import MenuList
@@ -23,32 +24,6 @@ from os import path as os_path, system as os_system, unlink
from re import compile as re_compile, search as re_search
-class InterfaceList(MenuList):
- def __init__(self, list, enableWrapAround=False):
- MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
- self.l.setFont(0, gFont("Regular", 20))
- self.l.setItemHeight(30)
-
-def InterfaceEntryComponent(index,name,default,active ):
- res = [
- (index),
- MultiContentEntryText(pos=(80, 5), size=(430, 25), font=0, text=name)
- ]
- num_configured_if = len(iNetwork.getConfiguredAdapters())
- if num_configured_if >= 2:
- if default is True:
- png = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/button_blue.png"))
- if default is False:
- png = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/button_blue_off.png"))
- res.append(MultiContentEntryPixmapAlphaTest(pos=(10, 5), size=(25, 25), png = png))
- if active is True:
- png2 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/lock_on.png"))
- if active is False:
- png2 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/lock_error.png"))
- res.append(MultiContentEntryPixmapAlphaTest(pos=(40, 1), size=(25, 25), png = png2))
- return res
-
-
class NetworkAdapterSelection(Screen,HelpableScreen):
def __init__(self, session):
Screen.__init__(self, session)
@@ -91,13 +66,49 @@ class NetworkAdapterSelection(Screen,HelpableScreen):
})
self.list = []
- self["list"] = InterfaceList(self.list)
+ self["list"] = List(self.list)
self.updateList()
if len(self.adapters) == 1:
self.onFirstExecBegin.append(self.okbuttonClick)
self.onClose.append(self.cleanup)
+ def buildInterfaceList(self,iface,name,default,active ):
+ divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
+ defaultpng = None
+ activepng = None
+ description = None
+ interfacepng = None
+
+ if iface in iNetwork.lan_interfaces:
+ if active is True:
+ interfacepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/network_wired-active.png"))
+ elif active is False:
+ interfacepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/network_wired-inactive.png"))
+ else:
+ interfacepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/network_wired.png"))
+ elif iface in iNetwork.wlan_interfaces:
+ if active is True:
+ interfacepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/network_wireless-active.png"))
+ elif active is False:
+ interfacepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/network_wireless-inactive.png"))
+ else:
+ interfacepng = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/network_wireless.png"))
+
+ num_configured_if = len(iNetwork.getConfiguredAdapters())
+ if num_configured_if >= 2:
+ if default is True:
+ defaultpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/button_blue.png"))
+ elif default is False:
+ defaultpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/button_blue_off.png"))
+ if active is True:
+ activepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/lock_on.png"))
+ elif active is False:
+ activepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/lock_error.png"))
+
+ description = iNetwork.getFriendlyAdapterDescription(iface)
+
+ return((iface, name, description, interfacepng, defaultpng, activepng, divpng))
def updateList(self):
self.list = []
@@ -122,7 +133,7 @@ class NetworkAdapterSelection(Screen,HelpableScreen):
default_gw = result
if len(self.adapters) == 0: # no interface available => display only eth0
- self.list.append(InterfaceEntryComponent("eth0",iNetwork.getFriendlyAdapterName('eth0'),True,True ))
+ self.list.append(self.buildInterfaceList("eth0",iNetwork.getFriendlyAdapterName('eth0'),True,True ))
else:
for x in self.adapters:
if x[1] == default_gw:
@@ -133,11 +144,11 @@ class NetworkAdapterSelection(Screen,HelpableScreen):
active_int = True
else:
active_int = False
- self.list.append(InterfaceEntryComponent(index = x[1],name = _(x[0]),default=default_int,active=active_int ))
+ self.list.append(self.buildInterfaceList(x[1],_(x[0]),default_int,active_int ))
if os_path.exists(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/NetworkWizard/networkwizard.xml")):
self["key_blue"].setText(_("NetworkWizard"))
- self["list"].l.setList(self.list)
+ self["list"].setList(self.list)
def setDefaultInterface(self):
selection = self["list"].getCurrent()
@@ -253,7 +264,7 @@ class NameserverSetup(Screen, ConfigListScreen, HelpableScreen):
self.list = []
ConfigListScreen.__init__(self, self.list)
self.createSetup()
-
+
def createConfig(self):
self.nameservers = iNetwork.getNameserverList()
self.nameserverEntries = [ NoSave(ConfigIP(default=nameserver)) for nameserver in self.nameservers]
@@ -412,7 +423,7 @@ class AdapterSetup(Screen, ConfigListScreen, HelpableScreen):
self.wsconfig = None
self.default = None
- if self.iface == "wlan0" or self.iface == "ath0" :
+ if self.iface in iNetwork.wlan_interfaces:
from Plugins.SystemPlugins.WirelessLan.Wlan import wpaSupplicant,Wlan
self.w = Wlan(self.iface)
self.ws = wpaSupplicant()
@@ -535,7 +546,7 @@ class AdapterSetup(Screen, ConfigListScreen, HelpableScreen):
self.createSetup()
if self["config"].getCurrent() == self.gatewayEntry:
self.createSetup()
- if self.iface == "wlan0" or self.iface == "ath0" :
+ if self.iface in iNetwork.wlan_interfaces:
if self["config"].getCurrent() == self.wlanSSID:
self.createSetup()
if self["config"].getCurrent() == self.encryptionEnabled:
@@ -731,17 +742,24 @@ class AdapterSetupConfiguration(Screen, HelpableScreen):
def ok(self):
self.cleanup()
if self["menulist"].getCurrent()[1] == 'edit':
- if self.iface == 'wlan0' or self.iface == 'ath0':
+ if self.iface in iNetwork.wlan_interfaces:
try:
from Plugins.SystemPlugins.WirelessLan.plugin import WlanScan
- from Plugins.SystemPlugins.WirelessLan.iwlibs import Wireless
+ from pythonwifi.iwlibs import Wireless
except ImportError:
self.session.open(MessageBox, _("The wireless LAN plugin is not installed!\nPlease install it."), type = MessageBox.TYPE_INFO,timeout = 10 )
else:
ifobj = Wireless(self.iface) # a Wireless NIC Object
- self.wlanresponse = ifobj.getStatistics()
- if self.wlanresponse[0] != 19: # Wlan Interface found.
- self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetup,self.iface)
+ try:
+ self.wlanresponse = ifobj.getAPaddr()
+ except IOError:
+ self.wlanresponse = ifobj.getStatistics()
+ if self.wlanresponse:
+ if self.wlanresponse[0] not in (19,95): # 19 = 'No such device', 95 = 'Operation not supported'
+ self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetup,self.iface)
+ else:
+ # Display Wlan not available Message
+ self.showErrorMessage()
else:
# Display Wlan not available Message
self.showErrorMessage()
@@ -754,28 +772,42 @@ class AdapterSetupConfiguration(Screen, HelpableScreen):
if self["menulist"].getCurrent()[1] == 'scanwlan':
try:
from Plugins.SystemPlugins.WirelessLan.plugin import WlanScan
- from Plugins.SystemPlugins.WirelessLan.iwlibs import Wireless
+ from pythonwifi.iwlibs import Wireless
except ImportError:
self.session.open(MessageBox, _("The wireless LAN plugin is not installed!\nPlease install it."), type = MessageBox.TYPE_INFO,timeout = 10 )
else:
ifobj = Wireless(self.iface) # a Wireless NIC Object
- self.wlanresponse = ifobj.getStatistics()
- if self.wlanresponse[0] != 19:
- self.session.openWithCallback(self.WlanScanClosed, WlanScan, self.iface)
+ try:
+ self.wlanresponse = ifobj.getAPaddr()
+ except IOError:
+ self.wlanresponse = ifobj.getStatistics()
+ if self.wlanresponse:
+ if self.wlanresponse[0] not in (19,95): # 19 = 'No such device', 95 = 'Operation not supported'
+ self.session.openWithCallback(self.WlanScanClosed, WlanScan, self.iface)
+ else:
+ # Display Wlan not available Message
+ self.showErrorMessage()
else:
# Display Wlan not available Message
self.showErrorMessage()
if self["menulist"].getCurrent()[1] == 'wlanstatus':
try:
from Plugins.SystemPlugins.WirelessLan.plugin import WlanStatus
- from Plugins.SystemPlugins.WirelessLan.iwlibs import Wireless
+ from pythonwifi.iwlibs import Wireless
except ImportError:
self.session.open(MessageBox, _("The wireless LAN plugin is not installed!\nPlease install it."), type = MessageBox.TYPE_INFO,timeout = 10 )
else:
ifobj = Wireless(self.iface) # a Wireless NIC Object
- self.wlanresponse = ifobj.getStatistics()
- if self.wlanresponse[0] != 19:
- self.session.openWithCallback(self.WlanStatusClosed, WlanStatus,self.iface)
+ try:
+ self.wlanresponse = ifobj.getAPaddr()
+ except IOError:
+ self.wlanresponse = ifobj.getStatistics()
+ if self.wlanresponse:
+ if self.wlanresponse[0] not in (19,95): # 19 = 'No such device', 95 = 'Operation not supported'
+ self.session.openWithCallback(self.WlanStatusClosed, WlanStatus,self.iface)
+ else:
+ # Display Wlan not available Message
+ self.showErrorMessage()
else:
# Display Wlan not available Message
self.showErrorMessage()
@@ -817,7 +849,7 @@ class AdapterSetupConfiguration(Screen, HelpableScreen):
if self["menulist"].getCurrent()[1] == 'dns':
self["description"].setText(_("Edit the Nameserver configuration of your Dreambox.\n" ) + self.oktext )
if self["menulist"].getCurrent()[1] == 'scanwlan':
- self["description"].setText(_("Scan your network for wireless Access Points and connect to them using your selected wireless device.\n" ) + self.oktext )
+ self["description"].setText(_("Scan your network for wireless access points and connect to them using your selected wireless device.\n" ) + self.oktext )
if self["menulist"].getCurrent()[1] == 'wlanstatus':
self["description"].setText(_("Shows the state of your wireless LAN connection.\n" ) + self.oktext )
if self["menulist"].getCurrent()[1] == 'lanrestart':
@@ -834,7 +866,7 @@ class AdapterSetupConfiguration(Screen, HelpableScreen):
self["IF"].setText(iNetwork.getFriendlyAdapterName(self.iface))
self["Statustext"].setText(_("Link:"))
- if self.iface == 'wlan0' or self.iface == 'ath0':
+ if self.iface in iNetwork.wlan_interfaces:
try:
from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus
except:
@@ -884,17 +916,24 @@ class AdapterSetupConfiguration(Screen, HelpableScreen):
def AdapterSetupClosed(self, *ret):
if ret is not None and len(ret):
- if ret[0] == 'ok' and (self.iface == 'wlan0' or self.iface == 'ath0') and iNetwork.getAdapterAttribute(self.iface, "up") is True:
+ if ret[0] == 'ok' and (self.iface in iNetwork.wlan_interfaces) and iNetwork.getAdapterAttribute(self.iface, "up") is True:
try:
from Plugins.SystemPlugins.WirelessLan.plugin import WlanStatus
- from Plugins.SystemPlugins.WirelessLan.iwlibs import Wireless
+ from pythonwifi.iwlibs import Wireless
except ImportError:
self.session.open(MessageBox, _("The wireless LAN plugin is not installed!\nPlease install it."), type = MessageBox.TYPE_INFO,timeout = 10 )
else:
ifobj = Wireless(self.iface) # a Wireless NIC Object
- self.wlanresponse = ifobj.getStatistics()
- if self.wlanresponse[0] != 19:
- self.session.openWithCallback(self.WlanStatusClosed, WlanStatus,self.iface)
+ try:
+ self.wlanresponse = ifobj.getAPaddr()
+ except IOError:
+ self.wlanresponse = ifobj.getStatistics()
+ if self.wlanresponse:
+ if self.wlanresponse[0] not in (19,95): # 19 = 'No such device', 95 = 'Operation not supported'
+ self.session.openWithCallback(self.WlanStatusClosed, WlanStatus,self.iface)
+ else:
+ # Display Wlan not available Message
+ self.showErrorMessage()
else:
# Display Wlan not available Message
self.showErrorMessage()
@@ -905,7 +944,7 @@ class AdapterSetupConfiguration(Screen, HelpableScreen):
def WlanStatusClosed(self, *ret):
if ret is not None and len(ret):
- from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status
+ from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus
iStatus.stopWlanConsole()
self.updateStatusbar()
@@ -913,7 +952,7 @@ class AdapterSetupConfiguration(Screen, HelpableScreen):
if ret[0] is not None:
self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetup, self.iface,ret[0],ret[1])
else:
- from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status
+ from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus
iStatus.stopWlanConsole()
self.updateStatusbar()
@@ -1263,6 +1302,7 @@ class NetworkAdapterTest(Screen):
self.nextStepTimer.stop()
def layoutFinished(self):
+ self.setTitle(_("Network test: ") + iNetwork.getFriendlyAdapterName(self.iface) )
self["shortcutsyellow"].setEnabled(False)
self["AdapterInfo_OK"].hide()
self["NetworkInfo_Check"].hide()
@@ -1282,7 +1322,7 @@ class NetworkAdapterTest(Screen):
self["AdapterInfo_Text"] = MultiColorLabel(_("Show Info"))
self["AdapterInfo_OK"] = Pixmap()
- if self.iface == 'wlan0' or self.iface == 'ath0':
+ if self.iface in iNetwork.wlan_interfaces:
self["Networktext"] = MultiColorLabel(_("Wireless Network"))
else:
self["Networktext"] = MultiColorLabel(_("Local Network"))
@@ -1321,9 +1361,9 @@ class NetworkAdapterTest(Screen):
self["InfoText"] = Label()
def getLinkState(self,iface):
- if iface == 'wlan0' or iface == 'ath0':
+ if iface in iNetwork.wlan_interfaces:
try:
- from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status
+ from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus
except:
self["Network"].setForegroundColorNum(1)
self["Network"].setText(_("disconnected"))
@@ -1405,7 +1445,7 @@ class NetworkAdapterTest(Screen):
iNetwork.stopLinkStateConsole()
iNetwork.stopDNSConsole()
try:
- from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status
+ from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus
except ImportError:
pass
else:
diff --git a/lib/python/Screens/ParentalControlSetup.py b/lib/python/Screens/ParentalControlSetup.py
index eae12da4..284294fc 100644
--- a/lib/python/Screens/ParentalControlSetup.py
+++ b/lib/python/Screens/ParentalControlSetup.py
@@ -3,7 +3,7 @@ from Components.ConfigList import ConfigListScreen
from Components.ActionMap import NumberActionMap
from Components.config import config, getConfigListEntry, ConfigNothing, NoSave, ConfigPIN
from Components.ParentalControlList import ParentalControlEntryComponent, ParentalControlList
-from Components.ParentalControl import parentalControl
+
from Components.Sources.StaticText import StaticText
from Screens.ChoiceBox import ChoiceBox
from Screens.MessageBox import MessageBox
@@ -78,21 +78,21 @@ class ParentalControlSetup(Screen, ConfigListScreen, ProtectedScreen):
#self.list.append(getConfigListEntry(_("Configuration mode"), config.ParentalControl.mode))
self.list.append(getConfigListEntry(_("Protect setup"), config.ParentalControl.setuppinactive))
if config.ParentalControl.setuppinactive.value:
- self.changeSetupPin = getConfigListEntry(_("Change setup pin"), NoSave(ConfigNothing()))
+ self.changeSetupPin = getConfigListEntry(_("Change setup PIN"), NoSave(ConfigNothing()))
self.list.append(self.changeSetupPin)
self.list.append(getConfigListEntry(_("Protect services"), config.ParentalControl.servicepinactive))
if config.ParentalControl.servicepinactive.value:
self.list.append(getConfigListEntry(_("Parental control type"), config.ParentalControl.type))
if config.ParentalControl.mode.value == "complex":
- self.changePin = getConfigListEntry(_("Change service pins"), NoSave(ConfigNothing()))
+ self.changePin = getConfigListEntry(_("Change service PINs"), NoSave(ConfigNothing()))
self.list.append(self.changePin)
elif config.ParentalControl.mode.value == "simple":
- self.changePin = getConfigListEntry(_("Change service pin"), NoSave(ConfigNothing()))
+ self.changePin = getConfigListEntry(_("Change service PIN"), NoSave(ConfigNothing()))
self.list.append(self.changePin)
#Added Option to remember the service pin
- self.list.append(getConfigListEntry(_("Remember service pin"), config.ParentalControl.storeservicepin))
+ self.list.append(getConfigListEntry(_("Remember service PIN"), config.ParentalControl.storeservicepin))
#Added Option to remember the cancellation of service pin entry
- self.list.append(getConfigListEntry(_("Remember service pin cancel"), config.ParentalControl.storeservicepincancel))
+ self.list.append(getConfigListEntry(_("Remember service PIN cancel"), config.ParentalControl.storeservicepincancel))
self.editListEntry = getConfigListEntry(_("Edit services list"), NoSave(ConfigNothing()))
self.list.append(self.editListEntry)
#New funtion: Possibility to add Bouquets to whitelist / blacklist
@@ -115,10 +115,11 @@ class ParentalControlSetup(Screen, ConfigListScreen, ProtectedScreen):
if config.ParentalControl.mode.value == "complex":
pass
else:
- self.session.open(ParentalControlChangePin, config.ParentalControl.servicepin[0], _("service pin"))
+ self.session.open(ParentalControlChangePin, config.ParentalControl.servicepin[0], _("service PIN"))
elif self["config"].l.getCurrentSelection() == self.changeSetupPin:
- self.session.open(ParentalControlChangePin, config.ParentalControl.setuppin, _("setup pin"))
+ self.session.open(ParentalControlChangePin, config.ParentalControl.setuppin, _("setup PIN"))
elif self["config"].l.getCurrentSelection() == self.reloadLists:
+ from Components.ParentalControl import parentalControl
parentalControl.open()
else:
ConfigListScreen.keyRight(self)
@@ -137,14 +138,14 @@ class ParentalControlSetup(Screen, ConfigListScreen, ProtectedScreen):
def SetupPinMessageCallback(self, value):
if value:
- self.session.openWithCallback(self.cancelCB, ParentalControlChangePin, config.ParentalControl.setuppin, _("setup pin"))
+ self.session.openWithCallback(self.cancelCB, ParentalControlChangePin, config.ParentalControl.setuppin, _("setup PIN"))
else:
config.ParentalControl.setuppinactive.value = False
self.keyCancel()
def ServicePinMessageCallback(self, value):
if value:
- self.session.openWithCallback(self.cancelCB, ParentalControlChangePin, config.ParentalControl.servicepin[0], _("service pin"))
+ self.session.openWithCallback(self.cancelCB, ParentalControlChangePin, config.ParentalControl.servicepin[0], _("service PIN"))
else:
config.ParentalControl.servicepinactive.value = False
self.keyCancel()
@@ -255,6 +256,7 @@ class ParentalControlEditor(Screen):
self.session.openWithCallback(self.letterChosen, ChoiceBox, title=_("Show services beginning with"), list=mylist, keys = [], selection = sel)
def letterChosen(self, result):
+ from Components.ParentalControl import parentalControl
if result is not None:
print "result:", result
self.currentLetter = result[1]
@@ -284,6 +286,7 @@ class ParentalControlBouquetEditor(Screen):
}, -1)
def cancel(self):
+ from Components.ParentalControl import parentalControl
parentalControl.save()
self.close()
@@ -300,6 +303,7 @@ class ParentalControlBouquetEditor(Screen):
self.bouquetlist = list.getContent("CN", True)
def selectBouquet(self):
+ from Components.ParentalControl import parentalControl
self.list = [ParentalControlEntryComponent(x[0], x[1], parentalControl.getProtectionType(x[0])) for x in self.bouquetlist]
self.bouquetslist.setList(self.list)
@@ -317,8 +321,8 @@ class ParentalControlChangePin(Screen, ConfigListScreen, ProtectedScreen):
self.pin2 = ConfigPIN(default = 1112, censor = "*")
self.pin1.addEndNotifier(boundFunction(self.valueChanged, 1))
self.pin2.addEndNotifier(boundFunction(self.valueChanged, 2))
- self.list.append(getConfigListEntry(_("New pin"), NoSave(self.pin1)))
- self.list.append(getConfigListEntry(_("Reenter new pin"), NoSave(self.pin2)))
+ self.list.append(getConfigListEntry(_("New PIN"), NoSave(self.pin1)))
+ self.list.append(getConfigListEntry(_("Reenter new PIN"), NoSave(self.pin2)))
ConfigListScreen.__init__(self, self.list)
# print "old pin:", pin
#if pin.value != "aaaa":
@@ -345,7 +349,7 @@ class ParentalControlChangePin(Screen, ConfigListScreen, ProtectedScreen):
self.keyOK()
def getPinText(self):
- return _("Please enter the old pin code")
+ return _("Please enter the old PIN code")
def isProtected(self):
return (self.pin.value != "aaaa")
@@ -364,9 +368,9 @@ class ParentalControlChangePin(Screen, ConfigListScreen, ProtectedScreen):
if self.pin1.value == self.pin2.value:
self.pin.value = self.pin1.value
self.pin.save()
- self.session.openWithCallback(self.close, MessageBox, _("The pin code has been changed successfully."), MessageBox.TYPE_INFO)
+ self.session.openWithCallback(self.close, MessageBox, _("The PIN code has been changed successfully."), MessageBox.TYPE_INFO)
else:
- self.session.open(MessageBox, _("The pin codes you entered are different."), MessageBox.TYPE_ERROR)
+ self.session.open(MessageBox, _("The PIN codes you entered are different."), MessageBox.TYPE_ERROR)
def cancel(self):
self.close(None)
diff --git a/lib/python/Screens/Satconfig.py b/lib/python/Screens/Satconfig.py
index 40e89420..a5712dcd 100644
--- a/lib/python/Screens/Satconfig.py
+++ b/lib/python/Screens/Satconfig.py
@@ -373,7 +373,6 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
new_configured_sats = nimmanager.getConfiguredSats()
self.unconfed_sats = old_configured_sats - new_configured_sats
self.satpos_to_remove = None
- self.restoreService(_("Zap back to service before tuner setup?"))
self.deleteConfirmed((None, "no"))
def deleteConfirmed(self, confirmed):
@@ -403,7 +402,9 @@ class NimSetup(Screen, ConfigListScreen, ServiceStopScreen):
if confirmed[1] == "yestoall" or confirmed[1] == "notoall":
self.deleteConfirmed(confirmed)
break
-
+ else:
+ self.restoreService(_("Zap back to service before tuner setup?"))
+
def __init__(self, session, slotid):
Screen.__init__(self, session)
self.list = [ ]
@@ -488,7 +489,7 @@ class NimSelection(Screen):
def okbuttonClick(self):
nim = self["nimlist"].getCurrent()
nim = nim and nim[3]
- if nim is not None and not nim.empty:
+ if nim is not None and not nim.empty and nim.isSupported():
self.session.openWithCallback(self.updateList, self.resultclass, nim.slot)
def showNim(self, nim):
@@ -547,6 +548,8 @@ class NimSelection(Screen):
text = _("enabled")
if x.isMultiType():
text = _("Switchable tuner types:") + "(" + ','.join(x.getMultiTypeList().values()) + ")" + "\n" + text
+ if not x.isSupported():
+ text = _("tuner is not supported")
self.list.append((slotid, x.friendly_full_description, text, x))
self["nimlist"].setList(self.list)
diff --git a/lib/python/Screens/ScanSetup.py b/lib/python/Screens/ScanSetup.py
index 1dbc1505..f9263d82 100644
--- a/lib/python/Screens/ScanSetup.py
+++ b/lib/python/Screens/ScanSetup.py
@@ -8,6 +8,7 @@ from Components.ConfigList import ConfigListScreen
from Components.NimManager import nimmanager, getConfigSatlist
from Components.Label import Label
from Tools.Directories import resolveFilename, SCOPE_DEFAULTPARTITIONMOUNTDIR, SCOPE_DEFAULTDIR, SCOPE_DEFAULTPARTITION
+from Tools.HardwareInfo import HardwareInfo
from Screens.MessageBox import MessageBox
from enigma import eTimer, eDVBFrontendParametersSatellite, eComponentScan, \
eDVBSatelliteEquipmentControl, eDVBFrontendParametersTerrestrial, \
@@ -106,6 +107,7 @@ class CableTransponderSearchSupport:
if raw_channel:
frontend = raw_channel.getFrontend()
if frontend:
+ frontend.closeFrontend() # immediate close...
del frontend
del raw_channel
return True
@@ -115,10 +117,14 @@ class CableTransponderSearchSupport:
print "cableTransponderSearchSessionClosed, val", val
self.cable_search_container.appClosed.remove(self.cableTransponderSearchClosed)
self.cable_search_container.dataAvail.remove(self.getCableTransponderData)
+ if val and len(val):
+ if val[0]:
+ self.setCableTransponderSearchResult(self.__tlist)
+ else:
+ self.cable_search_container.sendCtrlC()
+ self.setCableTransponderSearchResult(None)
self.cable_search_container = None
self.cable_search_session = None
- if val and len(val) and val[0]:
- self.setCableTransponderSearchResult(self.__tlist)
self.__tlist = None
self.cableTransponderSearchFinished()
@@ -154,12 +160,12 @@ class CableTransponderSearchSupport:
parm.modulation = qam[data[4]]
parm.inversion = inv[data[5]]
self.__tlist.append(parm)
- tmpstr = _("Try to find used Transponders in cable network.. please wait...")
- tmpstr += "\n\n"
- tmpstr += data[1]
- tmpstr += " kHz "
- tmpstr += data[0]
- self.cable_search_session["text"].setText(tmpstr)
+ tmpstr = _("Try to find used Transponders in cable network.. please wait...")
+ tmpstr += "\n\n"
+ tmpstr += data[1]
+ tmpstr += " kHz "
+ tmpstr += data[0]
+ self.cable_search_session["text"].setText(tmpstr)
def startCableTransponderSearch(self, nim_idx):
if not self.tryGetRawFrontend(nim_idx):
@@ -176,15 +182,17 @@ class CableTransponderSearchSupport:
self.cable_search_container.appClosed.append(self.cableTransponderSearchClosed)
self.cable_search_container.dataAvail.append(self.getCableTransponderData)
cableConfig = config.Nims[nim_idx].cable
- cmd = "tda1002x --init --scan --verbose --wakeup --inv 2 --bus "
- #FIXMEEEEEE hardcoded i2c devices for dm7025 and dm8000
- if nim_idx < 2:
- cmd += str(nim_idx)
+ tunername = nimmanager.getNimName(nim_idx)
+ bus = nimmanager.getI2CDevice(nim_idx)
+ if bus is None:
+ print "ERROR: could not get I2C device for nim", nim_idx, "for cable transponder search"
+ bus = 2
+
+ if tunername == "CXD1981":
+ cmd = "cxd1978 --init --scan --verbose --wakeup --inv 2 --bus %d" % bus
else:
- if nim_idx == 2:
- cmd += "2" # first nim socket on DM8000 use /dev/i2c/2
- else:
- cmd += "4" # second nim socket on DM8000 use /dev/i2c/4
+ cmd = "tda1002x --init --scan --verbose --wakeup --inv 2 --bus %d" % bus
+
if cableConfig.scan_type.value == "bands":
cmd += " --scan-bands "
bands = 0
@@ -827,7 +835,10 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport):
self.tlist = tlist
def cableTransponderSearchFinished(self):
- self.startScan(self.tlist, self.flags, self.feid)
+ if self.tlist is None:
+ self.tlist = []
+ else:
+ self.startScan(self.tlist, self.flags, self.feid)
def startScan(self, tlist, flags, feid):
if len(tlist):
@@ -993,7 +1004,8 @@ class ScanSimple(ConfigListScreen, Screen, CableTransponderSearchSupport):
self.session.open(MessageBox, _("Nothing to scan!\nPlease setup your tuner settings before you start a service scan."), MessageBox.TYPE_ERROR)
def setCableTransponderSearchResult(self, tlist):
- self.scanList.append({"transponders": tlist, "feid": self.feid, "flags": self.flags})
+ if tlist is not None:
+ self.scanList.append({"transponders": tlist, "feid": self.feid, "flags": self.flags})
def cableTransponderSearchFinished(self):
self.buildTransponderList()
diff --git a/lib/python/Screens/ServiceScan.py b/lib/python/Screens/ServiceScan.py
index 1fd32e06..df427f99 100644
--- a/lib/python/Screens/ServiceScan.py
+++ b/lib/python/Screens/ServiceScan.py
@@ -32,26 +32,11 @@ class ServiceScan(Screen):
def ok(self):
print "ok"
if self["scan"].isDone():
- self.resetTimeout()
self.close()
def cancel(self):
- self.resetTimeout()
self.close()
- def setTimeout(self):
- try:
- self.oldtimeoutvalue = open("/sys/module/dvb_core/parameters/dvb_shutdown_timeout", "r").readline()
- open("/sys/module/dvb_core/parameters/dvb_shutdown_timeout", "w").write("0")
- except:
- print "[info] no /sys/module/dvb_core/parameters/dvb_shutdown_timeout available"
-
- def resetTimeout(self):
- try:
- open("/sys/module/dvb_core/parameters/dvb_shutdown_timeout", "w").write(self.oldtimeoutvalue)
- except:
- print "[info] no /sys/module/dvb_core/parameters/dvb_shutdown_timeout available"
-
def __init__(self, session, scanList):
Screen.__init__(self, session)
@@ -73,9 +58,7 @@ class ServiceScan(Screen):
"ok": self.ok,
"cancel": self.cancel
})
-
- self.setTimeout()
-
+
self.onFirstExecBegin.append(self.doServiceScan)
def doServiceScan(self):
diff --git a/lib/python/Screens/Standby.py b/lib/python/Screens/Standby.py
index 406b87cb..1a7ebbd1 100644
--- a/lib/python/Screens/Standby.py
+++ b/lib/python/Screens/Standby.py
@@ -3,6 +3,7 @@ from Components.ActionMap import ActionMap
from Components.config import config
from Components.AVSwitch import AVSwitch
from Components.SystemInfo import SystemInfo
+from GlobalActions import globalActionMap
from enigma import eDVBVolumecontrol
inStandby = None
@@ -41,6 +42,8 @@ class Standby(Screen):
"power": self.Power
}, -1)
+ globalActionMap.setEnabled(False)
+
#mute adc
self.setMute()
@@ -72,6 +75,7 @@ class Standby(Screen):
elif self.paused_service:
self.paused_service.unPauseService()
self.session.screen["Standby"].boolean = False
+ globalActionMap.setEnabled(True)
def __onFirstExecBegin(self):
global inStandby
diff --git a/lib/python/Screens/Subtitles.py b/lib/python/Screens/Subtitles.py
deleted file mode 100644
index 9ba7e0a5..00000000
--- a/lib/python/Screens/Subtitles.py
+++ /dev/null
@@ -1,103 +0,0 @@
-from Screen import Screen
-from Components.ServiceEventTracker import ServiceEventTracker
-from Components.ActionMap import ActionMap
-from Components.ConfigList import ConfigListScreen
-from Components.config import config, getConfigListEntry, ConfigNothing
-from enigma import iPlayableService
-
-from Tools.ISO639 import LanguageCodes
-
-class Subtitles(Screen, ConfigListScreen):
- def __init__(self, session, infobar=None):
- Screen.__init__(self, session)
-
- self["actions"] = ActionMap(["SetupActions"],
- {
- "ok": self.ok,
- "cancel": self.cancel,
- }, -2)
-
- self.list = []
- ConfigListScreen.__init__(self, self.list)
- self.infobar = infobar or self.session.infobar
- self.fillList()
-
- self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
- {
- iPlayableService.evUpdatedInfo: self.__updatedInfo
- })
- self.cached_subtitle_checked = False
- self.__selected_subtitle = None
-
- def fillList(self):
- list = self.list
- del list[:]
- print "self.list", list
- if self.subtitlesEnabled():
- list.append(getConfigListEntry(_("Disable Subtitles"), ConfigNothing(), None))
- sel = self.infobar.selected_subtitle
- else:
- sel = None
- for x in self.getSubtitleList():
- if sel and sel[:4] == x[:4]: #ignore Language code in compare
- text = _("Running")
- else:
- text = _("Enable")
- if x[0] == 0:
- if LanguageCodes.has_key(x[4]):
- list.append(getConfigListEntry(text+" DVB "+LanguageCodes[x[4]][0], ConfigNothing(), x))
- else:
- list.append(getConfigListEntry(text+" DVB "+x[4], ConfigNothing(), x))
- elif x[0] == 1:
- if x[4] == 'und': #undefined
- list.append(getConfigListEntry(text+" TTX "+_("Page")+" %x%02x"%(x[3],x[2]), ConfigNothing(), x))
- else:
- if LanguageCodes.has_key(x[4]):
- list.append(getConfigListEntry(text+" TTX "+_("Page")+" %x%02x"%(x[3],x[2])+" "+LanguageCodes[x[4]][0], ConfigNothing(), x))
- else:
- list.append(getConfigListEntry(text+" TTX "+_("Page")+" %x%02x"%(x[3],x[2])+" "+x[4], ConfigNothing(), x))
- elif x[0] == 2:
- types = (" UTF-8 text "," SSA / AAS "," .SRT file ")
- if x[4] == 'und': #undefined
- list.append(getConfigListEntry(text+types[x[2]]+_("Subtitles")+" %d" % x[1], ConfigNothing(), x))
- else:
- if LanguageCodes.has_key(x[4]):
- list.append(getConfigListEntry(text+types[x[2]]+_("Subtitles") + ' ' + LanguageCodes[x[4]][0], ConfigNothing(), x))
- else:
- list.append(getConfigListEntry(text+types[x[2]]+_("Subtitles")+" %d " % x[1] +x[4], ConfigNothing(), x))
-# return _("Disable subtitles")
- self["config"].list = list
- self["config"].l.setList(list)
-
- def __updatedInfo(self):
- self.fillList()
-
- def getSubtitleList(self):
- s = self.infobar and self.infobar.getCurrentServiceSubtitle()
- l = s and s.getSubtitleList() or [ ]
- return l
-
- def subtitlesEnabled(self):
- return self.infobar.subtitles_enabled
-
- def enableSubtitle(self, subtitles):
- if self.infobar.selected_subtitle != subtitles:
- self.infobar.subtitles_enabled = False
- self.infobar.selected_subtitle = subtitles
- if subtitles:
- self.infobar.subtitles_enabled = True
-
- def keyLeft(self):
- ConfigListScreen.keyLeft(self)
-
- def keyRight(self):
- ConfigListScreen.keyRight(self)
-
- def ok(self):
- if self.list:
- cur = self["config"].getCurrent()
- self.enableSubtitle(cur[2])
- self.close(1)
-
- def cancel(self):
- self.close()
diff --git a/lib/python/Screens/TaskView.py b/lib/python/Screens/TaskView.py
index 9907e2fb..660fb276 100644
--- a/lib/python/Screens/TaskView.py
+++ b/lib/python/Screens/TaskView.py
@@ -7,7 +7,7 @@ import Screens.Standby
from Tools import Notifications
class JobView(InfoBarNotifications, Screen, ConfigListScreen):
- def __init__(self, session, job, parent=None, cancelable = True, backgroundable = True):
+ def __init__(self, session, job, parent=None, cancelable = True, backgroundable = True, afterEventChangeable = True):
from Components.Sources.StaticText import StaticText
from Components.Sources.Progress import Progress
from Components.Sources.Boolean import Boolean
@@ -50,11 +50,15 @@ class JobView(InfoBarNotifications, Screen, ConfigListScreen):
shutdownString = _("shut down")
self.settings.afterEvent = ConfigSelection(choices = [("nothing", _("do nothing")), ("close", _("Close")), ("standby", _("go to standby")), ("deepstandby", shutdownString)], default = self.job.afterEvent or "nothing")
self.job.afterEvent = self.settings.afterEvent.getValue()
+ self.afterEventChangeable = afterEventChangeable
self.setupList()
self.state_changed()
def setupList(self):
- self["config"].setList( [ getConfigListEntry(_("After event"), self.settings.afterEvent) ])
+ if self.afterEventChangeable:
+ self["config"].setList( [ getConfigListEntry(_("After event"), self.settings.afterEvent) ])
+ else:
+ self["config"].hide()
self.job.afterEvent = self.settings.afterEvent.getValue()
def keyLeft(self):
@@ -113,8 +117,8 @@ class JobView(InfoBarNotifications, Screen, ConfigListScreen):
self["config"].hide()
if self.settings.afterEvent.getValue() == "nothing":
return
- elif self.settings.afterEvent.getValue() == "close":
- self.abort()
+ elif self.settings.afterEvent.getValue() == "close" and self.job.status == self.job.FINISHED:
+ self.close(False)
from Screens.MessageBox import MessageBox
if self.settings.afterEvent.getValue() == "deepstandby":
if not Screens.Standby.inTryQuitMainloop:
@@ -123,6 +127,12 @@ class JobView(InfoBarNotifications, Screen, ConfigListScreen):
if not Screens.Standby.inStandby:
Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _("A sleep timer wants to set your\nDreambox to standby. Do that now?"), timeout = 20)
+ def checkNotifications(self):
+ InfoBarNotifications.checkNotifications(self)
+ if Notifications.notifications == []:
+ if self.settings.afterEvent.getValue() == "close" and self.job.status == self.job.FAILED:
+ self.close(False)
+
def sendStandbyNotification(self, answer):
if answer:
Notifications.AddNotification(Screens.Standby.Standby)
diff --git a/lib/python/Screens/TimerEntry.py b/lib/python/Screens/TimerEntry.py
index 64fa9f19..9885e700 100644
--- a/lib/python/Screens/TimerEntry.py
+++ b/lib/python/Screens/TimerEntry.py
@@ -13,8 +13,9 @@ from Components.UsageConfig import defaultMoviePath
from Screens.MovieSelection import getPreferredTagEditor
from Screens.LocationBox import MovieLocationBox
from Screens.ChoiceBox import ChoiceBox
+from Screens.MessageBox import MessageBox
from RecordTimer import AFTEREVENT
-from enigma import eEPGCache
+from enigma import eEPGCache, eServiceReference
from time import localtime, mktime, time, strftime
from datetime import datetime
@@ -245,7 +246,7 @@ class TimerEntry(Screen, ConfigListScreen):
self.timerentry_service_ref = ServiceReference(args[0])
self.timerentry_service.setCurrentText(self.timerentry_service_ref.getServiceName())
self["config"].invalidate(self.channelEntry)
-
+
def getTimestamp(self, date, mytime):
d = localtime(date)
dt = datetime(d.tm_year, d.tm_mon, d.tm_mday, mytime[0], mytime[1])
@@ -264,7 +265,22 @@ class TimerEntry(Screen, ConfigListScreen):
end += 86400
return begin, end
- def keyGo(self):
+ def selectChannelSelector(self, *args):
+ self.session.openWithCallback(
+ self.finishedChannelSelectionCorrection,
+ ChannelSelection.SimpleChannelSelection,
+ _("Select channel to record from")
+ )
+
+ def finishedChannelSelectionCorrection(self, *args):
+ if args:
+ self.finishedChannelSelection(*args)
+ self.keyGo()
+
+ def keyGo(self, result = None):
+ if not self.timerentry_service_ref.isRecordable():
+ self.session.openWithCallback(self.selectChannelSelector, MessageBox, _("You didn't select a channel to record from."), MessageBox.TYPE_ERROR)
+ return
self.timer.name = self.timerentry_name.value
self.timer.description = self.timerentry_description.value
self.timer.justplay = self.timerentry_justplay.value == "zap"
diff --git a/lib/python/Screens/Wizard.py b/lib/python/Screens/Wizard.py
index 1bff0284..a752d31c 100755
--- a/lib/python/Screens/Wizard.py
+++ b/lib/python/Screens/Wizard.py
@@ -387,10 +387,14 @@ class Wizard(Screen):
def keyNumberGlobal(self, number):
if (self.wizard[self.currStep]["config"]["screen"] != None):
self.configInstance.keyNumberGlobal(number)
+ elif (self.wizard[self.currStep]["config"]["type"] == "dynamic"):
+ self["config"].handleKey(KEY_0 + number)
def keyGotAscii(self):
if (self.wizard[self.currStep]["config"]["screen"] != None):
self["config"].handleKey(KEY_ASCII)
+ elif (self.wizard[self.currStep]["config"]["type"] == "dynamic"):
+ self["config"].handleKey(KEY_ASCII)
def left(self):
self.resetCounter()
diff --git a/lib/python/Tools/NumericalTextInput.py b/lib/python/Tools/NumericalTextInput.py
index df6a5ea8..da090b13 100644
--- a/lib/python/Tools/NumericalTextInput.py
+++ b/lib/python/Tools/NumericalTextInput.py
@@ -31,7 +31,7 @@ class NumericalTextInput:
return
if self.lang == 'de_DE':
- self.mapping.append (u".,?'+\"0-()@/:_$!") # 0
+ self.mapping.append (u".,?'+\"0-()@/:_$!=") # 0
self.mapping.append (u" 1") # 1
self.mapping.append (u"aäbc2AÄBC") # 2
self.mapping.append (u"def3DEF") # 3
@@ -42,7 +42,7 @@ class NumericalTextInput:
self.mapping.append (u"tuüv8TUÜV") # 8
self.mapping.append (u"wxyz9WXYZ") # 9
elif self.lang == 'es_ES':
- self.mapping.append (u".,?'+\"0-()@/:_$!") # 0
+ self.mapping.append (u".,?'+\"0-()@/:_$!=") # 0
self.mapping.append (u" 1") # 1
self.mapping.append (u"abcáà2ABCÁÀ") # 2
self.mapping.append (u"deéèf3DEFÉÈ") # 3
@@ -53,7 +53,7 @@ class NumericalTextInput:
self.mapping.append (u"tuvúù8TUVÚÙ") # 8
self.mapping.append (u"wxyz9WXYZ") # 9
if self.lang in ('sv_SE', 'fi_FI'):
- self.mapping.append (u".,?'+\"0-()@/:_$!") # 0
+ self.mapping.append (u".,?'+\"0-()@/:_$!=") # 0
self.mapping.append (u" 1") # 1
self.mapping.append (u"abcåä2ABCÅÄ") # 2
self.mapping.append (u"defé3DEFÉ") # 3
@@ -64,7 +64,7 @@ class NumericalTextInput:
self.mapping.append (u"tuv8TUV") # 8
self.mapping.append (u"wxyz9WXYZ") # 9
else:
- self.mapping.append (u".,?'+\"0-()@/:_$!") # 0
+ self.mapping.append (u".,?'+\"0-()@/:_$!=") # 0
self.mapping.append (u" 1") # 1
self.mapping.append (u"abc2ABC") # 2
self.mapping.append (u"def3DEF") # 3
diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i
index 2fec2ff1..19fb9254 100644
--- a/lib/python/enigma_python.i
+++ b/lib/python/enigma_python.i
@@ -39,6 +39,7 @@ is usually caused by not marking PSignals as immutable.
#include <lib/base/ebase.h>
#include <lib/base/smartptr.h>
#include <lib/base/eerror.h>
+#include <lib/base/etpm.h>
#include <lib/base/nconfig.h>
#include <lib/base/message.h>
#include <lib/driver/rc.h>
@@ -157,6 +158,7 @@ typedef long time_t;
%immutable ePythonMessagePump::recv_msg;
%immutable eDVBLocalTimeHandler::m_timeUpdated;
%include <lib/base/message.h>
+%include <lib/base/etpm.h>
%include <lib/base/nconfig.h>
%include <lib/driver/rc.h>
%include <lib/gdi/fb.h>
diff --git a/lib/service/listboxservice.cpp b/lib/service/listboxservice.cpp
index 05aaf731..cc8c32b5 100644
--- a/lib/service/listboxservice.cpp
+++ b/lib/service/listboxservice.cpp
@@ -526,7 +526,12 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const
ePtr<iStaticServiceInformation> service_info;
m_service_center->info(*m_cursor, service_info);
eServiceReference ref = *m_cursor;
- bool isPlayable = !(ref.flags & eServiceReference::isDirectory || ref.flags & eServiceReference::isMarker);
+ bool isMarker = ref.flags & eServiceReference::isMarker;
+ bool isPlayable = !(ref.flags & eServiceReference::isDirectory || isMarker);
+ bool paintProgress = false;
+ ePtr<eServiceEvent> evt;
+
+ bool serviceAvail = true;
if (!marked && isPlayable && service_info && m_is_playable_ignore.valid() && !service_info->isPlayable(*m_cursor, m_is_playable_ignore))
{
@@ -534,12 +539,13 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const
painter.setForegroundColor(m_color[serviceNotAvail]);
else
painter.setForegroundColor(gRGB(0xbbbbbb));
+ serviceAvail = false;
}
if (selected && local_style && local_style->m_selection)
painter.blit(local_style->m_selection, offset, eRect(), gPainter::BT_ALPHATEST);
- int xoffset=0; // used as offset when painting the folder/marker symbol
+ int xoffset=0; // used as offset when painting the folder/marker symbol or the serviceevent progress
for (int e = 0; e < celElements; ++e)
{
@@ -583,13 +589,19 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const
}
case celServiceInfo:
{
- ePtr<eServiceEvent> evt;
- if ( isPlayable && service_info && !service_info->getEvent(*m_cursor, evt) )
+ if ( isPlayable && !service_info->getEvent(*m_cursor, evt) )
{
std::string name = evt->getEventName();
if (!name.length())
continue;
text = '(' + evt->getEventName() + ')';
+ if (serviceAvail)
+ {
+ if (!selected && m_color_set[serviceDescriptionColor])
+ painter.setForegroundColor(m_color[serviceDescriptionColor]);
+ else if (selected && m_color_set[serviceDescriptionColorSelected])
+ painter.setForegroundColor(m_color[serviceDescriptionColorSelected]);
+ }
}
else
continue;
@@ -608,9 +620,9 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const
{
eRect bbox = para->getBoundBox();
int name_width = bbox.width()+8;
- m_element_position[celServiceInfo].setLeft(area.left()+name_width);
+ m_element_position[celServiceInfo].setLeft(area.left()+name_width+xoffs);
m_element_position[celServiceInfo].setTop(area.top());
- m_element_position[celServiceInfo].setWidth(area.width()-name_width);
+ m_element_position[celServiceInfo].setWidth(area.width()-(name_width+xoffs));
m_element_position[celServiceInfo].setHeight(area.height());
}
@@ -678,12 +690,62 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const
painter.clippop();
}
}
+ else if (e == celServiceEventProgressbar)
+ {
+ eRect area = m_element_position[celServiceEventProgressbar];
+ if (area.width() > 0 && (isPlayable || isMarker))
+ {
+ // we schedule it to paint it as last element.. so we dont need to reset fore/background color
+ paintProgress = isPlayable;
+ xoffset = area.width() + 10;
+ }
+ }
}
-
if (selected && (!local_style || !local_style->m_selection))
style.drawFrame(painter, eRect(offset, m_itemsize), eWindowStyle::frameListboxEntry);
+ if (paintProgress && evt)
+ {
+ eRect area = m_element_position[celServiceEventProgressbar];
+ if (!selected && m_color_set[serviceEventProgressbarBorderColor])
+ painter.setForegroundColor(m_color[serviceEventProgressbarBorderColor]);
+ else if (selected && m_color_set[serviceEventProgressbarBorderColorSelected])
+ painter.setForegroundColor(m_color[serviceEventProgressbarBorderColorSelected]);
+
+ int border = 1;
+ int progressH = 6;
+ int progressX = area.left() + offset.x();
+ int progressW = area.width() - 2 * border;
+ int progressT = offset.y() + (m_itemsize.height() - progressH - 2*border) / 2;
+
+ // paint progressbar frame
+ painter.fill(eRect(progressX, progressT, area.width(), border));
+ painter.fill(eRect(progressX, progressT + border, border, progressH));
+ painter.fill(eRect(progressX, progressT + progressH + border, area.width(), border));
+ painter.fill(eRect(progressX + area.width() - border, progressT + border, border, progressH));
+
+ // calculate value
+ time_t now = time(0);
+ int value = progressW * (now - evt->getBeginTime()) / evt->getDuration();
+
+ eRect tmp = eRect(progressX + border, progressT + border, value, progressH);
+ ePtr<gPixmap> &pixmap = m_pixmaps[picServiceEventProgressbar];
+ if (pixmap)
+ {
+ area.moveBy(offset);
+ painter.clip(area);
+ painter.blit(pixmap, ePoint(progressX + border, progressT + border), tmp, gPainter::BT_ALPHATEST);
+ painter.clippop();
+ }
+ else
+ {
+ if (!selected && m_color_set[serviceEventProgressbarColor])
+ painter.setForegroundColor(m_color[serviceEventProgressbarColor]);
+ else if (selected && m_color_set[serviceEventProgressbarColorSelected])
+ painter.setForegroundColor(m_color[serviceEventProgressbarColorSelected]);
+ painter.fill(tmp);
+ }
+ }
}
-
painter.clippop();
}
diff --git a/lib/service/listboxservice.h b/lib/service/listboxservice.h
index 5228a2f2..589afba6 100644
--- a/lib/service/listboxservice.h
+++ b/lib/service/listboxservice.h
@@ -49,6 +49,7 @@ public:
celServiceNumber,
celMarkerPixmap,
celFolderPixmap,
+ celServiceEventProgressbar,
celServiceName,
celServiceTypePixmap,
celServiceInfo, // "now" event
@@ -62,6 +63,7 @@ public:
picServiceGroup,
picFolder,
picMarker,
+ picServiceEventProgressbar,
picElements
};
@@ -84,6 +86,12 @@ public:
markedBackground,
markedBackgroundSelected,
serviceNotAvail,
+ serviceEventProgressbarColor,
+ serviceEventProgressbarColorSelected,
+ serviceEventProgressbarBorderColor,
+ serviceEventProgressbarBorderColorSelected,
+ serviceDescriptionColor,
+ serviceDescriptionColorSelected,
colorElements
};
diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp
index e498dd42..4d56a25e 100644
--- a/lib/service/servicedvb.cpp
+++ b/lib/service/servicedvb.cpp
@@ -309,7 +309,9 @@ eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceR
RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
{
ASSERT(ref == m_ref);
- if (m_parser.m_name.size())
+ if (!ref.name.empty())
+ name = ref.name;
+ else if (!m_parser.m_name.empty())
name = m_parser.m_name;
else
{
diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp
index 154f4868..1fb1e443 100644
--- a/lib/service/servicemp3.cpp
+++ b/lib/service/servicemp3.cpp
@@ -20,6 +20,8 @@
#include <gst/pbutils/missing-plugins.h>
#include <sys/stat.h>
+#define HTTP_TIMEOUT 10
+
// eServiceFactoryMP3
eServiceFactoryMP3::eServiceFactoryMP3()
@@ -217,6 +219,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
{
m_seekTimeout = eTimer::create(eApp);
m_subtitle_sync_timer = eTimer::create(eApp);
+ m_streamingsrc_timeout = 0;
m_stream_tags = 0;
m_currentAudioStream = -1;
m_currentSubtitleStream = 0;
@@ -237,63 +240,73 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
if (!ext)
ext = filename;
- sourceStream sourceinfo;
- sourceinfo.is_video = FALSE;
- sourceinfo.audiotype = atUnknown;
+ m_sourceinfo.is_video = FALSE;
+ m_sourceinfo.audiotype = atUnknown;
if ( (strcasecmp(ext, ".mpeg") && strcasecmp(ext, ".mpg") && strcasecmp(ext, ".vob") && strcasecmp(ext, ".bin") && strcasecmp(ext, ".dat") ) == 0 )
{
- sourceinfo.containertype = ctMPEGPS;
- sourceinfo.is_video = TRUE;
+ m_sourceinfo.containertype = ctMPEGPS;
+ m_sourceinfo.is_video = TRUE;
}
else if ( strcasecmp(ext, ".ts") == 0 )
{
- sourceinfo.containertype = ctMPEGTS;
- sourceinfo.is_video = TRUE;
+ m_sourceinfo.containertype = ctMPEGTS;
+ m_sourceinfo.is_video = TRUE;
}
else if ( strcasecmp(ext, ".mkv") == 0 )
{
- sourceinfo.containertype = ctMKV;
- sourceinfo.is_video = TRUE;
+ m_sourceinfo.containertype = ctMKV;
+ m_sourceinfo.is_video = TRUE;
}
else if ( strcasecmp(ext, ".avi") == 0 || strcasecmp(ext, ".divx") == 0)
{
- sourceinfo.containertype = ctAVI;
- sourceinfo.is_video = TRUE;
+ m_sourceinfo.containertype = ctAVI;
+ m_sourceinfo.is_video = TRUE;
}
else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0 || strcasecmp(ext, ".m4v") == 0)
{
- sourceinfo.containertype = ctMP4;
- sourceinfo.is_video = TRUE;
+ m_sourceinfo.containertype = ctMP4;
+ m_sourceinfo.is_video = TRUE;
}
else if ( strcasecmp(ext, ".m4a") == 0 )
{
- sourceinfo.containertype = ctMP4;
- sourceinfo.audiotype = atAAC;
+ m_sourceinfo.containertype = ctMP4;
+ m_sourceinfo.audiotype = atAAC;
}
else if ( strcasecmp(ext, ".mp3") == 0 )
- sourceinfo.audiotype = atMP3;
+ m_sourceinfo.audiotype = atMP3;
else if ( (strncmp(filename, "/autofs/", 8) || strncmp(filename+strlen(filename)-13, "/track-", 7) || strcasecmp(ext, ".wav")) == 0 )
- sourceinfo.containertype = ctCDA;
+ m_sourceinfo.containertype = ctCDA;
if ( strcasecmp(ext, ".dat") == 0 )
{
- sourceinfo.containertype = ctVCD;
- sourceinfo.is_video = TRUE;
+ m_sourceinfo.containertype = ctVCD;
+ m_sourceinfo.is_video = TRUE;
}
- if ( (strncmp(filename, "http://", 7)) == 0 || (strncmp(filename, "udp://", 6)) == 0 || (strncmp(filename, "rtp://", 6)) == 0 || (strncmp(filename, "https://", 8)) == 0 || (strncmp(filename, "mms://", 6)) == 0 || (strncmp(filename, "rtsp://", 7)) == 0 )
- sourceinfo.is_streaming = TRUE;
+ if ( (strncmp(filename, "http://", 7)) == 0 || (strncmp(filename, "udp://", 6)) == 0 || (strncmp(filename, "rtp://", 6)) == 0 || (strncmp(filename, "https://", 8)) == 0 || (strncmp(filename, "mms://", 6)) == 0 || (strncmp(filename, "rtsp://", 7)) == 0 || (strncmp(filename, "rtspt://", 7)) == 0 )
+ m_sourceinfo.is_streaming = TRUE;
gchar *uri;
- if ( sourceinfo.is_streaming )
+ if ( m_sourceinfo.is_streaming )
{
uri = g_strdup_printf ("%s", filename);
+ m_streamingsrc_timeout = eTimer::create(eApp);;
+ CONNECT(m_streamingsrc_timeout->timeout, eServiceMP3::sourceTimeout);
+
+ std::string config_str;
+ if( ePythonConfigQuery::getConfigValue("config.mediaplayer.useAlternateUserAgent", config_str) == 0 )
+ {
+ if ( config_str == "True" )
+ ePythonConfigQuery::getConfigValue("config.mediaplayer.alternateUserAgent", m_useragent);
+ }
+ if ( m_useragent.length() == 0 )
+ m_useragent = "Dream Multimedia Dreambox Enigma2 Mediaplayer";
}
- else if ( sourceinfo.containertype == ctCDA )
+ else if ( m_sourceinfo.containertype == ctCDA )
{
int i_track = atoi(filename+18);
uri = g_strdup_printf ("cdda://%i", i_track);
}
- else if ( sourceinfo.containertype == ctVCD )
+ else if ( m_sourceinfo.containertype == ctVCD )
{
int fd = open(filename,O_RDONLY);
char tmp[128*1024];
@@ -327,6 +340,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
else
{
m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this);
+ g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-pango-markup"), NULL);
g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL);
}
@@ -347,6 +361,10 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
subs.language_code = std::string("und");
m_subtitleStreams.push_back(subs);
}
+ if ( m_sourceinfo.is_streaming )
+ {
+ g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (gstHTTPSourceSetAgent), this);
+ }
} else
{
m_event((iPlayableService*)this, evUser+12);
@@ -414,6 +432,12 @@ RESULT eServiceMP3::start()
return 0;
}
+void eServiceMP3::sourceTimeout()
+{
+ eDebug("eServiceMP3::http source timeout! issuing eof...");
+ m_event((iPlayableService*)this, evEOF);
+}
+
RESULT eServiceMP3::stop()
{
ASSERT(m_state != stIdle);
@@ -1150,6 +1174,8 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
} break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
{
+ if ( m_sourceinfo.is_streaming && m_streamingsrc_timeout )
+ m_streamingsrc_timeout->stop();
} break;
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
{
@@ -1301,6 +1327,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
// g_free (g_type);
}
m_event((iPlayableService*)this, evUpdatedEventInfo);
+ break;
}
case GST_MESSAGE_ELEMENT:
{
@@ -1349,6 +1376,37 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
gst_message_parse_buffering(msg, &(m_bufferInfo.bufferPercent));
gst_message_parse_buffering_stats(msg, &mode, &(m_bufferInfo.avgInRate), &(m_bufferInfo.avgOutRate), &(m_bufferInfo.bufferingLeft));
m_event((iPlayableService*)this, evBuffering);
+ break;
+ }
+ case GST_MESSAGE_STREAM_STATUS:
+ {
+ GstStreamStatusType type;
+ GstElement *owner;
+ gst_message_parse_stream_status (msg, &type, &owner);
+ if ( type == GST_STREAM_STATUS_TYPE_CREATE && m_sourceinfo.is_streaming )
+ {
+ if ( GST_IS_PAD(source) )
+ owner = gst_pad_get_parent_element(GST_PAD(source));
+ else if ( GST_IS_ELEMENT(source) )
+ owner = GST_ELEMENT(source);
+ else
+ owner = 0;
+ if ( owner )
+ {
+ GstElementFactory *factory = gst_element_get_factory(GST_ELEMENT(owner));
+ const gchar *name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
+ if (!strcmp(name, "souphttpsrc"))
+ {
+ m_streamingsrc_timeout->start(HTTP_TIMEOUT*1000, true);
+ g_object_set (G_OBJECT (owner), "timeout", HTTP_TIMEOUT, NULL);
+ eDebug("eServiceMP3::GST_STREAM_STATUS_TYPE_CREATE -> setting timeout on %s to %is", name, HTTP_TIMEOUT);
+ }
+
+ }
+ if ( GST_IS_PAD(source) )
+ gst_object_unref(owner);
+ }
+ break;
}
default:
break;
@@ -1364,6 +1422,15 @@ GstBusSyncReply eServiceMP3::gstBusSyncHandler(GstBus *bus, GstMessage *message,
return GST_BUS_PASS;
}
+void eServiceMP3::gstHTTPSourceSetAgent(GObject *object, GParamSpec *unused, gpointer user_data)
+{
+ eServiceMP3 *_this = (eServiceMP3*)user_data;
+ GstElement *source;
+ g_object_get(_this->m_gst_playbin, "source", &source, NULL);
+ g_object_set (G_OBJECT (source), "user-agent", _this->m_useragent.c_str(), NULL);
+ gst_object_unref(source);
+}
+
audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure)
{
if (!structure)
diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h
index 56a068b9..01f7cf7f 100644
--- a/lib/service/servicemp3.h
+++ b/lib/service/servicemp3.h
@@ -208,18 +208,24 @@ private:
static void gstCBsubtitleAvail(GstElement *element, gpointer user_data);
GstPad* gstCreateSubtitleSink(eServiceMP3* _this, subtype_t type);
void gstPoll(const int&);
+ static void gstHTTPSourceSetAgent(GObject *source, GParamSpec *unused, gpointer user_data);
std::list<ePangoSubtitlePage> m_subtitle_pages;
ePtr<eTimer> m_subtitle_sync_timer;
+
+ ePtr<eTimer> m_streamingsrc_timeout;
void pushSubtitles();
void pullSubtitle();
+ void sourceTimeout();
int m_subs_to_pull;
+ sourceStream m_sourceinfo;
eSingleLock m_subs_to_pull_lock;
gulong m_subs_to_pull_handler_id;
RESULT seekToImpl(pts_t to);
gint m_aspect, m_width, m_height, m_framerate, m_progressive;
+ std::string m_useragent;
RESULT trickSeek(gdouble ratio);
};
#endif