diff options
author | geronimo <geronimo013@gmx.de> | 2012-07-13 04:26:40 +0200 |
---|---|---|
committer | geronimo <geronimo013@gmx.de> | 2012-07-13 04:26:40 +0200 |
commit | 2d48ae784ea6828e8626c32c848f64232d8f35c0 (patch) | |
tree | fab114b03e91125783a778b835dd1913b039cebe /libs/fsScan/src/FilesystemScanner.cc | |
download | cmp-2d48ae784ea6828e8626c32c848f64232d8f35c0.tar.gz cmp-2d48ae784ea6828e8626c32c848f64232d8f35c0.tar.bz2 |
initial import
Diffstat (limited to 'libs/fsScan/src/FilesystemScanner.cc')
-rw-r--r-- | libs/fsScan/src/FilesystemScanner.cc | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/libs/fsScan/src/FilesystemScanner.cc b/libs/fsScan/src/FilesystemScanner.cc new file mode 100644 index 0000000..8377691 --- /dev/null +++ b/libs/fsScan/src/FilesystemScanner.cc @@ -0,0 +1,166 @@ +/** + * ======================== legal notice ====================== + * + * File: FilesystemScanner.cc + * Created: 2. Juli 2012, 13:58 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libfsScan: mediatypes and filesystem scanning + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <FilesystemScanner.h> +#include <AbstractMedia.h> +#include <Logging.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <sys/dir.h> +#include <sys/stat.h> +#include <stdio.h> +#include <errno.h> +#include <util.h> + +void freeMediaCallback(void *elem) +{ + delete (cAbstractMedia *)elem; +} + +cFilesystemScanner::cFilesystemScanner() + : baseDirectory(NULL) + , fileBufSize(512) + , dirEntryBuf(NULL) + , pool(freeMediaCallback) + , mediaFactory(NULL) +{ +} + +cFilesystemScanner::~cFilesystemScanner() +{ + FREE(dirEntryBuf); + FREE(baseDirectory); + pool.clear(); + if (mediaFactory) delete mediaFactory; +} + +void cFilesystemScanner::SetBaseDirectory(const char* dir) +{ + FREE(baseDirectory); + baseDirectory = strdup(dir); + if (mediaFactory) mediaFactory->SetBaseDirectory(dir); +} + +void cFilesystemScanner::SetMediaFactory(cMediaFactory* factory) +{ + if ((mediaFactory = factory)) { + FREE(baseDirectory); + baseDirectory = strdup(mediaFactory->BaseDirectory()); + } +} + +// return true if a should be ordered before b +bool defaultMediaSortOrder(void *a, void *b) +{ + if (!a && !b) return true; + if (!a && b) return false; + if (a && !b) return true; + cAbstractMedia *m0 = (cAbstractMedia *)a; + cAbstractMedia *m1 = (cAbstractMedia *)b; + bool rv = (m0->MediaType() - m1->MediaType()) < 0; + + if (!rv) rv = strcmp(m0->Name(), m1->Name()); + + return rv; +} + +void cFilesystemScanner::Refresh() +{ + if (!mediaFactory) return; + pool.clear(); + categories.clear(); + dirEntryBuf = (struct dirent *)malloc(sizeof(struct dirent)); + if (!dirEntryBuf) { + esyslog("ERROR: out of memory!"); + return; + } + parseDir(baseDirectory, pool); + FREE(dirEntryBuf); +#ifdef REDNOSE + pool.sort(defaultMediaSortOrder); +#else + pool.sort(NULL); +#endif + cAbstractMedia::SupportedMediaType ot = cAbstractMedia::Invalid; + cAbstractMedia *m; + + for (size_t i=0; i < pool.size(); ++i) { + m = (cAbstractMedia *) pool[i]; + if (m->MediaType() != ot) { + ot = m->MediaType(); + categories[ot] = i; + } + } +} + +void cFilesystemScanner::parseDir(const char* dirName, cManagedVector &result) +{ + if (!mediaFactory) return; + DIR *dir = opendir(dirName); + cAbstractMedia *media; + char *pathBuf = (char *)malloc(fileBufSize); + struct dirent *dirEntry; + struct stat statBuf; + + if (!dir) return; + if (!pathBuf) { + closedir(dir); + return; + } + if (fileBufSize < strlen(dirName) + 128) { + fileBufSize += 256; + pathBuf = (char *)realloc(pathBuf, fileBufSize); + } + while (!readdir_r(dir, dirEntryBuf, &dirEntry) && dirEntry) { + if (*dirEntry->d_name == '.') continue; // don't bother with hidden stuff + strcpy(pathBuf, dirName); + strcat(pathBuf, "/"); + strcat(pathBuf, dirEntry->d_name); + if (stat(pathBuf, &statBuf) < 0) return; + if ((media = mediaFactory->CreateMedia(pathBuf, &statBuf))) { + result.push_back(media); + isyslog("found media %s - %s", media->MimeType(), media->LogicalPath()); + continue; + } + if ((statBuf.st_mode & S_IFMT) == S_IFDIR) parseDir(pathBuf, result); + } + closedir(dir); + FREE(pathBuf); +} + +cAbstractMedia *cFilesystemScanner::FindMedia(const char* LogicalPath) +{ + cAbstractMedia *rv = NULL, *tmp; + + for (size_t i=0; i < pool.size(); ++i) { + tmp = (cAbstractMedia *) pool[i]; + if (!strcmp(tmp->LogicalPath(), LogicalPath)) { + rv = tmp; + break; + } + } + return rv; +}
\ No newline at end of file |