--- /dev/null
+AC_DEFUN([TUXBOX_APPS],[
+
+INSTALL="$INSTALL -p"
+
+AC_GNU_SOURCE
+AC_SYS_LARGEFILE
+
+AC_ARG_WITH(target,
+ [ --with-target=TARGET target for compilation [[native,cdk]]],
+ [TARGET="$withval"],[TARGET="native"])
+
+AC_ARG_WITH(targetprefix,
+ [ --with-targetprefix=PATH prefix relative to target root (only applicable in cdk mode)],
+ [targetprefix="$withval"],[targetprefix="NONE"])
+
+AC_ARG_WITH(debug,
+ [ --without-debug disable debugging code],
+ [DEBUG="$withval"],[DEBUG="yes"])
+
+if test "$DEBUG" = "yes"; then
+ DEBUG_CFLAGS="-g3 -ggdb"
+ AC_DEFINE(DEBUG,1,[Enable debug messages])
+fi
+
+AC_MSG_CHECKING(target)
+
+if test "$TARGET" = "native"; then
+ AC_MSG_RESULT(native)
+
+ if test "$CFLAGS" = "" -a "$CXXFLAGS" = ""; then
+ CFLAGS="-Wall -O2 -pipe $DEBUG_CFLAGS"
+ CXXFLAGS="-Wall -O2 -pipe $DEBUG_CFLAGS"
+ fi
+ if test "$prefix" = "NONE"; then
+ prefix=/usr/local
+ fi
+ targetprefix=$prefix
+elif test "$TARGET" = "cdk"; then
+ AC_MSG_RESULT(cdk)
+
+ if test "$CC" = "" -a "$CXX" = ""; then
+ CC=powerpc-tuxbox-linux-gnu-gcc CXX=powerpc-tuxbox-linux-gnu-g++
+ fi
+ if test "$CFLAGS" = "" -a "$CXXFLAGS" = ""; then
+ CFLAGS="-Wall -Os -mcpu=823 -pipe $DEBUG_CFLAGS"
+ CXXFLAGS="-Wall -Os -mcpu=823 -pipe $DEBUG_CFLAGS"
+ fi
+ if test "$prefix" = "NONE"; then
+ AC_MSG_ERROR(invalid prefix, you need to specify one in cdk mode)
+ fi
+ if test "$targetprefix" = "NONE"; then
+ targetprefix=""
+ fi
+ if test "$host_alias" = ""; then
+ cross_compiling=yes
+ host_alias=powerpc-tuxbox-linux-gnu
+ fi
+else
+ AC_MSG_RESULT(none)
+ AC_MSG_ERROR([invalid target $TARGET, choose on from native,cdk]);
+fi
+
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+
+check_path () {
+ return $(perl -e "if(\"$1\"=~m#^/usr/(local/)?bin#){print \"0\"}else{print \"1\";}")
+}
+
+])
+
+AC_DEFUN([TUXBOX_APPS_DIRECTORY_ONE],[
+AC_ARG_WITH($1,[ $6$7 [[PREFIX$4$5]]],[
+ _$2=$withval
+ if test "$TARGET" = "cdk"; then
+ $2=`eval echo "${targetprefix}$withval"`
+ else
+ $2=$withval
+ fi
+],[
+ $2="\${$3}$5"
+ if test "$TARGET" = "cdk"; then
+ _$2=`eval echo "${target$3}$5"`
+ else
+ _$2=`eval echo "${$3}$5"`
+ fi
+])
+
+dnl automake <= 1.6 don't support this
+dnl AC_SUBST($2)
+AC_DEFINE_UNQUOTED($2,"$_$2",$7)
+])
+
+AC_DEFUN([TUXBOX_APPS_DIRECTORY],[
+AC_REQUIRE([TUXBOX_APPS])
+
+if test "$TARGET" = "cdk"; then
+ datadir="\${prefix}/share"
+ tuxboxdatadir="\${prefix}/share/tuxbox"
+ zoneinfodir="\${datadir}/zoneinfo"
+ sysconfdir="\${prefix}/etc"
+ localstatedir="\${prefix}/var"
+ localedir="\${prefix}/var"
+ libdir="\${prefix}/lib"
+ targetdatadir="\${targetprefix}/share"
+ targetsysconfdir="\${targetprefix}/etc"
+ targetlocalstatedir="\${targetprefix}/var"
+ targetlibdir="\${targetprefix}/lib"
+fi
+
+TUXBOX_APPS_DIRECTORY_ONE(configdir,CONFIGDIR,sysconfdir,/etc,,
+ [--with-configdir=PATH ],[where to find the config files])
+
+TUXBOX_APPS_DIRECTORY_ONE(datadir,DATADIR,datadir,/share,,
+ [--with-datadir=PATH ],[where to find data])
+
+TUXBOX_APPS_DIRECTORY_ONE(localedir,LOCALEDIR,datadir,/share,/locale,
+ [--with-localedir=PATH ],[where to find locales])
+
+TUXBOX_APPS_DIRECTORY_ONE(fontdir,FONTDIR,datadir,/share,/fonts,
+ [--with-fontdir=PATH ],[where to find the fonts])
+
+TUXBOX_APPS_DIRECTORY_ONE(gamesdir,GAMESDIR,localstatedir,/var,/tuxbox/games,
+ [--with-gamesdir=PATH ],[where games data is stored])
+
+TUXBOX_APPS_DIRECTORY_ONE(libdir,LIBDIR,libdir,/lib,,
+ [--with-libdir=PATH ],[where to find the internal libs])
+
+TUXBOX_APPS_DIRECTORY_ONE(plugindir,PLUGINDIR,libdir,/lib,/tuxbox/plugins,
+ [--with-plugindir=PATH ],[where to find the plugins])
+
+TUXBOX_APPS_DIRECTORY_ONE(tuxboxdatadir,TUXBOXDATADIR,datadir,/share,,
+ [--with-tuxboxdatadir=PATH],[where to find tuxbox data])
+
+TUXBOX_APPS_DIRECTORY_ONE(zoneinfodir,ZONEINFODIR,datadir,/share,/zoneinfo,
+ [--with-zoneinfodir=PATH ],[where to find zoneinfo db])
+])
+
+dnl automake <= 1.6 needs this specifications
+AC_SUBST(CONFIGDIR)
+AC_SUBST(DATADIR)
+AC_SUBST(ZONEINFODIR)
+AC_SUBST(FONTDIR)
+AC_SUBST(GAMESDIR)
+AC_SUBST(LIBDIR)
+AC_SUBST(LOCALEDIR)
+AC_SUBST(PLUGINDIR)
+AC_SUBST(TUXBOXDATADIR)
+dnl end workaround
+
+AC_DEFUN([TUXBOX_APPS_ENDIAN],[
+AC_CHECK_HEADERS(endian.h)
+AC_C_BIGENDIAN
+])
+
+AC_DEFUN([TUXBOX_APPS_DRIVER],[
+#AC_ARG_WITH(driver,
+# [ --with-driver=PATH path for driver sources [[NONE]]],
+# [DRIVER="$withval"],[DRIVER=""])
+#
+#if test -d "$DRIVER/include"; then
+# AC_DEFINE(HAVE_DBOX2_DRIVER,1,[Define to 1 if you have the dbox2 driver sources])
+#else
+# AC_MSG_ERROR([can't find driver sources])
+#fi
+
+#AC_SUBST(DRIVER)
+
+#CPPFLAGS="$CPPFLAGS -I$DRIVER/include"
+])
+
+AC_DEFUN([TUXBOX_APPS_DVB],[
+AC_ARG_WITH(dvbincludes,
+ [ --with-dvbincludes=PATH path for dvb includes [[NONE]]],
+ [DVBINCLUDES="$withval"],[DVBINCLUDES=""])
+
+if test "$DVBINCLUDES"; then
+ CPPFLAGS="$CPPFLAGS -I$DVBINCLUDES"
+fi
+
+AC_CHECK_HEADERS(ost/dmx.h,[
+ DVB_API_VERSION=1
+ AC_MSG_NOTICE([found dvb version 1])
+])
+
+if test -z "$DVB_API_VERSION"; then
+AC_CHECK_HEADERS(linux/dvb/version.h,[
+ AC_LANG_PREPROC_REQUIRE()
+ AC_REQUIRE([AC_PROG_EGREP])
+ AC_LANG_CONFTEST([AC_LANG_SOURCE([[
+#include <linux/dvb/version.h>
+version DVB_API_VERSION
+ ]])])
+ DVB_API_VERSION=`(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | $EGREP "^version" | sed "s,version\ ,,"`
+ rm -f conftest*
+
+ AC_MSG_NOTICE([found dvb version $DVB_API_VERSION])
+])
+fi
+
+if test "$DVB_API_VERSION"; then
+ AC_DEFINE(HAVE_DVB,1,[Define to 1 if you have the dvb includes])
+ AC_DEFINE_UNQUOTED(HAVE_DVB_API_VERSION,$DVB_API_VERSION,[Define to the version of the dvb api])
+else
+ AC_MSG_ERROR([can't find dvb headers])
+fi
+])
+
+AC_DEFUN([_TUXBOX_APPS_LIB_CONFIG],[
+AC_PATH_PROG($1_CONFIG,$2,no)
+if test "$$1_CONFIG" != "no"; then
+ if test "$TARGET" = "cdk" && check_path "$$1_CONFIG"; then
+ AC_MSG_$3([could not find a suitable version of $2]);
+ else
+ $1_CFLAGS=$($$1_CONFIG --cflags)
+ $1_LIBS=$($$1_CONFIG --libs)
+ fi
+fi
+
+AC_SUBST($1_CFLAGS)
+AC_SUBST($1_LIBS)
+])
+
+AC_DEFUN([TUXBOX_APPS_LIB_CONFIG],[
+_TUXBOX_APPS_LIB_CONFIG($1,$2,ERROR)
+if test "$$1_CONFIG" = "no"; then
+ AC_MSG_ERROR([could not find $2]);
+fi
+])
+
+AC_DEFUN([TUXBOX_APPS_LIB_CONFIG_CHECK],[
+_TUXBOX_APPS_LIB_CONFIG($1,$2,WARN)
+])
+
+AC_DEFUN([TUXBOX_APPS_PKGCONFIG],[
+AC_PATH_PROG(PKG_CONFIG, pkg-config,no)
+if test "$PKG_CONFIG" = "no" ; then
+ AC_MSG_ERROR([could not find pkg-config]);
+fi
+])
+
+AC_DEFUN([_TUXBOX_APPS_LIB_PKGCONFIG],[
+PKG_CHECK_MODULES($1,$2)
+AC_SUBST($1_CFLAGS)
+AC_SUBST($1_LIBS)
+])
+
+AC_DEFUN([_TUXBOX_APPS_LIB_PKGCONFIG_OPTIONAL],[
+PKG_CHECK_MODULES($1,$2,$3="yes",$3="no")
+if test "$$3" = "yes"; then
+ AC_DEFINE($3, 1, [$2 available])
+else
+ $1_CFLAGS=""
+ $1_LIBS=""
+fi
+AC_SUBST($1_CFLAGS)
+AC_SUBST($1_LIBS)
+])
+
+AC_DEFUN([TUXBOX_APPS_LIB_PKGCONFIG],[
+_TUXBOX_APPS_LIB_PKGCONFIG($1,$2)
+if test -z "$$1_CFLAGS" ; then
+ AC_MSG_ERROR([could not find package $2]);
+fi
+])
+
+AC_DEFUN([TUXBOX_APPS_LIB_PKGCONFIG_CHECK],[
+_TUXBOX_APPS_LIB_PKGCONFIG($1,$2)
+])
+
+AC_DEFUN([_TUXBOX_APPS_LIB_SYMBOL],[
+AC_CHECK_LIB($2,$3,HAVE_$1="yes",HAVE_$1="no")
+if test "$HAVE_$1" = "yes"; then
+ $1_LIBS=-l$2
+fi
+
+AC_SUBST($1_LIBS)
+])
+
+AC_DEFUN([TUXBOX_APPS_LIB_SYMBOL],[
+_TUXBOX_APPS_LIB_SYMBOL($1,$2,$3,ERROR)
+if test "$HAVE_$1" = "no"; then
+ AC_MSG_ERROR([could not find $2]);
+fi
+])
+
+AC_DEFUN([TUXBOX_APPS_LIB_CONFIG_SYMBOL],[
+_TUXBOX_APPS_LIB_SYMBOL($1,$2,$3,WARN)
+])
+
+AC_DEFUN([TUXBOX_APPS_GETTEXT],[
+AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1 &&
+ (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
+ :)
+AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+
+AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [$ac_dir/$ac_word --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 &&
+ (if $ac_dir/$ac_word --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
+ :)
+
+AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge,[$ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 2>&1],:)
+
+AC_MSG_CHECKING([whether NLS is requested])
+AC_ARG_ENABLE(nls,
+ [ --disable-nls do not use Native Language Support],
+ USE_NLS=$enableval, USE_NLS=yes)
+AC_MSG_RESULT($USE_NLS)
+AC_SUBST(USE_NLS)
+
+if test "$USE_NLS" = "yes"; then
+ AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc,[
+ AC_TRY_LINK([
+ #include <libintl.h>
+ #ifndef __GNU_GETTEXT_SUPPORTED_REVISION
+ #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1)
+ #endif
+ extern int _nl_msg_cat_cntr;
+ extern int *_nl_domain_bindings;
+ ],[
+ bindtextdomain ("", "");
+ return (int) gettext ("") + _nl_msg_cat_cntr + *_nl_domain_bindings;
+ ], gt_cv_func_gnugettext_libc=yes, gt_cv_func_gnugettext_libc=no
+ )]
+ )
+
+ if test "$gt_cv_func_gnugettext_libc" = "yes"; then
+ AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if translation of program messages to the user's native language is requested.])
+ gt_use_preinstalled_gnugettext=yes
+ else
+ USE_NLS=no
+ fi
+fi
+
+if test -f "$srcdir/po/LINGUAS"; then
+ ALL_LINGUAS=$(sed -e "/^#/d" "$srcdir/po/LINGUAS")
+fi
+
+POFILES=
+GMOFILES=
+UPDATEPOFILES=
+DUMMYPOFILES=
+for lang in $ALL_LINGUAS; do
+ POFILES="$POFILES $srcdirpre$lang.po"
+ GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
+ UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
+ DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
+done
+INST_LINGUAS=
+if test -n "$ALL_LINGUAS"; then
+ for presentlang in $ALL_LINGUAS; do
+ useit=no
+ if test -n "$LINGUAS"; then
+ desiredlanguages="$LINGUAS"
+ else
+ desiredlanguages="$ALL_LINGUAS"
+ fi
+ for desiredlang in $desiredlanguages; do
+ case "$desiredlang" in
+ "$presentlang"*) useit=yes;;
+ esac
+ done
+ if test $useit = yes; then
+ INST_LINGUAS="$INST_LINGUAS $presentlang"
+ fi
+ done
+fi
+CATALOGS=
+if test -n "$INST_LINGUAS"; then
+ for lang in $INST_LINGUAS; do
+ CATALOGS="$CATALOGS $lang.gmo"
+ done
+fi
+AC_SUBST(POFILES)
+AC_SUBST(GMOFILES)
+AC_SUBST(UPDATEPOFILES)
+AC_SUBST(DUMMYPOFILES)
+AC_SUBST(CATALOGS)
+])
+
+dnl backward compatiblity
+AC_DEFUN([AC_GNU_SOURCE],
+[AH_VERBATIM([_GNU_SOURCE],
+[/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif])dnl
+AC_BEFORE([$0], [AC_COMPILE_IFELSE])dnl
+AC_BEFORE([$0], [AC_RUN_IFELSE])dnl
+AC_DEFINE([_GNU_SOURCE])
+])
+
+AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+ [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])
+
+AC_DEFUN([AC_PYTHON_DEVEL],[
+ #
+ # should allow for checking of python version here...
+ #
+ if test $cross_compiling = "yes"; then
+ # Check for Python include path
+ AC_MSG_CHECKING([for Python include path])
+
+ # FIXME: yes, this is wrong. sorry about that. (tmbinc)
+ cross_PYTHON_VERSION=$PYTHON_VERSION
+ python_path=
+ for i in $CPPFLAGS ; do
+ p=`echo $i | sed "s,^-I,,"`
+ if test -f "$p/python$cross_PYTHON_VERSION/Python.h"; then
+ python_path="$p/python$cross_PYTHON_VERSION"
+ break
+ fi
+ done
+ AC_MSG_RESULT([$python_path])
+ if test -z "$python_path" ; then
+ AC_MSG_ERROR([cannot find Python include path])
+ fi
+ AC_SUBST([PYTHON_CPPFLAGS],[-I$python_path])
+
+ # Check for Python library path
+ AC_MSG_CHECKING([for Python library path])
+ python_path=
+ for i in $LDFLAGS; do
+ l=`echo $i | sed "s,^-L,,"`
+ python_path=`find $l -type f -name libpython$cross_PYTHON_VERSION.* -print | sed "1q"`
+ if test -n "$python_path" ; then
+ break
+ fi
+ done
+ python_path=`echo $python_path | sed "s,/libpython.*$,,"`
+ AC_MSG_RESULT([$python_path])
+ if test -z "$python_path" ; then
+ AC_MSG_ERROR([cannot find Python library path])
+ fi
+ AC_SUBST([PYTHON_LDFLAGS],["-L$python_path -lpython$cross_PYTHON_VERSION"])
+ #
+ python_site=`echo $python_path | sed "s/config/site-packages/"`
+ AC_SUBST([PYTHON_SITE_PKG],[$python_site])
+ else
+ AC_REQUIRE([AM_PATH_PYTHON])
+
+ # Check for Python include path
+ AC_MSG_CHECKING([for Python include path])
+ python_path=`echo $PYTHON | sed "s,/bin.*$,,"`
+ for i in "$python_path/include/python$PYTHON_VERSION/" "$python_path/include/python/" "$python_path/" ; do
+ python_path=`find $i -type f -name Python.h -print | sed "1q"`
+ if test -n "$python_path" ; then
+ break
+ fi
+ done
+ python_path=`echo $python_path | sed "s,/Python.h$,,"`
+ AC_MSG_RESULT([$python_path])
+ if test -z "$python_path" ; then
+ AC_MSG_ERROR([cannot find Python include path])
+ fi
+ AC_SUBST([PYTHON_CPPFLAGS],[-I$python_path])
+
+ # Check for Python library path
+ AC_MSG_CHECKING([for Python library path])
+ python_path=`echo $PYTHON | sed "s,/bin.*$,,"`
+ for i in "$python_path/lib/python$PYTHON_VERSION/config/" "$python_path/lib/python$PYTHON_VERSION/" "$python_path/lib/python/config/" "$python_path/lib/python/" "$python_path/" ; do
+ python_path=`find $i -type f -name libpython$PYTHON_VERSION.* -print | sed "1q"`
+ if test -n "$python_path" ; then
+ break
+ fi
+ done
+ python_path=`echo $python_path | sed "s,/libpython.*$,,"`
+ AC_MSG_RESULT([$python_path])
+ if test -z "$python_path" ; then
+ AC_MSG_ERROR([cannot find Python library path])
+ fi
+ AC_SUBST([PYTHON_LDFLAGS],["-L$python_path -lpython$PYTHON_VERSION"])
+ #
+ python_site=`echo $python_path | sed "s/config/site-packages/"`
+ AC_SUBST([PYTHON_SITE_PKG],[$python_site])
+ fi
+])
--- /dev/null
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <signal.h>
+#include "servicets.h"
+#include <lib/base/eerror.h>
+#include <lib/base/object.h>
+#include <lib/base/ebase.h>
+#include <servicets.h>
+#include <lib/service/service.h>
+#include <lib/base/init_num.h>
+#include <lib/base/init.h>
+#include <lib/dvb/decoder.h>
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+// eServiceFactoryTS
+
+eServiceFactoryTS::eServiceFactoryTS()
+{
+ ePtr<eServiceCenter> sc;
+
+ eServiceCenter::getPrivInstance(sc);
+ if (sc)
+ {
+ std::list<std::string> extensions;
+ sc->addServiceFactory(eServiceFactoryTS::id, this, extensions);
+ }
+
+ m_service_info = new eStaticServiceTSInfo();
+}
+
+eServiceFactoryTS::~eServiceFactoryTS()
+{
+ ePtr<eServiceCenter> sc;
+
+ eServiceCenter::getPrivInstance(sc);
+ if (sc)
+ sc->removeServiceFactory(eServiceFactoryTS::id);
+}
+
+DEFINE_REF(eServiceFactoryTS)
+
+ // iServiceHandler
+RESULT eServiceFactoryTS::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
+{
+ // check resources...
+ ptr = new eServiceTS(ref);
+ return 0;
+}
+
+RESULT eServiceFactoryTS::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
+{
+ ptr=0;
+ return -1;
+}
+
+RESULT eServiceFactoryTS::list(const eServiceReference &, ePtr<iListableService> &ptr)
+{
+ ptr=0;
+ return -1;
+}
+
+RESULT eServiceFactoryTS::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
+{
+ ptr = m_service_info;
+ return 0;
+}
+
+RESULT eServiceFactoryTS::offlineOperations(const eServiceReference &, ePtr<iServiceOfflineOperations> &ptr)
+{
+ ptr = 0;
+ return -1;
+}
+
+
+// eStaticServiceTSInfo
+DEFINE_REF(eStaticServiceTSInfo)
+
+eStaticServiceTSInfo::eStaticServiceTSInfo()
+{
+}
+
+RESULT eStaticServiceTSInfo::getName(const eServiceReference &ref, std::string &name)
+{
+ size_t last = ref.path.rfind('/');
+ if (last != std::string::npos)
+ name = ref.path.substr(last+1);
+ else
+ name = ref.path;
+ return 0;
+}
+
+int eStaticServiceTSInfo::getLength(const eServiceReference &ref)
+{
+ return -1;
+}
+
+// eServiceTS
+
+eServiceTS::eServiceTS(const eServiceReference &url): m_pump(eApp, 1)
+{
+ eDebug("ServiceTS construct!");
+ m_filename = url.path.c_str();
+ m_vpid = url.getData(0) == 0 ? 0x44 : url.getData(0);
+ m_apid = url.getData(1) == 0 ? 0x45 : url.getData(1);
+ m_state = stIdle;
+}
+
+eServiceTS::~eServiceTS()
+{
+ eDebug("ServiceTS destruct!");
+ if (m_state == stRunning)
+ stop();
+}
+
+DEFINE_REF(eServiceTS);
+
+size_t crop(char *buf)
+{
+ size_t len = strlen(buf) - 1;
+ while (len > 0 && (buf[len] == '\r' || buf[len] == '\n')) {
+ buf[len--] = '\0';
+ }
+ return len;
+}
+
+static int getline(char** pbuffer, size_t* pbufsize, int fd)
+{
+ size_t i = 0;
+ int rc;
+ while (true) {
+ if (i >= *pbufsize) {
+ char *newbuf = (char*)realloc(*pbuffer, (*pbufsize)+1024);
+ if (newbuf == NULL)
+ return -ENOMEM;
+ *pbuffer = newbuf;
+ *pbufsize = (*pbufsize)+1024;
+ }
+ rc = ::read(fd, (*pbuffer)+i, 1);
+ if (rc <= 0 || (*pbuffer)[i] == '\n')
+ {
+ (*pbuffer)[i] = '\0';
+ return rc <= 0 ? -1 : i;
+ }
+ if ((*pbuffer)[i] != '\r') i++;
+ }
+}
+
+int eServiceTS::openHttpConnection(std::string url)
+{
+ std::string host;
+ int port = 80;
+ std::string uri;
+
+ int slash = url.find("/", 7);
+ if (slash > 0) {
+ host = url.substr(7, slash-7);
+ uri = url.substr(slash, url.length()-slash);
+ } else {
+ host = url.substr(7, url.length()-7);
+ uri = "";
+ }
+ int dp = host.find(":");
+ if (dp == 0) {
+ port = atoi(host.substr(1, host.length()-1).c_str());
+ host = "localhost";
+ } else if (dp > 0) {
+ port = atoi(host.substr(dp+1, host.length()-dp-1).c_str());
+ host = host.substr(0, dp);
+ }
+
+ struct hostent* h = gethostbyname(host.c_str());
+ if (h == NULL || h->h_addr_list == NULL)
+ return -1;
+ int fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (fd == -1)
+ return -1;
+
+ struct sockaddr_in addr;
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = *((in_addr_t*)h->h_addr_list[0]);
+ addr.sin_port = htons(port);
+
+ eDebug("connecting to %s", url.c_str());
+
+ if (connect(fd, (sockaddr*)&addr, sizeof(addr)) == -1) {
+ std::string msg = "connect failed for: " + url;
+ eDebug(msg.c_str());
+ return -1;
+ }
+
+ std::string request = "GET ";
+ request.append(uri).append(" HTTP/1.1\n");
+ request.append("Host: ").append(host).append("\n");
+ request.append("Accept: */*\n");
+ request.append("Connection: close\n");
+ request.append("\n");
+ //eDebug(request.c_str());
+ write(fd, request.c_str(), request.length());
+
+ int rc;
+ size_t buflen = 1000;
+ char* linebuf = (char*)malloc(1000);
+
+ rc = getline(&linebuf, &buflen, fd);
+ //eDebug("RECV(%d): %s", rc, linebuf);
+ if (rc <= 0)
+ {
+ close(fd);
+ free(linebuf);
+ return -1;
+ }
+
+ char proto[100];
+ int statuscode = 0;
+ char statusmsg[100];
+ rc = sscanf(linebuf, "%99s %d %99s", proto, &statuscode, statusmsg);
+ if (rc != 3 || statuscode != 200) {
+ eDebug("wrong response: \"200 OK\" expected.");
+ free(linebuf);
+ close(fd);
+ return -1;
+ }
+ eDebug("proto=%s, code=%d, msg=%s", proto, statuscode, statusmsg);
+ while (rc > 0)
+ {
+ rc = getline(&linebuf, &buflen, fd);
+ //eDebug("RECV(%d): %s", rc, linebuf);
+ }
+ free(linebuf);
+
+ return fd;
+}
+
+RESULT eServiceTS::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
+{
+ connection = new eConnection((iPlayableService*)this, m_event.connect(event));
+ return 0;
+}
+
+RESULT eServiceTS::start()
+{
+ ePtr<eDVBResourceManager> rmgr;
+ eDVBResourceManager::getInstance(rmgr);
+ if (rmgr->allocateDemux(NULL, m_decodedemux, iDVBChannel::capDecode) != 0) {
+ eDebug("Cannot allocate decode-demux");
+ return 1;
+ }
+ if (m_decodedemux->get().getMPEGDecoder(m_decoder, 1) != 0) {
+ eDebug("Cannot allocate MPEGDecoder");
+ return 1;
+ }
+ m_decodedemux->get().setSourcePVR(0);
+ m_decoder->setVideoPID(m_vpid, eDVBVideo::MPEG2);
+ m_decoder->setAudioPID(m_apid, eDVBAudio::aMPEG);
+ m_streamthread = new eStreamThread();
+ CONNECT(m_streamthread->m_event, eServiceTS::recv_event);
+ m_decoder->freeze(0);
+ m_decoder->preroll();
+ if (unpause() != 0) return -1;
+ m_state = stRunning;
+ m_event(this, evStart);
+ return 0;
+}
+
+RESULT eServiceTS::stop()
+{
+ if (m_state != stRunning)
+ return -1;
+ printf("TS: %s stop\n", m_filename.c_str());
+ m_streamthread->stop();
+ m_decodedemux->get().flush();
+ m_state = stStopped;
+ return 0;
+}
+
+void eServiceTS::recv_event(int evt)
+{
+ eDebug("eServiceTS::recv_event: %d", evt);
+ switch (evt) {
+ case eStreamThread::evtEOS:
+ m_decodedemux->get().flush();
+ m_state = stStopped;
+ m_event((iPlayableService*)this, evEOF);
+ break;
+ case eStreamThread::evtReadError:
+ case eStreamThread::evtWriteError:
+ m_decoder->freeze(0);
+ m_state = stStopped;
+ m_event((iPlayableService*)this, evEOF);
+ }
+}
+
+RESULT eServiceTS::setTarget(int target)
+{
+ return -1;
+}
+
+RESULT eServiceTS::pause(ePtr<iPauseableService> &ptr)
+{
+ ptr=this;
+ return 0;
+}
+
+RESULT eServiceTS::setSlowMotion(int ratio)
+{
+ return -1;
+}
+
+RESULT eServiceTS::setFastForward(int ratio)
+{
+ return -1;
+}
+
+ // iPausableService
+RESULT eServiceTS::pause()
+{
+ m_streamthread->stop();
+ m_decoder->freeze(0);
+ return 0;
+}
+
+RESULT eServiceTS::unpause()
+{
+ int is_streaming = !strncmp(m_filename.c_str(), "http://", 7);
+ int srcfd = -1;
+ if (is_streaming) {
+ srcfd = openHttpConnection(m_filename);
+ } else {
+ srcfd = ::open(m_filename.c_str(), O_RDONLY);
+ }
+ if (srcfd < 0) {
+ eDebug("Cannot open source stream: %s", m_filename.c_str());
+ return 1;
+ }
+
+ int destfd = ::open("/dev/misc/pvr", O_WRONLY);
+ if (destfd < 0) {
+ eDebug("Cannot open source stream: %s", m_filename.c_str());
+ ::close(srcfd);
+ return 1;
+ }
+ m_decodedemux->get().flush();
+ m_streamthread->start(srcfd, destfd);
+ // let the video buffer fill up a bit
+ usleep(200*1000);
+ m_decoder->unfreeze();
+ return 0;
+}
+
+ /* iSeekableService */
+RESULT eServiceTS::seek(ePtr<iSeekableService> &ptr)
+{
+ ptr = this;
+ return 0;
+}
+
+RESULT eServiceTS::getLength(pts_t &pts)
+{
+ return 0;
+}
+
+RESULT eServiceTS::seekTo(pts_t to)
+{
+ return 0;
+}
+
+RESULT eServiceTS::seekRelative(int direction, pts_t to)
+{
+ return 0;
+}
+
+RESULT eServiceTS::getPlayPosition(pts_t &pts)
+{
+ return 0;
+}
+
+RESULT eServiceTS::setTrickmode(int trick)
+{
+ return -1;
+}
+
+
+RESULT eServiceTS::isCurrentlySeekable()
+{
+ return 1;
+}
+
+RESULT eServiceTS::info(ePtr<iServiceInformation>&i)
+{
+ i = this;
+ return 0;
+}
+
+RESULT eServiceTS::getName(std::string &name)
+{
+ name = m_filename;
+ size_t n = name.rfind('/');
+ if (n != std::string::npos)
+ name = name.substr(n + 1);
+ return 0;
+}
+
+int eServiceTS::getInfo(int w)
+{
+ return resNA;
+}
+
+std::string eServiceTS::getInfoString(int w)
+{
+ return "";
+}
+
+DEFINE_REF(eStreamThread)
+
+eStreamThread::eStreamThread(): m_messagepump(eApp, 0) {
+ CONNECT(m_messagepump.recv_msg, eStreamThread::recvEvent);
+}
+eStreamThread::~eStreamThread() {
+}
+
+void eStreamThread::start(int srcfd, int destfd) {
+ m_srcfd = srcfd;
+ m_destfd = destfd;
+ m_stop = false;
+ run(IOPRIO_CLASS_RT);
+}
+void eStreamThread::stop() {
+ m_stop = true;
+ kill();
+}
+
+void eStreamThread::recvEvent(const int &evt)
+{
+ m_event(evt);
+}
+
+void eStreamThread::thread() {
+ const int bufsize = 60000;
+ unsigned char buf[bufsize];
+ bool eof = false;
+ fd_set rfds;
+ fd_set wfds;
+ struct timeval timeout;
+ int rc,r,w,maxfd;
+
+ r = w = 0;
+ hasStarted();
+ eDebug("eStreamThread started");
+ while (!m_stop) {
+ pthread_testcancel();
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ maxfd = 0;
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ if (r < bufsize) {
+ FD_SET(m_srcfd, &rfds);
+ maxfd = MAX(maxfd, m_srcfd);
+ }
+ if (w < r) {
+ FD_SET(m_destfd, &wfds);
+ maxfd = MAX(maxfd, m_destfd);
+ }
+ rc = select(maxfd+1, &rfds, &wfds, NULL, &timeout);
+ if (rc == 0) {
+ eDebug("eStreamThread::thread: timeout!");
+ continue;
+ }
+ if (rc < 0) {
+ eDebug("eStreamThread::thread: error in select (%d)", errno);
+ break;
+ }
+ if (FD_ISSET(m_srcfd, &rfds)) {
+ rc = ::read(m_srcfd, buf+r, bufsize - r);
+ if (rc < 0) {
+ eDebug("eStreamThread::thread: error in read (%d)", errno);
+ m_messagepump.send(evtReadError);
+ break;
+ } else if (rc == 0) {
+ eof = true;
+ } else {
+ r += rc;
+ if (r == bufsize) eDebug("eStreamThread::thread: buffer full");
+ }
+ }
+ if (FD_ISSET(m_destfd, &wfds) && (w < r)) {
+ rc = ::write(m_destfd, buf+w, r-w);
+ if (rc < 0) {
+ eDebug("eStreamThread::thread: error in write (%d)", errno);
+ m_messagepump.send(evtWriteError);
+ break;
+ }
+ w += rc;
+ //eDebug("eStreamThread::thread: buffer r=%d w=%d",r,w);
+ if (w == r) w = r = 0;
+ }
+ if (eof && (r==w)) {
+ ::close(m_destfd);
+ m_destfd = -1;
+ ::close(m_srcfd);
+ m_srcfd = -1;
+ m_messagepump.send(evtEOS);
+ break;
+ }
+ }
+ eDebug("eStreamThread end");
+}
+
+void eStreamThread::thread_finished() {
+ if (m_srcfd >= 0) ::close(m_srcfd);
+ if (m_destfd >= 0) ::close(m_destfd);
+ eDebug("eStreamThread closed");
+}
+
+eAutoInitPtr<eServiceFactoryTS> init_eServiceFactoryTS(eAutoInitNumbers::service+1, "eServiceFactoryTS");
+
+PyMODINIT_FUNC
+initservicets(void)
+{
+ Py_InitModule("servicets", NULL);
+}
--- /dev/null
+#ifndef __servicets_h
+#define __servicets_h
+
+#include <lib/base/ioprio.h>
+#include <lib/base/message.h>
+#include <lib/service/iservice.h>
+#include <lib/dvb/dvb.h>
+
+class eStaticServiceTSInfo;
+
+class eServiceFactoryTS: public iServiceHandler
+{
+DECLARE_REF(eServiceFactoryTS);
+public:
+ eServiceFactoryTS();
+ virtual ~eServiceFactoryTS();
+ enum { id = 0x1002 };
+
+ // 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);
+private:
+ ePtr<eStaticServiceTSInfo> m_service_info;
+};
+
+class eStaticServiceTSInfo: public iStaticServiceInformation
+{
+ DECLARE_REF(eStaticServiceTSInfo);
+ friend class eServiceFactoryTS;
+ eStaticServiceTSInfo();
+public:
+ RESULT getName(const eServiceReference &ref, std::string &name);
+ int getLength(const eServiceReference &ref);
+};
+
+class eStreamThread;
+
+class eServiceTS: public iPlayableService, public iPauseableService,
+ public iServiceInformation, public iSeekableService, public Object
+{
+DECLARE_REF(eServiceTS);
+public:
+ virtual ~eServiceTS();
+
+ // iPlayableService
+ RESULT connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection);
+ RESULT start();
+ RESULT stop();
+ RESULT setTarget(int target);
+
+ RESULT pause(ePtr<iPauseableService> &ptr);
+ RESULT setSlowMotion(int ratio);
+ RESULT setFastForward(int ratio);
+
+ RESULT seek(ePtr<iSeekableService> &ptr);
+
+ // not implemented (yet)
+ RESULT audioChannel(ePtr<iAudioChannelSelection> &ptr) { ptr = 0; return -1; }
+ RESULT audioTracks(ePtr<iAudioTrackSelection> &ptr) { ptr = 0; return -1; }
+ RESULT frontendInfo(ePtr<iFrontendInformation> &ptr) { ptr = 0; return -1; }
+ RESULT subServices(ePtr<iSubserviceList> &ptr) { ptr = 0; return -1; }
+ RESULT timeshift(ePtr<iTimeshiftService> &ptr) { ptr = 0; return -1; }
+ RESULT cueSheet(ePtr<iCueSheet> &ptr) { ptr = 0; return -1; }
+ RESULT subtitle(ePtr<iSubtitleOutput> &ptr) { ptr = 0; return -1; }
+ RESULT audioDelay(ePtr<iAudioDelay> &ptr) { ptr = 0; return -1; }
+ RESULT rdsDecoder(ePtr<iRdsDecoder> &ptr) { ptr = 0; return -1; }
+ RESULT stream(ePtr<iStreamableService> &ptr) { ptr = 0; return -1; }
+ RESULT keys(ePtr<iServiceKeys> &ptr) { ptr = 0; return -1; }
+ // iPausableService
+ RESULT pause();
+ RESULT unpause();
+
+ RESULT info(ePtr<iServiceInformation>&);
+
+ // iSeekableService
+ RESULT getLength(pts_t &SWIG_OUTPUT);
+ RESULT seekTo(pts_t to);
+ RESULT seekRelative(int direction, pts_t to);
+ RESULT getPlayPosition(pts_t &SWIG_OUTPUT);
+ RESULT setTrickmode(int trick);
+ RESULT isCurrentlySeekable();
+
+ // iServiceInformation
+ RESULT getName(std::string &name);
+ int getInfo(int w);
+ std::string getInfoString(int w);
+private:
+ friend class eServiceFactoryTS;
+ std::string m_filename;
+ int m_vpid, m_apid;
+ int m_srcfd, m_destfd;
+ ePtr<eDVBAllocatedDemux> m_decodedemux;
+ ePtr<iTSMPEGDecoder> m_decoder;
+ ePtr<eStreamThread> m_streamthread;
+
+ eServiceTS(const eServiceReference &url);
+ int openHttpConnection(std::string url);
+
+ Signal2<void,iPlayableService*,int> m_event;
+ enum
+ {
+ stIdle, stRunning, stStopped
+ };
+ int m_state;
+ eFixedMessagePump<int> m_pump;
+ void recv_event(int evt);
+};
+
+class eStreamThread: public eThread, public Object {
+DECLARE_REF(eStreamThread);
+public:
+ eStreamThread();
+ virtual ~eStreamThread();
+ void start(int srcfd, int destfd);
+ void stop();
+
+ virtual void thread();
+ virtual void thread_finished();
+
+ enum { evtEOS, evtReadError, evtWriteError, evtUser };
+ Signal1<void,int> m_event;
+private:
+ bool m_stop;
+ int m_srcfd, m_destfd;
+ eFixedMessagePump<int> m_messagepump;
+ void recvEvent(const int &evt);
+};
+
+#endif
+
+