summaryrefslogtreecommitdiff
path: root/libs/fsScan/src/FilesystemScanner.cc
diff options
context:
space:
mode:
authorgeronimo <geronimo013@gmx.de>2012-07-13 04:26:40 +0200
committergeronimo <geronimo013@gmx.de>2012-07-13 04:26:40 +0200
commit2d48ae784ea6828e8626c32c848f64232d8f35c0 (patch)
treefab114b03e91125783a778b835dd1913b039cebe /libs/fsScan/src/FilesystemScanner.cc
downloadcmp-2d48ae784ea6828e8626c32c848f64232d8f35c0.tar.gz
cmp-2d48ae784ea6828e8626c32c848f64232d8f35c0.tar.bz2
initial import
Diffstat (limited to 'libs/fsScan/src/FilesystemScanner.cc')
-rw-r--r--libs/fsScan/src/FilesystemScanner.cc166
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