Compare commits
11 Commits
426de61525
...
e8be0adf37
Author | SHA1 | Date |
---|---|---|
Robert Gingras | e8be0adf37 | |
Robert Gingras | 9f4a82bb62 | |
Robert Gingras | 8d7e14f21d | |
Robert Gingras | d03d3622aa | |
Robert Gingras | 821c32992d | |
Robert Gingras | b52cf9f3cd | |
Robert Gingras | ab8e687f96 | |
Robert Gingras | 90703703aa | |
Jonas Kvinge | 176984afe0 | |
Jonas Kvinge | 542efa17ff | |
Jonas Kvinge | 6a2c2dbba1 |
|
@ -328,137 +328,8 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (TagLib::MPEG::File *file_mpeg = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
else if (TagLib::MPEG::File *file_mpeg = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||||
|
if (file_mpeg->hasID3v2Tag()) {
|
||||||
if (file_mpeg->ID3v2Tag()) {
|
ParseID3v2Tag(file_mpeg->ID3v2Tag(), &disc, &compilation, song);
|
||||||
const TagLib::ID3v2::FrameListMap &map = file_mpeg->ID3v2Tag()->frameListMap();
|
|
||||||
|
|
||||||
if (map.contains("TPOS")) disc = TStringToQString(map["TPOS"].front()->toString()).trimmed();
|
|
||||||
if (map.contains("TCOM")) TStringToStdString(map["TCOM"].front()->toString(), song->mutable_composer());
|
|
||||||
|
|
||||||
// content group
|
|
||||||
if (map.contains("TIT1")) TStringToStdString(map["TIT1"].front()->toString(), song->mutable_grouping());
|
|
||||||
|
|
||||||
// original artist/performer
|
|
||||||
if (map.contains("TOPE")) TStringToStdString(map["TOPE"].front()->toString(), song->mutable_performer());
|
|
||||||
|
|
||||||
// Skip TPE1 (which is the artist) here because we already fetched it
|
|
||||||
|
|
||||||
// non-standard: Apple, Microsoft
|
|
||||||
if (map.contains("TPE2")) TStringToStdString(map["TPE2"].front()->toString(), song->mutable_albumartist());
|
|
||||||
|
|
||||||
if (map.contains("TCMP")) compilation = TStringToQString(map["TCMP"].front()->toString()).trimmed();
|
|
||||||
|
|
||||||
if (map.contains("TDOR")) {
|
|
||||||
song->set_originalyear(map["TDOR"].front()->toString().substr(0, 4).toInt());
|
|
||||||
}
|
|
||||||
else if (map.contains("TORY")) {
|
|
||||||
song->set_originalyear(map["TORY"].front()->toString().substr(0, 4).toInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map.contains("USLT")) {
|
|
||||||
TStringToStdString(map["USLT"].front()->toString(), song->mutable_lyrics());
|
|
||||||
}
|
|
||||||
else if (map.contains("SYLT")) {
|
|
||||||
TStringToStdString(map["SYLT"].front()->toString(), song->mutable_lyrics());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map.contains("APIC")) song->set_art_embedded(true);
|
|
||||||
|
|
||||||
// Find a suitable comment tag. For now we ignore iTunNORM comments.
|
|
||||||
for (uint i = 0; i < map["COMM"].size(); ++i) {
|
|
||||||
const TagLib::ID3v2::CommentsFrame *frame = dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(map["COMM"][i]);
|
|
||||||
|
|
||||||
if (frame && TStringToQString(frame->description()) != QStringLiteral("iTunNORM")) {
|
|
||||||
TStringToStdString(frame->text(), song->mutable_comment());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_playcount = TagLib::ID3v2::UserTextIdentificationFrame::find(file_mpeg->ID3v2Tag(), "FMPS_Playcount")) {
|
|
||||||
TagLib::StringList frame_field_list = frame_fmps_playcount->fieldList();
|
|
||||||
if (frame_field_list.size() > 1) {
|
|
||||||
int playcount = TStringToQString(frame_field_list[1]).toInt();
|
|
||||||
if (song->playcount() <= 0 && playcount > 0) {
|
|
||||||
song->set_playcount(playcount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_rating = TagLib::ID3v2::UserTextIdentificationFrame::find(file_mpeg->ID3v2Tag(), "FMPS_Rating")) {
|
|
||||||
TagLib::StringList frame_field_list = frame_fmps_rating->fieldList();
|
|
||||||
if (frame_field_list.size() > 1) {
|
|
||||||
float rating = TStringToQString(frame_field_list[1]).toFloat();
|
|
||||||
if (song->rating() <= 0 && rating > 0 && rating <= 1.0) {
|
|
||||||
song->set_rating(rating);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map.contains("POPM")) {
|
|
||||||
const TagLib::ID3v2::PopularimeterFrame *frame = dynamic_cast<const TagLib::ID3v2::PopularimeterFrame*>(map["POPM"].front());
|
|
||||||
if (frame) {
|
|
||||||
if (song->playcount() <= 0 && frame->counter() > 0) {
|
|
||||||
song->set_playcount(frame->counter());
|
|
||||||
}
|
|
||||||
if (song->rating() <= 0 && frame->rating() > 0) {
|
|
||||||
song->set_rating(ConvertPOPMRating(frame->rating()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map.contains("UFID")) {
|
|
||||||
for (uint i = 0; i < map["UFID"].size(); ++i) {
|
|
||||||
if (TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast<TagLib::ID3v2::UniqueFileIdentifierFrame*>(map["UFID"][i])) {
|
|
||||||
const TagLib::PropertyMap property_map = frame->asProperties();
|
|
||||||
if (property_map.contains(kID3v2_MusicBrainz_RecordingID)) {
|
|
||||||
TStringToStdString(property_map[kID3v2_MusicBrainz_RecordingID].toString(), song->mutable_musicbrainz_recording_id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map.contains("TXXX")) {
|
|
||||||
for (uint i = 0; i < map["TXXX"].size(); ++i) {
|
|
||||||
if (TagLib::ID3v2::UserTextIdentificationFrame *frame = dynamic_cast<TagLib::ID3v2::UserTextIdentificationFrame*>(map["TXXX"][i])) {
|
|
||||||
const TagLib::StringList frame_field_list = frame->fieldList();
|
|
||||||
if (frame_field_list.size() != 2) continue;
|
|
||||||
if (frame->description() == kID3v2_AcoustID_ID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_id());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_AcoustID_Fingerprint) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_fingerprint());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_MusicBrainz_AlbumArtistID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_artist_id());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_MusicBrainz_ArtistID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_artist_id());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_MusicBrainz_OriginalArtistID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_artist_id());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_MusicBrainz_AlbumID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_id());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_MusicBrainz_OriginalAlbumID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_album_id());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_MusicBrainz_TrackID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_track_id());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_MusicBrainz_DiscID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_disc_id());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_MusicBrainz_ReleaseGroupID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_release_group_id());
|
|
||||||
}
|
|
||||||
if (frame->description() == kID3v2_MusicBrainz_WorkID) {
|
|
||||||
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_work_id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,6 +529,12 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
||||||
if (tag) TStringToStdString(tag->comment(), song->mutable_comment());
|
if (tag) TStringToStdString(tag->comment(), song->mutable_comment());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (TagLib::RIFF::WAV::File *file_wav = dynamic_cast<TagLib::RIFF::WAV::File*>(fileref->file())) {
|
||||||
|
if (file_wav->hasID3v2Tag()) {
|
||||||
|
ParseID3v2Tag(file_wav->ID3v2Tag(), &disc, &compilation, song);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else if (tag) {
|
else if (tag) {
|
||||||
TStringToStdString(tag->comment(), song->mutable_comment());
|
TStringToStdString(tag->comment(), song->mutable_comment());
|
||||||
}
|
}
|
||||||
|
@ -710,6 +587,139 @@ void TagReaderTagLib::TStringToStdString(const TagLib::String &tag, std::string
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TagReaderTagLib::ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const {
|
||||||
|
|
||||||
|
TagLib::ID3v2::FrameListMap map = tag->frameListMap();
|
||||||
|
|
||||||
|
if (map.contains("TPOS")) *disc = TStringToQString(map["TPOS"].front()->toString()).trimmed();
|
||||||
|
if (map.contains("TCOM")) TStringToStdString(map["TCOM"].front()->toString(), song->mutable_composer());
|
||||||
|
|
||||||
|
// content group
|
||||||
|
if (map.contains("TIT1")) TStringToStdString(map["TIT1"].front()->toString(), song->mutable_grouping());
|
||||||
|
|
||||||
|
// original artist/performer
|
||||||
|
if (map.contains("TOPE")) TStringToStdString(map["TOPE"].front()->toString(), song->mutable_performer());
|
||||||
|
|
||||||
|
// Skip TPE1 (which is the artist) here because we already fetched it
|
||||||
|
|
||||||
|
// non-standard: Apple, Microsoft
|
||||||
|
if (map.contains("TPE2")) TStringToStdString(map["TPE2"].front()->toString(), song->mutable_albumartist());
|
||||||
|
|
||||||
|
if (map.contains("TCMP")) *compilation = TStringToQString(map["TCMP"].front()->toString()).trimmed();
|
||||||
|
|
||||||
|
if (map.contains("TDOR")) {
|
||||||
|
song->set_originalyear(map["TDOR"].front()->toString().substr(0, 4).toInt());
|
||||||
|
}
|
||||||
|
else if (map.contains("TORY")) {
|
||||||
|
song->set_originalyear(map["TORY"].front()->toString().substr(0, 4).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map.contains("USLT")) {
|
||||||
|
TStringToStdString(map["USLT"].front()->toString(), song->mutable_lyrics());
|
||||||
|
}
|
||||||
|
else if (map.contains("SYLT")) {
|
||||||
|
TStringToStdString(map["SYLT"].front()->toString(), song->mutable_lyrics());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map.contains("APIC")) song->set_art_embedded(true);
|
||||||
|
|
||||||
|
// Find a suitable comment tag. For now we ignore iTunNORM comments.
|
||||||
|
for (uint i = 0; i < map["COMM"].size(); ++i) {
|
||||||
|
const TagLib::ID3v2::CommentsFrame *frame = dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(map["COMM"][i]);
|
||||||
|
|
||||||
|
if (frame && TStringToQString(frame->description()) != QStringLiteral("iTunNORM")) {
|
||||||
|
TStringToStdString(frame->text(), song->mutable_comment());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_playcount = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, "FMPS_Playcount")) {
|
||||||
|
TagLib::StringList frame_field_list = frame_fmps_playcount->fieldList();
|
||||||
|
if (frame_field_list.size() > 1) {
|
||||||
|
int playcount = TStringToQString(frame_field_list[1]).toInt();
|
||||||
|
if (song->playcount() <= 0 && playcount > 0) {
|
||||||
|
song->set_playcount(playcount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TagLib::ID3v2::UserTextIdentificationFrame *frame_fmps_rating = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, "FMPS_Rating")) {
|
||||||
|
TagLib::StringList frame_field_list = frame_fmps_rating->fieldList();
|
||||||
|
if (frame_field_list.size() > 1) {
|
||||||
|
float rating = TStringToQString(frame_field_list[1]).toFloat();
|
||||||
|
if (song->rating() <= 0 && rating > 0 && rating <= 1.0) {
|
||||||
|
song->set_rating(rating);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map.contains("POPM")) {
|
||||||
|
const TagLib::ID3v2::PopularimeterFrame *frame = dynamic_cast<const TagLib::ID3v2::PopularimeterFrame*>(map["POPM"].front());
|
||||||
|
if (frame) {
|
||||||
|
if (song->playcount() <= 0 && frame->counter() > 0) {
|
||||||
|
song->set_playcount(frame->counter());
|
||||||
|
}
|
||||||
|
if (song->rating() <= 0 && frame->rating() > 0) {
|
||||||
|
song->set_rating(ConvertPOPMRating(frame->rating()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map.contains("UFID")) {
|
||||||
|
for (uint i = 0; i < map["UFID"].size(); ++i) {
|
||||||
|
if (TagLib::ID3v2::UniqueFileIdentifierFrame *frame = dynamic_cast<TagLib::ID3v2::UniqueFileIdentifierFrame*>(map["UFID"][i])) {
|
||||||
|
const TagLib::PropertyMap property_map = frame->asProperties();
|
||||||
|
if (property_map.contains(kID3v2_MusicBrainz_RecordingID)) {
|
||||||
|
TStringToStdString(property_map[kID3v2_MusicBrainz_RecordingID].toString(), song->mutable_musicbrainz_recording_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map.contains("TXXX")) {
|
||||||
|
for (uint i = 0; i < map["TXXX"].size(); ++i) {
|
||||||
|
if (TagLib::ID3v2::UserTextIdentificationFrame *frame = dynamic_cast<TagLib::ID3v2::UserTextIdentificationFrame*>(map["TXXX"][i])) {
|
||||||
|
const TagLib::StringList frame_field_list = frame->fieldList();
|
||||||
|
if (frame_field_list.size() != 2) continue;
|
||||||
|
if (frame->description() == kID3v2_AcoustID_ID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_id());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_AcoustID_Fingerprint) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_acoustid_fingerprint());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_MusicBrainz_AlbumArtistID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_artist_id());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_MusicBrainz_ArtistID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_artist_id());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_MusicBrainz_OriginalArtistID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_artist_id());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_MusicBrainz_AlbumID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_album_id());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_MusicBrainz_OriginalAlbumID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_original_album_id());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_MusicBrainz_TrackID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_track_id());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_MusicBrainz_DiscID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_disc_id());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_MusicBrainz_ReleaseGroupID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_release_group_id());
|
||||||
|
}
|
||||||
|
if (frame->description() == kID3v2_MusicBrainz_WorkID) {
|
||||||
|
TStringToStdString(frame_field_list.back(), song->mutable_musicbrainz_work_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void TagReaderTagLib::ParseOggTag(const TagLib::Ogg::FieldListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const {
|
void TagReaderTagLib::ParseOggTag(const TagLib::Ogg::FieldListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const {
|
||||||
|
|
||||||
if (map.contains("COMPOSER")) TStringToStdString(map["COMPOSER"].front(), song->mutable_composer());
|
if (map.contains("COMPOSER")) TStringToStdString(map["COMPOSER"].front(), song->mutable_composer());
|
||||||
|
@ -943,14 +953,7 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
||||||
TagLib::ID3v2::Tag *tag = file_mpeg->ID3v2Tag(true);
|
TagLib::ID3v2::Tag *tag = file_mpeg->ID3v2Tag(true);
|
||||||
if (!tag) return false;
|
if (!tag) return false;
|
||||||
if (save_tags) {
|
if (save_tags) {
|
||||||
SetTextFrame("TPOS", song.disc() <= 0 ? QString() : QString::number(song.disc()), tag);
|
SaveID3v2Tag(tag, song);
|
||||||
SetTextFrame("TCOM", song.composer().empty() ? std::string() : song.composer(), tag);
|
|
||||||
SetTextFrame("TIT1", song.grouping().empty() ? std::string() : song.grouping(), tag);
|
|
||||||
SetTextFrame("TOPE", song.performer().empty() ? std::string() : song.performer(), tag);
|
|
||||||
// Skip TPE1 (which is the artist) here because we already set it
|
|
||||||
SetTextFrame("TPE2", song.albumartist().empty() ? std::string() : song.albumartist(), tag);
|
|
||||||
SetTextFrame("TCMP", song.compilation() ? QString::number(1) : QString(), tag);
|
|
||||||
SetUnsyncLyricsFrame(song.lyrics().empty() ? std::string() : song.lyrics(), tag);
|
|
||||||
}
|
}
|
||||||
if (save_playcount) {
|
if (save_playcount) {
|
||||||
SetPlaycount(tag, song);
|
SetPlaycount(tag, song);
|
||||||
|
@ -959,7 +962,7 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
||||||
SetRating(tag, song);
|
SetRating(tag, song);
|
||||||
}
|
}
|
||||||
if (save_cover) {
|
if (save_cover) {
|
||||||
SetEmbeddedArt(file_mpeg, tag, cover.data, cover.mime_type);
|
SetEmbeddedArt(tag, cover.data, cover.mime_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,6 +988,22 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (TagLib::RIFF::WAV::File *file_wav = dynamic_cast<TagLib::RIFF::WAV::File*>(fileref->file())) {
|
||||||
|
TagLib::ID3v2::Tag *tag = file_wav->ID3v2Tag();
|
||||||
|
if (save_tags) {
|
||||||
|
SaveID3v2Tag(tag, song);
|
||||||
|
}
|
||||||
|
if (save_playcount) {
|
||||||
|
SetPlaycount(tag, song);
|
||||||
|
}
|
||||||
|
if (save_rating) {
|
||||||
|
SetRating(tag, song);
|
||||||
|
}
|
||||||
|
if (save_cover) {
|
||||||
|
SetEmbeddedArt(tag, cover.data, cover.mime_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same way;
|
// Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same way;
|
||||||
// apart, so we keep specific behavior for some formats by adding another "else if" block above.
|
// apart, so we keep specific behavior for some formats by adding another "else if" block above.
|
||||||
if (!is_flac) {
|
if (!is_flac) {
|
||||||
|
@ -1016,6 +1035,19 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TagReaderTagLib::SaveID3v2Tag(TagLib::ID3v2::Tag *tag, const spb::tagreader::SongMetadata &song) const {
|
||||||
|
|
||||||
|
SetTextFrame("TPOS", song.disc() <= 0 ? QString() : QString::number(song.disc()), tag);
|
||||||
|
SetTextFrame("TCOM", song.composer().empty() ? std::string() : song.composer(), tag);
|
||||||
|
SetTextFrame("TIT1", song.grouping().empty() ? std::string() : song.grouping(), tag);
|
||||||
|
SetTextFrame("TOPE", song.performer().empty() ? std::string() : song.performer(), tag);
|
||||||
|
// Skip TPE1 (which is the artist) here because we already set it
|
||||||
|
SetTextFrame("TPE2", song.albumartist().empty() ? std::string() : song.albumartist(), tag);
|
||||||
|
SetTextFrame("TCMP", song.compilation() ? QString::number(1) : QString(), tag);
|
||||||
|
SetUnsyncLyricsFrame(song.lyrics().empty() ? std::string() : song.lyrics(), tag);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void TagReaderTagLib::SaveAPETag(TagLib::APE::Tag *tag, const spb::tagreader::SongMetadata &song) const {
|
void TagReaderTagLib::SaveAPETag(TagLib::APE::Tag *tag, const spb::tagreader::SongMetadata &song) const {
|
||||||
|
|
||||||
tag->setItem("album artist", TagLib::APE::Item("album artist", TagLib::StringList(song.albumartist().c_str())));
|
tag->setItem("album artist", TagLib::APE::Item("album artist", TagLib::StringList(song.albumartist().c_str())));
|
||||||
|
@ -1278,9 +1310,7 @@ void TagReaderTagLib::SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, con
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::MPEG::File *file_mp3, TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const {
|
void TagReaderTagLib::SetEmbeddedArt(TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const {
|
||||||
|
|
||||||
(void)file_mp3;
|
|
||||||
|
|
||||||
// Remove existing covers
|
// Remove existing covers
|
||||||
TagLib::ID3v2::FrameList apiclist = tag->frameListMap()["APIC"];
|
TagLib::ID3v2::FrameList apiclist = tag->frameListMap()["APIC"];
|
||||||
|
@ -1360,7 +1390,7 @@ bool TagReaderTagLib::SaveEmbeddedArt(const spb::tagreader::SaveEmbeddedArtReque
|
||||||
else if (TagLib::MPEG::File *file_mp3 = dynamic_cast<TagLib::MPEG::File*>(fileref.file())) {
|
else if (TagLib::MPEG::File *file_mp3 = dynamic_cast<TagLib::MPEG::File*>(fileref.file())) {
|
||||||
TagLib::ID3v2::Tag *tag = file_mp3->ID3v2Tag();
|
TagLib::ID3v2::Tag *tag = file_mp3->ID3v2Tag();
|
||||||
if (!tag) return false;
|
if (!tag) return false;
|
||||||
SetEmbeddedArt(file_mp3, tag, cover.data, cover.mime_type);
|
SetEmbeddedArt(tag, cover.data, cover.mime_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MP4/AAC
|
// MP4/AAC
|
||||||
|
|
|
@ -68,10 +68,12 @@ class TagReaderTagLib : public TagReaderBase {
|
||||||
private:
|
private:
|
||||||
spb::tagreader::SongMetadata_FileType GuessFileType(TagLib::FileRef *fileref) const;
|
spb::tagreader::SongMetadata_FileType GuessFileType(TagLib::FileRef *fileref) const;
|
||||||
|
|
||||||
|
void ParseID3v2Tag(TagLib::ID3v2::Tag *tag, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const;
|
||||||
void ParseOggTag(const TagLib::Ogg::FieldListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const;
|
void ParseOggTag(const TagLib::Ogg::FieldListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const;
|
||||||
void ParseAPETag(const TagLib::APE::ItemListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const;
|
void ParseAPETag(const TagLib::APE::ItemListMap &map, QString *disc, QString *compilation, spb::tagreader::SongMetadata *song) const;
|
||||||
|
|
||||||
void SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comment, const spb::tagreader::SongMetadata &song) const;
|
void SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comment, const spb::tagreader::SongMetadata &song) const;
|
||||||
|
void SaveID3v2Tag(TagLib::ID3v2::Tag *tag, const spb::tagreader::SongMetadata &song) const;
|
||||||
void SaveAPETag(TagLib::APE::Tag *tag, const spb::tagreader::SongMetadata &song) const;
|
void SaveAPETag(TagLib::APE::Tag *tag, const spb::tagreader::SongMetadata &song) const;
|
||||||
|
|
||||||
void SetTextFrame(const char *id, const QString &value, TagLib::ID3v2::Tag *tag) const;
|
void SetTextFrame(const char *id, const QString &value, TagLib::ID3v2::Tag *tag) const;
|
||||||
|
@ -98,7 +100,7 @@ class TagReaderTagLib : public TagReaderBase {
|
||||||
|
|
||||||
void SetEmbeddedArt(TagLib::FLAC::File *flac_file, TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const;
|
void SetEmbeddedArt(TagLib::FLAC::File *flac_file, TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const;
|
||||||
void SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const;
|
void SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const;
|
||||||
void SetEmbeddedArt(TagLib::MPEG::File *file_mp3, TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const;
|
void SetEmbeddedArt(TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const;
|
||||||
void SetEmbeddedArt(TagLib::MP4::File *aac_file, TagLib::MP4::Tag *tag, const QByteArray &data, const QString &mime_type) const;
|
void SetEmbeddedArt(TagLib::MP4::File *aac_file, TagLib::MP4::Tag *tag, const QByteArray &data, const QString &mime_type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -570,7 +570,8 @@ bool Song::write_tags_supported() const {
|
||||||
d->filetype_ == FileType::TrueAudio ||
|
d->filetype_ == FileType::TrueAudio ||
|
||||||
d->filetype_ == FileType::APE ||
|
d->filetype_ == FileType::APE ||
|
||||||
d->filetype_ == FileType::DSF ||
|
d->filetype_ == FileType::DSF ||
|
||||||
d->filetype_ == FileType::DSDIFF;
|
d->filetype_ == FileType::DSDIFF ||
|
||||||
|
d->filetype_ == FileType::WAV;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,7 +586,8 @@ bool Song::additional_tags_supported() const {
|
||||||
d->filetype_ == FileType::MPEG ||
|
d->filetype_ == FileType::MPEG ||
|
||||||
d->filetype_ == FileType::MP4 ||
|
d->filetype_ == FileType::MP4 ||
|
||||||
d->filetype_ == FileType::MPC ||
|
d->filetype_ == FileType::MPC ||
|
||||||
d->filetype_ == FileType::APE;
|
d->filetype_ == FileType::APE ||
|
||||||
|
d->filetype_ == FileType::WAV;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,7 +609,8 @@ bool Song::performer_supported() const {
|
||||||
d->filetype_ == FileType::OggSpeex ||
|
d->filetype_ == FileType::OggSpeex ||
|
||||||
d->filetype_ == FileType::MPEG ||
|
d->filetype_ == FileType::MPEG ||
|
||||||
d->filetype_ == FileType::MPC ||
|
d->filetype_ == FileType::MPC ||
|
||||||
d->filetype_ == FileType::APE;
|
d->filetype_ == FileType::APE ||
|
||||||
|
d->filetype_ == FileType::WAV;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1400,7 +1403,7 @@ void Song::InitFromQuery(const QSqlRecord &r, const bool reliable_metadata, cons
|
||||||
d->album_id_ = SqlHelper::ValueToString(r, ColumnIndex(QStringLiteral("album_id")) + col);
|
d->album_id_ = SqlHelper::ValueToString(r, ColumnIndex(QStringLiteral("album_id")) + col);
|
||||||
d->song_id_ = SqlHelper::ValueToString(r, ColumnIndex(QStringLiteral("song_id")) + col);
|
d->song_id_ = SqlHelper::ValueToString(r, ColumnIndex(QStringLiteral("song_id")) + col);
|
||||||
d->beginning_ = r.value(ColumnIndex(QStringLiteral("beginning")) + col).isNull() ? 0 : r.value(ColumnIndex(QStringLiteral("beginning")) + col).toLongLong();
|
d->beginning_ = r.value(ColumnIndex(QStringLiteral("beginning")) + col).isNull() ? 0 : r.value(ColumnIndex(QStringLiteral("beginning")) + col).toLongLong();
|
||||||
set_length_nanosec(SqlHelper::ValueToLongLong(r, ColumnIndex(QStringLiteral("length"))) + col);
|
set_length_nanosec(SqlHelper::ValueToLongLong(r, ColumnIndex(QStringLiteral("length")) + col));
|
||||||
d->bitrate_ = SqlHelper::ValueToInt(r, ColumnIndex(QStringLiteral("bitrate")) + col);
|
d->bitrate_ = SqlHelper::ValueToInt(r, ColumnIndex(QStringLiteral("bitrate")) + col);
|
||||||
d->samplerate_ = SqlHelper::ValueToInt(r, ColumnIndex(QStringLiteral("samplerate")) + col);
|
d->samplerate_ = SqlHelper::ValueToInt(r, ColumnIndex(QStringLiteral("samplerate")) + col);
|
||||||
d->bitdepth_ = SqlHelper::ValueToInt(r, ColumnIndex(QStringLiteral("bitdepth")) + col);
|
d->bitdepth_ = SqlHelper::ValueToInt(r, ColumnIndex(QStringLiteral("bitdepth")) + col);
|
||||||
|
|
|
@ -48,7 +48,7 @@ InternetPlaylistItem::InternetPlaylistItem(InternetServicePtr service, const Son
|
||||||
|
|
||||||
bool InternetPlaylistItem::InitFromQuery(const SqlRow &query) {
|
bool InternetPlaylistItem::InitFromQuery(const SqlRow &query) {
|
||||||
|
|
||||||
metadata_.InitFromQuery(query, false, static_cast<int>(Song::kRowIdColumns.count()) * 3);
|
metadata_.InitFromQuery(query, false, static_cast<int>(Song::kRowIdColumns.count()));
|
||||||
InitMetadata();
|
InitMetadata();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ SongPlaylistItem::SongPlaylistItem(const Song::Source source) : PlaylistItem(sou
|
||||||
SongPlaylistItem::SongPlaylistItem(const Song &song) : PlaylistItem(song.source()), song_(song) {}
|
SongPlaylistItem::SongPlaylistItem(const Song &song) : PlaylistItem(song.source()), song_(song) {}
|
||||||
|
|
||||||
bool SongPlaylistItem::InitFromQuery(const SqlRow &query) {
|
bool SongPlaylistItem::InitFromQuery(const SqlRow &query) {
|
||||||
song_.InitFromQuery(query, false, static_cast<int>(Song::kRowIdColumns.count()) * 3);
|
song_.InitFromQuery(query, false, static_cast<int>(Song::kRowIdColumns.count()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ RadioPlaylistItem::RadioPlaylistItem(const Song &metadata)
|
||||||
|
|
||||||
bool RadioPlaylistItem::InitFromQuery(const SqlRow &query) {
|
bool RadioPlaylistItem::InitFromQuery(const SqlRow &query) {
|
||||||
|
|
||||||
metadata_.InitFromQuery(query, false);
|
metadata_.InitFromQuery(query, false, static_cast<int>(Song::kRowIdColumns.count()));
|
||||||
InitMetadata();
|
InitMetadata();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue