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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include "threadwin.h"
28 #include "mediafile.h"
31 #include <sys/types.h>
40 MediaFile::MediaFile(ULONG pid){
44 MediaFile::~MediaFile(){
50 const char* extension;
53 {".mp3",MEDIA_TYPE_AUDIO},
54 {".MP3",MEDIA_TYPE_AUDIO},
55 {".jpg",MEDIA_TYPE_PICTURE},
56 {".JPG",MEDIA_TYPE_PICTURE},
57 {".jpeg",MEDIA_TYPE_PICTURE},
58 {".JPEG",MEDIA_TYPE_PICTURE},
59 {".mpg",MEDIA_TYPE_VIDEO},
60 {".MPG",MEDIA_TYPE_VIDEO}
62 //#define NUMTYPES (sizeof(mediatypes)/sizeof(mtype))
65 //helper from vdr tools.c
66 bool endswith(const char *s, const char *p)
68 const char *se = s + strlen(s) - 1;
69 const char *pe = p + strlen(p) - 1;
71 if (*pe-- != *se-- || (se < s && pe >= p))
77 MediaList* MediaFile::getRootList() {
78 //has to be implemented in the derived class
82 ULONG MediaFile::getMediaType(const char * filename) {
83 for (ULONG i=0;i<NUMTYPES;i++) {
84 if (endswith(filename,mediatypes[i].extension)) {
85 return mediatypes[i].type;
88 return MEDIA_TYPE_UNKNOWN;
92 Media * MediaFile::createMedia(const char * dirname, const char * filename, bool withURI) {
94 char *buffer=(char*)malloc(strlen(dirname)+strlen(filename)+2);
95 sprintf(buffer, "%s/%s", dirname, filename);
97 ULONG mtype=MEDIA_TYPE_UNKNOWN;
100 if (stat(buffer, &st) == 0) {
101 if (S_ISDIR(st.st_mode)) {
102 mtype=MEDIA_TYPE_DIR;
105 mtype=getMediaType(filename);
109 WIN32_FILE_ATTRIBUTE_DATA att;
110 GetFileAttributesEx(buffer,GetFileExInfoStandard,&att);
111 if (att.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
112 mtype=MEDIA_TYPE_DIR;
114 mtype=getMediaType(filename);
118 //only consider entries we accept by type here
119 if (mtype != MEDIA_TYPE_UNKNOWN) {
121 rt->setMediaType(mtype);
122 rt->setFileName(filename);
124 rt->setTime(st.st_mtime);
126 struct timespec targetTime;
127 targetTime.tv_sec=(*((__int64*) &att.ftCreationTime)-WINDOWS_TIME_BASE_OFFSET)/(10*1000*1000);
128 targetTime.tv_nsec=((*((__int64*)&att.ftCreationTime)-WINDOWS_TIME_BASE_OFFSET)%(10*1000*1000))*100;
129 rt->setTime(targetTime.tv_sec);
131 Log::getInstance()->log("Media",Log::DEBUG,"created Media %s, type=%d",filename,mtype);
133 MediaURI u(providerid,buffer,NULL);
141 MediaList* MediaFile::getMediaList(const MediaURI * parent){
142 ULONG mediaType=parent->getAllowedTypes();
143 Log::getInstance()->log("MediaFile::getMediaList",Log::DEBUG,"parent %s,types=0x%0lx",parent->getName(),mediaType);
145 rt=new MediaList(parent);
146 const char *dirname=parent->getName();
147 //open the directory and read out the entries
149 DIR *d=opendir(dirname);
151 union { // according to "The GNU C Library Reference Manual"
153 char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
155 while (d != NULL && (readdir_r(d,&u.d,&e) == 0) && e != NULL) {
156 const char * fname=e->d_name;
160 d=FindFirstFile(dirname,&e);
161 if (d==INVALID_HANDLE_VALUE) {
165 const char * fname=e.cFileName;
167 if ( fname == NULL) continue;
168 if (strcmp(fname,".") == 0) continue;
169 if (strcmp(fname,"..") == 0) continue;
170 Media *m=createMedia(dirname,fname);
171 if (m && ( m->getMediaType() & mediaType)) {
172 Log::getInstance()->log("Media",Log::DEBUG,"added entry %s, type=%d",fname,m->getMediaType());
180 if (d != NULL) closedir(d);
182 } while (FindNextFile(d,&e));
189 int MediaFile::openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize) {
190 Log::getInstance()->log("Media::openMedium",Log::DEBUG,"fn=%s,chan=%u",uri->getName(),channel);
192 if (channel <0 || channel >= NUMCHANNELS) return -1;
193 struct ChannelInfo *info=&channels[channel];
194 if (info->file) info->reset();
195 FILE *fp=fopen(uri->getName(),"r");
197 Log::getInstance()->log("Media::openMedium",Log::ERR,"unable to open file fn=%s,chan=%u",uri->getName(),channel);
204 if ( fstat(fileno(fp),&st) == 0) mysize=st.st_size;
206 mysize=_filelength(_fileno(fp));
209 Log::getInstance()->log("Media::openMedium",Log::ERR,"unable to open file fn=%s,chan=%u",uri->getName(),channel);
213 info->setFilename(uri->getName());
217 info->provider=providerid;
222 int MediaFile::getMediaBlock(ULONG channel, ULLONG offset, ULONG len, ULONG * outlen,
223 unsigned char ** buffer) {
224 Log::getInstance()->log("Media::getMediaBlock",Log::DEBUG,"chan=%u,offset=%llu,len=%lu",channel,offset,len);
226 if (channel <0 || channel >= NUMCHANNELS) return -1;
227 struct ChannelInfo *info=&channels[channel];
229 Log::getInstance()->log("Media::getMediaBlock",Log::ERR,"not open chan=%u",channel);
232 ULLONG cpos=ftell(info->file);
233 if (offset != cpos) {
234 fseek(info->file,offset-cpos,SEEK_CUR);
236 if (offset != (ULLONG)ftell(info->file)) {
237 Log::getInstance()->log("Client", Log::DEBUG, "getMediaBlock pos = %llu not available", offset);
240 if (*buffer == NULL) *buffer=(UCHAR *)malloc(len);
241 if (*buffer == NULL) {
242 Log::getInstance()->log("Media::getMediaBlock",Log::ERR,"uanble to allocate buffer");
245 ULONG amount=fread(*buffer,1,len,info->file);
246 Log::getInstance()->log("Media::getMediaBlock",Log::DEBUG,"readlen=%lu",amount);
252 int MediaFile::closeMediaChannel(ULONG channel){
253 Log::getInstance()->log("Media::closeMediaChannel",Log::DEBUG,"chan=%u",channel);
254 if (channel <0 || channel >= NUMCHANNELS) return -1;
255 struct ChannelInfo *info=&channels[channel];
260 //TODO: fill in more info
261 int MediaFile::getMediaInfo(ULONG channel, MediaInfo * result){
262 Log::getInstance()->log("Media::getMediaInfo",Log::DEBUG,"chan=%u",channel);
263 if (channel <0 || channel >= NUMCHANNELS) return -1;
264 struct ChannelInfo *info=&channels[channel];
265 if (! info->file) return -1;
266 result->size=info->size;
267 result->canPosition=true;