/** * Dequeues one item from the queue. */ SubmitItem* ScrobblerSubmitter::dequeueItem() { SubmitItem* item = 0; if( m_lastSubmissionFinishTime > 0 && !m_holdFakeQueue && m_fakeQueue.getFirst() ) { uint limit = QDateTime::currentDateTime( Qt::UTC ).toTime_t(); if ( m_submitQueue.getFirst() ) if ( m_submitQueue.getFirst()->playStartTime() <= limit ) limit = m_submitQueue.getFirst()->playStartTime(); if( m_lastSubmissionFinishTime + m_fakeQueue.getFirst()->length() <= limit ) { m_fakeQueue.first(); item = m_fakeQueue.take(); // don't backdate earlier than we have to if( m_lastSubmissionFinishTime + m_fakeQueueLength < limit ) item->m_playStartTime = limit - m_fakeQueueLength; else item->m_playStartTime = m_lastSubmissionFinishTime; m_fakeQueueLength -= item->length(); } } if( !item ) { m_submitQueue.first(); item = m_submitQueue.take(); } if( item ) { if( item->playStartTime() < m_lastSubmissionFinishTime ) { // debug() << "play times screwed up? - " << item->artist() << " - " << item->title() << ": " << item->playStartTime() << " < " << m_lastSubmissionFinishTime << endl; } int add = 30; if( item->length() / 2 + 1 > add ) add = item->length() / 2 + 1; if( item->playStartTime() + add > m_lastSubmissionFinishTime ) m_lastSubmissionFinishTime = item->playStartTime() + add; // Save submit queue to disk so it is more uptodate in case of crash. saveSubmitQueue(); } return item; }
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& ) ) ); }