| 1 | #include <math.h> |
| 2 | |
| 3 | #include "metaiowavpack.h" |
| 4 | #include "metadata.h" |
| 5 | |
| 6 | #include <apetag.h> |
| 7 | #include <apeitem.h> |
| 8 | |
| 9 | #include <mythtv/mythcontext.h> |
| 10 | |
| 11 | MetaIOWavPack::MetaIOWavPack(void) |
| 12 | : MetaIO(".wv") |
| 13 | { |
| 14 | } |
| 15 | |
| 16 | MetaIOWavPack::~MetaIOWavPack(void) |
| 17 | { |
| 18 | } |
| 19 | |
| 20 | /*! |
| 21 | * \brief Writes metadata back to a file |
| 22 | * |
| 23 | * \param mdata A pointer to a Metadata object |
| 24 | * \param exclusive Flag to indicate if only the data in mdata should be |
| 25 | * in the file. If false, any unrecognised tags already |
| 26 | * in the file will be maintained. |
| 27 | * \returns Boolean to indicate success/failure. |
| 28 | */ |
| 29 | bool MetaIOWavPack::write(Metadata* mdata, bool exclusive) |
| 30 | { |
| 31 | (void) exclusive; |
| 32 | |
| 33 | if (!mdata) |
| 34 | return false; |
| 35 | |
| 36 | TagLib::WavPack::File *taglib = |
| 37 | new TagLib::WavPack::File(mdata->Filename().local8Bit()); |
| 38 | |
| 39 | Tag *tag = taglib->tag(); |
| 40 | |
| 41 | if (!tag) |
| 42 | { |
| 43 | if (taglib) |
| 44 | delete taglib; |
| 45 | return false; |
| 46 | } |
| 47 | |
| 48 | if (!mdata->Artist().isEmpty()) |
| 49 | tag->setArtist(QStringToTString(mdata->Artist())); |
| 50 | |
| 51 | // APE Only Tags |
| 52 | if (taglib->APETag()) |
| 53 | { |
| 54 | // Compilation Artist ("Album artist") |
| 55 | if (mdata->Compilation()) |
| 56 | { |
| 57 | TagLib::String key="Album artist"; |
| 58 | TagLib::APE::Item item=TagLib::APE::Item(key, |
| 59 | QStringToTString(mdata->CompilationArtist())); |
| 60 | taglib->APETag()->setItem(key, item); |
| 61 | } |
| 62 | else |
| 63 | { |
| 64 | taglib->APETag()->removeItem("Album artist"); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | if (!mdata->Title().isEmpty()) |
| 69 | tag->setTitle(QStringToTString(mdata->Title())); |
| 70 | |
| 71 | if (!mdata->Album().isEmpty()) |
| 72 | tag->setAlbum(QStringToTString(mdata->Album())); |
| 73 | |
| 74 | if (mdata->Year() > 999 && mdata->Year() < 10000) // 4 digit year. |
| 75 | tag->setYear(mdata->Year()); |
| 76 | |
| 77 | if (!mdata->Genre().isEmpty()) |
| 78 | tag->setGenre(QStringToTString(mdata->Genre())); |
| 79 | |
| 80 | if (0 != mdata->Track()) |
| 81 | tag->setTrack(mdata->Track()); |
| 82 | |
| 83 | bool result = taglib->save(); |
| 84 | |
| 85 | if (taglib) |
| 86 | delete taglib; |
| 87 | |
| 88 | return (result); |
| 89 | } |
| 90 | |
| 91 | |
| 92 | /*! |
| 93 | * \brief Reads Metadata from a file. |
| 94 | * |
| 95 | * \param filename The filename to read metadata from. |
| 96 | * \returns Metadata pointer or NULL on error |
| 97 | */ |
| 98 | Metadata* MetaIOWavPack::read(QString filename) |
| 99 | { |
| 100 | QString artist = "", compilation_artist = "", album = "", title = "", |
| 101 | genre = ""; |
| 102 | int year = 0, tracknum = 0, length = 0, playcount = 0, rating = 0, id = 0; |
| 103 | bool compilation = false; |
| 104 | QValueList<struct AlbumArtImage> albumart; |
| 105 | |
| 106 | QString extension = filename.section( '.', -1 ) ; |
| 107 | |
| 108 | TagLib::WavPack::File *taglib = |
| 109 | new TagLib::WavPack::File(filename.local8Bit()); |
| 110 | |
| 111 | Tag *tag = taglib->tag(); |
| 112 | |
| 113 | if (!tag) |
| 114 | { |
| 115 | if (taglib) |
| 116 | delete taglib; |
| 117 | return NULL; |
| 118 | } |
| 119 | |
| 120 | // Basic Tags |
| 121 | if (! tag->isEmpty()) |
| 122 | { |
| 123 | title = TStringToQString(tag->title()).stripWhiteSpace(); |
| 124 | artist = TStringToQString(tag->artist()).stripWhiteSpace(); |
| 125 | album = TStringToQString(tag->album()).stripWhiteSpace(); |
| 126 | tracknum = tag->track(); |
| 127 | year = tag->year(); |
| 128 | genre = TStringToQString(tag->genre()).stripWhiteSpace(); |
| 129 | } |
| 130 | |
| 131 | // APE Only Tags |
| 132 | if (taglib->APETag()) |
| 133 | { |
| 134 | // Compilation Artist ("Album artist") |
| 135 | if(taglib->APETag()->itemListMap().contains("Album artist")) |
| 136 | { |
| 137 | compilation = true; |
| 138 | compilation_artist = TStringToQString( |
| 139 | taglib->APETag()->itemListMap()["Album artist"].toString()) |
| 140 | .stripWhiteSpace(); |
| 141 | } |
| 142 | |
| 143 | } |
| 144 | |
| 145 | // Fallback to filename reading |
| 146 | if (title.isEmpty()) |
| 147 | { |
| 148 | readFromFilename(filename, artist, album, title, genre, tracknum); |
| 149 | } |
| 150 | |
| 151 | if (length <= 0 && taglib->audioProperties()) |
| 152 | length = taglib->audioProperties()->length() * 1000; |
| 153 | |
| 154 | if (taglib) |
| 155 | delete taglib; |
| 156 | |
| 157 | // If we didn't get a valid length, add the metadata but show warning. |
| 158 | if (length <= 0) |
| 159 | VERBOSE(VB_GENERAL, QString("MetaIOWavPack: Failed to read length " |
| 160 | "from '%1'. It may be corrupt.").arg(filename)); |
| 161 | |
| 162 | // If we don't have title and artist or don't have the length return NULL |
| 163 | if (title.isEmpty() && artist.isEmpty()) |
| 164 | { |
| 165 | VERBOSE(VB_IMPORTANT, |
| 166 | QString("MetaIOWavPack: Failed to read metadata from '%1'") |
| 167 | .arg(filename)); |
| 168 | return NULL; |
| 169 | } |
| 170 | |
| 171 | Metadata *retdata = new Metadata(filename, artist, compilation_artist, album, |
| 172 | title, genre, year, tracknum, length, |
| 173 | id, rating, playcount); |
| 174 | |
| 175 | retdata->setCompilation(compilation); |
| 176 | |
| 177 | return retdata; |
| 178 | } |
| 179 | |
| 180 | /*! |
| 181 | * \brief Find the length of the track (in seconds) |
| 182 | * |
| 183 | * \param filename The filename for which we want to find the length. |
| 184 | * \returns An integer (signed!) to represent the length in seconds. |
| 185 | */ |
| 186 | int MetaIOWavPack::getTrackLength(QString filename) |
| 187 | { |
| 188 | int seconds = 0; |
| 189 | TagLib::WavPack::File *taglib = |
| 190 | new TagLib::WavPack::File(filename.local8Bit()); |
| 191 | |
| 192 | if (taglib) |
| 193 | { |
| 194 | seconds = taglib->audioProperties()->length(); |
| 195 | delete taglib; |
| 196 | } |
| 197 | |
| 198 | return seconds; |
| 199 | } |