Changeset View
Changeset View
Standalone View
Standalone View
src/extractors/taglibextractor.cpp
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Line(s) | |||||
42 | #include <asftag.h> | 42 | #include <asftag.h> | ||
43 | #include <asfattribute.h> | 43 | #include <asfattribute.h> | ||
44 | #include <id3v2tag.h> | 44 | #include <id3v2tag.h> | ||
45 | #include <mp4tag.h> | 45 | #include <mp4tag.h> | ||
46 | #include <popularimeterframe.h> | 46 | #include <popularimeterframe.h> | ||
47 | 47 | | |||
48 | using namespace KFileMetaData; | 48 | using namespace KFileMetaData; | ||
49 | 49 | | |||
50 | TagLibExtractor::TagLibExtractor(QObject* parent) | 50 | namespace { | ||
51 | : ExtractorPlugin(parent) | | |||
52 | { | | |||
53 | } | | |||
54 | 51 | | |||
55 | const QStringList supportedMimeTypes = { | 52 | const QStringList supportedMimeTypes = { | ||
56 | QStringLiteral("audio/flac"), | 53 | QStringLiteral("audio/flac"), | ||
57 | QStringLiteral("audio/mp4"), | 54 | QStringLiteral("audio/mp4"), | ||
58 | QStringLiteral("audio/mpeg"), | 55 | QStringLiteral("audio/mpeg"), | ||
59 | QStringLiteral("audio/mpeg3"), | 56 | QStringLiteral("audio/mpeg3"), | ||
60 | QStringLiteral("audio/ogg"), | 57 | QStringLiteral("audio/ogg"), | ||
61 | QStringLiteral("audio/opus"), | 58 | QStringLiteral("audio/opus"), | ||
62 | QStringLiteral("audio/speex"), | 59 | QStringLiteral("audio/speex"), | ||
63 | QStringLiteral("audio/wav"), | 60 | QStringLiteral("audio/wav"), | ||
64 | QStringLiteral("audio/x-aiff"), | 61 | QStringLiteral("audio/x-aiff"), | ||
65 | QStringLiteral("audio/x-aifc"), | 62 | QStringLiteral("audio/x-aifc"), | ||
66 | QStringLiteral("audio/x-ape"), | 63 | QStringLiteral("audio/x-ape"), | ||
67 | QStringLiteral("audio/x-mpeg"), | 64 | QStringLiteral("audio/x-mpeg"), | ||
68 | QStringLiteral("audio/x-ms-wma"), | 65 | QStringLiteral("audio/x-ms-wma"), | ||
69 | QStringLiteral("audio/x-musepack"), | 66 | QStringLiteral("audio/x-musepack"), | ||
70 | QStringLiteral("audio/x-opus+ogg"), | 67 | QStringLiteral("audio/x-opus+ogg"), | ||
71 | QStringLiteral("audio/x-speex+ogg"), | 68 | QStringLiteral("audio/x-speex+ogg"), | ||
72 | QStringLiteral("audio/x-vorbis+ogg"), | 69 | QStringLiteral("audio/x-vorbis+ogg"), | ||
73 | QStringLiteral("audio/x-wav"), | 70 | QStringLiteral("audio/x-wav"), | ||
74 | QStringLiteral("audio/x-wavpack"), | 71 | QStringLiteral("audio/x-wavpack"), | ||
75 | }; | 72 | }; | ||
76 | 73 | | |||
77 | QStringList TagLibExtractor::mimetypes() const | | |||
78 | { | | |||
79 | return supportedMimeTypes; | | |||
80 | } | | |||
81 | | ||||
82 | void extractAudioProperties(TagLib::File* file, ExtractionResult* result) | 74 | void extractAudioProperties(TagLib::File* file, ExtractionResult* result) | ||
83 | { | 75 | { | ||
84 | TagLib::AudioProperties* audioProp = file->audioProperties(); | 76 | TagLib::AudioProperties* audioProp = file->audioProperties(); | ||
85 | if (audioProp) { | 77 | if (audioProp) { | ||
86 | if (audioProp->length()) { | 78 | if (audioProp->length()) { | ||
87 | // What about the xml duration? | 79 | // What about the xml duration? | ||
88 | result->add(Property::Duration, audioProp->length()); | 80 | result->add(Property::Duration, audioProp->length()); | ||
89 | } | 81 | } | ||
90 | 82 | | |||
91 | if (audioProp->bitrate()) { | 83 | if (audioProp->bitrate()) { | ||
92 | result->add(Property::BitRate, audioProp->bitrate() * 1000); | 84 | result->add(Property::BitRate, audioProp->bitrate() * 1000); | ||
93 | } | 85 | } | ||
94 | 86 | | |||
95 | if (audioProp->channels()) { | 87 | if (audioProp->channels()) { | ||
96 | result->add(Property::Channels, audioProp->channels()); | 88 | result->add(Property::Channels, audioProp->channels()); | ||
97 | } | 89 | } | ||
98 | 90 | | |||
99 | if (audioProp->sampleRate()) { | 91 | if (audioProp->sampleRate()) { | ||
100 | result->add(Property::SampleRate, audioProp->sampleRate()); | 92 | result->add(Property::SampleRate, audioProp->sampleRate()); | ||
101 | } | 93 | } | ||
102 | } | 94 | } | ||
103 | } | 95 | } | ||
104 | 96 | | |||
105 | void TagLibExtractor::readGenericProperties(const TagLib::PropertyMap &savedProperties, ExtractionResult* result) | 97 | void readGenericProperties(const TagLib::PropertyMap &savedProperties, ExtractionResult* result) | ||
bruns: This puts `readGenericProperties(...)` with external linkage in the global namespace.
Put the… | |||||
astippich: Urgh, that was the plan actually. I could swear I've done that. | |||||
106 | { | 98 | { | ||
107 | if (savedProperties.isEmpty()) { | 99 | if (savedProperties.isEmpty()) { | ||
108 | return; | 100 | return; | ||
109 | } | 101 | } | ||
110 | if (savedProperties.contains("TITLE")) { | 102 | if (savedProperties.contains("TITLE")) { | ||
111 | result->add(Property::Title, TStringToQString(savedProperties["TITLE"].toString()).trimmed()); | 103 | result->add(Property::Title, TStringToQString(savedProperties["TITLE"].toString()).trimmed()); | ||
112 | } | 104 | } | ||
113 | if (savedProperties.contains("ALBUM")) { | 105 | if (savedProperties.contains("ALBUM")) { | ||
▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Line(s) | 245 | if (savedProperties.contains("REPLAYGAIN_ALBUM_PEAK")) { | |||
255 | bool success = false; | 247 | bool success = false; | ||
256 | double replayGainAlbumPeak = albumPeakString.toDouble(&success); | 248 | double replayGainAlbumPeak = albumPeakString.toDouble(&success); | ||
257 | if (success) { | 249 | if (success) { | ||
258 | result->add(Property::ReplayGainAlbumPeak, replayGainAlbumPeak); | 250 | result->add(Property::ReplayGainAlbumPeak, replayGainAlbumPeak); | ||
259 | } | 251 | } | ||
260 | } | 252 | } | ||
261 | } | 253 | } | ||
262 | 254 | | |||
263 | void TagLibExtractor::extractId3Tags(TagLib::ID3v2::Tag* Id3Tags, ExtractionResult* result) | 255 | void extractId3Tags(TagLib::ID3v2::Tag* Id3Tags, ExtractionResult* result) | ||
264 | { | 256 | { | ||
265 | if (Id3Tags->isEmpty()) { | 257 | if (Id3Tags->isEmpty()) { | ||
266 | return; | 258 | return; | ||
267 | } | 259 | } | ||
268 | TagLib::ID3v2::FrameList lstID3v2; | 260 | TagLib::ID3v2::FrameList lstID3v2; | ||
269 | 261 | | |||
270 | /* | 262 | /* | ||
271 | * Publisher. | 263 | * Publisher. | ||
Show All 32 Lines | 290 | } else if (rating == 1) { | |||
304 | } | 296 | } | ||
305 | } else if (rating >= 1 && rating <= 255) { | 297 | } else if (rating >= 1 && rating <= 255) { | ||
306 | rating = static_cast<int>(0.032 * rating + 2); | 298 | rating = static_cast<int>(0.032 * rating + 2); | ||
307 | } | 299 | } | ||
308 | result->add(Property::Rating, rating); | 300 | result->add(Property::Rating, rating); | ||
309 | } | 301 | } | ||
310 | } | 302 | } | ||
311 | 303 | | |||
312 | void TagLibExtractor::extractMp4Tags(TagLib::MP4::Tag* mp4Tags, ExtractionResult* result) | 304 | void extractMp4Tags(TagLib::MP4::Tag* mp4Tags, ExtractionResult* result) | ||
313 | { | 305 | { | ||
314 | if (mp4Tags->isEmpty()) { | 306 | if (mp4Tags->isEmpty()) { | ||
315 | return; | 307 | return; | ||
316 | } | 308 | } | ||
317 | TagLib::MP4::ItemListMap allTags = mp4Tags->itemListMap(); | 309 | TagLib::MP4::ItemListMap allTags = mp4Tags->itemListMap(); | ||
318 | 310 | | |||
319 | /* | 311 | /* | ||
320 | * There is no standard regarding ratings. Mimic MediaMonkey's behavior | 312 | * There is no standard regarding ratings. Mimic MediaMonkey's behavior | ||
321 | * with a range of 0 to 100 (stored in steps of 10) and make it compatible | 313 | * with a range of 0 to 100 (stored in steps of 10) and make it compatible | ||
322 | * with baloo rating with a range from 0 to 10. | 314 | * with baloo rating with a range from 0 to 10. | ||
323 | */ | 315 | */ | ||
324 | TagLib::MP4::ItemListMap::Iterator itRating = allTags.find("rate"); | 316 | TagLib::MP4::ItemListMap::Iterator itRating = allTags.find("rate"); | ||
325 | if (itRating != allTags.end()) { | 317 | if (itRating != allTags.end()) { | ||
326 | result->add(Property::Rating, itRating->second.toStringList().toString().toInt() / 10); | 318 | result->add(Property::Rating, itRating->second.toStringList().toString().toInt() / 10); | ||
327 | } | 319 | } | ||
328 | } | 320 | } | ||
329 | 321 | | |||
330 | void TagLibExtractor::extractAsfTags(TagLib::ASF::Tag* asfTags, ExtractionResult* result) | 322 | void extractAsfTags(TagLib::ASF::Tag* asfTags, ExtractionResult* result) | ||
331 | { | 323 | { | ||
332 | if (asfTags->isEmpty()) { | 324 | if (asfTags->isEmpty()) { | ||
333 | return; | 325 | return; | ||
334 | } | 326 | } | ||
335 | 327 | | |||
336 | TagLib::ASF::AttributeList lstASF = asfTags->attribute("WM/SharedUserRating"); | 328 | TagLib::ASF::AttributeList lstASF = asfTags->attribute("WM/SharedUserRating"); | ||
337 | if (!lstASF.isEmpty()) { | 329 | if (!lstASF.isEmpty()) { | ||
338 | int rating = lstASF.front().toString().toInt(); | 330 | int rating = lstASF.front().toString().toInt(); | ||
Show All 30 Lines | |||||
369 | */ | 361 | */ | ||
370 | lstASF = asfTags->attribute("WM/Publisher"); | 362 | lstASF = asfTags->attribute("WM/Publisher"); | ||
371 | if (!lstASF.isEmpty()) { | 363 | if (!lstASF.isEmpty()) { | ||
372 | const auto attribute = lstASF.front(); | 364 | const auto attribute = lstASF.front(); | ||
373 | result->add(Property::Publisher, TStringToQString(attribute.toString()).trimmed()); | 365 | result->add(Property::Publisher, TStringToQString(attribute.toString()).trimmed()); | ||
374 | } | 366 | } | ||
375 | } | 367 | } | ||
376 | 368 | | |||
369 | } // anonymous namespace | ||||
370 | | ||||
371 | TagLibExtractor::TagLibExtractor(QObject* parent) | ||||
372 | : ExtractorPlugin(parent) | ||||
373 | { | ||||
374 | } | ||||
375 | | ||||
376 | QStringList TagLibExtractor::mimetypes() const | ||||
377 | { | ||||
378 | return supportedMimeTypes; | ||||
379 | } | ||||
380 | | ||||
377 | void TagLibExtractor::extract(ExtractionResult* result) | 381 | void TagLibExtractor::extract(ExtractionResult* result) | ||
378 | { | 382 | { | ||
379 | const QString fileUrl = result->inputUrl(); | 383 | const QString fileUrl = result->inputUrl(); | ||
380 | const QString mimeType = getSupportedMimeType(result->inputMimetype()); | 384 | const QString mimeType = getSupportedMimeType(result->inputMimetype()); | ||
381 | 385 | | |||
382 | // Open the file readonly. Important if we're sandboxed. | 386 | // Open the file readonly. Important if we're sandboxed. | ||
383 | TagLib::FileStream stream(fileUrl.toUtf8().constData(), true); | 387 | TagLib::FileStream stream(fileUrl.toUtf8().constData(), true); | ||
384 | if (!stream.isOpen()) { | 388 | if (!stream.isOpen()) { | ||
▲ Show 20 Lines • Show All 123 Lines • Show Last 20 Lines |
This puts readGenericProperties(...) with external linkage in the global namespace.
Put the private helpers in an anonymous namespace (and also include extractAudioProperties(...) in it).