1 ///
2 /// Metadata support.
3 /// Extract metadata from media files and return in a standard format.
4 ///	@file		metadata.cpp - pianod2
5 ///	@author		Perette Barella
6 ///	@date		2015-11-30
7 ///	@copyright	Copyright (c) 2015-2016 Devious Fish. All rights reserved.
8 ///
9 
10 #include <config.h>
11 
12 #include <cassert>
13 #include <cmath>
14 
15 #include "metadata.h"
16 
17 #ifdef WITH_TAGLIB
18 #include "taglibreader.h"
19 #elif defined (WITH_GSTREAMER)
20 #include "gstreammetadata.h"
21 #elif defined (WITH_FFMPEG)
22 #include "ffmpegmetadata.h"
23 #elif defined (WITH_AVFOUNDATION)
24 #include "osxmetadata.h"
25 #endif
26 
27 using namespace std;
28 
29 namespace Media {
30 
31     /** Get a file's gain for playback.  This is currently done only if:
32         - taglib is compiled in.
33         - ffmpeg is the media engine.
34         AVFoundation does this itself; taglib only improves over
35         ffmpeg when there is iTunes normalization and *not*
36         replay gain in the file's metadata. */
getFileGain(const std::string & filename)37     float Metadata::getFileGain (const std::string &filename) {
38 #if defined(WITH_FFMPEG) && defined(WITH_TAGLIB)
39         return TaglibReader::getFileGain (filename);
40 #else
41         (void) filename;
42         return 0.0f;
43 #endif
44     };
45 
46     /** Get metadata using whatever best mechanism is available. */
getMetadata(const std::string & filename)47     const Metadata Metadata::getMetadata (const std::string &filename) {
48 #ifdef WITH_TAGLIB
49         return TaglibReader { filename };  // Holy slicing Batman!
50 #elif defined (WITH_GSTREAMER)
51         try {
52             return GstreamerMetadataReader {filename};
53         } catch (const Audio::AudioException &e) {
54             throw MediaException (e.what ());
55         }
56 #elif defined (WITH_FFMPEG)
57         try {
58             return LavMetadataReader {filename};
59         } catch (const Audio::LavAudioException &e) {
60             throw MediaException (e.what());
61         }
62 #elif defined (WITH_AVFOUNDATION)
63         return OSXMetadataReader { filename };
64 #endif
65         assert (!"Compiled without a metadata reader.");
66         throw MediaException ("No metadata reader available");
67     };
68 
69     /** Split a string '<number>/<number>' into its two components.
70         @param value The string to split.
71         @param first The value before the slash, or the single value.
72         @param second The value after a slash, if present. */
splitOf(const char * value,int * first,int * second)73     void Metadata::splitOf (const char *value, int *first, int *second) {
74         int num, count;
75         int matched = sscanf (value, "%d/%d", &num, &count);
76         if (matched >= 1) {
77             *first = num;
78         }
79         if (matched == 2) {
80             *second = count;
81         }
82     }
83 
84     /** Get the iTunes normalization, a/k/a sound check.
85         @param value The value from the iTunNORM ID3 comment.
86         @return The gain specified by iTunNORM. */
gainFromiTunesNormalization(const char * value)87     float Metadata::gainFromiTunesNormalization (const char *value) {
88         long values [4];
89         if (sscanf(value, "%lx %lx %lx %lx",
90                    &values [0], &values [1], &values [2], &values [3]) == 4) {
91             if (values [0] > 0) {
92                 float gain = -10 * log10 (double (values [0]) / 1000.0);
93                 // flog (LOG_WHERE (LOG_GENERAL), "Using iTunNORM gain ", gain, "dB");
94                 return gain;
95             }
96         }
97         return 0.0;
98     }
99 
100 }
101