musicbrainzquery.cpp 8.28 KB
Newer Older
Zack Rusin's avatar
Zack Rusin committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// musicbrainzquery.cpp
//
// Copyright (C)  2003  Zack Rusin <zack@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., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.

20
#include <config.h>
Zack Rusin's avatar
Zack Rusin committed
21 22 23 24 25 26

#if HAVE_MUSICBRAINZ

#include "musicbrainzquery.h"

#include <kprocess.h>
27
#include <klocale.h>
28
#include <kdeversion.h>
Zack Rusin's avatar
Zack Rusin committed
29 30 31 32 33 34 35 36
#include <kdebug.h>

#include <qtimer.h>
#include <qvaluelist.h>

#include <string>
#include <vector>

37 38 39 40 41 42 43
MusicBrainzQuery::MusicBrainzQuery(QueryType query, const QStringList &args,
                                   QObject *parent, const char *name)
    : QObject(parent, name),
      MusicBrainz(),
      m_query(query),
      m_arguments(args),
      m_tracks(false)
Zack Rusin's avatar
Zack Rusin committed
44 45 46 47 48 49
{

}

void MusicBrainzQuery::start()
{
50
    if(m_query == File) {
51
#if KDE_IS_VERSION(3,1,90)
52
        KProcess *process = new KProcess(this);
53 54 55
#else
        KProcess *process = new KProcess;
#endif
56 57 58 59 60 61 62 63 64
        *process << "trm";
        *process << m_arguments.first();

        connect(process, SIGNAL(receivedStdout(KProcess *, char *, int)),
                SLOT(slotTrmData(KProcess *, char *, int)));

        connect(process, SIGNAL(processExited(KProcess *)),
                SLOT(slotTrmGenerationFinished(KProcess *)));

65
        emit signalStatusMsg( i18n( "Generating TRM signature..." ), 0 );
66
        bool started = process->start(KProcess::NotifyOnExit, KProcess::AllOutput);
67 68 69 70
        if(!started) {
            kdDebug(65432) << "trm utility could not be started." << endl;
            emit signalDone();
        }
71 72
    }
    else
Zack Rusin's avatar
Zack Rusin committed
73 74 75 76 77 78 79 80 81 82
        QTimer::singleShot(0, this, SLOT(slotQuery()));
}

void MusicBrainzQuery::slotQuery()
{
    std::string queryString;
    std::string resultString;
    std::string extractString;
    AlbumList albums;
    TrackList tracks;
83
    std::vector<std::string> v;
Zack Rusin's avatar
Zack Rusin committed
84 85 86

    queryStrings(queryString, resultString, extractString);

87
    emit signalStatusMsg( i18n( "Querying MusicBrainz server..." ), 0 );
88

89
    // UseUTF8(false);
Zack Rusin's avatar
Zack Rusin committed
90

91 92 93 94 95
    SetDepth(4);

    QStringList::ConstIterator it = m_arguments.begin();
    for(; it != m_arguments.end(); ++it)
        v.push_back(std::string((*it).latin1()));
Zack Rusin's avatar
Zack Rusin committed
96

97 98
    bool ret = Query(queryString, &v);
    if(ret) {
Zack Rusin's avatar
Zack Rusin committed
99
        int numEntries = DataInt(resultString);
100 101

        for(int i = 1; i <= numEntries; ++i) {
Zack Rusin's avatar
Zack Rusin committed
102
            Select(extractString, i);
103 104

            if(m_tracks) {
Zack Rusin's avatar
Zack Rusin committed
105 106
                Track track(extractTrack(i));
                tracks.append(track);
107 108 109 110
            }
	    else {
                Album album(extractAlbum());
                albums.append(album);
Zack Rusin's avatar
Zack Rusin committed
111 112
            }
        }
113 114
    } 
    else {
Zack Rusin's avatar
Zack Rusin committed
115 116
        std::string error;
        GetQueryError(error);
117
        kdDebug(65432) << "Query failed: " << error.c_str() << endl;
Zack Rusin's avatar
Zack Rusin committed
118 119 120
    }

    if (m_tracks)
121
        emit signalDone(tracks);
Zack Rusin's avatar
Zack Rusin committed
122
    else
123
        emit signalDone(albums);
Zack Rusin's avatar
Zack Rusin committed
124

125
    deleteLater(); // schedule deletion
Zack Rusin's avatar
Zack Rusin committed
126 127
}

128
QString MusicBrainzQuery::dataExtract(const QString &type, int i)
Zack Rusin's avatar
Zack Rusin committed
129
{
130 131 132
    std::string s = Data(type.latin1(), i);

    if(s.empty())
Zack Rusin's avatar
Zack Rusin committed
133
        return QString::null;
134 135

    return s.c_str();
Zack Rusin's avatar
Zack Rusin committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
}

void MusicBrainzQuery::queryStrings(std::string& query, std::string& result, std::string& extraction)
{
    switch(m_query) {
    case CD:
        query      = MBQ_GetCDInfo;
        result     = MBE_GetNumAlbums;
        extraction = MBS_SelectAlbum;
        break;
    case TrackFromTRM:
        query      = MBQ_TrackInfoFromTRMId;
        result     = MBE_GetNumTracks;
        extraction = MBS_SelectTrack;
        m_tracks   = true;
        break;
    case TrackFromID:
        query      = MBQ_QuickTrackInfoFromTrackId;
        result     = MBE_GetNumTracks;
        extraction = MBS_SelectTrack;
        m_tracks   = true;
        break;
    case ArtistByName:
        query      = MBQ_FindArtistByName;
        result     = MBE_GetNumArtists;
        extraction = MBS_SelectArtist ;
        break;
    case AlbumByName:
        query      = MBQ_FindAlbumByName;
        result     = MBE_GetNumAlbums;
        extraction = MBS_SelectAlbum ;
        break;
    case TrackByName:
        query      = MBQ_FindTrackByName;
        result     = MBE_GetNumTracks;
        extraction = MBS_SelectTrack;
        m_tracks   = true;
        break;
    case TRM:
        query      = MBQ_FindDistinctTRMId;
        result     = MBE_GetNumTrmids;
        extraction = MBS_SelectTrack;
        break;
    case ArtistByID:
        query      = MBQ_GetArtistById;
        result     = MBE_GetNumArtists;
        extraction = MBS_SelectArtist ;
        break;
    case AlbumByID:
        query      = MBQ_GetAlbumById;
        result     = MBE_GetNumAlbums;
        extraction = MBS_SelectAlbum;
        break;
    case TrackByID:
        query      = MBQ_GetTrackById;
        result     = MBE_GetNumTracks;
        extraction = MBS_SelectTrack;
        m_tracks   = true;
        break;
    default:
196
        kdDebug(65432) << "Unrecognized query reported" << endl;
Zack Rusin's avatar
Zack Rusin committed
197 198 199
    }
}

200
MusicBrainzQuery::Album MusicBrainzQuery::extractAlbum()
Zack Rusin's avatar
Zack Rusin committed
201
{
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
    kdDebug(65432) << "Extracting album" << endl;

    std::string s;

    GetIDFromURL(Data(MBE_AlbumGetAlbumId), s);

    Album album;

    album.id         = s.c_str();
    album.name       = dataExtract(MBE_AlbumGetAlbumName);
    album.numTracks  = DataInt(MBE_AlbumGetNumTracks);
    album.artist     = dataExtract(MBE_AlbumGetArtistName, 1);

    GetIDFromURL(Data(MBE_AlbumGetArtistId, 1), s);

    album.artistId   = s.c_str();
    album.status     = dataExtract(MBE_AlbumGetAlbumStatus);
    album.type       = dataExtract(MBE_AlbumGetAlbumType);
    album.cdIndexId  = dataExtract(MBE_AlbumGetNumCdindexIds);
Zack Rusin's avatar
Zack Rusin committed
221 222 223

    TrackList tracks;

224 225 226 227 228 229
    for(int i = 1; i <= album.numTracks; ++i)
        tracks.append(extractTrackFromAlbum(i));

    album.tracksList = tracks;

    return album;
Zack Rusin's avatar
Zack Rusin committed
230 231
}

232
MusicBrainzQuery::Track MusicBrainzQuery::extractTrackFromAlbum(int trackNumber)
Zack Rusin's avatar
Zack Rusin committed
233 234
{
    Track track;
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

    track.number      = trackNumber;
    track.name        = dataExtract(MBE_AlbumGetTrackName, trackNumber);
    track.duration    = dataExtract(MBE_AlbumGetTrackDuration, trackNumber);
    track.artist      = dataExtract(MBE_AlbumGetArtistName, trackNumber);

    std::string s;

    GetIDFromURL(Data(MBE_AlbumGetTrackId), s);

    track.id = s.empty() ? QString::null : QString(s.c_str());

    GetIDFromURL(Data(MBE_AlbumGetArtistId), s);

    track.artistId = s.empty() ? QString::null : QString(s.c_str());

Zack Rusin's avatar
Zack Rusin committed
251 252 253
    return track;
}

254
MusicBrainzQuery::Track MusicBrainzQuery::extractTrack(int trackNumber)
Zack Rusin's avatar
Zack Rusin committed
255 256
{
    Track track;
257 258 259 260 261 262 263 264 265 266 267 268
    const std::string source = Data(MBE_TrackGetTrackId);
    std::string target = source;

    track.name     = dataExtract(MBE_TrackGetTrackName, trackNumber);
    track.duration = dataExtract(MBE_TrackGetTrackDuration, trackNumber);
    track.artist   = dataExtract(MBE_TrackGetArtistName, trackNumber);
    track.album    = dataExtract(MBE_AlbumGetAlbumName, trackNumber);

    GetIDFromURL(source, target);

    track.id = target.empty() ? QString::null : QString(target.c_str());

Zack Rusin's avatar
Zack Rusin committed
269
    Select(MBS_SelectTrackAlbum);
270 271 272 273 274 275 276

    track.number = GetOrdinalFromList(MBE_AlbumGetTrackList, source);

    GetIDFromURL(Data(MBE_AlbumGetArtistId), target);

    track.artistId = target.empty() ? QString::null : QString(target.c_str());

Zack Rusin's avatar
Zack Rusin committed
277
    Select(MBS_Rewind);
278

Zack Rusin's avatar
Zack Rusin committed
279 280 281
    return track;
}

282
void MusicBrainzQuery::slotTrmData(KProcess *, char *buffer, int bufferLength)
Zack Rusin's avatar
Zack Rusin committed
283
{
284
    m_trm += QString::fromLatin1(buffer, bufferLength);
Zack Rusin's avatar
Zack Rusin committed
285 286
}

Scott Wheeler's avatar
Scott Wheeler committed
287
void MusicBrainzQuery::slotTrmGenerationFinished(KProcess *process)
Zack Rusin's avatar
Zack Rusin committed
288
{
289
#if KDE_VERSION < KDE_MAKE_VERSION(3,1,90)
Scott Wheeler's avatar
Scott Wheeler committed
290
    delete process;
291
#endif
Scott Wheeler's avatar
Scott Wheeler committed
292 293
    Q_UNUSED(process);

Zack Rusin's avatar
Zack Rusin committed
294 295 296
    m_arguments.clear();
    m_arguments << m_trm;
    m_query = TrackFromTRM;
297
    kdDebug(65432) << "Generation finished " << m_trm << endl;
298 299 300 301 302
    if (m_trm.isEmpty())
        emit signalStatusMsg( i18n( "TRM generation failed" ), 2000 );
    else
        slotQuery();
    
Zack Rusin's avatar
Zack Rusin committed
303 304 305 306 307
}

#include "musicbrainzquery.moc"

#endif