All pastes #1300006 Raw Edit

Stuff

public diff v1 · immutable
#1300006 ·published 2009-01-05 09:54 UTC
rendered paste body
Index: xbmc/lib/libscrobbler/scrobbler.h===================================================================--- xbmc/lib/libscrobbler/scrobbler.h	(revision 16881)+++ xbmc/lib/libscrobbler/scrobbler.h	(working copy)@@ -20,6 +20,9 @@ #ifndef _SCROBBLER_H #define _SCROBBLER_H +#include <vector>+using namespace std;+ namespace MUSIC_INFO {   class CMusicInfoTag;@@ -59,6 +62,24 @@  }; +typedef struct SubmissionJournalEntry_s {+  CStdString strArtist;+  CStdString strAlbum;+  CStdString strTitle;+  CStdString strLength;+  CStdString strStartTime;+  CStdString strMusicBrainzID;+  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;+  };+} SubmissionJournalEntry_t;+ /**   Audioscrobbler client class.   $Id$@@ -134,13 +155,6 @@   */   void SetUsername(const CStdString& strUser); -  /**-    Clears the internal submission cache.--    @see      setCache()-  */-  void ClearCache();-   void SetSubmitSong(bool bSubmit);   bool ShouldSubmit();   void SetSongStartTime();@@ -150,19 +164,6 @@   CStdString GetFilesCached();   void  SetSecsTillSubmit(int iSecs);   CStdString GetSubmitState();-protected:--  /**-    Sets the contents of the submission cache, to be called from -    loadCache().--    @param cache  The contents of the cache to set.-    @param numentries The number of entries in the cache.-    @see      loadCache()-    @see      clearCache()-  */-  void SetCache(const CStdString& strCache, int iNumEntries);- private:    /**@@ -194,23 +195,21 @@   /**     Override this to save the cache - called from the destructor. -    @param cache  The contents of the cache to save.-    @param numentries The number of entries in the cache - save this too.-    @see      loadCache()+    @see        LoadJournal()     @retval 1   You saved some cache.     @retval 0   You didn't save cache, or can't.   */-  virtual int SaveCache(const CStdString& strCache, int iNumEntries);+  virtual int SaveJournal();      /**     This is called when you should load the cache. Use setCache. -    @see      saveCache()-    @see      setCache()+    @see      SaveJournal()     @retval 1   You loaded some cache.     @retval 0   There was no cache to load, or you can't.   */   virtual int LoadCache();+  virtual int LoadJournal();    virtual void GenSessionKey(); @@ -230,6 +229,7 @@ #endif    CStdString GetTempFileName();+  CStdString GetJournalFileName();    CStdString m_strUserName;   CStdString m_strPassword; // MD5 hash@@ -265,8 +265,9 @@   int m_iSecsTillSubmit;   bool m_bShouldSubmit;   bool m_bReHandShaking;+  +  vector<SubmissionJournalEntry_t> m_vecSubmissionJournal; -   static CScrobbler* m_pInstance; }; Index: xbmc/lib/libscrobbler/scrobbler.cpp===================================================================--- xbmc/lib/libscrobbler/scrobbler.cpp	(revision 16881)+++ xbmc/lib/libscrobbler/scrobbler.cpp	(working copy)@@ -29,6 +29,9 @@ #include "Application.h" #include "MusicInfoTag.h" #include "FileSystem/File.h"+#include "tinyXML/tinyxml.h"+#include "XMLUtils.h"+#include "RegExp.h"  using namespace std; using namespace MUSIC_INFO;@@ -38,6 +41,7 @@ #define MINLENGTH 30 #define MAXLENGTH 10800 #define HS_FAIL_WAIT 100000+#define MAXSUBMISSIONS 50  //#define CLIENT_ID "tst" #define CLIENT_ID "xbm"@@ -118,15 +122,14 @@   SetPassword(strPassword);   SetUsername(strUserName); -  ClearCache();-  LoadCache();+  LoadJournal();   DoHandshake(); }  void CScrobbler::Term() {   m_bReadyToSubmit=false;-  SaveCache(m_strPostString.c_str(), m_iSongNum);+  SaveJournal(); }  void CScrobbler::SetPassword(const CStdString& strPass)@@ -162,18 +165,6 @@   m_strHsString = "http://post.audioscrobbler.com/?hs=true&p=1.1&c=" + m_strClientId + "&v=" + m_strClientVer + "&u=" + m_strUserName; } -void CScrobbler::ClearCache()-{-  m_iSongNum = 0;-  m_strPostString = "";-}--void CScrobbler::SetCache(const CStdString& strCache, int iNumEntries)-{-  m_strPostString = strCache;-  m_iSongNum = iNumEntries;-}- int CScrobbler::AddSong(const CMusicInfoTag& tag) {   if ((!g_guiSettings.GetBool("lastfm.enable") && !g_guiSettings.GetBool("lastfm.recordtoprofile")) || !g_guiSettings.GetBool("network.enableinternet"))@@ -195,39 +186,71 @@   struct tm *today = gmtime(&m_SongStartTime);   strftime(ti, sizeof(ti), "%Y-%m-%d %H:%M:%S", today); -  CStdString a, b, t;+  SubmissionJournalEntry_t entry;   // our tags are stored as UTF-8, so no conversion needed-  a = tag.GetArtist();-  b = tag.GetAlbum();-  t = tag.GetTitle();-  CStdString i=ti;-  CStdString m=tag.GetMusicBrainzTrackID();-  CUtil::URLEncode(a);-  CUtil::URLEncode(b);-  CUtil::URLEncode(t);-  CUtil::URLEncode(i);-  CUtil::URLEncode(m);+  entry.strArtist = tag.GetArtist();+  entry.strAlbum = tag.GetAlbum();+  entry.strTitle = tag.GetTitle();+  entry.strStartTime = ti;+  entry.strLength.Format("%d",tag.GetDuration());+  entry.strMusicBrainzID = tag.GetMusicBrainzTrackID();+  m_vecSubmissionJournal.push_back(entry);+  SaveJournal(); -  CStdString strSubmitStr;-  strSubmitStr.Format("a[%i]=%s&t[%i]=%s&b[%i]=%s&m[%i]=%s&l[%i]=%i&i[%i]=%s&", m_iSongNum, a.c_str(), m_iSongNum, t.c_str(), m_iSongNum, b.c_str(), m_iSongNum, m.c_str(), m_iSongNum, tag.GetDuration(), m_iSongNum, i.c_str());--  if(m_strPostString.find(ti) != m_strPostString.npos)+  while ((unsigned)m_iSongNum < m_vecSubmissionJournal.size() && m_iSongNum < MAXSUBMISSIONS)   {-    // we have already tried to add a song at this time stamp-    // I have no idea how this could happen but apparently it does so-    // we stop it now+    entry = m_vecSubmissionJournal[m_iSongNum];+    CStdString strStartTime = entry.strStartTime;+    CUtil::URLEncode(entry.strArtist); +    CUtil::URLEncode(entry.strTitle);+    CUtil::URLEncode(entry.strAlbum);+    CUtil::URLEncode(entry.strMusicBrainzID);+    CUtil::URLEncode(entry.strLength);+    CUtil::URLEncode(entry.strStartTime);+    CStdString strSubmitStr;+    strSubmitStr.Format("a[%i]=%s&t[%i]=%s&b[%i]=%s&m[%i]=%s&l[%i]=%s&i[%i]=%s&", +        m_iSongNum, +        entry.strArtist, +        m_iSongNum, +        entry.strTitle,+        m_iSongNum,+        entry.strAlbum,+        m_iSongNum, +        entry.strMusicBrainzID,+        m_iSongNum, +        entry.strLength,+        m_iSongNum, +        entry.strStartTime); -    StatusUpdate(S_NOT_SUBMITTING,strSubmitStr);-    StatusUpdate(S_NOT_SUBMITTING,m_strPostString);+    if(m_strPostString.find(strStartTime) != m_strPostString.npos)+    {+      // we have already tried to add a song at this time stamp+      // I have no idea how this could happen but apparently it does so+      // we stop it now -    StatusUpdate(S_NOT_SUBMITTING,"Submission error, duplicate subbmission time found");-    return 3;-  }+      StatusUpdate(S_NOT_SUBMITTING,strSubmitStr);+      StatusUpdate(S_NOT_SUBMITTING,m_strPostString);+      StatusUpdate(S_NOT_SUBMITTING,"Submission error, duplicate subbmission time found");+      +      vector<SubmissionJournalEntry_t>::iterator it = m_vecSubmissionJournal.begin();+      for (int i = 0; i <m_iSongNum; i++, it++)+        ;+      m_vecSubmissionJournal.erase(it);+      SaveJournal(); -  m_strPostString += strSubmitStr;-  m_iSongNum++;+      return 3;+    } -  SaveCache(m_strPostString.c_str(), m_iSongNum);+    // FIXME For some reason CStdString won't grow past 1036 chars...+    if(m_strPostString.length() + strSubmitStr.length() > 975) {+      printf("%d %s\n", m_strPostString.length(), m_strPostString.c_str());+      printf("%d %s\n", strSubmitStr.length(), strSubmitStr.c_str());+      break;+    }+  +    m_strPostString += strSubmitStr;+    m_iSongNum++;+  }    time_t now;   time (&now);@@ -349,10 +372,8 @@   if (stricmp("OK", response) == 0)   {     StatusUpdate(S_SUBMIT_SUCCESS,"Submission succeeded.");-     StatusUpdate(S_DEBUG,m_strPostString.c_str()); -    ClearCache();     char *inttext = strtok(NULL, seps);     if (inttext && (stricmp("INTERVAL", inttext) == 0))     {@@ -361,6 +382,14 @@       strBuf.Format("Submit interval set to %i seconds.", m_Interval);       StatusUpdate(S_SUBMIT_INTERVAL, strBuf);     }+    +    // Remove successfully submitted songs from journal and clear POST data+    printf("before: %d %d\n", m_iSongNum, m_vecSubmissionJournal.size());+    while (--m_iSongNum)+      m_vecSubmissionJournal.erase(m_vecSubmissionJournal.begin());+    printf("after: %d %d\n", m_iSongNum, m_vecSubmissionJournal.size());+    m_strPostString = "";+    SaveJournal();   }   else if (stricmp("BADPASS", response) == 0)   {@@ -432,43 +461,117 @@  int CScrobbler::LoadCache() {-  StatusUpdate(S_SUBMITTING,"load cache");--  int iNumEntries=0;-  CStdString strCache;-   CFile file;   if (file.Open(GetTempFileName()))   {     CArchive ar(&file, CArchive::load);-    ar >> iNumEntries;-    ar >> strCache;+    ar >> m_iSongNum;+    ar >> m_strPostString;     ar.Close();     file.Close();-    SetCache(strCache, iNumEntries);     return 1;   }   return 0; } -int CScrobbler::SaveCache(const CStdString& strCache, int iNumEntries)-{-  if (iNumEntries<=0)+int CScrobbler::LoadJournal() {+  SubmissionJournalEntry_t entry;+  m_vecSubmissionJournal.clear();+  +  if (LoadCache()) +  {+    // load old style cache+    CLog::Log(LOGDEBUG, "Audioscrobbler: Found old submission cache, converting to submission journal.");+    for (int i = 0; i < m_iSongNum; i++)+    {+      CStdString strRegEx;+      strRegEx.Format("a\\[%i\\]=(.*?)&t\\[%i\\]=(.*?)&b\\[%i\\]=(.*?)&m\\[%i\\]=(.*?)&l\\[%i\\]=(.*?)&i\\[%i\\]=(.*?)&", i, i, i, i, i, i);+      CRegExp re;+      if (!re.RegComp(strRegEx.c_str()))+        break;+      if (re.RegFind(m_strPostString) < 0) {+        continue;+      }+      entry.strArtist = re.GetReplaceString("\\1");+      entry.strTitle = re.GetReplaceString("\\2");+      entry.strAlbum = re.GetReplaceString("\\3");+      entry.strMusicBrainzID = re.GetReplaceString("\\4");+      entry.strLength = re.GetReplaceString("\\5");+      entry.strStartTime = re.GetReplaceString("\\6");+      CUtil::UrlDecode(entry.strArtist);+      CUtil::UrlDecode(entry.strTitle);+      CUtil::UrlDecode(entry.strAlbum);+      CUtil::UrlDecode(entry.strMusicBrainzID);+      CUtil::UrlDecode(entry.strLength);+      CUtil::UrlDecode(entry.strStartTime);+      m_vecSubmissionJournal.push_back(entry);+    }+    m_iSongNum = 0;+    m_strPostString = "";+    ::DeleteFile(GetTempFileName());+    CLog::Log(LOGDEBUG, "Audioscrobbler: Added %d entries from old cache file (%s) to journal.", m_vecSubmissionJournal.size(), GetTempFileName().c_str());+  }++  TiXmlDocument xmlDoc;+  CStdString JournalFileName = GetJournalFileName();+  if (!xmlDoc.LoadFile(JournalFileName))+  {+    CLog::Log(LOGDEBUG, "Audioscrobbler: %s, Line %d (%s)", JournalFileName.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());     return 0;+  } -  CFile file;-  if (file.OpenForWrite(GetTempFileName(), true, true)) // overwrite always+  TiXmlElement *pRoot = xmlDoc.RootElement();+  if (strcmpi(pRoot->Value(), "asjournal") != 0)   {-    CArchive ar(&file, CArchive::store);-    ar << iNumEntries;-    ar << strCache;-    ar.Close();-    file.Close();-    return 1;+    CLog::Log(LOGDEBUG, "Audioscrobbler: %s missing <asjournal>", JournalFileName.c_str());+    return 0;   }-  return 0;++  TiXmlNode *pNode = pRoot->FirstChild("entry");+  while (pNode)+  {+    XMLUtils::GetString(pNode, "artist", entry.strArtist);+    XMLUtils::GetString(pNode, "album", entry.strAlbum);+    XMLUtils::GetString(pNode, "title", entry.strTitle);+    XMLUtils::GetString(pNode, "length", entry.strLength);+    XMLUtils::GetString(pNode, "starttime", entry.strStartTime);+    XMLUtils::GetString(pNode, "musicbrainzid", entry.strMusicBrainzID);+    m_vecSubmissionJournal.push_back(entry);+    pNode = pNode->NextSibling("entry");+  }++  CLog::Log(LOGDEBUG, "Audioscrobbler: Journal loaded with %d entries.", m_vecSubmissionJournal.size());+  return (m_vecSubmissionJournal.size() > 0) ? 1 : 0; } +int CScrobbler::SaveJournal()+{+  TiXmlDocument xmlDoc;+  TiXmlDeclaration decl("1.0", "utf-8", "yes");+  xmlDoc.InsertEndChild(decl);+  TiXmlElement xmlRootElement("asjournal");+  TiXmlNode *pRoot = xmlDoc.InsertEndChild(xmlRootElement);+  if (!pRoot)+    return 0;+  vector<SubmissionJournalEntry_t>::iterator it = m_vecSubmissionJournal.begin();+  for (; it != m_vecSubmissionJournal.end(); it++)+  {+    TiXmlElement entryNode("entry");+    TiXmlNode *pNode = pRoot->InsertEndChild(entryNode);+    if (!pNode)+      return 0;+    XMLUtils::SetString(pNode, "artist", it->strArtist);+    XMLUtils::SetString(pNode, "album", it->strAlbum);+    XMLUtils::SetString(pNode, "title", it->strTitle);+    XMLUtils::SetString(pNode, "length", it->strLength);+    XMLUtils::SetString(pNode, "starttime", it->strStartTime);+    XMLUtils::SetString(pNode, "musicbrainzid", it->strMusicBrainzID);+  }++  CStdString FileName = GetJournalFileName();+  return (xmlDoc.SaveFile(FileName)) ? 1 : 0;+}+ void CScrobbler::StatusUpdate(ScrobbleStatus status, const CStdString& strText) {   switch (status)@@ -541,8 +644,6 @@     if (m_bCloseThread)       break; -    StatusUpdate(S_DEBUG,"...");-     CHTTP http;     CStdString strHtml;     bool bSuccess;@@ -566,7 +667,6 @@         LPSTR lphtml=strHtml.GetBuffer();         HandleSubmit(lphtml);         strHtml.ReleaseBuffer();-        ::DeleteFile(GetTempFileName());         if (m_bReHandShaking) continue;       }     }@@ -579,7 +679,6 @@       StatusUpdate(S_CONNECT_ERROR,"Could not connect to server.");     } -     // OK, if this was a handshake, it failed since m_bReadyToSubmit isn't true. Submissions get cached.     while (!m_bReadyToSubmit)     {@@ -634,7 +733,7 @@     return strCachedFiles;    CStdString strFormat=g_localizeStrings.Get(15210);  // Cached %i Songs-  strCachedFiles.Format(strFormat.c_str(), m_iSongNum);+  strCachedFiles.Format(strFormat.c_str(), m_vecSubmissionJournal.size());    return strCachedFiles; }@@ -683,3 +782,10 @@   CStdString strFileName = g_settings.GetProfileUserDataFolder();   return CUtil::AddFileToFolder(strFileName, "Scrobbler.tmp"); }++CStdString CScrobbler::GetJournalFileName()+{+  CStdString strFileName = g_settings.GetProfileUserDataFolder();+  return CUtil::AddFileToFolder(strFileName, "Scrobbler.xml");+}+