### The C++ compiler and options:
CXX ?= g++
-CXXFLAGS ?= -O2 -fPIC -Wall -Woverloaded-virtual -Werror
+ifdef DEBUG
+CXXFLAGS ?= -g -fPIC -Wall -Woverloaded-virtual #-Werror
+else
+CXXFLAGS ?= -O2 -fPIC -Wall -Woverloaded-virtual #-Werror
+endif
### The directory environment:
-include $(VDRDIR)/Make.config
+### read standlone settings if there
+-include .standalone
+
### The version number of VDR (taken from VDR's "config.h"):
VDRVERSION = $(shell grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g')
INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include
-DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' -DVOMPSERVER
### The object files (add further files here):
OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o bootpd.o tftpd.o i18n.o vompclient.o tcp.o \
ringbuffer.o mvprelay.o vompclientrrproc.o \
- recplayer.o config.o log.o thread.o mvpreceiver.o tftpclient.o \
- media.o responsepacket.o
+ config.o log.o thread.o tftpclient.o \
+ media.o responsepacket.o \
+ mediafile.o mediaplayer.o servermediafile.o serialize.o medialauncher.o
+
+OBJS2 = recplayer.o mvpreceiver.o
### Implicit rules:
### Targets:
-all: libvdr-$(PLUGIN).so
+all: allbase libvdr-$(PLUGIN).so
+standalone: standalonebase vompserver-standalone
+
+objectsstandalone: $(OBJS)
+objects: $(OBJS) $(OBJS2)
-libvdr-$(PLUGIN).so: $(OBJS)
- $(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@
+allbase:
+ ( if [ -f .standalone ] ; then ( rm -f .standalone; make clean ; make objects ) ; else exit 0 ;fi )
+standalonebase:
+ ( if [ ! -f .standalone ] ; then ( make clean; echo "DEFINES+=-DVOMPSTANDALONE" > .standalone; echo "DEFINES+=-D_FILE_OFFSET_BITS=64" >> .standalone; make objectsstandalone ) ; else exit 0 ;fi )
+
+libvdr-$(PLUGIN).so: objects
+ $(CXX) $(CXXFLAGS) -shared $(OBJS) $(OBJS2) -o $@
@cp $@ $(LIBDIR)/$@.$(APIVERSION)
+vompserver-standalone: objectsstandalone
+ $(CXX) $(CXXFLAGS) $(OBJS) -lpthread -o $@
+ chmod u+x $@
+
dist: clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@mkdir $(TMPDIR)/$(ARCHIVE)
@echo Distribution package created as $(PACKAGE).tgz
clean:
- rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
+ rm -f $(OBJS) $(OBJS2) $(DEPFILE) libvdr*.so.* *.tgz core* *~ .standalone vompserver-standalone
+
You should have received a copy of the GNU General Public License
along with VOMP; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "media.h"
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <iostream>
+#include <time.h>
+#include <arpa/inet.h>
+#ifndef SNPRINTF
+#define SNPRINTF snprintf
+#endif
+MediaURI::MediaURI(const MediaURI *cp) {
+ if ( ! cp) {
+ _providerId=0;
+ _name=NULL;
+ _display=NULL;
+ _allowedTypes=MEDIA_TYPE_ALL;
+ }
+ else {
+ _providerId=cp->_providerId;
+ _allowedTypes=cp->_allowedTypes;
+ _name=NULL;
+ if (cp->_name) {
+ _name=new char[strlen(cp->_name)+1];
+ strcpy(_name,cp->_name);
+ }
+ _display=NULL;
+ if (cp->_display) {
+ _display=new char[strlen(cp->_display)+1];
+ strcpy(_display,cp->_display);
+ }
+ }
+}
+MediaURI::MediaURI(ULONG p, const char * n, const char * dp) {
+ _allowedTypes=MEDIA_TYPE_ALL;
+ _providerId=p;
+ if (n) {
+ _name=new char[strlen(n)+1];
+ strcpy(_name,n);
+ } else {
+ _name=NULL;
+ }
+ _display=NULL;
+ if (dp) {
+ _display=new char[strlen(dp)+1];
+ strcpy(_display,dp);
+ }
+}
-Media::Media(int type, const char * filename, int time){
- _filename=NULL;
- if (filename) {
- int len=strlen(filename)+1;
- _filename=new char[len];
- strcpy(_filename,filename);
- }
- _type=type;
- _time=time;
- };
+int MediaURI::getSerializedLenImpl() {
+ int rt=4+4; //provider+allowedType
+ rt+=getSerializedStringLen(_name);
+ rt+=getSerializedStringLen(_display);
+ return rt;
+}
+/**
+ * 4 provider
+ * 4 allowedType
+ * 4 namelen (incl. 0)
+ * name+0
+ * 4 displaylen (incl. 0)
+ * display+0
+ */
+int MediaURI::serializeImpl(SerializeBuffer *b) {
+ version=1;
+ if (b->encodeLong(_providerId) != 0) return -1;
+ if (b->encodeLong(_allowedTypes) != 0) return -1;
+ if (b->encodeString(_name) != 0) return -1;
+ if (b->encodeString(_display) != 0) return -1;
+ return 0;
+}
+
+int MediaURI::deserializeImpl(SerializeBuffer *b) {
+ if (_name) delete _name;
+ _name=NULL;
+ if (_display) delete _display;
+ _display=NULL;
+ if (b->decodeLong(_providerId) != 0) return -1;
+ if (b->decodeLong(_allowedTypes) != 0) return -1;
+ ULONG nlen=0;
+ if (b->decodeString(nlen,_name) != 0) return -1;
+ if (b->decodeString(nlen,_display) != 0) return -1;
+ //if (version > 1) ...
+ return 0;
+}
+
+
+
+
+int MediaInfo::getSerializedLenImpl() {
+ int rt=8+1+4+4; //8len+1canPos+4type+4subtype
+ return rt;
+}
+
+
+/**
+ * serialize to buffer
+ * 8 len
+ * 1 canPos
+ * 4 type
+ * 4 subtype
+ */
+int MediaInfo::serializeImpl(SerializeBuffer *b) {
+ if (b->encodeLongLong(size) != 0) return -1;
+ if (b->encodeByte(canPosition?1:0) != 0) return -1;
+ if (b->encodeLong(type) != 0) return -1;
+ if (b->encodeLong(subtype) != 0) return -1;
+ return 0;
+}
+/**
+ * deserialize
+ * should be compatible to older serialize functions
+ */
+int MediaInfo::deserializeImpl(SerializeBuffer *b) {
+ if (b->decodeLongLong(size) != 0) return -1;
+ UCHAR cp=0;
+ if (b->decodeByte(cp) != 0) return -1;
+ canPosition=cp!=0;
+ if (b->decodeLong(type) != 0) return -1;
+ if (b->decodeLong(subtype) != 0) return -1;
+ return 0;
+}
+
+
+
+Media::Media()
+{
+ mtime = 0;
+ displayName = NULL;
+ fileName = NULL;
+ mediaType=MEDIA_TYPE_UNKNOWN;
+ uri=NULL;
+ index=0;
+}
-Media::~Media(){
- delete _filename;
- _filename=NULL;
- };
+Media::Media(const Media *m) {
+ Media();
+ if (! m) return;
+ mtime=m->mtime;
+ mediaType=m->mediaType;
+ uri=NULL;
+ fileName=NULL;
+ displayName=NULL;
+ if (m->uri) uri=new MediaURI(m->uri);
+ setFileName(m->fileName);
+ setDisplayName(m->displayName);
+ index=m->index;
+}
+
+Media::~Media()
+{
+ if (displayName) { delete[] displayName; displayName = NULL; }
+ if (fileName) { delete[] fileName; fileName = NULL; }
+ if (uri) delete uri;
+ index = -1; // just in case
+}
+
+ULONG Media::getTime() const
+{
+ return mtime;
+}
+
+const char* Media::getDisplayName() const
+{
+ if (displayName) return displayName;
+ return fileName;
+}
+
+const char* Media::getFileName() const
+{
+ return fileName;
+}
+
+void Media::setTime(ULONG tstartTime)
+{
+ mtime = tstartTime;
+}
+
+void Media::setMediaType(ULONG mtype)
+{
+ mediaType=mtype;
+}
+
+ULONG Media::getMediaType() const
+{
+ return mediaType;
+}
+
+void Media::setDisplayName(const char* tDisplayName)
+{
+ if (displayName) delete[] displayName;
+ displayName=NULL;
+ if (! tDisplayName) return;
+ displayName = new char[strlen(tDisplayName) + 1];
+ if (displayName) strcpy(displayName, tDisplayName);
+}
+
+void Media::setFileName(const char* tFileName)
+{
+ if (fileName) delete[] fileName;
+ fileName=NULL;
+ if (! tFileName) return;
+ fileName = new char[strlen(tFileName) + 1];
+ if (fileName) strcpy(fileName, tFileName);
+}
-const char * Media::getFilename() {
- return _filename;
+bool Media::hasDisplayName() const {
+ return (displayName != NULL);
+}
+
+char * Media::getTimeString(char * buffer) const {
+ if (! buffer) buffer=new char[TIMEBUFLEN];
+ struct tm ltime;
+ time_t tTime = (time_t)getTime();
+ struct tm *btime = localtime(&tTime);
+ memcpy(<ime,btime, sizeof(struct tm));
+ btime=<ime;
+ if (btime && tTime != 0) {
+#ifndef _MSC_VER
+ strftime(buffer,TIMEBUFLEN, "%0g/%0m/%0d %0H:%0M ", btime);
+#else
+ strftime(buffer, TIMEBUFLEN, "%g/%m/%d %H:%M ", btime);
+#endif
}
+ else {
+ SNPRINTF(buffer,TIMEBUFLEN,"00/00/00 00:00 ");
+ }
+ return buffer;
+}
+
+const MediaURI * Media::getURI() const {
+ return uri;
+}
+
+void Media::setURI(const MediaURI *u) {
+ if (uri) delete uri;
+ uri=new MediaURI(u);
+}
+
+int Media::getSerializedLenImpl() {
+ int rt=4+4+1; //type,time,hasURI
+ rt+=getSerializedStringLen(fileName);
+ rt+=getSerializedStringLen(displayName);
+ if (uri) rt+=uri->getSerializedLen();
+ return rt;
+}
+/**
+ * 4 type
+ * 4 time
+ * 4 namelen (incl. 0)
+ * name+0
+ * 4 displaylen (incl. 0)
+ * display+0
+ * 1 hasURI
+ * URI
+ */
+int Media::serializeImpl(SerializeBuffer *b) {
+ if (b->encodeLong(mediaType) != 0) return -1;
+ if (b->encodeLong(mtime) != 0) return -1;
+ if (b->encodeString(fileName) != 0) return -1;
+ if (b->encodeString(displayName) != 0) return -1;
-int Media::getType() {
- return _type;
+ if (b->encodeByte(uri?1:0) != 0) return -1;
+ if (uri) {
+ if (uri->serialize(b) != 0) return -1;
}
-int Media::getTime() {
- return _time;
+ return 0;
+}
+
+int Media::deserializeImpl(SerializeBuffer *b) {
+ if (fileName) delete fileName;
+ fileName=NULL;
+ if (displayName) delete displayName;
+ displayName=NULL;
+ if (uri) delete uri;
+ uri=NULL;
+ if (b->decodeLong(mediaType) != 0) return -1;
+ if (b->decodeLong(mtime) != 0) return -1;
+ ULONG nlen=0;
+ if (b->decodeString(nlen,fileName) != 0) return -1;
+ if (b->decodeString(nlen,displayName) != 0) return -1;
+ UCHAR hasURI=0;
+ if (b->decodeByte(hasURI) != 0) return -1;
+ if (hasURI!=0) {
+ uri=new MediaURI();
+ if (uri->deserialize(b) != 0) return -1;
}
+ return 0;
+}
-static struct mtype{
- const char* extension;
- int type;
- } mediatypes[]= {
- {".mp3",MEDIA_TYPE_AUDIO},
- {".MP3",MEDIA_TYPE_AUDIO},
- {".jpg",MEDIA_TYPE_PICTURE},
- {".JPG",MEDIA_TYPE_PICTURE},
- {".jpeg",MEDIA_TYPE_PICTURE},
- {".JPEG",MEDIA_TYPE_PICTURE}
- };
-//#define NUMTYPES (sizeof(mediatypes)/sizeof(mtype))
-#define NUMTYPES 6
-//helper from vdr tools.c
-bool endswith(const char *s, const char *p)
-{
- const char *se = s + strlen(s) - 1;
- const char *pe = p + strlen(p) - 1;
- while (pe >= p) {
- if (*pe-- != *se-- || (se < s && pe >= p))
- return false;
- }
- return true;
-}
-
-
-MediaList * MediaList::readList(Config * cfg,const char * dirname, int type) {
- MediaList *rt=NULL;
- if (dirname == NULL) {
- //the configured Media List
- //for the moment up to 10 entries [Media] Dir.1 ...Dir.10
- for (int nr=1;nr<=10;nr++){
- char buffer[20];
- sprintf(buffer,"Dir.%d",nr);
- const char * dn=cfg->getValueString("Media",buffer);
- if (dn != NULL) {
- if (rt == NULL) rt=new MediaList();
- Media *m=new Media(MEDIA_TYPE_DIR,dn,0);
- rt->push_back(m);
- Log::getInstance()->log("Media",Log::DEBUG,"added base dir %s",dn);
- }
- }
- }
- if (rt != NULL) return rt;
- //if nothing is configured, we start at /
- if (dirname == NULL) dirname="/";
- rt=new MediaList();
- //open the directory and read out the entries
- DIR *d=opendir(dirname);
- struct dirent *e;
- union { // according to "The GNU C Library Reference Manual"
- struct dirent d;
- char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
- } u;
-
- while (d != NULL && (readdir_r(d,&u.d,&e) == 0) && e != NULL) {
- {
- const char * fname=e->d_name;
- if ( fname == NULL) continue;
- if (strcmp(fname,".") == 0) continue;
- char *buffer;
- asprintf(&buffer, "%s/%s", dirname, e->d_name);
- struct stat st;
- int mtype=MEDIA_TYPE_UNKNOWN;
- if (stat(buffer, &st) == 0) {
- if (S_ISDIR(st.st_mode)) {
- mtype=MEDIA_TYPE_DIR;
- }
- else {
- for (int i=0;i<NUMTYPES;i++) {
- if (endswith(fname,mediatypes[i].extension)) {
- mtype=mediatypes[i].type;
- break;
- }
- }
- }
- }
- free(buffer);
- //only consider entries we accept by type here
- if (mtype & type) {
- Media * m =new Media(mtype,fname,(int)(st.st_mtime));
- rt->push_back(m);
- Log::getInstance()->log("Media",Log::DEBUG,"added entry %s, type=%d",fname,mtype);
- }
+MediaURI * MediaList::getURI(Media * m) {
+ if (! m) return NULL;
+ const MediaURI *rtc=m->getURI();
+ if (rtc) return new MediaURI(rtc);
+ if (!_root) return NULL;
+ if (! m->getFileName()) return NULL;
+ int len=strlen(m->getFileName());
+ if (_root->getName()) len+=strlen(_root->getName())+1;
+ MediaURI *rt=new MediaURI();
+ rt->_name=new char[len+1];
+ const char *fn=m->getFileName();
+ if (_root->getName()) {
+ while (*fn=='/') fn++;
+ sprintf(rt->_name,"%s/%s",_root->getName(),fn);
+ }
+ else {
+ sprintf(rt->_name,"%s",fn);
+ }
+ if (m->hasDisplayName() || _root->hasDisplayName()) {
+ len=strlen(m->getDisplayName())+1;
+ if (_root->hasDisplayName()) {
+ len+=strlen(_root->getDisplayName())+2;
+ }
+ rt->_display=new char[len];
+ if (_root->hasDisplayName()) {
+ const char *sp=m->getDisplayName();
+ if (*sp=='/')sp++;
+ sprintf(rt->_display,"%s/%s",_root->getDisplayName(),sp);
+ }
+ else {
+ sprintf(rt->_display,"%s",m->getDisplayName());
}
}
- if (d != NULL) closedir(d);
+ rt->_providerId=_root->_providerId;
+ rt->_allowedTypes=_root->_allowedTypes;
return rt;
+}
+
+MediaURI * MediaList::getParent(MediaURI *c) {
+ MediaURI * rt=new MediaURI();
+ rt->_providerId=c->_providerId;
+ rt->_allowedTypes=c->_allowedTypes;
+ ULONG nlen=0;
+ if (c->_name) {
+ char * ls=strrchr(c->_name,'/');
+ if (ls) {
+ nlen=ls-c->_name;
+ rt->_name=new char[nlen+1];
+ strncpy(rt->_name,c->_name,nlen);
+ rt->_name[nlen]=0;
+ }
+ }
+ if (c->_display) {
+ char * ls=strrchr(c->_display,'/');
+ if (ls) {
+ nlen=ls-c->_display;
+ rt->_display=new char[nlen+1];
+ strncpy(rt->_display,c->_display,nlen);
+ rt->_display[nlen]=0;
+ }
}
+ return rt;
+}
+
+
+MediaList::MediaList(const MediaURI *root) {
+ _root=new MediaURI(root);
+ _owning=true;
+}
+
MediaList::~MediaList() {
- MediaList::iterator it=this->begin();
- while (it < this->end()) {
- delete *it;
- it++;
+ emptyList();
+}
+void MediaList::emptyList(){
+ if (_owning) {
+ for (UINT i = 0; i < size(); i++)
+ {
+ delete (*this)[i];
+ }
}
+ clear();
+ if (_root) delete _root;
+ _root=NULL;
+ _owning=true;
+}
+
+
+MediaURI * MediaList::getRootURI() {
+ if ( ! _root) return NULL;
+ return new MediaURI(_root);
+}
+
+ULONG MediaList::getProvider() {
+ if (! _root) return 0;
+ return _root->getProvider();
}
+void MediaList::setOwning(bool owning) {
+ _owning=owning;
+}
+
+
+
+int MediaList::getSerializedLenImpl() {
+ int rt=4+1; //numelem+hasRoot
+ if (_root) rt+=_root->getSerializedLen();
+ for (MediaList::iterator it=begin();it<end();it++) {
+ rt+=(*it)->getSerializedLen();
+ }
+ return rt;
+}
+
+/**
+ * 4 numelem
+ * 1 hasRoot
+ * URI root
+ * nx Media elements
+ *
+ */
+int MediaList::serializeImpl(SerializeBuffer *b) {
+ if (b->encodeLong(size()) != 0) return -1;
+ if (b->encodeByte(_root?1:0) != 0) return -1;
+ if (_root) {
+ if (_root->serialize(b) != 0) return -1;
+ }
+ for (MediaList::iterator it=begin();it<end();it++) {
+ if ((*it)->serialize(b) !=0) return -1;
+ }
+ return 0;
+}
+
+int MediaList::deserializeImpl(SerializeBuffer *b) {
+ emptyList();
+ ULONG numelem;
+ if (b->decodeLong(numelem) != 0) return -1;
+ UCHAR hasRoot=0;
+ if (b->decodeByte(hasRoot) != 0) return -1;
+ if (hasRoot!=0) {
+ _root=new MediaURI();
+ if (_root->deserialize(b) != 0) return -1;
+ }
+ for (ULONG i=0;i<numelem;i++) {
+ Media *m=new Media();
+ if (m->deserialize(b) != 0) {
+ delete m;
+ return -1;
+ }
+ push_back(m);
+ }
+ return 0;
+}
+
+
You should have received a copy of the GNU General Public License
along with VOMP; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef MEDIA_H
#define MEDIA_H
-#include <stdio.h>
-#include <pthread.h>
-#include <signal.h>
-#include <endian.h>
-
-#include <unistd.h> // sleep
-#include <vector>
-
using namespace std;
-//#include "defines.h"
-//#include "tcp.h"
-//#include "mvpreceiver.h"
-//#include "recplayer.h"
-#include "config.h"
+#include <vector>
+#include <stdio.h>
+#include <string.h>
+#include "defines.h"
+#include "serialize.h"
-//the following defines must be consisten to the client side
/* media types form a bitmask
so you can add them to have > 1*/
#define MEDIA_TYPE_DIR 1
#define MEDIA_TYPE_AUDIO 2
#define MEDIA_TYPE_VIDEO 4
#define MEDIA_TYPE_PICTURE 8
-#define MEDIA_TYPE_UNKNOWN 256
+#define MEDIA_TYPE_UNKNOWN 0
#define MEDIA_TYPE_ALL (1+2+4+8)
-class Media
-{
+/**
+ * MediaURI - a data holder for the complete path to a media
+ * depending on the provider there is an internal name and a display name
+ * by providing own MediaList implementations the provider can control
+ * how URIs are concatenated
+ */
+class MediaURI : public Serializable{
+ //to be able to access private members
+ friend class MediaList;
+ private:
+ char * _name;
+ char * _display;
+ ULONG _providerId;
+ ULONG _allowedTypes;
public:
+ MediaURI() {
+ _name=NULL;
+ _display=NULL;
+ _providerId=0;
+ _allowedTypes=MEDIA_TYPE_ALL;
+ }
+ //constructor copying params
+ MediaURI(ULONG provider, const char * name, const char * display);
+ virtual ~MediaURI() {
+ if (_name) delete _name;
+ if (_display) delete _display;
+ }
+ MediaURI(const MediaURI *cp) ;
+ const char * getName() const { return _name;}
+ const char * getDisplayName() const {
+ if (_display) return _display;
+ return _name;
+ }
+ ULONG getProvider() const {
+ return _providerId;
+ }
+ void setProvider(ULONG pid) {
+ _providerId=pid;
+ }
+ ULONG getAllowedTypes() const {
+ return _allowedTypes;
+ }
+ void setAllowedTypes(ULONG allowedTypes) {
+ _allowedTypes=allowedTypes;
+ }
+ bool hasDisplayName() const {
+ return _display!=NULL;
+ }
+
+ //serialize functions
+ //get the #of bytes needed to serialize
+ virtual int getSerializedLenImpl();
+ //serialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ virtual int serializeImpl(SerializeBuffer *b);
+ //deserialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ virtual int deserializeImpl(SerializeBuffer *b);
+
+};
+
+/**
+ * a class providing additional info for a medium
+ */
+class MediaInfo : public Serializable{
+ public:
+ ULLONG size;
+ bool canPosition;
+ ULONG type; //a media type
+ ULONG subtype; //TODO
/**
- * create a media entry
- * filename will get copied
+ * return any info item contained within this info
*/
- Media(int type, const char * filename, int time);
- ~Media();
- const char * getFilename();
- int getType();
- int getTime();
+ virtual const char * getInfo(ULONG infoId) { return NULL;}
+ virtual ULLONG getIntegerInfo(ULONG infoId) { return 0;}
+ virtual const char * getInfoName(ULONG infoId) { return NULL;}
+ virtual bool hasInfo(ULONG infoId) { return false;}
+ MediaInfo() {
+ size=0;
+ canPosition=true;
+ type=MEDIA_TYPE_UNKNOWN;
+ subtype=0;
+ }
+ virtual ~MediaInfo(){};
+ //serialize functions
+ //get the #of bytes needed to serialize
+ virtual int getSerializedLenImpl();
+ //serialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ virtual int serializeImpl(SerializeBuffer *b);
+ //deserialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ virtual int deserializeImpl(SerializeBuffer *b);
+};
+
+/**
+ * the Media class - a data holder describing a single media
+ * WITHOUT the complete path
+ * to retrieve an URI you need the list where this media is contained
+ * this has the root URI and can construct the URI for this media
+ * optional the media can contain an UIR by itself - then this is used
+ */
+
+class Media : public Serializable
+{
+ friend class MediaList;
+ public:
+ Media();
+ Media(const Media *m);
+ virtual ~Media();
+
+ void setTime(ULONG mtimeTime);
+ void setDisplayName(const char* displayName);
+ void setFileName(const char* fileName);
+ void setMediaType(ULONG mtype);
+
+ ULONG getTime() const;
+ const char* getDisplayName() const;
+ const char* getFileName() const;
+ //return the time as a string
+ //if the user provides a buffer, this one is used, if NULL
+ //is given a new buffer is allocated
+ //caller must delete the buffer after usage!
+ char * getTimeString(char *buffer) const;
+ //length for the time display buffer
+ const static int TIMEBUFLEN=100;
+ int index;
+ ULONG getMediaType() const;
+ bool hasDisplayName() const;
+ //optionally the media can contain an URI
+ //in this case the filename is not considered
+ //but the data from the URI is taken
+ //this enables having another providerId set in the media...
+ //returns URI without copy
+ const MediaURI * getURI() const;
+ void setURI(const MediaURI *uri);
+
+ //serialize functions
+ //get the #of bytes needed to serialize
+ virtual int getSerializedLenImpl();
+ //serialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ virtual int serializeImpl(SerializeBuffer *b);
+ //deserialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ virtual int deserializeImpl(SerializeBuffer *b);
+
private:
- char * _filename;
- int _type;
- int _time;
+ ULONG mtime;
+ char* displayName;
+ char* fileName;
+ ULONG mediaType;
+ MediaURI *uri;
};
-class MediaList : public vector<Media*> {
+
+typedef vector<Media*> MediaListI;
+
+/**
+ * the MediaList - containing a root URI and
+ * all the Media entries
+ * providers can provide derived classes to overwrite the URI-Methods
+ */
+class MediaList : public MediaListI , public Serializable{
+ private:
+ MediaURI *_root;
+ bool _owning;
+ void emptyList();
public:
- static MediaList *readList(Config *cfg,const char * dirname,int type=MEDIA_TYPE_ALL);
- ~MediaList();
- };
+ MediaList(const MediaURI *root); //root is copied
+ virtual ~MediaList();
+ //no copy root UIR
+ virtual MediaURI * getRoot() {return _root;}
+ //all methods return a copy of the URI
+ //so the caller has to destroy this
+ virtual MediaURI * getRootURI();
+ virtual MediaURI * getParent(MediaURI *c) ;
+ virtual MediaURI * getURI(Media *m);
+ virtual ULONG getProvider();
+ virtual void setOwning(bool owning);
+ //serialize functions
+ //get the #of bytes needed to serialize
+ virtual int getSerializedLenImpl();
+ //serialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ virtual int serializeImpl(SerializeBuffer *b);
+ //deserialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ virtual int deserializeImpl(SerializeBuffer *b);
+ };
#endif
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "mediafile.h"
+#include "media.h"
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <iostream>
+#include "log.h"
+
+
+
+
+MediaFile::MediaFile(ULONG pid){
+ providerid=pid;
+}
+
+MediaFile::~MediaFile(){
+ };
+
+
+
+static struct mtype{
+ const char* extension;
+ ULONG type;
+ } mediatypes[]= {
+ {".mp3",MEDIA_TYPE_AUDIO},
+ {".MP3",MEDIA_TYPE_AUDIO},
+ {".jpg",MEDIA_TYPE_PICTURE},
+ {".JPG",MEDIA_TYPE_PICTURE},
+ {".jpeg",MEDIA_TYPE_PICTURE},
+ {".JPEG",MEDIA_TYPE_PICTURE},
+ {".mpg",MEDIA_TYPE_VIDEO},
+ {".MPG",MEDIA_TYPE_VIDEO}
+ };
+//#define NUMTYPES (sizeof(mediatypes)/sizeof(mtype))
+#define NUMTYPES 8
+
+//helper from vdr tools.c
+bool endswith(const char *s, const char *p)
+{
+ const char *se = s + strlen(s) - 1;
+ const char *pe = p + strlen(p) - 1;
+ while (pe >= p) {
+ if (*pe-- != *se-- || (se < s && pe >= p))
+ return false;
+ }
+ return true;
+}
+
+MediaList* MediaFile::getRootList() {
+ //has to be implemented in the derived class
+ return NULL;
+}
+
+ULONG MediaFile::getMediaType(const char * filename) {
+ for (ULONG i=0;i<NUMTYPES;i++) {
+ if (endswith(filename,mediatypes[i].extension)) {
+ return mediatypes[i].type;
+ }
+ }
+ return MEDIA_TYPE_UNKNOWN;
+}
+
+
+Media * MediaFile::createMedia(const char * dirname, const char * filename, bool withURI) {
+ Media * rt=NULL;
+ char *buffer;
+ asprintf(&buffer, "%s/%s", dirname, filename);
+ struct stat st;
+ ULONG mtype=MEDIA_TYPE_UNKNOWN;
+ if (stat(buffer, &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ mtype=MEDIA_TYPE_DIR;
+ }
+ else {
+ mtype=getMediaType(filename);
+ }
+ }
+ //only consider entries we accept by type here
+ if (mtype != MEDIA_TYPE_UNKNOWN) {
+ rt =new Media();
+ rt->setMediaType(mtype);
+ rt->setFileName(filename);
+ rt->setTime(st.st_mtime);
+ Log::getInstance()->log("Media",Log::DEBUG,"created Media %s, type=%d",filename,mtype);
+ if (withURI) {
+ MediaURI u(providerid,buffer,NULL);
+ rt->setURI(&u);
+ }
+ }
+ free(buffer);
+ return rt;
+}
+
+MediaList* MediaFile::getMediaList(const MediaURI * parent){
+ ULONG mediaType=parent->getAllowedTypes();
+ Log::getInstance()->log("MediaFile::getMediaList",Log::DEBUG,"parent %s,types=0x%0lx",parent->getName(),mediaType);
+ MediaList *rt=NULL;
+ rt=new MediaList(parent);
+ const char *dirname=parent->getName();
+ //open the directory and read out the entries
+ DIR *d=opendir(dirname);
+ struct dirent *e;
+ union { // according to "The GNU C Library Reference Manual"
+ struct dirent d;
+ char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
+ } u;
+
+ while (d != NULL && (readdir_r(d,&u.d,&e) == 0) && e != NULL) {
+ const char * fname=e->d_name;
+ if ( fname == NULL) continue;
+ if (strcmp(fname,".") == 0) continue;
+ if (strcmp(fname,"..") == 0) continue;
+ Media *m=createMedia(dirname,fname);
+ if (m && ( m->getMediaType() & mediaType)) {
+ Log::getInstance()->log("Media",Log::DEBUG,"added entry %s, type=%d",fname,m->getMediaType());
+ rt->push_back(m);
+ }
+ else {
+ if (m) delete m;
+ }
+ }
+ if (d != NULL) closedir(d);
+ return rt;
+ }
+
+
+int MediaFile::openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize) {
+ Log::getInstance()->log("Media::openMedium",Log::DEBUG,"fn=%s,chan=%u",uri->getName(),channel);
+ *size=0;
+ if (channel <0 || channel >= NUMCHANNELS) return -1;
+ struct ChannelInfo *info=&channels[channel];
+ if (info->file) info->reset();
+ FILE *fp=fopen(uri->getName(),"r");
+ if (! fp) {
+ Log::getInstance()->log("Media::openMedium",Log::ERR,"unable to open file fn=%s,chan=%u",uri->getName(),channel);
+ return -1;
+ }
+ struct stat st;
+ ULLONG mysize=0;
+ if ( fstat(fileno(fp),&st) == 0) mysize=st.st_size;
+ if (mysize == 0) {
+ Log::getInstance()->log("Media::openMedium",Log::ERR,"unable to open file fn=%s,chan=%u",uri->getName(),channel);
+ fclose(fp);
+ return -1;
+ }
+ info->setFilename(uri->getName());
+ info->file=fp;
+ info->size=mysize;
+ *size=mysize;
+ info->provider=providerid;
+ return 0;
+}
+
+
+int MediaFile::getMediaBlock(ULONG channel, ULLONG offset, ULONG len, ULONG * outlen,
+ unsigned char ** buffer) {
+ Log::getInstance()->log("Media::getMediaBlock",Log::DEBUG,"chan=%u,offset=%llu,len=%lu",channel,offset,len);
+ *outlen=0;
+ if (channel <0 || channel >= NUMCHANNELS) return -1;
+ struct ChannelInfo *info=&channels[channel];
+ if (! info->file) {
+ Log::getInstance()->log("Media::getMediaBlock",Log::ERR,"not open chan=%u",channel);
+ return -1;
+ }
+ ULLONG cpos=ftell(info->file);
+ if (offset != cpos) {
+ fseek(info->file,offset-cpos,SEEK_CUR);
+ }
+ if (offset != (ULLONG)ftell(info->file)) {
+ Log::getInstance()->log("Client", Log::DEBUG, "getMediaBlock pos = %llu not available", offset);
+ return -1;
+ }
+ if (*buffer == NULL) *buffer=(UCHAR *)malloc(len);
+ if (*buffer == NULL) {
+ Log::getInstance()->log("Media::getMediaBlock",Log::ERR,"uanble to allocate buffer");
+ return -1;
+ }
+ ULONG amount=fread(*buffer,1,len,info->file);
+ Log::getInstance()->log("Media::getMediaBlock",Log::DEBUG,"readlen=%lu",amount);
+ *outlen=amount;
+ return 0;
+}
+
+
+int MediaFile::closeMediaChannel(ULONG channel){
+ Log::getInstance()->log("Media::closeMediaChannel",Log::DEBUG,"chan=%u",channel);
+ if (channel <0 || channel >= NUMCHANNELS) return -1;
+ struct ChannelInfo *info=&channels[channel];
+ info->reset();
+ return 0;
+}
+
+//TODO: fill in more info
+int MediaFile::getMediaInfo(ULONG channel, MediaInfo * result){
+ Log::getInstance()->log("Media::getMediaInfo",Log::DEBUG,"chan=%u",channel);
+ if (channel <0 || channel >= NUMCHANNELS) return -1;
+ struct ChannelInfo *info=&channels[channel];
+ if (! info->file) return -1;
+ result->size=info->size;
+ result->canPosition=true;
+ return 0;
+}
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef MEDIAFILE_H
+#define MEDIAFILE_H
+
+#include "defines.h"
+#include "mediaprovider.h"
+
+
+class MediaFile : public MediaProvider
+{
+ public:
+ MediaFile(ULONG providerId);
+ virtual ~MediaFile();
+ /**
+ * get the root media list
+ * the returned list has to be destroyed by the caller
+ * if NULL is returned currently no media is available
+ */
+ virtual MediaList* getRootList();
+
+ /**
+ * get a medialist for a given parent
+ * the returned list has to be destroyed by the caller
+ * NULL if no entries found
+ */
+ virtual MediaList* getMediaList(const MediaURI * parent);
+
+ /**
+ * open a media uri
+ * afterwards getBlock or other functions must be possible
+ * currently only one medium is open at the same time
+ * for a given channel
+ * @param channel: channel id, NUMCHANNELS must be supported
+ * @param xsize,ysize: size of the screen
+ * @param size out: the size of the medium
+ * @return != 0 in case of error
+ *
+ */
+ virtual int openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize);
+
+ /**
+ * get a block for a channel
+ * @param offset - the offset
+ * @param len - the required len
+ * @param outlen out - the read len if 0 this is EOF
+ * @param buffer out the allocated buffer (must be freed with free!)
+ * @return != 0 in case of error
+ */
+ virtual int getMediaBlock(ULONG channel, ULLONG offset, ULONG len, ULONG * outlen,
+ unsigned char ** buffer);
+
+ /**
+ * close a media channel
+ */
+ virtual int closeMediaChannel(ULONG channel);
+
+ /**
+ * return the media info for a given channel
+ * return != 0 on error
+ * the caller has to provide a pointer to an existing media info
+ */
+ virtual int getMediaInfo(ULONG channel, MediaInfo * result);
+
+
+ protected:
+ /**
+ * create a Media out of a given file
+ * the Media object ha sto be deleted by the caller
+ * return NULL if not there or no matching type
+ */
+ Media * createMedia(const char * dirname, const char * filename, bool withURI=false);
+ struct ChannelInfo {
+ public:
+ FILE *file;
+ ULONG provider;
+ char *filename;
+ ULLONG size;
+ ChannelInfo(){
+ file=NULL;
+ provider=0;
+ filename=NULL;
+ size=0;
+ }
+ ~ChannelInfo(){
+ if (filename) delete[]filename;
+ if (file) fclose(file);
+ }
+ void setFilename(const char *f) {
+ if (filename) delete[] filename;
+ filename=NULL;
+ if (f) {
+ filename=new char[strlen(f)+1];
+ strcpy(filename,f);
+ }
+ }
+ void reset() {
+ if (file) fclose(file);
+ file=NULL;
+ if (filename) delete [] filename;
+ filename=NULL;
+ }
+ };
+ struct ChannelInfo channels[NUMCHANNELS];
+ ULONG providerid;
+
+ virtual ULONG getMediaType(const char *filename);
+
+};
+
+#endif
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "medialauncher.h"
+#include "media.h"
+#include <iostream>
+#include "log.h"
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+
+
+#define MAXCMD 50
+
+MediaLauncher::MediaLauncher(Config *c) {
+ cfg=c;
+ numcommands=0;
+ commands=NULL;
+ pnum=-1;
+ child=-1;
+}
+
+MediaLauncher::~MediaLauncher(){
+ if (commands) {
+ for (int i=0;i<numcommands;i++)
+ delete commands[i];
+ delete commands;
+ }
+ };
+
+MediaLauncher::MCommand::MCommand(const char *n,ULONG t,const char *ext) {
+ command=new char[strlen(n)+1];
+ strcpy(command,n);
+ mediaType=t;
+ extension=new char[strlen(ext)+1];
+ strcpy(extension,ext);
+}
+MediaLauncher::MCommand::~MCommand() {
+ delete command;
+ delete extension;
+}
+
+#define NUMTYPES 4
+
+static struct {
+ const char* mtypename;
+ ULONG mtypeid;
+} mediatypes[]= {
+ {"PICTURE",MEDIA_TYPE_PICTURE},
+ {"AUDIO",MEDIA_TYPE_AUDIO},
+ {"VIDEO",MEDIA_TYPE_VIDEO},
+ {"LIST",MEDIA_TYPE_DIR}
+};
+
+static ULONG typeIdFromName(const char *name) {
+ for(int i=0;i<NUMTYPES;i++){
+ if (strcasecmp(mediatypes[i].mtypename,name) == 0) return mediatypes[i].mtypeid;
+ }
+ return MEDIA_TYPE_UNKNOWN;
+}
+
+int MediaLauncher::init() {
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"init");
+
+ commands=new Pcmd[MAXCMD];
+ char buf[100];
+ for(int i=1;i<=MAXCMD;i++){
+ sprintf(buf,"Command.Name.%d",i);
+ const char *cmname=cfg->getValueString("Media",buf);
+ if (!cmname) continue;
+ sprintf(buf,"Command.Extension.%d",i);
+ const char *cmext=cfg->getValueString("Media",buf);
+ if (!cmext) continue;
+ sprintf(buf,"Command.Type.%d",i);
+ const char *cmtype=cfg->getValueString("Media",buf);
+ if (! cmtype) continue;
+ ULONG cmtypeid=typeIdFromName(cmtype);
+ if (cmtypeid == MEDIA_TYPE_UNKNOWN) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"unknown media type %s",cmtype);
+ continue;
+ }
+ commands[numcommands]=new MCommand(cmname,cmtypeid,cmext);
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"found command %s for ext %s, type %s",cmname,cmext,cmtype);
+ //check the command
+ char cbuf[strlen(cmname)+40];
+ sprintf(cbuf,"%s check",cmname);
+ int rt=system(cbuf);
+ if (rt != 0) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"testting command %s failed, ignore",cmname);
+ continue;
+ }
+ numcommands++;
+ }
+
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"found %d commands",numcommands);
+ return 0;
+}
+
+int MediaLauncher::init(MediaLauncher *cp) {
+ commands=new Pcmd[MAXCMD];
+ for (int i=0;i<cp->numcommands;i++) {
+ commands[i]=new MCommand(cp->commands[i]->command,cp->commands[i]->mediaType,cp->commands[i]->extension);
+ }
+ numcommands=cp->numcommands;
+ return 0;
+}
+
+
+
+int MediaLauncher::findCommand(const char *name){
+ const char *ext=name+strlen(name);
+ while (*ext != '.' && ext > name) ext--;
+ if (*ext == '.') ext++;
+ //Log::getInstance()->log("MediaLauncher",Log::DEBUG,"found extension %s for name %s",ext,name);
+ for (int i=0;i<numcommands;i++) {
+ if (strcasecmp(ext,commands[i]->extension) == 0) {
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"found command %s to handle name %s",commands[i]->command,name);
+ return i;
+ }
+ }
+ return -1;
+}
+
+ULONG MediaLauncher::getTypeForName(const char *name) {
+ int rt=findCommand(name);
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"getTypeForName %s entry %d",name,rt);
+ if (rt>=0) return commands[rt]->mediaType;
+ return MEDIA_TYPE_UNKNOWN;
+}
+
+int MediaLauncher::openStream(const char *fname,ULONG xsize,ULONG ysize,const char * command) {
+ if (command == NULL) command="play";
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"open stream for %s command %s",fname,command);
+ int cmnum=findCommand(fname);
+ if (cmnum < 0) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"unable to find command for %s",fname);
+ return -1;
+ }
+ if (pnum >= 0) closeStream();
+ int pfd[2];
+ if (pipe(pfd) == -1) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"unable to create pipe");
+ return -1;
+ }
+ pnum=pfd[0];
+ child=fork();
+ if (child == -1) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"unable to fork");
+ return -1;
+ }
+ if (child == 0) {
+ //we are the child
+ close(pfd[0]);
+ dup2(pfd[1],fileno(stdout));
+ close(fileno(stdin));
+ dup2(pfd[1],fileno(stderr));
+ //try to close all open FDs
+ for (int i=0;i<=sysconf(_SC_OPEN_MAX);i++) {
+ if (i != fileno(stderr) && i != fileno(stdout)) close(i);
+ }
+ char buf1[30];
+ char buf2[30];
+ sprintf(buf1,"%u",xsize);
+ sprintf(buf2,"%u",ysize);
+ execlp(commands[cmnum]->command,commands[cmnum]->command,command,fname,buf1,buf2,NULL);
+ //no chance for logging here after close... Log::getInstance()->log("MediaLauncher",Log::ERR,"unable to execlp %s",commands[cmnum]->command);
+ exit(-1);
+ }
+ if (fcntl(pnum,F_SETFL,fcntl(pnum,F_GETFL)|O_NONBLOCK) != 0) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"unable to set to nonblocking");
+ closeStream();
+ return -1;
+ }
+ //the parent
+ return child;
+}
+
+
+int MediaLauncher::closeStream() {
+ if (child <= 0) return -1;
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"close stream for child %d",child);
+ close(pnum);
+ if (kill(child,0) == 0) {
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"trying to kill child %d",child);
+ kill(child,SIGINT);
+ }
+ waitpid(child,NULL,WNOHANG);
+ for (int i=0;i< 150;i++) {
+ if (kill(child,0) == 0) {
+ usleep(10000);
+ waitpid(child,NULL,WNOHANG);
+ }
+ }
+ if (kill(child,0) == 0) {
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"child %d aktive after wait, kill -9",child);
+ kill(child,SIGKILL);
+ }
+ for (int i=0;i< 100;i++) {
+ if (kill(child,0) == 0) {
+ usleep(10000);
+ }
+ }
+ waitpid(child,NULL,WNOHANG);
+ child=-1;
+ pnum=-1;
+ return 0;
+}
+
+int MediaLauncher::getNextBlock(ULONG size,unsigned char **buffer,ULONG *readLen) {
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"get Block buf %p, len %lu",*buffer,size);
+ if (pnum <= 0) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"stream not open in getnextBlock");
+ return -1;
+ }
+ *readLen=0;
+ struct timeval to;
+ to.tv_sec=0;
+ to.tv_usec=100000; //100ms
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(pnum,&readfds);
+ int rt=select(pnum+1,&readfds,NULL,NULL,&to);
+ if (rt < 0) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"error in select");
+ return -1;
+ }
+ if (rt == 0) {
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"read 0 bytes (no data within 100ms)");
+ waitpid(child,NULL,WNOHANG);
+ if (kill(child,0) != 0) {
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"child is dead, returning EOF");
+ return 1;
+ }
+ return 0;
+ }
+ if (! FD_ISSET(pnum,&readfds)) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"error in select - nothing read");
+ return -1;
+ }
+ if (! *buffer) {
+ *buffer=(UCHAR *)malloc(size);
+ }
+ if (! *buffer) {
+ Log::getInstance()->log("MediaLauncher",Log::ERR,"unable to allocate buffer");
+ return -1;
+ }
+ ssize_t rdsz=read(pnum,*buffer,size);
+ *readLen=(ULONG)rdsz;
+ Log::getInstance()->log("MediaLauncher",Log::DEBUG,"read %lu bytes",*readLen);
+ if (rdsz == 0) return 1; //EOF
+ return 0;
+}
+
+bool MediaLauncher::isOpen() {
+ return pnum > 0;
+}
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef MEDIALAUNCHER_H
+#define MEDIALAUNCHER_H
+
+#include "media.h"
+#include "config.h"
+
+
+class MediaLauncher
+{
+ public:
+ MediaLauncher(Config *c);
+ ~MediaLauncher();
+ //let the launcher read it's config
+ //return != 0 if nothing handled
+ int init();
+ //init as a copy of another launcher
+ int init(MediaLauncher *cp);
+ //get the type for a file (if the launcher can handle it)
+ //return MEDIA_TYPE_UNKNOWN if it cannot be handled
+ ULONG getTypeForName(const char *name);
+ //open a stream, return PID of child , <0 on error
+ int openStream(const char *filename,ULONG xsize, ULONG ysize,const char * command=NULL);
+ //get the next chunk
+ //if *buffer!= NULL - use this one, else allocate an own (with malloc!)
+ //return read len (can be 0!)
+ //return <0 on error, >0 on stream end,0 on OK
+ int getNextBlock(ULONG size,unsigned char **buffer,ULONG *readLen);
+ int closeStream();
+ bool isOpen();
+
+ private:
+ Config *cfg;
+ class MCommand{
+ public:
+ char *command;
+ ULONG mediaType;
+ char *extension;
+ MCommand(const char *name,ULONG type,const char *ext);
+ ~MCommand();
+ } ;
+ typedef MCommand *Pcmd;
+ Pcmd *commands;
+ int numcommands;
+ int pnum;
+ pid_t child;
+ int findCommand(const char *name); //return -1 if not found
+
+
+};
+
+#endif
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "mediaplayer.h"
+#include "media.h"
+#include "log.h"
+
+class MediaProviderHolder {
+ public:
+ MediaProvider *provider;
+ ULONG id;
+ ULONG range;
+ MediaProviderHolder(MediaProvider *p,ULONG i, ULONG r=1) {
+ provider=p;
+ range=r;
+ id=i;
+ }
+};
+
+
+
+MediaPlayer::MediaPlayer(){}
+MediaPlayer::~MediaPlayer(){
+ for (Tplist::iterator it=plist.begin();it<plist.end();it++) {
+ delete *it;
+ }
+}
+
+/**
+ * get the root media list
+ * the returned list has to be destroyed by the caller
+ * if NULL is returned currently no media is available
+ */
+MediaList* MediaPlayer::getRootList(){
+ Log::getInstance()->log("MediaPlayer::getRootList",Log::DEBUG,"numproviders %d",plist.size());
+ MediaList * rt=new MediaList(new MediaURI(0,NULL,NULL));
+ for (Tplist::iterator it=plist.begin();it<plist.end();it++) {
+ MediaList *cur=(*it)->provider->getRootList();
+ if (cur) {
+ //we take the entries away from the list - so don't delete them with the list
+ cur->setOwning(false);
+ Log::getInstance()->log("MediaPlayer::getRootList",Log::DEBUG,"got list for provider %p with %d items",(*it),cur->size());
+ for (MediaList::iterator mi=cur->begin();mi<cur->end();mi++) {
+ Media *m=*mi;
+ //always set the URI in the root list because we combine entries
+ //from different lists
+ if (! m->getURI()) {
+ MediaURI *u=cur->getURI(m);
+ m->setURI(u);
+ Log::getInstance()->log("MediaPlayer::getRootList",Log::DEBUG,"set uri n=%s,d=%s",u->getName(),u->getDisplayName());
+ delete u;
+ }
+ rt->push_back(m);
+ Log::getInstance()->log("MediaPlayer::getRootList",Log::DEBUG,"added item to list name=%s",m->getFileName());
+ }
+ }
+ delete cur;
+ }
+ return rt;
+}
+
+/**
+ * get a medialist for a given parent
+ * the returned list has to be destroyed by the caller
+ * NULL if no entries found
+ */
+MediaList* MediaPlayer::getMediaList(const MediaURI * parent){
+ Log::getInstance()->log("MediaPlayer::getMediaList",Log::DEBUG,"numproviders %d,parent=%p",plist.size(),parent);
+ MediaProvider *p=providerById(parent->getProvider());
+ if (! p) {
+ return NULL;
+ }
+ return p->getMediaList(parent);
+}
+
+/**
+ * open a media uri
+ * afterwards getBlock or other functions must be possible
+ * currently only one medium is open at the same time
+ * for a given channel
+ * @param channel: channel id, NUMCHANNELS must be supported
+ * @param xsize,ysize: size of the screen
+ * @param size out: the size of the medium
+ * @return != 0 in case of error
+ *
+ */
+int MediaPlayer::openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize){
+ if ( channel >= NUMCHANNELS) return -1;
+ info[channel].provider=NULL;
+ *size= 0;
+ MediaProvider *p=providerById(uri->getProvider());
+ if (!p) {
+ return -1;
+ }
+ int rt=p->openMedium(channel,uri,size,xsize,ysize);
+ if (rt == 0) {
+ info[channel].providerId=uri->getProvider();
+ info[channel].provider=p;
+ }
+ return rt;
+
+}
+
+/**
+ * get a block for a channel
+ * @param offset - the offset
+ * @param len - the required len
+ * @param outlen out - the read len if 0 this is EOF
+ * @param buffer out the allocated buffer (must be freed with free!)
+ * @return != 0 in case of error
+ */
+int MediaPlayer::getMediaBlock(ULONG channel, ULLONG offset, ULONG len, ULONG * outlen,
+ unsigned char ** buffer) {
+ if ( channel >= NUMCHANNELS) return -1;
+ if ( info[channel].provider == NULL) return -1;
+ return info[channel].provider->getMediaBlock(channel,offset,len,outlen,buffer);
+}
+
+
+/**
+ * close a media channel
+ */
+int MediaPlayer::closeMediaChannel(ULONG channel){
+ if ( channel >= NUMCHANNELS) return -1;
+ if ( info[channel].provider == NULL) return -1;
+ int rt=info[channel].provider->closeMediaChannel(channel);
+ info[channel].provider=NULL;
+ info[channel].providerId=0;
+ return rt;
+}
+
+/**
+ * return the media info for a given channel
+ * return != 0 on error
+ * the caller has to provide a pointer to an existing media info
+ */
+int MediaPlayer::getMediaInfo(ULONG channel, struct MediaInfo * result){
+ if ( channel >= NUMCHANNELS) return -1;
+ if ( info[channel].provider == NULL) return -1;
+ return info[channel].provider->getMediaInfo(channel,result);
+}
+
+
+
+void MediaPlayer::registerMediaProvider(MediaProvider *p,ULONG providerId,ULONG range) {
+ if (! p) return;
+ MediaProviderHolder *h=new MediaProviderHolder(p,providerId,range);
+ Log::getInstance()->log("MediaPlayer::registerMediaProvider",Log::DEBUG,"p=%p",p);
+ plist.push_back(h);
+}
+
+MediaProvider * MediaPlayer::providerById(ULONG id) {
+ MediaProvider *rt=NULL;
+ for (Tplist::iterator it=plist.begin();it<plist.end();it++) {
+ MediaProviderHolder *h=*it;
+ if (id >= h->id && id < (h->id+h->range)) {
+ rt=h->provider;
+ break;
+ }
+ }
+ Log::getInstance()->log("MediaPlayer::providerById",Log::DEBUG,"id=%d,p=%p",id,rt);
+ return rt;
+}
+
+MediaPlayer* MediaPlayer::getInstance() {
+ return (MediaPlayer *) MediaPlayerRegister::getInstance();
+}
+
+MediaPlayerRegister* MediaPlayerRegister::getInstance() {
+ if ( ! instance) {
+ instance=new MediaPlayer();
+ }
+ return instance;
+}
+MediaPlayerRegister *MediaPlayerRegister::instance=NULL;
+
+
+
+
+
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef MEDIAPLAYER
+#define MEDIAPLAYER
+
+using namespace std;
+#include <vector>
+#include <stdio.h>
+#include <string.h>
+#include "mediaprovider.h"
+
+class MediaProviderHolder;
+
+
+class MediaPlayer : public MediaPlayerRegister, public MediaProvider
+{
+ public:
+ MediaPlayer();
+ virtual ~MediaPlayer();
+
+ /**
+ * get the root media list
+ * the returned list has to be destroyed by the caller
+ * if NULL is returned currently no media is available
+ */
+ virtual MediaList* getRootList();
+
+ /**
+ * get a medialist for a given parent
+ * the returned list has to be destroyed by the caller
+ * NULL if no entries found
+ */
+ virtual MediaList* getMediaList(const MediaURI * parent);
+
+ /**
+ * open a media uri
+ * afterwards getBlock or other functions must be possible
+ * currently only one medium is open at the same time
+ * for a given channel
+ * @param channel: channel id, NUMCHANNELS must be supported
+ * @param xsize,ysize: size of the screen
+ * @param size out: the size of the medium
+ * @return != 0 in case of error
+ *
+ */
+ virtual int openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize);
+
+ /**
+ * get a block for a channel
+ * @param offset - the offset
+ * @param len - the required len
+ * @param outlen out - the read len if 0 this is EOF
+ * @param buffer out the allocated buffer (must be freed with free!)
+ * @return != 0 in case of error
+ */
+ virtual int getMediaBlock(ULONG channel, ULLONG offset, ULONG len, ULONG * outlen,
+ unsigned char ** buffer);
+
+ /**
+ * close a media channel
+ */
+ virtual int closeMediaChannel(ULONG channel);
+
+ /**
+ * return the media info for a given channel
+ * return != 0 on error
+ * the caller has to provide a pointer to an existing media info
+ */
+ virtual int getMediaInfo(ULONG channel, struct MediaInfo * result);
+
+ /**
+ * from MediaPlayerRegister
+ */
+ virtual void registerMediaProvider(MediaProvider *p,ULONG providerID,ULONG range);
+
+ /**
+ * the instance
+ */
+ static MediaPlayer * getInstance();
+
+ private:
+ MediaProvider * providerById(ULONG id);
+ typedef vector<MediaProviderHolder *> Tplist;
+ Tplist plist;
+ struct channelInfo {
+ ULONG providerId;
+ MediaProvider *provider;
+ channelInfo() {
+ provider=NULL;
+ providerId=0;
+ }
+ };
+ struct channelInfo info[NUMCHANNELS];
+
+};
+
+
+#endif
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef MEDIAPROVIDER_H
+#define MEDIAPROVIDER_H
+
+#include <stdio.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include "defines.h"
+
+class Media;
+class MediaURI;
+class MediaInfo;
+class MediaList;
+
+
+/**
+ this interface has to be implemented by
+ any provider of media data.
+ In all URIs the provider has to insert providerIds out of its range.
+ threading issues:
+ all operations to one channel are not thread save - so users have to ensure
+ that at most one thread at a time is accesing operations to one channel.
+ Implementers have to ensure that other operations are thread safe.
+ Exception: registering providers is not thread safe (at least at the moment).
+ **/
+
+//the max number of media channels used in parallel
+#define NUMCHANNELS 3
+//name of a media file
+#define NAMESIZE 255
+
+class MediaProvider
+{
+ public:
+ MediaProvider(){}
+ virtual ~MediaProvider(){}
+
+ /**
+ * get the root media list
+ * the returned list has to be destroyed by the caller
+ * if NULL is returned currently no media is available
+ */
+ virtual MediaList* getRootList()=0;
+
+ /**
+ * get a medialist for a given parent
+ * the returned list has to be destroyed by the caller
+ * NULL if no entries found
+ */
+ virtual MediaList* getMediaList(const MediaURI * parent)=0;
+
+ /**
+ * open a media uri
+ * afterwards getBlock or other functions must be possible
+ * currently only one medium is open at the same time
+ * for a given channel
+ * @param channel: channel id, NUMCHANNELS must be supported
+ * @param xsize,ysize: size of the screen
+ * @param size out: the size of the medium
+ * @return != 0 in case of error
+ *
+ */
+ virtual int openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize)=0;
+
+ /**
+ * get a block for a channel
+ * @param offset - the offset
+ * @param len - the required len
+ * @param outlen out - the read len if 0 this is EOF
+ * @param buffer out the allocated buffer (must be freed with free!)
+ * if buffer is set at input the implementation CAN use
+ * this buffer - it is up to the caller to test if the buffer
+ * is at the same value when the method returns.
+ * it is assumed that there is enough room in the buffer if it set
+ * when calling
+ * @return != 0 in case of error
+ */
+ virtual int getMediaBlock(ULONG channel, ULLONG offset, ULONG len, ULONG * outlen,
+ unsigned char ** buffer)=0;
+
+ /**
+ * close a media channel
+ */
+ virtual int closeMediaChannel(ULONG channel)=0;
+
+ /**
+ * return the media info for a given channel
+ * return != 0 on error
+ * the caller has to provide a pointer to an existing media info
+ */
+ virtual int getMediaInfo(ULONG channel, MediaInfo * result)=0;
+
+};
+
+
+/**
+ * the mediaplayer to register providers at
+ * can be static ctor's
+ */
+class MediaPlayerRegister {
+ public:
+ virtual void registerMediaProvider(MediaProvider *pi,ULONG id,ULONG range=1)=0;
+ virtual ~MediaPlayerRegister(){}
+ static MediaPlayerRegister* getInstance();
+ protected:
+ static MediaPlayerRegister *instance;
+};
+
+
+#endif
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/*
+ This file contaisn the IDs for mediaproviders
+ Each provider should have it's ID defined here.
+ They should follow the name pattern:
+ MPROVIDERID_<name>
+ This is the ID a provider has ro use to register at it's local MediaProviderRegister
+ As the mediaprovider architecture is hierarchical there are distributors on each level, that
+ forward requests to their children.
+ Currently it looks like follows:
+
+ MediaPlayer client
+ - LocalMediaFile client
+ - VDR (distributor) client
+ |- <comm> - MediaPlayer server
+ - ServerFileMediaProvider server
+
+ As a distributor must forward multiple requests, it must register with a range of Ids.
+ This range includes it's own Id + a range for all its children.
+ This Range should be defined here as
+ MPROVIDERRANGE_<name>
+ If no range is defined here, the range is 1 - so no distribution.
+
+*/
+
+//we reserve the range 1...999 for client side providers
+static const ULONG MPROVIDERID_LOCALMEDIAFILE=1;
+static const ULONG MPROVIDERID_VDR=1000;
+static const ULONG MPROVIDERRANGE_VDR=10000; //so it has the IDs 1000..10999
+ //all providers on the server side
+ //must fit into this range
+
+static const ULONG MPROVIDERID_SERVERMEDIAFILE=1001;
+
+#ifndef MEDIAPROVIDERIDS_H
+#define MEDIAPROVIDERIDS_H
+
+#include "defines.h"
+
+#endif
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "serialize.h"
+#include <stdlib.h>
+#include <arpa/inet.h>
+#ifndef SNPRINTF
+#define SNPRINTF snprintf
+#endif
+
+#define BUFFERINCREASE 1024
+
+int SerializeBuffer::seek(int amount) {
+ UCHAR *np=current+amount;
+ if (np < start || np > end) return -1;
+ current=np;
+ return 0;
+}
+
+void SerializeBuffer::rewind() {
+ current=start;
+}
+
+int SerializeBuffer::checkSpace(int amount) {
+ if ((current+amount) <= end) return 0;
+ if (owning && autoincrease) {
+ if (start+size > current+amount) {
+ end=start+size;
+ return 0;
+ }
+ UCHAR *ns=new UCHAR[size+BUFFERINCREASE];
+ if (!ns) return -1;
+ memcpy(ns,start,end-start);
+ size=size+BUFFERINCREASE;
+ end=ns+size;
+ if (useMalloc) free( start);
+ else delete [] start;
+ start=ns;
+ return 0;
+ }
+ return -1;
+}
+
+SerializeBuffer::~SerializeBuffer() {
+ if (owning) {
+ if (useMalloc) free(start);
+ else delete[] start;
+ start=NULL;
+ }
+}
+SerializeBuffer::SerializeBuffer(ULONG sz,bool isMalloc,bool ai){
+ autoincrease=ai;
+ useMalloc=isMalloc;
+ if (isMalloc) {
+ start=(UCHAR *)malloc(sz);
+ }
+ else {
+ start=new UCHAR[sz];
+ }
+ end=start;
+ current=start;
+ size=sz;
+ owning=true;
+}
+ //constructor for SerializeBuffers with external buffers
+SerializeBuffer::SerializeBuffer(UCHAR *buffer,ULONG sz,bool ow,bool isMalloc,bool ai) {
+ useMalloc=isMalloc;
+ autoincrease=ai;
+ owning=ow;
+ size=sz;
+ start=buffer;
+ current=start;
+ end=start+size;
+}
+/**
+ * helper for serialize and deserialize
+ * always return != if no space
+ * advance buffer pointer
+ */
+
+int SerializeBuffer::encodeLong(ULONG data) {
+ if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
+ *((ULONG *)(current))=htonl(data);
+ current+=sizeof(ULONG);
+ return 0;
+}
+int SerializeBuffer::encodeShort(USHORT data) {
+ if (checkSpace( (int)sizeof(USHORT))!=0) return -1;
+ *((USHORT *)(current))=htons(data);
+ current+=sizeof(USHORT);
+ return 0;
+}
+int SerializeBuffer::encodeByte(UCHAR data) {
+ if (checkSpace( (int)sizeof(UCHAR))!=0) return -1;
+ *((UCHAR *)(current))=data;
+ current+=sizeof(UCHAR);
+ return 0;
+}
+int SerializeBuffer::encodeLongLong(ULLONG data) {
+ if (checkSpace( (int)sizeof(ULLONG))!=0) return -1;
+ *((ULONG *)(current))=htonl((data>>32) & 0xffffffff);
+ current+=sizeof(ULONG);
+ *((ULONG *)(current))=htonl(data & 0xffffffff);
+ current+=sizeof(ULONG);
+ return 0;
+}
+//string: 4 len, string with 0
+int SerializeBuffer::encodeString(const char *str) {
+ if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
+ ULONG len=0;
+ if (str) len=strlen(str)+1;
+ *((ULONG *)(current))=htonl(len);
+ current+=sizeof(ULONG);
+ if (len == 0) return 0;
+ if (checkSpace((int)len)!=0) return -1;
+ strcpy((char *) current,str);
+ current+=len;
+ return 0;
+}
+int SerializeBuffer::decodeLong( int &data) {
+ if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
+ data=(int)ntohl(*((ULONG *)(current)));
+ current+=sizeof(ULONG);
+ return 0;
+}
+int SerializeBuffer::decodeLong(ULONG &data) {
+ if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
+ data=ntohl(*((ULONG *)(current)));
+ current+=sizeof(ULONG);
+ return 0;
+}
+int SerializeBuffer::decodeShort(USHORT &data) {
+ if (checkSpace( (int)sizeof(USHORT))!=0) return -1;
+ data=ntohs(*((USHORT *)(current)));
+ current+=sizeof(USHORT);
+ return 0;
+}
+int SerializeBuffer::decodeByte(UCHAR &data) {
+ if (checkSpace( (int)sizeof(UCHAR))!=0) return -1;
+ data=*((UCHAR *)current);
+ current+=sizeof(UCHAR);
+ return 0;
+}
+int SerializeBuffer::decodeLongLong(ULLONG &data) {
+ if (checkSpace( (int)sizeof(ULLONG))!=0) return -1;
+ ULLONG hd=ntohl(*((ULONG *)(current)));
+ current+=sizeof(ULONG);
+ ULLONG ld=ntohl(*((ULONG *)(current)));
+ current+=sizeof(ULONG);
+ data=(hd << 32) | ld;
+ return 0;
+}
+//string: 4 len, string with 0
+int SerializeBuffer::decodeString(ULONG &len, char *&strbuf) {
+ strbuf=NULL;
+ len=0;
+ if (checkSpace( (int)sizeof(ULONG))!=0) return -1;
+ len=ntohl(*((ULONG *)(current)));
+ current+=sizeof(ULONG);
+ if (len == 0) return 0;
+ if (checkSpace((int)len)!=0) return -1;
+ strbuf=new char[len];
+ strncpy(strbuf,(char *)current,len);
+ *(strbuf+len-1)=0;
+ current+=len;
+ return 0;
+}
+
+
+UCHAR * SerializeBuffer::steelBuffer() {
+ UCHAR *rt=start;
+ owning=false;
+ autoincrease=false;
+ return rt;
+}
+
+int Serializable::getSerializedStringLen(const char * str) {
+ int rt=4;
+ if (str) rt+=strlen(str)+1;
+ return rt;
+}
+
+USHORT Serializable::getVersion() {
+ return version;
+}
+
+
+Serializable::Serializable() {
+ version=1;
+}
+Serializable::~Serializable(){}
+
+int Serializable::getSerializedLen() {
+ //2version+4len
+ return 6 + getSerializedLenImpl();
+}
+int Serializable::serialize(SerializeBuffer *b) {
+ UCHAR *ptr=b->getCurrent();
+ if (b->encodeShort(version) != 0) return -1;
+ if (b->encodeLong(0) != 0) return -1; //dummy len
+ if (serializeImpl(b) != 0) return -1;
+ UCHAR *ep=b->getCurrent();
+ //now write the len
+ int len=ep-ptr-6;
+ if (len < 0) return -1 ; //internal error
+ b->seek(ptr-ep+2); //to len field
+ if (b->encodeLong(len) != 0) return -1;
+ b->seek(ep-b->getCurrent()); //back to end
+ return 0;
+}
+
+int Serializable::deserialize(SerializeBuffer *b) {
+ USHORT vers=0;
+ if (b->decodeShort(vers) != 0) return -1;
+ ULONG len=0;
+ if (b->decodeLong(len) != 0) return -1;
+ UCHAR *data=b->getCurrent();
+ if (data+len > b->getEnd()) return -1;
+ //TODO: set end temp. to current+len
+ //for better error handling in deserializeImpl
+ if (deserializeImpl(b) != 0) return -1;
+ //ensure we go to end of this element regardless of the things we know
+ b->seek(data+len-b->getCurrent());
+ return 0;
+}
+
+SerializableList::SerializableList() {
+ version=1;
+ encodeOnly=false;
+}
+SerializableList::~SerializableList(){}
+
+int SerializableList::addParam(Serializable *p,USHORT v) {
+ if (v < version || p == NULL) return -1;
+ Pentry entry;
+ entry.ptype=TSER;
+ entry.ptr.pser=p;
+ entry.version=v;
+ list.push_back(entry);
+ version=v;
+ return 0;
+}
+int SerializableList::addParam(USHORT *p,USHORT v) {
+ if (v < version || p == NULL) return -1;
+ Pentry entry;
+ entry.ptype=TUSHORT;
+ entry.ptr.pshort=p;
+ entry.version=v;
+ list.push_back(entry);
+ version=v;
+ return 0;
+}
+int SerializableList::addParam(ULONG *p,USHORT v) {
+ if (v < version || p == NULL) return -1;
+ Pentry entry;
+ entry.ptype=TULONG;
+ entry.ptr.plong=p;
+ entry.version=v;
+ list.push_back(entry);
+ version=v;
+ return 0;
+}
+int SerializableList::addParam(ULLONG *p,USHORT v) {
+ if (v < version || p == NULL) return -1;
+ Pentry entry;
+ entry.ptype=TULLONG;
+ entry.ptr.pllong=p;
+ entry.version=v;
+ list.push_back(entry);
+ version=v;
+ return 0;
+}
+int SerializableList::addParam(char **p,USHORT v) {
+ if (v < version || p == NULL) return -1;
+ Pentry entry;
+ entry.ptype=TCHAR;
+ entry.ptr.pchar=p;
+ entry.version=v;
+ list.push_back(entry);
+ version=v;
+ return 0;
+}
+
+bool SerializableList::Pentry::isEqual(void *p,SerializableList::Ptypes t) {
+ void *cmp=NULL;
+ switch(t) {
+ case TUSHORT:
+ cmp=(void *)ptr.pshort;
+ break;
+ case TULONG:
+ cmp=(void *)ptr.plong;
+ break;
+ case TULLONG:
+ cmp=(void *)ptr.pllong;
+ break;
+ case TSER:
+ cmp=(void *)ptr.pser;
+ break;
+ case TCHAR:
+ cmp=(void *)ptr.pchar;
+ break;
+ case TUNKNOWN:
+ break;
+ }
+ return p==cmp;
+}
+
+SerializableList::Pentry *SerializableList::findEntry(void *p,SerializableList::Ptypes t) {
+ for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
+ if ( (*it).isEqual(p,t)) return &(*it);
+ }
+ return NULL;
+}
+bool SerializableList::isDeserialized(Serializable *p){
+ SerializableList::Pentry *e=findEntry(p,TSER);
+ if (!e) return false;
+ return e->isDeserialized;
+}
+bool SerializableList::isDeserialized(USHORT *p){
+ SerializableList::Pentry *e=findEntry(p,TUSHORT);
+ if (!e) return false;
+ return e->isDeserialized;
+}
+bool SerializableList::isDeserialized(ULONG *p){
+ SerializableList::Pentry *e=findEntry(p,TULONG);
+ if (!e) return false;
+ return e->isDeserialized;
+}
+
+bool SerializableList::isDeserialized(ULLONG *p){
+ SerializableList::Pentry *e=findEntry(p,TULLONG);
+ if (!e) return false;
+ return e->isDeserialized;
+}
+
+bool SerializableList::isDeserialized(char **p){
+ SerializableList::Pentry *e=findEntry(p,TCHAR);
+ if (!e) return false;
+ return e->isDeserialized;
+}
+
+int SerializableList::getSerializedLenImpl(){
+ int rt=0;
+ for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
+ switch((*it).ptype){
+ case TUSHORT:
+ rt+=sizeof(USHORT);
+ break;
+ case TULONG:
+ rt+=sizeof(ULONG);
+ break;
+ case TULLONG:
+ rt+=sizeof(ULLONG);
+ break;
+ case TCHAR:
+ rt+=getSerializedStringLen(*((*it).ptr.pchar));
+ break;
+ case TSER:
+ rt+=(*it).ptr.pser->getSerializedLen();
+ break;
+ case TUNKNOWN:
+ break;
+ }
+ }
+ return rt;
+}
+
+int SerializableList::serializeImpl(SerializeBuffer *b){
+ for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
+ switch((*it).ptype){
+ case TUSHORT:
+ if (b->encodeShort(*(*it).ptr.pshort) != 0) return -1;
+ break;
+ case TULONG:
+ if (b->encodeLong(*(*it).ptr.plong) != 0) return -1;
+ break;
+ case TULLONG:
+ if (b->encodeLongLong(*(*it).ptr.pllong) != 0) return -1;
+ break;
+ case TCHAR:
+ if (b->encodeString(*(*it).ptr.pchar) != 0) return -1;
+ break;
+ case TSER:
+ if ((*it).ptr.pser->serialize(b) != 0) return -1;
+ break;
+ case TUNKNOWN:
+ break;
+ }
+ }
+ return 0;
+}
+
+int SerializableList::deserializeImpl(SerializeBuffer *b){
+ ULONG dlen=0;
+ for (vector<Pentry>::iterator it=list.begin();it<list.end();it++) {
+ if ((*it).version > version) {
+ //OK - we received an older version - stop here
+ break;
+ }
+ switch((*it).ptype){
+ case TUSHORT:
+ if (b->decodeShort(*(*it).ptr.pshort) != 0) return -1;
+ break;
+ case TULONG:
+ if (b->decodeLong(*(*it).ptr.plong) != 0) return -1;
+ break;
+ case TULLONG:
+ if (b->decodeLongLong(*(*it).ptr.pllong) != 0) return -1;
+ break;
+ case TCHAR:
+ if (b->decodeString(dlen,*(*it).ptr.pchar) != 0) return -1;
+ break;
+ case TSER:
+ if ((*it).ptr.pser->deserialize(b) != 0) return -1;
+ break;
+ case TUNKNOWN:
+ break;
+ }
+ (*it).isDeserialized=true;
+ }
+ return 0;
+}
+
+
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef SERIALIZE_H
+#define SERIALIZE_H
+#include <vector>
+using namespace std;
+#include <stdio.h>
+#include <string.h>
+#include "defines.h"
+
+class SerializeBuffer {
+ public:
+ //constructor for send buffers
+ SerializeBuffer(ULONG size,bool isMalloc=false,bool autoincrease=false);
+ //constructor for SerializeBuffers with external buffers
+ SerializeBuffer(UCHAR *buffer,ULONG size,bool owning=false,bool isMalloc=true,bool autoincrease=false);
+ ~SerializeBuffer();
+ //access to bufferpointer
+ UCHAR * getStart(){ return start;}
+ UCHAR * getCurrent(){ return current;}
+ UCHAR * getEnd(){ return end;}
+ //get the buffer and take it away from this object
+ UCHAR * steelBuffer();
+ //seek relative to current
+ int seek(int amount);
+ void rewind();
+
+ //encode/decode functions
+ //always return != 0 on error
+ int encodeLong(ULONG data);
+ int encodeLongLong(ULLONG data);
+ int encodeShort(USHORT data);
+ int encodeString(const char *data);
+ int encodeByte(UCHAR data);
+
+ int decodeLong(ULONG & data);
+ int decodeLong(int & data);
+ int decodeLongLong(ULLONG & data);
+ int decodeShort(USHORT & data);
+ int decodeString(ULONG &len,char * &data);
+ int decodeByte(UCHAR &data);
+
+ private:
+ UCHAR * start;
+ UCHAR * end;
+ UCHAR * current;
+ ULONG size;
+ bool useMalloc;
+ bool owning;
+ bool autoincrease;
+
+ //check buffer space and enlarge if allowed
+ int checkSpace(int size);
+
+};
+
+class Serializable {
+ public:
+ Serializable();
+ virtual ~Serializable();
+ //serialize functions
+ //get the #of bytes needed to serialize
+ int getSerializedLen();
+ //serialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ int serialize(SerializeBuffer *b);
+ //deserialize
+ //advance buffer, check if >= end
+ //return 0 if OK
+ int deserialize(SerializeBuffer *b);
+ //or the received version after deserialize
+ //can be queried with deserializeImpl
+ USHORT getVersion();
+ //helper
+ static int getSerializedStringLen(const char *str);
+ protected:
+ //methods to be overwritten by impl
+ //those methods can use the version info
+ //the length and version is automatically encoded and decoded by the base class
+ virtual int getSerializedLenImpl()=0;
+ virtual int serializeImpl(SerializeBuffer *b)=0;
+ virtual int deserializeImpl(SerializeBuffer *b)=0;
+ USHORT version;
+ };
+
+/**
+ * a class for creating a list of serializable parameters
+ * by including a version handling this automatically maintains compatibility
+ * by correct usage.
+ * usage example:
+ * 1. version
+ * USHORT myP1=0;
+ * ULONG myP2=0;
+ * SerializableList myList();
+ * myList.addParam(&myP1);
+ * myList.addParam(&myP2);
+ * //now serialize/deserialize...
+ * //later - second version:
+ * USHORT myP1=0;
+ * ULONG myP2=0;
+ * char *myString=NULL;
+ * SerializableList myList();
+ * myList.addParam(&myP1);
+ * myList.addParam(&myP2);
+ * myList.addParam(&myString,2); //this parameter is new in version 2
+ * myList.deserialize(buffer);
+ * if (!myList.isDeserialized(&myString)) {
+ * //we got a version 1 message
+ * myString=strcpy(new char[22],"default-for-myString");
+ * }
+ *
+ */
+class SerializableList : public Serializable{
+ public:
+ SerializableList();
+ virtual ~SerializableList();
+ /**
+ * addParam
+ * add a parameter to the list
+ * no life cycle handling included
+ * params should be initialized before!
+ * when adding new params after having released a version
+ * add them to the end with a new version - this will automatically maintain
+ * compatibility
+ * will return !=0 if adding is not possible (e.g. adding with a smaller version)
+ */
+ int addParam(Serializable *p,USHORT version=1);
+ int addParam(USHORT *p,USHORT version=1);
+ int addParam(ULONG *p,USHORT version=1);
+ int addParam(ULLONG *p,USHORT version=1);
+ int addParam(char **p,USHORT version=1);
+
+ /**
+ * for lists only intended for encoding also
+ * const members will be added
+ * this is fully compatible to non const addParams on the other side
+ * so on the sender side you can use the addParam(const ... ) methods, on the receiver
+ * the non-const
+ * After having called one of this methods deserialize will always fail!
+ */
+ int addParam(const Serializable *p,USHORT vs=1){
+ encodeOnly=true;
+ return addParam((Serializable *)p,vs);
+ }
+ int addParam(const USHORT *p,USHORT vs=1){
+ encodeOnly=true;
+ return addParam((USHORT *)p,vs);
+ }
+ int addParam(const ULONG *p,USHORT vs=1){
+ encodeOnly=true;
+ return addParam((ULONG *)p,vs);
+ }
+ int addParam(const int *p,USHORT vs=1){
+ encodeOnly=true;
+ return addParam((ULONG *)p,vs);
+ }
+ int addParam(const ULLONG *p,USHORT vs=1){
+ encodeOnly=true;
+ return addParam((ULLONG *)p,vs);
+ }
+ int addParam(const char **p,USHORT vs=1){
+ encodeOnly=true;
+ return addParam((char **)p,vs);
+ }
+
+
+ /**
+ * check functions to test if a certain parameter has been filled
+ * during deserialize
+ */
+ bool isDeserialized(Serializable *p);
+ bool isDeserialized(USHORT *p);
+ bool isDeserialized(ULONG *p);
+ bool isDeserialized(ULLONG *p);
+ bool isDeserialized(char **p);
+
+ //return the highest version after adding params
+
+
+ protected:
+ virtual int getSerializedLenImpl();
+ virtual int serializeImpl(SerializeBuffer *b);
+ virtual int deserializeImpl(SerializeBuffer *b);
+ bool encodeOnly; //if any addParam(const ...) is called this will be set
+
+ private:
+ typedef enum{
+ TUNKNOWN,
+ TSER,
+ TUSHORT,
+ TULONG,
+ TULLONG,
+ TCHAR } Ptypes;
+ struct Pentry{
+ Ptypes ptype;
+ bool isDeserialized;
+ USHORT version;
+ union {
+ Serializable *pser;
+ USHORT *pshort;
+ ULONG *plong;
+ ULLONG *pllong;
+ char **pchar;
+ } ptr;
+ Pentry() {
+ ptype=TUNKNOWN;
+ version=1;
+ isDeserialized=false;
+ ptr.pser=NULL;
+ }
+ bool isEqual(void *p,Ptypes t);
+ } ;
+ vector<struct Pentry>list;
+ Pentry *findEntry(void *p,Ptypes t);
+};
+
+
+
+#endif
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "servermediafile.h"
+#include "mediaproviderids.h"
+#include "media.h"
+#include "medialauncher.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <iostream>
+#include "log.h"
+
+
+/* input buffer for reading dir */
+#define BUFSIZE 2048
+/* how long to wait until a list has to be finished (100ms units)*/
+#define MAXWAIT 50
+
+ServerMediaFile::ServerMediaFile(Config *c,MediaPlayerRegister *distributor):MediaFile(MPROVIDERID_SERVERMEDIAFILE){
+ cfg=c;
+ distributor->registerMediaProvider(this,MPROVIDERID_SERVERMEDIAFILE);
+ dirhandler=new MediaLauncher(cfg);
+ dirhandler->init();
+ for (int i=0;i<NUMCHANNELS;i++) {
+ launchers[i]=new MediaLauncher(cfg);
+ launchers[i]->init(dirhandler);
+ }
+}
+
+ServerMediaFile::~ServerMediaFile(){
+ for (int i=0;i<NUMCHANNELS;i++) {
+ launchers[i]->closeStream();
+ delete launchers[i];
+ }
+ delete dirhandler;
+ }
+
+MediaList* ServerMediaFile::getRootList() {
+ Log::getInstance()->log("MediaFile::getRootList",Log::DEBUG,"");
+ MediaURI *ru=new MediaURI(providerid,NULL,NULL);
+ MediaList *rt=new MediaList(ru);
+ delete ru;
+ //the configured Media List
+ //for the moment up to 50 entries [Media] Dir.1 ...Dir.10
+ struct stat st;
+ for (int nr=1;nr<=50;nr++){
+ char buffer[30];
+ sprintf(buffer,"Dir.%d",nr);
+ const char * dn=cfg->getValueString("Media",buffer);
+ if (dn != NULL) {
+ if (stat(dn,&st) != 0 || ! S_ISDIR(st.st_mode)) {
+ Log::getInstance()->log("MediaFile::getRootList",Log::ERR,"unable to open basedir %s",dn);
+ }
+ else {
+ Media *m=new Media();
+ m->setFileName(dn);
+ m->setMediaType(MEDIA_TYPE_DIR);
+ m->setTime(st.st_mtime);
+ sprintf(buffer,"Dir.Name.%d",nr);
+ m->setDisplayName(cfg->getValueString("Media",buffer));
+ rt->push_back(m);
+ Log::getInstance()->log("Media",Log::DEBUG,"added base dir %s",dn);
+ }
+ }
+ }
+ return rt;
+}
+
+ULONG ServerMediaFile::getMediaType(const char *filename) {
+ ULONG rt=dirhandler->getTypeForName(filename);
+ if (rt != MEDIA_TYPE_UNKNOWN) return rt;
+ return MediaFile::getMediaType(filename);
+}
+
+int ServerMediaFile::openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize){
+ if (channel >= NUMCHANNELS) return -1;
+ launchers[channel]->closeStream();
+ ULONG rt=launchers[channel]->getTypeForName(uri->getName());
+ if (rt != MEDIA_TYPE_UNKNOWN) {
+ *size=0;
+ channels[channel].reset();
+ int rtstat=launchers[channel]->openStream(uri->getName(),xsize,ysize);
+ channels[channel].setFilename(uri->getName());
+ return rtstat>=0?0:1;
+ }
+ return MediaFile::openMedium(channel,uri,size,xsize,ysize);
+}
+
+int ServerMediaFile::getMediaBlock(ULONG channel, ULLONG offset, ULONG len, ULONG * outlen,
+ unsigned char ** buffer)
+{
+ if (channel >= NUMCHANNELS) return -1;
+ if (launchers[channel]->isOpen()) {
+ return launchers[channel]->getNextBlock(len,buffer,outlen);
+ }
+ return MediaFile::getMediaBlock(channel,offset,len,outlen,buffer);
+}
+int ServerMediaFile::closeMediaChannel(ULONG channel){
+ if (channel >= NUMCHANNELS) return -1;
+ if (launchers[channel]->isOpen()) {
+ return launchers[channel]->closeStream();
+ }
+ return MediaFile::closeMediaChannel(channel);
+}
+int ServerMediaFile::getMediaInfo(ULONG channel, MediaInfo * result){
+ if (channel >= NUMCHANNELS) return -1;
+ if (launchers[channel]->isOpen()) {
+ result->canPosition=false;
+ result->type=launchers[channel]->getTypeForName(channels[channel].filename);
+ return 0;
+ }
+ return MediaFile::getMediaInfo(channel,result);
+}
+
+
+MediaList* ServerMediaFile::getMediaList(const MediaURI *parent) {
+ ULONG rt=dirhandler->getTypeForName(parent->getName());
+ if (rt == MEDIA_TYPE_UNKNOWN) return MediaFile::getMediaList(parent);
+ int op=dirhandler->openStream(parent->getName(),0,0);
+ if (op < 0) {
+ Log::getInstance()->log("Media",Log::ERR,"unable to open handler for %s",parent->getName());
+ dirhandler->closeStream();
+ return NULL;
+ }
+ int maxtries=0;
+ unsigned char *inbuf=NULL;
+ unsigned char linebuf[2*BUFSIZE];
+ unsigned char *wrp=linebuf;
+ ULONG outlen=0;
+ MediaList *ml=new MediaList(parent);
+ while (maxtries < MAXWAIT) {
+ int ert=dirhandler->getNextBlock(BUFSIZE,&inbuf,&outlen);
+ if (ert != 0) break;
+ if (outlen == 0) {
+ if (inbuf != NULL) free(inbuf);
+ inbuf=NULL;
+ maxtries++;
+ continue;
+ }
+ maxtries=0;
+ if (outlen > BUFSIZE) {
+ Log::getInstance()->log("Media",Log::ERR,"invalid read len %llu in getBlock for list %s",outlen,parent->getName());
+ free(inbuf);
+ inbuf=NULL;
+ continue;
+ }
+ memcpy(wrp,inbuf,outlen);
+ free(inbuf);
+ inbuf=NULL;
+ ULONG handledBytes=addDataToList(linebuf,outlen+(wrp-linebuf),ml,true);
+ memcpy(linebuf,wrp+outlen-handledBytes,wrp-linebuf+outlen-handledBytes);
+ if (handledBytes > outlen) wrp-=handledBytes-outlen;
+ if (wrp >= linebuf+BUFSIZE) {
+ Log::getInstance()->log("Media",Log::ERR,"line to long in getBlock for list %s",parent->getName());
+ wrp=linebuf;
+ }
+ }
+ dirhandler->closeStream();
+ return ml;
+}
+
+
+ULONG ServerMediaFile::addDataToList(unsigned char * buf, ULONG buflen,MediaList *list,bool extendedFormat) {
+ ULONG handledBytes=0;
+ char entrybuf[BUFSIZE+1];
+ char display[BUFSIZE+1];
+ int ebpos=0;
+ while (handledBytes < buflen) {
+ unsigned char c=buf[handledBytes];
+ if (c == '\n') {
+ entrybuf[ebpos]=0;
+ /* complete line */
+ /* handle # lines */
+ for (int i=0;i<ebpos;i++) {
+ if (entrybuf[i] == '#') {
+ entrybuf[i]=0;
+ break;
+ }
+ if (entrybuf[i] != ' ') break;
+ }
+ if (strlen(entrybuf) > 0) {
+ Log::getInstance()->log("Media",Log::DEBUG,"handle list line %s",entrybuf);
+ char *uriptr=entrybuf;
+ if (extendedFormat) {
+ /* search for a delimiter */
+ while (*uriptr != ';' && *uriptr != 0) uriptr++;
+ if (*uriptr == ';') uriptr++;
+ if (*uriptr == 0) uriptr=entrybuf;
+ }
+ ULONG mt=getMediaType(uriptr);
+ if (mt != MEDIA_TYPE_UNKNOWN) {
+ if (uriptr != entrybuf) {
+ memcpy(display,entrybuf,uriptr-entrybuf-1);
+ display[uriptr-entrybuf-1]=0;
+ }
+ else {
+ int i=strlen(entrybuf)-1;
+ int len=i+1;
+ for(;i>=0;i--) {
+ if (entrybuf[i]=='/') break;
+ }
+ i++;
+ if (entrybuf[i] != 0) {
+ memcpy(display,&entrybuf[i],len-i);
+ display[len-i]=0;
+ }
+ else {
+ memcpy(display,entrybuf,len);
+ display[len]=0;
+ }
+ }
+ Media *m=new Media();
+ MediaURI *u=NULL;
+ if (*uriptr != '/') {
+ /* add the directory of the list in front */
+ MediaURI *p=list->getParent(list->getRoot());
+ char ubuf[strlen(p->getName())+strlen(uriptr)+2];
+ sprintf(ubuf,"%s/%s",p->getName(),uriptr);
+ u=new MediaURI(providerid,ubuf,display);
+ delete p;
+ }
+ else {
+ u=new MediaURI(providerid,uriptr,display);
+ }
+ m->setFileName(display);
+ m->setURI(u);
+ delete u;
+ m->setMediaType(mt);
+ list->push_back(m);
+ Log::getInstance()->log("Media",Log::DEBUG,"added media display %s, type %lu",display,mt);
+ }
+ }
+
+
+ //do handling
+ ebpos=0;
+ }
+ else if (c != '\r') {
+ entrybuf[ebpos]=c;
+ ebpos++;
+ if (ebpos >= BUFSIZE) {
+ /* line too long - ignore */
+ Log::getInstance()->log("Media",Log::ERR,"line to long in add data");
+ ebpos=0;
+ }
+ }
+ handledBytes++;
+ }
+ return handledBytes-ebpos;
+}
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef SERVERMEDIAFILE_H
+#define SERVERMEDIAFILE_H
+
+#include "mediafile.h"
+#include "config.h"
+
+class MediaLauncher;
+
+
+class ServerMediaFile : public MediaFile
+{
+ public:
+ ServerMediaFile(Config *c,MediaPlayerRegister *distributor);
+ virtual ~ServerMediaFile();
+ virtual MediaList* getRootList();
+ virtual int openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize);
+ virtual int getMediaBlock(ULONG channel, ULLONG offset, ULONG len, ULONG * outlen,
+ unsigned char ** buffer);
+ virtual int closeMediaChannel(ULONG channel);
+ virtual int getMediaInfo(ULONG channel, MediaInfo * result);
+ virtual MediaList* getMediaList(const MediaURI *parent);
+
+
+
+ protected:
+ virtual ULONG getMediaType(const char *fname);
+ MediaLauncher * launchers[NUMCHANNELS];
+ MediaLauncher * dirhandler;
+
+ private:
+ Config *cfg;
+ ULONG addDataToList(unsigned char * buf, ULONG buflen,MediaList *list,bool extendedFormat) ;
+
+
+};
+
+#endif
--- /dev/null
+/*
+ Copyright 2004-2005 Chris Tallon, Andreas Vogel
+
+ This file is part of VOMP.
+
+ VOMP 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.
+
+ VOMP 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 VOMP; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef VDRCOMMAND_H
+#define VDRCOMMAND_H
+
+#include "defines.h"
+#include "serialize.h"
+#include "media.h"
+
+/**
+ * data holder for VDR commands
+ * it's only important to add serializable objects
+ * in the same order on both sides
+ */
+
+//until we really have response - commands we simply take
+//the request+this flag for responses
+//not really necessary but for checks it's better to have a command ID at least in some responses
+const static ULONG VDR_RESPONSE_FLAG =0x1000000;
+
+//as this header is only included by vdr.cc the constants are this way private
+//but can easily be used on the server side as well
+
+const static ULONG VDR_LOGIN = 1;
+const static ULONG VDR_GETRECORDINGLIST = 2;
+const static ULONG VDR_DELETERECORDING = 3;
+const static ULONG VDR_GETCHANNELLIST = 5;
+const static ULONG VDR_STREAMCHANNEL = 6;
+const static ULONG VDR_GETBLOCK = 7;
+const static ULONG VDR_STOPSTREAMING = 8;
+const static ULONG VDR_STREAMRECORDING = 9;
+const static ULONG VDR_GETCHANNELSCHEDULE = 10;
+const static ULONG VDR_CONFIGSAVE = 11;
+const static ULONG VDR_CONFIGLOAD = 12;
+const static ULONG VDR_RESCANRECORDING = 13; // FIXME obselete
+const static ULONG VDR_GETTIMERS = 14;
+const static ULONG VDR_SETTIMER = 15;
+const static ULONG VDR_POSFROMFRAME = 16;
+const static ULONG VDR_FRAMEFROMPOS = 17;
+const static ULONG VDR_MOVERECORDING = 18;
+const static ULONG VDR_GETNEXTIFRAME = 19;
+const static ULONG VDR_GETRECINFO = 20;
+const static ULONG VDR_GETMARKS = 21;
+const static ULONG VDR_GETCHANNELPIDS = 22;
+const static ULONG VDR_DELETETIMER = 23;
+const static ULONG VDR_GETLANGUAGELIST = 33;
+const static ULONG VDR_GETLANGUAGECONTENT = 34;
+const static ULONG VDR_GETMEDIALIST = 30;
+const static ULONG VDR_OPENMEDIA = 31;
+const static ULONG VDR_GETMEDIABLOCK = 32;
+const static ULONG VDR_GETMEDIAINFO = 35;
+const static ULONG VDR_CLOSECHANNEL = 36;
+
+class VDR_Command : public SerializableList {
+ public:
+ VDR_Command(const ULONG cmd) {
+ command=cmd;
+ addParam(&command);
+ }
+ virtual ~VDR_Command(){}
+ ULONG command;
+};
+
+class VDR_GetMediaListRequest : public VDR_Command {
+ public:
+ VDR_GetMediaListRequest(MediaURI *root) :VDR_Command(VDR_GETMEDIALIST) {
+ addParam(root);
+ }
+};
+
+class VDR_GetMediaListResponse : public VDR_Command {
+ public:
+ VDR_GetMediaListResponse(ULONG *flags,MediaList *m) : VDR_Command(VDR_GETMEDIALIST|VDR_RESPONSE_FLAG){
+ addParam(flags);
+ addParam(m);
+ }
+};
+
+class VDR_OpenMediumRequest : public VDR_Command {
+ public:
+ VDR_OpenMediumRequest(ULONG *channel,MediaURI *u,ULONG *xsize, ULONG *ysize) :
+ VDR_Command(VDR_OPENMEDIA) {
+ addParam(channel);
+ addParam(u);
+ addParam(xsize);
+ addParam(ysize);
+ }
+};
+class VDR_OpenMediumResponse : public VDR_Command {
+ public:
+ VDR_OpenMediumResponse(ULONG *flags,ULLONG *size) :
+ VDR_Command(VDR_OPENMEDIA|VDR_RESPONSE_FLAG) {
+ addParam(flags);
+ addParam(size);
+ }
+};
+class VDR_GetMediaBlockRequest : public VDR_Command {
+ public:
+ VDR_GetMediaBlockRequest(ULONG * channel, ULLONG *pos, ULONG *max):
+ VDR_Command(VDR_GETMEDIABLOCK) {
+ addParam(channel);
+ addParam(pos);
+ addParam(max);
+ }
+};
+
+//no response class for GetMediaBlock
+
+
+class VDR_CloseMediaChannelRequest : public VDR_Command {
+ public:
+ VDR_CloseMediaChannelRequest(ULONG * channel):
+ VDR_Command(VDR_CLOSECHANNEL) {
+ addParam(channel);
+ }
+};
+
+class VDR_CloseMediaChannelResponse : public VDR_Command {
+ public:
+ VDR_CloseMediaChannelResponse(ULONG * flags):
+ VDR_Command(VDR_CLOSECHANNEL|VDR_RESPONSE_FLAG) {
+ addParam(flags);
+ }
+};
+
+class VDR_GetMediaInfoRequest : public VDR_Command {
+ public:
+ VDR_GetMediaInfoRequest(ULONG * channel):
+ VDR_Command(VDR_GETMEDIAINFO) {
+ addParam(channel);
+ }
+};
+class VDR_GetMediaInfoResponse : public VDR_Command {
+ public:
+ VDR_GetMediaInfoResponse(ULONG * flags,MediaInfo *info):
+ VDR_Command(VDR_GETMEDIAINFO|VDR_RESPONSE_FLAG) {
+ addParam(flags);
+ addParam(info);
+ }
+};
+
+
+
+
+#endif
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "mediaplayer.h"
+#include "media.h"
+#include "servermediafile.h"
+#include "vdrcommand.h"
#include "vompclient.h"
#include "responsepacket.h"
recplayer = NULL;
recordingManager = NULL;
#endif
- imageFile = 0;
log = Log::getInstance();
loggedIn = false;
configDir = tconfigDir;
log->log("Client", Log::DEBUG, "Config dir: %s", configDir);
baseConfig = cfgBase;
incClients();
+ media=new MediaPlayer();
+ mediaprovider=new ServerMediaFile(cfgBase,media);
rrproc.init();
}
#include "defines.h"
#include "tcp.h"
#include "config.h"
+#include "media.h"
#include "i18n.h"
#include "vompclientrrproc.h"
+class ResponsePacket;
+class ServerMediaFile;
+class SerializeBuffer;
+class MediaPlayer;
+
class VompClient
{
friend class VompClientRRProc;
I18n i18n;
bool loggedIn;
char* configDir;
- FILE* imageFile;
void cleanConfig();
cRecordings* recordingManager;
RecPlayer* recplayer;
#endif
+ MediaPlayer *media;
+ ServerMediaFile *mediaprovider;
};
#endif
#include "vompclient.h"
#include "log.h"
#include "media.h"
+#include "mediaplayer.h"
+#include "servermediafile.h"
#include "i18n.h"
+#include "vdrcommand.h"
VompClientRRProc::VompClientRRProc(VompClient& x)
: x(x)
case 9:
result = processStartStreamingRecording();
break;
-#endif
case 10:
result = processGetChannelSchedule();
break;
+#endif
case 11:
result = processConfigSave();
break;
result = processDeleteTimer();
break;
#endif
- case 30:
+ case VDR_GETMEDIALIST:
result = processGetMediaList();
break;
- case 31:
- result = processGetPicture();
+ case VDR_OPENMEDIA:
+ result = processOpenMedia();
break;
- case 32:
- result = processGetImageBlock();
+ case VDR_GETMEDIABLOCK:
+ result = processGetMediaBlock();
break;
case 33:
result = processGetLanguageList();
case 34:
result = processGetLanguageContent();
break;
+ case VDR_GETMEDIAINFO:
+ result= processGetMediaInfo();
+ break;
+ case VDR_CLOSECHANNEL:
+ result= processCloseMediaChannel();
+ break;
+
}
delete resp;
return 1;
}
+
+//helper for sending from a serialize buffer
+//insert the used len into the first 4 Bytes of the buffer
+void VompClientRRProc::sendPacket(SerializeBuffer *b) {
+ resp->copyin(b->getStart(),b->getCurrent()-b->getStart());
+ resp->finalise();
+ x.tcp.sendPacket(resp->getPtr(), resp->getLen());
+}
+
/**
* media List Request:
- * 4 length
- * 4 VDR_GETMEDIALIST
- * 4 flags (currently unused)
- * n dirname
- * n+1 0
* Media List response:
- * 4 length
- * 4 VDR_
- * 4 numentries
- * per entry:
- * 4 media type
- * 4 time stamp
- * 4 flags
- * 4 strlen (incl. 0 Byte)
- * string
- * 0
+ * flags, mediaList
*/
-
+#define MLISTBUF 500000
int VompClientRRProc::processGetMediaList()
{
- if (req->dataLength < 4) {
- log->log("RRProc", Log::ERR, "getMediaList packet too short %d", req->dataLength);
+ SerializeBuffer buffer(req->data,req->dataLength);
+ MediaURI uri(0,NULL,NULL);
+ VDR_GetMediaListRequest request(&uri);
+ if (request.deserialize(&buffer) != 0) {
+ log->log("Client", Log::ERR, "getMediaList unable to deserialize");
return 0;
}
- char * dirname=NULL;
- if (req->dataLength > 4) {
- //we have a dirname provided
- dirname=(char *)&req->data[4];
- log->log("RRProc", Log::DEBUG, "getMediaList for %s", dirname);
- }
+ const char *dirname=uri.getName();
+ log->log("Client", Log::DEBUG, "getMediaList for %s", dirname);
- MediaList * ml=MediaList::readList(x.baseConfig, dirname);
+ MediaList * ml=NULL;
+ if (dirname == NULL) {
+ ml=x.media->getRootList();
+ } else {
+ ml=x.media->getMediaList(&uri);
+ }
if (ml == NULL) {
- log->log("RRProc", Log::ERR, "getMediaList returned NULL");
+ log->log("Client", Log::ERR, "getMediaList returned NULL");
return 0;
}
-
- //response code (not yet set)
- resp->addULONG(0);
-
- //numentries
- resp->addULONG(ml->size());
-
- for (MediaList::iterator nm=ml->begin(); nm<ml->end(); nm++)
- {
- Media *m=*nm;
- log->log("RRProc", Log::DEBUG, "found media entry %s, type=%d",m->getFilename(),m->getType());
- resp->addULONG(m->getType());
- //time stamp
- resp->addULONG(m->getTime());
- //flags
- resp->addULONG(0);
- int len=strlen(m->getFilename());
- //strlen
- resp->addULONG(len+1);
- resp->addString(m->getFilename());
+ SerializeBuffer rbuf(MLISTBUF,false,true);
+ ULONG flags=0; //TODO: real error handling by setting flags
+ VDR_GetMediaListResponse response(&flags,ml);
+ if (response.serialize(&rbuf) != 0) {
+ log->log("Client", Log::ERR, "getMediaList returned NULL");
+ delete ml;
+ return 0;
}
+ log->log("Client", Log::DEBUG, "getMediaList size %u", ml->size());
delete ml;
-
- resp->finalise();
- x.tcp.sendPacket(resp->getPtr(), resp->getLen());
- log->log("RRProc", Log::DEBUG, "Written Media list");
+
+ sendPacket(&rbuf);
+ log->log("Client", Log::DEBUG, "Written Media list");
return 1;
}
-
/**
- * get image Request:
- * 4 flags (currently unused)
- * 4 x size
- * 4 y size
- * n filename
- * n+1 0
- * get image response:
- * 4 length
- * 4 VDR_GETIMAGE
- * 4 len of image
+ * openMedia Request:
+ * openMedia response:
*/
-
-int VompClientRRProc::processGetPicture()
+int VompClientRRProc::processOpenMedia()
{
- if (req->dataLength < 12) {
- log->log("RRProc", Log::ERR, "getPicture packet too short %d", req->dataLength);
+ SerializeBuffer buffer(req->data,req->dataLength);
+ MediaURI uri(0,NULL,NULL);
+ ULONG channel=0;
+ ULONG xs=0;
+ ULONG ys=0;
+ VDR_OpenMediumRequest request(&channel,&uri,&xs,&ys);
+ if (request.deserialize(&buffer) != 0) {
+ log->log("Client", Log::ERR, "openMediaRequest unable to deserialize");
return 0;
}
- if (x.imageFile) {
- fclose(x.imageFile);
- x.imageFile=NULL;
- }
- char * filename=NULL;
- if (req->dataLength > 12) {
- //we have a dirname provided
- filename=(char *)&req->data[12];
- log->log("RRProc", Log::DEBUG, "getPicture %s", filename);
+ const char *name=uri.getName();
+ log->log("Client", Log::DEBUG, "openMediaRequest for %s", name);
+ ULLONG size=0;
+ int rt=x.media->openMedium(channel,&uri,&size,xs,ys);
+ ULONG flags=0;
+ if (rt != 0) {
+ size=0;
+ flags=1;
+ log->log("Client", Log::ERR, "openMediaRequest unable to open");
+ }
+ VDR_OpenMediumResponse response(&flags,&size);
+ SerializeBuffer rbuf(response.getSerializedLen()+4,false,true);
+ if (response.serialize(&rbuf) != 0) {
+ log->log("Client", Log::ERR, "openMediaRequest cannot serialize");
+ return 0;
}
- else {
- log->log("RRProc", Log::ERR, "getPicture empty filename");
+ log->log("Client", Log::DEBUG, "openMediaRequest size %llu", size);
+ sendPacket(&rbuf);
+ return 1;
+}
+/**
+ * VDR_GETMEDIABLOCK
+ * resp
+ * packet - no serialized response!
+ */
+int VompClientRRProc::processGetMediaBlock()
+{
+ SerializeBuffer buffer(req->data,req->dataLength);
+ ULLONG position = 0;
+ ULONG amount = 0;
+ ULONG channel = 0;
+ VDR_GetMediaBlockRequest request(&channel,&position,&amount);
+ if (request.deserialize(&buffer) != 0) {
+ log->log("Client", Log::ERR, "getMediaBlock unable to deserialize");
+ return 0;
}
- if (filename) {
- x.imageFile=fopen(filename,"r");
- if (!x.imageFile) log->log("RRProc", Log::ERR, "getPicture unable to open %s",filename);
+ log->log("Client", Log::DEBUG, "getMediaBlock pos = %llu length = %lu,chan=%lu", position, amount,channel);
+
+ UCHAR sendBuffer[amount ];
+ ULONG amountReceived = 0;
+ UCHAR *rbuf=sendBuffer;
+ int rt=x.media->getMediaBlock(channel,position,amount,&amountReceived,&rbuf);
+ if (!amountReceived || rt != 0)
+ {
+ log->log("Client", Log::DEBUG, "written 4(0) as getblock got 0");
}
- int size=0;
- if (x.imageFile) {
- struct stat st;
- if ( fstat(fileno(x.imageFile),&st) == 0) size=st.st_size;
+ else
+ {
+ if (rbuf != sendBuffer) {
+ //the provider did not use the optimized handling with using my buffer
+ resp->copyin(rbuf,amountReceived);
+ free(rbuf);
+ } else {
+ // the provider did not allocate a new buffer
+ resp->copyin(sendBuffer,amountReceived);
+ }
}
- //response code (not yet set)
- resp->addULONG(31);
- //size
- resp->addULONG(size);
-
- log->log("RRProc", Log::DEBUG, "getPicture size %u", size);
-
resp->finalise();
x.tcp.sendPacket(resp->getPtr(), resp->getLen());
-
- log->log("RRProc", Log::DEBUG, "Written getPicture");
-
+ log->log("Client", Log::DEBUG, "written ok %lu", amountReceived);
return 1;
}
+/**
+ * VDR_GETMEDIAINFO
+ */
-
-int VompClientRRProc::processGetImageBlock()
+int VompClientRRProc::processGetMediaInfo()
{
- if (!x.imageFile)
- {
- log->log("RRProc", Log::DEBUG, "Get image block called when no image active");
+ SerializeBuffer buffer(req->data,req->dataLength);
+ ULONG channel=0;
+ VDR_GetMediaInfoRequest request(&channel);
+ if (request.deserialize(&buffer) != 0) {
+ log->log("Client", Log::ERR, "getMediaInfo unable to deserialize");
return 0;
}
+ log->log("Client", Log::DEBUG, "getMediaInfo chan=%lu", channel);
+ ULONG flags=0;
+ MediaInfo mi;
+ int rt=x.media->getMediaInfo(channel,&mi);
+ if (rt != 0) {
+ flags=1;
+ log->log("Client", Log::ERR, "getMediaInfo unable to get");
+ }
+ VDR_GetMediaInfoResponse response(&flags,&mi);
+ SerializeBuffer rbuf(response.getSerializedLen()+4,false,true);
+ if (response.serialize(&rbuf) != 0) {
+ log->log("Client", Log::ERR, "getMediaInfo cannot serialize");
+ return 0;
+ }
+ sendPacket(&rbuf);
+ return 1;
+}
- UCHAR* data = req->data;
-
- ULLONG position = x.ntohll(*(ULLONG*)data);
- data += sizeof(ULLONG);
- ULONG amount = ntohl(*(ULONG*)data);
-
- log->log("RRProc", Log::DEBUG, "getImageblock pos = %llu length = %lu", position, amount);
+/**
+ * VDR_CLOSECHANNEL
+ */
- UCHAR sendBuffer[amount];
- ULONG amountReceived = 0; // compiler moan.
- ULLONG cpos=ftell(x.imageFile);
- if (position != cpos) {
- fseek(x.imageFile,position-cpos,SEEK_CUR);
- }
- if (position != (ULLONG)ftell(x.imageFile)) {
- log->log("RRProc", Log::DEBUG, "getImageblock pos = %llu not available", position);
- }
- else {
- amountReceived=fread(&sendBuffer[0],1,amount,x.imageFile);
- }
- if (!amountReceived)
- {
- resp->addULONG(0);
- log->log("RRProc", Log::DEBUG, "written 4(0) as getblock got 0");
+int VompClientRRProc::processCloseMediaChannel()
+{
+ SerializeBuffer buffer(req->data,req->dataLength);
+ ULONG channel=0;
+ VDR_CloseMediaChannelRequest request(&channel);
+ if (request.deserialize(&buffer) != 0) {
+ log->log("Client", Log::ERR, "closeMediaChannel unable to deserialize");
+ return 0;
}
- else
- {
- resp->copyin(sendBuffer, amount);
- log->log("RRProc", Log::DEBUG, "written %lu", amountReceived);
+ ULONG flags=0;
+ log->log("Client", Log::DEBUG, "closeMediaChannel chan=%lu", channel);
+ int rt=x.media->closeMediaChannel(channel);
+ if (rt != 0) {
+ flags=1;
+ log->log("Client", Log::ERR, "closeMediaChannel unable to get");
+ }
+ VDR_CloseMediaChannelResponse response(&flags);
+ SerializeBuffer rbuf(response.getSerializedLen()+4,false,true);
+ if (response.serialize(&rbuf) != 0) {
+ log->log("Client", Log::ERR, "closeMediaChannel cannot serialize");
+ return 0;
}
-
- resp->finalise();
- x.tcp.sendPacket(resp->getPtr(), resp->getLen());
-
+ sendPacket(&rbuf);
return 1;
}
+
int VompClientRRProc::processGetLanguageList()
{
x.i18n.findLanguages();
#include "thread.h"
#include "responsepacket.h"
#include <queue>
+#include "serialize.h"
using namespace std;
private:
bool processPacket();
+ void sendPacket(SerializeBuffer *b);
#ifndef VOMPSTANDALONE
int processGetRecordingsList();
int processConfigSave();
int processConfigLoad();
int processGetMediaList();
- int processGetPicture();
- int processGetImageBlock();
+ int processOpenMedia();
+ int processGetMediaBlock();
+ int processGetMediaInfo();
+ int processCloseMediaChannel();
int processGetLanguageList();
int processGetLanguageContent();