1 #include "TagLibParser.h"
2 #include <stdlib.h>
3 #include <string.h>
4 #include <limits.h>
5
6 #include <vector>
7
8 #include <scx/Conv.h>
9 #include <scx/FileHelper.h>
10 #include <scx/IconvHelper.h>
11 using namespace scx;
12
13 #include "CoverArt.h"
14
15 #include <taglib/mpegfile.h>
16
StringToStdString(const String & str)17 static string StringToStdString(const String& str)
18 {
19 if (str.isLatin1()) {
20 return str.to8Bit();
21 } else {
22 string stdStr;
23 const ByteVector& v = str.data(String::UTF16BE);
24 if (IconvHelper::ConvFromTo("UTF-16BE", "UTF-8", v.data(), v.size(), stdStr))
25 return stdStr;
26 else
27 return str.to8Bit();
28 }
29 }
30
TagLibParser()31 TagLibParser::TagLibParser()
32 {
33 m_DumpHandlers["mp3"] = &DumpMp3Cover;
34 m_DumpHandlers["m4a"] = &DumpMp4Cover;
35
36 m_StoreHandlers["mp3"] = &StoreMp3Cover;
37 m_StoreHandlers["m4a"] = &StoreMp4Cover;
38 }
39
~TagLibParser()40 TagLibParser::~TagLibParser()
41 {
42 m_DumpHandlers.clear();
43 Close();
44 }
45
FileSuffix() const46 vector<string> TagLibParser::FileSuffix() const
47 {
48 return { "*" };
49 }
50
Open(const string & path)51 ErrorCode TagLibParser::Open(const string& path)
52 {
53 m_FileName = path;
54
55 m_pFileRef = new FileRef(path.c_str(), true);//AudioProperties::);
56 if (!m_pFileRef->isNull() && m_pFileRef->tag() != nullptr) {
57 m_pTag = m_pFileRef->tag();
58 m_pProp = m_pFileRef->audioProperties();
59 }
60 return ErrorCode::Ok;
61 }
62
Close()63 void TagLibParser::Close()
64 {
65 if (m_pFileRef != nullptr) {
66 delete m_pFileRef;
67 m_pFileRef = nullptr;
68 m_pTag = nullptr;
69 m_pProp = nullptr;
70 }
71
72 m_FileName.clear();
73 }
74
HasTag() const75 bool TagLibParser::HasTag() const
76 {
77 return (m_pTag != nullptr) ? !m_pTag->isEmpty() : false;
78 }
79
Title() const80 string TagLibParser::Title() const
81 {
82 if (m_pTag != nullptr) {
83 return StringToStdString(m_pTag->title());
84 } else {
85 return "";
86 }
87 }
88
Artist() const89 string TagLibParser::Artist() const
90 {
91 if (m_pTag != nullptr) {
92 return StringToStdString(m_pTag->artist());
93 } else {
94 return "";
95 }
96 }
97
Album() const98 string TagLibParser::Album() const
99 {
100 if (m_pTag != nullptr) {
101 return StringToStdString(m_pTag->album());
102 } else {
103 return "";
104 }
105 }
106
Comment() const107 string TagLibParser::Comment() const
108 {
109 if (m_pTag != nullptr) {
110 return StringToStdString(m_pTag->comment());
111 } else {
112 return "";
113 }
114 }
115
Genre() const116 string TagLibParser::Genre() const
117 {
118 if (m_pTag != nullptr) {
119 return StringToStdString(m_pTag->genre());
120 } else {
121 return "";
122 }
123 }
124
Year() const125 int32_t TagLibParser::Year() const
126 {
127 if (m_pTag != nullptr) {
128 return m_pTag->year();
129 } else {
130 return -1;
131 }
132 }
133
Track() const134 int32_t TagLibParser::Track() const
135 {
136 if (m_pTag != nullptr) {
137 return m_pTag->track();
138 } else {
139 return -1;
140 }
141 }
142
HasAudioProperty() const143 bool TagLibParser::HasAudioProperty() const
144 {
145 return (m_pProp != nullptr) ? true : false;
146 }
147
Duration() const148 int32_t TagLibParser::Duration() const
149 {
150 if (m_pProp != nullptr) {
151 return m_pProp->length()*1000;
152 } else {
153 return 0;
154 }
155 }
156
BitRate() const157 int32_t TagLibParser::BitRate() const
158 {
159 if (m_pProp != nullptr) {
160 return m_pProp->bitrate();
161 } else {
162 return 0;
163 }
164 }
165
CanEdit() const166 bool TagLibParser::CanEdit() const
167 {
168 return true;
169 }
170
Save()171 bool TagLibParser::Save()
172 {
173 const string& ext = ToLower(FileHelper::FileSuffix(m_FileName));
174 if (ext == "mp3") {
175 auto ref = dynamic_cast<TagLib::MPEG::File*>(m_pFileRef->file());
176 if (ref == nullptr) {
177 cout << "bad type" << endl;
178 return false;
179 }
180 return ref->save(TagLib::MPEG::File::TagTypes::ID3v2, true, 3, true);
181 } else {
182 return m_pFileRef != nullptr ? m_pFileRef->save() : false;
183 }
184 }
185
SetTitle(const string & title)186 void TagLibParser::SetTitle(const string& title)
187 {
188 if (m_pTag != nullptr)
189 m_pTag->setTitle(title.c_str());
190 }
191
SetArtist(const string & artist)192 void TagLibParser::SetArtist(const string& artist)
193 {
194 if (m_pTag != nullptr)
195 m_pTag->setArtist(artist.c_str());
196 }
197
SetAlbum(const string & album)198 void TagLibParser::SetAlbum(const string& album)
199 {
200 if (m_pTag != nullptr)
201 m_pTag->setAlbum(album.c_str());
202 }
203
SetComment(const string & comment)204 void TagLibParser::SetComment(const string& comment)
205 {
206 if (m_pTag != nullptr)
207 m_pTag->setComment(comment.c_str());
208 }
209
SetGenre(const string & genre)210 void TagLibParser::SetGenre(const string& genre)
211 {
212 if (m_pTag != nullptr)
213 m_pTag->setGenre(genre.c_str());
214 }
215
SetYear(int32_t year)216 void TagLibParser::SetYear(int32_t year)
217 {
218 if (m_pTag != nullptr)
219 m_pTag->setYear(year);
220 }
221
SetTrack(int32_t track)222 void TagLibParser::SetTrack(int32_t track)
223 {
224 if (m_pTag != nullptr)
225 m_pTag->setTrack(track);
226 }
227
DumpCoverArt(vector<char> & buf)228 CoverFormat TagLibParser::DumpCoverArt(vector<char>& buf)
229 {
230 if (m_FileName.empty())
231 return CoverFormat::None;
232
233 const string& ext = ToLower(FileHelper::FileSuffix(m_FileName));
234
235 if (m_DumpHandlers.find(ext) != m_DumpHandlers.end())
236 return m_DumpHandlers[ext](m_FileName, buf);
237 else
238 return CoverFormat::None;
239 }
240
StoreCoverArt(CoverFormat fmt,const char * buf,size_t len)241 bool TagLibParser::StoreCoverArt(CoverFormat fmt, const char* buf, size_t len)
242 {
243 if (m_FileName.empty())
244 return false;
245
246 const string& ext = ToLower(FileHelper::FileSuffix(m_FileName));
247
248 if (m_StoreHandlers.find(ext) != m_StoreHandlers.end())
249 return m_StoreHandlers[ext](m_FileName, fmt, buf, len);
250 else
251 return false;
252 }
253