vlcproc.cpp 27.6 KB
Newer Older
1 2 3
/*****************************************************************************
 * vlcproc.cpp
 *****************************************************************************
4
 * Copyright (C) 2003-2009 the VideoLAN team
5
 * $Id$
6 7
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
8
 *          Olivier Teulière <ipkiss@via.ecp.fr>
9
 *          Erwan Tulou      <erwan10@videolan.org>
10 11 12 13 14 15 16 17 18 19 20
 *
 * 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.
 *
21 22 23
 * 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.
24 25
 *****************************************************************************/

26 27 28 29
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

30
#include <vlc_common.h>
Clément Stenac's avatar
Clément Stenac committed
31 32 33
#include <vlc_aout.h>
#include <vlc_vout.h>
#include <vlc_playlist.h>
34
#include <vlc_url.h>
Erwan Tulou's avatar
Erwan Tulou committed
35
#include <vlc_strings.h>
36 37 38

#include "vlcproc.hpp"
#include "os_factory.hpp"
39
#include "os_loop.hpp"
40
#include "os_timer.hpp"
Cyril Deguet's avatar
Cyril Deguet committed
41
#include "var_manager.hpp"
42
#include "vout_manager.hpp"
43
#include "fsc_window.hpp"
44 45
#include "theme.hpp"
#include "window_manager.hpp"
46
#include "../commands/async_queue.hpp"
47
#include "../commands/cmd_change_skin.hpp"
48
#include "../commands/cmd_show_window.hpp"
49
#include "../commands/cmd_quit.hpp"
50
#include "../commands/cmd_resize.hpp"
51
#include "../commands/cmd_vars.hpp"
52
#include "../commands/cmd_dialogs.hpp"
53
#include "../commands/cmd_audio.hpp"
54
#include "../commands/cmd_callbacks.hpp"
55
#include "../utils/var_bool.hpp"
56
#include "../utils/var_string.hpp"
57
#include <sstream>
58

Erwan Tulou's avatar
Erwan Tulou committed
59
#include <assert.h>
60 61 62 63 64 65 66 67 68 69 70 71 72 73

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 )
{
74 75
    delete pIntf->p_sys->p_vlcProc;
    pIntf->p_sys->p_vlcProc = NULL;
76 77
}

78 79 80 81
#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)
82
#define SET_VOLUME(m,v,b)     ((Volume*)(m).get())->setVolume(v,b)
83

84
VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ),
85
    m_varEqBands( pIntf ), m_pVout( NULL )
86
{
Cyril Deguet's avatar
Cyril Deguet committed
87 88
    // Create and register VLC variables
    VarManager *pVarManager = VarManager::instance( getIntf() );
89

90 91 92
#define REGISTER_VAR( var, type, name ) \
    var = VariablePtr( new type( getIntf() ) ); \
    pVarManager->registerVar( var, name );
93
    REGISTER_VAR( m_cVarRandom, VarBoolImpl, "playlist.isRandom" )
94
    REGISTER_VAR( m_cVarLoop, VarBoolImpl, "playlist.isLoop" )
95
    REGISTER_VAR( m_cVarRepeat, VarBoolImpl, "playlist.isRepeat" )
96 97 98
    REGISTER_VAR( m_cPlaytree, Playtree, "playtree" )
    pVarManager->registerVar( getPlaytreeVar().getPositionVarPtr(),
                              "playtree.slider" );
99 100
    pVarManager->registerVar( m_cVarRandom, "playtree.isRandom" );
    pVarManager->registerVar( m_cVarLoop, "playtree.isLoop" );
Clément Stenac's avatar
Clément Stenac committed
101

102 103 104
    REGISTER_VAR( m_cVarPlaying, VarBoolImpl, "vlc.isPlaying" )
    REGISTER_VAR( m_cVarStopped, VarBoolImpl, "vlc.isStopped" )
    REGISTER_VAR( m_cVarPaused, VarBoolImpl, "vlc.isPaused" )
Clément Stenac's avatar
Clément Stenac committed
105 106 107 108

    /* Input variables */
    pVarManager->registerVar( m_cVarRepeat, "playtree.isRepeat" );
    REGISTER_VAR( m_cVarTime, StreamTime, "time" )
109
    REGISTER_VAR( m_cVarSeekable, VarBoolImpl, "vlc.isSeekable" )
110
    REGISTER_VAR( m_cVarDvdActive, VarBoolImpl, "dvd.isActive" )
Clément Stenac's avatar
Clément Stenac committed
111

112 113 114
    REGISTER_VAR( m_cVarRecordable, VarBoolImpl, "vlc.canRecord" )
    REGISTER_VAR( m_cVarRecording, VarBoolImpl, "vlc.isRecording" )

Clément Stenac's avatar
Clément Stenac committed
115
    /* Vout variables */
116
    REGISTER_VAR( m_cVarFullscreen, VarBoolImpl, "vlc.isFullscreen" )
117
    REGISTER_VAR( m_cVarHasVout, VarBoolImpl, "vlc.hasVout" )
Clément Stenac's avatar
Clément Stenac committed
118 119

    /* Aout variables */
Clément Stenac's avatar
Clément Stenac committed
120
    REGISTER_VAR( m_cVarHasAudio, VarBoolImpl, "vlc.hasAudio" )
Clément Stenac's avatar
Clément Stenac committed
121 122 123 124 125
    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" )

126
#undef REGISTER_VAR
127 128 129
    m_cVarSpeed = VariablePtr( new VarText( getIntf(), false ) );
    pVarManager->registerVar( m_cVarSpeed, "speed" );
    SET_TEXT( m_cVarSpeed, UString( getIntf(), "1") );
130 131 132 133
    m_cVarStreamName = VariablePtr( new VarText( getIntf(), false ) );
    pVarManager->registerVar( m_cVarStreamName, "streamName" );
    m_cVarStreamURI = VariablePtr( new VarText( getIntf(), false ) );
    pVarManager->registerVar( m_cVarStreamURI, "streamURI" );
134 135
    m_cVarStreamBitRate = VariablePtr( new VarText( getIntf(), false ) );
    pVarManager->registerVar( m_cVarStreamBitRate, "bitrate" );
136 137
    m_cVarStreamSampleRate = VariablePtr( new VarText( getIntf(), false ) );
    pVarManager->registerVar( m_cVarStreamSampleRate, "samplerate" );
138 139
    m_cVarStreamArt = VariablePtr( new VarString( getIntf() ) );
    pVarManager->registerVar( m_cVarStreamArt, "streamArt" );
Cyril Deguet's avatar
Cyril Deguet committed
140

141 142 143
    // Register the equalizer bands
    for( int i = 0; i < EqualizerBands::kNbBands; i++)
    {
144
        std::stringstream ss;
145 146 147 148
        ss << "equalizer.band(" << i << ")";
        pVarManager->registerVar( m_varEqBands.getBand( i ), ss.str() );
    }

149 150 151 152 153
    // 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)

154 155 156
#define ADD_CALLBACK( p_object, var ) \
    var_AddCallback( p_object, var, onGenericCallback, this );

157 158
    ADD_CALLBACK( getPL(), "volume" )
    ADD_CALLBACK( getPL(), "mute" )
159
    ADD_CALLBACK( pIntf->obj.libvlc, "intf-toggle-fscontrol" )
160

161 162 163
    ADD_CALLBACK( getPL(), "random" )
    ADD_CALLBACK( getPL(), "loop" )
    ADD_CALLBACK( getPL(), "repeat" )
164 165 166

#undef ADD_CALLBACK

167
    // Called when a playlist item is added
168
    var_AddCallback( getPL(), "playlist-item-append", onItemAppend, this );
169 170
    // Called when a playlist item is deleted
    // TODO: properly handle item-deleted
171
    var_AddCallback( getPL(), "playlist-item-deleted", onItemDelete, this );
172
    // Called when the current input changes
173
    var_AddCallback( getPL(), "input-current", onInputNew, this );
174
    // Called when a playlist item changed
175
    var_AddCallback( getPL(), "item-change", onItemChange, this );
176

177 178 179 180
    // Called when we have an interaction dialog to display
    var_Create( pIntf, "interaction", VLC_VAR_ADDRESS );
    var_AddCallback( pIntf, "interaction", onInteraction, this );

181 182
    // initialize variables refering to liblvc and playlist objects
    init_variables();
183 184 185 186 187
}


VlcProc::~VlcProc()
{
188
    if( m_pVout )
189
    {
190 191 192 193
        vlc_object_release( m_pVout );
        m_pVout = NULL;
    }

194 195
    var_DelCallback( getPL(), "volume", onGenericCallback, this );
    var_DelCallback( getPL(), "mute",onGenericCallback, this );
196
    var_DelCallback( getIntf()->obj.libvlc, "intf-toggle-fscontrol",
197
                     onGenericCallback, this );
198

199 200 201
    var_DelCallback( getPL(), "random", onGenericCallback, this );
    var_DelCallback( getPL(), "loop", onGenericCallback, this );
    var_DelCallback( getPL(), "repeat", onGenericCallback, this );
202

203 204 205 206
    var_DelCallback( getPL(), "playlist-item-append", onItemAppend, this );
    var_DelCallback( getPL(), "playlist-item-deleted", onItemDelete, this );
    var_DelCallback( getPL(), "input-current", onInputNew, this );
    var_DelCallback( getPL(), "item-change", onItemChange, this );
207
    var_DelCallback( getIntf(), "interaction", onInteraction, this );
208 209
}

210 211 212
int VlcProc::onInputNew( vlc_object_t *pObj, const char *pVariable,
                         vlc_value_t oldval, vlc_value_t newval, void *pParam )
{
213
    (void)pObj; (void)pVariable; (void)oldval;
214 215 216
    VlcProc *pThis = (VlcProc*)pParam;
    input_thread_t *pInput = static_cast<input_thread_t*>(newval.p_address);

217 218 219 220 221 222 223
    if( pInput != NULL )
    {
        var_AddCallback( pInput, "intf-event", onGenericCallback2, pThis );
        var_AddCallback( pInput, "bit-rate", onGenericCallback, pThis );
        var_AddCallback( pInput, "sample-rate", onGenericCallback, pThis );
        var_AddCallback( pInput, "can-record", onGenericCallback, pThis );
    }
224 225 226
    return VLC_SUCCESS;
}

227

228
int VlcProc::onItemChange( vlc_object_t *pObj, const char *pVariable,
Laurent Aimar's avatar
Laurent Aimar committed
229
                           vlc_value_t oldval, vlc_value_t newval,
230 231
                           void *pParam )
{
232
    (void)pObj; (void)pVariable; (void)oldval;
233
    VlcProc *pThis = (VlcProc*)pParam;
Laurent Aimar's avatar
Laurent Aimar committed
234
    input_item_t *p_item = static_cast<input_item_t*>(newval.p_address);
235

236
    // Create a playtree notify command
237
    CmdItemUpdate *pCmdTree = new CmdItemUpdate( pThis->getIntf(),
238
                                                         p_item );
239 240 241

    // Push the command in the asynchronous command queue
    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
242
    pQueue->push( CmdGenericPtr( pCmdTree ), true );
243

244 245 246
    return VLC_SUCCESS;
}

Clément Stenac's avatar
Clément Stenac committed
247 248 249 250
int VlcProc::onItemAppend( vlc_object_t *pObj, const char *pVariable,
                           vlc_value_t oldVal, vlc_value_t newVal,
                           void *pParam )
{
251
    (void)pObj; (void)pVariable; (void)oldVal;
Clément Stenac's avatar
Clément Stenac committed
252 253
    VlcProc *pThis = (VlcProc*)pParam;

254
    playlist_item_t *item = static_cast<playlist_item_t *>(newVal.p_address);
Erwan Tulou's avatar
Erwan Tulou committed
255
    CmdPlaytreeAppend *pCmdTree =
256
        new CmdPlaytreeAppend( pThis->getIntf(), item->i_id );
Clément Stenac's avatar
Clément Stenac committed
257

Clément Stenac's avatar
Clément Stenac committed
258 259
    // Push the command in the asynchronous command queue
    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
Erwan Tulou's avatar
Erwan Tulou committed
260
    pQueue->push( CmdGenericPtr( pCmdTree ), false );
Clément Stenac's avatar
Clément Stenac committed
261 262 263 264

    return VLC_SUCCESS;
}

265 266 267 268
int VlcProc::onItemDelete( vlc_object_t *pObj, const char *pVariable,
                           vlc_value_t oldVal, vlc_value_t newVal,
                           void *pParam )
{
269
    (void)pObj; (void)pVariable; (void)oldVal;
270 271
    VlcProc *pThis = (VlcProc*)pParam;

272
    playlist_item_t *item = static_cast<playlist_item_t *>(newVal.p_address);
Erwan Tulou's avatar
Erwan Tulou committed
273
    CmdPlaytreeDelete *pCmdTree =
274
        new CmdPlaytreeDelete( pThis->getIntf(), item->i_id);
275 276 277

    // Push the command in the asynchronous command queue
    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
Erwan Tulou's avatar
Erwan Tulou committed
278
    pQueue->push( CmdGenericPtr( pCmdTree ), false );
279 280 281 282

    return VLC_SUCCESS;
}

283 284 285 286
int VlcProc::onInteraction( vlc_object_t *pObj, const char *pVariable,
                            vlc_value_t oldVal, vlc_value_t newVal,
                            void *pParam )
{
287
    (void)pObj; (void)pVariable; (void)oldVal;
288 289 290 291 292 293 294 295 296
    VlcProc *pThis = (VlcProc*)pParam;
    interaction_dialog_t *p_dialog = (interaction_dialog_t *)(newVal.p_address);

    CmdInteraction *pCmd = new CmdInteraction( pThis->getIntf(), p_dialog );
    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
    pQueue->push( CmdGenericPtr( pCmd ) );
    return VLC_SUCCESS;
}

297 298 299 300
int VlcProc::onEqBandsChange( vlc_object_t *pObj, const char *pVariable,
                              vlc_value_t oldVal, vlc_value_t newVal,
                              void *pParam )
{
301
    (void)pObj; (void)pVariable; (void)oldVal;
302 303 304 305 306 307 308 309 310 311 312 313
    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;
}

314 315 316 317 318

int VlcProc::onEqPreampChange( vlc_object_t *pObj, const char *pVariable,
                               vlc_value_t oldVal, vlc_value_t newVal,
                               void *pParam )
{
319
    (void)pObj; (void)pVariable; (void)oldVal;
320 321 322 323 324 325 326 327 328 329 330 331
    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;
}

332 333 334 335 336

int VlcProc::onGenericCallback( vlc_object_t *pObj, const char *pVariable,
                                vlc_value_t oldVal, vlc_value_t newVal,
                                void *pParam )
{
337
    (void)oldVal;
338 339 340
    VlcProc *pThis = (VlcProc*)pParam;
    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );

Erwan Tulou's avatar
Erwan Tulou committed
341
#define ADD_CALLBACK_ENTRY( var, func, remove ) \
342 343
    { \
    if( strcmp( pVariable, var ) == 0 ) \
Erwan Tulou's avatar
Erwan Tulou committed
344
    { \
345
        std::string label = var; \
Erwan Tulou's avatar
Erwan Tulou committed
346 347 348 349 350 351
        CmdGeneric *pCmd = new CmdCallback( pThis->getIntf(), pObj, newVal, \
                                            &VlcProc::func, label ); \
        if( pCmd ) \
            pQueue->push( CmdGenericPtr( pCmd ), remove ); \
        return VLC_SUCCESS; \
    } \
352 353
    }

354
    ADD_CALLBACK_ENTRY( "volume", on_volume_changed, true )
Erwan Tulou's avatar
Erwan Tulou committed
355
    ADD_CALLBACK_ENTRY( "mute", on_mute_changed, true )
356

Erwan Tulou's avatar
Erwan Tulou committed
357 358 359
    ADD_CALLBACK_ENTRY( "bit-rate", on_bit_rate_changed, false )
    ADD_CALLBACK_ENTRY( "sample-rate", on_sample_rate_changed, false )
    ADD_CALLBACK_ENTRY( "can-record", on_can_record_changed, false )
360

Erwan Tulou's avatar
Erwan Tulou committed
361 362 363
    ADD_CALLBACK_ENTRY( "random", on_random_changed, false )
    ADD_CALLBACK_ENTRY( "loop", on_loop_changed, false )
    ADD_CALLBACK_ENTRY( "repeat", on_repeat_changed, false )
364

Erwan Tulou's avatar
Erwan Tulou committed
365
    ADD_CALLBACK_ENTRY( "audio-filter", on_audio_filter_changed, false )
366

367
    ADD_CALLBACK_ENTRY( "intf-toggle-fscontrol", on_intf_show_changed, false )
368

369 370
    ADD_CALLBACK_ENTRY( "mouse-moved", on_mouse_moved_changed, false )

371 372
#undef ADD_CALLBACK_ENTRY

Erwan Tulou's avatar
Erwan Tulou committed
373 374 375
    msg_Err( pThis->getIntf(), "no callback entry for %s", pVariable );
    return VLC_EGENERIC;
}
376

Erwan Tulou's avatar
Erwan Tulou committed
377 378 379 380 381

int VlcProc::onGenericCallback2( vlc_object_t *pObj, const char *pVariable,
                                 vlc_value_t oldVal, vlc_value_t newVal,
                                 void *pParam )
{
382
    (void)oldVal;
Erwan Tulou's avatar
Erwan Tulou committed
383 384 385 386 387 388 389 390 391 392 393 394 395
    VlcProc *pThis = (VlcProc*)pParam;
    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );

    /**
     * For intf-event, commands are labeled based on the value of newVal.
     *
     * For some values (e.g position), only keep the latest command
     * when there are multiple pending commands (remove=true).
     *
     * for others, don't discard commands (remove=false)
     **/
    if( strcmp( pVariable, "intf-event" ) == 0 )
    {
396
        std::stringstream label;
Erwan Tulou's avatar
Erwan Tulou committed
397 398 399 400 401
        bool b_remove;
        switch( newVal.i_int )
        {
            case INPUT_EVENT_STATE:
            case INPUT_EVENT_POSITION:
402
            case INPUT_EVENT_RATE:
Erwan Tulou's avatar
Erwan Tulou committed
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
            case INPUT_EVENT_ES:
            case INPUT_EVENT_CHAPTER:
            case INPUT_EVENT_RECORD:
                b_remove = true;
                break;
            case INPUT_EVENT_VOUT:
            case INPUT_EVENT_AOUT:
            case INPUT_EVENT_DEAD:
                b_remove = false;
                break;
            default:
                return VLC_SUCCESS;
        }
        label <<  pVariable << "_" << newVal.i_int;
        CmdGeneric *pCmd = new CmdCallback( pThis->getIntf(), pObj, newVal,
                                            &VlcProc::on_intf_event_changed,
                                            label.str() );
        if( pCmd )
            pQueue->push( CmdGenericPtr( pCmd ), b_remove );

        return VLC_SUCCESS;
    }

    msg_Err( pThis->getIntf(), "no callback entry for %s", pVariable );
    return VLC_EGENERIC;
428 429
}

Erwan Tulou's avatar
Erwan Tulou committed
430

431 432 433 434
void VlcProc::on_intf_event_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
    input_thread_t* pInput = (input_thread_t*) p_obj;

Erwan Tulou's avatar
Erwan Tulou committed
435 436 437 438
    assert( getIntf()->p_sys->p_input == NULL || getIntf()->p_sys->p_input == pInput );

    if( !getIntf()->p_sys->p_input )
    {
439
        msg_Dbg( getIntf(), "new input %p detected", (void *)pInput );
Erwan Tulou's avatar
Erwan Tulou committed
440 441 442

        getIntf()->p_sys->p_input = pInput;
        vlc_object_hold( pInput );
443

444
        // update global variables pertaining to this input
Erwan Tulou's avatar
Erwan Tulou committed
445
        update_current_input();
446 447 448 449

        // ensure the playtree is also updated
        // (highlights the new item to be played back)
        getPlaytreeVar().onUpdateCurrent( true );
Erwan Tulou's avatar
Erwan Tulou committed
450 451
    }

452
    switch( newVal.i_int )
453
    {
454
        case INPUT_EVENT_STATE:
455
        {
456
            int state = var_GetInteger( pInput, "state" );
457 458 459
            SET_BOOL( m_cVarStopped, false );
            SET_BOOL( m_cVarPlaying, state != PAUSE_S );
            SET_BOOL( m_cVarPaused, state == PAUSE_S );
460 461
            break;
        }
462

463 464 465
        case INPUT_EVENT_POSITION:
        {
            float pos = var_GetFloat( pInput, "position" );
466 467
            SET_STREAMTIME( m_cVarTime, pos, false );
            SET_BOOL( m_cVarSeekable, pos != 0.0 );
468 469
            break;
        }
470

471 472 473 474 475 476 477 478 479 480 481 482
        case INPUT_EVENT_RATE:
        {
            float rate = var_GetFloat( pInput, "rate" );
            char* buffer;
            if( asprintf( &buffer, "%.3g", rate ) != -1 )
            {
                SET_TEXT( m_cVarSpeed, UString( getIntf(), buffer ) );
                free( buffer );
            }
            break;
        }

483 484 485 486 487 488
        case INPUT_EVENT_ES:
        {
            // Do we have audio
            vlc_value_t audio_es;
            var_Change( pInput, "audio-es", VLC_VAR_CHOICESCOUNT,
                            &audio_es, NULL );
489
            SET_BOOL( m_cVarHasAudio, audio_es.i_int > 0 );
490 491 492 493 494 495
            break;
        }

        case INPUT_EVENT_VOUT:
        {
            vout_thread_t* pVout = input_GetVout( pInput );
496
            SET_BOOL( m_cVarHasVout, pVout != NULL );
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
            if( !pVout || pVout == m_pVout )
            {
                // end of input or vout reuse (nothing to do)
                if( pVout )
                    vlc_object_release( pVout );
                break;
            }
            if( m_pVout )
            {
                // remove previous Vout callbacks
                var_DelCallback( m_pVout, "mouse-moved",
                                 onGenericCallback, this );
                vlc_object_release( m_pVout );
                m_pVout = NULL;
            }

            // add new Vout callbackx
            var_AddCallback( pVout, "mouse-moved",
                             onGenericCallback, this );
            m_pVout = pVout;
517 518
            break;
        }
519

520 521 522 523 524
        case INPUT_EVENT_CHAPTER:
        {
            vlc_value_t chapters_count;
            var_Change( pInput, "chapter", VLC_VAR_CHOICESCOUNT,
                        &chapters_count, NULL );
525
            SET_BOOL( m_cVarDvdActive, chapters_count.i_int > 0 );
526 527
            break;
        }
528

529
        case INPUT_EVENT_RECORD:
530
            SET_BOOL( m_cVarRecording, var_GetBool( pInput, "record" ) );
531
            break;
532

533
        case INPUT_EVENT_DEAD:
534 535
            msg_Dbg( getIntf(), "end of input detected for %p",
                     (void *)pInput );
Erwan Tulou's avatar
Erwan Tulou committed
536

Erwan Tulou's avatar
Erwan Tulou committed
537
            var_DelCallback( pInput, "intf-event", onGenericCallback2, this );
Erwan Tulou's avatar
Erwan Tulou committed
538 539 540 541 542
            var_DelCallback( pInput, "bit-rate", onGenericCallback, this );
            var_DelCallback( pInput, "sample-rate", onGenericCallback, this );
            var_DelCallback( pInput, "can-record" , onGenericCallback, this );
            vlc_object_release( pInput );
            getIntf()->p_sys->p_input = NULL;
543 544
            reset_input();
            break;
545

546 547
        default:
            break;
548 549 550 551 552
    }
}

void VlcProc::on_bit_rate_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
553
    (void)newVal;
554 555
    input_thread_t* pInput = (input_thread_t*) p_obj;

Erwan Tulou's avatar
Erwan Tulou committed
556 557
    assert( getIntf()->p_sys->p_input == NULL || getIntf()->p_sys->p_input == pInput );

558
    int bitrate = var_GetInteger( pInput, "bit-rate" ) / 1000;
559
    SET_TEXT( m_cVarStreamBitRate, UString::fromInt( getIntf(), bitrate ) );
560 561 562 563
}

void VlcProc::on_sample_rate_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
564
    (void)newVal;
565 566
    input_thread_t* pInput = (input_thread_t*) p_obj;

Erwan Tulou's avatar
Erwan Tulou committed
567 568
    assert( getIntf()->p_sys->p_input == NULL || getIntf()->p_sys->p_input == pInput );

569
    int sampleRate = var_GetInteger( pInput, "sample-rate" ) / 1000;
570
    SET_TEXT( m_cVarStreamSampleRate, UString::fromInt(getIntf(),sampleRate) );
571 572
}

573 574
void VlcProc::on_can_record_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
575
    (void)newVal;
576 577
    input_thread_t* pInput = (input_thread_t*) p_obj;

Erwan Tulou's avatar
Erwan Tulou committed
578 579
    assert( getIntf()->p_sys->p_input == NULL || getIntf()->p_sys->p_input == pInput );

580
    SET_BOOL( m_cVarRecordable, var_GetBool(  pInput, "can-record" ) );
581 582
}

583 584
void VlcProc::on_random_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
585
    (void)newVal;
586 587
    playlist_t* pPlaylist = (playlist_t*) p_obj;

588
    SET_BOOL( m_cVarRandom, var_GetBool( pPlaylist, "random" ) );
589 590 591 592
}

void VlcProc::on_loop_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
593
    (void)newVal;
594 595
    playlist_t* pPlaylist = (playlist_t*) p_obj;

596
    SET_BOOL( m_cVarLoop, var_GetBool( pPlaylist, "loop" ) );
597 598 599 600
}

void VlcProc::on_repeat_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
601
    (void)newVal;
602 603
    playlist_t* pPlaylist = (playlist_t*) p_obj;

604
    SET_BOOL( m_cVarRepeat, var_GetBool( pPlaylist, "repeat" ) );
605 606 607 608 609 610
}

void VlcProc::on_volume_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
    (void)p_obj; (void)newVal;

611
    SET_VOLUME( m_cVarVolume, var_GetFloat( getPL(), "volume" ), false );
Erwan Tulou's avatar
Erwan Tulou committed
612 613 614 615 616 617
}

void VlcProc::on_mute_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
    (void)p_obj;
    SET_BOOL( m_cVarMute, newVal.b_bool );
618 619 620 621
}

void VlcProc::on_audio_filter_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
Erwan Tulou's avatar
Erwan Tulou committed
622
    (void)p_obj;
Erwan Tulou's avatar
Erwan Tulou committed
623
    char *pFilters = newVal.psz_string;
624
    bool b_equalizer = pFilters && strstr( pFilters, "equalizer" );
625
    SET_BOOL( m_cVarEqualizer, b_equalizer );
626
}
627

628 629
void VlcProc::on_intf_show_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
630
    (void)p_obj; (void)newVal;
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
    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
    {
648 649
        VoutManager* pVoutManager =  VoutManager::instance( getIntf() );
        FscWindow *pWin = pVoutManager->getFscWindow();
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
        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 ) );
            }
        }
    }
}

673 674
void VlcProc::on_mouse_moved_changed( vlc_object_t* p_obj, vlc_value_t newVal )
{
675
    (void)p_obj; (void)newVal;
676 677 678 679 680
    FscWindow* pFscWindow = VoutManager::instance( getIntf() )->getFscWindow();
    if( pFscWindow )
        pFscWindow->onMouseMoved();
}

681 682
void VlcProc::reset_input()
{
683 684 685 686 687 688 689 690 691 692 693
    SET_BOOL( m_cVarSeekable, false );
    SET_BOOL( m_cVarRecordable, false );
    SET_BOOL( m_cVarRecording, false );
    SET_BOOL( m_cVarDvdActive, false );
    SET_BOOL( m_cVarHasAudio, false );
    SET_BOOL( m_cVarHasVout, false );
    SET_BOOL( m_cVarStopped, true );
    SET_BOOL( m_cVarPlaying, false );
    SET_BOOL( m_cVarPaused, false );

    SET_STREAMTIME( m_cVarTime, 0, false );
694 695
    SET_TEXT( m_cVarStreamName, UString( getIntf(), "") );
    SET_TEXT( m_cVarStreamURI, UString( getIntf(), "") );
696 697
    SET_TEXT( m_cVarStreamBitRate, UString( getIntf(), "") );
    SET_TEXT( m_cVarStreamSampleRate, UString( getIntf(), "") );
698 699

    getPlaytreeVar().onUpdateCurrent( false );
700 701 702 703
}

void VlcProc::init_variables()
{
704
    playlist_t* pPlaylist = getPL();
705

706 707 708
    SET_BOOL( m_cVarRandom, var_GetBool( pPlaylist, "random" ) );
    SET_BOOL( m_cVarLoop, var_GetBool( pPlaylist, "loop" ) );
    SET_BOOL( m_cVarRepeat, var_GetBool( pPlaylist, "repeat" ) );
709

710
    SET_VOLUME( m_cVarVolume, var_GetFloat( pPlaylist, "volume" ), false );
Erwan Tulou's avatar
Erwan Tulou committed
711
    SET_BOOL( m_cVarMute, var_GetBool( pPlaylist, "mute" ) );
Erwan Tulou's avatar
Erwan Tulou committed
712

713 714
    SET_BOOL( m_cVarStopped, true );

715
    init_equalizer();
Erwan Tulou's avatar
Erwan Tulou committed
716 717
}

Erwan Tulou's avatar
Erwan Tulou committed
718 719 720 721 722 723 724

void VlcProc::update_current_input()
{
    input_thread_t* pInput = getIntf()->p_sys->p_input;
    if( !pInput )
        return;

725 726
    input_item_t *pItem = input_GetItem( pInput );
    if( pItem )
Erwan Tulou's avatar
Erwan Tulou committed
727
    {
Erwan Tulou's avatar
Erwan Tulou committed
728 729
        // Update short name (as defined by --input-title-format)
        char *psz_fmt = var_InheritString( getIntf(), "input-title-format" );
730 731 732
        char *psz_name = NULL;
        if( psz_fmt != NULL )
        {
733
            psz_name = vlc_strfinput( pInput, psz_fmt );
734 735 736 737 738
            free( psz_fmt );
        }

        SET_TEXT( m_cVarStreamName, UString( getIntf(),
                                             psz_name ? psz_name : "" ) );
Erwan Tulou's avatar
Erwan Tulou committed
739 740 741
        free( psz_name );

        // Update local path (if possible) or full uri
742
        char *psz_uri = input_item_GetURI( pItem );
743
        char *psz_path = vlc_uri2path( psz_uri );
Erwan Tulou's avatar
Erwan Tulou committed
744 745 746 747 748 749
        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
750
        char *psz_art = input_item_GetArtURL( pItem );
751
        SET_STRING( m_cVarStreamArt, std::string( psz_art ? psz_art : "" ) );
Erwan Tulou's avatar
Erwan Tulou committed
752 753 754 755
        free( psz_art );
    }
}

756
void VlcProc::init_equalizer()
Erwan Tulou's avatar
Erwan Tulou committed
757
{
758
    audio_output_t* pAout = playlist_GetAout( getPL() );
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775
    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",
                         onGenericCallback, this );
        var_AddCallback( pAout, "equalizer-bands",
                         onEqBandsChange, this );
        var_AddCallback( pAout, "equalizer-preamp",
                         onEqPreampChange, this );
    }
Erwan Tulou's avatar
Erwan Tulou committed
776

777 778 779 780
    // is equalizer enabled ?
    char *pFilters = pAout ?
                   var_GetNonEmptyString( pAout, "audio-filter" ) :
                   var_InheritString( getIntf(), "audio-filter" );
Erwan Tulou's avatar
Erwan Tulou committed
781 782
    bool b_equalizer = pFilters && strstr( pFilters, "equalizer" );
    free( pFilters );
783
    SET_BOOL( m_cVarEqualizer, b_equalizer );
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803

    // 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 );

    if( pAout )
        vlc_object_release( pAout);
804 805
}

806 807 808 809 810
void VlcProc::setFullscreenVar( bool b_fullscreen )
{
    SET_BOOL( m_cVarFullscreen, b_fullscreen );
}

811 812 813
#undef  SET_BOOL
#undef  SET_STREAMTIME
#undef  SET_TEXT
814
#undef  SET_STRING
815
#undef  SET_VOLUME