diff --git a/src/libtomahawk/audio/AudioEngine.cpp b/src/libtomahawk/audio/AudioEngine.cpp
index 5a177c08e..1a2d0ae08 100644
--- a/src/libtomahawk/audio/AudioEngine.cpp
+++ b/src/libtomahawk/audio/AudioEngine.cpp
@@ -109,9 +109,9 @@ AudioEnginePrivate::onStateChanged( AudioOutput::AudioState newState, AudioOutpu
case AudioOutput::Paused:
{
if ( audioOutput && currentTrack )
- {/* TODO
+ {
qint64 duration = audioOutput->totalTime() > 0 ? audioOutput->totalTime() : currentTrack->track()->duration() * 1000;
- stopped = ( duration - 1000 < audioOutput->currentTime() ); */
+ stopped = ( duration - 1000 < audioOutput->currentTime() );
}
else
stopped = true;
@@ -133,7 +133,7 @@ AudioEnginePrivate::onStateChanged( AudioOutput::AudioState newState, AudioOutpu
if ( stopped && expectStop )
{
expectStop = false;
- tDebug( LOGVERBOSE ) << "Finding next track.";
+ tDebug() << "Finding next track.";
if ( q_ptr->canGoNext() )
{
q_ptr->loadNextTrack();
@@ -194,6 +194,7 @@ AudioEngine::AudioEngine()
connect( d->audioOutput, SIGNAL( stateChanged( AudioOutput::AudioState, AudioOutput::AudioState ) ), d_func(), SLOT( onStateChanged( AudioOutput::AudioState, AudioOutput::AudioState ) ) );
connect( d->audioOutput, SIGNAL( tick( qint64 ) ), SLOT( timerTriggered( qint64 ) ) );
+ connect( d->audioOutput, SIGNAL( aboutToFinish() ), SLOT( onAboutToFinish() ) );
qRegisterMetaType< AudioErrorCode >("AudioErrorCode");
qRegisterMetaType< AudioState >("AudioState");
@@ -1248,6 +1249,11 @@ AudioEngine::currentTime() const
qint64
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://)
+ if ( d_func()->currentTrack && d_func()->currentTrack->track() ) {
+ return d_func()->currentTrack->track()->duration() * 1000 + 1000;
+ }
return d_func()->audioOutput->totalTime();
}
diff --git a/src/libtomahawk/audio/AudioOutput.cpp b/src/libtomahawk/audio/AudioOutput.cpp
index c5dcfee14..f45f573a4 100644
--- a/src/libtomahawk/audio/AudioOutput.cpp
+++ b/src/libtomahawk/audio/AudioOutput.cpp
@@ -18,6 +18,7 @@
* along with Tomahawk. If not, see .
*/
+#include "AudioEngine.h"
#include "AudioOutput.h"
#include "utils/Logger.h"
@@ -37,6 +38,7 @@
static QString s_aeInfoIdentifier = QString( "AUDIOOUTPUT" );
+static const int ABOUT_TO_FINISH_TIME = 2000;
AudioOutput* AudioOutput::s_instance = 0;
@@ -55,12 +57,15 @@ AudioOutput::AudioOutput( QObject* parent )
, m_volume( 1.0 )
, m_currentTime( 0 )
, m_totalTime( 0 )
+ , m_aboutToFinish( false )
, dspPluginCallback( 0 )
{
tDebug() << Q_FUNC_INFO;
AudioOutput::s_instance = this;
currentStream = 0;
+
+ qRegisterMetaType("AudioOutput::AudioState");
QList args;
@@ -94,7 +99,7 @@ AudioOutput::AudioOutput( QObject* parent )
vlcPlayer = libvlc_media_player_new( vlcInstance );
- libvlc_event_manager_t *manager = libvlc_media_player_event_manager( vlcPlayer );
+ libvlc_event_manager_t* manager = libvlc_media_player_event_manager( vlcPlayer );
libvlc_event_type_t events[] = {
libvlc_MediaPlayerMediaChanged,
libvlc_MediaPlayerNothingSpecial,
@@ -113,7 +118,7 @@ AudioOutput::AudioOutput( QObject* parent )
libvlc_MediaPlayerPausableChanged,
libvlc_MediaPlayerTitleChanged,
libvlc_MediaPlayerSnapshotTaken,
- libvlc_MediaPlayerLengthChanged,
+ //libvlc_MediaPlayerLengthChanged,
libvlc_MediaPlayerVout
};
const int eventCount = sizeof(events) / sizeof( *events );
@@ -142,9 +147,12 @@ void
AudioOutput::setCurrentSource(MediaStream* stream)
{
tDebug() << Q_FUNC_INFO;
- currentStream = stream;
- currentState = Loading;
+ setState(Loading);
+
+ currentStream = stream;
+ m_totalTime = 0;
+ m_currentTime = 0;
QByteArray url;
switch (stream->type()) {
@@ -173,10 +181,21 @@ AudioOutput::setCurrentSource(MediaStream* stream)
tDebug() << "MediaStream::Final Url:" << url;
+
vlcMedia = libvlc_media_new_location( vlcInstance, url.constData() );
+ libvlc_event_manager_t* manager = libvlc_media_event_manager( vlcMedia );
+ libvlc_event_type_t events[] = {
+ libvlc_MediaDurationChanged,
+ };
+ const int eventCount = sizeof(events) / sizeof( *events );
+ for ( int i = 0 ; i < eventCount ; i++ ) {
+ libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
+ }
+
libvlc_media_player_set_media( vlcPlayer, vlcMedia );
+
if ( stream->type() == MediaStream::Url ) {
m_totalTime = libvlc_media_get_duration( vlcMedia );
}
@@ -194,7 +213,8 @@ AudioOutput::setCurrentSource(MediaStream* stream)
libvlc_media_add_option(vlcMedia, ":audio-filter dsp");
libvlc_media_add_option(vlcMedia, "--audio-filter dsp");
- currentState = Stopped;
+ m_aboutToFinish = false;
+ setState(Stopped);
}
@@ -210,8 +230,9 @@ void
AudioOutput::setState( AudioState state )
{
tDebug() << Q_FUNC_INFO;
- emit stateChanged ( state, currentState );
+ AudioState last = currentState;
currentState = state;
+ emit stateChanged ( state, last );
}
@@ -226,7 +247,20 @@ void
AudioOutput::setCurrentTime( qint64 time )
{
m_currentTime = time;
+ if ( m_totalTime <= 0 ) {
+ m_totalTime = AudioEngine::instance()->currentTrackTotalTime();
+ }
emit tick( time );
+
+ tDebug() << "Current time : " << m_currentTime << " / " << m_totalTime;
+
+ if ( time < m_totalTime - ABOUT_TO_FINISH_TIME ) {
+ m_aboutToFinish = false;
+ }
+ if ( !m_aboutToFinish && m_totalTime > 0 && time >= m_totalTime - ABOUT_TO_FINISH_TIME ) {
+ m_aboutToFinish = true;
+ emit aboutToFinish();
+ }
}
@@ -237,6 +271,17 @@ AudioOutput::totalTime()
}
+void
+AudioOutput::setTotalTime( qint64 time )
+{
+ if ( time > 0 ) {
+ m_totalTime = time;
+ // emit current time to refresh total time
+ emit tick( m_currentTime );
+ }
+}
+
+
void
AudioOutput::play()
{
@@ -367,16 +412,23 @@ AudioOutput::vlcEventCallback( const libvlc_event_t* event, void* opaque )
case libvlc_MediaPlayerSeekableChanged:
//TODO, bool event->u.media_player_seekable_changed.new_seekable
break;
- case libvlc_MediaPlayerLengthChanged:
- that->m_totalTime = event->u.media_player_length_changed.new_length;
+ case libvlc_MediaDurationChanged:
+ that->setTotalTime( event->u.media_duration_changed.new_duration );
break;
+ /*
+ case libvlc_MediaPlayerLengthChanged:
+ that->setTotalTime( event->u.media_player_length_changed.new_length );
+ break;
+ */
case libvlc_MediaPlayerNothingSpecial:
case libvlc_MediaPlayerOpening:
case libvlc_MediaPlayerBuffering:
case libvlc_MediaPlayerPlaying:
case libvlc_MediaPlayerPaused:
case libvlc_MediaPlayerStopped:
+ break;
case libvlc_MediaPlayerEndReached:
+ that->setState(Stopped);
break;
case libvlc_MediaPlayerEncounteredError:
// TODO emit Error
diff --git a/src/libtomahawk/audio/AudioOutput.h b/src/libtomahawk/audio/AudioOutput.h
index 175c4c4bb..d5610f923 100644
--- a/src/libtomahawk/audio/AudioOutput.h
+++ b/src/libtomahawk/audio/AudioOutput.h
@@ -68,10 +68,12 @@ public slots:
signals:
void stateChanged( AudioOutput::AudioState, AudioOutput::AudioState );
void tick( qint64 );
+ void aboutToFinish();
private:
void setState( AudioState state );
void setCurrentTime( qint64 time );
+ void setTotalTime( qint64 time );
static void vlcEventCallback( const libvlc_event_t *event, void *opaque );
static void s_dspCallback( signed short* samples, int nb_channels, int nb_samples );
@@ -83,6 +85,7 @@ private:
qreal m_volume;
qint64 m_currentTime;
qint64 m_totalTime;
+ bool m_aboutToFinish;
void ( *dspPluginCallback ) ( signed short* samples, int nb_channels, int nb_samples );
diff --git a/src/libtomahawk/utils/MediaStream.cpp b/src/libtomahawk/utils/MediaStream.cpp
index 5b7dc7ad1..ac2cee4ab 100644
--- a/src/libtomahawk/utils/MediaStream.cpp
+++ b/src/libtomahawk/utils/MediaStream.cpp
@@ -29,6 +29,7 @@ static QString s_aeInfoIdentifier = QString( "MEDIASTREAM" );
MediaStream::MediaStream()
: m_type( Unknown )
, m_url( QUrl() )
+ , m_eos( false )
, m_pos( 0 )
, m_streamSize( 0 )
{
@@ -85,6 +86,15 @@ MediaStream::setStreamSize( qint64 size )
}
+void
+MediaStream::endOfData()
+{
+ tDebug() << Q_FUNC_INFO;
+
+ m_eos = true;
+}
+
+
int
MediaStream::readCallback ( void* data, const char* cookie, int64_t* dts, int64_t* pts, unsigned* flags, size_t* bufferSize, void** buffer )
{
@@ -97,6 +107,10 @@ MediaStream::readCallback ( void* data, const char* cookie, int64_t* dts, int64_
MediaStream* that = static_cast < MediaStream * > ( data );
+ if ( that->m_eos == true ) {
+ return -1;
+ }
+
*bufferSize = that->needData(buffer);
return 0;
}
@@ -110,7 +124,9 @@ MediaStream::readDoneCallback ( void *data, const char *cookie, size_t bufferSiz
Q_UNUSED(data);
Q_UNUSED(cookie);
Q_UNUSED(bufferSize);
- delete static_cast(buffer);
+
+// TODO : causes segfault
+// delete static_cast(buffer);
return 0;
}
diff --git a/src/libtomahawk/utils/MediaStream.h b/src/libtomahawk/utils/MediaStream.h
index 28000c4ca..b7dd67987 100644
--- a/src/libtomahawk/utils/MediaStream.h
+++ b/src/libtomahawk/utils/MediaStream.h
@@ -53,9 +53,12 @@ public:
static int seekCallback ( void *data, const uint64_t pos );
protected:
+ void endOfData();
+
MediaType m_type;
QUrl m_url;
+ bool m_eos;
qint64 m_pos;
qint64 m_streamSize;
};
diff --git a/src/libtomahawk/utils/Qnr_IoDeviceStream.cpp b/src/libtomahawk/utils/Qnr_IoDeviceStream.cpp
index ed72c4463..8c80fa3c2 100644
--- a/src/libtomahawk/utils/Qnr_IoDeviceStream.cpp
+++ b/src/libtomahawk/utils/Qnr_IoDeviceStream.cpp
@@ -100,7 +100,7 @@ QNR_IODeviceStream::needData ( void** buffer )
if ( ( data.size() == 0 ) && m_networkReply->atEnd() && m_networkReply->isFinished() )
{
// We're done.
-//TODO endOfData();
+ endOfData();
return 0;
}