aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/dvb/pmt.cpp16
-rw-r--r--lib/gui/elistboxcontent.cpp3
-rwxr-xr-xlib/python/Components/FileList.py3
-rwxr-xr-xlib/python/Plugins/Extensions/MediaPlayer/plugin.py2
-rw-r--r--lib/service/servicem2ts.cpp344
-rw-r--r--lib/service/servicem2ts.h33
6 files changed, 399 insertions, 2 deletions
diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp
index 46fa12ed..e54601cf 100644
--- a/lib/dvb/pmt.cpp
+++ b/lib/dvb/pmt.cpp
@@ -131,6 +131,8 @@ void eDVBServicePMTHandler::PATready(int)
ePtr<eTable<ProgramAssociationSection> > ptr;
if (!m_PAT.getCurrent(ptr))
{
+ int service_id_single = -1;
+ int pmtpid_single = -1;
int pmtpid = -1;
std::vector<ProgramAssociationSection*>::const_iterator i;
for (i = ptr->getSections().begin(); pmtpid == -1 && i != ptr->getSections().end(); ++i)
@@ -138,8 +140,22 @@ void eDVBServicePMTHandler::PATready(int)
const ProgramAssociationSection &pat = **i;
ProgramAssociationConstIterator program;
for (program = pat.getPrograms()->begin(); pmtpid == -1 && program != pat.getPrograms()->end(); ++program)
+ {
if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID())
pmtpid = (*program)->getProgramMapPid();
+ if (pmtpid_single == -1 && pmtpid == -1)
+ {
+ pmtpid_single = (*program)->getProgramMapPid();
+ service_id_single = (*program)->getProgramNumber();
+ }
+ else
+ pmtpid_single = service_id_single = -1;
+ }
+ }
+ if (pmtpid_single != -1) // only one PAT entry .. so we use this one
+ {
+ m_reference.setServiceID(eServiceID(service_id_single));
+ pmtpid = pmtpid_single;
}
if (pmtpid == -1)
serviceEvent(eventNoPATEntry);
diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp
index 43fbc594..97e2cc67 100644
--- a/lib/gui/elistboxcontent.cpp
+++ b/lib/gui/elistboxcontent.cpp
@@ -967,6 +967,9 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c
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");
diff --git a/lib/python/Components/FileList.py b/lib/python/Components/FileList.py
index 1d71514b..1b7e81f5 100755
--- a/lib/python/Components/FileList.py
+++ b/lib/python/Components/FileList.py
@@ -28,7 +28,8 @@ EXTENSIONS = {
"mpeg": "movie",
"mkv": "movie",
"mp4": "movie",
- "mov": "movie"
+ "mov": "movie",
+ "m2ts": "movie",
}
def FileEntryComponent(name, absolute = None, isDir = False):
diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py
index 9ae886fc..d61dbc76 100755
--- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py
+++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py
@@ -110,7 +110,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB
# 'None' is magic to start at the list of mountpoints
defaultDir = config.mediaplayer.defaultDir.getValue()
- self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|m4v|mkv|mp4|m4a|dat|flac|mov)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls")
+ self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|m4v|mkv|mp4|m4a|dat|flac|mov|m2ts)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls")
self["filelist"] = self.filelist
self.playlist = MyPlayList()
diff --git a/lib/service/servicem2ts.cpp b/lib/service/servicem2ts.cpp
new file mode 100644
index 00000000..a86642c3
--- /dev/null
+++ b/lib/service/servicem2ts.cpp
@@ -0,0 +1,344 @@
+#include <lib/base/init_num.h>
+#include <lib/base/init.h>
+#include <lib/dvb/metaparser.h>
+#include <lib/service/servicem2ts.h>
+
+DEFINE_REF(eServiceFactoryM2TS)
+
+class eM2TSFile: public iDataSource
+{
+ DECLARE_REF(eM2TSFile);
+ eSingleLock m_lock;
+public:
+ eM2TSFile(const char *filename, bool cached=false);
+ ~eM2TSFile();
+
+ // iDataSource
+ off_t lseek(off_t offset, int whence);
+ ssize_t read(off_t offset, void *buf, size_t count);
+ off_t length();
+ int valid();
+private:
+ int m_fd; /* for uncached */
+ FILE *m_file; /* for cached */
+ off_t m_current_offset, m_length;
+ bool m_cached;
+ off_t lseek_internal(off_t offset, int whence);
+};
+
+class eStaticServiceM2TSInformation: public iStaticServiceInformation
+{
+ DECLARE_REF(eStaticServiceM2TSInformation);
+ eServiceReference m_ref;
+ eDVBMetaParser m_parser;
+public:
+ eStaticServiceM2TSInformation(const eServiceReference &ref);
+ RESULT getName(const eServiceReference &ref, std::string &name);
+ int getLength(const eServiceReference &ref);
+ RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
+ int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
+ int getInfo(const eServiceReference &ref, int w);
+ std::string getInfoString(const eServiceReference &ref,int w);
+ PyObject *getInfoObject(const eServiceReference &r, int what);
+};
+
+DEFINE_REF(eStaticServiceM2TSInformation);
+
+eStaticServiceM2TSInformation::eStaticServiceM2TSInformation(const eServiceReference &ref)
+{
+ m_ref = ref;
+ m_parser.parseFile(ref.path);
+}
+
+RESULT eStaticServiceM2TSInformation::getName(const eServiceReference &ref, std::string &name)
+{
+ ASSERT(ref == m_ref);
+ if (m_parser.m_name.size())
+ name = m_parser.m_name;
+ else
+ {
+ name = ref.path;
+ size_t n = name.rfind('/');
+ if (n != std::string::npos)
+ name = name.substr(n + 1);
+ }
+ return 0;
+}
+
+int eStaticServiceM2TSInformation::getLength(const eServiceReference &ref)
+{
+ ASSERT(ref == m_ref);
+
+ eDVBTSTools tstools;
+
+ struct stat s;
+ stat(ref.path.c_str(), &s);
+
+ eM2TSFile *file = new eM2TSFile(ref.path.c_str());
+ ePtr<iDataSource> source = file;
+
+ if (!source->valid())
+ return 0;
+
+ tstools.setSource(source);
+
+ /* check if cached data is still valid */
+ if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
+ return m_parser.m_length / 90000;
+
+ /* open again, this time with stream info */
+ tstools.setSource(source, ref.path.c_str());
+
+ /* otherwise, re-calc length and update meta file */
+ pts_t len;
+ if (tstools.calcLen(len))
+ return 0;
+
+ m_parser.m_length = len;
+ m_parser.m_filesize = s.st_size;
+ m_parser.updateMeta(ref.path);
+ return m_parser.m_length / 90000;
+}
+
+int eStaticServiceM2TSInformation::getInfo(const eServiceReference &ref, int w)
+{
+ switch (w)
+ {
+ case iServiceInformation::sDescription:
+ return iServiceInformation::resIsString;
+ case iServiceInformation::sServiceref:
+ return iServiceInformation::resIsString;
+ case iServiceInformation::sFileSize:
+ return m_parser.m_filesize;
+ case iServiceInformation::sTimeCreate:
+ if (m_parser.m_time_create)
+ return m_parser.m_time_create;
+ else
+ return iServiceInformation::resNA;
+ default:
+ return iServiceInformation::resNA;
+ }
+}
+
+std::string eStaticServiceM2TSInformation::getInfoString(const eServiceReference &ref,int w)
+{
+ switch (w)
+ {
+ case iServiceInformation::sDescription:
+ return m_parser.m_description;
+ case iServiceInformation::sServiceref:
+ return m_parser.m_ref.toString();
+ case iServiceInformation::sTags:
+ return m_parser.m_tags;
+ default:
+ return "";
+ }
+}
+
+PyObject *eStaticServiceM2TSInformation::getInfoObject(const eServiceReference &r, int what)
+{
+ switch (what)
+ {
+ case iServiceInformation::sFileSize:
+ return PyLong_FromLongLong(m_parser.m_filesize);
+ default:
+ Py_RETURN_NONE;
+ }
+}
+
+RESULT eStaticServiceM2TSInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
+{
+ if (!ref.path.empty())
+ {
+ ePtr<eServiceEvent> event = new eServiceEvent;
+ std::string filename = ref.path;
+ filename.erase(filename.length()-4, 2);
+ filename+="eit";
+ if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
+ {
+ evt = event;
+ return 0;
+ }
+ }
+ evt = 0;
+ return -1;
+}
+
+DEFINE_REF(eM2TSFile);
+
+eM2TSFile::eM2TSFile(const char *filename, bool cached)
+ :m_lock(false), m_fd(-1), m_file(NULL), m_current_offset(0), m_length(0), m_cached(cached)
+{
+ if (!m_cached)
+ m_fd = ::open(filename, O_RDONLY | O_LARGEFILE);
+ else
+ m_file = ::fopen64(filename, "rb");
+ if (valid())
+ m_current_offset = m_length = lseek_internal(0, SEEK_END);
+}
+
+eM2TSFile::~eM2TSFile()
+{
+ if (m_cached)
+ {
+ if (m_file)
+ {
+ ::fclose(m_file);
+ m_file = 0;
+ }
+ }
+ else
+ {
+ if (m_fd >= 0)
+ ::close(m_fd);
+ m_fd = -1;
+ }
+}
+
+off_t eM2TSFile::lseek(off_t offset, int whence)
+{
+ eSingleLocker l(m_lock);
+
+ offset = (offset * 192) / 188;
+ ASSERT(!(offset % 192));
+
+ if (offset != m_current_offset)
+ m_current_offset = lseek_internal(offset, whence);
+
+ return m_current_offset;
+}
+
+off_t eM2TSFile::lseek_internal(off_t offset, int whence)
+{
+ off_t ret;
+
+ if (!m_cached)
+ ret = ::lseek(m_fd, offset, whence);
+ else
+ {
+ if (::fseeko(m_file, offset, whence) < 0)
+ perror("fseeko");
+ ret = ::ftello(m_file);
+ }
+ return ret <= 0 ? ret : (ret*188)/192;
+}
+
+ssize_t eM2TSFile::read(off_t offset, void *b, size_t count)
+{
+ eSingleLocker l(m_lock);
+ unsigned char tmp[192];
+ unsigned char *buf = (unsigned char*)b;
+ size_t rd=0;
+
+ offset = (offset * 192) / 188;
+ ASSERT(!(offset % 192));
+ ASSERT(!(count % 188));
+
+ if (offset != m_current_offset)
+ {
+ m_current_offset = lseek_internal(offset, SEEK_SET);
+ if (m_current_offset < 0)
+ return m_current_offset;
+ }
+
+ while (rd < count) {
+ size_t ret;
+ if (!m_cached)
+ ret = ::read(m_fd, tmp, 192);
+ else
+ ret = ::fread(tmp, 1, 192, m_file);
+ if (ret < 0 || ret < 192)
+ return rd ? rd : ret;
+ memcpy(buf+rd, tmp+4, 188);
+
+ ASSERT(buf[rd] == 0x47);
+
+ rd += 188;
+ m_current_offset += 188;
+ }
+
+ return rd;
+}
+
+int eM2TSFile::valid()
+{
+ if (!m_cached)
+ return m_fd != -1;
+ else
+ return !!m_file;
+}
+
+off_t eM2TSFile::length()
+{
+ return m_length;
+}
+
+eServiceFactoryM2TS::eServiceFactoryM2TS()
+{
+ ePtr<eServiceCenter> sc;
+ eServiceCenter::getPrivInstance(sc);
+ if (sc)
+ {
+ std::list<std::string> extensions;
+ extensions.push_back("m2ts");
+ extensions.push_back("mts");
+ sc->addServiceFactory(eServiceFactoryM2TS::id, this, extensions);
+ }
+}
+
+eServiceFactoryM2TS::~eServiceFactoryM2TS()
+{
+ ePtr<eServiceCenter> sc;
+
+ eServiceCenter::getPrivInstance(sc);
+ if (sc)
+ sc->removeServiceFactory(eServiceFactoryM2TS::id);
+}
+
+RESULT eServiceFactoryM2TS::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
+{
+ ptr = new eServiceM2TS(ref);
+ return 0;
+}
+
+RESULT eServiceFactoryM2TS::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
+{
+ ptr=0;
+ return -1;
+}
+
+RESULT eServiceFactoryM2TS::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
+{
+ ptr=0;
+ return -1;
+}
+
+RESULT eServiceFactoryM2TS::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
+{
+ ptr=new eStaticServiceM2TSInformation(ref);
+ return 0;
+}
+
+RESULT eServiceFactoryM2TS::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
+{
+ ptr = 0;
+ return -1;
+}
+
+eServiceM2TS::eServiceM2TS(const eServiceReference &ref)
+ :eDVBServicePlay(ref, NULL)
+{
+}
+
+ePtr<iDataSource> eServiceM2TS::createDataSource(eServiceReferenceDVB &ref)
+{
+ ePtr<iDataSource> source = new eM2TSFile(ref.path.c_str());
+ return source;
+}
+
+RESULT eServiceM2TS::isCurrentlySeekable()
+{
+ return 1; // for fast winding we need index files... so only skip forward/backward yet
+}
+
+eAutoInitPtr<eServiceFactoryM2TS> init_eServiceFactoryM2TS(eAutoInitNumbers::service+1, "eServiceFactoryM2TS");
diff --git a/lib/service/servicem2ts.h b/lib/service/servicem2ts.h
new file mode 100644
index 00000000..a53f731f
--- /dev/null
+++ b/lib/service/servicem2ts.h
@@ -0,0 +1,33 @@
+#ifndef __servicem2ts_h
+#define __servicem2ts_h
+
+#include <lib/service/servicedvb.h>
+
+class eServiceFactoryM2TS: public iServiceHandler
+{
+ DECLARE_REF(eServiceFactoryM2TS);
+public:
+ eServiceFactoryM2TS();
+ virtual ~eServiceFactoryM2TS();
+ enum { id = 0x3 };
+
+ // iServiceHandler
+ RESULT play(const eServiceReference &, ePtr<iPlayableService> &ptr);
+ RESULT record(const eServiceReference &, ePtr<iRecordableService> &ptr);
+ RESULT list(const eServiceReference &, ePtr<iListableService> &ptr);
+ RESULT info(const eServiceReference &, ePtr<iStaticServiceInformation> &ptr);
+ RESULT offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr);
+};
+
+class eServiceM2TS: public eDVBServicePlay
+{
+ friend class eServiceFactoryM2TS;
+protected:
+ eServiceM2TS(const eServiceReference &ref);
+ ePtr<iDataSource> createDataSource(eServiceReferenceDVB &ref);
+
+ // iSeekableService
+ RESULT isCurrentlySeekable();
+};
+
+#endif