Lines 17-26
Link Here
|
17 |
#define I18N_NOOP(s) QT_TR_NOOP(s) |
17 |
#define I18N_NOOP(s) QT_TR_NOOP(s) |
18 |
#endif |
18 |
#endif |
19 |
#include <qfile.h> |
19 |
#include <qfile.h> |
|
|
20 |
#if HAVE_TUNEPIMP >= 5 |
21 |
#include <qsocket.h> |
22 |
#include <qdom.h> |
23 |
#endif |
20 |
#include "musicbrainzconfig.h" |
24 |
#include "musicbrainzconfig.h" |
21 |
#include "freedbclient.h" |
25 |
#include "freedbclient.h" |
22 |
#include "importtrackdata.h" |
26 |
#include "importtrackdata.h" |
23 |
|
27 |
|
|
|
28 |
#if HAVE_TUNEPIMP >= 5 |
29 |
/** |
30 |
* Constructor. |
31 |
* |
32 |
* @param numFiles number of files to be queried |
33 |
* @param serverName server name |
34 |
* @param serverPort server port |
35 |
* @param proxyName proxy name, empty if no proxy |
36 |
* @param proxyPort proxy port |
37 |
*/ |
38 |
LookupQuery::LookupQuery(int numFiles, |
39 |
const QString& serverName, Q_UINT16 serverPort, |
40 |
const QString& proxyName, Q_UINT16 proxyPort) : |
41 |
m_numFiles(numFiles), m_serverName(serverName), m_serverPort(serverPort), |
42 |
m_proxyName(proxyName), m_proxyPort(proxyPort), |
43 |
m_currentFile(-1), m_fileQueries(new FileQuery[numFiles]), |
44 |
m_sock(new QSocket) |
45 |
{ |
46 |
for (int i = 0; i < m_numFiles; ++i) { |
47 |
m_fileQueries[i].requested = false; |
48 |
m_fileQueries[i].puid = ""; |
49 |
} |
50 |
connect(m_sock, SIGNAL(connected()), |
51 |
this, SLOT(socketConnected())); |
52 |
connect(m_sock, SIGNAL(error(int)), |
53 |
this, SLOT(socketError())); |
54 |
connect(m_sock, SIGNAL(connectionClosed()), |
55 |
this, SLOT(socketConnectionClosed())); |
56 |
} |
57 |
|
58 |
/** |
59 |
* Destructor. |
60 |
*/ |
61 |
LookupQuery::~LookupQuery() |
62 |
{ |
63 |
m_sock->close(); |
64 |
m_sock->disconnect(); |
65 |
delete m_sock; |
66 |
delete [] m_fileQueries; |
67 |
} |
68 |
|
69 |
/** |
70 |
* Connect to server to query information about the current file. |
71 |
*/ |
72 |
void LookupQuery::socketQuery() |
73 |
{ |
74 |
if (m_currentFile >= 0 && m_currentFile < m_numFiles) { |
75 |
QString destName = m_proxyName.isEmpty() ? m_serverName : m_proxyName; |
76 |
Q_UINT16 destPort = m_proxyName.isEmpty() ? m_serverPort : m_proxyPort; |
77 |
m_request = "GET http://"; |
78 |
m_request += m_serverName; |
79 |
if (m_serverPort != 80) { |
80 |
m_request += ':'; |
81 |
m_request += QString::number(m_serverPort); |
82 |
} |
83 |
m_request += "/ws/1/track/?type=xml&puid="; |
84 |
m_request += m_fileQueries[m_currentFile].puid; |
85 |
m_request += " HTTP/1.0\r\nHost: "; |
86 |
m_request += m_serverName; |
87 |
m_request += "\r\nUser-agent: Kid3/" VERSION "\r\n\r\n"; |
88 |
m_sock->connectToHost(destName, destPort); |
89 |
m_fileQueries[m_currentFile].requested = true; |
90 |
} |
91 |
} |
92 |
|
93 |
/** |
94 |
* Query the next file. |
95 |
*/ |
96 |
void LookupQuery::queryNext() |
97 |
{ |
98 |
// handle the first pending query |
99 |
for (int i = 0; i < m_numFiles; ++i) { |
100 |
if (!m_fileQueries[i].requested && |
101 |
!m_fileQueries[i].puid.isEmpty()) { |
102 |
m_currentFile = i; |
103 |
socketQuery(); |
104 |
return; |
105 |
} |
106 |
} |
107 |
// no pending query => socketQuery() will be done in next query() |
108 |
m_currentFile = -1; |
109 |
} |
110 |
|
111 |
/** |
112 |
* Query a PUID from the server. |
113 |
* |
114 |
* @param puid PUID |
115 |
* @param index index of file |
116 |
*/ |
117 |
void LookupQuery::query(const char* puid, int index) |
118 |
{ |
119 |
m_fileQueries[index].puid = QString(puid); |
120 |
// if no request is being executed, start the current request |
121 |
if (m_currentFile < 0 || m_currentFile >= m_numFiles || |
122 |
!m_fileQueries[m_currentFile].requested) { |
123 |
m_currentFile = index; |
124 |
socketQuery(); |
125 |
} |
126 |
} |
127 |
|
128 |
/** |
129 |
* Send query when the socket is connected. |
130 |
*/ |
131 |
void LookupQuery::socketConnected() |
132 |
{ |
133 |
m_sock->writeBlock(m_request.latin1(), m_request.length()); |
134 |
} |
135 |
|
136 |
/** |
137 |
* Error on socket connection. |
138 |
*/ |
139 |
void LookupQuery::socketError() |
140 |
{ |
141 |
queryNext(); |
142 |
} |
143 |
|
144 |
/** |
145 |
* Read received data when the server has closed the connection. |
146 |
*/ |
147 |
void LookupQuery::socketConnectionClosed() |
148 |
{ |
149 |
Q_ULONG len = m_sock->bytesAvailable(); |
150 |
QCString buf; |
151 |
buf.resize(len + 1 ); |
152 |
m_sock->readBlock(buf.data(), len); |
153 |
m_sock->close(); |
154 |
|
155 |
int xmlStart = buf.find("<?xml"); |
156 |
if (xmlStart >= 0 && |
157 |
m_currentFile >= 0 && m_currentFile < m_numFiles && |
158 |
m_fileQueries[m_currentFile].requested) { |
159 |
emit queryResponseReceived(m_currentFile, buf.mid(xmlStart, len - xmlStart)); |
160 |
} |
161 |
queryNext(); |
162 |
} |
163 |
|
164 |
#else |
165 |
|
166 |
LookupQuery::LookupQuery(int, const QString&, Q_UINT16, const QString&, Q_UINT16) {} |
167 |
LookupQuery::~LookupQuery() {} |
168 |
void LookupQuery::socketConnected() {} |
169 |
void LookupQuery::socketError() {} |
170 |
void LookupQuery::socketConnectionClosed() {} |
171 |
|
172 |
#endif |
173 |
|
174 |
|
24 |
/** |
175 |
/** |
25 |
* Constructor. |
176 |
* Constructor. |
26 |
* |
177 |
* |
Lines 29-34
Link Here
|
29 |
*/ |
180 |
*/ |
30 |
MusicBrainzClient::MusicBrainzClient(ImportTrackDataVector& trackDataList) : |
181 |
MusicBrainzClient::MusicBrainzClient(ImportTrackDataVector& trackDataList) : |
31 |
m_trackDataVector(trackDataList), m_tp(0), m_ids(0), m_numFiles(0) |
182 |
m_trackDataVector(trackDataList), m_tp(0), m_ids(0), m_numFiles(0) |
|
|
183 |
#if HAVE_TUNEPIMP >= 5 |
184 |
, m_lookupQuery(0) |
185 |
#endif |
32 |
{ |
186 |
{ |
33 |
m_tp = tp_New("kid3", VERSION); |
187 |
m_tp = tp_New("kid3", VERSION); |
34 |
#ifdef WIN32 |
188 |
#ifdef WIN32 |
Lines 39-45
Link Here
|
39 |
#else |
193 |
#else |
40 |
tp_SetUseUTF8(m_tp, 1); |
194 |
tp_SetUseUTF8(m_tp, 1); |
41 |
#endif |
195 |
#endif |
|
|
196 |
#if HAVE_TUNEPIMP >= 5 |
197 |
tp_SetMusicDNSClientId(m_tp, "a95f5c7cd37fd4bce12dc86d196fb4fe"); |
198 |
#else |
42 |
tp_SetAutoFileLookup(m_tp, 1); |
199 |
tp_SetAutoFileLookup(m_tp, 1); |
|
|
200 |
#endif |
43 |
tp_SetRenameFiles(m_tp, 0); |
201 |
tp_SetRenameFiles(m_tp, 0); |
44 |
tp_SetMoveFiles(m_tp, 0); |
202 |
tp_SetMoveFiles(m_tp, 0); |
45 |
tp_SetWriteID3v1(m_tp, 0); |
203 |
tp_SetWriteID3v1(m_tp, 0); |
Lines 110-117
Link Here
|
110 |
{ eUnrecognized, I18N_NOOP("Unrecognized") }, |
268 |
{ eUnrecognized, I18N_NOOP("Unrecognized") }, |
111 |
{ eRecognized, I18N_NOOP("Recognized") }, |
269 |
{ eRecognized, I18N_NOOP("Recognized") }, |
112 |
{ ePending, I18N_NOOP("Pending") }, |
270 |
{ ePending, I18N_NOOP("Pending") }, |
|
|
271 |
#if HAVE_TUNEPIMP >= 5 |
272 |
{ ePUIDLookup, I18N_NOOP("PUID Lookup") }, |
273 |
{ ePUIDCollision, I18N_NOOP("PUID Collision") }, |
274 |
#else |
113 |
{ eTRMLookup, I18N_NOOP("TRM Lookup") }, |
275 |
{ eTRMLookup, I18N_NOOP("TRM Lookup") }, |
114 |
{ eTRMCollision, I18N_NOOP("TRM Collision") }, |
276 |
{ eTRMCollision, I18N_NOOP("TRM Collision") }, |
|
|
277 |
#endif |
115 |
{ eFileLookup, I18N_NOOP("File Lookup") }, |
278 |
{ eFileLookup, I18N_NOOP("File Lookup") }, |
116 |
{ eUserSelection, I18N_NOOP("User Selection") }, |
279 |
{ eUserSelection, I18N_NOOP("User Selection") }, |
117 |
{ eVerified, I18N_NOOP("Verified") }, |
280 |
{ eVerified, I18N_NOOP("Verified") }, |
Lines 163-169
Link Here
|
163 |
track_t track = tp_GetTrack(m_tp, id); |
326 |
track_t track = tp_GetTrack(m_tp, id); |
164 |
if (track) { |
327 |
if (track) { |
165 |
tr_Lock(track); |
328 |
tr_Lock(track); |
|
|
329 |
#if HAVE_TUNEPIMP >= 5 |
330 |
tr_GetPUID(track, trm, sizeof(trm)); |
331 |
#else |
166 |
tr_GetTRM(track, trm, sizeof(trm)); |
332 |
tr_GetTRM(track, trm, sizeof(trm)); |
|
|
333 |
#endif |
167 |
if (trm[0] == '\0') { |
334 |
if (trm[0] == '\0') { |
168 |
tr_SetStatus(track, ePending); |
335 |
tr_SetStatus(track, ePending); |
169 |
tp_Wake(m_tp, track); |
336 |
tp_Wake(m_tp, track); |
Lines 189-201
Link Here
|
189 |
ImportTrackData trackData; |
356 |
ImportTrackData trackData; |
190 |
getMetaData(id, trackData); |
357 |
getMetaData(id, trackData); |
191 |
emit metaDataReceived(index, trackData); |
358 |
emit metaDataReceived(index, trackData); |
192 |
} else if (statusCode == eTRMCollision || |
359 |
} |
193 |
statusCode == eUserSelection) { |
360 |
#if HAVE_TUNEPIMP >= 5 |
|
|
361 |
else if (statusCode == ePUIDLookup || |
362 |
statusCode == ePUIDCollision || |
363 |
statusCode == eFileLookup) { |
364 |
char puid[255]; |
365 |
puid[0] = '\0'; |
366 |
track_t track = tp_GetTrack(m_tp, id); |
367 |
if (track) { |
368 |
tr_Lock(track); |
369 |
tr_GetPUID(track, puid, sizeof(puid)); |
370 |
tr_Unlock(track); |
371 |
tp_ReleaseTrack(m_tp, track); |
372 |
} |
373 |
if (m_lookupQuery) { |
374 |
m_lookupQuery->query(puid, index); |
375 |
} |
376 |
} |
377 |
#else |
378 |
else if (statusCode == eTRMCollision || |
379 |
statusCode == eUserSelection) { |
194 |
ImportTrackDataVector trackDataList; |
380 |
ImportTrackDataVector trackDataList; |
195 |
if (getResults(id, trackDataList)) { |
381 |
if (getResults(id, trackDataList)) { |
196 |
emit resultsReceived(index, trackDataList); |
382 |
emit resultsReceived(index, trackDataList); |
197 |
} |
383 |
} |
198 |
} |
384 |
} |
|
|
385 |
#endif |
199 |
} |
386 |
} |
200 |
break; |
387 |
break; |
201 |
} |
388 |
} |
Lines 242-247
Link Here
|
242 |
m_numFiles = m_trackDataVector.count(); |
429 |
m_numFiles = m_trackDataVector.count(); |
243 |
#endif |
430 |
#endif |
244 |
m_ids = new int[m_numFiles]; |
431 |
m_ids = new int[m_numFiles]; |
|
|
432 |
#if HAVE_TUNEPIMP >= 5 |
433 |
char serverName[80], proxyName[80]; |
434 |
short serverPort, proxyPort; |
435 |
tp_GetServer(m_tp, serverName, sizeof(serverName) - 1, &serverPort); |
436 |
tp_GetProxy(m_tp, proxyName, sizeof(proxyName) - 1, &proxyPort); |
437 |
m_lookupQuery = new LookupQuery(m_numFiles, serverName, serverPort, |
438 |
proxyName, proxyPort); |
439 |
connect(m_lookupQuery, SIGNAL(queryResponseReceived(int, const QCString&)), |
440 |
this, SLOT(parseLookupResponse(int, const QCString&))); |
441 |
#endif |
245 |
int i = 0; |
442 |
int i = 0; |
246 |
for ( |
443 |
for ( |
247 |
#if QT_VERSION >= 300 |
444 |
#if QT_VERSION >= 300 |
Lines 271-276
Link Here
|
271 |
} |
468 |
} |
272 |
delete [] m_ids; |
469 |
delete [] m_ids; |
273 |
m_ids = 0; |
470 |
m_ids = 0; |
|
|
471 |
#if HAVE_TUNEPIMP >= 5 |
472 |
delete m_lookupQuery; |
473 |
m_lookupQuery = 0; |
474 |
#endif |
274 |
m_numFiles = 0; |
475 |
m_numFiles = 0; |
275 |
} |
476 |
} |
276 |
} |
477 |
} |
Lines 308-313
Link Here
|
308 |
} |
509 |
} |
309 |
} |
510 |
} |
310 |
|
511 |
|
|
|
512 |
#if HAVE_TUNEPIMP >= 5 |
513 |
|
514 |
bool MusicBrainzClient::getResults(int, ImportTrackDataVector&) { |
515 |
return false; |
516 |
} |
517 |
|
518 |
/** |
519 |
* Process server response with lookup data. |
520 |
* |
521 |
* @param index index of file |
522 |
* @param response response from server |
523 |
*/ |
524 |
void MusicBrainzClient::parseLookupResponse(int index, const QCString& response) |
525 |
{ |
526 |
ImportTrackDataVector trackDataList; |
527 |
QDomDocument doc; |
528 |
if (doc.setContent(response)) { |
529 |
QDomElement trackList = |
530 |
doc.namedItem("metadata").toElement().namedItem("track-list").toElement(); |
531 |
|
532 |
for (QDomNode trackNode = trackList.namedItem("track"); |
533 |
!trackNode.isNull(); |
534 |
trackNode = trackNode.nextSibling()) { |
535 |
QDomElement track = trackNode.toElement(); |
536 |
|
537 |
ImportTrackData trackData; |
538 |
trackData.artist = |
539 |
track.namedItem("artist").toElement().namedItem("name").toElement().text(); |
540 |
trackData.title = track.namedItem("title").toElement().text(); |
541 |
|
542 |
for (QDomNode releaseNode = |
543 |
track.namedItem("release-list").toElement().namedItem("release"); |
544 |
!releaseNode.isNull(); |
545 |
releaseNode = releaseNode.nextSibling() ) { |
546 |
QDomElement release = releaseNode.toElement(); |
547 |
|
548 |
trackData.album = release.namedItem("title").toElement().text(); |
549 |
trackData.track = -1; |
550 |
QDomNode releaseTrackNode = release.namedItem("track-list"); |
551 |
if (!releaseTrackNode.isNull()) { |
552 |
QDomElement releaseTrack = releaseTrackNode.toElement(); |
553 |
if (!releaseTrack.attribute("offset").isEmpty()) |
554 |
trackData.track = releaseTrack.attribute("offset").toInt() + 1; |
555 |
} |
556 |
} |
557 |
trackDataList.append(trackData); |
558 |
} |
559 |
} |
560 |
|
561 |
if (trackDataList.size() > 1) { |
562 |
emit resultsReceived(index, trackDataList); |
563 |
emit statusChanged(index, i18n("User Selection")); |
564 |
} else if (trackDataList.size() == 1) { |
565 |
emit metaDataReceived(index, *trackDataList.begin()); |
566 |
emit statusChanged(index, i18n("Recognized")); |
567 |
} else { |
568 |
emit statusChanged(index, i18n("Unrecognized")); |
569 |
} |
570 |
} |
571 |
|
572 |
#else |
573 |
|
311 |
/** |
574 |
/** |
312 |
* Get results for an ambiguous file. |
575 |
* Get results for an ambiguous file. |
313 |
* |
576 |
* |
Lines 388-393
Link Here
|
388 |
return resultsAvailable; |
651 |
return resultsAvailable; |
389 |
} |
652 |
} |
390 |
|
653 |
|
|
|
654 |
void MusicBrainzClient::parseLookupResponse(int, const QCString&) {} |
655 |
|
656 |
#endif |
657 |
|
391 |
#else // HAVE_TUNEPIMP |
658 |
#else // HAVE_TUNEPIMP |
392 |
|
659 |
|
393 |
MusicBrainzClient::MusicBrainzClient(ImportTrackDataVector&) {} |
660 |
MusicBrainzClient::MusicBrainzClient(ImportTrackDataVector&) {} |