2 Copyright 2004-2005 Chris Tallon, Andreas Vogel
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "servermediafile.h"
22 #include "mediaproviderids.h"
24 #include "medialauncher.h"
26 #include <sys/types.h>
32 /* input buffer for reading dir */
34 /* how long to wait until a list has to be finished (100ms units)*/
37 ServerMediaFile::ServerMediaFile(Config *c,MediaPlayerRegister *distributor):MediaFile(MPROVIDERID_SERVERMEDIAFILE){
39 distributor->registerMediaProvider(this,MPROVIDERID_SERVERMEDIAFILE);
40 dirhandler=new MediaLauncher(cfg);
42 for (int i=0;i<NUMCHANNELS;i++) {
43 launchers[i]=new MediaLauncher(cfg);
44 launchers[i]->init(dirhandler);
48 ServerMediaFile::~ServerMediaFile(){
49 for (int i=0;i<NUMCHANNELS;i++) {
50 launchers[i]->closeStream();
56 MediaList* ServerMediaFile::getRootList() {
57 Log::getInstance()->log("MediaFile::getRootList",Log::DEBUG,"");
58 MediaURI *ru=new MediaURI(providerid,NULL,NULL);
59 MediaList *rt=new MediaList(ru);
61 //the configured Media List
62 //for the moment up to 50 entries [Media] Dir.1 ...Dir.10
64 for (int nr=1;nr<=50;nr++){
66 sprintf(buffer,"Dir.%d",nr);
67 const char * dn=cfg->getValueString("Media",buffer);
69 if (stat(dn,&st) != 0 || ! S_ISDIR(st.st_mode)) {
70 Log::getInstance()->log("MediaFile::getRootList",Log::ERR,"unable to open basedir %s",dn);
75 m->setMediaType(MEDIA_TYPE_DIR);
76 m->setTime(st.st_mtime);
77 sprintf(buffer,"Dir.Name.%d",nr);
78 m->setDisplayName(cfg->getValueString("Media",buffer));
80 Log::getInstance()->log("Media",Log::DEBUG,"added base dir %s",dn);
87 ULONG ServerMediaFile::getMediaType(const char *filename) {
88 ULONG rt=dirhandler->getTypeForName(filename);
89 if (rt != MEDIA_TYPE_UNKNOWN) return rt;
90 return MediaFile::getMediaType(filename);
93 int ServerMediaFile::openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize){
94 if (channel >= NUMCHANNELS) return -1;
95 launchers[channel]->closeStream();
96 ULONG rt=launchers[channel]->getTypeForName(uri->getName());
97 if (rt != MEDIA_TYPE_UNKNOWN) {
99 channels[channel].reset();
100 int rtstat=launchers[channel]->openStream(uri->getName(),xsize,ysize);
101 channels[channel].setFilename(uri->getName());
102 return rtstat>=0?0:1;
104 return MediaFile::openMedium(channel,uri,size,xsize,ysize);
107 int ServerMediaFile::getMediaBlock(ULONG channel, ULLONG offset, ULONG len, ULONG * outlen,
108 unsigned char ** buffer)
110 if (channel >= NUMCHANNELS) return -1;
111 if (launchers[channel]->isOpen()) {
112 return launchers[channel]->getNextBlock(len,buffer,outlen);
114 return MediaFile::getMediaBlock(channel,offset,len,outlen,buffer);
116 int ServerMediaFile::closeMediaChannel(ULONG channel){
117 if (channel >= NUMCHANNELS) return -1;
118 if (launchers[channel]->isOpen()) {
119 return launchers[channel]->closeStream();
121 return MediaFile::closeMediaChannel(channel);
123 int ServerMediaFile::getMediaInfo(ULONG channel, MediaInfo * result){
124 if (channel >= NUMCHANNELS) return -1;
125 if (launchers[channel]->isOpen()) {
126 result->canPosition=false;
127 result->type=launchers[channel]->getTypeForName(channels[channel].filename);
130 return MediaFile::getMediaInfo(channel,result);
134 MediaList* ServerMediaFile::getMediaList(const MediaURI *parent) {
135 ULONG rt=dirhandler->getTypeForName(parent->getName());
136 if (rt == MEDIA_TYPE_UNKNOWN) return MediaFile::getMediaList(parent);
137 int op=dirhandler->openStream(parent->getName(),0,0);
139 Log::getInstance()->log("Media",Log::ERR,"unable to open handler for %s",parent->getName());
140 dirhandler->closeStream();
144 unsigned char *inbuf=NULL;
145 unsigned char linebuf[2*BUFSIZE];
146 unsigned char *wrp=linebuf;
148 MediaList *ml=new MediaList(parent);
149 while (maxtries < MAXWAIT) {
150 int ert=dirhandler->getNextBlock(BUFSIZE,&inbuf,&outlen);
153 if (inbuf != NULL) free(inbuf);
159 if (outlen > BUFSIZE) {
160 Log::getInstance()->log("Media",Log::ERR,"invalid read len %llu in getBlock for list %s",outlen,parent->getName());
165 memcpy(wrp,inbuf,outlen);
168 ULONG handledBytes=addDataToList(linebuf,outlen+(wrp-linebuf),ml,true);
169 memcpy(linebuf,wrp+outlen-handledBytes,wrp-linebuf+outlen-handledBytes);
170 if (handledBytes > outlen) wrp-=handledBytes-outlen;
171 if (wrp >= linebuf+BUFSIZE) {
172 Log::getInstance()->log("Media",Log::ERR,"line to long in getBlock for list %s",parent->getName());
176 dirhandler->closeStream();
181 ULONG ServerMediaFile::addDataToList(unsigned char * buf, ULONG buflen,MediaList *list,bool extendedFormat) {
182 ULONG handledBytes=0;
183 char entrybuf[BUFSIZE+1];
184 char display[BUFSIZE+1];
186 while (handledBytes < buflen) {
187 unsigned char c=buf[handledBytes];
192 for (int i=0;i<ebpos;i++) {
193 if (entrybuf[i] == '#') {
197 if (entrybuf[i] != ' ') break;
199 if (strlen(entrybuf) > 0) {
200 Log::getInstance()->log("Media",Log::DEBUG,"handle list line %s",entrybuf);
201 char *uriptr=entrybuf;
202 if (extendedFormat) {
203 /* search for a delimiter */
204 while (*uriptr != ';' && *uriptr != 0) uriptr++;
205 if (*uriptr == ';') uriptr++;
206 if (*uriptr == 0) uriptr=entrybuf;
208 ULONG mt=getMediaType(uriptr);
209 if (mt != MEDIA_TYPE_UNKNOWN) {
210 if (uriptr != entrybuf) {
211 memcpy(display,entrybuf,uriptr-entrybuf-1);
212 display[uriptr-entrybuf-1]=0;
215 int i=strlen(entrybuf)-1;
218 if (entrybuf[i]=='/') break;
221 if (entrybuf[i] != 0) {
222 memcpy(display,&entrybuf[i],len-i);
226 memcpy(display,entrybuf,len);
230 Media *m=new Media();
232 if (*uriptr != '/') {
233 /* add the directory of the list in front */
234 MediaURI *p=list->getParent(list->getRoot());
235 char ubuf[strlen(p->getName())+strlen(uriptr)+2];
236 sprintf(ubuf,"%s/%s",p->getName(),uriptr);
237 u=new MediaURI(providerid,ubuf,display);
241 u=new MediaURI(providerid,uriptr,display);
243 m->setFileName(display);
248 Log::getInstance()->log("Media",Log::DEBUG,"added media display %s, type %lu",display,mt);
256 else if (c != '\r') {
259 if (ebpos >= BUFSIZE) {
260 /* line too long - ignore */
261 Log::getInstance()->log("Media",Log::ERR,"line to long in add data");
267 return handledBytes-ebpos;