mirror of https://code.videolan.org/videolan/vlc
905 lines
30 KiB
C++
905 lines
30 KiB
C++
/*****************************************************************************
|
|
* vlcproc.cpp
|
|
*****************************************************************************
|
|
* Copyright (C) 2003-2019 the VideoLAN team
|
|
*
|
|
* Authors: Cyril Deguet <asmax@via.ecp.fr>
|
|
* Olivier Teulière <ipkiss@via.ecp.fr>
|
|
* Erwan Tulou <erwan10@videolan.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <vlc_common.h>
|
|
#include <vlc_aout.h>
|
|
#include <vlc_vout.h>
|
|
#include <vlc_player.h>
|
|
#include <vlc_playlist.h>
|
|
#include <vlc_url.h>
|
|
#include <vlc_strings.h>
|
|
|
|
#include "vlcproc.hpp"
|
|
#include "os_factory.hpp"
|
|
#include "os_loop.hpp"
|
|
#include "os_timer.hpp"
|
|
#include "var_manager.hpp"
|
|
#include "vout_manager.hpp"
|
|
#include "fsc_window.hpp"
|
|
#include "theme.hpp"
|
|
#include "window_manager.hpp"
|
|
#include "../commands/async_queue.hpp"
|
|
#include "../commands/cmd_change_skin.hpp"
|
|
#include "../commands/cmd_show_window.hpp"
|
|
#include "../commands/cmd_quit.hpp"
|
|
#include "../commands/cmd_resize.hpp"
|
|
#include "../commands/cmd_vars.hpp"
|
|
#include "../commands/cmd_playtree.hpp"
|
|
#include "../commands/cmd_dialogs.hpp"
|
|
#include "../commands/cmd_audio.hpp"
|
|
#include "../commands/cmd_callbacks.hpp"
|
|
#include "../utils/var_bool.hpp"
|
|
#include "../utils/var_string.hpp"
|
|
#include <sstream>
|
|
|
|
#include <cassert>
|
|
|
|
void on_playlist_items_reset( vlc_playlist_t *playlist,
|
|
vlc_playlist_item_t *const items[],
|
|
size_t count, void *data )
|
|
{
|
|
(void)playlist;(void)items;(void)count;
|
|
VlcProc *pThis = (VlcProc*)data;
|
|
CmdGeneric *pCmdTree = new CmdPlaytreeReset( pThis->getIntf() );
|
|
|
|
// Push the command in the asynchronous command queue
|
|
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
|
|
pQueue->push( CmdGenericPtr( pCmdTree ), true );
|
|
}
|
|
|
|
void on_playlist_items_added( vlc_playlist_t *playlist, size_t index,
|
|
vlc_playlist_item_t *const items[],
|
|
size_t count, void *data )
|
|
{
|
|
(void)playlist;(void)items;
|
|
VlcProc *pThis = (VlcProc*)data;
|
|
for( size_t i = 0; i < count; i++ )
|
|
{
|
|
CmdGeneric *pCmdTree =
|
|
new CmdPlaytreeAppend( pThis->getIntf(), index + i );
|
|
|
|
// Push the command in the asynchronous command queue
|
|
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
|
|
pQueue->push( CmdGenericPtr( pCmdTree ), false );
|
|
}
|
|
}
|
|
|
|
void on_playlist_items_removed( vlc_playlist_t *playlist, size_t index,
|
|
size_t count, void *data )
|
|
{
|
|
(void)playlist;
|
|
VlcProc *pThis = (VlcProc*)data;
|
|
for( size_t i = 0; i < count; i++ )
|
|
{
|
|
CmdPlaytreeDelete *pCmdTree =
|
|
new CmdPlaytreeDelete( pThis->getIntf(), index + i );
|
|
|
|
// Push the command in the asynchronous command queue
|
|
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
|
|
pQueue->push( CmdGenericPtr( pCmdTree ), false );
|
|
}
|
|
}
|
|
|
|
void on_playlist_items_updated( vlc_playlist_t *playlist, size_t index,
|
|
vlc_playlist_item_t *const items[],
|
|
size_t count, void *data )
|
|
{
|
|
(void)playlist;(void)items;
|
|
VlcProc *pThis = (VlcProc*)data;
|
|
for( size_t i = 0; i < count; i++ )
|
|
{
|
|
CmdGeneric *pCmd = new CmdItemUpdate( pThis->getIntf(), index + i );
|
|
|
|
// Push the command in the asynchronous command queue
|
|
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
|
|
pQueue->push( CmdGenericPtr( pCmd ), false );
|
|
}
|
|
}
|
|
|
|
void on_playlist_playback_repeat_changed( vlc_playlist_t *playlist,
|
|
enum vlc_playlist_playback_repeat repeat, void *data)
|
|
{
|
|
(void)playlist;
|
|
vlc_value_t val = { .i_int = repeat };
|
|
VlcProc::onGenericCallback( "repeat", val, data );
|
|
}
|
|
|
|
void on_playlist_playback_order_changed( vlc_playlist_t *playlist,
|
|
enum vlc_playlist_playback_order order, void *data)
|
|
{
|
|
(void)playlist;
|
|
vlc_value_t val = { .i_int = order };
|
|
VlcProc::onGenericCallback( "order", val, data );
|
|
}
|
|
|
|
void on_playlist_current_index_changed( vlc_playlist_t *playlist,
|
|
ssize_t index, void *data )
|
|
{
|
|
(void)playlist;
|
|
VlcProc *pThis = (VlcProc*)data;
|
|
msg_Dbg( pThis->getIntf(), "current index changed %i", (int)index );
|
|
CmdGeneric *pCmd = new CmdItemPlaying( pThis->getIntf(), index );
|
|
|
|
// Push the command in the asynchronous command queue
|
|
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
|
|
pQueue->push( CmdGenericPtr( pCmd ), false );
|
|
}
|
|
|
|
void on_player_current_media_changed( vlc_player_t *player,
|
|
input_item_t *media, void *data )
|
|
{
|
|
(void)player;
|
|
vlc_value_t val = { .p_address = media };
|
|
if( media ) input_item_Hold( media );
|
|
VlcProc::onGenericCallback( "current_media", val, data );
|
|
}
|
|
|
|
void on_player_state_changed( vlc_player_t *player,
|
|
enum vlc_player_state new_state, void *data)
|
|
{
|
|
(void)player;
|
|
vlc_value_t val = { .i_int = new_state };
|
|
VlcProc::onGenericCallback( "state", val, data );
|
|
}
|
|
|
|
void on_player_rate_changed( vlc_player_t *player, float new_rate, void *data )
|
|
{
|
|
(void)player;
|
|
vlc_value_t val = { .f_float = new_rate };
|
|
VlcProc::onGenericCallback( "rate", val, data );
|
|
}
|
|
|
|
void on_player_capabilities_changed( vlc_player_t *player,
|
|
int old_caps, int new_caps, void *data )
|
|
{
|
|
(void)player;(void)old_caps;
|
|
vlc_value_t val = { .i_int = new_caps };
|
|
VlcProc::onGenericCallback( "capabilities", val, data );
|
|
}
|
|
|
|
void on_player_position_changed( vlc_player_t *player, vlc_tick_t time,
|
|
double pos, void *data )
|
|
{
|
|
(void)player;(void)time;
|
|
vlc_value_t val = { .f_float = static_cast<float>(pos)};
|
|
VlcProc::onGenericCallback( "position", val, data );
|
|
}
|
|
|
|
void on_player_track_selection_changed( vlc_player_t *player,
|
|
vlc_es_id_t *unselected_id, vlc_es_id_t *selected_id, void *data)
|
|
{
|
|
(void)player;
|
|
vlc_value_t val;
|
|
const struct vlc_player_track *track;
|
|
|
|
if( selected_id )
|
|
{
|
|
track = vlc_player_GetTrack( player, selected_id );
|
|
if( track && track->fmt.i_cat == AUDIO_ES )
|
|
{
|
|
val.b_bool = true;
|
|
VlcProc::onGenericCallback( "audio_es", val, data );
|
|
|
|
val.i_int = track->fmt.i_bitrate;
|
|
VlcProc::onGenericCallback( "bit_rate", val, data );
|
|
|
|
val.i_int = track->fmt.audio.i_rate;
|
|
VlcProc::onGenericCallback( "sample_rate", val, data );
|
|
}
|
|
}
|
|
else if( unselected_id )
|
|
{
|
|
track = vlc_player_GetSelectedTrack( player, AUDIO_ES );
|
|
if( !track )
|
|
{
|
|
val.b_bool = false;
|
|
VlcProc::onGenericCallback( "audio_es", val, data );
|
|
|
|
val.i_int = 0;
|
|
VlcProc::onGenericCallback( "bit_rate", val, data );
|
|
VlcProc::onGenericCallback( "sample_rate", val, data );
|
|
}
|
|
}
|
|
}
|
|
|
|
void on_player_titles_changed( vlc_player_t *player,
|
|
vlc_player_title_list *titles, void *data)
|
|
{
|
|
(void)player;
|
|
if (!titles) {
|
|
return;
|
|
}
|
|
bool isDvd = vlc_player_title_list_GetCount( titles ) > 0;
|
|
vlc_value_t val = { .b_bool = isDvd };
|
|
VlcProc::onGenericCallback( "isDvd", val, data );
|
|
}
|
|
|
|
void on_player_recording_changed( vlc_player_t *player,
|
|
bool recording, void *data )
|
|
{
|
|
(void)player;
|
|
vlc_value_t val;
|
|
val.b_bool = recording;
|
|
VlcProc::onGenericCallback( "recording", val, data );
|
|
}
|
|
|
|
void on_player_vout_changed( vlc_player_t *player,
|
|
enum vlc_player_vout_action action, vout_thread_t *vout,
|
|
enum vlc_vout_order order, vlc_es_id_t *es_id, void *data )
|
|
{
|
|
(void)player;(void)order;(void)es_id;
|
|
vlc_value_t val = { .p_address = NULL };
|
|
if( vout && action == VLC_PLAYER_VOUT_STARTED )
|
|
{
|
|
val.p_address = vout;
|
|
vout_Hold( vout );
|
|
}
|
|
VlcProc::onGenericCallback( "vout", val, data );
|
|
}
|
|
|
|
void on_player_aout_volume_changed( audio_output *aout,
|
|
float volume, void *data )
|
|
{
|
|
(void)aout;
|
|
vlc_value_t val = { .f_float = volume };
|
|
VlcProc::onGenericCallback( "volume", val, data );
|
|
}
|
|
|
|
void on_player_aout_mute_changed( audio_output_t *aout, bool mute, void *data )
|
|
{
|
|
(void)aout;
|
|
vlc_value_t val = { .b_bool = mute};
|
|
VlcProc::onGenericCallback( "mute", val, data );
|
|
}
|
|
|
|
VlcProc *VlcProc::instance( intf_thread_t *pIntf )
|
|
{
|
|
if( pIntf->p_sys->p_vlcProc == NULL )
|
|
{
|
|
pIntf->p_sys->p_vlcProc = new VlcProc( pIntf );
|
|
}
|
|
|
|
return pIntf->p_sys->p_vlcProc;
|
|
}
|
|
|
|
|
|
void VlcProc::destroy( intf_thread_t *pIntf )
|
|
{
|
|
delete pIntf->p_sys->p_vlcProc;
|
|
pIntf->p_sys->p_vlcProc = NULL;
|
|
}
|
|
|
|
#define SET_BOOL(m,v) ((VarBoolImpl*)(m).get())->set(v)
|
|
#define SET_STREAMTIME(m,v,b) ((StreamTime*)(m).get())->set(v,b)
|
|
#define SET_TEXT(m,v) ((VarText*)(m).get())->set(v)
|
|
#define SET_STRING(m,v) ((VarString*)(m).get())->set(v)
|
|
#define SET_VOLUME(m,v,b) ((Volume*)(m).get())->setVolume(v,b)
|
|
|
|
VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ),
|
|
m_varEqBands( pIntf ), m_pVout( NULL ), m_pAout( NULL ),
|
|
mPlaylistListenerId( NULL ),
|
|
mPlayerListenerId( NULL ),
|
|
mPlayerAoutListenerId( NULL ),
|
|
mPlayerVoutListenerId( NULL )
|
|
{
|
|
// Create and register VLC variables
|
|
VarManager *pVarManager = VarManager::instance( getIntf() );
|
|
|
|
#define REGISTER_VAR( var, type, name ) \
|
|
var = VariablePtr( new type( getIntf() ) ); \
|
|
pVarManager->registerVar( var, name );
|
|
REGISTER_VAR( m_cVarRandom, VarBoolImpl, "playlist.isRandom" )
|
|
REGISTER_VAR( m_cVarLoop, VarBoolImpl, "playlist.isLoop" )
|
|
REGISTER_VAR( m_cVarRepeat, VarBoolImpl, "playlist.isRepeat" )
|
|
REGISTER_VAR( m_cPlaytree, Playtree, "playtree" )
|
|
pVarManager->registerVar( getPlaytreeVar().getPositionVarPtr(),
|
|
"playtree.slider" );
|
|
pVarManager->registerVar( m_cVarRandom, "playtree.isRandom" );
|
|
pVarManager->registerVar( m_cVarLoop, "playtree.isLoop" );
|
|
|
|
REGISTER_VAR( m_cVarPlaying, VarBoolImpl, "vlc.isPlaying" )
|
|
REGISTER_VAR( m_cVarStopped, VarBoolImpl, "vlc.isStopped" )
|
|
REGISTER_VAR( m_cVarPaused, VarBoolImpl, "vlc.isPaused" )
|
|
|
|
/* Input variables */
|
|
pVarManager->registerVar( m_cVarRepeat, "playtree.isRepeat" );
|
|
REGISTER_VAR( m_cVarTime, StreamTime, "time" )
|
|
REGISTER_VAR( m_cVarSeekable, VarBoolImpl, "vlc.isSeekable" )
|
|
REGISTER_VAR( m_cVarDvdActive, VarBoolImpl, "dvd.isActive" )
|
|
|
|
REGISTER_VAR( m_cVarRecordable, VarBoolImpl, "vlc.canRecord" )
|
|
REGISTER_VAR( m_cVarRecording, VarBoolImpl, "vlc.isRecording" )
|
|
|
|
/* Vout variables */
|
|
REGISTER_VAR( m_cVarFullscreen, VarBoolImpl, "vlc.isFullscreen" )
|
|
REGISTER_VAR( m_cVarHasVout, VarBoolImpl, "vlc.hasVout" )
|
|
|
|
/* Aout variables */
|
|
REGISTER_VAR( m_cVarHasAudio, VarBoolImpl, "vlc.hasAudio" )
|
|
REGISTER_VAR( m_cVarVolume, Volume, "volume" )
|
|
REGISTER_VAR( m_cVarMute, VarBoolImpl, "vlc.isMute" )
|
|
REGISTER_VAR( m_cVarEqualizer, VarBoolImpl, "equalizer.isEnabled" )
|
|
REGISTER_VAR( m_cVarEqPreamp, EqualizerPreamp, "equalizer.preamp" )
|
|
|
|
#undef REGISTER_VAR
|
|
m_cVarSpeed = VariablePtr( new VarText( getIntf(), false ) );
|
|
pVarManager->registerVar( m_cVarSpeed, "speed" );
|
|
SET_TEXT( m_cVarSpeed, UString( getIntf(), "1") );
|
|
m_cVarStreamName = VariablePtr( new VarText( getIntf(), false ) );
|
|
pVarManager->registerVar( m_cVarStreamName, "streamName" );
|
|
m_cVarStreamURI = VariablePtr( new VarText( getIntf(), false ) );
|
|
pVarManager->registerVar( m_cVarStreamURI, "streamURI" );
|
|
m_cVarStreamBitRate = VariablePtr( new VarText( getIntf(), false ) );
|
|
pVarManager->registerVar( m_cVarStreamBitRate, "bitrate" );
|
|
m_cVarStreamSampleRate = VariablePtr( new VarText( getIntf(), false ) );
|
|
pVarManager->registerVar( m_cVarStreamSampleRate, "samplerate" );
|
|
m_cVarStreamArt = VariablePtr( new VarString( getIntf() ) );
|
|
pVarManager->registerVar( m_cVarStreamArt, "streamArt" );
|
|
|
|
// Register the equalizer bands
|
|
for( int i = 0; i < EqualizerBands::kNbBands; i++)
|
|
{
|
|
std::stringstream ss;
|
|
ss << "equalizer.band(" << i << ")";
|
|
pVarManager->registerVar( m_varEqBands.getBand( i ), ss.str() );
|
|
}
|
|
|
|
static const struct vlc_playlist_callbacks playlist_cbs = []{
|
|
struct vlc_playlist_callbacks cbs {};
|
|
cbs.on_items_reset = on_playlist_items_reset;
|
|
cbs.on_items_added = on_playlist_items_added;
|
|
cbs.on_items_removed = on_playlist_items_removed;
|
|
cbs.on_items_updated = on_playlist_items_updated;
|
|
cbs.on_playback_repeat_changed = on_playlist_playback_repeat_changed;
|
|
cbs.on_playback_order_changed = on_playlist_playback_order_changed;
|
|
cbs.on_current_index_changed = on_playlist_current_index_changed;
|
|
return cbs;
|
|
}();
|
|
|
|
static const struct vlc_player_cbs player_cbs = []{
|
|
struct vlc_player_cbs cbs {};
|
|
cbs.on_current_media_changed = on_player_current_media_changed;
|
|
cbs.on_state_changed = on_player_state_changed;
|
|
cbs.on_rate_changed = on_player_rate_changed;
|
|
cbs.on_capabilities_changed = on_player_capabilities_changed;
|
|
cbs.on_position_changed = on_player_position_changed;
|
|
cbs.on_track_selection_changed = on_player_track_selection_changed;
|
|
cbs.on_titles_changed = on_player_titles_changed;
|
|
cbs.on_recording_changed = on_player_recording_changed;
|
|
cbs.on_vout_changed = on_player_vout_changed;
|
|
return cbs;
|
|
}();
|
|
|
|
static const struct vlc_player_vout_cbs player_vout_cbs {};
|
|
static const struct vlc_player_aout_cbs player_aout_cbs = []{
|
|
struct vlc_player_aout_cbs cbs {};
|
|
cbs.on_volume_changed = on_player_aout_volume_changed;
|
|
cbs.on_mute_changed = on_player_aout_mute_changed;
|
|
return cbs;
|
|
}();
|
|
|
|
// Add various listeners
|
|
vlc_playlist_Lock( getPL() );
|
|
|
|
mPlaylistListenerId =
|
|
vlc_playlist_AddListener( getPL(), &playlist_cbs, this, true);
|
|
|
|
vlc_player_t *player = vlc_playlist_GetPlayer( getPL() );
|
|
|
|
mPlayerListenerId =
|
|
vlc_player_AddListener( player, &player_cbs, this );
|
|
mPlayerAoutListenerId =
|
|
vlc_player_aout_AddListener( player, &player_aout_cbs, this );
|
|
mPlayerVoutListenerId =
|
|
vlc_player_vout_AddListener( player, &player_vout_cbs, this );
|
|
|
|
vlc_playlist_Unlock( getPL() );
|
|
|
|
// XXX WARNING XXX
|
|
// The object variable callbacks are called from other VLC threads,
|
|
// so they must put commands in the queue and NOT do anything else
|
|
// (X11 calls are not reentrant)
|
|
|
|
|
|
var_AddCallback( vlc_object_instance(getIntf()), "intf-toggle-fscontrol",
|
|
genericCallback, this );
|
|
|
|
// initialize variables referring to libvlc and playlist objects
|
|
init_variables();
|
|
}
|
|
|
|
|
|
VlcProc::~VlcProc()
|
|
{
|
|
if( m_pVout )
|
|
{
|
|
var_DelCallback( m_pVout, "mouse-moved",
|
|
genericCallback, this );
|
|
vout_Release( m_pVout );
|
|
m_pVout = NULL;
|
|
}
|
|
if( m_pAout )
|
|
{
|
|
var_DelCallback( m_pAout, "audio-filter", genericCallback, this );
|
|
var_DelCallback( m_pAout, "equalizer-bands",
|
|
EqBandsCallback, this );
|
|
var_DelCallback( m_pAout, "equalizer-preamp",
|
|
EqPreampCallback, this );
|
|
aout_Release( m_pAout );
|
|
m_pAout = NULL;
|
|
}
|
|
|
|
var_DelCallback( vlc_object_instance(getIntf()), "intf-toggle-fscontrol",
|
|
genericCallback, this );
|
|
|
|
// Remove various listeners
|
|
vlc_playlist_Lock( getPL() );
|
|
|
|
vlc_playlist_RemoveListener( getPL(), mPlaylistListenerId );
|
|
|
|
vlc_player_t *player = vlc_playlist_GetPlayer( getPL() );
|
|
vlc_player_RemoveListener( player, mPlayerListenerId );
|
|
vlc_player_aout_RemoveListener( player, mPlayerAoutListenerId );
|
|
vlc_player_vout_RemoveListener( player, mPlayerVoutListenerId );
|
|
|
|
vlc_playlist_Unlock( getPL() );
|
|
}
|
|
|
|
int VlcProc::genericCallback( vlc_object_t *pObj, const char *pVariable,
|
|
vlc_value_t oldVal, vlc_value_t newVal,
|
|
void *pParam )
|
|
{
|
|
(void)pObj; (void)oldVal;
|
|
onGenericCallback( pVariable, newVal, pParam );
|
|
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
int VlcProc::EqBandsCallback( vlc_object_t *pObj, const char *pVariable,
|
|
vlc_value_t oldVal, vlc_value_t newVal,
|
|
void *pParam )
|
|
{
|
|
(void)pObj; (void)pVariable; (void)oldVal;
|
|
VlcProc *pThis = (VlcProc*)pParam;
|
|
|
|
// Post a set equalizer bands command
|
|
CmdSetEqBands *pCmd = new CmdSetEqBands( pThis->getIntf(),
|
|
pThis->m_varEqBands,
|
|
newVal.psz_string );
|
|
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
|
|
pQueue->push( CmdGenericPtr( pCmd ) );
|
|
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
int VlcProc::EqPreampCallback( vlc_object_t *pObj, const char *pVariable,
|
|
vlc_value_t oldVal, vlc_value_t newVal,
|
|
void *pParam )
|
|
{
|
|
(void)pObj; (void)pVariable; (void)oldVal;
|
|
VlcProc *pThis = (VlcProc*)pParam;
|
|
EqualizerPreamp *pVarPreamp = (EqualizerPreamp*)(pThis->m_cVarEqPreamp.get());
|
|
|
|
// Post a set preamp command
|
|
CmdSetEqPreamp *pCmd = new CmdSetEqPreamp( pThis->getIntf(), *pVarPreamp,
|
|
(newVal.f_float + 20.0) / 40.0 );
|
|
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
|
|
pQueue->push( CmdGenericPtr( pCmd ) );
|
|
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
#define ADD_CALLBACK_ENTRY( var, func, remove ) \
|
|
if( strcmp( pVariable, var ) == 0 ){\
|
|
cb = &VlcProc::func; \
|
|
bRemove = remove; \
|
|
}\
|
|
else
|
|
|
|
void VlcProc::onGenericCallback( const char *pVariable,
|
|
vlc_value_t newVal, void *data )
|
|
{
|
|
VlcProc *pThis = (VlcProc*)data;
|
|
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
|
|
std::string label = pVariable;
|
|
void (VlcProc::*cb)(vlc_value_t);
|
|
bool bRemove;
|
|
|
|
ADD_CALLBACK_ENTRY( "current_media", on_current_media_changed, false )
|
|
ADD_CALLBACK_ENTRY( "repeat", on_repeat_changed, false )
|
|
ADD_CALLBACK_ENTRY( "order", on_order_changed, false )
|
|
ADD_CALLBACK_ENTRY( "volume", on_volume_changed, true )
|
|
ADD_CALLBACK_ENTRY( "mute", on_mute_changed, false )
|
|
ADD_CALLBACK_ENTRY( "random", on_random_changed, false )
|
|
|
|
ADD_CALLBACK_ENTRY( "state", on_state_changed, false )
|
|
ADD_CALLBACK_ENTRY( "rate", on_rate_changed, true )
|
|
ADD_CALLBACK_ENTRY( "capabilities", on_capabilities_changed, true )
|
|
ADD_CALLBACK_ENTRY( "position", on_position_changed, true )
|
|
ADD_CALLBACK_ENTRY( "audio_es", on_audio_es_changed, false )
|
|
ADD_CALLBACK_ENTRY( "bit_rate", on_bit_rate_changed, false )
|
|
ADD_CALLBACK_ENTRY( "sample_rate", on_sample_rate_changed, false )
|
|
ADD_CALLBACK_ENTRY( "isDvd", on_isDvd_changed, false )
|
|
ADD_CALLBACK_ENTRY( "recording", on_recording_changed, true )
|
|
ADD_CALLBACK_ENTRY( "vout", on_vout_changed, false )
|
|
|
|
ADD_CALLBACK_ENTRY( "intf-toggle-fscontrol", on_intf_show_changed, false )
|
|
|
|
ADD_CALLBACK_ENTRY( "mouse-moved", on_mouse_moved_changed,false )
|
|
ADD_CALLBACK_ENTRY( "audio-filter", on_audio_filter_changed, false )
|
|
vlc_assert_unreachable();
|
|
|
|
CmdGeneric *pCmd = new CmdCallback( pThis->getIntf(), newVal, cb, label );
|
|
if( pCmd )
|
|
pQueue->push( CmdGenericPtr( pCmd ), bRemove );
|
|
}
|
|
|
|
#undef ADD_CALLBACK_ENTRY
|
|
|
|
void VlcProc::on_bit_rate_changed( vlc_value_t newVal )
|
|
{
|
|
int bitrate = newVal.i_int / 1000;
|
|
if( bitrate != 0 )
|
|
SET_TEXT( m_cVarStreamBitRate, UString::fromInt( getIntf(), bitrate ) );
|
|
else
|
|
SET_TEXT( m_cVarStreamBitRate, UString( getIntf(), "") );
|
|
}
|
|
|
|
void VlcProc::on_sample_rate_changed( vlc_value_t newVal )
|
|
{
|
|
int sampleRate = newVal.i_int / 1000;
|
|
if( sampleRate != 0 )
|
|
SET_TEXT( m_cVarStreamSampleRate, UString::fromInt(getIntf(),sampleRate) );
|
|
else
|
|
SET_TEXT( m_cVarStreamSampleRate, UString( getIntf(), "") );
|
|
}
|
|
|
|
void VlcProc::on_random_changed( vlc_value_t newVal )
|
|
{
|
|
SET_BOOL( m_cVarRandom, newVal.b_bool );
|
|
}
|
|
|
|
void VlcProc::on_loop_changed( vlc_value_t newVal )
|
|
{
|
|
SET_BOOL( m_cVarLoop, newVal.b_bool );
|
|
}
|
|
|
|
void VlcProc::on_current_media_changed( vlc_value_t newVal )
|
|
{
|
|
input_item_t* pItem = static_cast<input_item_t*>(newVal.p_address);
|
|
msg_Dbg(getIntf(),"current media changed %p", static_cast<void*>(pItem) );
|
|
if( pItem )
|
|
{
|
|
// Update short name (as defined by --input-title-format)
|
|
char *psz_name = NULL;
|
|
char *psz_fmt = var_InheritString( getIntf(), "input-title-format" );
|
|
if( psz_fmt != NULL )
|
|
{
|
|
vlc_playlist_Lock( getPL() );
|
|
vlc_player_t* player = vlc_playlist_GetPlayer( getPL() );
|
|
psz_name = vlc_strfplayer( player, NULL, psz_fmt );
|
|
vlc_playlist_Unlock( getPL() );
|
|
free( psz_fmt );
|
|
}
|
|
|
|
SET_TEXT( m_cVarStreamName, UString( getIntf(),
|
|
psz_name ? psz_name : "" ) );
|
|
free( psz_name );
|
|
|
|
// Update local path (if possible) or full uri
|
|
char *psz_uri = input_item_GetURI( pItem );
|
|
char *psz_path = vlc_uri2path( psz_uri );
|
|
char *psz_save = psz_path ? psz_path : psz_uri;
|
|
SET_TEXT( m_cVarStreamURI, UString( getIntf(), psz_save ) );
|
|
free( psz_path );
|
|
free( psz_uri );
|
|
|
|
// Update art uri
|
|
char *psz_art = input_item_GetArtURL( pItem );
|
|
SET_STRING( m_cVarStreamArt, std::string( psz_art ? psz_art : "" ) );
|
|
free( psz_art );
|
|
|
|
input_item_Release( pItem );
|
|
}
|
|
}
|
|
|
|
void VlcProc::on_repeat_changed( vlc_value_t newVal )
|
|
{
|
|
enum vlc_playlist_playback_repeat repeat =
|
|
(enum vlc_playlist_playback_repeat)newVal.i_int;
|
|
|
|
if( repeat == VLC_PLAYLIST_PLAYBACK_REPEAT_ALL )
|
|
{
|
|
SET_BOOL( m_cVarRepeat, false );
|
|
SET_BOOL( m_cVarLoop, true );
|
|
}
|
|
else if( repeat == VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT )
|
|
{
|
|
SET_BOOL( m_cVarLoop, false );
|
|
SET_BOOL( m_cVarRepeat, true );
|
|
}
|
|
else
|
|
{
|
|
SET_BOOL( m_cVarRepeat, false );
|
|
SET_BOOL( m_cVarLoop, false );
|
|
}
|
|
}
|
|
|
|
void VlcProc::on_order_changed( vlc_value_t newVal )
|
|
{
|
|
enum vlc_playlist_playback_order order =
|
|
(enum vlc_playlist_playback_order)newVal.i_int;
|
|
|
|
SET_BOOL( m_cVarRandom, (order == VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM) );
|
|
}
|
|
|
|
void VlcProc::on_volume_changed( vlc_value_t newVal )
|
|
{
|
|
SET_VOLUME( m_cVarVolume, newVal.f_float, false );
|
|
}
|
|
|
|
void VlcProc::on_mute_changed( vlc_value_t newVal )
|
|
{
|
|
SET_BOOL( m_cVarMute, newVal.b_bool );
|
|
}
|
|
|
|
void VlcProc::on_recording_changed( vlc_value_t newVal )
|
|
{
|
|
SET_BOOL( m_cVarRecording, newVal.b_bool );
|
|
}
|
|
|
|
void VlcProc::on_state_changed( vlc_value_t newVal )
|
|
{
|
|
enum vlc_player_state state = (enum vlc_player_state)newVal.i_int;
|
|
msg_Dbg( getIntf(),"playlist state changed : %i", state );
|
|
|
|
bool stopped = ( state == VLC_PLAYER_STATE_STOPPED );
|
|
bool playing = ( state == VLC_PLAYER_STATE_STARTED ||
|
|
state == VLC_PLAYER_STATE_PLAYING ||
|
|
state == VLC_PLAYER_STATE_STOPPING );
|
|
bool paused = ( state == VLC_PLAYER_STATE_PAUSED );
|
|
|
|
SET_BOOL( m_cVarStopped, stopped );
|
|
SET_BOOL( m_cVarPlaying, playing );
|
|
SET_BOOL( m_cVarPaused, paused );
|
|
|
|
// extra cleaning done
|
|
if( state == VLC_PLAYER_STATE_STOPPED )
|
|
reset_input();
|
|
}
|
|
|
|
void VlcProc::on_rate_changed( vlc_value_t newVal )
|
|
{
|
|
float rate = newVal.f_float;
|
|
char* buffer;
|
|
if( asprintf( &buffer, "%.3g", rate ) != -1 )
|
|
{
|
|
SET_TEXT( m_cVarSpeed, UString( getIntf(), buffer ) );
|
|
free( buffer );
|
|
}
|
|
}
|
|
|
|
void VlcProc::on_capabilities_changed( vlc_value_t newVal )
|
|
{
|
|
int capabilities = newVal.i_int;
|
|
SET_BOOL( m_cVarSeekable, capabilities & VLC_PLAYER_CAP_SEEK );
|
|
}
|
|
|
|
void VlcProc::on_position_changed( vlc_value_t newVal )
|
|
{
|
|
float pos = newVal.f_float;
|
|
SET_STREAMTIME( m_cVarTime, pos, false );
|
|
}
|
|
|
|
void VlcProc::on_audio_es_changed( vlc_value_t newVal )
|
|
{
|
|
SET_BOOL( m_cVarHasAudio, newVal.b_bool );
|
|
}
|
|
|
|
void VlcProc::on_isDvd_changed( vlc_value_t newVal )
|
|
{
|
|
SET_BOOL( m_cVarDvdActive, newVal.b_bool );
|
|
}
|
|
|
|
void VlcProc::on_vout_changed( vlc_value_t newVal )
|
|
{
|
|
vout_thread_t* pVout = (vout_thread_t*)newVal.p_address;
|
|
SET_BOOL( m_cVarHasVout, pVout != NULL );
|
|
if( !pVout || pVout == m_pVout )
|
|
{
|
|
if( pVout )
|
|
vout_Release( pVout );
|
|
return;
|
|
}
|
|
|
|
// release previous Vout
|
|
if( m_pVout )
|
|
{
|
|
var_DelCallback( m_pVout, "mouse-moved",
|
|
genericCallback, this );
|
|
vout_Release( m_pVout );
|
|
m_pVout = NULL;
|
|
}
|
|
|
|
// keep new vout held and install callback
|
|
m_pVout = pVout;
|
|
var_AddCallback( m_pVout, "mouse-moved", genericCallback, this );
|
|
}
|
|
|
|
void VlcProc::on_audio_filter_changed( vlc_value_t newVal )
|
|
{
|
|
char *pFilters = newVal.psz_string;
|
|
bool b_equalizer = pFilters && strstr( pFilters, "equalizer" );
|
|
SET_BOOL( m_cVarEqualizer, b_equalizer );
|
|
}
|
|
|
|
void VlcProc::on_intf_show_changed( vlc_value_t newVal )
|
|
{
|
|
bool b_fullscreen = getFullscreenVar().get();
|
|
|
|
if( !b_fullscreen )
|
|
{
|
|
if( newVal.b_bool )
|
|
{
|
|
// Create a raise all command
|
|
CmdRaiseAll *pCmd = new CmdRaiseAll( getIntf(),
|
|
getIntf()->p_sys->p_theme->getWindowManager() );
|
|
|
|
// Push the command in the asynchronous command queue
|
|
AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
|
|
pQueue->push( CmdGenericPtr( pCmd ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VoutManager* pVoutManager = VoutManager::instance( getIntf() );
|
|
FscWindow *pWin = pVoutManager->getFscWindow();
|
|
if( pWin )
|
|
{
|
|
bool b_visible = pWin->getVisibleVar().get();
|
|
AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
|
|
|
|
if( !b_visible )
|
|
{
|
|
CmdShowWindow* pCmd = new CmdShowWindow( getIntf(),
|
|
getIntf()->p_sys->p_theme->getWindowManager(),
|
|
*pWin );
|
|
pQueue->push( CmdGenericPtr( pCmd ) );
|
|
}
|
|
else
|
|
{
|
|
CmdHideWindow* pCmd = new CmdHideWindow( getIntf(),
|
|
getIntf()->p_sys->p_theme->getWindowManager(),
|
|
*pWin );
|
|
pQueue->push( CmdGenericPtr( pCmd ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void VlcProc::on_mouse_moved_changed( vlc_value_t newVal )
|
|
{
|
|
(void)newVal;
|
|
FscWindow* pFscWindow = VoutManager::instance( getIntf() )->getFscWindow();
|
|
if( pFscWindow )
|
|
pFscWindow->onMouseMoved();
|
|
}
|
|
|
|
void VlcProc::reset_input()
|
|
{
|
|
SET_BOOL( m_cVarSeekable, false );
|
|
SET_BOOL( m_cVarRecordable, true );
|
|
SET_BOOL( m_cVarRecording, false );
|
|
SET_BOOL( m_cVarDvdActive, false );
|
|
SET_BOOL( m_cVarHasAudio, false );
|
|
SET_BOOL( m_cVarHasVout, false );
|
|
|
|
SET_STREAMTIME( m_cVarTime, 0, false );
|
|
SET_TEXT( m_cVarStreamName, UString( getIntf(), "") );
|
|
SET_TEXT( m_cVarStreamURI, UString( getIntf(), "") );
|
|
SET_STRING( m_cVarStreamArt, std::string( "" ) );
|
|
SET_TEXT( m_cVarStreamBitRate, UString( getIntf(), "") );
|
|
SET_TEXT( m_cVarStreamSampleRate, UString( getIntf(), "") );
|
|
}
|
|
|
|
void VlcProc::init_variables()
|
|
{
|
|
vlc_player_t *player = vlc_playlist_GetPlayer( getPL() );
|
|
|
|
float volume = vlc_player_aout_GetVolume( player );
|
|
SET_VOLUME( m_cVarVolume, volume, false );
|
|
|
|
bool mute = vlc_player_aout_IsMuted( player ) == 1;
|
|
SET_BOOL( m_cVarMute, mute );
|
|
|
|
SET_BOOL( m_cVarStopped, true );
|
|
init_equalizer();
|
|
}
|
|
|
|
void VlcProc::init_equalizer()
|
|
{
|
|
//audio_output_t* pAout = playlist_GetAout( getPL() );
|
|
vlc_player_t* player = vlc_playlist_GetPlayer( getPL() );
|
|
audio_output_t* pAout = vlc_player_aout_Hold( player );
|
|
if( pAout )
|
|
{
|
|
if( !var_Type( pAout, "equalizer-bands" ) )
|
|
var_Create( pAout, "equalizer-bands",
|
|
VLC_VAR_STRING | VLC_VAR_DOINHERIT);
|
|
if( !var_Type( pAout, "equalizer-preamp" ) )
|
|
var_Create( pAout, "equalizer-preamp",
|
|
VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
|
|
|
|
// New Aout (addCallbacks)
|
|
var_AddCallback( pAout, "audio-filter", genericCallback, this );
|
|
var_AddCallback( pAout, "equalizer-bands",
|
|
EqBandsCallback, this );
|
|
var_AddCallback( pAout, "equalizer-preamp",
|
|
EqPreampCallback, this );
|
|
|
|
assert( !m_pAout );
|
|
m_pAout = pAout;
|
|
}
|
|
|
|
// is equalizer enabled ?
|
|
char *pFilters = pAout ?
|
|
var_GetNonEmptyString( pAout, "audio-filter" ) :
|
|
var_InheritString( getIntf(), "audio-filter" );
|
|
bool b_equalizer = pFilters && strstr( pFilters, "equalizer" );
|
|
free( pFilters );
|
|
SET_BOOL( m_cVarEqualizer, b_equalizer );
|
|
|
|
// retrieve initial bands
|
|
char* bands = pAout ?
|
|
var_GetString( pAout, "equalizer-bands" ) :
|
|
var_InheritString( getIntf(), "equalizer-bands" );
|
|
if( bands )
|
|
{
|
|
m_varEqBands.set( bands );
|
|
free( bands );
|
|
}
|
|
|
|
// retrieve initial preamp
|
|
float preamp = pAout ?
|
|
var_GetFloat( pAout, "equalizer-preamp" ) :
|
|
var_InheritFloat( getIntf(), "equalizer-preamp" );
|
|
EqualizerPreamp *pVarPreamp = (EqualizerPreamp*)m_cVarEqPreamp.get();
|
|
pVarPreamp->set( (preamp + 20.0) / 40.0 );
|
|
}
|
|
|
|
void VlcProc::setFullscreenVar( bool b_fullscreen )
|
|
{
|
|
SET_BOOL( m_cVarFullscreen, b_fullscreen );
|
|
}
|
|
|
|
#undef SET_BOOL
|
|
#undef SET_STREAMTIME
|
|
#undef SET_TEXT
|
|
#undef SET_STRING
|
|
#undef SET_VOLUME
|