File indexing completed on 2024-04-28 12:40:11

0001 /*
0002     SPDX-FileCopyrightText: 2002 Rik Hemsley (rikkus) <rik@kde.org>
0003     SPDX-FileCopyrightText: 2002-2005 Benjamin C. Meyer <ben at meyerhome dot net>
0004     SPDX-FileCopyrightText: 2003 Richard Lärkäng <nouseforaname@home.se>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "client.h"
0010 
0011 #include "asynccddbplookup.h"
0012 #include "asynchttplookup.h"
0013 #include "asynchttpsubmit.h"
0014 #include "cache.h"
0015 #include "logging.h"
0016 #include "lookup.h"
0017 #include "synccddbplookup.h"
0018 #include "synchttplookup.h"
0019 #include "synchttpsubmit.h"
0020 
0021 #include "config-musicbrainz.h"
0022 #ifdef HAVE_MUSICBRAINZ5
0023 #include "musicbrainz/musicbrainzlookup.h"
0024 #include "musicbrainz/asyncmusicbrainzlookup.h"
0025 #endif
0026 
0027 namespace KCDDB
0028 {
0029   class Client::Private
0030   {
0031     public:
0032 
0033       Private()
0034         : cdInfoLookup(nullptr),
0035           cdInfoSubmit(nullptr),
0036           block( true )
0037       {}
0038 
0039       ~Private()
0040       {
0041         delete cdInfoLookup;
0042         delete cdInfoSubmit;
0043         qDeleteAll(pendingLookups);
0044       }
0045 
0046       Lookup * cdInfoLookup;
0047       Submit * cdInfoSubmit;
0048 
0049       Config config;
0050       CDInfoList cdInfoList;
0051       TrackOffsetList trackOffsetList;
0052       QList<Lookup *> pendingLookups;
0053       bool block;
0054   };
0055 
0056   Client::Client()
0057     : d(new Private)
0058   {
0059     d->config.load();
0060   }
0061 
0062   Client::~Client()
0063   {
0064     delete d;
0065   }
0066 
0067     Config &
0068   Client::config() const
0069   {
0070     return d->config;
0071   }
0072 
0073     void
0074   Client::setBlockingMode( bool enable )
0075   {
0076     d->block = enable;
0077   }
0078 
0079     bool
0080   Client::blockingMode() const
0081   {
0082     return d->block;
0083   }
0084 
0085     CDInfoList
0086   Client::lookupResponse() const
0087   {
0088     return d->cdInfoList;
0089   }
0090 
0091     Result
0092   Client::lookup(const TrackOffsetList & trackOffsetList)
0093   {
0094     d->cdInfoList.clear();
0095     d->trackOffsetList = trackOffsetList;
0096 
0097     if ( trackOffsetList.count() <= 1 )
0098     {
0099       qCDebug(LIBKCDDB) << "Lookup called with empty offset list";
0100       return NoRecordFound;
0101     }
0102 
0103     if ( d->config.cacheLookupEnabled() )
0104     {
0105       d->cdInfoList = Cache::lookup( trackOffsetList, config() );
0106 
0107       qCDebug(LIBKCDDB) << "Found " << d->cdInfoList.count() << " hit(s)";
0108 
0109       if ( !d->cdInfoList.isEmpty() )
0110       {
0111         if ( !blockingMode() )
0112           Q_EMIT finished( Success );
0113 
0114         return Success;
0115       }
0116     }
0117 
0118     Result r = NoRecordFound;
0119 
0120     // just in case we have an info lookup hanging around, prevent mem leakage
0121     delete d->cdInfoLookup;
0122     d->cdInfoLookup = nullptr;
0123     qDeleteAll(d->pendingLookups);
0124     d->pendingLookups.clear();
0125 
0126     if ( blockingMode() )
0127     {
0128 #ifdef HAVE_MUSICBRAINZ5
0129       if ( d->config.musicBrainzLookupEnabled() )
0130       {
0131         d->cdInfoLookup = new MusicBrainzLookup();
0132 
0133         r = d->cdInfoLookup->lookup( d->config.hostname(),
0134                 d->config.port(), trackOffsetList );
0135 
0136         if ( Success == r )
0137         {
0138           d->cdInfoList = d->cdInfoLookup->lookupResponse();
0139           Cache::store( d->trackOffsetList, d->cdInfoList, config() );
0140 
0141           return r;
0142         }
0143 
0144         delete d->cdInfoLookup;
0145         d->cdInfoLookup = nullptr;
0146       }
0147 #endif
0148 
0149       if ( d->config.freedbLookupEnabled() )
0150       {
0151         Lookup::Transport t = ( Lookup::Transport )d->config.freedbLookupTransport();
0152         if( Lookup::CDDBP == t )
0153           d->cdInfoLookup = new SyncCDDBPLookup();
0154         else
0155           d->cdInfoLookup = new SyncHTTPLookup();
0156 
0157         r = d->cdInfoLookup->lookup( d->config.hostname(),
0158                 d->config.port(), trackOffsetList );
0159 
0160         if ( Success == r )
0161         {
0162           d->cdInfoList = d->cdInfoLookup->lookupResponse();
0163           Cache::store( d->trackOffsetList, d->cdInfoList, config() );
0164 
0165           return r;
0166         }
0167 
0168         delete d->cdInfoLookup;
0169         d->cdInfoLookup = nullptr;
0170       }
0171 
0172       return r;
0173     }
0174     else
0175     {
0176 #ifdef HAVE_MUSICBRAINZ5
0177       if ( d->config.musicBrainzLookupEnabled() )
0178       {
0179         AsyncMusicBrainzLookup* lookup = new AsyncMusicBrainzLookup();
0180 
0181         connect( lookup, &AsyncMusicBrainzLookup::finished,
0182                  this, &Client::slotFinished );
0183         d->pendingLookups.append( lookup );
0184       }
0185 #endif
0186 
0187       if ( d->config.freedbLookupEnabled() )
0188       {
0189         Lookup::Transport t = ( Lookup::Transport )d->config.freedbLookupTransport();
0190 
0191         if( Lookup::CDDBP == t )
0192         {
0193           AsyncCDDBPLookup* lookup = new AsyncCDDBPLookup();
0194 
0195           connect( lookup, &AsyncCDDBPLookup::finished,
0196                    this, &Client::slotFinished );
0197           d->pendingLookups.append( lookup );
0198         }
0199         else
0200         {
0201           AsyncHTTPLookup* lookup = new AsyncHTTPLookup();
0202 
0203           connect( lookup, &AsyncHTTPLookup::finished,
0204                    this, &Client::slotFinished );
0205           d->pendingLookups.append( lookup );
0206         }
0207       }
0208 
0209       return runPendingLookups();
0210     }
0211   }
0212 
0213     void
0214   Client::slotFinished( Result r )
0215   {
0216     if ( d->cdInfoLookup && Success == r )
0217     {
0218       d->cdInfoList = d->cdInfoLookup->lookupResponse();
0219       Cache::store( d->trackOffsetList, d->cdInfoList, config() );
0220     }
0221     else
0222       d->cdInfoList.clear();
0223 
0224     if ( d->cdInfoLookup ) // in case someone called lookup() while finished() was being processed, and deleted cdInfoLookup.
0225     {
0226       d->cdInfoLookup->deleteLater();
0227       d->cdInfoLookup = nullptr;
0228     }
0229 
0230     if ( Success == r )
0231     {
0232       Q_EMIT finished( r );
0233       qDeleteAll( d->pendingLookups );
0234       d->pendingLookups.clear();
0235     }
0236     else
0237     {
0238       runPendingLookups();
0239     }
0240   }
0241 
0242     void
0243   Client::slotSubmitFinished( Result r )
0244   {
0245     Q_EMIT finished( r );
0246 
0247     d->cdInfoSubmit->deleteLater();
0248     d->cdInfoSubmit=nullptr;
0249   }
0250 
0251     Result
0252   Client::submit(const CDInfo &cdInfo, const TrackOffsetList& offsetList)
0253   {
0254     // Check if it's valid
0255 
0256     if (!cdInfo.isValid())
0257       return CannotSave;
0258 
0259     uint last=0;
0260     for (int i=0; i < offsetList.count(); i++)
0261     {
0262       if(last >= offsetList[i])
0263         return CannotSave;
0264       last = offsetList[i];
0265     }
0266 
0267     //TODO Check that it is edited
0268 
0269     // just in case we have a cdInfoSubmit, prevent memory leakage
0270     delete d->cdInfoSubmit;
0271 
0272     QString from = d->config.emailAddress();
0273 
0274     QString hostname = d->config.httpSubmitServer();
0275     uint port = d->config.httpSubmitPort();
0276 
0277     if ( blockingMode() )
0278       d->cdInfoSubmit = new SyncHTTPSubmit(from, hostname, port);
0279     else
0280     {
0281       d->cdInfoSubmit = new AsyncHTTPSubmit(from, hostname, port);
0282       connect( static_cast<AsyncHTTPSubmit *>( d->cdInfoSubmit ),
0283               &AsyncHTTPSubmit::finished,
0284               this, &Client::slotSubmitFinished );
0285     }
0286 
0287     Result r = d->cdInfoSubmit->submit( cdInfo, offsetList );
0288 
0289     if ( blockingMode() )
0290     {
0291       delete d->cdInfoSubmit;
0292       d->cdInfoSubmit = nullptr;
0293     }
0294 
0295     return r;
0296   }
0297 
0298     Result
0299   Client::runPendingLookups()
0300   {
0301     if (!d->pendingLookups.empty())
0302     {
0303       d->cdInfoLookup = d->pendingLookups.takeFirst();
0304 
0305       Result r = d->cdInfoLookup->lookup( d->config.hostname(),
0306               d->config.port(), d->trackOffsetList );
0307 
0308       if ( Success != r )
0309       {
0310         delete d->cdInfoLookup;
0311         d->cdInfoLookup = nullptr;
0312       }
0313 
0314       return r;
0315     }
0316     else
0317     {
0318       Q_EMIT finished( NoRecordFound );
0319       return NoRecordFound;
0320     }
0321   }
0322 
0323     void
0324   Client::store(const CDInfo &cdInfo, const TrackOffsetList& offsetList)
0325   {
0326     Cache::store(offsetList, cdInfo, config());
0327   }
0328 }
0329 
0330 #include "moc_client.cpp"
0331 
0332 // vim:tabstop=2:shiftwidth=2:expandtab:cinoptions=(s,U1,m1