From 0c8710ce4c791d2f463d42f7e4cbda2e42f321a1 Mon Sep 17 00:00:00 2001 From: Anton Romanov Date: Wed, 15 Apr 2015 19:55:14 -0700 Subject: [PATCH] Fallback to position-based progress/seeking if timing info is not available --- src/libtomahawk/audio/AudioEngine.cpp | 9 ++-- src/libtomahawk/audio/AudioEngine.h | 3 ++ src/libtomahawk/audio/AudioOutput.cpp | 76 ++++++++++++++++++--------- src/libtomahawk/audio/AudioOutput.h | 3 ++ src/tomahawk/AudioControls.cpp | 25 ++++++++- src/tomahawk/AudioControls.h | 2 + 6 files changed, 89 insertions(+), 29 deletions(-) diff --git a/src/libtomahawk/audio/AudioEngine.cpp b/src/libtomahawk/audio/AudioEngine.cpp index 3c572ab1a..90218405f 100644 --- a/src/libtomahawk/audio/AudioEngine.cpp +++ b/src/libtomahawk/audio/AudioEngine.cpp @@ -401,10 +401,6 @@ AudioEngine::canSeek() { Q_D( AudioEngine ); - if ( !d->audioOutput->isSeekable() ) { - return false; - } - return !d->playlist.isNull() && ( d->playlist.data()->seekRestrictions() != PlaylistModes::NoSeek ); } @@ -606,6 +602,11 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result ) } } +void AudioEngine::positionChanged(float new_position) +{ + emit trackPosition( new_position ); +} + void AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url ) diff --git a/src/libtomahawk/audio/AudioEngine.h b/src/libtomahawk/audio/AudioEngine.h index 168b540a2..aff5e24f6 100644 --- a/src/libtomahawk/audio/AudioEngine.h +++ b/src/libtomahawk/audio/AudioEngine.h @@ -147,6 +147,8 @@ public slots: void setRepeatMode( Tomahawk::PlaylistModes::RepeatMode mode ); void setShuffled( bool enabled ); + void positionChanged(float new_position); + signals: void loading( const Tomahawk::result_ptr track ); void started( const Tomahawk::result_ptr track ); @@ -171,6 +173,7 @@ signals: void timerMilliSeconds( qint64 msElapsed ); void timerSeconds( unsigned int secondsElapsed ); void timerPercentage( unsigned int percentage ); + void trackPosition( float position ); void playlistChanged( Tomahawk::playlistinterface_ptr playlist ); void currentTrackPlaylistChanged( Tomahawk::playlistinterface_ptr playlist ); diff --git a/src/libtomahawk/audio/AudioOutput.cpp b/src/libtomahawk/audio/AudioOutput.cpp index 8ce2a467e..7de589e17 100644 --- a/src/libtomahawk/audio/AudioOutput.cpp +++ b/src/libtomahawk/audio/AudioOutput.cpp @@ -37,7 +37,7 @@ #include #include -static const int ABOUT_TO_FINISH_TIME = 2000; +static const float ABOUT_TO_FINISH_POS = 0.95f; AudioOutput* AudioOutput::s_instance = 0; @@ -53,8 +53,8 @@ AudioOutput::AudioOutput( QObject* parent ) : QObject( parent ) , m_currentState( Stopped ) , m_currentStream( nullptr ) - , m_seekable( true ) , m_muted( false ) + , m_seekable( true ) , m_autoDelete ( true ) , m_volume( 1.0 ) , m_currentTime( 0 ) @@ -306,6 +306,22 @@ AudioOutput::currentTime() const return m_currentTime; } +void +AudioOutput::setCurrentPosition( float position ) +{ + //tDebug() << Q_FUNC_INFO << position; + AudioEngine::instance()->positionChanged(position); + m_havePosition = position > 0.0; + if ( position < ABOUT_TO_FINISH_POS ) + { + m_aboutToFinish = false; + } + else if ( !m_aboutToFinish ) + { + m_aboutToFinish = true; + emit aboutToFinish(); + } +} void AudioOutput::setCurrentTime( qint64 time ) @@ -315,7 +331,6 @@ AudioOutput::setCurrentTime( qint64 time ) if ( m_totalTime == 0 ) { m_totalTime = AudioEngine::instance()->currentTrackTotalTime(); - m_seekable = true; } m_currentTime = time; @@ -331,14 +346,24 @@ AudioOutput::setCurrentTime( qint64 time ) total = AudioEngine::instance()->currentTrackTotalTime(); } - if ( time < total - ABOUT_TO_FINISH_TIME ) + if ( time <= 0 ) { - m_aboutToFinish = false; + m_seekable = false; + } else { + m_seekable = true; } - if ( !m_aboutToFinish && total > 0 && time >= total - ABOUT_TO_FINISH_TIME ) + + if ( !m_havePosition ) { - m_aboutToFinish = true; - emit aboutToFinish(); + if ( time < ABOUT_TO_FINISH_POS * total ) + { + m_aboutToFinish = false; + } + else if ( !m_aboutToFinish ) + { + m_aboutToFinish = true; + emit aboutToFinish(); + } } } @@ -355,13 +380,9 @@ AudioOutput::setTotalTime( qint64 time ) { // tDebug() << Q_FUNC_INFO << time; - if ( time <= 0 ) - { - m_seekable = false; - } else + if ( time > 0 ) { m_totalTime = time; - m_seekable = true; // emit current time to refresh total time emit tick( time ); } @@ -411,12 +432,6 @@ AudioOutput::seek( qint64 milliseconds ) { tDebug() << Q_FUNC_INFO; - // Even seek if reported as not seekable. VLC can seek in some cases where - // it tells us it can't. - // if ( !seekable ) { - // return; - // } - switch ( m_currentState ) { case Playing: @@ -428,18 +443,29 @@ AudioOutput::seek( qint64 milliseconds ) return; } - // tDebug() << Q_FUNC_INFO << "AudioOutput:: seeking" << milliseconds << "msec"; + if ( m_seekable ) + { + // tDebug() << Q_FUNC_INFO << "AudioOutput:: seeking" << milliseconds << "msec"; + libvlc_media_player_set_time( m_vlcPlayer, milliseconds ); + setCurrentTime( milliseconds ); + } + else + { + qint64 duration = AudioEngine::instance()->currentTrackTotalTime(); + float position = float(float(milliseconds) / duration); + libvlc_media_player_set_position(m_vlcPlayer, position); + tDebug() << Q_FUNC_INFO << "AudioOutput:: seeking via position" << position << "pos"; + } m_justSeeked = true; - libvlc_media_player_set_time( m_vlcPlayer, milliseconds ); - setCurrentTime( milliseconds ); } bool AudioOutput::isSeekable() const { - return m_seekable; + tDebug() << Q_FUNC_INFO << m_seekable << m_havePosition << m_totalTime << libvlc_media_player_is_seekable( m_vlcPlayer ); + return !m_havePosition || (libvlc_media_player_is_seekable( m_vlcPlayer ) && m_totalTime > 0); } @@ -495,6 +521,9 @@ AudioOutput::onVlcEvent( const libvlc_event_t* event ) case libvlc_MediaPlayerTimeChanged: setCurrentTime( event->u.media_player_time_changed.new_time ); break; + case libvlc_MediaPlayerPositionChanged: + setCurrentPosition(event->u.media_player_position_changed.new_position); + break; case libvlc_MediaPlayerSeekableChanged: // tDebug() << Q_FUNC_INFO << " : seekable changed : " << event->u.media_player_seekable_changed.new_seekable; break; @@ -526,7 +555,6 @@ AudioOutput::onVlcEvent( const libvlc_event_t* event ) case libvlc_MediaPlayerMediaChanged: case libvlc_MediaPlayerForward: case libvlc_MediaPlayerBackward: - case libvlc_MediaPlayerPositionChanged: case libvlc_MediaPlayerPausableChanged: case libvlc_MediaPlayerTitleChanged: case libvlc_MediaPlayerSnapshotTaken: diff --git a/src/libtomahawk/audio/AudioOutput.h b/src/libtomahawk/audio/AudioOutput.h index cf643f7a2..ed314619f 100644 --- a/src/libtomahawk/audio/AudioOutput.h +++ b/src/libtomahawk/audio/AudioOutput.h @@ -79,6 +79,7 @@ signals: private: void setState( AudioState state ); void setCurrentTime( qint64 time ); + void setCurrentPosition( float position ); void setTotalTime( qint64 time ); void onVlcEvent( const libvlc_event_t* event ); @@ -91,6 +92,8 @@ private: bool m_seekable; bool m_muted; bool m_autoDelete; + bool m_havePosition; + bool m_haveTiming; qreal m_volume; qint64 m_currentTime; qint64 m_totalTime; diff --git a/src/tomahawk/AudioControls.cpp b/src/tomahawk/AudioControls.cpp index ed6dc7df0..9bf45f75c 100644 --- a/src/tomahawk/AudioControls.cpp +++ b/src/tomahawk/AudioControls.cpp @@ -56,6 +56,7 @@ AudioControls::AudioControls( QWidget* parent ) , ui( new Ui::AudioControls ) , m_repeatMode( PlaylistModes::NoRepeat ) , m_shuffled( false ) + , m_haveTiming ( false ) , m_lastSliderCheck( 0 ) , m_parent( parent ) { @@ -166,6 +167,7 @@ AudioControls::AudioControls( QWidget* parent ) connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ) ); connect( AudioEngine::instance(), SIGNAL( seeked( qint64 ) ), SLOT( onPlaybackSeeked( qint64 ) ) ); connect( AudioEngine::instance(), SIGNAL( timerMilliSeconds( qint64 ) ), SLOT( onPlaybackTimer( qint64 ) ) ); + connect( AudioEngine::instance(), SIGNAL( trackPosition( float ) ), SLOT( onTrackPosition( float ) ) ); connect( AudioEngine::instance(), SIGNAL( volumeChanged( int ) ), SLOT( onVolumeChanged( int ) ) ); connect( AudioEngine::instance(), SIGNAL( mutedChanged( bool ) ), SLOT( onMutedChanged( bool ) ) ); connect( AudioEngine::instance(), SIGNAL( controlStateChanged() ), SLOT( onControlStateChanged() ) ); @@ -469,7 +471,10 @@ AudioControls::onPlaybackSeeked( qint64 msec ) { tDebug( LOGEXTRA ) << Q_FUNC_INFO; m_seeked = true; - onPlaybackTimer( msec ); + if ( m_haveTiming ) + { + onPlaybackTimer( msec ); + } } @@ -517,6 +522,20 @@ AudioControls::onPlaybackStopped() } +void +AudioControls::onTrackPosition( float position ) +{ + if (!m_haveTiming) + { + qint64 duration = AudioEngine::instance()->currentTrackTotalTime(); + ui->seekSlider->blockSignals( true ); + ui->seekSlider->setSliderPosition( position * duration ); + ui->seekSlider->blockSignals( false ); + m_sliderTimeLine.stop(); + } +} + + void AudioControls::onPlaybackTimer( qint64 msElapsed ) { @@ -541,7 +560,11 @@ AudioControls::onPlaybackTimer( qint64 msElapsed ) m_phononTickCheckTimer.start( 500 ); if ( msElapsed == 0 ) + { + m_haveTiming = false; return; + } + m_haveTiming = true; int currentTime = m_sliderTimeLine.currentTime(); //tDebug( LOGEXTRA ) << Q_FUNC_INFO << "msElapsed =" << msElapsed << "and timer current time =" << currentTime << "and audio engine state is" << (int)AudioEngine::instance()->state(); diff --git a/src/tomahawk/AudioControls.h b/src/tomahawk/AudioControls.h index 4f16784fa..75325f828 100644 --- a/src/tomahawk/AudioControls.h +++ b/src/tomahawk/AudioControls.h @@ -75,6 +75,7 @@ private slots: void onPlaybackStopped(); void onPlaybackTimer( qint64 msElapsed ); + void onTrackPosition( float position ); void onVolumeChanged( int volume ); void onMutedChanged( bool muted ); void onControlStateChanged(); @@ -111,6 +112,7 @@ private: QTimer m_phononTickCheckTimer; QTimeLine m_sliderTimeLine; bool m_seeked; + bool m_haveTiming; qint64 m_lastSliderCheck; qint64 m_lastTextSecondShown;