1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-21 05:11:44 +02:00

More track duration calculation and seeking

This commit is contained in:
dridri
2014-09-30 01:30:44 +02:00
committed by Uwe L. Korn
parent 5daca7f0e7
commit ce3d372749
6 changed files with 93 additions and 13 deletions

View File

@@ -109,9 +109,9 @@ AudioEnginePrivate::onStateChanged( AudioOutput::AudioState newState, AudioOutpu
case AudioOutput::Paused: case AudioOutput::Paused:
{ {
if ( audioOutput && currentTrack ) if ( audioOutput && currentTrack )
{/* TODO {
qint64 duration = audioOutput->totalTime() > 0 ? audioOutput->totalTime() : currentTrack->track()->duration() * 1000; qint64 duration = audioOutput->totalTime() > 0 ? audioOutput->totalTime() : currentTrack->track()->duration() * 1000;
stopped = ( duration - 1000 < audioOutput->currentTime() ); */ stopped = ( duration - 1000 < audioOutput->currentTime() );
} }
else else
stopped = true; stopped = true;
@@ -133,7 +133,7 @@ AudioEnginePrivate::onStateChanged( AudioOutput::AudioState newState, AudioOutpu
if ( stopped && expectStop ) if ( stopped && expectStop )
{ {
expectStop = false; expectStop = false;
tDebug( LOGVERBOSE ) << "Finding next track."; tDebug() << "Finding next track.";
if ( q_ptr->canGoNext() ) if ( q_ptr->canGoNext() )
{ {
q_ptr->loadNextTrack(); 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( 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( tick( qint64 ) ), SLOT( timerTriggered( qint64 ) ) );
connect( d->audioOutput, SIGNAL( aboutToFinish() ), SLOT( onAboutToFinish() ) );
qRegisterMetaType< AudioErrorCode >("AudioErrorCode"); qRegisterMetaType< AudioErrorCode >("AudioErrorCode");
qRegisterMetaType< AudioState >("AudioState"); qRegisterMetaType< AudioState >("AudioState");
@@ -1248,6 +1249,11 @@ AudioEngine::currentTime() const
qint64 qint64
AudioEngine::currentTrackTotalTime() const 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(); return d_func()->audioOutput->totalTime();
} }

View File

@@ -18,6 +18,7 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "AudioEngine.h"
#include "AudioOutput.h" #include "AudioOutput.h"
#include "utils/Logger.h" #include "utils/Logger.h"
@@ -37,6 +38,7 @@
static QString s_aeInfoIdentifier = QString( "AUDIOOUTPUT" ); static QString s_aeInfoIdentifier = QString( "AUDIOOUTPUT" );
static const int ABOUT_TO_FINISH_TIME = 2000;
AudioOutput* AudioOutput::s_instance = 0; AudioOutput* AudioOutput::s_instance = 0;
@@ -55,6 +57,7 @@ AudioOutput::AudioOutput( QObject* parent )
, m_volume( 1.0 ) , m_volume( 1.0 )
, m_currentTime( 0 ) , m_currentTime( 0 )
, m_totalTime( 0 ) , m_totalTime( 0 )
, m_aboutToFinish( false )
, dspPluginCallback( 0 ) , dspPluginCallback( 0 )
{ {
tDebug() << Q_FUNC_INFO; tDebug() << Q_FUNC_INFO;
@@ -62,6 +65,8 @@ AudioOutput::AudioOutput( QObject* parent )
AudioOutput::s_instance = this; AudioOutput::s_instance = this;
currentStream = 0; currentStream = 0;
qRegisterMetaType<AudioOutput::AudioState>("AudioOutput::AudioState");
QList<QByteArray> args; QList<QByteArray> args;
args << "--ignore-config"; args << "--ignore-config";
@@ -113,7 +118,7 @@ AudioOutput::AudioOutput( QObject* parent )
libvlc_MediaPlayerPausableChanged, libvlc_MediaPlayerPausableChanged,
libvlc_MediaPlayerTitleChanged, libvlc_MediaPlayerTitleChanged,
libvlc_MediaPlayerSnapshotTaken, libvlc_MediaPlayerSnapshotTaken,
libvlc_MediaPlayerLengthChanged, //libvlc_MediaPlayerLengthChanged,
libvlc_MediaPlayerVout libvlc_MediaPlayerVout
}; };
const int eventCount = sizeof(events) / sizeof( *events ); const int eventCount = sizeof(events) / sizeof( *events );
@@ -142,9 +147,12 @@ void
AudioOutput::setCurrentSource(MediaStream* stream) AudioOutput::setCurrentSource(MediaStream* stream)
{ {
tDebug() << Q_FUNC_INFO; tDebug() << Q_FUNC_INFO;
currentStream = stream;
currentState = Loading; setState(Loading);
currentStream = stream;
m_totalTime = 0;
m_currentTime = 0;
QByteArray url; QByteArray url;
switch (stream->type()) { switch (stream->type()) {
@@ -173,10 +181,21 @@ AudioOutput::setCurrentSource(MediaStream* stream)
tDebug() << "MediaStream::Final Url:" << url; tDebug() << "MediaStream::Final Url:" << url;
vlcMedia = libvlc_media_new_location( vlcInstance, url.constData() ); 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 ); libvlc_media_player_set_media( vlcPlayer, vlcMedia );
if ( stream->type() == MediaStream::Url ) { if ( stream->type() == MediaStream::Url ) {
m_totalTime = libvlc_media_get_duration( vlcMedia ); 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");
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 ) AudioOutput::setState( AudioState state )
{ {
tDebug() << Q_FUNC_INFO; tDebug() << Q_FUNC_INFO;
emit stateChanged ( state, currentState ); AudioState last = currentState;
currentState = state; currentState = state;
emit stateChanged ( state, last );
} }
@@ -226,7 +247,20 @@ void
AudioOutput::setCurrentTime( qint64 time ) AudioOutput::setCurrentTime( qint64 time )
{ {
m_currentTime = time; m_currentTime = time;
if ( m_totalTime <= 0 ) {
m_totalTime = AudioEngine::instance()->currentTrackTotalTime();
}
emit tick( time ); 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 void
AudioOutput::play() AudioOutput::play()
{ {
@@ -367,16 +412,23 @@ AudioOutput::vlcEventCallback( const libvlc_event_t* event, void* opaque )
case libvlc_MediaPlayerSeekableChanged: case libvlc_MediaPlayerSeekableChanged:
//TODO, bool event->u.media_player_seekable_changed.new_seekable //TODO, bool event->u.media_player_seekable_changed.new_seekable
break; break;
case libvlc_MediaPlayerLengthChanged: case libvlc_MediaDurationChanged:
that->m_totalTime = event->u.media_player_length_changed.new_length; that->setTotalTime( event->u.media_duration_changed.new_duration );
break; break;
/*
case libvlc_MediaPlayerLengthChanged:
that->setTotalTime( event->u.media_player_length_changed.new_length );
break;
*/
case libvlc_MediaPlayerNothingSpecial: case libvlc_MediaPlayerNothingSpecial:
case libvlc_MediaPlayerOpening: case libvlc_MediaPlayerOpening:
case libvlc_MediaPlayerBuffering: case libvlc_MediaPlayerBuffering:
case libvlc_MediaPlayerPlaying: case libvlc_MediaPlayerPlaying:
case libvlc_MediaPlayerPaused: case libvlc_MediaPlayerPaused:
case libvlc_MediaPlayerStopped: case libvlc_MediaPlayerStopped:
break;
case libvlc_MediaPlayerEndReached: case libvlc_MediaPlayerEndReached:
that->setState(Stopped);
break; break;
case libvlc_MediaPlayerEncounteredError: case libvlc_MediaPlayerEncounteredError:
// TODO emit Error // TODO emit Error

View File

@@ -68,10 +68,12 @@ public slots:
signals: signals:
void stateChanged( AudioOutput::AudioState, AudioOutput::AudioState ); void stateChanged( AudioOutput::AudioState, AudioOutput::AudioState );
void tick( qint64 ); void tick( qint64 );
void aboutToFinish();
private: private:
void setState( AudioState state ); void setState( AudioState state );
void setCurrentTime( qint64 time ); void setCurrentTime( qint64 time );
void setTotalTime( qint64 time );
static void vlcEventCallback( const libvlc_event_t *event, void *opaque ); static void vlcEventCallback( const libvlc_event_t *event, void *opaque );
static void s_dspCallback( signed short* samples, int nb_channels, int nb_samples ); static void s_dspCallback( signed short* samples, int nb_channels, int nb_samples );
@@ -83,6 +85,7 @@ private:
qreal m_volume; qreal m_volume;
qint64 m_currentTime; qint64 m_currentTime;
qint64 m_totalTime; qint64 m_totalTime;
bool m_aboutToFinish;
void ( *dspPluginCallback ) ( signed short* samples, int nb_channels, int nb_samples ); void ( *dspPluginCallback ) ( signed short* samples, int nb_channels, int nb_samples );

View File

@@ -29,6 +29,7 @@ static QString s_aeInfoIdentifier = QString( "MEDIASTREAM" );
MediaStream::MediaStream() MediaStream::MediaStream()
: m_type( Unknown ) : m_type( Unknown )
, m_url( QUrl() ) , m_url( QUrl() )
, m_eos( false )
, m_pos( 0 ) , m_pos( 0 )
, m_streamSize( 0 ) , m_streamSize( 0 )
{ {
@@ -85,6 +86,15 @@ MediaStream::setStreamSize( qint64 size )
} }
void
MediaStream::endOfData()
{
tDebug() << Q_FUNC_INFO;
m_eos = true;
}
int int
MediaStream::readCallback ( void* data, const char* cookie, int64_t* dts, int64_t* pts, unsigned* flags, size_t* bufferSize, void** buffer ) 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 ); MediaStream* that = static_cast < MediaStream * > ( data );
if ( that->m_eos == true ) {
return -1;
}
*bufferSize = that->needData(buffer); *bufferSize = that->needData(buffer);
return 0; return 0;
} }
@@ -110,7 +124,9 @@ MediaStream::readDoneCallback ( void *data, const char *cookie, size_t bufferSiz
Q_UNUSED(data); Q_UNUSED(data);
Q_UNUSED(cookie); Q_UNUSED(cookie);
Q_UNUSED(bufferSize); Q_UNUSED(bufferSize);
delete static_cast<char *>(buffer);
// TODO : causes segfault
// delete static_cast<char *>(buffer);
return 0; return 0;
} }

View File

@@ -53,9 +53,12 @@ public:
static int seekCallback ( void *data, const uint64_t pos ); static int seekCallback ( void *data, const uint64_t pos );
protected: protected:
void endOfData();
MediaType m_type; MediaType m_type;
QUrl m_url; QUrl m_url;
bool m_eos;
qint64 m_pos; qint64 m_pos;
qint64 m_streamSize; qint64 m_streamSize;
}; };

View File

@@ -100,7 +100,7 @@ QNR_IODeviceStream::needData ( void** buffer )
if ( ( data.size() == 0 ) && m_networkReply->atEnd() && m_networkReply->isFinished() ) if ( ( data.size() == 0 ) && m_networkReply->atEnd() && m_networkReply->isFinished() )
{ {
// We're done. // We're done.
//TODO endOfData(); endOfData();
return 0; return 0;
} }