mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-04-07 01:13:50 +02:00
* Removed a debugging printf() from 'lib/rdcddblookup.cpp'. Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
415 lines
10 KiB
C++
415 lines
10 KiB
C++
// rdcddblookup.cpp
|
|
//
|
|
// RDDiscLookup instance class for accessing the FreeDB CD Database.
|
|
//
|
|
// (C) Copyright 2003-2022 Fred Gleason <fredg@paravelsystems.com>
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU Library General Public License
|
|
// version 2 as published by the Free Software Foundation.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public
|
|
// License along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
//
|
|
//
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <q3process.h>
|
|
|
|
#include <qapplication.h>
|
|
#include <qdatetime.h>
|
|
#include <qregexp.h>
|
|
#include <qtimer.h>
|
|
|
|
#include "rdapplication.h"
|
|
#include "rdcddblookup.h"
|
|
#include "rdprofile.h"
|
|
|
|
RDCddbLookup::RDCddbLookup(const QString &caption,FILE *profile_msgs,
|
|
QWidget *parent)
|
|
: RDDiscLookup(caption,profile_msgs,parent)
|
|
{
|
|
lookup_state=0;
|
|
|
|
setWindowTitle(caption+" - "+tr("CDDB Query"));
|
|
|
|
//
|
|
// Socket
|
|
//
|
|
lookup_socket=new QTcpSocket(this);
|
|
connect(lookup_socket,SIGNAL(readyRead()),this,SLOT(readyReadData()));
|
|
connect(lookup_socket,SIGNAL(error(QAbstractSocket::SocketError)),
|
|
this,SLOT(errorData(QAbstractSocket::SocketError)));
|
|
}
|
|
|
|
|
|
RDCddbLookup::~RDCddbLookup()
|
|
{
|
|
delete lookup_socket;
|
|
}
|
|
|
|
|
|
QString RDCddbLookup::sourceName() const
|
|
{
|
|
return QString("CDDB");
|
|
}
|
|
|
|
|
|
void RDCddbLookup::lookupRecord()
|
|
{
|
|
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
|
|
|
lookup_username=rda->user()->name();
|
|
lookup_hostname=rda->libraryConf()->cddbServer();
|
|
lookup_appname="rivendell";
|
|
lookup_appver=VERSION;
|
|
|
|
profile("starting CDDB lookup");
|
|
lookup_socket->connectToHost(lookup_hostname,RDCDDBLOOKUP_DEFAULT_PORT);
|
|
}
|
|
|
|
|
|
void RDCddbLookup::readyReadData()
|
|
{
|
|
QString line;
|
|
QString tag;
|
|
QString value;
|
|
int index;
|
|
int code;
|
|
char buffer[2048];
|
|
char offset[256];
|
|
QStringList f0;
|
|
bool ok=false;
|
|
int index_line;
|
|
|
|
while(lookup_socket->canReadLine()) {
|
|
line=QString::fromUtf8(lookup_socket->readLine());
|
|
profile("recevied from server: \""+line+"\"");
|
|
code=line.split(" ").at(0).toInt();
|
|
switch(lookup_state) {
|
|
case 0: // Login Banner
|
|
if((code==200)||(code==201)) {
|
|
snprintf(buffer,2048,"cddb hello %s %s %s %s",
|
|
(const char *)lookup_username.utf8(),
|
|
(const char *)lookup_hostname.utf8(),
|
|
(const char *)lookup_appname.utf8(),
|
|
(const char *)lookup_appver.utf8());
|
|
SendToServer(buffer);
|
|
lookup_state=1;
|
|
}
|
|
else {
|
|
FinishCddbLookup(RDCddbLookup::LookupError,
|
|
"Unexpected response from CDDB server");
|
|
}
|
|
break;
|
|
|
|
case 1: // Handshake Response
|
|
if((code==200)||(code==402)) {
|
|
SendToServer("proto 6");
|
|
lookup_state=2;
|
|
}
|
|
else {
|
|
FinishCddbLookup(RDCddbLookup::LookupError,
|
|
"Unexpected response from CDDB server");
|
|
}
|
|
break;
|
|
|
|
case 2: // Protocol Level Response
|
|
if(code==201) {
|
|
snprintf(buffer,2048,"cddb query %08x %d",
|
|
discRecord()->discId(),discRecord()->tracks());
|
|
for(int i=0;i<discRecord()->tracks();i++) {
|
|
snprintf(offset,256," %d",discRecord()->trackOffset(i));
|
|
strcat(buffer,offset);
|
|
}
|
|
snprintf(offset,256," %d",discRecord()->discLength()/75);
|
|
strcat(buffer,offset);
|
|
SendToServer(buffer);
|
|
lookup_state=3;
|
|
}
|
|
else {
|
|
FinishCddbLookup(RDCddbLookup::LookupError,
|
|
"Unexpected response from CDDB server");
|
|
}
|
|
break;
|
|
|
|
case 3: // Query Response
|
|
switch(code) {
|
|
case 200: // Exact Match
|
|
case 201: // Exact Match,read-only
|
|
f0=line.split(" ");
|
|
if(f0.size()>=4) {
|
|
discRecord()->setDiscId(f0[2].toUInt(&ok,16));
|
|
if(!ok) {
|
|
FinishCddbLookup(RDCddbLookup::LookupError,
|
|
"Invalid discid received from CDDB server");
|
|
}
|
|
discRecord()->setDiscGenre(f0[1]);
|
|
f0.erase(f0.begin());
|
|
f0.erase(f0.begin());
|
|
f0.erase(f0.begin());
|
|
discRecord()->setDiscTitle(RDDiscRecord::RemoteSource,f0.join(" "));
|
|
snprintf(buffer,2048,"cddb read %s %08x\n",
|
|
(const char *)discRecord()->discGenre().utf8(),
|
|
discRecord()->discId());
|
|
SendToServer(buffer);
|
|
lookup_state=5;
|
|
}
|
|
else {
|
|
FinishCddbLookup(RDCddbLookup::LookupError,
|
|
"Unexpected response from CDDB server");
|
|
}
|
|
break;
|
|
|
|
case 210: // Multiple Exact Matches
|
|
titlesBox()->clear();
|
|
titlesKey()->clear();
|
|
lookup_state=4;
|
|
break;
|
|
|
|
case 202: // No Match
|
|
case 211: // Inexact Match
|
|
case 230:
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,"OK");
|
|
break;
|
|
|
|
case 401:
|
|
case 402:
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,"Server failure");
|
|
break;
|
|
|
|
case 403:
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,
|
|
"CDDB database entry is corrupt");
|
|
break;
|
|
|
|
case 409:
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,"No handshake");
|
|
break;
|
|
|
|
case 431:
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,
|
|
"Handshake not successful, closing connection");
|
|
break;
|
|
|
|
case 432:
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,
|
|
"No connections allowed: permission denied");
|
|
break;
|
|
|
|
case 433:
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,
|
|
"No connections allowed: too many users");
|
|
break;
|
|
|
|
case 434:
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,
|
|
"No connections allowed: system load too high");
|
|
break;
|
|
|
|
case 501:
|
|
case 502:
|
|
case 503:
|
|
case 530:
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,"Server error");
|
|
break;
|
|
|
|
default:
|
|
FinishCddbLookup(RDCddbLookup::LookupError,
|
|
"Unexpected response from CDDB server");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 4: // Process Multiple Matches
|
|
if(line.trimmed()==".") {
|
|
profile("Match list complete, showing chooser dialog...");
|
|
QApplication::restoreOverrideCursor();
|
|
if((index_line=exec())>=0) {
|
|
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
|
f0=titlesKey()->at(index_line).split(" ",QString::SkipEmptyParts);
|
|
if(f0.size()!=2) {
|
|
FinishCddbLookup(RDCddbLookup::LookupError,
|
|
"Unexpected response from CDDB server");
|
|
}
|
|
discRecord()->setDiscId(f0.at(1).toUInt(&ok,16));
|
|
if(!ok) {
|
|
FinishCddbLookup(RDCddbLookup::LookupError,
|
|
"Invalid discid received from CDDB server");
|
|
}
|
|
discRecord()->setDiscGenre(f0.at(0));
|
|
f0=titlesBox()->currentText().split("/");
|
|
if(f0.size()==2) {
|
|
discRecord()->setDiscTitle(RDDiscRecord::RemoteSource,
|
|
f0.at(1).trimmed());
|
|
}
|
|
else {
|
|
discRecord()->setDiscTitle(RDDiscRecord::RemoteSource,
|
|
titlesBox()->currentText().trimmed());
|
|
}
|
|
snprintf(buffer,2048,"cddb read %s %08x\n",
|
|
(const char *)discRecord()->discGenre().utf8(),
|
|
discRecord()->discId());
|
|
SendToServer(buffer);
|
|
lookup_state=5;
|
|
}
|
|
else {
|
|
FinishCddbLookup(RDCddbLookup::NoMatch,"OK");
|
|
}
|
|
}
|
|
else {
|
|
f0.clear();
|
|
f0=line.split(" ");
|
|
titlesKey()->push_back(f0.at(0).trimmed()+" "+
|
|
f0.at(1).trimmed());
|
|
f0.removeFirst();
|
|
f0.removeFirst();
|
|
titlesBox()->insertItem(titlesBox()->count(),f0.join(" ").trimmed());
|
|
}
|
|
break;
|
|
|
|
case 5: // Read Response
|
|
if((code==210)) {
|
|
lookup_state=6;
|
|
}
|
|
else {
|
|
FinishCddbLookup(RDCddbLookup::LookupError,
|
|
"Unexpected response from CDDB server");
|
|
}
|
|
break;
|
|
|
|
case 6: // Record Lines
|
|
if(line[0]!='#') { // Ignore Comments
|
|
if(line[0]=='.') { // Done
|
|
FinishCddbLookup(RDCddbLookup::ExactMatch,"OK");
|
|
}
|
|
ParsePair(&line,&tag,&value,&index);
|
|
if(tag=="DTITLE") {
|
|
discRecord()->setDiscTitle(RDDiscRecord::RemoteSource,
|
|
value.left(value.length()-1));
|
|
}
|
|
if(tag=="DYEAR") {
|
|
discRecord()->setDiscYear(value.toUInt());
|
|
}
|
|
if(tag=="EXTD") {
|
|
discRecord()->
|
|
setDiscExtended(discRecord()->discExtended()+
|
|
DecodeString(value));
|
|
}
|
|
if(tag=="PLAYORDER") {
|
|
discRecord()->setDiscPlayOrder(value);
|
|
}
|
|
if((tag=="TTITLE")&&(index!=-1)) {
|
|
discRecord()->setTrackTitle(RDDiscRecord::RemoteSource,index,
|
|
value.left(value.length()-1));
|
|
}
|
|
if((tag=="EXTT")&&(index!=-1)) {
|
|
discRecord()->
|
|
setTrackExtended(index,
|
|
discRecord()->trackExtended(index)+value);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void RDCddbLookup::errorData(QAbstractSocket::SocketError err)
|
|
{
|
|
QString err_msg="Network error";
|
|
switch(err) {
|
|
case QTcpSocket::ErrConnectionRefused:
|
|
err_msg="Connection to \""+rda->libraryConf()->cddbServer()+"\" refused";
|
|
break;
|
|
|
|
case QTcpSocket::ErrHostNotFound:
|
|
err_msg="Host \""+rda->libraryConf()->cddbServer()+"\" not found";
|
|
break;
|
|
|
|
case QTcpSocket::ErrSocketRead:
|
|
err_msg="Socket read error";
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
lookup_state=0;
|
|
QApplication::restoreOverrideCursor();
|
|
}
|
|
|
|
|
|
void RDCddbLookup::FinishCddbLookup(RDCddbLookup::Result res,
|
|
const QString &err_msg)
|
|
{
|
|
SendToServer("quit");
|
|
lookup_socket->close();
|
|
lookup_state=0;
|
|
QApplication::restoreOverrideCursor();
|
|
profile("CDDB lookup finished");
|
|
processLookup(res,err_msg);
|
|
}
|
|
|
|
|
|
QString RDCddbLookup::DecodeString(QString &str)
|
|
{
|
|
QString outstr;
|
|
QChar ch;
|
|
|
|
for(int i=0;i<str.length();i++) {
|
|
if((ch=str.at(i))=='\\') {
|
|
outstr+=QString("\n");
|
|
i++;
|
|
}
|
|
else {
|
|
outstr+=QString(ch);
|
|
}
|
|
}
|
|
return outstr;
|
|
}
|
|
|
|
|
|
void RDCddbLookup::ParsePair(QString *line,QString *tag,QString *value,
|
|
int *index)
|
|
{
|
|
for(int i=0;i<line->length();i++) {
|
|
if(line->at(i)=='=') {
|
|
*tag=line->left(i);
|
|
*value=line->right(line->length()-i-1);
|
|
*value=value->left(value->length()-1); // Lose the silly linefeed
|
|
*index=GetIndex(tag);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int RDCddbLookup::GetIndex(QString *tag)
|
|
{
|
|
int index;
|
|
|
|
for(int i=0;i<tag->length();i++) {
|
|
if(tag->at(i).isDigit()) {
|
|
index=tag->right(tag->length()-i).toInt();
|
|
*tag=tag->left(i);
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
void RDCddbLookup::SendToServer(const QString &msg)
|
|
{
|
|
lookup_socket->writeBlock(msg+"\n",msg.length()+1);
|
|
profile("sent to server: \""+msg+"\"");
|
|
}
|