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