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.
amarok/amarok/src/scrobbler.h

187 lines
5.4 KiB

// (c) 2004 Christian Muehlhaeuser <chris@chris.de>
// (c) 2004 Sami Nieminen <sami.nieminen@iki.fi>
// (c) 2006 Shane King <kde@dontletsstart.com>
// (c) 2006 Iain Benson <iain@arctos.me.uk>
// See COPYING file for licensing information
#ifndef AMAROK_SCROBBLER_H
#define AMAROK_SCROBBLER_H
#include "engineobserver.h"
#include <tqdom.h>
#include <tqobject.h>
#include <tqptrdict.h>
#include <tqptrlist.h>
#include <tqtimer.h>
//some setups require this
#undef PROTOCOL_VERSION
namespace KIO { class Job; }
class TQStringList;
class SubmitItem;
class SubmitQueue;
class ScrobblerSubmitter;
class Scrobbler : public TQObject, public EngineObserver
{
friend class MediaDevice;
Q_OBJECT
TQ_OBJECT
public:
static Scrobbler *instance();
void similarArtists( const TQString & /*artist*/ );
void applySettings();
signals:
void similarArtistsFetched( const TQString& artist, const TQStringList& suggestions );
public slots:
void subTrack( long currentPos, long startPos, long endPos ); // cuefiles can update length without track change
protected:
Scrobbler();
~Scrobbler();
void engineNewMetaData( const MetaBundle& /*bundle*/, bool /*state*/ );
void engineTrackPositionChanged( long /*position*/ , bool /*userSeek*/ );
private slots:
void audioScrobblerSimilarArtistsResult( KIO::Job* /*job*/ );
void audioScrobblerSimilarArtistsData(
KIO::Job* /*job*/, const TQByteArray& /*data*/ );
private:
TQTimer m_timer; //works around xine bug
//http://sourceforge.net/tracker/index.php?func=detail&aid=1401026&group_id=9655&atid=109655
TQByteArray m_similarArtistsBuffer;
KIO::Job* m_similarArtistsJob;
TQString m_artist;
bool m_validForSending;
long m_startPos;
ScrobblerSubmitter* m_submitter;
SubmitItem* m_item;
};
class SubmitItem
{
friend class ScrobblerSubmitter;
public:
SubmitItem(
const TQString& /*artist*/,
const TQString& /*album*/,
const TQString& /*title*/,
int /*length*/,
bool now = true );
SubmitItem( const TQDomElement& /* domElement */ );
SubmitItem();
bool operator==( const SubmitItem& item );
void setArtist( const TQString& artist ) { m_artist = artist; }
void setAlbum( const TQString& album ) { m_album = album; }
void setTitle( const TQString& title ) { m_title = title; }
const TQString artist() const { return m_artist; }
const TQString album() const { return m_album; }
const TQString title() const { return m_title; }
int length() const { return m_length; }
uint playStartTime() const { return m_playStartTime; }
TQDomElement toDomElement( TQDomDocument& /* document */ ) const;
bool valid() const { return !m_artist.isEmpty() && !m_title.isEmpty() && m_length >= 30; }
private:
TQString m_artist;
TQString m_album;
TQString m_title;
int m_length;
uint m_playStartTime;
};
class SubmitQueue : public TQPtrList<SubmitItem>
{
protected:
int compareItems( TQPtrCollection::Item item1, TQPtrCollection::Item item2 );
};
class ScrobblerSubmitter : public TQObject
{
Q_OBJECT
TQ_OBJECT
public:
static TQString PROTOCOL_VERSION;
static TQString CLIENT_ID;
static TQString CLIENT_VERSION;
static TQString HANDSHAKE_URL;
ScrobblerSubmitter();
~ScrobblerSubmitter();
void submitItem( SubmitItem* /* item */ );
void configure( const TQString& /*username*/, const TQString& /* password*/, bool /*enabled*/ );
void syncComplete();
private slots:
void scheduledTimeReached();
void audioScrobblerHandshakeResult( KIO::Job* /*job*/ );
void audioScrobblerSubmitResult( KIO::Job* /*job*/ );
void audioScrobblerSubmitData(
KIO::Job* /*job*/, const TQByteArray& /*data*/ );
private:
bool canSubmit() const;
void enqueueItem( SubmitItem* /* item */ );
SubmitItem* dequeueItem();
void enqueueJob( KIO::Job* /* job */ );
void finishJob( KIO::Job* /* job */ );
void announceSubmit(
SubmitItem* /* item */, int /* tracks */, bool /* success */ ) const;
void saveSubmitQueue();
void readSubmitQueue();
bool schedule( bool failure );
void performHandshake();
void performSubmit();
// on failure, start at MIN_BACKOFF, and double on subsequent failures
// until MAX_BACKOFF is reached
static const int MIN_BACKOFF = 60;
static const int MAX_BACKOFF = 60 * 60;
TQString m_submitResultBuffer;
TQString m_username;
TQString m_password;
TQString m_submitUrl;
TQString m_challenge;
TQString m_savePath;
bool m_scrobblerEnabled;
bool m_holdFakeQueue;
bool m_inProgress;
bool m_needHandshake;
uint m_prevSubmitTime;
uint m_interval;
uint m_backoff;
uint m_lastSubmissionFinishTime;
uint m_fakeQueueLength;
TQPtrDict<SubmitItem> m_ongoingSubmits;
SubmitQueue m_submitQueue; // songs played by Amarok
SubmitQueue m_fakeQueue; // songs for which play times have to be faked (e.g. when submitting from media device)
TQTimer m_timer;
};
#endif /* AMAROK_SCROBBLER_H */