Line 0
Link Here
|
|
|
1 |
--- ./kid3/musicbrainzclient.cpp.orig Tue Jun 6 00:18:36 2006 |
2 |
+++ ./kid3/musicbrainzclient.cpp Sat Sep 23 01:27:55 2006 |
3 |
@@ -17,10 +17,161 @@ |
4 |
#define I18N_NOOP(s) QT_TR_NOOP(s) |
5 |
#endif |
6 |
#include <qfile.h> |
7 |
+#if HAVE_TUNEPIMP >= 5 |
8 |
+#include <qsocket.h> |
9 |
+#include <qdom.h> |
10 |
+#endif |
11 |
#include "musicbrainzconfig.h" |
12 |
#include "freedbclient.h" |
13 |
#include "importtrackdata.h" |
14 |
|
15 |
+#if HAVE_TUNEPIMP >= 5 |
16 |
+/** |
17 |
+ * Constructor. |
18 |
+ * |
19 |
+ * @param numFiles number of files to be queried |
20 |
+ * @param serverName server name |
21 |
+ * @param serverPort server port |
22 |
+ * @param proxyName proxy name, empty if no proxy |
23 |
+ * @param proxyPort proxy port |
24 |
+ */ |
25 |
+LookupQuery::LookupQuery(int numFiles, |
26 |
+ const QString& serverName, Q_UINT16 serverPort, |
27 |
+ const QString& proxyName, Q_UINT16 proxyPort) : |
28 |
+ m_numFiles(numFiles), m_serverName(serverName), m_serverPort(serverPort), |
29 |
+ m_proxyName(proxyName), m_proxyPort(proxyPort), |
30 |
+ m_currentFile(-1), m_fileQueries(new FileQuery[numFiles]), |
31 |
+ m_sock(new QSocket) |
32 |
+{ |
33 |
+ for (int i = 0; i < m_numFiles; ++i) { |
34 |
+ m_fileQueries[i].requested = false; |
35 |
+ m_fileQueries[i].puid = ""; |
36 |
+ } |
37 |
+ connect(m_sock, SIGNAL(connected()), |
38 |
+ this, SLOT(socketConnected())); |
39 |
+ connect(m_sock, SIGNAL(error(int)), |
40 |
+ this, SLOT(socketError())); |
41 |
+ connect(m_sock, SIGNAL(connectionClosed()), |
42 |
+ this, SLOT(socketConnectionClosed())); |
43 |
+} |
44 |
+ |
45 |
+/** |
46 |
+ * Destructor. |
47 |
+ */ |
48 |
+LookupQuery::~LookupQuery() |
49 |
+{ |
50 |
+ m_sock->close(); |
51 |
+ m_sock->disconnect(); |
52 |
+ delete m_sock; |
53 |
+ delete [] m_fileQueries; |
54 |
+} |
55 |
+ |
56 |
+/** |
57 |
+ * Connect to server to query information about the current file. |
58 |
+ */ |
59 |
+void LookupQuery::socketQuery() |
60 |
+{ |
61 |
+ if (m_currentFile >= 0 && m_currentFile < m_numFiles) { |
62 |
+ QString destName = m_proxyName.isEmpty() ? m_serverName : m_proxyName; |
63 |
+ Q_UINT16 destPort = m_proxyName.isEmpty() ? m_serverPort : m_proxyPort; |
64 |
+ m_request = "GET http://"; |
65 |
+ m_request += m_serverName; |
66 |
+ if (m_serverPort != 80) { |
67 |
+ m_request += ':'; |
68 |
+ m_request += QString::number(m_serverPort); |
69 |
+ } |
70 |
+ m_request += "/ws/1/track/?type=xml&puid="; |
71 |
+ m_request += m_fileQueries[m_currentFile].puid; |
72 |
+ m_request += " HTTP/1.0\r\nHost: "; |
73 |
+ m_request += m_serverName; |
74 |
+ m_request += "\r\nUser-agent: Kid3/" VERSION "\r\n\r\n"; |
75 |
+ m_sock->connectToHost(destName, destPort); |
76 |
+ m_fileQueries[m_currentFile].requested = true; |
77 |
+ } |
78 |
+} |
79 |
+ |
80 |
+/** |
81 |
+ * Query the next file. |
82 |
+ */ |
83 |
+void LookupQuery::queryNext() |
84 |
+{ |
85 |
+ // handle the first pending query |
86 |
+ for (int i = 0; i < m_numFiles; ++i) { |
87 |
+ if (!m_fileQueries[i].requested && |
88 |
+ !m_fileQueries[i].puid.isEmpty()) { |
89 |
+ m_currentFile = i; |
90 |
+ socketQuery(); |
91 |
+ return; |
92 |
+ } |
93 |
+ } |
94 |
+ // no pending query => socketQuery() will be done in next query() |
95 |
+ m_currentFile = -1; |
96 |
+} |
97 |
+ |
98 |
+/** |
99 |
+ * Query a PUID from the server. |
100 |
+ * |
101 |
+ * @param puid PUID |
102 |
+ * @param index index of file |
103 |
+ */ |
104 |
+void LookupQuery::query(const char* puid, int index) |
105 |
+{ |
106 |
+ m_fileQueries[index].puid = QString(puid); |
107 |
+ // if no request is being executed, start the current request |
108 |
+ if (m_currentFile < 0 || m_currentFile >= m_numFiles || |
109 |
+ !m_fileQueries[m_currentFile].requested) { |
110 |
+ m_currentFile = index; |
111 |
+ socketQuery(); |
112 |
+ } |
113 |
+} |
114 |
+ |
115 |
+/** |
116 |
+ * Send query when the socket is connected. |
117 |
+ */ |
118 |
+void LookupQuery::socketConnected() |
119 |
+{ |
120 |
+ m_sock->writeBlock(m_request.latin1(), m_request.length()); |
121 |
+} |
122 |
+ |
123 |
+/** |
124 |
+ * Error on socket connection. |
125 |
+ */ |
126 |
+void LookupQuery::socketError() |
127 |
+{ |
128 |
+ queryNext(); |
129 |
+} |
130 |
+ |
131 |
+/** |
132 |
+ * Read received data when the server has closed the connection. |
133 |
+ */ |
134 |
+void LookupQuery::socketConnectionClosed() |
135 |
+{ |
136 |
+ Q_ULONG len = m_sock->bytesAvailable(); |
137 |
+ QCString buf; |
138 |
+ buf.resize(len + 1 ); |
139 |
+ m_sock->readBlock(buf.data(), len); |
140 |
+ m_sock->close(); |
141 |
+ |
142 |
+ int xmlStart = buf.find("<?xml"); |
143 |
+ if (xmlStart >= 0 && |
144 |
+ m_currentFile >= 0 && m_currentFile < m_numFiles && |
145 |
+ m_fileQueries[m_currentFile].requested) { |
146 |
+ emit queryResponseReceived(m_currentFile, buf.mid(xmlStart, len - xmlStart)); |
147 |
+ } |
148 |
+ queryNext(); |
149 |
+} |
150 |
+ |
151 |
+#else |
152 |
+ |
153 |
+LookupQuery::LookupQuery(int, const QString&, Q_UINT16, const QString&, Q_UINT16) {} |
154 |
+LookupQuery::~LookupQuery() {} |
155 |
+void LookupQuery::socketConnected() {} |
156 |
+void LookupQuery::socketError() {} |
157 |
+void LookupQuery::socketConnectionClosed() {} |
158 |
+ |
159 |
+#endif |
160 |
+ |
161 |
+ |
162 |
/** |
163 |
* Constructor. |
164 |
* |
165 |
@@ -29,6 +180,9 @@ |
166 |
*/ |
167 |
MusicBrainzClient::MusicBrainzClient(ImportTrackDataVector& trackDataList) : |
168 |
m_trackDataVector(trackDataList), m_tp(0), m_ids(0), m_numFiles(0) |
169 |
+#if HAVE_TUNEPIMP >= 5 |
170 |
+ , m_lookupQuery(0) |
171 |
+#endif |
172 |
{ |
173 |
m_tp = tp_New("kid3", VERSION); |
174 |
#ifdef WIN32 |
175 |
@@ -39,7 +193,11 @@ |
176 |
#else |
177 |
tp_SetUseUTF8(m_tp, 1); |
178 |
#endif |
179 |
+#if HAVE_TUNEPIMP >= 5 |
180 |
+ tp_SetMusicDNSClientId(m_tp, "a95f5c7cd37fd4bce12dc86d196fb4fe"); |
181 |
+#else |
182 |
tp_SetAutoFileLookup(m_tp, 1); |
183 |
+#endif |
184 |
tp_SetRenameFiles(m_tp, 0); |
185 |
tp_SetMoveFiles(m_tp, 0); |
186 |
tp_SetWriteID3v1(m_tp, 0); |
187 |
@@ -110,8 +268,13 @@ |
188 |
{ eUnrecognized, I18N_NOOP("Unrecognized") }, |
189 |
{ eRecognized, I18N_NOOP("Recognized") }, |
190 |
{ ePending, I18N_NOOP("Pending") }, |
191 |
+#if HAVE_TUNEPIMP >= 5 |
192 |
+ { ePUIDLookup, I18N_NOOP("PUID Lookup") }, |
193 |
+ { ePUIDCollision, I18N_NOOP("PUID Collision") }, |
194 |
+#else |
195 |
{ eTRMLookup, I18N_NOOP("TRM Lookup") }, |
196 |
{ eTRMCollision, I18N_NOOP("TRM Collision") }, |
197 |
+#endif |
198 |
{ eFileLookup, I18N_NOOP("File Lookup") }, |
199 |
{ eUserSelection, I18N_NOOP("User Selection") }, |
200 |
{ eVerified, I18N_NOOP("Verified") }, |
201 |
@@ -163,7 +326,11 @@ |
202 |
track_t track = tp_GetTrack(m_tp, id); |
203 |
if (track) { |
204 |
tr_Lock(track); |
205 |
+#if HAVE_TUNEPIMP >= 5 |
206 |
+ tr_GetPUID(track, trm, sizeof(trm)); |
207 |
+#else |
208 |
tr_GetTRM(track, trm, sizeof(trm)); |
209 |
+#endif |
210 |
if (trm[0] == '\0') { |
211 |
tr_SetStatus(track, ePending); |
212 |
tp_Wake(m_tp, track); |
213 |
@@ -189,13 +356,33 @@ |
214 |
ImportTrackData trackData; |
215 |
getMetaData(id, trackData); |
216 |
emit metaDataReceived(index, trackData); |
217 |
- } else if (statusCode == eTRMCollision || |
218 |
- statusCode == eUserSelection) { |
219 |
+ } |
220 |
+#if HAVE_TUNEPIMP >= 5 |
221 |
+ else if (statusCode == ePUIDLookup || |
222 |
+ statusCode == ePUIDCollision || |
223 |
+ statusCode == eFileLookup) { |
224 |
+ char puid[255]; |
225 |
+ puid[0] = '\0'; |
226 |
+ track_t track = tp_GetTrack(m_tp, id); |
227 |
+ if (track) { |
228 |
+ tr_Lock(track); |
229 |
+ tr_GetPUID(track, puid, sizeof(puid)); |
230 |
+ tr_Unlock(track); |
231 |
+ tp_ReleaseTrack(m_tp, track); |
232 |
+ } |
233 |
+ if (m_lookupQuery) { |
234 |
+ m_lookupQuery->query(puid, index); |
235 |
+ } |
236 |
+ } |
237 |
+#else |
238 |
+ else if (statusCode == eTRMCollision || |
239 |
+ statusCode == eUserSelection) { |
240 |
ImportTrackDataVector trackDataList; |
241 |
if (getResults(id, trackDataList)) { |
242 |
emit resultsReceived(index, trackDataList); |
243 |
} |
244 |
} |
245 |
+#endif |
246 |
} |
247 |
break; |
248 |
} |
249 |
@@ -242,6 +429,16 @@ |
250 |
m_numFiles = m_trackDataVector.count(); |
251 |
#endif |
252 |
m_ids = new int[m_numFiles]; |
253 |
+#if HAVE_TUNEPIMP >= 5 |
254 |
+ char serverName[80], proxyName[80]; |
255 |
+ short serverPort, proxyPort; |
256 |
+ tp_GetServer(m_tp, serverName, sizeof(serverName) - 1, &serverPort); |
257 |
+ tp_GetProxy(m_tp, proxyName, sizeof(proxyName) - 1, &proxyPort); |
258 |
+ m_lookupQuery = new LookupQuery(m_numFiles, serverName, serverPort, |
259 |
+ proxyName, proxyPort); |
260 |
+ connect(m_lookupQuery, SIGNAL(queryResponseReceived(int, const QCString&)), |
261 |
+ this, SLOT(parseLookupResponse(int, const QCString&))); |
262 |
+#endif |
263 |
int i = 0; |
264 |
for ( |
265 |
#if QT_VERSION >= 300 |
266 |
@@ -271,6 +468,10 @@ |
267 |
} |
268 |
delete [] m_ids; |
269 |
m_ids = 0; |
270 |
+#if HAVE_TUNEPIMP >= 5 |
271 |
+ delete m_lookupQuery; |
272 |
+ m_lookupQuery = 0; |
273 |
+#endif |
274 |
m_numFiles = 0; |
275 |
} |
276 |
} |
277 |
@@ -308,6 +509,68 @@ |
278 |
} |
279 |
} |
280 |
|
281 |
+#if HAVE_TUNEPIMP >= 5 |
282 |
+ |
283 |
+bool MusicBrainzClient::getResults(int, ImportTrackDataVector&) { |
284 |
+ return false; |
285 |
+} |
286 |
+ |
287 |
+/** |
288 |
+ * Process server response with lookup data. |
289 |
+ * |
290 |
+ * @param index index of file |
291 |
+ * @param response response from server |
292 |
+ */ |
293 |
+void MusicBrainzClient::parseLookupResponse(int index, const QCString& response) |
294 |
+{ |
295 |
+ ImportTrackDataVector trackDataList; |
296 |
+ QDomDocument doc; |
297 |
+ if (doc.setContent(response)) { |
298 |
+ QDomElement trackList = |
299 |
+ doc.namedItem("metadata").toElement().namedItem("track-list").toElement(); |
300 |
+ |
301 |
+ for (QDomNode trackNode = trackList.namedItem("track"); |
302 |
+ !trackNode.isNull(); |
303 |
+ trackNode = trackNode.nextSibling()) { |
304 |
+ QDomElement track = trackNode.toElement(); |
305 |
+ |
306 |
+ ImportTrackData trackData; |
307 |
+ trackData.artist = |
308 |
+ track.namedItem("artist").toElement().namedItem("name").toElement().text(); |
309 |
+ trackData.title = track.namedItem("title").toElement().text(); |
310 |
+ |
311 |
+ for (QDomNode releaseNode = |
312 |
+ track.namedItem("release-list").toElement().namedItem("release"); |
313 |
+ !releaseNode.isNull(); |
314 |
+ releaseNode = releaseNode.nextSibling() ) { |
315 |
+ QDomElement release = releaseNode.toElement(); |
316 |
+ |
317 |
+ trackData.album = release.namedItem("title").toElement().text(); |
318 |
+ trackData.track = -1; |
319 |
+ QDomNode releaseTrackNode = release.namedItem("track-list"); |
320 |
+ if (!releaseTrackNode.isNull()) { |
321 |
+ QDomElement releaseTrack = releaseTrackNode.toElement(); |
322 |
+ if (!releaseTrack.attribute("offset").isEmpty()) |
323 |
+ trackData.track = releaseTrack.attribute("offset").toInt() + 1; |
324 |
+ } |
325 |
+ } |
326 |
+ trackDataList.append(trackData); |
327 |
+ } |
328 |
+ } |
329 |
+ |
330 |
+ if (trackDataList.size() > 1) { |
331 |
+ emit resultsReceived(index, trackDataList); |
332 |
+ emit statusChanged(index, i18n("User Selection")); |
333 |
+ } else if (trackDataList.size() == 1) { |
334 |
+ emit metaDataReceived(index, *trackDataList.begin()); |
335 |
+ emit statusChanged(index, i18n("Recognized")); |
336 |
+ } else { |
337 |
+ emit statusChanged(index, i18n("Unrecognized")); |
338 |
+ } |
339 |
+} |
340 |
+ |
341 |
+#else |
342 |
+ |
343 |
/** |
344 |
* Get results for an ambiguous file. |
345 |
* |
346 |
@@ -387,6 +650,10 @@ |
347 |
} |
348 |
return resultsAvailable; |
349 |
} |
350 |
+ |
351 |
+void MusicBrainzClient::parseLookupResponse(int, const QCString&) {} |
352 |
+ |
353 |
+#endif |
354 |
|
355 |
#else // HAVE_TUNEPIMP |
356 |
|