KCDDB

asynccddbplookup.cpp
1 /*
2  SPDX-FileCopyrightText: 2002 Rik Hemsley (rikkus) <[email protected]>
3  SPDX-FileCopyrightText: 2002 Benjamin Meyer <[email protected]>
4  SPDX-FileCopyrightText: 2005 Richard Lärkäng <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "asynccddbplookup.h"
10 #include "logging.h"
11 
12 namespace KCDDB
13 {
14  AsyncCDDBPLookup::AsyncCDDBPLookup()
15  : CDDBPLookup(),
16  state_(Idle)
17  {
18 
19  }
20 
21  AsyncCDDBPLookup::~AsyncCDDBPLookup()
22  {
23  }
24 
25  Result
26  AsyncCDDBPLookup::lookup
27  (
28  const QString & hostname,
29  uint port,
30  const TrackOffsetList & trackOffsetList
31  )
32  {
33  socket_ = new QTcpSocket;
34  socket_->connectToHost(hostname, port);
35 
36  connect (socket_, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(slotGotError(QAbstractSocket::SocketError)));
37 
38  connect (socket_, &QAbstractSocket::connected,
39  this, &AsyncCDDBPLookup::slotConnectionSuccess );
40 
41  connect (socket_, &QIODevice::readyRead, this, &AsyncCDDBPLookup::slotReadyRead );
42 
43  trackOffsetList_ = trackOffsetList;
44 
45  state_ = WaitingForConnection;
46 
47  return Success;
48  }
49 
50  void
51  AsyncCDDBPLookup::slotGotError(QAbstractSocket::SocketError error)
52  {
53  state_ = Idle;
54 
56  Q_EMIT finished( HostNotFound );
57  else if ( error == QAbstractSocket::SocketTimeoutError )
58  Q_EMIT finished( NoResponse );
59  else
60  Q_EMIT finished( UnknownError );
61  }
62 
63  void
64  AsyncCDDBPLookup::slotConnectionSuccess()
65  {
66  qCDebug(LIBKCDDB) << "Connection successful";
67  state_ = WaitingForGreeting;
68  }
69 
70  void
71  AsyncCDDBPLookup::slotReadyRead()
72  {
73  qCDebug(LIBKCDDB) << "Ready to read. State: " << stateToString();
74 
75  while ( Idle != state_ && isConnected() && socket_->canReadLine() )
76  read();
77  }
78 
79  void
80  AsyncCDDBPLookup::read()
81  {
82  switch ( state_ )
83  {
84  case WaitingForGreeting:
85 
86  if ( !parseGreeting( readLine() ) )
87  {
88  result_ = ServerError;
89  doQuit();
90  return;
91  }
92 
93  doHandshake();
94 
95  break;
96 
97  case WaitingForHandshake:
98 
99  if ( !parseHandshake( readLine() ) )
100  {
101  result_ = ServerError;
102  doQuit();
103  return;
104  }
105 
106  doProto();
107 
108  break;
109 
110  case WaitingForProtoResponse:
111 
112  // Ignore the response for now
113  readLine();
114 
115  doQuery();
116 
117  break;
118 
119  case WaitingForQueryResponse:
120  result_ = parseQuery( readLine() );
121 
122  switch ( result_ )
123  {
124  case Success:
125  requestCDInfoForMatch();
126  break;
127 
128  case MultipleRecordFound:
129  state_ = WaitingForMoreMatches;
130  break;
131 
132  default: // Error :(
133  doQuit();
134  return;
135  }
136 
137  break;
138 
139  case WaitingForMoreMatches:
140  {
141  QString line = readLine();
142 
143  if (line.startsWith(QLatin1String( "." )))
144  requestCDInfoForMatch();
145  else
146  parseExtraMatch( line );
147  }
148 
149  break;
150 
151  case WaitingForCDInfoResponse:
152  {
153  Result result = parseRead( readLine() );
154 
155  if ( Success != result )
156  {
157  result_ = result;
158  doQuit();
159  return;
160  }
161 
162  state_ = WaitingForCDInfoData;
163  }
164 
165  break;
166 
167  case WaitingForCDInfoData:
168  {
169  QString line = readLine();
170 
171  if (line.startsWith(QLatin1String( "." )))
172  {
173  parseCDInfoData();
174  requestCDInfoForMatch();
175  }
176  else
177  cdInfoBuffer_ << line;
178  }
179 
180  break;
181 
182  case WaitingForQuitResponse:
183 
184  state_ = Idle;
185 
186  char c;
187  while ( socket_->bytesAvailable() )
188  socket_->getChar(&c);
189 
190  close();
191 
192  Q_EMIT finished( result_ );
193 
194  break;
195 
196  default:
197 
198  break;
199  }
200  }
201 
202  QString
203  AsyncCDDBPLookup::readLine()
204  {
205  return QString::fromUtf8(socket_->readLine());
206  }
207 
208  void
209  AsyncCDDBPLookup::doHandshake()
210  {
211  sendHandshake();
212 
213  state_ = WaitingForHandshake;
214  }
215 
216  void
217  AsyncCDDBPLookup::doProto()
218  {
219  sendProto();
220 
221  state_ = WaitingForProtoResponse;
222  }
223 
224  void
225  AsyncCDDBPLookup::doQuery()
226  {
227  sendQuery();
228 
229  state_ = WaitingForQueryResponse;
230  }
231 
232  void
233  AsyncCDDBPLookup::requestCDInfoForMatch()
234  {
235  if (matchList_.isEmpty())
236  {
237  result_ = cdInfoList_.isEmpty()? NoRecordFound : Success;
238  doQuit();
239  return;
240  }
241 
242  CDDBMatch match = matchList_.takeFirst();
243 
244  sendRead( match );
245 
246  state_ = WaitingForCDInfoResponse;
247  }
248 
249  void
250  AsyncCDDBPLookup::parseCDInfoData()
251  {
252  CDInfo info;
253 
254  if (info.load( cdInfoBuffer_ ))
255  {
256  info.set( QLatin1String( "category" ), category_ );
257  info.set( QLatin1String( "discid" ), discid_ );
258  info.set( QLatin1String( "source" ), QLatin1String( "freedb" ) );
259  cdInfoList_.append( info );
260  }
261 
262  cdInfoBuffer_.clear();
263  }
264 
265  void
266  AsyncCDDBPLookup::doQuit()
267  {
268  state_ = WaitingForQuitResponse;
269 
270  sendQuit();
271  }
272 
273  QString
274  AsyncCDDBPLookup::stateToString() const
275  {
276  switch (state_)
277  {
278  case Idle:
279  return QLatin1String( "Idle" );
280  break;
281 
282  case WaitingForConnection:
283  return QLatin1String( "WaitingForConnection" );
284  break;
285 
286  case WaitingForGreeting:
287  return QLatin1String( "WaitingForGreeting" );
288  break;
289 
290  case WaitingForProtoResponse:
291  return QLatin1String( "WaitingForProtoResponse" );
292  break;
293 
294  case WaitingForHandshake:
295  return QLatin1String( "WaitingForHandshake" );
296  break;
297 
298  case WaitingForQueryResponse:
299  return QLatin1String( "WaitingForQueryResponse" );
300  break;
301 
302  case WaitingForMoreMatches:
303  return QLatin1String( "WaitingForMoreMatches" );
304  break;
305 
306  case WaitingForCDInfoResponse:
307  return QLatin1String( "WaitingForCDInfoResponse" );
308  break;
309 
310  case WaitingForCDInfoData:
311  return QLatin1String( "WaitingForCDInfoData" );
312  break;
313 
314  case WaitingForQuitResponse:
315  return QLatin1String( "WaitingForQuitResponse" );
316  break;
317 
318  default:
319  return QLatin1String( "Unknown" );
320  break;
321  }
322  }
323 }
324 
325 
326 // vim:tabstop=2:shiftwidth=2:expandtab:cinoptions=(s,U1,m1
const QList< QKeySequence > & close()
virtual void connectToHost(const QString &hostName, quint16 port, QIODevice::OpenMode openMode, QAbstractSocket::NetworkLayerProtocol protocol)
QString fromUtf8(const char *str, int size)
QVariant read(const QByteArray &data, int versionOverride=0)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
void readyRead()
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Fri Nov 26 2021 23:22:53 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.