Commit 64a6e968 authored by Erwan Tulou's avatar Erwan Tulou

skins2: avoid deadlock when audio-visual is used (accounts for vlc often but...

skins2: avoid deadlock when audio-visual is used (accounts for vlc often but not always hanging in this case)

Audio-visual holds the audio_mixer lock during its initialization phase which includes initialization of the vout.
On the other hand, skins polls every 10ms to check change in the audio volume (this also requires holding the audio_mixer lock)
This leads to a frequent deadlock at the skins level.

The patch stops polling w.r.t volume and rather reacts on change signalled by the core via a callback. This makes deadlock occurence almost nil.

A long term solution could be that 1/ audio_visual doesn't keep on holding the lock during vout initialisation and 2/ skins stops polling every 10ms for a whole bunch of things (rather use callbacks as qt4 does)
parent 3567c033
......@@ -22,6 +22,7 @@
*****************************************************************************/
#include "cmd_audio.hpp"
#include "../src/vlcproc.hpp"
#include <vlc_aout.h>
#include <string>
......@@ -53,3 +54,10 @@ void CmdSetEqualizer::execute()
}
}
void CmdVolumeChanged::execute()
{
VlcProc* p_VlcProc = getIntf()->p_sys->p_vlcProc;
p_VlcProc->refreshVolume();
}
......@@ -46,4 +46,21 @@ class CmdSetEqualizer: public CmdGeneric
};
/// Command to enable/disable the equalizer
class CmdVolumeChanged: public CmdGeneric
{
public:
CmdVolumeChanged( intf_thread_t *pIntf ) : CmdGeneric( pIntf ) {}
virtual ~CmdVolumeChanged() {}
/// This method does the real job of the command
virtual void execute();
/// Return the type of the command
virtual string getType() const { return "set volume"; }
private:
};
#endif
......@@ -47,6 +47,7 @@
#include "../commands/cmd_vars.hpp"
#include "../commands/cmd_dialogs.hpp"
#include "../commands/cmd_update_item.hpp"
#include "../commands/cmd_audio.hpp"
#include "../utils/var_bool.hpp"
#include <sstream>
......@@ -137,6 +138,9 @@ VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ),
// so they must put commands in the queue and NOT do anything else
// (X11 calls are not reentrant)
// Called when volume sound changes
var_AddCallback( pIntf->p_libvlc, "volume-change",
onVolumeChanged, this );
// Called when the playlist changes
var_AddCallback( pIntf->p_sys->p_playlist, "intf-change",
onIntfChange, this );
......@@ -180,6 +184,8 @@ VlcProc::~VlcProc()
interaction_Unregister( getIntf() );
var_DelCallback( getIntf()->p_libvlc, "volume-change",
onVolumeChanged, this );
var_DelCallback( getIntf()->p_sys->p_playlist, "intf-change",
onIntfChange, this );
var_DelCallback( getIntf()->p_sys->p_playlist, "playlist-item-append",
......@@ -252,6 +258,14 @@ void VlcProc::refreshAudio()
pFilters = config_GetPsz( getIntf(), "audio-filter" );
}
// Refresh the equalizer variable
VarBoolImpl *pVarEqualizer = (VarBoolImpl*)m_cVarEqualizer.get();
pVarEqualizer->set( pFilters && strstr( pFilters, "equalizer" ) );
free( pFilters );
}
void VlcProc::refreshVolume()
{
// Refresh sound volume
audio_volume_t volume;
aout_VolumeGet( getIntf()->p_sys->p_playlist, &volume );
......@@ -261,11 +275,6 @@ void VlcProc::refreshAudio()
// Set the mute variable
VarBoolImpl *pVarMute = (VarBoolImpl*)m_cVarMute.get();
pVarMute->set( volume == 0 );
// Refresh the equalizer variable
VarBoolImpl *pVarEqualizer = (VarBoolImpl*)m_cVarEqualizer.get();
pVarEqualizer->set( pFilters && strstr( pFilters, "equalizer" ) );
free( pFilters );
}
void VlcProc::refreshPlaylist()
......@@ -372,6 +381,23 @@ void VlcProc::refreshInput()
}
}
int VlcProc::onVolumeChanged( vlc_object_t *pObj, const char *pVariable,
vlc_value_t oldVal, vlc_value_t newVal,
void *pParam )
{
VlcProc *pThis = (VlcProc*)pParam;
// Create a playtree notify command (for new style playtree)
CmdVolumeChanged *pCmd = new CmdVolumeChanged( pThis->getIntf() );
// Push the command in the asynchronous command queue
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
pQueue->push( CmdGenericPtr( pCmd ) );
return VLC_SUCCESS;
}
int VlcProc::onIntfChange( vlc_object_t *pObj, const char *pVariable,
vlc_value_t oldVal, vlc_value_t newVal,
void *pParam )
......
......@@ -85,6 +85,9 @@ class VlcProc: public SkinObject
/// Indicate whether the embedded video output is currently used
bool isVoutUsed() const { return m_pVout != NULL; }
/// Refresh Volume
void refreshVolume();
protected:
// Protected because it is a singleton
VlcProc( intf_thread_t *pIntf );
......@@ -154,6 +157,11 @@ class VlcProc: public SkinObject
/// Update the stream name variable
void updateStreamName();
/// Callback for volume variable
static int onVolumeChanged( vlc_object_t *pObj, const char *pVariable,
vlc_value_t oldVal, vlc_value_t newVal,
void *pParam );
/// Callback for intf-change variable
static int onIntfChange( vlc_object_t *pObj, const char *pVariable,
vlc_value_t oldVal, vlc_value_t newVal,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment