mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-11 08:34:34 +02:00
Merge pull request #448 from tomahawk-player/vlc-volume-fix
Fix #441: Handle VLC volume and muted state properly
This commit is contained in:
@@ -9,19 +9,20 @@ fi
|
|||||||
|
|
||||||
rm -rvf vlc/
|
rm -rvf vlc/
|
||||||
|
|
||||||
|
VLC_TARBALL="vlc-2.2.3.tar.bz2"
|
||||||
|
|
||||||
echo "Download phonon archive..."
|
echo "Download phonon archive..."
|
||||||
# wget -c "http://downloads.sourceforge.net/project/vlc/1.1.9/win32/vlc-1.1.9-win32.7z?r=http%3A%2F%2Fwww.videolan.org%2Fvlc%2Fdownload-windows.html&ts=1306272584&use_mirror=leaseweb"
|
# wget -c "http://downloads.sourceforge.net/project/vlc/1.1.9/win32/vlc-1.1.9-win32.7z?r=http%3A%2F%2Fwww.videolan.org%2Fvlc%2Fdownload-windows.html&ts=1306272584&use_mirror=leaseweb"
|
||||||
# wget -c "http://download.tomahawk-player.org/tomahawk-vlc-0.1.zip"
|
# wget -c "http://download.tomahawk-player.org/tomahawk-vlc-0.1.zip"
|
||||||
# wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z
|
# wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z
|
||||||
# wget -c http://people.videolan.org/~jb/phonon/phonon_phonon-vlc_20111128.7z
|
# wget -c http://people.videolan.org/~jb/phonon/phonon_phonon-vlc_20111128.7z
|
||||||
wget -c http://download.tomahawk-player.org/test/vlc.tar.bz2
|
wget -c "http://download.tomahawk-player.org/test/$VLC_TARBALL"
|
||||||
|
|
||||||
echo "Extract binary..."
|
echo "Extract binary..."
|
||||||
# 7z x phonon*.7z
|
# 7z x phonon*.7z
|
||||||
# mv -v vlc-*/ vlc/
|
# mv -v vlc-*/ vlc/
|
||||||
# unzip tomahawk-vlc-0.1.zip
|
# unzip tomahawk-vlc-0.1.zip
|
||||||
tar xvjf vlc.tar.bz2
|
tar xvjf "$VLC_TARBALL"
|
||||||
|
|
||||||
# echo "Download phonon_vlc_no_video.dll..."
|
# echo "Download phonon_vlc_no_video.dll..."
|
||||||
# wget -c http://people.videolan.org/~jb/phonon/phonon_vlc_no_video.dll
|
# wget -c http://people.videolan.org/~jb/phonon/phonon_vlc_no_video.dll
|
||||||
|
BIN
data/sounds/silence.ogg
Normal file
BIN
data/sounds/silence.ogg
Normal file
Binary file not shown.
@@ -170,5 +170,6 @@
|
|||||||
<file>data/images/downloadbutton.svg</file>
|
<file>data/images/downloadbutton.svg</file>
|
||||||
<file>data/images/nav-back.svg</file>
|
<file>data/images/nav-back.svg</file>
|
||||||
<file>data/images/nav-forward.svg</file>
|
<file>data/images/nav-forward.svg</file>
|
||||||
|
<file>data/sounds/silence.ogg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -929,6 +929,20 @@ TomahawkSettings::setVolume( unsigned int volume )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
TomahawkSettings::muted() const
|
||||||
|
{
|
||||||
|
return value( "audio/muted" ).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TomahawkSettings::setMuted( bool muted )
|
||||||
|
{
|
||||||
|
setValue( "audio/muted", muted );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QString
|
QString
|
||||||
TomahawkSettings::proxyHost() const
|
TomahawkSettings::proxyHost() const
|
||||||
{
|
{
|
||||||
|
@@ -107,6 +107,9 @@ public:
|
|||||||
unsigned int volume() const;
|
unsigned int volume() const;
|
||||||
void setVolume( unsigned int volume );
|
void setVolume( unsigned int volume );
|
||||||
|
|
||||||
|
bool muted() const;
|
||||||
|
void setMuted( bool muted );
|
||||||
|
|
||||||
/// Playlist stuff
|
/// Playlist stuff
|
||||||
QByteArray playlistColumnSizes( const QString& playlistid ) const;
|
QByteArray playlistColumnSizes( const QString& playlistid ) const;
|
||||||
void setPlaylistColumnSizes( const QString& playlistid, const QByteArray& state );
|
void setPlaylistColumnSizes( const QString& playlistid, const QByteArray& state );
|
||||||
|
@@ -167,10 +167,17 @@ AudioEngine::AudioEngine()
|
|||||||
|
|
||||||
d->audioOutput = new AudioOutput( this );
|
d->audioOutput = new AudioOutput( this );
|
||||||
|
|
||||||
|
connect( d->audioOutput, SIGNAL( initialized() ), this, SIGNAL( initialized() ) );
|
||||||
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( positionChanged( float ) ), SLOT( onPositionChanged( float ) ) );
|
connect( d->audioOutput, SIGNAL( positionChanged( float ) ), SLOT( onPositionChanged( float ) ) );
|
||||||
|
connect( d->audioOutput, SIGNAL( volumeChanged( qreal ) ), SLOT( onVolumeChanged( qreal ) ) );
|
||||||
|
connect( d->audioOutput, SIGNAL( mutedChanged( bool ) ), SIGNAL( mutedChanged( bool ) ) );
|
||||||
|
|
||||||
|
if ( TomahawkSettings::instance()->muted() )
|
||||||
|
{
|
||||||
|
mute();
|
||||||
|
}
|
||||||
setVolume( TomahawkSettings::instance()->volume() );
|
setVolume( TomahawkSettings::instance()->volume() );
|
||||||
|
|
||||||
qRegisterMetaType< AudioErrorCode >("AudioErrorCode");
|
qRegisterMetaType< AudioErrorCode >("AudioErrorCode");
|
||||||
@@ -183,6 +190,7 @@ AudioEngine::~AudioEngine()
|
|||||||
tDebug() << Q_FUNC_INFO;
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
TomahawkSettings::instance()->setVolume( volume() );
|
TomahawkSettings::instance()->setVolume( volume() );
|
||||||
|
TomahawkSettings::instance()->setMuted( isMuted() );
|
||||||
|
|
||||||
delete d_ptr;
|
delete d_ptr;
|
||||||
}
|
}
|
||||||
@@ -289,8 +297,11 @@ AudioEngine::stop( AudioErrorCode errorCode )
|
|||||||
if ( d->waitingOnNewTrack )
|
if ( d->waitingOnNewTrack )
|
||||||
sendWaitingNotification();
|
sendWaitingNotification();
|
||||||
|
|
||||||
Tomahawk::InfoSystem::InfoPushData pushData( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowStopped, QVariant(), Tomahawk::InfoSystem::PushNoFlag );
|
if ( d->audioOutput->isInitialized() )
|
||||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
|
{
|
||||||
|
Tomahawk::InfoSystem::InfoPushData pushData( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowStopped, QVariant(), Tomahawk::InfoSystem::PushNoFlag );
|
||||||
|
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -566,6 +577,12 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
|||||||
Q_D( AudioEngine );
|
Q_D( AudioEngine );
|
||||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
||||||
|
|
||||||
|
|
||||||
|
if ( !d->audioOutput->isInitialized() )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !result )
|
if ( !result )
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
|
@@ -149,6 +149,8 @@ public slots:
|
|||||||
void setShuffled( bool enabled );
|
void setShuffled( bool enabled );
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void initialized();
|
||||||
|
|
||||||
void loading( const Tomahawk::result_ptr track );
|
void loading( const Tomahawk::result_ptr track );
|
||||||
void started( const Tomahawk::result_ptr track );
|
void started( const Tomahawk::result_ptr track );
|
||||||
void finished( const Tomahawk::result_ptr track );
|
void finished( const Tomahawk::result_ptr track );
|
||||||
|
@@ -25,11 +25,13 @@
|
|||||||
|
|
||||||
#include "audio/MediaStream.h"
|
#include "audio/MediaStream.h"
|
||||||
#include "utils/Logger.h"
|
#include "utils/Logger.h"
|
||||||
|
#include "utils/TomahawkUtils.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QVarLengthArray>
|
#include <QVarLengthArray>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include <vlc/libvlc.h>
|
#include <vlc/libvlc.h>
|
||||||
#include <vlc/libvlc_media.h>
|
#include <vlc/libvlc_media.h>
|
||||||
@@ -58,6 +60,7 @@ AudioOutput::AudioOutput( QObject* parent )
|
|||||||
, m_currentTime( 0 )
|
, m_currentTime( 0 )
|
||||||
, m_totalTime( 0 )
|
, m_totalTime( 0 )
|
||||||
, m_justSeeked( false )
|
, m_justSeeked( false )
|
||||||
|
, m_initialized( false )
|
||||||
, dspPluginCallback( nullptr )
|
, dspPluginCallback( nullptr )
|
||||||
, m_vlcInstance( nullptr )
|
, m_vlcInstance( nullptr )
|
||||||
, m_vlcPlayer( nullptr )
|
, m_vlcPlayer( nullptr )
|
||||||
@@ -120,6 +123,11 @@ AudioOutput::AudioOutput( QObject* parent )
|
|||||||
libvlc_MediaPlayerTitleChanged,
|
libvlc_MediaPlayerTitleChanged,
|
||||||
libvlc_MediaPlayerSnapshotTaken,
|
libvlc_MediaPlayerSnapshotTaken,
|
||||||
//libvlc_MediaPlayerLengthChanged,
|
//libvlc_MediaPlayerLengthChanged,
|
||||||
|
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
|
||||||
|
libvlc_MediaPlayerAudioVolume,
|
||||||
|
libvlc_MediaPlayerMuted,
|
||||||
|
libvlc_MediaPlayerUnmuted,
|
||||||
|
#endif
|
||||||
libvlc_MediaPlayerVout
|
libvlc_MediaPlayerVout
|
||||||
};
|
};
|
||||||
const int eventCount = sizeof(events) / sizeof( *events );
|
const int eventCount = sizeof(events) / sizeof( *events );
|
||||||
@@ -128,8 +136,24 @@ AudioOutput::AudioOutput( QObject* parent )
|
|||||||
libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
|
libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_muted = isMuted();
|
// HACK: play silent ogg file and set volume on that to workaround vlc not allowing to set volume before a file is played
|
||||||
tDebug() << Q_FUNC_INFO << "Init OK";
|
m_silenceFile.setFileName( RESPATH "sounds/silence.ogg" );
|
||||||
|
Q_ASSERT( m_silenceFile.exists() );
|
||||||
|
Q_ASSERT( m_silenceFile.open( QIODevice::ReadOnly ) );
|
||||||
|
|
||||||
|
setCurrentSource( new MediaStream( &m_silenceFile, true ) );
|
||||||
|
libvlc_media_player_play( m_vlcPlayer );
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5,4,0)
|
||||||
|
// if the silence file did not play for 15 secs, we pretend the AudioOutput is initialized, to allow proper error reporting
|
||||||
|
QTimer::singleShot( 15000, [&]()
|
||||||
|
{
|
||||||
|
if ( !m_initialized ) {
|
||||||
|
m_initialized = true;
|
||||||
|
emit initialized();
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -155,6 +179,28 @@ AudioOutput::~AudioOutput()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::onInitVlcEvent( const libvlc_event_t* event )
|
||||||
|
{
|
||||||
|
switch ( event->type )
|
||||||
|
{
|
||||||
|
case libvlc_MediaPlayerTimeChanged:
|
||||||
|
setVolume( volume() );
|
||||||
|
setMuted( isMuted() );
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
|
m_silenceFile.close();
|
||||||
|
|
||||||
|
tDebug() << Q_FUNC_INFO << "Init OK";
|
||||||
|
emit initialized();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioOutput::setAutoDelete( bool ad )
|
AudioOutput::setAutoDelete( bool ad )
|
||||||
{
|
{
|
||||||
@@ -303,6 +349,13 @@ AudioOutput::setCurrentSource( MediaStream* stream )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioOutput::isInitialized() const
|
||||||
|
{
|
||||||
|
return m_initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AudioOutput::AudioState
|
AudioOutput::AudioState
|
||||||
AudioOutput::state() const
|
AudioOutput::state() const
|
||||||
{
|
{
|
||||||
@@ -457,7 +510,7 @@ AudioOutput::isSeekable() const
|
|||||||
bool
|
bool
|
||||||
AudioOutput::isMuted() const
|
AudioOutput::isMuted() const
|
||||||
{
|
{
|
||||||
return libvlc_audio_get_mute( m_vlcPlayer );
|
return m_muted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -530,6 +583,20 @@ AudioOutput::onVlcEvent( const libvlc_event_t* event )
|
|||||||
// Don't call stop() here - it will deadlock libvlc
|
// Don't call stop() here - it will deadlock libvlc
|
||||||
setState( Error );
|
setState( Error );
|
||||||
break;
|
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;
|
||||||
|
#endif
|
||||||
case libvlc_MediaPlayerNothingSpecial:
|
case libvlc_MediaPlayerNothingSpecial:
|
||||||
case libvlc_MediaPlayerOpening:
|
case libvlc_MediaPlayerOpening:
|
||||||
case libvlc_MediaPlayerBuffering:
|
case libvlc_MediaPlayerBuffering:
|
||||||
@@ -555,7 +622,14 @@ AudioOutput::vlcEventCallback( const libvlc_event_t* event, void* opaque )
|
|||||||
AudioOutput* that = reinterpret_cast < AudioOutput * > ( opaque );
|
AudioOutput* that = reinterpret_cast < AudioOutput * > ( opaque );
|
||||||
Q_ASSERT( that );
|
Q_ASSERT( that );
|
||||||
|
|
||||||
that->onVlcEvent( event );
|
if ( !that->isInitialized() )
|
||||||
|
{
|
||||||
|
that->onInitVlcEvent( event );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
that->onVlcEvent( event );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -25,6 +25,8 @@
|
|||||||
#include "DllMacro.h"
|
#include "DllMacro.h"
|
||||||
#include "Typedefs.h"
|
#include "Typedefs.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
struct libvlc_instance_t;
|
struct libvlc_instance_t;
|
||||||
@@ -44,6 +46,7 @@ public:
|
|||||||
explicit AudioOutput( QObject* parent = nullptr );
|
explicit AudioOutput( QObject* parent = nullptr );
|
||||||
~AudioOutput();
|
~AudioOutput();
|
||||||
|
|
||||||
|
bool isInitialized() const;
|
||||||
AudioState state() const;
|
AudioState state() const;
|
||||||
|
|
||||||
void setCurrentSource( const QUrl& stream );
|
void setCurrentSource( const QUrl& stream );
|
||||||
@@ -72,11 +75,16 @@ public:
|
|||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void initialized();
|
||||||
void stateChanged( AudioOutput::AudioState, AudioOutput::AudioState );
|
void stateChanged( AudioOutput::AudioState, AudioOutput::AudioState );
|
||||||
void tick( qint64 );
|
void tick( qint64 );
|
||||||
void positionChanged( float );
|
void positionChanged( float );
|
||||||
|
void volumeChanged( qreal volume );
|
||||||
|
void mutedChanged( bool );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void onInitVlcEvent( const libvlc_event_t* event );
|
||||||
|
|
||||||
void setState( AudioState state );
|
void setState( AudioState state );
|
||||||
void setCurrentTime( qint64 time );
|
void setCurrentTime( qint64 time );
|
||||||
void setCurrentPosition( float position );
|
void setCurrentPosition( float position );
|
||||||
@@ -99,6 +107,9 @@ private:
|
|||||||
qint64 m_totalTime;
|
qint64 m_totalTime;
|
||||||
bool m_justSeeked;
|
bool m_justSeeked;
|
||||||
|
|
||||||
|
bool m_initialized;
|
||||||
|
QFile m_silenceFile;
|
||||||
|
|
||||||
std::function< void( int state, int frameNumber, float* samples, int nb_channels, int nb_samples ) > dspPluginCallback;
|
std::function< void( int state, int frameNumber, float* samples, int nb_channels, int nb_samples ) > dspPluginCallback;
|
||||||
|
|
||||||
libvlc_instance_t* m_vlcInstance;
|
libvlc_instance_t* m_vlcInstance;
|
||||||
|
@@ -41,12 +41,16 @@ MediaStream::MediaStream( const QUrl &url )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MediaStream::MediaStream( QIODevice* device )
|
MediaStream::MediaStream( QIODevice* device, bool bufferingFinished )
|
||||||
: QObject( nullptr )
|
: QObject( nullptr )
|
||||||
, m_type( IODevice )
|
, m_type( IODevice )
|
||||||
, m_ioDevice ( device )
|
, m_ioDevice ( device )
|
||||||
|
, m_bufferingFinished( bufferingFinished )
|
||||||
{
|
{
|
||||||
QObject::connect( m_ioDevice, SIGNAL( readChannelFinished() ), this, SLOT( bufferingFinished() ) );
|
if ( !bufferingFinished )
|
||||||
|
{
|
||||||
|
QObject::connect( m_ioDevice, SIGNAL( readChannelFinished() ), this, SLOT( bufferingFinished() ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
MediaStream( QObject* parent = nullptr );
|
MediaStream( QObject* parent = nullptr );
|
||||||
explicit MediaStream( const QUrl &url );
|
explicit MediaStream( const QUrl &url );
|
||||||
explicit MediaStream( QIODevice* device );
|
explicit MediaStream( QIODevice* device, bool bufferingFinished = false );
|
||||||
virtual ~MediaStream();
|
virtual ~MediaStream();
|
||||||
|
|
||||||
MediaType type() const;
|
MediaType type() const;
|
||||||
|
Reference in New Issue
Block a user