#ifndef LIBSCROBBLER_H__#define LIBSCROBBLER_H__#include <vector>#include "StdString.h"#include "Thread.h"#include "FileSystem/FileCurl.h"#include "CriticalSection.h"namespace MUSIC_INFO{ class CMusicInfoTag;}/* The following structure describes an entry in the scrobbler submission * journal. Declare members added purely for convenience at the top and * members which will actually be read/written from/to disk under a * version number comment. Also, remember to bump the version macro in * scrobbler.cpp. */typedef struct SubmissionJournalEntry_s{ int length; // v0 CStdString strArtist; CStdString strAlbum; CStdString strTitle; CStdString strLength; // Required if strSource below is "P" CStdString strStartTime; CStdString strMusicBrainzID; // v1 CStdString strTrackNum; CStdString strSource; /* strSource must be one of the following. * P: Chosen by the user (the most common value, unless you have a reason * for choosing otherwise, use this). * R: Non-personalised broadcast (e.g. Shoutcast, BBC Radio 1). * E: Personalised recommendation except Last.fm (e.g. Pandora, Launchcast). * L: Last.fm (any mode). In this case, the 5-digit Last.fm recommendation * key must be appended to this source ID to prove the validity of the * submission (for example, "o[0]=L1b48a"). * U: Source unknown. */ CStdString strRating; /* strRating must be one of the following or empty. * L: Love (on any mode if the user has manually loved the track). This * implies a listen. * B: Ban (only if source=L). This implies a skip, and the client should * skip to the next track when a ban happens. * S: Skip (only if source=L) * * NOTE: This will eventually replace the love/ban web service. */ SubmissionJournalEntry_s() {} SubmissionJournalEntry_s(const struct SubmissionJournalEntry_s& j) { strArtist = j.strArtist; strAlbum = j.strAlbum; strTitle = j.strTitle; strLength = j.strLength; strStartTime = j.strStartTime; strMusicBrainzID = j.strMusicBrainzID; strTrackNum = j.strTrackNum; strSource = j.strSource; strRating = j.strRating; length = j.length; } void Clear() { strArtist.clear(); strAlbum.clear(); strTitle.clear(); strLength.clear(); strStartTime.clear(); strMusicBrainzID.clear(); strTrackNum.clear(); strSource = "P"; strRating.clear(); length = 0; }} SubmissionJournalEntry;typedef std::vector<SubmissionJournalEntry>::iterator SCROBBLERJOURNALITERATOR;class CScrobbler : public CThread{private: static long m_instanceLock; static CScrobbler *m_pInstance; bool m_bRunThread; bool m_bNotified; bool m_bSubmitted; bool m_bBanned; bool m_bBadAuth; int m_submissionTimer; int m_hardErrorCount; int m_failedHandshakeDelay; int m_action; time_t m_lastFailedHandshake; CStdString m_strUsername; CStdString m_strPasswordHash; CStdString m_strSessionID; CStdString m_strNowPlayingURL; CStdString m_strSubmissionURL; CStdString m_strHandshakeTimeStamp; SubmissionJournalEntry m_CurrentTrack; HANDLE m_hEvent; XFILE::CFileCurl m_http; CCriticalSection m_journalLock; CCriticalSection m_actionLock; std::vector<SubmissionJournalEntry> m_vecSubmissionQueue;private: void ResetState(); void ClearErrorState(); void ClearSubmissionState(); void ClearSession(); void HandleHardError(); bool CanScrobble(); bool LoadJournal(); bool SaveJournal(); bool DoHandshake(time_t now); bool HandleHandshake(CStdString &strResponse); bool DoNowPlayingNotification(); bool HandleNowPlayingNotification(CStdString &strResponse); bool DoSubmission(); bool HandleSubmission(CStdString &strResponse); CStdString GetJournalFileName(); virtual void Process();public: CScrobbler(); virtual ~CScrobbler(); static CScrobbler *GetInstance(); static void RemoveInstance(); void Init(); void Term(); void AddSong(const MUSIC_INFO::CMusicInfoTag &tag); void UpdateStatus(); void SubmitQueue(); void SetUsername(const CStdString &strUser); void SetPassword(const CStdString &strPass);};#endif // LIBSCROBBLER_H__