void MMF::MediaObject::createPlayer(const MediaSource &source)
{
    TRACE_CONTEXT(MediaObject::createPlayer, EAudioApi);
    TRACE_ENTRY("state %d source.type %d", state(), source.type());
    TRACE_ENTRY("source.type %d", source.type());

    MediaType mediaType = MediaTypeUnknown;

    AbstractPlayer* oldPlayer = m_player.data();

    const bool oldPlayerHasVideo = oldPlayer->hasVideo();
    const bool oldPlayerSeekable = oldPlayer->isSeekable();

    QString errorMessage;

    // Determine media type
    switch (source.type()) {
    case MediaSource::LocalFile:
        mediaType = fileMediaType(source.fileName());
        break;

    case MediaSource::Url:
        {
            const QUrl url(source.url());
            if (url.scheme() == QLatin1String("file")) {
                mediaType = fileMediaType(url.toLocalFile());
            }
            else {
                // Streaming playback is generally not supported by the implementation
                // of the audio player API, so we use CVideoPlayerUtility for both
                // audio and video streaming.
                mediaType = MediaTypeVideo;
            }
        }
        break;

    case MediaSource::Invalid:
    case MediaSource::Disc:
    case MediaSource::Stream:
        errorMessage = tr("Error opening source: type not supported");
        break;

    case MediaSource::Empty:
        TRACE_0("Empty media source");
        break;
    }

    if (oldPlayer)
        oldPlayer->close();

    AbstractPlayer* newPlayer = 0;

    // Construct newPlayer using oldPlayer (if not 0) in order to copy
    // parameters (volume, prefinishMark, transitionTime) which may have
    // been set on oldPlayer.

    switch (mediaType) {
    case MediaTypeUnknown:
        TRACE_0("Media type could not be determined");
        newPlayer = new DummyPlayer(oldPlayer);
        errorMessage = tr("Error opening source: media type could not be determined");
        break;

    case MediaTypeAudio:
        newPlayer = new AudioPlayer(this, oldPlayer);
        break;

    case MediaTypeVideo:
#ifdef PHONON_MMF_VIDEO_SURFACES
        newPlayer = SurfaceVideoPlayer::create(this, oldPlayer);
#else
        newPlayer = DsaVideoPlayer::create(this, oldPlayer);
#endif
        break;
    }

    if (oldPlayer)
        emit abstractPlayerChanged(0);
    m_player.reset(newPlayer);
    emit abstractPlayerChanged(newPlayer);

    if (oldPlayerHasVideo != hasVideo()) {
        emit hasVideoChanged(hasVideo());
    }

    if (oldPlayerSeekable != isSeekable()) {
        emit seekableChanged(isSeekable());
    }

    connect(m_player.data(), SIGNAL(totalTimeChanged(qint64)), SIGNAL(totalTimeChanged(qint64)));
    connect(m_player.data(), SIGNAL(stateChanged(Phonon::State,Phonon::State)), SIGNAL(stateChanged(Phonon::State,Phonon::State)));
    connect(m_player.data(), SIGNAL(finished()), SIGNAL(finished()));
    connect(m_player.data(), SIGNAL(bufferStatus(int)), SIGNAL(bufferStatus(int)));
    connect(m_player.data(), SIGNAL(metaDataChanged(QMultiMap<QString,QString>)), SIGNAL(metaDataChanged(QMultiMap<QString,QString>)));
    connect(m_player.data(), SIGNAL(aboutToFinish()), SIGNAL(aboutToFinish()));
    connect(m_player.data(), SIGNAL(prefinishMarkReached(qint32)), SIGNAL(prefinishMarkReached(qint32)));
    connect(m_player.data(), SIGNAL(prefinishMarkReached(qint32)), SLOT(handlePrefinishMarkReached(qint32)));
    connect(m_player.data(), SIGNAL(tick(qint64)), SIGNAL(tick(qint64)));

    // We need to call setError() after doing the connects, otherwise the
    // error won't be received.
    if (!errorMessage.isEmpty()) {
        Q_ASSERT(m_player);
        m_player->setError(errorMessage);
    }

    TRACE_EXIT_0();
}