//----------------------------------------
//--- Primary playback control methods ---
//----------------------------------------
void Playlist::playItemAt(int row, Model model)
{
    bool isQueue = (model == QueueModel);
    MediaItem nextMediaItem = isQueue ? m_queue->mediaItemAt(row) :
                                        m_currentPlaylist->mediaItemAt(row);
    if (!isQueue) {
        nextMediaItem.playlistIndex = row;
    }
    nextMediaItem.nowPlaying = true;
    
    //Update Queue Model
    if (!m_shuffle) {
        //Just build a new queue from the row of the item in the playlist
        buildQueueFrom(nextMediaItem.playlistIndex);
    } else {
        int rowInQueue = isQueue ? row : m_queue->rowOfUrl(nextMediaItem.url);

        //Add currently playing item to history
        if (rowInQueue > 0 && m_nowPlaying->rowCount() > 0) {
            if (m_nowPlaying->mediaItemAt(0).type == "Audio" || m_nowPlaying->mediaItemAt(0).type == "Video") {
                int nowPlayingIndex = m_nowPlaying->mediaItemAt(0).playlistIndex;
                m_playlistIndicesHistory.append(nowPlayingIndex);
                m_playlistUrlHistory.append(m_nowPlaying->mediaItemAt(0).url);
                if (m_queue->rowCount() > 1) {
                    m_queue->removeMediaItemAt(0);
                    rowInQueue--;
                }
            }
        }

        //Remove requested item from history
        bool inHistory = (m_playlistIndicesHistory.indexOf(nextMediaItem.playlistIndex) != -1);
        if ( inHistory ) { //remove from history
            int idx = m_playlistIndicesHistory.indexOf(row);
            m_playlistIndicesHistory.removeAt(idx);
            m_playlistUrlHistory.removeAt(idx);
        }

        //Place requested item at front of queue
        QList<MediaItem> queueMediaList = m_queue->mediaList();
        if ( rowInQueue > 0 ) { //in queue, but not at first place, so move it
            queueMediaList.move(rowInQueue, 0);
        } else if (rowInQueue < 0) { //not in queue, so add it at first place
            queueMediaList.insert(0, nextMediaItem);
            if (queueMediaList.count() > m_queueDepth) {
                queueMediaList.removeLast();
            }
        } //else it is already at first place in the queue
        m_queue->clearMediaListData();
        m_queue->loadMediaList(queueMediaList, true);

        //Fill out queue
        shuffle();
    }
    
    //Play media Item
    m_mediaObject->clearQueue();
    m_currentStream.clear();
    QString subType;
    if (nextMediaItem.type == "Audio") {
        subType = nextMediaItem.fields["audioType"].toString();
    } else if(nextMediaItem.type == "Video") {
        subType = nextMediaItem.fields["videoType"].toString();
    }
    m_currentUrl = nextMediaItem.url;
    bool isDiscTitle = Utilities::isDisc( nextMediaItem.url );
    if (isDiscTitle) {
        Solid::Device device = Solid::Device( Utilities::deviceUdiFromUrl(nextMediaItem.url) );
        if (!device.isValid()) {
            stop();
            return;
        }
        const Solid::Block* block = device.as<const Solid::Block>();
        Phonon::DiscType discType = (subType == "CD Track") ? Phonon::Cd : Phonon::Dvd;
        Phonon::MediaSource src = Phonon::MediaSource(discType, block->device());
        int title = nextMediaItem.fields["trackNumber"].toInt();
        if (m_mediaObject->currentSource().discType() != src.discType() ||
            m_mediaObject->currentSource().deviceName() != src.deviceName()) {
            m_mediaObject->setCurrentSource(src);
        }
        if (title != -1) {
            m_mediaController->setCurrentTitle(title);
            m_mediaController->setAutoplayTitles(true);
        }
        m_mediaObject->play();
    } else if (subType == "Audio Stream") {
        m_currentStream = nextMediaItem.url;
        m_streamListUrls.clear();
        if (Utilities::isPls(nextMediaItem.url) || Utilities::isM3u(nextMediaItem.url)) {
            QList<MediaItem> streamList = Utilities::mediaListFromSavedList(nextMediaItem);
            for (int i = 0; i < streamList.count(); i++) {
                m_streamListUrls << streamList.at(i).url;
                if (i == 0) {
                    m_currentUrl = streamList.at(i).url;
                } else {
                    m_mediaObject->enqueue(Phonon::MediaSource(QUrl::fromPercentEncoding(streamList.at(i).url.toUtf8())));
                }
            }
        } else {
            m_streamListUrls << nextMediaItem.url;
        }
        m_mediaObject->setCurrentSource(Phonon::MediaSource(QUrl::fromPercentEncoding(m_currentUrl.toUtf8())));
        m_mediaObject->play();
    } else {
        m_mediaObject->setCurrentSource(Phonon::MediaSource(QUrl::fromEncoded(m_currentUrl.toUtf8())));
        m_mediaObject->play();
    }
    m_state = Playlist::Playing;
}