/** * Enqueues the given item for later submission. */ void ScrobblerSubmitter::enqueueItem( SubmitItem* item ) { // Maintain max size of the queue, Audioscrobbler won't accept too old // submissions anyway. m_fakeQueue.first(); for ( uint size = m_fakeQueue.count() + m_submitQueue.count(); size >= 500; size-- ) { SubmitItem* itemFromQueue = m_fakeQueue.getFirst(); m_fakeQueue.removeFirst(); if ( itemFromQueue ) { debug() << "Dropping " << itemFromQueue->artist() << " - " << itemFromQueue->title() << " from fake queue" << endl; m_fakeQueueLength -= itemFromQueue->length(); } delete itemFromQueue; } m_submitQueue.first(); for ( uint size = m_submitQueue.count(); size >= 500; size-- ) { SubmitItem* itemFromQueue = m_submitQueue.getFirst(); m_submitQueue.removeFirst(); debug() << "Dropping " << itemFromQueue->artist() << " - " << itemFromQueue->title() << " from submit queue" << endl; delete itemFromQueue; } if( item->playStartTime() == 0 ) { m_fakeQueue.inSort( item ); m_fakeQueueLength += item->length(); } else { m_submitQueue.inSort( item ); } if( !m_holdFakeQueue ) { // Save submit queue to disk so it is more uptodate in case of crash. saveSubmitQueue(); } }
bool SubmitItem::operator==( const SubmitItem& item ) { bool result = true; if ( m_artist != item.artist() || m_album != item.album() || m_title != item.title() || m_length != item.length() || m_playStartTime != item.playStartTime() ) { result = false; } return result; }
/** * Flushes the submit queues */ void ScrobblerSubmitter::performSubmit() { QString data; // Audioscrobbler accepts max 10 tracks on one submit. SubmitItem* items[10]; for ( int submitCounter = 0; submitCounter < 10; submitCounter++ ) items[submitCounter] = 0; if ( PROTOCOL_VERSION == "1.1" ) { // Audioscrobbler protocol 1.1 (current) // http://post.audioscrobbler.com/v1.1-lite.php // u=<user> // &s=<MD5 response>& // a[0]=<artist 0>&t[0]=<track 0>&b[0]=<album 0>& // m[0]=<mbid 0>&l[0]=<length 0>&i[0]=<time 0>& // a[1]=<artist 1>&t[1]=<track 1>&b[1]=<album 1>& // m[1]=<mbid 1>&l[1]=<length 1>&i[1]=<time 1>& // ... // a[n]=<artist n>&t[n]=<track n>&b[n]=<album n>& // m[n]=<mbid n>&l[n]=<length n>&i[n]=<time n>& data = "u=" + KURL::encode_string_no_slash( m_username ) + "&s=" + KURL::encode_string_no_slash( KMD5( KMD5( m_password.utf8() ).hexDigest() + m_challenge.utf8() ).hexDigest() ); m_submitQueue.first(); for ( int submitCounter = 0; submitCounter < 10; submitCounter++ ) { SubmitItem* itemFromQueue = dequeueItem(); if ( itemFromQueue == 0 ) { if( submitCounter == 0 ) { // this shouldn't happen, since we shouldn't be scheduled until we have something to do! debug() << "Nothing to submit!" << endl; return; } else { break; } } else data += '&'; items[submitCounter] = itemFromQueue; QDateTime playStartTime = QDateTime(); playStartTime.setTime_t( itemFromQueue->playStartTime() ); const QString count = QString::number( submitCounter ); data += "a[" + count + "]=" + KURL::encode_string_no_slash( itemFromQueue->artist(), 106 /*utf-8*/ ) + "&t[" + count + "]=" + KURL::encode_string_no_slash( itemFromQueue->title(), 106 /*utf-8*/ ) + "&b[" + count + "]=" + KURL::encode_string_no_slash( itemFromQueue->album(), 106 /*utf-8*/ ) + "&m[" + count + "]=" + "&l[" + count + "]=" + QString::number( itemFromQueue->length() ) + "&i[" + count + "]=" + KURL::encode_string_no_slash( playStartTime.toString( "yyyy-MM-dd hh:mm:ss" ) ); } } else { debug() << "Submit not implemented for protocol version: " << PROTOCOL_VERSION << endl; return; } debug() << "Submit data: " << data << endl; m_submitResultBuffer = ""; m_inProgress = true; KIO::TransferJob* job = KIO::http_post( m_submitUrl, data.utf8(), false ); job->addMetaData( "content-type", "Content-Type: application/x-www-form-urlencoded" ); // Loop in reverse order, which helps when items are later fetched from // m_ongoingSubmits and possibly put back to queue, in correct order // (i.e. oldest first). for ( int submitCounter = 9; submitCounter >= 0; submitCounter-- ) if ( items[submitCounter] != 0 ) m_ongoingSubmits.insert( job, items[submitCounter] ); Amarok::StatusBar::instance()->newProgressOperation( job ) .setDescription( i18n( "Submitting to last.fm" ) ); connect( job, SIGNAL( result( KIO::Job* ) ), this, SLOT( audioScrobblerSubmitResult( KIO::Job* ) ) ); connect( job, SIGNAL( data( KIO::Job*, const QByteArray& ) ), this, SLOT( audioScrobblerSubmitData( KIO::Job*, const QByteArray& ) ) ); }