1 /* TaggingLyrics.cpp */
2 
3 /* Copyright (C) 2011-2020 Michael Lugmair (Lucio Carreras)
4  *
5  * This file is part of sayonara player
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11 
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16 
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "TaggingLyrics.h"
22 
23 #include "Tagging.h"
24 #include "Tagging/ID3v2/Lyrics.h"
25 #include "Tagging/Xiph/LyricsFrame.h"
26 
27 #include "Utils/MetaData/MetaData.h"
28 #include "Utils/Logger/Logger.h"
29 
30 #include <QString>
31 
32 #include <taglib/fileref.h>
33 
34 namespace
35 {
36 	QString readLyricsFromId3(const Tagging::ParsedTag& parsedTag)
37 	{
38 		QString lyrics;
39 
40 		auto* id3v2 = parsedTag.id3Tag();
41 		const auto lyricsFrame = ID3v2::LyricsFrame(id3v2);
42 
43 		if(lyricsFrame.isFrameAvailable())
44 		{
45 			lyricsFrame.read(lyrics);
46 		}
47 
48 		return lyrics;
49 	}
50 
51 	QString readLyricsFromXiph(const Tagging::ParsedTag& parsedTag)
52 	{
53 		QString lyrics;
54 
55 		auto* xiph = parsedTag.xiphTag();
56 		const auto lyricsFrame = Xiph::LyricsFrame(xiph);
57 		lyricsFrame.read(lyrics);
58 
59 		return lyrics;
60 	}
61 
62 	bool writeLyricsToId3(const Tagging::ParsedTag& parsedTag, const QString& lyrics)
63 	{
64 		auto* id3v2 = parsedTag.id3Tag();
65 		auto lyricsFrame = ID3v2::LyricsFrame(id3v2);
66 
67 		return lyricsFrame.write(lyrics);
68 	}
69 
70 	bool writeLyricsToXiph(const Tagging::ParsedTag& parsedTag, const QString& lyrics)
71 	{
72 		auto* xiph = parsedTag.xiphTag();
73 		auto lyricsFrame = Xiph::LyricsFrame(xiph);
74 
75 		return lyricsFrame.write(lyrics);
76 	}
77 }
78 
79 bool Tagging::writeLyrics(const MetaData& track, const QString& lyricsData)
80 {
81 	auto fileRef = TagLib::FileRef(TagLib::FileName(track.filepath().toUtf8()));
82 	if(!Tagging::isValidFile(fileRef))
83 	{
84 		spLog(Log::Warning, "Tagging") << "Cannot open tags for " << track.filepath();
85 		return false;
86 	}
87 
88 	auto success = false;
89 
90 	const auto parsedTag = Tagging::getParsedTagFromFileRef(fileRef);
91 	if((parsedTag.type == Tagging::TagType::ID3v2) && parsedTag.id3Tag())
92 	{
93 		success = writeLyricsToId3(parsedTag, lyricsData);
94 	}
95 
96 	else if((parsedTag.type == Tagging::TagType::Xiph) && parsedTag.xiphTag())
97 	{
98 		success = writeLyricsToXiph(parsedTag, lyricsData);
99 	}
100 
101 	return (success)
102 	       ? fileRef.save()
103 	       : false;
104 }
105 
106 bool Tagging::extractLyrics(const MetaData& track, QString& lyricsData)
107 {
108 	lyricsData.clear();
109 
110 	const auto fileRef = TagLib::FileRef(TagLib::FileName(track.filepath().toUtf8()));
111 	if(!Tagging::isValidFile(fileRef))
112 	{
113 		spLog(Log::Warning, "Tagging") << "Cannot open tags for " << track.filepath();
114 		return false;
115 	}
116 
117 	const auto parsedTag = Tagging::getParsedTagFromFileRef(fileRef);
118 
119 	if((parsedTag.type == Tagging::TagType::ID3v2) && parsedTag.id3Tag())
120 	{
121 		lyricsData = readLyricsFromId3(parsedTag);
122 	}
123 
124 	else if((parsedTag.type == Tagging::TagType::Xiph) && parsedTag.xiphTag())
125 	{
126 		lyricsData = readLyricsFromXiph(parsedTag);
127 	}
128 
129 	return (!lyricsData.isEmpty());
130 }
131 
132 bool Tagging::isLyricsSupported(const QString& filepath)
133 {
134 	const auto fileRef = TagLib::FileRef(TagLib::FileName(filepath.toUtf8()));
135 	if(!Tagging::isValidFile(fileRef))
136 	{
137 		return false;
138 	}
139 
140 	const auto parsedTag = Tagging::getParsedTagFromFileRef(fileRef);
141 	return ((parsedTag.type == Tagging::TagType::ID3v2) ||
142 	        (parsedTag.type == Tagging::TagType::Xiph));
143 }
144 
145