// (c) 2004 Christian Muehlhaeuser // (c) 2004 Sami Nieminen // (c) 2006 Shane King // (c) 2006 Iain Benson // See COPYING file for licensing information #ifndef AMAROK_SCROBBLER_H #define AMAROK_SCROBBLER_H #include "engineobserver.h" #include #include #include #include #include //some setups require this #undef PROTOCOL_VERSION namespace TDEIO { class Job; } class TQStringList; class SubmitItem; class SubmitQueue; class ScrobblerSubmitter; class Scrobbler : public TQObject, public EngineObserver { friend class MediaDevice; Q_OBJECT public: static Scrobbler *instance(); 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 void similarArtists( const TQString & /*artist*/ ); protected: Scrobbler(); ~Scrobbler(); void engineNewMetaData( const MetaBundle& /*bundle*/, bool /*state*/ ); void engineTrackPositionChanged( long /*position*/ , bool /*userSeek*/ ); private slots: void audioScrobblerSimilarArtistsResult( TDEIO::Job* /*job*/ ); void audioScrobblerSimilarArtistsData( TDEIO::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; TDEIO::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 { protected: int compareItems( TQPtrCollection::Item item1, TQPtrCollection::Item item2 ); }; class ScrobblerSubmitter : public TQObject { Q_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( TDEIO::Job* /*job*/ ); void audioScrobblerSubmitResult( TDEIO::Job* /*job*/ ); void audioScrobblerSubmitData( TDEIO::Job* /*job*/, const TQByteArray& /*data*/ ); private: bool canSubmit() const; void enqueueItem( SubmitItem* /* item */ ); SubmitItem* dequeueItem(); void enqueueJob( TDEIO::Job* /* job */ ); void finishJob( TDEIO::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 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 */