diff --git a/CMakeLists.txt b/CMakeLists.txt index fada86a5e85124ce6b52bbdc88a6f8c9fd7d8dae..d170192eec1fbafcbd8b9063c857d85e26dcba1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,9 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") find_package(Wt REQUIRED) find_package(Groove REQUIRED) +find_package(TagLib REQUIRED) add_executable(arbitrateor src/main.cpp src/WebInterface.cpp src/GroovePlayer.cpp src/ui/LoginInterface.cpp src/ui/PlayerInterface.cpp) -target_link_libraries(arbitrateor ${Wt_LIBRARIES} ${GROOVE_LIBRARY} ${GROOVE_FINGERPRINT_LIBRARY} ${GROOVE_PLAYER_LIBRARY} pthread stdc++fs) #TODO get threading links based on platform. Remove gcc experimental fs when official c++17 exists. +target_link_libraries(arbitrateor ${Wt_LIBRARIES} ${GROOVE_LIBRARY} ${GROOVE_FINGERPRINT_LIBRARY} ${GROOVE_PLAYER_LIBRARY} ${TAGLIB_LIBRARY} pthread stdc++fs) #TODO get threading links based on platform. Remove gcc experimental fs when official c++17 exists. install(TARGETS arbitrateor RUNTIME DESTINATION bin) diff --git a/cmake/FindTagLib.cmake b/cmake/FindTagLib.cmake new file mode 100644 index 0000000000000000000000000000000000000000..d0fa28b008fc4233ca0039be8c97969485f9b1f1 --- /dev/null +++ b/cmake/FindTagLib.cmake @@ -0,0 +1,8 @@ +find_path(TAGLIB_INCLUDE_DIR NAMES taglib/id3v2tag.h) + +find_library(TAGLIB_LIBRARY NAMES tag) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(TAGLIB DEFAULT_MSG TAGLIB_LIBRARY TAGLIB_INCLUDE_DIR) + +mark_as_advanced(TAGLIB_INCLUDE_DIR TAGLIB_LIBRARY) diff --git a/src/GroovePlayer.cpp b/src/GroovePlayer.cpp index 7b548ad1b09d458ec78c7c55f0bab1e94d63844b..bddb0b17584bfc18ae61461ce1afcb51e71fc536 100644 --- a/src/GroovePlayer.cpp +++ b/src/GroovePlayer.cpp @@ -28,6 +28,10 @@ #include #include #include +#include +#include +#include +#include GroovePlayerMgr::GroovePlayerMgr (std::string dbFile) { @@ -412,6 +416,7 @@ bool GroovePlayerMgr::addFileToTrackDBIfTagged(Wt::Dbo::Session* session, std::f if(artist_tag == nullptr || album_tag == nullptr || name_tag == nullptr || genre_tag == nullptr) { //Only accept song with all metadata for DB. + Wt::log("info") << "Audio track " << file << " did not have all required tags."; groove_file_close(gfile); return false; } @@ -451,6 +456,16 @@ bool GroovePlayerMgr::addFileToTrackDBIfTagged(Wt::Dbo::Session* session, std::f newTrack->trackLengthSeconds = trackLen; newTrack->trackFingerprint = fingerprint; newTrack->trackPath = file.string(); + + //Quickly see if there is cover artist + getPictureFromTrack(newTrack); + if(newTrack->coverArt.size() == 0) + { + Wt::log("info") << "Audio track " << newTrack->trackPath << " did not have cover art in the file."; + groove_file_close(gfile); + return false; + } + session->add(newTrack); transaction.commit(); groove_file_close(gfile); @@ -473,6 +488,32 @@ void GroovePlayerMgr::removeOrphanedTracks(Wt::Dbo::Session* session) transaction.commit(); } +void GroovePlayerMgr::getPictureFromTrack(AudioTrack* trackToFill) +{ + if(trackToFill->trackPath != "") + { + TagLib::String file = TagLib::String(trackToFill->trackPath); + if(file.substr(file.size()-3).upper() == "MP3" && TagLib::MPEG::File(trackToFill->trackPath.c_str()).hasID3v2Tag()) + { + TagLib::MPEG::File file(trackToFill->trackPath.c_str()); + TagLib::ID3v2::Tag* tag = file.ID3v2Tag(); + if(!tag->frameListMap()["APIC"].isEmpty() && dynamic_cast(tag->frameListMap()["APIC"].front()) != nullptr) + { + TagLib::ID3v2::AttachedPictureFrame* pic = dynamic_cast(tag->frameListMap()["APIC"].front()); + trackToFill->coverArt = TagLib::ByteVector(pic->picture().data(),pic->picture().size()); + trackToFill->coverMimeType = std::string(pic->mimeType().toCString(true)); + } + } +// else if(dynamic_cast(tagTrack.tag()) != nullptr && !dynamic_cast(tagTrack.tag())->isEmpty()) +// { +// TagLib::Ogg::XiphComment* tag = dynamic_cast(tagTrack.tag()); +// if(tag->fieldListMap()["METADATA_BLOCK_PICTURE"].isEmpty()) +// { +// tag->fieldListMap()["METADATA_BLOCK_PICTURE"];//TODO? +// } +// } + } +} void GroovePlayerMgr::grooveAudioScannerLoop() @@ -497,7 +538,7 @@ void GroovePlayerMgr::grooveAudioScannerLoop() { extensionLowered.push_back(std::tolower(elem)); } - if(extensionLowered == ".mp3" || extensionLowered == ".ogg") //TODO:think about supporting more than mp3s and oggs. + if(extensionLowered == ".mp3") //TODO:think about supporting more than mp3s. { if(addFileToTrackDBIfTagged(&sqlSession, p.path())) { diff --git a/src/GroovePlayer.h b/src/GroovePlayer.h index ce05c213fa320670db2bdf4c71e5082352862ab4..f9eaef918b96af5bccda707525adcef8ab10438e 100644 --- a/src/GroovePlayer.h +++ b/src/GroovePlayer.h @@ -72,6 +72,7 @@ private: void removeOrphanedTracks(Wt::Dbo::Session* session); AudioTrack getCurrentTrack(Wt::Dbo::Session* session); + void getPictureFromTrack(AudioTrack* trackToFill); }; diff --git a/src/db/AudioTrack.h b/src/db/AudioTrack.h index 4a10aad11d21bf1322c4a542a9449afd5f8c6446..1e7384d8dd5c7b4cbf7164c5f40cad93ef8ca225 100644 --- a/src/db/AudioTrack.h +++ b/src/db/AudioTrack.h @@ -21,6 +21,7 @@ #define AUDIOTRACK_H #include +#include class AudioTrack { @@ -33,6 +34,10 @@ public: std::string trackFingerprint; std::string trackPath; + //Non-persisted data + TagLib::ByteVector coverArt; + std::string coverMimeType; + template void persist(Action& a) {