1 /* 2 * tuple.h 3 * Copyright 2007-2013 Ariadne Conill, Christian Birchinger, Matti Hämäläinen, 4 * Giacomo Lozito, Eugene Zagidullin, and John Lindgren 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions, and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions, and the following disclaimer in the documentation 14 * provided with the distribution. 15 * 16 * This software is provided "as is" and without any warranty, express or 17 * implied. In no event shall the authors be liable for any damages arising from 18 * the use of this software. 19 */ 20 21 /** 22 * @file tuple.h 23 * @brief Basic Tuple handling API. 24 */ 25 26 #ifndef LIBAUDCORE_TUPLE_H 27 #define LIBAUDCORE_TUPLE_H 28 29 #include <libaudcore/objects.h> 30 31 struct ReplayGainInfo; 32 struct TupleData; 33 class PluginHandle; 34 class VFSFile; 35 36 class Tuple 37 { 38 public: 39 /* Smart pointer to the actual TupleData struct. 40 * Uses create-on-write and copy-on-write. */ 41 42 enum State 43 { 44 Initial, /* Song info has not yet been read */ 45 Valid, /* Song info has been successfully read */ 46 Failed /* Song info could not be read */ 47 }; 48 49 enum Field 50 { 51 Invalid = -1, 52 53 Title = 0, /* Song title */ 54 Artist, /* Song artist */ 55 Album, /* Album name */ 56 AlbumArtist, /* Artist for entire album, if different than song artist 57 */ 58 Comment, /* Freeform comment */ 59 Genre, /* Song's genre */ 60 Year, /* Year of production, performance, etc. */ 61 62 Composer, /* Composer, if different than artist */ 63 Performer, /* Performer, if different than artist */ 64 Copyright, /* Copyright declaration */ 65 Date, /* Date of production, performance, etc. */ 66 67 Track, /* Track number */ 68 Length, /* Track length in milliseconds */ 69 70 Bitrate, /* Bitrate in kilobits (1000 bits)/sec */ 71 Codec, /* Codec name, such as "Ogg Vorbis" */ 72 Quality, /* String representing quality, such as "Stereo, 44 kHz" */ 73 74 Basename, /* Base filename, not including the folder path */ 75 Path, /* Folder path, including the trailing "/" */ 76 Suffix, /* Filename extension, not including the "." */ 77 78 AudioFile, /* URI of audio file, if different from the nominal URI 79 * (e.g. for a cuesheet entry, where the nominal URI 80 * points to the .cue file) */ 81 82 Subtune, /* Index number of subtune */ 83 NumSubtunes, /* Total number of subtunes in the file */ 84 85 StartTime, /* Playback start point (used for cuesheets) */ 86 EndTime, /* Playback end point (used for cuesheets) */ 87 88 /* Preserving replay gain information accurately is a challenge since 89 * there are several different formats around. We use an integer 90 * fraction, with the denominator stored in the *Divisor fields. For 91 * example, if AlbumGain is 512 and GainDivisor is 256, then the album 92 * gain is +2 dB. If TrackPeak is 787 and PeakDivisor is 1000, then the 93 * peak volume is 0.787 in a -1.0 to 1.0 range. */ 94 AlbumGain, 95 AlbumPeak, 96 TrackGain, 97 TrackPeak, 98 GainDivisor, 99 PeakDivisor, 100 101 /* Title formatted for display; input plugins do not need to set this 102 field */ 103 FormattedTitle, 104 105 /* TODO: reorder these at next ABI break! */ 106 Description, /* Track description */ 107 MusicBrainzID, /* MusicBrainz identifier */ 108 Channels, /* Track channels count */ 109 110 n_fields 111 }; 112 113 typedef aud::range<Field, Field(0), Field(n_fields - 1)> all_fields; 114 115 enum ValueType 116 { 117 String, 118 Int, 119 Empty 120 }; 121 122 static Field field_by_name(const char * name); 123 static const char * field_get_name(Field field); 124 static ValueType field_get_type(Field field); 125 Tuple()126 constexpr Tuple() : data(nullptr) {} 127 128 ~Tuple(); 129 Tuple(Tuple && b)130 Tuple(Tuple && b) : data(b.data) { b.data = nullptr; } 131 132 Tuple & operator=(Tuple && b) 133 { 134 return aud::move_assign(*this, std::move(b)); 135 } 136 137 bool operator==(const Tuple & b) const; 138 bool operator!=(const Tuple & b) const { return !operator==(b); } 139 140 Tuple ref() const; 141 142 /* Gets/sets the state of the song info. Before setting the state to Valid, 143 * you should ensure that, at a minimum, set_filename() has been called. */ 144 State state() const; 145 void set_state(State st); 146 147 /* Returns the value type of a field if set, otherwise Empty. */ 148 ValueType get_value_type(Field field) const; 149 150 /* Convenience functions */ valid()151 bool valid() const { return state() == Valid; } is_set(Field field)152 bool is_set(Field field) const { return get_value_type(field) != Empty; } 153 154 /* Returns the integer value of a field if set, otherwise -1. If you need 155 * to distinguish between a value of -1 and an unset value, use 156 * get_value_type(). */ 157 int get_int(Field field) const; 158 159 /* Returns the string value of a field if set, otherwise null. */ 160 ::String get_str(Field field) const; 161 162 /* Sets a field to the integer value <x>. */ 163 void set_int(Field field, int x); 164 165 /* Sets a field to the string value <str>. If <str> is not valid UTF-8, it 166 * will be converted according to the user's character set detection rules. 167 * Equivalent to unset() if <str> is null. */ 168 void set_str(Field field, const char * str); 169 170 /* Clears any value that a field is currently set to. */ 171 void unset(Field field); 172 173 /* Parses the URI <filename> and sets Basename, Path, Suffix, and Subtune 174 * accordingly. */ 175 void set_filename(const char * filename); 176 177 /* Fills in format-related fields (specifically Codec, Quality, 178 * and Bitrate). Plugins should use this function instead of setting 179 * these fields individually to allow a consistent style across file 180 * formats. <format> should be a brief description such as "Ogg Vorbis", 181 * "MPEG-1 layer 3", "Audio CD", and so on. <samplerate> is in Hertz. 182 * <bitrate> is in (decimal) kbps. */ 183 void set_format(const char * format, int channels, int samplerate, 184 int bitrate); 185 186 /* In addition to the normal fields, tuples contain an integer array of 187 * subtune ID numbers. This function sets that array. It also sets 188 * NumSubtunes to the value <n_subtunes>. */ 189 void set_subtunes(short n_subtunes, const short * subtunes); 190 191 /* Returns the length of the subtune array. If the array has not been set, 192 * returns zero. Note that if NumSubtunes is changed after 193 * set_subtunes() is called, this function returns the value <n_subtunes> 194 * passed to set_subtunes(), not the value of NumSubtunes. */ 195 short get_n_subtunes() const; 196 197 /* Returns the <n>th member of the subtune array. */ 198 short get_nth_subtune(short n) const; 199 200 /* Sets a Replay Gain field pair from a decimal string. */ 201 void set_gain(Field field, Field unit_field, const char * str); 202 203 /* Returns true if minimal ReplayGainInfo is present. */ 204 bool has_replay_gain() const; 205 /* Fills ReplayGainInfo struct from various fields. */ 206 ReplayGainInfo get_replay_gain() const; 207 208 /* Set various fields based on the ICY metadata of <stream>. Returns true 209 * if any fields were changed. */ 210 bool fetch_stream_info(VFSFile & stream); 211 212 /* Guesses the song title, artist, and album, if not already set, from the 213 * filename. */ 214 void generate_fallbacks(); 215 216 /* Guesses only the song title, if not already set, from the filename. */ 217 void generate_title(); 218 219 /* Removes guesses made by generate_fallbacks(). This function should be 220 * called, for example, before writing a song tag from the tuple. */ 221 void delete_fallbacks(); 222 223 private: 224 TupleData * data; 225 }; 226 227 /* somewhat out of place here */ 228 struct PlaylistAddItem 229 { 230 String filename; 231 Tuple tuple; 232 PluginHandle * decoder; 233 copyPlaylistAddItem234 PlaylistAddItem copy() const { return {filename, tuple.ref(), decoder}; } 235 }; 236 237 #endif /* LIBAUDCORE_TUPLE_H */ 238