mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-07-31 19:30:21 +02:00
Precache next track to play when reaching end of current song
This commit is contained in:
@@ -685,7 +685,7 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
qTrackname = queryTrack()->trackSortname();
|
||||
}
|
||||
|
||||
static const QRegExp filterOutChars = QRegExp(QString::fromUtf8("[-`´~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]"));
|
||||
static const QRegExp filterOutChars = QRegExp(QString::fromUtf8("[-`´~!@#$%^&*\\(\\)_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]"));
|
||||
|
||||
//Cleanup symbols for minor naming differences
|
||||
qArtistname.remove(filterOutChars);
|
||||
|
@@ -572,10 +572,10 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type )
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
AudioEngine::loadTrack( const Tomahawk::result_ptr& result, bool preload )
|
||||
{
|
||||
Q_D( AudioEngine );
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() ) << " preload:" << preload;
|
||||
|
||||
|
||||
if ( !d->audioOutput->isInitialized() )
|
||||
@@ -589,18 +589,57 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
return;
|
||||
}
|
||||
|
||||
// We do this to stop the audio as soon as a user activated another track
|
||||
// If we don't block the audioOutput signals, the state change will trigger
|
||||
// loading yet another track
|
||||
d->audioOutput->blockSignals( true );
|
||||
d->audioOutput->stop();
|
||||
d->audioOutput->blockSignals( false );
|
||||
if (preload && d->preloadedTrack == result)
|
||||
return;
|
||||
|
||||
setCurrentTrack( result );
|
||||
if (preload)
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << "not preloaded yet, preloading";
|
||||
|
||||
if (preload)
|
||||
{
|
||||
setPreloadTrack( result );
|
||||
}
|
||||
else
|
||||
{
|
||||
// We do this to stop the audio as soon as a user activated another track
|
||||
// If we don't block the audioOutput signals, the state change will trigger
|
||||
// loading yet another track
|
||||
d->audioOutput->blockSignals( true );
|
||||
d->audioOutput->stop();
|
||||
d->audioOutput->blockSignals( false );
|
||||
|
||||
setCurrentTrack( result );
|
||||
if ( result == d->preloadedTrack )
|
||||
{
|
||||
setPreloadTrack( Tomahawk::result_ptr(nullptr) );
|
||||
d->state = Loading;
|
||||
emit loading( d->currentTrack );
|
||||
d->audioOutput->switchToPreloadedMedia();
|
||||
if ( !d->input.isNull() )
|
||||
{
|
||||
d->input->close();
|
||||
d->input.clear();
|
||||
}
|
||||
d->input = d->inputPreloaded;
|
||||
|
||||
d->audioOutput->play();
|
||||
|
||||
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
|
||||
{
|
||||
d->currentTrack->track()->startPlaying();
|
||||
}
|
||||
|
||||
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowPlaying );
|
||||
return;
|
||||
}
|
||||
setPreloadTrack( Tomahawk::result_ptr(nullptr) );
|
||||
}
|
||||
|
||||
ScriptJob* job = result->resolvedBy()->getStreamUrl( result );
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( gotStreamUrl( QVariantMap ) ) );
|
||||
job->setProperty( "result", QVariant::fromValue( result ) );
|
||||
job->setProperty( "isPreload", QVariant::fromValue(preload) );
|
||||
tDebug() << "preload:" << preload << ", for result:" << result;
|
||||
job->start();
|
||||
}
|
||||
|
||||
@@ -611,6 +650,9 @@ AudioEngine::gotStreamUrl( const QVariantMap& data )
|
||||
QString streamUrl = data[ "url" ].toString();
|
||||
QVariantMap headers = data[ "headers" ].toMap();
|
||||
Tomahawk::result_ptr result = sender()->property( "result" ).value<result_ptr>();
|
||||
bool isPreload = sender()->property( "isPreload" ).value<bool>();
|
||||
|
||||
tDebug() << Q_FUNC_INFO << " is preload:" << isPreload << ", for result:" << result;
|
||||
|
||||
if ( streamUrl.isEmpty() || headers.isEmpty() ||
|
||||
!( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) ) )
|
||||
@@ -618,7 +660,7 @@ AudioEngine::gotStreamUrl( const QVariantMap& data )
|
||||
// We can't supply custom headers to VLC - but prefer using its HTTP streaming due to improved seeking ability
|
||||
// Not an RTMP or HTTP-with-headers URL, get IO device
|
||||
QSharedPointer< QIODevice > sp;
|
||||
performLoadIODevice( result, streamUrl );
|
||||
performLoadIODevice( result, streamUrl, isPreload );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -654,26 +696,32 @@ AudioEngine::gotStreamUrl( const QVariantMap& data )
|
||||
void
|
||||
AudioEngine::gotRedirectedStreamUrl( const Tomahawk::result_ptr& result, NetworkReply* reply )
|
||||
{
|
||||
Q_D( AudioEngine );
|
||||
// std::functions cannot accept temporaries as parameters
|
||||
QSharedPointer< QIODevice > sp ( reply->reply(), &QObject::deleteLater );
|
||||
QString url = reply->reply()->url().toString();
|
||||
reply->disconnectFromReply();
|
||||
reply->deleteLater();
|
||||
|
||||
performLoadTrack( result, url, sp );
|
||||
bool isPreload = result == d->preloadedTrack;
|
||||
tDebug() << Q_FUNC_INFO << " is preload:" << isPreload;
|
||||
|
||||
performLoadTrack( result, url, sp, isPreload );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::onPositionChanged( float new_position )
|
||||
{
|
||||
if ( new_position >= 0.90 )
|
||||
loadNextTrack(true);
|
||||
// tDebug() << Q_FUNC_INFO << new_position << state();
|
||||
emit trackPosition( new_position );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url )
|
||||
AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url, bool preload )
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : url );
|
||||
|
||||
@@ -683,37 +731,39 @@ AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url )
|
||||
std::function< void ( const QString, QSharedPointer< QIODevice > ) > callback =
|
||||
std::bind( &AudioEngine::performLoadTrack, this, result,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2 );
|
||||
std::placeholders::_2,
|
||||
preload );
|
||||
Tomahawk::UrlHandler::getIODeviceForUrl( result, url, callback );
|
||||
}
|
||||
else
|
||||
{
|
||||
QSharedPointer< QIODevice > io;
|
||||
performLoadTrack( result, url, io );
|
||||
performLoadTrack( result, url, io, preload );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io )
|
||||
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io, bool preload )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "performLoadTrack", Qt::QueuedConnection,
|
||||
Q_ARG( const Tomahawk::result_ptr, result ),
|
||||
Q_ARG( const QString, url ),
|
||||
Q_ARG( QSharedPointer< QIODevice >, io )
|
||||
Q_ARG( QSharedPointer< QIODevice >, io ),
|
||||
Q_ARG( bool, preload )
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
Q_D( AudioEngine );
|
||||
if ( currentTrack() != result )
|
||||
if ( !preload && currentTrack() != result )
|
||||
{
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Track loaded too late, skip.";
|
||||
return;
|
||||
}
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() ) << preload;
|
||||
QSharedPointer< QIODevice > ioToKeep = io;
|
||||
|
||||
bool err = false;
|
||||
@@ -727,9 +777,16 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
|
||||
|
||||
if ( !err )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Starting new song:" << url;
|
||||
d->state = Loading;
|
||||
emit loading( d->currentTrack );
|
||||
if (preload)
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Preloading new song:" << url;
|
||||
}
|
||||
else
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Starting new song:" << url;
|
||||
d->state = Loading;
|
||||
emit loading( d->currentTrack );
|
||||
}
|
||||
|
||||
if ( !TomahawkUtils::isLocalResult( url )
|
||||
&& !( TomahawkUtils::isHttpResult( url ) && io.isNull() )
|
||||
@@ -738,18 +795,18 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
|
||||
QSharedPointer<QNetworkReply> qnr = io.objectCast<QNetworkReply>();
|
||||
if ( !qnr.isNull() )
|
||||
{
|
||||
d->audioOutput->setCurrentSource( new QNR_IODeviceStream( qnr, this ) );
|
||||
d->audioOutput->setCurrentSource( new QNR_IODeviceStream( qnr, this ), preload );
|
||||
// We keep track of the QNetworkReply in QNR_IODeviceStream
|
||||
// and AudioOutput handles the deletion of the
|
||||
// QNR_IODeviceStream object
|
||||
ioToKeep.clear();
|
||||
d->audioOutput->setAutoDelete( true );
|
||||
d->audioOutput->setAutoDelete( true, preload );
|
||||
}
|
||||
else
|
||||
{
|
||||
d->audioOutput->setCurrentSource( io.data() );
|
||||
d->audioOutput->setCurrentSource( io.data(), preload);
|
||||
// We handle the deletion via tracking in d->input
|
||||
d->audioOutput->setAutoDelete( false );
|
||||
d->audioOutput->setAutoDelete( false, preload);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -768,7 +825,7 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
|
||||
}
|
||||
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Passing to VLC:" << furl;
|
||||
d->audioOutput->setCurrentSource( furl );
|
||||
d->audioOutput->setCurrentSource( furl, preload );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -777,26 +834,37 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
|
||||
furl = furl.right( furl.length() - 7 );
|
||||
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Passing to VLC:" << QUrl::fromLocalFile( furl );
|
||||
d->audioOutput->setCurrentSource( QUrl::fromLocalFile( furl ) );
|
||||
d->audioOutput->setCurrentSource( QUrl::fromLocalFile( furl ), preload );
|
||||
}
|
||||
|
||||
d->audioOutput->setAutoDelete( true );
|
||||
d->audioOutput->setAutoDelete( true, preload );
|
||||
}
|
||||
|
||||
if ( !d->input.isNull() )
|
||||
if ( preload ) {
|
||||
if ( !d->inputPreloaded.isNull() )
|
||||
{
|
||||
d->inputPreloaded->close();
|
||||
d->inputPreloaded.clear();
|
||||
}
|
||||
d->inputPreloaded = ioToKeep;
|
||||
}
|
||||
else
|
||||
{
|
||||
d->input->close();
|
||||
d->input.clear();
|
||||
}
|
||||
d->input = ioToKeep;
|
||||
d->audioOutput->play();
|
||||
if ( !d->input.isNull() )
|
||||
{
|
||||
d->input->close();
|
||||
d->input.clear();
|
||||
}
|
||||
d->input = ioToKeep;
|
||||
d->audioOutput->play();
|
||||
|
||||
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
|
||||
{
|
||||
d->currentTrack->track()->startPlaying();
|
||||
}
|
||||
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
|
||||
{
|
||||
d->currentTrack->track()->startPlaying();
|
||||
}
|
||||
|
||||
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowPlaying );
|
||||
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowPlaying );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,7 +874,10 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
|
||||
return;
|
||||
}
|
||||
|
||||
d->waitingOnNewTrack = false;
|
||||
if ( !preload )
|
||||
{
|
||||
d->waitingOnNewTrack = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -838,18 +909,19 @@ AudioEngine::loadPreviousTrack()
|
||||
}
|
||||
|
||||
if ( result )
|
||||
loadTrack( result );
|
||||
loadTrack( result, false );
|
||||
else
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::loadNextTrack()
|
||||
AudioEngine::loadNextTrack( bool preload )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "loadNextTrack", Qt::QueuedConnection );
|
||||
QMetaObject::invokeMethod( this, "loadNextTrack", Qt::QueuedConnection,
|
||||
Q_ARG( bool, preload ));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -863,8 +935,11 @@ AudioEngine::loadNextTrack()
|
||||
{
|
||||
if ( d->stopAfterTrack->track()->equals( d->currentTrack->track() ) )
|
||||
{
|
||||
d->stopAfterTrack.clear();
|
||||
stop();
|
||||
if ( !preload )
|
||||
{
|
||||
d->stopAfterTrack.clear();
|
||||
stop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -882,17 +957,24 @@ AudioEngine::loadNextTrack()
|
||||
|
||||
if ( d->playlist.data()->nextResult() )
|
||||
{
|
||||
result = d->playlist.data()->setSiblingResult( 1 );
|
||||
setCurrentTrackPlaylist( d->playlist );
|
||||
if ( preload )
|
||||
{
|
||||
result = d->playlist.data()->nextResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = d->playlist.data()->setSiblingResult( 1 );
|
||||
setCurrentTrackPlaylist( d->playlist );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( result )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Got next item, loading track";
|
||||
loadTrack( result );
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Got next item, loading track, preload:" << preload;
|
||||
loadTrack( result, preload );
|
||||
}
|
||||
else
|
||||
else if ( !preload )
|
||||
{
|
||||
if ( !d->playlist.isNull() && d->playlist.data()->retryMode() == Tomahawk::PlaylistModes::Retry )
|
||||
d->waitingOnNewTrack = true;
|
||||
@@ -961,7 +1043,7 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
|
||||
|
||||
if ( result )
|
||||
{
|
||||
loadTrack( result );
|
||||
loadTrack( result, false );
|
||||
}
|
||||
else if ( !d->playlist.isNull() && d->playlist.data()->retryMode() == PlaylistModes::Retry )
|
||||
{
|
||||
@@ -1236,6 +1318,14 @@ AudioEngine::setStopAfterTrack( const query_ptr& query )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::setPreloadTrack( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
Q_D( AudioEngine );
|
||||
|
||||
d->preloadedTrack = result;
|
||||
}
|
||||
|
||||
void
|
||||
AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
@@ -1262,7 +1352,6 @@ AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::setState( AudioState state )
|
||||
{
|
||||
|
@@ -135,10 +135,10 @@ public slots:
|
||||
void toggleMute();
|
||||
|
||||
void play( const QUrl& url );
|
||||
void playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::result_ptr& result, const Tomahawk::query_ptr& fromQuery = Tomahawk::query_ptr() );
|
||||
void playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::query_ptr& query );
|
||||
void playItem( const Tomahawk::artist_ptr& artist );
|
||||
void playItem( const Tomahawk::album_ptr& album );
|
||||
void playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::result_ptr& result, const Tomahawk::query_ptr& fromQuery = Tomahawk::query_ptr());
|
||||
void playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::query_ptr& query);
|
||||
void playItem( const Tomahawk::artist_ptr& artist);
|
||||
void playItem( const Tomahawk::album_ptr& album);
|
||||
void playPlaylistInterface( const Tomahawk::playlistinterface_ptr& playlist );
|
||||
void setPlaylist( Tomahawk::playlistinterface_ptr playlist );
|
||||
void setQueue( const Tomahawk::playlistinterface_ptr& queue );
|
||||
@@ -182,21 +182,22 @@ signals:
|
||||
void error( AudioEngine::AudioErrorCode errorCode );
|
||||
|
||||
private slots:
|
||||
void loadTrack( const Tomahawk::result_ptr& result ); //async!
|
||||
void loadTrack( const Tomahawk::result_ptr& result, bool preload ); //async!
|
||||
void gotStreamUrl( const QVariantMap& data );
|
||||
void gotRedirectedStreamUrl( const Tomahawk::result_ptr& result, NetworkReply* reply );
|
||||
|
||||
|
||||
void performLoadIODevice( const Tomahawk::result_ptr& result, const QString& url ); //only call from loadTrack kthxbi
|
||||
void performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io ); //only call from loadTrack or performLoadIODevice kthxbi
|
||||
void performLoadIODevice( const Tomahawk::result_ptr& result, const QString& url, bool preload ); //only call from loadTrack kthxbi
|
||||
void performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io, bool preload ); //only call from loadTrack or performLoadIODevice kthxbi
|
||||
void loadPreviousTrack();
|
||||
void loadNextTrack();
|
||||
void loadNextTrack(bool preload = false);
|
||||
|
||||
void onVolumeChanged( qreal volume );
|
||||
void timerTriggered( qint64 time );
|
||||
void onPositionChanged( float new_position );
|
||||
|
||||
void setCurrentTrack( const Tomahawk::result_ptr& result );
|
||||
void setPreloadTrack( const Tomahawk::result_ptr& result );
|
||||
void onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type );
|
||||
void onPlaylistNextTrackAvailable();
|
||||
|
||||
|
@@ -28,9 +28,11 @@ public slots:
|
||||
|
||||
private:
|
||||
QSharedPointer<QIODevice> input;
|
||||
QSharedPointer<QIODevice> inputPreloaded;
|
||||
|
||||
Tomahawk::query_ptr stopAfterTrack;
|
||||
Tomahawk::result_ptr currentTrack;
|
||||
Tomahawk::result_ptr preloadedTrack;
|
||||
Tomahawk::playlistinterface_ptr playlist;
|
||||
Tomahawk::playlistinterface_ptr currentTrackPlaylist;
|
||||
Tomahawk::playlistinterface_ptr queue;
|
||||
|
@@ -56,9 +56,11 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
: QObject( parent )
|
||||
, m_currentState( Stopped )
|
||||
, m_currentStream( nullptr )
|
||||
, m_preloadedStream( nullptr )
|
||||
, m_seekable( true )
|
||||
, m_muted( false )
|
||||
, m_autoDelete( true )
|
||||
, m_preloadedAutoDelete( true )
|
||||
, m_volume( 1.0 )
|
||||
, m_currentTime( 0 )
|
||||
, m_totalTime( 0 )
|
||||
@@ -68,6 +70,8 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
, m_vlcInstance( nullptr )
|
||||
, m_vlcPlayer( nullptr )
|
||||
, m_vlcMedia( nullptr )
|
||||
, m_vlcPreloadedPlayer( nullptr )
|
||||
, m_vlcPreloadedMedia( nullptr )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
@@ -123,37 +127,46 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
#endif
|
||||
|
||||
m_vlcPlayer = libvlc_media_player_new( m_vlcInstance );
|
||||
libvlc_event_manager_t* manager = libvlc_media_player_event_manager( m_vlcPlayer );
|
||||
libvlc_event_type_t events[] = {
|
||||
libvlc_MediaPlayerMediaChanged,
|
||||
libvlc_MediaPlayerNothingSpecial,
|
||||
libvlc_MediaPlayerOpening,
|
||||
libvlc_MediaPlayerBuffering,
|
||||
libvlc_MediaPlayerPlaying,
|
||||
libvlc_MediaPlayerPaused,
|
||||
libvlc_MediaPlayerStopped,
|
||||
libvlc_MediaPlayerForward,
|
||||
libvlc_MediaPlayerBackward,
|
||||
libvlc_MediaPlayerEndReached,
|
||||
libvlc_MediaPlayerEncounteredError,
|
||||
libvlc_MediaPlayerTimeChanged,
|
||||
libvlc_MediaPlayerPositionChanged,
|
||||
libvlc_MediaPlayerSeekableChanged,
|
||||
libvlc_MediaPlayerPausableChanged,
|
||||
libvlc_MediaPlayerTitleChanged,
|
||||
libvlc_MediaPlayerSnapshotTaken,
|
||||
//libvlc_MediaPlayerLengthChanged,
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
|
||||
libvlc_MediaPlayerAudioVolume,
|
||||
libvlc_MediaPlayerMuted,
|
||||
libvlc_MediaPlayerUnmuted,
|
||||
#endif
|
||||
libvlc_MediaPlayerVout
|
||||
};
|
||||
const int eventCount = sizeof(events) / sizeof( *events );
|
||||
for ( int i = 0; i < eventCount; i++ )
|
||||
m_vlcPreloadedPlayer = libvlc_media_player_new( m_vlcInstance );
|
||||
|
||||
for( auto player : { m_vlcPlayer, m_vlcPreloadedPlayer } )
|
||||
{
|
||||
libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
|
||||
libvlc_audio_set_mute( player, 0 );
|
||||
{
|
||||
libvlc_event_manager_t* current_manager = libvlc_media_player_event_manager( player );
|
||||
libvlc_event_manager_t* new_manager = libvlc_media_player_event_manager( player );
|
||||
static libvlc_event_type_t events[] = {
|
||||
libvlc_MediaPlayerMediaChanged,
|
||||
libvlc_MediaPlayerNothingSpecial,
|
||||
libvlc_MediaPlayerOpening,
|
||||
libvlc_MediaPlayerBuffering,
|
||||
libvlc_MediaPlayerPlaying,
|
||||
libvlc_MediaPlayerPaused,
|
||||
libvlc_MediaPlayerStopped,
|
||||
libvlc_MediaPlayerForward,
|
||||
libvlc_MediaPlayerBackward,
|
||||
libvlc_MediaPlayerEndReached,
|
||||
libvlc_MediaPlayerEncounteredError,
|
||||
libvlc_MediaPlayerTimeChanged,
|
||||
libvlc_MediaPlayerPositionChanged,
|
||||
libvlc_MediaPlayerSeekableChanged,
|
||||
libvlc_MediaPlayerPausableChanged,
|
||||
libvlc_MediaPlayerTitleChanged,
|
||||
libvlc_MediaPlayerSnapshotTaken,
|
||||
//libvlc_MediaPlayerLengthChanged,
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
|
||||
libvlc_MediaPlayerAudioVolume,
|
||||
libvlc_MediaPlayerMuted,
|
||||
libvlc_MediaPlayerUnmuted,
|
||||
#endif
|
||||
libvlc_MediaPlayerVout
|
||||
};
|
||||
const int eventCount = sizeof(events) / sizeof( *events );
|
||||
for ( int i = 0; i < eventCount; i++ )
|
||||
{
|
||||
libvlc_event_attach( new_manager, events[ i ], &AudioOutput::vlcEventCallback, this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HACK: play silent ogg file and set volume on that to workaround vlc not allowing to set volume before a file is played
|
||||
@@ -161,7 +174,9 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
Q_ASSERT( m_silenceFile.exists() );
|
||||
Q_ASSERT( m_silenceFile.open( QIODevice::ReadOnly ) );
|
||||
|
||||
setCurrentSource( new MediaStream( &m_silenceFile, true ) );
|
||||
setCurrentSource( new MediaStream( &m_silenceFile, true ), false );
|
||||
setCurrentSource( new MediaStream( &m_silenceFile, true ), true );
|
||||
|
||||
libvlc_media_player_play( m_vlcPlayer );
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,4,0)
|
||||
@@ -169,24 +184,71 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
QTimer::singleShot( 15000, [&]()
|
||||
{
|
||||
if ( !m_initialized ) {
|
||||
m_initialized = true;
|
||||
m_initialized = 2;
|
||||
emit initialized();
|
||||
}
|
||||
} );
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioOutput::switchToPreloadedMedia( void )
|
||||
{
|
||||
|
||||
//Swap
|
||||
auto tempPlayer = m_vlcPreloadedPlayer;
|
||||
m_vlcPreloadedPlayer = m_vlcPlayer;
|
||||
m_vlcPlayer = tempPlayer;
|
||||
|
||||
libvlc_media_player_stop( m_vlcPreloadedPlayer );
|
||||
|
||||
if ( m_vlcMedia != nullptr )
|
||||
{
|
||||
libvlc_media_release( m_vlcMedia );
|
||||
}
|
||||
//Now Media
|
||||
{
|
||||
if ( m_autoDelete && m_currentStream != nullptr )
|
||||
{
|
||||
delete m_currentStream;
|
||||
}
|
||||
|
||||
m_vlcMedia = m_vlcPreloadedMedia;
|
||||
m_vlcPreloadedMedia = nullptr;
|
||||
m_currentStream = m_preloadedStream;
|
||||
m_preloadedStream = nullptr;
|
||||
m_autoDelete = m_preloadedAutoDelete;
|
||||
|
||||
m_totalTime = libvlc_media_get_duration( m_vlcMedia );
|
||||
|
||||
m_currentTime = 0;
|
||||
m_justSeeked = false;
|
||||
m_seekable = true;
|
||||
}
|
||||
|
||||
libvlc_media_player_set_position( m_vlcPlayer, 0.0 );
|
||||
}
|
||||
|
||||
AudioOutput::~AudioOutput()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( m_vlcPreloadedPlayer != nullptr )
|
||||
{
|
||||
libvlc_media_player_stop( m_vlcPreloadedPlayer );
|
||||
libvlc_media_player_release( m_vlcPreloadedPlayer );
|
||||
m_vlcPreloadedPlayer = nullptr;
|
||||
}
|
||||
if ( m_vlcPlayer != nullptr )
|
||||
{
|
||||
libvlc_media_player_stop( m_vlcPlayer );
|
||||
libvlc_media_player_release( m_vlcPlayer );
|
||||
m_vlcPlayer = nullptr;
|
||||
}
|
||||
if ( m_vlcPreloadedMedia != nullptr )
|
||||
{
|
||||
libvlc_media_release( m_vlcPreloadedMedia );
|
||||
m_vlcPreloadedMedia = nullptr;
|
||||
}
|
||||
if ( m_vlcMedia != nullptr )
|
||||
{
|
||||
libvlc_media_release( m_vlcMedia );
|
||||
@@ -208,11 +270,19 @@ AudioOutput::onInitVlcEvent( const libvlc_event_t* event )
|
||||
setVolume( volume() );
|
||||
setMuted( isMuted() );
|
||||
|
||||
m_initialized = true;
|
||||
m_silenceFile.close();
|
||||
m_initialized ++;
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "Init OK";
|
||||
emit initialized();
|
||||
if (m_initialized >=2)
|
||||
{
|
||||
m_silenceFile.close();
|
||||
emit initialized();
|
||||
}
|
||||
else
|
||||
{
|
||||
switchToPreloadedMedia();
|
||||
libvlc_media_player_play( m_vlcPlayer );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -222,23 +292,26 @@ AudioOutput::onInitVlcEvent( const libvlc_event_t* event )
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::setAutoDelete( bool ad )
|
||||
AudioOutput::setAutoDelete( bool ad, bool preload )
|
||||
{
|
||||
m_autoDelete = ad;
|
||||
if (preload)
|
||||
m_preloadedAutoDelete = ad;
|
||||
else
|
||||
m_autoDelete = ad;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::setCurrentSource( const QUrl& stream )
|
||||
AudioOutput::setCurrentSource( const QUrl& stream, bool preload )
|
||||
{
|
||||
setCurrentSource( new MediaStream( stream ) );
|
||||
setCurrentSource( new MediaStream( stream ), preload );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::setCurrentSource( QIODevice* stream )
|
||||
AudioOutput::setCurrentSource( QIODevice* stream, bool preload )
|
||||
{
|
||||
setCurrentSource( new MediaStream( stream ) );
|
||||
setCurrentSource( new MediaStream( stream ), preload );
|
||||
}
|
||||
|
||||
|
||||
@@ -258,29 +331,24 @@ readDoneCallback( void* data, const char* cookie, size_t bufferSize, void* buffe
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::setCurrentSource( MediaStream* stream )
|
||||
AudioOutput::setCurrentSource( MediaStream* stream, bool preload )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
tDebug() << Q_FUNC_INFO << ", preload = " << preload;
|
||||
|
||||
setState( Loading );
|
||||
if ( !preload )
|
||||
setState( Loading );
|
||||
|
||||
if ( m_vlcMedia != nullptr )
|
||||
{
|
||||
// Ensure playback is stopped, then release media
|
||||
libvlc_media_player_stop( m_vlcPlayer );
|
||||
libvlc_media_release( m_vlcMedia );
|
||||
m_vlcMedia = nullptr;
|
||||
if ( m_vlcPreloadedMedia ) {
|
||||
libvlc_media_player_stop( m_vlcPreloadedPlayer );
|
||||
libvlc_media_release( m_vlcPreloadedMedia );
|
||||
m_vlcPreloadedMedia = nullptr;
|
||||
}
|
||||
if ( m_autoDelete && m_currentStream != nullptr )
|
||||
if ( m_preloadedAutoDelete && m_preloadedStream != nullptr )
|
||||
{
|
||||
delete m_currentStream;
|
||||
delete m_preloadedStream;
|
||||
}
|
||||
|
||||
m_currentStream = stream;
|
||||
m_totalTime = 0;
|
||||
m_currentTime = 0;
|
||||
m_justSeeked = false;
|
||||
m_seekable = true;
|
||||
m_preloadedStream = stream;
|
||||
|
||||
QByteArray url;
|
||||
switch ( stream->type() )
|
||||
@@ -314,23 +382,19 @@ AudioOutput::setCurrentSource( MediaStream* stream )
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "MediaStream::Final Url:" << url;
|
||||
|
||||
m_vlcMedia = libvlc_media_new_location( m_vlcInstance, url.constData() );
|
||||
if ( stream->type() == MediaStream::Url )
|
||||
{
|
||||
m_totalTime = libvlc_media_get_duration( m_vlcMedia );
|
||||
}
|
||||
else if ( stream->type() == MediaStream::Stream || stream->type() == MediaStream::IODevice )
|
||||
m_vlcPreloadedMedia = libvlc_media_new_location( m_vlcInstance, url.constData() );
|
||||
if ( stream->type() == MediaStream::Stream || stream->type() == MediaStream::IODevice )
|
||||
{
|
||||
QString tempString;
|
||||
libvlc_media_add_option_flag(m_vlcMedia, "imem-cat=4", libvlc_media_option_trusted);
|
||||
libvlc_media_add_option_flag(m_vlcPreloadedMedia, "imem-cat=4", libvlc_media_option_trusted);
|
||||
tempString = QString( "imem-data=%1" ).arg( (uintptr_t)stream );
|
||||
libvlc_media_add_option_flag(m_vlcMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
|
||||
libvlc_media_add_option_flag(m_vlcPreloadedMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
|
||||
tempString = QString( "imem-get=%1" ).arg( (uintptr_t)&readCallback );
|
||||
libvlc_media_add_option_flag(m_vlcMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
|
||||
libvlc_media_add_option_flag(m_vlcPreloadedMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
|
||||
tempString = QString( "imem-release=%1" ).arg( (uintptr_t)&readDoneCallback );
|
||||
libvlc_media_add_option_flag(m_vlcMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
|
||||
libvlc_media_add_option_flag(m_vlcPreloadedMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
|
||||
tempString = QString( "imem-seek=%1" ).arg( (uintptr_t)&MediaStream::seekCallback );
|
||||
libvlc_media_add_option_flag(m_vlcMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
|
||||
libvlc_media_add_option_flag(m_vlcPreloadedMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
|
||||
}
|
||||
if ( qApp->arguments().contains( "--chromecast-ip" ) )
|
||||
{
|
||||
@@ -346,7 +410,7 @@ AudioOutput::setCurrentSource( MediaStream* stream )
|
||||
{
|
||||
QString castIP = qApp->arguments().at( qApp->arguments().indexOf( "--chromecast-ip" ) + 1 );
|
||||
QString sout( ":sout=#transcode{vcodec=none,acodec=vorb,ab=320,channels=2,samplerate=44100}:chromecast{ip=%1,mux=webm}" );
|
||||
libvlc_media_add_option( m_vlcMedia, sout.arg( castIP ).toLatin1().constData() );
|
||||
libvlc_media_add_option( m_vlcPreloadedMedia, sout.arg( castIP ).toLatin1().constData() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -354,8 +418,8 @@ AudioOutput::setCurrentSource( MediaStream* stream )
|
||||
}
|
||||
}
|
||||
|
||||
libvlc_event_manager_t* manager = libvlc_media_event_manager( m_vlcMedia );
|
||||
libvlc_event_type_t events[] = {
|
||||
libvlc_event_manager_t* manager = libvlc_media_event_manager( m_vlcPreloadedMedia );
|
||||
static libvlc_event_type_t events[] = {
|
||||
libvlc_MediaDurationChanged,
|
||||
};
|
||||
const int eventCount = sizeof(events) / sizeof( *events );
|
||||
@@ -364,7 +428,13 @@ AudioOutput::setCurrentSource( MediaStream* stream )
|
||||
libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
|
||||
}
|
||||
|
||||
libvlc_media_player_set_media( m_vlcPlayer, m_vlcMedia );
|
||||
libvlc_media_player_set_media( m_vlcPreloadedPlayer, m_vlcPreloadedMedia );
|
||||
|
||||
libvlc_audio_set_volume( m_vlcPreloadedPlayer, 0.0 );
|
||||
libvlc_media_player_play( m_vlcPreloadedPlayer );
|
||||
|
||||
if ( !preload )
|
||||
switchToPreloadedMedia();
|
||||
|
||||
// setState( Stopped );
|
||||
}
|
||||
@@ -373,7 +443,7 @@ AudioOutput::setCurrentSource( MediaStream* stream )
|
||||
bool
|
||||
AudioOutput::isInitialized() const
|
||||
{
|
||||
return m_initialized;
|
||||
return m_initialized > 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -526,7 +596,7 @@ AudioOutput::seek( qint64 milliseconds )
|
||||
bool
|
||||
AudioOutput::isSeekable() const
|
||||
{
|
||||
// tDebug() << Q_FUNC_INFO << m_seekable << m_havePosition << m_totalTime << libvlc_media_player_is_seekable( m_vlcPlayer );
|
||||
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 );
|
||||
}
|
||||
|
||||
@@ -576,64 +646,107 @@ AudioOutput::setVolume( qreal vol )
|
||||
void
|
||||
AudioOutput::onVlcEvent( const libvlc_event_t* event )
|
||||
{
|
||||
switch ( event->type )
|
||||
if ( event->p_obj == m_vlcPlayer || event->p_obj == m_vlcMedia )
|
||||
{
|
||||
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;
|
||||
case libvlc_MediaDurationChanged:
|
||||
setTotalTime( event->u.media_duration_changed.new_duration );
|
||||
break;
|
||||
case libvlc_MediaPlayerLengthChanged:
|
||||
// tDebug() << Q_FUNC_INFO << " : length changed : " << event->u.media_player_length_changed.new_length;
|
||||
break;
|
||||
case libvlc_MediaPlayerPlaying:
|
||||
setState( Playing );
|
||||
break;
|
||||
case libvlc_MediaPlayerPaused:
|
||||
setState( Paused );
|
||||
break;
|
||||
case libvlc_MediaPlayerEndReached:
|
||||
setState( Stopped );
|
||||
break;
|
||||
case libvlc_MediaPlayerEncounteredError:
|
||||
tDebug() << Q_FUNC_INFO << "LibVLC error: MediaPlayerEncounteredError. Stopping";
|
||||
// Don't call stop() here - it will deadlock libvlc
|
||||
setState( Error );
|
||||
break;
|
||||
switch ( event->type )
|
||||
{
|
||||
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;
|
||||
case libvlc_MediaDurationChanged:
|
||||
setTotalTime( event->u.media_duration_changed.new_duration );
|
||||
break;
|
||||
case libvlc_MediaPlayerLengthChanged:
|
||||
// tDebug() << Q_FUNC_INFO << " : length changed : " << event->u.media_player_length_changed.new_length;
|
||||
break;
|
||||
case libvlc_MediaPlayerPlaying:
|
||||
setState( Playing );
|
||||
break;
|
||||
case libvlc_MediaPlayerPaused:
|
||||
setState( Paused );
|
||||
break;
|
||||
case libvlc_MediaPlayerEndReached:
|
||||
setState( Stopped );
|
||||
break;
|
||||
case libvlc_MediaPlayerEncounteredError:
|
||||
tDebug() << Q_FUNC_INFO << "LibVLC error: MediaPlayerEncounteredError. Stopping";
|
||||
// Don't call stop() here - it will deadlock libvlc
|
||||
setState( Error );
|
||||
break;
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
|
||||
case libvlc_MediaPlayerAudioVolume:
|
||||
m_volume = event->u.media_player_audio_volume.volume;
|
||||
emit volumeChanged( volume() );
|
||||
break;
|
||||
case libvlc_MediaPlayerMuted:
|
||||
m_muted = true;
|
||||
emit mutedChanged( true );
|
||||
break;
|
||||
case libvlc_MediaPlayerUnmuted:
|
||||
m_muted = false;
|
||||
emit mutedChanged( false );
|
||||
break;
|
||||
case libvlc_MediaPlayerAudioVolume:
|
||||
m_volume = event->u.media_player_audio_volume.volume;
|
||||
tDebug() << Q_FUNC_INFO << "Got signal in current player that volume changed to:" << m_volume;
|
||||
emit volumeChanged( volume() );
|
||||
break;
|
||||
case libvlc_MediaPlayerMuted:
|
||||
m_muted = true;
|
||||
emit mutedChanged( true );
|
||||
break;
|
||||
case libvlc_MediaPlayerUnmuted:
|
||||
m_muted = false;
|
||||
emit mutedChanged( false );
|
||||
break;
|
||||
#endif
|
||||
case libvlc_MediaPlayerNothingSpecial:
|
||||
case libvlc_MediaPlayerOpening:
|
||||
case libvlc_MediaPlayerBuffering:
|
||||
case libvlc_MediaPlayerStopped:
|
||||
case libvlc_MediaPlayerVout:
|
||||
case libvlc_MediaPlayerMediaChanged:
|
||||
case libvlc_MediaPlayerForward:
|
||||
case libvlc_MediaPlayerBackward:
|
||||
case libvlc_MediaPlayerPausableChanged:
|
||||
case libvlc_MediaPlayerTitleChanged:
|
||||
case libvlc_MediaPlayerSnapshotTaken:
|
||||
default:
|
||||
break;
|
||||
case libvlc_MediaPlayerNothingSpecial:
|
||||
case libvlc_MediaPlayerOpening:
|
||||
case libvlc_MediaPlayerBuffering:
|
||||
case libvlc_MediaPlayerStopped:
|
||||
case libvlc_MediaPlayerVout:
|
||||
case libvlc_MediaPlayerMediaChanged:
|
||||
case libvlc_MediaPlayerForward:
|
||||
case libvlc_MediaPlayerBackward:
|
||||
case libvlc_MediaPlayerPausableChanged:
|
||||
case libvlc_MediaPlayerTitleChanged:
|
||||
case libvlc_MediaPlayerSnapshotTaken:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tDebug() << "Event for preloaded: " << libvlc_event_type_name(event->type);
|
||||
switch ( event->type )
|
||||
{
|
||||
case libvlc_MediaPlayerPausableChanged:
|
||||
case libvlc_MediaPlayerPlaying:
|
||||
case libvlc_MediaPlayerMediaChanged:
|
||||
case libvlc_MediaPlayerTitleChanged:
|
||||
case libvlc_MediaPlayerSeekableChanged:
|
||||
case libvlc_MediaDurationChanged:
|
||||
case libvlc_MediaPlayerPositionChanged:
|
||||
case libvlc_MediaPlayerPaused:
|
||||
case libvlc_MediaPlayerBuffering:
|
||||
libvlc_media_player_set_pause( m_vlcPreloadedPlayer, 1 );
|
||||
libvlc_audio_set_volume( m_vlcPreloadedPlayer, 0.0 );
|
||||
libvlc_media_player_set_position( m_vlcPreloadedPlayer, 0.0 );
|
||||
break;
|
||||
case libvlc_MediaPlayerTimeChanged:
|
||||
case libvlc_MediaPlayerLengthChanged:
|
||||
case libvlc_MediaPlayerOpening:
|
||||
case libvlc_MediaPlayerEndReached:
|
||||
case libvlc_MediaPlayerEncounteredError:
|
||||
//TODO
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
|
||||
case libvlc_MediaPlayerAudioVolume:
|
||||
case libvlc_MediaPlayerMuted:
|
||||
case libvlc_MediaPlayerUnmuted:
|
||||
#endif
|
||||
case libvlc_MediaPlayerNothingSpecial:
|
||||
case libvlc_MediaPlayerStopped:
|
||||
case libvlc_MediaPlayerVout:
|
||||
case libvlc_MediaPlayerForward:
|
||||
case libvlc_MediaPlayerBackward:
|
||||
case libvlc_MediaPlayerSnapshotTaken:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -49,9 +49,10 @@ public:
|
||||
bool isInitialized() const;
|
||||
AudioState state() const;
|
||||
|
||||
void setCurrentSource( const QUrl& stream );
|
||||
void setCurrentSource( QIODevice* stream );
|
||||
void setCurrentSource( MediaStream* stream );
|
||||
void setCurrentSource( const QUrl& stream, bool preload );
|
||||
void setCurrentSource( QIODevice* stream, bool preload );
|
||||
void setCurrentSource( MediaStream* stream, bool preload );
|
||||
void setPreloadedSourceAsCurrent( void );
|
||||
|
||||
void play();
|
||||
void pause();
|
||||
@@ -65,13 +66,15 @@ public:
|
||||
qreal volume() const;
|
||||
qint64 currentTime() const;
|
||||
qint64 totalTime() const;
|
||||
void setAutoDelete ( bool ad );
|
||||
void setAutoDelete ( bool ad, bool preload );
|
||||
|
||||
void setDspCallback( std::function< void( int, int, float*, int, int ) > cb );
|
||||
|
||||
static AudioOutput* instance();
|
||||
libvlc_instance_t* vlcInstance() const;
|
||||
|
||||
void switchToPreloadedMedia( void );
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
@@ -90,6 +93,7 @@ private:
|
||||
void setCurrentPosition( float position );
|
||||
void setTotalTime( qint64 time );
|
||||
|
||||
|
||||
void onVlcEvent( const libvlc_event_t* event );
|
||||
static void vlcEventCallback( const libvlc_event_t* event, void* opaque );
|
||||
static void s_dspCallback( int frameNumber, float* samples, int nb_channels, int nb_samples );
|
||||
@@ -97,9 +101,11 @@ private:
|
||||
static AudioOutput* s_instance;
|
||||
AudioState m_currentState;
|
||||
MediaStream* m_currentStream;
|
||||
MediaStream* m_preloadedStream;
|
||||
bool m_seekable;
|
||||
bool m_muted;
|
||||
bool m_autoDelete;
|
||||
bool m_preloadedAutoDelete;
|
||||
bool m_havePosition;
|
||||
bool m_haveTiming;
|
||||
qreal m_volume;
|
||||
@@ -107,7 +113,7 @@ private:
|
||||
qint64 m_totalTime;
|
||||
bool m_justSeeked;
|
||||
|
||||
bool m_initialized;
|
||||
int m_initialized;
|
||||
QFile m_silenceFile;
|
||||
|
||||
std::function< void( int state, int frameNumber, float* samples, int nb_channels, int nb_samples ) > dspPluginCallback;
|
||||
@@ -115,6 +121,9 @@ private:
|
||||
libvlc_instance_t* m_vlcInstance;
|
||||
libvlc_media_player_t* m_vlcPlayer;
|
||||
libvlc_media_t* m_vlcMedia;
|
||||
libvlc_media_player_t* m_vlcBackPlayer;
|
||||
libvlc_media_player_t* m_vlcPreloadedPlayer;
|
||||
libvlc_media_t* m_vlcPreloadedMedia;
|
||||
};
|
||||
|
||||
#endif // AUDIOOUTPUT_H
|
||||
|
@@ -190,7 +190,7 @@ JSAccount::reportNativeScriptJobResult( int resultId, const QVariantMap& result
|
||||
.arg( serializeQVariantMap( result ) );
|
||||
|
||||
// Remove when new scripting api turned out to work reliably
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << eval;
|
||||
//tDebug( LOGVERBOSE ) << Q_FUNC_INFO << eval;
|
||||
|
||||
evaluateJavaScript( eval );
|
||||
}
|
||||
|
Reference in New Issue
Block a user