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:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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 );
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user