Example #1
0
/**
 * 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;
}
Example #2
0
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;
}
Example #3
0
/**
 * 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();
    }
}
Example #4
0
/**
 * 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& ) ) );
}