From: Felix Domke Date: Fri, 17 Oct 2003 15:36:42 +0000 (+0000) Subject: import of enigma2 X-Git-Tag: 2.6.0~5982 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5 import of enigma2 --- d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..e69de29b diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/DEADJOE b/DEADJOE new file mode 100644 index 00000000..e69de29b diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..157daf03 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,4 @@ +AUTOMAKE_OPTIONS = gnu + +SUBDIRS = lib main + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/README b/README new file mode 100644 index 00000000..e69de29b diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000..e69de29b diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..d646011e --- /dev/null +++ b/autogen.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +package="tuxbox-enigma" + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +cd "$srcdir" +DIE=0 + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile $package." + echo "Download the appropriate package for your system," + echo "or get the source from one of the GNU ftp sites" + echo "listed in http://www.gnu.org/order/ftp.html" + DIE=1 +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile $package." + echo "Download the appropriate package for your system," + echo "or get the source from one of the GNU ftp sites" + echo "listed in http://www.gnu.org/order/ftp.html" + DIE=1 +} + +(libtool --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have libtool installed to compile $package." + echo "Download the appropriate package for your system," + echo "or get the source from one of the GNU ftp sites" + echo "listed in http://www.gnu.org/order/ftp.html" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +if [ ! -e acinclude.m4 ]; then + for i in .. ../.. ../../..; do + if [ -e `pwd`/$i/acinclude.m4 ]; then + ln -s `pwd`/$i/acinclude.m4 . + fi + done +fi + +echo "Generating configuration files for $package, please wait...." + +echo " aclocal" +aclocal +echo " libtoolize --automake" +libtoolize --automake +echo " autoconf" +autoconf +echo " autoheader" +autoheader +echo " automake --add-missing" +automake --add-missing + diff --git a/autom4te.cache/output.0 b/autom4te.cache/output.0 new file mode 100644 index 00000000..e69de29b diff --git a/autom4te.cache/requests b/autom4te.cache/requests new file mode 100644 index 00000000..e69de29b diff --git a/autom4te.cache/traces.0 b/autom4te.cache/traces.0 new file mode 100644 index 00000000..e69de29b diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000..3224a09a --- /dev/null +++ b/config.h.in @@ -0,0 +1,97 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* where to find the config files */ +#undef CONFIGDIR + +/* where to find data like icons */ +#undef DATADIR + +/* Enable debug messages */ +#undef DEBUG + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* where to find the fonts */ +#undef FONTDIR + +/* where games data is stored */ +#undef GAMESDIR + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_DVB_VERSION_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OST_DMX_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* where to find the internal libs */ +#undef LIBDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* where to find the plugins */ +#undef PLUGINDIR + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* where to find the ucodes (firmware) */ +#undef UCODEDIR + +/* Version number of package */ +#undef VERSION + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES diff --git a/configure b/configure new file mode 100755 index 00000000..e69de29b diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..54d97899 --- /dev/null +++ b/configure.ac @@ -0,0 +1,42 @@ +AC_INIT(tuxbox-enigma,0.0.1) +AM_INIT_AUTOMAKE(tuxbox-enigma,0.0.1) + +TUXBOX_APPS +TUXBOX_APPS_DIRECTORY + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_RANLIB + +TUXBOX_APPS_DVB +TUXBOX_APPS_DRIVER + +TUXBOX_APPS_LIB_CONFIG(FREETYPE,freetype-config) +TUXBOX_APPS_LIB_PKGCONFIG(FRIBIDI,fribidi) +TUXBOX_APPS_LIB_PKGCONFIG(ID3TAG,id3tag) +TUXBOX_APPS_LIB_PKGCONFIG(MAD,mad) +TUXBOX_APPS_LIB_PKGCONFIG(MD5SUM,tuxbox-md5sum) +TUXBOX_APPS_LIB_PKGCONFIG(PLUGINS,tuxbox-plugins) +TUXBOX_APPS_LIB_PKGCONFIG(PNG,libpng) +TUXBOX_APPS_LIB_PKGCONFIG(SIGC,sigc++-1.2) +TUXBOX_APPS_LIB_PKGCONFIG(XMLTREE,tuxbox-xmltree) + +CPPFLAGS="$CPPFLAGS $FREETYPE_CFLAGS $FRIBIDI_CFLAGS $ID3TAG_CFLAGS $MAD_CFLAGS $MD5SUM_CFLAGS $PLUGINS_CFLAGS $PNG_CFLAGS $SIGC_CFLAGS $XMLTREE_CFLAGS" +CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions" + +TUXBOX_APPS_GETTEXT + +AC_OUTPUT([ +Makefile +lib/Makefile +lib/base/Makefile +lib/driver/Makefile +lib/dvb/Makefile +lib/dvb_si/Makefile +lib/gdi/Makefile +lib/gui/Makefile +lib/network/Makefile +lib/service/Makefile +main/Makefile +]) + diff --git a/debug b/debug new file mode 100755 index 00000000..d9b87717 --- /dev/null +++ b/debug @@ -0,0 +1,5 @@ +#!/bin/sh + +powerpc-linux-gdb /dbox2/cdkroot/bin/enigma2 -x debug.gdb + + diff --git a/debug.gdb b/debug.gdb new file mode 100644 index 00000000..f2b4fca4 --- /dev/null +++ b/debug.gdb @@ -0,0 +1,3 @@ +set solib-absolute-prefix /dbox2/cdkroot +target remote 10.0.0.82:1234 +continue diff --git a/include/connection.h b/include/connection.h new file mode 100644 index 00000000..3ccaec19 --- /dev/null +++ b/include/connection.h @@ -0,0 +1,17 @@ +#ifndef __connection_h +#define __connection_h + +#include +#include + +class eConnection: public virtual iObject, public Connection +{ + int ref; +public: +DEFINE_REF(eConnection); +public: + eConnection(const Connection &conn): Connection(conn), ref(0) { }; + virtual ~eConnection() { disconnect(); } +}; + +#endif diff --git a/include/libsig_comp.h b/include/libsig_comp.h new file mode 100644 index 00000000..83550ed5 --- /dev/null +++ b/include/libsig_comp.h @@ -0,0 +1,33 @@ +#ifndef __LIBSIG_COMP_H +#define __LIBSIG_COMP_H + +#include +#include + +#ifdef SIGC_CXX_NAMESPACES +using namespace SigC; +#endif + +#define CONNECT(SENDER, EMPFAENGER) SENDER.connect(slot(*this, &EMPFAENGER)) +// use this Makro to connect with a method +// void bla::foo(int x); +// to an +// Signal testSig; +// +// CONNECT(testSig, bla::foo); +// signal and method (slot) must have the same signature + +#define CONNECT_1_0(SENDER, EMPFAENGER, PARAM) SENDER.connect( bind( slot(*this, &EMPFAENGER) ,PARAM ) ) +// use this for connect with a method +// void bla::foo(int); +// to an +// Signal0 testSig; +// CONNECT_1_0(testSig, bla:foo, 0); +// here the signal has no parameter, but the slot have an int +// the last parameter of the CONNECT_1_0 makro is the value that given to the paramater of the Slot method + +#define CONNECT_2_0(SENDER, EMPFAENGER, PARAM1, PARAM2) SENDER.connect( bind( slot(*this, &EMPFAENGER) ,PARAM1, PARAM2 ) ) + +#define CONNECT_2_1(SENDER, EMPFAENGER, PARAM) SENDER.connect( bind( slot(*this, &EMPFAENGER) ,PARAM ) ) + +#endif // __LIBSIG_COMP_H diff --git a/lib/DEADJOE b/lib/DEADJOE new file mode 100644 index 00000000..e69de29b diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 00000000..7811ca1f --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = base dvb dvb_si gdi gui network service driver + + diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am new file mode 100644 index 00000000..3e695a39 --- /dev/null +++ b/lib/base/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = \ + -I$(top_srcdir)/include + +noinst_LIBRARIES = libenigma_base.a + +libenigma_base_a_SOURCES = \ + buffer.cpp console.cpp ebase.cpp econfig.cpp eerror.cpp elock.cpp \ + estring.cpp init.cpp message.cpp nconfig.cpp nxml.cpp thread.cpp \ + smartptr.cpp diff --git a/lib/base/Makefile.in b/lib/base/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/lib/base/a b/lib/base/a new file mode 100644 index 00000000..e69de29b diff --git a/lib/base/buffer.cpp b/lib/base/buffer.cpp new file mode 100644 index 00000000..07e9d7f1 --- /dev/null +++ b/lib/base/buffer.cpp @@ -0,0 +1,196 @@ +#include +#include +#include +#include +#include + +void eIOBuffer::removeblock() +{ + ASSERT(!buffer.empty()); + eIOBufferData &b=buffer.front(); + delete[] b.data; + buffer.pop_front(); + ptr=0; +} + +eIOBuffer::eIOBufferData &eIOBuffer::addblock() +{ + eIOBufferData s; + s.data=new __u8[allocationsize]; + s.len=0; + buffer.push_back(s); + return buffer.back(); +} + +eIOBuffer::~eIOBuffer() +{ + clear(); +} + +void eIOBuffer::clear() +{ + while (!buffer.empty()) + removeblock(); +} + +int eIOBuffer::size() const +{ + int total=0; + for (std::list::const_iterator i(buffer.begin()); i != buffer.end(); ++i) + total+=i->len; + total-=ptr; + return total; +} + +int eIOBuffer::empty() const +{ + return buffer.empty(); +} + +int eIOBuffer::peek(void *dest, int len) const +{ + __u8 *dst=(__u8*)dest; + std::list::const_iterator i(buffer.begin()); + int p=ptr; + int written=0; + while (len) + { + if (i == buffer.end()) + break; + int tc=i->len-p; + if (tc > len) + tc = len; + + memcpy(dst, i->data+p, tc); + dst+=tc; + written+=tc; + + ++i; + p=0; + + len-=tc; + } + return written; +} + +void eIOBuffer::skip(int len) +{ + while (len) + { + ASSERT(! buffer.empty()); + int tn=len; + if (tn > (buffer.front().len-ptr)) + tn=buffer.front().len-ptr; + + ptr+=tn; + if (ptr == buffer.front().len) + removeblock(); + len-=tn; + } +} + +int eIOBuffer::read(void *dest, int len) +{ + __u8 *dst=(__u8*)dest; + len=peek(dst, len); + skip(len); + return len; +} + +void eIOBuffer::write(const void *source, int len) +{ + const __u8 *src=(const __u8*)source; + while (len) + { + int tc=len; + if (buffer.empty() || (allocationsize == buffer.back().len)) + addblock(); + if (tc > allocationsize-buffer.back().len) + tc=allocationsize-buffer.back().len; + memcpy(buffer.back().data+buffer.back().len, src, tc); + src+=tc; + buffer.back().len+=tc; + len-=tc; + } +} + +int eIOBuffer::fromfile(int fd, int len) +{ + int re=0; + while (len) + { + int tc=len; + int r; + if (buffer.empty() || (allocationsize == buffer.back().len)) + addblock(); + if (tc > allocationsize-buffer.back().len) + tc=allocationsize-buffer.back().len; + r=::read(fd, buffer.back().data+buffer.back().len, tc); + buffer.back().len+=r; + len-=r; + if (r < 0) + { + if (errno != EWOULDBLOCK) + eDebug("read: %m"); + r=0; + } + re+=r; + if (r != tc) + break; + } + return re; +} + +int eIOBuffer::tofile(int fd, int len) +{ + int written=0; + int w; + while (len && !buffer.empty()) + { + if (buffer.begin() == buffer.end()) + break; + int tc=buffer.front().len-ptr; + if (tc > len) + tc = len; + + w=::write(fd, buffer.front().data+ptr, tc); + if (w < 0) + { + if (errno != EWOULDBLOCK) + eDebug("write: %m"); + w=0; + } + ptr+=w; + if (ptr == buffer.front().len) + removeblock(); + written+=w; + + len-=w; + if (tc != w) + break; + } + return written; +} + +int eIOBuffer::searchchr(char ch) const +{ + std::list::const_iterator i(buffer.begin()); + int p=ptr; + int c=0; + while (1) + { + if (i == buffer.end()) + break; + while (p < i->len) + { + if (i->data[p] == ch) + return c; + else + c++, p++; + } + ++i; + p=0; + } + return -1; +} + diff --git a/lib/base/buffer.h b/lib/base/buffer.h new file mode 100644 index 00000000..9108ba8b --- /dev/null +++ b/lib/base/buffer.h @@ -0,0 +1,40 @@ +#ifndef __src_lib_base_buffer_h +#define __src_lib_base_buffer_h + +#include +#include + +/** + * IO buffer. + */ +class eIOBuffer +{ + int allocationsize; + struct eIOBufferData + { + __u8 *data; + int len; + }; + std::list buffer; + void removeblock(); + eIOBufferData &addblock(); + int ptr; +public: + eIOBuffer(int allocationsize): allocationsize(allocationsize), ptr(0) + { + } + ~eIOBuffer(); + int size() const; + int empty() const; + void clear(); + int peek(void *dest, int len) const; + void skip(int len); + int read(void *dest, int len); + void write(const void *source, int len); + int fromfile(int fd, int len); + int tofile(int fd, int len); + + int searchchr(char ch) const; +}; + +#endif diff --git a/lib/base/console.cpp b/lib/base/console.cpp new file mode 100644 index 00000000..2609582f --- /dev/null +++ b/lib/base/console.cpp @@ -0,0 +1,248 @@ +/* + * console.cpp + * + * Copyright (C) 2002 Felix Domke + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: console.cpp,v 1.1 2003-10-17 15:35:47 tmbinc Exp $ + */ + +#include + +#include +#include // for statfs +#include +#include +#include + +int bidirpipe(int pfd[], char *cmd , char *argv[]) +{ + int pfdin[2]; /* from child to parent */ + int pfdout[2]; /* from parent to child */ + int pfderr[2]; /* stderr from child to parent */ + int pid; /* child's pid */ + + if ( pipe(pfdin) == -1 || pipe(pfdout) == -1 || pipe(pfderr) == -1) + return(-1); + + if ( ( pid = fork() ) == -1 ) + return(-1); + else if (pid == 0) /* child process */ + { + if ( close(0) == -1 || close(1) == -1 || close(2) == -1 ) + _exit(0); + + if (dup(pfdout[0]) != 0 || dup(pfdin[1]) != 1 || dup(pfderr[1]) != 2 ) + _exit(0); + + if (close(pfdout[0]) == -1 || close(pfdout[1]) == -1 || + close(pfdin[0]) == -1 || close(pfdin[1]) == -1 || + close(pfderr[0]) == -1 || close(pfderr[1]) == -1 ) + _exit(0); + + execv(cmd,argv); + _exit(0); + } + if (close(pfdout[0]) == -1 || close(pfdin[1]) == -1 || close(pfderr[1]) == -1) + return(-1); + + pfd[0] = pfdin[0]; + pfd[1] = pfdout[1]; + pfd[2] = pfderr[0]; + + return(pid); +} + +eConsoleAppContainer::eConsoleAppContainer( const eString &cmd ) +:pid(-1), killstate(0), outbuf(0) +{ +// eDebug("cmd = %s", cmd.c_str() ); + memset(fd, 0, sizeof(fd) ); + int cnt=2; // path to app + terminated 0 + eString str(cmd?cmd:""); + + while( str.length() && str[0] == ' ' ) // kill spaces at beginning + str = str.mid(1); + + while( str.length() && str[str.length()-1] == ' ' ) // kill spaces at the end + str = str.left( str.length() - 1 ); + + if (!str.length()) + return; + + unsigned int idx=0; + eString path = str.left( (idx = str.find(' ')) != eString::npos ? idx : str.length() ); +// eDebug("path = %s", path.c_str() ); + + eString cmds = str.mid( path.length()+1 ); +// eDebug("cmds = %s", cmds.c_str() ); + + idx = 0; + while ( (idx = cmds.find(' ',idx) ) != eString::npos ) // count args + { + cnt++; + idx++; + } + +// eDebug("idx = %d, %d counted spaces", idx, cnt-2); + + if ( cmds.length() ) + { + cnt++; +// eDebug("increase cnt"); + } + +// eDebug("%d args", cnt-2); + char **argv = new char*[cnt]; // min two args... path and terminating 0 + argv[0] = new char[ path.length() ]; + strcpy( argv[0], path.c_str() ); + argv[cnt-1] = 0; // set terminating null + + if ( cnt > 2 ) // more then default args? + { + cnt=1; // do not overwrite path in argv[0] + + while ( (idx = cmds.find(' ')) != eString::npos ) // parse all args.. + { + argv[cnt] = new char[ idx ]; +// eDebug("idx=%d, arg = %s", idx, cmds.left(idx).c_str() ); + strcpy( argv[cnt++], cmds.left( idx ).c_str() ); + cmds = cmds.mid(idx+1); +// eDebug("str = %s", cmds.c_str() ); + } + // store the last arg + argv[cnt] = new char[ cmds.length() ]; + strcpy( argv[cnt], cmds.c_str() ); + } + + // get one read ,one write and the err pipe to the prog.. + + if ( (pid = bidirpipe(fd, argv[0], argv)) == -1 ) + { + while ( cnt-- > 0 ) + delete [] argv[cnt]; + delete [] argv; + return; + } + + while ( cnt-- > 0 ) // release heap memory + delete [] argv[cnt]; + delete [] argv; + + eDebug("pipe in = %d, out = %d, err = %d", fd[0], fd[1], fd[2]); + + in = new eSocketNotifier(eApp, fd[0], 19 ); // 19 = POLLIN, POLLPRI, POLLHUP + out = new eSocketNotifier(eApp, fd[1], eSocketNotifier::Write); // POLLOUT + err = new eSocketNotifier(eApp, fd[2], 19 ); // 19 = POLLIN, POLLPRI, POLLHUP + CONNECT(in->activated, eConsoleAppContainer::readyRead); + CONNECT(out->activated, eConsoleAppContainer::readyWrite); + CONNECT(err->activated, eConsoleAppContainer::readyErrRead); + signal(SIGCHLD, SIG_IGN); // no zombie when child killed +} + +eConsoleAppContainer::~eConsoleAppContainer() +{ + if ( running() ) + { + killstate=-1; + kill(); + } + if ( outbuf ) + delete [] outbuf; +} + +void eConsoleAppContainer::kill() +{ + killstate=-1; + system( eString().sprintf("kill %d", pid).c_str() ); + eDebug("user kill console App"); +} + +void eConsoleAppContainer::closePipes() +{ + in->stop(); + out->stop(); + err->stop(); + ::close(fd[0]); + fd[0]=0; + ::close(fd[1]); + fd[1]=0; + ::close(fd[2]); + fd[2]=0; + eDebug("pipes closed"); +} + +void eConsoleAppContainer::readyRead(int what) +{ + if (what & POLLPRI|POLLIN) + { + eDebug("what = %d"); + char buf[2048]; + int readed = read(fd[0], buf, 2048); + eDebug("%d bytes read", readed); + if ( readed != -1 && readed ) + /*emit*/ dataAvail( eString( buf ) ); + else if (readed == -1) + eDebug("readerror %d", errno); + } + if (what & eSocketNotifier::Hungup) + { + eDebug("child has terminated"); + closePipes(); + /*emit*/ appClosed(killstate); + } +} + +void eConsoleAppContainer::readyErrRead(int what) +{ + if (what & POLLPRI|POLLIN) + { + eDebug("what = %d"); + char buf[2048]; + int readed = read(fd[2], buf, 2048); + eDebug("%d bytes read", readed); + if ( readed != -1 && readed ) + /*emit*/ dataAvail( eString( buf ) ); + else if (readed == -1) + eDebug("readerror %d", errno); + } +} + +void eConsoleAppContainer::write( const eString & str ) +{ + outbuf = new char[ str.length()]; + strcpy( outbuf, str.c_str() ); +} + +void eConsoleAppContainer::readyWrite(int what) +{ + if (what == 4 && outbuf) + { + if ( ::write( fd[1], outbuf, strlen(outbuf) ) != (int) strlen(outbuf) ) + { + /* emit */ dataSent(-1); + eDebug("writeError"); + } + else + { + /* emit */ dataSent(0); + eDebug("write ok"); + } + + delete outbuf; + outbuf=0; + } +} diff --git a/lib/base/console.h b/lib/base/console.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/base/ebase.cpp b/lib/base/ebase.cpp new file mode 100644 index 00000000..3babc2eb --- /dev/null +++ b/lib/base/ebase.cpp @@ -0,0 +1,206 @@ +#include + +#include +#include + +#include + +eSocketNotifier::eSocketNotifier(eMainloop *context, int fd, int requested, bool startnow): context(*context), fd(fd), state(0), requested(requested) +{ + if (startnow) + start(); +} + +eSocketNotifier::~eSocketNotifier() +{ + stop(); +} + +void eSocketNotifier::start() +{ + if (state) + stop(); + + context.addSocketNotifier(this); + state=1; +} + +void eSocketNotifier::stop() +{ + if (state) + context.removeSocketNotifier(this); + + state=0; +} + + // timer +void eTimer::start(long msek, bool singleShot) +{ + if (bActive) + stop(); + + bActive = true; + bSingleShot = singleShot; + interval = msek; + gettimeofday(&nextActivation, 0); +// eDebug("this = %p\nnow sec = %d, usec = %d\nadd %d msec", this, nextActivation.tv_sec, nextActivation.tv_usec, msek); + nextActivation += (msek<0 ? 0 : msek); +// eDebug("next Activation sec = %d, usec = %d", nextActivation.tv_sec, nextActivation.tv_usec ); + context.addTimer(this); +} + +void eTimer::stop() +{ + if (bActive) + { + bActive=false; + context.removeTimer(this); + } +} + +void eTimer::changeInterval(long msek) +{ + if (bActive) // Timer is running? + { + context.removeTimer(this); // then stop + nextActivation -= interval; // sub old interval + } + else + bActive=true; // then activate Timer + + interval = msek; // set new Interval + nextActivation += interval; // calc nextActivation + + context.addTimer(this); // add Timer to context TimerList +} + +void eTimer::activate() // Internal Funktion... called from eApplication +{ + timeval now; + gettimeofday(&now, 0); +// eDebug("this = %p\nnow sec = %d, usec = %d\nnextActivation sec = %d, usec = %d", this, now.tv_sec, now.tv_usec, nextActivation.tv_sec, nextActivation.tv_usec ); +// eDebug("Timer emitted"); + context.removeTimer(this); + + if (!bSingleShot) + { + nextActivation += interval; + context.addTimer(this); + } + else + bActive=false; + + /*emit*/ timeout(); +} + +// mainloop + +void eMainloop::addSocketNotifier(eSocketNotifier *sn) +{ + notifiers.insert(std::pair (sn->getFD(), sn)); +} + +void eMainloop::removeSocketNotifier(eSocketNotifier *sn) +{ + notifiers.erase(sn->getFD()); +} + +void eMainloop::processOneEvent() +{ +// process pending timers... + long usec=0; + + while (TimerList && (usec = timeout_usec( TimerList.begin()->getNextActivation() ) ) <= 0 ) + TimerList.begin()->activate(); + + int fdAnz = notifiers.size(); + pollfd* pfd = new pollfd[fdAnz]; // make new pollfd array + +// fill pfd array + std::map::iterator it(notifiers.begin()); + for (int i=0; i < fdAnz; i++, it++) + { + pfd[i].fd = it->first; + pfd[i].events = it->second->getRequested(); + } + + int ret=poll(pfd, fdAnz, TimerList ? usec / 1000 : -1); // milli .. not micro seks + + if (ret>0) + { +// eDebug("bin aussem poll raus und da war was"); + for (int i=0; i < fdAnz ; i++) + { + if( notifiers.find(pfd[i].fd) == notifiers.end()) + continue; + + int req = notifiers[pfd[i].fd]->getRequested(); + + if ( pfd[i].revents & req ) + { + notifiers[pfd[i].fd]->activate(pfd[i].revents); + + if (!--ret) + break; + } else if (pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) + eDebug("poll: unhandled POLLERR/HUP/NVAL for fd %d(%d)", pfd[i].fd,pfd[i].revents); + } + } + else if (ret<0) + eDebug("poll made error"); + + // check Timers... + while ( TimerList && timeout_usec( TimerList.begin()->getNextActivation() ) <= 0 ) + TimerList.begin()->activate(); + + delete [] pfd; +} + + +int eMainloop::exec() +{ + if (!loop_level) + { + app_quit_now = false; + enter_loop(); + } + return retval; +} + +void eMainloop::enter_loop() +{ + loop_level++; + + // Status der vorhandenen Loop merken + bool old_exit_loop = app_exit_loop; + + app_exit_loop = false; + + while (!app_exit_loop && !app_quit_now) + { + processOneEvent(); + } + + // wiederherstellen der vorherigen app_exit_loop + app_exit_loop = old_exit_loop; + + loop_level--; + + if (!loop_level) + { + // do something here on exit the last loop + } +} + +void eMainloop::exit_loop() // call this to leave the current loop +{ + app_exit_loop = true; +} + +void eMainloop::quit( int ret ) // call this to leave all loops +{ + retval=ret; + app_quit_now = true; +} + +eApplication* eApp = 0; diff --git a/lib/base/ebase.h b/lib/base/ebase.h new file mode 100644 index 00000000..b929cb6d --- /dev/null +++ b/lib/base/ebase.h @@ -0,0 +1,252 @@ +#ifndef __ebase_h +#define __ebase_h + +#include +#include +#include +#include +#include +#include + +#include +#include + +class eApplication; + +extern eApplication* eApp; + +static inline bool operator<( const timeval &t1, const timeval &t2 ) +{ + return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); +} + +static inline timeval &operator+=( timeval &t1, const timeval &t2 ) +{ + t1.tv_sec += t2.tv_sec; + if ( (t1.tv_usec += t2.tv_usec) >= 1000000 ) + { + t1.tv_sec++; + t1.tv_usec -= 1000000; + } + return t1; +} + +static inline timeval operator+( const timeval &t1, const timeval &t2 ) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec + t2.tv_sec; + if ( (tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000 ) + { + tmp.tv_sec++; + tmp.tv_usec -= 1000000; + } + return tmp; +} + +static inline timeval operator-( const timeval &t1, const timeval &t2 ) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec - t2.tv_sec; + if ( (tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0 ) + { + tmp.tv_sec--; + tmp.tv_usec += 1000000; + } + return tmp; +} + +static inline timeval operator-=( timeval &t1, const timeval &t2 ) +{ + t1.tv_sec -= t2.tv_sec; + if ( (t1.tv_usec -= t2.tv_usec) < 0 ) + { + t1.tv_sec--; + t1.tv_usec += 1000000; + } + return t1; +} + +static inline timeval &operator+=( timeval &t1, const long msek ) +{ + t1.tv_sec += msek / 1000; + if ( (t1.tv_usec += (msek % 1000) * 1000) >= 1000000 ) + { + t1.tv_sec++; + t1.tv_usec -= 1000000; + } + return t1; +} + +static inline timeval operator+( const timeval &t1, const long msek ) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec + msek / 1000; + if ( (tmp.tv_usec = t1.tv_usec + (msek % 1000) * 1000) >= 1000000 ) + { + tmp.tv_sec++; + tmp.tv_usec -= 1000000; + } + return tmp; +} + +static inline timeval operator-( const timeval &t1, const long msek ) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec - msek / 1000; + if ( (tmp.tv_usec = t1.tv_usec - (msek % 1000)*1000) < 0 ) + { + tmp.tv_sec--; + tmp.tv_usec += 1000000; + } + return tmp; +} + +static inline timeval operator-=( timeval &t1, const long msek ) +{ + t1.tv_sec -= msek / 1000; + if ( (t1.tv_usec -= (msek % 1000) * 1000) < 0 ) + { + t1.tv_sec--; + t1.tv_usec += 1000000; + } + return t1; +} + +static inline timeval timeout_timeval ( const timeval & orig ) +{ + timeval now; + gettimeofday(&now,0); + + return orig-now; +} + +static inline long timeout_usec ( const timeval & orig ) +{ + timeval now; + gettimeofday(&now,0); + + return (orig-now).tv_sec*1000000 + (orig-now).tv_usec; +} + +class eMainloop; + + // die beiden signalquellen: SocketNotifier... + +/** + * \brief Gives a callback when data on a file descriptor is ready. + * + * This class emits the signal \c eSocketNotifier::activate whenever the + * event specified by \c req is available. + */ +class eSocketNotifier +{ +public: + enum { Read=POLLIN, Write=POLLOUT, Priority=POLLPRI, Error=POLLERR, Hungup=POLLHUP }; +private: + eMainloop &context; + int fd; + int state; + int requested; // requested events (POLLIN, ...) +public: + /** + * \brief Constructs a eSocketNotifier. + * \param context The thread where to bind the socketnotifier to. The signal is emitted from that thread. + * \param fd The filedescriptor to monitor. Can be a device or a socket. + * \param req The events to watch to, normally either \c Read or \c Write. You can specify any events that \c poll supports. + * \param startnow Specifies if the socketnotifier should start immediately. + */ + eSocketNotifier(eMainloop *context, int fd, int req, bool startnow=true); + ~eSocketNotifier(); + + Signal1 activated; + void activate(int what) { /*emit*/ activated(what); } + + void start(); + void stop(); + bool isRunning() { return state; } + + int getFD() { return fd; } + int getRequested() { return requested; } + void setRequested(int req) { requested=req; } +}; + + // ... und Timer +/** + * \brief Gives a callback after a specified timeout. + * + * This class emits the signal \c eTimer::timeout after the specified timeout. + */ +class eTimer +{ + eMainloop &context; + timeval nextActivation; + long interval; + bool bSingleShot; + bool bActive; +public: + /** + * \brief Constructs a timer. + * + * The timer is not yet active, it has to be started with \c start. + * \param context The thread from which the signal should be emitted. + */ + eTimer(eMainloop *context): context(*context), bActive(false) { } + ~eTimer() { if (bActive) stop(); } + + Signal0 timeout; + void activate(); + + bool isActive() { return bActive; } + timeval &getNextActivation() { return nextActivation; } + + void start(long msec, bool singleShot=false); + void stop(); + void changeInterval(long msek); + bool operator<(const eTimer& t) const { return nextActivation < t.nextActivation; } +}; + + // werden in einer mainloop verarbeitet +class eMainloop +{ + std::map notifiers; + ePtrList TimerList; + bool app_exit_loop; + bool app_quit_now; + int loop_level; + void processOneEvent(); + int retval; +public: + eMainloop():app_quit_now(0),loop_level(0),retval(0){ } + void addSocketNotifier(eSocketNotifier *sn); + void removeSocketNotifier(eSocketNotifier *sn); + void addTimer(eTimer* e) { TimerList.push_back(e); TimerList.sort(); } + void removeTimer(eTimer* e) { TimerList.remove(e); } + + int looplevel() { return loop_level; } + + int exec(); // recursive enter the loop + void quit(int ret=0); // leave all pending loops (recursive leave()) + void enter_loop(); + void exit_loop(); +}; + +/** + * \brief The application class. + * + * An application provides a mainloop, and runs in the primary thread. + * You can have other threads, too, but this is the primary one. + */ +class eApplication: public eMainloop +{ +public: + eApplication() + { + if (!eApp) + eApp = this; + } + ~eApplication() + { + eApp = 0; + } +}; +#endif diff --git a/lib/base/econfig.cpp b/lib/base/econfig.cpp new file mode 100644 index 00000000..3d51255b --- /dev/null +++ b/lib/base/econfig.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + +eConfig *eConfig::instance; + +eConfig::eConfig() +{ + if (!instance) + instance=this; + + setName(CONFIGDIR "/enigma/registry"); + int e=open(); + if (e == NC_ERR_CORRUPT) + { + eWarning("CORRUTPED REGISTRY!"); + ::remove(CONFIGDIR "/enigma/registry"); + } + if (e) + { + if (createNew()) + { + mkdir(CONFIGDIR "/enigma", 0777); + if (createNew()) + eFatal("error while opening/creating registry - create " CONFIGDIR "/enigma"); + } + if (open()) + eFatal("still can't open configfile"); + } + locked=1; + ppin=0; + getKey("/elitedvb/pins/parentallock", ppin ); +} + +eConfig::~eConfig() +{ + if (instance==this) + instance=0; +} + +eAutoInitP0 init_eRCConfig(eAutoInitNumbers::configuration, "Configuration"); diff --git a/lib/base/econfig.h b/lib/base/econfig.h new file mode 100644 index 00000000..d9f3becd --- /dev/null +++ b/lib/base/econfig.h @@ -0,0 +1,27 @@ +#ifndef __econfig_h +#define __econfig_h + +#include + +class eConfig: public NConfig +{ + static eConfig *instance; + int ppin; +public: + int locked; + static eConfig *getInstance() { return instance; } + void setParentalPin( int pin ) + { + ppin = pin; + setKey("/elitedvb/pins/parentallock", ppin ); + } + int getParentalPin() { return ppin; } + bool pLockActive() + { + return ppin && locked; + } + eConfig(); + ~eConfig(); +}; + +#endif diff --git a/lib/base/eerror.cpp b/lib/base/eerror.cpp new file mode 100644 index 00000000..0871bb71 --- /dev/null +++ b/lib/base/eerror.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +#include + +int infatal=0; + +Signal2 logOutput; +int logOutputConsole=1; + +void eFatal(const char* fmt, ...) +{ + char buf[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, 1024, fmt, ap); + va_end(ap); + logOutput(lvlFatal, buf); + fprintf(stderr, "%s\n",buf ); + if (!infatal) + { + infatal=1; + eMessageBox msg(buf, "FATAL ERROR", eMessageBox::iconError|eMessageBox::btOK); + msg.show(); + msg.exec(); + } + _exit(0); +} + +#ifdef DEBUG +void eDebug(const char* fmt, ...) +{ + char buf[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, 1024, fmt, ap); + va_end(ap); + logOutput(lvlDebug, eString(buf) + "\n"); + if (logOutputConsole) + fprintf(stderr, "%s\n", buf); +} + +void eDebugNoNewLine(const char* fmt, ...) +{ + char buf[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, 1024, fmt, ap); + va_end(ap); + logOutput(lvlDebug, buf); + if (logOutputConsole) + fprintf(stderr, "%s", buf); +} + +void eWarning(const char* fmt, ...) +{ + char buf[1024]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, 1024, fmt, ap); + va_end(ap); + logOutput(lvlWarning, eString(buf) + "\n"); + if (logOutputConsole) + fprintf(stderr, "%s\n", buf); +} +#endif // DEBUG diff --git a/lib/base/eerror.h b/lib/base/eerror.h new file mode 100644 index 00000000..bf913959 --- /dev/null +++ b/lib/base/eerror.h @@ -0,0 +1,43 @@ +#ifndef __E_ERROR__ +#define __E_ERROR__ + +#include "config.h" +#include +#include +#include +#include + +void eFatal(const char* fmt, ...); + +class eString; + +enum { lvlDebug=1, lvlWarning=2, lvlFatal=4 }; + +extern Signal2 logOutput; +extern int logOutputConsole; + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef DEBUG + void eDebug(const char* fmt, ...); + void eDebugNoNewLine(const char* fmt, ...); + void eWarning(const char* fmt, ...); + #define ASSERT(x) { if (!(x)) eFatal("%s:%d ASSERTION %s FAILED!", __FILE__, __LINE__, #x); } +#else + inline void eDebug(const char* fmt, ...) + { + } + + inline void eDebugNoNewLine(const char* fmt, ...) + { + } + + inline void eWarning(const char* fmt, ...) + { + } + #define ASSERT(x) do { } while (0) +#endif //DEBUG + +#endif // __E_ERROR__ diff --git a/lib/base/elock.cpp b/lib/base/elock.cpp new file mode 100644 index 00000000..afddcc6f --- /dev/null +++ b/lib/base/elock.cpp @@ -0,0 +1,104 @@ +#include +#include + +void eLock::lock(int res) +{ + if (res>max) + res=max; + pthread_mutex_lock(&mutex); + while ((counter+res)>max) + pthread_cond_wait(&cond, &mutex); + counter+=res; + pthread_mutex_unlock(&mutex); +} + +void eLock::unlock(int res) +{ + if (res>max) + res=max; + pthread_mutex_lock(&mutex); + counter-=res; + pthread_mutex_unlock(&mutex); + pthread_cond_signal(&cond); +} + +eLock::eLock(int max): max(max) +{ + pthread_mutex_init(&mutex, 0); + pthread_cond_init(&cond, 0); + counter=0; + pid=-1; +} + +eLock::~eLock() +{ + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); +} + +eLocker::eLocker(eLock &lock, int res): lock(lock), res(res) +{ + lock.lock(res); +} + +eLocker::~eLocker() +{ + lock.unlock(res); +} + +eSemaphore::eSemaphore() +{ + v=1; + pthread_mutex_init(&mutex, 0); + pthread_cond_init(&cond, 0); +} + +eSemaphore::~eSemaphore() +{ + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); +} + +int eSemaphore::down() +{ + int value_after_op; + pthread_mutex_lock(&mutex); + while (v<=0) + pthread_cond_wait(&cond, &mutex); + v--; + value_after_op=v; + pthread_mutex_unlock(&mutex); + return value_after_op; +} + +int eSemaphore::decrement() +{ + int value_after_op; + pthread_mutex_lock(&mutex); + v--; + value_after_op=v; + pthread_mutex_unlock(&mutex); + pthread_cond_signal(&cond); + return value_after_op; +} + +int eSemaphore::up() +{ + int value_after_op; + pthread_mutex_lock(&mutex); + v++; + value_after_op=v; + pthread_mutex_unlock(&mutex); + pthread_cond_signal(&cond); + return value_after_op; +} + +int eSemaphore::value() +{ + int value_after_op; + pthread_mutex_lock(&mutex); + value_after_op=v; + pthread_mutex_unlock(&mutex); + return value_after_op; +} + diff --git a/lib/base/elock.h b/lib/base/elock.h new file mode 100644 index 00000000..6a47f8c9 --- /dev/null +++ b/lib/base/elock.h @@ -0,0 +1,60 @@ +#ifndef __elock_h +#define __elock_h + +#include + +class singleLock +{ + pthread_mutex_t &lock; +public: + singleLock( pthread_mutex_t &m ) + :lock(m) + { + pthread_mutex_lock(&lock); + } + ~singleLock() + { + pthread_mutex_unlock(&lock); + } +}; + +class eLock +{ + pthread_mutex_t mutex; + pthread_cond_t cond; + + int pid; + int counter, max; +public: + void lock(int res=100); + void unlock(int res=100); + + eLock(int max=100); + ~eLock(); +}; + +class eLocker +{ + eLock &lock; + int res; +public: + eLocker(eLock &lock, int res=100); + ~eLocker(); +}; + +class eSemaphore +{ + int v; + pthread_mutex_t mutex; + pthread_cond_t cond; +public: + eSemaphore(); + ~eSemaphore(); + + int down(); + int decrement(); + int up(); + int value(); +}; + +#endif diff --git a/lib/base/eptrlist.h b/lib/base/eptrlist.h new file mode 100644 index 00000000..f1421eb2 --- /dev/null +++ b/lib/base/eptrlist.h @@ -0,0 +1,1338 @@ +#ifndef _E_PTRLIST_ +#define _E_PTRLIST_ + +#include +#include +#include + +template +class ePtrList : public std::list +{ +public: + typedef typename std::list >::iterator std_list_T_iterator; // to remove compiler warnings + typedef typename std::list >::const_iterator std_list_T_const_iterator; + typedef typename std::list >::reverse_iterator std_list_T_reverse_iterator; + typedef typename std::list >::const_reverse_iterator std_list_T_const_reverse_iterator; + typedef typename ePtrList::iterator T_iterator; + typedef typename ePtrList::const_iterator T_const_iterator; + typedef typename ePtrList::reverse_iterator T_reverse_iterator; + typedef typename ePtrList::const_reverse_iterator T_const_reverse_iterator; + +// Iterator classes + class iterator; + class const_iterator; + class reverse_iterator; + class const_reverse_iterator; + +// Constructors + inline ePtrList(); + inline ePtrList(const ePtrList&); + inline ~ePtrList(); + +// overwritted sort method + inline void sort(); + +// changed methods for autodelete and current implementation + inline void remove(T* t); + inline void clear(); + inline void pop_back(); + inline void pop_front(); + inline void push_back(T*); + inline void push_front(T*); + +// added methods for current implementation + inline T* take(); + inline void take(T* t); + inline T* current(); + inline T* next(); + inline T* prev(); + inline T* first(); + inline T* last(); + inline T* setCurrent(const T*); + inline const T* current() const; + inline const T* next() const; + inline const T* prev() const; + inline const T* first() const; + inline const T* last() const; + +// added operator methods + inline operator bool(); + inline bool operator!(); + +// added methods for autodelete implementation + inline void setAutoDelete(bool b); + inline bool isAutoDelete(); + +// added compare struct ... to sort + struct less; +private: + iterator cur; + bool autoDelete; + +public: + iterator ePtrList::begin() + { + // makes implicit type conversion form std::list::iterator to ePtrList::iterator + return std::list::begin(); + } + + iterator ePtrList::end() + { + // makes implicit type conversion form std::list::iterator to ePtrList::iterator + return std::list::end(); + } + + const_iterator ePtrList::begin() const + { + // makes implicit type conversion form std::list::const_iterator to ePtrList::const_iterator + return std::list::begin(); + } + + const_iterator ePtrList::end() const + { + // makes implicit type conversion form std::list::const_iterator to ePtrList::const_iterator + return std::list::end(); + } + + reverse_iterator ePtrList::rbegin() + { + // makes implicit type conversion form std::list::reverse:_iterator to ePtrList::reverse_iterator + return std::list::rbegin(); + } + + reverse_iterator ePtrList::rend() + { + // makes implicit type conversion form std::list::reverse_iterator to ePtrList::reverse_iterator + return std::list::rend(); + } + + const_reverse_iterator ePtrList::rbegin() const + { + // makes implicit type conversion form std::list::const_reverse_iterator to ePtrList::const_reverse_iterator + return std::list::rbegin(); + } + + const_reverse_iterator ePtrList::rend() const + { + // makes implicit type conversion form std::list::const_reverse_iterator to ePtrList::const_reverse_iterator + return std::list::rend(); + } + + iterator ePtrList::erase(iterator it) + { + // Remove the item it, if auto-deletion is enabled, than the list call delete for this item + // If current is equal to the item that was removed, current is set to the next item in the list + if (autoDelete && *it) + delete *it; + + if (cur == it) + return cur = std::list::erase(it); + else + return std::list::erase(it); + } + + iterator ePtrList::erase(iterator from, iterator to) + { + // Remove all items between the to iterators from and to + // If auto-deletion is enabled, than the list call delete for all removed items + while (from != to) + from = erase(from); + + return from; + } + + operator iterator() + { + // Returns a iterator that equal to begin() of the list + return begin(); + } + + operator const_iterator() const + { + // Returns a const_iterator that equal to begin() of the list + return begin(); + } + + operator reverse_iterator() + { + // Returns a reverse_iterator that equal to rbegin() of the list + return rbegin(); + } + + operator const_reverse_iterator() const + { + // Returns a const_reverse_iterator that equal to rbegin() of the list + return rbegin(); + } + + std::vector* getVector() + { + // Creates an vector and copys all elements to this vector + // returns a pointer to this new vector ( the reserved memory must deletet from the receiver !! ) + std::vector* v=new std::vector(); + v->reserve( size() ); + for ( std_list_T_iterator it( std::list::begin() ); it != std::list::end(); it++) + v->push_back( **it ); + + return v; + } + + inline iterator insert_in_order( T* e ) + { + // added a new item to the list... in order + // returns a iterator to the new item + return insert( std::lower_bound( std::list::begin(), std::list::end(), e ), e ); + } + +}; + +/////////////////// iterator class ///////////////////////////// +template +class ePtrList::iterator : public std::list::iterator +{ +public: + // Constructors + iterator(const std_list_T_iterator& Q) : std_list_T_iterator(Q) { } + + // changed operator for pointer + T* operator->() const + { + return *std::list::iterator::operator->(); + } + + operator T&() const + { + return *operator->(); + } + + operator T*() const + { + return operator->(); + } + + iterator& operator++() + { + std::list::iterator::operator++(); + return *this; + } + + iterator operator++(int) + { + return std::list::iterator::operator++(0); + } + + iterator& operator--() + { + std::list::iterator::operator--(); + return *this; + } + + iterator operator--(int) + { + return std::list::iterator::operator--(0); + } +}; + +/////////////////// const_iterator class ///////////////////////////// +template +class ePtrList::const_iterator : public std::list::const_iterator +{ +public: + // Constructors + const_iterator(const std_list_T_const_iterator& Q) :std_list_T_const_iterator(Q) { } + + // changed operator for pointer + T* operator->() const + { + return *std::list::const_iterator::operator->(); + } + + operator T&() const + { + return *operator->(); + } + + operator T*() const + { + return operator->(); + } + + const_iterator& operator++() + { + std::list::const_iterator::operator++(); + return *this; + } + + const_iterator operator++(int) + { + return std::list::const_iterator::operator++(0); + } + + const_iterator& operator--() + { + std::list::const_iterator::operator--(); + return *this; + } + + const_iterator operator--(int) + { + return std::list::const_iterator::operator--(0); + } +}; + +/////////////////// reverse_iterator class ///////////////////////////// +template +class ePtrList::reverse_iterator : public std::list::reverse_iterator +{ +public: + // Constructors + reverse_iterator(const std_list_T_reverse_iterator& Q) :std_list_T_reverse_iterator(Q) { } + + // changed operators for pointer + T* operator->() const + { + return *std::list::reverse_iterator::operator->(); + } + + operator T&() const + { + return *operator->(); + } + + operator T*() const + { + return operator->(); + } + + reverse_iterator& operator++() + { + std::list::reverse_iterator::operator++(); + return *this; + } + + reverse_iterator operator++(int) + { + return std::list::reverse_iterator::operator++(0); + } + + reverse_iterator& operator--() + { + std::list::reverse_iterator::operator--(); + return *this; + } + + reverse_iterator operator--(int) + { + return std::list::reverse_iterator::operator--(0); + } +}; + +/////////////////// const_reverse_iterator class ///////////////////////////// +template +class ePtrList::const_reverse_iterator : public std::list::const_reverse_iterator +{ +public: + // Constructors + const_reverse_iterator(const std_list_T_const_reverse_iterator& Q) :std_list_T_const_reverse_iterator(Q) { } + + // changed operators for pointer + T* operator->() const + { + return *std::list::const_reverse_iterator::operator->(); + } + + operator T&() const + { + return *operator->(); + } + + operator T*() const + { + return operator->(); + } + + const_reverse_iterator& operator++() + { + std::list::const_reverse_iterator::operator++(); + return *this; + } + + const_reverse_iterator operator++(int) + { + return std::list::const_reverse_iterator::operator++(0); + } + + const_reverse_iterator& operator--() + { + std::list::const_reverse_iterator::operator--(); + return *this; + } + + const_reverse_iterator operator--(int) + { + return std::list::const_reverse_iterator::operator--(0); + } +}; + +/////////////////// Default Constructor ///////////////////////////// +template +ePtrList::ePtrList() + :cur(std::list::begin()), autoDelete(false) +{ + +} + +/////////////////// Copy Constructor ///////////////////////////// +template +ePtrList::ePtrList(const ePtrList& e) + :std::list(e), cur(e.cur), autoDelete( false ) +{ + if ( e.autoDelete ) + if ( e.size() ) + eDebug("Warning !! We make a Copy of a non empty ePtrList, with autoDelete enabled" + "We disable autoDelete in the new ePtrList !!"); + else + autoDelete=true; +} + +/////////////////// ePtrList Destructor ///////////////////////////// +template +inline ePtrList::~ePtrList() +{ +// if autoDelete is enabled, delete is called for all elements in the list + if (autoDelete) + for (std_list_T_iterator it(std::list::begin()); it != std::list::end(); it++) + delete *it; +} + + +/////////////////// ePtrList sort() ///////////////////////// +template +inline void ePtrList::sort() +{ +// Sorts all items in the list. +// The type T must have a operator <. + std::list::sort(ePtrList::less()); +} + +/////////////////// ePtrList remove(T*) ///////////////////////// +template +inline void ePtrList::remove(T* t) +{ +// Remove all items that, equals to t, if auto-deletion is enabled, than the list call delete for the removed items +// If current is equal to one of the removed items, current is set to the next valid item + T_iterator it(std::list::begin()); + + while (it != std::list::end()) + if (*it == t) + { + it=erase(it); + break; // one item is complete removed an deleted + } + else + it++; + + while (it != std::list::end()) + if (*it == t) + it = std::list::erase(it); // remove all other items that equals to t (no delete is called..) + else + it++; + +} + +/////////////////// ePtrList clear() ////////////////// +template +inline void ePtrList::clear() +{ +// Remove all items from the list +// If auto-deletion is enabled, than the list call delete for all items in the list + erase(std::list::begin(), std::list::end()); +} + +/////////////////// ePtrList pop_back() //////////////////// +template +inline void ePtrList::pop_back() +{ +// Removes the last item from the list. If the current item ist the last, than the current is set to the new +// last item in the list; +// The removed item is deleted if auto-deletion is enabled. + erase(--end()); +} + +/////////////////// ePtrList pop_front() //////////////////// +template +inline void ePtrList::pop_front() +{ +// Removes the first item from the list. If the current item ist the first, than the current is set to the new +// first item in the list; +// The removed item is deleted if auto-deletion is enabled. + erase(begin()); +} + +/////////////////// ePtrList push_back(T*) //////////////////// +template +inline void ePtrList::push_back(T* x) +{ +// Add a new item at the end of the list. +// The current item is set to the last item; + std::list::push_back(x); + last(); +} + +/////////////////// ePtrList push_front(T*) //////////////////// +template +inline void ePtrList::push_front(T* x) +{ +// Add a new item at the begin of the list. +// The current item is set to the first item; + std::list::push_front(x); + first(); +} + +/////////////////// ePtrList take() //////////////////// +template +inline T* ePtrList::take() +{ +// Takes the current item out of the list without deleting it (even if auto-deletion is enabled). +// Returns a pointer to the item taken out of the list, or null if the index is out of range. +// The item after the taken item becomes the new current list item if the taken item is not the last item in the list. If the last item is taken, the new last item becomes the current item. +// The current item is set to null if the list becomes empty. + T* tmp = *cur; + cur = std::list::erase(cur); + return tmp; +} + +/////////////////// ePtrList take(T*) //////////////////// +template +inline void ePtrList::take(T* t) +{ +// Takes all item with T* out of the list without deleting it (even if auto-deletion is enabled). + std::list::remove(t); +} + +/////////////////// ePtrList setCurrent(T*) //////////////////// +template +inline T* ePtrList::setCurrent(const T* t) +{ + // Sets the internal current iterator to the first element that equals to t, and returns t when a item is found, + // otherwise it returns 0 ! + for (T_iterator it(std::list::begin()); it != std::list::end(); ++it) + if (*it == t) + { + cur = it; + return *it; + } + + return 0; +} + +/////////////////// ePtrList current() //////////////////// +template +inline T* ePtrList::current() +{ +// Returns a pointer to the current list item. The current item may be null (implies that the current index is -1). + return cur==end() ? 0 : *cur; +} + +/////////////////// ePtrList next() //////////////////// +template +inline T* ePtrList::next() +{ +// Returns a pointer to the item succeeding the current item. Returns null if the current items is null or equal to the last item. +// Makes the succeeding item current. If the current item before this function call was the last item, the current item will be set to null. If the current item was null, this function does nothing. + if (cur == end()) + return 0; + else + if (++cur == end()) + return 0; + else + return *cur; +} + +/////////////////// ePtrList prev() //////////////////// +template +inline T* ePtrList::prev() +{ +// Returns a pointer to the item preceding the current item. Returns null if the current items is null or equal to the first item. +// Makes the preceding item current. If the current item before this function call was the first item, the current item will be set to null. If the current item was null, this function does nothing. + if (cur == begin()) + return 0; + else + return *--cur; +} + +/////////////////// ePtrList first() //////////////////// +template +inline T* ePtrList::first() +{ +// Returns a pointer to the first item in the list and makes this the current list item, or null if the list is empty. + return *(cur = begin()); +} + +/////////////////// ePtrList last() //////////////////// +template +inline T* ePtrList::last() +{ +// Returns a pointer to the last item in the list and makes this the current list item, or null if the list is empty. + return *(cur = --end()); +} + +/////////////////// const ePtrList current() //////////////////// +template +inline const T* ePtrList::current() const +{ +// Returns a pointer to the current list item. The current item may be null (implies that the current index is not valid) + return cur==end() ? 0 : *cur; +} + +/////////////////// const ePtrList next() //////////////////// +template +inline const T* ePtrList::next() const +{ +// Returns a pointer to the item succeeding the current item. Returns null if the current items is null or equal to the last item. +// Makes the succeeding item current. If the current item before this function call was the last item, the current item will be set to null. If the current item was null, this function does nothing. + if (cur == end()) + return 0; + else + if (++cur == end()) + return 0; + else + return *cur; +} + +/////////////////// const ePtrList prev() //////////////////// +template +inline const T* ePtrList::prev() const +{ +// Returns a pointer to the item preceding the current item. Returns null if the current items is null or equal to the first item. +// Makes the preceding item current. If the current item before this function call was the first item, the current item will be set to null. If the current item was null, this function does nothing. + if (cur == begin()) + return 0; + else + return *--cur; +} + +/////////////////// const ePtrList first() //////////////////// +template +inline const T* ePtrList::first() const +{ +// Returns a pointer to the first item in the list and makes this the current list item, or null if the list is empty. + return *(cur = begin()); +} + +/////////////////// const ePtrList last() //////////////////// +template +inline const T* ePtrList::last() const +{ +// Returns a pointer to the last item in the list and makes this the current list item, or null if the list is empty. + return *(cur = --end()); +} + +////////////////// struct less ////////////////////////////// +template +struct ePtrList::less +{ +// operator() is used internal from the list to sort them + bool operator() (const T* t1, const T* t2) + { + return (*t1 < *t2); + } +}; + +/////////////////// ePtrList operator bool //////////////////// +template +ePtrList::operator bool() +{ +// Returns a bool that contains true, when the list is NOT empty otherwise false + return !empty(); +} + +template +bool ePtrList::operator!() +{ +// Returns a bool that contains true, when the list is empty otherwise false + return empty(); +} + +template +void ePtrList::setAutoDelete(bool b) +{ +// switched autoDelete on or off +// if autoDelete is true, than the pointer list controls the heap memory behind the pointer itself +// the list calls delete for the item before it removed from the list + autoDelete=b; +} + +template +bool ePtrList::isAutoDelete() +{ +// returns a bool that contains the state of autoDelete + return autoDelete; +} + +template +class eSmartPtrList : public std::list > +{ +public: + typedef typename std::list, std::allocator > >::iterator std_list_T_iterator; // to remove compiler warnings + typedef typename std::list, std::allocator > >::const_iterator std_list_T_const_iterator; + typedef typename std::list, std::allocator > >::reverse_iterator std_list_T_reverse_iterator; + typedef typename std::list, std::allocator > >::const_reverse_iterator std_list_T_const_reverse_iterator; + typedef typename eSmartPtrList::iterator T_iterator; + typedef typename eSmartPtrList::const_iterator T_const_iterator; + typedef typename eSmartPtrList::reverse_iterator T_reverse_iterator; + typedef typename eSmartPtrList::const_reverse_iterator T_const_reverse_iterator; + +// Iterator classes + class iterator; + class const_iterator; + class reverse_iterator; + class const_reverse_iterator; + +// Constructors + inline eSmartPtrList(); + inline eSmartPtrList(const eSmartPtrList&); + inline ~eSmartPtrList(); + +// overwritted sort method + inline void sort(); + +// changed methods for autodelete and current implementation + inline void remove(T* t); + inline void clear(); + inline void pop_back(); + inline void pop_front(); + inline void push_back(T*); + inline void push_front(T*); + +// added methods for current implementation +// inline T* take(); +// inline void take(T* t); + inline T* current(); + inline T* next(); + inline T* prev(); + inline T* first(); + inline T* last(); + inline T* setCurrent(const T*); + inline const T* current() const; + inline const T* next() const; + inline const T* prev() const; + inline const T* first() const; + inline const T* last() const; + +// added operator methods + inline operator bool(); + inline bool operator!(); + +// added methods for autodelete implementation + inline void setAutoDelete(bool b); + inline bool isAutoDelete(); + +// added compare struct ... to sort + struct less; +private: + iterator cur; + bool autoDelete; + +public: + iterator eSmartPtrList::begin() + { + // makes implicit type conversion form std::list::iterator to eSmartPtrList::iterator + return std::list >::begin(); + } + + iterator eSmartPtrList::end() + { + // makes implicit type conversion form std::list::iterator to eSmartPtrList::iterator + return std::list >::end(); + } + + const_iterator eSmartPtrList::begin() const + { + // makes implicit type conversion form std::list::const_iterator to eSmartPtrList::const_iterator + return std::list >::begin(); + } + + const_iterator eSmartPtrList::end() const + { + // makes implicit type conversion form std::list::const_iterator to eSmartPtrList::const_iterator + return std::list >::end(); + } + + reverse_iterator eSmartPtrList::rbegin() + { + // makes implicit type conversion form std::list::reverse:_iterator to eSmartPtrList::reverse_iterator + return std::list >::rbegin(); + } + + reverse_iterator eSmartPtrList::rend() + { + // makes implicit type conversion form std::list::reverse_iterator to eSmartPtrList::reverse_iterator + return std::list >::rend(); + } + + const_reverse_iterator eSmartPtrList::rbegin() const + { + // makes implicit type conversion form std::list::const_reverse_iterator to eSmartPtrList::const_reverse_iterator + return std::list >::rbegin(); + } + + const_reverse_iterator eSmartPtrList::rend() const + { + // makes implicit type conversion form std::list::const_reverse_iterator to eSmartPtrList::const_reverse_iterator + return std::list >::rend(); + } + + iterator eSmartPtrList::erase(iterator it) + { + // Remove the item it, if auto-deletion is enabled, than the list call delete for this item + // If current is equal to the item that was removed, current is set to the next item in the list + if (autoDelete && *it) + delete *it; + + if (cur == it) + return cur = std::list >::erase(it); + else + return std::list >::erase(it); + } + + iterator eSmartPtrList::erase(iterator from, iterator to) + { + // Remove all items between the to iterators from and to + // If auto-deletion is enabled, than the list call delete for all removed items + while (from != to) + from = erase(from); + + return from; + } + + operator iterator() + { + // Returns a iterator that equal to begin() of the list + return begin(); + } + + operator const_iterator() const + { + // Returns a const_iterator that equal to begin() of the list + return begin(); + } + + operator reverse_iterator() + { + // Returns a reverse_iterator that equal to rbegin() of the list + return rbegin(); + } + + operator const_reverse_iterator() const + { + // Returns a const_reverse_iterator that equal to rbegin() of the list + return rbegin(); + } + + std::vector* getVector() + { + // Creates an vector and copys all elements to this vector + // returns a pointer to this new vector ( the reserved memory must deletet from the receiver !! ) + std::vector* v=new std::vector(); + v->reserve( size() ); + for ( std_list_T_iterator it( std::list >::begin() ); it != std::list >::end(); it++) + v->push_back( **it ); + + return v; + } + + inline iterator insert_in_order( T* e ) + { + // added a new item to the list... in order + // returns a iterator to the new item + return insert( std::lower_bound( std::list >::begin(), std::list >::end(), e ), e ); + } + +}; + +/////////////////// iterator class ///////////////////////////// +template +class eSmartPtrList::iterator : public std::list >::iterator +{ +public: + // Constructors + iterator(const std_list_T_iterator& Q) : std_list_T_iterator(Q) { } + + // changed operator for pointer + T* operator->() const + { + return *std::list >::iterator::operator->(); + } + + operator T&() const + { + return *operator->(); + } + + operator T*() const + { + return operator->(); + } + + iterator& operator++() + { + std::list >::iterator::operator++(); + return *this; + } + + iterator operator++(int) + { + return std::list >::iterator::operator++(0); + } + + iterator& operator--() + { + std::list >::iterator::operator--(); + return *this; + } + + iterator operator--(int) + { + return std::list >::iterator::operator--(0); + } +}; + +/////////////////// const_iterator class ///////////////////////////// +template +class eSmartPtrList::const_iterator : public std::list >::const_iterator +{ +public: + // Constructors + const_iterator(const std_list_T_const_iterator& Q) :std_list_T_const_iterator(Q) { } + + // changed operator for pointer + T* operator->() const + { + return *std::list >::const_iterator::operator->(); + } + + operator T&() const + { + return *operator->(); + } + + operator T*() const + { + return operator->(); + } + + const_iterator& operator++() + { + std::list >::const_iterator::operator++(); + return *this; + } + + const_iterator operator++(int) + { + return std::list >::const_iterator::operator++(0); + } + + const_iterator& operator--() + { + std::list >::const_iterator::operator--(); + return *this; + } + + const_iterator operator--(int) + { + return std::list >::const_iterator::operator--(0); + } +}; + +/////////////////// reverse_iterator class ///////////////////////////// +template +class eSmartPtrList::reverse_iterator : public std::list >::reverse_iterator +{ +public: + // Constructors + reverse_iterator(const std_list_T_reverse_iterator& Q) :std_list_T_reverse_iterator(Q) { } + + // changed operators for pointer + T* operator->() const + { + return *std::list >::reverse_iterator::operator->(); + } + + operator T&() const + { + return *operator->(); + } + + operator T*() const + { + return operator->(); + } + + reverse_iterator& operator++() + { + std::list >::reverse_iterator::operator++(); + return *this; + } + + reverse_iterator operator++(int) + { + return std::list >::reverse_iterator::operator++(0); + } + + reverse_iterator& operator--() + { + std::list >::reverse_iterator::operator--(); + return *this; + } + + reverse_iterator operator--(int) + { + return std::list >::reverse_iterator::operator--(0); + } +}; + +/////////////////// const_reverse_iterator class ///////////////////////////// +template +class eSmartPtrList::const_reverse_iterator : public std::list >::const_reverse_iterator +{ +public: + // Constructors + const_reverse_iterator(const std_list_T_const_reverse_iterator& Q) :std_list_T_const_reverse_iterator(Q) { } + + // changed operators for pointer + T* operator->() const + { + return *std::list >::const_reverse_iterator::operator->(); + } + + operator T&() const + { + return *operator->(); + } + + operator T*() const + { + return operator->(); + } + + const_reverse_iterator& operator++() + { + std::list >::const_reverse_iterator::operator++(); + return *this; + } + + const_reverse_iterator operator++(int) + { + return std::list >::const_reverse_iterator::operator++(0); + } + + const_reverse_iterator& operator--() + { + std::list >::const_reverse_iterator::operator--(); + return *this; + } + + const_reverse_iterator operator--(int) + { + return std::list >::const_reverse_iterator::operator--(0); + } +}; + +/////////////////// Default Constructor ///////////////////////////// +template +eSmartPtrList::eSmartPtrList() + :cur(std::list >::begin()), autoDelete(false) +{ + +} + +/////////////////// Copy Constructor ///////////////////////////// +template +eSmartPtrList::eSmartPtrList(const eSmartPtrList& e) + :std::list >(e), cur(e.cur), autoDelete( false ) +{ + if ( e.autoDelete ) + if ( e.size() ) + eDebug("Warning !! We make a Copy of a non empty eSmartPtrList, with autoDelete enabled" + "We disable autoDelete in the new eSmartPtrList !!"); + else + autoDelete=true; +} + +/////////////////// eSmartPtrList Destructor ///////////////////////////// +template +inline eSmartPtrList::~eSmartPtrList() +{ +// if autoDelete is enabled, delete is called for all elements in the list + if (autoDelete) + for (std_list_T_iterator it(std::list >::begin()); it != std::list >::end(); it++) + delete *it; +} + + +/////////////////// eSmartPtrList sort() ///////////////////////// +template +inline void eSmartPtrList::sort() +{ +// Sorts all items in the list. +// The type T must have a operator <. + std::list >::sort(eSmartPtrList::less()); +} + +/////////////////// eSmartPtrList remove(T*) ///////////////////////// +template +inline void eSmartPtrList::remove(T* t) +{ +// Remove all items that, equals to t, if auto-deletion is enabled, than the list call delete for the removed items +// If current is equal to one of the removed items, current is set to the next valid item + T_iterator it(std::list >::begin()); + + while (it != std::list >::end()) + if (*it == t) + { + it=erase(it); + break; // one item is complete removed an deleted + } + else + it++; + + while (it != std::list >::end()) + if (*it == t) + it = std::list >::erase(it); // remove all other items that equals to t (no delete is called..) + else + it++; + +} + +/////////////////// eSmartPtrList clear() ////////////////// +template +inline void eSmartPtrList::clear() +{ +// Remove all items from the list +// If auto-deletion is enabled, than the list call delete for all items in the list + erase(std::list >::begin(), std::list >::end()); +} + +/////////////////// eSmartPtrList pop_back() //////////////////// +template +inline void eSmartPtrList::pop_back() +{ +// Removes the last item from the list. If the current item ist the last, than the current is set to the new +// last item in the list; +// The removed item is deleted if auto-deletion is enabled. + erase(--end()); +} + +/////////////////// eSmartPtrList pop_front() //////////////////// +template +inline void eSmartPtrList::pop_front() +{ +// Removes the first item from the list. If the current item ist the first, than the current is set to the new +// first item in the list; +// The removed item is deleted if auto-deletion is enabled. + erase(begin()); +} + +/////////////////// eSmartPtrList push_back(T*) //////////////////// +template +inline void eSmartPtrList::push_back(T* x) +{ +// Add a new item at the end of the list. +// The current item is set to the last item; + std::list >::push_back(x); + last(); +} + +/////////////////// eSmartPtrList push_front(T*) //////////////////// +template +inline void eSmartPtrList::push_front(T* x) +{ +// Add a new item at the begin of the list. +// The current item is set to the first item; + std::list >::push_front(x); + first(); +} + +/////////////////// eSmartPtrList take() //////////////////// +//template +//inline T* eSmartPtrList::take() +//{ +//// Takes the current item out of the list without deleting it (even if auto-deletion is enabled). +//// Returns a pointer to the item taken out of the list, or null if the index is out of range. +//// The item after the taken item becomes the new current list item if the taken item is not the last item in the list. If the last item is taken, the new last item becomes the current item. +//// The current item is set to null if the list becomes empty. +// T* tmp = *cur; +// cur = std::list::erase(cur); +// return tmp; +//} + +/////////////////// eSmartPtrList take(T*) //////////////////// +//template +//inline void eSmartPtrList::take(T* t) +//{ +//// Takes all item with T* out of the list without deleting it (even if auto-deletion is enabled). +// std::list::remove(t); +//} + +/////////////////// eSmartPtrList setCurrent(T*) //////////////////// +template +inline T* eSmartPtrList::setCurrent(const T* t) +{ + // Sets the internal current iterator to the first element that equals to t, and returns t when a item is found, + // otherwise it returns 0 ! + for (T_iterator it(std::list >::begin()); it != std::list >::end(); ++it) + if (*it == t) + { + cur = it; + return *it; + } + + return 0; +} + +/////////////////// eSmartPtrList current() //////////////////// +template +inline T* eSmartPtrList::current() +{ +// Returns a pointer to the current list item. The current item may be null (implies that the current index is -1). + return cur==end() ? 0 : *cur; +} + +/////////////////// eSmartPtrList next() //////////////////// +template +inline T* eSmartPtrList::next() +{ +// Returns a pointer to the item succeeding the current item. Returns null if the current items is null or equal to the last item. +// Makes the succeeding item current. If the current item before this function call was the last item, the current item will be set to null. If the current item was null, this function does nothing. + if (cur == end()) + return 0; + else + if (++cur == end()) + return 0; + else + return *cur; +} + +/////////////////// eSmartPtrList prev() //////////////////// +template +inline T* eSmartPtrList::prev() +{ +// Returns a pointer to the item preceding the current item. Returns null if the current items is null or equal to the first item. +// Makes the preceding item current. If the current item before this function call was the first item, the current item will be set to null. If the current item was null, this function does nothing. + if (cur == begin()) + return 0; + else + return *--cur; +} + +/////////////////// eSmartPtrList first() //////////////////// +template +inline T* eSmartPtrList::first() +{ +// Returns a pointer to the first item in the list and makes this the current list item, or null if the list is empty. + return *(cur = begin()); +} + +/////////////////// eSmartPtrList last() //////////////////// +template +inline T* eSmartPtrList::last() +{ +// Returns a pointer to the last item in the list and makes this the current list item, or null if the list is empty. + return *(cur = --end()); +} + +/////////////////// const eSmartPtrList current() //////////////////// +template +inline const T* eSmartPtrList::current() const +{ +// Returns a pointer to the current list item. The current item may be null (implies that the current index is not valid) + return cur==end() ? 0 : *cur; +} + +/////////////////// const eSmartPtrList next() //////////////////// +template +inline const T* eSmartPtrList::next() const +{ +// Returns a pointer to the item succeeding the current item. Returns null if the current items is null or equal to the last item. +// Makes the succeeding item current. If the current item before this function call was the last item, the current item will be set to null. If the current item was null, this function does nothing. + if (cur == end()) + return 0; + else + if (++cur == end()) + return 0; + else + return *cur; +} + +/////////////////// const eSmartPtrList prev() //////////////////// +template +inline const T* eSmartPtrList::prev() const +{ +// Returns a pointer to the item preceding the current item. Returns null if the current items is null or equal to the first item. +// Makes the preceding item current. If the current item before this function call was the first item, the current item will be set to null. If the current item was null, this function does nothing. + if (cur == begin()) + return 0; + else + return *--cur; +} + +/////////////////// const eSmartPtrList first() //////////////////// +template +inline const T* eSmartPtrList::first() const +{ +// Returns a pointer to the first item in the list and makes this the current list item, or null if the list is empty. + return *(cur = begin()); +} + +/////////////////// const eSmartPtrList last() //////////////////// +template +inline const T* eSmartPtrList::last() const +{ +// Returns a pointer to the last item in the list and makes this the current list item, or null if the list is empty. + return *(cur = --end()); +} + +////////////////// struct less ////////////////////////////// +template +struct eSmartPtrList::less +{ +// operator() is used internal from the list to sort them + bool operator() (const T* t1, const T* t2) + { + return (*t1 < *t2); + } +}; + +/////////////////// eSmartPtrList operator bool //////////////////// +template +eSmartPtrList::operator bool() +{ +// Returns a bool that contains true, when the list is NOT empty otherwise false + return !empty(); +} + +template +bool eSmartPtrList::operator!() +{ +// Returns a bool that contains true, when the list is empty otherwise false + return empty(); +} + +template +void eSmartPtrList::setAutoDelete(bool b) +{ +// switched autoDelete on or off +// if autoDelete is true, than the pointer list controls the heap memory behind the pointer itself +// the list calls delete for the item before it removed from the list + autoDelete=b; +} + +template +bool eSmartPtrList::isAutoDelete() +{ +// returns a bool that contains the state of autoDelete + return autoDelete; +} + +#endif // _E_PTRLIST diff --git a/lib/base/estring.cpp b/lib/base/estring.cpp new file mode 100644 index 00000000..bf30d5f9 --- /dev/null +++ b/lib/base/estring.cpp @@ -0,0 +1,468 @@ +#include +#include +#include +#include + +static pthread_mutex_t lock=PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP; + +///////////////////////////////////////// eString sprintf ///////////////////////////////////////////////// +eString& eString::sprintf(char *fmt, ...) +{ + singleLock s(lock); +// Implements the normal sprintf method, to use format strings with eString +// The max length of the result string is 1024 char. + static char buf[1024]; + va_list ap; + va_start(ap, fmt); + std::vsnprintf(buf, 1024, fmt, ap); + va_end(ap); + assign(buf); + return *this; +} + +///////////////////////////////////////// eString setNum(uint, uint) /////////////////////////////////////// +eString& eString::setNum(int val, int sys) +{ +// Returns a string that contain the value val as string +// if sys == 16 than hexadezimal if sys == 10 than decimal + char buf[12]; + + if (sys == 10) + std::snprintf(buf, 12, "%i", val); + else if (sys == 16) + std::snprintf(buf, 12, "%X", val); + + assign(buf); + return *this; +} + +///////////////////////////////////////// eString replaceChars(char, char) ///////////////////////////// +eString& eString::removeChars(char fchar) +{ +// Remove all chars that equal to fchar, and returns a reference to itself + unsigned int index=0; + + while ( ( index = find(fchar, index) ) != npos ) + erase(index, 1); + + return *this; +} + +/////////////////////////////////////// eString upper() //////////////////////////////////////////////// +eString& eString::upper() +{ +// convert all lowercase characters to uppercase, and returns a reference to itself + for (iterator it = begin(); it != end(); it++) + switch(*it) + { + case 'a' ... 'z' : + *it -= 32; + break; + + case 'ä' : + *it = 'Ä'; + break; + + case 'ü' : + *it = 'Ü'; + break; + + case 'ö' : + *it = 'Ö'; + break; + } + + return *this; +} + +eString& eString::strReplace(const char* fstr, const eString& rstr) +{ +// replace all occurrence of fstr with rstr and, and returns a reference to itself + unsigned int index=0; + unsigned int fstrlen = strlen(fstr); + int rstrlen=rstr.size(); + + while ( ( index = find(fstr, index) ) != npos ) + { + replace(index, fstrlen, rstr); + index+=rstrlen; + } + + return *this; +} + +int strnicmp(const char *s1, const char *s2, int len) +{ +// makes a case insensitive string compare with len Chars + while ( *s1 && *s2 && len-- ) + if ( tolower(*s1) != tolower(*s2) ) + return tolower(*s1) < tolower(*s2) ? -1 : 1; + else + s1++, s2++; + + return 0; +} + +/////////////////////////////////////// eString icompare(const eString&) //////////////////////////////////////////////// +int eString::icompare(const eString& s) +{ +// makes a case insensitive string compare + std::string::const_iterator p = begin(), + p2 = s.begin(); + + while ( p != end() && p2 != s.end() ) + if ( tolower(*p) != tolower(*p2) ) + return tolower(*p) < tolower(*p2) ? -1 : 1; + else + p++, p2++; + + return length() == s.length() ? 0 : length() < s.length() ? -1 : 1; +} + + // 8859-x to dvb coding tables. taken from www.unicode.org/Public/MAPPINGS/ISO8859/ +static unsigned long c88595[128]={ +0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, +0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, +0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f, +0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, +0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, +0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, +0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, +0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f}; + +static unsigned long c88596[128]={ +0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, +0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, +0x00a0, 0x0000, 0x0000, 0x0000, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x060c, 0x00ad, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, +0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, +0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, +0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; + +static unsigned long c88597[128]={ +0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, +0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, +0x00a0, 0x2018, 0x2019, 0x00a3, 0x0000, 0x0000, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x0000, 0x00ab, 0x00ac, 0x00ad, 0x0000, 0x2015, +0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x0385, 0x0386, 0x00b7, 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f, +0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, +0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, +0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, +0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000}; + +static unsigned long c88598[128]={ +0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, +0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, +0x00a0, 0x0000, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, +0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017, +0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, +0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x200e, 0x200f, 0x0000}; + +static unsigned long c88599[128]={ +0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, +0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, +0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, +0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, +0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, +0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, +0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, +0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff}; + + // UPC Direct / HBO strange two-character encoding. 0xC2 means acute, 0xC8 doule 'dot', 0xCA small 'circle', 0xCD double 'acute', 0xCF acute. + // many thanks to the czechs who helped me while solving this. +static inline unsigned int doCzech(int c1, int c2) +{ + switch (c1) + { + case 0xC2: // acute + switch (c2) + { + case 'A': return 0x00C1; + case 'a': return 0x00E1; + case 'E': return 0x00C9; + case 'e': return 0x00E9; + case 'I': return 0x00CD; + case 'i': return 0x00ED; + case 'O': return 0x00D3; + case 'o': return 0x00F3; // corrected, was 0x00E3 + case 'U': return 0x00DA; + case 'u': return 0x00FA; + case 'Y': return 0x00DD; + case 'y': return 0x00FD; + default: + return 0; + } + case 0xC8: // double 'dot' + switch (c2) + { + case 'A': return 0x00C4; + case 'a': return 0x00E4; + case 'E': return 0x00CB; + case 'e': return 0x00EB; + case 'O': return 0x00D6; + case 'o': return 0x00F6; + case 'U': return 0x00DC; + case 'u': return 0x00FC; + default: + return 0; + } + case 0xCA: // small 'circle' + switch (c2) + { + case 'U': return 0x016E; + case 'u': return 0x016F; + default: + return 0; + } + case 0xCD: // double 'acute' + switch (c2) + { + case 'O': return 0x0150; + case 'o': return 0x0151; + case 'U': return 0x0170; + case 'u': return 0x0171; + default: + return 0; + } + case 0xCF: // caron + switch (c2) + { + case 'C': return 0x010C; + case 'c': return 0x010D; + case 'D': return 0x010E; + case 'd': return 0x010F; + case 'E': return 0x011A; + case 'e': return 0x011B; + case 'L': return 0x013D; // not sure if they really exist. + case 'l': return 0x013E; + case 'N': return 0x0147; + case 'n': return 0x0148; + case 'R': return 0x0158; + case 'r': return 0x0159; + case 'S': return 0x0160; + case 's': return 0x0161; + case 'T': return 0x0164; + case 't': return 0x0165; + case 'Z': return 0x017D; + case 'z': return 0x017E; + default: + return 0; + } + default: + return 0; + } +} + +static inline unsigned int recode(unsigned char d, int cp) +{ + if (d < 0x80) + return d; + switch (cp) + { + case 0: // 8859-1 Latin1 <-> unicode mapping + return d; + case 1: // 8859-5 -> unicode mapping + return c88595[d-0x80]; + case 2: // 8859-6 -> unicode mapping + return c88596[d-0x80]; + case 3: // 8859-7 -> unicode mapping + return c88597[d-0x80]; + case 4: // 8859-8 -> unicode mapping + return c88598[d-0x80]; + case 5: // 8859-9 -> unicode mapping + return c88599[d-0x80]; + default: + return d; + } +} + +eString convertDVBUTF8(unsigned char *data, int len, int table) +{ + int i; + if (!len) + return ""; + + i=0; + if (data[0] <= 5) + table=data[i++]; + if ((data[0] >= 0x10) && (data[0] <= 0x12)) + return ""; + + int bytesneeded=0, t=0, s=i; + + for (; i= 0x10000) + bytesneeded++; + if (code >= 0x800) + bytesneeded++; + if (code >= 0x80) + bytesneeded++; + bytesneeded++; + } + + i=s; + + unsigned char res[bytesneeded]; + + while (i < len) + { + unsigned long code=0; + if ((table == 5) && ((data[i] == 0xC2) || (data[i] == 0xC8) || (data[i] == 0xCA) || (data[i] == 0xCD) || (data[i] == 0xCF)) && (i+1 < len)) + // braindead czech encoding... + if ((code=doCzech(data[i], data[i+1]))) + i+=2; + if (!code) + code=recode(data[i++], table); + if (!code) + continue; + // Unicode->UTF8 encoding + if (code < 0x80) // identity ascii <-> utf8 mapping + res[t++]=char(code); + else if (code < 0x800) // two byte mapping + { + res[t++]=(code>>6)|0xC0; + res[t++]=(code&0x3F)|0x80; + } else if (code < 0x10000) // three bytes mapping + { + res[t++]=(code>>12)|0xE0; + res[t++]=((code>>6)&0x3F)|0x80; + res[t++]=(code&0x3F)|0x80; + } else + { + res[t++]=(code>>18)|0xF0; + res[t++]=((code>>12)&0x3F)|0x80; + res[t++]=((code>>6)&0x3F)|0x80; + res[t++]=(code&0x3F)|0x80; + } + } + if ( t != bytesneeded) + eFatal("t: %d, bytesneeded: %d", t, bytesneeded); + return eString().assign((char*)res, t); +} + +eString convertUTF8DVB(const eString &string) +{ + eString ss=eString(); + + int len=string.length(); + for(int i=0;i=0x80){ + for(unsigned int j=0;j<128;j++){ + if(c88599[j]==c){ // now only 8859-9 .... + c=0x80+j; + break; + } + } + } + ss+=c; + } + + return ss; +} + +eString convertLatin1UTF8(const eString &string) +{ + unsigned int bytesneeded=0, t=0, i; + + unsigned int len=string.size(); + + for (i=0; i= 0x10000) + bytesneeded++; + if (code >= 0x800) + bytesneeded++; + if (code >= 0x80) + bytesneeded++; + bytesneeded++; + } + + i=0; + + unsigned char res[bytesneeded]; + + while (i < len) + { + unsigned long code=string[i++]; + // Unicode->UTF8 encoding + if (code < 0x80) // identity latin <-> utf8 mapping + res[t++]=char(code); + else if (code < 0x800) // two byte mapping + { + res[t++]=(code>>6)|0xC0; + res[t++]=(code&0x3F)|0x80; + } else if (code < 0x10000) // three bytes mapping + { + res[t++]=(code>>12)|0xE0; + res[t++]=((code>>6)&0x3F)|0x80; + res[t++]=(code&0x3F)|0x80; + } else + { + res[t++]=(code>>18)|0xF0; + res[t++]=((code>>12)&0x3F)|0x80; + res[t++]=((code>>6)&0x3F)|0x80; + res[t++]=(code&0x3F)|0x80; + } + } + if ( t != bytesneeded) + eFatal("t: %d, bytesneeded: %d", t, bytesneeded); + return eString().assign((char*)res, t); +} + +int isUTF8(const eString &string) +{ + unsigned int len=string.size(); + + for (unsigned int i=0; i < len; ++i) + { + if (!(string[i]&0x80)) // normal ASCII + continue; + if ((string[i] & 0xE0) == 0xC0) // one char following. + { + // first, length check: + if (i+1 >= len) + return 0; // certainly NOT utf-8 + i++; + if ((string[i]&0xC0) != 0x80) + return 0; // no, not UTF-8. + } else if ((string[i] & 0xF0) == 0xE0) + { + if ((i+1) >= len) + return 0; + i++; + if ((string[i]&0xC0) != 0x80) + return 0; + i++; + if ((string[i]&0xC0) != 0x80) + return 0; + } + } + return 1; // can be UTF8 (or pure ASCII, at least no non-UTF-8 8bit characters) +} + diff --git a/lib/base/estring.h b/lib/base/estring.h new file mode 100644 index 00000000..36f6636a --- /dev/null +++ b/lib/base/estring.h @@ -0,0 +1,113 @@ +#ifndef __E_STRING__ +#define __E_STRING__ + +#include +#include +#include +#include "eerror.h" + +int strnicmp(const char*, const char*, int); + +class eString : public std::string +{ +public: +// constructors + inline eString() {} + inline eString(const char* p); + inline eString(const char* p, int cnt); + inline eString(const std::string &s); +// methods + inline eString left(unsigned int len) const; + inline eString mid(unsigned int index, unsigned int len=(unsigned)-1) const; + inline eString right(unsigned int len) const; + bool isNull() const; +// operators + inline operator bool() const; + inline bool operator!() const; +// methods with implementation in estring.cpp + eString& sprintf(char *fmt, ...); + eString& setNum(int val, int sys=10); + eString& removeChars(const char fchar); + eString& strReplace(const char* fstr, const eString& rstr); + eString& upper(); + int icompare(const eString& s); +}; + +eString convertDVBUTF8(unsigned char *data, int len, int table=5); +eString convertUTF8DVB(const eString &string); // with default ISO8859-5 +eString convertLatin1UTF8(const eString &string); +int isUTF8(const eString &string); + +/////////////////////////////////////////////// Copy Constructors //////////////////////////////////////////////// +inline eString::eString(const std::string &s) + :std::string(s) +{ +} + +inline eString::eString(const char* p) + :std::string(p?p:"") // when the char* p is null, than use ""... otherwise crash... +{ +} + +inline eString::eString(const char* p, int cnt) + :std::string(p, cnt) +{ +} + +///////////////////////////////////////// eString operator bool ///////////////////////////////////////////////// +inline eString::operator bool() const +{ +// Returns a bool that contains true if the string longer than 0 Character otherwise false; + return !empty(); +} + +///////////////////////////////////////// eString operator! //////////////////////////////////////////////////// +inline bool eString::operator!() const +{ +// Returns a bool that contains true if the string ist empty otherwise false; + return empty(); +} + +///////////////////////////////////////// eString left ////////////////////////////////////////////////////////// +inline eString eString::left(unsigned int len) const +{ +// Returns a substring that contains the len leftmost characters of the string. +// The whole string is returned if len exceeds the length of the string. + return len >= length() ? *this : substr(0, len); +} + +//////////////////////////////////////// eString mid //////////////////////////////////////////////////////////// +inline eString eString::mid(unsigned int index, unsigned int len) const +{ +// Returns a substring that contains the len characters of this string, starting at position index. +// Returns a null string if the string is empty or index is out of range. Returns the whole string from index if index+len exceeds the length of the string. + register unsigned int strlen = length(); + + if (index >= strlen) + return eString(); + + if (len == (unsigned)-1) + return substr(index); + + if (strlen < index + len) + len = strlen-index; + + return substr(index, len); +} + +//////////////////////////////////////// eString right //////////////////////////////////////////////////////////// +inline eString eString::right(unsigned int len) const +{ +// Returns a substring that contains the len rightmost characters of the string. +// The whole string is returned if len exceeds the length of the string. + register unsigned int strlen = length(); + return len >= strlen ? *this : substr(strlen-len, len); +} + +inline bool eString::isNull() const +{ +// Returns a bool, that contains true, when the internal char* is null (only when a string ist empty constructed) + return !c_str(); +} + +#endif // __E_STRING__ diff --git a/lib/base/i18n.h b/lib/base/i18n.h new file mode 100644 index 00000000..96d5402b --- /dev/null +++ b/lib/base/i18n.h @@ -0,0 +1,29 @@ +/* + * i18n.h: gettext defines and includes + * + * Copyright (C) 2002 Bastian Blank + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id: i18n.h,v 1.1 2003-10-17 15:35:47 tmbinc Exp $ + */ + +#ifndef __CORE__BASE__I18N_H +#define __CORE__BASE__I18N_H + +#include +#define _(string) gettext (string) + +#endif diff --git a/lib/base/init.cpp b/lib/base/init.cpp new file mode 100644 index 00000000..b9cf1dec --- /dev/null +++ b/lib/base/init.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +int eInit::rl=-1; +std::list > *eInit::cl; + +void eInit::add(int trl, eAutoInit *c) +{ + if (!cl) + cl=new std::list >; + cl->push_back(std::pair(trl, c)); + if (rl>=trl) + c->initNow(); +} + +void eInit::remove(int trl, eAutoInit *c) +{ + if (!cl) + return; + cl->remove(std::pair(trl, c)); + if (rl>=trl) + c->closeNow(); +} + +eInit::eInit() +{ +} + +eInit::~eInit() +{ + setRunlevel(-1); + delete cl; + cl=0; +} + +void eInit::setRunlevel(int nrl) +{ + while (nrl>rl) + { + rl++; + + for (std::list >::iterator i(cl->begin()); i!=cl->end(); ++i) + { + if ((*i).first == rl) + { + eDebug("+ (%d) %s", rl, (*i).second->getDescription()); + (*i).second->initNow(); + } + } + } + + while (nrl >::iterator i(cl->begin()); i!=cl->end(); ++i) + if ((*i).first == rl) + { + eDebug("- (%d) %s", rl, (*i).second->getDescription()); + (*i).second->closeNow(); + } + rl--; + } + eDebug("reached rl %d", rl); +} + +eAutoInit::~eAutoInit() +{ +} diff --git a/lib/base/init.h b/lib/base/init.h new file mode 100644 index 00000000..465bac40 --- /dev/null +++ b/lib/base/init.h @@ -0,0 +1,97 @@ +#ifndef __init_h +#define __init_h + +#include +#include + +class eAutoInit; + +class eInit +{ + static std::list > *cl; + friend class eAutoInit; + static int rl; +public: + eInit(); + ~eInit(); + static void setRunlevel(int rlev); + static void add(int trl, eAutoInit *c); + static void remove(int trl, eAutoInit *c); +}; + +class eAutoInit +{ + friend class eInit; + virtual void initNow()=0; + virtual void closeNow()=0; +protected: + int rl; + char *description; +public: + eAutoInit(int rl, char *description): rl(rl), description(description) + { + } + virtual ~eAutoInit(); + const char *getDescription() const { return description; }; +}; + +template class +eAutoInitP1: protected eAutoInit +{ + T1 *t; + const T2 &arg; + void initNow() + { + t=new T1(arg); + } + void closeNow() + { + delete t; + } +public: + operator T1*() + { + return t; + } + eAutoInitP1(const T2 &arg, int runl, char *description): eAutoInit(runl, description), arg(arg) + { + eInit::add(rl, this); + } + ~eAutoInitP1() + { + eInit::remove(rl, this); + } +}; + +template class +eAutoInitP0: protected eAutoInit +{ + T1 *t; + void initNow() + { + t=new T1(); + } + void closeNow() + { + delete t; + } +public: + operator T1*() + { + return t; + } + T1 *operator->() + { + return t; + } + eAutoInitP0(int runl, char *description): eAutoInit(runl, description) + { + eInit::add(rl, this); + } + ~eAutoInitP0() + { + eInit::remove(rl, this); + } +}; + +#endif diff --git a/lib/base/init_num.h b/lib/base/init_num.h new file mode 100644 index 00000000..a9da0624 --- /dev/null +++ b/lib/base/init_num.h @@ -0,0 +1,24 @@ +#ifndef __lib_system_init_num_ +#define __lib_system_init_num_ + +namespace eAutoInitNumbers +{ + enum { increment=5 }; + enum + { + configuration=0, + lowlevel=configuration+increment, + graphic=lowlevel+increment, + skin=graphic+increment, + rc=skin+increment, + guiobject=rc+increment, + actions=guiobject+increment, + dvb=actions+increment, + service=dvb+increment, + osd=service+increment, + wizard=osd+increment, + main=osd+increment*5, + }; +}; + +#endif diff --git a/lib/base/message.cpp b/lib/base/message.cpp new file mode 100644 index 00000000..dafbf3f8 --- /dev/null +++ b/lib/base/message.cpp @@ -0,0 +1,49 @@ +#include +#include +#include + +eMessagePump::eMessagePump(int mt): content(1024*1024), ismt(mt) +{ + pipe(fd); +} + +eMessagePump::~eMessagePump() +{ + if (ismt) + content.lock(); // blocks until all messages are processed. + close(fd[0]); + close(fd[1]); +} + +int eMessagePump::send(const void *data, int len) +{ + if (ismt) + content.lock(len); + return ::write(fd[1], data, len)<0; +} + +int eMessagePump::recv(void *data, int len) +{ + unsigned char*dst=(unsigned char*)data; + while (len) + { + if (ismt) + content.unlock(len); + int r=::read(fd[0], dst, len); + if (r<0) + return r; + dst+=r; + len-=r; + } + return 0; +} + +int eMessagePump::getInputFD() const +{ + return fd[1]; +} + +int eMessagePump::getOutputFD() const +{ + return fd[0]; +} diff --git a/lib/base/message.h b/lib/base/message.h new file mode 100644 index 00000000..6a9ff43e --- /dev/null +++ b/lib/base/message.h @@ -0,0 +1,64 @@ +#ifndef __lib_base_message_h +#define __lib_base_message_h + +#include +#include +#include + +/** + * \brief A generic messagepump. + * + * You can send and receive messages with this class. Internally a fifo is used, + * so you can use them together with a \c eMainloop. + */ +class eMessagePump +{ + int fd[2]; + eLock content; + int ismt; +public: + eMessagePump(int mt=0); + ~eMessagePump(); + int send(const void *data, int len); + int recv(void *data, int len); // blockierend + int getInputFD() const; + int getOutputFD() const; +}; + +/** + * \brief A messagepump with fixed-length packets. + * + * Based on \ref eMessagePump, with this class you can send and receive fixed size messages. + * Automatically creates a eSocketNotifier and gives you a callback. + */ +template +class eFixedMessagePump: private eMessagePump, public Object +{ + eSocketNotifier *sn; + void do_recv(int) + { + T msg; + recv(&msg, sizeof(msg)); + /*emit*/ recv_msg(msg); + } +public: + Signal1 recv_msg; + void send(const T &msg) + { + eMessagePump::send(&msg, sizeof(msg)); + } + eFixedMessagePump(eMainloop *context, int mt): eMessagePump(mt) + { + sn=new eSocketNotifier(context, getOutputFD(), eSocketNotifier::Read); + CONNECT(sn->activated, eFixedMessagePump::do_recv); + sn->start(); + } + ~eFixedMessagePump() + { + delete sn; + } + void start() { sn->start(); } + void stop() { sn->stop(); } +}; + +#endif diff --git a/lib/base/nconfig.cpp b/lib/base/nconfig.cpp new file mode 100644 index 00000000..a0e4a313 --- /dev/null +++ b/lib/base/nconfig.cpp @@ -0,0 +1,1027 @@ +// this is nconfig 0.92, a bit modified +#define NO_MAP_SHARED +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifndef PAGESIZE +#ifdef PAGE_SIZE +#define PAGESIZE PAGE_SIZE +#else +#define PAGESIZE 4096 +#endif +#endif + +#define SB ((struct nc_sb_s *) data) +#define CM(x) ((struct nc_chunk_s *) (data+(x))) +#define DE(x) ((struct nc_de_s *) (data+(x))) +#define IDE(x, y) (DE(((unsigned *) (data+(x)->offset))[(y)])) +#define CS(x) (((unsigned *) (data+(x)))[-1]) + +inline unsigned NConfig::crc(const char *d, unsigned len) +{ + unsigned ret = 0; + unsigned l = len / sizeof(unsigned); + + while (l) { + ret += *(const unsigned *)d; + ret = (ret << 3) & (ret >> 29); + l--; + d += sizeof(unsigned); + } + return ret; +} + +NConfig::NConfig(int protect) +{ + fd = -1; + cname = fname = data = NULL; + sb = NULL; + cdir = NULL; + chunks = NULL; + revision = update = lsize = omode = 0; + olck = 0; + lock = NC_L_NONE; + careful = protect; +} + +NConfig::~NConfig() +{ + close(); + free(fname); +} + +void NConfig::close() +{ + free(cname); + cname = NULL; + if (fd > -1) { +#ifdef NO_MAP_SHARED + if (data) { + int size=sb->size; + char *buffer=new char[size]; + memcpy(buffer, data, size); + munmap(data, size); + data = NULL; + ::lseek(fd, 0, SEEK_SET); + ::write(fd, buffer, size); + delete[] buffer; + } +#endif + ::close(fd); + fd = -1; + } + if (data) { + munmap(data, sb->size); + data = NULL; + } +} + +void NConfig::flush() +{ + close(); + open(omode); +} + +int NConfig::setName(const char *name) +{ + if (!name) + return NC_ERR_NVAL; + if (fd > -1) + return NC_ERR_PERM; + free(fname); + fname = strdup(name); + return NC_ERR_OK; +} + +int NConfig::createNew(unsigned resize, unsigned dirent, unsigned mchunks) +{ + if (fd > -1) + return NC_ERR_NVAL; + if (!access(fname, F_OK)) + return NC_ERR_PERM; + + int ff; + if ((ff = ::open(fname, O_WRONLY | O_CREAT, 0600)) == -1) + return NC_ERR_NFILE; + struct nc_sb_s bsb = {NC_SB_MAGIC, resize*PAGESIZE, + dirent, mchunks, resize, mchunks, + sizeof(struct nc_sb_s)+sizeof(struct nc_de_s)+2*sizeof(unsigned), + sizeof(struct nc_sb_s), 0}; + struct nc_de_s bde = {sizeof(struct nc_sb_s)+sizeof(struct nc_de_s), + NC_DIR, sizeof(struct nc_sb_s), 0, 0, 0}; + struct nc_chunk_s bcm; + + write(ff, &bsb, sizeof(bsb)); + write(ff, &bde, sizeof(bde)); + write(ff, "/", 2); + + lseek(ff, sizeof(unsigned)-2, SEEK_CUR); + unsigned cl = sizeof(nc_chunk_s)*mchunks+sizeof(unsigned); + write(ff, &cl, sizeof(unsigned)); + + bcm.offset = bsb.chunk + sizeof(struct nc_chunk_s)*mchunks; + bcm.size = bsb.size - bcm.offset; + + write(ff, &bcm, sizeof(bcm)); + + lseek(ff, bsb.size-1, SEEK_SET); + write(ff, "", 1); + ::close(ff); + return NC_ERR_OK; +} + + +int NConfig::open(int how) +{ + if (!fname) + return NC_ERR_NFILE; + if (how != NC_O_RO && how != NC_O_RW) + return NC_ERR_TYPE; + if (fd > -1) + close(); + + int ff; + if ((ff = ::open(fname, how)) == -1) + return NC_ERR_PERM; + + struct stat sbuf; + fstat(ff, &sbuf); + + if (!sbuf.st_size) + return NC_ERR_CORRUPT; + +#ifdef NO_MAP_SHARED + if ((data = (char *) mmap(NULL, sbuf.st_size, how == NC_O_RO ? PROT_READ : (PROT_READ|PROT_WRITE), MAP_PRIVATE, ff, 0)) == MAP_FAILED) { +#else + if ((data = (char *) mmap(NULL, sbuf.st_size, how == NC_O_RO ? PROT_READ : (PROT_READ|PROT_WRITE), MAP_SHARED, ff, 0)) == MAP_FAILED) { +#endif + ::close(ff); + return NC_ERR_NMEM; + } + if (memcmp(((struct nc_sb_s *) data)->magic, NC_SB_MAGIC, 4)) { + munmap(data, sbuf.st_size); + ::close(ff); + return NC_ERR_CORRUPT; + } + fd = ff; + omode = how; + sb = SB; + lsize = 0; + cname = strdup("/"); + + lockFile(NC_L_RO, TRUE); + rdir = DE(sb->root); + unLockFile(); + return NC_ERR_OK; +} + +void NConfig::expand(unsigned toadd) +{ + unsigned nsize = sb->size + toadd; + lseek(fd, nsize-1, SEEK_SET); + write(fd, "", 1); + _remap(sb->size, nsize); + sb->size = nsize; + cdir = getDirEnt(cname); + chunks = CM(sb->chunk); +#ifdef NC_DEBUG_ALLOC + fprintf(stderr, "Expanded from %u to %u\n", nsize-toadd, nsize); +#endif +} + +unsigned NConfig::getChunk(unsigned s) +{ + int lst = -1; + + // Make sure we get aligned data + s = alignSize(s) + sizeof(unsigned); + +#ifdef NC_DEBUG_ALLOC + fprintf(stderr, "Taking %u (total %u)\n", s, sb->chunk_ttl); +#endif + + do { + int left = 0, right = sb->chunk_ttl - 1, c; + while (left <= right) { + int diff = chunks[c = (left + right) / 2].size - s; + if (diff < 0 || diff == sizeof(unsigned)) { +#ifdef NC_DEBUG_ALLOC + if (diff > 0) + fprintf(stderr, "Rejected chunk %d (%u:%u)\n", c, chunks[c].offset, chunks[c].size); +#endif + right = c - 1; + continue; + } + lst = c; + if (!diff) + break; + left = c + 1; + } + if (lst < 0) { + unsigned ll = (s / (sb->size_inc*PAGESIZE) + 1) * PAGESIZE * sb->size_inc; + // we don't have a suitable chunk + expand(ll); + // insert new chunk into list (always succeeds) + *(unsigned *)(data+sb->size-ll) = ll; + fast_free(sb->size-ll+sizeof(unsigned)); + } + } while (lst < 0); + +#ifdef NC_DEBUG_ALLOC + fprintf(stderr, "haluz 7: off = %u size = %u\n", chunks[7].offset, chunks[7].size); + fprintf(stderr, "Got %u chunk (pos %d), taking %u\n", chunks[lst].size, lst, s); + fprintf(stderr, "chunk (%u:%u)\n", chunks[lst].offset, chunks[lst].size); +#endif + + unsigned best = chunks[lst].offset+sizeof(unsigned); + memset(data+best, 0, s-sizeof(unsigned)); + chunks[lst].size -= s; + chunks[lst].offset += s; + CS(best) = s; + + while (lst < ((signed)sb->chunk_ttl - 1) && chunks[lst].size < chunks[lst+1].size) { + unsigned b = chunks[lst].size; + unsigned i = lst + 1; + chunks[lst].size = chunks[i].size; + chunks[i].size = b; + b = chunks[lst].offset; + chunks[lst].offset = chunks[i].offset; + chunks[i].offset = b; + lst = i; + } + +#ifdef NC_DEBUG_ALLOC + fprintf(stderr, "Returned %u:%u\n", best, CS(best)); +#endif + return best; +} + +void NConfig::freeChunk(unsigned where) +{ +#ifdef NC_DEBUG_ALLOC + fprintf(stderr, "Free chunk: %u\n", CS(where)); +#endif + if (chunks[sb->chunk_ttl-2].size) { +#ifdef NC_DEBUG_ALLOC + fprintf(stderr, "Last slot available.\n"); +#endif + unsigned n = getChunk((sb->chunk_ttl+sb->chunk_inc)*sizeof(struct nc_chunk_s)); + unsigned f = sb->chunk; + memcpy(data+n, chunks, (sb->chunk_ttl-1)*sizeof(struct nc_chunk_s)); + chunks = CM(sb->chunk = n); + sb->chunk_ttl += sb->chunk_inc; + fast_free(f); + } + fast_free(where); +} + +inline unsigned NConfig::alignSize(unsigned s) +{ + unsigned of = s % sizeof(unsigned); + return of ? s + sizeof(unsigned) - of : s; +} + +void NConfig::delKey(const char *name) +{ + _delKey(name, NULL, TRUE); +} + +void NConfig::_delKey(const char *name, struct nc_de_s *p, int tosort) +{ + if (fd < 0) + return; + lockFile(NC_L_RW); + struct nc_de_s *nd = getDirEnt(name, p); + if (nd && nd != rdir && nd != cdir) { + unsigned ndo = ((char *)nd) - data; + if (nd->type == NC_DIR) + for (unsigned i=0; ipages; i++) { + struct nc_de_s *dd = IDE(nd, i); + if (dd->type) + _delKey(data+dd->name, nd, FALSE); + nd = DE(ndo); + } + sb->modtime++; + freeChunk(nd->offset); + freeChunk(DE(ndo)->name); + nd = DE(ndo); + struct nc_de_s *parent = DE(nd->parent); + memset(nd, 0, sizeof(struct nc_de_s)); + // keep parent directory sorted + if (tosort) { + unsigned i = 0; + while (i < parent->pages && IDE(parent, i) != nd) + i++; + memmove(((unsigned *)(data+parent->offset))+i, + ((unsigned *)(data+parent->offset))+i+1, + sizeof(unsigned)*(parent->pages-i-1)); + ((unsigned *)(data+parent->offset))[parent->pages-1] = ndo; + } + } + unLockFile(); +} + +int NConfig::_setKey(const char *name, const unsigned t, const char *value, const unsigned len) +{ + if (fd < 0) + return NC_ERR_NFILE; + if (omode != NC_O_RW) + return NC_ERR_RDONLY; + lockFile(NC_L_RW); + struct nc_de_s *nd = getDirEnt(name); +#ifdef NC_DEBUG_INSERT + fprintf(stderr, "Found DE %p\n", nd); +#endif + if (!nd) { + struct nc_de_s *sd = *name == '/' ? rdir : cdir; + char *parse = canonize(name), *p = parse; + + while ((nd = getDirEnt(p, sd))) + if (nd->type == NC_DIR) { + sd = nd; + p += strlen(p)+1; + } else { + free(parse); + unLockFile(); + return NC_ERR_PERM; + } + + size_t pl = 0; + struct nc_de_s ds; + unsigned sdo = ((char *)sd) - data; + while (*(p+(pl = strlen(p)+1))) { + ds.pages = ds.offset = 0; + ds.name = getChunk(pl); + memcpy(data+ds.name, p, pl); + ds.type = NC_DIR; +#ifdef NC_DEBUG_INSERT + fprintf(stderr, "Insertion parent 2: %p\n", DE(sdo)); +#endif + // FIXME: crc calculation + sdo = ((char *)insert(sdo, &ds)) - data; + p += pl; + } + ds.type = t; + memcpy(data+(ds.name = getChunk(pl)), p, pl); + ds.pages = ds.offset = 0; +#ifdef NC_DEBUG_INSERT + fprintf(stderr, "Insertion parent 1: %p\n", DE(sdo)); +#endif + nd = insert(sdo, &ds); + sb->modtime++; + free(parse); + } else + if (nd->type != t) { + unLockFile(); + return NC_ERR_TYPE; + } + unsigned ndo = ((char *)nd) - data; + if (t != NC_DIR) { + if (value) { + if (nd->offset && CS(nd->offset)-sizeof(unsigned) < len) { + freeChunk(nd->offset); + nd = DE(ndo); + nd->offset = 0; + } + if (nd->offset) { + if (CS(nd->offset)-sizeof(unsigned) > alignSize(len)+sizeof(unsigned)) { + unsigned trim = CS(nd->offset) - alignSize(len) - sizeof(unsigned); + unsigned off = nd->offset + alignSize(len) + sizeof(unsigned); + CS(off) = trim; + CS(nd->offset) -= trim; + freeChunk(off); + nd = DE(ndo); + } + } else { + unsigned off = getChunk(len); + nd = DE(ndo); + nd->offset = off; + } + memcpy(data+nd->offset, value, len); + nd->pages = len; + } else + if (nd->offset) { + freeChunk(nd->offset); + DE(ndo)->offset = 0; + } + } else + // Preallocate pages for directory + if (len > nd->pages) { + unsigned off = getChunk(sizeof(unsigned)*len); + if (DE(ndo)->offset) { + memcpy(data+off, data+DE(ndo)->offset, sizeof(unsigned)*(DE(ndo)->pages)); + freeChunk(DE(ndo)->offset); + } + DE(ndo)->offset = off; + for (unsigned al = len - DE(ndo)->pages; al; al--) { + off = getChunk(sizeof(struct nc_de_s)); + ((unsigned *)(data+DE(ndo)->offset))[DE(ndo)->pages++] = off; + } + } + unLockFile(); +#ifdef NC_DEBUG_INSERT + fprintf(stderr, "%p\n", cdir); +#endif + return NC_ERR_OK; +} + +char *NConfig::getName(const struct nc_de_s *w) +{ + if (w == rdir) + return strdup("/"); + char *parent = getName(DE(w->parent)); + unsigned l1 = strlen(parent); + unsigned l2 = strlen(data+w->name)+1; + + parent = (char *) realloc(parent, l1 + l2 + (l1 == 1 ? 0 : 1)); + if (l1 != 1) { + memcpy(parent+l1, "/", 2); + l1++; + } + memcpy(parent+l1, data+w->name, l2); + return parent; +} + +int NConfig::chDir(const char *name) +{ + if (fd < 0) + return NC_ERR_NFILE; + lockFile(NC_L_RO); + + int ret = NC_ERR_OK; + struct nc_de_s *nd = getDirEnt(name); + if (nd) { + if (nd->type == NC_DIR) { + cdir = nd; + free(cname); + cname = getName(cdir); + } else + ret = NC_ERR_NDIR; + } else + ret = NC_ERR_NEXIST; + unLockFile(); + return ret; +} + +const char *NConfig::pwDir() +{ + if (fd < 0) + return NULL; + lockFile(NC_L_RO); + struct nc_de_s *l = cdir; + char * ret = strdup(data+l->name); + while (DE(l->parent) != l) { + unsigned len = CS(l->name); + char *r = (char *) malloc(strlen(ret) + len + 2); + memcpy(r, data+l->name, len); + if (*ret != '/' && DE(l->parent) != rdir) + strcat(r, "/"); + strcat(r, ret); + free(ret); + ret = r; + l = DE(l->parent); + } + unLockFile(); + return ret; +} + +struct nc_de_s *NConfig::getDirEnt(const char *name, struct nc_de_s *cc) +{ + struct nc_de_s *ret = cc ? cc : ((*name == '/') ? rdir : cdir); + char *c = canonize(name), *can; + + if (!(can = c)) + return ret; + while (*c) { + if (!strcmp(c, "..")) + ret = DE(ret->parent); + else + if (strcmp(c, ".")) { + struct nc_de_s *re = ret; + int left = 0, right = ret->pages-1, p, r; + + ret = NULL; + while (left <= right) { + p = (left + right) / 2; + r = strcmp(c, data+IDE(re, p)->name); + if (r < 0) { + left = p + 1; + continue; + } + if (!r) { + ret = IDE(re, p); + break; + } + right = p - 1; + } + } + c += strlen(c)+1; + if (!ret || (*c && ret->type != NC_DIR)) { + ret = NULL; + break; + } + } + free(can); + return ret; +} + +char *NConfig::canonize(const char *name) +{ + if (*name == '/') + name++; + size_t i = strlen(name); + char *ret = (char *)calloc(1, i+3); + memcpy(ret, name, i); + for (size_t j=0; jname, what->type); +#endif + struct nc_de_s *w = DE(where); + if (!DE(where)->offset || IDE(w, w->pages-1)->type) { + unsigned a = getChunk((w->pages+sb->ent_inc)*sizeof(unsigned)); + w = DE(where); + if (w->offset) { + memcpy(data+a, data+w->offset, w->pages*sizeof(unsigned)); + freeChunk(w->offset); + w = DE(where); + } + w->offset = a; + for (unsigned ha = 0; haent_inc; ha++) { + unsigned off = getChunk(sizeof(struct nc_de_s)); + w = DE(where); + ((unsigned *)(data+w->offset))[w->pages] = off; + w->pages++; + } + } + int i = 0, l = 0, r = w->pages - 1, c; + while (l <= r) { + c = (l + r) / 2; + if (!IDE(w, c)->type || strcmp(data+what->name, data+IDE(w, c)->name) > 0) { + i = c; + r = c - 1; + } else + l = c + 1; + } + +#ifdef NC_DEBUG_INSERT + fprintf(stderr, "Insertion to slot %u (%s)\n", i, data+what->name); +#endif + what->parent = where; + unsigned to = ((unsigned *)(data+w->offset))[w->pages-1]; + memmove(((unsigned *)(data+w->offset))+i+1, ((unsigned *)(data+w->offset))+i, sizeof(unsigned)*(w->pages-i-1)); + ((unsigned *)(data+w->offset))[i] = to; + void *ret = memcpy(DE(to), what, sizeof(struct nc_de_s)); + sb->modtime++; + return (struct nc_de_s *)ret; +} + +void NConfig::status() +{ + if (fd < 0) + return; + lockFile(NC_L_RO); + fprintf(stderr, "Size:\t%u\n", sb->size); + unsigned low=0, hi=chunks[0].size, cnt=0, ttl=0; + for (unsigned i=0; ichunk_ttl; i++) + if (chunks[i].size > 0) { + if (!low || low > chunks[i].size) + low = chunks[i].size; + ttl += chunks[i].size; + cnt++; + } + unLockFile(); + fprintf(stderr, "Free:\t%u in %u chunk%s\n", ttl, cnt, cnt > 1 ? "s" : ""); + if (cnt > 0) + fprintf(stderr, "Min:\t%u\nAvg:\t%u\nMax:\t%u\n", low, ttl / cnt, hi); +} + +struct nc_ls_s *NConfig::ls(const char *name) +{ + if (fd < 0) + return NULL; + lockFile(NC_L_RO); + + struct nc_ls_s *rt = NULL; + unsigned count = 0; + struct nc_de_s *de = NULL; + struct nc_de_s *ds = name ? getDirEnt(name) : cdir; + + if (ds && ds->type == NC_DIR) { + for (unsigned i=0; ipages; i++) { + de = IDE(ds, i); + if (de->type && de->name) { + rt = (struct nc_ls_s *) realloc(rt, (count+2)*sizeof(nc_ls_s)); + rt[count].type = de->type; + rt[count].name = strdup(data+de->name); + rt[++count].type = 0; + rt[count].name = NULL; + } + } + } + unLockFile(); + return rt; +} + +void NConfig::fast_free(unsigned offset) +{ + unsigned s = CS(offset), i = 0; + offset -= sizeof(unsigned); + + while (1) { + if (!chunks[i].size) { +#ifdef NC_DEBUG_ALLOC + fprintf(stderr, "Inserting %u:%u to %u\n", offset, s, i); +#endif + chunks[i].offset = offset; + chunks[i].size = s; + break; + } + if (chunks[i].offset == offset + s) { +#ifdef NC_DEBUG_ALLOC + fprintf(stderr, "Prepending %u:%u to %u (%u:%u)\n", offset, s, i, chunks[i].offset, chunks[i].size); +#endif + chunks[i].offset -= s; + chunks[i].size += s; + break; + } + if (offset == chunks[i].offset + chunks[i].size) { +#ifdef NC_DEBUG_ALLOC + fprintf(stderr, "Appending %u:%u to %u (%u:%u)\n", offset, s, i, chunks[i].offset, chunks[i].size); +#endif + chunks[i].size += s; + break; + } + i++; + } + + // Keep the array sorted + while (i && chunks[i].size > chunks[i-1].size) { + unsigned b = chunks[i].size; + unsigned j = i - 1; + chunks[i].size = chunks[j].size; + chunks[j].size = b; + b = chunks[i].offset; + chunks[i].offset = chunks[j].offset; + chunks[j].offset = b; + i = j; + } +} + +int NConfig::renameKey(const char *oldname, const char *newname) +{ + if (fd < 0) + return NC_ERR_NFILE; + if (omode != NC_O_RW) + return NC_ERR_RDONLY; + lockFile(NC_L_RW); + int ret = NC_ERR_OK; + struct nc_de_s *parent, *nd = getDirEnt(newname); + if (nd) { + if ((nd = getDirEnt(oldname))) { + size_t len = strlen(newname)+1; + int inc = strcmp(oldname, newname); + unsigned i, off, pos, ndo = ((char *)nd) - data; + if (alignSize(len) != CS(nd->name)) { + freeChunk(nd->name); + off = getChunk(len); + DE(ndo)->name = off; + nd = DE(ndo); + } + memcpy(data+nd->name, newname, len); + parent = DE(nd->parent); + for (pos = 0; pos < parent->pages && IDE(parent, pos) != nd; pos++) + ; + for (i = pos; i>=0 && ipages; i += inc) + if (strcmp(data+IDE(parent, i)->name, newname) != inc) + break; + if (inc == -1) + memmove(((unsigned *)(data+parent->offset))+i+1, + ((unsigned *)(data+parent->offset))+i, + sizeof(unsigned)*(pos - i)); + else + memmove(((unsigned *)(data+parent->offset))+pos, + ((unsigned *)(data+parent->offset))+pos+1, + sizeof(unsigned)*(i-pos)); + ((unsigned *)(data+parent->offset))[i] = ndo; + sb->modtime++; + } else + ret = NC_ERR_NEXIST; + } else + ret = NC_ERR_PERM; + unLockFile(); + return NC_ERR_OK; +} + +int NConfig::createDir(const char *name, unsigned entries) +{ + return _setKey(name, NC_DIR, NULL, entries); +} + +int NConfig::setKey(const char *name, const unsigned long long value) +{ + return _setKey(name, NC_UINT, (const char *)&value, sizeof(value)); +} + +int NConfig::setKey(const char *name, const unsigned value) +{ + unsigned long long b = value; + return _setKey(name, NC_UINT, (const char *)&b, sizeof(b)); +} + +int NConfig::setKey(const char *name, const signed long long value) +{ + return _setKey(name, NC_INT, (const char *)&value, sizeof(value)); +} + +int NConfig::setKey(const char *name, const int value) +{ + signed long long b = value; + return _setKey(name, NC_INT, (const char *)&b, sizeof(b)); +} + +int NConfig::setKey(const char *name, const char *value) +{ + return _setKey(name, NC_STRING, value, strlen(value)+1); +} + +int NConfig::setKey(const char *name, const long double value) +{ + return _setKey(name, NC_DOUBLE, (const char *)&value, sizeof(value)); +} + +int NConfig::setKey(const char *name, const double value) +{ + long double b = value; + return _setKey(name, NC_DOUBLE, (const char *)&b, sizeof(b)); +} + +int NConfig::setKey(const char *name, const char *value, const unsigned len) +{ + if (!value && len) + return NC_ERR_NVAL; + if (!len) + return _setKey(name, NC_RAW, NULL, 0); + return _setKey(name, NC_RAW, value, len); +} + +int NConfig::getKey(const char *name, unsigned long long &value) +{ + if (fd < 0) + return NC_ERR_NFILE; + lockFile(NC_L_RO); + int ret = NC_ERR_OK; + struct nc_de_s *k = getDirEnt(name); + if (k) { + if (k->type == NC_UINT) { + memcpy(&value, data+k->offset, sizeof(value)); + } else + ret = NC_ERR_TYPE; + } else + ret = NC_ERR_NEXIST; + unLockFile(); + return ret; +} + +int NConfig::getKey(const char *name, unsigned &value) +{ + if (fd < 0) + return NC_ERR_NFILE; + lockFile(NC_L_RO); + int ret = NC_ERR_OK; + struct nc_de_s *k = getDirEnt(name); + if (k) { + if (k->type == NC_UINT) { + unsigned long long b; + memcpy(&b, data+k->offset, sizeof(b)); + value = b; + } else + ret = NC_ERR_TYPE; + } else + ret = NC_ERR_NEXIST; + unLockFile(); + return ret; +} + +int NConfig::getKey(const char *name, long double &value) +{ + if (fd < 0) + return NC_ERR_NFILE; + lockFile(NC_L_RO); + int ret = NC_ERR_OK; + struct nc_de_s *k = getDirEnt(name); + if (k) { + if (k->type == NC_DOUBLE) { + memcpy(&value, data+k->offset, sizeof(value)); + } else + ret = NC_ERR_TYPE; + } else + ret = NC_ERR_NEXIST; + unLockFile(); + return ret; +} + +int NConfig::getKey(const char *name, double &value) +{ + if (fd < 0) + return NC_ERR_NFILE; + lockFile(NC_L_RO); + int ret = NC_ERR_OK; + struct nc_de_s *k = getDirEnt(name); + if (k) { + if (k->type == NC_DOUBLE) { + long double b; + memcpy(&b, data+k->offset, sizeof(b)); + value = b; + } else + ret = NC_ERR_TYPE; + } else + ret = NC_ERR_NEXIST; + unLockFile(); + return ret; +} + +int NConfig::getKey(const char *name, signed long long &value) +{ + if (fd < 0) + return NC_ERR_NFILE; + lockFile(NC_L_RO); + int ret = NC_ERR_OK; + struct nc_de_s *k = getDirEnt(name); + if (k) { + if (k->type == NC_INT) { + memcpy(&value, data+k->offset, sizeof(value)); + } else + ret = NC_ERR_TYPE; + } else + ret = NC_ERR_NEXIST; + unLockFile(); + return ret; +} + +int NConfig::getKey(const char *name, int &value) +{ + if (fd < 0) + return NC_ERR_NFILE; + lockFile(NC_L_RO); + int ret = NC_ERR_OK; + struct nc_de_s *k = getDirEnt(name); + if (k) { + if (k->type == NC_INT) { + signed long long b; + memcpy(&b, data+k->offset, sizeof(b)); + value = b; + } else + ret = NC_ERR_TYPE; + } else + ret = NC_ERR_NEXIST; + unLockFile(); + return ret; +} + +int NConfig::getKey(const char *name, char *&value) +{ + if (fd < 0) + return NC_ERR_NFILE; + lockFile(NC_L_RO); + int ret = NC_ERR_OK; + struct nc_de_s *k = getDirEnt(name); + if (k) { + if (k->type == NC_STRING) { + if (k->offset) { + if (!(value = strdup(data+k->offset))) + ret = NC_ERR_NMEM; + } else + value = NULL; + } else + ret = NC_ERR_TYPE; + } else + ret = NC_ERR_NEXIST; + unLockFile(); + return ret; +} + +int NConfig::getKey(const char *name, char *&value, unsigned &len) +{ + if (fd < 0) + return NC_ERR_NFILE; + lockFile(NC_L_RO); + int ret = NC_ERR_OK; + struct nc_de_s *k = getDirEnt(name); + if (k) { + if (k->type == NC_RAW) { + if (k->offset) { + len = k->pages; + value = (char *)malloc(len); + memcpy(value, data+k->offset, len); + } else { + len = 0; + value = NULL; + } + } else + ret = NC_ERR_TYPE; + } else + ret = NC_ERR_NEXIST; + unLockFile(); + return ret; +} + +void NConfig::lockFile(int type, int force) +{ +#ifdef NC_DEBUG_LOCK + fprintf(stderr, "Lock called type=%d force=%d lock=%d olck=%u\n", type, force, lock, olck); +#endif + if (lock == NC_L_RO && type == NC_L_RW) { + fprintf(stderr, "Lock promotion is not possible.\n"); + abort(); + } + if (lock != NC_L_NONE) { + olck++; + return; + } + + struct flock flc = { type == NC_L_RW ? F_WRLCK : F_RDLCK, SEEK_SET, 0, 0, 0 }; + while (fcntl(fd, F_SETLKW, &flc)) { + sched_yield(); + flc.l_type = type == NC_L_RW ? F_WRLCK : F_RDLCK; + flc.l_whence = SEEK_SET; + flc.l_len = flc.l_start = 0; + } + +#ifdef NC_DEBUG_LOCK + fprintf(stderr, "Locked %u %u %s\n", sb->modtime, update, force ? "forced." : ""); +#endif + if (careful && type == NC_L_RW) + mprotect(data, sb->size, PROT_READ | PROT_WRITE); + lock = type; + olck = 0; + if (sb->modtime != update || force) { + // refresh memory mapping + if (lsize != sb->size) { + _remap(lsize, sb->size); + lsize = sb->size; + chunks = CM(sb->chunk); + } + cdir = getDirEnt(cname); + update = sb->modtime; + } +} + +void NConfig::unLockFile() +{ +#ifdef NC_DEBUG_LOCK + fprintf(stderr, "UnLock called lock=%u olck=%u\n", lock, olck); +#endif + if (olck) { + olck--; + return; + } + if (lock == NC_L_NONE) + return; + struct flock flc = {F_UNLCK, SEEK_SET, 0, 0, 0 }; + update = sb->modtime; +#ifdef NC_DEBUG_LOCK + fprintf(stderr, "Unlock %u\n", update); +#endif + if (careful) + mprotect(data, sb->size, PROT_READ); + fcntl(fd, F_SETLK, &flc); + lock = NC_L_NONE; + olck = 0; +} + +void NConfig::_remap(const size_t osize, const size_t nsize) +{ + data = (char *) mremap(data, osize, nsize, 1); + if (data == MAP_FAILED) { + perror("mremap"); + abort(); + } + sb = SB; + rdir = DE(sb->root); +} + +char * NConfig::version() +{ + return strdup("EliteDVB registry"); +} + diff --git a/lib/base/nconfig.h b/lib/base/nconfig.h new file mode 100644 index 00000000..12a3c6c4 --- /dev/null +++ b/lib/base/nconfig.h @@ -0,0 +1,392 @@ +#ifndef NC_NCONFIG_H +#define NC_NCONFIG_H 1 + +#include +#include + +/* + * Superblock definitions + */ +#define NC_SB_MAGIC ("\0\11\22") // Superblock identifier + +/* + * Key type definitions + */ +#define NC_DIR 0x01 // The key is a directory +#define NC_STRING 0x02 // The key contains a string +#define NC_INT 0x03 // The key contains a signed integer +#define NC_UINT 0x04 // The key contains an unsigned integer +#define NC_RAW 0x05 // The key contains raw data +#define NC_DOUBLE 0x06 // The key contains a double +#define NC_LINK 0x07 // The key points somewhere else + +/* + * File access definitions + */ +#define NC_O_RO 0x01 // Open file in read-only mode +#define NC_O_RW 0x02 // Open file in read-write mode + +/* + * Lock types + */ +#define NC_L_NONE 0x00 // No lock +#define NC_L_RO 0x01 // Read-only lock +#define NC_L_RW 0x02 // Read-write lock + +/* + * Error codes + */ +#define NC_ERR_OK 0 // Everything is OK +#define NC_ERR_TYPE -1 // Type mismatch +#define NC_ERR_NDIR -2 // Key is not a directory +#define NC_ERR_PERM -3 // Operation is not allowed +#define NC_ERR_NMEM -4 // Not enough memory to complete operation +#define NC_ERR_NEXIST -5 // Key does not exist +#define NC_ERR_NFILE -6 // No file is assigned/open +#define NC_ERR_CORRUPT -7 // File is corrupted +#define NC_ERR_NVAL -8 // Invalid value +#define NC_ERR_RDONLY -9 // File is open in read-only mode +#define NC_ERR_NOSUPPORT -10 // Support is not compiled-in + +/* + * Truth value definitions + */ +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* + * Header of the config file. + */ +struct nc_sb_s { + char magic[4]; // superblock magic + unsigned size; // Current file size + unsigned ent_inc; // directory increment + unsigned chunk_inc; // Memory chunks increment + unsigned size_inc; // file size increment + unsigned chunk_ttl; // size of chunkmap + unsigned chunk; // pointer to chunkmap + unsigned root; // pointer to root direntry + unsigned modtime; // file version +}; + +/* + * Free chunk descriptor + */ +struct nc_chunk_s { + unsigned offset; + unsigned size; +}; + +/* + * In-file directory entry + */ +struct nc_de_s { + unsigned name; + unsigned type; + unsigned parent; + unsigned offset; + unsigned pages; + unsigned crc; +}; + +/* + * Ls reporting + */ +struct nc_ls_s { + const char *name; + unsigned type; +}; + +class NConfig +{ +public: + /* + * Class constructor + * pass TRUE as parameter to enable + * write protection when leaving library + */ + NConfig(int protect = FALSE); + virtual ~NConfig(); + + /* + * Set file name (prior to open) + * Errors: + * NC_ERR_PERM file is already open + * NC_ERR_NVAL no file name is given + */ + int setName(const char *name); + + /* + * Open the configuration file, re-open it + * Errors: + * NC_ERR_NFILE no file name is assigned + * NC_ERR_TYPE file open mode is invalid + * NC_ERR_PERM file cannot be opened/created + * NC_ERR_NMEM unable to mmap the file + * NC_ERR_CORRUPT superblock magic mismatch + */ + int open(const int how = NC_O_RW); + + /* + * Close the configuration file + * No errors defined + */ + void close(); + + void flush(); // flush file if not mmap'ed + + /* + * Create a new file + * resize is filesize increment is system pages + * dirent is directory increment + * mchunks is memory block increment + * Errors: + * NC_ERR_PERM file already exists + * NC_ERR_NFILE cannot create new file + * NC_ERR_NVAL file is already open + */ + int createNew(unsigned resize = 4, unsigned dirent = 32, unsigned mchunks = 32); + + /* + * Get an unsigned integer + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_NEXIST the key does not exist + * NC_ERR_TYPE the key exists, but is of different type + */ + int getKey(const char *name, unsigned &value); + int getKey(const char *name, unsigned long long &value); + + /* + * Get a signed integer + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_NEXIST the key does not exist + * NC_ERR_TYPE the key exists, but is of different type + */ + int getKey(const char *name, int &value); + int getKey(const char *name, signed long long &value); + + /* + * Get a string + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_NEXIST the key does not exist + * NC_ERR_TYPE the key exists, but is of different type + */ + int getKey(const char *name, char *&value); + + /* + * Get a long double + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_NEXIST the key does not exist + * NC_ERR_TYPE the key exists, but is of different type + */ + int getKey(const char *name, double &value); + int getKey(const char *name, long double &value); + + /* + * Get raw data + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_NEXIST the key does not exist + * NC_ERR_TYPE the key exists, but is of different type + */ + int getKey(const char *name, char *&value, unsigned &len); + + /* + * Insert an unsigned integer + * NC_ERR_NFILE no file is open + * NC_ERR_RDONLY file is open in read-only mode + * NC_ERR_PERM intermediate key is not a directory + * NC_ERR_TYPE key already exists, but is not an usigned integer + * NC_ERR_NEXIST key does not exist (should NEVER happen) + */ + int setKey(const char *name, const unsigned value); + int setKey(const char *name, const unsigned long long value); + + /* + * Insert an integer + * NC_ERR_NFILE no file is open + * NC_ERR_RDONLY file is open in read-only mode + * NC_ERR_PERM intermediate key is not a directory + * NC_ERR_TYPE key already exists, but is not a signed integer + * NC_ERR_NEXIST key does not exist (should NEVER happen) + */ + int setKey(const char *name, const int value); + int setKey(const char *name, const signed long long value); + + /* + * Insert a string + * NC_ERR_NFILE no file is open + * NC_ERR_RDONLY file is open in read-only mode + * NC_ERR_PERM intermediate key is not a directory + * NC_ERR_TYPE key already exists, but is not a string + * NC_ERR_NEXIST key does not exist (should NEVER happen) + */ + int setKey(const char *name, const char *value); + + /* + * Insert raw data + * NC_ERR_NFILE no file is open + * NC_ERR_RDONLY file is open in read-only mode + * NC_ERR_PERM intermediate key is not a directory + * NC_ERR_TYPE key already exists, but is not raw data + * NC_ERR_NEXIST key does not exist (should NEVER happen) + */ + int setKey(const char *name, const char *value, const unsigned len); + + /* + * Insert a double + * NC_ERR_NFILE no file is open + * NC_ERR_RDONLY file is open in read-only mode + * NC_ERR_PERM intermediate key is not a directory + * NC_ERR_TYPE key already exists, but is not raw data + * NC_ERR_NEXIST key does not exist (should NEVER happen) + */ + int setKey(const char *name, const double value); + int setKey(const char *name, const long double value); + + /* + * Rename a key + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_RDONLY file is open read-only + * NC_ERR_NEXIST the key does not exist + * NC_ERR_PERM key with specified name already exists + */ + int renameKey(const char *oldname, const char *newname); + + /* + * Delete a key + * No errors defined + */ + void delKey(const char *name); + + /* + * Create a directory + * entries parameter specifies number of direntries to preallocate + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_RDONLY file is open in read-only mode + * NC_ERR_PERM intermediate key is not a directory + * NC_ERR_TYPE key already exists, but is not a directory + * NC_ERR_NEXIST key does not exist (should NEVER happen) + */ + int createDir(const char *name, unsigned entries = 0); + + /* + * Change working directory + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_NDIR target key is not a directory + * NC_ERR_NEXIST target key direcotry does not exist + */ + int chDir(const char *name); + + /* + * Print working directory + * Errors: + * Returns NULL on error + */ + const char *pwDir(); + + /* + * List all keys in current/specified directory + * Result is a NULL-terminated array of nc_ls_s + * structures. + * Errors: + * Returns NULL on error + * Note: + * You need to free the returned pointer, + * as well as all the names in it. + */ + struct nc_ls_s *ls(const char *dir = NULL); + + /* + * Lock file + * This will block until lock becomes available + * type is either: + * NC_L_RO for read-only lock + * NC_L_RW for read-write lock + * No errors defined + * + * NOTE: lock may get promoted + */ + void lockFile(int type, int force = FALSE); + + /* + * Unlock file + * No errors defined + */ + void unLockFile(); + + /* + * Print out (to stderr) information about current file + * No errors defined + */ + void status(); + + /* + * Return version string + */ + static char *version(); + + /* + * Dump current file to XML + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_PERM could not write XML output + */ + int toXML(const char *filename); + + /* + * Load XML to current file + * a file has to be open + * force can be + * TRUE - existing keys will be deleted + * FALSE - import will ignore a key if existing key type conflicts + * Errors: + * NC_ERR_NFILE no file is open + * NC_ERR_PERM file is open read-only + */ + int fromXML(const char *filename, int force = TRUE); + +protected: + int fd, omode, lock, careful; + char *fname, *data, *cname; + unsigned lsize, update; + unsigned revision, olck; + struct nc_sb_s *sb; + struct nc_de_s *rdir, *cdir; + struct nc_chunk_s *chunks; + + int _setKey(const char *, const unsigned, const char *, const unsigned); + void _delKey(const char *, struct nc_de_s *, int); + void expand(unsigned); + + void fast_free(unsigned); + + unsigned getChunk(unsigned); + void freeChunk(unsigned); + static inline unsigned alignSize(unsigned); + + struct nc_de_s *getDirEnt(const char *, struct nc_de_s * = NULL); + struct nc_de_s *insert(unsigned, struct nc_de_s *); + char *canonize(const char *); + char *getName(const struct nc_de_s *); + + void _remap(const size_t, const size_t); + + inline unsigned crc(const char *, unsigned); + void store(nc_de_s *, FILE *); + void restore(void *, int); +}; + +#endif /* NC_NCONFIG_H */ + diff --git a/lib/base/nxml.cpp b/lib/base/nxml.cpp new file mode 100644 index 00000000..f32880a6 --- /dev/null +++ b/lib/base/nxml.cpp @@ -0,0 +1,339 @@ +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_LIBXML2 +#include +#include +#include +#else +#define xmlChar char +#endif /* HAVE_LIBXML2 */ + +#define DE(x) ((struct nc_de_s *) (data+(x))) +#define IDE(x, y) (DE(((unsigned *) (data+(x)->offset))[(y)])) +#define XML_DE ((const xmlChar *) "dirEntry") +#define XML_NS ((const xmlChar *) "http://hq.alert.sk/projects/nconfig") +#define XML_ROOT ((const xmlChar *) "NConfigExport") + +static char *encodeXml(const char *what) +{ + unsigned p = 0, size = 6*strlen(what)+1; + char *ret = (char *)malloc(size); + for (; *what; what++) { + switch (*what) { + case '"': + ret[p++] = '&'; + ret[p++] = 'q'; + ret[p++] = 'u'; + ret[p++] = 'o'; + ret[p++] = 't'; + ret[p++] = ';'; + continue; + case '>': + ret[p++] = '&'; + ret[p++] = 'q'; + ret[p++] = 't'; + ret[p++] = ';'; + continue; + case '<': + ret[p++] = '&'; + ret[p++] = 'l'; + ret[p++] = 't'; + ret[p++] = ';'; + continue; + case '&': + ret[p++] = '&'; + ret[p++] = 'a'; + ret[p++] = 'm'; + ret[p++] = 'p'; + ret[p++] = ';'; + continue; + } + if (*what >= 0x20 || *what == '\n' || *what == '\r' || *what == '\t') + ret[p++] = *what; + else + p += sprintf(ret+p, "&#%d;", *what); + } + ret[p] = '\0'; + return ret; +} + +void NConfig::store(nc_de_s *de, FILE *f) +{ + struct nc_de_s *cc; + for (unsigned i=0; ipages; i++) + if ((cc = IDE(de, i))->type) { + char *encname = encodeXml(data+cc->name); + fprintf(f, "type); + free(encname); + switch (cc->type) { + case NC_DIR: + fprintf(f, "%u\">\n", cc->pages); + store(cc, f); + fprintf(f, "\n", XML_DE); + break; + case NC_STRING: + fprintf(f, "%s\"/>\n", encname = encodeXml(data+cc->offset)); + free(encname); + break; + case NC_INT: + fprintf(f, "%lld\"/>\n", *((signed long long *) (data+cc->offset))); + break; + case NC_UINT: + fprintf(f, "%llu\"/>\n", *((unsigned long long *) (data+cc->offset))); + break; + case NC_DOUBLE: + fprintf(f, "%La\"/>\n", *((long double *) (data+cc->offset))); + break; + case NC_RAW: + { + const char *raw = data+cc->offset; + for (unsigned j=0; jpages; j++) + fprintf(f, "%d%d%d", raw[j] / 100, (raw[j] % 100) / 10, raw[j] % 10); + fprintf(f, "\"/>\n"); + } + } + } +} + +int NConfig::toXML(const char *filename) +{ + if (fd < 0) + return NC_ERR_NFILE; + + FILE *f = fopen(filename, "w"); + if (!f) + return NC_ERR_PERM; + + fprintf(f, "%s", "\n"); + fprintf(f, "\n"); + lockFile(NC_L_RO); + + store(rdir, f); + + unLockFile(); + fprintf(f, "\n", XML_ROOT); + fclose(f); + return NC_ERR_OK; +} + +#ifdef HAVE_LIBXML2 +static xmlSAXHandler sh; +enum stateEnum {noRoot = 0, inRoot, inDir, inEnt, unknown}; + +struct ncParseState { + stateEnum state, pState; + xmlChar *ns; + unsigned depth; + unsigned unDepth; + unsigned force; + NConfig *which; +}; + +static int ncXmlSAXParseFile(xmlSAXHandlerPtr sax, void *user_data, const char *filename) +{ + int ret = 0; + xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename); + if (!ctxt) + return -1; + ctxt->sax = sax; + ctxt->userData = user_data; + xmlParseDocument(ctxt); + ret = ctxt->wellFormed ? 0 : -1; + if (sax) + ctxt->sax = NULL; + xmlFreeParserCtxt(ctxt); + return ret; +} + +static xmlEntityPtr ncXmlGetEntity(void *user_data, const CHAR *name) +{ + return xmlGetPredefinedEntity(name); +} + +static void ncXmlStartElement(void *user_data, const CHAR *name, const CHAR **attrs) +{ + struct ncParseState *p = (struct ncParseState *)user_data; +#ifdef NC_DEBUG_XML + fprintf(stderr, "New element %s state=%d %s\n", name, p->state, p->ns); +#endif + if (p->state == unknown) { + p->unDepth++; + return; + } + if (p->state == noRoot) { + while (*attrs) { + if (!xmlStrncmp(*attrs, (const xmlChar *) "xmlns:", 6)) { + if (!xmlStrcmp(attrs[1], XML_NS)) { + p->ns = xmlStrdup((*attrs)+6); + break; + } + } + attrs += 2; + } + char *b = (char *) malloc(xmlStrlen(p->ns)+xmlStrlen(XML_ROOT)+2); + sprintf(b, "%s:%s", p->ns, XML_ROOT); + if (xmlStrcmp(name, (xmlChar *)b)) { +#ifdef NC_DEBUG_XML + fprintf(stderr, "NewElement, entering unknown %s\n", name); +#endif + p->pState = p->state; + p->state = unknown; + } else + p->state = inRoot; + free(b); + return; + } + if (p->state == inRoot || p->state == inDir) { + const xmlChar *value = NULL, *n = NULL; + int type = 0; + while (*attrs) { + if (!xmlStrcmp(*attrs, (const xmlChar *)"value")) + value = attrs[1]; + if (!xmlStrcmp(*attrs, (const xmlChar *)"name")) + n = attrs[1]; + if (!xmlStrcmp(*attrs, (const xmlChar *)"type")) + type = atoi(attrs[1]); + attrs += 2; + } +#ifdef NC_DEBUG_XML + fprintf(stderr, "%s %s %s %d %d\n", name, n, value, type, p->state); +#endif + char *b = (char *) malloc(xmlStrlen(p->ns)+xmlStrlen(XML_DE)+2); + sprintf(b, "%s:%s", p->ns, XML_DE); + if (xmlStrcmp(name, (xmlChar *)b) || !type || !value || !n) { +#ifdef NC_DEBUG_XML + fprintf(stderr, "NewElement, entering unknown on mismatch\n"); +#endif + p->pState = p->state; + p->state = unknown; + free(b); + return; + } + free(b); + if (p->force) + p->which->delKey((const char *)n); + + switch (type) { + case NC_DIR: + if (p->which->createDir((const char *)n, strtoul((const char *)value, NULL, 0)) != NC_ERR_OK) { + p->pState = p->state; + p->state = unknown; +#ifdef NC_DEBUG_XML + fprintf(stderr, "NewElement, entering unknown on failed mkdir\n"); +#endif + return; + } + p->which->chDir((const char *)n); + break; + case NC_STRING: + p->which->setKey((const char *)n, (const char *)value); + break; + case NC_INT: + p->which->setKey((const char *)n, strtoll((const char *)value, NULL, 0)); + break; + case NC_UINT: + p->which->setKey((const char *)n, strtoull((const char *)value, NULL, 0)); + break; + case NC_DOUBLE: + { + long double c; + sscanf((const char *)value, "%La", &c); + p->which->setKey((const char *)n, c); + } + break; + case NC_RAW: + { + unsigned size = xmlStrlen(value) / 3; + char *dec = NULL; + if (size) { + dec = (char *)malloc(size); + for (unsigned i=0, k=0; iwhich->setKey((const char *)n, dec, size); + free(dec); + } + } + if (type == NC_DIR) { + p->state = inDir; + p->depth++; + } else { + p->pState = p->state; + p->state = inEnt; + } + return; + } +} + +static void ncXmlEndElement(void *user_data, const CHAR *name) +{ + struct ncParseState *p = (struct ncParseState *)user_data; +#ifdef NC_DEBUG_XML + fprintf(stderr, "EndElement %s %s %d\n", name, p->ns, p->state); +#endif + if (p->state == inEnt) { + p->state = p->pState; + return; + } + if (p->state == unknown) { + if (p->unDepth) + p->unDepth--; + else + p->state = p->pState; + return; + } + if (p->state == inRoot) { + p->state = noRoot; + free(p->ns); + p->ns = NULL; + return; + } + if (p->state == inDir) { + p->depth--; + if (!p->depth) + p->state = inRoot; + p->which->chDir(".."); + } +} +#endif /* HAVE_LIBXML2 */ + +int NConfig::fromXML(const char *filename, int force) +{ + if (fd < 0) + return NC_ERR_NFILE; + if (omode != NC_O_RW) + return NC_ERR_PERM; +#ifndef HAVE_LIBXML2 + return NC_ERR_NOSUPPORT; +#else + struct ncParseState state = { noRoot, noRoot, NULL, 0, 0, force, this }; + sh.getEntity = ncXmlGetEntity; + sh.startElement = ncXmlStartElement; + sh.endElement = ncXmlEndElement; + + lockFile(NC_L_RW); + cdir = rdir; + int ret = ncXmlSAXParseFile(&sh, &state, filename); + cdir = rdir; + unLockFile(); + + return ret < 0 ? NC_ERR_NVAL : NC_ERR_OK; +#endif /* HAVE_LIBXML2 */ +} + diff --git a/lib/base/object.h b/lib/base/object.h new file mode 100644 index 00000000..744bff19 --- /dev/null +++ b/lib/base/object.h @@ -0,0 +1,30 @@ +#ifndef __base_object_h +#define __base_object_h + +#include + +// #define OBJECT_DEBUG + +#include +#ifdef OBJECT_DEBUG +#include +#endif + +typedef int RESULT; + +class iObject +{ +public: + virtual void AddRef()=0; + virtual void Release()=0; +}; + +#define DECLARE_REF private: int ref; public: void AddRef(); void Release(); +#ifdef OBJECT_DEBUG +extern int object_total_remaining; +#define DEFINE_REF(c) void c::AddRef() { ++object_total_remaining; ++ref; eDebug("OBJECT_DEBUG " #c "+%p now %d", this, ref); } void c::Release() { --object_total_remaining; eDebug("OBJECT_DEBUG " #c "-%p now %d", this, ref-1); if (!--ref) delete this; } +#else +#define DEFINE_REF(c) void c::AddRef() { ++ref; } void c::Release() { if (!--ref) delete this; } +#endif + +#endif diff --git a/lib/base/ringbuffer.h b/lib/base/ringbuffer.h new file mode 100644 index 00000000..f2cd9058 --- /dev/null +++ b/lib/base/ringbuffer.h @@ -0,0 +1,109 @@ +#ifndef QueueRingBufferH +#define QueueRingBufferH + +template +class queueRingBuffer +{ + template + struct link + { + link ( const A &val ) + :value(val) + {} + A value; + link *nextLink; + link *prevLink; + }; + + link *lastFilled; + link *lastFree; + unsigned int max; + int count; +public: + queueRingBuffer( unsigned int max ); + ~queueRingBuffer(); + int size() { return count; } + T& queueRingBuffer::dequeue(); + T& queueRingBuffer::current(); + void queueRingBuffer::enqueue( const T &val ); +}; + +template +queueRingBuffer::queueRingBuffer( unsigned int max ) +{ + // constructor for queues based on ring buffers + // create the first link + T initialvalue; + lastFree = new link( initialvalue ); + lastFilled = lastFree; + // make value point to itself + lastFilled->nextLink = lastFilled; + lastFilled->prevLink = lastFilled; + // now add the remainder of the elements + while ( max-- > 0 ) + { + link * newLink = new link( initialvalue ); + newLink->prevLink = lastFilled; + newLink->nextLink = lastFilled->nextLink; + lastFilled->nextLink->prevLink = newLink; + lastFilled->nextLink = newLink; + } +} + +template +queueRingBuffer::~queueRingBuffer() +{ + // delete all memory associated with ring buffer + link * p = lastFree; + link * next; + + // walk around the circle deleting nodes + while( p->nextLink != lastFree ) + { + next = p->nextLink; + delete p; + p = next; + } +} + +template +T& queueRingBuffer::dequeue() +{ + // remove element form front of queue + // advance last free position + lastFree = lastFree->nextLink; + count--; + // return value stored in last free position + return lastFree->value; +} + +template +T& queueRingBuffer::current() +{ + // return value stored in current + return lastFree->nextLink->value; +} + +template +void queueRingBuffer::enqueue( const T &val ) +{ + // add new element to end of queue buffer + // first check for potential overflow + if( lastFilled->nextLink == lastFree ) + { + eDebug("increase size %d", count); + link * newLink = new link( val ); + newLink->prevLink = lastFilled; + newLink->nextLink = lastFilled->nextLink; + lastFilled->nextLink->prevLink = newLink; + lastFilled->nextLink = newLink; + } + else + { + // simply advance the last filled pointer + lastFilled = lastFilled->nextLink; + lastFilled->value = val; + } + count++; +} +#endif diff --git a/lib/base/smartptr.cpp b/lib/base/smartptr.cpp new file mode 100644 index 00000000..95269d74 --- /dev/null +++ b/lib/base/smartptr.cpp @@ -0,0 +1,2 @@ +#include "smartptr.h" +#include diff --git a/lib/base/smartptr.h b/lib/base/smartptr.h new file mode 100644 index 00000000..029fd1dc --- /dev/null +++ b/lib/base/smartptr.h @@ -0,0 +1,60 @@ +#ifndef __smartptr_h +#define __smartptr_h + +#include "object.h" +#include + +template +class ePtr +{ +protected: + T *ptr; +public: + T &operator*() { return *ptr; } + ePtr(): ptr(0) + { + } + ePtr(T *c): ptr(c) + { + if (c) + c->AddRef(); + } + ePtr(const ePtr &c) + { + ptr=c.ptr; + if (ptr) + ptr->AddRef(); + } + ePtr &operator=(T *c) + { + if (ptr) + ptr->Release(); + ptr=c; + if (ptr) + ptr->AddRef(); + return *this; + } + + ePtr &operator=(ePtr &c) + { + if (ptr) + ptr->Release(); + ptr=c.ptr; + if (ptr) + ptr->AddRef(); + return *this; + } + + ~ePtr() + { + if (ptr) + ptr->Release(); + } + T* &ptrref() { assert(!ptr); return ptr; } + T* operator->() { assert(ptr); return ptr; } + const T* operator->() const { assert(ptr); return ptr; } + operator T*() const { return this->ptr; } +}; + + +#endif diff --git a/lib/base/thread.cpp b/lib/base/thread.cpp new file mode 100644 index 00000000..4cff9259 --- /dev/null +++ b/lib/base/thread.cpp @@ -0,0 +1,34 @@ +#include +#include +#include + +void *eThread::wrapper(void *ptr) +{ + ((eThread*)ptr)->thread(); + pthread_exit(0); +} + +eThread::eThread() +{ + alive=0; +} + +void eThread::run() +{ + alive=1; + pthread_create(&the_thread, 0, wrapper, this); +} + +eThread::~eThread() +{ + if (alive) + kill(); +} + +void eThread::kill() +{ + alive=0; + eDebug("waiting for thread shutdown"); + pthread_join(the_thread, 0); + eDebug("ok"); +} diff --git a/lib/base/thread.h b/lib/base/thread.h new file mode 100644 index 00000000..56b74bed --- /dev/null +++ b/lib/base/thread.h @@ -0,0 +1,23 @@ +#ifndef __lib_base_thread_h +#define __lib_base_thread_h + +#include + +class eThread +{ + pthread_t the_thread; + static void *wrapper(void *ptr); + int alive; +public: + bool thread_running() { return alive; } + eThread(); + virtual ~eThread(); + + void run(); + + virtual void thread()=0; + + void kill(); +}; + +#endif diff --git a/lib/driver/Makefile.am b/lib/driver/Makefile.am new file mode 100644 index 00000000..eff4486f --- /dev/null +++ b/lib/driver/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = \ + -I$(top_srcdir)/include + +noinst_LIBRARIES = libenigma_driver.a + +libenigma_driver_a_SOURCES = \ + rc.cpp rcinput.cpp \ No newline at end of file diff --git a/lib/driver/Makefile.in b/lib/driver/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/lib/driver/input_fake.h b/lib/driver/input_fake.h new file mode 100644 index 00000000..7aecc9f9 --- /dev/null +++ b/lib/driver/input_fake.h @@ -0,0 +1,84 @@ +#ifndef _INPUT_FAKE_H +#define _INPUT_FAKE_H + +#include + + +#if !defined(KEY_OK) + +/** + * define some additional remote control keys in case they + * were not already defined above in + */ + +#define KEY_OK 0x160 +#define KEY_SELECT 0x161 +#define KEY_GOTO 0x162 +#define KEY_CLEAR 0x163 +#define KEY_POWER2 0x164 +#define KEY_OPTION 0x165 +#define KEY_INFO 0x166 +#define KEY_TIME 0x167 +#define KEY_VENDOR 0x168 +#define KEY_ARCHIVE 0x169 +#define KEY_PROGRAM 0x16a +#define KEY_CHANNEL 0x16b +#define KEY_FAVORITES 0x16c +#define KEY_EPG 0x16d +#define KEY_PVR 0x16e +#define KEY_MHP 0x16f +#define KEY_LANGUAGE 0x170 +#define KEY_TITLE 0x171 +#define KEY_SUBTITLE 0x172 +#define KEY_ANGLE 0x173 +#define KEY_ZOOM 0x174 +#define KEY_MODE 0x175 +#define KEY_KEYBOARD 0x176 +#define KEY_SCREEN 0x177 +#define KEY_PC 0x178 +#define KEY_TV 0x179 +#define KEY_TV2 0x17a +#define KEY_VCR 0x17b +#define KEY_VCR2 0x17c +#define KEY_SAT 0x17d +#define KEY_SAT2 0x17e +#define KEY_CD 0x17f +#define KEY_TAPE 0x180 +#define KEY_RADIO 0x181 +#define KEY_TUNER 0x182 +#define KEY_PLAYER 0x183 +#define KEY_TEXT 0x184 +#define KEY_DVD 0x185 +#define KEY_AUX 0x186 +#define KEY_MP3 0x187 +#define KEY_AUDIO 0x188 +#define KEY_VIDEO 0x189 +#define KEY_DIRECTORY 0x18a +#define KEY_LIST 0x18b +#define KEY_MEMO 0x18c +#define KEY_CALENDAR 0x18d +#define KEY_RED 0x18e +#define KEY_GREEN 0x18f +#define KEY_YELLOW 0x190 +#define KEY_BLUE 0x191 +#define KEY_CHANNELUP 0x192 +#define KEY_CHANNELDOWN 0x193 +#define KEY_FIRST 0x194 +#define KEY_LAST 0x195 +#define KEY_AB 0x196 +#define KEY_PLAY 0x197 +#define KEY_RESTART 0x198 +#define KEY_SLOW 0x199 +#define KEY_SHUFFLE 0x19a +#define KEY_FASTFORWARD 0x19b +#define KEY_PREVIOUS 0x19c +#define KEY_NEXT 0x19d +#define KEY_DIGITS 0x19e +#define KEY_TEEN 0x19f +#define KEY_TWEN 0x1a0 +#define KEY_BREAK 0x1a1 + + +#endif /* !defined(KEY_OK) */ +#endif /* _INPUT_FAKE_H */ + diff --git a/lib/driver/rc.cpp b/lib/driver/rc.cpp new file mode 100644 index 00000000..790c5f6c --- /dev/null +++ b/lib/driver/rc.cpp @@ -0,0 +1,245 @@ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * note on the enigma input layer: + * the enigma input layer (rc*) supports n different devices which + * all have completely different interfaces, mapped down to 32bit + + * make/break/release codes mapped down (via xml files) to "actions". + * this was necessary to support multiple remote controls with proprietary + * interfaces. now everybody is using input devices, and thus adding + * another input layer seems to be a bit overkill. BUT: + * image a remote control with two hundred buttons. each and every function + * in enigma can be bound to a button. no need to use them twice. + * for example, you would have KEY_MENU assigned to a menu for setup etc., + * but no audio and video settings, since you have special keys for that, + * and you don't want to display a big menu with entries that are available + * with another single key. + * then image a remote control with ten buttons. do you really want to waste + * KEY_MENU for a simple menu? you need the audio/video settings there too. + * take this just as a (bad) example. another (better) example might be front- + * button-keys. usually you have KEY_UP, KEY_DOWN, KEY_POWER. you don't want + * them to behave like the remote-control-KEY_UP, KEY_DOWN and KEY_POWER, + * don't you? + * so here we can map same keys of different input devices to different + * actions. have fun. + */ + +int eRCDevice::getKeyCompatibleCode(const eRCKey &) const +{ + return -1; +} + +eRCDevice::eRCDevice(eString id, eRCDriver *driver): driver(driver), id(id) +{ + input=driver->getInput(); + driver->addCodeListener(this); + eRCInput::getInstance()->addDevice(id, this); +} + +eRCDevice::~eRCDevice() +{ + driver->removeCodeListener(this); + eRCInput::getInstance()->removeDevice(id.c_str()); +} + +eRCDriver::eRCDriver(eRCInput *input): input(input), enabled(1) +{ +} + +eRCDriver::~eRCDriver() +{ + for (std::list::iterator i=listeners.begin(); i!=listeners.end(); ++i) + delete *i; +} + +void eRCShortDriver::keyPressed(int) +{ + __u16 rccode; + while (1) + { + if (read(handle, &rccode, 2)!=2) + break; + if (enabled && !input->islocked()) + for (std::list::iterator i(listeners.begin()); i!=listeners.end(); ++i) + (*i)->handleCode(rccode); + } +} + +eRCShortDriver::eRCShortDriver(const char *filename): eRCDriver(eRCInput::getInstance()) +{ + handle=open(filename, O_RDONLY|O_NONBLOCK); + if (handle<0) + { + eDebug("failed to open %s", filename); + sn=0; + } else + { + sn=new eSocketNotifier(eApp, handle, eSocketNotifier::Read); + CONNECT(sn->activated, eRCShortDriver::keyPressed); + eRCInput::getInstance()->setFile(handle); + } +} + +eRCShortDriver::~eRCShortDriver() +{ + if (handle>=0) + close(handle); + if (sn) + delete sn; +} + +void eRCInputEventDriver::keyPressed(int) +{ + struct input_event ev; + while (1) + { + if (read(handle, &ev, sizeof(struct input_event))!=sizeof(struct input_event)) + break; + if (enabled && !input->islocked()) + for (std::list::iterator i(listeners.begin()); i!=listeners.end(); ++i) + (*i)->handleCode((int)&ev); + } +} + +eRCInputEventDriver::eRCInputEventDriver(const char *filename): eRCDriver(eRCInput::getInstance()) +{ + handle=open(filename, O_RDONLY|O_NONBLOCK); + if (handle<0) + { + eDebug("failed to open %s", filename); + sn=0; + } else + { + sn=new eSocketNotifier(eApp, handle, eSocketNotifier::Read); + CONNECT(sn->activated, eRCInputEventDriver::keyPressed); + eRCInput::getInstance()->setFile(handle); + } +} + +eString eRCInputEventDriver::getDeviceName() +{ + char name[128]=""; + if (handle >= 0) + ::ioctl(handle, EVIOCGNAME(128), name); + return name; +} + +eRCInputEventDriver::~eRCInputEventDriver() +{ + if (handle>=0) + close(handle); + if (sn) + delete sn; +} + +eRCConfig::eRCConfig() +{ + reload(); +} + +eRCConfig::~eRCConfig() +{ + save(); +} + +void eRCConfig::set( int delay, int repeat ) +{ + rdelay = delay; + rrate = repeat; +} + +void eRCConfig::reload() +{ + rdelay=500; + rrate=100; + if ( eConfig::getInstance()->getKey("/ezap/rc/repeatRate", rrate) ) + save(); + eConfig::getInstance()->getKey("/ezap/rc/repeatDelay", rdelay); +} + +void eRCConfig::save() +{ + eConfig::getInstance()->setKey("/ezap/rc/repeatRate", rrate); + eConfig::getInstance()->setKey("/ezap/rc/repeatDelay", rdelay); +} + +eRCInput *eRCInput::instance; + +eRCInput::eRCInput() +{ + ASSERT( !instance); + instance=this; + handle = -1; + locked = 0; +} + +eRCInput::~eRCInput() +{ +} + +void eRCInput::close() +{ +} + +bool eRCInput::open() +{ + return false; +} + +int eRCInput::lock() +{ + locked=1; + return handle; +} + +void eRCInput::unlock() +{ + if (locked) + locked=0; +} + +void eRCInput::setFile(int newh) +{ + handle=newh; +} + +void eRCInput::addDevice(const eString &id, eRCDevice *dev) +{ + devices.insert(std::pair(id, dev)); +} + +void eRCInput::removeDevice(const eString &id) +{ + devices.erase(id); +} + +eRCDevice *eRCInput::getDevice(const eString &id) +{ + std::map::iterator i=devices.find(id); + if (i == devices.end()) + { + eDebug("failed, possible choices are:"); + for (std::map::iterator i=devices.begin(); i != devices.end(); ++i) + eDebug("%s", i->first.c_str()); + return 0; + } + return i->second; +} + +std::map &eRCInput::getDevices() +{ + return devices; +} + +eAutoInitP0 init_rcinput(eAutoInitNumbers::rc, "RC Input layer"); diff --git a/lib/driver/rc.h b/lib/driver/rc.h new file mode 100644 index 00000000..557be5ea --- /dev/null +++ b/lib/driver/rc.h @@ -0,0 +1,226 @@ +#ifndef __rc_h +#define __rc_h + +#include +#include + +#include +#include +#include + +class eRCInput; +class eRCDriver; +class eRCKey; + +/** + * \brief A remote control. + * + * Handles one remote control. Gets codes from a \ref eRCDriver. Produces events in \ref eRCInput. + */ +class eRCDevice: public Object +{ +protected: + eRCInput *input; + eRCDriver *driver; + eString id; +public: + /** + * \brief Constructs a new remote control. + * + * \param id The identifier of the RC, for use in settings. + * \param input The \ref eRCDriver where this remote gets its codes from. + */ + eRCDevice(eString id, eRCDriver *input); + ~eRCDevice(); + /** + * \brief Handles a device specific code. + * + * Generates events in \ref eRCInput. code is highly device- and driver dependant. + * For Example, it might be 16bit codes with one bit make/break or special codes + * for repeat. + */ + virtual void handleCode(int code)=0; + /** + * \brief Get user readable description. + * \result The description. + */ + virtual const char *getDescription() const=0; + const eString getIdentifier() const { return id; } + /** + * \brief Get a description for a specific key. + * \param key The key to get the description for. + * \result User readable description of given key. + */ + virtual const char *getKeyDescription(const eRCKey &key) const=0; + /** + * \brief Get a dbox2-compatible keycode. + * + * THIS IS DEPRECATED! DON'T USE IT UNLESS YOU NEED IT! + * \param key The key to get the compatible code for. + * \result The dbox2-compatible code. (new RC as defined in enum). + */ + virtual int getKeyCompatibleCode(const eRCKey &key) const; +}; + +/** + * Receives codes from one or more remote controls. + */ +class eRCDriver: public Object +{ +protected: + std::list listeners; + eRCInput *input; + int enabled; +public: + /** + * \brief Constructs a driver. + * + * \param input The RCInput to bind this driver to. + */ + eRCDriver(eRCInput *input); + /** + * \brief Get pointer to key-consumer. + */ + eRCInput *getInput() const { return input; } + /** + * \brief Adds a code lister + */ + void addCodeListener(eRCDevice *dev) + { + listeners.push_back(dev); + } + void removeCodeListener(eRCDevice *dev) + { + listeners.remove(dev); + } + ~eRCDriver(); + + void enable(int en) { enabled=en; } +}; + +class eRCShortDriver: public eRCDriver +{ +protected: + int handle; + eSocketNotifier *sn; + void keyPressed(int); +public: + eRCShortDriver(const char *filename); + ~eRCShortDriver(); +}; + +class eRCInputEventDriver: public eRCDriver +{ +protected: + int handle; + eSocketNotifier *sn; + void keyPressed(int); +public: + eString getDeviceName(); + eRCInputEventDriver(const char *filename); + ~eRCInputEventDriver(); +}; + +class eRCKey +{ +public: + eRCDevice *producer; + int code, flags; + + eRCKey(eRCDevice *producer, int code, int flags): + producer(producer), code(code), flags(flags) + { + } + enum + { + flagBreak=1, + flagRepeat=2 + }; + + bool operator<(const eRCKey &r) const + { + if (r.producer == producer) + { + if (r.code == code) + { + if (r.flags < flags) + return 1; + else + return 0; + } else if (r.code < code) + return 1; + else + return 0; + } else if (r.producer < producer) + return 1; + else + return 0; + } +}; + +class eRCConfig +{ +public: + eRCConfig(); + ~eRCConfig(); + void reload(); + void save(); + void set(int delay, int repeat); + int rdelay, // keypress delay after first keypress to begin of repeat (in ms) + rrate; // repeat rate (in ms) +}; + +class eRCInput: public Object +{ + int locked; + int handle; + static eRCInput *instance; + +public: + struct lstr + { + bool operator()(const eString &a, const eString &b) const + { + return a devices; +public: + Signal1 keyEvent; + enum + { + RC_0=0, RC_1=0x1, RC_2=0x2, RC_3=0x3, RC_4=0x4, RC_5=0x5, RC_6=0x6, RC_7=0x7, + RC_8=0x8, RC_9=0x9, + RC_RIGHT=10, RC_LEFT=11, RC_UP=12, RC_DOWN=13, RC_OK=14, RC_MUTE=15, + RC_STANDBY=16, RC_GREEN=17, RC_YELLOW=18, RC_RED=19, RC_BLUE=20, RC_PLUS=21, RC_MINUS=22, + RC_HELP=23, RC_DBOX=24, + RC_UP_LEFT=27, RC_UP_RIGHT=28, RC_DOWN_LEFT=29, RC_DOWN_RIGHT=30, RC_HOME=31 + }; + eRCInput(); + ~eRCInput(); + + int lock(); + void unlock(); + int islocked() { return locked; } + void close(); + bool open(); + + void setFile(int handle); + + void keyPressed(const eRCKey &key) + { + /*emit*/ keyEvent(key); + } + + void addDevice(const eString &id, eRCDevice *dev); + void removeDevice(const eString &id); + eRCDevice *getDevice(const eString &id); + std::map &getDevices(); + + static eRCInput *getInstance() { return instance; } + + eRCConfig config; +}; + +#endif diff --git a/lib/driver/rcdbox.h b/lib/driver/rcdbox.h new file mode 100644 index 00000000..bd361f67 --- /dev/null +++ b/lib/driver/rcdbox.h @@ -0,0 +1,61 @@ +#ifndef DISABLE_DBOX_RC + +#ifndef __rcdbox_h +#define __rcdbox_h + +#include + +class eRCDeviceDBoxOld: public eRCDevice +{ + int last, ccode; + eTimer timeout, repeattimer; +private: + void timeOut(); + void repeat(); +public: + void handleCode(int code); + eRCDeviceDBoxOld(eRCDriver *driver); + const char *getDescription() const; + const char *getKeyDescription(const eRCKey &key) const; + int getKeyCompatibleCode(const eRCKey &key) const; +}; + +class eRCDeviceDBoxNew: public eRCDevice +{ + int last, ccode; + eTimer timeout, repeattimer; +private: + void timeOut(); + void repeat(); +public: + void handleCode(int code); + eRCDeviceDBoxNew(eRCDriver *driver); + const char *getDescription() const; + const char *getKeyDescription(const eRCKey &key) const; + int getKeyCompatibleCode(const eRCKey &key) const; +}; + +class eRCDeviceDBoxButton: public eRCDevice +{ + int last; + eTimer repeattimer; +private: + void repeat(); +public: + void handleCode(int code); + eRCDeviceDBoxButton(eRCDriver *driver); + const char *getDescription() const; + + const char *getKeyDescription(const eRCKey &key) const; + int getKeyCompatibleCode(const eRCKey &key) const; +}; + +class eRCDBoxDriver: public eRCShortDriver +{ +public: + eRCDBoxDriver(); +}; + +#endif + +#endif // DISABLE_DBOX_RC diff --git a/lib/driver/rcdreambox2.h b/lib/driver/rcdreambox2.h new file mode 100644 index 00000000..e77beb4e --- /dev/null +++ b/lib/driver/rcdreambox2.h @@ -0,0 +1,51 @@ +#ifndef DISABLE_DREAMBOX_RC + +#ifndef __rcdreambox2_h +#define __rcdreambox2_h + +#include + +class eRCDeviceDreambox2: public eRCDevice +{ + int last, ccode; + eTimer timeout, repeattimer; +private: + void timeOut(); + void repeat(); +public: + void handleCode(int code); + eRCDeviceDreambox2(eRCDriver *driver); + const char *getDescription() const; + const char *getKeyDescription(const eRCKey &key) const; + int getKeyCompatibleCode(const eRCKey &key) const; +}; + +class eRCDreamboxDriver2: public eRCShortDriver +{ +public: + eRCDreamboxDriver2(); +}; + +class eRCDeviceDreamboxButton: public eRCDevice +{ + int last; + eTimer repeattimer; +private: + void repeat(); +public: + void handleCode(int code); + eRCDeviceDreamboxButton(eRCDriver *driver); + const char *getDescription() const; + + const char *getKeyDescription(const eRCKey &key) const; + int getKeyCompatibleCode(const eRCKey &key) const; +}; + +class eRCDreamboxButtonDriver: public eRCShortDriver +{ +public: + eRCDreamboxButtonDriver(); +}; +#endif + +#endif // DISABLE_DREAMBOX_RC diff --git a/lib/driver/rcinput.cpp b/lib/driver/rcinput.cpp new file mode 100644 index 00000000..041330a1 --- /dev/null +++ b/lib/driver/rcinput.cpp @@ -0,0 +1,126 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include + +void eRCDeviceInputDev::handleCode(int rccode) +{ + struct input_event *ev = (struct input_event *)rccode; + if (ev->type!=EV_KEY) + return; + eDebug("%x %x %x", ev->value, ev->code, ev->type); + switch (ev->value) + { + case 0: + /*emit*/ input->keyPressed(eRCKey(this, ev->code, eRCKey::flagBreak)); + break; + case 1: + /*emit*/ input->keyPressed(eRCKey(this, ev->code, 0)); + break; + case 2: + /*emit*/ input->keyPressed(eRCKey(this, ev->code, eRCKey::flagRepeat)); + break; + } +} + +eRCDeviceInputDev::eRCDeviceInputDev(eRCInputEventDriver *driver): eRCDevice(driver->getDeviceName(), driver) +{ +} + +const char *eRCDeviceInputDev::getDescription() const +{ + return id.c_str(); +} + +const char *eRCDeviceInputDev::getKeyDescription(const eRCKey &key) const +{ + switch (key.code) + { + case KEY_0: return "0"; + case KEY_1: return "1"; + case KEY_2: return "2"; + case KEY_3: return "3"; + case KEY_4: return "4"; + case KEY_5: return "5"; + case KEY_6: return "6"; + case KEY_7: return "7"; + case KEY_8: return "8"; + case KEY_9: return "9"; + case KEY_RIGHT: return "rechts"; + case KEY_LEFT: return "links"; + case KEY_UP: return "oben"; + case KEY_DOWN: return "unten"; + case KEY_OK: return "ok"; + case KEY_MUTE: return "mute"; + case KEY_POWER: return "power"; + case KEY_GREEN: return "gruen"; + case KEY_YELLOW: return "gelb"; + case KEY_RED: return "rot"; + case KEY_BLUE: return "blau"; + case KEY_VOLUMEUP: return "Lautstaerke plus"; + case KEY_VOLUMEDOWN: return "Lautstaerke minus"; + case KEY_HELP: return "?"; + case KEY_SETUP: return "d-Box"; +#if 0 + case KEY_TOPLEFT: return "oben links"; + case KEY_TOPRIGHT: return "oben rechts"; + case KEY_BOTTOMLEFT: return "unten links"; + case KEY_BOTTOMRIGHT: return "unten rechts"; +#endif + case KEY_HOME: return "home"; + default: return 0; + } +} + +int eRCDeviceInputDev::getKeyCompatibleCode(const eRCKey &key) const +{ + switch (key.code) + { + case KEY_0: return eRCInput::RC_0; + case KEY_1: return eRCInput::RC_1; + case KEY_2: return eRCInput::RC_2; + case KEY_3: return eRCInput::RC_3; + case KEY_4: return eRCInput::RC_4; + case KEY_5: return eRCInput::RC_5; + case KEY_6: return eRCInput::RC_6; + case KEY_7: return eRCInput::RC_7; + case KEY_8: return eRCInput::RC_8; + case KEY_9: return eRCInput::RC_9; + case KEY_RIGHT: return eRCInput::RC_RIGHT; + case KEY_LEFT: return eRCInput::RC_LEFT; + case KEY_UP: return eRCInput::RC_UP; + case KEY_DOWN: return eRCInput::RC_DOWN; + case KEY_OK: return eRCInput::RC_OK; + case KEY_MUTE: return eRCInput::RC_MUTE; + case KEY_POWER: return eRCInput::RC_STANDBY; + case KEY_GREEN: return eRCInput::RC_GREEN; + case KEY_YELLOW: return eRCInput::RC_YELLOW; + case KEY_RED: return eRCInput::RC_RED; + case KEY_VOLUMEUP: return eRCInput::RC_PLUS; + case KEY_BLUE: return eRCInput::RC_BLUE; + case KEY_VOLUMEDOWN: return eRCInput::RC_MINUS; + case KEY_HELP: return eRCInput::RC_HELP; + case KEY_SETUP: return eRCInput::RC_DBOX; + case KEY_HOME: return eRCInput::RC_HOME; + } + return -1; +} + + +class eInputDeviceInit +{ + eRCInputEventDriver driver; + eRCDeviceInputDev deviceInputDev; +public: + eInputDeviceInit(): driver("/dev/input/event0"), deviceInputDev(&driver) + { + } +}; + +eAutoInitP0 init_rcinputdev(eAutoInitNumbers::rc+1, "input device driver"); diff --git a/lib/driver/rcinput.h b/lib/driver/rcinput.h new file mode 100644 index 00000000..c13eafb1 --- /dev/null +++ b/lib/driver/rcinput.h @@ -0,0 +1,17 @@ +#ifndef __rcdbox_h +#define __rcdbox_h + +#include + +class eRCDeviceInputDev: public eRCDevice +{ +public: + void handleCode(int code); + eRCDeviceInputDev(eRCInputEventDriver *driver); + const char *getDescription() const; + + const char *getKeyDescription(const eRCKey &key) const; + int getKeyCompatibleCode(const eRCKey &key) const; +}; + +#endif diff --git a/lib/driver/rfmod.h b/lib/driver/rfmod.h new file mode 100644 index 00000000..e3acc47d --- /dev/null +++ b/lib/driver/rfmod.h @@ -0,0 +1,33 @@ +#ifdef ENABLE_RFMOD + +#ifndef __erfmod_h +#define __erfmod_h + +#include + +class eRFmod: public Object +{ + static eRFmod *instance; + + int rfmodfd; + int channel,soundsubcarrier,soundenable,finetune; + +public: + eRFmod(); + ~eRFmod(); + + void init(); + + static eRFmod *getInstance(); + + int save(); + + int setChannel(int channel); + int setSoundSubCarrier(int val); + int setSoundEnable(int val); + int setFinetune(int val); + int setTestPattern(int val); +}; +#endif + +#endif // ENABLE_RFMOD diff --git a/lib/driver/streamwd.h b/lib/driver/streamwd.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/dvb/Makefile.am b/lib/dvb/Makefile.am new file mode 100644 index 00000000..a3b81bc7 --- /dev/null +++ b/lib/dvb/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = \ + -I$(top_srcdir)/include + +noinst_LIBRARIES = libenigma_dvb.a + +libenigma_dvb_a_SOURCES = dvb.cpp demux.cpp frontend.cpp esection.cpp db.cpp \ + sec.cpp scan.cpp crc32.cpp pmt.cpp decoder.cpp + \ No newline at end of file diff --git a/lib/dvb/Makefile.in b/lib/dvb/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/lib/dvb/crc32.cpp b/lib/dvb/crc32.cpp new file mode 100644 index 00000000..049af37e --- /dev/null +++ b/lib/dvb/crc32.cpp @@ -0,0 +1,164 @@ +/* + * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + * code or tables extracted from it, as desired without restriction. + * + * First, the polynomial itself and its table of feedback terms. The + * polynomial is + * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 + * + * Note that we take it "backwards" and put the highest-order term in + * the lowest-order bit. The X^32 term is "implied"; the LSB is the + * X^31 term, etc. The X^0 term (usually shown as "+1") results in + * the MSB being 1 + * + * Note that the usual hardware shift register implementation, which + * is what we're using (we're merely optimizing it by doing eight-bit + * chunks at a time) shifts bits into the lowest-order term. In our + * implementation, that means shifting towards the right. Why do we + * do it this way? Because the calculated CRC must be transmitted in + * order from highest-order term to lowest-order term. UARTs transmit + * characters in order from LSB to MSB. By storing the CRC this way + * we hand it to the UART in the order low-byte to high-byte; the UART + * sends each low-bit to hight-bit; and the result is transmission bit + * by bit from highest- to lowest-order term without requiring any bit + * shuffling on our part. Reception works similarly + * + * The feedback terms table consists of 256, 32-bit entries. Notes + * + * The table can be generated at runtime if desired; code to do so + * is shown later. It might not be obvious, but the feedback + * terms simply represent the results of eight shift/xor opera + * tions for all combinations of data and CRC register values + * + * The values must be right-shifted by eight bits by the "updcrc + * logic; the shift must be unsigned (bring in zeroes). On some + * hardware you could probably optimize the shift in assembler by + * using byte-swap instructions + * polynomial $edb88320 + */ + +/* $Id: crc32.cpp,v 1.1 2003-10-17 15:35:50 tmbinc Exp $ */ + +#include "crc32.h" +#if 0 +const uint32_t crc32_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#else +const uint32_t crc32_table[256] = { + 0, 0x4C11DB7, 0x9823B6E, 0xD4326D9, + 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, + 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, + 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, + 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, + 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, + 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, + 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, + 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, + 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, + 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, + 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, + 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, + 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, + 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, + 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, + 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, + 0x18AEB13, 0x54BF6A4, 0x808D07D, 0xCC9CDCA, + 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, + 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, + 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, + 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, + 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, + 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, + 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, + 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, + 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, + 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, + 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, + 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, + 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, + 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, + 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, + 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, + 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, + 0x315D626, 0x7D4CB91, 0xA97ED48, 0xE56F0FF, + 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, + 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, + 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, + 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, + 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, + 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, + 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, + 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, + 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, + 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, + 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, + 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, + 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, + 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, + 0x29F3D35, 0x65E2082, 0xB1D065B, 0xFDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, + 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, + 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, + 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, + 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, + 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, + 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, + 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, + 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, + 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4}; +#endif diff --git a/lib/dvb/crc32.h b/lib/dvb/crc32.h new file mode 100644 index 00000000..99254532 --- /dev/null +++ b/lib/dvb/crc32.h @@ -0,0 +1,22 @@ +#ifndef CRC32_H +#define CRC32_H + +/* $Id: crc32.h,v 1.1 2003-10-17 15:35:49 tmbinc Exp $ */ + +typedef unsigned int uint32_t; + +extern const uint32_t crc32_table[256]; + +/* Return a 32-bit CRC of the contents of the buffer. */ + +static inline uint32_t +crc32(uint32_t val, const void *ss, int len) +{ + const unsigned char *s =(const unsigned char *) ss; + while (--len >= 0) +// val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); + val = (val << 8) ^ crc32_table[(val >> 24) ^ *s++]; + return val; +} + +#endif diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp new file mode 100644 index 00000000..f8233a64 --- /dev/null +++ b/lib/dvb/db.cpp @@ -0,0 +1,274 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_REF(eDVBService); + +eDVBService::eDVBService(): ref(0) +{ +} + +eDVBService::~eDVBService() +{ +} + +DEFINE_REF(eDVBDB); + +eDVBDB::eDVBDB() +{ + eDebug("---- opening lame channel db"); + FILE *f=fopen("lamedb", "rt"); + if (!f) + return; + char line[256]; + if ((!fgets(line, 256, f)) || strncmp(line, "eDVB services", 13)) + { + eDebug("not a servicefile"); + fclose(f); + return; + } + eDebug("reading services"); + if ((!fgets(line, 256, f)) || strcmp(line, "transponders\n")) + { + eDebug("services invalid, no transponders"); + fclose(f); + return; + } + + // clear all transponders + + while (!feof(f)) + { + if (!fgets(line, 256, f)) + break; + if (!strcmp(line, "end\n")) + break; + int dvb_namespace=-1, transport_stream_id=-1, original_network_id=-1; + sscanf(line, "%x:%x:%x", &dvb_namespace, &transport_stream_id, &original_network_id); + if (original_network_id == -1) + continue; + eDVBChannelID channelid = eDVBChannelID( + eDVBNamespace(dvb_namespace), + eTransportStreamID(transport_stream_id), + eOriginalNetworkID(original_network_id)); + + ePtr feparm = new eDVBFrontendParameters; + while (!feof(f)) + { + fgets(line, 256, f); + if (!strcmp(line, "/\n")) + break; + if (line[1]=='s') + { + eDVBFrontendParametersSatellite sat; + int frequency, symbol_rate, polarisation, fec, orbital_position, inversion; + sscanf(line+2, "%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &orbital_position, &inversion); + sat.frequency = frequency; + sat.symbol_rate = symbol_rate; + sat.polarisation = polarisation; + sat.fec = fec; + sat.orbital_position = orbital_position; + sat.inversion = inversion; + // ... +// t.setSatellite(frequency, symbol_rate, polarisation, fec, sat, inversion); + feparm->setDVBS(sat); + } + if (line[1]=='c') + { + int frequency, symbol_rate, inversion=0, modulation=3; + sscanf(line+2, "%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation); +// t.setCable(frequency, symbol_rate, inversion, modulation); + } + } + addChannelToList(channelid, feparm); + } + + if ((!fgets(line, 256, f)) || strcmp(line, "services\n")) + { + eDebug("services invalid, no services"); + return; + } + + // clear all services + + int count=0; + + while (!feof(f)) + { + if (!fgets(line, 256, f)) + break; + if (!strcmp(line, "end\n")) + break; + + int service_id=-1, dvb_namespace, transport_stream_id=-1, original_network_id=-1, service_type=-1, service_number=-1; + sscanf(line, "%x:%x:%x:%x:%d:%d", &service_id, &dvb_namespace, &transport_stream_id, &original_network_id, &service_type, &service_number); + if (service_number == -1) + continue; + ePtr s = new eDVBService; + eServiceReferenceDVB ref = + eServiceReferenceDVB( + eDVBNamespace(dvb_namespace), + eTransportStreamID(transport_stream_id), + eOriginalNetworkID(original_network_id), + eServiceID(service_id), + service_type); + count++; + fgets(line, 256, f); + if (strlen(line)) + line[strlen(line)-1]=0; + s->m_service_name=line; + fgets(line, 256, f); + if (strlen(line)) + line[strlen(line)-1]=0; + + eString str=line; + + if (str[1]!=':') // old ... (only service_provider) + { + s->m_provider_name=line; + } else + while ((!str.empty()) && str[1]==':') // new: p:, f:, c:%02d... + { + unsigned int c=str.find(','); + char p=str[0]; + eString v; + if (c == eString::npos) + { + v=str.mid(2); + str=""; + } else + { + v=str.mid(2, c-2); + str=str.mid(c+1); + } +// eDebug("%c ... %s", p, v.c_str()); + if (p == 'p') + s->m_provider_name=v; + else if (p == 'f') + { + sscanf(v.c_str(), "%x", &s->m_flags); + } else if (p == 'c') + { + int cid, val; + sscanf(v.c_str(), "%02d%04x", &cid, &val); + s->m_cache[cid]=val; + } else if (p == 'C') + { + int val; + sscanf(v.c_str(), "%04x", &val); + s->m_ca.insert(val); + } + } + addService(ref, s); + } + + eDebug("loaded %d services", count); + + fclose(f); + +} + +eDVBDB::~eDVBDB() +{ + eDebug("---- saving lame channel db"); + FILE *f=fopen("lamedb", "wt"); + int channels=0, services=0; + if (!f) + eFatal("couldn't save lame channel db!"); + fprintf(f, "eDVB services /3/\n"); + fprintf(f, "transponders\n"); + for (std::map::const_iterator i(m_channels.begin()); + i != m_channels.end(); ++i) + { + const eDVBChannelID &chid = i->first; + const channel &ch = i->second; + + fprintf(f, "%08x:%04x:%04x\n", chid.dvbnamespace.get(), + chid.transport_stream_id.get(), chid.original_network_id.get()); + eDVBFrontendParametersSatellite sat; + if (!ch.m_frontendParameters->getDVBS(sat)) + { + fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n", + sat.frequency, sat.symbol_rate, + sat.polarisation, sat.fec, sat.inversion, + sat.orbital_position); + } + fprintf(f, "/\n"); + channels++; + } + fprintf(f, "end\nservices\n"); + + for (std::map >::iterator i(m_services.begin()); + i != m_services.end(); ++i) + { + const eServiceReferenceDVB &s = i->first; + fprintf(f, "%04x:%08x:%04x:%04x:%d:%d\n", + s.getServiceID().get(), s.getDVBNamespace().get(), + s.getOriginalNetworkID().get(), s.getTransportStreamID().get(), + s.getServiceType(), + 0); + + fprintf(f, "%s\n", i->second->m_service_name.c_str()); + fprintf(f, "p=%s", i->second->m_provider_name.c_str()); + for (std::set::const_iterator ca(i->second->m_ca.begin()); + ca != i->second->m_ca.end(); ++ca) + fprintf(f, ",C=%04x", *ca); + fprintf(f, "\n"); + services++; + } + fprintf(f, "end\nHave a lot of bugs!\n"); + eDebug("saved %d channels and %d services!", channels, services); + fclose(f); +} + +RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm) +{ + channel ch; + assert(feparm); + ch.m_frontendParameters = feparm; + m_channels.insert(std::pair(id, ch)); + return 0; +} + +RESULT eDVBDB::removeChannel(const eDVBChannelID &id) +{ + m_channels.erase(id); + return 0; +} + +RESULT eDVBDB::getChannelFrontendData(const eDVBChannelID &id, ePtr &parm) +{ + std::map::iterator i = m_channels.find(id); + if (i == m_channels.end()) + { + parm = 0; + return -ENOENT; + } + parm = i->second.m_frontendParameters; + return 0; +} + +RESULT eDVBDB::addService(const eServiceReferenceDVB &serviceref, eDVBService *service) +{ + m_services.insert(std::pair >(serviceref, service)); + return 0; +} + +RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr &service) +{ + std::map >::iterator i; + i = m_services.find(reference); + if (i == m_services.end()) + { + service = 0; + return -ENOENT; + } + service = i->second; + return 0; +} + diff --git a/lib/dvb/db.h b/lib/dvb/db.h new file mode 100644 index 00000000..763df7eb --- /dev/null +++ b/lib/dvb/db.h @@ -0,0 +1,48 @@ +#ifndef __db_h +#define __db_h + +#include +#include + +class eDVBService: public iObject +{ + DECLARE_REF; +public: + eDVBService(); + eString m_service_name; + eString m_provider_name; + + int m_flags; + std::set m_ca; + std::map m_cache; + virtual ~eDVBService(); +}; + +class ServiceDescriptionTable; + +class eDVBDB: public virtual iDVBChannelList +{ +DECLARE_REF; +private: + struct channel + { + ePtr m_frontendParameters; + }; + + std::map m_channels; + + std::map > m_services; +public: + eDVBDB(); + virtual ~eDVBDB(); + + RESULT addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm); + RESULT removeChannel(const eDVBChannelID &id); + + RESULT getChannelFrontendData(const eDVBChannelID &id, ePtr &parm); + + RESULT addService(const eServiceReferenceDVB &service, eDVBService *service); + RESULT getService(const eServiceReferenceDVB &reference, ePtr &service); +}; + +#endif diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp new file mode 100644 index 00000000..e21e4567 --- /dev/null +++ b/lib/dvb/decoder.cpp @@ -0,0 +1,245 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +DEFINE_REF(eDVBAudio); + +eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev): ref(0), m_demux(demux) +{ + char filename[128]; + sprintf(filename, "/dev/dvb/adapter%d/audio%d", demux->adapter, dev); + m_fd = ::open(filename, O_RDWR); + if (m_fd < 0) + eWarning("%s: %m", filename); + sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux); + m_fd_demux = ::open(filename, O_RDWR); + if (m_fd_demux < 0) + eWarning("%s: %m", filename); +} + +int eDVBAudio::startPid(int pid) +{ + eDebug("setting audio pid to %x", pid); + if ((m_fd < 0) || (m_fd_demux < 0)) + return -1; + dmx_pes_filter_params pes; + + pes.pid = pid; + pes.input = DMX_IN_FRONTEND; + pes.output = DMX_OUT_DECODER; + pes.pes_type = DMX_PES_AUDIO0; + pes.flags = 0; + if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0) + { + eWarning("audio: DMX_SET_PES_FILTER: %m"); + return -errno; + } + if (::ioctl(m_fd_demux, DMX_START, &pes) < 0) + { + eWarning("audio: DMX_START: %m"); + return -errno; + } + + if (::ioctl(m_fd, AUDIO_PLAY) < 0) + eWarning("audio: AUDIO_PLAY: %m"); + return 0; +} + +void eDVBAudio::stop() +{ + if (::ioctl(m_fd, AUDIO_STOP) < 0) + eWarning("audio: AUDIO_STOP: %m"); + if (::ioctl(m_fd_demux, DMX_STOP) < 0) + eWarning("audio: DMX_STOP: %m"); +} + +eDVBAudio::~eDVBAudio() +{ + if (m_fd >= 0) + ::close(m_fd); + if (m_fd_demux >= 0) + ::close(m_fd_demux); +} + +DEFINE_REF(eDVBVideo); + +eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev): ref(0), m_demux(demux) +{ + char filename[128]; + sprintf(filename, "/dev/dvb/adapter%d/video%d", demux->adapter, dev); + m_fd = ::open(filename, O_RDWR); + if (m_fd < 0) + eWarning("%s: %m", filename); + sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux); + m_fd_demux = ::open(filename, O_RDWR); + if (m_fd_demux < 0) + eWarning("%s: %m", filename); +} + +int eDVBVideo::startPid(int pid) +{ + if ((m_fd < 0) || (m_fd_demux < 0)) + return -1; + dmx_pes_filter_params pes; + + pes.pid = pid; + pes.input = DMX_IN_FRONTEND; + pes.output = DMX_OUT_DECODER; + pes.pes_type = DMX_PES_VIDEO0; + pes.flags = 0; + if (::ioctl(m_fd_demux, DMX_SET_PES_FILTER, &pes) < 0) + { + eWarning("video: DMX_SET_PES_FILTER: %m"); + return -errno; + } + if (::ioctl(m_fd_demux, DMX_START, &pes) < 0) + { + eWarning("video: DMX_START: %m"); + return -errno; + } + + if (::ioctl(m_fd, VIDEO_PLAY) < 0) + eWarning("video: VIDEO_PLAY: %m"); + else + eDebug("video ok"); + return 0; +} + +void eDVBVideo::stop() +{ + if (::ioctl(m_fd, VIDEO_STOP) < 0) + eWarning("video: VIDEO_STOP: %m"); + if (::ioctl(m_fd_demux, DMX_STOP) < 0) + eWarning("video: DMX_STOP: %m"); +} + +eDVBVideo::~eDVBVideo() +{ + if (m_fd >= 0) + ::close(m_fd); + if (m_fd_demux >= 0) + ::close(m_fd_demux); +} + +DEFINE_REF(eTSMPEGDecoder); + +int eTSMPEGDecoder::setState() +{ + int res = 0; + eDebug("changed %x", m_changed); + if (m_changed & changeAudio) + { + if (m_audio) + m_audio->stop(); + m_audio = 0; + m_audio = new eDVBAudio(m_demux, 0); + if (m_audio->startPid(m_apid)) + { + eWarning("audio: startpid failed!"); + res = -1; + } + m_changed &= ~changeAudio; + } + if (m_changed & changeVideo) + { + if (m_video) + m_video->stop(); + m_video = 0; + m_video = new eDVBVideo(m_demux, 0); + if (m_video->startPid(m_vpid)) + { + eWarning("video: startpid failed!"); + res = -1; + } + m_changed &= ~changeVideo; + } + return res; +} + +eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder): m_demux(demux) +{ +} + +eTSMPEGDecoder::~eTSMPEGDecoder() +{ + m_vpid = m_apid = m_pcrpid = pidNone; + m_changed = -1; + setState(); +} + +RESULT eTSMPEGDecoder::setVideoPID(int vpid) +{ + if (m_vpid != vpid) + { + m_changed |= changeVideo; + m_vpid = vpid; + } + return 0; +} + +RESULT eTSMPEGDecoder::setAudioPID(int apid, int type) +{ + if ((m_apid != apid) || (m_atype != type)) + { + m_changed |= changeAudio; + m_atype = type; + m_apid = apid; + } + return 0; +} + +RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid) +{ + if (m_pcrpid != pcrpid) + { + m_changed |= changeAudio; + m_pcrpid = pcrpid; + } + return -1; +} + +RESULT eTSMPEGDecoder::setSyncMaster(int who) +{ + return -1; +} + +RESULT eTSMPEGDecoder::start() +{ + return setState(); +} + +RESULT eTSMPEGDecoder::freeze(int cont) +{ + return -1; +} + +RESULT eTSMPEGDecoder::unfreeze() +{ + return -1; +} + +RESULT eTSMPEGDecoder::setSinglePictureMode(int when) +{ + return -1; +} + +RESULT eTSMPEGDecoder::setPictureSkipMode(int what) +{ + return -1; +} + +RESULT eTSMPEGDecoder::setSlowMotion(int repeat) +{ + return -1; +} + +RESULT eTSMPEGDecoder::setZoom(int what) +{ + return -1; +} diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h new file mode 100644 index 00000000..6694e9fc --- /dev/null +++ b/lib/dvb/decoder.h @@ -0,0 +1,66 @@ +#ifndef __decoder_h +#define __decoder_h + +#include +#include + +class eDVBAudio: public virtual iObject +{ +DECLARE_REF; +private: + ePtr m_demux; + int m_fd, m_fd_demux; +public: + eDVBAudio(eDVBDemux *demux, int dev); + int startPid(int pid); + void stop(); + virtual ~eDVBAudio(); +}; + +class eDVBVideo: public virtual iObject +{ +DECLARE_REF; +private: + ePtr m_demux; + int m_fd, m_fd_demux; +public: + eDVBVideo(eDVBDemux *demux, int dev); + int startPid(int pid); + void stop(); + virtual ~eDVBVideo(); +}; + +class eTSMPEGDecoder: public virtual iTSMPEGDecoder +{ +DECLARE_REF; +private: + ePtr m_demux; + ePtr m_audio; + ePtr m_video; + + int m_vpid, m_apid, m_atype, m_pcrpid; + enum + { + changeVideo = 1, + changeAudio = 2, + changePCR = 4 + }; + int m_changed; + int setState(); +public: + enum { pidNone = -1 }; + eTSMPEGDecoder(eDVBDemux *demux, int decoder); + virtual ~eTSMPEGDecoder(); + RESULT setVideoPID(int vpid); + RESULT setAudioPID(int apid, int type); + RESULT setSyncPCR(int pcrpid); + RESULT setSyncMaster(int who); + RESULT start(); + RESULT freeze(int cont); + RESULT unfreeze(); + RESULT setSinglePictureMode(int when); + RESULT setPictureSkipMode(int what); + RESULT setSlowMotion(int repeat); + RESULT setZoom(int what); +}; +#endif diff --git a/lib/dvb/demux.cpp b/lib/dvb/demux.cpp new file mode 100644 index 00000000..e1d8bbaf --- /dev/null +++ b/lib/dvb/demux.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include + +#include +#include "crc32.h" + +#include +#include +#include +#include +#include + +eDVBDemux::eDVBDemux(int adapter, int demux): adapter(adapter), demux(demux), ref(0) +{ +} + +eDVBDemux::~eDVBDemux() +{ +} + +DEFINE_REF(eDVBDemux) + +RESULT eDVBDemux::createSectionReader(eMainloop *context, ePtr &reader) +{ + RESULT res; + reader = new eDVBSectionReader(this, context, res); + if (res) + reader = 0; + return res; +} + +RESULT eDVBDemux::getMPEGDecoder(ePtr &decoder) +{ + decoder = new eTSMPEGDecoder(this, 0); + return 0; +} + +void eDVBSectionReader::data(int) +{ + __u8 data[4096]; // max. section size + int r; + r = ::read(fd, data, 4096); + if(r < 0) + { + eWarning("ERROR reading section - %m\n"); + return; + } + if (checkcrc) + { + // this check should never happen unless the driver is crappy! + unsigned int c; + if ((c = crc32((unsigned)-1, data, r))) + eFatal("crc32 failed! is %x\n", c); + } + read(data); +} + +eDVBSectionReader::eDVBSectionReader(eDVBDemux *demux, eMainloop *context, RESULT &res): ref(0), demux(demux) +{ + char filename[128]; + sprintf(filename, "/dev/dvb/adapter%d/demux%d", demux->adapter, demux->demux); + fd = ::open(filename, O_RDWR); + + if (fd >= 0) + { + notifier=new eSocketNotifier(context, fd, eSocketNotifier::Read); + CONNECT(notifier->activated, eDVBSectionReader::data); + res = 0; + } else + { + perror(filename); + res = errno; + } +} + +DEFINE_REF(eDVBSectionReader) + +eDVBSectionReader::~eDVBSectionReader() +{ + if (notifier) + delete notifier; + if (fd >= 0) + ::close(fd); +} + +RESULT eDVBSectionReader::start(const eDVBSectionFilterMask &mask) +{ + RESULT res; + if (fd < 0) + return -ENODEV; + + dmx_sct_filter_params sct; + + sct.pid = mask.pid; + sct.timeout = 0; + sct.flags = DMX_IMMEDIATE_START; + if (mask.flags & eDVBSectionFilterMask::rfCRC) + { + sct.flags |= DMX_CHECK_CRC; + checkcrc = 1; + } else + checkcrc = 0; + + memcpy(sct.filter.filter, mask.data, DMX_FILTER_SIZE); + memcpy(sct.filter.mask, mask.mask, DMX_FILTER_SIZE); + memcpy(sct.filter.mode, mask.mode, DMX_FILTER_SIZE); + + res = ::ioctl(fd, DMX_SET_FILTER, &sct); + if (!res) + active = 1; + return res; +} + +RESULT eDVBSectionReader::stop() +{ + if (!active) + return -1; + + ::ioctl(fd, DMX_STOP); + + return 0; +} + +RESULT eDVBSectionReader::connectRead(const Slot1 &r, ePtr &conn) +{ + conn = new eConnection(read.connect(r)); + return 0; +} diff --git a/lib/dvb/demux.h b/lib/dvb/demux.h new file mode 100644 index 00000000..3b4cbede --- /dev/null +++ b/lib/dvb/demux.h @@ -0,0 +1,41 @@ +#ifndef __dvb_demux_h +#define __dvb_demux_h + +#include +#include + +class eDVBDemux: public virtual iDVBDemux +{ + int adapter, demux; + friend class eDVBSectionReader; + friend class eDVBAudio; + friend class eDVBVideo; +public: + DECLARE_REF + eDVBDemux(int adapter, int demux); + virtual ~eDVBDemux(); + RESULT createSectionReader(eMainloop *context, ePtr &reader); + RESULT getMPEGDecoder(ePtr &reader); +}; + +class eDVBSectionReader: public virtual iDVBSectionReader, public Object +{ + DECLARE_REF +private: + int fd; + Signal1 read; + ePtr demux; + int active; + int checkcrc; + void data(int); + eSocketNotifier *notifier; +public: + + eDVBSectionReader(eDVBDemux *demux, eMainloop *context, RESULT &res); + virtual ~eDVBSectionReader(); + RESULT start(const eDVBSectionFilterMask &mask); + RESULT stop(); + RESULT connectRead(const Slot1 &read, ePtr &conn); +}; + +#endif diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp new file mode 100644 index 00000000..176b07c5 --- /dev/null +++ b/lib/dvb/dvb.cpp @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include + +DEFINE_REF(eDVBResourceManager); + +eDVBResourceManager *eDVBResourceManager::instance; + +eDVBResourceManager::eDVBResourceManager(): ref(0) +{ + avail = 1; + busy = 0; + m_sec = new eDVBSatelliteEquipmentControl; + if (!instance) + instance = this; +} + +eDVBResourceManager::~eDVBResourceManager() +{ + if (instance == this) + instance = 0; +} + +RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list) +{ + m_list = list; + return 0; +} + +RESULT eDVBResourceManager::getChannelList(ePtr &list) +{ + list = m_list; + if (list) + return 0; + else + return -ENOENT; +} + + +RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, ePtr &channel) +{ + RESULT res; + eDVBChannel *ch; + channel = ch = new eDVBChannel(this, 0, 0, 0); + + ePtr fe; + if (!channel->getFrontend(fe)) + fe->setSEC(m_sec); + + res = ch->setChannel(channelid); + if (res) + { + channel = 0; + return res; + } + return 0; +} + +RESULT eDVBResourceManager::allocateRawChannel(ePtr &channel) +{ + channel = new eDVBChannel(this, 0, 0, 0); + ePtr fe; + if (!channel->getFrontend(fe)) + fe->setSEC(m_sec); + + return 0; +} + +RESULT eDVBResourceManager::allocatePVRChannel(int caps) +{ + return -1; // will nicht, mag nicht, und das interface ist auch kaputt +} + +RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch) +{ + eDebug("add channel %p", ch); + m_active_channels.insert(std::pair(chid, ch)); + return 0; +} + +RESULT eDVBResourceManager::removeChannel(const eDVBChannelID &chid, eDVBChannel *) +{ + int cnt = m_active_channels.erase(chid); + eDebug("remove channel: removed %d channels", cnt); + ASSERT(cnt <= 1); + if (cnt == 1) + return 0; + return -ENOENT; +} + +eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, int adapter, int frontend, int demux): eDVBDemux(adapter, demux), m_state(state_idle), m_mgr(mgr) +{ + if (frontend >= 0) + { + int ok; + m_frontend = new eDVBFrontend(adapter, frontend, ok); + if (!ok) + { + eDebug("warning, frontend failed"); + m_frontend = 0; + return; + } + m_frontend->connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged); + } +} + +eDVBChannel::~eDVBChannel() +{ + if (m_channel_id) + m_mgr->removeChannel(m_channel_id, this); +} + +void eDVBChannel::frontendStateChanged(iDVBFrontend*fe) +{ + eDebug("fe state changed!"); + int state, ourstate = 0; + if (fe->getState(state)) + return; + + if (state == iDVBFrontend::stateLock) + { + eDebug("OURSTATE: ok"); + ourstate = state_ok; + } else if (state == iDVBFrontend::stateTuning) + { + eDebug("OURSTATE: tuning"); + ourstate = state_tuning; + } else if (state == iDVBFrontend::stateFailed) + { + eDebug("OURSTATE: failed/unavailable"); + ourstate = state_unavailable; + } else + eFatal("state unknown"); + + if (ourstate != m_state) + { + m_state = ourstate; + m_stateChanged(this); + } +} + +RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid) +{ + ePtr list; + + if (m_mgr->getChannelList(list)) + { + eDebug("no channel list set!"); + return -ENOENT; + } + + eDebug("tuning to chid: ns: %08x tsid %04x onid %04x", + channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get()); + + + ePtr feparm; + if (list->getChannelFrontendData(channelid, feparm)) + { + eDebug("channel not found!"); + return -ENOENT; + } + eDebug("allocateChannel: channel found.."); + + if (!m_frontend) + { + eDebug("no frontend to tune!"); + return -ENODEV; + } + + if (m_channel_id) + m_mgr->removeChannel(m_channel_id, this); + m_channel_id = channelid; + m_mgr->addChannel(m_channel_id, this); + m_state = state_tuning; + eDebug("%p", &*feparm); + return m_frontend->tune(*feparm); +} + +RESULT eDVBChannel::connectStateChange(const Slot1 &stateChange, ePtr &connection) +{ + connection = new eConnection( m_stateChanged.connect(stateChange) ); + return 0; +} + +RESULT eDVBChannel::getState(int &state) +{ + state = m_state; + return 0; +} + +RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing) +{ + return -1; +} + +RESULT eDVBChannel::getDemux(ePtr &demux) +{ + demux = this; + return 0; +} + +RESULT eDVBChannel::getFrontend(ePtr &frontend) +{ + frontend = m_frontend; + if (frontend) + return 0; + else + return -ENODEV; +} diff --git a/lib/dvb/dvb.h b/lib/dvb/dvb.h new file mode 100644 index 00000000..f6aae238 --- /dev/null +++ b/lib/dvb/dvb.h @@ -0,0 +1,67 @@ +#ifndef __dvb_dvb_h +#define __dvb_dvb_h + +#include +#include +#include +#include + +class eDVBChannel; + +class eDVBResourceManager: public virtual iDVBResourceManager +{ + DECLARE_REF; + int avail, busy; + struct adapter + { + eSmartPtrList fe; + eSmartPtrList demux; + }; + std::multimap m_active_channels; + ePtr m_list; + ePtr m_sec; + static eDVBResourceManager *instance; +public: + eDVBResourceManager(); + virtual ~eDVBResourceManager(); + + static RESULT getInstance(ePtr &ptr) { if (instance) { ptr = instance; return 0; } return -1; } + + RESULT setChannelList(iDVBChannelList *list); + RESULT getChannelList(ePtr &list); + + RESULT allocateChannel(const eDVBChannelID &channelid, ePtr &channel); + RESULT allocateRawChannel(ePtr &channel); + RESULT allocatePVRChannel(int caps); + + RESULT addChannel(const eDVBChannelID &chid, eDVBChannel *ch); + RESULT removeChannel(const eDVBChannelID &chid, eDVBChannel *ch); +}; + +class eDVBChannel: public virtual iDVBChannel, public virtual eDVBDemux, public Object +{ + ePtr m_frontend; + ePtr m_current_frontend_parameters; + eDVBChannelID m_channel_id; + Signal1 m_stateChanged; + int m_state; + ePtr m_mgr; + + void frontendStateChanged(iDVBFrontend*fe); + ePtr m_conn_frontendStateChanged; +public: + eDVBChannel(eDVBResourceManager *mgr, int adapter, int frontend, int demux); + virtual ~eDVBChannel(); + + /* only for managed channels */ + RESULT setChannel(const eDVBChannelID &id); + + RESULT connectStateChange(const Slot1 &stateChange, ePtr &connection); + RESULT getState(int &state); + + RESULT setCIRouting(const eDVBCIRouting &routing); + RESULT getDemux(ePtr &demux); + RESULT getFrontend(ePtr &frontend); +}; + +#endif diff --git a/lib/dvb/esection.cpp b/lib/dvb/esection.cpp new file mode 100644 index 00000000..08cb49be --- /dev/null +++ b/lib/dvb/esection.cpp @@ -0,0 +1,130 @@ +#include +#include + +void eGTable::sectionRead(const __u8 *d) +{ + unsigned int last_section_number = d[7]; + m_table.flags &= ~eDVBTableSpec::tfAnyVersion; + m_table.flags |= eDVBTableSpec::tfThisVersion; + m_table.version = (d[5]>>1)&0x1F; + + + if (createTable(d[6], d, last_section_number + 1)) + { + if (m_timeout) + m_timeout->stop(); + m_reader->stop(); + ready = 1; + tableReady(error); + } else if ((m_table.flags & eDVBTableSpec::tfHaveTimeout) && m_timeout) + m_timeout->start(m_table.timeout, 1); // reset timeout +} + +void eGTable::timeout() +{ + eDebug("timeout!"); + m_reader->stop(); + ready = 1; + error = -1; + tableReady(error); +} + +eGTable::eGTable(): + ref(0), m_timeout(0), error(0) +{ +} + +DEFINE_REF(eGTable); + +RESULT eGTable::start(iDVBSectionReader *reader, const eDVBTableSpec &table) +{ + RESULT res; + m_table = table; + + m_reader = reader; + m_reader->connectRead(slot(*this, &eGTable::sectionRead), m_sectionRead_conn); + + // setup filter struct + eDVBSectionFilterMask mask; + + memset(&mask, 0, sizeof(mask)); + mask.pid = m_table.pid; + mask.flags = 0; + + if (m_table.flags & eDVBTableSpec::tfCheckCRC) + mask.flags |= eDVBSectionFilterMask::rfCRC; + + if (m_table.flags & eDVBTableSpec::tfHaveTID) + { + mask.data[0] = m_table.tid; + mask.mask[0] = 0xFF; + } + + if (m_table.flags & eDVBTableSpec::tfHaveTIDExt) + { + mask.data[1] = m_table.tidext >> 8; + mask.data[2] = m_table.tidext; + mask.mask[1] = 0xFF; + mask.mask[2] = 0xFF; + } + + if (!(m_table.flags & eDVBTableSpec::tfAnyVersion)) + { + eDebug("doing version filtering"); + mask.data[3] |= (m_table.version << 1)|1; + mask.mask[3] |= 0x3f; + if (!(m_table.flags & eDVBTableSpec::tfThisVersion)) + mask.mode[3] |= 0x3e; // negative filtering + } else + eDebug("no version filtering"); + + eDebug("%04x: %02x %02x %02x %02x %02x %02x", + mask.pid, + mask.data[0], mask.data[1], mask.data[2], + mask.data[3], mask.data[4], mask.data[5]); + eDebug("mask: %02x %02x %02x %02x %02x %02x", + mask.mask[0], mask.mask[1], mask.mask[2], + mask.mask[3], mask.mask[4], mask.mask[5]); + eDebug("mode: %02x %02x %02x %02x %02x %02x", + mask.mode[0], mask.mode[1], mask.mode[2], + mask.mode[3], mask.mode[4], mask.mode[5]); + + if ((res = m_reader->start(mask))) + { + eDebug("reader failed to start."); + return res; + } + + if (m_table.flags & eDVBTableSpec::tfHaveTimeout) + { + eDebug("have timeout, %d", m_table.timeout); + if (m_timeout) + delete m_timeout; + m_timeout = new eTimer(eApp); + m_timeout->start(m_table.timeout, 1); // begin timeout + CONNECT(m_timeout->timeout, eGTable::timeout); + } + + return 0; +} + +RESULT eGTable::start(iDVBDemux *demux, const eDVBTableSpec &table) +{ + int res; + ePtr reader; + res = demux->createSectionReader(eApp, reader); + if (res) + return res; + return start(reader, table); +} + +eGTable::~eGTable() +{ + if (m_timeout) + delete m_timeout; +} + +void eAUGTable::slotTableReady(int error) +{ + getNext(error); +} diff --git a/lib/dvb/esection.h b/lib/dvb/esection.h new file mode 100644 index 00000000..ca63c184 --- /dev/null +++ b/lib/dvb/esection.h @@ -0,0 +1,189 @@ +#ifndef __esection_h +#define __esection_h + +#include +#include + +class eGTable: public virtual iObject, public Object +{ +DECLARE_REF; +private: + ePtr m_reader; + eDVBTableSpec m_table; + + eTimer *m_timeout; + + void sectionRead(const __u8 *data); + void timeout(); + ePtr m_sectionRead_conn; +protected: + virtual int createTable(int nr, const __u8 *data, unsigned int max)=0; +public: + Signal1 tableReady; + eGTable(); + RESULT start(iDVBSectionReader *reader, const eDVBTableSpec &table); + RESULT start(iDVBDemux *reader, const eDVBTableSpec &table); + RESULT getSpec(eDVBTableSpec &spec) { spec = m_table; return 0; } + virtual ~eGTable(); + int error; + int ready; +}; + +template +class eTable: public eGTable +{ +private: + std::vector sections; + std::set avail; +protected: + int createTable(int nr, const __u8 *data, unsigned int max) + { + if (avail.find(nr) != avail.end()) + delete sections[nr]; + sections.resize(max); + + + sections[nr] = new Section(data); + avail.insert(nr); + + for (unsigned int i = 0; i < max; ++i) + if (avail.find(i) != avail.end()) + printf("+"); + else + printf("-"); + + printf(" %d/%d\n", avail.size(), max); + + if (avail.size() == max) + return 1; + else + return 0; + } +public: + std::vector &getSections() { return sections; } + eTable(): eGTable() + { + } + ~eTable() + { + for (typename std::vector::iterator i(sections.begin()); i != sections.end(); ++i) + delete *i; + } +}; + +class eAUGTable: public Object +{ +protected: + void slotTableReady(int); +public: + Signal1 tableReady; + virtual void getNext(int err)=0; +}; + +template +class eAUTable: public eAUGTable +{ + ePtr current, next; // current is READY AND ERRORFREE, next is not yet ready + int first; + ePtr m_demux; + eMainloop *ml; +public: + + eAUTable() + { + } + + ~eAUTable() + { + current=next=0; + } + + int begin(eMainloop *m, const eDVBTableSpec &spec, ePtr demux) + { + ml = m; + m_demux = demux; + first= 1; + current = 0; + next = new Table(); + CONNECT(next->tableReady, eAUTable::slotTableReady); + next->start(demux, spec); + return 0; + } + + int get() + { + if (current) + { + /*emit*/ tableReady(0); + return 0; + } else if (!next) + { + /*emit*/ tableReady(-1); + return 0; + } else + return 1; + } + + RESULT getCurrent(ePtr
&ptr) + { + if (!current) + return -1; + ptr = current; + return 0; + } + +#if 0 + void abort() + { + eDebug("eAUTable: aborted!"); + if (next) + next->abort(); + delete next; + next=0; + } +#endif + + int ready() + { + return !!current; + } + + void inject(Table *t) + { + next=t; + getNext(0); + } + + void getNext(int error) + { + current = 0; + if (error) + { + next=0; + if (first) + /*emit*/ tableReady(error); + first=0; + return; + } else + current=next; + + next=0; + first=0; + + assert(current->ready); + + /*emit*/ tableReady(0); + + eDVBTableSpec spec; + + if (current && (!current->getSpec(spec))) + { + next = new Table(); + CONNECT(next->tableReady, eAUTable::slotTableReady); + spec.flags &= ~(eDVBTableSpec::tfAnyVersion|eDVBTableSpec::tfThisVersion|eDVBTableSpec::tfHaveTimeout); + next->eGTable::start(m_demux, spec); + } + } +}; + +#endif diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp new file mode 100644 index 00000000..c51eeea7 --- /dev/null +++ b/lib/dvb/frontend.cpp @@ -0,0 +1,465 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +void eDVBFrontendParametersSatellite::set(const SatelliteDeliverySystemDescriptor &descriptor) +{ + frequency = descriptor.getFrequency() * 10; + symbol_rate = descriptor.getSymbolRate() * 100; + switch (descriptor.getPolarization()) + { + case 0: + polarisation = Polarisation::Horizontal; + break; + case 1: + polarisation = Polarisation::Vertical; + break; + case 2: + polarisation = Polarisation::CircularLeft; + break; + case 3: + polarisation = Polarisation::CircularRight; + break; + } + switch (descriptor.getFecInner()) + { + case 1: + fec = FEC::f1_2; + break; + case 2: + fec = FEC::f2_3; + break; + case 3: + fec = FEC::f3_4; + break; + case 4: + fec = FEC::f5_6; + break; + case 5: + fec = FEC::f7_8; + break; + case 0xF: + fec = FEC::fNone; + break; + default: + fec = FEC::fAuto; + break; + } + inversion = Inversion::Unknown; + orbital_position = ((descriptor.getOrbitalPosition() >> 12) & 0xF) * 1000; + orbital_position += ((descriptor.getOrbitalPosition() >> 8) & 0xF) * 100; + orbital_position += ((descriptor.getOrbitalPosition() >> 4) & 0xF) * 10; + orbital_position += ((descriptor.getOrbitalPosition()) & 0xF); + if (orbital_position && (!descriptor.getWestEastFlag())) + orbital_position = 3600 - orbital_position; +} + +void eDVBFrontendParametersCable::set(const CableDeliverySystemDescriptor &descriptor) +{ + eFatal("nyi"); +} + +void eDVBFrontendParametersTerrestrial::set(const TerrestrialDeliverySystemDescriptor &) +{ + eFatal("nyi"); +} + +eDVBFrontendParameters::eDVBFrontendParameters(): ref(0), m_type(-1) +{ +} + +DEFINE_REF(eDVBFrontendParameters); + +RESULT eDVBFrontendParameters::getSystem(int &t) const +{ + if (m_type == -1) + return -1; + t = m_type; + return 0; +} + +RESULT eDVBFrontendParameters::getDVBS(eDVBFrontendParametersSatellite &p) const +{ + if (m_type != iDVBFrontend::feSatellite) + return -1; + p = sat; + return 0; +} + +RESULT eDVBFrontendParameters::getDVBC(eDVBFrontendParametersCable &p) const +{ + if (m_type != iDVBFrontend::feCable) + return -1; + p = cable; + return 0; +} + +RESULT eDVBFrontendParameters::getDVBT(eDVBFrontendParametersTerrestrial &p) const +{ + if (m_type != iDVBFrontend::feTerrestrial) + return -1; + p = terrestrial; + return 0; +} + +RESULT eDVBFrontendParameters::setDVBS(eDVBFrontendParametersSatellite &p) +{ + sat = p; + m_type = iDVBFrontend::feSatellite; + return 0; +} + +RESULT eDVBFrontendParameters::setDVBC(eDVBFrontendParametersCable &p) +{ + cable = p; + m_type = iDVBFrontend::feCable; + return 0; +} + +RESULT eDVBFrontendParameters::setDVBT(eDVBFrontendParametersTerrestrial &p) +{ + terrestrial = p; + m_type = iDVBFrontend::feTerrestrial; + return 0; +} + +RESULT eDVBFrontendParameters::calculateDifference(const iDVBFrontendParameters *parm, int &diff) const +{ + if (!parm) + return -1; + int type; + if (parm->getSystem(type)) + return -1; + if (type != m_type) + { + diff = 1<<30; // big difference + return 0; + } + + switch (type) + { + case iDVBFrontend::feSatellite: + { + eDVBFrontendParametersSatellite osat; + if (parm->getDVBS(osat)) + return -2; + + if (sat.orbital_position != osat.orbital_position) + diff = 1<<29; + else if (sat.polarisation != osat.polarisation) + diff = 1<<28; + else + diff = abs(sat.frequency - osat.frequency); + return 0; + } + case iDVBFrontend::feCable: + case iDVBFrontend::feTerrestrial: + default: + return -1; + } + return 0; +} + +RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const +{ + switch (m_type) + { + case iDVBFrontend::feSatellite: + { + hash = sat.frequency & 0xFFFF; + hash |= sat.orbital_position << 16; + return 0; + } + case iDVBFrontend::feCable: + case iDVBFrontend::feTerrestrial: + default: + return -1; + } +} + +DEFINE_REF(eDVBFrontend); + +eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok): ref(0), m_type(-1) +{ + char filename[128]; + int result; + dvb_frontend_info fe_info; + + m_sn = 0; + m_timeout = 0; + + sprintf(filename, "/dev/dvb/adapter%d/frontend%d", adap, fe); + eDebug("opening frontend."); + m_fd = ::open(filename, O_RDWR|O_NONBLOCK); + if (m_fd < 0) + { + eWarning("failed! (%s) %m", filename); + ok = 0; + return; + } + + result = ::ioctl(m_fd, FE_GET_INFO, &fe_info); + + if (result < 0) { + eWarning("ioctl FE_GET_INFO failed"); + ::close(m_fd); + m_fd = -1; + ok = 0; + return; + } + + switch (fe_info.type) + { + case FE_QPSK: + m_type = feSatellite; + break; + case FE_QAM: + m_type = feCable; + break; + case FE_OFDM: + m_type = feTerrestrial; + break; + default: + eWarning("unknown frontend type."); + ::close(m_fd); + m_fd = -1; + ok = 0; + return; + } + eDebug("detected %s frontend", "satellite\0cable\0 terrestrial"+feSatellite*9); + ok = 1; + + m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read); + CONNECT(m_sn->activated, eDVBFrontend::feEvent); + m_sn->start(); + + m_timeout = new eTimer(eApp); + CONNECT(m_timeout->timeout, eDVBFrontend::timeout); + + return; +} + +eDVBFrontend::~eDVBFrontend() +{ + if (m_fd >= 0) + ::close(m_fd); + if (m_sn) + delete m_sn; + if (m_timeout) + delete m_timeout; +} + +void eDVBFrontend::feEvent(int w) +{ + while (1) + { + dvb_frontend_event event; + int res; + int state; + res = ::ioctl(m_fd, FE_GET_EVENT, &event); + + if (res && (errno == EAGAIN)) + break; + + if (res) + { + eWarning("FE_GET_EVENT failed! %m"); + return; + } + + if (w < 0) + continue; + + eDebug("fe event: status %x, inversion %s", event.status, (event.parameters.inversion == INVERSION_ON) ? "on" : "off"); + if (event.status & FE_HAS_LOCK) + { + state = stateLock; + } else + { + if (m_tuning) + state = stateTuning; + else + state = stateFailed; + } + if (m_state != state) + { + m_state = state; + m_stateChanged(this); + } + } +} + +void eDVBFrontend::timeout() +{ + int state; + if (m_state == stateTuning) + { + state = stateFailed; + eDebug("DVBFrontend: timeout"); + if (m_state != state) + { + m_state = state; + m_stateChanged(this); + } + } else + m_tuning = 0; +} + +RESULT eDVBFrontend::getFrontendType(int &t) +{ + if (m_type == -1) + return -ENODEV; + t = m_type; + return 0; +} + +RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where) +{ + if (m_type == -1) + return -ENODEV; + + dvb_frontend_parameters parm; + + feEvent(-1); + + switch (m_type) + { + case feSatellite: + { + int res; + eDVBFrontendParametersSatellite feparm; + if (where.getDVBS(feparm)) + { + eDebug("no dvbs data!"); + return -EINVAL; + } + if (!m_sec) + { + eWarning("no SEC module active!"); + return -ENOENT; + } + + res = m_sec->prepare(*this, parm, feparm); + if (res) + return res; + + eDebug("tuning to %d mhz", parm.frequency/1000); + break; + } + case feCable: + { + eDVBFrontendParametersCable feparm; + if (where.getDVBC(feparm)) + return -EINVAL; + eFatal("cable tuning nyi"); + } + case feTerrestrial: + { + eDVBFrontendParametersTerrestrial feparm; + if (where.getDVBT(feparm)) + return -EINVAL; + eFatal("terrestrial tuning nyi"); + } + } + + if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1) + { + perror("FE_SET_FRONTEND failed"); + return errno; + } + + if (m_state != stateTuning) + { + m_tuning = 1; + m_state = stateTuning; + m_stateChanged(this); + } + + m_timeout->start(5000, 1); // 5 sec timeout. TODO: symbolrate dependent + + return 0; +} + +RESULT eDVBFrontend::connectStateChange(const Slot1 &stateChange, ePtr &connection) +{ + connection = new eConnection(m_stateChanged.connect(stateChange)); + return 0; +} + +RESULT eDVBFrontend::setVoltage(int voltage) +{ + fe_sec_voltage_t vlt; + + switch (voltage) + { + case voltageOff: + vlt = SEC_VOLTAGE_OFF; + break; + case voltage13: + vlt = SEC_VOLTAGE_13; + break; + case voltage18: + vlt = SEC_VOLTAGE_18; + break; + default: + return -ENODEV; + } + + return ::ioctl(m_fd, FE_SET_VOLTAGE, vlt); +} + +RESULT eDVBFrontend::getState(int &state) +{ + state = m_state; + return 0; +} + +RESULT eDVBFrontend::setTone(int t) +{ + fe_sec_tone_mode_t tone; + + switch (t) + { + case toneOn: + tone = SEC_TONE_ON; + break; + case toneOff: + tone = SEC_TONE_OFF; + break; + default: + return -ENODEV; + } + + return ::ioctl(m_fd, FE_SET_TONE, tone); +} + +RESULT eDVBFrontend::sendDiseqc(const eDVBDiseqcCommand &diseqc) +{ + struct dvb_diseqc_master_cmd cmd; + if (::ioctl(m_fd, FE_SET_TONE, SEC_TONE_OFF)) + return -EINVAL; + usleep(15 * 1000); + memcpy(cmd.msg, diseqc.data, diseqc.len); + cmd.msg_len = diseqc.len; + + if (::ioctl(m_fd, FE_DISEQC_SEND_MASTER_CMD, &cmd)) + return -EINVAL; + usleep(15 * 1000); + eDebug("diseqc ok"); + return 0; +} + +RESULT eDVBFrontend::setSEC(iDVBSatelliteEquipmentControl *sec) +{ + m_sec = sec; + return 0; +} diff --git a/lib/dvb/frontend.h b/lib/dvb/frontend.h new file mode 100644 index 00000000..ee7f945a --- /dev/null +++ b/lib/dvb/frontend.h @@ -0,0 +1,61 @@ +#ifndef __dvb_frontend_h +#define __dvb_frontend_h + +#include + +class eDVBFrontendParameters: public virtual iDVBFrontendParameters +{ + DECLARE_REF; + union + { + eDVBFrontendParametersSatellite sat; + eDVBFrontendParametersCable cable; + eDVBFrontendParametersTerrestrial terrestrial; + }; + int m_type; +public: + eDVBFrontendParameters(); + + RESULT getSystem(int &type) const; + RESULT getDVBS(eDVBFrontendParametersSatellite &p) const; + RESULT getDVBC(eDVBFrontendParametersCable &p) const; + RESULT getDVBT(eDVBFrontendParametersTerrestrial &p) const; + + RESULT setDVBS(eDVBFrontendParametersSatellite &p); + RESULT setDVBC(eDVBFrontendParametersCable &p); + RESULT setDVBT(eDVBFrontendParametersTerrestrial &p); + + RESULT calculateDifference(const iDVBFrontendParameters *parm, int &diff) const; + + RESULT getHash(unsigned long &hash) const; +}; + +class eDVBFrontend: public virtual iDVBFrontend, public Object +{ + DECLARE_REF; + int m_type; + int m_fd; + int m_state; + Signal1 m_stateChanged; + ePtr m_sec; + eSocketNotifier *m_sn; + int m_tuning; + eTimer *m_timeout; + + void feEvent(int); + void timeout(); +public: + eDVBFrontend(int adap, int fe, int &ok); + virtual ~eDVBFrontend(); + + RESULT getFrontendType(int &type); + RESULT tune(const iDVBFrontendParameters &where); + RESULT connectStateChange(const Slot1 &stateChange, ePtr &connection); + RESULT getState(int &state); + RESULT setTone(int tone); + RESULT setVoltage(int voltage); + RESULT sendDiseqc(const eDVBDiseqcCommand &diseqc); + RESULT setSEC(iDVBSatelliteEquipmentControl *sec); +}; + +#endif diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h new file mode 100644 index 00000000..c4ae488d --- /dev/null +++ b/lib/dvb/idvb.h @@ -0,0 +1,354 @@ +#ifndef __dvb_idvb_h +#define __dvb_idvb_h + +#include +#include +#include +#include +#include + + // bitte KEINE operator int() definieren, sonst bringt das ganze nix! +struct eTransportStreamID +{ +private: + int v; +public: + int get() const { return v; } + eTransportStreamID(int i): v(i) { } + eTransportStreamID(): v(-1) { } + bool operator == (const eTransportStreamID &c) const { return v == c.v; } + bool operator != (const eTransportStreamID &c) const { return v != c.v; } + bool operator < (const eTransportStreamID &c) const { return v < c.v; } + bool operator > (const eTransportStreamID &c) const { return v > c.v; } +}; + +struct eServiceID +{ +private: + int v; +public: + int get() const { return v; } + eServiceID(int i): v(i) { } + eServiceID(): v(-1) { } + bool operator == (const eServiceID &c) const { return v == c.v; } + bool operator != (const eServiceID &c) const { return v != c.v; } + bool operator < (const eServiceID &c) const { return v < c.v; } + bool operator > (const eServiceID &c) const { return v > c.v; } +}; + +struct eOriginalNetworkID +{ +private: + int v; +public: + int get() const { return v; } + eOriginalNetworkID(int i): v(i) { } + eOriginalNetworkID(): v(-1) { } + bool operator == (const eOriginalNetworkID &c) const { return v == c.v; } + bool operator != (const eOriginalNetworkID &c) const { return v != c.v; } + bool operator < (const eOriginalNetworkID &c) const { return v < c.v; } + bool operator > (const eOriginalNetworkID &c) const { return v > c.v; } +}; + +struct eDVBNamespace +{ +private: + int v; +public: + int get() const { return v; } + eDVBNamespace(int i): v(i) { } + eDVBNamespace(): v(-1) { } + bool operator == (const eDVBNamespace &c) const { return v == c.v; } + bool operator != (const eDVBNamespace &c) const { return v != c.v; } + bool operator < (const eDVBNamespace &c) const { return v < c.v; } + bool operator > (const eDVBNamespace &c) const { return v > c.v; } +}; + +struct eDVBChannelID +{ + eDVBNamespace dvbnamespace; + eTransportStreamID transport_stream_id; + eOriginalNetworkID original_network_id; + bool operator<(const eDVBChannelID &c) const + { + if (dvbnamespace < c.dvbnamespace) + return 1; + else if (dvbnamespace == c.dvbnamespace) + { + if (original_network_id < c.original_network_id) + return 1; + else if (original_network_id == c.original_network_id) + if (transport_stream_id < c.transport_stream_id) + return 1; + } + return 0; + } + eDVBChannelID(eDVBNamespace dvbnamespace, eTransportStreamID tsid, eOriginalNetworkID onid): + dvbnamespace(dvbnamespace), transport_stream_id(tsid), original_network_id(onid) + { + } + eDVBChannelID(): + dvbnamespace(-1), transport_stream_id(-1), original_network_id(-1) + { + } + operator bool() const + { + return (dvbnamespace != -1) && (transport_stream_id != -1) && (original_network_id != -1); + } +}; + +struct eServiceReferenceDVB: public eServiceReference +{ + int getServiceType() const { return data[0]; } + void setServiceType(int service_type) { data[0]=service_type; } + + eServiceID getServiceID() const { return eServiceID(data[1]); } + void setServiceID(eServiceID service_id) { data[1]=service_id.get(); } + + eTransportStreamID getTransportStreamID() const { return eTransportStreamID(data[2]); } + void setTransportStreamID(eTransportStreamID transport_stream_id) { data[2]=transport_stream_id.get(); } + + eOriginalNetworkID getOriginalNetworkID() const { return eOriginalNetworkID(data[3]); } + void setOriginalNetworkID(eOriginalNetworkID original_network_id) { data[3]=original_network_id.get(); } + + eDVBNamespace getDVBNamespace() const { return eDVBNamespace(data[4]); } + void setDVBNamespace(eDVBNamespace dvbnamespace) { data[4]=dvbnamespace.get(); } + + eServiceReferenceDVB(eDVBNamespace dvbnamespace, eTransportStreamID transport_stream_id, eOriginalNetworkID original_network_id, eServiceID service_id, int service_type) + :eServiceReference(eServiceReference::idDVB, 0) + { + setTransportStreamID(transport_stream_id); + setOriginalNetworkID(original_network_id); + setDVBNamespace(dvbnamespace); + setServiceID(service_id); + setServiceType(service_type); + } + + void set(const eDVBChannelID &chid) + { + setDVBNamespace(chid.dvbnamespace); + setOriginalNetworkID(chid.original_network_id); + setTransportStreamID(chid.transport_stream_id); + } + + void getChannelID(eDVBChannelID &chid) + { + chid = eDVBChannelID(getDVBNamespace(), getTransportStreamID(), getOriginalNetworkID()); + } + + eServiceReferenceDVB() + :eServiceReference(eServiceReference::idDVB, 0) + { + } +}; + + +class iDVBChannel; +class iDVBDemux; +class iDVBFrontendParameters; + +class iDVBChannelList: public virtual iObject +{ +public: + virtual RESULT getChannelFrontendData(const eDVBChannelID &id, ePtr &parm)=0; +}; + +class iDVBResourceManager: public virtual iObject +{ +public: + /* + solange rumloopen bis eine resource gefunden wurde, die eine frequenz + tunen will + + wenn natuerlich sowas schon vorhanden ist, dann einfach ne ref darauf + geben. (zwei services auf dem gleichen transponder teilen sich einen + channel) + */ + virtual RESULT setChannelList(iDVBChannelList *list)=0; + virtual RESULT getChannelList(ePtr &list)=0; + virtual RESULT allocateChannel(const eDVBChannelID &channel, ePtr &channel)=0; + virtual RESULT allocateRawChannel(ePtr &channel)=0; + virtual RESULT allocatePVRChannel(int caps)=0; +}; + +class SatelliteDeliverySystemDescriptor; +class CableDeliverySystemDescriptor; +class TerrestrialDeliverySystemDescriptor; + +struct eDVBFrontendParametersSatellite +{ + struct Polarisation + { + enum { + Horizontal, Vertical, CircularLeft, CircularRight + }; + }; + struct Inversion + { + enum { + On, Off, Unknown + }; + }; + struct FEC + { + enum { + fNone, f1_2, f2_3, f3_4, f5_6, f7_8, fAuto + }; + }; + unsigned int frequency, symbol_rate; + int polarisation, fec, inversion, orbital_position; + + void set(const SatelliteDeliverySystemDescriptor &); +}; + +struct eDVBFrontendParametersCable +{ + unsigned int frequency, symbol_rate; + int modulation, inversion, fec_inner; + void set(const CableDeliverySystemDescriptor &); +}; + +struct eDVBFrontendParametersTerrestrial +{ + int unknown; + void set(const TerrestrialDeliverySystemDescriptor &); +}; + +class iDVBFrontendParameters: public virtual iObject +{ +public: + virtual RESULT getSystem(int &type) const = 0; + virtual RESULT getDVBS(eDVBFrontendParametersSatellite &p) const = 0; + virtual RESULT getDVBC(eDVBFrontendParametersCable &p) const = 0; + virtual RESULT getDVBT(eDVBFrontendParametersTerrestrial &p) const = 0; + + virtual RESULT calculateDifference(const iDVBFrontendParameters *parm, int &diff) const = 0; + virtual RESULT getHash(unsigned long &hash) const = 0; +}; + +#define MAX_DISEQC_LENGTH 16 + +struct eDVBDiseqcCommand +{ + int len; + __u8 data[MAX_DISEQC_LENGTH]; +}; + +class iDVBSatelliteEquipmentControl; + +class iDVBFrontend: public virtual iObject +{ +public: + enum { + feSatellite, feCable, feTerrestrial + }; + virtual RESULT getFrontendType(int &type)=0; + virtual RESULT tune(const iDVBFrontendParameters &where)=0; + virtual RESULT connectStateChange(const Slot1 &stateChange, ePtr &connection)=0; + enum { + stateIdle = 0, + stateTuning = 1, + stateFailed = 2, + stateLock = 3 + }; + virtual RESULT getState(int &state)=0; + enum { + toneOn, toneOff + }; + virtual RESULT setTone(int tone)=0; + enum { + voltageOff, voltage13, voltage18 + }; + virtual RESULT setVoltage(int voltage)=0; + virtual RESULT sendDiseqc(const eDVBDiseqcCommand &diseqc)=0; + virtual RESULT setSEC(iDVBSatelliteEquipmentControl *sec)=0; +}; + +class iDVBSatelliteEquipmentControl: public iObject +{ +public: + virtual RESULT prepare(iDVBFrontend &frontend, struct dvb_frontend_parameters &parm, eDVBFrontendParametersSatellite &sat)=0; +}; + +struct eDVBCIRouting +{ + int enabled; +}; + +class iDVBChannel: public virtual iObject +{ +public: + enum + { + state_idle, /* not yet tuned */ + state_tuning, /* currently tuning (first time) */ + state_unavailable, /* currently unavailable, will be back without further interaction */ + state_ok /* ok */ + }; + virtual RESULT connectStateChange(const Slot1 &stateChange, ePtr &connection)=0; + virtual RESULT getState(int &state)=0; + enum + { + cap_decode, + cap_ci + }; + virtual RESULT setCIRouting(const eDVBCIRouting &routing)=0; + virtual RESULT getDemux(ePtr &demux)=0; + + /* direct frontend access for raw channels and/or status inquiries. */ + virtual RESULT getFrontend(ePtr &frontend)=0; +}; + +class iDVBSectionReader; +class iTSMPEGDecoder; + +class iDVBDemux: public virtual iObject +{ +public: + virtual RESULT createSectionReader(eMainloop *context, ePtr &reader)=0; + virtual RESULT getMPEGDecoder(ePtr &reader)=0; +}; + +class iTSMPEGDecoder: public iObject +{ +public: + enum { pidDisabled = -1 }; + /** Set Displayed Video PID */ + virtual RESULT setVideoPID(int vpid)=0; + + enum { af_MPEG, af_AC3, af_DTS }; + /** Set Displayed Audio PID and type */ + virtual RESULT setAudioPID(int apid, int type)=0; + + /** Set Sync mode to PCR */ + virtual RESULT setSyncPCR(int pcrpid)=0; + enum { sm_Audio, sm_Video }; + /** Set Sync mode to either audio or video master */ + virtual RESULT setSyncMaster(int who)=0; + + /** Apply settings */ + virtual RESULT start()=0; + + /** Freeze frame. Either continue decoding (without display) or halt. */ + virtual RESULT freeze(int cont)=0; + /** Continue after freeze. */ + virtual RESULT unfreeze()=0; + + // stop on .. Picture + enum { spm_I, spm_Ref, spm_Any }; + /** Stop on specific decoded picture. For I-Frame display. */ + virtual RESULT setSinglePictureMode(int when)=0; + + enum { pkm_B, pkm_PB }; + /** Fast forward by skipping either B or P/B pictures */ + virtual RESULT setPictureSkipMode(int what)=0; + + /** Slow Motion by repeating pictures */ + virtual RESULT setSlowMotion(int repeat)=0; + + enum { zoom_Normal, zoom_PanScan, zoom_Letterbox, zoom_Fullscreen }; + /** Set Zoom. mode *must* be fitting. */ + virtual RESULT setZoom(int what)=0; +}; + +#endif diff --git a/lib/dvb/isection.h b/lib/dvb/isection.h new file mode 100644 index 00000000..04b50f52 --- /dev/null +++ b/lib/dvb/isection.h @@ -0,0 +1,53 @@ +#ifndef __dvb_isection_h +#define __dvb_isection_h + +#include + +#ifndef DMX_FILTER_SIZE +#define DMX_FILTER_SIZE 16 +#endif + +struct eDVBSectionFilterMask +{ + int pid; + /* mode is 0 for positive, 1 for negative filtering */ + __u8 data[DMX_FILTER_SIZE], mask[DMX_FILTER_SIZE], mode[DMX_FILTER_SIZE]; + enum { + rfCRC=1, + rfNoAbort=2 + }; + int flags; +}; + +struct eDVBTableSpec +{ + int pid, tid, tidext; + int version; + int timeout; /* timeout in ms */ + enum + { + tfInOrder=1, + /* + tfAnyVersion filter ANY version + 0 filter all EXCEPT given version (negative filtering) + tfThisVersion filter only THIS version + */ + tfAnyVersion=2, + tfThisVersion=4, + tfHaveTID=8, + tfHaveTIDExt=16, + tfCheckCRC=32, + tfHaveTimeout=64, + }; + int flags; +}; + +class iDVBSectionReader: public virtual iObject +{ +public: + virtual RESULT start(const eDVBSectionFilterMask &mask)=0; + virtual RESULT stop()=0; + virtual RESULT connectRead(const Slot1 &read, ePtr &conn)=0; +}; + +#endif diff --git a/lib/dvb/list.h b/lib/dvb/list.h new file mode 100644 index 00000000..6df49803 --- /dev/null +++ b/lib/dvb/list.h @@ -0,0 +1,13 @@ +#ifndef __list_h +#define __list_h + +class eDVBTransponderList: iDVBChannelList +{ + DECLARE_REF; +private: + std::map > channels; +public: + virtual RESULT getChannelFrontendData(const eDVBChannelID &id, ePtr &parm)=0; +}; + +#endif diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp new file mode 100644 index 00000000..4ab551f1 --- /dev/null +++ b/lib/dvb/pmt.cpp @@ -0,0 +1,142 @@ +#include +#include +#include + +eDVBServicePMTHandler::eDVBServicePMTHandler() +{ + ePtr mgr; + eDVBResourceManager::getInstance(mgr); + m_resourceManager = mgr; + CONNECT(m_PMT.tableReady, eDVBServicePMTHandler::PMTready); + CONNECT(m_PAT.tableReady, eDVBServicePMTHandler::PATready); +} + +void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel) +{ + int state; + channel->getState(state); + + if ((m_last_channel_state != iDVBChannel::state_ok) + && (state == iDVBChannel::state_ok) && (!m_demux)) + { + if (m_channel) + if (m_channel->getDemux(m_demux)) + eDebug("shit it failed.. again."); + + if (m_demux) + { + eDebug("ok ... now we start!!"); + m_PAT.begin(eApp, eDVBPATSpec(), m_demux); + } + } +} + +void eDVBServicePMTHandler::PMTready(int error) +{ + if (error) + serviceEvent(eventNoPMT); + else + serviceEvent(eventNewProgramInfo); +} + +void eDVBServicePMTHandler::PATready(int) +{ + ePtr > ptr; + if (!m_PAT.getCurrent(ptr)) + { + int pmtpid = -1; + ProgramAssociationTableConstIterator i; + for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i) + { + const ProgramAssociationTable &pat = **i; + ProgramAssociationConstIterator program; + for (program = pat.getPrograms()->begin(); program != pat.getPrograms()->end(); ++program) + if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID()) + pmtpid = (*program)->getProgramMapPid(); + } + if (pmtpid == -1) + serviceEvent(eventNoPATEntry); + else + m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux); + } else + serviceEvent(eventNoPAT); +} + +int eDVBServicePMTHandler::getProgramInfo(struct program &program) +{ + ePtr > ptr; + + program.videoStreams.clear(); + program.audioStreams.clear(); + program.pcrPid = -1; + + if (!m_PMT.getCurrent(ptr)) + { + ProgramMapTableConstIterator i; + for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i) + { + const ProgramMapTable &pmt = **i; + program.pcrPid = pmt.getPcrPid(); + + ElementaryStreamInfoConstIterator es; + for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) + { + int isaudio = 0, isvideo = 0; + videoStream video; + audioStream audio; + + video.pid = (*es)->getPid(); + audio.pid = (*es)->getPid(); + + switch ((*es)->getType()) + { + case 0x01: // MPEG 1 video + case 0x02: // MPEG 2 video + isvideo = 1; + break; + case 0x03: // MPEG 1 audio + case 0x04: // MPEG 2 audio: + isaudio = 1; + audio.type = audioStream::atMPEG; + break; + } + if (isaudio) + program.audioStreams.push_back(audio); + if (isvideo) + program.videoStreams.push_back(video); + } + } + return 0; + } else + return -1; +} + +int eDVBServicePMTHandler::getDemux(ePtr &demux) +{ + demux = m_demux; + if (demux) + return 0; + else + return -1; +} + +int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref) +{ + RESULT res; + m_channel = 0; + m_channelStateChanged_connection = 0; + m_reference = ref; + eDVBChannelID chid; + ref.getChannelID(chid); + res = m_resourceManager->allocateChannel(chid, m_channel); + eDebug("eDVBServicePMTHandler: tune %d", res); + if (m_channel) + { + m_channel->connectStateChange( + slot(*this, &eDVBServicePMTHandler::channelStateChanged), + m_channelStateChanged_connection); + m_last_channel_state = -1; + channelStateChanged(m_channel); + } + return res; +} diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h new file mode 100644 index 00000000..ee2040af --- /dev/null +++ b/lib/dvb/pmt.h @@ -0,0 +1,71 @@ +#ifndef __lib_dvb_dvbmid_h +#define __lib_dvb_dvbmid_h + +#include +#include +#include +#include +#include + +class eDVBServicePMTHandler: public Object +{ + eServiceReferenceDVB m_reference; +// ePtr m_service; + + int m_last_channel_state; + + eAUTable > m_PMT; + eAUTable > m_PAT; + + ePtr m_channel; + ePtr m_resourceManager; + ePtr m_demux; + + void channelStateChanged(iDVBChannel *); + ePtr m_channelStateChanged_connection; + + void PMTready(int error); + void PATready(int error); + +public: + eDVBServicePMTHandler(); + + enum + { + eventNoResources, // a requested resource couldn't be allocated + eventNoPAT, // no pat could be received (timeout) + eventNoPATEntry, // no pat entry for the corresponding SID could be found + eventNoPMT, // no pmt could be received (timeout) + eventNewProgramInfo // we just received a PMT + }; + + Signal1 serviceEvent; + + struct videoStream + { + int pid; + }; + + struct audioStream + { + int pid; + enum { atMPEG, atAC3, atDTS }; + int type; // mpeg2, ac3, dts, ... + // language code, ... + }; + + struct program + { + std::vector videoStreams; + std::vector audioStreams; + // ca info + int pcrPid; + }; + + int getProgramInfo(struct program &program); + int getDemux(ePtr &demux); + + int tune(eServiceReferenceDVB &ref); +}; + +#endif diff --git a/lib/dvb/scan.cpp b/lib/dvb/scan.cpp new file mode 100644 index 00000000..68121c44 --- /dev/null +++ b/lib/dvb/scan.cpp @@ -0,0 +1,374 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +eDVBScan::eDVBScan(iDVBChannel *channel): m_channel(channel) +{ + if (m_channel->getDemux(m_demux)) + eDebug("scan: failed to allocate demux!"); + m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection); +} + +eDVBScan::~eDVBScan() +{ +} + +int eDVBScan::isValidONIDTSID(eOriginalNetworkID onid, eTransportStreamID tsid) +{ + switch (onid.get()) + { + case 0: + case 0xFFFF: + case 0x1111: + return 0; + case 1: + return tsid>1; + case 0x00B1: + return tsid != 0x00B0; + case 0x0002: + return tsid != 0x07E8; + default: + return 1; + } +} + +eDVBNamespace eDVBScan::buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash) +{ + // on valid ONIDs, ignore frequency ("sub network") part + if (isValidONIDTSID(onid, tsid)) + hash &= ~0xFFFF; + return eDVBNamespace(hash); +} + +void eDVBScan::stateChange(iDVBChannel *ch) +{ + int state; + if (ch->getState(state)) + return; + if (m_channel_state == state) + return; + + if (state == iDVBChannel::state_ok) + { + startFilter(); + m_channel_state = state; + } else if (state == iDVBChannel::state_unavailable) + { + m_ch_unavailable.push_back(m_ch_current); + nextChannel(); + } +} + +RESULT eDVBScan::nextChannel() +{ + ePtr fe; + + m_SDT = 0; m_BAT = 0; m_NIT = 0; + + m_ready = readyBAT; + if (m_ch_toScan.empty()) + { + eDebug("no channels left to scan."); + eDebug("%d channels scanned, %d were unavailable.", + m_ch_scanned.size(), m_ch_unavailable.size()); + eDebug("%d channels in database.", m_new_channels.size()); + m_event(evtFinish); + return -ENOENT; + } + + m_ch_current = m_ch_toScan.front(); + m_ch_toScan.pop_front(); + + if (m_channel->getFrontend(fe)) + return -ENOTSUP; + + m_channel_state = iDVBChannel::state_idle; + if (fe->tune(*m_ch_current)) + return -EINVAL; + + m_event(evtUpdate); + return 0; +} + +RESULT eDVBScan::startFilter() +{ + assert(m_demux); + + m_SDT = new eTable(); + if (m_SDT->start(m_demux, eDVBSDTSpec())) + return -1; + CONNECT(m_SDT->tableReady, eDVBScan::SDTready); + + m_NIT = 0; + m_NIT = new eTable(); + if (m_NIT->start(m_demux, eDVBNITSpec())) + return -1; + CONNECT(m_NIT->tableReady, eDVBScan::NITready); + + m_BAT = new eTable(); + if (m_BAT->start(m_demux, eDVBBATSpec())) + return -1; + CONNECT(m_BAT->tableReady, eDVBScan::BATready); + + return 0; +} + +void eDVBScan::SDTready(int err) +{ + eDebug("got sdt"); + m_ready |= readySDT; + if (!err) + m_ready |= validSDT; + channelDone(); +} + +void eDVBScan::NITready(int err) +{ + eDebug("got nit, err %d", err); + m_ready |= readyNIT; + if (!err) + m_ready |= validNIT; + channelDone(); +} + +void eDVBScan::BATready(int err) +{ + eDebug("got bat"); + m_ready |= readyBAT; + if (!err) + m_ready |= validBAT; + channelDone(); +} + +void eDVBScan::addChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm) +{ + /* add it to the list of known channels. */ + if (chid) + m_new_channels.insert(std::pair >(chid, feparm)); + + /* check if we don't already have that channel ... */ + + /* ... in the list of channels to scan */ + for (std::list >::const_iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end(); ++i) + if (sameChannel(*i, feparm)) + return; + + /* ... in the list of successfully scanned channels */ + for (std::list >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i) + if (sameChannel(*i, feparm)) + return; + + /* ... in the list of unavailable channels */ + for (std::list >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i) + if (sameChannel(*i, feparm)) + return; + + /* ... on the current channel */ + if (sameChannel(m_ch_current, feparm)) + return; + + /* otherwise, add it to the todo list. */ + m_ch_toScan.push_back(feparm); +} + +int eDVBScan::sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2) const +{ + int diff; + if (ch1->calculateDifference(ch2, diff)) + return 0; + if (diff < 4000) // more than 4mhz difference? + return 1; + return 0; +} + +void eDVBScan::channelDone() +{ + if (m_ready & validSDT) + { + unsigned long hash = 0; + m_ch_current->getHash(hash); + + eDVBNamespace dvbnamespace = buildNamespace( + (**m_SDT->getSections().begin()).getOriginalNetworkId(), + (**m_SDT->getSections().begin()).getTransportStreamId(), + hash); + + eDebug("SDT: "); + ServiceDescriptionTableConstIterator i; + for (i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i) + processSDT(dvbnamespace, **i); + m_ready &= ~validSDT; + } + + if (m_ready & validNIT) + { + eDebug("dumping NIT"); + NetworkInformationTableConstIterator i; + for (i = m_NIT->getSections().begin(); i != m_NIT->getSections().end(); ++i) + { + const TransportStreamInfoVector &tsinfovec = *(*i)->getTsInfo(); + + for (TransportStreamInfoConstIterator tsinfo(tsinfovec.begin()); + tsinfo != tsinfovec.end(); ++tsinfo) + { + eDebug("TSID: %04x ONID: %04x", (*tsinfo)->getTransportStreamId(), + (*tsinfo)->getOriginalNetworkId()); + + eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId(); + eTransportStreamID tsid = (*tsinfo)->getTransportStreamId(); + + for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin(); + desc != (*tsinfo)->getDescriptors()->end(); ++desc) + { + switch ((*desc)->getTag()) + { +// case SERVICE_LIST_DESCRIPTOR: + case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR: + { + SatelliteDeliverySystemDescriptor &d = (SatelliteDeliverySystemDescriptor&)**desc; + eDebug("%d kHz, %d%d%d.%d%c %s MOD:%d %d symb/s, fec %d", + d.getFrequency(), + (d.getOrbitalPosition()>>12)&0xF, + (d.getOrbitalPosition()>>8)&0xF, + (d.getOrbitalPosition()>>4)&0xF, + d.getOrbitalPosition()&0xF, d.getWestEastFlag()?'E':'W', + d.getPolarization() ? "hor" : "vert", + d.getModulation(), d.getSymbolRate(), d.getFecInner()); + + /* some sanity checking: below 100MHz is invalid */ + if (d.getFrequency() < 10000) + break; + + ePtr feparm = new eDVBFrontendParameters; + eDVBFrontendParametersSatellite sat; + sat.set(d); + feparm->setDVBS(sat); + unsigned long hash=0; + feparm->getHash(hash); + + eDVBNamespace ns = buildNamespace(onid, tsid, hash); + + addChannel( + eDVBChannelID(ns, tsid, onid), + feparm); + break; + } + default: + eDebug("descr<%x>", (*desc)->getTag()); + break; + } + } + + } + } + m_ready &= ~validNIT; + } + + if ((m_ready & readyAll) != readyAll) + return; + eDebug("channel done!"); + m_ch_scanned.push_back(m_ch_current); + nextChannel(); +} + +void eDVBScan::start(const std::list > &known_transponders) +{ + m_ch_toScan.clear(); + m_ch_scanned.clear(); + m_ch_unavailable.clear(); + m_new_channels.clear(); + m_new_services.clear(); + m_ch_toScan.insert(m_ch_toScan.end(), known_transponders.begin(), known_transponders.end()); + nextChannel(); +} + +void eDVBScan::insertInto(eDVBDB *db) +{ + for (std::map >::const_iterator + ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch) + db->addChannelToList(ch->first, ch->second); + for (std::map >::const_iterator + service(m_new_services.begin()); service != m_new_services.end(); ++service) + { + ePtr dvb_service; + if (!db->getService(service->first, dvb_service)) + *dvb_service = *service->second; + else + db->addService(service->first, service->second); + } +} + +RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionTable &sdt) +{ + const ServiceDescriptionVector &services = *sdt.getDescriptions(); + eDebug("ONID: %04x", sdt.getOriginalNetworkId()); + eDVBChannelID chid(dvbnamespace, sdt.getTransportStreamId(), sdt.getOriginalNetworkId()); + + for (ServiceDescriptionConstIterator s(services.begin()); s != services.end(); ++s) + { + eDebugNoNewLine("SID %04x: ", (*s)->getServiceId()); + + eServiceReferenceDVB ref; + ePtr service = new eDVBService; + + ref.set(chid); + ref.setServiceID((*s)->getServiceId()); + + for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin(); + desc != (*s)->getDescriptors()->end(); ++desc) + if ((*desc)->getTag() == SERVICE_DESCRIPTOR) + ref.setServiceType(((ServiceDescriptor&)**desc).getServiceType()); + + for (DescriptorConstIterator desc = (*s)->getDescriptors()->begin(); + desc != (*s)->getDescriptors()->end(); ++desc) + { + switch ((*desc)->getTag()) + { + case SERVICE_DESCRIPTOR: + { + ServiceDescriptor &d = (ServiceDescriptor&)**desc; + eDebug("name '%s', provider_name '%s'", d.getServiceName().c_str(), d.getServiceProviderName().c_str()); + service->m_service_name = d.getServiceName(); + service->m_provider_name = d.getServiceProviderName(); + break; + } + case CA_IDENTIFIER_DESCRIPTOR: + { + CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc; + const CaSystemIdVector &caids = *d.getCaSystemIds(); + eDebugNoNewLine("CA "); + for (CaSystemIdVector::const_iterator i(caids.begin()); i != caids.end(); ++i) + { + eDebugNoNewLine("%04x ", *i); + service->m_ca.insert(*i); + } + eDebug(""); + break; + } + default: + eDebug("descr<%x>", (*desc)->getTag()); + break; + } + } + + m_new_services.insert(std::pair >(ref, service)); + } + return 0; +} + +RESULT eDVBScan::connectEvent(const Slot1 &event, ePtr &connection) +{ + connection = new eConnection(m_event.connect(event)); + return 0; +} diff --git a/lib/dvb/scan.h b/lib/dvb/scan.h new file mode 100644 index 00000000..196e52fc --- /dev/null +++ b/lib/dvb/scan.h @@ -0,0 +1,69 @@ +#ifndef __lib_dvb_scan_h +#define __lib_dvb_scan_h + +#include +#include +#include +#include + +class eDVBScan: public Object +{ + /* chid helper functions: */ + + /* heuristically determine if onid/tsid is valid */ + int isValidONIDTSID(eOriginalNetworkID onid, eTransportStreamID tsid); + /* build dvb namespace */ + eDVBNamespace buildNamespace(eOriginalNetworkID onid, eTransportStreamID tsid, unsigned long hash); + + /* scan resources */ + ePtr m_channel; + ePtr m_demux; + + /* infrastructure */ + void stateChange(iDVBChannel *); + ePtr m_stateChanged_connection; + + /* state handling */ + RESULT nextChannel(); + + RESULT startFilter(); + enum { readySDT=1, readyNIT=2, readyBAT=4, readyAll=7, + validSDT=8, validNIT=16, validBAT=32}; + + /* scan state variables */ + int m_channel_state; + int m_ready; + + std::map > m_new_channels; + std::map > m_new_services; + + std::list > m_ch_toScan, m_ch_scanned, m_ch_unavailable; + ePtr m_ch_current; + + ePtr > m_SDT; + ePtr > m_NIT; + ePtr > m_BAT; + + void SDTready(int err); + void NITready(int err); + void BATready(int err); + + void addChannel(const eDVBChannelID &chid, iDVBFrontendParameters *feparm); + int sameChannel(iDVBFrontendParameters *ch1, iDVBFrontendParameters *ch2) const; + + void channelDone(); + + Signal1 m_event; + RESULT processSDT(eDVBNamespace dvbnamespace, const ServiceDescriptionTable &sdt); +public: + eDVBScan(iDVBChannel *channel); + ~eDVBScan(); + + void start(const std::list > &known_transponders); + + enum { evtUpdate, evtFinish }; + RESULT connectEvent(const Slot1 &event, ePtr &connection); + void insertInto(eDVBDB *db); +}; + +#endif diff --git a/lib/dvb/sec.cpp b/lib/dvb/sec.cpp new file mode 100644 index 00000000..99e39ea6 --- /dev/null +++ b/lib/dvb/sec.cpp @@ -0,0 +1,58 @@ +#include +#include +#include + +DEFINE_REF(eDVBSatelliteEquipmentControl); + +RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, struct dvb_frontend_parameters &parm, eDVBFrontendParametersSatellite &sat) +{ + int hi; + eDebug("(very) ugly and hardcoded eDVBSatelliteEquipmentControl"); + + if (sat.frequency > 11700000) + hi = 1; + else + hi = 0; + + if (hi) + parm.frequency = sat.frequency - 10600000; + else + parm.frequency = sat.frequency - 9750000; + +// frontend.sentDiseqc(...); + + parm.inversion = sat.inversion ? INVERSION_ON : INVERSION_OFF; + + switch (sat.fec) + { +// case 1: +// case ...: + default: + parm.u.qpsk.fec_inner = FEC_AUTO; + break; + } + parm.u.qpsk.symbol_rate = sat.symbol_rate; + + + frontend.setVoltage((sat.polarisation == eDVBFrontendParametersSatellite::Polarisation::Vertical) ? iDVBFrontend::voltage13 : iDVBFrontend::voltage18); + + eDVBDiseqcCommand diseqc; + + diseqc.len = 4; + diseqc.data[0] = 0xe0; + diseqc.data[1] = 0x10; + diseqc.data[2] = 0x38; + diseqc.data[3] = 0xF0; + + if (hi) + diseqc.data[3] |= 1; + + if (sat.polarisation == eDVBFrontendParametersSatellite::Polarisation::Horizontal) + diseqc.data[3] |= 2; + + frontend.sendDiseqc(diseqc); + frontend.setTone(hi ? iDVBFrontend::toneOn : iDVBFrontend::toneOff); + + return 0; +} + diff --git a/lib/dvb/sec.h b/lib/dvb/sec.h new file mode 100644 index 00000000..e4b2d1d2 --- /dev/null +++ b/lib/dvb/sec.h @@ -0,0 +1,13 @@ +#ifndef __dvb_sec_h +#define __dvb_sec_h + +#include + +class eDVBSatelliteEquipmentControl: public iDVBSatelliteEquipmentControl +{ +public: + DECLARE_REF; + RESULT prepare(iDVBFrontend &frontend, struct dvb_frontend_parameters &parm, eDVBFrontendParametersSatellite &sat); +}; + +#endif diff --git a/lib/dvb/specs.h b/lib/dvb/specs.h new file mode 100644 index 00000000..3c6908c2 --- /dev/null +++ b/lib/dvb/specs.h @@ -0,0 +1,108 @@ +#ifndef __lib_dvb_specs_h +#define __lib_dvb_specs_h + +#include +#include +#include +#include +#include +#include +#include + +struct eDVBPMTSpec +{ + eDVBTableSpec m_spec; +public: + eDVBPMTSpec(int pid, int sid) + { + m_spec.pid = pid; + m_spec.tid = ProgramMapTable::TID; + m_spec.tidext = sid; + m_spec.timeout = ProgramMapTable::TIMEOUT; + m_spec.flags = eDVBTableSpec::tfAnyVersion | + eDVBTableSpec::tfHaveTID | eDVBTableSpec::tfHaveTIDExt | + eDVBTableSpec::tfCheckCRC | eDVBTableSpec::tfHaveTimeout; + } + operator eDVBTableSpec &() + { + return m_spec; + } +}; + +struct eDVBSDTSpec +{ + eDVBTableSpec m_spec; +public: + eDVBSDTSpec() + { + m_spec.pid = ServiceDescriptionTable::PID; + m_spec.tid = ServiceDescriptionTable::TID; + m_spec.timeout = ServiceDescriptionTable::TIMEOUT; + m_spec.flags = eDVBTableSpec::tfAnyVersion | + eDVBTableSpec::tfHaveTID | eDVBTableSpec::tfCheckCRC | + eDVBTableSpec::tfHaveTimeout; + } + operator eDVBTableSpec &() + { + return m_spec; + } +}; + +struct eDVBNITSpec +{ + eDVBTableSpec m_spec; +public: + eDVBNITSpec() + { + m_spec.pid = NetworkInformationTable::PID; + m_spec.tid = NetworkInformationTable::TID; + m_spec.timeout = NetworkInformationTable::TIMEOUT; + m_spec.flags = eDVBTableSpec::tfAnyVersion | + eDVBTableSpec::tfHaveTID | eDVBTableSpec::tfCheckCRC | + eDVBTableSpec::tfHaveTimeout; + } + operator eDVBTableSpec &() + { + return m_spec; + } +}; + +struct eDVBBATSpec +{ + eDVBTableSpec m_spec; +public: + eDVBBATSpec() + { + m_spec.pid = BouquetAssociationTable::PID; + m_spec.tid = BouquetAssociationTable::TID; + m_spec.timeout = BouquetAssociationTable::TIMEOUT; + m_spec.flags = eDVBTableSpec::tfAnyVersion | + eDVBTableSpec::tfHaveTID | eDVBTableSpec::tfCheckCRC | + eDVBTableSpec::tfHaveTimeout; + } + operator eDVBTableSpec &() + { + return m_spec; + } +}; + +struct eDVBPATSpec +{ + eDVBTableSpec m_spec; +public: + eDVBPATSpec() + { + m_spec.pid = ProgramAssociationTable::PID; + m_spec.tid = ProgramAssociationTable::TID; + m_spec.timeout = ProgramAssociationTable::TIMEOUT; + m_spec.flags = eDVBTableSpec::tfAnyVersion | + eDVBTableSpec::tfHaveTID | eDVBTableSpec::tfCheckCRC | + eDVBTableSpec::tfHaveTimeout; + } + operator eDVBTableSpec &() + { + return m_spec; + } +}; + +#endif diff --git a/lib/dvb/stT1RVV7 b/lib/dvb/stT1RVV7 new file mode 100644 index 00000000..a9d6d3dc Binary files /dev/null and b/lib/dvb/stT1RVV7 differ diff --git a/lib/dvb_si/Makefile.am b/lib/dvb_si/Makefile.am new file mode 100644 index 00000000..e69de29b diff --git a/lib/dvb_si/Makefile.in b/lib/dvb_si/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/lib/dvb_si/ac3_descriptor.cpp b/lib/dvb_si/ac3_descriptor.cpp new file mode 100644 index 00000000..a4f5d635 --- /dev/null +++ b/lib/dvb_si/ac3_descriptor.cpp @@ -0,0 +1,102 @@ +/* + * $Id: ac3_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +Ac3Descriptor::Ac3Descriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + if (buffer[1] >= 1) + { + ac3TypeFlag = (buffer[2] >> 7) & 0x01; + bsidFlag = (buffer[2] >> 6) & 0x01; + mainidFlag = (buffer[2] >> 5) & 0x01; + asvcFlag = (buffer[2] >> 4) & 0x01; + reserved = buffer[2] & 0x0F; + if (ac3TypeFlag == 1) + ac3Type = buffer[3]; + + if (bsidFlag == 1) + bsid = buffer[ac3TypeFlag + 3]; + + if (mainidFlag == 1) + mainid = buffer[ac3TypeFlag + mainidFlag + 3]; + + if (asvcFlag == 1) + avsc = buffer[ac3TypeFlag + bsidFlag + mainidFlag + 3]; + + if (descriptorLength > ac3TypeFlag + bsidFlag + mainidFlag + asvcFlag) + for (uint16_t i = 0; i < descriptorLength - ac3TypeFlag - bsidFlag - mainidFlag - asvcFlag - 1; ++i) + additionalInfo.push_back(buffer[ac3TypeFlag + bsidFlag + mainidFlag + asvcFlag + i + 3]); + } else + { + ac3TypeFlag = 0; + bsidFlag = 0; + mainidFlag = 0; + asvcFlag = 0; + reserved = 0; + } +} + +uint8_t Ac3Descriptor::getAc3TypeFlag(void) const +{ + return ac3TypeFlag; +} + +uint8_t Ac3Descriptor::getBsidFlag(void) const +{ + return bsidFlag; +} + +uint8_t Ac3Descriptor::getMainidFlag(void) const +{ + return mainidFlag; +} + +uint8_t Ac3Descriptor::getAsvcFlag(void) const +{ + return asvcFlag; +} + +uint8_t Ac3Descriptor::getAc3Type(void) const +{ + return ac3Type; +} + +uint8_t Ac3Descriptor::getBsid(void) const +{ + return bsid; +} + +uint8_t Ac3Descriptor::getMainid(void) const +{ + return mainid; +} + +uint8_t Ac3Descriptor::getAvsc(void) const +{ + return avsc; +} + +const AdditionalInfoVector *Ac3Descriptor::getAdditionalInfo(void) const +{ + return &additionalInfo; +} + diff --git a/lib/dvb_si/ac3_descriptor.h b/lib/dvb_si/ac3_descriptor.h new file mode 100644 index 00000000..d5eaf835 --- /dev/null +++ b/lib/dvb_si/ac3_descriptor.h @@ -0,0 +1,59 @@ +/* + * $Id: ac3_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_ac3_descriptor_h__ +#define __dvb_descriptor_ac3_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector AdditionalInfoVector; +typedef AdditionalInfoVector::iterator AdditionalInfoIterator; +typedef AdditionalInfoVector::const_iterator AdditionalInfoConstIterator; + +class Ac3Descriptor : public Descriptor +{ + protected: + unsigned ac3TypeFlag : 1; + unsigned bsidFlag : 1; + unsigned mainidFlag : 1; + unsigned asvcFlag : 1; + unsigned reserved : 4; + unsigned ac3Type : 8; + unsigned bsid : 8; + unsigned mainid : 8; + unsigned avsc : 8; + AdditionalInfoVector additionalInfo; + + public: + Ac3Descriptor(const uint8_t * const buffer); + + uint8_t getAc3TypeFlag(void) const; + uint8_t getBsidFlag(void) const; + uint8_t getMainidFlag(void) const; + uint8_t getAsvcFlag(void) const; + uint8_t getAc3Type(void) const; + uint8_t getBsid(void) const; + uint8_t getMainid(void) const; + uint8_t getAvsc(void) const; + const AdditionalInfoVector *getAdditionalInfo(void) const; +}; + +#endif /* __dvb_descriptor_ac3_descriptor_h__ */ diff --git a/lib/dvb_si/ait.cpp b/lib/dvb_si/ait.cpp new file mode 100644 index 00000000..74e38ca2 --- /dev/null +++ b/lib/dvb_si/ait.cpp @@ -0,0 +1,94 @@ +/* + * $Id: ait.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ApplicationIdentifier::ApplicationIdentifier(const uint8_t * const buffer) +{ + organisationId = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; + applicationId = (buffer[4] << 8) | buffer[5]; +} + +uint32_t ApplicationIdentifier::getOrganisationId(void) const +{ + return organisationId; +} + +uint16_t ApplicationIdentifier::getApplicationId(void) const +{ + return applicationId; +} + +ApplicationInformation::ApplicationInformation(const uint8_t * const buffer) +{ + applicationIdentifier = new ApplicationIdentifier(&buffer[0]); + applicationControlCode = buffer[6]; + reserved = (buffer[7] >> 4) & 0x0f; + applicationDescriptorsLoopLength = ((buffer[7] & 0x0f) << 8) | buffer[8]; + + for (uint16_t i = 0; i < applicationDescriptorsLoopLength; i += buffer[i + 10] + 2) + descriptor(&buffer[i + 9]); +} + +ApplicationInformation::~ApplicationInformation(void) +{ + delete applicationIdentifier; +} + +const ApplicationIdentifier *ApplicationInformation::getApplicationIdentifier(void) const +{ + return applicationIdentifier; +} + +uint8_t ApplicationInformation::getApplicationControlCode(void) const +{ + return applicationControlCode; +} + +ApplicationInformationTable::ApplicationInformationTable(const uint8_t * const buffer) : LongCrcTable(buffer) +{ + reserved4 = (buffer[8] >> 4) & 0x0f; + commonDescriptorsLength = ((buffer[8] & 0x0f) << 8) | buffer[9]; + + for (uint16_t i = 0; i < commonDescriptorsLength; i += buffer[i + 11] + 2) + descriptor(&buffer[i + 10]); + + reserved5 = (buffer[commonDescriptorsLength + 10] >> 4) & 0x0f; + applicationLoopLength = ((buffer[commonDescriptorsLength + 10] & 0x0f) << 8) | buffer[commonDescriptorsLength + 11]; + + for (uint16_t i = 0; i < applicationLoopLength; i += 9) { + ApplicationInformation *a = new ApplicationInformation(&buffer[commonDescriptorsLength + 12]); + applicationInformation.push_back(a); + i += a->applicationDescriptorsLoopLength; + } +} + +ApplicationInformationTable::~ApplicationInformationTable(void) +{ + for (ApplicationInformationIterator i = applicationInformation.begin(); i != applicationInformation.end(); ++i) + delete *i; +} + +const ApplicationInformationVector *ApplicationInformationTable::getApplicationInformation(void) const +{ + return &applicationInformation; +} + diff --git a/lib/dvb_si/ait.h b/lib/dvb_si/ait.h new file mode 100644 index 00000000..8dd71f68 --- /dev/null +++ b/lib/dvb_si/ait.h @@ -0,0 +1,86 @@ +/* + * $Id: ait.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_ait_h__ +#define __dvb_table_ait_h__ + +#include +#include "long_crc_table.h" + +class ApplicationIdentifier +{ + protected: + unsigned organisationId : 32; + unsigned applicationId : 16; + + public: + ApplicationIdentifier(const uint8_t * const buffer); + + uint32_t getOrganisationId(void) const; + uint16_t getApplicationId(void) const; +}; + +class ApplicationInformation : public DescriptorContainer +{ + protected: + ApplicationIdentifier *applicationIdentifier; + unsigned applicationControlCode : 8; + unsigned reserved : 4; + unsigned applicationDescriptorsLoopLength : 12; + + public: + ApplicationInformation(const uint8_t * const buffer); + ~ApplicationInformation(void); + + const ApplicationIdentifier *getApplicationIdentifier(void) const; + uint8_t getApplicationControlCode(void) const; + + friend class ApplicationInformationTable; +}; + +typedef std::vector ApplicationInformationVector; +typedef ApplicationInformationVector::iterator ApplicationInformationIterator; +typedef ApplicationInformationVector::const_iterator ApplicationInformationConstIterator; + +class ApplicationInformationTable : public LongCrcTable, public DescriptorContainer +{ + protected: + unsigned reserved4 : 4; + unsigned commonDescriptorsLength : 12; + unsigned reserved5 : 4; + unsigned applicationLoopLength : 12; + ApplicationInformationVector applicationInformation; + + public: + ApplicationInformationTable(const uint8_t * const buffer); + ~ApplicationInformationTable(void); + + static const enum TableId TID = TID_AIT; + static const uint32_t TIMEOUT = 12000; + + const ApplicationInformationVector *getApplicationInformation(void) const; +}; + +typedef std::vector ApplicationInformationTableVector; +typedef ApplicationInformationTableVector::iterator ApplicationInformationTableIterator; +typedef ApplicationInformationTableVector::const_iterator ApplicationInformationTableConstIterator; + +#endif /* __dvb_table_ait_h__ */ diff --git a/lib/dvb_si/ancillary_data_descriptor.cpp b/lib/dvb_si/ancillary_data_descriptor.cpp new file mode 100644 index 00000000..33cb85c2 --- /dev/null +++ b/lib/dvb_si/ancillary_data_descriptor.cpp @@ -0,0 +1,33 @@ +/* + * $Id: ancillary_data_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +AncillaryDataDescriptor::AncillaryDataDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + ancillaryDataIdentifier = buffer[2]; +} + +uint8_t AncillaryDataDescriptor::getAncillaryDataIdentifier(void) const +{ + return ancillaryDataIdentifier; +} + diff --git a/lib/dvb_si/ancillary_data_descriptor.h b/lib/dvb_si/ancillary_data_descriptor.h new file mode 100644 index 00000000..f6ddd115 --- /dev/null +++ b/lib/dvb_si/ancillary_data_descriptor.h @@ -0,0 +1,38 @@ +/* + * $Id: ancillary_data_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_ancillary_data_descriptor_h__ +#define __dvb_descriptor_ancillary_data_descriptor_h__ + +#include "descriptor.h" + +class AncillaryDataDescriptor : public Descriptor +{ + protected: + unsigned ancillaryDataIdentifier : 8; + + public: + AncillaryDataDescriptor(const uint8_t * const buffer); + + uint8_t getAncillaryDataIdentifier(void) const; +}; + +#endif /* __dvb_descriptor_ancillary_data_descriptor_h__ */ diff --git a/lib/dvb_si/announcement_support_descriptor.cpp b/lib/dvb_si/announcement_support_descriptor.cpp new file mode 100644 index 00000000..5cc13f7a --- /dev/null +++ b/lib/dvb_si/announcement_support_descriptor.cpp @@ -0,0 +1,107 @@ +/* + * $Id: announcement_support_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +Announcement::Announcement(const uint8_t * const buffer) +{ + announcementType = (buffer[0] >> 4) & 0x0f; + reserved = (buffer[0] >> 3) & 0x01; + referenceType = buffer[0] & 0x07; + + if ((referenceType >= 0x01) && (referenceType <= 0x03)) { + originalNetworkId = (buffer[1] << 8) | buffer[2]; + transportStreamId = (buffer[3] << 8) | buffer[4]; + serviceId = (buffer[5] << 8) | buffer[6]; + componentTag = buffer[7]; + } +} + +uint8_t Announcement::getAnnouncementType(void) const +{ + return announcementType; +} + +uint8_t Announcement::getReferenceType(void) const +{ + return referenceType; +} + +uint16_t Announcement::getOriginalNetworkId(void) const +{ + return originalNetworkId; +} + +uint16_t Announcement::getTransportStreamId(void) const +{ + return transportStreamId; +} + +uint16_t Announcement::getServiceId(void) const +{ + return serviceId; +} + +uint8_t Announcement::getComponentTag(void) const +{ + return componentTag; +} + +AnnouncementSupportDescriptor::AnnouncementSupportDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + Announcement *a; + + announcementSupportIndicator = (buffer[2] << 8) | buffer[3]; + + if (descriptorLength < 2) + return; + + for (uint16_t i = 0; i < descriptorLength - 2; ++i) { + a = new Announcement(&buffer[i + 4]); + announcements.push_back(a); + switch (a->getReferenceType()) { + case 0x01: + case 0x02: + case 0x03: + i += 7; + break; + default: + break; + } + } +} + +AnnouncementSupportDescriptor::~AnnouncementSupportDescriptor(void) +{ + for (AnnouncementIterator i = announcements.begin(); i != announcements.end(); ++i) + delete *i; +} + +uint16_t AnnouncementSupportDescriptor::getAnnouncementSupportIndicator(void) const +{ + return announcementSupportIndicator; +} + +const AnnouncementVector *AnnouncementSupportDescriptor::getAnnouncements(void) const +{ + return &announcements; +} + diff --git a/lib/dvb_si/announcement_support_descriptor.h b/lib/dvb_si/announcement_support_descriptor.h new file mode 100644 index 00000000..ce80cbe7 --- /dev/null +++ b/lib/dvb_si/announcement_support_descriptor.h @@ -0,0 +1,67 @@ +/* + * $Id: announcement_support_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_announcement_support_descriptor_h__ +#define __dvb_descriptor_announcement_support_descriptor_h__ + +#include "descriptor.h" + +class Announcement +{ + protected: + unsigned announcementType : 4; + unsigned reserved : 1; + unsigned referenceType : 3; + unsigned originalNetworkId : 16; + unsigned transportStreamId : 16; + unsigned serviceId : 16; + unsigned componentTag : 8; + + public: + Announcement(const uint8_t * const buffer); + + uint8_t getAnnouncementType(void) const; + uint8_t getReferenceType(void) const; + uint16_t getOriginalNetworkId(void) const; + uint16_t getTransportStreamId(void) const; + uint16_t getServiceId(void) const; + uint8_t getComponentTag(void) const; +}; + +typedef std::vector AnnouncementVector; +typedef AnnouncementVector::iterator AnnouncementIterator; +typedef AnnouncementVector::const_iterator AnnouncementConstIterator; + +class AnnouncementSupportDescriptor : public Descriptor +{ + protected: + unsigned announcementSupportIndicator : 16; + AnnouncementVector announcements; + + public: + AnnouncementSupportDescriptor(const uint8_t * const buffer); + ~AnnouncementSupportDescriptor(void); + + uint16_t getAnnouncementSupportIndicator(void) const; + const AnnouncementVector *getAnnouncements(void) const; +}; + +#endif /* __dvb_descriptor_announcement_support_descriptor_h__ */ diff --git a/lib/dvb_si/application_signalling_descriptor.cpp b/lib/dvb_si/application_signalling_descriptor.cpp new file mode 100644 index 00000000..978780f7 --- /dev/null +++ b/lib/dvb_si/application_signalling_descriptor.cpp @@ -0,0 +1,57 @@ +/* + * $Id: application_signalling_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ApplicationSignalling::ApplicationSignalling(const uint8_t * const buffer) +{ + applicationType = (buffer[0] << 8) | buffer[1]; + reserved = (buffer[2] >> 5) & 0x07; + aitVersionNumber = buffer[2] & 0x1f; +} + +uint16_t ApplicationSignalling::getApplicationType(void) const +{ + return applicationType; +} + +uint8_t ApplicationSignalling::getAitVersionNumber(void) const +{ + return aitVersionNumber; +} + +ApplicationSignallingDescriptor::ApplicationSignallingDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 3) + applicationSignallings.push_back(new ApplicationSignalling(&buffer[i + 2])); +} + +ApplicationSignallingDescriptor::~ApplicationSignallingDescriptor(void) +{ + for (ApplicationSignallingIterator i = applicationSignallings.begin(); i != applicationSignallings.end(); ++i) + delete *i; +} + +const ApplicationSignallingVector *ApplicationSignallingDescriptor::getApplicationSignallings(void) const +{ + return &applicationSignallings; +} + diff --git a/lib/dvb_si/application_signalling_descriptor.h b/lib/dvb_si/application_signalling_descriptor.h new file mode 100644 index 00000000..c4533e13 --- /dev/null +++ b/lib/dvb_si/application_signalling_descriptor.h @@ -0,0 +1,57 @@ +/* + * $Id: application_signalling_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_application_signalling_descriptor_h__ +#define __dvb_descriptor_application_signalling_descriptor_h__ + +#include "descriptor.h" + +class ApplicationSignalling +{ + protected: + unsigned applicationType : 16; + unsigned reserved : 3; + unsigned aitVersionNumber : 5; + + public: + ApplicationSignalling(const uint8_t * const buffer); + + uint16_t getApplicationType(void) const; + uint8_t getAitVersionNumber(void) const; +}; + +typedef std::vector ApplicationSignallingVector; +typedef ApplicationSignallingVector::iterator ApplicationSignallingIterator; +typedef ApplicationSignallingVector::const_iterator ApplicationSignallingConstIterator; + +class ApplicationSignallingDescriptor : public Descriptor +{ + protected: + ApplicationSignallingVector applicationSignallings; + + public: + ApplicationSignallingDescriptor(const uint8_t * const buffer); + ~ApplicationSignallingDescriptor(void); + + const ApplicationSignallingVector *getApplicationSignallings(void) const; +}; + +#endif /* __dvb_descriptor_application_signalling_descriptor_h__ */ diff --git a/lib/dvb_si/audio_stream_descriptor.cpp b/lib/dvb_si/audio_stream_descriptor.cpp new file mode 100644 index 00000000..6a27af19 --- /dev/null +++ b/lib/dvb_si/audio_stream_descriptor.cpp @@ -0,0 +1,52 @@ +/* + * $Id: audio_stream_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +AudioStreamDescriptor::AudioStreamDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + freeFormatFlag = (buffer[2] >> 7) & 0x01; + id = (buffer[2] >> 6) & 0x01; + layer = (buffer[2] >> 4) & 0x03; + variableRateAudioIndicator = (buffer[2] >> 3) & 0x01; + reserved = buffer[2] & 0x07; +} + +uint8_t AudioStreamDescriptor::getFreeFormatFlag(void) const +{ + return freeFormatFlag; +} + +uint8_t AudioStreamDescriptor::getId(void) const +{ + return id; +} + +uint8_t AudioStreamDescriptor::getLayer(void) const +{ + return layer; +} + +uint8_t AudioStreamDescriptor::getVariableRateAudioIndicator(void) const +{ + return variableRateAudioIndicator; +} + diff --git a/lib/dvb_si/audio_stream_descriptor.h b/lib/dvb_si/audio_stream_descriptor.h new file mode 100644 index 00000000..17876b7c --- /dev/null +++ b/lib/dvb_si/audio_stream_descriptor.h @@ -0,0 +1,45 @@ +/* + * $Id: audio_stream_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_audio_stream_descriptor_h__ +#define __dvb_descriptor_audio_stream_descriptor_h__ + +#include "descriptor.h" + +class AudioStreamDescriptor : public Descriptor +{ + protected: + unsigned freeFormatFlag : 1; + unsigned id : 1; + unsigned layer : 2; + unsigned variableRateAudioIndicator : 1; + unsigned reserved : 3; + + public: + AudioStreamDescriptor(const uint8_t * const buffer); + + uint8_t getFreeFormatFlag(void) const; + uint8_t getId(void) const; + uint8_t getLayer(void) const; + uint8_t getVariableRateAudioIndicator(void) const; +}; + +#endif /* __dvb_descriptor_audio_stream_descriptor_h__ */ diff --git a/lib/dvb_si/bat.cpp b/lib/dvb_si/bat.cpp new file mode 100644 index 00000000..a3763f71 --- /dev/null +++ b/lib/dvb_si/bat.cpp @@ -0,0 +1,55 @@ +/* + * $Id: bat.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +BouquetAssociation::BouquetAssociation(const uint8_t * const buffer) +{ + transportStreamId = (buffer[0] << 8) | buffer[1]; + originalNetworkId = (buffer[2] << 8) | buffer[3]; + reserved = (buffer[4] >> 4) & 0x0f; + transportStreamLoopLength = ((buffer[4] & 0x0f) << 8) | buffer[5]; + + for (uint16_t i = 6; i < transportStreamLoopLength + 6; i += buffer[i + 1] + 2) + descriptor(&buffer[i]); +} + +BouquetAssociationTable::BouquetAssociationTable(const uint8_t * const buffer) : LongCrcTable(buffer) +{ + reserved4 = (buffer[8] >> 4) & 0x0f; + bouquetDescriptorsLength = ((buffer[8] & 0x0f) << 8) | buffer[9]; + + for (uint16_t i = 10; i < bouquetDescriptorsLength + 10; i += buffer[i + 1] + 2) + descriptor(&buffer[i]); + + reserved5 = (buffer[bouquetDescriptorsLength + 10] >> 4) & 0x0f; + transportStreamLoopLength = ((buffer[bouquetDescriptorsLength + 10] & 0x0f) << 8) | buffer[bouquetDescriptorsLength + 11]; + + for (uint16_t i = bouquetDescriptorsLength + 12; i < sectionLength - 1; i += ((buffer[i + 4] & 0x0f) | buffer[i + 5]) + 6) + bouquet.push_back(new BouquetAssociation(&buffer[i])); +} + +BouquetAssociationTable::~BouquetAssociationTable(void) +{ + for (BouquetAssociationIterator b = bouquet.begin(); b != bouquet.end(); ++b) + delete *b; +} + diff --git a/lib/dvb_si/bat.h b/lib/dvb_si/bat.h new file mode 100644 index 00000000..41fd97fe --- /dev/null +++ b/lib/dvb_si/bat.h @@ -0,0 +1,66 @@ +/* + * $Id: bat.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_bat_h__ +#define __dvb_table_bat_h__ + +#include +#include "long_crc_table.h" + +class BouquetAssociation : public DescriptorContainer +{ + protected: + unsigned transportStreamId : 16; + unsigned originalNetworkId : 16; + unsigned reserved : 4; + unsigned transportStreamLoopLength : 12; + + public: + BouquetAssociation(const uint8_t * const buffer); +}; + +typedef std::vector BouquetAssociationVector; +typedef BouquetAssociationVector::iterator BouquetAssociationIterator; +typedef BouquetAssociationVector::const_iterator BouquetAssociationConstIterator; + +class BouquetAssociationTable : public LongCrcTable , public DescriptorContainer +{ + protected: + unsigned reserved4 : 4; + unsigned bouquetDescriptorsLength : 12; + unsigned reserved5 : 4; + unsigned transportStreamLoopLength : 12; + BouquetAssociationVector bouquet; + + public: + BouquetAssociationTable(const uint8_t * const buffer); + ~BouquetAssociationTable(void); + + static const enum PacketId PID = PID_BAT; + static const enum TableId TID = TID_BAT; + static const uint32_t TIMEOUT = 12000; +}; + +typedef std::vector BouquetAssociationTableVector; +typedef BouquetAssociationTableVector::iterator BouquetAssociationTableIterator; +typedef BouquetAssociationTableVector::const_iterator BouquetAssociationTableConstIterator; + +#endif /* __dvb_table_bat_h__ */ diff --git a/lib/dvb_si/bouquet_name_descriptor.cpp b/lib/dvb_si/bouquet_name_descriptor.cpp new file mode 100644 index 00000000..e11a2088 --- /dev/null +++ b/lib/dvb_si/bouquet_name_descriptor.cpp @@ -0,0 +1,33 @@ +/* + * $Id: bouquet_name_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +BouquetNameDescriptor::BouquetNameDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + bouquetName.assign((char *)&buffer[2], descriptorLength); +} + +std::string BouquetNameDescriptor::getBouquetName(void) const +{ + return bouquetName; +} + diff --git a/lib/dvb_si/bouquet_name_descriptor.h b/lib/dvb_si/bouquet_name_descriptor.h new file mode 100644 index 00000000..5f608bc3 --- /dev/null +++ b/lib/dvb_si/bouquet_name_descriptor.h @@ -0,0 +1,39 @@ +/* + * $Id: bouquet_name_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_bouquet_name_descriptor_h__ +#define __dvb_descriptor_bouquet_name_descriptor_h__ + +#include "descriptor.h" + +class BouquetNameDescriptor : public Descriptor +{ + protected: + std::string bouquetName; + + public: + BouquetNameDescriptor(const uint8_t * const buffer); + ~BouquetNameDescriptor(void); + + std::string getBouquetName(void) const; +}; + +#endif /* __dvb_descriptor_bouquet_name_descriptor_h__ */ diff --git a/lib/dvb_si/ca_descriptor.cpp b/lib/dvb_si/ca_descriptor.cpp new file mode 100644 index 00000000..019855db --- /dev/null +++ b/lib/dvb_si/ca_descriptor.cpp @@ -0,0 +1,50 @@ +/* + * $Id: ca_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +CaDescriptor::CaDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + caSystemId = (buffer[2] << 8) | buffer[3]; + reserved = buffer[4] >> 5; + caPid = ((buffer[4] & 0x1F) << 8) | buffer[5]; + + if (descriptorLength < 4) + return; + for (uint16_t i = 0; i < descriptorLength - 4; ++i) + privateDataBytes.push_back(buffer[i + 6]); +} + +uint16_t CaDescriptor::getCaSystemId(void) const +{ + return caSystemId; +} + +uint16_t CaDescriptor::getCaPid(void) const +{ + return caPid; +} + +const PrivateDataByteVector *CaDescriptor::getPrivateDataBytes(void) const +{ + return &privateDataBytes; +} + diff --git a/lib/dvb_si/ca_descriptor.h b/lib/dvb_si/ca_descriptor.h new file mode 100644 index 00000000..b02add95 --- /dev/null +++ b/lib/dvb_si/ca_descriptor.h @@ -0,0 +1,51 @@ +/* + * $Id: ca_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_ca_descriptor_h__ +#define __dvb_descriptor_ca_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector PrivateDataByteVector; +typedef PrivateDataByteVector::iterator PrivateDataByteIterator; +typedef PrivateDataByteVector::const_iterator PrivateDataByteConstIterator; + +class CaDescriptor : public Descriptor +{ + protected: + unsigned caSystemId : 16; + unsigned reserved : 3; + unsigned caPid : 13; + PrivateDataByteVector privateDataBytes; + + public: + CaDescriptor(const uint8_t * const buffer); + + uint16_t getCaSystemId(void) const; + uint16_t getCaPid(void) const; + const PrivateDataByteVector *getPrivateDataBytes(void) const; +}; + +typedef std::vector CaDescriptorVector; +typedef CaDescriptorVector::iterator CaDescriptorIterator; +typedef CaDescriptorVector::const_iterator CaDescriptorConstIterator; + +#endif /* __dvb_descriptor_ca_descriptor_h__ */ diff --git a/lib/dvb_si/ca_identifier_descriptor.cpp b/lib/dvb_si/ca_identifier_descriptor.cpp new file mode 100644 index 00000000..5804c5d4 --- /dev/null +++ b/lib/dvb_si/ca_identifier_descriptor.cpp @@ -0,0 +1,34 @@ +/* + * $Id: ca_identifier_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +CaIdentifierDescriptor::CaIdentifierDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 2) + caSystemIds.push_back((buffer[i + 2] << 8) | buffer[i + 3]); +} + +const CaSystemIdVector *CaIdentifierDescriptor::getCaSystemIds(void) const +{ + return &caSystemIds; +} + diff --git a/lib/dvb_si/ca_identifier_descriptor.h b/lib/dvb_si/ca_identifier_descriptor.h new file mode 100644 index 00000000..432d8d5a --- /dev/null +++ b/lib/dvb_si/ca_identifier_descriptor.h @@ -0,0 +1,42 @@ +/* + * $Id: ca_identifier_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_ca_identifier_descriptor_h__ +#define __dvb_descriptor_ca_identifier_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector CaSystemIdVector; +typedef CaSystemIdVector::iterator CaSystemIdIterator; +typedef CaSystemIdVector::const_iterator CaSystemIdConstIterator; + +class CaIdentifierDescriptor : public Descriptor +{ + protected: + CaSystemIdVector caSystemIds; + + public: + CaIdentifierDescriptor(const uint8_t * const buffer); + + const CaSystemIdVector *getCaSystemIds(void) const; +}; + +#endif /* __dvb_descriptor_ca_identifier_descriptor_h__ */ diff --git a/lib/dvb_si/ca_system_descriptor.cpp b/lib/dvb_si/ca_system_descriptor.cpp new file mode 100644 index 00000000..acae51f0 --- /dev/null +++ b/lib/dvb_si/ca_system_descriptor.cpp @@ -0,0 +1,33 @@ +/* + * $Id: ca_system_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +CaSystemDescriptor::CaSystemDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + scramblingCode = buffer[2]; +} + +uint8_t CaSystemDescriptor::getScramblingCode(void) const +{ + return scramblingCode; +} + diff --git a/lib/dvb_si/ca_system_descriptor.h b/lib/dvb_si/ca_system_descriptor.h new file mode 100644 index 00000000..01491973 --- /dev/null +++ b/lib/dvb_si/ca_system_descriptor.h @@ -0,0 +1,38 @@ +/* + * $Id: ca_system_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_ca_system_descriptor_h__ +#define __dvb_descriptor_ca_system_descriptor_h__ + +#include "descriptor.h" + +class CaSystemDescriptor : public Descriptor +{ + protected: + unsigned scramblingCode : 8; + + public: + CaSystemDescriptor(const uint8_t * const buffer); + + uint8_t getScramblingCode(void) const; +}; + +#endif /* __dvb_descriptor_ca_system_descriptor_h__ */ diff --git a/lib/dvb_si/cable_delivery_system_descriptor.cpp b/lib/dvb_si/cable_delivery_system_descriptor.cpp new file mode 100644 index 00000000..4d07080d --- /dev/null +++ b/lib/dvb_si/cable_delivery_system_descriptor.cpp @@ -0,0 +1,80 @@ +/* + * $Id: cable_delivery_system_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +CableDeliverySystemDescriptor::CableDeliverySystemDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + frequency = + ( + ((buffer[2] >> 4) * 10000000) + + ((buffer[2] & 0x0F) * 1000000) + + ((buffer[3] >> 4) * 100000) + + ((buffer[3] & 0x0F) * 10000) + + ((buffer[4] >> 4) * 1000) + + ((buffer[4] & 0x0F) * 100) + + ((buffer[5] >> 4) * 10) + + ((buffer[5] & 0x0F) * 1) + ); + + reserved = (buffer[6] << 4) | ((buffer[7] >> 4) & 0x0F); + fecOuter = buffer[7] & 0x0F; + modulation = buffer[8]; + + symbolRate = + ( + ((buffer[9] >> 4) * 1000000) + + ((buffer[9] & 0x0F) * 100000) + + ((buffer[10] >> 4) * 10000) + + ((buffer[10] & 0x0F) * 1000) + + ((buffer[11] >> 4) * 100) + + ((buffer[11] & 0x0F) * 10) + + ((buffer[12] >> 4) * 1) + ); + + fecInner = buffer[12] & 0x0F; +} + +uint32_t CableDeliverySystemDescriptor::getFrequency(void) const +{ + return frequency; +} + +uint8_t CableDeliverySystemDescriptor::getFecOuter(void) const +{ + return fecOuter; +} + +uint8_t CableDeliverySystemDescriptor::getModulation(void) const +{ + return modulation; +} + +uint32_t CableDeliverySystemDescriptor::getSymbolRate(void) const +{ + return symbolRate; +} + +uint8_t CableDeliverySystemDescriptor::getFecInner(void) const +{ + return fecInner; +} + diff --git a/lib/dvb_si/cable_delivery_system_descriptor.h b/lib/dvb_si/cable_delivery_system_descriptor.h new file mode 100644 index 00000000..c063222b --- /dev/null +++ b/lib/dvb_si/cable_delivery_system_descriptor.h @@ -0,0 +1,47 @@ +/* + * $Id: cable_delivery_system_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_cable_delivery_system_descriptor_h__ +#define __dvb_descriptor_cable_delivery_system_descriptor_h__ + +#include "descriptor.h" + +class CableDeliverySystemDescriptor : public Descriptor +{ + protected: + unsigned frequency : 32; + unsigned reserved : 12; + unsigned fecOuter : 4; + unsigned modulation : 8; + unsigned symbolRate : 28; + unsigned fecInner : 4; + + public: + CableDeliverySystemDescriptor(const uint8_t * const buffer); + + uint32_t getFrequency(void) const; + uint8_t getFecOuter(void) const; + uint8_t getModulation(void) const; + uint32_t getSymbolRate(void) const; + uint8_t getFecInner(void) const; +}; + +#endif /* __dvb_descriptor_cable_delivery_system_descriptor_h__ */ diff --git a/lib/dvb_si/camt.cpp b/lib/dvb_si/camt.cpp new file mode 100644 index 00000000..7383a215 --- /dev/null +++ b/lib/dvb_si/camt.cpp @@ -0,0 +1,29 @@ +/* + * $Id: camt.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ConditionalAccessMessageTable::ConditionalAccessMessageTable(const uint8_t * const buffer) : ShortTable(buffer) +{ + for (uint16_t i = 8; i < sectionLength - 1; ++i) + caDataByte.push_back(buffer[i]); +} + diff --git a/lib/dvb_si/camt.h b/lib/dvb_si/camt.h new file mode 100644 index 00000000..e01b8061 --- /dev/null +++ b/lib/dvb_si/camt.h @@ -0,0 +1,43 @@ +/* + * $Id: camt.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_camt_h__ +#define __dvb_table_camt_h__ + +#include "short_table.h" + +class ConditionalAccessMessageTable : public ShortTable +{ + protected: + std::vector caDataByte; + + public: + ConditionalAccessMessageTable(const uint8_t * const buffer); + + static const uint16_t LENGTH = 256; + static const enum TableId TID = TID_CAMT_ECM_0; +}; + +typedef std::vector ConditionalAccessMessageTableVector; +typedef ConditionalAccessMessageTableVector::iterator ConditionalAccessMessageTableIterator; +typedef ConditionalAccessMessageTableVector::const_iterator ConditionalAccessMessageTableConstIterator; + +#endif /* __dvb_table_camt_h__ */ diff --git a/lib/dvb_si/capmt.cpp b/lib/dvb_si/capmt.cpp new file mode 100644 index 00000000..c5a6ab9e --- /dev/null +++ b/lib/dvb_si/capmt.cpp @@ -0,0 +1,124 @@ +/* + * $Id: capmt.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include + +CaLengthField::CaLengthField(const uint64_t length) +{ + if (length < 0x80) { + sizeIndicator = 0; + lengthValue = length; + } + + else { + uint64_t mask = 0xFF; + + sizeIndicator = 1; + lengthFieldSize = 1; + + while ((length & mask) != length) { + lengthFieldSize++; + mask = ((uint64_t)(mask << 8)) | ((uint64_t)0xFFULL); + } + + for (uint8_t i = lengthFieldSize; i > 0; i--) + lengthValueByte.push_back((length >> ((i - 1) << 3)) & 0xFF); + } +} + +CaElementaryStreamInfo::CaElementaryStreamInfo(const ElementaryStreamInfo * const info, const uint8_t cmdId) +{ + streamType = info->streamType; + reserved1 = info->reserved1; + elementaryPid = info->elementaryPid; + reserved2 = info->reserved2; + esInfoLength = 0; + + for (DescriptorConstIterator i = info->getDescriptors()->begin(); i != info->getDescriptors()->end(); ++i) + if ((*i)->getTag() == CA_DESCRIPTOR) { + descriptors.push_back(new CaDescriptor(*(CaDescriptor *)*i)); + esInfoLength += (*i)->getLength() + 2; + } + + if (esInfoLength) { + caPmtCmdId = cmdId; + esInfoLength++; + } +} + +CaElementaryStreamInfo::~CaElementaryStreamInfo(void) +{ + for (CaDescriptorIterator i = descriptors.begin(); i != descriptors.end(); ++i) + delete *i; +} + +uint16_t CaElementaryStreamInfo::getLength(void) const +{ + return esInfoLength + 5; +} + +CaProgramMapTable::CaProgramMapTable(const ProgramMapTable * const pmt, const uint8_t listManagement, const uint8_t cmdId) +{ + uint64_t length = 6; + + caPmtTag = 0x9F80C3; + caPmtListManagement = listManagement; + + programNumber = pmt->tableIdExtension; + reserved1 = pmt->reserved3; + versionNumber = pmt->versionNumber; + currentNextIndicator = pmt->currentNextIndicator; + reserved2 = pmt->reserved5; + programInfoLength = 0; + + for (DescriptorConstIterator i = pmt->getDescriptors()->begin(); i != pmt->getDescriptors()->end(); ++i) + if ((*i)->getTag() == CA_DESCRIPTOR) { + descriptors.push_back(new CaDescriptor(*(CaDescriptor *)*i)); + programInfoLength += (*i)->getLength() + 2; + } + + if (programInfoLength) { + caPmtCmdId = cmdId; + programInfoLength++; + length += programInfoLength; + } + + for (ElementaryStreamInfoConstIterator i = pmt->esInfo.begin(); i != pmt->esInfo.end(); ++i) { + CaElementaryStreamInfo *info = new CaElementaryStreamInfo(*i, cmdId); + esInfo.push_back(info); + length += info->getLength(); + } + + lengthField = new CaLengthField(length); +} + +CaProgramMapTable::~CaProgramMapTable(void) +{ + for (CaDescriptorIterator i = descriptors.begin(); i != descriptors.end(); ++i) + delete *i; + + for (CaElementaryStreamInfoIterator i = esInfo.begin(); i != esInfo.end(); ++i) + delete *i; + + delete lengthField; +} + diff --git a/lib/dvb_si/capmt.h b/lib/dvb_si/capmt.h new file mode 100644 index 00000000..6d8dc43d --- /dev/null +++ b/lib/dvb_si/capmt.h @@ -0,0 +1,87 @@ +/* + * $Id: capmt.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_capmt_h__ +#define __dvb_table_capmt_h__ + +#include +#include "pmt.h" + +class CaLengthField +{ + protected: + unsigned sizeIndicator : 1; + unsigned lengthValue : 7; + unsigned lengthFieldSize : 7; + std::vector lengthValueByte; + + public: + CaLengthField(const uint64_t length); +}; + +class CaElementaryStreamInfo +{ + protected: + unsigned streamType : 8; + unsigned reserved1 : 3; + unsigned elementaryPid : 13; + unsigned reserved2 : 4; + unsigned esInfoLength : 12; + unsigned caPmtCmdId : 8; + CaDescriptorVector descriptors; + + public: + CaElementaryStreamInfo(const ElementaryStreamInfo * const info, const uint8_t cmdId); + ~CaElementaryStreamInfo(void); + + uint16_t getLength(void) const; +}; + +typedef std::vector CaElementaryStreamInfoVector; +typedef CaElementaryStreamInfoVector::iterator CaElementaryStreamInfoIterator; +typedef CaElementaryStreamInfoVector::const_iterator CaElementaryStreamInfoConstIterator; + +class CaProgramMapTable +{ + protected: + unsigned caPmtTag : 24; + CaLengthField *lengthField; + unsigned caPmtListManagement : 8; + unsigned programNumber : 16; + unsigned reserved1 : 2; + unsigned versionNumber : 5; + unsigned currentNextIndicator : 1; + unsigned reserved2 : 4; + unsigned programInfoLength : 12; + unsigned caPmtCmdId : 8; + CaDescriptorVector descriptors; + CaElementaryStreamInfoVector esInfo; + + public: + CaProgramMapTable(const ProgramMapTable * const pmt, const uint8_t listManagement, const uint8_t cmdId); + ~CaProgramMapTable(void); +}; + +typedef std::vector CaProgramMapTableVector; +typedef CaProgramMapTableVector::iterator CaProgramMapTableIterator; +typedef CaProgramMapTableVector::const_iterator CaProgramMapTableConstIterator; + +#endif /* __dvb_table_capmt_h__ */ diff --git a/lib/dvb_si/cat.cpp b/lib/dvb_si/cat.cpp new file mode 100644 index 00000000..de692301 --- /dev/null +++ b/lib/dvb_si/cat.cpp @@ -0,0 +1,29 @@ +/* + * $Id: cat.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ConditionalAccessTable::ConditionalAccessTable(const uint8_t * const buffer) : LongCrcTable(buffer) +{ + for (uint16_t i = 8; i < sectionLength - 1; i += buffer[i + 1] + 2) + descriptor(&buffer[i]); +} + diff --git a/lib/dvb_si/cat.h b/lib/dvb_si/cat.h new file mode 100644 index 00000000..3c3e3cdc --- /dev/null +++ b/lib/dvb_si/cat.h @@ -0,0 +1,42 @@ +/* + * $Id: cat.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_cat_h__ +#define __dvb_table_cat_h__ + +#include +#include "long_crc_table.h" + +class ConditionalAccessTable : public LongCrcTable, public DescriptorContainer +{ + public: + ConditionalAccessTable(const uint8_t * const buffer); + + static const enum PacketId PID = PID_CAT; + static const enum TableId TID = TID_CAT; + static const uint32_t TIMEOUT = 200; +}; + +typedef std::vector ConditionalAccessTableVector; +typedef ConditionalAccessTableVector::iterator ConditionalAccessTableIterator; +typedef ConditionalAccessTableVector::const_iterator ConditionalAccessTableConstIterator; + +#endif /* __dvb_table_cat_h__ */ diff --git a/lib/dvb_si/cell_frequency_link_descriptor.cpp b/lib/dvb_si/cell_frequency_link_descriptor.cpp new file mode 100644 index 00000000..f4c44510 --- /dev/null +++ b/lib/dvb_si/cell_frequency_link_descriptor.cpp @@ -0,0 +1,87 @@ +/* + * $Id: cell_frequency_link_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +SubcellInfo::SubcellInfo(const uint8_t * const buffer) +{ + cellIdExtenstion = buffer[0]; + transposerFrequency = (buffer[1] << 24) | (buffer[2] << 16) | (buffer[3] << 8) | buffer[4]; +} + +uint8_t SubcellInfo::getCellIdExtension(void) const +{ + return cellIdExtenstion; +} + +uint32_t SubcellInfo::getTransposerFrequency(void) const +{ + return transposerFrequency; +} + +CellFrequencyLink::CellFrequencyLink(const uint8_t * const buffer) +{ + cellId = (buffer[0] << 8) | buffer[1]; + frequency = (buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | buffer[5]; + subcellInfoLoopLength = buffer[6]; + + for (uint16_t i = 0; i < subcellInfoLoopLength; i += 5) + subcells.push_back(new SubcellInfo(&buffer[i + 7])); +} + +CellFrequencyLink::~CellFrequencyLink(void) +{ + for (SubcellInfoIterator i = subcells.begin(); i != subcells.end(); ++i) + delete *i; +} + +uint16_t CellFrequencyLink::getCellId(void) const +{ + return cellId; +} + +uint32_t CellFrequencyLink::getFrequency(void) const +{ + return frequency; +} + +const SubcellInfoVector *CellFrequencyLink::getSubcells(void) const +{ + return &subcells; +} + +CellFrequencyLinkDescriptor::CellFrequencyLinkDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += buffer[i + 10] + 6) + cellFrequencyLinks.push_back(new CellFrequencyLink(&buffer[i + 2])); +} + +CellFrequencyLinkDescriptor::~CellFrequencyLinkDescriptor(void) +{ + for (CellFrequencyLinkIterator i = cellFrequencyLinks.begin(); i != cellFrequencyLinks.end(); ++i) + delete *i; +} + +const CellFrequencyLinkVector *CellFrequencyLinkDescriptor::getCellFrequencyLinks(void) const +{ + return &cellFrequencyLinks; +} + diff --git a/lib/dvb_si/cell_frequency_link_descriptor.h b/lib/dvb_si/cell_frequency_link_descriptor.h new file mode 100644 index 00000000..29395ebc --- /dev/null +++ b/lib/dvb_si/cell_frequency_link_descriptor.h @@ -0,0 +1,78 @@ +/* + * $Id: cell_frequency_link_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_cell_frequency_link_descriptor_h__ +#define __dvb_descriptor_cell_frequency_link_descriptor_h__ + +#include "descriptor.h" + +class SubcellInfo +{ + protected: + unsigned cellIdExtenstion : 8; + unsigned transposerFrequency : 32; + + public: + SubcellInfo(const uint8_t * const buffer); + + uint8_t getCellIdExtension(void) const; + uint32_t getTransposerFrequency(void) const; +}; + +typedef std::vector SubcellInfoVector; +typedef SubcellInfoVector::iterator SubcellInfoIterator; +typedef SubcellInfoVector::const_iterator SubcellInfoConstIterator; + +class CellFrequencyLink +{ + protected: + unsigned cellId : 16; + unsigned frequency : 32; + unsigned subcellInfoLoopLength : 8; + SubcellInfoVector subcells; + + public: + CellFrequencyLink(const uint8_t * const buffer); + ~CellFrequencyLink(void); + + uint16_t getCellId(void) const; + uint32_t getFrequency(void) const; + const SubcellInfoVector *getSubcells(void) const; + +}; + +typedef std::vector CellFrequencyLinkVector; +typedef CellFrequencyLinkVector::iterator CellFrequencyLinkIterator; +typedef CellFrequencyLinkVector::const_iterator CellFrequencyLinkConstIterator; + +class CellFrequencyLinkDescriptor : public Descriptor +{ + protected: + CellFrequencyLinkVector cellFrequencyLinks; + + public: + CellFrequencyLinkDescriptor(const uint8_t * const buffer); + ~CellFrequencyLinkDescriptor(void); + + const CellFrequencyLinkVector *getCellFrequencyLinks(void) const; +}; + +#endif /* __dvb_descriptor_cell_frequency_link_descriptor_h__ */ diff --git a/lib/dvb_si/cell_list_descriptor.cpp b/lib/dvb_si/cell_list_descriptor.cpp new file mode 100644 index 00000000..c8588aeb --- /dev/null +++ b/lib/dvb_si/cell_list_descriptor.cpp @@ -0,0 +1,124 @@ +/* + * $Id: cell_list_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include + +Subcell::Subcell(const uint8_t * const buffer) +{ + cellIdExtension = buffer[0]; + subcellLatitude = (buffer[1] << 8) | buffer[2]; + subcellLongitude = (buffer[3] << 8) | buffer[4]; + subcellExtendOfLatitude = (buffer[5] << 4) | ((buffer[6] >> 4) & 0x0f); + subcellExtendOfLongitude = ((buffer[6] & 0x0f) << 8) | buffer[7]; +} + +uint8_t Subcell::getCellIdExtension(void) const +{ + return cellIdExtension; +} + +uint16_t Subcell::getSubcellLatitude(void) const +{ + return subcellLatitude; +} + +uint16_t Subcell::getSubcellLongtitude(void) const +{ + return subcellLongitude; +} + +uint16_t Subcell::getSubcellExtendOfLatitude(void) const +{ + return subcellExtendOfLatitude; +} + +uint16_t Subcell::getSubcellExtendOfLongtitude(void) const +{ + return subcellExtendOfLongitude; +} + +Cell::Cell(const uint8_t * const buffer) +{ + cellId = (buffer[0] << 8) | buffer[1]; + cellLatitude = (buffer[2] << 8) | buffer[3]; + cellLongtitude = (buffer[4] << 8) | buffer[5]; + cellExtendOfLatitude = (buffer[6] << 4) | ((buffer[7] >> 4) & 0x0f); + cellExtendOfLongtitude = ((buffer[7] & 0x0f) << 8) | buffer[8]; + subcellInfoLoopLength = buffer[9]; + + for (uint16_t i = 0; i < subcellInfoLoopLength; i += 8) + subcells.push_back(new Subcell(&buffer[i + 10])); +} + +Cell::~Cell(void) +{ + for (SubcellIterator i = subcells.begin(); i != subcells.end(); ++i) + delete *i; +} + +uint16_t Cell::getCellId(void) const +{ + return cellId; +} + +uint16_t Cell::getCellLatitude(void) const +{ + return cellLatitude; +} + +uint16_t Cell::getCellLongtitude(void) const +{ + return cellLongtitude; +} + +uint16_t Cell::getCellExtendOfLatitude(void) const +{ + return cellExtendOfLatitude; +} + +uint16_t Cell::getCellExtendOfLongtitude(void) const +{ + return cellExtendOfLongtitude; +} + +const SubcellVector *Cell::getSubcells(void) const +{ + return &subcells; +} + +CellListDescriptor::CellListDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += buffer[i + 11] + 10) + cells.push_back(new Cell(&buffer[i + 2])); +} + +CellListDescriptor::~CellListDescriptor(void) +{ + for (CellIterator i = cells.begin(); i != cells.end(); ++i) + delete *i; +} + +const CellVector *CellListDescriptor::getCells(void) const +{ + return &cells; +} + diff --git a/lib/dvb_si/cell_list_descriptor.h b/lib/dvb_si/cell_list_descriptor.h new file mode 100644 index 00000000..cfe93d98 --- /dev/null +++ b/lib/dvb_si/cell_list_descriptor.h @@ -0,0 +1,89 @@ +/* + * $Id: cell_list_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_cell_list_descriptor_h__ +#define __dvb_descriptor_cell_list_descriptor_h__ + +#include "descriptor.h" + +class Subcell +{ + protected: + unsigned cellIdExtension : 8; + unsigned subcellLatitude : 16; + unsigned subcellLongitude : 16; + unsigned subcellExtendOfLatitude : 12; + unsigned subcellExtendOfLongitude : 12; + + public: + Subcell(const uint8_t * const buffer); + + uint8_t getCellIdExtension(void) const; + uint16_t getSubcellLatitude(void) const; + uint16_t getSubcellLongtitude(void) const; + uint16_t getSubcellExtendOfLatitude(void) const; + uint16_t getSubcellExtendOfLongtitude(void) const; +}; + +typedef std::vector SubcellVector; +typedef SubcellVector::iterator SubcellIterator; +typedef SubcellVector::const_iterator SubcellConstIterator; + +class Cell +{ + protected: + unsigned cellId : 16; + unsigned cellLatitude : 16; + unsigned cellLongtitude : 16; + unsigned cellExtendOfLatitude : 12; + unsigned cellExtendOfLongtitude : 12; + unsigned subcellInfoLoopLength : 8; + SubcellVector subcells; + + public: + Cell(const uint8_t * const buffer); + ~Cell(void); + + uint16_t getCellId(void) const; + uint16_t getCellLatitude(void) const; + uint16_t getCellLongtitude(void) const; + uint16_t getCellExtendOfLatitude(void) const; + uint16_t getCellExtendOfLongtitude(void) const; + const SubcellVector *getSubcells(void) const; +}; + +typedef std::vector CellVector; +typedef CellVector::iterator CellIterator; +typedef CellVector::const_iterator CellConstIterator; + +class CellListDescriptor : public Descriptor +{ + protected: + CellVector cells; + + public: + CellListDescriptor(const uint8_t * const buffer); + ~CellListDescriptor(void); + + const CellVector *getCells(void) const; +}; + +#endif /* __dvb_descriptor_cell_list_descriptor_h__ */ diff --git a/lib/dvb_si/component_descriptor.cpp b/lib/dvb_si/component_descriptor.cpp new file mode 100644 index 00000000..8b043e13 --- /dev/null +++ b/lib/dvb_si/component_descriptor.cpp @@ -0,0 +1,60 @@ +/* + * $Id: component_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ComponentDescriptor::ComponentDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + reserved = (buffer[2] >> 4) & 0x0f; + streamContent = buffer[2] & 0x0f; + componentType = buffer[3]; + componentTag = buffer[4]; + iso639LanguageCode.assign((char *) &buffer[5], 3); + if (descriptorLength < 6) + return; + text.assign((char *) &buffer[8], descriptorLength - 6); +} + +uint8_t ComponentDescriptor::getStreamContent(void) const +{ + return streamContent; +} + +uint8_t ComponentDescriptor::getComponentType(void) const +{ + return componentType; +} + +uint8_t ComponentDescriptor::getComponentTag(void) const +{ + return componentTag; +} + +std::string ComponentDescriptor::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +std::string ComponentDescriptor::getText(void) const +{ + return text; +} + diff --git a/lib/dvb_si/component_descriptor.h b/lib/dvb_si/component_descriptor.h new file mode 100644 index 00000000..c910ad4d --- /dev/null +++ b/lib/dvb_si/component_descriptor.h @@ -0,0 +1,47 @@ +/* + * $Id: component_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_component_descriptor_h__ +#define __dvb_descriptor_component_descriptor_h__ + +#include "descriptor.h" + +class ComponentDescriptor : public Descriptor +{ + protected: + unsigned reserved : 4; + unsigned streamContent : 4; + unsigned componentType : 8; + unsigned componentTag : 8; + std::string iso639LanguageCode; + std::string text; + + public: + ComponentDescriptor(const uint8_t * const buffer); + + uint8_t getStreamContent(void) const; + uint8_t getComponentType(void) const; + uint8_t getComponentTag(void) const; + std::string getIso639LanguageCode(void) const; + std::string getText(void) const; +}; + +#endif /* __dvb_descriptor_component_descriptor_h__ */ diff --git a/lib/dvb_si/container.cpp b/lib/dvb_si/container.cpp new file mode 100644 index 00000000..1c14c2f3 --- /dev/null +++ b/lib/dvb_si/container.cpp @@ -0,0 +1,289 @@ +/* + * $Id: container.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DescriptorContainer::~DescriptorContainer(void) +{ + for (DescriptorIterator i = descriptorVector.begin(); i != descriptorVector.end(); ++i) + delete *i; +} + +void DescriptorContainer::descriptor(const uint8_t * const buffer) +{ + switch (buffer[0]) { + case VIDEO_STREAM_DESCRIPTOR: + descriptorVector.push_back(new VideoStreamDescriptor(buffer)); + break; + + case AUDIO_STREAM_DESCRIPTOR: + descriptorVector.push_back(new AudioStreamDescriptor(buffer)); + break; + + case TARGET_BACKGROUND_GRID_DESCRIPTOR: + descriptorVector.push_back(new TargetBackgroundGridDescriptor(buffer)); + break; + + case VIDEO_WINDOW_DESCRIPTOR: + descriptorVector.push_back(new VideoWindowDescriptor(buffer)); + break; + + case CA_DESCRIPTOR: + descriptorVector.push_back(new CaDescriptor(buffer)); + break; + + case ISO_639_LANGUAGE_DESCRIPTOR: + descriptorVector.push_back(new Iso639LanguageDescriptor(buffer)); + break; + + case NETWORK_NAME_DESCRIPTOR: + descriptorVector.push_back(new NetworkNameDescriptor(buffer)); + break; + + case SERVICE_LIST_DESCRIPTOR: + descriptorVector.push_back(new ServiceListDescriptor(buffer)); + break; + + case STUFFING_DESCRIPTOR: + descriptorVector.push_back(new StuffingDescriptor(buffer)); + break; + + case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR: + descriptorVector.push_back(new SatelliteDeliverySystemDescriptor(buffer)); + break; + + case CABLE_DELIVERY_SYSTEM_DESCRIPTOR: + descriptorVector.push_back(new CableDeliverySystemDescriptor(buffer)); + break; + + case VBI_DATA_DESCRIPTOR: + descriptorVector.push_back(new VbiDataDescriptor(buffer)); + break; + + case VBI_TELETEXT_DESCRIPTOR: + descriptorVector.push_back(new VbiTeletextDescriptor(buffer)); + break; + + case BOUQUET_NAME_DESCRIPTOR: + descriptorVector.push_back(new BouquetNameDescriptor(buffer)); + break; + + case SERVICE_DESCRIPTOR: + descriptorVector.push_back(new ServiceDescriptor(buffer)); + break; + + case COUNTRY_AVAILABILITY_DESCRIPTOR: + descriptorVector.push_back(new CountryAvailabilityDescriptor(buffer)); + break; + + case LINKAGE_DESCRIPTOR: + descriptorVector.push_back(new LinkageDescriptor(buffer)); + break; + + case NVOD_REFERENCE_DESCRIPTOR: + descriptorVector.push_back(new NvodReferenceDescriptor(buffer)); + break; + + case TIME_SHIFTED_SERVICE_DESCRIPTOR: + descriptorVector.push_back(new TimeShiftedServiceDescriptor(buffer)); + break; + + case SHORT_EVENT_DESCRIPTOR: + descriptorVector.push_back(new ShortEventDescriptor(buffer)); + break; + + case EXTENDED_EVENT_DESCRIPTOR: + descriptorVector.push_back(new ExtendedEventDescriptor(buffer)); + break; + + case COMPONENT_DESCRIPTOR: + descriptorVector.push_back(new ComponentDescriptor(buffer)); + break; + + case MOSAIC_DESCRIPTOR: + descriptorVector.push_back(new MosaicDescriptor(buffer)); + break; + + case STREAM_IDENTIFIER_DESCRIPTOR: + descriptorVector.push_back(new StreamIdentifierDescriptor(buffer)); + break; + + case CA_IDENTIFIER_DESCRIPTOR: + descriptorVector.push_back(new CaIdentifierDescriptor(buffer)); + break; + + case CONTENT_DESCRIPTOR: + descriptorVector.push_back(new ContentDescriptor(buffer)); + break; + + case PARENTAL_RATING_DESCRIPTOR: + descriptorVector.push_back(new ParentalRatingDescriptor(buffer)); + break; + + case TELETEXT_DESCRIPTOR: + descriptorVector.push_back(new TeletextDescriptor(buffer)); + break; + + case TELEPHONE_DESCRIPTOR: + descriptorVector.push_back(new TelephoneDescriptor(buffer)); + break; + + case LOCAL_TIME_OFFSET_DESCRIPTOR: + descriptorVector.push_back(new LocalTimeOffsetDescriptor(buffer)); + break; + + case SUBTITLING_DESCRIPTOR: + descriptorVector.push_back(new SubtitlingDescriptor(buffer)); + break; + + case TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR: + descriptorVector.push_back(new TerrestrialDeliverySystemDescriptor(buffer)); + break; + + case MULTILINGUAL_NETWORK_NAME_DESCRIPTOR: + descriptorVector.push_back(new MultilingualNetworkNameDescriptor(buffer)); + break; + + case MULTILINGUAL_BOUQUET_NAME_DESCRIPTOR: + descriptorVector.push_back(new MultilingualBouquetNameDescriptor(buffer)); + break; + + case MULTILINGUAL_SERVICE_NAME_DESCRIPTOR: + descriptorVector.push_back(new MultilingualServiceNameDescriptor(buffer)); + break; + + case MULTILINGUAL_COMPONENT_DESCRIPTOR: + descriptorVector.push_back(new MultilingualComponentDescriptor(buffer)); + break; + + case PRIVATE_DATA_SPECIFIER_DESCRIPTOR: + descriptorVector.push_back(new PrivateDataSpecifierDescriptor(buffer)); + break; + + case SERVICE_MOVE_DESCRIPTOR: + descriptorVector.push_back(new ServiceMoveDescriptor(buffer)); + break; + + case FREQUENCY_LIST_DESCRIPTOR: + descriptorVector.push_back(new FrequencyListDescriptor(buffer)); + break; + + case DATA_BROADCAST_DESCRIPTOR: + descriptorVector.push_back(new DataBroadcastDescriptor(buffer)); + break; + + case CA_SYSTEM_DESCRIPTOR: + descriptorVector.push_back(new CaSystemDescriptor(buffer)); + break; + + case DATA_BROADCAST_ID_DESCRIPTOR: + descriptorVector.push_back(new DataBroadcastIdDescriptor(buffer)); + break; + + case PDC_DESCRIPTOR: + descriptorVector.push_back(new PdcDescriptor(buffer)); + break; + + case AC3_DESCRIPTOR: + descriptorVector.push_back(new Ac3Descriptor(buffer)); + break; + + case ANCILLARY_DATA_DESCRIPTOR: + descriptorVector.push_back(new AncillaryDataDescriptor(buffer)); + break; + + case CELL_LIST_DESCRIPTOR: + descriptorVector.push_back(new CellListDescriptor(buffer)); + break; + + case CELL_FREQUENCY_LINK_DESCRIPTOR: + descriptorVector.push_back(new CellFrequencyLinkDescriptor(buffer)); + break; + + case ANNOUNCEMENT_SUPPORT_DESCRIPTOR: + descriptorVector.push_back(new AnnouncementSupportDescriptor(buffer)); + break; + + case APPLICATION_SIGNALLING_DESCRIPTOR: + descriptorVector.push_back(new ApplicationSignallingDescriptor(buffer)); + break; + + default: + descriptorVector.push_back(new Descriptor(buffer)); + break; + } +} + +const DescriptorVector *DescriptorContainer::getDescriptors(void) const +{ + return &descriptorVector; +} + diff --git a/lib/dvb_si/container.h b/lib/dvb_si/container.h new file mode 100644 index 00000000..9d1d5e3a --- /dev/null +++ b/lib/dvb_si/container.h @@ -0,0 +1,39 @@ +/* + * $Id: container.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_container_h__ +#define __dvb_descriptor_container_h__ + +#include "descriptor.h" + +class DescriptorContainer +{ + protected: + void descriptor(const uint8_t * const buffer); + DescriptorVector descriptorVector; + + public: + ~DescriptorContainer(void); + + const DescriptorVector *getDescriptors(void) const; +}; + +#endif /* __dvb_descriptor_container_h__ */ diff --git a/lib/dvb_si/content_descriptor.cpp b/lib/dvb_si/content_descriptor.cpp new file mode 100644 index 00000000..b8996a4c --- /dev/null +++ b/lib/dvb_si/content_descriptor.cpp @@ -0,0 +1,68 @@ +/* + * $Id: content_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ContentClassification::ContentClassification(const uint8_t * const buffer) +{ + contentNibbleLevel1 = (buffer[0] >> 4) & 0x0f; + contentNibbleLevel2 = buffer[0] & 0x0f; + userNibble1 = (buffer[1] >> 4) & 0x0f; + userNibble2 = buffer[1] & 0x0f; +} + +uint8_t ContentClassification::getContentNibbleLevel1(void) const +{ + return contentNibbleLevel1; +} + +uint8_t ContentClassification::getContentNibbleLevel2(void) const +{ + return contentNibbleLevel2; +} + +uint8_t ContentClassification::getUserNibble1(void) const +{ + return userNibble1; +} + +uint8_t ContentClassification::getUserNibble2(void) const +{ + return userNibble2; +} + +ContentDescriptor::ContentDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 2) + classifications.push_back(new ContentClassification(&buffer[i + 2])); +} + +ContentDescriptor::~ContentDescriptor(void) +{ + for (ContentClassificationVector::iterator i = classifications.begin(); i != classifications.end(); ++i) + delete *i; +} + +const ContentClassificationVector *ContentDescriptor::getClassifications(void) const +{ + return &classifications; +} + diff --git a/lib/dvb_si/content_descriptor.h b/lib/dvb_si/content_descriptor.h new file mode 100644 index 00000000..31f4e718 --- /dev/null +++ b/lib/dvb_si/content_descriptor.h @@ -0,0 +1,60 @@ +/* + * $Id: content_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_content_descriptor_h__ +#define __dvb_descriptor_content_descriptor_h__ + +#include "descriptor.h" + +class ContentClassification +{ + protected: + unsigned contentNibbleLevel1 : 4; + unsigned contentNibbleLevel2 : 4; + unsigned userNibble1 : 4; + unsigned userNibble2 : 4; + + public: + ContentClassification(const uint8_t * const buffer); + + uint8_t getContentNibbleLevel1(void) const; + uint8_t getContentNibbleLevel2(void) const; + uint8_t getUserNibble1(void) const; + uint8_t getUserNibble2(void) const; +}; + +typedef std::vector ContentClassificationVector; +typedef ContentClassificationVector::iterator ContentClassificationIterator; +typedef ContentClassificationVector::const_iterator ContentClassificationConstIterator; + +class ContentDescriptor : public Descriptor +{ + protected: + ContentClassificationVector classifications; + + public: + ContentDescriptor(const uint8_t * const buffer); + ~ContentDescriptor(void); + + const ContentClassificationVector *getClassifications(void) const; +}; + +#endif /* __dvb_descriptor_content_descriptor_h__ */ diff --git a/lib/dvb_si/copyright_descriptor.h b/lib/dvb_si/copyright_descriptor.h new file mode 100644 index 00000000..89d0c283 --- /dev/null +++ b/lib/dvb_si/copyright_descriptor.h @@ -0,0 +1,44 @@ +/* + * $Id: copyright_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_copyright_descriptor_h__ +#define __dvb_descriptor_copyright_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector AdditionalCopyrightInfoVector; +typedef AdditionalCopyrightInfoVector::iterator AdditionalCopyrightInfoIterator; +typedef AdditionalCopyrightInfoVector::const_iterator AdditionalCopyrightInfoConstIterator; + +class CopyrightDescriptor : public Descriptor +{ + protected: + unsigned copyrightIdentifier : 32; + AdditionalCopyrightInfoVector additionalCopyrightInfo; + + public: + CopyrightDescriptor(const uint8_t * const buffer); + + uint32_t getCopyrightIdentifier(void) const; + const AdditionalCopyrightInfoVector *getAdditionalCopyrightInfo(void) const; +}; + +#endif /* __dvb_descriptor_copyright_descriptor_h__ */ diff --git a/lib/dvb_si/country_availability_descriptor.cpp b/lib/dvb_si/country_availability_descriptor.cpp new file mode 100644 index 00000000..7aa37ff9 --- /dev/null +++ b/lib/dvb_si/country_availability_descriptor.cpp @@ -0,0 +1,47 @@ +/* + * $Id: country_availability_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +CountryAvailabilityDescriptor::CountryAvailabilityDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + std::string countryCode; + countryAvailabilityFlag = (buffer[2] >> 7) & 0x01; + + if (descriptorLength < 1) + return; + + for (uint16_t i = 0; i < descriptorLength - 1; i += 3) { + countryCode.assign((char *)&buffer[i + 3], 3); + countryCodes.push_back(countryCode); + } +} + +uint8_t CountryAvailabilityDescriptor::getCountryAvailabilityFlag(void) const +{ + return countryAvailabilityFlag; +} + +const CountryCodeVector *CountryAvailabilityDescriptor::getCountryCodes(void) const +{ + return &countryCodes; +} + diff --git a/lib/dvb_si/country_availability_descriptor.h b/lib/dvb_si/country_availability_descriptor.h new file mode 100644 index 00000000..baa0b845 --- /dev/null +++ b/lib/dvb_si/country_availability_descriptor.h @@ -0,0 +1,45 @@ +/* + * $Id: country_availability_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_country_availability_descriptor_h__ +#define __dvb_descriptor_country_availability_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector CountryCodeVector; +typedef CountryCodeVector::iterator CountryCodeIterator; +typedef CountryCodeVector::const_iterator CountryCodeConstIterator; + +class CountryAvailabilityDescriptor : public Descriptor +{ + protected: + unsigned countryAvailabilityFlag : 1; + unsigned reserved : 7; + CountryCodeVector countryCodes; + + public: + CountryAvailabilityDescriptor(const uint8_t * const buffer); + + uint8_t getCountryAvailabilityFlag(void) const; + const CountryCodeVector *getCountryCodes(void) const; +}; + +#endif /* __dvb_descriptor_country_availability_descriptor_h__ */ diff --git a/lib/dvb_si/data_broadcast_descriptor.cpp b/lib/dvb_si/data_broadcast_descriptor.cpp new file mode 100644 index 00000000..b5f8b2aa --- /dev/null +++ b/lib/dvb_si/data_broadcast_descriptor.cpp @@ -0,0 +1,62 @@ +/* + * $Id: data_broadcast_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +DataBroadcastDescriptor::DataBroadcastDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + dataBroadcastId = (buffer[2] << 8) | buffer[3]; + componentTag = buffer[3]; + selectorLength = buffer[4]; + + for (uint16_t i = 0; i < selectorLength; ++i) + selectorBytes.push_back(buffer[i + 5]); + + iso639LanguageCode.assign((char *)&buffer[selectorLength + 5], 3); + textLength = buffer[selectorLength + 8]; + text.assign((char *)&buffer[selectorLength + 9], textLength); +} + +uint16_t DataBroadcastDescriptor::getDataBroadcastId(void) const +{ + return dataBroadcastId; +} + +uint8_t DataBroadcastDescriptor::getComponentTag(void) const +{ + return componentTag; +} + +const selectorByteVector *DataBroadcastDescriptor::getSelectorBytes(void) const +{ + return &selectorBytes; +} + +std::string DataBroadcastDescriptor::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +std::string DataBroadcastDescriptor::getText(void) const +{ + return text; +} + diff --git a/lib/dvb_si/data_broadcast_descriptor.h b/lib/dvb_si/data_broadcast_descriptor.h new file mode 100644 index 00000000..aa5bb5d2 --- /dev/null +++ b/lib/dvb_si/data_broadcast_descriptor.h @@ -0,0 +1,52 @@ +/* + * $Id: data_broadcast_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_data_broadcast_descriptor_h__ +#define __dvb_descriptor_data_broadcast_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector selectorByteVector; +typedef selectorByteVector::iterator selectorByteIterator; +typedef selectorByteVector::const_iterator selectorByteConstIterator; + +class DataBroadcastDescriptor : public Descriptor +{ + protected: + unsigned dataBroadcastId : 16; + unsigned componentTag : 8; + unsigned selectorLength : 8; + selectorByteVector selectorBytes; + std::string iso639LanguageCode; + unsigned textLength : 8; + std::string text; + + public: + DataBroadcastDescriptor(const uint8_t * const buffer); + + uint16_t getDataBroadcastId(void) const; + uint8_t getComponentTag(void) const; + const selectorByteVector *getSelectorBytes(void) const; + std::string getIso639LanguageCode(void) const; + std::string getText(void) const; +}; + +#endif /* __dvb_descriptor_data_broadcast_descriptor_h__ */ diff --git a/lib/dvb_si/data_broadcast_id_descriptor.cpp b/lib/dvb_si/data_broadcast_id_descriptor.cpp new file mode 100644 index 00000000..2e058c4a --- /dev/null +++ b/lib/dvb_si/data_broadcast_id_descriptor.cpp @@ -0,0 +1,44 @@ +/* + * $Id: data_broadcast_id_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +DataBroadcastIdDescriptor::DataBroadcastIdDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + if (descriptorLength < 2) + return; + + dataBroadcastId = (buffer[2] << 8) | buffer[3]; + + for (uint16_t i = 0; i < descriptorLength - 2; ++i) + idSelectorBytes.push_back(buffer[i + 4]); +} + +uint16_t DataBroadcastIdDescriptor::getDataBroadcastId(void) const +{ + return dataBroadcastId; +} + +const IdSelectorByteVector *DataBroadcastIdDescriptor::getIdSelectorBytes(void) const +{ + return &idSelectorBytes; +} + diff --git a/lib/dvb_si/data_broadcast_id_descriptor.h b/lib/dvb_si/data_broadcast_id_descriptor.h new file mode 100644 index 00000000..a933c6ee --- /dev/null +++ b/lib/dvb_si/data_broadcast_id_descriptor.h @@ -0,0 +1,44 @@ +/* + * $Id: data_broadcast_id_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_data_broadcast_id_descriptor_h__ +#define __dvb_descriptor_data_broadcast_id_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector IdSelectorByteVector; +typedef IdSelectorByteVector::iterator IdSelectorByteIterator; +typedef IdSelectorByteVector::const_iterator IdSelectorByteConstIterator; + +class DataBroadcastIdDescriptor : public Descriptor +{ + protected: + unsigned dataBroadcastId : 16; + IdSelectorByteVector idSelectorBytes; + + public: + DataBroadcastIdDescriptor(const uint8_t * const buffer); + + uint16_t getDataBroadcastId(void) const; + const IdSelectorByteVector *getIdSelectorBytes(void) const; +}; + +#endif /* __dvb_descriptor_data_broadcast_id_descriptor_h__ */ diff --git a/lib/dvb_si/data_stream_alignment_descriptor.h b/lib/dvb_si/data_stream_alignment_descriptor.h new file mode 100644 index 00000000..988cb6dc --- /dev/null +++ b/lib/dvb_si/data_stream_alignment_descriptor.h @@ -0,0 +1,38 @@ +/* + * $Id: data_stream_alignment_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_data_stream_alignment_descriptor_h__ +#define __dvb_descriptor_data_stream_alignment_descriptor_h__ + +#include "descriptor.h" + +class DataStreamAlignmentDescriptor : public Descriptor +{ + protected: + unsigned alignmentType : 8; + + private: + DataStreamAlignmentDescriptor(const uint8_t * const buffer); + + uint8_t getAlignmentType(void) const; +}; + +#endif /* __dvb_descriptor_data_stream_alignment_descriptor_h__ */ diff --git a/lib/dvb_si/descriptor.cpp b/lib/dvb_si/descriptor.cpp new file mode 100644 index 00000000..f81ed9a1 --- /dev/null +++ b/lib/dvb_si/descriptor.cpp @@ -0,0 +1,39 @@ +/* + * $Id: descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +Descriptor::Descriptor(const uint8_t * const buffer) +{ + descriptorTag = buffer[0]; + descriptorLength = buffer[1]; +} + +uint8_t Descriptor::getTag(void) const +{ + return descriptorTag; +} + +uint8_t Descriptor::getLength(void) const +{ + return descriptorLength; +} + diff --git a/lib/dvb_si/descriptor.h b/lib/dvb_si/descriptor.h new file mode 100644 index 00000000..3572cce6 --- /dev/null +++ b/lib/dvb_si/descriptor.h @@ -0,0 +1,46 @@ +/* + * $Id: descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_descriptor_h__ +#define __dvb_descriptor_descriptor_h__ + +#include +#include +#include + +class Descriptor +{ + protected: + unsigned descriptorTag : 8; + unsigned descriptorLength : 8; + + public: + Descriptor(const uint8_t * const buffer); + + uint8_t getTag(void) const; + uint8_t getLength(void) const; +}; + +typedef std::vector DescriptorVector; +typedef DescriptorVector::iterator DescriptorIterator; +typedef DescriptorVector::const_iterator DescriptorConstIterator; + +#endif /* __dvb_descriptor_descriptor_h__ */ diff --git a/lib/dvb_si/descriptor_tag.h b/lib/dvb_si/descriptor_tag.h new file mode 100644 index 00000000..c3f83272 --- /dev/null +++ b/lib/dvb_si/descriptor_tag.h @@ -0,0 +1,127 @@ +/* + * $Id: descriptor_tag.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_id_descriptor_tag_h__ +#define __dvb_id_descriptor_tag_h__ + +enum DescriptorTag { + /* 0x00 - 0x3F: ITU-T Rec. H.222.0 | ISO/IEC 13818-1 */ + VIDEO_STREAM_DESCRIPTOR = 0x02, + AUDIO_STREAM_DESCRIPTOR = 0x03, + HIERARCHY_DESCRIPTOR = 0x04, + REGISTRATION_DESCRIPTOR = 0x05, + DATA_STREAM_ALIGNMENT_DESCRIPTOR = 0x06, + TARGET_BACKGROUND_GRID_DESCRIPTOR = 0x07, + VIDEO_WINDOW_DESCRIPTOR = 0x08, + CA_DESCRIPTOR = 0x09, + ISO_639_LANGUAGE_DESCRIPTOR = 0x0A, + SYSTEM_CLOCK_DESCRIPTOR = 0x0B, + MULTIPLEX_BUFFER_UTILIZATION_DESCRIPTOR = 0x0C, + COPYRIGHT_DESCRIPTOR = 0x0D, + MAXIMUM_BITRATE_DESCRIPTOR = 0x0E, + PRIVATE_DATA_INDICATOR_DESCRIPTOR = 0x0F, + SMOOTHING_BUFFER_DESCRIPTOR = 0x10, + STD_DESCRIPTOR = 0x11, + IBP_DESCRIPTOR = 0x12, + CAROUSEL_IDENTIFIER_DESCRIPTOR = 0x13, + /* 0x40 - 0x7F: ETSI EN 300 468 V1.5.1 (2003-01) */ + NETWORK_NAME_DESCRIPTOR = 0x40, + SERVICE_LIST_DESCRIPTOR = 0x41, + STUFFING_DESCRIPTOR = 0x42, + SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR = 0x43, + CABLE_DELIVERY_SYSTEM_DESCRIPTOR = 0x44, + VBI_DATA_DESCRIPTOR = 0x45, + VBI_TELETEXT_DESCRIPTOR = 0x46, + BOUQUET_NAME_DESCRIPTOR = 0x47, + SERVICE_DESCRIPTOR = 0x48, + COUNTRY_AVAILABILITY_DESCRIPTOR = 0x49, + LINKAGE_DESCRIPTOR = 0x4A, + NVOD_REFERENCE_DESCRIPTOR = 0x4B, + TIME_SHIFTED_SERVICE_DESCRIPTOR = 0x4C, + SHORT_EVENT_DESCRIPTOR = 0x4D, + EXTENDED_EVENT_DESCRIPTOR = 0x4E, + TIME_SHIFTED_EVENT_DESCRIPTOR = 0x4F, + COMPONENT_DESCRIPTOR = 0x50, + MOSAIC_DESCRIPTOR = 0x51, + STREAM_IDENTIFIER_DESCRIPTOR = 0x52, + CA_IDENTIFIER_DESCRIPTOR = 0x53, + CONTENT_DESCRIPTOR = 0x54, + PARENTAL_RATING_DESCRIPTOR = 0x55, + TELETEXT_DESCRIPTOR = 0x56, + TELEPHONE_DESCRIPTOR = 0x57, + LOCAL_TIME_OFFSET_DESCRIPTOR = 0x58, + SUBTITLING_DESCRIPTOR = 0x59, + TERRESTRIAL_DELIVERY_SYSTEM_DESCRIPTOR = 0x5A, + MULTILINGUAL_NETWORK_NAME_DESCRIPTOR = 0x5B, + MULTILINGUAL_BOUQUET_NAME_DESCRIPTOR = 0x5C, + MULTILINGUAL_SERVICE_NAME_DESCRIPTOR = 0x5D, + MULTILINGUAL_COMPONENT_DESCRIPTOR = 0x5E, + PRIVATE_DATA_SPECIFIER_DESCRIPTOR = 0x5F, + SERVICE_MOVE_DESCRIPTOR = 0x60, + SHORT_SMOOTHING_BUFFER_DESCRIPTOR = 0x61, + FREQUENCY_LIST_DESCRIPTOR = 0x62, + PARTIAL_TRANSPORT_STREAM_DESCRIPTOR = 0x63, + DATA_BROADCAST_DESCRIPTOR = 0x64, + CA_SYSTEM_DESCRIPTOR = 0x65, + DATA_BROADCAST_ID_DESCRIPTOR = 0x66, + TRANSPORT_STREAM_DESCRIPTOR = 0x67, + DSNG_DESCRIPTOR = 0x68, + PDC_DESCRIPTOR = 0x69, + AC3_DESCRIPTOR = 0x6A, + ANCILLARY_DATA_DESCRIPTOR = 0x6B, + CELL_LIST_DESCRIPTOR = 0x6C, + CELL_FREQUENCY_LINK_DESCRIPTOR = 0x6D, + ANNOUNCEMENT_SUPPORT_DESCRIPTOR = 0x6E, + APPLICATION_SIGNALLING_DESCRIPTOR = 0x6F, + ADAPTATION_FIELD_DATA_DESCRIPTOR = 0x70, + SERVICE_IDENTIFIER_DESCRIPTOR = 0x71, + SERVICE_AVAILABILITY_DESCRIPTOR = 0x72, + /* 0x80 - 0xFE: user defined */ + VIASAT_LOGIC_CHANNEL_DESCRIPTOR = 0x82, + NORDIG_LOGIC_CHANNEL_DESCRIPTOR = 0x83, + EACEM_LOGIC_CHANNEL_DESCRIPTOR = 0x83, + EACEM_PREFERRED_NAME_LIST_DESCRIPTOR = 0x84, + EACEM_PREFERRED_NAME_IDENTIFIER_DESCRIPTOR = 0x85, + EACEM_STREAM_IDENTIFIER_DESCRIPTOR = 0x86, + SENDA_CHANNEL_LIST_DESCRIPTOR = 0xF1, + /* 0xFF: Forbidden */ + FORBIDDEN_DESCRIPTOR = 0xFF +}; + +enum MhpDescriptorTag { + /* ETSI TS 101 812 V1.2.1 (2002-06) */ + APPLICATION_DESCRIPTOR = 0x00, + APPLICATION_NAME_DESCRIPTOR = 0x01, + TRANSPORT_PROTOCOL_DESCRIPTOR = 0x02, + DVB_J_APPLICATION_DESCRIPTOR = 0x03, + DVB_J_APPLICATION_LOCATION_DESCRIPTOR = 0x04, + EXTERNAL_APPLICATION_AUTHORISATION_DESCRIPTOR = 0x05, + ROUTING_DESCRIPTOR_IP4 = 0x06, + ROUTING_DESCRIPTOR_IP6 = 0x07, + DVB_HTML_APPLICATION_DESCRIPTOR = 0x08, + DVB_HTML_APPLICATION_LOCATION_DESCRIPTOR = 0x09, + DVB_HTML_APPLICATION_BOUNDARY_DESCRIPTOR = 0x0A, + APPLICATION_ICONS_DESCRIPTOR = 0x0B, + PREFETCH_DESCRIPTOR = 0x0C, + DII_LOCATION_DESCRIPTOR = 0x0D, +}; + +#endif /* __dvb_id_descriptor_tag_h__ */ diff --git a/lib/dvb_si/dsng_descriptor.h b/lib/dvb_si/dsng_descriptor.h new file mode 100644 index 00000000..f12d554a --- /dev/null +++ b/lib/dvb_si/dsng_descriptor.h @@ -0,0 +1,42 @@ +/* + * $Id: dsng_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_dsng_descriptor_h__ +#define __dvb_descriptor_dsng_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector ByteVector; +typedef ByteVector::iterator ByteIterator; +typedef ByteVector::const_iterator ByteConstIterator; + +class DsngDescriptor : public Descriptor +{ + protected: + ByteVector bytes; + + public: + DsngDescriptor(const uint8_t * const buffer); + + const ByteVector *getBytes(void) const; +}; + +#endif /* __dvb_descriptor_dsng_descriptor_h__ */ diff --git a/lib/dvb_si/eit.cpp b/lib/dvb_si/eit.cpp new file mode 100644 index 00000000..cf7c02b4 --- /dev/null +++ b/lib/dvb_si/eit.cpp @@ -0,0 +1,109 @@ +/* + * $Id: eit.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +Event::Event(const uint8_t * const buffer) +{ + eventId = (buffer[0] << 8) | buffer[1]; + startTimeMjd = (buffer[2] << 8) | buffer[3]; + startTimeBcd = (buffer[4] << 16) | (buffer[5] << 8) | buffer[6]; + duration = (buffer[7] << 16) | (buffer[8] << 8) | buffer[9]; + runningStatus = (buffer[10] >> 5) & 0x07; + freeCaMode = (buffer[10] >> 4) & 0x01; + descriptorsLoopLength = ((buffer[10] & 0x0f) << 8) | buffer[11]; + + for (uint16_t i = 12; i < descriptorsLoopLength + 12; i += buffer[i + 1] + 2) + descriptor(&buffer[i]); +} + +uint16_t Event::getEventId(void) const +{ + return eventId; +} + +uint16_t Event::getStartTimeMjd(void) const +{ + return startTimeMjd; +} + +uint32_t Event::getStartTimeBcd(void) const +{ + return startTimeBcd; +} + +uint32_t Event::getDuration(void) const +{ + return duration; +} + +uint8_t Event::getRunningStatus(void) const +{ + return runningStatus; +} + +uint8_t Event::getFreeCaMode(void) const +{ + return freeCaMode; +} + +EventInformationTable::EventInformationTable(const uint8_t * const buffer) : LongCrcTable(buffer) +{ + transportStreamId = (buffer[8] << 8) | buffer[9]; + originalNetworkId = (buffer[10] << 8) | buffer[11]; + segmentLastSectionNumber = buffer[12]; + lastTableId = buffer[13]; + + for (uint16_t i = 14; i < sectionLength - 1; i += (((buffer[i + 10] & 0x0f) << 8) | buffer[i + 11]) + 12) + events.push_back(new Event(&buffer[i])); +} + +EventInformationTable::~EventInformationTable(void) +{ + for (EventIterator i = events.begin(); i != events.end(); ++i) + delete *i; +} + +uint16_t EventInformationTable::getTransportStreamId(void) const +{ + return transportStreamId; +} + +uint16_t EventInformationTable::getOriginalNetworkId(void) const +{ + return originalNetworkId; +} + +uint8_t EventInformationTable::getLastSectionNumber(void) const +{ + return lastSectionNumber; +} + +uint8_t EventInformationTable::getLastTableId(void) const +{ + return lastTableId; +} + +const EventVector *EventInformationTable::getEvents(void) const +{ + return &events; +} + diff --git a/lib/dvb_si/eit.h b/lib/dvb_si/eit.h new file mode 100644 index 00000000..1b278ca3 --- /dev/null +++ b/lib/dvb_si/eit.h @@ -0,0 +1,83 @@ +/* + * $Id: eit.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_eit_h__ +#define __dvb_table_eit_h__ + +#include +#include "long_crc_table.h" + +class Event : public DescriptorContainer +{ + protected: + unsigned eventId : 16; + unsigned startTimeMjd : 16; + unsigned startTimeBcd : 24; + unsigned duration : 24; + unsigned runningStatus : 3; + unsigned freeCaMode : 1; + unsigned descriptorsLoopLength : 12; + + public: + Event(const uint8_t * const buffer); + + uint16_t getEventId(void) const; + uint16_t getStartTimeMjd(void) const; + uint32_t getStartTimeBcd(void) const; + uint32_t getDuration(void) const; + uint8_t getRunningStatus(void) const; + uint8_t getFreeCaMode(void) const; +}; + +typedef std::vector EventVector; +typedef EventVector::iterator EventIterator; +typedef EventVector::const_iterator EventConstIterator; + +class EventInformationTable : public LongCrcTable +{ + protected: + unsigned transportStreamId : 16; + unsigned originalNetworkId : 16; + unsigned segmentLastSectionNumber : 8; + unsigned lastTableId : 8; + EventVector events; + + public: + EventInformationTable(const uint8_t * const buffer); + ~EventInformationTable(void); + + static const uint16_t LENGTH = 4096; + static const enum PacketId PID = PID_EIT; + static const enum TableId TID = TID_EIT_ACTUAL; + static const uint32_t TIMEOUT = 3000; + + uint16_t getTransportStreamId(void) const; + uint16_t getOriginalNetworkId(void) const; + uint8_t getLastSectionNumber(void) const; + uint8_t getLastTableId(void) const; + const EventVector *getEvents(void) const; +}; + +typedef std::vector EventInformationTableVector; +typedef EventInformationTableVector::iterator EventInformationTableIterator; +typedef EventInformationTableVector::const_iterator EventInformationTableConstIterator; + +#endif /* __dvb_table_eit_h__ */ diff --git a/lib/dvb_si/element_descriptor.h b/lib/dvb_si/element_descriptor.h new file mode 100644 index 00000000..3587569e --- /dev/null +++ b/lib/dvb_si/element_descriptor.h @@ -0,0 +1,34 @@ +/* + * $Id: element_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_element_descriptor_h__ +#define __dvb_descriptor_element_descriptor_h__ + +#include "descriptor.h" + +/* 0x92 */ +class ElementDescriptor : public Descriptor +{ + public: + ElementDescriptor(const uint8_t * const buffer); +}; + +#endif /* __dvb_descriptor_element_descriptor_h__ */ diff --git a/lib/dvb_si/extended_event_descriptor.cpp b/lib/dvb_si/extended_event_descriptor.cpp new file mode 100644 index 00000000..11b639ad --- /dev/null +++ b/lib/dvb_si/extended_event_descriptor.cpp @@ -0,0 +1,90 @@ +/* + * $Id: extended_event_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ExtendedEvent::ExtendedEvent(const uint8_t * const buffer) +{ + itemDescriptionLength = buffer[0]; + itemDescription.assign((char *)&buffer[1], itemDescriptionLength); + itemLength = buffer[itemDescriptionLength + 1]; + item.assign((char *)&buffer[itemDescriptionLength + 2], itemLength); +} + +std::string ExtendedEvent::getItemDescription(void) const +{ + return itemDescription; +} + +std::string ExtendedEvent::getItem(void) const +{ + return item; +} + +ExtendedEventDescriptor::ExtendedEventDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + descriptorNumber = (buffer[2] >> 4) & 0x0f; + lastDescriptorNumber = buffer[2] & 0x0f; + iso639LanguageCode.assign((char *)&buffer[3], 3); + lengthOfItems = buffer[6]; + + ExtendedEvent *e; + + for (uint16_t i = 0; i < lengthOfItems; i += e->itemDescriptionLength + e->itemLength + 2) { + e = new ExtendedEvent(&buffer[i + 7]); + items.push_back(e); + } + + textLength = buffer[lengthOfItems + 7]; + text.assign((char *)&buffer[lengthOfItems + 8], textLength); +} + +ExtendedEventDescriptor::~ExtendedEventDescriptor(void) +{ + for (ExtendedEventIterator i = items.begin(); i != items.end(); ++i) + delete *i; +} + +uint8_t ExtendedEventDescriptor::getDescriptorNumber(void) const +{ + return descriptorNumber; +} + +uint8_t ExtendedEventDescriptor::getLastDescriptorNumber(void) const +{ + return lastDescriptorNumber; +} + +std::string ExtendedEventDescriptor::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +const ExtendedEventVector *ExtendedEventDescriptor::getItems(void) const +{ + return &items; +} + +std::string ExtendedEventDescriptor::getText(void) const +{ + return text; +} + diff --git a/lib/dvb_si/extended_event_descriptor.h b/lib/dvb_si/extended_event_descriptor.h new file mode 100644 index 00000000..9b170d07 --- /dev/null +++ b/lib/dvb_si/extended_event_descriptor.h @@ -0,0 +1,70 @@ +/* + * $Id: extended_event_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_extended_event_descriptor_h__ +#define __dvb_descriptor_extended_event_descriptor_h__ + +#include "descriptor.h" + +class ExtendedEvent +{ + protected: + unsigned itemDescriptionLength : 8; + std::string itemDescription; + unsigned itemLength : 8; + std::string item; + + public: + ExtendedEvent(const uint8_t * const buffer); + + std::string getItemDescription(void) const; + std::string getItem(void) const; + + friend class ExtendedEventDescriptor; +}; + +typedef std::vector ExtendedEventVector; +typedef ExtendedEventVector::iterator ExtendedEventIterator; +typedef ExtendedEventVector::const_iterator ExtendedEventConstIterator; + +class ExtendedEventDescriptor : public Descriptor +{ + protected: + unsigned descriptorNumber : 4; + unsigned lastDescriptorNumber : 4; + std::string iso639LanguageCode; + unsigned lengthOfItems : 8; + ExtendedEventVector items; + unsigned textLength : 8; + std::string text; + + public: + ExtendedEventDescriptor(const uint8_t * const buffer); + ~ExtendedEventDescriptor(void); + + uint8_t getDescriptorNumber(void) const; + uint8_t getLastDescriptorNumber(void) const; + std::string getIso639LanguageCode(void) const; + const ExtendedEventVector *getItems(void) const; + std::string getText(void) const; +}; + +#endif /* __dvb_descriptor_extended_event_descriptor_h__ */ diff --git a/lib/dvb_si/frequency_list_descriptor.cpp b/lib/dvb_si/frequency_list_descriptor.cpp new file mode 100644 index 00000000..fe6ea32e --- /dev/null +++ b/lib/dvb_si/frequency_list_descriptor.cpp @@ -0,0 +1,44 @@ +/* + * $Id: frequency_list_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +FrequencyListDescriptor::FrequencyListDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + if (descriptorLength < 1) + return; + reserved = (buffer[2] >> 2) & 0x3f; + codingType = buffer[2] & 0x03; + + for (uint16_t i = 0; i < descriptorLength - 1; i += 4) + centreFrequencies.push_back((buffer[i + 3] << 24) | (buffer[i + 4] << 16) | (buffer[i + 5] << 8) | buffer[i + 6]); +} + +uint8_t FrequencyListDescriptor::getCodingType(void) const +{ + return codingType; +} + +const CentreFrequencyVector *FrequencyListDescriptor::getCentreFrequencies(void) const +{ + return ¢reFrequencies; +} + diff --git a/lib/dvb_si/frequency_list_descriptor.h b/lib/dvb_si/frequency_list_descriptor.h new file mode 100644 index 00000000..83fdf925 --- /dev/null +++ b/lib/dvb_si/frequency_list_descriptor.h @@ -0,0 +1,45 @@ +/* + * $Id: frequency_list_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_frequency_list_descriptor_h__ +#define __dvb_descriptor_frequency_list_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector CentreFrequencyVector; +typedef CentreFrequencyVector::iterator CentreFrequencyIterator; +typedef CentreFrequencyVector::const_iterator CentreFrequencyConstIterator; + +class FrequencyListDescriptor : public Descriptor +{ + protected: + unsigned reserved : 6; + unsigned codingType : 2; + CentreFrequencyVector centreFrequencies; + + public: + FrequencyListDescriptor(const uint8_t * const buffer); + + uint8_t getCodingType(void) const; + const CentreFrequencyVector *getCentreFrequencies(void) const; +}; + +#endif /* __dvb_descriptor_frequency_list_descriptor_h__ */ diff --git a/lib/dvb_si/group_descriptor.h b/lib/dvb_si/group_descriptor.h new file mode 100644 index 00000000..fd3292d3 --- /dev/null +++ b/lib/dvb_si/group_descriptor.h @@ -0,0 +1,34 @@ +/* + * $Id: group_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_group_descriptor_h__ +#define __dvb_descriptor_group_descriptor_h__ + +#include "descriptor.h" + +/* 0x91 */ +class GroupDescriptor : public Descriptor +{ + public: + GroupDescriptor(const uint8_t * const buffer); +}; + +#endif /* __dvb_descriptor_group_descriptor_h__ */ diff --git a/lib/dvb_si/hierarchy_descriptor.h b/lib/dvb_si/hierarchy_descriptor.h new file mode 100644 index 00000000..3c990fc1 --- /dev/null +++ b/lib/dvb_si/hierarchy_descriptor.h @@ -0,0 +1,48 @@ +/* + * $Id: hierarchy_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_hierarchy_descriptor_h__ +#define __dvb_descriptor_hierarchy_descriptor_h__ + +#include "descriptor.h" + +class HierarchyDescriptor : public Descriptor +{ + protected: + unsigned reserved : 4; + unsigned hierarchyType : 4; + unsigned reserved2 : 2; + unsigned hierarchyLayerIndex : 6; + unsigned reserved3 : 2; + unsigned hierarchyEmbeddedLayerIndex : 6; + unsigned reserved4 : 2; + unsigned hierarchyChannel : 6; + + private: + HierarchyDescriptor(const uint8_t * const buffer); + + uint8_t getHierarchyType(void) const; + uint8_t getHierarchyLayerIndex(void) const; + uint8_t getHierarchyEmbeddedLayerIndex(void) const; + uint8_t getHierarchyChannel(void) const; +}; + +#endif /* __dvb_descriptor_hierarchy_descriptor_h__ */ diff --git a/lib/dvb_si/ibp_descriptor.h b/lib/dvb_si/ibp_descriptor.h new file mode 100644 index 00000000..d601fe42 --- /dev/null +++ b/lib/dvb_si/ibp_descriptor.h @@ -0,0 +1,42 @@ +/* + * $Id: ibp_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_ibp_descriptor_h__ +#define __dvb_descriptor_ibp_descriptor_h__ + +#include "descriptor.h" + +class IbpDescriptor : public Descriptor +{ + protected: + unsigned closedGopFlag : 1; + unsigned identicalGopFlag : 1; + unsigned maxGopLength : 14; + + public: + IbpDescriptor(const uint8_t * const buffer); + + uint8_t getClosedGopFlag(void) const; + uint8_t getIdenticalGopFlag(void) const; + uint16_t getMaxGopLength(void) const; +}; + +#endif /* __dvb_descriptor_ibp_descriptor_h__ */ diff --git a/lib/dvb_si/ippv_booking_descriptor.h b/lib/dvb_si/ippv_booking_descriptor.h new file mode 100644 index 00000000..950bb452 --- /dev/null +++ b/lib/dvb_si/ippv_booking_descriptor.h @@ -0,0 +1,34 @@ +/* + * $Id: ippv_booking_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_ippv_booking_descriptor_h__ +#define __dvb_descriptor_ippv_booking_descriptor_h__ + +#include "descriptor.h" + +/* 0x81 */ +class IppvBookingDescriptor : public Descriptor +{ + public: + IppvBookingDescriptor(const uint8_t * const buffer); +}; + +#endif /* __dvb_descriptor_ippv_booking_descriptor_h__ */ diff --git a/lib/dvb_si/ippv_descriptor.h b/lib/dvb_si/ippv_descriptor.h new file mode 100644 index 00000000..967c9b59 --- /dev/null +++ b/lib/dvb_si/ippv_descriptor.h @@ -0,0 +1,62 @@ +/* + * $Id: ippv_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_ippv_descriptor_h__ +#define __dvb_descriptor_ippv_descriptor_h__ + +#include "descriptor.h" + +/* 0xF0 */ +class CurrencyEntry +{ + public: + CurrencyEntry(const uint8_t * const buffer); +}; + +class CountryEntry +{ + protected: + unsigned country : 24; + unsigned unknown : 5; + unsigned currencyAndCostDetail : 3; + // if (currencyAndCostDetail & 1) + unsigned bcdCost : 32; + unsigned length : 8; + std::vector currency; + + public: + CountryEntry(const uint8_t * const buffer); +}; + +class IppvDescriptor : public Descriptor +{ + protected: + unsigned unknown1 : 16; + unsigned unknown2 : 16; + unsigned unknown3 : 16; + unsigned IppvEventId : 16; + std::vector country; + + private: + IppvDescriptor(const uint8_t * const buffer); +}; + +#endif /* __dvb_descriptor_ippv_descriptor_h__ */ diff --git a/lib/dvb_si/iso639_language_descriptor.cpp b/lib/dvb_si/iso639_language_descriptor.cpp new file mode 100644 index 00000000..26ca1e0f --- /dev/null +++ b/lib/dvb_si/iso639_language_descriptor.cpp @@ -0,0 +1,56 @@ +/* + * $Id: iso639_language_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +Iso639Language::Iso639Language(const uint8_t * const buffer) +{ + iso639LanguageCode.assign((char *)&buffer[0], 3); + audioType = buffer[3]; +} + +std::string Iso639Language::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +uint8_t Iso639Language::getAudioType(void) const +{ + return audioType; +} + +Iso639LanguageDescriptor::Iso639LanguageDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 4) + iso639Languages.push_back(new Iso639Language(&buffer[i + 2])); +} + +Iso639LanguageDescriptor::~Iso639LanguageDescriptor(void) +{ + for (Iso639LanguageIterator i = iso639Languages.begin(); i != iso639Languages.end(); ++i) + delete *i; +} + +const Iso639LanguageVector *Iso639LanguageDescriptor::getIso639Languages(void) const +{ + return &iso639Languages; +} + diff --git a/lib/dvb_si/iso639_language_descriptor.h b/lib/dvb_si/iso639_language_descriptor.h new file mode 100644 index 00000000..89836397 --- /dev/null +++ b/lib/dvb_si/iso639_language_descriptor.h @@ -0,0 +1,56 @@ +/* + * $Id: iso639_language_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_iso639_language_descriptor_h__ +#define __dvb_descriptor_iso639_language_descriptor_h__ + +#include "descriptor.h" + +class Iso639Language +{ + protected: + std::string iso639LanguageCode; + unsigned audioType : 8; + + public: + Iso639Language(const uint8_t * const buffer); + + std::string getIso639LanguageCode(void) const; + uint8_t getAudioType(void) const; +}; + +typedef std::vector Iso639LanguageVector; +typedef Iso639LanguageVector::iterator Iso639LanguageIterator; +typedef Iso639LanguageVector::const_iterator Iso639LanguageConstIterator; + +class Iso639LanguageDescriptor : public Descriptor +{ + protected: + Iso639LanguageVector iso639Languages; + + public: + Iso639LanguageDescriptor(const uint8_t * const buffer); + ~Iso639LanguageDescriptor(void); + + const Iso639LanguageVector *getIso639Languages(void) const; +}; + +#endif /* __dvb_descriptor_iso639_language_descriptor_h__ */ diff --git a/lib/dvb_si/linkage_descriptor.cpp b/lib/dvb_si/linkage_descriptor.cpp new file mode 100644 index 00000000..77b991e1 --- /dev/null +++ b/lib/dvb_si/linkage_descriptor.cpp @@ -0,0 +1,107 @@ +/* + * $Id: linkage_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +LinkageDescriptor::LinkageDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + transportStreamId = (buffer[2] << 8) | buffer[3]; + originalNetworkId = (buffer[4] << 8) | buffer[5]; + serviceId = (buffer[6] << 8) | buffer[7]; + linkageType = buffer[8]; + + if (linkageType != 0x08) + { + if (descriptorLength < 7) + return; + + for (uint16_t i = 0; i < descriptorLength - 7; ++i) + privateDataBytes.push_back(buffer[i + 9]); + } + + else { + handOverType = (buffer[9] >> 4) & 0x0f; + reserved = (buffer[9] >> 1) & 0x07; + originType = buffer[9] & 0x01; + + uint8_t offset = 0; + + if ((handOverType >= 0x01) && (handOverType <= 0x03)) { + networkId = (buffer[10] << 8) | buffer[11]; + offset += 2; + } + + if (originType == 0x00) { + initialServiceId = (buffer[offset + 10] << 8) | buffer[offset + 11]; + offset += 2; + } + + if (descriptorLength >= (unsigned)(offset+8)) + for (uint16_t i = 0; i < descriptorLength - (offset + 8); ++i) + privateDataBytes.push_back(buffer[i + offset + 10]); + } +} + +uint16_t LinkageDescriptor::getTransportStreamId(void) const +{ + return transportStreamId; +} + +uint16_t LinkageDescriptor::getOriginalNetworkId(void) const +{ + return originalNetworkId; +} + +uint16_t LinkageDescriptor::getServiceId(void) const +{ + return serviceId; +} + +uint8_t LinkageDescriptor::getLinkageType(void) const +{ + return linkageType; +} + +const PrivateDataByteVector *LinkageDescriptor::getPrivateDataBytes(void) const +{ + return &privateDataBytes; +} + +uint8_t LinkageDescriptor::getHandOverType(void) const +{ + return handOverType; +} + +uint8_t LinkageDescriptor::getOriginType(void) const +{ + return originType; +} + +uint16_t LinkageDescriptor::getNetworkId(void) const +{ + return networkId; +} + +uint16_t LinkageDescriptor::getInitialServiceId(void) const +{ + return initialServiceId; +} + diff --git a/lib/dvb_si/linkage_descriptor.h b/lib/dvb_si/linkage_descriptor.h new file mode 100644 index 00000000..cfecf50c --- /dev/null +++ b/lib/dvb_si/linkage_descriptor.h @@ -0,0 +1,59 @@ +/* + * $Id: linkage_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_linkage_descriptor_h__ +#define __dvb_descriptor_linkage_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector PrivateDataByteVector; +typedef PrivateDataByteVector::iterator PrivateDataByteIterator; +typedef PrivateDataByteVector::const_iterator PrivateDataByteConstIterator; + +class LinkageDescriptor : public Descriptor +{ + protected: + unsigned transportStreamId : 16; + unsigned originalNetworkId : 16; + unsigned serviceId : 16; + unsigned linkageType : 8; + PrivateDataByteVector privateDataBytes; + unsigned handOverType : 4; + unsigned reserved : 3; + unsigned originType : 1; + unsigned networkId : 16; + unsigned initialServiceId : 16; + + public: + LinkageDescriptor(const uint8_t * const buffer); + + uint16_t getTransportStreamId(void) const; + uint16_t getOriginalNetworkId(void) const; + uint16_t getServiceId(void) const; + uint8_t getLinkageType(void) const; + const PrivateDataByteVector *getPrivateDataBytes(void) const; + uint8_t getHandOverType(void) const; + uint8_t getOriginType(void) const; + uint16_t getNetworkId(void) const; + uint16_t getInitialServiceId(void) const; +}; + +#endif /* __dvb_descriptor_linkage_descriptor_h__ */ diff --git a/lib/dvb_si/local_time_offset_descriptor.cpp b/lib/dvb_si/local_time_offset_descriptor.cpp new file mode 100644 index 00000000..72fc53b3 --- /dev/null +++ b/lib/dvb_si/local_time_offset_descriptor.cpp @@ -0,0 +1,88 @@ +/* + * $Id: local_time_offset_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +LocalTimeOffset::LocalTimeOffset(const uint8_t * const buffer) +{ + countryCode.assign((char *)&buffer[0], 3); + countryRegionId = (buffer[3] >> 2) & 0x3f; + reserved = (buffer[3] >> 1) & 0x01; + localTimeOffsetPolarity = buffer[3] & 0x01; + localTimeOffset = (buffer[4] << 8) | buffer[5]; + timeOfChangeMjd = (buffer[6] << 8) | buffer[7]; + timeOfChangeBcd = (buffer[8] << 16) | (buffer[9] << 8) | buffer[10]; + nextTimeOffset = (buffer[11] << 8) | buffer[12]; +} + +std::string LocalTimeOffset::getCountryCode(void) const +{ + return countryCode; +} + +uint8_t LocalTimeOffset::getCountryRegionId(void) const +{ + return countryRegionId; +} + +uint8_t LocalTimeOffset::getLocalTimeOffsetPolarity(void) const +{ + return localTimeOffsetPolarity; +} + +uint16_t LocalTimeOffset::getLocalTimeOffset(void) const +{ + return localTimeOffset; +} + +uint16_t LocalTimeOffset::getTimeOfChangeMjd(void) const +{ + return timeOfChangeMjd; +} + +uint32_t LocalTimeOffset::getTimeOfChangeBcd(void) const +{ + return timeOfChangeBcd; +} + +uint16_t LocalTimeOffset::getNextTimeOffset(void) const +{ + return nextTimeOffset; +} + +LocalTimeOffsetDescriptor::LocalTimeOffsetDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 13) + localTimeOffsets.push_back(new LocalTimeOffset(&buffer[i + 2])); +} + + +LocalTimeOffsetDescriptor::~LocalTimeOffsetDescriptor(void) +{ + for (LocalTimeOffsetIterator i = localTimeOffsets.begin(); i != localTimeOffsets.end(); ++i) + delete *i; +} + +const LocalTimeOffsetVector *LocalTimeOffsetDescriptor::getLocalTimeOffsets(void) const +{ + return &localTimeOffsets; +} + diff --git a/lib/dvb_si/local_time_offset_descriptor.h b/lib/dvb_si/local_time_offset_descriptor.h new file mode 100644 index 00000000..85373f70 --- /dev/null +++ b/lib/dvb_si/local_time_offset_descriptor.h @@ -0,0 +1,67 @@ +/* + * $Id: local_time_offset_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_local_time_offset_descriptor_h__ +#define __dvb_descriptor_local_time_offset_descriptor_h__ + +#include "descriptor.h" + +class LocalTimeOffset +{ + protected: + std::string countryCode; + unsigned countryRegionId : 6; + unsigned reserved : 1; + unsigned localTimeOffsetPolarity : 1; + unsigned localTimeOffset : 16; + unsigned timeOfChangeMjd : 16; + unsigned timeOfChangeBcd : 24; + unsigned nextTimeOffset : 16; + + public: + LocalTimeOffset(const uint8_t * const buffer); + + std::string getCountryCode(void) const; + uint8_t getCountryRegionId(void) const; + uint8_t getLocalTimeOffsetPolarity(void) const; + uint16_t getLocalTimeOffset(void) const; + uint16_t getTimeOfChangeMjd(void) const; + uint32_t getTimeOfChangeBcd(void) const; + uint16_t getNextTimeOffset(void) const; +}; + +typedef std::vector LocalTimeOffsetVector; +typedef LocalTimeOffsetVector::iterator LocalTimeOffsetIterator; +typedef LocalTimeOffsetVector::const_iterator LocalTimeOffsetConstIterator; + +class LocalTimeOffsetDescriptor : public Descriptor +{ + protected: + LocalTimeOffsetVector localTimeOffsets; + + public: + LocalTimeOffsetDescriptor(const uint8_t * const buffer); + ~LocalTimeOffsetDescriptor(void); + + const LocalTimeOffsetVector *getLocalTimeOffsets(void) const; +}; + +#endif /* __dvb_descriptor_local_time_offset_descriptor_h__ */ diff --git a/lib/dvb_si/long_crc_table.cpp b/lib/dvb_si/long_crc_table.cpp new file mode 100644 index 00000000..2f916520 --- /dev/null +++ b/lib/dvb_si/long_crc_table.cpp @@ -0,0 +1,36 @@ +/* + * $Id: long_crc_table.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +LongCrcTable::LongCrcTable(const uint8_t * const buffer) : LongTable(buffer) +{ + crc32 = (buffer[sectionLength - 1] << 24) | + (buffer[sectionLength + 0] << 16) | + (buffer[sectionLength + 1] << 8) | + (buffer[sectionLength + 2]); +} + +uint32_t LongCrcTable::getCrc32(void) const +{ + return crc32; +} + diff --git a/lib/dvb_si/long_crc_table.h b/lib/dvb_si/long_crc_table.h new file mode 100644 index 00000000..14f4dedb --- /dev/null +++ b/lib/dvb_si/long_crc_table.h @@ -0,0 +1,44 @@ +/* + * $Id: long_crc_table.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_long_crc_table_h__ +#define __dvb_table_long_crc_table_h__ + +#include "long_table.h" + +class LongCrcTable : public LongTable +{ + protected: + unsigned crc32 : 32; + + public: + LongCrcTable(const uint8_t * const buffer); + + static const uint8_t CRC32 = 1; + + uint32_t getCrc32(void) const; +}; + +typedef std::vector LongCrcTableVector; +typedef LongCrcTableVector::iterator LongCrcTableIterator; +typedef LongCrcTableVector::const_iterator LongCrcTableConstIterator; + +#endif /* __dvb_table_long_crc_table_h__ */ diff --git a/lib/dvb_si/long_table.cpp b/lib/dvb_si/long_table.cpp new file mode 100644 index 00000000..f6bcbdf0 --- /dev/null +++ b/lib/dvb_si/long_table.cpp @@ -0,0 +1,88 @@ +/* + * $Id: long_table.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +LongTable::LongTable(const uint8_t * const buffer) : ShortTable(buffer) +{ + tableIdExtension = (buffer[3] << 8) | buffer[4]; + reserved3 = (buffer[5] >> 6) & 0x03; + versionNumber = (buffer[5] >> 1) & 0x1F; + currentNextIndicator = buffer[5] & 0x01; + sectionNumber = buffer[6]; + lastSectionNumber = buffer[7]; +} + +uint16_t LongTable::getTableIdExtension(void) const +{ + return tableIdExtension; +} + +uint8_t LongTable::getVersionNumber(void) const +{ + return versionNumber; +} + +uint8_t LongTable::getCurrentNextIndicator(void) const +{ + return currentNextIndicator; +} + +uint8_t LongTable::getSectionNumber(void) const +{ + return sectionNumber; +} + +uint8_t LongTable::getLastSectionNumber(void) const +{ + return lastSectionNumber; +} + +bool LongTable::operator< (const LongTable &t) const +{ + return (sectionNumber < t.sectionNumber); +} + +bool LongTable::operator> (const LongTable &t) const +{ + return (sectionNumber > t.sectionNumber); +} + +bool LongTable::operator<= (const LongTable &t) const +{ + return (sectionNumber <= t.sectionNumber); +} + +bool LongTable::operator>= (const LongTable &t) const +{ + return (sectionNumber >= t.sectionNumber); +} + +bool LongTable::operator== (const LongTable &t) const +{ + return (sectionNumber == t.sectionNumber); +} + +bool LongTable::operator!= (const LongTable &t) const +{ + return (sectionNumber != t.sectionNumber); +} + diff --git a/lib/dvb_si/long_table.h b/lib/dvb_si/long_table.h new file mode 100644 index 00000000..31341d4c --- /dev/null +++ b/lib/dvb_si/long_table.h @@ -0,0 +1,60 @@ +/* + * $Id: long_table.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_long_table_h__ +#define __dvb_table_long_table_h__ + +#include "short_table.h" + +class LongTable : public ShortTable +{ + protected: + unsigned tableIdExtension : 16; + unsigned reserved3 : 2; + unsigned versionNumber : 5; + unsigned currentNextIndicator : 1; + unsigned sectionNumber : 8; + unsigned lastSectionNumber : 8; + + public: + LongTable(const uint8_t * const buffer); + + static const uint8_t SYNTAX = 1; + + uint16_t getTableIdExtension(void) const; + uint8_t getVersionNumber(void) const; + uint8_t getCurrentNextIndicator(void) const; + uint8_t getSectionNumber(void) const; + uint8_t getLastSectionNumber(void) const; + + bool operator< (const LongTable &t) const; + bool operator> (const LongTable &t) const; + bool operator<= (const LongTable &t) const; + bool operator>= (const LongTable &t) const; + bool operator== (const LongTable &t) const; + bool operator!= (const LongTable &t) const; +}; + +typedef std::vector LongTableVector; +typedef LongTableVector::iterator LongTableIterator; +typedef LongTableVector::const_iterator LongTableConstIterator; + +#endif /* __dvb_table_long_table_h__ */ diff --git a/lib/dvb_si/maximum_bitrate_descriptor.h b/lib/dvb_si/maximum_bitrate_descriptor.h new file mode 100644 index 00000000..54ed29c4 --- /dev/null +++ b/lib/dvb_si/maximum_bitrate_descriptor.h @@ -0,0 +1,39 @@ +/* + * $Id: maximum_bitrate_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_maximum_bitrate_descriptor_h__ +#define __dvb_descriptor_maximum_bitrate_descriptor_h__ + +#include "descriptor.h" + +class MaximumBitrateDescriptor : public Descriptor +{ + protected: + unsigned reserved : 2; + unsigned maximumBitrate : 22; + + public: + MaximumBitrateDescriptor(const uint8_t * const buffer); + + uint32_t getMaximumBitrate(void) const; +}; + +#endif /* __dvb_descriptor_maximum_bitrate_descriptor_h__ */ diff --git a/lib/dvb_si/mosaic_descriptor.cpp b/lib/dvb_si/mosaic_descriptor.cpp new file mode 100644 index 00000000..f13bccff --- /dev/null +++ b/lib/dvb_si/mosaic_descriptor.cpp @@ -0,0 +1,171 @@ +/* + * $Id: mosaic_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ElementaryCellField::ElementaryCellField (const uint8_t * const buffer) +{ + reserved = (buffer[0] >> 6) & 0x03; + elementaryCellId = buffer[0] & 0x3F; +} + +uint8_t ElementaryCellField::getElementaryCellId(void) const +{ + return elementaryCellId; +} + +MosaicCell::MosaicCell (const uint8_t * const buffer) +{ + logicalCellId = (buffer[0] >> 2) & 0x3F; + reserved = (((buffer[0] & 0x03) << 8) | (buffer[1] & 0xF1)) >> 3; + logicalCellPresentationInfo = buffer[1] & 0x07; + elementaryCellFieldLength = buffer[2]; + + for (uint16_t i = 0; i < elementaryCellFieldLength; ++i) + elementaryCellFields.push_back(new ElementaryCellField(&buffer[i + 3])); + + cellLinkageInfo = buffer[elementaryCellFieldLength + 3]; + + switch (cellLinkageInfo) { + case 0x01: + bouquetId = (buffer[elementaryCellFieldLength + 4] << 8) | buffer[elementaryCellFieldLength + 5]; + break; + case 0x02: + case 0x03: + case 0x04: + originalNetworkId = (buffer[elementaryCellFieldLength + 4] << 8) | buffer[elementaryCellFieldLength + 5]; + transportStreamId = (buffer[elementaryCellFieldLength + 6] << 8) | buffer[elementaryCellFieldLength + 7]; + serviceId = (buffer[elementaryCellFieldLength + 8] << 8) | buffer[elementaryCellFieldLength + 9]; + break; + default: + break; + } + + if (cellLinkageInfo == 0x04) + eventId = (buffer[elementaryCellFieldLength + 10] << 8) | buffer[elementaryCellFieldLength + 11]; +} + +MosaicCell::~MosaicCell(void) +{ + for (ElementaryCellFieldIterator i = elementaryCellFields.begin(); i != elementaryCellFields.end(); ++i) + delete *i; +} + +uint8_t MosaicCell::getLogicalCellId(void) const +{ + return logicalCellId; +} + +uint8_t MosaicCell::getLogicalCellPresentationInfo(void) const +{ + return logicalCellPresentationInfo; +} + +const ElementaryCellFieldVector *MosaicCell::getElementaryCellFields(void) const +{ + return &elementaryCellFields; +} + +uint8_t MosaicCell::getCellLinkageInfo(void) const +{ + return cellLinkageInfo; +} + +uint16_t MosaicCell::getBouquetId(void) const +{ + return bouquetId; +} + +uint16_t MosaicCell::getOriginalNetworkId(void) const +{ + return originalNetworkId; +} + +uint16_t MosaicCell::getTransportStreamId(void) const +{ + return transportStreamId; +} + +uint16_t MosaicCell::getServiceId(void) const +{ + return serviceId; +} + +uint16_t MosaicCell::getEventId(void) const +{ + return eventId; +} + +MosaicDescriptor::MosaicDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + if (descriptorLength < 1) + return; + + mosaicEntryPoint = (buffer[2] >> 7) & 0x01; + numberOfHorizontalElementaryCells = (buffer[2] >> 4) & 0x07; + reserved = (buffer[2] >> 3) & 0x01; + numberOfVerticalElementaryCells = buffer[2] & 0x07; + + for (uint16_t i = 0; i < descriptorLength - 1; i += buffer[i + 6] + 2) { + mosaicCells.push_back(new MosaicCell(&buffer[i + 1])); + switch (buffer[i + 6 + buffer[i + 6] + 1]) { + case 0x01: + i += 2; + break; + case 0x02: + case 0x03: + i += 6; + break; + case 0x04: + i += 8; + break; + default: + break; + } + } +} + +MosaicDescriptor::~MosaicDescriptor(void) +{ + for (MosaicCellIterator i = mosaicCells.begin(); i != mosaicCells.end(); ++i) + delete *i; +} + +uint8_t MosaicDescriptor::getMosaicEntryPoint(void) const +{ + return mosaicEntryPoint; +} + +uint8_t MosaicDescriptor::getNumberOfHorizontalElementaryCells(void) const +{ + return numberOfHorizontalElementaryCells; +} + +uint8_t MosaicDescriptor::getNumberOfVerticalElementaryCells(void) const +{ + return numberOfVerticalElementaryCells; +} + +const MosaicCellVector *MosaicDescriptor::getMosaicCells(void) const +{ + return &mosaicCells; +} + diff --git a/lib/dvb_si/mosaic_descriptor.h b/lib/dvb_si/mosaic_descriptor.h new file mode 100644 index 00000000..e9f112e6 --- /dev/null +++ b/lib/dvb_si/mosaic_descriptor.h @@ -0,0 +1,96 @@ +/* + * $Id: mosaic_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_mosaic_descriptor_h__ +#define __dvb_descriptor_mosaic_descriptor_h__ + +#include "descriptor.h" + +class ElementaryCellField +{ + protected: + unsigned reserved : 2; + unsigned elementaryCellId : 6; + + public: + ElementaryCellField(const uint8_t * const buffer); + + uint8_t getElementaryCellId(void) const; +}; + +typedef std::vector ElementaryCellFieldVector; +typedef ElementaryCellFieldVector::iterator ElementaryCellFieldIterator; +typedef ElementaryCellFieldVector::const_iterator ElementaryCellFieldConstIterator; + +class MosaicCell +{ + protected: + unsigned logicalCellId : 6; + unsigned reserved : 7; + unsigned logicalCellPresentationInfo : 3; + unsigned elementaryCellFieldLength : 8; + ElementaryCellFieldVector elementaryCellFields; + unsigned cellLinkageInfo : 8; + unsigned bouquetId : 16; + unsigned originalNetworkId : 16; + unsigned transportStreamId : 16; + unsigned serviceId : 16; + unsigned eventId : 16; + + public: + MosaicCell(const uint8_t * const buffer); + ~MosaicCell(void); + + uint8_t getLogicalCellId(void) const; + uint8_t getLogicalCellPresentationInfo(void) const; + const ElementaryCellFieldVector *getElementaryCellFields(void) const; + uint8_t getCellLinkageInfo(void) const; + uint16_t getBouquetId(void) const; + uint16_t getOriginalNetworkId(void) const; + uint16_t getTransportStreamId(void) const; + uint16_t getServiceId(void) const; + uint16_t getEventId(void) const; +}; + +typedef std::vector MosaicCellVector; +typedef MosaicCellVector::iterator MosaicCellIterator; +typedef MosaicCellVector::const_iterator MosaicCellConstIterator; + +class MosaicDescriptor : public Descriptor +{ + protected: + unsigned mosaicEntryPoint : 1; + unsigned numberOfHorizontalElementaryCells : 3; + unsigned reserved : 1; + unsigned numberOfVerticalElementaryCells : 3; + MosaicCellVector mosaicCells; + + public: + MosaicDescriptor(const uint8_t * const buffer); + ~MosaicDescriptor(void); + + uint8_t getMosaicEntryPoint(void) const; + uint8_t getNumberOfHorizontalElementaryCells(void) const; + uint8_t getNumberOfVerticalElementaryCells(void) const; + const MosaicCellVector *getMosaicCells(void) const; +}; + +#endif /* __dvb_descriptor_mosaic_descriptor_h__ */ diff --git a/lib/dvb_si/multilingual_bouquet_name_descriptor.cpp b/lib/dvb_si/multilingual_bouquet_name_descriptor.cpp new file mode 100644 index 00000000..d628dc01 --- /dev/null +++ b/lib/dvb_si/multilingual_bouquet_name_descriptor.cpp @@ -0,0 +1,57 @@ +/* + * $Id: multilingual_bouquet_name_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +MultilingualBouquetName::MultilingualBouquetName(const uint8_t * const buffer) +{ + iso639LanguageCode.assign((char *)&buffer[0], 3); + bouquetNameLength = buffer[3]; + bouquetName.assign((char *)&buffer[4], bouquetNameLength); +} + +std::string MultilingualBouquetName::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +std::string MultilingualBouquetName::getBouquetName(void) const +{ + return bouquetName; +} + +MultilingualBouquetNameDescriptor::MultilingualBouquetNameDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += buffer[i + 3] + 2) + multilingualBouquetNames.push_back(new MultilingualBouquetName(&buffer[i + 2])); +} + +MultilingualBouquetNameDescriptor::~MultilingualBouquetNameDescriptor(void) +{ + for (MultilingualBouquetNameIterator i = multilingualBouquetNames.begin(); i != multilingualBouquetNames.end(); ++i) + delete *i; +} + +const MultilingualBouquetNameVector *MultilingualBouquetNameDescriptor::getMultilingualBouquetNames(void) const +{ + return &multilingualBouquetNames; +} + diff --git a/lib/dvb_si/multilingual_bouquet_name_descriptor.h b/lib/dvb_si/multilingual_bouquet_name_descriptor.h new file mode 100644 index 00000000..3864f74b --- /dev/null +++ b/lib/dvb_si/multilingual_bouquet_name_descriptor.h @@ -0,0 +1,57 @@ +/* + * $Id: multilingual_bouquet_name_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_multilingual_bouquet_name_descriptor_h__ +#define __dvb_descriptor_multilingual_bouquet_name_descriptor_h__ + +#include "descriptor.h" + +class MultilingualBouquetName +{ + protected: + std::string iso639LanguageCode; + unsigned bouquetNameLength : 8; + std::string bouquetName; + + public: + MultilingualBouquetName(const uint8_t * const buffer); + + std::string getIso639LanguageCode(void) const; + std::string getBouquetName(void) const; +}; + +typedef std::vector MultilingualBouquetNameVector; +typedef MultilingualBouquetNameVector::iterator MultilingualBouquetNameIterator; +typedef MultilingualBouquetNameVector::const_iterator MultilingualBouquetNameConstIterator; + +class MultilingualBouquetNameDescriptor : public Descriptor +{ + protected: + MultilingualBouquetNameVector multilingualBouquetNames; + + public: + MultilingualBouquetNameDescriptor(const uint8_t * const buffer); + ~MultilingualBouquetNameDescriptor(void); + + const MultilingualBouquetNameVector *getMultilingualBouquetNames(void) const; +}; + +#endif /* __dvb_descriptor_multilingual_bouquet_name_descriptor_h__ */ diff --git a/lib/dvb_si/multilingual_component_descriptor.cpp b/lib/dvb_si/multilingual_component_descriptor.cpp new file mode 100644 index 00000000..ecd49506 --- /dev/null +++ b/lib/dvb_si/multilingual_component_descriptor.cpp @@ -0,0 +1,64 @@ +/* + * $Id: multilingual_component_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +MultilingualComponent::MultilingualComponent(const uint8_t * const buffer) +{ + iso639LanguageCode.assign((char *)&buffer[0], 3); + textDescriptionLength = buffer[3]; + text.assign((char *)&buffer[4], textDescriptionLength); +} + +std::string MultilingualComponent::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +std::string MultilingualComponent::getText(void) const +{ + return text; +} + +MultilingualComponentDescriptor::MultilingualComponentDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + componentTag = buffer[2]; + + for (uint16_t i = 0; i < descriptorLength - 1; i += buffer[i + 4] + 2) + multilingualComponents.push_back(new MultilingualComponent(&buffer[i + 3])); +} + +MultilingualComponentDescriptor::~MultilingualComponentDescriptor(void) +{ + for (MultilingualComponentIterator i = multilingualComponents.begin(); i != multilingualComponents.end(); ++i) + delete *i; +} + +uint8_t MultilingualComponentDescriptor::getComponentTag(void) const +{ + return componentTag; +} + +const MultilingualComponentVector *MultilingualComponentDescriptor::getMultilingualComponents(void) const +{ + return &multilingualComponents; +} + diff --git a/lib/dvb_si/multilingual_component_descriptor.h b/lib/dvb_si/multilingual_component_descriptor.h new file mode 100644 index 00000000..d7d21010 --- /dev/null +++ b/lib/dvb_si/multilingual_component_descriptor.h @@ -0,0 +1,59 @@ +/* + * $Id: multilingual_component_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_multilingual_component_descriptor_h__ +#define __dvb_descriptor_multilingual_component_descriptor_h__ + +#include "descriptor.h" + +class MultilingualComponent +{ + protected: + std::string iso639LanguageCode; + unsigned textDescriptionLength : 8; + std::string text; + + public: + MultilingualComponent(const uint8_t * const buffer); + + std::string getIso639LanguageCode(void) const; + std::string getText(void) const; +}; + +typedef std::vector MultilingualComponentVector; +typedef MultilingualComponentVector::iterator MultilingualComponentIterator; +typedef MultilingualComponentVector::const_iterator MultilingualComponentConstIterator; + +class MultilingualComponentDescriptor : public Descriptor +{ + protected: + unsigned componentTag : 8; + MultilingualComponentVector multilingualComponents; + + public: + MultilingualComponentDescriptor(const uint8_t * const buffer); + ~MultilingualComponentDescriptor(void); + + uint8_t getComponentTag(void) const; + const MultilingualComponentVector *getMultilingualComponents(void) const; +}; + +#endif /* __dvb_descriptor_multilingual_component_descriptor_h__ */ diff --git a/lib/dvb_si/multilingual_network_name_descriptor.cpp b/lib/dvb_si/multilingual_network_name_descriptor.cpp new file mode 100644 index 00000000..8bccc6c0 --- /dev/null +++ b/lib/dvb_si/multilingual_network_name_descriptor.cpp @@ -0,0 +1,57 @@ +/* + * $Id: multilingual_network_name_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +MultilingualNetworkName::MultilingualNetworkName(const uint8_t * const buffer) +{ + iso639LanguageCode.assign((char *)&buffer[0], 3); + networkNameLength = buffer[3]; + networkName.assign((char *)&buffer[4], networkNameLength); +} + +std::string MultilingualNetworkName::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +std::string MultilingualNetworkName::getNetworkName(void) const +{ + return networkName; +} + +MultilingualNetworkNameDescriptor::MultilingualNetworkNameDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += buffer[i + 5] + 4) + multilingualNetworkNames.push_back(new MultilingualNetworkName(&buffer[i + 2])); +} + +MultilingualNetworkNameDescriptor::~MultilingualNetworkNameDescriptor(void) +{ + for (MultilingualNetworkNameIterator i = multilingualNetworkNames.begin(); i != multilingualNetworkNames.end(); ++i) + delete *i; +} + +const MultilingualNetworkNameVector *MultilingualNetworkNameDescriptor::getMultilingualNetworkNames(void) const +{ + return &multilingualNetworkNames; +} + diff --git a/lib/dvb_si/multilingual_network_name_descriptor.h b/lib/dvb_si/multilingual_network_name_descriptor.h new file mode 100644 index 00000000..b7df57b2 --- /dev/null +++ b/lib/dvb_si/multilingual_network_name_descriptor.h @@ -0,0 +1,57 @@ +/* + * $Id: multilingual_network_name_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_multilingual_network_name_descriptor_h__ +#define __dvb_descriptor_multilingual_network_name_descriptor_h__ + +#include "descriptor.h" + +class MultilingualNetworkName +{ + protected: + std::string iso639LanguageCode; + unsigned networkNameLength : 8; + std::string networkName; + + public: + MultilingualNetworkName(const uint8_t * const buffer); + + std::string getIso639LanguageCode(void) const; + std::string getNetworkName(void) const; +}; + +typedef std::vector MultilingualNetworkNameVector; +typedef MultilingualNetworkNameVector::iterator MultilingualNetworkNameIterator; +typedef MultilingualNetworkNameVector::const_iterator MultilingualNetworkNameConstIterator; + +class MultilingualNetworkNameDescriptor : public Descriptor +{ + protected: + MultilingualNetworkNameVector multilingualNetworkNames; + + public: + MultilingualNetworkNameDescriptor(const uint8_t * const buffer); + ~MultilingualNetworkNameDescriptor(void); + + const MultilingualNetworkNameVector *getMultilingualNetworkNames(void) const; +}; + +#endif /* __dvb_descriptor_multilingual_network_name_descriptor_h__ */ diff --git a/lib/dvb_si/multilingual_service_name_descriptor.cpp b/lib/dvb_si/multilingual_service_name_descriptor.cpp new file mode 100644 index 00000000..d811aaef --- /dev/null +++ b/lib/dvb_si/multilingual_service_name_descriptor.cpp @@ -0,0 +1,68 @@ +/* + * $Id: multilingual_service_name_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +MultilingualServiceName::MultilingualServiceName(const uint8_t * const buffer) +{ + iso639LanguageCode.assign((char *)&buffer[0], 3); + serviceProviderNameLength = buffer[3]; + serviceProviderName.assign((char *)&buffer[4], serviceProviderNameLength); + serviceNameLength = buffer[serviceProviderNameLength + 4]; + serviceName.assign((char *)&buffer[serviceProviderNameLength + 5], serviceNameLength); +} + +std::string MultilingualServiceName::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +std::string MultilingualServiceName::getServiceProviderName(void) const +{ + return serviceProviderName; +} + +std::string MultilingualServiceName::getServiceName(void) const +{ + return serviceName; +} + +MultilingualServiceNameDescriptor::MultilingualServiceNameDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + MultilingualServiceName *name; + + for (uint16_t i = 0; i < descriptorLength; i += name->serviceProviderNameLength + name->serviceNameLength + 5) { + name = new MultilingualServiceName(&buffer[i + 2]); + multilingualServiceNames.push_back(name); + } +} + +MultilingualServiceNameDescriptor::~MultilingualServiceNameDescriptor(void) +{ + for (MultilingualServiceNameIterator i = multilingualServiceNames.begin(); i != multilingualServiceNames.end(); ++i) + delete *i; +} + +const MultilingualServiceNameVector *MultilingualServiceNameDescriptor::getMultilingualServiceNames(void) const +{ + return &multilingualServiceNames; +} + diff --git a/lib/dvb_si/multilingual_service_name_descriptor.h b/lib/dvb_si/multilingual_service_name_descriptor.h new file mode 100644 index 00000000..5979b5c0 --- /dev/null +++ b/lib/dvb_si/multilingual_service_name_descriptor.h @@ -0,0 +1,62 @@ +/* + * $Id: multilingual_service_name_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_multilingual_service_name_descriptor_h__ +#define __dvb_descriptor_multilingual_service_name_descriptor_h__ + +#include "descriptor.h" + +class MultilingualServiceName +{ + protected: + std::string iso639LanguageCode; + unsigned serviceProviderNameLength : 8; + std::string serviceProviderName; + unsigned serviceNameLength : 8; + std::string serviceName; + + public: + MultilingualServiceName(const uint8_t * const buffer); + + std::string getIso639LanguageCode(void) const; + std::string getServiceProviderName(void) const; + std::string getServiceName(void) const; + + friend class MultilingualServiceNameDescriptor; +}; + +typedef std::vector MultilingualServiceNameVector; +typedef MultilingualServiceNameVector::iterator MultilingualServiceNameIterator; +typedef MultilingualServiceNameVector::const_iterator MultilingualServiceNameConstIterator; + +class MultilingualServiceNameDescriptor : public Descriptor +{ + protected: + MultilingualServiceNameVector multilingualServiceNames; + + public: + MultilingualServiceNameDescriptor(const uint8_t * const buffer); + ~MultilingualServiceNameDescriptor(void); + + const MultilingualServiceNameVector *getMultilingualServiceNames(void) const; +}; + +#endif /* __dvb_descriptor_multilingual_service_name_descriptor_h__ */ diff --git a/lib/dvb_si/multiplex_buffer_utilization_descriptor.h b/lib/dvb_si/multiplex_buffer_utilization_descriptor.h new file mode 100644 index 00000000..dc7a160a --- /dev/null +++ b/lib/dvb_si/multiplex_buffer_utilization_descriptor.h @@ -0,0 +1,43 @@ +/* + * $Id: multiplex_buffer_utilization_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_multiplex_buffer_utilization_descriptor_h__ +#define __dvb_descriptor_multiplex_buffer_utilization_descriptor_h__ + +#include "descriptor.h" + +class MultiplexBufferUtilizationDescriptor : public Descriptor +{ + protected: + unsigned boundValidFlag : 1; + unsigned ltwOffsetLowerBound : 15; + unsigned reserved : 1; + unsigned ltwOffsetUpperBound : 15; + + public: + MultiplexBufferUtilizationDescriptor(const uint8_t * const buffer); + + uint8_t getBoundValidFlag(void) const; + uint16_t getLtwOffsetLowerBound(void) const; + uint16_t getLtwOffsetUpperBound(void) const; +}; + +#endif /* __dvb_descriptor_multiplex_buffer_utilization_descriptor_h__ */ diff --git a/lib/dvb_si/network_name_descriptor.cpp b/lib/dvb_si/network_name_descriptor.cpp new file mode 100644 index 00000000..3ba38725 --- /dev/null +++ b/lib/dvb_si/network_name_descriptor.cpp @@ -0,0 +1,33 @@ +/* + * $Id: network_name_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +NetworkNameDescriptor::NetworkNameDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + networkName.assign((char *)&buffer[2], descriptorLength); +} + +std::string NetworkNameDescriptor::getNetworkName(void) const +{ + return networkName; +} + diff --git a/lib/dvb_si/network_name_descriptor.h b/lib/dvb_si/network_name_descriptor.h new file mode 100644 index 00000000..694e3706 --- /dev/null +++ b/lib/dvb_si/network_name_descriptor.h @@ -0,0 +1,38 @@ +/* + * $Id: network_name_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_network_name_descriptor_h__ +#define __dvb_descriptor_network_name_descriptor_h__ + +#include "descriptor.h" + +class NetworkNameDescriptor : public Descriptor +{ + protected: + std::string networkName; + + public: + NetworkNameDescriptor(const uint8_t * const buffer); + + std::string getNetworkName(void) const; +}; + +#endif /* __dvb_descriptor_network_name_descriptor_h__ */ diff --git a/lib/dvb_si/nit.cpp b/lib/dvb_si/nit.cpp new file mode 100644 index 00000000..dcf90e3c --- /dev/null +++ b/lib/dvb_si/nit.cpp @@ -0,0 +1,70 @@ +/* + * $Id: nit.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +TransportStreamInfo::TransportStreamInfo(const uint8_t * const buffer) +{ + transportStreamId = (buffer[0] << 8) | buffer[1]; + originalNetworkId = (buffer[2] << 8) | buffer[3]; + reserved1 = (buffer[4] >> 8) & 0x0F; + transportDescriptorsLength = ((buffer[4] & 0x0F) << 8) | buffer[5]; + + for (uint16_t i = 6; i < transportDescriptorsLength + 6; i += buffer[i + 1] + 2) + descriptor(&buffer[i]); +} + +uint16_t TransportStreamInfo::getTransportStreamId(void) const +{ + return transportStreamId; +} + +uint16_t TransportStreamInfo::getOriginalNetworkId(void) const +{ + return originalNetworkId; +} + +NetworkInformationTable::NetworkInformationTable(const uint8_t * const buffer) : LongCrcTable(buffer) +{ + reserved4 = (buffer[8] >> 5) & 0x0F; + networkDescriptorsLength = ((buffer[8] & 0x0F) << 8) | buffer[9]; + + for (uint16_t i = 10; i < networkDescriptorsLength + 10; i += buffer[i + 1] + 2) + descriptor(&buffer[i]); + + reserved5 = (buffer[networkDescriptorsLength + 10] >> 4) & 0x0F; + transportStreamLoopLength = ((buffer[networkDescriptorsLength + 10] & 0x0F) << 8) | buffer[networkDescriptorsLength + 11]; + + for (uint16_t i = networkDescriptorsLength + 12; i < sectionLength + 3 - 4; i += ((buffer[i + 4] & 0x0F) | buffer[i + 5]) + 6) + tsInfo.push_back(new TransportStreamInfo(&buffer[i])); +} + +NetworkInformationTable::~NetworkInformationTable(void) +{ + for (TransportStreamInfoIterator i = tsInfo.begin(); i != tsInfo.end(); ++i) + delete *i; +} + +const TransportStreamInfoVector *NetworkInformationTable::getTsInfo(void) const +{ + return &tsInfo; +} + diff --git a/lib/dvb_si/nit.h b/lib/dvb_si/nit.h new file mode 100644 index 00000000..de92a34b --- /dev/null +++ b/lib/dvb_si/nit.h @@ -0,0 +1,71 @@ +/* + * $Id: nit.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_nit_h__ +#define __dvb_table_nit_h__ + +#include +#include "long_crc_table.h" + +class TransportStreamInfo : public DescriptorContainer +{ + protected: + unsigned transportStreamId : 16; + unsigned originalNetworkId : 16; + unsigned reserved1 : 4; + unsigned transportDescriptorsLength : 12; + + public: + TransportStreamInfo(const uint8_t * const buffer); + + uint16_t getTransportStreamId(void) const; + uint16_t getOriginalNetworkId(void) const; +}; + +typedef std::vector TransportStreamInfoVector; +typedef TransportStreamInfoVector::iterator TransportStreamInfoIterator; +typedef TransportStreamInfoVector::const_iterator TransportStreamInfoConstIterator; + +class NetworkInformationTable : public LongCrcTable, public DescriptorContainer +{ + protected: + unsigned reserved4 : 3; + unsigned networkDescriptorsLength : 12; + unsigned reserved5 : 4; + unsigned transportStreamLoopLength : 12; + TransportStreamInfoVector tsInfo; + + public: + NetworkInformationTable(const uint8_t * const buffer); + ~NetworkInformationTable(void); + + static const enum PacketId PID = PID_NIT; + static const enum TableId TID = TID_NIT_ACTUAL; + static const uint32_t TIMEOUT = 12000; + + const TransportStreamInfoVector *getTsInfo(void) const; +}; + +typedef std::vector NetworkInformationTableVector; +typedef NetworkInformationTableVector::iterator NetworkInformationTableIterator; +typedef NetworkInformationTableVector::const_iterator NetworkInformationTableConstIterator; + +#endif /* __dvb_table_nit_h__ */ diff --git a/lib/dvb_si/nvod_reference_descriptor.cpp b/lib/dvb_si/nvod_reference_descriptor.cpp new file mode 100644 index 00000000..d7425811 --- /dev/null +++ b/lib/dvb_si/nvod_reference_descriptor.cpp @@ -0,0 +1,63 @@ +/* + * $Id: nvod_reference_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + + +NvodReference::NvodReference(const uint8_t * const buffer) +{ + transportStreamId = (buffer[0] << 8) | buffer[1]; + originalNetworkId = (buffer[2] << 8) | buffer[3]; + serviceId = (buffer[4] << 8) | buffer[5]; +} + +uint16_t NvodReference::getTransportStreamId(void) const +{ + return transportStreamId; +} + +uint16_t NvodReference::getOriginalNetworkId(void) const +{ + return originalNetworkId; +} + +uint16_t NvodReference::getServiceId(void) const +{ + return serviceId; +} + +NvodReferenceDescriptor::NvodReferenceDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 6) + nvodReferences.push_back(new NvodReference(&buffer[i + 2])); +} + +NvodReferenceDescriptor::~NvodReferenceDescriptor(void) +{ + for (NvodReferenceIterator i = nvodReferences.begin(); i != nvodReferences.end(); ++i) + delete *i; +} + +const NvodReferenceVector *NvodReferenceDescriptor::getNvodReferences(void) const +{ + return &nvodReferences; +} + diff --git a/lib/dvb_si/nvod_reference_descriptor.h b/lib/dvb_si/nvod_reference_descriptor.h new file mode 100644 index 00000000..4b434c3b --- /dev/null +++ b/lib/dvb_si/nvod_reference_descriptor.h @@ -0,0 +1,58 @@ +/* + * $Id: nvod_reference_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_nvod_reference_descriptor_h__ +#define __dvb_descriptor_nvod_reference_descriptor_h__ + +#include "descriptor.h" + +class NvodReference +{ + protected: + unsigned transportStreamId : 16; + unsigned originalNetworkId : 16; + unsigned serviceId : 16; + + public: + NvodReference(const uint8_t * const buffer); + + uint16_t getTransportStreamId(void) const; + uint16_t getOriginalNetworkId(void) const; + uint16_t getServiceId(void) const; +}; + +typedef std::vector NvodReferenceVector; +typedef NvodReferenceVector::iterator NvodReferenceIterator; +typedef NvodReferenceVector::const_iterator NvodReferenceConstIterator; + +class NvodReferenceDescriptor : public Descriptor +{ + protected: + NvodReferenceVector nvodReferences; + + public: + NvodReferenceDescriptor(const uint8_t * const buffer); + ~NvodReferenceDescriptor(void); + + const NvodReferenceVector* getNvodReferences(void) const; +}; + +#endif /* __dvb_descriptor_nvod_reference_descriptor_h__ */ diff --git a/lib/dvb_si/packet_id.h b/lib/dvb_si/packet_id.h new file mode 100644 index 00000000..3f18f084 --- /dev/null +++ b/lib/dvb_si/packet_id.h @@ -0,0 +1,45 @@ +/* + * $Id: packet_id.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_id_packet_id_h__ +#define __dvb_id_packet_id_h__ + +enum PacketId { + /* ETSI EN 300 468 V1.5.1 (2003-01) */ + PID_PAT = 0x0000, + PID_CAT = 0x0001, + PID_TSDT = 0x0002, + PID_NIT = 0x0010, + PID_BAT = 0x0011, + PID_SDT = 0x0011, + PID_EIT = 0x0012, + PID_RST = 0x0013, + PID_TDT = 0x0014, + PID_TOT = 0x0014, + PID_NS = 0x0015, /* network synchronization */ + PID_IS = 0x001C, /* inband signaling (SIS-12) */ + PID_M = 0x001D, /* measurement (SIS-10) */ + PID_DIT = 0x001E, + PID_SIT = 0x001F, + PID_RESERVED = 0x1FFF +}; + +#endif /* __dvb_id_packet_id_h__ */ diff --git a/lib/dvb_si/parental_rating_descriptor.cpp b/lib/dvb_si/parental_rating_descriptor.cpp new file mode 100644 index 00000000..39262679 --- /dev/null +++ b/lib/dvb_si/parental_rating_descriptor.cpp @@ -0,0 +1,56 @@ +/* + * $Id: parental_rating_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ParentalRating::ParentalRating(const uint8_t * const buffer) +{ + countryCode.assign((char *)&buffer[0], 3); + rating = buffer[3]; +} + +std::string ParentalRating::getCountryCode(void) const +{ + return countryCode; +} + +uint8_t ParentalRating::getRating(void) const +{ + return rating; +} + +ParentalRatingDescriptor::ParentalRatingDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 4) + parentalRatings.push_back(new ParentalRating(&buffer[i + 2])); +} + +ParentalRatingDescriptor::~ParentalRatingDescriptor(void) +{ + for (ParentalRatingIterator i = parentalRatings.begin(); i != parentalRatings.end(); ++i) + delete *i; +} + +const ParentalRatingVector *ParentalRatingDescriptor::getParentalRatings(void) const +{ + return &parentalRatings; +} + diff --git a/lib/dvb_si/parental_rating_descriptor.h b/lib/dvb_si/parental_rating_descriptor.h new file mode 100644 index 00000000..5528872b --- /dev/null +++ b/lib/dvb_si/parental_rating_descriptor.h @@ -0,0 +1,56 @@ +/* + * $Id: parental_rating_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_parental_rating_descriptor_h__ +#define __dvb_descriptor_parental_rating_descriptor_h__ + +#include "descriptor.h" + +class ParentalRating +{ + protected: + std::string countryCode; + unsigned rating : 8; + + public: + ParentalRating(const uint8_t * const buffer); + + std::string getCountryCode(void) const; + uint8_t getRating(void) const; +}; + +typedef std::vector ParentalRatingVector; +typedef ParentalRatingVector::iterator ParentalRatingIterator; +typedef ParentalRatingVector::const_iterator ParentalRatingConstIterator; + +class ParentalRatingDescriptor : public Descriptor +{ + protected: + ParentalRatingVector parentalRatings; + + public: + ParentalRatingDescriptor(const uint8_t * const buffer); + ~ParentalRatingDescriptor(void); + + const ParentalRatingVector *getParentalRatings(void) const; +}; + +#endif /* __dvb_descriptor_parental_rating_descriptor_h__ */ diff --git a/lib/dvb_si/partial_transport_stream_descriptor.h b/lib/dvb_si/partial_transport_stream_descriptor.h new file mode 100644 index 00000000..dc91226f --- /dev/null +++ b/lib/dvb_si/partial_transport_stream_descriptor.h @@ -0,0 +1,45 @@ +/* + * $Id: partial_transport_stream_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_partial_transport_stream_descriptor_h__ +#define __dvb_descriptor_partial_transport_stream_descriptor_h__ + +#include "descriptor.h" + +class PartialTransportStreamDescriptor : public Descriptor +{ + protected: + unsigned reserved : 2; + unsigned peakRate : 22; + unsigned reserved2 : 2; + unsigned minimumOverallSmootingRate : 22; + unsigned reserved3 : 2; + unsigned maximumOverallSmoothingBuffer : 14; + + public: + PartialTransportStreamDescriptor(const uint8_t * const buffer); + + uint32_t getPeakRate(void) const; + uint32_t getMinimumOverallSmoothingRate(void) const; + uint16_t getMaximumOverallSmoothingBuffer(void) const; +}; + +#endif /* __dvb_descriptor_partial_transport_stream_descriptor_h__ */ diff --git a/lib/dvb_si/pat.cpp b/lib/dvb_si/pat.cpp new file mode 100644 index 00000000..498f67fb --- /dev/null +++ b/lib/dvb_si/pat.cpp @@ -0,0 +1,81 @@ +/* + * $Id: pat.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +NetworkAssociation::NetworkAssociation(const uint8_t * const buffer) +{ + programNumber = (buffer[0] << 8) | buffer[1]; + reserved = (buffer[2] >> 5) & 0x07; + networkPid = ((buffer[2] & 0x1F) << 8) | buffer[3]; +} + +uint16_t NetworkAssociation::getNetworkPid(void) const +{ + return networkPid; +} + +ProgramAssociation::ProgramAssociation(const uint8_t * const buffer) +{ + programNumber = (buffer[0] << 8) | buffer[1]; + reserved = (buffer[2] >> 5) & 0x07; + programMapPid = ((buffer[2] & 0x1F) << 8) | buffer[3]; +} + +uint16_t ProgramAssociation::getProgramNumber(void) const +{ + return programNumber; +} + +uint16_t ProgramAssociation::getProgramMapPid(void) const +{ + return programMapPid; +} + +ProgramAssociationTable::ProgramAssociationTable(const uint8_t * const buffer) : LongCrcTable(buffer) +{ + for (uint16_t i = 8; i < sectionLength - 1; i += 4) { + if (((buffer[i] << 8) | buffer[i + 1]) == 0) + networks.push_back(new NetworkAssociation(&buffer[i])); + else + programs.push_back(new ProgramAssociation(&buffer[i])); + } +} + +ProgramAssociationTable::~ProgramAssociationTable(void) +{ + for (NetworkAssociationIterator i = networks.begin(); i != networks.end(); ++i) + delete *i; + + for (ProgramAssociationIterator i = programs.begin(); i != programs.end(); ++i) + delete *i; +} + +const NetworkAssociationVector *ProgramAssociationTable::getNetworks(void) const +{ + return &networks; +} + +const ProgramAssociationVector *ProgramAssociationTable::getPrograms(void) const +{ + return &programs; +} + diff --git a/lib/dvb_si/pat.h b/lib/dvb_si/pat.h new file mode 100644 index 00000000..f17586a6 --- /dev/null +++ b/lib/dvb_si/pat.h @@ -0,0 +1,84 @@ +/* + * $Id: pat.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_pat_h__ +#define __dvb_table_pat_h__ + +#include "long_crc_table.h" + +class NetworkAssociation +{ + protected: + unsigned programNumber : 16; + unsigned reserved : 3; + unsigned networkPid : 13; + + public: + NetworkAssociation(const uint8_t * buffer); + + uint16_t getNetworkPid(void) const; +}; + +typedef std::vector NetworkAssociationVector; +typedef NetworkAssociationVector::iterator NetworkAssociationIterator; +typedef NetworkAssociationVector::const_iterator NetworkAssociationConstIterator; + +class ProgramAssociation +{ + protected: + unsigned programNumber : 16; + unsigned reserved : 3; + unsigned programMapPid : 13; + + public: + ProgramAssociation(const uint8_t * buffer); + + uint16_t getProgramNumber(void) const; + uint16_t getProgramMapPid(void) const; +}; + +typedef std::vector ProgramAssociationVector; +typedef ProgramAssociationVector::iterator ProgramAssociationIterator; +typedef ProgramAssociationVector::const_iterator ProgramAssociationConstIterator; + +class ProgramAssociationTable : public LongCrcTable +{ + protected: + NetworkAssociationVector networks; + ProgramAssociationVector programs; + + public: + ProgramAssociationTable(const uint8_t * const buffer); + ~ProgramAssociationTable(void); + + static const enum PacketId PID = PID_PAT; + static const enum TableId TID = TID_PAT; + static const uint32_t TIMEOUT = 1200; + + const NetworkAssociationVector *getNetworks(void) const; + const ProgramAssociationVector *getPrograms(void) const; +}; + +typedef std::vector ProgramAssociationTableVector; +typedef ProgramAssociationTableVector::iterator ProgramAssociationTableIterator; +typedef ProgramAssociationTableVector::const_iterator ProgramAssociationTableConstIterator; + +#endif /* __dvb_table_pat_h__ */ diff --git a/lib/dvb_si/pdc_descriptor.cpp b/lib/dvb_si/pdc_descriptor.cpp new file mode 100644 index 00000000..8a8c61a7 --- /dev/null +++ b/lib/dvb_si/pdc_descriptor.cpp @@ -0,0 +1,34 @@ +/* + * $Id: pdc_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +PdcDescriptor::PdcDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + reserved = (buffer[2] >> 4) & 0x0f; + programmeIdentificationLabel = ((buffer[2] & 0x0f) << 16) | buffer[3] | buffer[4]; +} + +uint32_t PdcDescriptor::getProgrammeIdentificationLabel(void) const +{ + return programmeIdentificationLabel; +} + diff --git a/lib/dvb_si/pdc_descriptor.h b/lib/dvb_si/pdc_descriptor.h new file mode 100644 index 00000000..0c8851b5 --- /dev/null +++ b/lib/dvb_si/pdc_descriptor.h @@ -0,0 +1,39 @@ +/* + * $Id: pdc_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_pdc_descriptor_h__ +#define __dvb_descriptor_pdc_descriptor_h__ + +#include "descriptor.h" + +class PdcDescriptor : public Descriptor +{ + protected: + unsigned reserved : 4; + unsigned programmeIdentificationLabel : 20; + + public: + PdcDescriptor(const uint8_t * const buffer); + + uint32_t getProgrammeIdentificationLabel(void) const; +}; + +#endif /* __dvb_descriptor_pcd_descriptor_h__ */ diff --git a/lib/dvb_si/pmt.cpp b/lib/dvb_si/pmt.cpp new file mode 100644 index 00000000..1c0da43c --- /dev/null +++ b/lib/dvb_si/pmt.cpp @@ -0,0 +1,75 @@ +/* + * $Id: pmt.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ElementaryStreamInfo::ElementaryStreamInfo(const uint8_t * const buffer) +{ + streamType = buffer[0]; + reserved1 = (buffer[1] >> 5) & 0x07; + elementaryPid = ((buffer[1] & 0x1F) << 8) | buffer[2]; + reserved2 = (buffer[3] >> 4) & 0x0F; + esInfoLength = ((buffer[3] & 0x0F) << 8) | buffer[4]; + + for (uint16_t i = 5; i < esInfoLength + 5; i += buffer[i + 1] + 2) + descriptor(&buffer[i]); +} + +uint8_t ElementaryStreamInfo::getType(void) const +{ + return streamType; +} + +uint16_t ElementaryStreamInfo::getPid(void) const +{ + return elementaryPid; +} + +ProgramMapTable::ProgramMapTable(const uint8_t * const buffer) : LongCrcTable(buffer) +{ + reserved4 = (buffer[8] >> 5) & 0x07; + pcrPid = ((buffer[8] & 0x1F) << 8) | buffer[9]; + reserved5 = (buffer[10] >> 4) & 0x0F; + programInfoLength = ((buffer[10] & 0x0F) << 8) | buffer[11]; + + for (uint16_t i = 12; i < programInfoLength + 12; i += buffer[i + 1] + 2) + descriptor(&buffer[i]); + + for (uint16_t i = programInfoLength + 12; i < sectionLength - 1; i += ((buffer[i + 3] & 0x0F) | buffer[i + 4]) + 5) + esInfo.push_back(new ElementaryStreamInfo(&buffer[i])); +} + +uint16_t ProgramMapTable::getPcrPid(void) const +{ + return pcrPid; +} + +const ElementaryStreamInfoVector *ProgramMapTable::getEsInfo(void) const +{ + return &esInfo; +} + +ProgramMapTable::~ProgramMapTable(void) +{ + for (ElementaryStreamInfoIterator i = esInfo.begin(); i != esInfo.end(); ++i) + delete *i; +} + diff --git a/lib/dvb_si/pmt.h b/lib/dvb_si/pmt.h new file mode 100644 index 00000000..781d7d9a --- /dev/null +++ b/lib/dvb_si/pmt.h @@ -0,0 +1,77 @@ +/* + * $Id: pmt.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_pmt_h__ +#define __dvb_table_pmt_h__ + +#include +#include "long_crc_table.h" + +class ElementaryStreamInfo : public DescriptorContainer +{ + protected: + unsigned streamType : 8; + unsigned reserved1 : 3; + unsigned elementaryPid : 13; + unsigned reserved2 : 4; + unsigned esInfoLength : 12; + + public: + ElementaryStreamInfo(const uint8_t * const buffer); + + uint8_t getType(void) const; + uint16_t getPid(void) const; + + friend class CaElementaryStreamInfo; + +}; + +typedef std::vector ElementaryStreamInfoVector; +typedef ElementaryStreamInfoVector::iterator ElementaryStreamInfoIterator; +typedef ElementaryStreamInfoVector::const_iterator ElementaryStreamInfoConstIterator; + +class ProgramMapTable : public LongCrcTable, public DescriptorContainer +{ + protected: + unsigned reserved4 : 3; + unsigned pcrPid : 13; + unsigned reserved5 : 4; + unsigned programInfoLength : 12; + ElementaryStreamInfoVector esInfo; + + public: + ProgramMapTable(const uint8_t * const buffer); + ~ProgramMapTable(void); + + static const enum TableId TID = TID_PMT; + static const uint32_t TIMEOUT = 600; + + uint16_t getPcrPid(void) const; + const ElementaryStreamInfoVector *getEsInfo(void) const; + + friend class CaProgramMapTable; +}; + +typedef std::vector ProgramMapTableVector; +typedef ProgramMapTableVector::iterator ProgramMapTableIterator; +typedef ProgramMapTableVector::const_iterator ProgramMapTableConstIterator; + +#endif /* __dvb_table_pmt_h__ */ diff --git a/lib/dvb_si/private_data_indicator_descriptor.h b/lib/dvb_si/private_data_indicator_descriptor.h new file mode 100644 index 00000000..8e783cd7 --- /dev/null +++ b/lib/dvb_si/private_data_indicator_descriptor.h @@ -0,0 +1,38 @@ +/* + * $Id: private_data_indicator_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_private_data_indicator_descriptor_h__ +#define __dvb_descriptor_private_data_indicator_descriptor_h__ + +#include "descriptor.h" + +class PrivateDataIndicatorDescriptor : public Descriptor +{ + protected: + unsigned privateDataIndicator : 32; + + public: + PrivateDataIndicatorDescriptor(const uint8_t * const buffer); + + uint32_t getPrivateDataIndicator(void) const; +}; + +#endif /* __dvb_descriptor_private_data_indicator_descriptor_h__ */ diff --git a/lib/dvb_si/private_data_specifier_descriptor.cpp b/lib/dvb_si/private_data_specifier_descriptor.cpp new file mode 100644 index 00000000..dedcb712 --- /dev/null +++ b/lib/dvb_si/private_data_specifier_descriptor.cpp @@ -0,0 +1,33 @@ +/* + * $Id: private_data_specifier_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +PrivateDataSpecifierDescriptor::PrivateDataSpecifierDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + privateDataSpecifier = (buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | buffer[5]; +} + +uint32_t PrivateDataSpecifierDescriptor::getPrivateDataSpecifier(void) const +{ + return privateDataSpecifier; +} + diff --git a/lib/dvb_si/private_data_specifier_descriptor.h b/lib/dvb_si/private_data_specifier_descriptor.h new file mode 100644 index 00000000..53b0fb57 --- /dev/null +++ b/lib/dvb_si/private_data_specifier_descriptor.h @@ -0,0 +1,38 @@ +/* + * $Id: private_data_specifier_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_private_data_specifier_descriptor_h__ +#define __dvb_descriptor_private_data_specifier_descriptor_h__ + +#include "descriptor.h" + +class PrivateDataSpecifierDescriptor : public Descriptor +{ + protected: + unsigned privateDataSpecifier : 32; + + public: + PrivateDataSpecifierDescriptor(const uint8_t * const buffer); + + uint32_t getPrivateDataSpecifier(void) const; +}; + +#endif /* __dvb_descriptor_private_data_specifier_descriptor_h__ */ diff --git a/lib/dvb_si/registration_descriptor.h b/lib/dvb_si/registration_descriptor.h new file mode 100644 index 00000000..0f766a16 --- /dev/null +++ b/lib/dvb_si/registration_descriptor.h @@ -0,0 +1,44 @@ +/* + * $Id: registration_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_registration_descriptor_h__ +#define __dvb_descriptor_registration_descriptor_h__ + +#include "descriptor.h" + +typedef std::vector AdditionalIdentificationInfoVector; +typedef AdditionalIdentificationInfoVector::iterator AdditionalIdentificationInfoIterator; +typedef AdditionalIdentificationInfoVector::const_iterator AdditionalIdentificationInfoConstIterator; + +class RegistrationDescriptor : public Descriptor +{ + protected: + unsigned formatIdentifier : 32; + AdditionalIdentificationInfoVector additionalIdentificationInfo; + + private: + RegistrationDescriptor(const uint8_t * const buffer); + + uint32_t getFormatIdentifier(void) const; + const AdditionalIdentificationInfoVector *getAdditionalIdentificationInfo(void) const; +}; + +#endif /* __dvb_descriptor_registration_descriptor_h__ */ diff --git a/lib/dvb_si/satellite_delivery_system_descriptor.cpp b/lib/dvb_si/satellite_delivery_system_descriptor.cpp new file mode 100644 index 00000000..32ff194b --- /dev/null +++ b/lib/dvb_si/satellite_delivery_system_descriptor.cpp @@ -0,0 +1,91 @@ +/* + * $Id: satellite_delivery_system_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +SatelliteDeliverySystemDescriptor::SatelliteDeliverySystemDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + frequency = + ( + ((buffer[2] >> 4) * 10000000) + + ((buffer[2] & 0x0F) * 1000000) + + ((buffer[3] >> 4) * 100000) + + ((buffer[3] & 0x0F) * 10000) + + ((buffer[4] >> 4) * 1000) + + ((buffer[4] & 0x0F) * 100) + + ((buffer[5] >> 4) * 10) + + ((buffer[5] & 0x0F) * 1) + ); + + orbitalPosition = (buffer[6] << 8) | buffer[7]; + westEastFlag = (buffer[8] >> 7) & 0x01; + polarization = (buffer[8] >> 5) & 0x03; + modulation = buffer[8] & 0x1F; + + symbolRate = + ( + ((buffer[9] >> 4) * 1000000) + + ((buffer[9] & 0x0F) * 100000) + + ((buffer[10] >> 4) * 10000) + + ((buffer[10] & 0x0F) * 1000) + + ((buffer[11] >> 4) * 100) + + ((buffer[11] & 0x0F) * 10) + + ((buffer[12] >> 4) * 1) + ); + + fecInner = buffer[12] & 0x0F; +} + +uint32_t SatelliteDeliverySystemDescriptor::getFrequency(void) const +{ + return frequency; +} + +uint16_t SatelliteDeliverySystemDescriptor::getOrbitalPosition(void) const +{ + return orbitalPosition; +} + +uint8_t SatelliteDeliverySystemDescriptor::getWestEastFlag(void) const +{ + return westEastFlag; +} + +uint8_t SatelliteDeliverySystemDescriptor::getPolarization(void) const +{ + return polarization; +} + +uint8_t SatelliteDeliverySystemDescriptor::getModulation(void) const +{ + return modulation; +} + +uint32_t SatelliteDeliverySystemDescriptor::getSymbolRate(void) const +{ + return symbolRate; +} + +uint8_t SatelliteDeliverySystemDescriptor::getFecInner(void) const +{ + return fecInner; +} + diff --git a/lib/dvb_si/satellite_delivery_system_descriptor.h b/lib/dvb_si/satellite_delivery_system_descriptor.h new file mode 100644 index 00000000..b6c2a668 --- /dev/null +++ b/lib/dvb_si/satellite_delivery_system_descriptor.h @@ -0,0 +1,50 @@ +/* + * $Id: satellite_delivery_system_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_satellite_delivery_system_descriptor_h__ +#define __dvb_descriptor_satellite_delivery_system_descriptor_h__ + +#include "descriptor.h" + +class SatelliteDeliverySystemDescriptor : public Descriptor +{ + protected: + unsigned frequency : 32; + unsigned orbitalPosition : 16; + unsigned westEastFlag : 1; + unsigned polarization : 2; + unsigned modulation : 5; + unsigned symbolRate : 28; + unsigned fecInner : 4; + + public: + SatelliteDeliverySystemDescriptor(const uint8_t * const buffer); + + uint32_t getFrequency(void) const; + uint16_t getOrbitalPosition(void) const; + uint8_t getWestEastFlag(void) const; + uint8_t getPolarization(void) const; + uint8_t getModulation(void) const; + uint32_t getSymbolRate(void) const; + uint8_t getFecInner(void) const; +}; + +#endif /* __dvb_descriptor_satellite_delivery_system_descriptor_h__ */ diff --git a/lib/dvb_si/sdt.cpp b/lib/dvb_si/sdt.cpp new file mode 100644 index 00000000..cce81039 --- /dev/null +++ b/lib/dvb_si/sdt.cpp @@ -0,0 +1,87 @@ +/* + * $Id: sdt.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ServiceDescription::ServiceDescription(const uint8_t * const buffer) +{ + serviceId = (buffer[0] << 8) | buffer[1]; + reserved1 = (buffer[2] >> 2) & 0x3F; + eitScheduleFlag = (buffer[2] >> 1) & 0x01; + eitPresentFollowingFlag = buffer[2] & 0x01; + runningStatus = (buffer[3] >> 5) & 0x07; + freeCaMode = (buffer[3] >> 4) & 0x01; + descriptorsLoopLength = ((buffer[3] & 0x0F) << 8) | buffer[4]; + + for (uint16_t i = 5; i < descriptorsLoopLength + 5; i += buffer[i + 1] + 2) + descriptor(&buffer[i]); +} + +uint16_t ServiceDescription::getServiceId(void) const +{ + return serviceId; +} + +uint8_t ServiceDescription::getEitScheduleFlag(void) const +{ + return eitScheduleFlag; +} + +uint8_t ServiceDescription::getEitPresentFollowingFlag(void) const +{ + return eitPresentFollowingFlag; +} + +uint8_t ServiceDescription::getRunningStatus(void) const +{ + return runningStatus; +} + +uint8_t ServiceDescription::getFreeCaMode(void) const +{ + return freeCaMode; +} + +ServiceDescriptionTable::ServiceDescriptionTable(const uint8_t * const buffer) : LongCrcTable (buffer) +{ + originalNetworkId = (buffer[8] << 8) | buffer[9]; + reserved4 = buffer[10]; + + for (uint16_t i = 11; i < sectionLength - 1; i += ((buffer[i + 3] & 0x0F) | buffer[i + 4]) + 5) + description.push_back(new ServiceDescription(&buffer[i])); +} + +ServiceDescriptionTable::~ServiceDescriptionTable(void) +{ + for (ServiceDescriptionIterator i = description.begin(); i != description.end(); ++i) + delete *i; +} + +uint16_t ServiceDescriptionTable::getOriginalNetworkId(void) const +{ + return originalNetworkId; +} + +const ServiceDescriptionVector *ServiceDescriptionTable::getDescriptions(void) const +{ + return &description; +} + diff --git a/lib/dvb_si/sdt.h b/lib/dvb_si/sdt.h new file mode 100644 index 00000000..e1d511be --- /dev/null +++ b/lib/dvb_si/sdt.h @@ -0,0 +1,77 @@ +/* + * $Id: sdt.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002 by Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_sdt_h__ +#define __dvb_table_sdt_h__ + +#include +#include "long_crc_table.h" + +class ServiceDescription : public DescriptorContainer +{ + protected: + unsigned serviceId : 16; + unsigned reserved1 : 6; + unsigned eitScheduleFlag : 1; + unsigned eitPresentFollowingFlag : 1; + unsigned runningStatus : 3; + unsigned freeCaMode : 1; + unsigned descriptorsLoopLength : 12; + + public: + ServiceDescription(const uint8_t * const buffer); + + uint16_t getServiceId(void) const; + uint8_t getEitScheduleFlag(void) const; + uint8_t getEitPresentFollowingFlag(void) const; + uint8_t getRunningStatus(void) const; + uint8_t getFreeCaMode(void) const; +}; + +typedef std::vector ServiceDescriptionVector; +typedef ServiceDescriptionVector::iterator ServiceDescriptionIterator; +typedef ServiceDescriptionVector::const_iterator ServiceDescriptionConstIterator; + +class ServiceDescriptionTable : public LongCrcTable +{ + protected: + unsigned originalNetworkId : 16; + unsigned reserved4 : 8; + ServiceDescriptionVector description; + + public: + ServiceDescriptionTable(const uint8_t * const buffer); + ~ServiceDescriptionTable(void); + + static const enum PacketId PID = PID_SDT; + static const enum TableId TID = TID_SDT_ACTUAL; + static const uint32_t TIMEOUT = 3000; + + uint16_t getOriginalNetworkId(void) const; + uint16_t getTransportStreamId(void) const { return getTableIdExtension(); } + const ServiceDescriptionVector *getDescriptions(void) const; +}; + +typedef std::vector ServiceDescriptionTableVector; +typedef ServiceDescriptionTableVector::iterator ServiceDescriptionTableIterator; +typedef ServiceDescriptionTableVector::const_iterator ServiceDescriptionTableConstIterator; + +#endif /* __dvb_table_sdt_h__ */ diff --git a/lib/dvb_si/service_descriptor.cpp b/lib/dvb_si/service_descriptor.cpp new file mode 100644 index 00000000..a8bffc9c --- /dev/null +++ b/lib/dvb_si/service_descriptor.cpp @@ -0,0 +1,47 @@ +/* + * $Id: service_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ServiceDescriptor::ServiceDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + serviceType = buffer[2]; + serviceProviderNameLength = buffer[3]; + serviceProviderName.assign((char *)&buffer[4], serviceProviderNameLength); + serviceNameLength = buffer[serviceProviderNameLength + 4]; + serviceName.assign((char *)&buffer[serviceProviderNameLength + 5], serviceNameLength); +} + +uint8_t ServiceDescriptor::getServiceType(void) const +{ + return serviceType; +} + +std::string ServiceDescriptor::getServiceProviderName(void) const +{ + return serviceProviderName; +} + +std::string ServiceDescriptor::getServiceName(void) const +{ + return serviceName; +} + diff --git a/lib/dvb_si/service_descriptor.h b/lib/dvb_si/service_descriptor.h new file mode 100644 index 00000000..38ccc839 --- /dev/null +++ b/lib/dvb_si/service_descriptor.h @@ -0,0 +1,44 @@ +/* + * $Id: service_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_service_descriptor_h__ +#define __dvb_descriptor_service_descriptor_h__ + +#include "descriptor.h" + +class ServiceDescriptor : public Descriptor +{ + protected: + unsigned serviceType : 8; + unsigned serviceProviderNameLength : 8; + std::string serviceProviderName; + unsigned serviceNameLength : 8; + std::string serviceName; + + public: + ServiceDescriptor(const uint8_t * const buffer); + + uint8_t getServiceType(void) const; + std::string getServiceProviderName(void) const; + std::string getServiceName(void) const; +}; + +#endif /* __dvb_descriptor_service_descriptor_h__ */ diff --git a/lib/dvb_si/service_list_descriptor.cpp b/lib/dvb_si/service_list_descriptor.cpp new file mode 100644 index 00000000..0e595cb9 --- /dev/null +++ b/lib/dvb_si/service_list_descriptor.cpp @@ -0,0 +1,56 @@ +/* + * $Id: service_list_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ServiceListItem::ServiceListItem(const uint8_t * const buffer) +{ + serviceId = (buffer[0] << 8) | buffer[1]; + serviceType = buffer[2]; +} + +uint16_t ServiceListItem::getServiceId(void) const +{ + return serviceId; +} + +uint8_t ServiceListItem::getServiceType(void) const +{ + return serviceType; +} + +ServiceListDescriptor::ServiceListDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 3) + serviceList.push_back(new ServiceListItem(&buffer[i + 2])); +} + +ServiceListDescriptor::~ServiceListDescriptor(void) +{ + for (ServiceListItemIterator i = serviceList.begin(); i != serviceList.end(); ++i) + delete *i; +} + +const ServiceListItemVector *ServiceListDescriptor::getServiceList(void) const +{ + return &serviceList; +} + diff --git a/lib/dvb_si/service_list_descriptor.h b/lib/dvb_si/service_list_descriptor.h new file mode 100644 index 00000000..bd9c04ff --- /dev/null +++ b/lib/dvb_si/service_list_descriptor.h @@ -0,0 +1,56 @@ +/* + * $Id: service_list_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_service_list_descriptor_h__ +#define __dvb_descriptor_service_list_descriptor_h__ + +#include "descriptor.h" + +class ServiceListItem +{ + protected: + unsigned serviceId : 16; + unsigned serviceType : 8; + + public: + ServiceListItem(const uint8_t * const buffer); + + uint16_t getServiceId(void) const; + uint8_t getServiceType(void) const; +}; + +typedef std::vector ServiceListItemVector; +typedef ServiceListItemVector::iterator ServiceListItemIterator; +typedef ServiceListItemVector::const_iterator ServiceListItemConstIterator; + +class ServiceListDescriptor : public Descriptor +{ + protected: + ServiceListItemVector serviceList; + + public: + ServiceListDescriptor(const uint8_t * const buffer); + ~ServiceListDescriptor(void); + + const ServiceListItemVector *getServiceList(void) const; +}; + +#endif /* __dvb_descriptor_service_list_descriptor_h__ */ diff --git a/lib/dvb_si/service_move_descriptor.cpp b/lib/dvb_si/service_move_descriptor.cpp new file mode 100644 index 00000000..817b480a --- /dev/null +++ b/lib/dvb_si/service_move_descriptor.cpp @@ -0,0 +1,45 @@ +/* + * $Id: service_move_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ServiceMoveDescriptor::ServiceMoveDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + newOriginalNetworkId = (buffer[2] << 8) | buffer[3]; + newTransportStreamId = (buffer[4] << 8) | buffer[5]; + newServiceId = (buffer[6] << 8) | buffer[7]; +} + +uint16_t ServiceMoveDescriptor::getNewOriginalNetworkId(void) const +{ + return newOriginalNetworkId; +} + +uint16_t ServiceMoveDescriptor::getNewTransportStreamId(void) const +{ + return newTransportStreamId; +} + +uint16_t ServiceMoveDescriptor::getNewServiceId(void) const +{ + return newServiceId; +} + diff --git a/lib/dvb_si/service_move_descriptor.h b/lib/dvb_si/service_move_descriptor.h new file mode 100644 index 00000000..55c10c47 --- /dev/null +++ b/lib/dvb_si/service_move_descriptor.h @@ -0,0 +1,42 @@ +/* + * $Id: service_move_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_service_move_descriptor_h__ +#define __dvb_descriptor_service_move_descriptor_h__ + +#include "descriptor.h" + +class ServiceMoveDescriptor : public Descriptor +{ + protected: + unsigned newOriginalNetworkId : 16; + unsigned newTransportStreamId : 16; + unsigned newServiceId : 16; + + public: + ServiceMoveDescriptor(const uint8_t * const buffer); + + uint16_t getNewOriginalNetworkId(void) const; + uint16_t getNewTransportStreamId(void) const; + uint16_t getNewServiceId(void) const; +}; + +#endif /* __dvb_descriptor_service_move_descriptor_h__ */ diff --git a/lib/dvb_si/service_type.h b/lib/dvb_si/service_type.h new file mode 100644 index 00000000..0871af41 --- /dev/null +++ b/lib/dvb_si/service_type.h @@ -0,0 +1,50 @@ +/* + * $Id: service_type.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_id_service_type_h__ +#define __dvb_id_service_type_h__ + +enum ServiceType { + /* 0x00 - 0x10: ETSI EN 300 468 V1.5.1 (2003-01) */ + ST_RESERVED = 0x00, + ST_DIGITAL_TELEVISION_SERVICE = 0x01, + ST_DIGITAL_RADIO_SOUND_SERVICE = 0x02, + ST_TELETEXT_SERVICE = 0x03, + ST_NVOD_REFERENCE_SERVICE = 0x04, + ST_NVOD_TIME_SHIFTED_SERVICE = 0x05, + ST_MOSAIC_SERVICE = 0x06, + ST_PAL_CODED_SIGNAL = 0x07, + ST_SECAM_CODED_SIGNAL = 0x08, + ST_D_D2_MAC = 0x09, + ST_FM_RADIO = 0x0A, + ST_NTSC_CODED_SIGNAL = 0x0B, + ST_DATA_BROADCAST_SERVICE = 0x0C, + ST_COMMON_INTERFACE_RESERVED = 0x0D, + ST_RCS_MAP = 0x0E, + ST_RCS_FLS = 0x0F, + ST_DVB_MHP_SERVICE = 0x10, + /* 0x11 - 0x7F: reserved for future use */ + ST_MULTIFEED = 0x69 + /* 0x80 - 0xFE: user defined */ + /* 0xFF: reserved for future use */ +}; + +#endif /* __dvb_id_service_type_h__ */ diff --git a/lib/dvb_si/short_crc_table.cpp b/lib/dvb_si/short_crc_table.cpp new file mode 100644 index 00000000..bd626ffd --- /dev/null +++ b/lib/dvb_si/short_crc_table.cpp @@ -0,0 +1,36 @@ +/* + * $Id: short_crc_table.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ShortCrcTable::ShortCrcTable(const uint8_t * const buffer) : ShortTable(buffer) +{ + crc32 = (buffer[sectionLength - 1] << 24) | + (buffer[sectionLength + 0] << 16) | + (buffer[sectionLength + 1] << 8) | + (buffer[sectionLength + 2]); +} + +uint32_t ShortCrcTable::getCrc32(void) const +{ + return crc32; +} + diff --git a/lib/dvb_si/short_crc_table.h b/lib/dvb_si/short_crc_table.h new file mode 100644 index 00000000..d9ef6fd8 --- /dev/null +++ b/lib/dvb_si/short_crc_table.h @@ -0,0 +1,44 @@ +/* + * $Id: short_crc_table.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_short_crc_table_h__ +#define __dvb_table_short_crc_table_h__ + +#include "short_table.h" + +class ShortCrcTable : public ShortTable +{ + protected: + unsigned crc32 : 32; + + public: + ShortCrcTable(const uint8_t * const buffer); + + static const uint8_t CRC32 = 1; + + uint32_t getCrc32(void) const; +}; + +typedef std::vector ShortCrcTableVector; +typedef ShortCrcTableVector::iterator ShortCrcTableIterator; +typedef ShortCrcTableVector::const_iterator ShortCrcTableConstIterator; + +#endif /* __dvb_table_short_crc_table_h__ */ diff --git a/lib/dvb_si/short_event_descriptor.cpp b/lib/dvb_si/short_event_descriptor.cpp new file mode 100644 index 00000000..e5fffe89 --- /dev/null +++ b/lib/dvb_si/short_event_descriptor.cpp @@ -0,0 +1,47 @@ +/* + * $Id: short_event_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ShortEventDescriptor::ShortEventDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + iso639LanguageCode.assign((char *)&buffer[2], 3); + eventNameLength = buffer[5]; + eventName.assign((char *)&buffer[6], eventNameLength); + textLength = buffer[6 + eventNameLength]; + text.assign((char *)&buffer[7 + eventNameLength], textLength); +} + +std::string ShortEventDescriptor::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +std::string ShortEventDescriptor::getEventName(void) const +{ + return eventName; +} + +std::string ShortEventDescriptor::getText(void) const +{ + return text; +} + diff --git a/lib/dvb_si/short_event_descriptor.h b/lib/dvb_si/short_event_descriptor.h new file mode 100644 index 00000000..e421cdea --- /dev/null +++ b/lib/dvb_si/short_event_descriptor.h @@ -0,0 +1,44 @@ +/* + * $Id: short_event_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_short_event_descriptor_h__ +#define __dvb_descriptor_short_event_descriptor_h__ + +#include "descriptor.h" + +class ShortEventDescriptor : public Descriptor +{ + protected: + std::string iso639LanguageCode; + unsigned eventNameLength : 8; + std::string eventName; + unsigned textLength : 8; + std::string text; + + public: + ShortEventDescriptor(const uint8_t * const buffer); + + std::string getIso639LanguageCode(void) const; + std::string getEventName(void) const; + std::string getText(void) const; +}; + +#endif /* __dvb_descriptor_short_event_descriptor_h__ */ diff --git a/lib/dvb_si/short_smoothing_buffer_descriptor.h b/lib/dvb_si/short_smoothing_buffer_descriptor.h new file mode 100644 index 00000000..66c0802b --- /dev/null +++ b/lib/dvb_si/short_smoothing_buffer_descriptor.h @@ -0,0 +1,41 @@ +/* + * $Id: short_smoothing_buffer_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_short_smoothing_buffer_descriptor_h__ +#define __dvb_descriptor_short_smoothing_buffer_descriptor_h__ + +#include "descriptor.h" + +class ShortSmoothingBufferDescriptor : public Descriptor +{ + protected: + unsigned sbSize : 2; + unsigned sbLeakRate : 6; + std::vector reserved; + + public: + ShortSmoothingBufferDescriptor(const uint8_t * const buffer); + + uint8_t getSbSize(void) const; + uint8_t getSbLeakRate(void) const; +}; + +#endif /* __dvb_descriptor_short_smoothing_buffer_descriptor_h__ */ diff --git a/lib/dvb_si/short_table.cpp b/lib/dvb_si/short_table.cpp new file mode 100644 index 00000000..b162fe99 --- /dev/null +++ b/lib/dvb_si/short_table.cpp @@ -0,0 +1,47 @@ +/* + * $Id: short_table.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +ShortTable::ShortTable(const uint8_t * const buffer) +{ + tableId = buffer[0]; + sectionSyntaxIndicator = (buffer[1] >> 7) & 0x01; + reserved1 = (buffer[1] >> 6) & 0x01; + reserved2 = (buffer[1] >> 4) & 0x03; + sectionLength = ((buffer[1] & 0x0F) << 8) | buffer[2]; +} + +uint8_t ShortTable::getTableId(void) const +{ + return tableId; +} + +uint8_t ShortTable::getSectionSyntaxIndicator(void) const +{ + return sectionSyntaxIndicator; +} + +uint16_t ShortTable::getSectionLength(void) const +{ + return sectionLength; +} + diff --git a/lib/dvb_si/short_table.h b/lib/dvb_si/short_table.h new file mode 100644 index 00000000..743891f8 --- /dev/null +++ b/lib/dvb_si/short_table.h @@ -0,0 +1,58 @@ +/* + * $Id: short_table.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_short_table_h__ +#define __dvb_table_short_table_h__ + +#include +#include +#include +#include + +class ShortTable +{ + protected: + unsigned tableId : 8; + unsigned sectionSyntaxIndicator : 1; + unsigned reserved1 : 1; + unsigned reserved2 : 2; + unsigned sectionLength : 12; + + public: + ShortTable(const uint8_t * const buffer); + + static const uint8_t CRC32 = 0; + static const uint16_t LENGTH = 1024; + static const enum PacketId PID = PID_RESERVED; + static const uint8_t SYNTAX = 0; + static const enum TableId TID = TID_RESERVED; + static const uint32_t TIMEOUT = 0; + + uint8_t getTableId(void) const; + uint8_t getSectionSyntaxIndicator(void) const; + uint16_t getSectionLength(void) const; +}; + +typedef std::vector ShortTableVector; +typedef ShortTableVector::iterator ShortTableIterator; +typedef ShortTableVector::const_iterator ShortTableConstIterator; + +#endif /* __dvb_table_short_table_h__ */ diff --git a/lib/dvb_si/smoothing_buffer_descriptor.h b/lib/dvb_si/smoothing_buffer_descriptor.h new file mode 100644 index 00000000..68ccdde5 --- /dev/null +++ b/lib/dvb_si/smoothing_buffer_descriptor.h @@ -0,0 +1,42 @@ +/* + * $Id: smoothing_buffer_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_smoothing_buffer_descriptor_h__ +#define __dvb_descriptor_smoothing_buffer_descriptor_h__ + +#include "descriptor.h" + +class SmoothingBufferDescriptor : public Descriptor +{ + protected: + unsigned reserved : 2; + unsigned sbLeakRate : 22; + unsigned reserved2 : 2; + unsigned sbSize : 22; + + public: + SmoothingBufferDescriptor(const uint8_t * const buffer); + + uint32_t getSbLeakRate(void) const; + uint32_t getSbSize(void) const; +}; + +#endif /* __dvb_descriptor_smoothing_buffer_descriptor_h__ */ diff --git a/lib/dvb_si/std_descriptor.h b/lib/dvb_si/std_descriptor.h new file mode 100644 index 00000000..a216b04f --- /dev/null +++ b/lib/dvb_si/std_descriptor.h @@ -0,0 +1,39 @@ +/* + * $Id: std_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_std_descriptor_h__ +#define __dvb_descriptor_std_descriptor_h__ + +#include "descriptor.h" + +class StdDescriptor : public Descriptor +{ + protected: + unsigned reserved : 7; + unsigned leakValidFlag : 1; + + public: + StdDescriptor(const uint8_t * const buffer); + + uint8_t getLeakValidFlag(void) const; +}; + +#endif /* __dvb_descriptor_std_descriptor_h__ */ diff --git a/lib/dvb_si/stream_identifier_descriptor.cpp b/lib/dvb_si/stream_identifier_descriptor.cpp new file mode 100644 index 00000000..55956997 --- /dev/null +++ b/lib/dvb_si/stream_identifier_descriptor.cpp @@ -0,0 +1,33 @@ +/* + * $Id: stream_identifier_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +StreamIdentifierDescriptor::StreamIdentifierDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + componentTag = buffer[2]; +} + +uint8_t StreamIdentifierDescriptor::getComponentTag(void) const +{ + return componentTag; +} + diff --git a/lib/dvb_si/stream_identifier_descriptor.h b/lib/dvb_si/stream_identifier_descriptor.h new file mode 100644 index 00000000..4a37b4e7 --- /dev/null +++ b/lib/dvb_si/stream_identifier_descriptor.h @@ -0,0 +1,38 @@ +/* + * $Id: stream_identifier_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_stream_identifier_descriptor_h__ +#define __dvb_descriptor_stream_identifier_descriptor_h__ + +#include "descriptor.h" + +class StreamIdentifierDescriptor : public Descriptor +{ + protected: + unsigned componentTag : 8; + + public: + StreamIdentifierDescriptor(const uint8_t * const buffer); + + uint8_t getComponentTag(void) const; +}; + +#endif /* __dvb_descriptor_stream_identifier_descriptor_h__ */ diff --git a/lib/dvb_si/stream_type.h b/lib/dvb_si/stream_type.h new file mode 100644 index 00000000..d9f68dd6 --- /dev/null +++ b/lib/dvb_si/stream_type.h @@ -0,0 +1,51 @@ +/* + * $Id: stream_type.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_id_stream_type_h__ +#define __dvb_id_stream_type_h__ + +enum StreamType { + STT_RESERVED = 0x00, + STT_MPEG1_VIDEO = 0x01, + STT_MPEG2_VIDEO = 0x02, + STT_MPEG1_AUDIO = 0x03, + STT_MPEG2_AUDIO = 0x04, + STT_MPEG2_SECTIONS = 0x05, + STT_MPEG2_PES = 0x06, + STT_MHEG = 0x07, + STT_DSM_CC = 0x08, + STT_TREC_H_222_1 = 0x09, + STT_13818_6_A = 0x0A, + STT_13818_6_B = 0x0B, + STT_13818_6_C = 0x0C, + STT_13818_6_D = 0x0D, + STT_AUXILIARY = 0x0E, + STT_ADTS_AUDIO = 0x0F, + STT_MPEG4_VIDEO = 0x10, + STT_MPEG4_AUDIO = 0x11, + STT_MPEG4_PES = 0x12, + STT_MPEG4_SECTIONS = 0x13, + STT_SYNC_DOWNLOAD_PROT = 0x14 + /* 0x15 - 0x7F: ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved */ + /* 0x80 - 0xFF: User Private */ +}; + +#endif /* __dvb_id_stream_type_h__ */ diff --git a/lib/dvb_si/stuffing_descriptor.cpp b/lib/dvb_si/stuffing_descriptor.cpp new file mode 100644 index 00000000..f672fbfe --- /dev/null +++ b/lib/dvb_si/stuffing_descriptor.cpp @@ -0,0 +1,29 @@ +/* + * $Id: stuffing_descriptor.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +StuffingDescriptor::StuffingDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; ++i) + stuffingByte.push_back(buffer[i + 2]); +} + diff --git a/lib/dvb_si/stuffing_descriptor.h b/lib/dvb_si/stuffing_descriptor.h new file mode 100644 index 00000000..31486c2f --- /dev/null +++ b/lib/dvb_si/stuffing_descriptor.h @@ -0,0 +1,36 @@ +/* + * $Id: stuffing_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_stuffing_descriptor_h__ +#define __dvb_descriptor_stuffing_descriptor_h__ + +#include "descriptor.h" + +class StuffingDescriptor : public Descriptor +{ + protected: + std::vector stuffingByte; + + public: + StuffingDescriptor(const uint8_t * const buffer); +}; + +#endif /* __dvb_descriptor_stuffing_descriptor_h__ */ diff --git a/lib/dvb_si/subtitling_descriptor.cpp b/lib/dvb_si/subtitling_descriptor.cpp new file mode 100644 index 00000000..c2bdfb9e --- /dev/null +++ b/lib/dvb_si/subtitling_descriptor.cpp @@ -0,0 +1,68 @@ +/* + * $Id: subtitling_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +Subtitling::Subtitling(const uint8_t * const buffer) +{ + iso639LanguageCode.assign((char *)&buffer[0], 3); + subtitlingType = buffer[3]; + compositionPageId = (buffer[4] << 8) | buffer[5]; + ancillaryPageId = (buffer[6] << 8) | buffer[7]; +} + +std::string Subtitling::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +uint8_t Subtitling::getSubtitlingType(void) const +{ + return subtitlingType; +} + +uint16_t Subtitling::getCompositionPageId(void) const +{ + return compositionPageId; +} + +uint16_t Subtitling::getAncillaryPageId(void) const +{ + return ancillaryPageId; +} + +SubtitlingDescriptor::SubtitlingDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 8) + subtitlings.push_back(new Subtitling(&buffer[i + 2])); +} + +SubtitlingDescriptor::~SubtitlingDescriptor(void) +{ + for (SubtitlingIterator i = subtitlings.begin(); i != subtitlings.end(); ++i) + delete *i; +} + +const SubtitlingVector *SubtitlingDescriptor::getSubtitlings(void) const +{ + return &subtitlings; +} + diff --git a/lib/dvb_si/subtitling_descriptor.h b/lib/dvb_si/subtitling_descriptor.h new file mode 100644 index 00000000..5232dbdb --- /dev/null +++ b/lib/dvb_si/subtitling_descriptor.h @@ -0,0 +1,60 @@ +/* + * $Id: subtitling_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_subtitling_descriptor_h__ +#define __dvb_descriptor_subtitling_descriptor_h__ + +#include "descriptor.h" + +class Subtitling +{ + protected: + std::string iso639LanguageCode; + unsigned subtitlingType : 8; + unsigned compositionPageId : 16; + unsigned ancillaryPageId : 16; + + public: + Subtitling(const uint8_t * const buffer); + + std::string getIso639LanguageCode(void) const; + uint8_t getSubtitlingType(void) const; + uint16_t getCompositionPageId(void) const; + uint16_t getAncillaryPageId(void) const; +}; + +typedef std::vector SubtitlingVector; +typedef SubtitlingVector::iterator SubtitlingIterator; +typedef SubtitlingVector::const_iterator SubtitlingConstIterator; + +class SubtitlingDescriptor : public Descriptor +{ + protected: + SubtitlingVector subtitlings; + + public: + SubtitlingDescriptor(const uint8_t * const buffer); + ~SubtitlingDescriptor(void); + + const SubtitlingVector *getSubtitlings(void) const; +}; + +#endif /* __dvb_descriptor_subtitling_descriptor_h__ */ diff --git a/lib/dvb_si/system_clock_descriptor.h b/lib/dvb_si/system_clock_descriptor.h new file mode 100644 index 00000000..2216cef5 --- /dev/null +++ b/lib/dvb_si/system_clock_descriptor.h @@ -0,0 +1,44 @@ +/* + * $Id: system_clock_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_system_clock_descriptor_h__ +#define __dvb_descriptor_system_clock_descriptor_h__ + +#include "descriptor.h" + +class SystemClockDescriptor : public Descriptor +{ + protected: + unsigned externalClockReferenceIndicator : 1; + unsigned reserved : 1; + unsigned clockAccuracyInteger : 6; + unsigned clockAccuracyExponent : 3; + unsigned reserved2 : 5; + + public: + SystemClockDescriptor(const uint8_t * const buffer); + + uint8_t getExternalClockReferenceIndicator(void) const; + uint8_t getClockAccuracyInteger(void) const; + uint8_t getClockAccuracyExponent(void) const; +}; + +#endif /* __dvb_descriptor_system_clock_descriptor_h__ */ diff --git a/lib/dvb_si/table_id.h b/lib/dvb_si/table_id.h new file mode 100644 index 00000000..39e005c1 --- /dev/null +++ b/lib/dvb_si/table_id.h @@ -0,0 +1,123 @@ +/* + * $Id: table_id.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_id_table_id_h__ +#define __dvb_id_table_id_h__ + +enum TableId { + /* ISO/IEC 13818-1, ITU T-REC H.222.0 */ + TID_PAT = 0x00, /* program_association_section */ + TID_CAT = 0x01, /* conditional_access_section */ + TID_PMT = 0x02, /* TS_program_map_section */ + TID_TSDT = 0x03, /* TS_description_section */ + TID_SDT = 0x04, /* ISO_IEC_14496_scene_description_section */ + TID_ODT = 0x05, /* ISO_IEC_14496_object_descriptor_section */ + + /* 0x06 - 0x09: ITU-T Rec. H.222.0 | ISO/IEC 13818-1 reserved */ + + /* 0x0A - 0x0D: ISO/IEC 13818-6 */ + TID_DSMCC_MULTIPROTOCOL = 0x0A, /* Multiprotocol */ + TID_DSMCC_MSG_HEADER = 0x0B, /* DSM-CC Messages Header (U-N) */ + TID_DSMCC_DESCR_LOOP = 0x0C, /* DSM-CC Descriptors Loop */ + TID_DSMCC_TBD = 0x0D, /* TBD */ + + /* 0x0E - 0x37: ITU-T Rec. H.222.0 | ISO/IEC 13818-1 reserved */ + + /* 0x38 - 0x3F: Defined in ISO/IEC 13818-6 */ + TID_DSMCC_DL_MESSAGE = 0x3B, /* DSM-CC Download Message */ + TID_DSMCC_DL_DATA = 0x3C, /* DSM-CC Download Data */ + TID_DSMCC_DL_EVENT = 0x3D, /* DSM-CC Download Event */ + + /* 0x40 - 0x7F: ETSI EN 300 468 V1.5.1 (2003-01) */ + TID_NIT_ACTUAL = 0x40, /* network_information_section - actual_network */ + TID_NIT_OTHER = 0x41, /* network_information_section - other_network */ + TID_SDT_ACTUAL = 0x42, /* service_description_section - actual_transport_stream */ + TID_SDT_OTHER = 0x46, /* service_description_section - other_transport_stream */ + TID_BAT = 0x4A, /* bouquet_association_section */ + TID_EIT_ACTUAL = 0x4E, /* event_information_section - actual_transport_stream, present/following */ + TID_EIT_OTHER = 0x4F, /* event_information_section - other_transport_stream, present/following */ + TID_EIT_ACTUAL_SCHED_0 = 0x50, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_1 = 0x51, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_2 = 0x52, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_3 = 0x53, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_4 = 0x54, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_5 = 0x55, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_6 = 0x56, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_7 = 0x57, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_8 = 0x58, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_9 = 0x59, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_A = 0x5A, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_B = 0x5B, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_C = 0x5C, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_D = 0x5D, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_E = 0x5E, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_ACTUAL_SCHED_F = 0x5F, /* event_information_section - actual_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_0 = 0x60, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_1 = 0x61, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_2 = 0x62, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_3 = 0x63, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_4 = 0x64, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_5 = 0x65, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_6 = 0x66, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_7 = 0x67, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_8 = 0x68, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_9 = 0x69, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_A = 0x6A, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_B = 0x6B, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_C = 0x6C, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_D = 0x6D, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_E = 0x6E, /* event_information_section - other_transport_stream, schedule */ + TID_EIT_OTHER_SCHED_F = 0x6F, /* event_information_section - other_transport_stream, schedule */ + TID_TDT = 0x70, /* time_date_section */ + TID_RST = 0x71, /* running_status_section */ + TID_ST = 0x72, /* stuffing_section */ + TID_TOT = 0x73, /* time_offset_section */ + TID_AIT = 0x74, /* application_information_section */ + TID_DIT = 0x7E, /* discontinuity_information_section */ + TID_SIT = 0x7F, /* selection_information_section */ + + /* 0x80 - 0x8F: ETSI ETR 289 ed.1 (1996-10) */ + TID_CAMT_ECM_0 = 0x80, + TID_CAMT_ECM_1 = 0x81, + TID_CAMT_PRIVATE_0 = 0x82, + TID_CAMT_PRIVATE_1 = 0x83, + TID_CAMT_PRIVATE_2 = 0x84, + TID_CAMT_PRIVATE_3 = 0x85, + TID_CAMT_PRIVATE_4 = 0x86, + TID_CAMT_PRIVATE_5 = 0x87, + TID_CAMT_PRIVATE_6 = 0x88, + TID_CAMT_PRIVATE_7 = 0x89, + TID_CAMT_PRIVATE_8 = 0x8A, + TID_CAMT_PRIVATE_9 = 0x8B, + TID_CAMT_PRIVATE_A = 0x8C, + TID_CAMT_PRIVATE_B = 0x8D, + TID_CAMT_PRIVATE_C = 0x8E, + TID_CAMT_PRIVATE_D = 0x8F, + + /* 0x90 - 0xFE: PRIVATE */ + TID_TOC = 0x91, + TID_HIT = 0x92, + + /* 0xFF: ISO RESERVED */ + TID_RESERVED = 0xFF +}; + +#endif /* __dvb_id_table_id_h__ */ diff --git a/lib/dvb_si/target_background_grid_descriptor.cpp b/lib/dvb_si/target_background_grid_descriptor.cpp new file mode 100644 index 00000000..921157f1 --- /dev/null +++ b/lib/dvb_si/target_background_grid_descriptor.cpp @@ -0,0 +1,45 @@ +/* + * $Id: target_background_grid_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +TargetBackgroundGridDescriptor::TargetBackgroundGridDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + horizontalSize = ((buffer[2] << 8) | (buffer[3] & 0xF3)) >> 2; + verticalSize = (((buffer[3] & 0x03) << 16) | (buffer[4] << 8) | (buffer[5] & 0xF0)) >> 4; + aspectRatioInformation = buffer[5] & 0x0F; +} + +uint16_t TargetBackgroundGridDescriptor::getHorizontalSize(void) const +{ + return horizontalSize; +} + +uint16_t TargetBackgroundGridDescriptor::getVerticalSize(void) const +{ + return verticalSize; +} + +uint8_t TargetBackgroundGridDescriptor::getAspectRatioInformation(void) const +{ + return aspectRatioInformation; +} + diff --git a/lib/dvb_si/target_background_grid_descriptor.h b/lib/dvb_si/target_background_grid_descriptor.h new file mode 100644 index 00000000..38ce5182 --- /dev/null +++ b/lib/dvb_si/target_background_grid_descriptor.h @@ -0,0 +1,42 @@ +/* + * $Id: target_background_grid_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_target_background_grid_descriptor_h__ +#define __dvb_descriptor_target_background_grid_descriptor_h__ + +#include "descriptor.h" + +class TargetBackgroundGridDescriptor : public Descriptor +{ + protected: + unsigned horizontalSize : 14; + unsigned verticalSize : 14; + unsigned aspectRatioInformation : 4; + + public: + TargetBackgroundGridDescriptor(const uint8_t * const buffer); + + uint16_t getHorizontalSize(void) const; + uint16_t getVerticalSize(void) const; + uint8_t getAspectRatioInformation(void) const; +}; + +#endif /* __dvb_descriptor_target_background_grid_descriptor_h__ */ diff --git a/lib/dvb_si/tdt.cpp b/lib/dvb_si/tdt.cpp new file mode 100644 index 00000000..dcbd3e38 --- /dev/null +++ b/lib/dvb_si/tdt.cpp @@ -0,0 +1,39 @@ +/* + * $Id: tdt.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +TimeAndDateTable::TimeAndDateTable(const uint8_t * const buffer) : ShortTable(buffer) +{ + utcTimeMjd = (buffer[3] << 8) | buffer[4]; + utcTimeBcd = (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; +} + +uint16_t TimeAndDateTable::getUtcTimeMjd(void) const +{ + return utcTimeMjd; +} + +uint32_t TimeAndDateTable::getUtcTimeBcd(void) const +{ + return utcTimeBcd; +} + diff --git a/lib/dvb_si/tdt.h b/lib/dvb_si/tdt.h new file mode 100644 index 00000000..ef4a0ab6 --- /dev/null +++ b/lib/dvb_si/tdt.h @@ -0,0 +1,48 @@ +/* + * $Id: tdt.h,v 1.1 2003-10-17 15:36:39 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_tdt_h__ +#define __dvb_table_tdt_h__ + +#include "short_table.h" + +class TimeAndDateTable : public ShortTable +{ + protected: + unsigned utcTimeMjd : 16; + unsigned utcTimeBcd : 24; + + public: + TimeAndDateTable(const uint8_t * const buffer); + + static const enum PacketId PID = PID_TDT; + static const enum TableId TID = TID_TDT; + static const uint32_t TIMEOUT = 36000; + + uint16_t getUtcTimeMjd(void) const; + uint32_t getUtcTimeBcd(void) const; +}; + +typedef std::vector TimeAndDateTableVector; +typedef TimeAndDateTableVector::iterator TimeAndDateTableIterator; +typedef TimeAndDateTableVector::const_iterator TimeAndDateTableConstIterator; + +#endif /* __dvb_table_tdt_h__ */ diff --git a/lib/dvb_si/telephone_descriptor.cpp b/lib/dvb_si/telephone_descriptor.cpp new file mode 100644 index 00000000..38492155 --- /dev/null +++ b/lib/dvb_si/telephone_descriptor.cpp @@ -0,0 +1,83 @@ +/* + * $Id: telephone_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +TelephoneDescriptor::TelephoneDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + reserved = (buffer[2] >> 6) & 0x03; + foreignAvailability = (buffer[2] >> 5) & 0x01; + connectionType = buffer[2] & 0x1f; + reserved2 = (buffer[3] >> 7) & 0x01; + countryPrefixLength = (buffer[3] >> 5) & 0x03; + internationalAreaCodeLength = (buffer[3] >> 2) & 0x07; + operatorCodeLength = buffer[3] & 0x03; + reserved3 = (buffer[4] >> 7) & 0x01; + nationalAreaCodeLength = (buffer[4] >> 4) & 0x07; + coreNumberLength = buffer[4] & 0x0f; + + uint16_t offset = 5; + countryPrefix.assign((char *)&buffer[offset], countryPrefixLength); + offset += countryPrefixLength; + internationalAreaCode.assign((char *)&buffer[offset], internationalAreaCodeLength); + offset += internationalAreaCodeLength; + operatorCode.assign((char *)&buffer[offset], operatorCodeLength); + offset += operatorCodeLength; + nationalAreaCode.assign((char *)&buffer[offset], nationalAreaCodeLength); + offset += nationalAreaCodeLength; + coreNumber.assign((char *)&buffer[offset], coreNumberLength); +} + +uint8_t TelephoneDescriptor::getForeignAvailability(void) const +{ + return foreignAvailability; +} + +uint8_t TelephoneDescriptor::getConnectionType(void) const +{ + return connectionType; +} + +std::string TelephoneDescriptor::getCountryPrefix(void) const +{ + return countryPrefix; +} + +std::string TelephoneDescriptor::getInternationalAreaCode(void) const +{ + return internationalAreaCode; +} + +std::string TelephoneDescriptor::getOperatorCode(void) const +{ + return operatorCode; +} + +std::string TelephoneDescriptor::getNationalAreaCode(void) const +{ + return nationalAreaCode; +} + +std::string TelephoneDescriptor::getCoreNumber(void) const +{ + return coreNumber; +} + diff --git a/lib/dvb_si/telephone_descriptor.h b/lib/dvb_si/telephone_descriptor.h new file mode 100644 index 00000000..c64bc2ca --- /dev/null +++ b/lib/dvb_si/telephone_descriptor.h @@ -0,0 +1,58 @@ +/* + * $Id: telephone_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_telephone_descriptor_h__ +#define __dvb_descriptor_telephone_descriptor_h__ + +#include "descriptor.h" + +class TelephoneDescriptor : public Descriptor +{ + protected: + unsigned reserved : 2; + unsigned foreignAvailability : 1; + unsigned connectionType : 5; + unsigned reserved2 : 1; + unsigned countryPrefixLength : 2; + unsigned internationalAreaCodeLength : 3; + unsigned operatorCodeLength : 2; + unsigned reserved3 : 1; + unsigned nationalAreaCodeLength : 3; + unsigned coreNumberLength : 4; + std::string countryPrefix; + std::string internationalAreaCode; + std::string operatorCode; + std::string nationalAreaCode; + std::string coreNumber; + + public: + TelephoneDescriptor(const uint8_t * const buffer); + + uint8_t getForeignAvailability(void) const; + uint8_t getConnectionType(void) const; + std::string getCountryPrefix(void) const; + std::string getInternationalAreaCode(void) const; + std::string getOperatorCode(void) const; + std::string getNationalAreaCode(void) const; + std::string getCoreNumber(void) const; +}; + +#endif /* __dvb_descriptor_telephone_descriptor_h__ */ diff --git a/lib/dvb_si/teletext_descriptor.cpp b/lib/dvb_si/teletext_descriptor.cpp new file mode 100644 index 00000000..dcbb4991 --- /dev/null +++ b/lib/dvb_si/teletext_descriptor.cpp @@ -0,0 +1,27 @@ +/* + * $Id: teletext_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +TeletextDescriptor::TeletextDescriptor(const uint8_t * const buffer) : VbiTeletextDescriptor(buffer) +{ +} + diff --git a/lib/dvb_si/teletext_descriptor.h b/lib/dvb_si/teletext_descriptor.h new file mode 100644 index 00000000..d95d5adb --- /dev/null +++ b/lib/dvb_si/teletext_descriptor.h @@ -0,0 +1,33 @@ +/* + * $Id: teletext_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_teletext_descriptor_h__ +#define __dvb_descriptor_teletext_descriptor_h__ + +#include "vbi_teletext_descriptor.h" + +class TeletextDescriptor : public VbiTeletextDescriptor +{ + public: + TeletextDescriptor(const uint8_t * const buffer); +}; + +#endif /* __dvb_descriptor_teletext_descriptor_h__ */ diff --git a/lib/dvb_si/terrestrial_delivery_system_descriptor.cpp b/lib/dvb_si/terrestrial_delivery_system_descriptor.cpp new file mode 100644 index 00000000..bddc9d7f --- /dev/null +++ b/lib/dvb_si/terrestrial_delivery_system_descriptor.cpp @@ -0,0 +1,83 @@ +/* + * $Id: terrestrial_delivery_system_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +TerrestrialDeliverySystemDescriptor::TerrestrialDeliverySystemDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + centreFrequency = (buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | buffer[5]; + bandwidth = (buffer[6] >> 5) & 0x07; + reserved = buffer[6] & 0x1f; + constellation = (buffer[7] >> 6) & 0x03; + hierarchyInformation = (buffer[7] >> 3) & 0x07; + codeRateHpStream = buffer[7] & 0x07; + codeRateLpStream = (buffer[8] >> 5) & 0x07; + guardInterval = (buffer[8] >> 3) & 0x03; + transmissionMode = (buffer[8] >> 1) & 0x03; + otherFrequencyFlag = buffer[8] & 0x01; + reserved2 = (buffer[9] << 24) | (buffer[10] << 16) | (buffer[11] << 8) | buffer[12]; +} + +uint32_t TerrestrialDeliverySystemDescriptor::getCentreFrequency(void) const +{ + return centreFrequency; +} + +uint8_t TerrestrialDeliverySystemDescriptor::getBandwidth(void) const +{ + return bandwidth; +} + +uint8_t TerrestrialDeliverySystemDescriptor::getConstellation(void) const +{ + return constellation; +} + +uint8_t TerrestrialDeliverySystemDescriptor::getHierarchyInformation(void) const +{ + return hierarchyInformation; +} + +uint8_t TerrestrialDeliverySystemDescriptor::getCodeRateHpStream(void) const +{ + return codeRateHpStream; +} + +uint8_t TerrestrialDeliverySystemDescriptor::getCodeRateLpStream(void) const +{ + return codeRateLpStream; +} + +uint8_t TerrestrialDeliverySystemDescriptor::getGuardInterval(void) const +{ + return guardInterval; +} + +uint8_t TerrestrialDeliverySystemDescriptor::getTransmissionMode(void) const +{ + return transmissionMode; +} + +uint8_t TerrestrialDeliverySystemDescriptor::getOtherFrequencyFlag(void) const +{ + return otherFrequencyFlag; +} + diff --git a/lib/dvb_si/terrestrial_delivery_system_descriptor.h b/lib/dvb_si/terrestrial_delivery_system_descriptor.h new file mode 100644 index 00000000..9bbe8178 --- /dev/null +++ b/lib/dvb_si/terrestrial_delivery_system_descriptor.h @@ -0,0 +1,56 @@ +/* + * $Id: terrestrial_delivery_system_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_terrestrial_delivery_system_descriptor_h__ +#define __dvb_descriptor_terrestrial_delivery_system_descriptor_h__ + +#include "descriptor.h" + +class TerrestrialDeliverySystemDescriptor : public Descriptor +{ + protected: + unsigned centreFrequency : 32; + unsigned bandwidth : 3; + unsigned reserved : 5; + unsigned constellation : 2; + unsigned hierarchyInformation : 3; + unsigned codeRateHpStream : 3; + unsigned codeRateLpStream : 3; + unsigned guardInterval : 2; + unsigned transmissionMode : 2; + unsigned otherFrequencyFlag : 1; + unsigned reserved2 : 32; + + public: + TerrestrialDeliverySystemDescriptor(const uint8_t * const buffer); + + uint32_t getCentreFrequency(void) const; + uint8_t getBandwidth(void) const; + uint8_t getConstellation(void) const; + uint8_t getHierarchyInformation(void) const; + uint8_t getCodeRateHpStream(void) const; + uint8_t getCodeRateLpStream(void) const; + uint8_t getGuardInterval(void) const; + uint8_t getTransmissionMode(void) const; + uint8_t getOtherFrequencyFlag(void) const; +}; + +#endif /* __dvb_descriptor_terrestrial_delivery_system_descriptor_h__ */ diff --git a/lib/dvb_si/time_shifted_event_descriptor.h b/lib/dvb_si/time_shifted_event_descriptor.h new file mode 100644 index 00000000..bd9a1b66 --- /dev/null +++ b/lib/dvb_si/time_shifted_event_descriptor.h @@ -0,0 +1,40 @@ +/* + * $Id: time_shifted_event_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_time_shifted_event_descriptor_h__ +#define __dvb_descriptor_time_shifted_event_descriptor_h__ + +#include "descriptor.h" + +class TimeShiftedEventDescriptor : public Descriptor +{ + protected: + unsigned referenceServiceId : 16; + unsigned referenceEventId : 16; + + public: + TimeShiftedEventDescriptor(const uint8_t * const buffer); + + uint16_t getReferenceServiceId(void) const; + uint16_t getReferenceEventId(void) const; +}; + +#endif /* __dvb_descriptor_time_shifted_event_descriptor_h__ */ diff --git a/lib/dvb_si/time_shifted_service_descriptor.cpp b/lib/dvb_si/time_shifted_service_descriptor.cpp new file mode 100644 index 00000000..0d77946d --- /dev/null +++ b/lib/dvb_si/time_shifted_service_descriptor.cpp @@ -0,0 +1,33 @@ +/* + * $Id: time_shifted_service_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +TimeShiftedServiceDescriptor::TimeShiftedServiceDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + referenceServiceId = (buffer[2] << 8) | buffer[3]; +} + +uint16_t TimeShiftedServiceDescriptor::getReferenceServiceId(void) const +{ + return referenceServiceId; +} + diff --git a/lib/dvb_si/time_shifted_service_descriptor.h b/lib/dvb_si/time_shifted_service_descriptor.h new file mode 100644 index 00000000..57ba72b3 --- /dev/null +++ b/lib/dvb_si/time_shifted_service_descriptor.h @@ -0,0 +1,38 @@ +/* + * $Id: time_shifted_service_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_time_shifted_service_descriptor_h__ +#define __dvb_descriptor_time_shifted_service_descriptor_h__ + +#include "descriptor.h" + +class TimeShiftedServiceDescriptor : public Descriptor +{ + protected: + unsigned referenceServiceId : 16; + + public: + TimeShiftedServiceDescriptor(const uint8_t * const buffer); + + uint16_t getReferenceServiceId(void) const; +}; + +#endif /* __dvb_descriptor_time_shifted_service_descriptor_h__ */ diff --git a/lib/dvb_si/tot.cpp b/lib/dvb_si/tot.cpp new file mode 100644 index 00000000..16171a53 --- /dev/null +++ b/lib/dvb_si/tot.cpp @@ -0,0 +1,44 @@ +/* + * $Id: tot.cpp,v 1.1 2003-10-17 15:36:37 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +TimeOffsetTable::TimeOffsetTable(const uint8_t * const buffer) : ShortCrcTable(buffer) +{ + utcTimeMjd = (buffer[3] << 8) | buffer[4]; + utcTimeBcd = (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; + reserved = (buffer[8] >> 4) & 0x0f; + descriptorsLoopLength = ((buffer[8] & 0x0f) << 8) | buffer[9]; + + for (uint16_t i = 0; i < descriptorsLoopLength; i += buffer[i + 11] + 2) + descriptor(&buffer[i + 10]); +} + +uint16_t TimeOffsetTable::getUtcTimeMjd(void) const +{ + return utcTimeMjd; +} + +uint32_t TimeOffsetTable::getUtcTimeBcd(void) const +{ + return utcTimeBcd; +} + diff --git a/lib/dvb_si/tot.h b/lib/dvb_si/tot.h new file mode 100644 index 00000000..ce434887 --- /dev/null +++ b/lib/dvb_si/tot.h @@ -0,0 +1,51 @@ +/* + * $Id: tot.h,v 1.1 2003-10-17 15:36:39 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_table_tot_h__ +#define __dvb_table_tot_h__ + +#include +#include "short_crc_table.h" + +class TimeOffsetTable : public ShortCrcTable, public DescriptorContainer +{ + protected: + unsigned utcTimeMjd : 16; + unsigned utcTimeBcd : 24; + unsigned reserved : 4; + unsigned descriptorsLoopLength : 12; + + public: + TimeOffsetTable(const uint8_t * const buffer); + + static const enum PacketId PID = PID_TOT; + static const enum TableId TID = TID_TOT; + static const uint32_t TIMEOUT = 36000; + + uint16_t getUtcTimeMjd(void) const; + uint32_t getUtcTimeBcd(void) const; +}; + +typedef std::vector TimeOffsetTableVector; +typedef TimeOffsetTableVector::iterator TimeOffsetTableIterator; +typedef TimeOffsetTableVector::const_iterator TimeOffsetTableConstIterator; + +#endif /* __dvb_table_tot_h__ */ diff --git a/lib/dvb_si/transport_stream_descriptor.h b/lib/dvb_si/transport_stream_descriptor.h new file mode 100644 index 00000000..0c223e2f --- /dev/null +++ b/lib/dvb_si/transport_stream_descriptor.h @@ -0,0 +1,38 @@ +/* + * $Id: transport_stream_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_transport_stream_descriptor_h__ +#define __dvb_descriptor_transport_stream_descriptor_h__ + +#include "descriptor.h" + +class TransportStreamDescriptor : public Descriptor +{ + protected: + std::string bytes; + + public: + TransportStreamDescriptor(const uint8_t * const buffer); + + std::string getBytes(void) const; +}; + +#endif /* __dvb_descriptor_transport_stream_descriptor_h__ */ diff --git a/lib/dvb_si/url_descriptor.h b/lib/dvb_si/url_descriptor.h new file mode 100644 index 00000000..23db23aa --- /dev/null +++ b/lib/dvb_si/url_descriptor.h @@ -0,0 +1,34 @@ +/* + * $Id: url_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_url_descriptor_h__ +#define __dvb_descriptor_url_descriptor_h__ + +#include "descriptor.h" + +/* 0x90 */ +class UrlDescriptor : public Descriptor +{ + public: + UrlDescriptor(const uint8_t * const buffer); +}; + +#endif /* __dvb_descriptor_url_descriptor_h__ */ diff --git a/lib/dvb_si/vbi_data_descriptor.cpp b/lib/dvb_si/vbi_data_descriptor.cpp new file mode 100644 index 00000000..87911555 --- /dev/null +++ b/lib/dvb_si/vbi_data_descriptor.cpp @@ -0,0 +1,98 @@ +/* + * $Id: vbi_data_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +VbiDataLine::VbiDataLine(const uint8_t * const buffer) +{ + reserved = (buffer[0] >> 6) & 0x03; + fieldParity = (buffer[0] >> 5) & 0x01; + lineOffset = buffer[0] & 0x1F; +} + +uint8_t VbiDataLine::getFieldParity(void) const +{ + return fieldParity; +} + +uint8_t VbiDataLine::getLineOffset(void) const +{ + return lineOffset; +} + +VbiDataService::VbiDataService(const uint8_t * const buffer) +{ + uint16_t i; + + dataServiceId = buffer[0]; + dataServiceDescriptorLength = buffer[1]; + + switch (dataServiceId) { + case 0x01: + case 0x02: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + for (i = 0; i < dataServiceDescriptorLength; ++i); + vbiDataLines.push_back(new VbiDataLine(&buffer[i + 2])); + break; + + default: + for (i = 0; i < dataServiceDescriptorLength; ++i) + reserved.push_back(buffer[i + 2]); + break; + } +} + +VbiDataService::~VbiDataService(void) +{ + for (VbiDataLineIterator i = vbiDataLines.begin(); i != vbiDataLines.end(); ++i) + delete *i; +} + +uint8_t VbiDataService::getDataServiceId(void) const +{ + return dataServiceId; +} + +const VbiDataLineVector *VbiDataService::getVbiDataLines(void) const +{ + return &vbiDataLines; +} + +VbiDataDescriptor::VbiDataDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += buffer[i + 3] + 2) + vbiDataServices.push_back(new VbiDataService(&buffer[i + 2])); +} + +VbiDataDescriptor::~VbiDataDescriptor(void) +{ + for (VbiDataServiceIterator i = vbiDataServices.begin(); i != vbiDataServices.end(); ++i) + delete *i; +} + +const VbiDataServiceVector *VbiDataDescriptor::getVbiDataServices(void) const +{ + return &vbiDataServices; +} + diff --git a/lib/dvb_si/vbi_data_descriptor.h b/lib/dvb_si/vbi_data_descriptor.h new file mode 100644 index 00000000..aa26b91c --- /dev/null +++ b/lib/dvb_si/vbi_data_descriptor.h @@ -0,0 +1,77 @@ +/* + * $Id: vbi_data_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_vbi_data_descriptor_h__ +#define __dvb_descriptor_vbi_data_descriptor_h__ + +#include "descriptor.h" + +class VbiDataLine +{ + protected: + unsigned reserved : 2; + unsigned fieldParity : 1; + unsigned lineOffset : 5; + + public: + VbiDataLine(const uint8_t * const buffer); + + uint8_t getFieldParity(void) const; + uint8_t getLineOffset(void) const; +}; + +typedef std::vector VbiDataLineVector; +typedef VbiDataLineVector::iterator VbiDataLineIterator; +typedef VbiDataLineVector::const_iterator VbiDataLineConstIterator; + +class VbiDataService +{ + protected: + unsigned dataServiceId : 8; + unsigned dataServiceDescriptorLength : 8; + VbiDataLineVector vbiDataLines; + std::vector reserved; + + public: + VbiDataService(const uint8_t * const buffer); + ~VbiDataService(void); + + uint8_t getDataServiceId(void) const; + const VbiDataLineVector *getVbiDataLines(void) const; +}; + +typedef std::vector VbiDataServiceVector; +typedef VbiDataServiceVector::iterator VbiDataServiceIterator; +typedef VbiDataServiceVector::const_iterator VbiDataServiceConstIterator; + +class VbiDataDescriptor : public Descriptor +{ + protected: + VbiDataServiceVector vbiDataServices; + + public: + VbiDataDescriptor(const uint8_t * const buffer); + ~VbiDataDescriptor(void); + + const VbiDataServiceVector *getVbiDataServices(void) const; +}; + +#endif /* __dvb_descriptor_vbi_data_descriptor_h__ */ diff --git a/lib/dvb_si/vbi_teletext_descriptor.cpp b/lib/dvb_si/vbi_teletext_descriptor.cpp new file mode 100644 index 00000000..bf7c0ab1 --- /dev/null +++ b/lib/dvb_si/vbi_teletext_descriptor.cpp @@ -0,0 +1,68 @@ +/* + * $Id: vbi_teletext_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +VbiTeletext::VbiTeletext(const uint8_t * const buffer) +{ + iso639LanguageCode.assign((char *)&buffer[0], 3); + teletextType = (buffer[3] >> 3) & 0x1F; + teletextMagazineNumber = buffer[3] & 0x07; + teletextPageNumber = buffer[4]; +} + +std::string VbiTeletext::getIso639LanguageCode(void) const +{ + return iso639LanguageCode; +} + +uint8_t VbiTeletext::getTeletextType(void) const +{ + return teletextType; +} + +uint8_t VbiTeletext::getTeletextMagazineNumber(void) const +{ + return teletextMagazineNumber; +} + +uint8_t VbiTeletext::getTeletextPageNumber(void) const +{ + return teletextPageNumber; +} + +VbiTeletextDescriptor::VbiTeletextDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + for (uint16_t i = 0; i < descriptorLength; i += 5) + vbiTeletexts.push_back(new VbiTeletext(&buffer[i + 2])); +} + +VbiTeletextDescriptor::~VbiTeletextDescriptor(void) +{ + for (VbiTeletextIterator i = vbiTeletexts.begin(); i != vbiTeletexts.end(); ++i) + delete *i; +} + +const VbiTeletextVector *VbiTeletextDescriptor::getVbiTeletexts(void) const +{ + return &vbiTeletexts; +} + diff --git a/lib/dvb_si/vbi_teletext_descriptor.h b/lib/dvb_si/vbi_teletext_descriptor.h new file mode 100644 index 00000000..084d2486 --- /dev/null +++ b/lib/dvb_si/vbi_teletext_descriptor.h @@ -0,0 +1,60 @@ +/* + * $Id: vbi_teletext_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_vbi_teletext_descriptor_h__ +#define __dvb_descriptor_vbi_teletext_descriptor_h__ + +#include "descriptor.h" + +class VbiTeletext +{ + protected: + std::string iso639LanguageCode; + unsigned teletextType : 5; + unsigned teletextMagazineNumber : 3; + unsigned teletextPageNumber : 8; + + public: + VbiTeletext(const uint8_t * const buffer); + + std::string getIso639LanguageCode(void) const; + uint8_t getTeletextType(void) const; + uint8_t getTeletextMagazineNumber(void) const; + uint8_t getTeletextPageNumber(void) const; +}; + +typedef std::vector VbiTeletextVector; +typedef VbiTeletextVector::iterator VbiTeletextIterator; +typedef VbiTeletextVector::const_iterator VbiTeletextConstIterator; + +class VbiTeletextDescriptor : public Descriptor +{ + protected: + VbiTeletextVector vbiTeletexts; + + public: + VbiTeletextDescriptor(const uint8_t * const buffer); + ~VbiTeletextDescriptor(void); + + const VbiTeletextVector *getVbiTeletexts(void) const; +}; + +#endif /* __dvb_descriptor_vbi_teletext_descriptor_h__ */ diff --git a/lib/dvb_si/video_stream_descriptor.cpp b/lib/dvb_si/video_stream_descriptor.cpp new file mode 100644 index 00000000..103026d3 --- /dev/null +++ b/lib/dvb_si/video_stream_descriptor.cpp @@ -0,0 +1,73 @@ +/* + * $Id: video_stream_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +VideoStreamDescriptor::VideoStreamDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + multipleFrameRateFlag = (buffer[2] >> 7) & 0x01; + frameRateCode = (buffer[2] >> 3) & 0x0F; + mpeg1OnlyFlag = (buffer[2] >> 2) & 0x01; + constrainedParameterFlag = (buffer[2] >> 1) & 0x01; + + if (!mpeg1OnlyFlag) { + profileAndLevelIndication = buffer[3]; + chromaFormat = (buffer[4] >> 6) & 0x03; + frameRateExtensionFlag = (buffer[4] >> 5) & 0x01; + reserved = buffer[4] & 0x1F; + } +} + +uint8_t VideoStreamDescriptor::getMultipleFrameRateFlag(void) const +{ + return multipleFrameRateFlag; +} + +uint8_t VideoStreamDescriptor::getFrameRateCode(void) const +{ + return frameRateCode; +} + +uint8_t VideoStreamDescriptor::getMpeg1OnlyFlag(void) const +{ + return mpeg1OnlyFlag; +} + +uint8_t VideoStreamDescriptor::getConstrainedParameterFlag(void) const +{ + return constrainedParameterFlag; +} + +uint8_t VideoStreamDescriptor::getProfileAndLevelIndication(void) const +{ + return profileAndLevelIndication; +} + +uint8_t VideoStreamDescriptor::getChromaFormat(void) const +{ + return chromaFormat; +} + +uint8_t VideoStreamDescriptor::getFrameRateExtensionFlag(void) const +{ + return frameRateExtensionFlag; +} + diff --git a/lib/dvb_si/video_stream_descriptor.h b/lib/dvb_si/video_stream_descriptor.h new file mode 100644 index 00000000..2652acc6 --- /dev/null +++ b/lib/dvb_si/video_stream_descriptor.h @@ -0,0 +1,53 @@ +/* + * $Id: video_stream_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_video_stream_descriptor_h__ +#define __dvb_descriptor_video_stream_descriptor_h__ + +#include "descriptor.h" + +class VideoStreamDescriptor : public Descriptor +{ + protected: + unsigned multipleFrameRateFlag : 1; + unsigned frameRateCode : 4; + unsigned mpeg1OnlyFlag : 1; + unsigned constrainedParameterFlag : 1; + unsigned stillPictureFlag : 1; + unsigned profileAndLevelIndication : 8; + unsigned chromaFormat : 2; + unsigned frameRateExtensionFlag : 1; + unsigned reserved : 5; + + public: + VideoStreamDescriptor(const uint8_t * const buffer); + + uint8_t getMultipleFrameRateFlag(void) const; + uint8_t getFrameRateCode(void) const; + uint8_t getMpeg1OnlyFlag(void) const; + uint8_t getConstrainedParameterFlag(void) const; + uint8_t getStillPictureFlag(void) const; + uint8_t getProfileAndLevelIndication(void) const; + uint8_t getChromaFormat(void) const; + uint8_t getFrameRateExtensionFlag(void) const; +}; + +#endif /* __dvb_descriptor_video_stream_descriptor_h__ */ diff --git a/lib/dvb_si/video_window_descriptor.cpp b/lib/dvb_si/video_window_descriptor.cpp new file mode 100644 index 00000000..d8e7d691 --- /dev/null +++ b/lib/dvb_si/video_window_descriptor.cpp @@ -0,0 +1,45 @@ +/* + * $Id: video_window_descriptor.cpp,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +VideoWindowDescriptor::VideoWindowDescriptor(const uint8_t * const buffer) : Descriptor(buffer) +{ + horizontalOffset = ((buffer[2] << 8) | (buffer[3] & 0xF3)) >> 2; + verticalOffset = (((buffer[3] & 0x03) << 16) | (buffer[4] << 8) | (buffer[5] & 0xF0)) >> 4; + windowPriority = buffer[5] & 0x0F; +} + +uint16_t VideoWindowDescriptor::getHorizontalOffset(void) const +{ + return horizontalOffset; +} + +uint16_t VideoWindowDescriptor::getVerticalOffset(void) const +{ + return verticalOffset; +} + +uint8_t VideoWindowDescriptor::getWindowPriority(void) const +{ + return windowPriority; +} + diff --git a/lib/dvb_si/video_window_descriptor.h b/lib/dvb_si/video_window_descriptor.h new file mode 100644 index 00000000..1558f782 --- /dev/null +++ b/lib/dvb_si/video_window_descriptor.h @@ -0,0 +1,42 @@ +/* + * $Id: video_window_descriptor.h,v 1.1 2003-10-17 15:36:38 tmbinc Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __dvb_descriptor_video_window_descriptor_h__ +#define __dvb_descriptor_video_window_descriptor_h__ + +#include "descriptor.h" + +class VideoWindowDescriptor : public Descriptor +{ + protected: + unsigned horizontalOffset : 14; + unsigned verticalOffset : 14; + unsigned windowPriority : 4; + + public: + VideoWindowDescriptor(const uint8_t * const buffer); + + uint16_t getHorizontalOffset(void) const; + uint16_t getVerticalOffset(void) const; + uint8_t getWindowPriority(void) const; +}; + +#endif /* __dvb_descriptor_video_window_descriptor_h__ */ diff --git a/lib/gdi/.cvsignore b/lib/gdi/.cvsignore new file mode 100644 index 00000000..316b06f5 --- /dev/null +++ b/lib/gdi/.cvsignore @@ -0,0 +1,7 @@ +*.moc.* +Makefile +Makefile.in +.deps +.libs +*.lo +*.la diff --git a/lib/gdi/Makefile.am b/lib/gdi/Makefile.am new file mode 100644 index 00000000..eff43b08 --- /dev/null +++ b/lib/gdi/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = \ + -I$(top_srcdir)/include + +noinst_LIBRARIES = libenigma_gdi.a + +libenigma_gdi_a_SOURCES = \ + epng.cpp erect.cpp fb.cpp font.cpp font_arabic.cpp gfbdc.cpp \ + glcddc.cpp gpixmap.cpp grc.cpp lcd.cpp diff --git a/lib/gdi/epng.cpp b/lib/gdi/epng.cpp new file mode 100644 index 00000000..d476ec3a --- /dev/null +++ b/lib/gdi/epng.cpp @@ -0,0 +1,187 @@ +#include +#include +#include +#include + +gImage *loadPNG(const char *filename) +{ + __u8 header[8]; + FILE *fp=fopen(filename, "rb"); + + gImage *res=0; + + if (!fp) + { +// eDebug("couldn't open %s", filename ); + return 0; + } + if (!fread(header, 8, 1, fp)) + { + eDebug("couldn't read"); + fclose(fp); + return 0; + } + if (png_sig_cmp(header, 0, 8)) + { + fclose(fp); + return 0; + } + png_structp png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + if (!png_ptr) + { + eDebug("no pngptr"); + fclose(fp); + return 0; + } + png_infop info_ptr=png_create_info_struct(png_ptr); + if (!info_ptr) + { + eDebug("no info ptr"); + png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0); + fclose(fp); + return 0; + } + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + eDebug("no end"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); + fclose(fp); + return 0; + } + if (setjmp(png_ptr->jmpbuf)) + { + eDebug("das war wohl nix"); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fp); + if (res) + delete res; + return 0; + } + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_set_invert_alpha(png_ptr); + png_read_info(png_ptr, info_ptr); + + png_uint_32 width, height; + int bit_depth; + int color_type; + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); + +// eDebug("%s: %dx%dx%d png, %d", filename, (int)width, (int)height, (int)bit_depth, color_type); + + if (color_type != 6) + { + res=new gImage(eSize(width, height), bit_depth); + + png_bytep *rowptr=new png_bytep[height]; + + for (unsigned int i=0; idata))+i*res->stride; + png_read_rows(png_ptr, rowptr, 0, height); + + delete rowptr; + + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) + { + png_color *palette; + int num_palette; + png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); + if (num_palette) + res->clut.data=new gRGB[num_palette]; + else + res->clut.data=0; + res->clut.colors=num_palette; + + for (int i=0; iclut.data[i].a=0; + res->clut.data[i].r=palette[i].red; + res->clut.data[i].g=palette[i].green; + res->clut.data[i].b=palette[i].blue; + } + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + { + png_byte *trans; + png_get_tRNS(png_ptr, info_ptr, &trans, &num_palette, 0); + for (int i=0; iclut.data[i].a=255-trans[i]; + } + } else + { + res->clut.data=0; + res->clut.colors=0; + } + png_read_end(png_ptr, end_info); + } else + res=0; + + png_destroy_read_struct(&png_ptr, &info_ptr,&end_info); + fclose(fp); + return res; +} + +int savePNG(const char *filename, gPixmap *pixmap) +{ + FILE *fp=fopen(filename, "wb"); + if (!fp) + return -1; + png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + if (!png_ptr) + { + eDebug("write png, couldnt allocate write struct"); + fclose(fp); + unlink(filename); + return -2; + } + png_infop info_ptr=png_create_info_struct(png_ptr); + if (!info_ptr) + { + eDebug("info"); + png_destroy_write_struct(&png_ptr, 0); + fclose(fp); + unlink(filename); + return -3; + } + if (setjmp(png_ptr->jmpbuf)) + { + eDebug("error :/"); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + unlink(filename); + return -4; + } + png_init_io(png_ptr, fp); + png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH); + png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + + png_set_IHDR(png_ptr, info_ptr, pixmap->x, pixmap->y, pixmap->bpp, + pixmap->clut.data ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + if (pixmap->clut.data) + { + png_color palette[pixmap->clut.colors]; + png_byte trans[pixmap->clut.colors]; + for (int i=0; iclut.colors; ++i) + { + palette[i].red=pixmap->clut.data[i].r; + palette[i].green=pixmap->clut.data[i].g; + palette[i].blue=pixmap->clut.data[i].b; + trans[i]=255-pixmap->clut.data[i].a; + } + png_set_PLTE(png_ptr, info_ptr, palette, pixmap->clut.colors); + png_set_tRNS(png_ptr, info_ptr, trans, pixmap->clut.colors, 0); + } + png_write_info(png_ptr, info_ptr); + png_set_packing(png_ptr); + png_byte *row_pointers[pixmap->y]; + for (int i=0; iy; ++i) + row_pointers[i]=((png_byte*)pixmap->data)+i*pixmap->stride; + png_write_image(png_ptr, row_pointers); + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + eDebug("wrote png ! fine !"); + return 0; +} diff --git a/lib/gdi/epng.h b/lib/gdi/epng.h new file mode 100644 index 00000000..650c2513 --- /dev/null +++ b/lib/gdi/epng.h @@ -0,0 +1,9 @@ +#ifndef __png_h +#define __png_h + +#include "grc.h" + +gImage *loadPNG(const char *filename); +int savePNG(const char *filename, gPixmap *pixmap); + +#endif diff --git a/lib/gdi/epoint.h b/lib/gdi/epoint.h new file mode 100644 index 00000000..fc5f9836 --- /dev/null +++ b/lib/gdi/epoint.h @@ -0,0 +1,172 @@ +#ifndef EPOINT_H +#define EPOINT_H + +#include + +#ifndef ABS +#define ABS(x) ( x>0 ? x : -x ) +#endif + +class ePoint +{ +public: + ePoint(); + ePoint( int xpos, int ypos ); + + bool isNull() const; + + int x() const; + int y() const; + void setX( int x ); + void setY( int y ); + + int manhattanLength() const; + + int &rx(); + int &ry(); + + ePoint &operator+=( const ePoint &p ); + ePoint &operator-=( const ePoint &p ); + ePoint &operator*=( int c ); + ePoint &operator*=( double c ); + ePoint &operator/=( int c ); + ePoint &operator/=( double c ); + + friend inline bool operator==( const ePoint &, const ePoint & ); + friend inline bool operator!=( const ePoint &, const ePoint & ); + friend inline ePoint operator+( const ePoint &, const ePoint & ); + friend inline ePoint operator-( const ePoint &, const ePoint & ); + friend inline ePoint operator*( const ePoint &, int ); + friend inline ePoint operator*( int, const ePoint & ); + friend inline ePoint operator*( const ePoint &, double ); + friend inline ePoint operator*( double, const ePoint & ); + friend inline ePoint operator-( const ePoint & ); + friend inline ePoint operator/( const ePoint &, int ); + friend inline ePoint operator/( const ePoint &, double ); +private: + int xp; + int yp; +}; + + +inline int ePoint::manhattanLength() const +{ + return ABS(x())+ABS(y()); +} + + +/***************************************************************************** + ePoint stream functions + *****************************************************************************/ +namespace std +{ + inline ostream &operator<<( ostream & s, const ePoint & p ) + { + s << p.x() << p.y(); + return s; + } + + inline istream &operator>>( istream & s, ePoint & p ) + { + s >> p.rx() >> p.ry(); + return s; + } +} + + +/***************************************************************************** + ePoint inline functions + *****************************************************************************/ + +inline ePoint::ePoint() +{ xp=0; yp=0; } + +inline ePoint::ePoint( int xpos, int ypos ) +{ xp=(int)xpos; yp=(int)ypos; } + +inline bool ePoint::isNull() const +{ return xp == 0 && yp == 0; } + +inline int ePoint::x() const +{ return xp; } + +inline int ePoint::y() const +{ return yp; } + +inline void ePoint::setX( int x ) +{ xp = (int)x; } + +inline void ePoint::setY( int y ) +{ yp = (int)y; } + +inline int &ePoint::rx() +{ return xp; } + +inline int &ePoint::ry() +{ return yp; } + +inline ePoint &ePoint::operator+=( const ePoint &p ) +{ xp+=p.xp; yp+=p.yp; return *this; } + +inline ePoint &ePoint::operator-=( const ePoint &p ) +{ xp-=p.xp; yp-=p.yp; return *this; } + +inline ePoint &ePoint::operator*=( int c ) +{ xp*=(int)c; yp*=(int)c; return *this; } + +inline ePoint &ePoint::operator*=( double c ) +{ xp=(int)(xp*c); yp=(int)(yp*c); return *this; } + +inline bool operator==( const ePoint &p1, const ePoint &p2 ) +{ return p1.xp == p2.xp && p1.yp == p2.yp; } + +inline bool operator!=( const ePoint &p1, const ePoint &p2 ) +{ return p1.xp != p2.xp || p1.yp != p2.yp; } + +inline ePoint operator+( const ePoint &p1, const ePoint &p2 ) +{ return ePoint(p1.xp+p2.xp, p1.yp+p2.yp); } + +inline ePoint operator-( const ePoint &p1, const ePoint &p2 ) +{ return ePoint(p1.xp-p2.xp, p1.yp-p2.yp); } + +inline ePoint operator*( const ePoint &p, int c ) +{ return ePoint(p.xp*c, p.yp*c); } + +inline ePoint operator*( int c, const ePoint &p ) +{ return ePoint(p.xp*c, p.yp*c); } + +inline ePoint operator*( const ePoint &p, double c ) +{ return ePoint((int)(p.xp*c), (int)(p.yp*c)); } + +inline ePoint operator*( double c, const ePoint &p ) +{ return ePoint((int)(p.xp*c), (int)(p.yp*c)); } + +inline ePoint operator-( const ePoint &p ) +{ return ePoint(-p.xp, -p.yp); } + +inline ePoint &ePoint::operator/=( int c ) +{ + xp/=(int)c; + yp/=(int)c; + return *this; +} + +inline ePoint &ePoint::operator/=( double c ) +{ + xp=(int)(xp/c); + yp=(int)(yp/c); + return *this; +} + +inline ePoint operator/( const ePoint &p, int c ) +{ + return ePoint(p.xp/c, p.yp/c); +} + +inline ePoint operator/( const ePoint &p, double c ) +{ + return ePoint((int)(p.xp/c), (int)(p.yp/c)); +} + + +#endif // EPOINT_H diff --git a/lib/gdi/erect.cpp b/lib/gdi/erect.cpp new file mode 100644 index 00000000..b72e5d04 --- /dev/null +++ b/lib/gdi/erect.cpp @@ -0,0 +1,204 @@ +#include +#include + +/***************************************************************************** + eRect member functions + *****************************************************************************/ + +eRect::eRect( const ePoint &topLeft, const ePoint &bottomRight ) +{ + x1 = topLeft.x(); + y1 = topLeft.y(); + x2 = bottomRight.x(); + y2 = bottomRight.y(); +} + +eRect eRect::normalize() const +{ + eRect r; + if ( x2 < x1 ) { // swap bad x values + r.x1 = x2; + r.x2 = x1; + } else { + r.x1 = x1; + r.x2 = x2; + } + if ( y2 < y1 ) { // swap bad y values + r.y1 = y2; + r.y2 = y1; + } else { + r.y1 = y1; + r.y2 = y2; + } + return r; +} + +void eRect::rect( int *x, int *y, int *w, int *h ) const +{ + *x = x1; + *y = y1; + *w = x2-x1; + *h = y2-y1; +} + +void eRect::coords( int *xp1, int *yp1, int *xp2, int *yp2 ) const +{ + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +void eRect::moveTopLeft( const ePoint &p ) +{ + x2 += (p.x() - x1); + y2 += (p.y() - y1); + x1 = p.x(); + y1 = p.y(); +} + +void eRect::moveBottomRight( const ePoint &p ) +{ + x1 += (p.x() - x2); + y1 += (p.y() - y2); + x2 = p.x(); + y2 = p.y(); +} + +void eRect::moveTopRight( const ePoint &p ) +{ + x1 += (p.x() - x2); + y2 += (p.y() - y1); + x2 = p.x(); + y1 = p.y(); +} + +void eRect::moveBottomLeft( const ePoint &p ) +{ + x2 += (p.x() - x1); + y1 += (p.y() - y2); + x1 = p.x(); + y2 = p.y(); +} + +void eRect::moveCenter( const ePoint &p ) +{ + int w = x2 - x1; + int h = y2 - y1; + x1 = (p.x() - w/2); + y1 = (p.y() - h/2); + x2 = x1 + w; + y2 = y1 + h; +} + +void eRect::setRect( int x, int y, int w, int h ) +{ + x1 = x; + y1 = y; + x2 = (x+w); + y2 = (y+h); +} + +void eRect::setCoords( int xp1, int yp1, int xp2, int yp2 ) +{ + x1 = xp1; + y1 = yp1; + x2 = xp2; + y2 = yp2; +} + +void eRect::setWidth( int w ) +{ + x2 = x1 + w; +} + +void eRect::setHeight( int h ) +{ + y2 = y1 + h; +} + +void eRect::setSize( const eSize &s ) +{ + x2 = s.width() +x1; + y2 = s.height()+y1; +} + +bool eRect::contains( const ePoint &p) const +{ + return p.x() >= x1 && p.x() < x2 && + p.y() >= y1 && p.y() < y2; +} + +bool eRect::contains( const eRect &r) const +{ + return r.x1 >= x1 && + r.x2 <= x2 && + r.y1 >= y1 && + r.y2 <= y2; +} + +eRect& eRect::operator|=(const eRect &r) +{ + *this = *this | r; + return *this; +} + +eRect& eRect::operator&=(const eRect &r) +{ + *this = *this & r; + return *this; +} + +eRect eRect::operator|(const eRect &r) const +{ + if ( isValid() ) { + if ( r.isValid() ) { + eRect tmp; + tmp.setLeft( MIN( x1, r.x1 ) ); + tmp.setRight( MAX( x2, r.x2 ) ); + tmp.setTop( MIN( y1, r.y1 ) ); + tmp.setBottom( MAX( y2, r.y2 ) ); + return tmp; + } else { + return *this; + } + } else { + return r; + } +} + +eRect eRect::unite( const eRect &r ) const +{ + return *this | r; +} + +eRect eRect::operator&( const eRect &r ) const +{ + eRect tmp; + tmp.x1 = MAX( x1, r.x1 ); + tmp.x2 = MIN( x2, r.x2 ); + tmp.y1 = MAX( y1, r.y1 ); + tmp.y2 = MIN( y2, r.y2 ); + return tmp; +} + +eRect eRect::intersect( const eRect &r ) const +{ + return *this & r; +} + +bool eRect::intersects( const eRect &r ) const +{ + return ( MAX( x1, r.x1 ) < MIN( x2, r.x2 ) && + MAX( y1, r.y1 ) < MIN( y2, r.y2 ) ); +} + +bool operator==( const eRect &r1, const eRect &r2 ) +{ + return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2; +} + +bool operator!=( const eRect &r1, const eRect &r2 ) +{ + return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2; +} diff --git a/lib/gdi/erect.h b/lib/gdi/erect.h new file mode 100644 index 00000000..c41d8314 --- /dev/null +++ b/lib/gdi/erect.h @@ -0,0 +1,229 @@ +#ifndef ERECT_H +#define ERECT_H + +#include +#include + + +// x2 = x1 + width (AND NOT, NEVER, NEVER EVER +1 or -1 !!!!) + +class eRect // rectangle class +{ +public: + eRect() { x1 = y1 = x2 = y2 = 0; } + eRect( const ePoint &topleft, const ePoint &bottomright ); + + // we use this contructor very often... do it inline... + eRect( const ePoint &topleft, const eSize &size ) + { + x1 = topleft.x(); + y1 = topleft.y(); + x2 = (x1+size.width()); + y2 = (y1+size.height()); + } + + eRect( int left, int top, int width, int height ); + + bool isNull() const; + bool isEmpty() const; + bool isValid() const; + eRect normalize() const; + + int left() const; + int top() const; + int right() const; + int bottom() const; + int &rLeft(); + int &rTop(); + int &rRight(); + int &rBottom(); + + int x() const; + int y() const; + void setLeft( int pos ); + void setTop( int pos ); + void setRight( int pos ); + void setBottom( int pos ); + void setX( int x ); + void setY( int y ); + + ePoint topLeft() const; + ePoint bottomRight() const; + ePoint topRight() const; + ePoint bottomLeft() const; + ePoint center() const; + + void rect( int *x, int *y, int *w, int *h ) const; + void coords( int *x1, int *y1, int *x2, int *y2 ) const; + + void moveTopLeft( const ePoint &p ); + void moveBottomRight( const ePoint &p ); + void moveTopRight( const ePoint &p ); + void moveBottomLeft( const ePoint &p ); + void moveCenter( const ePoint &p ); + + void moveBy( int dx, int dy ) + { + x1 += dx; + y1 += dy; + x2 += dx; + y2 += dy; + } + + void setRect( int x, int y, int w, int h ); + void setCoords( int x1, int y1, int x2, int y2 ); + + eSize size() const; + int width() const; + int height() const; + void setWidth( int w ); + void setHeight( int h ); + void setSize( const eSize &s ); + + eRect operator|(const eRect &r) const; + eRect operator&(const eRect &r) const; + eRect& operator|=(const eRect &r); + eRect& operator&=(const eRect &r); + + bool contains( const ePoint &p) const; + bool contains( int x, int y) const; + bool contains( const eRect &r) const; + eRect unite( const eRect &r ) const; + eRect intersect( const eRect &r ) const; + bool intersects( const eRect &r ) const; + + friend bool operator==( const eRect &, const eRect & ); + friend bool operator!=( const eRect &, const eRect & ); + +private: + int x1; + int y1; + int x2; + int y2; +}; + +bool operator==( const eRect &, const eRect & ); +bool operator!=( const eRect &, const eRect & ); + + +/***************************************************************************** + eRect stream functions + *****************************************************************************/ +namespace std +{ + inline ostream &operator<<( ostream & s, const eRect & r ) + { + s << r.left() << r.top() + << r.right() << r.bottom(); + + return s; + } + + inline istream &operator>>( istream & s, eRect & r ) + { + int x1, y1, x2, y2; + s >> x1 >> y1 >> x2 >> y2; + r.setCoords( x1, y1, x2, y2 ); + return s; + } +} + +/***************************************************************************** + eRect inline member functions + *****************************************************************************/ + +inline eRect::eRect( int left, int top, int width, int height ) +{ + x1 = left; + y1 = top; + x2 = left+width; + y2 = top+height; +} + +inline bool eRect::isNull() const +{ return x2 == x1 && y2 == y1; } + +inline bool eRect::isEmpty() const +{ return x1 >= x2 || y1 >= y2; } + +inline bool eRect::isValid() const +{ return x1 <= x2 && y1 <= y2; } + +inline int eRect::left() const +{ return x1; } + +inline int eRect::top() const +{ return y1; } + +inline int eRect::right() const +{ return x2; } + +inline int eRect::bottom() const +{ return y2; } + +inline int &eRect::rLeft() +{ return x1; } + +inline int & eRect::rTop() +{ return y1; } + +inline int & eRect::rRight() +{ return x2; } + +inline int & eRect::rBottom() +{ return y2; } + +inline int eRect::x() const +{ return x1; } + +inline int eRect::y() const +{ return y1; } + +inline void eRect::setLeft( int pos ) +{ x1 = pos; } + +inline void eRect::setTop( int pos ) +{ y1 = pos; } + +inline void eRect::setRight( int pos ) +{ x2 = pos; } + +inline void eRect::setBottom( int pos ) +{ y2 = pos; } + +inline void eRect::setX( int x ) +{ x1 = x; } + +inline void eRect::setY( int y ) +{ y1 = y; } + +inline ePoint eRect::topLeft() const +{ return ePoint(x1, y1); } + +inline ePoint eRect::bottomRight() const +{ return ePoint(x2, y2); } + +inline ePoint eRect::topRight() const +{ return ePoint(x2, y1); } + +inline ePoint eRect::bottomLeft() const +{ return ePoint(x1, y2); } + +inline ePoint eRect::center() const +{ return ePoint((x1+x2)/2, (y1+y2)/2); } + +inline int eRect::width() const +{ return x2 - x1; } + +inline int eRect::height() const +{ return y2 - y1; } + +inline eSize eRect::size() const +{ return eSize(x2-x1, y2-y1); } + +inline bool eRect::contains( int x, int y) const +{ + return x >= x1 && x < x2 && y >= y1 && y < y2; +} + +#endif // eRect_H diff --git a/lib/gdi/esize.h b/lib/gdi/esize.h new file mode 100644 index 00000000..d4bd4afb --- /dev/null +++ b/lib/gdi/esize.h @@ -0,0 +1,187 @@ +#ifndef ESIZE_H +#define ESIZE_H + +#include + +#define MIN(a,b) (a < b ? a : b) +#define MAX(a,b) (a > b ? a : b) + +class eSize +{ +public: + eSize(); + eSize( int w, int h ); + + bool isNull() const; + bool isEmpty() const; + bool isValid() const; + + int width() const; + int height() const; + void setWidth( int w ); + void setHeight( int h ); + void transpose(); + + eSize expandedTo( const eSize & ) const; + eSize boundedTo( const eSize & ) const; + + int &rwidth(); + int &rheight(); + + eSize &operator+=( const eSize & ); + eSize &operator-=( const eSize & ); + eSize &operator*=( int c ); + eSize &operator*=( double c ); + eSize &operator/=( int c ); + eSize &operator/=( double c ); + + friend inline bool operator==( const eSize &, const eSize & ); + friend inline bool operator!=( const eSize &, const eSize & ); + friend inline eSize operator+( const eSize &, const eSize & ); + friend inline eSize operator-( const eSize &, const eSize & ); + friend inline eSize operator*( const eSize &, int ); + friend inline eSize operator*( int, const eSize & ); + friend inline eSize operator*( const eSize &, double ); + friend inline eSize operator*( double, const eSize & ); + friend inline eSize operator/( const eSize &, int ); + friend inline eSize operator/( const eSize &, double ); + +private: + int wd; + int ht; +}; + + +/***************************************************************************** + eSize stream functions + *****************************************************************************/ + +namespace std +{ + inline ostream &operator<<( ostream &s, const eSize &sz ) + { + s << sz.width() << sz.height(); + return s; + } + + inline istream &operator>>( istream &s, eSize &sz ) + { + s >> sz.rwidth() >> sz.rheight(); + return s; + } +} + + +/***************************************************************************** + eSize inline functions + *****************************************************************************/ + +inline eSize::eSize() +{ wd = ht = -1; } + +inline eSize::eSize( int w, int h ) +{ wd=w; ht=h; } + +inline bool eSize::isNull() const +{ return wd==0 && ht==0; } + +inline bool eSize::isEmpty() const +{ return wd<1 || ht<1; } + +inline bool eSize::isValid() const +{ return wd>=0 && ht>=0; } + +inline int eSize::width() const +{ return wd; } + +inline int eSize::height() const +{ return ht; } + +inline void eSize::setWidth( int w ) +{ wd=w; } + +inline void eSize::setHeight( int h ) +{ ht=h; } + +inline int &eSize::rwidth() +{ return wd; } + +inline int &eSize::rheight() +{ return ht; } + +inline eSize &eSize::operator+=( const eSize &s ) +{ wd+=s.wd; ht+=s.ht; return *this; } + +inline eSize &eSize::operator-=( const eSize &s ) +{ wd-=s.wd; ht-=s.ht; return *this; } + +inline eSize &eSize::operator*=( int c ) +{ wd*=c; ht*=c; return *this; } + +inline eSize &eSize::operator*=( double c ) +{ wd=(int)(wd*c); ht=(int)(ht*c); return *this; } + +inline bool operator==( const eSize &s1, const eSize &s2 ) +{ return s1.wd == s2.wd && s1.ht == s2.ht; } + +inline bool operator!=( const eSize &s1, const eSize &s2 ) +{ return s1.wd != s2.wd || s1.ht != s2.ht; } + +inline eSize operator+( const eSize & s1, const eSize & s2 ) +{ return eSize(s1.wd+s2.wd, s1.ht+s2.ht); } + +inline eSize operator-( const eSize &s1, const eSize &s2 ) +{ return eSize(s1.wd-s2.wd, s1.ht-s2.ht); } + +inline eSize operator*( const eSize &s, int c ) +{ return eSize(s.wd*c, s.ht*c); } + +inline eSize operator*( int c, const eSize &s ) +{ return eSize(s.wd*c, s.ht*c); } + +inline eSize operator*( const eSize &s, double c ) +{ return eSize((int)(s.wd*c), (int)(s.ht*c)); } + +inline eSize operator*( double c, const eSize &s ) +{ return eSize((int)(s.wd*c), (int)(s.ht*c)); } + +inline eSize &eSize::operator/=( int c ) +{ + wd/=c; ht/=c; + return *this; +} + +inline eSize &eSize::operator/=( double c ) +{ + wd=(int)(wd/c); ht=(int)(ht/c); + return *this; +} + +inline eSize operator/( const eSize &s, int c ) +{ + return eSize(s.wd/c, s.ht/c); +} + +inline eSize operator/( const eSize &s, double c ) +{ + return eSize((int)(s.wd/c), (int)(s.ht/c)); +} + +inline eSize eSize::expandedTo( const eSize & otherSize ) const +{ + return eSize( MAX(wd,otherSize.wd), MAX(ht,otherSize.ht) ); +} + +inline eSize eSize::boundedTo( const eSize & otherSize ) const +{ + return eSize( MIN(wd,otherSize.wd), MIN(ht,otherSize.ht) ); +} + +inline void eSize::transpose() +{ + int tmp = wd; + wd = ht; + ht = tmp; +} + +#endif // ESIZE_H diff --git a/lib/gdi/fb.cpp b/lib/gdi/fb.cpp new file mode 100644 index 00000000..96ca4313 --- /dev/null +++ b/lib/gdi/fb.cpp @@ -0,0 +1,186 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +fbClass *fbClass::instance; + +fbClass *fbClass::getInstance() +{ + return instance; +} + +fbClass::fbClass(const char *fb) +{ + instance=this; + locked=0; + available=0; + cmap.start=0; + cmap.len=256; + cmap.red=red; + cmap.green=green; + cmap.blue=blue; + cmap.transp=trans; + + int state=0; + eConfig::getInstance()->getKey("/ezap/osd/showConsoleOnFB", state); + + fd=open(fb, O_RDWR); + if (fd<0) + { + perror(fb); + goto nolfb; + } + if (ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo)<0) + { + perror("FBIOGET_VSCREENINFO"); + goto nolfb; + } + + memcpy(&oldscreen, &screeninfo, sizeof(screeninfo)); + + fb_fix_screeninfo fix; + if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0) + { + perror("FBIOGET_FSCREENINFO"); + goto nolfb; + } + + available=fix.smem_len; + eDebug("%dk video mem", available/1024); + lfb=(unsigned char*)mmap(0, available, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); + if (!lfb) + { + perror("mmap"); + goto nolfb; + } + + showConsole(state); + return; +nolfb: + lfb=0; + printf("framebuffer not available.\n"); + return; +} + +int fbClass::showConsole(int state) +{ + int fd=open("/dev/vc/0", O_RDWR); + if(fd>=0) + { + if(ioctl(fd, KDSETMODE, state?KD_TEXT:KD_GRAPHICS)<0) + { + eDebug("setting /dev/vc/0 status failed."); + } + close(fd); + } + return 0; +} + +int fbClass::SetMode(unsigned int nxRes, unsigned int nyRes, unsigned int nbpp) +{ + screeninfo.xres_virtual=screeninfo.xres=nxRes; + screeninfo.yres_virtual=screeninfo.yres=nyRes; + screeninfo.xoffset=screeninfo.yoffset=0; + screeninfo.bits_per_pixel=nbpp; + if (ioctl(fd, FBIOPUT_VSCREENINFO, &screeninfo)<0) + { + perror("FBIOPUT_VSCREENINFO"); + printf("fb failed\n"); + return -1; + } + if ((screeninfo.xres!=nxRes) && (screeninfo.yres!=nyRes) && (screeninfo.bits_per_pixel!=nbpp)) + { + eDebug("SetMode failed: wanted: %dx%dx%d, got %dx%dx%d", + nxRes, nyRes, nbpp, + screeninfo.xres, screeninfo.yres, screeninfo.bits_per_pixel); + } + xRes=screeninfo.xres; + yRes=screeninfo.yres; + bpp=screeninfo.bits_per_pixel; + fb_fix_screeninfo fix; + if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0) + { + perror("FBIOGET_FSCREENINFO"); + printf("fb failed\n"); + } + stride=fix.line_length; + memset(lfb, 0, stride*yRes); + return 0; +} + +fbClass::~fbClass() +{ + if (available) + ioctl(fd, FBIOPUT_VSCREENINFO, &oldscreen); + if (lfb) + munmap(lfb, available); +} + +int fbClass::PutCMAP() +{ + return ioctl(fd, FBIOPUTCMAP, &cmap); +} + +void fbClass::Box(int x, int y, int width, int height, int color, int backcolor) +{ + if (width<=2) + return; + int offset=y*stride+x/2; + int first=0xF0|((color&0xF0)>>4); + int last= 0xF0|((backcolor&0xF0)>>4); + color=(color&0xF)*0x11; + int halfwidth=width/2; + for (int ay=y; ay<(y+height); ay++) + { + lfb[offset]=first; + memset(lfb+offset+1, color, halfwidth-2); + lfb[offset+halfwidth-1]=last; + offset+=stride; + } +} + +void fbClass::NBox(int x, int y, int width, int height, int color) +{ + int offset=y*stride+x/2; + int halfwidth=width/2; + for (int ay=y; ay<(y+height); ay++) + { + memset(lfb+offset, color, halfwidth); + offset+=stride; + } +} + +void fbClass::VLine(int x, int y, int sy, int color) +{ + int offset=y*stride+x/2; + while (sy--) + { + lfb[offset]=color; + offset+=stride; + } +} + +int fbClass::lock() +{ + if (locked) + return -1; + locked=1; + return fd; +} + +void fbClass::unlock() +{ + if (!locked) + return; + locked=0; + SetMode(xRes, yRes, bpp); + PutCMAP(); +} diff --git a/lib/gdi/fb.h b/lib/gdi/fb.h new file mode 100644 index 00000000..d0ad6fed --- /dev/null +++ b/lib/gdi/fb.h @@ -0,0 +1,43 @@ +#ifndef __FB_H +#define __FB_H + +#include +#include + +class fbClass +{ + int fd; + unsigned int xRes, yRes, stride, bpp; + int available; + struct fb_var_screeninfo screeninfo, oldscreen; + fb_cmap cmap; + __u16 red[256], green[256], blue[256], trans[256]; + static fbClass *instance; + + int locked; +public: + unsigned char *lfb; + int showConsole(int state); + int SetMode(unsigned int xRes, unsigned int yRes, unsigned int bpp); + int Available() { return available; } + unsigned int Stride() { return stride; } + fb_cmap *CMAP() { return &cmap; } + + fbClass(const char *fb="/dev/fb/0"); + ~fbClass(); + + static fbClass *getInstance(); + + // low level gfx stuff + int PutCMAP(); + + // gfx stuff (colors are 8bit!) + void Box(int x, int y, int width, int height, int color, int backcolor=0); + void NBox(int x, int y, int width, int height, int color); + void VLine(int x, int y, int sy, int color); + + int lock(); + void unlock(); +}; + +#endif diff --git a/lib/gdi/font.cpp b/lib/gdi/font.cpp new file mode 100644 index 00000000..e7a0074f --- /dev/null +++ b/lib/gdi/font.cpp @@ -0,0 +1,855 @@ +#include + +#include +#include +#include +#include +#include +#include + +// use this for init Freetype... +#include +#include FT_FREETYPE_H + +#include +#include +#include +#include +#include +#include + +//#define HAVE_FRIBIDI +// until we have it in the cdk + +#ifdef HAVE_FRIBIDI +#include +#endif + +#include + +fontRenderClass *fontRenderClass::instance; + +static pthread_mutex_t ftlock=PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP; +static pthread_mutex_t refcntlck=PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP; + +static FTC_Font cache_current_font=0; + +struct fntColorCacheKey +{ + gRGB start, end; + fntColorCacheKey(const gRGB &start, const gRGB &end) + : start(start), end(end) + { + } + bool operator <(const fntColorCacheKey &c) const + { + if (start < c.start) + return 1; + else if (start == c.start) + return end < c.end; + return 0; + } +}; + +std::map colorcache; + +static gLookup &getColor(const gPalette &pal, const gRGB &start, const gRGB &end) +{ + fntColorCacheKey key(start, end); + std::map::iterator i=colorcache.find(key); + if (i != colorcache.end()) + return i->second; + gLookup &n=colorcache.insert(std::pair(key,gLookup())).first->second; + eDebug("[FONT] creating new font color cache entry %02x%02x%02x%02x .. %02x%02x%02x%02x", start.a, start.r, start.g, start.b, + end.a, end.r, end.g, end.b); + n.build(16, pal, start, end); +/* for (int i=0; i<16; i++) + eDebugNoNewLine("%02x|%02x%02x%02x%02x ", (int)n.lookup[i], pal.data[n.lookup[i]].a, pal.data[n.lookup[i]].r, pal.data[n.lookup[i]].g, pal.data[n.lookup[i]].b); + eDebug("");*/ + return n; +} + +fontRenderClass *fontRenderClass::getInstance() +{ + return instance; +} + +FT_Error myFTC_Face_Requester(FTC_FaceID face_id, + FT_Library library, + FT_Pointer request_data, + FT_Face* aface) +{ + return ((fontRenderClass*)request_data)->FTC_Face_Requester(face_id, aface); +} + + +FT_Error fontRenderClass::FTC_Face_Requester(FTC_FaceID face_id, FT_Face* aface) +{ + fontListEntry *font=(fontListEntry *)face_id; + if (!font) + return -1; + +// eDebug("[FONT] FTC_Face_Requester (%s)", font->face.c_str()); + + int error; + if ((error=FT_New_Face(library, font->filename.c_str(), 0, aface))) + { + eDebug(" failed: %s", strerror(error)); + return error; + } + FT_Select_Charmap(*aface, ft_encoding_unicode); + return 0; +} + +FTC_FaceID fontRenderClass::getFaceID(const eString &face) +{ + for (fontListEntry *f=font; f; f=f->next) + { + if (f->face == face) + return (FTC_FaceID)f; + } + return 0; +} + +FT_Error fontRenderClass::getGlyphBitmap(FTC_Image_Desc *font, FT_ULong glyph_index, FTC_SBit *sbit) +{ + FT_Error res=FTC_SBit_Cache_Lookup(sbitsCache, font, glyph_index, sbit); + return res; +} + +eString fontRenderClass::AddFont(const eString &filename, const eString &name, int scale) +{ + eDebugNoNewLine("[FONT] adding font %s...", filename.c_str()); + fflush(stdout); + int error; + fontListEntry *n=new fontListEntry; + + n->scale=scale; + FT_Face face; + singleLock s(ftlock); + + if ((error=FT_New_Face(library, filename.c_str(), 0, &face))) + eFatal(" failed: %s", strerror(error)); + + n->filename=filename; + n->face=name; + FT_Done_Face(face); + + n->next=font; + eDebug("OK (%s)", n->face.c_str()); + font=n; + + return n->face; +} + +fontRenderClass::fontListEntry::~fontListEntry() +{ +} + +fontRenderClass::fontRenderClass(): fb(fbClass::getInstance()) +{ + instance=this; + eDebug("[FONT] initializing lib..."); + { + if (FT_Init_FreeType(&library)) + { + eDebug("[FONT] initializing failed."); + return; + } + } + eDebug("[FONT] loading fonts..."); + fflush(stdout); + font=0; + + int maxbytes=4*1024*1024; + eDebug("[FONT] Intializing font cache, using max. %dMB...", maxbytes/1024/1024); + fflush(stdout); + { + if (FTC_Manager_New(library, 8, 8, maxbytes, myFTC_Face_Requester, this, &cacheManager)) + { + eDebug("[FONT] initializing font cache failed!"); + return; + } + if (!cacheManager) + { + eDebug("[FONT] initializing font cache manager error."); + return; + } + if (FTC_SBit_Cache_New(cacheManager, &sbitsCache)) + { + eDebug("[FONT] initializing font cache sbit failed!"); + return; + } + if (FTC_Image_Cache_New(cacheManager, &imageCache)) + { + eDebug("[FONT] initializing font cache imagecache failed!"); + } + } + return; +} + +float fontRenderClass::getLineHeight(const gFont& font) +{ + if (!instance) + return 0; + Font *fnt = getFont( font.family.c_str(), font.pointSize); + if (!fnt) + return 0; + singleLock s(ftlock); + FT_Face current_face; + if (FTC_Manager_Lookup_Size(cacheManager, &fnt->font.font, ¤t_face, &fnt->size)<0) + { + eDebug("FTC_Manager_Lookup_Size failed!"); + return 0; + } + int linegap=current_face->size->metrics.height-(current_face->size->metrics.ascender+current_face->size->metrics.descender); + float height=(current_face->size->metrics.ascender+current_face->size->metrics.descender+linegap/2.0)/64; + delete fnt; + return height; +} + + +fontRenderClass::~fontRenderClass() +{ + singleLock s(ftlock); +// auskommentiert weil freetype und enigma die kritische masse des suckens ueberschreiten. +// FTC_Manager_Done(cacheManager); +// FT_Done_FreeType(library); +} + +Font *fontRenderClass::getFont(const eString &face, int size, int tabwidth) +{ + FTC_FaceID id=getFaceID(face); + if (!id) + return 0; + return new Font(this, id, size * ((fontListEntry*)id)->scale / 100, tabwidth); +} + +Font::Font(fontRenderClass *render, FTC_FaceID faceid, int isize, int tw): tabwidth(tw) +{ + renderer=render; + font.font.face_id=faceid; + font.font.pix_width = isize; + font.font.pix_height = isize; + font.image_type = ftc_image_grays; + height=isize; + if (tabwidth==-1) + tabwidth=8*isize; + ref=0; +// font.image_type |= ftc_image_flag_autohinted; +} + +FT_Error Font::getGlyphBitmap(FT_ULong glyph_index, FTC_SBit *sbit) +{ + return renderer->getGlyphBitmap(&font, glyph_index, sbit); +} + +Font::~Font() +{ +} + +void Font::lock() +{ + ref++; +} + +void Font::unlock() +{ + ref--; + if (!ref) + delete this; +} + +int eTextPara::appendGlyph(Font *current_font, FT_Face current_face, FT_UInt glyphIndex, int flags, int rflags) +{ + FTC_SBit glyph; + if (current_font->getGlyphBitmap(glyphIndex, &glyph)) + return 1; + + int nx=cursor.x(); + + nx+=glyph->xadvance; + + if ( + (rflags&RS_WRAP) && + (nx >= area.right()) + ) + { + int cnt = 0; + glyphString::iterator i(glyphs.end()); + --i; + while (i != glyphs.begin()) + { + if (i->flags&(GS_ISSPACE|GS_ISFIRST)) + break; + cnt++; + --i; + } + if (i != glyphs.begin() && ((i->flags&(GS_ISSPACE|GS_ISFIRST))==GS_ISSPACE) && (++i != glyphs.end())) // skip space + { + int linelength=cursor.x()-i->x; + i->flags|=GS_ISFIRST; + ePoint offset=ePoint(i->x, i->y); + newLine(rflags); + offset-=cursor; + while (i != glyphs.end()) // rearrange them into the next line + { + i->x-=offset.x(); + i->y-=offset.y(); + i->bbox.moveBy(-offset.x(), -offset.y()); + ++i; + } + cursor+=ePoint(linelength, 0); // put the cursor after that line + } else + { + if (cnt) + { + newLine(rflags); + flags|=GS_ISFIRST; + } + } + } + + int xadvance=glyph->xadvance, kern=0; + + if (previous && use_kerning) + { + FT_Vector delta; + FT_Get_Kerning(current_face, previous, glyphIndex, ft_kerning_default, &delta); + kern=delta.x>>6; + } + + pGlyph ng; + + ng.bbox.setLeft( (flags&GS_ISFIRST|glyphs.empty()?cursor.x():cursor.x()-1) + glyph->left ); + ng.bbox.setTop( cursor.y() - glyph->top ); + ng.bbox.setWidth( glyph->width ); + ng.bbox.setHeight( glyph->height ); + + xadvance+=kern; + + ng.x=cursor.x()+kern; + + ng.y=cursor.y(); + ng.w=xadvance; + ng.font=current_font; + ng.font->lock(); + ng.glyph_index=glyphIndex; + ng.flags=flags; + glyphs.push_back(ng); + + cursor+=ePoint(xadvance, 0); + previous=glyphIndex; + return 0; +} + +void eTextPara::calc_bbox() +{ + boundBox.setLeft( 32000 ); + boundBox.setTop( 32000 ); + boundBox.setRight( -32000 ); // for each glyph image, compute its bounding box, translate it, + boundBox.setBottom( -32000 ); + // and grow the string bbox + + for ( glyphString::iterator i(glyphs.begin()); i != glyphs.end(); ++i) + { + if ( i->bbox.left() < boundBox.left() ) + boundBox.setLeft( i->bbox.left() ); + if ( i->bbox.top() < boundBox.top() ) + boundBox.setTop( i->bbox.top() ); + if ( i->bbox.right() > boundBox.right() ) + boundBox.setRight( i->bbox.right() ); + if ( i->bbox.bottom() > boundBox.bottom() ) + boundBox.setBottom( i->bbox.bottom() ); + } +// eDebug("boundBox left = %i, top = %i, right = %i, bottom = %i", boundBox.left(), boundBox.top(), boundBox.right(), boundBox.bottom() ); + bboxValid=1; +} + +void eTextPara::newLine(int flags) +{ + if (maximum.width()size->metrics.height-(current_face->size->metrics.ascender+current_face->size->metrics.descender); + cursor+=ePoint(0, (current_face->size->metrics.ascender+current_face->size->metrics.descender+linegap*1/2)>>6); + if (maximum.height()=0) + eFatal("verdammt man der war noch gelockt :/\n"); +} + +void eTextPara::destroy() +{ + singleLock s(refcntlck); + + if (!refcnt--) + delete this; +} + +eTextPara *eTextPara::grab() +{ + singleLock s(refcntlck); + + refcnt++; + return this; +} + +void eTextPara::setFont(const gFont &font) +{ + if (refcnt) + eFatal("mod. after lock"); + Font *fnt=fontRenderClass::getInstance()->getFont(font.family.c_str(), font.pointSize); + if (!fnt) + eWarning("FONT '%s' MISSING!", font.family.c_str()); + setFont(fnt, + fontRenderClass::getInstance()->getFont(replacement_facename.c_str(), font.pointSize)); +} + +eString eTextPara::replacement_facename; + +void eTextPara::setFont(Font *fnt, Font *replacement) +{ + if (refcnt) + eFatal("mod. after lock"); + if (!fnt) + return; + if (current_font && !current_font->ref) + delete current_font; + current_font=fnt; + replacement_font=replacement; + singleLock s(ftlock); + + // we ask for replacment_font first becauseof the cache + if (replacement_font) + { + if (FTC_Manager_Lookup_Size(fontRenderClass::instance->cacheManager, + &replacement_font->font.font, &replacement_face, + &replacement_font->size)<0) + { + eDebug("FTC_Manager_Lookup_Size failed!"); + return; + } + } + if (current_font) + { + if (FTC_Manager_Lookup_Size(fontRenderClass::instance->cacheManager, ¤t_font->font.font, ¤t_face, ¤t_font->size)<0) + { + eDebug("FTC_Manager_Lookup_Size failed!"); + return; + } + } + cache_current_font=¤t_font->font.font; + previous=0; + use_kerning=FT_HAS_KERNING(current_face); +} + +void +shape (std::vector &string, const std::vector &text); + +int eTextPara::renderString(const eString &string, int rflags) +{ + singleLock s(ftlock); + + if (refcnt) + eFatal("mod. after lock"); + + if (!current_font) + return -1; + + if (cursor.y()==-1) + { + cursor=ePoint(area.x(), area.y()+(current_face->size->metrics.ascender>>6)); + left=cursor.x(); + } + + if (¤t_font->font.font != cache_current_font) + { + if (FTC_Manager_Lookup_Size(fontRenderClass::instance->cacheManager, ¤t_font->font.font, ¤t_face, ¤t_font->size)<0) + { + eDebug("FTC_Manager_Lookup_Size failed!"); + return -1; + } + cache_current_font=¤t_font->font.font; + } + + std::vector uc_string, uc_visual; + uc_string.reserve(string.length()); + + std::string::const_iterator p(string.begin()); + + while(p != string.end()) + { + unsigned int unicode=*p++; + + if (unicode & 0x80) // we have (hopefully) UTF8 here, and we assume that the encoding is VALID + { + if ((unicode & 0xE0)==0xC0) // two bytes + { + unicode&=0x1F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + } else if ((unicode & 0xF0)==0xE0) // three bytes + { + unicode&=0x0F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + } else if ((unicode & 0xF8)==0xF0) // four bytes + { + unicode&=0x07; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + } + } + uc_string.push_back(unicode); + } + + std::vector uc_shape; + + // character -> glyph conversion + shape(uc_shape, uc_string); + + // now do the usual logical->visual reordering +#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); + } +#else + uc_visual=uc_shape; +#endif + + glyphs.reserve(uc_visual.size()); + + for (std::vector::const_iterator i(uc_visual.begin()); + i != uc_visual.end(); ++i) + { + int isprintable=1; + int flags=0; + if (!(rflags&RS_DIRECT)) + { + switch (*i) + { + case '\\': + { + unsigned long c = *(i+1); + switch (c) + { + case 'n': + i++; + goto newline; + case 't': + i++; + goto tab; + case 'r': + i++; + goto nprint; + default: + ; + } + break; + } + case '\t': +tab: isprintable=0; + cursor+=ePoint(current_font->tabwidth, 0); + cursor-=ePoint(cursor.x()%current_font->tabwidth, 0); + break; + case 0x8A: + case 0xE08A: + case '\n': +newline:isprintable=0; + newLine(rflags); + flags|=GS_ISFIRST; + break; + case '\r': + case 0x86: case 0xE086: + case 0x87: case 0xE087: +nprint: isprintable=0; + break; + case ' ': + flags|=GS_ISSPACE; + default: + break; + } + } + if (isprintable) + { + FT_UInt index; + + index=(rflags&RS_DIRECT)? *i : FT_Get_Char_Index(current_face, *i); + + if (!index) + { + if (replacement_face) + index=(rflags&RS_DIRECT)? *i : FT_Get_Char_Index(replacement_face, *i); + + if (!index) + eDebug("unicode %d ('%c') not present", *i, *i); + else + appendGlyph(replacement_font, replacement_face, index, flags, rflags); + } else + appendGlyph(current_font, current_face, index, flags, rflags); + } + } + bboxValid=false; + calc_bbox(); +#ifdef HAVE_FRIBIDI + if (dir & FRIBIDI_MASK_RTL) + realign(dirRight); +#endif + return 0; +} + +void eTextPara::blit(gPixmapDC &dc, const ePoint &offset, const gRGB &background, const gRGB &foreground) +{ + singleLock s(ftlock); + + if (!current_font) + return; + + if (¤t_font->font.font != cache_current_font) + { + if (FTC_Manager_Lookup_Size(fontRenderClass::instance->cacheManager, ¤t_font->font.font, ¤t_face, ¤t_font->size)<0) + { + eDebug("FTC_Manager_Lookup_Size failed!"); + return; + } + cache_current_font=¤t_font->font.font; + } + + ePtr target; + dc.getPixmap(target); + + register int opcode; + gColor *lookup8=0; + __u32 lookup32[16]; + + if (target->bpp == 8) + { + if (target->clut.data) + { + lookup8=getColor(target->clut, background, foreground).lookup; + opcode=0; + } else + opcode=1; + } else if (target->bpp == 32) + { + opcode=3; + if (target->clut.data) + { + lookup8=getColor(target->clut, background, foreground).lookup; + for (int i=0; i<16; ++i) + lookup32[i]=((target->clut.data[lookup8[i]].a<<24)| + (target->clut.data[lookup8[i]].r<<16)| + (target->clut.data[lookup8[i]].g<<8)| + (target->clut.data[lookup8[i]].b))^0xFF000000; + } else + { + for (int i=0; i<16; ++i) + lookup32[i]=(0x010101*i)|0xFF000000; + } + } else + { + eWarning("can't render to %dbpp", target->bpp); + return; + } + + eRect clip(0, 0, target->x, target->y); + clip&=dc.getClip(); + + int buffer_stride=target->stride; + + for (glyphString::iterator i(glyphs.begin()); i != glyphs.end(); ++i) + { + 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(); + __u8 *d=(__u8*)(target->data)+buffer_stride*ry+rx*target->bypp; + __u8 *s=glyph_bitmap->buffer; + register int sx=glyph_bitmap->width; + int sy=glyph_bitmap->height; + if ((sy+ry) >= clip.bottom()) + sy=clip.bottom()-ry; + if ((sx+rx) >= clip.right()) + sx=clip.right()-rx; + if (rx < clip.left()) + { + int diff=clip.left()-rx; + s+=diff; + sx-=diff; + rx+=diff; + d+=diff*target->bypp; + } + if (ry < clip.top()) + { + int diff=clip.top()-ry; + s+=diff*glyph_bitmap->pitch; + sy-=diff; + ry+=diff; + d+=diff*buffer_stride; + } + if (sx>0) + for (int ay=0; ay>4; + if(b) + *td++=lookup8[b]; + else + td++; + } + } else if (opcode == 1) // 8bit direct + { + register __u8 *td=d; + register int ax; + for (ax=0; ax>4; + if(b) + *td++=lookup32[b]; + else + td++; + } + } + s+=glyph_bitmap->pitch-sx; + d+=buffer_stride; + } + } +} + +void eTextPara::realign(int dir) // der code hier ist ein wenig merkwuerdig. +{ + glyphString::iterator begin(glyphs.begin()), c(glyphs.begin()), end(glyphs.begin()), last; + if (dir==dirLeft) + return; + while (c != glyphs.end()) + { + int linelength=0; + int numspaces=0, num=0; + begin=end; + + ASSERT( end != glyphs.end()); + + // zeilenende suchen + do { + last=end; + ++end; + } while ((end != glyphs.end()) && (!(end->flags&GS_ISFIRST))); + // end zeigt jetzt auf begin der naechsten zeile + + for (c=begin; c!=end; ++c) + { + // space am zeilenende skippen + if ((c==last) && (c->flags&GS_ISSPACE)) + continue; + + if (c->flags&GS_ISSPACE) + numspaces++; + linelength+=c->w; + num++; + } + if (!num) // line mit nur einem space + continue; + + switch (dir) + { + case dirRight: + case dirCenter: + { + int offset=area.width()-linelength; + if (dir==dirCenter) + offset/=2; + offset+=area.left(); + while (begin != end) + { + begin->bbox.moveBy(offset-begin->x,0); + begin->x=offset; + offset+=begin->w; + ++begin; + } + break; + } + case dirBlock: + { + if (end == glyphs.end()) // letzte zeile linksbuendig lassen + continue; + int spacemode; + if (numspaces) + spacemode=1; + else + spacemode=0; + if ((!spacemode) && (num<2)) + break; + int off=(area.width()-linelength)*256/(spacemode?numspaces:(num-1)); + int curoff=0; + while (begin != end) + { + int doadd=0; + if ((!spacemode) || (begin->flags&GS_ISSPACE)) + doadd=1; + begin->x+=curoff>>8; + begin->bbox.moveBy(curoff>>8,0); + if (doadd) + curoff+=off; + ++begin; + } + break; + } + } + } + bboxValid=false; + calc_bbox(); +} + +void eTextPara::clear() +{ + singleLock s(ftlock); + + for (glyphString::iterator i(glyphs.begin()); i!=glyphs.end(); ++i) + i->font->unlock(); + + glyphs.clear(); +} + +eAutoInitP0 init_fontRenderClass(eAutoInitNumbers::graphic-1, "Font Render Class"); diff --git a/lib/gdi/font.cpp-new b/lib/gdi/font.cpp-new new file mode 100644 index 00000000..e9aa5430 --- /dev/null +++ b/lib/gdi/font.cpp-new @@ -0,0 +1,787 @@ +#include + +#include +#include +#include +#include +#include +#include + +// use this for init Freetype... +#include +#include FT_FREETYPE_H + +#include +#include +#include +#include +#include + +#include + +fontRenderClass *fontRenderClass::instance; +static eLock ftlock; +static FTC_Font cache_current_font=0; + +struct fntColorCacheKey +{ + gRGB start, end; + fntColorCacheKey(const gRGB &start, const gRGB &end) + : start(start), end(end) + { + } + bool operator <(const fntColorCacheKey &c) const + { + if (start < c.start) + return 1; + else if (start == c.start) + return end < c.end; + return 0; + } +}; + +std::map colorcache; + +static gLookup &getColor(const gPalette &pal, const gRGB &start, const gRGB &end) +{ + fntColorCacheKey key(start, end); + std::map::iterator i=colorcache.find(key); + if (i != colorcache.end()) + return i->second; + gLookup &n=colorcache.insert(std::pair(key,gLookup())).first->second; + eDebug("[FONT] creating new font color cache entry %02x%02x%02x%02x .. %02x%02x%02x%02x", start.a, start.r, start.g, start.b, + end.a, end.r, end.g, end.b); + n.build(16, pal, start, end); +/* for (int i=0; i<16; i++) + eDebugNoNewLine("%02x|%02x%02x%02x%02x ", (int)n.lookup[i], pal.data[n.lookup[i]].a, pal.data[n.lookup[i]].r, pal.data[n.lookup[i]].g, pal.data[n.lookup[i]].b); + eDebug("");*/ + return n; +} + +fontRenderClass *fontRenderClass::getInstance() +{ + return instance; +} + +FT_Error myFTC_Face_Requester(FTC_FaceID face_id, + FT_Library library, + FT_Pointer request_data, + FT_Face* aface) +{ + return ((fontRenderClass*)request_data)->FTC_Face_Requester(face_id, aface); +} + + +FT_Error fontRenderClass::FTC_Face_Requester(FTC_FaceID face_id, FT_Face* aface) +{ + fontListEntry *font=(fontListEntry *)face_id; + if (!font) + return -1; + + eDebug("[FONT] FTC_Face_Requester (%s)", font->face); + + int error; + if ((error=FT_New_Face(library, font->filename, 0, aface))) + { + eDebug(" failed: %s", strerror(error)); + return error; + } + FT_Select_Charmap(*aface, ft_encoding_unicode); + return 0; +} + +FTC_FaceID fontRenderClass::getFaceID(const char *face) +{ + for (fontListEntry *f=font; f; f=f->next) + { + if (!strcmp(f->face, face)) + return (FTC_FaceID)f; + } + return 0; +} + +FT_Error fontRenderClass::getGlyphBitmap(FTC_ImageTypeRec *font, FT_ULong glyph_index, FTC_SBit *sbit) +{ + FT_Error res=FTC_SBitCache_Lookup(sbitsCache, font, glyph_index, sbit, 0); + eDebug("%x", sizeof(**sbit)); + return res; +} + +const char* fontRenderClass::AddFont(const char *filename) +{ + eDebugNoNewLine("[FONT] adding font %s...", filename); + fflush(stdout); + int error; + fontListEntry *n=new fontListEntry; + + FT_Face face; + eLocker lock(ftlock); + + if ((error=FT_New_Face(library, filename, 0, &face))) + eFatal(" failed: %s", strerror(error)); + + strcpy(n->filename=new char[strlen(filename)+1], filename); + strcpy(n->face=new char[strlen(face->family_name)+strlen(face->style_name)+2], face->family_name); + if (face->style_name[0]!=' ') + strcat(n->face, " "); + strcat(n->face, face->style_name); + FT_Done_Face(face); + + n->next=font; + eDebug("OK (%s)", n->face); + font=n; + + return n->face; +} + +fontRenderClass::fontListEntry::~fontListEntry() +{ + delete[] filename; + delete[] face; +} + +fontRenderClass::fontRenderClass(): fb(fbClass::getInstance()) +{ + instance=this; + eDebug("[FONT] initializing lib..."); + { + if (FT_Init_FreeType(&library)) + { + eDebug("[FONT] initializing failed."); + return; + } + } + eDebug("[FONT] loading fonts..."); + fflush(stdout); + font=0; + + int maxbytes=4*1024*1024; + eDebug("[FONT] Intializing font cache, using max. %dMB...", maxbytes/1024/1024); + fflush(stdout); + { + if (FTC_Manager_New(library, 8, 8, maxbytes, myFTC_Face_Requester, this, &cacheManager)) + { + eDebug("[FONT] initializing font cache failed!"); + return; + } + if (!cacheManager) + { + eDebug("[FONT] initializing font cache manager error."); + return; + } + if (FTC_SBitCache_New(cacheManager, &sbitsCache)) + { + eDebug("[FONT] initializing font cache sbit failed!"); + return; + } +/* if (FTC_ImageCache_New(cacheManager, &imageCache)) + { + eDebug("[FONT] initializing font cache imagecache failed!"); + } */ + } + return; +} + +fontRenderClass::~fontRenderClass() +{ + ftlock.lock(); +// auskommentiert weil freetype und enigma die kritische masse des suckens ueberschreiten. +// FTC_Manager_Done(cacheManager); +// FT_Done_FreeType(library); +} + +Font *fontRenderClass::getFont(const char *face, int size, int tabwidth) +{ + FTC_FaceID id=getFaceID(face); + if (!id) + eDebug("face %s does not exist!", face); + if (!id) + return 0; + return new Font(this, id, size, tabwidth); +} + +Font::Font(fontRenderClass *render, FTC_FaceID faceid, int isize, int tw): tabwidth(tw) +{ + renderer=render; + font.font.face_id=faceid; + font.font.pix_width = isize; + font.font.pix_height = isize; + font.flags = FT_LOAD_DEFAULT; + height=isize; + if (tabwidth==-1) + tabwidth=8*isize; + ref=0; +} + +FT_Error Font::getGlyphBitmap(FT_ULong glyph_index, FTC_SBit *sbit) +{ + return renderer->getGlyphBitmap(&font, glyph_index, sbit); +} + +Font::~Font() +{ +} + +void Font::lock() +{ + ref++; +} + +void Font::unlock() +{ + ref--; + if (!ref) + delete this; +} + +int eTextPara::appendGlyph(FT_UInt glyphIndex, int flags, int rflags) +{ + FTC_SBit glyph; + if (current_font->getGlyphBitmap(glyphIndex, &glyph)) + return 1; + + int nx=cursor.x(); + + if (! (rflags & RS_RTL)) + nx+=glyph->xadvance; + else + { + eDebug("RTL: glyph->xadvance: %d", glyph->xadvance); + nx-=glyph->xadvance; + } + + if ( + (rflags&RS_WRAP) && + ( + (!(rflags & RS_RTL)) + ? + (nx >= area.right()) : + (nx < area.left()) + ) + ) + { + int cnt = 0; + glyphString::iterator i(glyphs.end()); + --i; + while (i != glyphs.begin()) + { + if (i->flags&(GS_ISSPACE|GS_ISFIRST)) + break; + cnt++; + --i; + } + if (i != glyphs.begin() && ((i->flags&(GS_ISSPACE|GS_ISFIRST))==GS_ISSPACE) && (++i != glyphs.end())) // skip space + { + int linelength=cursor.x()-i->x; + // RTL: linelength is negative + i->flags|=GS_ISFIRST; + ePoint offset=ePoint(i->x, i->y); + newLine(rflags); + offset-=cursor; + while (i != glyphs.end()) // rearrange them into the next line + { + i->x-=offset.x(); + i->y-=offset.y(); + i->bbox->moveBy(-offset.x(), -offset.y()); + ++i; + } + cursor+=ePoint(linelength, 0); // put the cursor after that line + } else + { + if (cnt) + { + newLine(rflags); + flags|=GS_ISFIRST; + } + } + } + + int xadvance=glyph->xadvance, kern=0; + + if (previous && use_kerning) + { + FT_Vector delta; + FT_Get_Kerning(current_face, previous, glyphIndex, ft_kerning_default, &delta); + kern=delta.x>>6; + } + + eRect* bbox = new eRect(); + bbox->setLeft( (flags&GS_ISFIRST|glyphs.empty()?cursor.x():cursor.x()-1) + glyph->left ); + bbox->setTop( cursor.y() - glyph->top ); + bbox->setWidth( glyph->width ); + bbox->setHeight( glyph->height ); + + pGlyph ng; + + xadvance+=kern; + + if (!(rflags & RS_RTL)) + ng.x=cursor.x()+kern; + else + ng.x=cursor.x()-xadvance; + + ng.y=cursor.y(); + ng.w=xadvance; + ng.font=current_font; + ng.font->lock(); + ng.glyph_index=glyphIndex; + ng.flags=flags; + ng.bbox=bbox; + glyphs.push_back(ng); + + if (!(rflags & RS_RTL)) + cursor+=ePoint(xadvance, 0); + else + cursor-=ePoint(xadvance, 0); + previous=glyphIndex; + return 0; +} + +void eTextPara::calc_bbox() +{ + boundBox.setLeft( 32000 ); + boundBox.setTop( 32000 ); + boundBox.setRight( -32000 ); // for each glyph image, compute its bounding box, translate it, + boundBox.setBottom( -32000 ); + // and grow the string bbox + + for ( glyphString::iterator i(glyphs.begin()); i != glyphs.end(); ++i) + { + if ( i->bbox->left() < boundBox.left() ) + boundBox.setLeft( i->bbox->left() ); + if ( i->bbox->top() < boundBox.top() ) + boundBox.setTop( i->bbox->top() ); + if ( i->bbox->right() > boundBox.right() ) + boundBox.setRight( i->bbox->right() ); + if ( i->bbox->bottom() > boundBox.bottom() ) + boundBox.setBottom( i->bbox->bottom() ); + } +// eDebug("boundBox left = %i, top = %i, right = %i, bottom = %i", boundBox.left(), boundBox.top(), boundBox.right(), boundBox.bottom() ); + bboxValid=1; +} + +void eTextPara::newLine(int flags) +{ + if (!(flags & RS_RTL)) + { + if (maximum.width()size->metrics.height-(current_face->size->metrics.ascender+current_face->size->metrics.descender); + cursor+=ePoint(0, (current_face->size->metrics.ascender+current_face->size->metrics.descender+linegap*1/2)>>6); + if (maximum.height()=0) + eFatal("verdammt man der war noch gelockt :/\n"); +} + +void eTextPara::destroy() +{ + eLocker lock(refcntlck); + + if (!refcnt--) + delete this; +} + +eTextPara *eTextPara::grab() +{ + eLocker lock(refcntlck); + + refcnt++; + return this; +} + +void eTextPara::setFont(const gFont &font) +{ + if (refcnt) + eFatal("mod. after lock"); + setFont(fontRenderClass::getInstance()->getFont(font.family.c_str(), font.pointSize)); +} + +void eTextPara::setFont(Font *fnt) +{ + if (refcnt) + eFatal("mod. after lock"); + if (!fnt) + return; + if (current_font && !current_font->ref) + delete current_font; + current_font=fnt; + eLocker lock(ftlock); + + if (FTC_Manager_Lookup_Size(fontRenderClass::instance->cacheManager, ¤t_font->font.font, ¤t_face, ¤t_font->size)<0) + { + eDebug("FTC_Manager_Lookup_Size failed!"); + return; + } + cache_current_font=¤t_font->font.font; + previous=0; + use_kerning=FT_HAS_KERNING(current_face); +} + +int eTextPara::renderString(const eString &string, int rflags) +{ + eLocker lock(ftlock); + + if (refcnt) + eFatal("mod. after lock"); + + if (!current_font) + return -1; + + if (cursor.y()==-1) + { + if (!(rflags & RS_RTL)) + { + cursor=ePoint(area.x(), area.y()+(current_face->size->metrics.ascender>>6)); + } else + { + cursor=ePoint(area.right(), area.y()+(current_face->size->metrics.ascender>>6)); + } + left=cursor.x(); + } + + glyphs.reserve(glyphs.size()+string.length()); + + if (¤t_font->font.font != cache_current_font) + { + if (FTC_Manager_Lookup_Size(fontRenderClass::instance->cacheManager, ¤t_font->font.font, ¤t_face, ¤t_font->size)<0) + { + eDebug("FTC_Manager_Lookup_Size failed!"); + return -1; + } + cache_current_font=¤t_font->font.font; + } + + std::string::const_iterator p(string.begin()); + + while(p != string.end()) + { + int isprintable=1; + int flags=0; + + unsigned int unicode=*p++; + + if (unicode & 0x80) // we have (hopefully) UTF8 here, and we assume that the encoding is VALID + { + if ((unicode & 0xE0)==0xC0) // two bytes + { + unicode&=0x1F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + } else if ((unicode & 0xF0)==0xE0) // three bytes + { + unicode&=0x0F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + } else if ((unicode & 0xF8)==0xF0) // four bytes + { + unicode&=0x07; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + unicode<<=6; + if (p != string.end()) + unicode|=(*p++)&0x3F; + } + } + + if (!(rflags&RS_DIRECT)) + { + switch (unicode) + { + case '\t': + isprintable=0; + if (!(rflags & RS_RTL)) + { + cursor+=ePoint(current_font->tabwidth, 0); + cursor-=ePoint(cursor.x()%current_font->tabwidth, 0); + } else + { + // does this work? + cursor-=ePoint(current_font->tabwidth, 0); + cursor+=ePoint(cursor.x()%current_font->tabwidth, 0); + } + break; + case 0x8A: + case 0xE08A: + case '\n': + isprintable=0; + newLine(rflags); + flags|=GS_ISFIRST; + break; + case '\r': + case 0x86: case 0xE086: + case 0x87: case 0xE087: + isprintable=0; + break; + case ' ': + flags|=GS_ISSPACE; + default: + break; + } + } + if (isprintable) + { + FT_UInt index; + + index=(rflags&RS_DIRECT)? unicode : FT_Get_Char_Index(current_face, unicode); + + if (!index) + eDebug("unicode %d ('%c') not present", unicode, unicode); + else + appendGlyph(index, flags, rflags); + } + } + bboxValid=false; + calc_bbox(); + return 0; +} + +void eTextPara::blit(gPixmapDC &dc, const ePoint &offset, const gRGB &background, const gRGB &foreground) +{ + eLocker lock(ftlock); + + if (¤t_font->font.font != cache_current_font) + { + if (FTC_Manager_Lookup_Size(fontRenderClass::instance->cacheManager, ¤t_font->font.font, ¤t_face, ¤t_font->size)<0) + { + eDebug("FTC_Manager_Lookup_Size failed!"); + return; + } + cache_current_font=¤t_font->font.font; + } + + gPixmap &target=dc.getPixmap(); + + register int opcode; + gColor *lookup8=0; + __u32 lookup32[16]; + + if (target.bpp == 8) + { + if (target.clut.data) + { + lookup8=getColor(target.clut, background, foreground).lookup; + opcode=0; + } else + opcode=1; + } else if (target.bpp == 32) + { + opcode=3; + if (target.clut.data) + { + lookup8=getColor(target.clut, background, foreground).lookup; + for (int i=0; i<16; ++i) + lookup32[i]=((target.clut.data[lookup8[i]].a<<24)| + (target.clut.data[lookup8[i]].r<<16)| + (target.clut.data[lookup8[i]].g<<8)| + (target.clut.data[lookup8[i]].b))^0xFF000000; + } else + { + for (int i=0; i<16; ++i) + lookup32[i]=(0x010101*i)|0xFF000000; + } + } else + { + eWarning("can't render to %dbpp", target.bpp); + return; + } + + eRect clip(0, 0, target.x, target.y); + clip&=dc.getClip(); + + int buffer_stride=target.stride; + + for (glyphString::iterator i(glyphs.begin()); i != glyphs.end(); ++i) + { + FTC_SBit glyph_bitmap; + memset(&glyph_bitmap, 0, sizeof(glyph_bitmap)); + if (fontRenderClass::instance->getGlyphBitmap(&i->font->font, i->glyph_index, &glyph_bitmap)) + continue; + if (!glyph_bitmap->buffer) + eFatal("you suck."); + int rx=i->x+glyph_bitmap->left + offset.x(); + int ry=i->y-glyph_bitmap->top + offset.y(); + __u8 *d=(__u8*)(target.data)+buffer_stride*ry+rx*target.bypp; + __u8 *s=glyph_bitmap->buffer; + register int sx=glyph_bitmap->width; + int sy=glyph_bitmap->height; + if ((sy+ry) >= clip.bottom()) + sy=clip.bottom()-ry; + if ((sx+rx) >= clip.right()) + sx=clip.right()-rx; + if (rx < clip.left()) + { + int diff=clip.left()-rx; + s+=diff; + sx-=diff; + rx+=diff; + d+=diff*target.bypp; + } + if (ry < clip.top()) + { + int diff=clip.top()-ry; + s+=diff*glyph_bitmap->pitch; + sy-=diff; + ry+=diff; + d+=diff*buffer_stride; + } + if (sx>0) + for (int ay=0; ay>4; + if(b) + *td++=lookup8[b]; + else + td++; + } + } else if (opcode == 1) // 8bit direct + { + register __u8 *td=d; + register int ax; + for (ax=0; ax>4; + if(b) + *td++=lookup32[b]; + else + td++; + } + } + s+=glyph_bitmap->pitch-sx; + d+=buffer_stride; + } + } +} + +void eTextPara::realign(int dir) // der code hier ist ein wenig merkwuerdig. +{ + glyphString::iterator begin(glyphs.begin()), c(glyphs.begin()), end(glyphs.begin()), last; + if (dir==dirLeft) + return; + while (c != glyphs.end()) + { + int linelength=0; + int numspaces=0, num=0; + begin=end; + + // zeilenende suchen + do { + last=end; + ++end; + } while ((end != glyphs.end()) && (!(end->flags&GS_ISFIRST))); + // end zeigt jetzt auf begin der naechsten zeile + + for (c=begin; c!=end; ++c) + { + // space am zeilenende skippen + if ((c==last) && (c->flags&GS_ISSPACE)) + continue; + + if (c->flags&GS_ISSPACE) + numspaces++; + linelength+=c->w;; + num++; + } + if (!num) // line mit nur einem space + continue; + + switch (dir) + { + case dirRight: + case dirCenter: + { + int offset=area.width()-linelength; + if (dir==dirCenter) + offset/=2; + while (begin != end) + { + begin->x+=offset; + begin->bbox->moveBy(offset,0); + ++begin; + } + break; + } + case dirBlock: + { + if (end == glyphs.end()) // letzte zeile linksbuendig lassen + continue; + int spacemode; + if (numspaces) + spacemode=1; + else + spacemode=0; + if ((!spacemode) && (num<2)) + break; + int off=(area.width()-linelength)*256/(spacemode?numspaces:(num-1)); + int curoff=0; + while (begin != end) + { + int doadd=0; + if ((!spacemode) || (begin->flags&GS_ISSPACE)) + doadd=1; + begin->x+=curoff>>8; + begin->bbox->moveBy(curoff>>8,0); + if (doadd) + curoff+=off; + ++begin; + } + break; + } + } + } + bboxValid=false; +} + +void eTextPara::clear() +{ + eLocker lock(ftlock); + + for (glyphString::iterator i(glyphs.begin()); i!=glyphs.end(); ++i) + { + i->font->unlock(); + delete i->bbox; + } + glyphs.clear(); +} + +eAutoInitP0 init_fontRenderClass(1, "Font Render Class"); diff --git a/lib/gdi/font.h b/lib/gdi/font.h new file mode 100644 index 00000000..ac55c884 --- /dev/null +++ b/lib/gdi/font.h @@ -0,0 +1,163 @@ +#ifndef __FONT_H +#define __FONT_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class FontRenderClass; +class Font; +class gPixmapDC; +class gFont; +class gRGB; + +class fontRenderClass +{ + friend class Font; + friend class eTextPara; + fbClass *fb; + struct fontListEntry + { + eString filename, face; + int scale; // 100 is 1:1 + fontListEntry *next; + ~fontListEntry(); + } *font; + + FT_Library library; + FTC_Manager cacheManager; /* the cache manager */ + FTC_Image_Cache imageCache; /* the glyph image cache */ + FTC_SBit_Cache sbitsCache; /* the glyph small bitmaps cache */ + + FTC_FaceID getFaceID(const eString &face); + FT_Error getGlyphBitmap(FTC_Image_Desc *font, FT_ULong glyph_index, FTC_SBit *sbit); + static fontRenderClass *instance; +public: + float getLineHeight(const gFont& font); + eString AddFont(const eString &filename, const eString &name, int scale); + static fontRenderClass *getInstance(); + FT_Error FTC_Face_Requester(FTC_FaceID face_id, + FT_Face* aface); + Font *getFont(const eString &face, int size, int tabwidth=-1); + fontRenderClass(); + ~fontRenderClass(); +}; + +#define RS_WRAP 1 +#define RS_DOT 2 +#define RS_DIRECT 4 +#define RS_FADE 8 + +#define GS_ISSPACE 1 +#define GS_ISFIRST 2 +#define GS_USED 4 + +struct pGlyph +{ + int x, y, w; + Font *font; + FT_ULong glyph_index; + int flags; + eRect bbox; +}; + +typedef std::vector glyphString; + +class Font; +class eLCD; + +class eTextPara +{ + Font *current_font, *replacement_font; + FT_Face current_face, replacement_face; + int use_kerning; + int previous; + static eString replacement_facename; + + eRect area; + ePoint cursor; + eSize maximum; + int left; + glyphString glyphs; + int refcnt; + + int appendGlyph(Font *current_font, FT_Face current_face, FT_UInt glyphIndex, int flags, int rflags); + void newLine(int flags); + void setFont(Font *font, Font *replacement_font); + eRect boundBox; + void calc_bbox(); + int bboxValid; +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()), refcnt(0), bboxValid(0) + { + } + ~eTextPara(); + + static void setReplacementFont(eString font) { replacement_facename=font; } + + void destroy(); + eTextPara *grab(); + + void setFont(const gFont &font); + int renderString(const eString &string, int flags=0); + + void clear(); + + void blit(gPixmapDC &dc, const ePoint &offset, const gRGB &background, const gRGB &foreground); + + enum + { + dirLeft, dirRight, dirCenter, dirBlock + }; + + void realign(int dir); + + const eRect & getBoundBox() + { + if (!bboxValid) + calc_bbox(); + + return boundBox; + } + + const eRect& getGlyphBBox(int num) const + { + return glyphs[num].bbox; + } +}; + +class Font +{ +public: + FTC_Image_Desc font; + fontRenderClass *renderer; + int ref; + FT_Error getGlyphBitmap(FT_ULong glyph_index, FTC_SBit *sbit); + FT_Face face; + FT_Size size; + + int tabwidth; + int height; + Font(fontRenderClass *render, FTC_FaceID faceid, int isize, int tabwidth); + ~Font(); + + void lock(); + void unlock(); // deletes if ref==0 +}; + +extern fontRenderClass *font; + +#endif diff --git a/lib/gdi/font_arabic.cpp b/lib/gdi/font_arabic.cpp new file mode 100644 index 00000000..573f9fa2 --- /dev/null +++ b/lib/gdi/font_arabic.cpp @@ -0,0 +1,266 @@ +/* + * This was taken from pango. + * Modified for enigma by Felix Domke . + * I removed support for vowels and ligatures. Sorry. + * + * Original header: + * + * This is part of Pango - Arabic shaping module + * + * (C) 2000 Karl Koehler + * (C) 2001 Roozbeh Pournader + * + */ + +#include +#include + +typedef struct +{ + unsigned long basechar; + int count; + unsigned long charshape[4]; +} shapestruct; + +typedef struct +{ + unsigned long basechar; + char numshapes; +} charstruct; + +static void +charstruct_init (charstruct * s) +{ + s->basechar = 0; + s->numshapes = 1; +} + +#define connects_to_left(a) ((a).numshapes > 2) + +/* The Unicode order is always 'isolated, final, initial, medial'. */ + +/* *INDENT-OFF* */ +static shapestruct chartable[] = { + {0x0621, 1, {0xFE80}}, /* HAMZA */ + {0x0622, 2, {0xFE81, 0xFE82}}, /* ALEF WITH MADDA ABOVE */ + {0x0623, 2, {0xFE83, 0xFE84}}, /* ALEF WITH HAMZA ABOVE */ + {0x0624, 2, {0xFE85, 0xFE86}}, /* WAW WITH HAMZA ABOVE */ + {0x0625, 2, {0xFE87, 0xFE88}}, /* ALEF WITH HAMZA BELOW */ + {0x0626, 4, {0xFE89, 0xFE8A, 0xFE8B, 0xFE8C}}, /* YEH WITH HAMZA ABOVE */ + {0x0627, 2, {0xFE8D, 0xFE8E}}, /* ALEF */ + {0x0628, 4, {0xFE8F, 0xFE90, 0xFE91, 0xFE92}}, /* BEH */ + {0x0629, 2, {0xFE93, 0xFE94}}, /* TEH MARBUTA */ + {0x062A, 4, {0xFE95, 0xFE96, 0xFE97, 0xFE98}}, /* TEH */ + {0x062B, 4, {0xFE99, 0xFE9A, 0xFE9B, 0xFE9C}}, /* THEH */ + {0x062C, 4, {0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0}}, /* JEEM */ + {0x062D, 4, {0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4}}, /* HAH */ + {0x062E, 4, {0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8}}, /* KHAH */ + {0x062F, 2, {0xFEA9, 0xFEAA}}, /* DAL */ + {0x0630, 2, {0xFEAB, 0xFEAC}}, /* THAL */ + {0x0631, 2, {0xFEAD, 0xFEAE}}, /* REH */ + {0x0632, 2, {0xFEAF, 0xFEB0}}, /* ZAIN */ + {0x0633, 4, {0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4}}, /* SEEN */ + {0x0634, 4, {0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8}}, /* SHEEN */ + {0x0635, 4, {0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC}}, /* SAD */ + {0x0636, 4, {0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0}}, /* DAD */ + {0x0637, 4, {0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4}}, /* TAH */ + {0x0638, 4, {0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8}}, /* ZAH */ + {0x0639, 4, {0xFEC9, 0xFECA, 0xFECB, 0xFECC}}, /* AIN */ + {0x063A, 4, {0xFECD, 0xFECE, 0xFECF, 0xFED0}}, /* GHAIN */ + {0x0640, 4, {0x0640, 0x0640, 0x0640, 0x0640}}, /* TATWEEL */ + {0x0641, 4, {0xFED1, 0xFED2, 0xFED3, 0xFED4}}, /* FEH */ + {0x0642, 4, {0xFED5, 0xFED6, 0xFED7, 0xFED8}}, /* QAF */ + {0x0643, 4, {0xFED9, 0xFEDA, 0xFEDB, 0xFEDC}}, /* KAF */ + {0x0644, 4, {0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0}}, /* LAM */ + {0x0645, 4, {0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4}}, /* MEEM */ + {0x0646, 4, {0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8}}, /* NOON */ + {0x0647, 4, {0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC}}, /* HEH */ + {0x0648, 2, {0xFEED, 0xFEEE}}, /* WAW */ + {0x0649, 4, {0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}}, /* ALEF MAKSURA */ + {0x064A, 4, {0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4}}, /* YEH */ + {0x0671, 2, {0xFB50, 0xFB51}}, /* ALEF WASLA */ + {0x0679, 4, {0xFB66, 0xFB67, 0xFB68, 0xFB69}}, /* TTEH */ + {0x067A, 4, {0xFB5E, 0xFB5F, 0xFB60, 0xFB61}}, /* TTEHEH */ + {0x067B, 4, {0xFB52, 0xFB53, 0xFB54, 0xFB55}}, /* BEEH */ + {0x067E, 4, {0xFB56, 0xFB57, 0xFB58, 0xFB59}}, /* PEH */ + {0x067F, 4, {0xFB62, 0xFB63, 0xFB64, 0xFB65}}, /* TEHEH */ + {0x0680, 4, {0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D}}, /* BEHEH */ + {0x0683, 4, {0xFB76, 0xFB77, 0xFB78, 0xFB79}}, /* NYEH */ + {0x0684, 4, {0xFB72, 0xFB73, 0xFB74, 0xFB75}}, /* DYEH */ + {0x0686, 4, {0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D}}, /* TCHEH */ + {0x0687, 4, {0xFB7E, 0xFB7F, 0xFB80, 0xFB81}}, /* TCHEHEH */ + {0x0688, 2, {0xFB88, 0xFB89}}, /* DDAL */ + {0x068C, 2, {0xFB84, 0xFB85}}, /* DAHAL */ + {0x068D, 2, {0xFB82, 0xFB83}}, /* DDAHAL */ + {0x068E, 2, {0xFB86, 0xFB87}}, /* DUL */ + {0x0691, 2, {0xFB8C, 0xFB8D}}, /* RREH */ + {0x0698, 2, {0xFB8A, 0xFB8B}}, /* JEH */ + {0x06A4, 4, {0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D}}, /* VEH */ + {0x06A6, 4, {0xFB6E, 0xFB6F, 0xFB70, 0xFB71}}, /* PEHEH */ + {0x06A9, 4, {0xFB8E, 0xFB8F, 0xFB90, 0xFB91}}, /* KEHEH */ + {0x06AD, 4, {0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6}}, /* NG */ + {0x06AF, 4, {0xFB92, 0xFB93, 0xFB94, 0xFB95}}, /* GAF */ + {0x06B1, 4, {0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D}}, /* NGOEH */ + {0x06B3, 4, {0xFB96, 0xFB97, 0xFB98, 0xFB99}}, /* GUEH */ + {0x06BB, 4, {0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3}}, /* RNOON */ + {0x06BE, 4, {0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD}}, /* HEH DOACHASHMEE */ + {0x06C0, 2, {0xFBA4, 0xFBA5}}, /* HEH WITH YEH ABOVE */ + {0x06C1, 4, {0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9}}, /* HEH GOAL */ + {0x06C5, 2, {0xFBE0, 0xFBE1}}, /* KIRGHIZ OE */ + {0x06C6, 2, {0xFBD9, 0xFBDA}}, /* OE */ + {0x06C7, 2, {0xFBD7, 0xFBD8}}, /* U */ + {0x06C8, 2, {0xFBDB, 0xFBDC}}, /* YU */ + {0x06C9, 2, {0xFBE2, 0xFBE3}}, /* KIRGHIZ YU */ + {0x06CB, 2, {0xFBDE, 0xFBDF}}, /* VE */ + {0x06CC, 4, {0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF}}, /* FARSI YEH */ + {0x06D0, 4, {0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7}}, /* E */ + {0x06D2, 2, {0xFBAE, 0xFBAF}}, /* YEH BARREE */ + {0x06D3, 2, {0xFBB0, 0xFBB1}}, /* YEH BARREE WITH HAMZA ABOVE */ +}; + +#define ALEF 0x0627 +#define ALEFHAMZA 0x0623 +#define ALEFHAMZABELOW 0x0625 +#define ALEFMADDA 0x0622 +#define LAM 0x0644 +#define HAMZA 0x0621 +#define TATWEEL 0x0640 +#define ZWJ 0x200D + +#define HAMZAABOVE 0x0654 +#define HAMZABELOW 0x0655 + +#define WAWHAMZA 0x0624 +#define YEHHAMZA 0x0626 +#define WAW 0x0648 +#define ALEFMAKSURA 0x0649 +#define YEH 0x064A +#define FARSIYEH 0x06CC + +#define SHADDA 0x0651 +#define KASRA 0x0650 +#define FATHA 0x064E +#define DAMMA 0x064F +#define MADDA 0x0653 + +#define LAM_ALEF 0xFEFB +#define LAM_ALEFHAMZA 0xFEF7 +#define LAM_ALEFHAMZABELOW 0xFEF9 +#define LAM_ALEFMADDA 0xFEF5 + +static short +shapecount (unsigned long s) +{ + int l, r, m; + if ((s >= 0x0621) && (s <= 0x06D3)) + { + l = 0; + r = sizeof (chartable) / sizeof (shapestruct); + while (l <= r) + { + m = (l + r) / 2; + if (s == chartable[m].basechar) + { + return chartable[m].count; + } + else if (s < chartable[m].basechar) + { + r = m - 1; + } + else + { + l = m + 1; + } + } + } + else if (s == ZWJ) + { + return 4; + } + return 1; +} + +static unsigned long +charshape (unsigned long s, int which) +/* which 0=isolated 1=final 2=initial 3=medial */ +{ + int l, r, m; + if ((s >= 0x0621) && (s <= 0x06D3)) + { + l = 0; + r = sizeof (chartable) / sizeof (shapestruct); + while (l <= r) + { + m = (l + r) / 2; + if (s == chartable[m].basechar) + { + return chartable[m].charshape[which]; + } + else if (s < chartable[m].basechar) + { + r = m - 1; + } + else + { + l = m + 1; + } + } + } + else if ((s >= 0xFEF5) && (s <= 0xFEFB)) + { /* Lam+Alef */ + return s + which; + } + + return s; +} + +void +shape (std::vector &string, const std::vector &text) +{ + string.reserve(text.size()); + + charstruct oldchar, curchar; + int which; + unsigned long nextletter; + + charstruct_init (&oldchar); + charstruct_init (&curchar); + + for (std::vector::const_iterator i(text.begin()); + i != text.end(); ++i) + { + nextletter = *i; + int nc = shapecount (nextletter); + + if (nc == 1) + which = 0; /* final or isolated */ + else + which = 2; /* medial or initial */ + if (connects_to_left (oldchar)) + which++; + which = which % (curchar.numshapes); + curchar.basechar = charshape (curchar.basechar, which); + /* get rid of oldchar */ + if (oldchar.basechar) + string.push_back(oldchar.basechar); + oldchar = curchar; /* new values in oldchar */ + + /* init new curchar */ + charstruct_init (&curchar); + curchar.basechar = nextletter; + curchar.numshapes = nc; + } + + /* Handle last char */ + if (connects_to_left (oldchar)) + which = 1; + else + which = 0; + which = which % (curchar.numshapes); + curchar.basechar = charshape (curchar.basechar, which); + + if (oldchar.basechar != 0) + string.push_back(oldchar.basechar); + if (curchar.basechar != 0) + string.push_back(curchar.basechar); +} diff --git a/lib/gdi/gfbdc.cpp b/lib/gdi/gfbdc.cpp new file mode 100644 index 00000000..83f681d7 --- /dev/null +++ b/lib/gdi/gfbdc.cpp @@ -0,0 +1,166 @@ +#include + +#include +#include +#include + +gFBDC *gFBDC::instance; + +gFBDC::gFBDC() +{ + instance=this; + fb=new fbClass; + + if (!fb->Available()) + eFatal("no framebuffer available"); + + fb->SetMode(720, 576, 8); + for (int y=0; y<576; y++) // make whole screen transparent + memset(fb->lfb+y*fb->Stride(), 0x00, fb->Stride()); + + pixmap=new gPixmap(); + pixmap->x=720; + pixmap->y=576; + pixmap->bpp=8; + pixmap->bypp=1; + pixmap->stride=fb->Stride(); + pixmap->data=fb->lfb; + + pixmap->clut.colors=256; + pixmap->clut.data=new gRGB[pixmap->clut.colors]; + memset(pixmap->clut.data, 0, sizeof(*pixmap->clut.data)*pixmap->clut.colors); + reloadSettings(); +} + +gFBDC::~gFBDC() +{ + delete pixmap; + delete fb; + instance=0; +} + +void gFBDC::calcRamp() +{ +#if 0 + float fgamma=gamma ? gamma : 1; + fgamma/=10.0; + fgamma=1/log(fgamma); + for (int i=0; i<256; i++) + { + float raw=i/255.0; // IIH, float. + float corr=pow(raw, fgamma) * 256.0; + + int d=corr * (float)(256-brightness) / 256 + brightness; + if (d < 0) + d=0; + if (d > 255) + d=255; + ramp[i]=d; + + rampalpha[i]=i*alpha/256; + } +#endif + for (int i=0; i<256; i++) + { + int d; + d=i; + d=(d-128)*(gamma+64)/(128+64)+128; + d+=brightness-128; // brightness correction + if (d<0) + d=0; + if (d>255) + d=255; + ramp[i]=d; + +/* if ( eDVB::getInstance()->getmID == 1 ) + rampalpha[i]=i*alpha/65535; + else*/ + rampalpha[i]=i*alpha/256; + } + + rampalpha[255]=255; // transparent BLEIBT bitte so. +} + +void gFBDC::setPalette() +{ + if (!pixmap->clut.data) + return; + + for (int i=0; i<256; ++i) + { + fb->CMAP()->red[i]=ramp[pixmap->clut.data[i].r]<<8; + fb->CMAP()->green[i]=ramp[pixmap->clut.data[i].g]<<8; + fb->CMAP()->blue[i]=ramp[pixmap->clut.data[i].b]<<8; + fb->CMAP()->transp[i]=rampalpha[pixmap->clut.data[i].a]<<8; + if (!fb->CMAP()->red[i]) + fb->CMAP()->red[i]=0x100; + } + fb->PutCMAP(); +} + +void gFBDC::exec(gOpcode *o) +{ + switch (o->opcode) + { + case gOpcode::setPalette: + { + gPixmapDC::exec(o); + setPalette(); + break; + } + default: + gPixmapDC::exec(o); + break; + } +} + +gFBDC *gFBDC::getInstance() +{ + return instance; +} + +void gFBDC::setAlpha(int a) +{ + alpha=a; + + calcRamp(); + setPalette(); +} + +void gFBDC::setBrightness(int b) +{ + brightness=b; + + calcRamp(); + setPalette(); +} + +void gFBDC::setGamma(int g) +{ + gamma=g; + + calcRamp(); + setPalette(); +} + +void gFBDC::saveSettings() +{ + eConfig::getInstance()->setKey("/ezap/osd/alpha", alpha); + eConfig::getInstance()->setKey("/ezap/osd/gamma", gamma); + eConfig::getInstance()->setKey("/ezap/osd/brightness", brightness); +} + +void gFBDC::reloadSettings() +{ + if (eConfig::getInstance()->getKey("/ezap/osd/alpha", alpha)) + alpha=255; + if (eConfig::getInstance()->getKey("/ezap/osd/gamma", gamma)) + gamma=128; + if (eConfig::getInstance()->getKey("/ezap/osd/brightness", brightness)) + brightness=128; + + calcRamp(); + setPalette(); +} + +eAutoInitP0 init_gFBDC(eAutoInitNumbers::graphic+1, "GFBDC"); diff --git a/lib/gdi/gfbdc.h b/lib/gdi/gfbdc.h new file mode 100644 index 00000000..f975fb5f --- /dev/null +++ b/lib/gdi/gfbdc.h @@ -0,0 +1,35 @@ +#ifndef __gfbdc_h +#define __gfbdc_h + +#include "fb.h" +#include "gpixmap.h" +#include "grc.h" + +class gFBDC: public gPixmapDC +{ + fbClass *fb; + static gFBDC *instance; + void exec(gOpcode *opcode); + unsigned char ramp[256], rampalpha[256]; // RGB ramp 0..255 + int brightness, gamma, alpha; + void calcRamp(); + void setPalette(); +public: + void reloadSettings(); + void setAlpha(int alpha); + void setBrightness(int brightness); + void setGamma(int gamma); + + int getAlpha() { return alpha; } + int getBrightness() { return brightness; } + int getGamma() { return gamma; } + + void saveSettings(); + + gFBDC(); + ~gFBDC(); + static gFBDC *getInstance(); +}; + + +#endif diff --git a/lib/gdi/glcddc.cpp b/lib/gdi/glcddc.cpp new file mode 100644 index 00000000..3895df9a --- /dev/null +++ b/lib/gdi/glcddc.cpp @@ -0,0 +1,56 @@ +#ifndef DISABLE_LCD + +#include +#include + +gLCDDC *gLCDDC::instance; + +gLCDDC::gLCDDC(eLCD *lcd): lcd(lcd) +{ + instance=this; + + update=1; + + pixmap=new gPixmap(); + pixmap->x=lcd->size().width(); + pixmap->y=lcd->size().height(); + pixmap->bpp=8; + pixmap->bypp=1; + pixmap->stride=lcd->stride(); + pixmap->data=lcd->buffer(); + + pixmap->clut.colors=256; + pixmap->clut.data=0; +} + +gLCDDC::~gLCDDC() +{ + delete pixmap; + instance=0; +} + +void gLCDDC::exec(gOpcode *o) +{ + switch (o->opcode) + { + case gOpcode::flush: + case gOpcode::end: + if (update) + lcd->update(); + default: + gPixmapDC::exec(o); + break; + } +} + +gLCDDC *gLCDDC::getInstance() +{ + return instance; +} + +void gLCDDC::setUpdate(int u) +{ + update=u; +} + +#endif //DISABLE_LCD diff --git a/lib/gdi/glcddc.h b/lib/gdi/glcddc.h new file mode 100644 index 00000000..9342e5e2 --- /dev/null +++ b/lib/gdi/glcddc.h @@ -0,0 +1,26 @@ +#ifndef DISABLE_LCD + +#ifndef __glcddc_h +#define __glcddc_h + +#include "grc.h" + +class eLCD; + +class gLCDDC: public gPixmapDC +{ + eLCD *lcd; + static gLCDDC *instance; + int update; + void exec(gOpcode *opcode); +public: + gLCDDC(eLCD *lcd); + ~gLCDDC(); + void setUpdate(int update); + static gLCDDC *getInstance(); +}; + + +#endif + +#endif //DISABLE_LCD diff --git a/lib/gdi/gpixmap.cpp b/lib/gdi/gpixmap.cpp new file mode 100644 index 00000000..c089051d --- /dev/null +++ b/lib/gdi/gpixmap.cpp @@ -0,0 +1,295 @@ +#include + +gLookup::gLookup() +{ + size=0; + lookup=0; +} + +gLookup::gLookup(int size, const gPalette &pal, const gRGB &start, const gRGB &end) +{ + size=0; + lookup=0; + build(size, pal, start, end); +} + +void gLookup::build(int _size, const gPalette &pal, const gRGB &start, const gRGB &end) +{ + if (lookup) + { + delete lookup; + lookup=0; + size=0; + } + size=_size; + if (!size) + return; + lookup=new gColor[size]; + + for (int i=0; i= 0) goto AFTERNEGX; dX=-dX; // ndet und beheben kann. das liegt nicht zuletzt an den komment +fbXincr=-1; AFTERNEGX: fbYincr=stride; if ( (dY=By // aren. und ausserdem, je kuerzer der code, desto weniger k +-Ay) >= 0) goto AFTERNEGY; fbYincr=-stride; dY=-dY;AFTERNEGY: // ann daran falsch sein. erwaehnte ich schon, da +fbXYincr = fbXincr+fbYincr; if (dY > dX) goto YisIndependent; dPr = dY+ // s dieser tolle code wahnsinnig schnell +dY; P = -dX; dPru = P+P; dY = dX>>1; XLOOP: *AfbAddr=color; *BfbAddr=color; if ((P+=dPr) > 0) // ist? bye, tmbinc +goto RightAndUp; AfbAddr+=fbXincr; BfbAddr-=fbXincr; if ((dY=dY-1) > 0) goto XLOOP; *AfbAddr=color; if ((dX & 1) +== 0) return; *BfbAddr=color; return; RightAndUp: AfbAddr+=fbXYincr; BfbAddr-=fbXYincr; P+=dPru; if ((dY=dY-1) > +0) goto XLOOP; *AfbAddr=color; if ((dX & 1) == 0) return; *BfbAddr=color; return; YisIndependent: dPr = dX+dX; P += -dY; dPru = P+P; dX = dY>>1; YLOOP: *AfbAddr=color; *BfbAddr=color; if ((P+=dPr) > 0) goto RightAndUp2; AfbAddr ++=fbYincr; BfbAddr-=fbYincr; if ((dX=dX-1) > 0) goto YLOOP; *AfbAddr=color; if ((dY & 1) == 0) return; *BfbAddr= +color;return; RightAndUp2: AfbAddr+=fbXYincr; BfbAddr-=fbXYincr; P+=dPru; if ((dX=dX-1) > 0) goto YLOOP; *AfbAddr +=color; if((dY & 1) == 0) return; *BfbAddr=color; return; // nun ist der tolle code leider zu ende. tut mir leid. +} + +gColor gPalette::findColor(const gRGB &rgb) const +{ + int difference=1<<30, best_choice=0; + for (int t=0; t=difference) + continue; + td=(signed)(rgb.g-data[t].g); td*=td; td*=(255-data[t].a); + ttd+=td; + if (ttd>=difference) + continue; + td=(signed)(rgb.b-data[t].b); td*=td; td*=(255-data[t].a); + ttd+=td; + if (ttd>=difference) + continue; + td=(signed)(rgb.a-data[t].a); td*=td; td*=255; + ttd+=td; + if (ttd>=difference) + continue; + difference=ttd; + best_choice=t; + } + return best_choice; +} + +gPixmap::gPixmap() +{ +} + +gPixmap::~gPixmap() +{ +} + +gImage::gImage(eSize size, int _bpp) +{ + x=size.width(); + y=size.height(); + bpp=_bpp; + switch (bpp) + { + case 8: + bypp=1; + break; + case 15: + case 16: + bypp=2; + break; + case 24: // never use 24bit mode + case 32: + bypp=4; + break; + default: + bypp=(bpp+7)/8; + } + stride=x*bypp; + if (bpp==8) + { + clut.colors=256; + clut.data=new gRGB[clut.colors]; + } else + { + clut.colors=0; + clut.data=0; + } + data=new char[x*y*bypp]; +} + +gImage::~gImage() +{ + delete[] clut.data; + delete[] (char*)data; +} diff --git a/lib/gdi/gpixmap.h b/lib/gdi/gpixmap.h new file mode 100644 index 00000000..f68a5748 --- /dev/null +++ b/lib/gdi/gpixmap.h @@ -0,0 +1,142 @@ +#ifndef __gpixmap_h +#define __gpixmap_h + +#include +#include +#include +#include +#include + +#include + +struct gColor +{ + int color; + gColor(int color): color(color) + { + } + gColor(): color(0) + { + } + operator int() const { return color; } + bool operator==(const gColor &o) const { return o.color==color; } +}; + +struct gRGB +{ + int b, g, r, a; + gRGB(int r, int g, int b, int a=0): b(b), g(g), r(r), a(a) + { + } + gRGB(unsigned long val): b(val&0xFF), g((val>>8)&0xFF), r((val>>16)&0xFF), a((val>>24)&0xFF) // ARGB + { + } + gRGB() + { + } + bool operator < (const gRGB &c) const + { + if (b < c.b) + return 1; + if (b == c.b) + { + if (g < c.g) + return 1; + if (g == c.g) + { + if (r < c.r) + return 1; + if (r == c.r) + return a < c.a; + } + } + return 0; + } + bool operator==(const gRGB &c) const + { + return (b == c.b) && (g == c.g) && (r == c.r) && (a == c.a); + } +}; + +struct gPalette +{ + int start, colors; + gRGB *data; + gColor findColor(const gRGB &rgb) const; +}; + +struct gLookup +{ + int size; + gColor *lookup; + gLookup(int size, const gPalette &pal, const gRGB &start, const gRGB &end); + gLookup(); + void build(int size, const gPalette &pal, const gRGB &start, const gRGB &end); +}; + +/** + * \brief A softreference to a font. + * + * The font is specified by a name and a size. + * \c gFont is part of the \ref gdi. + */ +struct gFont +{ + eString family; + int pointSize; + + /** + * \brief Constructs a font with the given name and size. + * \param family The name of the font, for example "NimbusSansL-Regular Sans L Regular". + * \param pointSize the size of the font in PIXELS. + */ + gFont(const eString &family, int pointSize): + family(family), pointSize(pointSize) + { + } + + enum + { + tRegular, tFixed + }; + + gFont(int type, int pointSize); + + gFont() + :pointSize(0) + { + } +}; + +struct gPixmap: public iObject +{ +DECLARE_REF; +public: + int x, y, bpp, bypp, stride; + void *data; + + gPalette clut; + + eSize getSize() const { return eSize(x, y); } + + void fill(const eRect &area, const gColor &color); + + enum + { + blitAlphaTest=1 + }; + void blit(const gPixmap &src, ePoint pos, const eRect &clip=eRect(), int flags=0); + + void mergePalette(const gPixmap &target); + void line(ePoint start, ePoint end, gColor color); + gPixmap(); + virtual ~gPixmap(); +}; + +struct gImage: gPixmap +{ + gImage(eSize size, int bpp); + ~gImage(); +}; + +#endif diff --git a/lib/gdi/grc.cpp b/lib/gdi/grc.cpp new file mode 100644 index 00000000..3bd00782 --- /dev/null +++ b/lib/gdi/grc.cpp @@ -0,0 +1,348 @@ +// for debugging use: +// #define SYNC_PAINT +#include +#ifndef SYNC_PAINT +#include +#endif + +#include +#include +#include +#include + +#define MAXSIZE 1024 + +#ifndef SYNC_PAINT +void *gRC::thread_wrapper(void *ptr) +{ + nice(3); + return ((gRC*)ptr)->thread(); +} +#endif + +gRC *gRC::instance=0; + +gRC::gRC(): queuelock(MAXSIZE), queue(2048) +{ + ASSERT(!instance); + instance=this; + queuelock.lock(MAXSIZE); +#ifndef SYNC_PAINT + eDebug(pthread_create(&the_thread, 0, thread_wrapper, this)?"RC thread couldn't be created":"RC thread createted successfully"); +#endif +} + +gRC::~gRC() +{ + gOpcode o; + o.dc=0; + o.opcode=gOpcode::shutdown; + submit(o); + instance=0; +} + +void *gRC::thread() +{ +#ifndef SYNC_PAINT + while (1) +#else + while (queue.size()) +#endif + { + queuelock.lock(1); + gOpcode& o(queue.current()); + if (o.opcode==gOpcode::shutdown) + break; + o.dc->exec(&o); + queue.dequeue(); + } +#ifndef SYNC_PAINT + pthread_exit(0); +#endif + return 0; +} + +gRC &gRC::getInstance() +{ + return *instance; +} + +static int gPainter_instances; + +gPainter::gPainter(gDC &dc, eRect rect): dc(dc), rc(gRC::getInstance()), foregroundColor(0), backgroundColor(0) +{ + if (rect.isNull()) + rect=eRect(ePoint(0, 0), dc.getSize()); +// ASSERT(!gPainter_instances); + gPainter_instances++; + begin(rect); +} + +gPainter::~gPainter() +{ + end(); + gPainter_instances--; +} + +void gPainter::begin(const eRect &rect) +{ + gOpcode o; + dc.lock(); + o.dc=&dc; + o.opcode=gOpcode::begin; + o.parm.begin=new gOpcode::para::pbegin(rect); +// cliparea=std::stack >(); + cliparea=std::stack(); + cliparea.push(rect); + setLogicalZero(cliparea.top().topLeft()); + rc.submit(o); +} + +void gPainter::setBackgroundColor(const gColor &color) +{ + backgroundColor=color; +} + +void gPainter::setForegroundColor(const gColor &color) +{ + foregroundColor=color; +} + +void gPainter::setFont(const gFont &mfont) +{ + font=mfont; +} + +void gPainter::renderText(const eRect &pos, const std::string &string, int flags) +{ + eRect area=pos; + area.moveBy(logicalZero.x(), logicalZero.y()); + + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::renderText; + o.parm.renderText=new gOpcode::para::prenderText(font, area, string, dc.getRGB(foregroundColor), dc.getRGB(backgroundColor)); + o.flags=flags; + rc.submit(o); +} + +void gPainter::renderPara(eTextPara ¶, ePoint offset) +{ + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::renderPara; + o.parm.renderPara=new gOpcode::para::prenderPara(logicalZero+offset, para.grab(), dc.getRGB(foregroundColor), dc.getRGB(backgroundColor)); + rc.submit(o); +} + +void gPainter::fill(const eRect &area) +{ + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::fill; + eRect a=area; + a.moveBy(logicalZero.x(), logicalZero.y()); + a&=cliparea.top(); + + o.parm.fill=new gOpcode::para::pfill(a, foregroundColor); + rc.submit(o); +} + +void gPainter::clear() +{ + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::fill; + o.parm.fill=new gOpcode::para::pfill(cliparea.top(), backgroundColor); + rc.submit(o); +} + +void gPainter::setPalette(gRGB *colors, int start, int len) +{ + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::setPalette; + gPalette *p=new gPalette; + + p->data=new gRGB[len]; + memcpy(p->data, colors, len*sizeof(gRGB)); + p->start=start; + p->colors=len; + o.parm.setPalette=new gOpcode::para::psetPalette(p); + rc.submit(o); +} + +void gPainter::mergePalette(gPixmap *target) +{ + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::mergePalette; + o.parm.mergePalette=new gOpcode::para::pmergePalette(target); + rc.submit(o); +} + +void gPainter::line(ePoint start, ePoint end) +{ + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::line; + o.parm.line=new gOpcode::para::pline(start+logicalZero, end+logicalZero, foregroundColor); + rc.submit(o); +} + +void gPainter::setLogicalZero(ePoint rel) +{ + logicalZero=rel; +} + +void gPainter::moveLogicalZero(ePoint rel) +{ + logicalZero+=rel; +} + +void gPainter::resetLogicalZero() +{ + logicalZero.setX(0); + logicalZero.setY(0); +} + +void gPainter::clip(eRect clip) +{ + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::clip; + clip.moveBy(logicalZero.x(), logicalZero.y()); + cliparea.push(cliparea.top()&clip); + o.parm.clip=new gOpcode::para::pclip(cliparea.top()); + + rc.submit(o); +} + +void gPainter::clippop() +{ + ASSERT (cliparea.size()>1); + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::clip; + cliparea.pop(); + o.parm.clip=new gOpcode::para::pclip(cliparea.top()); + rc.submit(o); +} + +void gPainter::flush() +{ + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::flush; + rc.submit(o); +} + +void gPainter::end() +{ + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::end; + rc.submit(o); +} + +gDC::~gDC() +{ +} + +gPixmapDC::gPixmapDC(): pixmap(0) +{ +} + +gPixmapDC::gPixmapDC(gPixmap *pixmap): pixmap(pixmap) +{ +} + +gPixmapDC::~gPixmapDC() +{ + dclock.lock(); +} + +void gPixmapDC::exec(gOpcode *o) +{ + switch(o->opcode) + { + case gOpcode::begin: + clip=o->parm.begin->area; + delete o->parm.begin; + break; + case gOpcode::renderText: + { + eTextPara *para=new eTextPara(o->parm.renderText->area); + para->setFont(o->parm.renderText->font); + para->renderString(o->parm.renderText->text, o->flags); + para->blit(*this, ePoint(0, 0), o->parm.renderText->backgroundColor, o->parm.renderText->foregroundColor); + para->destroy(); + delete o->parm.renderText; + break; + } + case gOpcode::renderPara: + { + o->parm.renderPara->textpara->blit(*this, o->parm.renderPara->offset, o->parm.renderPara->backgroundColor, o->parm.renderPara->foregroundColor); + o->parm.renderPara->textpara->destroy(); + delete o->parm.renderPara; + break; + } + case gOpcode::fill: + pixmap->fill(o->parm.fill->area, o->parm.fill->color); + delete o->parm.fill; + break; + case gOpcode::blit: + { + if (o->parm.blit->clip.isNull()) + o->parm.blit->clip=clip; + else + o->parm.blit->clip&=clip; + pixmap->blit(*o->parm.blit->pixmap, o->parm.blit->position, o->parm.blit->clip, o->flags); + delete o->parm.blit; + break; + } + case gOpcode::setPalette: + if (o->parm.setPalette->palette->start>pixmap->clut.colors) + o->parm.setPalette->palette->start=pixmap->clut.colors; + if (o->parm.setPalette->palette->colors>(pixmap->clut.colors-o->parm.setPalette->palette->start)) + o->parm.setPalette->palette->colors=pixmap->clut.colors-o->parm.setPalette->palette->start; + if (o->parm.setPalette->palette->colors) + memcpy(pixmap->clut.data+o->parm.setPalette->palette->start, o->parm.setPalette->palette->data, o->parm.setPalette->palette->colors*sizeof(gRGB)); + delete[] o->parm.setPalette->palette->data; + delete o->parm.setPalette->palette; + delete o->parm.setPalette; + break; + case gOpcode::mergePalette: + pixmap->mergePalette(*o->parm.blit->pixmap); + delete o->parm.blit; + break; + case gOpcode::line: + pixmap->line(o->parm.line->start, o->parm.line->end, o->parm.line->color); + delete o->parm.line; + break; + case gOpcode::clip: + clip=o->parm.clip->clip; + delete o->parm.clip; + break; + case gOpcode::end: + unlock(); + case gOpcode::flush: + break; + default: + eFatal("illegal opcode %d. expect memory leak!", o->opcode); + } +} + +gRGB gPixmapDC::getRGB(gColor col) +{ + if ((!pixmap) || (!pixmap->clut.data)) + return gRGB(col, col, col); + if (col<0) + { + eFatal("bla transp"); + return gRGB(0, 0, 0, 0xFF); + } + return pixmap->clut.data[col]; +} + +eAutoInitP0 init_grc(eAutoInitNumbers::graphic, "gRC"); diff --git a/lib/gdi/grc.h b/lib/gdi/grc.h new file mode 100644 index 00000000..53cd4a8c --- /dev/null +++ b/lib/gdi/grc.h @@ -0,0 +1,245 @@ +#ifndef __grc_h +#define __grc_h + +/* + gPainter ist die high-level version. die highlevel daten werden zu low level opcodes ueber + die gRC-queue geschickt und landen beim gDC der hardwarespezifisch ist, meist aber auf einen + gPixmap aufsetzt (und damit unbeschleunigt ist). +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include + + +class eTextPara; + +class gDC; +struct gOpcode +{ + enum Opcode + { + begin, + + renderText, + renderPara, + + fill, + blit, + + setPalette, + mergePalette, + + line, + + clip, + + flush, + end, + + shutdown + } opcode; + + union para + { + struct pbegin + { + eRect area; + pbegin(const eRect &area): area(area) { } + } *begin; + + struct pfill + { + eRect area; + gColor color; + pfill(const eRect &area, gColor color): area(area), color(color) { } + } *fill; + + struct prenderText + { + gFont font; + eRect area; + eString text; + gRGB foregroundColor, backgroundColor; + prenderText(const gFont &font, const eRect &area, const eString &text, const gRGB &foregroundColor, const gRGB &backgroundColor): + font(font), area(area), text(text), foregroundColor(foregroundColor), backgroundColor(backgroundColor) { } + } *renderText; + + struct prenderPara + { + ePoint offset; + eTextPara *textpara; + gRGB foregroundColor, backgroundColor; + prenderPara(const ePoint &offset, eTextPara *textpara, const gRGB &foregroundColor, const gRGB &backgroundColor) + : offset(offset), textpara(textpara), foregroundColor(foregroundColor), backgroundColor(backgroundColor) { } + } *renderPara; + + struct psetPalette + { + gPalette *palette; + psetPalette(gPalette *palette): palette(palette) { } + } *setPalette; + + struct pblit + { + ePtr pixmap; + ePoint position; + eRect clip; + pblit(gPixmap *pixmap, const ePoint &position, const eRect &clip) + : pixmap(pixmap), position(position), clip(clip) { } + } *blit; + + struct pmergePalette + { + ePtr target; + pmergePalette(gPixmap *target): target(target) { } + } *mergePalette; + + struct pline + { + ePoint start, end; + gColor color; + pline(const ePoint &start, const ePoint &end, gColor color): start(start), end(end), color(color) { } + } *line; + + struct pclip + { + eRect clip; + pclip(const eRect &clip): clip(clip) { } + } *clip; + } parm; + + int flags; + + gDC *dc; +}; + +class gRC +{ + static gRC *instance; + + static void *thread_wrapper(void *ptr); + pthread_t the_thread; + void *thread(); + + eLock queuelock; + + queueRingBuffer queue; +public: + gRC(); + virtual ~gRC(); + + void submit(const gOpcode &o) + { + static int collected=0; + queue.enqueue(o); + collected++; + if (o.opcode==gOpcode::end) + { + queuelock.unlock(collected); +#ifdef SYNC_PAINT + thread(); +#endif + collected=0; + } + } + + static gRC &getInstance(); +}; + +class gPainter +{ + gDC &dc; + gRC &rc; + friend class gRC; + + gOpcode *beginptr; + /* paint states */ +// std::stack > cliparea; + std::stack cliparea; + gFont font; + gColor foregroundColor, backgroundColor; + ePoint logicalZero; + void begin(const eRect &rect); + void end(); +public: + gPainter(gDC &dc, eRect rect=eRect()); + virtual ~gPainter(); + + void setBackgroundColor(const gColor &color); + void setForegroundColor(const gColor &color); + + void setFont(const gFont &font); + void renderText(const eRect &position, const std::string &string, int flags=0); + void renderPara(eTextPara ¶, ePoint offset=ePoint(0, 0)); + + void fill(const eRect &area); + + void clear(); + + void gPainter::blit(gPixmap *pixmap, ePoint pos, eRect clip=eRect(), int flags=0) + { + gOpcode o; + o.dc=&dc; + o.opcode=gOpcode::blit; + pos+=logicalZero; + clip.moveBy(logicalZero.x(), logicalZero.y()); + o.parm.blit=new gOpcode::para::pblit(pixmap, pos, clip); + o.flags=flags; + rc.submit(o); + } + + void setPalette(gRGB *colors, int start=0, int len=256); + void mergePalette(gPixmap *target); + + void line(ePoint start, ePoint end); + + void setLogicalZero(ePoint abs); + void moveLogicalZero(ePoint rel); + void resetLogicalZero(); + + void clip(eRect clip); + void clippop(); + + void flush(); +}; + +class gDC +{ +protected: + eLock dclock; +public: + virtual void exec(gOpcode *opcode)=0; + virtual RESULT getPixmap(ePtr &)=0; + virtual eSize getSize()=0; + virtual const eRect &getClip()=0; + virtual gRGB getRGB(gColor col)=0; + virtual ~gDC(); + void lock() { dclock.lock(1); } + void unlock() { dclock.unlock(1); } +}; + +class gPixmapDC: public gDC +{ +protected: + ePtr pixmap; + eRect clip; + + void exec(gOpcode *opcode); + gPixmapDC(); +public: + gPixmapDC(gPixmap *pixmap); + virtual ~gPixmapDC(); + RESULT getPixmap(ePtr &ptr) { ptr = pixmap; return 0; } + gRGB getRGB(gColor col); + const eRect &getClip() { return clip; } + virtual eSize getSize() { return eSize(pixmap->x, pixmap->y); } +}; + +#endif diff --git a/lib/gdi/lcd.cpp b/lib/gdi/lcd.cpp new file mode 100644 index 00000000..844ad08f --- /dev/null +++ b/lib/gdi/lcd.cpp @@ -0,0 +1,210 @@ +#ifndef DISABLE_LCD + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +eDBoxLCD *eDBoxLCD::instance; + +eLCD::eLCD(eSize size): res(size) +{ + locked=0; + _buffer=new unsigned char[res.height()*res.width()]; + _stride=res.width(); +} + +eLCD::~eLCD() +{ + delete [] _buffer; +} + +int eLCD::lock() +{ + if (locked) + return -1; + + locked=1; + return lcdfd; +} + +void eLCD::unlock() +{ + read( lcdfd, NULL, 0); + if ( errno == 9 ) + { + eDebug("reopen lcd"); + lcdfd=open("/dev/dbox/lcd0", O_RDWR); // reopen device + } + else + eDebug("do not reopen lcd.. errno = %d", errno); + + locked=0; +} + +/* void eLCD::line(ePoint start, ePoint dst, int color) +{ +int Ax=start.x(), // dieser code rult ganz ganz doll weil er ganz ganz fast ist und auch sehr gut dokumentiert is +Ay=start.y(), Bx=dst.x(), // t. es handelt sich immerhin um den weltbekannten bresenham algorithmus der nicht nur +By=dst.y(); int dX, dY, fbXincr, // sehr schnell ist sondern auch sehr gut dokumentiert und getestet wurde. nicht +fbYincr, fbXYincr, dPr, dPru, P; __u8 // nur auf dem LCD der dbox, sondern auch ueberall anders. und auch auf der +*AfbAddr = &buffer()[Ay*stride()+Ax]; __u8 // dbox mit LCD soll das teil nun tun, und ich denke das tut es. ausse +*BfbAddr = &buffer()[By*stride()+Bx]; fbXincr= // rdem hat dieser algo den vorteil dass man fehler sehr leicht fi +1; if ( (dX=Bx-Ax) >= 0) goto AFTERNEGX; dX=-dX; // ndet und beheben kann. das liegt nicht zuletzt an den komment +fbXincr=-1; AFTERNEGX: fbYincr=stride(); if ( (dY=By // aren. und ausserdem, je kuerzer der code, desto weniger k +-Ay) >= 0) goto AFTERNEGY; fbYincr=-stride(); dY=-dY;AFTERNEGY: // ann daran falsch sein. erwaehnte ich schon, da +fbXYincr = fbXincr+fbYincr; if (dY > dX) goto YisIndependent; dPr = dY+ // s dieser tolle code wahnsinnig schnell +dY; P = -dX; dPru = P+P; dY = dX>>1; XLOOP: *AfbAddr=color; *BfbAddr=color; if ((P+=dPr) > 0) // ist? bye, tmbinc +goto RightAndUp; AfbAddr+=fbXincr; BfbAddr-=fbXincr; if ((dY=dY-1) > 0) goto XLOOP; *AfbAddr=color; if ((dX & 1) +== 0) return; *BfbAddr=color; return; RightAndUp: AfbAddr+=fbXYincr; BfbAddr-=fbXYincr; P+=dPru; if ((dY=dY-1) > +0) goto XLOOP; *AfbAddr=color; if ((dX & 1) == 0) return; *BfbAddr=color; return; YisIndependent: dPr = dX+dX; P += -dY; dPru = P+P; dX = dY>>1; YLOOP: *AfbAddr=color; *BfbAddr=color; if ((P+=dPr) > 0) goto RightAndUp2; AfbAddr ++=fbYincr; BfbAddr-=fbYincr; if ((dX=dX-1) > 0) goto YLOOP; *AfbAddr=color; if ((dY & 1) == 0) return; *BfbAddr= +color;return; RightAndUp2: AfbAddr+=fbXYincr; BfbAddr-=fbXYincr; P+=dPru; if ((dX=dX-1) > 0) goto YLOOP; *AfbAddr +=color; if((dY & 1) == 0) return; *BfbAddr=color; return; // nun ist der tolle code leider zu ende. tut mir leid. +} */ + +eDBoxLCD::eDBoxLCD(): eLCD(eSize(128, 64)) +{ +#ifndef NO_LCD + lcdfd=open("/dev/dbox/lcd0", O_RDWR); +#else + lcdfd=-1; +#endif + instance=this; + + if (lcdfd<0) + eDebug("couldn't open LCD - load lcd.o!"); + else + { + int i=LCD_MODE_BIN; + ioctl(lcdfd, LCD_IOCTL_ASC_MODE, &i); + int lcdbrightness=0, lcdcontrast=0; + + if( eConfig::getInstance()->getKey("/ezap/lcd/brightness", lcdbrightness) ) + { + lcdbrightness=130; + eConfig::getInstance()->setKey("/ezap/lcd/brightness", lcdbrightness); + } + if( eConfig::getInstance()->getKey("/ezap/lcd/contrast", lcdcontrast) ) + { + lcdcontrast=32; + eConfig::getInstance()->setKey("/ezap/lcd/contrast", lcdcontrast); + } + setLCDParameter(lcdbrightness, lcdcontrast); + int tmp; + if( eConfig::getInstance()->getKey("/ezap/lcd/inverted", tmp ) ) + { + inverted=0; + eConfig::getInstance()->setKey("/ezap/lcd/inverted", (int) 0 ); + } + else + inverted=(unsigned char)tmp; + } +} + +void eDBoxLCD::setInverted(unsigned char inv) +{ + inverted=inv; + update(); +} + +int eDBoxLCD::setLCDParameter(int brightness, int contrast) +{ + int fp; + if((fp=open("/dev/dbox/fp0", O_RDWR))<=0) + { + eDebug("[LCD] can't open /dev/dbox/fp0"); + return(-1); + } + + if(ioctl(lcdfd, LCD_IOCTL_SRV, &contrast)) + { + eDebug("[LCD] can't set lcd contrast"); + } + + if(ioctl(fp, FP_IOCTL_LCD_DIMM, &brightness)) + { + eDebug("[LCD] can't set lcd brightness"); + } + eDebug("[LCD] set brightness %d, contrast %d", brightness, contrast); + return(0); +} + +int eDBoxLCD::switchLCD(int state) +{ + int lcdbrightness, lcdcontrast, lcdstandby=0; + + eConfig::getInstance()->getKey("/ezap/lcd/contrast", lcdcontrast); + + if(state==0) + { + eConfig::getInstance()->getKey("/ezap/lcd/standby", lcdstandby); + setLCDParameter(lcdstandby, lcdcontrast); + } + else + { + eConfig::getInstance()->getKey("/ezap/lcd/brightness", lcdbrightness); + setLCDParameter(lcdbrightness, lcdcontrast); + + } + return(0); +} + +eDBoxLCD::~eDBoxLCD() +{ + if (lcdfd>0) + close(lcdfd); +} + +eDBoxLCD *eDBoxLCD::getInstance() +{ + return instance; +} + +void eDBoxLCD::update() +{ + if (!locked) + { + unsigned char raw[120*8]; + int x, y, yy; + for (y=0; y<8; y++) + { + for (x=0; x<120; x++) + { + int pix=0; + for (yy=0; yy<8; yy++) + { + pix|=(_buffer[(y*8+yy)*128+x]>=108)<0) + write(lcdfd, raw, 120*8); + } +} + +class eDBoxLCDHardware +{ + eDBoxLCD lcd; + gLCDDC lcddc; +public: + eDBoxLCDHardware(): lcddc(&lcd) + { + } +}; + +eAutoInitP0 init_eDBoxLCDHardware(eAutoInitNumbers::lowlevel, "d-Box LCD Hardware"); + +#endif //DISABLE_LCD diff --git a/lib/gdi/lcd.h b/lib/gdi/lcd.h new file mode 100644 index 00000000..567d0649 --- /dev/null +++ b/lib/gdi/lcd.h @@ -0,0 +1,53 @@ +#ifndef DISABLE_LCD + +#ifndef __lcd_h +#define __lcd_h + +#include +#include +#include + +#define LCD_CONTRAST_MIN 0 +#define LCD_CONTRAST_MAX 63 +#define LCD_BRIGHTNESS_MIN 0 +#define LCD_BRIGHTNESS_MAX 255 + +class eLCD +{ +protected: + eSize res; + unsigned char *_buffer; + int lcdfd; + int _stride; + int locked; +public: + int lock(); + void unlock(); + + eLCD(eSize size); + virtual ~eLCD(); + + __u8 *buffer() { return (__u8*)_buffer; } + int stride() { return _stride; } + eSize size() { return res; } + + virtual void update()=0; +}; + +class eDBoxLCD: public eLCD +{ + static eDBoxLCD *instance; + unsigned char inverted; +public: + static eDBoxLCD *getInstance(); + int switchLCD(int state); + int setLCDParameter(int brightness, int contrast); + void setInverted( unsigned char ); + eDBoxLCD(); + ~eDBoxLCD(); + void update(); +}; + +#endif + +#endif //DISABLE_LCD diff --git a/lib/gui/.cvsignore b/lib/gui/.cvsignore new file mode 100644 index 00000000..316b06f5 --- /dev/null +++ b/lib/gui/.cvsignore @@ -0,0 +1,7 @@ +*.moc.* +Makefile +Makefile.in +.deps +.libs +*.lo +*.la diff --git a/lib/gui/Makefile.am b/lib/gui/Makefile.am new file mode 100644 index 00000000..634f85b6 --- /dev/null +++ b/lib/gui/Makefile.am @@ -0,0 +1,13 @@ +INCLUDES = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src + +noinst_LIBRARIES = libenigma_gui.a + +libenigma_gui_a_SOURCES = \ + ebutton.cpp echeckbox.cpp elabel.cpp emessage.cpp \ + enumber.cpp eprogress.cpp eskin.cpp listbox.cpp eskin_register.cpp \ + ewidget.cpp ewindow.cpp multipage.cpp actions.cpp guiactions.cpp \ + decoration.cpp statusbar.cpp combobox.cpp numberactions.cpp slider.cpp \ + textinput.cpp testpicture.cpp + diff --git a/lib/gui/actions.cpp b/lib/gui/actions.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/actions.h b/lib/gui/actions.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/combobox.cpp b/lib/gui/combobox.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/combobox.h b/lib/gui/combobox.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/decoration.cpp b/lib/gui/decoration.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/decoration.h b/lib/gui/decoration.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/ebutton.cpp b/lib/gui/ebutton.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/ebutton.h b/lib/gui/ebutton.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/echeckbox.cpp b/lib/gui/echeckbox.cpp new file mode 100644 index 00000000..c41721ce --- /dev/null +++ b/lib/gui/echeckbox.cpp @@ -0,0 +1,138 @@ +#include + +#include +#include +#include +#include + +eCheckbox::eCheckbox(eWidget *parent, int checked, int takefocus, bool swapTxtPixmap, const char *deco) + :eButton(parent, 0, takefocus, deco), swapTxtPixmap(swapTxtPixmap) +{ + align=eTextPara::dirLeft; + ischecked = -1; + setCheck(checked); + CONNECT(selected, eCheckbox::sel); +} + +eCheckbox::~eCheckbox() +{ +} + +void eCheckbox::sel() +{ + setCheck(ischecked?0:1); + /*emit*/ checked(ischecked); +} + +void eCheckbox::gotFocus() +{ +#ifndef DISABLE_LCD + if (parent && parent->LCDElement) + { + LCDTmp = new eLabel(parent->LCDElement); + LCDTmp->hide(); + eSize s = parent->LCDElement->getSize(); + LCDTmp->move(ePoint(0,0)); + LCDTmp->resize(eSize(s.width(), s.height())); + ((eLabel*)LCDTmp)->setFlags(RS_WRAP); + ePtr pm; + eSkin::getActive()->queryImage(pm, ischecked?"eCheckboxLCD.checked":"eCheckboxLCD.unchecked"); + LCDTmp->setPixmap(pm); + ((eLabel*)LCDTmp)->pixmap_position=ePoint(0, (size.height()-15)/2); + ((eLabel*)LCDTmp)->text_position=ePoint(21, 0); + LCDTmp->setText(text); + LCDTmp->show(); + } +#endif + setForegroundColor(focusF, false); + setBackgroundColor(focusB); +// invalidate(); +} + +void eCheckbox::lostFocus() +{ +#ifndef DISABLE_LCD + if (LCDTmp) + { + delete LCDTmp; + LCDTmp = 0; + } +#endif + eButton::lostFocus(); +} + + +void eCheckbox::setCheck(int c) +{ + if (ischecked != -1 && ischecked == c) + return; + + ischecked=c; + + ePtr pixmap; + eSkin::getActive()->queryImage(pixmap, ischecked?"eCheckbox.checked":"eCheckbox.unchecked"); + setPixmap(pixmap); +#ifndef DISABLE_LCD + eSkin::getActive()->queryImage(pixmap, ischecked?"eCheckboxLCD.checked":"eCheckboxLCD.unchecked"); + if (LCDTmp) + LCDTmp->setPixmap(pixmap); +#endif +} + +int eCheckbox::setProperty(const eString &prop, const eString &value) +{ + if (prop=="swaptxtpixmap") + { + swapTxtPixmap = (value != "off"); + event( eWidgetEvent::changedSize ); + } + else + return eButton::setProperty(prop, value); + return 0; +} + +int eCheckbox::eventHandler(const eWidgetEvent &event) +{ + switch (event.type) + { + case eWidgetEvent::changedSize: + if (swapTxtPixmap) + { + text_position=ePoint(0,0); + eLabel::invalidate(); + validate(); + pixmap_position=ePoint( para->getBoundBox().right()+5, (size.height()-pixmap->y) / 2 ); + } + else + { + pixmap_position=ePoint(0, (size.height()-pixmap->y)/2); + text_position=ePoint((int)(pixmap->x*1.25), 0); + } + //return eButton::eventHandler(event); // changed Size must seen by eLabel... + break; + + default: + return eButton::eventHandler(event); + } + return 1; +} + +static eWidget *create_eCheckbox(eWidget *parent) +{ + return new eCheckbox(parent); +} + +class eCheckboxSkinInit +{ +public: + eCheckboxSkinInit() + { + eSkin::addWidgetCreator("eCheckbox", create_eCheckbox); + } + ~eCheckboxSkinInit() + { + eSkin::removeWidgetCreator("eCheckbox", create_eCheckbox); + } +}; + +eAutoInitP0 init_eCheckboxSkinInit(eAutoInitNumbers::guiobject, "eCheckbox"); diff --git a/lib/gui/echeckbox.h b/lib/gui/echeckbox.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/elabel.cpp b/lib/gui/elabel.cpp new file mode 100644 index 00000000..ae04eb46 --- /dev/null +++ b/lib/gui/elabel.cpp @@ -0,0 +1,253 @@ +#include + +#include +#include +#include +#include +#include +#include + +eLabel::eLabel(eWidget *parent, int flags, int takefocus, const char *deco ): + eDecoWidget(parent, takefocus, deco), blitFlags(0), flags(flags), + para(0), align( eTextPara::dirLeft ), shortcutPixmap(0) +{ +} + +eLabel::~eLabel() +{ + if (para) + { + para->destroy(); + para=0; + } +} + +void eLabel::setPixmapPosition( const ePoint &p ) +{ + pixmap_position = p; + invalidate(); +} + +void eLabel::validate( const eSize* s ) +{ + if (!para) + { + if (s) + para=new eTextPara( eRect(text_position.x(), text_position.y(), s->width() - text_position.x(), s->height() - text_position.y())); + else + para=new eTextPara( eRect(text_position.x(), text_position.y(), size.width() - text_position.x(), size.height() - text_position.y())); + + para->setFont(font); + para->renderString(text, flags); + para->realign(align); + } +} + +void eLabel::invalidate() +{ + if (para) + { + para->destroy(); + para=0; + } + if (isVisible()) + eDecoWidget::invalidate(); // we must redraw... +} + +void eLabel::setFlags(int flag) +{ + flags|=flag; + if (flag) + invalidate(); +} + +void eLabel::setBlitFlags( int flags ) +{ + blitFlags |= flags; +} + +void eLabel::removeFlags(int flag) +{ + flags &= ~flag; + if (flag) + invalidate(); +} + +void eLabel::setAlign(int align) +{ + this->align = align; + invalidate(); +} + +void eLabel::redrawWidget(gPainter *target, const eRect &rc) +{ +/* eDebug("decoStr = %s, text=%s, name=%s, %p left = %d, top = %d, width=%d, height = %d", strDeco?strDeco.c_str():"no", text?text.c_str():"no" , name?name.c_str():"no", this, this->getPosition().x(), this->getPosition().y(), this->getSize().width(), this->getSize().height() ); + eDebug("renderContext left = %d, top = %d, width = %d, height = %d", rc.left(), rc.top(), rc.width(), rc.height() );*/ + + target->clip( rc ); + eRect area=eRect(ePoint(0, 0), ePoint(width(), height())); +/* eDebug("area left = %d, top = %d, width = %d, height = %d", + area.left(), area.top(), + area.width(), area.height() );*/ + + if (deco_selected && have_focus) + { + deco_selected.drawDecoration(target, ePoint(width(), height())); + area=crect_selected; + } else if (deco) + { + deco.drawDecoration(target, ePoint(width(), height())); + area=crect; + } +/* eDebug("area left = %d, top = %d, width = %d, height = %d", + area.left(), area.top(), + area.width(), area.height() );*/ + + if (shortcutPixmap) + { + //area.setWidth(area.width()-area.height()); + area.setX(area.height()); + } + + if (text.length()) + { + if ( area.size().height() < size.height() || + area.size().width() < size.width() ) + { + // then deco is drawed + eSize s=area.size(); + validate( &s ); + } else + validate(); + + if (flags & flagVCenter) + yOffs = ( (area.height() - para->getBoundBox().height() ) / 2 + 0) - para->getBoundBox().top(); + else + yOffs = 0; + + eWidget *w; + if ((blitFlags & BF_ALPHATEST) && (transparentBackgroundColor >= 0)) + { + w=this; + target->setBackgroundColor(transparentBackgroundColor); + } else + { + w=getNonTransparentBackground(); + target->setBackgroundColor(w->getBackgroundColor()); + } + target->setFont(font); + target->renderPara(*para, ePoint( area.left(), area.top()+yOffs) ); + } + if (pixmap) + { +// eDebug("blit pixmap area left=%d, top=%d, right=%d, bottom=%d", rc.left(), rc.top(), rc.right(), rc.bottom() ); +// eDebug("pixmap_pos x = %d, y = %d, xsize=%d, ysize=%d", pixmap_position.x(), pixmap_position.y(), pixmap->x, pixmap->y ); + target->blit(pixmap, shortcutPixmap?pixmap_position+ePoint( area.left(), 0):pixmap_position, area, (blitFlags & BF_ALPHATEST) ? gPixmap::blitAlphaTest : 0); + } + if (shortcutPixmap) + target->blit(shortcutPixmap, + ePoint((area.height()-shortcutPixmap->x)/2, area.top()+(area.height()-shortcutPixmap->y)/2), + eRect(), + gPixmap::blitAlphaTest); + target->clippop(); +} + +int eLabel::eventHandler(const eWidgetEvent &event) +{ + switch (event.type) + { + case eWidgetEvent::changedFont: + case eWidgetEvent::changedText: + if (para) + { + para->destroy(); + para=0; + } + if ( have_focus && deco_selected ) + eDecoWidget::invalidate( crect_selected ); + else if ( deco ) + eDecoWidget::invalidate( crect ); + else + eDecoWidget::invalidate(); + break; + + case eWidgetEvent::changedSize: + invalidate(); + break; + + default: + return eDecoWidget::eventHandler(event); + break; + } + return 1; +} + +eSize eLabel::getExtend() +{ + validate(); + return eSize(para->getBoundBox().width()+(shortcutPixmap?shortcutPixmap->x*2:0), para->getBoundBox().height()); +} + +ePoint eLabel::getLeftTop() +{ + validate(); + return ePoint(para->getBoundBox().left(), para->getBoundBox().top()); +} + +int eLabel::setProperty(const eString &prop, const eString &value) +{ + if (prop=="wrap" && value == "on") + setFlags(RS_WRAP); + else if (prop=="alphatest" && value == "on") + { + transparentBackgroundColor=getBackgroundColor(); + setBackgroundColor(-1); + blitFlags |= BF_ALPHATEST; + } else if (prop=="align") + { + if (value=="left") + setAlign(eTextPara::dirLeft); + else if (value=="center") + setAlign(eTextPara::dirCenter); + else if (value=="right") + setAlign(eTextPara::dirRight); + else if (value=="block") + setAlign(eTextPara::dirBlock); + else + setAlign(eTextPara::dirLeft); + } + else if (prop=="vcenter") + setFlags( flagVCenter ); + else if (prop == "shortcut") + { + setShortcutPixmap(value); + return eWidget::setProperty(prop, value); + } else + return eDecoWidget::setProperty(prop, value); + return 0; +} + +void eLabel::setShortcutPixmap(const eString &shortcut) +{ + eSkin::getActive()->queryImage(shortcutPixmap, "shortcut." + shortcut); +} + +static eWidget *create_eLabel(eWidget *parent) +{ + return new eLabel(parent); +} + +class eLabelSkinInit +{ +public: + eLabelSkinInit() + { + eSkin::addWidgetCreator("eLabel", create_eLabel); + } + ~eLabelSkinInit() + { + eSkin::removeWidgetCreator("eLabel", create_eLabel); + } +}; + +eAutoInitP0 init_eLabelSkinInit(eAutoInitNumbers::guiobject, "eLabel"); diff --git a/lib/gui/elabel.h b/lib/gui/elabel.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/emessage.cpp b/lib/gui/emessage.cpp new file mode 100644 index 00000000..388eb14a --- /dev/null +++ b/lib/gui/emessage.cpp @@ -0,0 +1,163 @@ +#include + +#include +#include +#include +#include +#include + +eMessageBox::eMessageBox(eString message, eString caption, int flags, int def): eWindow(0), icon(0) +{ + setText(caption); + int fontsize=eSkin::getActive()->queryValue("fontsize", 20); + int posx = eSkin::getActive()->queryValue("eMessageBox.pos.x", 100); + int posy = eSkin::getActive()->queryValue("eMessageBox.pos.y", 70); + move(ePoint(posx, posy)); + resize(eSize(450, 430)); + + if ( flags > 15 ) // we have to draw an icon + { + ePtr pm; + switch ( flags & ~15 ) + { + case iconInfo: + eSkin::getActive()->queryImage(pm, "icon_info" ); + break; + case iconQuestion: + eSkin::getActive()->queryImage(pm, "icon_question" ); + break; + case iconWarning: + eSkin::getActive()->queryImage(pm, "icon_warning" ); + break; + case iconError: + eSkin::getActive()->queryImage(pm, "icon_error" ); + break; + } + if (pm) + { + icon = new eLabel(this); + icon->setPixmap( pm ); + icon->pixmap_position=ePoint(0,0); + icon->resize( eSize(pm->x, pm->y) ); + icon->setBlitFlags( BF_ALPHATEST ); + } + } + + text=new eLabel(this); + text->setText(message); + text->resize( eSize( clientrect.width(), clientrect.height() )); + text->setFlags( RS_WRAP|eLabel::flagVCenter ); + eSize txtSize=text->getExtend(); + txtSize+=eSize(8,4); // the given Size of the Text is okay... but the renderer sucks... + text->resize(txtSize); + + // here the two labels ( icon, text) has the correct size.. now we calc the border + + eSize ext; + + if ( icon ) + { + if ( icon->getSize().height() > text->getSize().height() ) + { + eDebug("icon is higher"); + eSize s = icon->getSize(); + icon->move( ePoint( 20, 20 ) ); + text->move( ePoint( 20 + s.width() + 20, icon->getPosition().y() + s.height() / 2 - txtSize.height() / 2 ) ); + ext.setHeight( icon->getPosition().y() + icon->getSize().height() + 20 ); + } + else + { + eDebug("text is higher"); + text->move( ePoint( 20 + icon->getSize().width() + 20 , 20 ) ); + icon->move( ePoint( 20, text->getPosition().y() + text->getSize().height() / 2 - icon->getSize().height() / 2 ) ); + ext.setHeight( text->getPosition().y() + text->getSize().height() + 20 ); + } + ext.setWidth( text->getPosition().x() + text->getSize().width() + 20 ); + } + else + { + text->move( ePoint(20, 20) ); + ext.setWidth( text->getPosition().x() + text->getSize().width()+20 ); + ext.setHeight( text->getPosition().y() + text->getSize().height() + 20 ); + } + + if (ext.width()<150) + ext.setWidth(150); + + int xpos=20; + + if ( flags & 15) + { + for (int i=btOK; iresize(eSize(size.width(), fontsize+4)); + const char *t="", *shortcut=""; + switch (i) + { + case btOK: t=_("OK"); shortcut="green"; CONNECT(b->selected, eMessageBox::pressedOK); break; + case btCancel: t=_("Cancel"); shortcut="red"; CONNECT(b->selected, eMessageBox::pressedCancel); break; + case btYes: t=_("Yes"); shortcut="green"; CONNECT(b->selected, eMessageBox::pressedYes); break; + case btNo: t=_("No"); shortcut="red"; CONNECT(b->selected, eMessageBox::pressedNo); break; + } + b->setProperty("shortcut", shortcut); + b->setText(t); + eSize bSize=b->getExtend(); + bSize.setWidth( bSize.width() * 2 ); + bSize.setHeight( fontsize + 4 + 10 ); + b->resize(bSize); + b->move( ePoint( xpos, ext.height() ) ); + + b->loadDeco(); + + if (def == i) + setFocus(b); + + xpos += bSize.width()+20; + if ( xpos+20 > ext.width() ) + cresize( eSize( xpos+20, ext.height() + bSize.height() + 20 ) ); + else + cresize( eSize( ext.width(), ext.height() + bSize.height() + 20 ) ); + } + } + else + cresize( ext ); + zOrderRaise(); +} + +eMessageBox::~eMessageBox() +{ +} + +void eMessageBox::pressedOK() +{ + if ( in_loop ) + close(btOK); + else + hide(); +} + +void eMessageBox::pressedCancel() +{ + if ( in_loop ) + close(btCancel); + else + hide(); +} + +void eMessageBox::pressedYes() +{ + if ( in_loop ) + close(btYes); + else + hide(); +} + +void eMessageBox::pressedNo() +{ + if ( in_loop ) + close(btNo); + else + hide(); +} diff --git a/lib/gui/emessage.h b/lib/gui/emessage.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/enumber.cpp b/lib/gui/enumber.cpp new file mode 100644 index 00000000..c03ec8f7 --- /dev/null +++ b/lib/gui/enumber.cpp @@ -0,0 +1,447 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +void eNumber::unpack(__u32 l, int *t) +{ + for (int i=0; i<4; i++) + *t++=(l>>((3-i)*8))&0xFF; +} + +void eNumber::pack(__u32 &l, int *t) +{ + l=0; + for (int i=0; i<4; i++) + l|=(*t++)<<((3-i)*8); +} + +eRect eNumber::getNumberRect(int n) +{ + if (deco_selected && have_focus) + return eRect( deco_selected.borderLeft + n * space_selected, deco_selected.borderTop, dspace, crect_selected.height() ); + else if (deco) + return eRect( deco.borderLeft + n * dspace, deco.borderTop, dspace, crect.height() ); + else + return eRect( n * dspace, 0, dspace, height() ); +} + +void eNumber::redrawNumber(gPainter *p, int n, const eRect &area) +{ + eRect pos = getNumberRect(n); + + if (!area.contains(pos) ) + return; + + p->setForegroundColor((have_focus && n==active)?cursorB:normalB); + p->fill(pos); + p->setFont(font); + + eString t; + if (flags & flagFillWithZeros || ( (flags & flagFixedNum) && n )) + { + eString s = "%0"+eString().setNum(maxdigits)+(base==10?"d":"X"); + const char* p = s.c_str(); + char* tmp = new char[10]; + strcpy( tmp, p ); + t.sprintf(tmp, number[n]); + delete [] tmp; + } + else + { + if (flags&flagHideInput) + t="*"; + else if (base==10) + t.sprintf("%d", number[n]); + else if (base==0x10) + t.sprintf("%X", number[n]); + } + + if (!n && flags & flagPosNeg && neg) + t="-"+t; + + if (n && (flags & flagTime)) + t=":"+t; + + else if (n && ( (flags & flagDrawPoints) || (flags & flagFixedNum)) ) + t="."+t; + + p->setForegroundColor((have_focus && n==active)?cursorF:normalF); + p->setBackgroundColor((have_focus && n==active)?cursorB:normalB); + + p->clip( pos ); + if (!n && len==2 && ((flags & flagFixedNum) || (flags & flagTime)) ) // first element... + { + eTextPara *para = new eTextPara( pos ); + para->setFont( font ); + para->renderString( t ); + para->realign( eTextPara::dirRight ); + p->renderPara( *para ); + para->destroy(); + } + else + p->renderText(pos, t); + + p->clippop(); +} + +double eNumber::getFixedNum() +{ + if (flags & flagFixedNum) + { + if (flags&flagPosNeg && neg) + { + double d = -((double)number[0]+(double)number[1]/1000); + eDebug("getFixedNum %lf", d); + return d; + } + else + { + float d = (double)number[0]+(double)number[1]/1000; + eDebug("getFixedNum %lf", d); + return d; + } + } + else + return 0; +} + +void eNumber::setFixedNum(double d) +{ + eDebug("setFixedNum %lf", d); + if (flags & flagPosNeg) + neg=d<0; + else + neg=0; + + d=fabs(d); + + if (flags & flagFixedNum) + { + number[0]=(int)d; + number[1]=(int)round(( ( d - number[0] ) * 1000) ); + } + else + eDebug("eNumber bug... the Number %s is not a fixed Point number", name.c_str()); +} + +void eNumber::redrawWidget(gPainter *p, const eRect &area) +{ + for (int i=0; ieventHandler(event); +#endif + switch (event.type) + { + case eWidgetEvent::changedSize: + if (deco) + dspace = (crect.width()) / len; + else + dspace = (size.width()) / len; + if (deco_selected) + space_selected = (crect_selected.width()) / len; + break; + case eWidgetEvent::evtAction: + if ( len > 1 && event.action == &i_cursorActions->left) + { + int oldac=active; + active--; + invalidate(getNumberRect(oldac)); + if (active<0) + active=len-1; + if (active!=oldac) + invalidate(getNumberRect(active)); + digit=0; + } else if ( len > 1 && (event.action == &i_cursorActions->right) || (event.action == &i_cursorActions->ok)) + { + int oldac=active; + active++; + invalidate(getNumberRect(oldac)); + if (active>=len) + { + if (event.action == &i_cursorActions->ok) + /*emit*/ selected(number); + active=0; + } + if (active!=oldac) + invalidate(getNumberRect(active)); + digit=0; + } else + break; + return 1; + default: + break; + } + return eDecoWidget::eventHandler(event); +} + +// isactive is the digit (always in the first field ) +// that ist active after get the first focus ! + +eNumber::eNumber(eWidget *parent, int _len, int _min, int _max, int _maxdigits, int *init, int isactive, eWidget* descr, int grabfocus, const char *deco) + :eDecoWidget(parent, grabfocus, deco ), + active(0), + cursorB(eSkin::getActive()->queryScheme("global.selected.background")), + cursorF(eSkin::getActive()->queryScheme("global.selected.foreground")), + normalB(eSkin::getActive()->queryScheme("global.normal.background")), + normalF(eSkin::getActive()->queryScheme("global.normal.foreground")), + have_focus(0), digit(isactive), isactive(isactive), flags(0), descr(descr), tmpDescr(0), + neg(false) +{ + setNumberOfFields(_len); + setLimits(_min, _max); + setMaximumDigits(_maxdigits); + setBase(10); + for (int i=0; init && imap); +} + +eNumber::~eNumber() +{ +} + +int eNumber::keyDown(int key) +{ +#ifndef DISABLE_LCD + if (LCDTmp) + ((eNumber*) LCDTmp)->keyDown(key); +#endif + switch (key) + { + case eRCInput::RC_0 ... eRCInput::RC_9: + { + int nn=(digit!=0)?number[active]*10:0; + nn+=key-eRCInput::RC_0; + if (flags & flagTime) + { + if ( active ) + max = 59; + else + max = 23; + } + else if (flags & flagFixedNum) + { + if (active) + max=999; + else + max=oldmax; + } + if (nn>=min && nn<=max) + { + number[active]=nn; + invalidate(getNumberRect(active)); + digit++; + if ((digit>=maxdigits) || (nn==0)) + { + active++; + invalidate(getNumberRect(active-1)); + digit=0; + /*emit*/ numberChanged(); + if (active>=len) + { + /*emit*/ selected(number); + active=0; + } + else + invalidate(getNumberRect(active)); + } + } + break; + + break; + } + case eRCInput::RC_PLUS: + if (flags & flagPosNeg && neg ) + { + neg=false; + invalidate(getNumberRect(0)); + } + break; + + case eRCInput::RC_MINUS: + if (flags & flagPosNeg && !neg ) + { + neg=true; + invalidate(getNumberRect(0)); + } + default: + return 0; + } + return 1; +} + +void eNumber::gotFocus() +{ + have_focus++; + digit=isactive; + + if (deco && deco_selected) + invalidate(); + else + invalidate(getNumberRect(active)); + +#ifndef DISABLE_LCD + if (parent && parent->LCDElement) // detect if LCD Avail + { + LCDTmp = new eNumber(parent->LCDElement, len, min, max, maxdigits, &(number[0]), isactive, 0, 0); + LCDTmp->hide(); + ((eNumber*)LCDTmp)->setFlags(flags); + eSize s = parent->LCDElement->getSize(); + + if (descr) + { + LCDTmp->move(ePoint(0,s.height()/2)); + LCDTmp->resize(eSize(s.width(), s.height()/2)); + tmpDescr = new eLabel(parent->LCDElement); + tmpDescr->hide(); + tmpDescr->move(ePoint(0,0)); + tmpDescr->resize(eSize(s.width(), s.height()/2)); + tmpDescr->setText(descr->getText()); + tmpDescr->show(); + } + else + { + LCDTmp->resize(s); + LCDTmp->move(ePoint(0,0)); + } + ((eNumber*)LCDTmp)->digit=digit; + ((eNumber*)LCDTmp)->active=active; + ((eNumber*)LCDTmp)->normalF=255; + ((eNumber*)LCDTmp)->normalB=0; + ((eNumber*)LCDTmp)->cursorF=0; + ((eNumber*)LCDTmp)->cursorB=255; + ((eNumber*)LCDTmp)->have_focus=1; + LCDTmp->show(); + } + #endif //DISABLE_LCD +} + +void eNumber::lostFocus() +{ +#ifndef DISABLE_LCD + if (LCDTmp) + { + delete LCDTmp; + LCDTmp=0; + if (tmpDescr) + { + delete tmpDescr; + tmpDescr=0; + } + } +#endif + have_focus--; + + if (deco && deco_selected) + invalidate(); + else + invalidate(getNumberRect(active)); + isactive=0; +} + +void eNumber::setNumber(int f, int n) +{ + if (flags & flagPosNeg) + { + if(!f && n<0) + neg=true; + else + neg=false; + } + else + neg=false; + + if ((f>=0) && (f 16) + n=16; + maxdigits=n; + if (digit >= maxdigits) + digit=0; +} + +void eNumber::setFlags(int _flags) +{ + if (flags&flagFixedNum) + len=2; + + flags=_flags; +} + +void eNumber::setBase(int _base) +{ + base=_base; +} + +void eNumber::setNumber(int n) +{ + if ( flags&flagPosNeg ) + neg = n < 0; + else + neg=0; + + if( len == 1 ) + number[0]=abs(n); + else + for (int i=len-1; i>=0; --i) + { + number[i]=n%base; + n/=base; + } + invalidateNum(); +} + +int eNumber::getNumber() +{ + int n=0; + for (int i=0; i +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +std::map< eString,tWidgetCreator > eSkin::widget_creator; + +eSkin *eSkin::active; + +eNamedColor *eSkin::searchColor(const eString &name) +{ + for (std::list::iterator i(colors.begin()); i != colors.end(); ++i) + { + if (!i->name.compare(name)) + return &*i; + } + return 0; +} + +void eSkin::clear() +{ +} + +void eSkin::addWidgetCreator(const eString &name, tWidgetCreator creator) +{ + widget_creator[name] = creator; // add this tWidgetCreator to map... if exist.. overwrite +} + +void eSkin::removeWidgetCreator(const eString &name, tWidgetCreator creator) +{ + widget_creator.erase(name); +} + +int eSkin::parseColor(const eString &name, const char* color, gRGB &col) +{ + if (color[0]=='#') + { + unsigned long vcol=0; + if (sscanf(color+1, "%lx", &vcol)!=1) + { + eDebug("invalid color named \"%s\" (value: %s)", name.c_str(), color+1); + return -1; + } + col.r=(vcol>>16)&0xFF; + col.g=(vcol>>8)&0xFF; + col.b=vcol&0xFF; + col.a=(vcol>>24)&0xFF; + } else + { + eNamedColor *n=searchColor(color); + if (!n) + { + eDebug("invalid color named \"%s\" (alias to: \"%s\")", name.c_str(), color); + return -1; + } + col=n->value; + } + return 0; +} + +int eSkin::parseColors(XMLTreeNode *xcolors) +{ + XMLTreeNode *node; + + std::list::iterator newcolors=colors.end(); + + for (node=xcolors->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "color")) + { + eDebug("junk found in colorsection (%s)", node->GetType()); + continue; + } + + const char *name=node->GetAttributeValue("name"), *color=node->GetAttributeValue("color"), *end=node->GetAttributeValue("end"); + + if (!color || !name) + { + eDebug("no color/name specified"); + continue; + } + + eNamedColor col; + col.name=name; + + const char *size=node->GetAttributeValue("size"); + + if (size) + col.size=atoi(size); + else + col.size=0; + + if (!col.size) + col.size=1; + + if ((col.size>1) && (!end)) + { + eDebug("no end specified in \"%s\" but is gradient", name); + continue; + } + + if (parseColor(name, color, col.value)) + continue; + + if (end && parseColor(name, end, col.end)) + continue; + + colors.push_back(col); + if (newcolors == colors.end()) + --newcolors; + } + + for (std::list::iterator i(newcolors); i != colors.end(); ++i) + { + eNamedColor &col=*i; + int d; + for (d=0; dmaxcolors) || colorused[d+s]) + break; + if (s==col.size) + break; + } + if (d==maxcolors) + continue; + col.index=gColor(d); + for (int s=0; sGetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "map")) + { + eDebug("illegal scheme entry found: %s", node->GetType()); + continue; + } + char *name=node->GetAttributeValue("name"), *color=node->GetAttributeValue("color"); + if (!name || !color) + { + eDebug("no name or color specified in colorscheme"); + continue; + } + eString base=color; + int offset=0, p; + if ((p=base.find('+'))!=-1) + { + offset=atoi(base.mid(p).c_str()); + base=base.left(p); + } + eNamedColor *n=searchColor(base); + if (!n) + { + eDebug("illegal color \"%s\" specified", base.c_str()); + continue; + } + scheme[name] = gColor(n->index+offset); + } + return 0; +} + +int eSkin::parseFontAlias(XMLTreeNode *xscheme) +{ + XMLTreeNode *node; + for (node=xscheme->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "map")) + { + eDebug("illegal fontalias entry found: %s", node->GetType()); + continue; + } + char *font=node->GetAttributeValue("font"), + *name=node->GetAttributeValue("name"), + *size=node->GetAttributeValue("size"); + + if (!name || !font || !size) + { + eDebug("no name, alias or size spezified in fontaliase"); + continue; + } + + std::map::iterator it = fontAlias.find(name); + if (it != fontAlias.end()) + continue; + + std::map::iterator i = fonts.find(font); + if (i == fonts.end()) + { + eDebug("font %s not found, skip make alias %s", font, name); + continue; + } + fontAlias[name]=gFont(i->second, atoi(size)); + } + return 0; +} + +int eSkin::parseImages(XMLTreeNode *inode) +{ + char *abasepath=inode->GetAttributeValue("basepath"); + if (!abasepath) + abasepath=""; + eString basepath=eString("/enigma/pictures/"); + if (abasepath[0] == '/') // allow absolute paths + basepath=""; + basepath+=abasepath; + if (basepath[basepath.length()-1]!='/') + basepath+="/"; + + for (XMLTreeNode *node=inode->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "img")) + { + eDebug("illegal image entry found: %s", node->GetType()); + continue; + } + const char *name=node->GetAttributeValue("name"); + if (!name) + { + eDebug("illegal entry: no name"); + continue; + } + const char *src=node->GetAttributeValue("src"); + if (!src) + { + eDebug("image/img=\"%s\" no src given", name); + continue; + } + std::map >::iterator it = images.find(name); + if (it != images.end()) + { +// eDebug("Image with name %s already loaded, skip %s", name, src); + continue; + } + ePtr image=0; + eString filename=basepath + eString(src); + if (abasepath[0] != '/') + { + // search first in CONFIGDIR + image=loadPNG((eString(CONFIGDIR)+filename).c_str()); + if (!image) + image=loadPNG((eString(DATADIR)+filename).c_str()); + } + else // abs path + image=loadPNG(filename.c_str()); + + if (!image) + { + eDebug("image/img=\"%s\" - %s: file not found", name, filename.c_str()); + continue; + } + + if (paldummy && !node->GetAttributeValue("nomerge")) + { + gPixmapDC mydc(image); + gPainter p(mydc); + p.mergePalette(paldummy); + } + images[name] = image; + } + return 0; +} + +int eSkin::parseImageAlias(XMLTreeNode *xvalues) +{ + for (XMLTreeNode *node=xvalues->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "map")) + { + eDebug("illegal values entry %s", node->GetType()); + continue; + } + const char *name=node->GetAttributeValue("name"), + *img=node->GetAttributeValue("img"); + if (!name || !img) + { + eDebug("map entry has no name or img"); + continue; + } + std::map::iterator it = imageAlias.find(name); + if (it != imageAlias.end()) + { + eDebug("imagealias %s does exist, skip make alias for image %s", name, img); + continue; + } + std::map >::iterator i = images.find(img); + if (i == images.end()) + { + eDebug("image %s not found, skip make alias %s", img , name); + continue; + } + imageAlias[name]=img; + } + return 0; +} + +int eSkin::parseFonts(XMLTreeNode *xfonts) +{ + const char *abasepath=xfonts->GetAttributeValue("basepath"); + eString basepath=abasepath?abasepath:FONTDIR; + + if (basepath.length()) + if (basepath[basepath.length()-1]!='/') + basepath+="/"; + + for (XMLTreeNode *node=xfonts->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "font")) + { + eDebug("illegal fonts entry %s", node->GetType()); + continue; + } + const char *file=node->GetAttributeValue("file"); + if (!file) + { + eDebug("fonts entry has no file"); + continue; + } + const char *name=node->GetAttributeValue("name"); + if (!name) + { + eDebug("fonts entry has no name use filename %s as name", file); + name = file; + } + std::map::iterator it = fonts.find(name); + const char *ascale=node->GetAttributeValue("scale"); + int scale=0; + if (ascale) + scale=atoi(ascale); + if (!scale) + scale=100; + if (it != fonts.end()) + { + eDebug("Font with name %s already loaded, skip %s", name, file); + continue; + } + fonts[name]=fontRenderClass::getInstance()->AddFont(basepath+eString(file), name, scale); + if (node->GetAttributeValue("replacement")) + eTextPara::setReplacementFont(name); + } + return 0; +} + +int eSkin::parseValues(XMLTreeNode *xvalues) +{ + for (XMLTreeNode *node=xvalues->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "value")) + { + eDebug("illegal values entry %s", node->GetType()); + continue; + } + const char *name=node->GetAttributeValue("name"); + if (!name) + { + eDebug("values entry has no name"); + continue; + } + const char *value=node->GetAttributeValue("value"); + if (!value) + { + eDebug("values entry has no value"); + continue; + } + std::map::iterator it = values.find(name); + if (it != values.end()) + { + eDebug("value %s does exist, skip make value %s=%i", name, value); + continue; + } + values[name]=atoi(value); + } + return 0; +} + +gDC *eSkin::getDCbyName(const char *name) +{ + gPixmapDC *dc=0; + if (!strcmp(name, "fb")) + dc=gFBDC::getInstance(); +#ifndef DISABLE_LCD + else if (!strcmp(name, "lcd")) + dc=gLCDDC::getInstance(); +#endif + return dc; +} + +int eSkin::build(eWidget *widget, XMLTreeNode *node) +{ +// eDebug("building a %s", node->GetType()); +/* if (widget->getType() != node->GetType()) + return -1;*/ + + for (XMLAttribute *attrib=node->GetAttributes(); attrib; attrib=attrib->GetNext()) + { +// eDebug("setting %s := %s", attrib->GetName(), attrib->GetValue()); + if (widget->setProperty(attrib->GetName(), attrib->GetValue())) + { + eDebug("failed"); + return -1; + } + } + for (XMLTreeNode *c=node->GetChild(); c; c=c->GetNext()) + { + eWidget *w=0; + + const char *name=c->GetAttributeValue("name"); + + if (name) + w=widget->search(name); + + if (!w) + { + std::map< eString, tWidgetCreator >::iterator it = widget_creator.find(c->GetType()); + + if ( it == widget_creator.end() ) + { + eWarning("widget class %s does not exist", c->GetType()); + return -ENOENT; + } + w = (it->second)(widget); + } + if (!w) + { + // eDebug("failed."); + return -EINVAL; + } + w->zOrderRaise(); + int err; + if ((err=build(w, c))) + { + return err; + } + } + return 0; +} + +eSkin::eSkin() +{ + maxcolors=256; + + palette=new gRGB[maxcolors]; + + memset(palette, 0, sizeof(gRGB)*maxcolors); + paldummy=new gImage(eSize(1, 1), 8); + paldummy->clut.data=palette; + paldummy->clut.colors=maxcolors; + + colorused=new int[maxcolors]; + memset(colorused, 0, maxcolors*sizeof(int)); +} + +eSkin::~eSkin() +{ + if (active==this) + active=0; + + clear(); + + delete colorused; + + for (std::map >::iterator it(images.begin()); it != images.end(); it++) + delete it->second; + + if (paldummy) + delete paldummy; +} + +int eSkin::load(const char *filename) +{ + eDebug("loading skin: %s", filename); + FILE *in=fopen(filename, "rt"); + if (!in) + return -1; + + parsers.push_front(new XMLTreeParser("ISO-8859-1")); + XMLTreeParser &parser=*parsers.first(); + char buf[2048]; + + int done; + do + { + unsigned int len=fread(buf, 1, sizeof(buf), in); + done=lenGetType(), "eskin")) + { + eDebug("not an eskin"); + return -1; + } + + return 0; +} + +void eSkin::parseSkins() +{ + for (ePtrList::reverse_iterator it(parsers); it != parsers.rend(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "colors")) + parseColors(node); + } + + for (ePtrList::reverse_iterator it(parsers); it != parsers.rend(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "colorscheme")) + parseScheme(node); + } + + for (ePtrList::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "fonts")) + parseFonts(node); + } + + for (ePtrList::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "fontalias")) + parseFontAlias(node); + } + + for (ePtrList::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "images")) + parseImages(node); + + } + + for (ePtrList::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "imagealias")) + parseImageAlias(node); + + } + + for (ePtrList::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "values")) + parseValues(node); + } +} + + +int eSkin::build(eWidget *widget, const char *name) +{ + for (parserList::iterator i(parsers.begin()); i!=parsers.end(); ++i) + { + XMLTreeNode *node=i->RootNode(); + node=node->GetChild(); + while (node) + { + if (!strcmp(node->GetType(), "object")) + { + const char *oname=node->GetAttributeValue("name"); + if (!std::strcmp(name, oname)) + { + node=node->GetChild(); + return build(widget, node); + } + } + node=node->GetNext(); + } + } + eDebug("didn't found it"); + return -ENOENT; +} + +void eSkin::setPalette(gPixmapDC *pal) +{ + if (palette) + { + gPainter p(*pal); + p.setPalette(palette, 0, 256); + } +} + +eSkin *eSkin::getActive() +{ + if (!active) + eFatal("no active skin"); + return active; +} + +void eSkin::makeActive() +{ + active=this; +} + +gColor eSkin::queryScheme(const eString& name) const +{ + eString base=name; + int offset=0, p; + if ((p=base.find('+'))!=-1) + { + offset=atoi(base.mid(p).c_str()); + base=base.left(p); + } + + std::map::const_iterator it = scheme.find(base); + + if (it != scheme.end()) + return it->second + offset; + +// eWarning("%s does not exist", name.c_str()); + + return gColor(0); +} + +RESULT eSkin::queryImage(ePtr &ptr, const eString& name) const +{ + eString img; + + std::map::const_iterator i = imageAlias.find(name); + + if (i != imageAlias.end()) + img = i->second; + else + img = name; + + std::map >::const_iterator it = images.find(img); + + if (it != images.end()) + ptr = it->second; + + return 0; +} + +int eSkin::queryValue(const eString& name, int d) const +{ + std::map::const_iterator it = values.find(name); + + if (it != values.end()) + return it->second; + + return d; +} + +gColor eSkin::queryColor(const eString& name) +{ + char *end; + + int numcol=strtol(name.c_str(), &end, 10); + + if (!*end) + return gColor(numcol); + + eString base=name; + int offset=0, p; + if ((p=base.find('+'))!=-1) + { + offset=atoi(base.mid(p).c_str()); + base=base.left(p); + } + + eNamedColor *col=searchColor(base); + + if (!col) + { + return queryScheme(name); + } else + return col->index + offset; +} + +gFont eSkin::queryFont(const eString& name) +{ + std::map::iterator it = fontAlias.find(name); // check if name is a font alias + + if ( it != fontAlias.end() ) // font alias found + return it->second; + + eString family; + int size=0; + + unsigned int sem = name.rfind(';'); // check if exist ';' in name + if (sem != eString::npos) // then exist + { + family=name.left(sem); + size = atoi( name.mid(sem+1).c_str() ); + if (size<=0) + size=16; + } + + std::map::iterator i = fonts.find(family); // check if family is a font name + if ( i != fonts.end() ) // font exist + return gFont(i->second, size); + + for (i = fonts.begin() ; i != fonts.end(); i++) // as last check if family name is a complete font Face + if ( i->second == family) + return gFont(i->second, size); + + eFatal("Font %s does not exist", name.c_str() ); // halt Programm now... Font does not exist + + return gFont(); +} diff --git a/lib/gui/eskin.h b/lib/gui/eskin.h new file mode 100644 index 00000000..0a6bd352 --- /dev/null +++ b/lib/gui/eskin.h @@ -0,0 +1,87 @@ +#ifndef __eskin_h +#define __eskin_h + +#include +#include +#include + +#include +#include +#include + +class eWidget; +class gPixmap; +typedef eWidget *(*tWidgetCreator)(eWidget *parent); + +struct eNamedColor +{ + eString name; + gRGB value, end; + int index; + int size; +}; + +class eSkin +{ + typedef ePtrList parserList; + parserList parsers; + void clear(); + + int parseColor(const eString& name, const char *color, gRGB &col); + int parseColors(XMLTreeNode *colors); + int parseScheme(XMLTreeNode *scheme); + int parseImages(XMLTreeNode *images); + int parseImageAlias(XMLTreeNode *images); + int parseValues(XMLTreeNode *values); + int parseFonts(XMLTreeNode *fonts); + int parseFontAlias(XMLTreeNode *fonts); + + gDC *getDCbyName(const char *name); + + gRGB *palette; + int maxcolors; + gImage *paldummy; + int *colorused; + + static std::map< eString, tWidgetCreator > widget_creator; + int build(eWidget *widget, XMLTreeNode *rootwidget); + + std::list colors; + std::map scheme; + std::map > images; + std::map values; + std::map fonts; + std::map fontAlias; + std::map imageAlias; + + eNamedColor *searchColor(const eString &name); + + static eSkin *active; +public: + eSkin(); + ~eSkin(); + + static void addWidgetCreator(const eString &name, tWidgetCreator creator); + static void removeWidgetCreator(const eString &name, tWidgetCreator creator); + + int load(const char *filename); + void parseSkins(); + + int build(eWidget *widget, const char *name); + void setPalette(gPixmapDC *pal); + + gColor queryColor(const eString &name); + gColor queryScheme(const eString &name) const; + RESULT queryImage(ePtr &pixmap, const eString &name) const; + int queryValue(const eString &name, int d) const; + gFont queryFont(const eString &name); + + void makeActive(); + + static eSkin *getActive(); +}; + +#define ASSIGN(v, t, n) \ + v =(t*)search(n); if (! v ) { eWarning("skin has undefined element: %s", n); v=new t(this); } + +#endif diff --git a/lib/gui/eskin_register.cpp b/lib/gui/eskin_register.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/eskin_register.h b/lib/gui/eskin_register.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/ewidget.cpp b/lib/gui/ewidget.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/ewidget.h b/lib/gui/ewidget.h new file mode 100644 index 00000000..3a1199a0 --- /dev/null +++ b/lib/gui/ewidget.h @@ -0,0 +1,498 @@ +#ifndef __ewidget_h +#define __ewidget_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class eWidgetEvent +{ +public: + enum eventType + { + evtKey, + willShow, willHide, + execBegin, execDone, + gotFocus, lostFocus, + + changedText, changedFont, changedForegroundColor, changedBackgroundColor, + changedSize, changedPosition, changedPixmap, childChangedHelpText, + + evtAction, evtShortcut + } type; + union + { + int parameter; + const eAction *action; + const eRCKey *key; + }; + eWidgetEvent(eventType type, int parameter=0): type(type), parameter(parameter) { } + eWidgetEvent(eventType type, const eAction *action): type(type), action(action) { } + eWidgetEvent(eventType type, const eRCKey &key): type(type), key(&key) { } + + /** + * \brief Event should be delivered to the focused widget. + * + * \return true if the event should be delivered to the focused widget instead of the widget itself. + */ + int toFocus() const + { + switch (type) + { + case evtKey: + return 1; + default: + return 0; + } + } +}; + +/** \brief The main widget class. All widgets inherit this class. + * eWidget handles focus management. + */ +class eWidget: public Object +{ + enum + { + /// Widget was shown with show() or implicit show() + stateShow=1, + /// Widget is visible on screen. Implies stateShow. + stateVisible=2 + }; + +public: + /** + * \brief Exits a (model) widget. + * + * Quit the local event loop, thus returning the control to the function which called \a exec. + * \sa eWidget::accept + * \sa eWidget::reject + */ + void close(int result); + + /** + * \brief Closes with a returncode of 0 (success). + * + * Synonym to \a close(0);. Useful to use as a slot. + * \sa eWidget::close + */ + void accept(); + + /** + * \brief Closes with a returncode of -1 (failure). + * + * Synonym to \a close(-1);. Useful to use as a slot. + * \sa eWidget::close + */ + void reject(); + /** + * \brief Signal is send, when the focus Changed + * + * used from a existing statusbar. + * \sa eWidget::focusChanged + */ + Signal1 focusChanged; + static Signal2< void, ePtrList*, int > showHelp; +protected: + ePtrList actionHelpList; + int helpID; + ePtrList childlist; + static eWidget *root; + eWidget *parent; + eString name; + eString helptext; + ePoint position; + ePoint absPosition; + eSize size; + eRect clientrect; + eRect clientclip; + + eAction *shortcut; + eWidget *shortcutFocusWidget; + + ePtrList _focusList; + + ePtrList actionListener; + eWidget *focus, *TLW; + + /// old top-level focus + eWidget *oldTLfocus; + int takefocus; + int state; + + gDC *target; + + inline eWidget *getTLW() // pseudoTLW !! + { + return TLW ? TLW : (TLW = (parent && parent->parent) ? parent->getTLW() : this ); + } + int result, in_loop, have_focus, just_showing; + void takeFocus(); + void releaseFocus(); + + void _willShow(); + void _willHide(); + + virtual void willShow(); + virtual void willHide(); + + virtual void setPalette(); + + void willShowChildren(); + void willHideChildren(); + + /** + * \brief Hi priority event filter. + * + * This event filter is called before the event is delivered via \a event. + * \return 1 if the event should NOT be forwarded. + */ + virtual int eventFilter(const eWidgetEvent &event); + + /** + * \brief Handles an event. + * + * If re-implemented in a widget-sub-class, \c eWidget::event should be called whenever the event is + * not processed by the widget. + * \return 1 if the event was processed, 0 if ignored. it might be forwarded to other widgets then. + */ + + virtual int keyDown(int rc); + virtual int keyUp(int rc); + + virtual void gotFocus(); + virtual void lostFocus(); + + virtual void recalcClientRect(); + void recalcClip(); + void checkFocus(); + + typedef ePtrList actionMapList; + + void findAction(eActionPrioritySet &prio, const eRCKey &key, eWidget *context); + void addActionMap(eActionMap *map); + void removeActionMap(eActionMap *map); + actionMapList actionmaps; + static actionMapList globalActions; + + // generic properties + gFont font; + eString text; + gColor backgroundColor, foregroundColor; + + ePtr pixmap; + + eString descr; + +public: + virtual int eventHandler(const eWidgetEvent &event); + static void addGlobalActionMap(eActionMap *map); + static void removeGlobalActionMap(eActionMap *map); + inline eWidget *getNonTransparentBackground() + { + if (backgroundColor >= 0) + return this; + return parent?parent->getNonTransparentBackground():this; + } + +#ifndef DISABLE_LCD + eWidget *LCDTitle; + eWidget *LCDElement; + eWidget *LCDTmp; +#endif + + void recalcAbsolutePosition(); + + inline const ePoint &getAbsolutePosition() const + { + return absPosition; + } + + inline ePoint getRelativePosition(eWidget *e) const + { + ePoint pos=position; + if (this != e) + for (eWidget *a=parent; a && (a != e); a=a->parent) + pos+=a->clientrect.topLeft(); + return pos; + } + + virtual void redrawWidget(gPainter *target, const eRect &area); + + virtual void eraseBackground(gPainter *target, const eRect &area); + + /** + * \brief Constructs a new eWidget. + * \param parent The parent widget. The widget gets automatically removed when the parent gets removed. + * \param takefocus Specifies if the widget should be appended to the focus list of the TLW, i.e. if it can + receive keys. + */ + eWidget(eWidget *parent=0, int takefocus=0); + + /** + * \brief Destructs an eWidget and all its childs. + * + * hide() is called when the widget is shown. The set ePixmap is \e not + * freed. If the widget acquired focus, it will be removed from the focuslist. + * \sa eWidget::setPixmap + */ + virtual ~eWidget(); + + /** + * \brief Returns a pointer to the focus list. + * + * The focus list is the list of childs which have the \c takefocus flag set. + * This list is only maintained for TLWs. + */ + ePtrList *focusList() { return &_focusList; } + + /** + * \brief Resizes the widget. + * + * Sets the size of the widget to the given size. The event \c changedSize event will be generated. + * \param size The new size, relative to the position. + */ + void resize(const eSize& size); + + /** + * \brief Resizes clientrect (and the widget). + * + * Sets the clientrect of the widget to the given size. The real size of the widget will be set to met + * these requirement. The event \c changedSize event will be generated. + * \param size The new size of the clientrect, relative to the position. + */ + void cresize(const eSize& size); + + /** + * \brief Moves the widget. + * + * Set the new position of the widget to the given position. The \c changedPosition event will be generated. + * \param position The new position, relative to the parent's \c clientrect. + */ + void move(const ePoint& position); + + /** + * \brief Moves the clientrect (and the widget). + * + * Set the new position of the clientrect to the given position. The \c changedPosition event will be generated. + * \param position The new position, relative to the parent's \c clientrect. + */ + void cmove(const ePoint& position); + + /** + * \brief Returns the current size. + * + * \return Current size of the widget, relative to the position. + */ + const eSize& getSize() const { return size; } + + /** + * \brief Returns the current position. + * + * \return Current position, relative to the parent's \c clientrect. + */ + const ePoint& getPosition() const { return position; } + + /** + * \brief Returns the size of the clientrect. + * + * \return The usable size for the childwidgets. + */ + eSize getClientSize() const { return clientrect.size(); } + + /** + * \brief Returns the clientrect. + * + * \return The area usable for the childwidgets. + */ + const eRect& getClientRect() const { return clientrect; } + + /** + * \brief Recursive redraw of a widget. + * + * All client windows get repaint too, but no widgets above. Unless you have a good reason, you shouldn't + * use this function and use \c invalidate(). + * \param area The area which should be repaint. The default is to repaint the whole widget. + * \sa eWidget::invalidate + */ + void redraw(eRect area=eRect()); + + /** + * \brief Recursive (complete) redraw of a widget. + * + * Redraws the widget including background. This is the function to use if you want to manually redraw something! + * \param area The area which should be repaint. The default is to repaint the whole widget. + * \param force Forces a parent-invalidate even on non-visible widgets. Shouldn't be used outside eWidget. + * \sa eWidget::redraw + */ + void invalidate(eRect area=eRect(), int force=0); + + /** + * \brief Enters modal message loop. + * + * A new event loop will be launched. The function returns when \a close is called. + * \return The argument of \a close. + * \sa eWidget::close + */ + int exec(); + + /** + * \brief Visually clears the widget. + * + * Clears the widget. This is done on \a hide(). + * \sa eWidget::hide + */ + void clear(); + + /** + * \brief Delivers a widget-event. + * + * Internally calles \a eventFilter, then \a eventHandler() (in some cases of the focused widget) + * \param event The event to deliver. + */ + int event(const eWidgetEvent &event); + + /** + * \brief Shows the widget. + * + * If necessary, the widget will be linked into the TLW's active focus list. The widget will + * visually appear. + * \sa eWidget::hide + */ + void show(); + + /** + * \brief Hides the widget. + * + * The widget will be removed from the screen. All childs will be hidden too. + * \sa eWidget::show + */ + void hide(); + + /** + * \brief Returns if the widget is vissible. + * + * \return If the widget and all parents are visible, \c true is returned, else false. + */ + int isVisible() { return (state&stateVisible) && ( (!parent) || parent->isVisible() ); } + + /** + * \brief Possible focus directions. + */ + enum focusDirection + { + focusDirNext, focusDirPrev, focusDirN, focusDirE, focusDirS, focusDirW + }; + + /** + * \brief changes the focused widget. + * + * Focuses the next or previous widget of the \c focuslist. An \c gotFocus and \c lostFocus event will be + * generated. + * \param dir The direction, \c focusDirection. + */ + void focusNext(int dir=0); + + /** + * \brief Gives focus to a widget. + * + * Set the focus to the specified widget. The \c focuslist is updated, too. + * An \c gotFocus and \c lostFocus event will be generated. + * \param newfocus The new widget to focus. + */ + void setFocus(eWidget *newfocus); + + /** + * \brief Sets the widget font. + * + * The font is used for example by the \c eLabel. + * \sa eLabel + * \param font The new font used by widget-specific drawing code. + */ + void setFont(const gFont &font); + + /** + * \brief Sets the widget caption or text. + * + * \param label The text to assign to the widget. + */ + void setText(const eString &label); + + const eString& getText() const { return text; } + void setBackgroundColor(const gColor& color, bool inv=true); + void setForegroundColor(const gColor& color, bool inv=true); + void setPixmap(gPixmap *pmap); + void setTarget(gDC *target); + gDC *getTarget() { return target; } + +#ifndef DISABLE_LCD + void setLCD(eWidget *lcdtitle, eWidget *lcdelement); +#endif + + void setName(const char *name); + const eString& getName() const { return name; } + eWidget*& getParent() { return parent; } + const gFont& getFont() const { return font; } + + const gColor& getBackgroundColor() const { return backgroundColor; } + const gColor& getForegroundColor() const { return foregroundColor; } + + int width() { return getSize().width(); } + int height() { return getSize().height(); } + + gPainter *getPainter(eRect area); + + const eString& getHelpText() const { return helptext; } + + void setHelpText( const eString&); + /** + * \brief Sets a property. + * + * A property is a value/data pair which is used for serializing widgets (like in skinfiles). + * These properties are available to all \c "eWidget"-based classes. + * \arg \c position, the position of the widget, relative to the parent's childarea. Consider using csize for TLWs. + * Positions are specified in a "x:y" manner. + * \arg \c cposition, the position of the widget's clientrect (upper left). + * This is useful for specifing a position independant of a decoration which might be + * different sized. The real position will be calculated to match the requested position. + * \arg \c size, the size of the widget. Consider using csize for TLWs. Sizes are specified in a "width:height" manner. + * \arg \c csize, the size of the clientrect. The real size will be calculated to match the requested size. + * \arg \c text, the text/caption of the widget. + * \arg \c font, the primary font used in the widget. + * \arg \c name, the name of the widget for referring them. + * \arg \c pixmap, an already loaded, named pixmap to be used as the widget's pixmap. + * \arg \c foregroundColor, a named color, which will be used for the widget's foreground color. + * \arg \c backgroundColor + * \param prop The property to be set. + * \param value The value to be set. + */ + virtual int setProperty(const eString &prop, const eString &value); + + eWidget *search(const eString &name); + + eWidget* getFocus() { return focus; } + + void makeRoot(); + + void zOrderLower(); + void zOrderRaise(); + + /** + * \brief sets the shortcut (generate evtShortcut) + */ + void setShortcut(const eString &shortcut); + void setShortcutFocus(eWidget *focus); + + void addActionToHelpList(eAction *action); + void clearHelpList(); + void setHelpID(int fHelpID); +}; + +#endif diff --git a/lib/gui/ewindow.cpp b/lib/gui/ewindow.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/ewindow.h b/lib/gui/ewindow.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/guiactions.cpp b/lib/gui/guiactions.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/guiactions.h b/lib/gui/guiactions.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/listbox.cpp b/lib/gui/listbox.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/listbox.h b/lib/gui/listbox.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/multipage.cpp b/lib/gui/multipage.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/multipage.h b/lib/gui/multipage.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/numberactions.cpp b/lib/gui/numberactions.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/numberactions.h b/lib/gui/numberactions.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/slider.cpp b/lib/gui/slider.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/slider.h b/lib/gui/slider.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/statusbar.cpp b/lib/gui/statusbar.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/statusbar.h b/lib/gui/statusbar.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/testpicture.cpp b/lib/gui/testpicture.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/testpicture.h b/lib/gui/testpicture.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/textinput.cpp b/lib/gui/textinput.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib/gui/textinput.h b/lib/gui/textinput.h new file mode 100644 index 00000000..e69de29b diff --git a/lib/network/Makefile.am b/lib/network/Makefile.am new file mode 100644 index 00000000..cfdc79b1 --- /dev/null +++ b/lib/network/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = \ + -I$(top_srcdir)/include + +noinst_LIBRARIES = libenigma_network.a + +libenigma_network_a_SOURCES = \ + http_dyn.cpp http_file.cpp httpd.cpp serversocket.cpp socket.cpp xmlrpc.cpp diff --git a/lib/network/Makefile.in b/lib/network/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/lib/network/http_dyn.cpp b/lib/network/http_dyn.cpp new file mode 100644 index 00000000..ea47019b --- /dev/null +++ b/lib/network/http_dyn.cpp @@ -0,0 +1,66 @@ +#include + +eHTTPDyn::eHTTPDyn(eHTTPConnection *c, eString result): eHTTPDataSource(c), result(result) +{ + wptr=0; + char buffer[10]; + snprintf(buffer, 10, "%d", size=result.length()); + c->local_header["Content-Length"]=std::string(buffer); + if (c->code == -1) + { + c->code=200; + c->code_descr="OK"; + } +} + +eHTTPDyn::~eHTTPDyn() +{ +} + +int eHTTPDyn::doWrite(int hm) +{ + int tw=size-wptr; + if (tw>hm) + tw=hm; + if (tw<=0) + return -1; + connection->writeBlock(result.c_str()+wptr, tw); + wptr+=tw; + return (size > wptr) ? 1 : -1; +} + +eHTTPDynPathResolver::eHTTPDynPathResolver() +{ + dyn.setAutoDelete(true); +} + +void eHTTPDynPathResolver::addDyn(eString request, eString path, eString (*function)(eString, eString, eString, eHTTPConnection*)) +{ + dyn.push_back(new eHTTPDynEntry(request, path, function)); +} + +eHTTPDataSource *eHTTPDynPathResolver::getDataSource(eString request, eString path, eHTTPConnection *conn) +{ + eString p, opt; + if (path.find('?')!=eString::npos) + { + p=path.left(path.find('?')); + opt=path.mid(path.find('?')+1); + } else + { + p=path; + opt=""; + } + for (ePtrList::iterator i(dyn); i != dyn.end(); ++i) + if ((i->path==p) && (i->request==request)) + { + conn->code=-1; + eString s=i->function(request, path, opt, conn); + + if (s) + return new eHTTPDyn(conn, s); + + return new eHTTPError(conn, 500); + } + return 0; +} diff --git a/lib/network/http_dyn.h b/lib/network/http_dyn.h new file mode 100644 index 00000000..6fb8b9b1 --- /dev/null +++ b/lib/network/http_dyn.h @@ -0,0 +1,34 @@ +#ifndef __http_dyn_h_ +#define __http_dyn_h_ +#include +#include + +class eHTTPDyn: public eHTTPDataSource +{ + eString result; + int wptr, size; +public: + eHTTPDyn(eHTTPConnection *c, eString result); + ~eHTTPDyn(); + int doWrite(int); +}; + +class eHTTPDynPathResolver: public eHTTPPathResolver +{ + struct eHTTPDynEntry + { + eString request, path; + eString (*function)(eString request, eString path, eString opt, eHTTPConnection *content); + + eHTTPDynEntry(eString request, eString path, eString (*function)(eString, eString, eString, eHTTPConnection *)): request(request), path(path), function(function) + { + } + }; + ePtrList dyn; +public: + void addDyn(eString request, eString path, eString (*function)(eString, eString, eString, eHTTPConnection *conn)); + eHTTPDynPathResolver(); + eHTTPDataSource *getDataSource(eString request, eString path, eHTTPConnection *conn); +}; + +#endif diff --git a/lib/network/http_file.cpp b/lib/network/http_file.cpp new file mode 100644 index 00000000..89918569 --- /dev/null +++ b/lib/network/http_file.cpp @@ -0,0 +1,228 @@ +#include +#include +#include +#include +#include +#include +#include + +eHTTPFile::eHTTPFile(eHTTPConnection *c, int _fd, int method, const char *mime): eHTTPDataSource(c), method(method) +{ + fd=_fd; + if (method == methodGET) + { + c->local_header["Content-Type"]=std::string(mime); + size=lseek(fd, 0, SEEK_END); + char asize[10]; + snprintf(asize, 10, "%d", size); + lseek(fd, 0, SEEK_SET); + c->local_header["Content-Length"]=std::string(asize); + } + connection->code_descr="OK"; + connection->code=200; +} + +int eHTTPFile::doWrite(int bytes) +{ + if (method == methodGET) + { + char buff[bytes]; + if (!size) + return -1; + int len=bytes; + if (len>size) + len=size; + len=read(fd, buff, len); + if (len<=0) + return -1; + size-=connection->writeBlock(buff, len); + if (!size) + return -1; + else + return 1; + } else + return -1; +} + +void eHTTPFile::haveData(void *data, int len) +{ + if (method != methodPUT) + return; + ::write(fd, data, len); +} + +eHTTPFile::~eHTTPFile() +{ + close(fd); +} + +eHTTPFilePathResolver::eHTTPFilePathResolver() +{ + translate.setAutoDelete(true); +} + + +static char _base64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +static int unbase64(eString &dst, const eString string) +{ + dst=""; + char c[4]; + int pos=0; + unsigned int i=0; + + while (1) + { + if (i == string.size()) + break; + char *ch=strchr(_base64, string[i++]); + if (!ch) + { + i++; + continue; + } + c[pos++]=ch-_base64; + if (pos == 4) + { + char d[3]; + d[0]=c[0]<<2; + d[0]|=c[1]>>4; + d[1]=c[1]<<4; + d[1]|=c[2]>>2; + d[2]=c[2]<<6; + d[2]|=c[3]; + + dst+=d[0]; + if (c[2] != 64) + dst+=d[1]; + if (c[3] != 64) + dst+=d[2]; + pos=0; + } + } + return pos; +} + +int CheckUnixPassword(const char *user, const char *pass) +{ + passwd *pwd=getpwnam(user); + if (!pwd) + return -1; + char *cpwd=pwd->pw_passwd; + if (pwd && (!strcmp(pwd->pw_passwd, "x"))) + { + spwd *sp=getspnam(user); + if (!sp) // no shadow password defined. + return -1; + cpwd=sp->sp_pwdp; + } + if (!cpwd) + return -1; + if ((*cpwd=='!')||(*cpwd=='*')) // disabled user + return -2; + char *cres=crypt(pass, cpwd); + return !!strcmp(cres, cpwd); +} + +static int checkAuth(const eString cauth) +{ + eString auth; + if (cauth.left(6) != "Basic ") + return -1; + if (unbase64(auth, cauth.mid(6))) + return -1; + eString username=auth.left(auth.find(":")); + eString password=auth.mid(auth.find(":")+1); + if (CheckUnixPassword(username.c_str(), password.c_str())) + return -1; + return 0; +} + +eHTTPDataSource *eHTTPFilePathResolver::getDataSource(eString request, eString path, eHTTPConnection *conn) +{ + int method; + eDebug("request = %s, path = %s", request.c_str(), path.c_str()); + if (request == "GET") + method=eHTTPFile::methodGET; + else if (request == "PUT") + method=eHTTPFile::methodPUT; + else + return new eHTTPError(conn, 405); // method not allowed + if (path.find("../")!=eString::npos) // evil hax0r + return new eHTTPError(conn, 403); + if (path[0] != '/') // prepend '/' + path.insert(0,"/"); + if (path[path.length()-1]=='/') + path+="index.html"; + + eHTTPDataSource *data=0; + for (ePtrList::iterator i(translate); i != translate.end(); ++i) + { + if (i->root==path.left(i->root.length())) + { + eString newpath=i->path+path.mid(i->root.length()); + if (newpath.find('?')) + newpath=newpath.left(newpath.find('?')); + eDebug("translated %s to %s", path.c_str(), newpath.c_str()); + + if (i->authorized & ((method==eHTTPFile::methodGET)?1:2)) + { + std::map::iterator i=conn->remote_header.find("Authorization"); + if ((i == conn->remote_header.end()) || checkAuth(i->second)) + { + conn->local_header["WWW-Authenticate"]="Basic realm=\"dreambox\""; + return new eHTTPError(conn, 401); // auth req'ed + } + } + + int fd=open(newpath.c_str(), (method==eHTTPFile::methodGET)?O_RDONLY:(O_WRONLY|O_CREAT|O_TRUNC), 0644); + + if (fd==-1) + { + switch (errno) + { + case ENOENT: + data=new eHTTPError(conn, 404); + break; + case EACCES: + data=new eHTTPError(conn, 403); + break; + default: + data=new eHTTPError(conn, 403); // k.a. + break; + } + break; + } + + eString ext=path.mid(path.rfind('.')); + const char *mime="text/unknown"; + if ((ext==".html") || (ext==".htm")) + mime="text/html"; + else if ((ext==".jpeg") || (ext==".jpg")) + mime="image/jpeg"; + else if (ext==".gif") + mime="image/gif"; + else if (ext==".css") + mime="text/css"; + else if (ext==".png") + mime="image/png"; + else if (ext==".xml") + mime="text/xml"; + else if (ext==".xsl") + mime="text/xsl"; + + data=new eHTTPFile(conn, fd, method, mime); + break; + } + } + return data; +} + +void eHTTPFilePathResolver::addTranslation(eString path, eString root, int authorized) +{ + if (path[path.length()-1]!='/') + path+='/'; + if (root[root.length()-1]!='/') + root+='/'; + translate.push_back(new eHTTPFilePath(path, root, authorized)); +} diff --git a/lib/network/http_file.h b/lib/network/http_file.h new file mode 100644 index 00000000..88bffc60 --- /dev/null +++ b/lib/network/http_file.h @@ -0,0 +1,37 @@ +#ifndef __http_file_h +#define __http_file_h + +#include "httpd.h" + +class eHTTPFile: public eHTTPDataSource +{ + int fd, size; + const char *mime; + int method; +public: + enum { methodGET, methodPUT }; + eHTTPFile(eHTTPConnection *c, int fd, int method, const char *mime); + ~eHTTPFile(); + int doWrite(int); + void haveData(void *data, int len); +}; + +class eHTTPFilePathResolver: public eHTTPPathResolver +{ + struct eHTTPFilePath + { + eString path; + eString root; + int authorized; // must be authorized (1 means read, 2 write) + eHTTPFilePath(eString path, eString root, int authorized): path(path), root(root), authorized(authorized) + { + } + }; + ePtrList translate; +public: + eHTTPFilePathResolver(); + eHTTPDataSource *getDataSource(eString request, eString path, eHTTPConnection *conn); + void addTranslation(eString path, eString root, int auth); +}; + +#endif diff --git a/lib/network/httpd.cpp b/lib/network/httpd.cpp new file mode 100644 index 00000000..b8ed1a9d --- /dev/null +++ b/lib/network/httpd.cpp @@ -0,0 +1,631 @@ +// #define DEBUG_HTTPD +#include + +#include +#include +#include +#include +#include + +eHTTPDataSource::eHTTPDataSource(eHTTPConnection *c): connection(c) +{ +} + +eHTTPDataSource::~eHTTPDataSource() +{ +} + +void eHTTPDataSource::haveData(void *data, int len) +{ +} + +int eHTTPDataSource::doWrite(int) +{ + return 0; +} + +eHTTPError::eHTTPError(eHTTPConnection *c, int errcode): eHTTPDataSource(c), errcode(errcode) +{ + eString error="unknown error"; + switch (errcode) + { + case 400: error="Bad Request"; break; + case 401: error="Unauthorized"; break; + case 403: error="Forbidden"; break; + case 404: error="Not found"; break; + case 405: error="Method not allowed"; break; + case 500: error="Internal server error"; break; + } + connection->code_descr=error; + connection->code=errcode; + + connection->local_header["Content-Type"]=std::string("text/html"); +} + +int eHTTPError::doWrite(int w) +{ + eString html; + html+="Error "+eString().setNum(connection->code)+""+ + "

Error "+eString().setNum(errcode)+": "+connection->code_descr+"

\n"; + connection->writeBlock(html.c_str(), html.length()); + return -1; +} + +eHTTPConnection::eHTTPConnection(int socket, int issocket, eHTTPD *parent, int persistent): eSocket(socket, issocket, parent->ml), parent(parent), persistent(persistent) +{ +#ifdef DEBUG_HTTPD + eDebug("eHTTPConnection"); +#endif + CONNECT(this->readyRead_ , eHTTPConnection::readData); + CONNECT(this->bytesWritten_ , eHTTPConnection::bytesWritten); + CONNECT(this->error_ , eHTTPConnection::gotError); + CONNECT(this->connectionClosed_ , eHTTPConnection::destruct); + CONNECT(this->hangup , eHTTPConnection::gotHangup); + + buffersize=128*1024; + localstate=stateWait; + remotestate=stateRequest; + data=0; +} + +void eHTTPConnection::destruct() +{ + gotHangup(); + delete this; +} + +eHTTPConnection::eHTTPConnection(eMainloop *ml): eSocket(ml), parent(0), persistent(0) +{ + CONNECT(this->readyRead_ , eHTTPConnection::readData); + CONNECT(this->bytesWritten_ , eHTTPConnection::bytesWritten); + CONNECT(this->error_ , eHTTPConnection::gotError); + CONNECT(this->connected_ , eHTTPConnection::hostConnected); + CONNECT(this->connectionClosed_ , eHTTPConnection::destruct); + + localstate=stateWait; + remotestate=stateWait; + + buffersize=64*1024; + data=0; +} + +void eHTTPConnection::hostConnected() +{ + processLocalState(); +} + +void eHTTPConnection::start() +{ + if (localstate==stateWait) + { + localstate=stateRequest; + processLocalState(); + } +} + +void eHTTPConnection::gotHangup() +{ + if (data && remotestate == stateData) + data->haveData(0, 0); + if (data) + { + delete data; + data=0; + } + transferDone(0); + + localstate=stateWait; + remotestate=stateRequest; + + remote_header.clear(); + local_header.clear(); +} + +eHTTPConnection *eHTTPConnection::doRequest(const char *uri, eMainloop *ml, int *error) +{ + if (error) + *error=0; + + char *defaultproto="http"; + std::string proto, host, path; + int port=80; + + int state=0; // 0 proto, 1 host, 2 port 3 path + + while (*uri) + { + switch (state) + { + case 0: + if (!strncmp(uri, "://", 3)) + { + state=1; + uri+=3; + } else if ((*uri=='/') || (*uri==':')) + { + host=proto; + state=1; + proto=defaultproto; + } else + proto.push_back(*uri++); + break; + case 1: + if (*uri=='/') + state=3; + else if (*uri==':') + { + state=2; + port=0; + uri++; + } else + host.push_back(*uri++); + break; + case 2: + if (*uri=='/') + state=3; + else + { + if (!isdigit(*uri)) + { + port=-1; + state=3; + } else + { + port*=10; + port+=*uri++-'0'; + } + } + break; + case 3: + path.push_back(*uri++); + } + } + + if (state==0) + { + path=proto; + proto=defaultproto; + } + +#ifdef DEBUG_HTTPD + eDebug("proto: '%s', host '%s', path '%s', port '%d'", proto.c_str(), host.c_str(), path.c_str(), port); +#endif + + if (!host.size()) + { + eDebug("no host given"); + if (error) + *error=ENOENT; + return 0; + } + + if (strcmp(proto.c_str(), "http")) + { + eDebug("invalid protocol (%s)", proto.c_str()); + if (error) + *error=EINVAL; + return 0; + } + + if (port == -1) + { + eDebug("invalid port"); + if (error) + *error=EINVAL; + return 0; + } + + if (!path.size()) + path="/"; + + eHTTPConnection *c=new eHTTPConnection(ml); + c->request="GET"; + c->requestpath=path.c_str(); + c->httpversion="HTTP/1.0"; + c->local_header["Host"]=host; + if ((*error=c->connectToHost(host, port))) // already deleted by error + return 0; + return c; +} + +void eHTTPConnection::readData() +{ + processRemoteState(); +} + +void eHTTPConnection::bytesWritten(int) +{ + processLocalState(); +} + +int eHTTPConnection::processLocalState() +{ + switch (state()) + { + case Connection: + break; + default: + return 0; + } + int done=0; + while (!done) + { +#ifdef DEBUG_HTTPD + eDebug("processing local state %d", localstate); +#endif + switch (localstate) + { + case stateWait: +#ifdef DEBUG_HTTPD + eDebug("local wait"); +#endif + done=1; + break; + case stateRequest: + { +#ifdef DEBUG_HTTPD + eDebug("local request"); +#endif + eString req=request+" "+requestpath+" "+httpversion+"\r\n"; + writeBlock(req.c_str(), req.length()); + localstate=stateHeader; + remotestate=stateResponse; + break; + } + case stateResponse: + { +#ifdef DEBUG_HTTPD + eDebug("local Response"); +#endif + writeString( (httpversion + " " + eString().setNum(code)+" " + code_descr + "\r\n").c_str() ); + localstate=stateHeader; + local_header["Connection"]="close"; + break; + } + case stateHeader: +#ifdef DEBUG_HTTPD + eDebug("local header"); +#endif + for (std::map::iterator cur=local_header.begin(); cur!=local_header.end(); ++cur) + { + writeString(cur->first.c_str()); + writeString(": "); + writeString(cur->second.c_str()); + writeString("\r\n"); + } + writeString("\r\n"); + if (request=="HEAD") + localstate=stateDone; + else + localstate=stateData; + break; + case stateData: +#ifdef DEBUG_HTTPD + eDebug("local data"); +#endif + if (data) + { + int btw=buffersize-bytesToWrite(); + if (btw>0) + { + if (data->doWrite(btw)<0) + { + localstate=stateDone; + } else + done=1; + } else + done=1; + } else + done=1; // wait for remote response + break; + case stateDone: +#if 0 + // move to stateClose + if (remote_header.find("Connection") != remote_header.end()) + { + eString &connection=remote_header["Connection"]; + if (connection == "keep-alive") + localstate=stateWait; + else + localstate=stateClose; + } +#endif +#ifdef DEBUG_HTTPD + eDebug("locate state done"); +#endif + if (!persistent) + localstate=stateClose; + else + localstate=stateWait; + break; + case stateClose: +#ifdef DEBUG_HTTPD + eDebug("closedown"); +#endif + if (persistent) + { + if (data) + delete data; + data=0; + localstate=stateWait; + } else + close(); // bye, bye, remote + return 1; + } + } +#ifdef DEBUG_HTTPD + eDebug("end local"); +#endif + return 0; +} + +int eHTTPConnection::processRemoteState() +{ + int abort=0, done=0; +#ifdef DEBUG_HTTPD + eDebug("%d bytes avail", bytesAvailable()); +#endif + while (((!done) || bytesAvailable()) && !abort) + { + switch (remotestate) + { + case stateWait: + { + int i=0; +#ifdef DEBUG_HTTPD + eDebug("remote stateWait"); +#endif + char buffer[1024]; + while (bytesAvailable()) { + i=readBlock(buffer, 1024); + } + done=1; + break; + } + case stateRequest: + { +#ifdef DEBUG_HTTPD + eDebug("stateRequest"); +#endif + eString line; + if (!getLine(line)) + { + done=1; + abort=1; + break; + } + + int del[2]; + del[0]=line.find(" "); + del[1]=line.find(" ", del[0]+1); + if (del[0]==-1) + { + if (data) + delete data; + eDebug("request buggy"); + httpversion="HTTP/1.0"; + data=new eHTTPError(this, 400); + done=0; + localstate=stateResponse; + remotestate=stateDone; + if (processLocalState()) + return -1; + break; + } + request=line.left(del[0]); + requestpath=line.mid(del[0]+1, (del[1]==-1)?-1:(del[1]-del[0]-1)); + if (del[1]!=-1) + { + is09=0; + httpversion=line.mid(del[1]+1); + } else + is09=1; + + if (is09 || (httpversion.left(7) != "HTTP/1.") || httpversion.size()!=8) + { + remotestate=stateData; + done=0; + httpversion="HTTP/1.0"; + content_length_remaining=content_length_remaining=0; + data=new eHTTPError(this, 400); // bad request - not supporting version 0.9 yet + } else + remotestate=stateHeader; + break; + } + case stateResponse: + { +#ifdef DEBUG_HTTPD + eDebug("state response.."); +#endif + eString line; + if (!getLine(line)) + { + done=1; + abort=1; + break; + } +#ifdef DEBUG_HTTPD + eDebug("line: %s", line.c_str()); +#endif + int del[2]; + del[0]=line.find(" "); + del[1]=line.find(" ", del[0]+1); + if (del[0]==-1) + code=-1; + else + { + httpversion=line.left(del[0]); + code=atoi(line.mid(del[0]+1, (del[1]==-1)?-1:(del[1]-del[0]-1)).c_str()); + if (del[1] != -1) + code_descr=line.mid(del[1]+1); + else + code_descr=""; + } + + remotestate=stateHeader; + break; + } + case stateHeader: + { +#ifdef DEBUG_HTTPD + eDebug("remote stateHeader"); +#endif + eString line; + if (!getLine(line)) + { + done=1; + abort=1; + break; + } + if (!line.length()) + { + content_length=0; + content_length_remaining=-1; + if (remote_header.count("Content-Length")) + { + content_length=atoi(remote_header["Content-Length"].c_str()); + content_length_remaining=content_length; + } + + if (parent) + { + for (ePtrList::iterator i(parent->resolver); i != parent->resolver.end(); ++i) + { + if ((data=i->getDataSource(request, requestpath, this))) + break; + } + localstate=stateResponse; // can be overridden by dataSource + } else + data=createDataSource(this); + + if (!data) + { + if (data) + delete data; + data=new eHTTPError(this, 404); + } + + if (content_length || // if content-length is set, we have content + remote_header.count("Content-Type") || // content-type - the same + (localstate != stateResponse)) // however, if we are NOT in response-state, so we are NOT server, there's ALWAYS more data to come. (exception: http/1.1 persistent) + remotestate=stateData; + else + { + data->haveData(0, 0); + remotestate=stateDone; + } + if (processLocalState()) + return -1; + } else + { + int del=line.find(":"); + eString name=line.left(del), value=line.mid(del+1); + if (value[0]==' ') + value=value.mid(1); + remote_header[std::string(name)]=std::string(value); + } + done=1; + break; + } + case stateData: + { +#ifdef DEBUG_HTTPD + eDebug("remote stateData"); +#endif + ASSERT(data); + char buffer[16284]; + int len; + while (bytesAvailable()) + { + int tr=sizeof(buffer); + if (content_length_remaining != -1) + if (tr>content_length_remaining) + tr=content_length_remaining; + len=readBlock(buffer, tr); + data->haveData(buffer, len); + if (content_length_remaining != -1) + content_length_remaining-=len; + if (!content_length_remaining) + { + data->haveData(0, 0); + remotestate=stateDone; + break; + } + } + done=1; + if (processLocalState()) + return -1; + break; + } + case stateDone: + remotestate=stateClose; + break; + case stateClose: +// if (!persistent) + remotestate=stateWait; +// else +// remotestate=stateRequest; + abort=1; + break; + default: + eDebug("HTTP: invalid state %d", remotestate); + done=1; + } + } +#ifdef DEBUG_HTTPD + eDebug("end remote"); +#endif + return 0; +} + +void eHTTPConnection::writeString(const char *data) +{ + writeBlock(data, strlen(data)); +} + +int eHTTPConnection::getLine(eString &line) +{ + if (!canReadLine()) + return 0; + + line = readLine(); + line.erase(line.length()-1); + + if (line[(line.length()-1)] == '\r') + line.erase(line.length()-1); + + return 1; +} + +void eHTTPConnection::gotError(int err) +{ + if (data) + { + delete data; + data=0; + } + transferDone(err); + delete this; +} + +eHTTPD::eHTTPD(int port, eMainloop *ml): eServerSocket(port, ml), ml(ml) +{ + if (!ok()) + eDebug("[NET] httpd server FAILED on port %d", port); + else + eDebug("[NET] httpd server started on port %d", port); + resolver.setAutoDelete(true); +} + +eHTTPConnection::~eHTTPConnection() +{ + if ((!persistent) && (state()!=Idle)) + eWarning("~eHTTPConnection, status still %d", state()); + if (data) + delete data; +} + +void eHTTPD::newConnection(int socket) +{ + new eHTTPConnection(socket, 1, this); +} diff --git a/lib/network/httpd.h b/lib/network/httpd.h new file mode 100644 index 00000000..791d49c8 --- /dev/null +++ b/lib/network/httpd.h @@ -0,0 +1,123 @@ +#ifndef __httpd_h +#define __httpd_h + +#include +#include + +#include +#include +#include +#include +#include +#include + +class eHTTPConnection; +class eHTTPDataSource; +class eHTTPD; + +class eHTTPPathResolver +{ +public: + virtual ~eHTTPPathResolver() {}; + virtual eHTTPDataSource *getDataSource(eString request, eString path, eHTTPConnection *conn)=0; +}; + +class eHTTPDataSource +{ +protected: + eHTTPConnection *connection; +public: + eHTTPDataSource(eHTTPConnection *c); + virtual ~eHTTPDataSource(); + virtual void haveData(void *data, int len); + virtual int doWrite(int bytes); // number of written bytes, -1 for "no more" +}; + +class eHTTPError: public eHTTPDataSource +{ + int errcode; +public: + eHTTPError(eHTTPConnection *c, int errcode); + ~eHTTPError() { } + void haveData(); + int doWrite(int bytes); +}; + +class eHTTPConnection: public eSocket +{ + void doError(int error); + + int getLine(eString &line); + + int processLocalState(); + int processRemoteState(); + void writeString(const char *data); + + eHTTPDataSource *data; + eHTTPD *parent; + + int buffersize; +private: + void readData(); + void gotError(int); + void bytesWritten(int); + void hostConnected(); + void destruct(); +public: + Signal1 transferDone; + Signal1 createDataSource; + enum + { + /* + + < GET / HTTP/1.0 + < If-modified-since: bla + < + < Data + > 200 OK HTTP/1.0 + > Content-Type: text/html + > + > Data + */ + + stateWait, stateRequest, stateResponse, stateHeader, stateData, stateDone, stateClose + }; + int localstate, remotestate; + int persistent; + + eHTTPConnection(int socket, int issocket, eHTTPD *parent, int persistent=0); + eHTTPConnection(eMainloop *ml); // ready to do "connectToHost" + static eHTTPConnection *doRequest(const char *uri, eMainloop *ml, int *error=0); + void start(); + void gotHangup(); + ~eHTTPConnection(); + + // stateRequest + eString request, requestpath, httpversion; + int is09; + + // stateResponse + + int code; + eString code_descr; + + std::map remote_header, local_header; + + // stateData + int content_length, content_length_remaining; +}; + +class eHTTPD: public eServerSocket +{ + friend class eHTTPConnection; + ePtrList resolver; + eMainloop *ml; +public: + eHTTPD(int port, eMainloop *ml); + void newConnection(int socket); + + void addResolver(eHTTPPathResolver *r) { resolver.push_back(r); } + void removeResolver(eHTTPPathResolver *r) { resolver.remove(r); } +}; + +#endif diff --git a/lib/network/serversocket.cpp b/lib/network/serversocket.cpp new file mode 100644 index 00000000..fe2737eb --- /dev/null +++ b/lib/network/serversocket.cpp @@ -0,0 +1,55 @@ +#include + +bool eServerSocket::ok() +{ + return okflag; +} + +void eServerSocket::notifier(int) +{ + int clientfd, clientlen; + struct sockaddr_in client_addr; + + eDebug("[SERVERSOCKET] incoming connection!"); + + clientlen=sizeof(client_addr); + clientfd=accept(getDescriptor(), + (struct sockaddr *) &client_addr, + (socklen_t*)&clientlen); + if(clientfd<0) + eDebug("[SERVERSOCKET] error on accept()"); + + newConnection(clientfd); +} + +eServerSocket::eServerSocket(int port, eMainloop *ml): eSocket(ml) +{ + struct sockaddr_in serv_addr; + + serv_addr.sin_family=AF_INET; + serv_addr.sin_addr.s_addr=INADDR_ANY; + serv_addr.sin_port=htons(port); + + okflag=1; + int val=1; + + setsockopt(getDescriptor(), SOL_SOCKET, SO_REUSEADDR, &val, 4); + + if(bind(getDescriptor(), + (struct sockaddr *) &serv_addr, + sizeof(serv_addr))<0) + { + eDebug("[SERVERSOCKET] ERROR on bind() (%m)"); + okflag=0; + } + listen(getDescriptor(), 0); + + rsn->setRequested(eSocketNotifier::Read); +} + +eServerSocket::~eServerSocket() +{ +#if 0 + eDebug("[SERVERSOCKET] destructed"); +#endif +} diff --git a/lib/network/serversocket.h b/lib/network/serversocket.h new file mode 100644 index 00000000..6bd59f11 --- /dev/null +++ b/lib/network/serversocket.h @@ -0,0 +1,18 @@ +#ifndef __serversocket_h +#define __serversocket_h + +#include "socket.h" + +class eServerSocket: public eSocket +{ + void notifier(int handle); + int okflag; +protected: + virtual void newConnection(int socket)=0; +public: + eServerSocket(int port, eMainloop *ml); + virtual ~eServerSocket(); + bool ok(); +}; + +#endif /* __serversocket_h */ diff --git a/lib/network/serversocket.lo b/lib/network/serversocket.lo new file mode 100644 index 00000000..8039034b Binary files /dev/null and b/lib/network/serversocket.lo differ diff --git a/lib/network/socket.cpp b/lib/network/socket.cpp new file mode 100644 index 00000000..9de0ca0a --- /dev/null +++ b/lib/network/socket.cpp @@ -0,0 +1,294 @@ +#include +#include +#include +#include + +#include + +void eSocket::close() +{ + if (writebuffer.empty()) + { + int wasconnected=(mystate==Connection) || (mystate==Closing); + delete rsn; + rsn=0; + ::close(socketdesc); + socketdesc=-1; + mystate=Idle; + if (wasconnected) + connectionClosed_(); + } else + { + mystate=Closing; + rsn->setRequested(rsn->getRequested()|eSocketNotifier::Write); + } +} + +void eSocket::enableRead() +{ + if (rsn) + rsn->setRequested(rsn->getRequested()|eSocketNotifier::Read); +} + +void eSocket::disableRead() +{ + if (rsn) + rsn->setRequested(rsn->getRequested()&~eSocketNotifier::Read); +} + +void eSocket::inject(const char *data, int len) +{ + readbuffer.write(data, len); + if (mystate == Connection) + readyRead_(); +} + +eString eSocket::readLine() +{ + int size=readbuffer.searchchr('\n'); + if (size == -1) + return eString(); + size++; // ich will auch das \n + char buffer[size+1]; + buffer[size]=0; + readbuffer.read(buffer, size); + return eString(buffer); +} + +bool eSocket::canReadLine() +{ + return readbuffer.searchchr('\n') != -1; +} + +int eSocket::bytesAvailable() +{ + return readbuffer.size(); +} + +int eSocket::readBlock(char *data, unsigned int maxlen) +{ + return readbuffer.read(data, maxlen); +} + +int eSocket::bytesToWrite() +{ + return writebuffer.size(); +} + +int eSocket::state() +{ + return mystate; +} + +int eSocket::setSocket(int s, int iss, eMainloop *ml) +{ + socketdesc=s; + issocket=iss; + fcntl(socketdesc, F_SETFL, O_NONBLOCK); + last_break = 0xFFFFFFFF; + + if (rsn) + delete rsn; + rsn=new eSocketNotifier(ml, getDescriptor(), + eSocketNotifier::Read|eSocketNotifier::Hungup); + CONNECT(rsn->activated, eSocket::notifier); + return 0; +} + +void eSocket::notifier(int what) +{ + if ((what & eSocketNotifier::Read) && (mystate == Connection)) + { + int bytesavail=256; + if (issocket) + if (ioctl(getDescriptor(), FIONREAD, &bytesavail)<0) + eDebug("FIONREAD failed.\n"); + + { + if (issocket) + { + if (!bytesavail) // does the REMOTE END has closed the connection? (no Hungup here!) + { + writebuffer.clear(); + close(); + return; + } + } else // when operating on terminals, check for break + { + // where is this struct defined? + struct async_icount { + unsigned long cts, dsr, rng, dcd, tx, rx; + unsigned long frame, parity, overrun, brk; + unsigned long buf_overrun; + } icount; + + if (!ioctl(getDescriptor(), TIOCGICOUNT, &icount)) + { + if (last_break == 0xFFFFFFFF) + last_break = icount.brk; + else if (last_break != icount.brk) + { + last_break = icount.brk; + readbuffer.fromfile(getDescriptor(), bytesavail); + readbuffer.clear(); + writebuffer.clear(); + rsn->setRequested(rsn->getRequested()&~eSocketNotifier::Write); + write(getDescriptor(), "BREAK!", 6); + hangup(); + return; + } + } + } + int r; + if ((r=readbuffer.fromfile(getDescriptor(), bytesavail)) != bytesavail) + if (issocket) + eDebug("fromfile failed!"); + readyRead_(); + } + } else if (what & eSocketNotifier::Write) + { + if ((mystate == Connection) || (mystate == Closing)) + { + if (!writebuffer.empty()) + { + bytesWritten_(writebuffer.tofile(getDescriptor(), 65536)); + if (writebuffer.empty()) + { + rsn->setRequested(rsn->getRequested()&~eSocketNotifier::Write); + if (mystate == Closing) + { + close(); // warning, we might get destroyed after close. + return; + } + } + } else + eDebug("got ready to write, but nothin in buffer. strange."); + if (mystate == Closing) + close(); + } else if (mystate == Connecting) + { + mystate=Connection; + rsn->setRequested(rsn->getRequested()&~eSocketNotifier::Write); + + int res; + socklen_t size=sizeof(res); + ::getsockopt(getDescriptor(), SOL_SOCKET, SO_ERROR, &res, &size); + if (!res) + connected_(); + else + { + close(); + error_(res); + } + } + } else if (what & eSocketNotifier::Hungup) + { + if (mystate == Connection) + { + writebuffer.clear(); + close(); + } else if (mystate == Connecting) + { + int res; + socklen_t size=sizeof(res); + ::getsockopt(getDescriptor(), SOL_SOCKET, SO_ERROR, &res, &size); + close(); + error_(res); + } + } +} + +int eSocket::writeBlock(const char *data, unsigned int len) +{ + int w=len; + if (issocket && writebuffer.empty()) + { + int tw=::send(getDescriptor(), data, len, MSG_NOSIGNAL); + if ((tw < 0) && (errno != EWOULDBLOCK)) + eDebug("write: %m"); + + if (tw < 0) + tw = 0; + data+=tw; + len-=tw; + } + if (len) + writebuffer.write(data, len); + + if (!writebuffer.empty()) + rsn->setRequested(rsn->getRequested()|eSocketNotifier::Write); + return w; +} + +int eSocket::getDescriptor() +{ + return socketdesc; +} + +int eSocket::connectToHost(eString hostname, int port) +{ + struct hostent *server; + int res; + + if(!socketdesc){ + error_(errno); + return(-1); + } + server=gethostbyname(hostname.c_str()); + if(server==NULL) + { + eDebug("can't resolve %s", hostname.c_str()); + error_(errno); + return(-2); + } + bzero( (char*)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family=AF_INET; + bcopy( (char*)server->h_addr, + (char*)&serv_addr.sin_addr.s_addr, + server->h_length); + serv_addr.sin_port=htons(port); + res=::connect(socketdesc, (const sockaddr*)&serv_addr, sizeof(serv_addr)); + if ((res < 0) && (errno != EINPROGRESS)) + { + eDebug("can't connect to host: %s", hostname.c_str()); + close(); + error_(errno); + return(-3); + } + if (res < 0) // EINPROGRESS + { + rsn->setRequested(rsn->getRequested()|eSocketNotifier::Write); + mystate=Connecting; + } else + { + mystate=Connection; + connected_(); + } + return(0); +} + +eSocket::eSocket(eMainloop *ml): readbuffer(32768), writebuffer(32768), rsn(0) +{ + int s=socket(AF_INET, SOCK_STREAM, 0); +#if 0 + eDebug("[SOCKET]: initalized socket %d", socketdesc); +#endif + mystate=Idle; + setSocket(s, 1, ml); +} + +eSocket::eSocket(int socket, int issocket, eMainloop *ml): readbuffer(32768), writebuffer(32768), rsn(0) +{ + setSocket(socket, issocket, ml); + mystate=Connection; +} + +eSocket::~eSocket() +{ + if (rsn) + delete rsn; + if(socketdesc>=0) + { + ::close(socketdesc); + } +} diff --git a/lib/network/socket.h b/lib/network/socket.h new file mode 100644 index 00000000..edf9b904 --- /dev/null +++ b/lib/network/socket.h @@ -0,0 +1,63 @@ +#ifndef __socket_h +#define __socket_h + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class eSocket: public Object +{ + int mystate; + int issocket; + unsigned int last_break; +private: + int socketdesc; + eIOBuffer readbuffer; + eIOBuffer writebuffer; + int writebusy; + sockaddr_in serv_addr; +protected: + eSocketNotifier *rsn; + virtual void notifier(int); +public: + eSocket(eMainloop *ml); + eSocket(int socket, int issocket, eMainloop *ml); + ~eSocket(); + int connectToHost(eString hostname, int port); + int getDescriptor(); + int writeBlock(const char *data, unsigned int len); + int setSocket(int socketfd, int issocket, eMainloop *ml); + int bytesToWrite(); + int readBlock(char *data, unsigned int maxlen); + int bytesAvailable(); + bool canReadLine(); + eString readLine(); + void close(); + // flow control: start/stop data delivery into read buffer. + void enableRead(); + void disableRead(); + + void inject(const char *data, int len); + + enum State { Idle, HostLookup, Connecting, + Listening, Connection, Closing }; + int state(); + + Signal0 connectionClosed_; + Signal0 connected_; + Signal0 readyRead_; + Signal0 hangup; + Signal1 bytesWritten_; + Signal1 error_; +}; + +#endif /* __socket_h */ diff --git a/lib/network/socket.lo b/lib/network/socket.lo new file mode 100644 index 00000000..1d809469 Binary files /dev/null and b/lib/network/socket.lo differ diff --git a/lib/network/xmlrpc.cpp b/lib/network/xmlrpc.cpp new file mode 100644 index 00000000..a53b50a8 --- /dev/null +++ b/lib/network/xmlrpc.cpp @@ -0,0 +1,518 @@ +#ifndef DISABLE_NETWORK + +#include + + +static std::map&, ePtrList&)> rpcproc; + +void eXMLRPCVariant::zero() +{ + _struct=0; + _array=0; + _i4=0; + _boolean=0; + _string=0; + _double=0; +// _datetime=0; +// _base64=0; +} + +eXMLRPCVariant::eXMLRPCVariant(std::map *__struct) +{ + zero(); + _struct=__struct; +} + +eXMLRPCVariant::eXMLRPCVariant(std::vector *__array) +{ + zero(); + _array=__array; +} + +eXMLRPCVariant::eXMLRPCVariant(__s32 *__i4) +{ + zero(); + _i4=__i4; +} + +eXMLRPCVariant::eXMLRPCVariant(bool *__boolean) +{ + zero(); + _boolean=__boolean; +} + +eXMLRPCVariant::eXMLRPCVariant(eString *__string) +{ + zero(); + _string=__string; +} + +eXMLRPCVariant::eXMLRPCVariant(double *__double) +{ + zero(); + _double=__double; +} + +/*eXMLRPCVariant::eXMLRPCVariant(QDateTime *__datetime) +{ + zero(); + _datetime=__datetime; +} */ + +/*eXMLRPCVariant::eXMLRPCVariant(QByteArray *__base64) +{ + zero(); + _base64=__base64; +} */ + +eXMLRPCVariant::eXMLRPCVariant(const eXMLRPCVariant &c) +{ + zero(); + if (c._i4) + _i4=new int(*c._i4); + if (c._boolean) + _boolean=new bool(*c._boolean); + if (c._string) + _string=new eString(*c._string); + if (c._double) + _double=new double(*c._double); + // datetime, base64 + if (c._struct) + { + _struct=new std::map; + for (std::map::iterator b(c._struct->begin()); b != c._struct->end(); ++b) + _struct->insert(std::pair(b->first, new eXMLRPCVariant(*b->second))); + } + if (c._array) + _array = new std::vector(*c._array); +} + +eXMLRPCVariant::~eXMLRPCVariant() +{ + if (_struct) + { + for (std::map::iterator i(_struct->begin()); i != _struct->end(); ++i) + delete i->second; + + delete _struct; + } + if (_array) + delete _array; + if (_i4) + delete _i4; + if (_boolean) + delete _boolean; + if (_string) + delete _string; + if (_double) + delete _string; +/* if (_datetime) + delete _datetime;*/ +/* if (_base64) + delete _base64;*/ +} + +std::map *eXMLRPCVariant::getStruct() +{ + return _struct; +} + +std::vector *eXMLRPCVariant::getArray() +{ + return _array; +} + +__s32 *eXMLRPCVariant::getI4() +{ + return _i4; +} + +bool *eXMLRPCVariant::getBoolean() +{ + return _boolean; +} + +eString *eXMLRPCVariant::getString() +{ + return _string; +} + +double *eXMLRPCVariant::getDouble() +{ + return _double; +} + +/*QDateTime *eXMLRPCVariant::getDatetime() +{ + return _datetime; +} */ + +/*QByteArray *eXMLRPCVariant::getBase64() +{ + return _base64; +} */ + +void eXMLRPCVariant::toXML(eString &result) +{ + if (getArray()) + { + static eString s1(""); + result+=s1; + for (unsigned int i=0; isize(); i++) + { + static eString s(" "); + result+=s; + (*getArray())[i].toXML(result); + static eString s1("\n"); + result+=s1; + } + static eString s2("\n"); + result+=s2; + } else if (getStruct()) + { + static eString s1(""); + result+=s1; + for (std::map::iterator i(_struct->begin()); i != _struct->end(); ++i) + { + static eString s1(" "); + result+=s1; + result+=i->first; + static eString s2(""); + result+=s2; + i->second->toXML(result); + static eString s3("\n"); + result+=s3; + } + static eString s2("\n"); + result+=s2; + } else if (getI4()) + { + static eString s1(""); + result+=s1; + result+=eString().setNum(*getI4()); + static eString s2(""); + result+=s2; + } else if (getBoolean()) + { + static eString s0("0"); + static eString s1("1"); + result+=(*getBoolean())?s1:s0; + } else if (getString()) + { + static eString s1(""); + static eString s2(""); + result+=s1; + result+=*getString(); + result+=s2; + } else if (getDouble()) + { + result+=eString().sprintf("%lf", *getDouble()); + } else + eFatal("couldn't append"); +} + +static eXMLRPCVariant *fromXML(XMLTreeNode *n) +{ + if (strcmp(n->GetType(), "value")) + return 0; + n=n->GetChild(); + const char *data=n->GetData(); + if (!data) + data=""; + if ((!strcmp(n->GetType(), "i4")) || (!strcmp(n->GetType(), "int"))) + return new eXMLRPCVariant(new int(atoi(data))); + else if (!strcmp(n->GetType(), "boolean")) + return new eXMLRPCVariant(new bool(atoi(data))); + else if (!strcmp(n->GetType(), "string")) + return new eXMLRPCVariant(new eString(data)); + else if (!strcmp(n->GetType(), "double")) + return new eXMLRPCVariant(new double(atof(data))); + else if (!strcmp(n->GetType(), "struct")) { + std::map *s=new std::map; + for (n=n->GetChild(); n; n=n->GetNext()) + { + if (strcmp(data, "member")) + { + delete s; + return 0; + } + eString name=0; + eXMLRPCVariant *value; + for (XMLTreeNode *v=n->GetChild(); v; v=v->GetNext()) + { + if (!strcmp(v->GetType(), "name")) + name=eString(v->GetData()); + else if (!strcmp(v->GetType(), "value")) + value=fromXML(v); + } + if ((!value) || (!name)) + { + delete s; + return 0; + } + s->INSERT(name,value); + } + return new eXMLRPCVariant(s); + } else if (!strcmp(n->GetType(), "array")) + { + ePtrList l; + l.setAutoDelete(true); + n=n->GetChild(); + if (strcmp(data, "data")) + return 0; + for (n=n->GetChild(); n; n=n->GetNext()) + if (!strcmp(n->GetType(), "value")) + { + eXMLRPCVariant *value=fromXML(n); + if (!value) + return 0; + l.push_back(value); + } + + return new eXMLRPCVariant( l.getVector() ); + } + eDebug("couldn't convert %s", n->GetType()); + return 0; +} + +eXMLRPCResponse::eXMLRPCResponse(eHTTPConnection *c): + eHTTPDataSource(c), parser("ISO-8859-1") +{ + // size etc. setzen aber erst NACH data-phase + connection->localstate=eHTTPConnection::stateWait; +} + +eXMLRPCResponse::~eXMLRPCResponse() +{ +} + +int eXMLRPCResponse::doCall() +{ + eDebug("doing call"); + result=""; + // get method name + eString methodName=0; + + if (connection->remote_header["Content-Type"]!="text/xml") + { + eDebug("remote header failure (%s != text/xml)", (connection->remote_header["Content-Type"]).c_str()); + return -3; + } + + XMLTreeNode *methodCall=parser.RootNode(); + if (!methodCall) + { + eDebug("empty xml"); + return -1; + } + if (strcmp(methodCall->GetType(), "methodCall")) + { + eDebug("no methodCall found"); + return -2; + } + + ePtrList params; + params.setAutoDelete(true); + + for (XMLTreeNode *c=methodCall->GetChild(); c; c=c->GetNext()) + { + if (!strcmp(c->GetType(), "methodName")) + methodName=eString(c->GetData()); + else if (!strcmp(c->GetType(), "params")) + { + for (XMLTreeNode *p=c->GetChild(); p; p=p->GetNext()) + if (!strcmp(p->GetType(), "param")) + params.push_back(fromXML(p->GetChild())); + } else + { + eDebug("unknown stuff found"); + return 0; + } + } + + if (!methodName) + { + eDebug("no methodName found!"); + return -3; + } + + eDebug("methodName: %s", methodName.c_str() ); + + result="\n" + ""; + + ePtrList ret; + ret.setAutoDelete(true); + + int (*proc)(std::vector&, ePtrList &)=rpcproc[methodName]; + int fault; + + std::vector* v = params.getVector(); + + if (!proc) + { + fault=1; + xmlrpc_fault(ret, -1, "called method not present"); + } else + fault=proc( *v , ret); + + delete v; + + eDebug("converting to text..."); + + if (fault) + { + result+="\n"; + ret.current()->toXML(result); + result+="\n"; + } else + { + result+="\n"; + for (ePtrList::iterator i(ret); i != ret.end(); ++i) + { + result+=""; + i->toXML(result); + result+=""; + } + result+=""; + } + result+=""; + char buffer[10]; + snprintf(buffer, 10, "%d", size=result.length()); + wptr=0; + connection->local_header["Content-Type"]="text/xml"; + connection->local_header["Content-Length"]=buffer; + connection->code=200; + connection->code_descr="OK"; + connection->localstate=eHTTPConnection::stateResponse; + return 0; +} + +int eXMLRPCResponse::doWrite(int hm) +{ + int tw=size-wptr; + if (tw>hm) + tw=hm; + if (tw<=0) + return -1; + connection->writeBlock(result.c_str()+wptr, tw); + wptr+=tw; + return size > wptr ? 1 : -1; +} + +void eXMLRPCResponse::haveData(void *data, int len) +{ + if (result) + return; + int err=0; + + if (!parser.Parse((char*)data, len, !len)) + { + char temp[len+1]; + temp[len]=0; + memcpy(temp, data, len); + eDebug("%s: %s", temp, parser.ErrorString(parser.GetErrorCode())); + err=1; + } + + if ((!err) && (!len)) + err=doCall(); + + if (err) + { + eDebug("schade: %d", err); + connection->code=400; + connection->code_descr="Bad request"; + char buffer[10]; + snprintf(buffer, 10, "%d", size=result.length()); + wptr=0; + connection->local_header["Content-Type"]="text/html"; + connection->local_header["Content-Length"]=buffer; + result.sprintf("XMLRPC error %d\n", err); + connection->localstate=eHTTPConnection::stateResponse; + } +} + +void xmlrpc_initialize(eHTTPD *httpd) +{ + httpd->addResolver(new eHTTPXMLRPCResolver); +} + +void xmlrpc_addMethod(eString methodName, int (*proc)(std::vector&, ePtrList&)) +{ + rpcproc[methodName]=proc; +} + +void xmlrpc_fault(ePtrList &res, int faultCode, eString faultString) +{ + std::map *s=new std::map; + s->INSERT("faultCode", new eXMLRPCVariant(new __s32(faultCode))); + s->INSERT("faultString", new eXMLRPCVariant(new eString(faultString))); + res.push_back(new eXMLRPCVariant(s)); +} + +int xmlrpc_checkArgs(eString args, std::vector &parm, ePtrList &res) +{ + if (parm.size() != args.length()) + { + xmlrpc_fault(res, -500, eString().sprintf("parameter count mismatch (found %d, expected %d)", parm.size(), args.length())); + return 1; + } + + for (unsigned int i=0; i +#include +#include +#include + +#include +#include +#include + +#define INSERT(KEY,VALUE) insert(std::pair(KEY,VALUE)) + +class eXMLRPCVariant +{ + std::map *_struct; + std::vector *_array; + __s32 *_i4; + bool *_boolean; + eString *_string; + double *_double; +// QDateTime *_datetime; +// QByteArray *_base64; + void zero(); +public: + eXMLRPCVariant(std::map *_struct); + eXMLRPCVariant(std::vector *_array); + eXMLRPCVariant(__s32 *_i4); + eXMLRPCVariant(bool *_boolean); + eXMLRPCVariant(eString *_string); + eXMLRPCVariant(double *_double); +// eXMLRPCVariant(QDateTime *_datetime); +// eXMLRPCVariant(QByteArray *_base64); + eXMLRPCVariant(const eXMLRPCVariant &c); + ~eXMLRPCVariant(); + + std::map *getStruct(); + std::vector *getArray(); + __s32 *getI4(); + bool *getBoolean(); + eString *getString(); + double *getDouble(); +// QDateTime *getDatetime(); +// QByteArray *getBase64(); + + void toXML(eString &); +}; + +class eXMLRPCResponse: public eHTTPDataSource +{ + XMLTreeParser parser; + eString result; + int size; + int wptr; + int doCall(); +public: + eXMLRPCResponse(eHTTPConnection *c); + ~eXMLRPCResponse(); + + int doWrite(int); + void haveData(void *data, int len); +}; + +void xmlrpc_initialize(eHTTPD *httpd); +void xmlrpc_addMethod(eString methodName, int (*)(std::vector&, ePtrList&)); +void xmlrpc_fault(ePtrList &res, int faultCode, eString faultString); +int xmlrpc_checkArgs(eString args, std::vector&, ePtrList &res); + +class eHTTPXMLRPCResolver: public eHTTPPathResolver +{ +public: + eHTTPXMLRPCResolver(); + eHTTPDataSource *getDataSource(eString request, eString path, eHTTPConnection *conn); +}; + +#endif + +#endif //DISABLE_NETWORK diff --git a/lib/service/Makefile.am b/lib/service/Makefile.am new file mode 100644 index 00000000..09ba4ce8 --- /dev/null +++ b/lib/service/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = \ + -I$(top_srcdir)/include + +noinst_LIBRARIES = libenigma_service.a + +libenigma_service_a_SOURCES = \ + service.cpp servicemp3.cpp servicedvb.cpp servicefs.cpp + diff --git a/lib/service/Makefile.in b/lib/service/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/lib/service/iservice.h b/lib/service/iservice.h new file mode 100644 index 00000000..bedb0d6f --- /dev/null +++ b/lib/service/iservice.h @@ -0,0 +1,173 @@ +#ifndef __lib_dvb_iservice_h +#define __lib_dvb_iservice_h + +#include +#include +#include + +class eServiceReference +{ +public: + enum + { + idInvalid=-1, + idStructure, // service_id == 0 is root + idDVB, + idFile, + idUser=0x1000 + }; + int type; + + int flags; // flags will NOT be compared. + enum + { + isDirectory=1, // SHOULD enter (implies mustDescent) + mustDescent=2, // cannot be played directly - often used with "isDirectory" (implies canDescent) + /* + for example: + normal services have none of them - they can be fed directly into the "play"-handler. + normal directories have both of them set - you cannot play a directory directly and the UI should descent into it. + playlists have "mustDescent", but not "isDirectory" - you don't want the user to browse inside the playlist (unless he really wants) + services with sub-services have none of them, instead the have the "canDecsent" flag (as all of the above) + */ + canDescent=4, // supports enterDirectory/leaveDirectory + flagDirectory=isDirectory|mustDescent|canDescent, + shouldSort=8, // should be ASCII-sorted according to service_name. great for directories. + hasSortKey=16, // has a sort key in data[3]. not having a sort key implies 0. + sort1=32 // sort key is 1 instead of 0 + }; + + inline int getSortKey() const { return (flags & hasSortKey) ? data[3] : ((flags & sort1) ? 1 : 0); } + + int data[8]; + eString path; + + eServiceReference() + : type(idInvalid), flags(0) + { + } + + eServiceReference(int type, int flags) + : type(type), flags(flags) + { + memset(data, 0, sizeof(data)); + } + eServiceReference(int type, int flags, int data0) + : type(type), flags(flags) + { + memset(data, 0, sizeof(data)); + data[0]=data0; + } + eServiceReference(int type, int flags, int data0, int data1) + : type(type), flags(flags) + { + memset(data, 0, sizeof(data)); + data[0]=data0; + data[1]=data1; + } + eServiceReference(int type, int flags, int data0, int data1, int data2) + : type(type), flags(flags) + { + memset(data, 0, sizeof(data)); + data[0]=data0; + data[1]=data1; + data[2]=data2; + } + eServiceReference(int type, int flags, int data0, int data1, int data2, int data3) + : type(type), flags(flags) + { + memset(data, 0, sizeof(data)); + data[0]=data0; + data[1]=data1; + data[2]=data2; + data[3]=data3; + } + eServiceReference(int type, int flags, int data0, int data1, int data2, int data3, int data4) + : type(type), flags(flags) + { + memset(data, 0, sizeof(data)); + data[0]=data0; + data[1]=data1; + data[2]=data2; + data[3]=data3; + data[4]=data4; + } + eServiceReference(int type, int flags, const eString &path) + : type(type), flags(flags), path(path) + { + memset(data, 0, sizeof(data)); + } + eServiceReference(const eString &string); + eString toString() const; + bool operator==(const eServiceReference &c) const + { + if (type != c.type) + return 0; + return /* (flags == c.flags) && */ (memcmp(data, c.data, sizeof(int)*8)==0) && (path == c.path); + } + bool operator!=(const eServiceReference &c) const + { + return !(*this == c); + } + bool operator<(const eServiceReference &c) const + { + if (type < c.type) + return 1; + + if (type > c.type) + return 0; + +/* if (flags < c.flags) + return 1; + if (flags > c.flags) + return 0; */ + + int r=memcmp(data, c.data, sizeof(int)*8); + if (r) + return r < 0; + return path < c.path; + } + operator bool() const + { + return type != idInvalid; + } +}; + +class iPauseableService: public virtual iObject +{ +public: + virtual RESULT pause()=0; + virtual RESULT unpause()=0; +}; + +class iPlayableService: public virtual iObject +{ + friend class iServiceHandler; +public: + // it's PRIVATE to the class factory + virtual RESULT start()=0; + virtual RESULT getIPausableService(ePtr &ptr)=0; +}; + +class iRecordableService: public virtual iObject +{ +public: + virtual RESULT start()=0; + virtual RESULT stop()=0; +}; + +class iListableService: public virtual iObject +{ +public: + virtual RESULT getContent(std::list &list)=0; +}; + +class iServiceHandler: public virtual iObject +{ +public: + virtual RESULT play(const eServiceReference &, ePtr &ptr)=0; + virtual RESULT record(const eServiceReference &, ePtr &ptr)=0; + virtual RESULT list(const eServiceReference &, ePtr &ptr)=0; +}; + +#endif diff --git a/lib/service/service.cpp b/lib/service/service.cpp new file mode 100644 index 00000000..99199aa9 --- /dev/null +++ b/lib/service/service.cpp @@ -0,0 +1,94 @@ +#include +#include +#include + +eServiceReference::eServiceReference(const eString &string) +{ + const char *c=string.c_str(); + int pathl=-1; + + if ( sscanf(c, "%d:%d:%x:%x:%x:%x:%x:%x:%x:%x:%n", &type, &flags, &data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6], &data[7], &pathl) < 8 ) + { + memset( data, 0, sizeof(data) ); + eDebug("find old format eServiceReference string"); + sscanf(c, "%d:%d:%x:%x:%x:%x:%n", &type, &flags, &data[0], &data[1], &data[2], &data[3], &pathl); + } + + if (pathl) + path=c+pathl; +} + +eString eServiceReference::toString() const +{ + eString ret; + ret+=eString().sprintf("%d:", type); + ret+=eString().sprintf("%d", flags); + for (unsigned int i=0; i &ptr) +{ + std::map >::iterator i = handler.find(ref.type); + if (i == handler.end()) + { + ptr = 0; + return -1; + } + return i->second->play(ref, ptr); +} + +RESULT eServiceCenter::record(const eServiceReference &ref, ePtr &ptr) +{ + std::map >::iterator i = handler.find(ref.type); + if (i == handler.end()) + { + ptr = 0; + return -1; + } + return i->second->record(ref, ptr); +} + +RESULT eServiceCenter::list(const eServiceReference &ref, ePtr &ptr) +{ + std::map >::iterator i = handler.find(ref.type); + if (i == handler.end()) + { + ptr = 0; + return -1; + } + return i->second->list(ref, ptr); +} + +RESULT eServiceCenter::addServiceFactory(int id, iServiceHandler *hnd) +{ + handler.insert(std::pair >(id, hnd)); + return 0; +} + +RESULT eServiceCenter::removeServiceFactory(int id) +{ + handler.erase(id); + return 0; +} + +eAutoInitP0 init_eServiceCenter(eAutoInitNumbers::service, "eServiceCenter"); diff --git a/lib/service/service.h b/lib/service/service.h new file mode 100644 index 00000000..f32e23d9 --- /dev/null +++ b/lib/service/service.h @@ -0,0 +1,29 @@ +#ifndef __service_h +#define __service_h + +#include +#include +#include + +class eServiceCenter: public virtual iServiceHandler, public virtual iObject +{ +DECLARE_REF; +private: + std::map > handler; + static eServiceCenter *instance; +public: + eServiceCenter(); + virtual ~eServiceCenter(); + + // iServiceHandler + RESULT play(const eServiceReference &, ePtr &ptr); + RESULT record(const eServiceReference &, ePtr &ptr); + RESULT list(const eServiceReference &, ePtr &ptr); + + // eServiceCenter + static RESULT getInstance(ePtr &ptr) { ptr = instance; return 0; } + RESULT addServiceFactory(int id, iServiceHandler *hnd); + RESULT removeServiceFactory(int id); +}; + +#endif diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp new file mode 100644 index 00000000..fc48fa66 --- /dev/null +++ b/lib/service/servicedvb.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include +#include + +DEFINE_REF(eServiceFactoryDVB) + +eServiceFactoryDVB::eServiceFactoryDVB(): ref(0) +{ + ePtr sc; + + eServiceCenter::getInstance(sc); + if (sc) + sc->addServiceFactory(eServiceFactoryDVB::id, this); +} + +eServiceFactoryDVB::~eServiceFactoryDVB() +{ + ePtr sc; + + eServiceCenter::getInstance(sc); + if (sc) + sc->removeServiceFactory(eServiceFactoryDVB::id); +} + +RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr &ptr) +{ + RESULT res; + // check resources... + ptr = new eDVBServicePlay(ref); + res = ptr->start(); + if (res) + { + ptr = 0; + return res; + } + return 0; +} + +RESULT eServiceFactoryDVB::record(const eServiceReference &, ePtr &ptr) +{ + ptr = 0; + return -1; +} + +RESULT eServiceFactoryDVB::list(const eServiceReference &, ePtr &ptr) +{ + ptr = 0; + return -1; +} + +eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref): + ref(0), m_reference(ref) +{ + CONNECT(m_serviceHandler.serviceEvent, eDVBServicePlay::serviceEvent); + eDebug("DVB start (play)"); +} + +eDVBServicePlay::~eDVBServicePlay() +{ + eDebug("DVB stop (play)"); +} + +void eDVBServicePlay::serviceEvent(int event) +{ + eDebug("service event %d", event); + switch (event) + { + case eDVBServicePMTHandler::eventNewProgramInfo: + { + int vpid = -1, apid = -1, pcrpid = -1; + eDVBServicePMTHandler::program program; + if (m_serviceHandler.getProgramInfo(program)) + eDebug("getting program info failed."); + else + { + eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size()); + if (!program.videoStreams.empty()) + { + eDebugNoNewLine(" ("); + for (std::vector::const_iterator + i(program.videoStreams.begin()); + i != program.videoStreams.end(); ++i) + { + if (vpid == -1) + vpid = i->pid; + if (i != program.videoStreams.begin()) + eDebugNoNewLine(", "); + eDebugNoNewLine("%04x", i->pid); + } + eDebugNoNewLine(")"); + } + eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size()); + if (!program.audioStreams.empty()) + { + eDebugNoNewLine(" ("); + for (std::vector::const_iterator + i(program.audioStreams.begin()); + i != program.audioStreams.end(); ++i) + { + if (apid == -1) + apid = i->pid; + if (i != program.audioStreams.begin()) + eDebugNoNewLine(", "); + eDebugNoNewLine("%04x", i->pid); + } + eDebugNoNewLine(")"); + } + eDebug(", and the pcr pid is %04x", program.pcrPid); + if (program.pcrPid != 0x1fff) + pcrpid = program.pcrPid; + } + + if (!m_decoder) + { + ePtr demux; + m_serviceHandler.getDemux(demux); + if (demux) + demux->getMPEGDecoder(m_decoder); + } + + if (m_decoder) + { + m_decoder->setVideoPID(vpid); + m_decoder->setAudioPID(apid, 0); + m_decoder->setSyncPCR(pcrpid); + m_decoder->start(); + } + + break; + } + } +} + +RESULT eDVBServicePlay::start() +{ + eDebug("starting DVB service"); + m_serviceHandler.tune((eServiceReferenceDVB&)m_reference); + return 0; +} + +RESULT eDVBServicePlay::getIPausableService(ePtr &ptr) +{ + // not yet possible, maybe later... + ptr = 0; + return -1; +} + +DEFINE_REF(eDVBServicePlay) + +eAutoInitP0 init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB"); diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h new file mode 100644 index 00000000..fac9edf2 --- /dev/null +++ b/lib/service/servicedvb.h @@ -0,0 +1,45 @@ +#ifndef __servicemp3_h +#define __servicemp3_h + +#include +#include + +#include + +class eServiceFactoryDVB: public virtual iServiceHandler, public virtual iObject +{ +DECLARE_REF; +public: + eServiceFactoryDVB(); + virtual ~eServiceFactoryDVB(); + enum { id = 0x1 }; + + // iServiceHandler + RESULT play(const eServiceReference &, ePtr &ptr); + RESULT record(const eServiceReference &, ePtr &ptr); + RESULT list(const eServiceReference &, ePtr &ptr); +}; + +class eDVBServicePlay: public virtual iPlayableService, public virtual iObject, public Object +{ +DECLARE_REF; +private: + friend class eServiceFactoryDVB; + eServiceReference m_reference; + + ePtr m_decoder; + + eDVBServicePMTHandler m_serviceHandler; + + eDVBServicePlay(const eServiceReference &ref); + + void serviceEvent(int event); +public: + virtual ~eDVBServicePlay(); + + // iPlayableService + RESULT start(); + RESULT getIPausableService(ePtr &ptr); +}; + +#endif diff --git a/lib/service/servicefs.cpp b/lib/service/servicefs.cpp new file mode 100644 index 00000000..ad40f0af --- /dev/null +++ b/lib/service/servicefs.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// eServiceFactoryFS + +eServiceFactoryFS::eServiceFactoryFS(): ref(0) +{ + ePtr sc; + + eServiceCenter::getInstance(sc); + if (sc) + sc->addServiceFactory(eServiceFactoryFS::id, this); +} + +eServiceFactoryFS::~eServiceFactoryFS() +{ + ePtr sc; + + eServiceCenter::getInstance(sc); + if (sc) + sc->removeServiceFactory(eServiceFactoryFS::id); +} + +DEFINE_REF(eServiceFactoryFS) + + // iServiceHandler +RESULT eServiceFactoryFS::play(const eServiceReference &ref, ePtr &ptr) +{ + ptr=0; + return -1; +} + +RESULT eServiceFactoryFS::record(const eServiceReference &ref, ePtr &ptr) +{ + ptr=0; + return -1; +} + +RESULT eServiceFactoryFS::list(const eServiceReference &ref, ePtr &ptr) +{ + ptr = new eServiceFS(ref.path.c_str()); + return 0; +} + +// eServiceFS + +DEFINE_REF(eServiceFS); + +eServiceFS::eServiceFS(const char *path): ref(0), path(path) +{ +} + +eServiceFS::~eServiceFS() +{ +} + +RESULT eServiceFS::getContent(std::list &list) +{ + DIR *d=opendir(path.c_str()); + if (!d) + return -errno; + while (dirent *e=readdir(d)) + { + if (!(strcmp(e->d_name, ".") && strcmp(e->d_name, ".."))) + continue; + + eString filename; + + filename = path; + filename += e->d_name; + + struct stat s; + if (::stat(filename.c_str(), &s) < 0) + continue; + + if (S_ISDIR(s.st_mode)) + filename += "/"; + + if (S_ISDIR(s.st_mode)) + { + eServiceReference service(eServiceFactoryFS::id, + eServiceReference::isDirectory| + eServiceReference::canDescent|eServiceReference::mustDescent| + eServiceReference::shouldSort|eServiceReference::sort1, + filename); + service.data[0] = 1; + list.push_back(service); + } else + { + eServiceReference service(eServiceFactoryFS::id, + eServiceReference::isDirectory| + eServiceReference::canDescent|eServiceReference::mustDescent| + eServiceReference::shouldSort|eServiceReference::sort1, + filename); + service.data[0] = 0; + list.push_back(service); + } + } + return 0; +} + +eAutoInitP0 init_eServiceFactoryFS(eAutoInitNumbers::service+1, "eServiceFactoryFS"); diff --git a/lib/service/servicefs.h b/lib/service/servicefs.h new file mode 100644 index 00000000..9d49b42d --- /dev/null +++ b/lib/service/servicefs.h @@ -0,0 +1,33 @@ +#ifndef __servicefs_h +#define __servicefs_h + +#include + +class eServiceFactoryFS: public virtual iServiceHandler, public virtual iObject +{ +DECLARE_REF; +public: + eServiceFactoryFS(); + virtual ~eServiceFactoryFS(); + enum { id = 0x2 }; + + // iServiceHandler + RESULT play(const eServiceReference &, ePtr &ptr); + RESULT record(const eServiceReference &, ePtr &ptr); + RESULT list(const eServiceReference &, ePtr &ptr); +}; + +class eServiceFS: public virtual iListableService, public virtual iObject +{ +DECLARE_REF; +private: + eString path; + friend class eServiceFactoryFS; + eServiceFS(const char *path); +public: + virtual ~eServiceFS(); + + RESULT getContent(std::list &list); +}; + +#endif diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp new file mode 100644 index 00000000..fb5993e4 --- /dev/null +++ b/lib/service/servicemp3.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include + +// eServiceFactoryMP3 + +eServiceFactoryMP3::eServiceFactoryMP3(): ref(0) +{ + ePtr sc; + + eServiceCenter::getInstance(sc); + if (sc) + sc->addServiceFactory(eServiceFactoryMP3::id, this); +} + +eServiceFactoryMP3::~eServiceFactoryMP3() +{ + ePtr sc; + + eServiceCenter::getInstance(sc); + if (sc) + sc->removeServiceFactory(eServiceFactoryMP3::id); +} + +DEFINE_REF(eServiceFactoryMP3) + + // iServiceHandler +RESULT eServiceFactoryMP3::play(const eServiceReference &ref, ePtr &ptr) +{ + RESULT res; + // check resources... + ptr = new eServiceMP3(ref.path.c_str()); + res = ptr->start(); + if (res) + { + ptr = 0; + return res; + } + return 0; +} + +RESULT eServiceFactoryMP3::record(const eServiceReference &ref, ePtr &ptr) +{ + ptr=0; + return -1; +} + +RESULT eServiceFactoryMP3::list(const eServiceReference &, ePtr &ptr) +{ + ptr=0; + return -1; +} + +// eServiceMP3 + +eServiceMP3::eServiceMP3(const char *filename): filename(filename), ref(0) +{ + printf("MP3: %s start\n", filename); +} + +eServiceMP3::~eServiceMP3() +{ + printf("MP3: %s stop\n", filename.c_str()); +} + +void eServiceMP3::AddRef() +{ + ++ref; +} + +void eServiceMP3::Release() +{ + if (!--ref) + delete this; +} + +RESULT eServiceMP3::start() { printf("mp3 starts\n"); return 0; } +RESULT eServiceMP3::getIPausableService(ePtr &ptr) { ptr=this; return 0; } + + // iPausableService +RESULT eServiceMP3::pause() { printf("mp3 pauses!\n"); return 0; } +RESULT eServiceMP3::unpause() { printf("mp3 unpauses!\n"); return 0; } + + +eAutoInitP0 init_eServiceFactoryMP3(eAutoInitNumbers::service+1, "eServiceFactoryMP3"); diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h new file mode 100644 index 00000000..0f2c074f --- /dev/null +++ b/lib/service/servicemp3.h @@ -0,0 +1,42 @@ +#ifndef __servicemp3_h +#define __servicemp3_h + +#include + +class eServiceFactoryMP3: public virtual iServiceHandler, public virtual iObject +{ +DECLARE_REF; +public: + eServiceFactoryMP3(); + virtual ~eServiceFactoryMP3(); + enum { id = 0x1001 }; + + // iServiceHandler + RESULT play(const eServiceReference &, ePtr &ptr); + RESULT record(const eServiceReference &, ePtr &ptr); + RESULT list(const eServiceReference &, ePtr &ptr); +}; + +class eServiceMP3: public virtual iPlayableService, public virtual iPauseableService, public virtual iObject +{ + friend class eServiceFactoryMP3; + std::string filename; + eServiceMP3(const char *filename); + int ref; +public: + virtual ~eServiceMP3(); + + // iObject + void AddRef(); + void Release(); + + // iPlayableService + RESULT start(); + RESULT getIPausableService(ePtr &ptr); + + // iPausableService + RESULT pause(); + RESULT unpause(); +}; + +#endif diff --git a/main/Makefile.am b/main/Makefile.am new file mode 100644 index 00000000..2f63dff1 --- /dev/null +++ b/main/Makefile.am @@ -0,0 +1,31 @@ +INCLUDES = \ + -I$(top_srcdir)/include + +bin_PROGRAMS = enigma2 + +enigma2_SOURCES = \ + enigma.cpp + +enigma2_LDADD_WHOLE = \ + $(top_builddir)/lib/base/libenigma_base.a \ + $(top_builddir)/lib/driver/libenigma_driver.a \ + $(top_builddir)/lib/dvb/libenigma_dvb.a \ + $(top_builddir)/lib/dvb_si/libenigma_dvb_si.a \ + $(top_builddir)/lib/gui/libenigma_gui.a \ + $(top_builddir)/lib/gdi/libenigma_gdi.a \ + $(top_builddir)/lib/network/libenigma_network.a \ + $(top_builddir)/lib/service/libenigma_service.a + +enigma2_LDADD = \ + @FREETYPE_LIBS@ \ + @ID3TAG_LIBS@ \ + @MAD_LIBS@ \ + @MD5SUM_LIBS@ \ + @PNG_LIBS@ \ + @SIGC_LIBS@ \ + @XMLTREE_LIBS@ \ + -ldl -lpthread -lcrypt -lresolv + +enigma2$(EXEEXT): $(enigma2_OBJECTS) $(enigma2_DEPENDENCIES) $(enigma2_LDADD_WHOLE) + @rm -f enigma2$(EXEEXT) + $(CXXLINK) $(enigma2_LDFLAGS) $(enigma2_OBJECTS) -Wl,--export-dynamic -Wl,--whole-archive $(enigma2_LDADD_WHOLE) -Wl,--no-whole-archive $(enigma2_LDADD) $(LIBS) diff --git a/main/Makefile.in b/main/Makefile.in new file mode 100644 index 00000000..e69de29b diff --git a/main/enigma-dvbtest.cpp b/main/enigma-dvbtest.cpp new file mode 100644 index 00000000..4fdb6984 --- /dev/null +++ b/main/enigma-dvbtest.cpp @@ -0,0 +1,125 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class eMain: public eApplication, public Object +{ + ePtr m_mgr; + ePtr m_channel; + ePtr m_demux; + eAUTable > m_table; + + ePtr m_dvbdb; + + ePtr m_state_change_connection; + int m_last_channel_state; +public: + eMain() + { + eDebug("mich gibts nu!"); + + m_mgr = new eDVBResourceManager(); + + m_dvbdb = new eDVBDB(); + m_mgr->setChannelList(m_dvbdb); + + eDVBChannelID chid(1,2,3); + + eDVBFrontendParametersSatellite fesat; + + fesat.frequency = 12070000; + fesat.symbol_rate = 27500000; + fesat.polarisation = eDVBFrontendParametersSatellite::Polarisation::Horizontal; + fesat.fec = eDVBFrontendParametersSatellite::FEC::f3_4; + fesat.inversion = eDVBFrontendParametersSatellite::Inversion::Off; + fesat.orbital_position = 192; + + eDVBFrontendParameters *fe = new eDVBFrontendParameters(); + + fe->setDVBS(fesat); + + m_dvbdb->addChannelToList(chid, fe); + + if (m_mgr->allocateChannel(chid, m_channel)) + eDebug("shit it failed!"); + + if (m_channel) + { + m_channel->connectStateChange(slot(*this, &eMain::channelStateChanged), m_state_change_connection); + channelStateChanged(m_channel); + } + } + + void channelStateChanged(iDVBChannel *channel) + { + int state; + channel->getState(state); + eDebug("channel state is now %d", state); + + if ((m_last_channel_state != iDVBChannel::state_ok) + && (state == iDVBChannel::state_ok) && (!m_demux)) + { + eDebug("we'll start tuning!"); + if (m_channel) + if (m_channel->getDemux(m_demux)) + eDebug("shit it failed.. again."); + + if (m_demux) + { + CONNECT(m_table.tableReady, eMain::tableReady); + m_table.begin(this, eDVBPMTSpec(0x20, 0x33f6), m_demux); + } + } + + m_last_channel_state = state; + } + + void tableReady(int) + { + ePtr > ptr; + if (!m_table.getCurrent(ptr)) + { + ProgramMapTableConstIterator i; + for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i) + { + const ProgramMapTable &pmt = **i; + eDebug("pcr pid: %x", pmt.getPcrPid()); + } + eDebug("program map ..."); + quit(0); + } + eDebug("table ready."); + } + + ~eMain() + { + eDebug("... nicht mehr."); + } +}; + +#ifdef OBJECT_DEBUG +int object_total_remaining; + +void object_dump() +{ + printf("%d items left\n", object_total_remaining); +} +#endif + +int main() +{ +#ifdef OBJECT_DEBUG + atexit(object_dump); +#endif + eMain app; + return app.exec(); +} diff --git a/main/enigma-scan.cpp b/main/enigma-scan.cpp new file mode 100644 index 00000000..af50548e --- /dev/null +++ b/main/enigma-scan.cpp @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class eMain: public eApplication, public Object +{ + eInit init; + + eDVBScan *m_scan; + + ePtr m_mgr; + ePtr m_channel; + ePtr m_dvbdb; + + void scanEvent(int evt) + { + eDebug("scan event %d!", evt); + if (evt == eDVBScan::evtFinish) + { + m_scan->insertInto(m_dvbdb); + quit(0); + } + } + ePtr m_scan_event_connection; +public: + eMain() + { + m_dvbdb = new eDVBDB(); + m_mgr = new eDVBResourceManager(); + + eDVBFrontendParametersSatellite fesat; + + fesat.frequency = 11817000; // 12070000; + fesat.symbol_rate = 27500000; + fesat.polarisation = eDVBFrontendParametersSatellite::Polarisation::Vertical; + fesat.fec = eDVBFrontendParametersSatellite::FEC::f3_4; + fesat.inversion = eDVBFrontendParametersSatellite::Inversion::Off; + fesat.orbital_position = 192; + + eDVBFrontendParameters *fe = new eDVBFrontendParameters(); + + fe->setDVBS(fesat); + + if (m_mgr->allocateRawChannel(m_channel)) + eDebug("shit it failed!"); + +// init.setRunlevel(eAutoInitNumbers::main); + eDebug("starting scan..."); + + std::list > list; + + list.push_back(fe); + + m_scan = new eDVBScan(m_channel); + m_scan->start(list); + + m_scan->connectEvent(slot(*this, &eMain::scanEvent), m_scan_event_connection); + } + + ~eMain() + { + delete m_scan; + eDebug("... nicht mehr."); + } +}; + +#ifdef OBJECT_DEBUG +int object_total_remaining; + +void object_dump() +{ + printf("%d items left\n", object_total_remaining); +} +#endif + +int main() +{ +#ifdef OBJECT_DEBUG + atexit(object_dump); +#endif + eMain app; + return app.exec(); +} diff --git a/main/enigma.cpp b/main/enigma.cpp new file mode 100644 index 00000000..7543e451 --- /dev/null +++ b/main/enigma.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +class eMain: public eApplication, public Object +{ + eInit init; + + ePtr m_mgr; + ePtr m_channel; + ePtr m_dvbdb; + + ePtr m_playservice; +public: + eMain() + { + init.setRunlevel(eAutoInitNumbers::main); + m_dvbdb = new eDVBDB(); + m_mgr = new eDVBResourceManager(); + m_mgr->setChannelList(m_dvbdb); + + ePtr service_center; + eServiceCenter::getInstance(service_center); + + if (service_center) + { + eServiceReference ref("2:0:1:0:0:0:0:0:0:0:/"); + ePtr lst; + if (service_center->list(ref, lst)) + eDebug("no list available!"); + else + { + std::list list; + if (lst->getContent(list)) + eDebug("list itself SUCKED AROUND!!!"); + else + for (std::list::const_iterator i(list.begin()); + i != list.end(); ++i) + eDebug("%s", i->toString().c_str()); + } + } + + eServiceReference ref("1:0:1:6de2:44d:1:c00000:0:0:0:"); + + if (service_center) + { + if (service_center->play(ref, m_playservice)) + eDebug("play sucked around!"); + else + eDebug("play r00lz!"); + } else + eDebug("no service center: no play."); + } + + ~eMain() + { + + } +}; + +#ifdef OBJECT_DEBUG +int object_total_remaining; + +void object_dump() +{ + printf("%d items left\n", object_total_remaining); +} +#endif + +int main() +{ +#ifdef OBJECT_DEBUG + atexit(object_dump); +#endif + eMain app; + return app.exec(); +} diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 00000000..9788f702 --- /dev/null +++ b/stamp-h.in @@ -0,0 +1 @@ +timestamp