|
|
|
/*
|
|
|
|
Copyright (C) 2000 Michael Matz <matz@kde.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.
|
|
|
|
|
|
|
|
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 <config.h>
|
|
|
|
#ifdef HAVE_SYS_TIME_H
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_SELECT_H
|
|
|
|
#include <sys/select.h>
|
|
|
|
#endif
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
//#include <tqapp.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
// #include <tqcursor.h>
|
|
|
|
//#include <kdebug.h>
|
|
|
|
#include <ksock.h>
|
|
|
|
#include <kextsock.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kinputdialog.h>
|
|
|
|
|
|
|
|
#include "cddb.h"
|
|
|
|
#include "cddb.moc"
|
|
|
|
|
|
|
|
// FIXME //kdDebug
|
|
|
|
|
|
|
|
CDDB::CDDB()
|
|
|
|
: ks(0), port(80), remote(false), save_local(false)
|
|
|
|
{
|
|
|
|
TQString s = TQDir::homeDirPath()+"/.cddb";
|
|
|
|
cddb_dirs +=s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CDDB::~CDDB()
|
|
|
|
{
|
|
|
|
deinit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
CDDB::set_server(const char *hostname, unsigned short int _port)
|
|
|
|
{
|
|
|
|
if (ks)
|
|
|
|
{
|
|
|
|
if (h_name == hostname && port == _port)
|
|
|
|
return true;
|
|
|
|
deinit();
|
|
|
|
}
|
|
|
|
remote = (hostname != 0) && (*hostname != 0);
|
|
|
|
//kdDebug(7101) << "CDDB: set_server, host=" << hostname << "port=" << _port << endl;
|
|
|
|
if (remote)
|
|
|
|
{
|
|
|
|
ks = new KExtendedSocket(hostname, _port);
|
|
|
|
if (ks->connect() < 0)
|
|
|
|
{
|
|
|
|
//kdDebug(7101) << "CDDB: Can't connect!" << endl;
|
|
|
|
delete ks;
|
|
|
|
ks = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
h_name = hostname;
|
|
|
|
port = _port;
|
|
|
|
TQCString r;
|
|
|
|
readLine(r); // the server greeting
|
|
|
|
writeLine("cddb hello kde-user blubb kio_audiocd 0.4");
|
|
|
|
readLine(r);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
CDDB::deinit()
|
|
|
|
{
|
|
|
|
if (ks)
|
|
|
|
{
|
|
|
|
writeLine("quit");
|
|
|
|
TQCString r;
|
|
|
|
readLine(r);
|
|
|
|
ks->close();
|
|
|
|
}
|
|
|
|
h_name.resize(0);
|
|
|
|
port = 0;
|
|
|
|
remote = false;
|
|
|
|
ks = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
CDDB::readLine(TQCString& ret)
|
|
|
|
{
|
|
|
|
int read_length = 0;
|
|
|
|
char small_b[128];
|
|
|
|
//fd_set set;
|
|
|
|
|
|
|
|
ret.resize(0);
|
|
|
|
while (read_length < 40000)
|
|
|
|
{
|
|
|
|
// Look for a \n in buf
|
|
|
|
int ni = buf.tqfind('\n');
|
|
|
|
if (ni >= 0)
|
|
|
|
{
|
|
|
|
// Nice, so return this substring (without the \n),
|
|
|
|
// and truncate buf accordingly
|
|
|
|
ret = buf.left(ni);
|
|
|
|
if (ret.length() && ret[ret.length()-1] == '\r')
|
|
|
|
ret.resize(ret.length());
|
|
|
|
buf.remove(0, ni+1);
|
|
|
|
//kdDebug(7101) << "CDDB: got `" << ret << "'" << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to refill the buffer
|
|
|
|
ks->waitForMore(60 * 1000);
|
|
|
|
ssize_t l = ks->readBlock(small_b, sizeof(small_b)-1);
|
|
|
|
if (l <= 0)
|
|
|
|
{
|
|
|
|
// l==0 normally means fd got closed, but we really need a lineend
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
small_b[l] = 0;
|
|
|
|
read_length += l;
|
|
|
|
buf += small_b;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
CDDB::writeLine(const TQCString& line)
|
|
|
|
{
|
|
|
|
const char *b = line.data();
|
|
|
|
int l = line.length();
|
|
|
|
//kdDebug(7101) << "CDDB: send `" << line << "'" << endl;
|
|
|
|
while (l)
|
|
|
|
{
|
|
|
|
ssize_t wl = ks->writeBlock(b, l);
|
|
|
|
if (wl < 0 && errno != EINTR)
|
|
|
|
return false;
|
|
|
|
if (wl < 0)
|
|
|
|
wl = 0;
|
|
|
|
l -= wl;
|
|
|
|
b += wl;
|
|
|
|
}
|
|
|
|
l = line.length();
|
|
|
|
if (l && line.data()[l-1] != '\n')
|
|
|
|
{
|
|
|
|
char c = '\n';
|
|
|
|
ssize_t wl;
|
|
|
|
do {
|
|
|
|
wl = ks->writeBlock(&c, 1);
|
|
|
|
} while (wl <= 0 && errno == EINTR);
|
|
|
|
if (wl<=0 && errno != EINTR)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
CDDB::get_discid(TQValueList<int>& track_ofs)
|
|
|
|
{
|
|
|
|
unsigned int id = 0;
|
|
|
|
int num_tracks = track_ofs.count() - 2;
|
|
|
|
|
|
|
|
// the last two track_ofs[] are disc begin and disc end
|
|
|
|
|
|
|
|
for (int i = num_tracks - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
int n = track_ofs[i];
|
|
|
|
n /= 75;
|
|
|
|
while (n > 0)
|
|
|
|
{
|
|
|
|
id += n % 10;
|
|
|
|
n /= 10;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
unsigned int l = track_ofs[num_tracks + 1];
|
|
|
|
l -= track_ofs[num_tracks];
|
|
|
|
l /= 75;
|
|
|
|
id = ((id % 255) << 24) | (l << 8) | num_tracks;
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
get_code (const TQCString &s)
|
|
|
|
{
|
|
|
|
bool ok;
|
|
|
|
int code = s.left(3).toInt(&ok);
|
|
|
|
if (!ok)
|
|
|
|
code = -1;
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
parse_query_resp (const TQCString& _r, TQCString& catg, TQCString& d_id, TQCString& title)
|
|
|
|
{
|
|
|
|
TQCString r = _r.stripWhiteSpace();
|
|
|
|
int i = r.tqfind(' ');
|
|
|
|
if (i)
|
|
|
|
{
|
|
|
|
catg = r.left(i).stripWhiteSpace();
|
|
|
|
r.remove(0, i+1);
|
|
|
|
r = r.stripWhiteSpace();
|
|
|
|
}
|
|
|
|
i = r.tqfind(' ');
|
|
|
|
if (i)
|
|
|
|
{
|
|
|
|
d_id = r.left(i).stripWhiteSpace();
|
|
|
|
r.remove(0, i+1);
|
|
|
|
r = r.stripWhiteSpace();
|
|
|
|
}
|
|
|
|
title = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TQString
|
|
|
|
CDDB::track(int i) const
|
|
|
|
{
|
|
|
|
if (i < 0 || i >= int(m_names.count()))
|
|
|
|
return TQString();
|
|
|
|
return m_names[i].utf8();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TQString
|
|
|
|
CDDB::artist(int i) const
|
|
|
|
{
|
|
|
|
if (i < 0 || i >= int(m_artists.count()))
|
|
|
|
return TQString();
|
|
|
|
return m_artists[i].utf8();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
CDDB::parse_read_resp(TQTextStream *stream, TQTextStream *write_stream)
|
|
|
|
{
|
|
|
|
/* Note, that m_names and m_title should be empty */
|
|
|
|
TQCString end = ".";
|
|
|
|
|
|
|
|
m_disc = 0;
|
|
|
|
m_year = 0;
|
|
|
|
m_genre = "";
|
|
|
|
|
|
|
|
/* Fill table, so we can index it below. */
|
|
|
|
for (int i = 0; i < m_tracks; i++)
|
|
|
|
{
|
|
|
|
m_names.append("");
|
|
|
|
m_artists.append("");
|
|
|
|
}
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
TQCString r;
|
|
|
|
if (stream)
|
|
|
|
{
|
|
|
|
if (stream->atEnd())
|
|
|
|
break;
|
|
|
|
r = stream->readLine().latin1();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!readLine(r))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
/* Normally the "." is not saved into the local files, but be
|
|
|
|
tolerant about this. */
|
|
|
|
if (r == end)
|
|
|
|
break;
|
|
|
|
if (write_stream)
|
|
|
|
*write_stream << r << endl;
|
|
|
|
r = r.stripWhiteSpace();
|
|
|
|
if (r.isEmpty() || r[0] == '#')
|
|
|
|
continue;
|
|
|
|
if (r.left(7) == "DTITLE=")
|
|
|
|
{
|
|
|
|
r.remove(0, 7);
|
|
|
|
m_title += TQString::fromLocal8Bit(r.stripWhiteSpace());
|
|
|
|
}
|
|
|
|
else if (r.left(6) == "TTITLE")
|
|
|
|
{
|
|
|
|
r.remove(0, 6);
|
|
|
|
int e = r.tqfind('=');
|
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
bool ok;
|
|
|
|
int i = r.left(e).toInt(&ok);
|
|
|
|
if (ok && i >= 0 && i < m_tracks)
|
|
|
|
{
|
|
|
|
r.remove(0, e+1);
|
|
|
|
m_names[i] += TQString::fromLocal8Bit(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (r.left(6) == "DYEAR=")
|
|
|
|
{
|
|
|
|
r.remove(0, 6);
|
|
|
|
TQString year = TQString::fromLocal8Bit(r.stripWhiteSpace());
|
|
|
|
m_year = year.toInt();
|
|
|
|
//kdDebug(7101) << "CDDB: found Year: " << TQString().sprintf("%04i",m_year) << endl;
|
|
|
|
}
|
|
|
|
else if (r.left(7) == "DGENRE=")
|
|
|
|
{
|
|
|
|
r.remove(0, 7);
|
|
|
|
m_genre = TQString::fromLocal8Bit(r.stripWhiteSpace());
|
|
|
|
//kdDebug(7101) << "CDDB: found Genre: " << m_genre << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX We should canonicalize the strings ("\n" --> '\n' e.g.) */
|
|
|
|
|
|
|
|
int si = m_title.tqfind(" / ");
|
|
|
|
if (si > 0)
|
|
|
|
{
|
|
|
|
m_artist = m_title.left(si).stripWhiteSpace();
|
|
|
|
m_title.remove(0, si+3);
|
|
|
|
m_title = m_title.stripWhiteSpace();
|
|
|
|
}
|
|
|
|
|
|
|
|
si = m_title.tqfind(" - CD");
|
|
|
|
if (si > 0)
|
|
|
|
{
|
|
|
|
TQString disc = m_title.right(m_title.length()-(si+5)).stripWhiteSpace();
|
|
|
|
m_disc = disc.toInt();
|
|
|
|
//kdDebug(7101) << "CDDB: found Disc: " << disc << endl;
|
|
|
|
m_title = m_title.left(si).stripWhiteSpace();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_title.isEmpty())
|
|
|
|
m_title = i18n("No Title");
|
|
|
|
/*else
|
|
|
|
m_title.tqreplace(TQRegExp("/"), "%2f");*/
|
|
|
|
if (m_artist.isEmpty())
|
|
|
|
m_artist = i18n("Unknown");
|
|
|
|
/*else
|
|
|
|
m_artist.tqreplace(TQRegExp("/"), "%2f");*/
|
|
|
|
|
|
|
|
//kdDebug(7101) << "CDDB: found Title: `" << m_title << "'" << endl;
|
|
|
|
for (int i = 0; i < m_tracks; i++)
|
|
|
|
{
|
|
|
|
if (m_names[i].isEmpty())
|
|
|
|
m_names[i] += i18n("Track %1").tqarg(i);
|
|
|
|
//m_names[i].tqreplace(TQRegExp("/"), "%2f");
|
|
|
|
si = m_names[i].tqfind(" - ");
|
|
|
|
if (si < 0)
|
|
|
|
{
|
|
|
|
si = m_names[i].tqfind(" / ");
|
|
|
|
}
|
|
|
|
if (si > 0)
|
|
|
|
{
|
|
|
|
m_artists[i] = m_names[i].left(si).stripWhiteSpace();
|
|
|
|
m_names[i].remove(0, si+3);
|
|
|
|
m_names[i] = m_names[i].stripWhiteSpace();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_artists[i] = m_artist;
|
|
|
|
}
|
|
|
|
//kdDebug(7101) << "CDDB: found Track " << i+1 << ": `" << m_names[i] << "'" << endl;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
CDDB::add_cddb_dirs(const TQStringList& list)
|
|
|
|
{
|
|
|
|
TQString s = TQDir::homeDirPath()+"/.cddb";
|
|
|
|
|
|
|
|
cddb_dirs = list;
|
|
|
|
if (cddb_dirs.isEmpty())
|
|
|
|
cddb_dirs += s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Locates and opens the local file corresponding to that discid.
|
|
|
|
Returns TRUE, if file is found and ready for reading.
|
|
|
|
Returns FALSE, if file isn't found. In this case ret_file is initialized
|
|
|
|
with a TQFile which resides in the first cddb_dir, and has a temp name
|
|
|
|
(the ID + getpid()). You can open it for writing. */
|
|
|
|
bool
|
|
|
|
CDDB::searchLocal(unsigned int id, TQFile *ret_file)
|
|
|
|
{
|
|
|
|
TQDir dir;
|
|
|
|
TQString filename;
|
|
|
|
filename = TQString("%1").tqarg(id, 0, 16).rightJustify(8, '0');
|
|
|
|
TQStringList::ConstIterator it;
|
|
|
|
for (it = cddb_dirs.begin(); it != cddb_dirs.end(); ++it)
|
|
|
|
{
|
|
|
|
dir.setPath(*it);
|
|
|
|
if (!dir.exists())
|
|
|
|
continue;
|
|
|
|
/* First look in dir directly. */
|
|
|
|
ret_file->setName (*it + "/" + filename);
|
|
|
|
if (ret_file->exists() && ret_file->open(IO_ReadOnly))
|
|
|
|
return true;
|
|
|
|
/* And then in the subdirs of dir (representing the categories normally).
|
|
|
|
*/
|
|
|
|
const TQFileInfoList *subdirs = dir.entryInfoList (TQDir::Dirs);
|
|
|
|
TQFileInfoListIterator fiit(*subdirs);
|
|
|
|
TQFileInfo *fi;
|
|
|
|
while ((fi = fiit.current()) != 0)
|
|
|
|
{
|
|
|
|
ret_file->setName (*it + "/" + fi->fileName() + "/" + filename);
|
|
|
|
if (ret_file->exists() && ret_file->open(IO_ReadOnly))
|
|
|
|
return true;
|
|
|
|
++fiit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TQString pid;
|
|
|
|
pid.setNum(::getpid());
|
|
|
|
ret_file->setName (cddb_dirs[0] + "/" + filename + "." + pid);
|
|
|
|
/* Try to create the save location. */
|
|
|
|
dir.setPath(cddb_dirs[0]);
|
|
|
|
if (save_local && !dir.exists())
|
|
|
|
{
|
|
|
|
//dir = TQDir::current();
|
|
|
|
dir.mkdir(cddb_dirs[0]);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
CDDB::queryCD(TQValueList<int>& track_ofs)
|
|
|
|
{
|
|
|
|
int num_tracks = track_ofs.count() - 2;
|
|
|
|
if (num_tracks < 1)
|
|
|
|
return false;
|
|
|
|
unsigned int id = get_discid(track_ofs);
|
|
|
|
TQFile file;
|
|
|
|
bool local;
|
|
|
|
|
|
|
|
/* Already read this ID. */
|
|
|
|
if (id == m_discid)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
emit cddbMessage(i18n("Searching local cddb entry ..."));
|
|
|
|
tqApp->processEvents();
|
|
|
|
|
|
|
|
/* First look for a local file. */
|
|
|
|
local = searchLocal (id, &file);
|
|
|
|
/* If we have no local file, and no remote connection, barf. */
|
|
|
|
if (!local && (!remote || ks == 0))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
m_tracks = num_tracks;
|
|
|
|
m_title = "";
|
|
|
|
m_artist = "";
|
|
|
|
m_names.clear();
|
|
|
|
m_discid = id;
|
|
|
|
if (local)
|
|
|
|
{
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
/* XXX Hmm, what encoding is used by CDDB files? local? Unicode?
|
|
|
|
Nothing? */
|
|
|
|
//stream.setEncoding(TQTextStream::Locale);
|
|
|
|
parse_read_resp(&stream, 0);
|
|
|
|
file.close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
emit cddbMessage(i18n("Searching remote cddb entry ..."));
|
|
|
|
tqApp->processEvents();
|
|
|
|
|
|
|
|
/* Remote CDDB query. */
|
|
|
|
unsigned int length = track_ofs[num_tracks+1] - track_ofs[num_tracks];
|
|
|
|
TQCString q;
|
|
|
|
q.sprintf("cddb query %08x %d", id, num_tracks);
|
|
|
|
TQCString num;
|
|
|
|
for (int i = 0; i < num_tracks; i++)
|
|
|
|
q += " " + num.setNum(track_ofs[i]);
|
|
|
|
q += " " + num.setNum(length / 75);
|
|
|
|
if (!writeLine(q))
|
|
|
|
return false;
|
|
|
|
TQCString r;
|
|
|
|
if (!readLine(r))
|
|
|
|
return false;
|
|
|
|
r = r.stripWhiteSpace();
|
|
|
|
int code = get_code(r);
|
|
|
|
if (code == 200)
|
|
|
|
{
|
|
|
|
TQCString catg, d_id, title;
|
|
|
|
TQDir dir;
|
|
|
|
TQCString s, pid;
|
|
|
|
|
|
|
|
emit cddbMessage(i18n("Found exact match cddb entry ..."));
|
|
|
|
tqApp->processEvents();
|
|
|
|
|
|
|
|
/* an exact match */
|
|
|
|
r.remove(0, 3);
|
|
|
|
parse_query_resp(r, catg, d_id, title);
|
|
|
|
//kdDebug(7101) << "CDDB: found exact CD: category=" << catg << " DiscId=" << d_id << " Title=`" << title << "'" << endl;
|
|
|
|
q = "cddb read " + catg + " " + d_id;
|
|
|
|
if (!writeLine(q))
|
|
|
|
return false;
|
|
|
|
if (!readLine(r))
|
|
|
|
return false;
|
|
|
|
r = r.stripWhiteSpace();
|
|
|
|
code = get_code(r);
|
|
|
|
if (code != 210)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
pid.setNum(::getpid());
|
|
|
|
s = cddb_dirs[0].latin1();
|
|
|
|
//s = s + "/" +catg; // xine seems to not search in local subdirs
|
|
|
|
dir.setPath( s );
|
|
|
|
if ( !dir.exists() ) dir.mkdir( s );
|
|
|
|
s = s+"/"+ d_id;
|
|
|
|
file.setName( s );
|
|
|
|
|
|
|
|
if (save_local && file.open(IO_WriteOnly))
|
|
|
|
{
|
|
|
|
//kdDebug(7101) << "CDDB: file name to save =" << file.name() << endl;
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
if (!parse_read_resp(0, &stream))
|
|
|
|
{
|
|
|
|
file.remove();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
/*TQString newname (file.name());
|
|
|
|
newname.truncate(newname.tqfindRev('.'));
|
|
|
|
if (TQDir::current().rename(file.name(), newname)) {
|
|
|
|
//kdDebug(7101) << "CDDB: rename failed" << endl;
|
|
|
|
file.remove();
|
|
|
|
} */
|
|
|
|
}
|
|
|
|
else if (!parse_read_resp(0, 0))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if (code == 211)
|
|
|
|
{
|
|
|
|
// Found some close matches. We'll read the query response and ask the user
|
|
|
|
// which one should be fetched from the server.
|
|
|
|
TQCString end = ".";
|
|
|
|
TQCString catg, d_id, title;
|
|
|
|
TQDir dir;
|
|
|
|
TQCString s, pid, first_match;
|
|
|
|
TQStringList disc_ids;
|
|
|
|
|
|
|
|
/* some close matches */
|
|
|
|
//XXX may be try to find marker based on r
|
|
|
|
emit cddbMessage(i18n("Found close cddb entry ..."));
|
|
|
|
tqApp->processEvents();
|
|
|
|
|
|
|
|
int i=0;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (!readLine(r))
|
|
|
|
return false;
|
|
|
|
r = r.stripWhiteSpace();
|
|
|
|
if (r == end)
|
|
|
|
break;
|
|
|
|
disc_ids.append(r);
|
|
|
|
if (i == 0)
|
|
|
|
first_match = r;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ok = false;
|
|
|
|
|
|
|
|
// We don't want to be thinking too much, do we?
|
|
|
|
// TQApplication::restoreOverrideCursor();
|
|
|
|
|
|
|
|
// Oh, mylord, which match should I serve you?
|
|
|
|
TQString _answer = KInputDialog::getItem(i18n("CDDB Matches"), i18n("Several close CDDB entries found. Choose one:"),
|
|
|
|
disc_ids, 0, false, &ok );
|
|
|
|
TQCString answer = _answer.utf8();
|
|
|
|
|
|
|
|
if (ok){ // Get user selected match
|
|
|
|
parse_query_resp(answer, catg, d_id, title);
|
|
|
|
}
|
|
|
|
else{ // Get first match
|
|
|
|
parse_query_resp(first_match, catg, d_id, title);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we can continue thinking...
|
|
|
|
// TQApplication::setOverrideCursor( TQCursor(TQt::WaitCursor) );
|
|
|
|
|
|
|
|
/*kdDebug(7101) << "CDDB: found close CD: category=" << catg << " DiscId="
|
|
|
|
<< d_id << " Title=`" << title << "'" << endl;*/
|
|
|
|
|
|
|
|
// ... and forth we go as usual
|
|
|
|
|
|
|
|
q = "cddb read " + catg + " " + d_id;
|
|
|
|
if (!writeLine(q))
|
|
|
|
return false;
|
|
|
|
if (!readLine(r))
|
|
|
|
return false;
|
|
|
|
r = r.stripWhiteSpace();
|
|
|
|
code = get_code(r);
|
|
|
|
if (code != 210)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
pid.setNum(::getpid());
|
|
|
|
s = cddb_dirs[0].latin1();
|
|
|
|
dir.setPath( s );
|
|
|
|
if ( !dir.exists() ) dir.mkdir( s );
|
|
|
|
s = s+"/"+ d_id;
|
|
|
|
file.setName( s );
|
|
|
|
|
|
|
|
if (save_local && file.open(IO_WriteOnly))
|
|
|
|
{
|
|
|
|
//kdDebug(7101) << "CDDB: file name to save =" << file.name() << endl;
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
if (!parse_read_resp(0, &stream))
|
|
|
|
{
|
|
|
|
file.remove();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
else if (!parse_read_resp(0, 0))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* 202 - no match found
|
|
|
|
403 - Database entry corrupt
|
|
|
|
409 - no handshake */
|
|
|
|
//kdDebug(7101) << "CDDB: query returned code " << code << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|