summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/mediaScan/include/AbstractMedia.h10
-rw-r--r--libs/mediaScan/include/Audio.h3
-rw-r--r--libs/mediaScan/include/Movie.h5
-rw-r--r--libs/mediaScan/src/AbstractMedia.cc18
-rw-r--r--libs/mediaScan/src/Audio.cc49
-rw-r--r--libs/mediaScan/src/Movie.cc20
-rw-r--r--libs/util/include/util.h5
-rw-r--r--libs/util/src/util.cc138
8 files changed, 245 insertions, 3 deletions
diff --git a/libs/mediaScan/include/AbstractMedia.h b/libs/mediaScan/include/AbstractMedia.h
index 6dbf673..f877fb3 100644
--- a/libs/mediaScan/include/AbstractMedia.h
+++ b/libs/mediaScan/include/AbstractMedia.h
@@ -59,6 +59,7 @@ public:
SupportedMediaType MediaType(void) const { return mediaType; }
const char *MimeType(void) const { return mimeType; }
const char *AbsolutePath(void) const;
+ const char *Format(void) const { return format; }
virtual const char *KeyFile(void) const;
ulong LastModified(void) const;
const char *LogicalPath(void) const { return logicalPath; }
@@ -72,15 +73,23 @@ public:
virtual size_t ReadChunk(char *buf, size_t bufSize);
///< used to hide the differences between single- and multi-file media.
virtual void Reset(void);
+ int Width(void) const { return width; }
+ int Height(void) const { return height; }
void Dump(void) const;
static const char *MediaType2Text(int Type);
protected:
cAbstractMedia(const cFile &File, const char *Mime, SupportedMediaType Type);
+ virtual void SetFormat(const char *Format);
void SetMediaType(int NewType);
void SetMimeType(const char *MimeType);
const cFile &KeyPath(void) const { return keyPath; }
+ std::vector<cMediainfoReader::InfoEntry *> meta;
int fd;
+ char *format;
+ short width;
+ short height;
+ double aspect;
private:
SupportedMediaType mediaType;
@@ -88,7 +97,6 @@ private:
char *uri;
char *logicalPath;
cFile keyPath;
- std::vector<cMediainfoReader::InfoEntry *> meta;
};
#endif /* ABSTRACTMEDIA_H */
diff --git a/libs/mediaScan/include/Audio.h b/libs/mediaScan/include/Audio.h
index 3dc8faa..1677c53 100644
--- a/libs/mediaScan/include/Audio.h
+++ b/libs/mediaScan/include/Audio.h
@@ -32,11 +32,14 @@ public:
cAudio(const cFile &File, const char *Mime);
virtual ~cAudio();
+ virtual void AddMeta(cMediainfoReader::InfoEntry *Entry);
+ virtual const char *Name(void) const;
virtual bool NeedsFurtherScan(void) const;
static void EnableDeepScan(bool DoScan);
private:
static const char *ContentType(const char *Extension);
+ mutable char *name;
static SupportedExtension knownExtensions[];
friend class cMediaFactory;
friend class FScanTest;
diff --git a/libs/mediaScan/include/Movie.h b/libs/mediaScan/include/Movie.h
index 36355b3..64d024d 100644
--- a/libs/mediaScan/include/Movie.h
+++ b/libs/mediaScan/include/Movie.h
@@ -33,11 +33,16 @@ public:
virtual ~cMovie();
virtual void AddMeta(cMediainfoReader::InfoEntry *Entry);
+ bool IsHD(void) const { return isHD; }
virtual bool NeedsFurtherScan(void) const;
static void EnableDeepScan(bool DoScan);
+protected:
+ virtual void SetFormat(const char *Format);
+
private:
static const char *ContentType(const char *Extension);
+ bool isHD;
static SupportedExtension knownExtensions[];
friend class cMediaFactory;
friend class FScanTest;
diff --git a/libs/mediaScan/src/AbstractMedia.cc b/libs/mediaScan/src/AbstractMedia.cc
index 2cc85c5..40b94ea 100644
--- a/libs/mediaScan/src/AbstractMedia.cc
+++ b/libs/mediaScan/src/AbstractMedia.cc
@@ -36,9 +36,14 @@
#include <unistd.h>
#include <tuple>
#include <iostream>
+#include <string>
cAbstractMedia::cAbstractMedia(const cFile &File, const char *Mime, SupportedMediaType Type)
: fd(-1)
+ , format(NULL)
+ , width(0)
+ , height(0)
+ , aspect(0)
, mediaType(Type)
, mimeType(Mime ? strdup(Mime) : NULL)
, uri(NULL)
@@ -54,10 +59,18 @@ cAbstractMedia::~cAbstractMedia()
free(mimeType);
free(uri);
free(logicalPath);
+ free(format);
}
void cAbstractMedia::AddMeta(cMediainfoReader::InfoEntry* Entry)
{
+ if (!Entry) return;
+ std::string name = std::get<0>(*Entry);
+ std::string value = std::get<1>(*Entry);
+
+ if (!strcmp("Format", name.c_str()) && !format) SetFormat(value.c_str());
+ else if (!strcmp("Width", name.c_str())) width = parseInt(value);
+ else if (!strcmp("Height", name.c_str())) height = parseInt(value);
meta.push_back(Entry);
}
@@ -117,6 +130,11 @@ void cAbstractMedia::Reset(void)
}
}
+void cAbstractMedia::SetFormat(const char *Format)
+{
+ format = strdup(Format);
+}
+
void cAbstractMedia::SetMediaType(int NewType)
{
switch (NewType) {
diff --git a/libs/mediaScan/src/Audio.cc b/libs/mediaScan/src/Audio.cc
index fdaae7e..9420db6 100644
--- a/libs/mediaScan/src/Audio.cc
+++ b/libs/mediaScan/src/Audio.cc
@@ -23,8 +23,10 @@
* --------------------------------------------------------------
*/
#include <Audio.h>
+#include <StringBuilder.h>
#include <stddef.h>
#include <string.h>
+#include <util.h>
static bool deepScanEnabled = false;
@@ -50,11 +52,23 @@ SupportedExtension cAudio::knownExtensions[] = {
cAudio::cAudio(const cFile &File, const char *Mime)
: cAbstractMedia(File, Mime, Audio)
+ , name(NULL)
{
}
cAudio::~cAudio()
{
+ free(name);
+}
+
+void cAudio::AddMeta(cMediainfoReader::InfoEntry* Entry)
+{
+ if (!Entry) return;
+ std::string name = std::get<0>(*Entry);
+ std::string value = std::get<1>(*Entry);
+
+ if (!strcmp("Bit rate", name.c_str())) width = parseInt(value);
+ cAbstractMedia::AddMeta(Entry);
}
void cAudio::EnableDeepScan(bool DoScan)
@@ -70,6 +84,41 @@ const char *cAudio::ContentType(const char* Extension)
return NULL;
}
+const char *cAudio::Name(void) const
+{
+ if (!name) {
+ cMediainfoReader::InfoEntry *performer = NULL, *album = NULL, *track = NULL;
+
+ for (size_t i=0; i < meta.size(); ++i) {
+ cMediainfoReader::InfoEntry *ie = meta[i];
+ std::string name = std::get<0>(*ie);
+
+ if (!strcmp("Album", name.c_str())) album = ie;
+ else if (!strcmp("Performer", name.c_str())) performer = ie;
+ else if (!strcmp("Track name", name.c_str())) track = ie;
+ }
+
+ if (track) {
+ std::string tmp = std::get<1>(*track);
+ cStringBuilder sb(tmp.c_str());
+
+ if (performer) {
+ tmp = std::get<1>(*performer);
+ sb.Append(" / ").Append(tmp.c_str());
+ }
+ if (album) {
+ tmp = std::get<1>(*album);
+ sb.Append(" (").Append(tmp.c_str()).Append(")");
+ }
+ name = sb.toString();
+ }
+ else {
+ name = strdup(cAbstractMedia::Name());
+ }
+ }
+ return name;
+}
+
bool cAudio::NeedsFurtherScan(void) const
{
return deepScanEnabled;
diff --git a/libs/mediaScan/src/Movie.cc b/libs/mediaScan/src/Movie.cc
index d161dfe..51d1ff9 100644
--- a/libs/mediaScan/src/Movie.cc
+++ b/libs/mediaScan/src/Movie.cc
@@ -25,6 +25,7 @@
#include <Movie.h>
#include <stddef.h>
#include <string.h>
+#include <util.h>
static bool deepScanEnabled = true;
@@ -64,8 +65,16 @@ const char *cMovie::ContentType(const char* Extension)
void cMovie::AddMeta(cMediainfoReader::InfoEntry *Entry)
{
- if (!strcmp("Scan type", std::get<0>(*Entry).c_str())) {
- if (!strcmp("Interlaced", std::get<1>(*Entry).c_str())) SetMediaType(MediaType() + 1);
+ if (!Entry) return;
+ std::string name = std::get<0>(*Entry);
+ std::string value = std::get<1>(*Entry);
+
+ if (!strcmp("Scan type", name.c_str())) {
+ if (!strcmp("Interlaced", value.c_str())) SetMediaType(MediaType() + 1);
+ }
+ else if (!strcmp("Aspect", name.c_str())) {
+ aspect = parseAspect(value);
+ if (height > 0 && width > 0) width = height * aspect;
}
cAbstractMedia::AddMeta(Entry);
}
@@ -79,3 +88,10 @@ bool cMovie::NeedsFurtherScan(void) const
{
return deepScanEnabled;
}
+
+void cMovie::SetFormat(const char* Format) {
+ if (!strcmp("Matroska", Format) || !strcmp("Flash Video", Format)
+ || !strcmp("MPEG-PS", Format) || !strcmp("MPEG-TS", Format) || !strcmp("MPEG-PES", Format))
+ return; // skip containers
+ cAbstractMedia::SetFormat(Format);
+} \ No newline at end of file
diff --git a/libs/util/include/util.h b/libs/util/include/util.h
index 023c435..1f92380 100644
--- a/libs/util/include/util.h
+++ b/libs/util/include/util.h
@@ -26,6 +26,7 @@
#define UTIL_H
#include <stdlib.h>
+#include <string>
#define FREE(m) { void *_tmp_ = m; m = NULL; free(_tmp_); }
#define TO_STRING(s) #s
#define EVER ;;
@@ -37,6 +38,10 @@
extern const char *skipWhitespace(const char *Buffer);
extern const char *getWord(char *buf, int bufSize, const char *src);
extern const char *restOfLine(char *buf, int bufSize, const char *src);
+extern double parseAspect(const char *input, const char **next = NULL);
+extern double parseAspect(const std::string &input, const char **next = NULL);
+extern long parseInt(const char *input, const char **next = NULL);
+extern long parseInt(const std::string &input, const char **next = NULL);
#endif /* UTIL_H */
diff --git a/libs/util/src/util.cc b/libs/util/src/util.cc
index 61027a1..fa679da 100644
--- a/libs/util/src/util.cc
+++ b/libs/util/src/util.cc
@@ -59,3 +59,141 @@ const char *restOfLine(char *buf, int bufSize, const char *src)
return *s ? s : NULL;
}
+
+double parseAspect(const std::string &input, const char **next)
+{
+ return parseAspect(input.c_str(), next);
+}
+
+double parseAspect(const char *input, const char **next)
+{
+ enum { Double, TwoInt, OneInt } mode = OneInt;
+ char buf[32];
+ char *pd, *pmd, *nextBuf;
+ const char *ps, *pms;
+
+ for (pd = buf, pmd = buf + sizeof(buf) - 1, ps=input, pms = input + strlen(input); ps < pms && pd < pmd; ++ps) {
+ switch (*ps) {
+ case ' ':
+ case '\t':
+ continue;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ *pd++ = *ps;
+ break;
+
+ case '.':
+ mode = Double;
+ pms = ps;
+ break;
+
+ case ':':
+ mode = TwoInt;
+ pms = ps;
+ break;
+
+ default:
+ pms = --ps;
+ break;
+ }
+ }
+ *pd = 0;
+
+ if (mode == OneInt) {
+ if (next) *next = ps;
+ return strtod(buf, NULL);
+ }
+ nextBuf = mode == TwoInt ? pd + 1 : pd;
+
+ for (pd = nextBuf; ps < pms && pd < pmd; ++ps) {
+ switch (*ps) {
+ case ' ':
+ case '\t':
+ continue;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ *pd++ = *ps;
+ break;
+
+ case '.':
+ mode = Double;
+ pms = ps;
+ break;
+
+ case ':':
+ mode = TwoInt;
+ pms = ps;
+ break;
+
+ default:
+ pms = --ps;
+ break;
+ }
+ }
+ *pd = 0;
+ if (next) *next = ps;
+ if (mode == Double) return strtod(buf, NULL);
+ long a = atol(buf);
+ long b = atol(nextBuf);
+
+ return (double)a / (double)b;
+}
+
+long parseInt(const std::string &input, const char **next)
+{
+ return parseInt(input.c_str(), next);
+}
+
+long parseInt(const char *input, const char **next)
+{
+ char buf[32];
+ char *pd, *pmd;
+ const char *ps, *pms;
+
+ for (pd = buf, pmd = buf + sizeof(buf) - 1, ps=input, pms = input + strlen(input); ps < pms && pd < pmd; ++ps) {
+ switch (*ps) {
+ case ' ':
+ case '\t':
+ continue;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ *pd++ = *ps;
+ break;
+
+ default:
+ pms = --ps;
+ break;
+ }
+ }
+ *pd = 0;
+ if (next) *next = ps;
+
+ return atol(buf);
+}