[METADATA] TagLib support for embedded MP3 covers
This commit is contained in:
@@ -20,6 +20,8 @@
|
|||||||
#include <taglib/fileref.h>
|
#include <taglib/fileref.h>
|
||||||
#include <taglib/tag.h>
|
#include <taglib/tag.h>
|
||||||
#include <taglib/tpropertymap.h>
|
#include <taglib/tpropertymap.h>
|
||||||
|
#include <taglib/mpegfile.h>
|
||||||
|
#include <taglib/id3v2tag.h>
|
||||||
|
|
||||||
#include "logger/Logger.hpp"
|
#include "logger/Logger.hpp"
|
||||||
#include "utils/Utils.hpp"
|
#include "utils/Utils.hpp"
|
||||||
@@ -50,10 +52,22 @@ TagLibParser::parse(const boost::filesystem::path& p, Items& items)
|
|||||||
|
|
||||||
items.insert( std::make_pair(MetaData::Type::Duration, duration) );
|
items.insert( std::make_pair(MetaData::Type::Duration, duration) );
|
||||||
|
|
||||||
MetaData::AudioStream audioStream = { .desc = "", .bitRate = static_cast<std::size_t>(properties->bitrate()) };
|
MetaData::AudioStream audioStream = { .desc = "", .bitRate = static_cast<std::size_t>(properties->bitrate() * 1000) };
|
||||||
items.insert( std::make_pair(MetaData::Type::AudioStreams, std::vector<MetaData::AudioStream>(1, audioStream ) ));
|
items.insert( std::make_pair(MetaData::Type::AudioStreams, std::vector<MetaData::AudioStream>(1, audioStream ) ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not that good embedded pictures handling
|
||||||
|
|
||||||
|
// MP3
|
||||||
|
if (TagLib::MPEG::File *mp3File = dynamic_cast<TagLib::MPEG::File*>(f.file()))
|
||||||
|
{
|
||||||
|
if (mp3File->ID3v2Tag())
|
||||||
|
{
|
||||||
|
if (!mp3File->ID3v2Tag()->frameListMap()["APIC"].isEmpty())
|
||||||
|
items.insert( std::make_pair(MetaData::Type::HasCover, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (f.tag())
|
if (f.tag())
|
||||||
{
|
{
|
||||||
TagLib::PropertyMap tags = f.file()->properties();
|
TagLib::PropertyMap tags = f.file()->properties();
|
||||||
|
|||||||
+3
-2
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
TESTS = database-basics database-integrity sql-query database-user
|
TESTS = sql-query database-user
|
||||||
|
|
||||||
check_PROGRAMS = database-basics database-integrity sql-query database-user test-wt test-avmetadata
|
check_PROGRAMS = sql-query database-user test-wt test-avmetadata
|
||||||
|
|
||||||
database_basics_SOURCES = \
|
database_basics_SOURCES = \
|
||||||
$(srcdir)/CheckDbBasics.cpp \
|
$(srcdir)/CheckDbBasics.cpp \
|
||||||
@@ -91,6 +91,7 @@ test_avmetadata_SOURCES = TestAvMetadata.cpp \
|
|||||||
$(top_srcdir)/src/logger/Logger.cpp \
|
$(top_srcdir)/src/logger/Logger.cpp \
|
||||||
$(top_srcdir)/src/utils/Utils.cpp \
|
$(top_srcdir)/src/utils/Utils.cpp \
|
||||||
$(top_srcdir)/src/metadata/AvFormat.cpp \
|
$(top_srcdir)/src/metadata/AvFormat.cpp \
|
||||||
|
$(top_srcdir)/src/metadata/TagLibParser.cpp \
|
||||||
$(top_srcdir)/src/av/AvInfo.cpp
|
$(top_srcdir)/src/av/AvInfo.cpp
|
||||||
|
|
||||||
test_avmetadata_CXXFLAGS=-std=c++11 -Wall -Wextra -I$(top_srcdir)/src
|
test_avmetadata_CXXFLAGS=-std=c++11 -Wall -Wextra -I$(top_srcdir)/src
|
||||||
|
|||||||
+61
-3
@@ -1,10 +1,14 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <boost/date_time/time_duration.hpp>
|
||||||
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "av/AvInfo.hpp"
|
#include "av/AvInfo.hpp"
|
||||||
#include "metadata/AvFormat.hpp"
|
#include "metadata/AvFormat.hpp"
|
||||||
|
#include "metadata/TagLibParser.hpp"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -18,19 +22,49 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
Av::AvInit();
|
Av::AvInit();
|
||||||
|
|
||||||
MetaData::AvFormat parser;
|
|
||||||
|
MetaData::AvFormat avFormatParser;
|
||||||
|
MetaData::TagLibParser tagLibParser;
|
||||||
|
|
||||||
|
std::vector<MetaData::Parser*> parsers = { &avFormatParser, &tagLibParser };
|
||||||
|
|
||||||
|
for (auto& parser : parsers)
|
||||||
|
{
|
||||||
MetaData::Items items;
|
MetaData::Items items;
|
||||||
|
|
||||||
if (!parser.parse(argv[1], items))
|
if (!parser->parse(argv[1], items))
|
||||||
{
|
{
|
||||||
std::cout << "Parsing failed" << std::endl;
|
std::cout << "Parsing failed" << std::endl;
|
||||||
return EXIT_FAILURE;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "Items:" << std::endl;
|
||||||
for (auto item : items)
|
for (auto item : items)
|
||||||
{
|
{
|
||||||
switch (item.first)
|
switch (item.first)
|
||||||
{
|
{
|
||||||
|
case MetaData::Type::Title:
|
||||||
|
std::cout << "Title: " << boost::any_cast<std::string>(item.second) << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MetaData::Type::Artist:
|
||||||
|
std::cout << "Artist: " << boost::any_cast<std::string>(item.second) << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MetaData::Type::Album:
|
||||||
|
std::cout << "Album: " << boost::any_cast<std::string>(item.second) << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MetaData::Type::Genres:
|
||||||
|
for (auto& genre : boost::any_cast<std::list<std::string> >(item.second))
|
||||||
|
std::cout << "Genre: " << genre << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MetaData::Type::Duration:
|
||||||
|
std::cout << "Duration: " << boost::posix_time::to_simple_string(boost::any_cast<boost::posix_time::time_duration>(item.second)) << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case MetaData::Type::TrackNumber:
|
case MetaData::Type::TrackNumber:
|
||||||
std::cout << "Track: " << boost::any_cast<std::size_t>(item.second) << std::endl;
|
std::cout << "Track: " << boost::any_cast<std::size_t>(item.second) << std::endl;
|
||||||
break;
|
break;
|
||||||
@@ -45,12 +79,36 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
case MetaData::Type::TotalDisc:
|
case MetaData::Type::TotalDisc:
|
||||||
std::cout << "TotalDisc: " << boost::any_cast<std::size_t>(item.second) << std::endl;
|
std::cout << "TotalDisc: " << boost::any_cast<std::size_t>(item.second) << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MetaData::Type::Date:
|
||||||
|
std::cout << "Date: " << boost::posix_time::to_simple_string(boost::any_cast<boost::posix_time::ptime>(item.second)) << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MetaData::Type::OriginalDate:
|
||||||
|
std::cout << "Original date: " << boost::posix_time::to_simple_string(boost::any_cast<boost::posix_time::ptime>(item.second)) << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MetaData::Type::HasCover:
|
||||||
|
std::cout << "HasCover = " << std::boolalpha << boost::any_cast<bool>(item.second) << std::endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MetaData::Type::AudioStreams:
|
||||||
|
{
|
||||||
|
for (auto& audioStream : boost::any_cast<std::vector<MetaData::AudioStream> >(item.second))
|
||||||
|
std::cout << "Audio stream '" << audioStream.desc << "' - " << audioStream.bitRate << " bps" << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
|||||||
Reference in New Issue
Block a user