mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-18 03:41:27 +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:
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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>("AudioOutput::AudioState");
|
||||
|
||||
QList<QByteArray> 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
|
||||
|
@@ -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 );
|
||||
|
||||
|
@@ -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<char *>(buffer);
|
||||
|
||||
// TODO : causes segfault
|
||||
// delete static_cast<char *>(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user