You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k3b/libk3b/cddb/k3bcddbpquery.cpp

279 lines
6.3 KiB

/*
*
* $Id: k3bcddbpquery.cpp 619556 2007-01-03 17:38:12Z trueg $
*
* This file is part of the K3b project.
* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* See the file "COPYING" for the exact licensing terms.
*/
#include "k3bcddbpquery.h"
#include <tqstringlist.h>
#include <tqsocket.h>
#include <tqtextstream.h>
#include <klocale.h>
#include <kdebug.h>
K3bCddbpQuery::K3bCddbpQuery( TQObject* parent, const char* name )
:K3bCddbQuery( parent, name )
{
m_socket = new TQSocket( this );
m_stream.setDevice( m_socket );
m_stream.setEncoding( TQTextStream::UnicodeUTF8 );
connect( m_socket, TQT_SIGNAL(connected()), this, TQT_SLOT(slotConnected()) );
connect( m_socket, TQT_SIGNAL(hostFound()), this, TQT_SLOT(slotHostFound()) );
connect( m_socket, TQT_SIGNAL(connectionClosed()), this, TQT_SLOT(slotConnectionClosed()) );
connect( m_socket, TQT_SIGNAL(error(int)), this, TQT_SLOT(slotError(int)) );
connect( m_socket, TQT_SIGNAL(readyRead()), this, TQT_SLOT(slotReadyRead()) );
}
K3bCddbpQuery::~K3bCddbpQuery()
{
delete m_socket;
}
void K3bCddbpQuery::doQuery()
{
setError( WORKING );
m_state = GREETING;
// connect to the server
m_socket->connectToHost( m_server, m_port );
emit infoMessage( i18n("Searching %1 on port %2").arg(m_server).arg(m_port) );
}
void K3bCddbpQuery::doMatchQuery()
{
// we should still be connected
// TODO: check this
TQString read = TQString( "cddb read %1 %2").arg( header().category ).arg( header().discid );
m_state = READ;
m_parsingBuffer = "";
kdDebug() << "(K3bCddbpQuery) Read: " << read << endl;
m_stream << read << endl << flush;
}
void K3bCddbpQuery::slotHostFound()
{
emit infoMessage( i18n("Host found") );
}
void K3bCddbpQuery::slotConnected()
{
emit infoMessage( i18n("Connected") );
}
void K3bCddbpQuery::slotConnectionClosed()
{
emit infoMessage( i18n("Connection closed") );
emitQueryFinished();
}
void K3bCddbpQuery::cddbpQuit()
{
m_state = TQUIT;
m_stream << "quit" << endl << flush;
}
void K3bCddbpQuery::slotReadyRead()
{
while( m_socket->canReadLine() ) {
TQString line = m_stream.readLine();
// kdDebug() << "(K3bCddbpQuery) line: " << line << endl;
switch( m_state ) {
case GREETING:
if( getCode( line ) == 200 || getCode( line ) == 201) {
emit infoMessage( i18n("OK, read access") );
m_state = HANDSHAKE;
m_stream << "cddb hello " << handshakeString() << endl << flush;
}
else {
emit infoMessage( i18n("Connection refused") );
setError( CONNECTION_ERROR );
m_socket->close();
}
break;
case HANDSHAKE:
if( getCode( line ) == 200 ) {
emit infoMessage( i18n("Handshake successful") );
m_state = PROTO;
m_stream << "proto 6" << endl << flush;
}
else {
emit infoMessage( i18n("Handshake failed") ); // server closes connection
setError( CONNECTION_ERROR );
m_socket->close(); // just to be sure
}
break;
case PROTO:
{
if( getCode( line ) == 501 ) {
kdDebug() << "(K3bCddbpQuery) illigal protocol level!" << endl;
}
// just ignore the reply since it's not important for the functionality
m_state = TQUERY;
m_stream << queryString() << endl << flush;
break;
}
case TQUERY:
if( getCode( line ) == 200 ) {
// parse exact match and send a read command
K3bCddbResultHeader header;
parseMatchHeader( line.mid( 4 ), header );
emit infoMessage( i18n("Found exact match") );
queryMatch( header );
}
else if( getCode( line ) == 210 ) {
// TODO: perhaps add an "exact" field to K3bCddbEntry
kdDebug() << "(K3bCddbpQuery) Found multiple exact matches" << endl;
emit infoMessage( i18n("Found multiple exact matches") );
m_state = TQUERY_DATA;
}
else if( getCode( line ) == 211 ) {
kdDebug() << "(K3bCddbpQuery) Found inexact matches" << endl;
emit infoMessage( i18n("Found inexact matches") );
m_state = TQUERY_DATA;
}
else if( getCode( line ) == 202 ) {
kdDebug() << "(K3bCddbpQuery) no match found" << endl;
emit infoMessage( i18n("No match found") );
setError( NO_ENTRY_FOUND );
cddbpQuit();
}
else {
kdDebug() << "(K3bCddbpQuery) Error while querying: " << line << endl;
emit infoMessage( i18n("Error while querying") );
setError( TQUERY_ERROR );
cddbpQuit();
}
break;
case TQUERY_DATA:
if( line.startsWith( "." ) ) {
// finished query
// go on reading
emit inexactMatches( this );
return;
}
else {
kdDebug() << "(K3bCddbpQuery) inexact match: " << line << endl;
K3bCddbResultHeader header;
parseMatchHeader( line, header );
m_inexactMatches.append( header );
}
break;
case READ:
if( getCode( line ) == 210 ) {
// we just start parsing the read data
m_state = READ_DATA;
}
else {
emit infoMessage( i18n("Could not read match") );
setError( READ_ERROR );
cddbpQuit();
}
break;
case READ_DATA:
// kdDebug() << "(K3bCddbpQuery) parsing line: " << line << endl;
if( line.startsWith( "." ) ) {
kdDebug() << "(K3bCddbpQuery) query finished." << endl;
TQTextStream strStream( m_parsingBuffer, IO_ReadOnly );
parseEntry( strStream, result() );
setError( SUCCESS );
cddbpQuit();
}
else {
m_parsingBuffer.append(line + "\n");
}
break;
case TQUIT:
// no parsing needed
break;
}
}
}
void K3bCddbpQuery::slotError( int e )
{
switch(e) {
case TQSocket::ErrConnectionRefused:
kdDebug() << i18n("Connection to %1 refused").arg( m_server ) << endl;
emit infoMessage( i18n("Connection to %1 refused").arg( m_server ) );
break;
case TQSocket::ErrHostNotFound:
kdDebug() << i18n("Could not find host %1").arg( m_server ) << endl;
emit infoMessage( i18n("Could not find host %1").arg( m_server ) );
break;
case TQSocket::ErrSocketRead:
kdDebug() << i18n("Error while reading from %1").arg( m_server ) << endl;
emit infoMessage( i18n("Error while reading from %1").arg( m_server ) );
break;
}
m_socket->close();
emitQueryFinished();
}
#include "k3bcddbpquery.moc"