diff --git a/src/libtomahawk/audio/AudioEngine.cpp b/src/libtomahawk/audio/AudioEngine.cpp index ba4456e17..01b05e463 100644 --- a/src/libtomahawk/audio/AudioEngine.cpp +++ b/src/libtomahawk/audio/AudioEngine.cpp @@ -716,16 +716,14 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString // and Phonon handles the deletion of the // QNR_IODeviceStream object ioToKeep.clear(); - // TODO d->audioOutput->setAutoDelete( true ); + d->audioOutput->setAutoDelete( true ); } else { tLog() << "CASE 2"; -/* TODO d->audioOutput->setCurrentSource( io.data() ); // We handle the deletion via tracking in d->input d->audioOutput->setAutoDelete( false ); -*/ } } else @@ -758,9 +756,7 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString d->audioOutput->setCurrentSource( QUrl::fromLocalFile( furl ) ); } -/* TODO d->audioOutput->setAutoDelete( true ); -*/ } if ( !d->input.isNull() ) @@ -1251,6 +1247,8 @@ AudioEngine::currentTrackTotalTime() const { // TODO : This is too hacky. The problem is that I don't know why // libVLC doesn't report total duration for stream data (imem://) + // But it's not a real problem for playback, since + // EndOfStream is emitted by libVLC itself if ( d_func()->audioOutput->totalTime() == 0 && d_func()->currentTrack && d_func()->currentTrack->track() ) { return d_func()->currentTrack->track()->duration() * 1000 + 1000; } diff --git a/src/libtomahawk/audio/AudioEngine_p.h b/src/libtomahawk/audio/AudioEngine_p.h index 4d2f275a4..1bf5b9b1c 100644 --- a/src/libtomahawk/audio/AudioEngine_p.h +++ b/src/libtomahawk/audio/AudioEngine_p.h @@ -44,16 +44,6 @@ private: Tomahawk::playlistinterface_ptr queue; AudioOutput* audioOutput; -/* - Phonon::MediaObject* mediaObject; - Phonon::AudioOutput* audioOutput; - - Phonon::Path audioPath; - Phonon::Effect* audioEffect; - - Phonon::AudioDataOutput* audioDataOutput; - Phonon::Path audioDataPath; -*/ unsigned int timeElapsed; bool expectStop; diff --git a/src/libtomahawk/audio/AudioOutput.cpp b/src/libtomahawk/audio/AudioOutput.cpp index f45f573a4..3be3a0aba 100644 --- a/src/libtomahawk/audio/AudioOutput.cpp +++ b/src/libtomahawk/audio/AudioOutput.cpp @@ -54,11 +54,15 @@ AudioOutput::AudioOutput( QObject* parent ) : QObject( parent ) , currentState( Stopped ) , muted( false ) + , m_autoDelete ( true ) , m_volume( 1.0 ) , m_currentTime( 0 ) , m_totalTime( 0 ) , m_aboutToFinish( false ) , dspPluginCallback( 0 ) + , vlcInstance( 0 ) + , vlcPlayer( 0 ) + , vlcMedia( 0 ) { tDebug() << Q_FUNC_INFO; @@ -126,8 +130,6 @@ AudioOutput::AudioOutput( QObject* parent ) libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this ); } - - getchar(); tDebug() << "AudioOutput::AudioOutput OK !\n"; } @@ -137,6 +139,13 @@ AudioOutput::~AudioOutput() tDebug() << Q_FUNC_INFO; } + +void +AudioOutput::setAutoDelete ( bool ad ) +{ + m_autoDelete = ad; +} + void AudioOutput::setCurrentSource(MediaStream stream) { @@ -150,6 +159,15 @@ AudioOutput::setCurrentSource(MediaStream* stream) setState(Loading); + if ( vlcMedia != 0 ) { + // Ensure playback is stopped, then release media + libvlc_media_player_stop( vlcPlayer ); + libvlc_media_release( vlcMedia ); + vlcMedia = 0; + } + if ( m_autoDelete && currentStream != 0 ) { + delete currentStream; + } currentStream = stream; m_totalTime = 0; m_currentTime = 0; @@ -166,16 +184,18 @@ AudioOutput::setCurrentSource(MediaStream* stream) case MediaStream::Url: tDebug() << "MediaStream::Url:" << stream->url(); - if (stream->url().scheme().isEmpty()) { + if ( stream->url().scheme().isEmpty() ) { url = "file:///"; - if (stream->url().isRelative()) - url.append(QFile::encodeName(QDir::currentPath()) + '/'); + if ( stream->url().isRelative() ) { + url.append( QFile::encodeName( QDir::currentPath() ) + '/' ); + } } url += stream->url().toEncoded(); break; case MediaStream::Stream: - url = QByteArray("imem://"); + case MediaStream::IODevice: + url = QByteArray( "imem://" ); break; } @@ -199,19 +219,13 @@ AudioOutput::setCurrentSource(MediaStream* stream) if ( stream->type() == MediaStream::Url ) { m_totalTime = libvlc_media_get_duration( vlcMedia ); } - else if ( stream->type() == MediaStream::Stream ) { + else if ( stream->type() == MediaStream::Stream || stream->type() == MediaStream::IODevice ) { libvlc_media_add_option_flag(vlcMedia, "imem-cat=4", libvlc_media_option_trusted); libvlc_media_add_option_flag(vlcMedia, (QString("imem-data=") + QString::number((quint64)stream)).toUtf8().data(), libvlc_media_option_trusted); libvlc_media_add_option_flag(vlcMedia, (QString("imem-get=") + QString::number((quint64)&MediaStream::readCallback)).toUtf8().data(), libvlc_media_option_trusted); libvlc_media_add_option_flag(vlcMedia, (QString("imem-release=") + QString::number((quint64)&MediaStream::readDoneCallback)).toUtf8().data(), libvlc_media_option_trusted); libvlc_media_add_option_flag(vlcMedia, (QString("imem-seek=") + QString::number((quint64)&MediaStream::seekCallback)).toUtf8().data(), libvlc_media_option_trusted); } - libvlc_media_add_option(vlcMedia, "audio-filter=dsp"); - libvlc_media_add_option(vlcMedia, ":audio-filter=dsp"); - libvlc_media_add_option(vlcMedia, "--audio-filter=dsp"); - libvlc_media_add_option(vlcMedia, "audio-filter dsp"); - libvlc_media_add_option(vlcMedia, ":audio-filter dsp"); - libvlc_media_add_option(vlcMedia, "--audio-filter dsp"); m_aboutToFinish = false; setState(Stopped); @@ -246,13 +260,16 @@ AudioOutput::currentTime() void AudioOutput::setCurrentTime( qint64 time ) { - m_currentTime = time; + // TODO : This is a bit hacky, but m_totalTime is only used to determine + // if we are about to finish if ( m_totalTime <= 0 ) { m_totalTime = AudioEngine::instance()->currentTrackTotalTime(); } + + m_currentTime = time; emit tick( time ); - tDebug() << "Current time : " << m_currentTime << " / " << m_totalTime; +// tDebug() << "Current time : " << m_currentTime << " / " << m_totalTime; if ( time < m_totalTime - ABOUT_TO_FINISH_TIME ) { m_aboutToFinish = false; @@ -329,27 +346,13 @@ AudioOutput::seek( qint64 milliseconds ) case Buffering: break; default: - // Seeking while not being in a playingish state is cached for later. -// TODO m_seekpoint = milliseconds; return; } tDebug() << "AudioOutput:: seeking" << milliseconds << "msec"; libvlc_media_player_set_time ( vlcPlayer, milliseconds ); -/* - const qint64 time = currentTime(); - const qint64 total = totalTime(); -*/ -/* - // Reset last tick marker so we emit time even after seeking - if (time < m_lastTick) - m_lastTick = time; - if (time < total - m_prefinishMark) - m_prefinishEmitted = false; - if (time < total - ABOUT_TO_FINISH_TIME) - m_aboutToFinishEmitted = false; -*/ + setCurrentTime( milliseconds ); } diff --git a/src/libtomahawk/audio/AudioOutput.h b/src/libtomahawk/audio/AudioOutput.h index d5610f923..564515e58 100644 --- a/src/libtomahawk/audio/AudioOutput.h +++ b/src/libtomahawk/audio/AudioOutput.h @@ -58,6 +58,7 @@ public: qreal volume(); qint64 currentTime(); qint64 totalTime(); + void setAutoDelete ( bool ad ); void setDspCallback( void ( *cb ) ( signed short*, int, int ) ); @@ -82,6 +83,7 @@ private: AudioState currentState; MediaStream* currentStream; bool muted; + bool m_autoDelete; qreal m_volume; qint64 m_currentTime; qint64 m_totalTime; diff --git a/src/libtomahawk/utils/MediaStream.cpp b/src/libtomahawk/utils/MediaStream.cpp index ac2cee4ab..927f9f877 100644 --- a/src/libtomahawk/utils/MediaStream.cpp +++ b/src/libtomahawk/utils/MediaStream.cpp @@ -22,6 +22,7 @@ #include "utils/Logger.h" +#define BLOCK_SIZE 1048576 static QString s_aeInfoIdentifier = QString( "MEDIASTREAM" ); @@ -29,6 +30,7 @@ static QString s_aeInfoIdentifier = QString( "MEDIASTREAM" ); MediaStream::MediaStream() : m_type( Unknown ) , m_url( QUrl() ) + , m_ioDevice ( 0 ) , m_eos( false ) , m_pos( 0 ) , m_streamSize( 0 ) @@ -46,6 +48,15 @@ MediaStream::MediaStream( const QUrl &url ) } +MediaStream::MediaStream( QIODevice* device ) + : m_type(IODevice) +{ + tDebug() << Q_FUNC_INFO; + + m_ioDevice = device; +} + + MediaStream::~MediaStream() { tDebug() << Q_FUNC_INFO; @@ -98,7 +109,7 @@ MediaStream::endOfData() int MediaStream::readCallback ( void* data, const char* cookie, int64_t* dts, int64_t* pts, unsigned* flags, size_t* bufferSize, void** buffer ) { - tDebug() << Q_FUNC_INFO; +// tDebug() << Q_FUNC_INFO; Q_UNUSED(cookie); Q_UNUSED(dts); @@ -111,7 +122,16 @@ MediaStream::readCallback ( void* data, const char* cookie, int64_t* dts, int64_ return -1; } - *bufferSize = that->needData(buffer); + if ( that->m_type == Stream ) { + *bufferSize = that->needData(buffer); + } + else if ( that->m_type == IODevice ) { + QByteArray data = that->m_ioDevice->read(BLOCK_SIZE); + *buffer = new char[data.size()]; + memcpy(*buffer, data.data(), data.size()); + *bufferSize = data.size(); + } + return 0; } @@ -121,12 +141,16 @@ MediaStream::readDoneCallback ( void *data, const char *cookie, size_t bufferSiz { tDebug() << Q_FUNC_INFO; - Q_UNUSED(data); Q_UNUSED(cookie); Q_UNUSED(bufferSize); -// TODO : causes segfault -// delete static_cast(buffer); + MediaStream* that = static_cast < MediaStream * > ( data ); + + if ( ( that->m_type == Stream || that->m_type == IODevice ) && buffer != 0 && bufferSize > 0 ) { +// TODO : causes segfault + tDebug() << "buffer : " << buffer; + delete static_cast(buffer); + } return 0; } @@ -135,14 +159,18 @@ MediaStream::readDoneCallback ( void *data, const char *cookie, size_t bufferSiz int MediaStream::seekCallback ( void *data, const uint64_t pos ) { - tDebug() << Q_FUNC_INFO; +// tDebug() << Q_FUNC_INFO; MediaStream* that = static_cast < MediaStream * > ( data ); - if ( static_cast < int64_t > ( pos ) > that->streamSize() ) { + + if ( that->m_type == Stream && static_cast < int64_t > ( pos ) > that->streamSize() ) { return -1; } that->m_pos = pos; + if ( that->m_type == IODevice ) { + that->m_ioDevice->seek(pos); + } return 0; } diff --git a/src/libtomahawk/utils/MediaStream.h b/src/libtomahawk/utils/MediaStream.h index b7dd67987..66e5c2fdf 100644 --- a/src/libtomahawk/utils/MediaStream.h +++ b/src/libtomahawk/utils/MediaStream.h @@ -28,15 +28,17 @@ #include #include +#include class DLLEXPORT MediaStream { public: - enum MediaType { Unknown = -1, Empty = 0, Url = 1, Stream = 2 }; + enum MediaType { Unknown = -1, Empty = 0, Url = 1, Stream = 2, IODevice = 3 }; MediaStream(); MediaStream( const QUrl &url ); + MediaStream( QIODevice* device ); virtual ~MediaStream(); MediaType type(); @@ -57,6 +59,7 @@ protected: MediaType m_type; QUrl m_url; + QIODevice* m_ioDevice; bool m_eos; qint64 m_pos;