hotkeys.c 38.3 KB
Newer Older
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
1 2 3
/*****************************************************************************
 * hotkeys.c: Hotkey handling for vlc
 *****************************************************************************
4
 * Copyright (C) 2005 the VideoLAN team
5
 * $Id$
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
6
 *
7
 * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
8
 *          Jean-Paul Saman <jpsaman #_at_# m2x.nl>
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
9 10 11 12 13
 *
 * 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.
14
 *
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
15 16 17 18 19 20 21
 * 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
Antoine Cellerier's avatar
Antoine Cellerier committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
23 24 25 26 27 28
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/

29 30 31 32
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

33
#include <vlc_common.h>
34
#include <vlc_plugin.h>
Clément Stenac's avatar
Clément Stenac committed
35 36 37 38
#include <vlc_interface.h>
#include <vlc_input.h>
#include <vlc_vout.h>
#include <vlc_aout.h>
39
#include <vlc_osd.h>
Clément Stenac's avatar
Clément Stenac committed
40
#include <vlc_playlist.h>
Gildas Bazin's avatar
 
Gildas Bazin committed
41 42
#include "vlc_keys.h"

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
43
#define BUFFER_SIZE 10
44 45 46 47 48 49

#define CHANNELS_NUMBER 4
#define VOLUME_TEXT_CHAN     p_intf->p_sys->p_channels[ 0 ]
#define VOLUME_WIDGET_CHAN   p_intf->p_sys->p_channels[ 1 ]
#define POSITION_TEXT_CHAN   p_intf->p_sys->p_channels[ 2 ]
#define POSITION_WIDGET_CHAN p_intf->p_sys->p_channels[ 3 ]
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
50 51 52 53 54
/*****************************************************************************
 * intf_sys_t: description and status of FB interface
 *****************************************************************************/
struct intf_sys_t
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
55 56
    int                 p_actions[ BUFFER_SIZE ]; /* buffer that contains
                                                   * action events */
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
57
    int                 i_size;        /* number of events in buffer */
58 59
    int                 p_channels[ CHANNELS_NUMBER ]; /* contains registered
                                                        * channel IDs */
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
60 61 62 63 64 65 66 67 68 69
    input_thread_t *    p_input;       /* pointer to input */
    vout_thread_t *     p_vout;        /* pointer to vout object */
};

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int  Open    ( vlc_object_t * );
static void Close   ( vlc_object_t * );
static void Run     ( intf_thread_t * );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
70 71 72 73 74
static int  GetAction( intf_thread_t *);
static int  ActionEvent( vlc_object_t *, char const *,
                         vlc_value_t, vlc_value_t, void * );
static int  SpecialKeyEvent( vlc_object_t *, char const *,
                             vlc_value_t, vlc_value_t, void * );
75 76
static void PlayBookmark( intf_thread_t *, int );
static void SetBookmark ( intf_thread_t *, int );
77 78 79
static void DisplayPosition( intf_thread_t *, vout_thread_t *, input_thread_t * );
static void DisplayVolume  ( intf_thread_t *, vout_thread_t *, audio_volume_t );
static void ClearChannels  ( intf_thread_t *, vout_thread_t * );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
80 81 82 83

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
84 85 86 87 88 89 90 91 92 93 94
#define BOOKMARK1_TEXT    N_("Playlist bookmark 1")
#define BOOKMARK2_TEXT    N_("Playlist bookmark 2")
#define BOOKMARK3_TEXT    N_("Playlist bookmark 3")
#define BOOKMARK4_TEXT    N_("Playlist bookmark 4")
#define BOOKMARK5_TEXT    N_("Playlist bookmark 5")
#define BOOKMARK6_TEXT    N_("Playlist bookmark 6")
#define BOOKMARK7_TEXT    N_("Playlist bookmark 7")
#define BOOKMARK8_TEXT    N_("Playlist bookmark 8")
#define BOOKMARK9_TEXT    N_("Playlist bookmark 9")
#define BOOKMARK10_TEXT   N_("Playlist bookmark 10")
#define BOOKMARK_LONGTEXT N_("Define playlist bookmarks.")
95

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
96
vlc_module_begin();
97 98
    set_shortname( N_("Hotkeys") );
    set_description( N_("Hotkeys management interface") );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
99 100 101 102 103 104 105 106 107 108
    set_capability( "interface", 0 );
    set_callbacks( Open, Close );
vlc_module_end();

/*****************************************************************************
 * Open: initialize interface
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    intf_thread_t *p_intf = (intf_thread_t *)p_this;
Clément Stenac's avatar
Woops  
Clément Stenac committed
109
    MALLOC_ERR( p_intf->p_sys, intf_sys_t );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
110 111 112 113

    p_intf->p_sys->i_size = 0;
    p_intf->pf_run = Run;

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
114 115
    var_AddCallback( p_intf->p_libvlc, "key-pressed", SpecialKeyEvent, p_intf );
    var_AddCallback( p_intf->p_libvlc, "key-action", ActionEvent, p_intf );
116
    return VLC_SUCCESS;
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
117 118 119 120 121 122 123 124 125
}

/*****************************************************************************
 * Close: destroy interface
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
{
    intf_thread_t *p_intf = (intf_thread_t *)p_this;

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
126 127
    var_DelCallback( p_intf->p_libvlc, "key-action", ActionEvent, p_intf );
    var_DelCallback( p_intf->p_libvlc, "key-pressed", SpecialKeyEvent, p_intf );
128

Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
129 130 131 132 133 134 135 136 137 138
    /* Destroy structure */
    free( p_intf->p_sys );
}

/*****************************************************************************
 * Run: main loop
 *****************************************************************************/
static void Run( intf_thread_t *p_intf )
{
    vout_thread_t *p_vout = NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
139 140
    vlc_value_t val;
    int i;
141
    playlist_t *p_playlist = pl_Yield( p_intf );
142
    int canc = vlc_savecancel();
Gildas Bazin's avatar
 
Gildas Bazin committed
143 144

    /* Initialize hotkey structure */
145 146 147
    for( struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys;
         p_hotkey->psz_action != NULL;
         p_hotkey++ )
148
    {
149
        p_hotkey->i_key = config_GetInt( p_intf, p_hotkey->psz_action );
150
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
151

152
    for( ;; )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
153
    {
154 155
        input_thread_t *p_input;
        vout_thread_t *p_last_vout;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
156
        int i_action = GetAction( p_intf );
Gildas Bazin's avatar
 
Gildas Bazin committed
157

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
158
        if( i_action == -1 )
159
            break; /* die */
160

161 162 163 164 165 166
        /* Update the input */
        PL_LOCK;
        p_input = p_playlist->p_input;
        if( p_input )
            vlc_object_yield( p_input );
        PL_UNLOCK;
167

168 169 170 171 172 173 174 175 176 177 178 179 180 181
        /* Update the vout */
        p_last_vout = p_vout;
        p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );

        /* Register OSD channels */
        if( p_vout && p_vout != p_last_vout )
        {
            for( i = 0; i < CHANNELS_NUMBER; i++ )
            {
                spu_Control( p_vout->p_spu, SPU_CHANNEL_REGISTER,
                             &p_intf->p_sys->p_channels[ i ] );
            }
        }

182
        /* Quit */
Gildas Bazin's avatar
 
Gildas Bazin committed
183
        if( i_action == ACTIONID_QUIT )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
184
        {
185 186
            if( p_playlist )
                playlist_Stop( p_playlist );
187
            vlc_object_kill( p_intf->p_libvlc );
188
            vlc_object_kill( p_intf );
189 190
            ClearChannels( p_intf, p_vout );
            vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Quit" ) );
191 192 193 194
            if( p_vout )
                vlc_object_release( p_vout );
            if( p_input )
                vlc_object_release( p_input );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
195 196
            continue;
        }
197
        /* Volume and audio actions */
Gildas Bazin's avatar
 
Gildas Bazin committed
198
        else if( i_action == ACTIONID_VOL_UP )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
199 200 201
        {
            audio_volume_t i_newvol;
            aout_VolumeUp( p_intf, 1, &i_newvol );
202
            DisplayVolume( p_intf, p_vout, i_newvol );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
203
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
204
        else if( i_action == ACTIONID_VOL_DOWN )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
205 206 207
        {
            audio_volume_t i_newvol;
            aout_VolumeDown( p_intf, 1, &i_newvol );
208
            DisplayVolume( p_intf, p_vout, i_newvol );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
209
        }
Yoann Peronneau's avatar
Yoann Peronneau committed
210 211 212 213 214 215 216 217
        else if( i_action == ACTIONID_VOL_MUTE )
        {
            audio_volume_t i_newvol = -1;
            aout_VolumeMute( p_intf, &i_newvol );
            if( p_vout )
            {
                if( i_newvol == 0 )
                {
218 219 220
                    ClearChannels( p_intf, p_vout );
                    vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
                                  OSD_MUTE_ICON );
Yoann Peronneau's avatar
Yoann Peronneau committed
221 222 223
                }
                else
                {
224
                    DisplayVolume( p_intf, p_vout, i_newvol );
Yoann Peronneau's avatar
Yoann Peronneau committed
225 226 227
                }
            }
        }
228
        /* Interface showing */
229
        else if( i_action == ACTIONID_INTF_SHOW )
230
            var_SetBool( p_intf->p_libvlc, "intf-show", true );
231
        else if( i_action == ACTIONID_INTF_HIDE )
232
            var_SetBool( p_intf->p_libvlc, "intf-show", false );
233
        /* Video Output actions */
234 235 236 237
        else if( i_action == ACTIONID_SNAPSHOT )
        {
            if( p_vout ) vout_Control( p_vout, VOUT_SNAPSHOT );
        }
238
        else if( i_action == ACTIONID_TOGGLE_FULLSCREEN )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
239
        {
240 241
            if( p_vout )
            {
242 243
                var_Get( p_vout, "fullscreen", &val );
                val.b_bool = !val.b_bool;
244 245 246 247
                var_Set( p_vout, "fullscreen", val );
            }
            else
            {
248 249 250
                var_Get( p_playlist, "fullscreen", &val );
                val.b_bool = !val.b_bool;
                var_Set( p_playlist, "fullscreen", val );
251
            }
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
252
        }
253 254 255 256
        else if( i_action == ACTIONID_LEAVE_FULLSCREEN )
        {
            if( p_vout && var_GetBool( p_vout, "fullscreen" ) )
            {
257
                var_SetBool( p_vout, "fullscreen", false );
258 259
            }
        }
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
        else if( i_action == ACTIONID_ZOOM_QUARTER ||
                 i_action == ACTIONID_ZOOM_HALF ||
                 i_action == ACTIONID_ZOOM_ORIGINAL ||
                 i_action == ACTIONID_ZOOM_DOUBLE )
        {
            if( p_vout )
            {
                if( i_action == ACTIONID_ZOOM_QUARTER )
                    val.f_float = 0.25;
                if( i_action == ACTIONID_ZOOM_HALF )
                    val.f_float = 0.5;
                if( i_action == ACTIONID_ZOOM_ORIGINAL )
                    val.f_float = 1;
                if( i_action == ACTIONID_ZOOM_DOUBLE )
                    val.f_float = 2;
                var_Set( p_vout, "zoom", val );
            }
        }
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
        else if( i_action == ACTIONID_WALLPAPER )
        {
            if( p_vout )
            {
                var_Get( p_vout, "directx-wallpaper", &val );
                val.b_bool = !val.b_bool;
                var_Set( p_vout, "directx-wallpaper", val );
            }
            else
            {
                var_Get( p_playlist, "directx-wallpaper", &val );
                val.b_bool = !val.b_bool;
                var_Set( p_playlist, "directx-wallpaper", val );
            }
        }
293
        /* Playlist actions */
Antoine Cellerier's avatar
Antoine Cellerier committed
294 295 296 297 298 299
        else if( i_action == ACTIONID_LOOP )
        {
            /* Toggle Normal -> Loop -> Repeat -> Normal ... */
            vlc_value_t val2;
            var_Get( p_playlist, "loop", &val );
            var_Get( p_playlist, "repeat", &val2 );
300
            if( val2.b_bool == true )
Antoine Cellerier's avatar
Antoine Cellerier committed
301
            {
302 303
                val.b_bool = false;
                val2.b_bool = false;
Antoine Cellerier's avatar
Antoine Cellerier committed
304
            }
305
            else if( val.b_bool == true )
Antoine Cellerier's avatar
Antoine Cellerier committed
306
            {
307 308
                val.b_bool = false;
                val2.b_bool = true;
Antoine Cellerier's avatar
Antoine Cellerier committed
309 310 311
            }
            else
            {
312
                val.b_bool = true;
Antoine Cellerier's avatar
Antoine Cellerier committed
313 314 315 316 317 318 319 320 321 322
            }
            var_Set( p_playlist, "loop", val );
            var_Set( p_playlist, "repeat", val2 );
        }
        else if( i_action == ACTIONID_RANDOM )
        {
            var_Get( p_playlist, "random", &val );
            val.b_bool = !val.b_bool;
            var_Set( p_playlist, "random", val );
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
323
        else if( i_action == ACTIONID_PLAY_PAUSE )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
324
        {
325 326
            val.i_int = PLAYING_S;
            if( p_input )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
327
            {
328
                ClearChannels( p_intf, p_vout );
329 330 331 332 333 334 335 336 337 338 339 340 341 342

                var_Get( p_input, "state", &val );
                if( val.i_int != PAUSE_S )
                {
                    vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
                                  OSD_PAUSE_ICON );
                    val.i_int = PAUSE_S;
                }
                else
                {
                    vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
                                  OSD_PLAY_ICON );
                    val.i_int = PLAYING_S;
                }
343
                var_Set( p_input, "state", val );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
344 345 346
            }
            else
            {
347
                playlist_Play( p_playlist );
Gildas Bazin's avatar
 
Gildas Bazin committed
348
            }
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
349
        }
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
        else if( i_action == ACTIONID_AUDIODEVICE_CYCLE )
        {
            vlc_value_t val, list, list2;
            int i_count, i;

            aout_instance_t *p_aout =
                vlc_object_find( p_intf, VLC_OBJECT_AOUT, FIND_ANYWHERE );
            var_Get( p_aout, "audio-device", &val );
            var_Change( p_aout, "audio-device", VLC_VAR_GETCHOICES,
                    &list, &list2 );
            i_count = list.p_list->i_count;

            /* Not enough device to switch between */
            if( i_count <= 1 )
                continue;

            for( i = 0; i < i_count; i++ )
            {
                if( val.i_int == list.p_list->p_values[i].i_int )
                {
                    break;
                }
            }
            if( i == i_count )
            {
                msg_Warn( p_aout,
                        "invalid current audio device, selecting 0" );
                var_Set( p_aout, "audio-device",
                        list.p_list->p_values[0] );
                i = 0;
            }
            else if( i == i_count -1 )
            {
                var_Set( p_aout, "audio-device",
                        list.p_list->p_values[0] );
                i = 0;
            }
            else
            {
                var_Set( p_aout, "audio-device",
                        list.p_list->p_values[i+1] );
                i++;
            }
            vout_OSDMessage( p_intf, DEFAULT_CHAN,
                    _("Audio Device: %s"),
                    list2.p_list->p_values[i].psz_string);
            vlc_object_release( p_aout );
        }
398
        /* Input options */
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
399 400
        else if( p_input )
        {
401
            bool b_seekable = var_GetBool( p_input, "seekable" );
402
            int i_interval =0;
403

Gildas Bazin's avatar
 
Gildas Bazin committed
404
            if( i_action == ACTIONID_PAUSE )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
405
            {
406 407 408 409 410 411 412 413 414
                var_Get( p_input, "state", &val );
                if( val.i_int != PAUSE_S )
                {
                    ClearChannels( p_intf, p_vout );
                    vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
                                  OSD_PAUSE_ICON );
                    val.i_int = PAUSE_S;
                    var_Set( p_input, "state", val );
                }
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
415
            }
416 417
            else if( i_action == ACTIONID_JUMP_BACKWARD_EXTRASHORT
                     && b_seekable )
418
            {
419
#define SET_TIME( a, b ) \
Clément Stenac's avatar
Clément Stenac committed
420
    i_interval = config_GetInt( p_input, a "-jump-size" ); \
421
    if( i_interval > 0 ) { \
422
        val.i_time = (mtime_t)(i_interval * b) * 1000000L; \
423 424 425 426
        var_Set( p_input, "time-offset", val ); \
        DisplayPosition( p_intf, p_vout, p_input ); \
    }
                SET_TIME( "extrashort", -1 );
427
            }
428
            else if( i_action == ACTIONID_JUMP_FORWARD_EXTRASHORT && b_seekable )
429
            {
430
                SET_TIME( "extrashort", 1 );
431
            }
432
            else if( i_action == ACTIONID_JUMP_BACKWARD_SHORT && b_seekable )
Gildas Bazin's avatar
 
Gildas Bazin committed
433
            {
434
                SET_TIME( "short", -1 );
Gildas Bazin's avatar
 
Gildas Bazin committed
435
            }
436
            else if( i_action == ACTIONID_JUMP_FORWARD_SHORT && b_seekable )
Gildas Bazin's avatar
 
Gildas Bazin committed
437
            {
438
                SET_TIME( "short", 1 );
Gildas Bazin's avatar
 
Gildas Bazin committed
439
            }
440
            else if( i_action == ACTIONID_JUMP_BACKWARD_MEDIUM && b_seekable )
Gildas Bazin's avatar
 
Gildas Bazin committed
441
            {
442
                SET_TIME( "medium", -1 );
Gildas Bazin's avatar
 
Gildas Bazin committed
443
            }
444
            else if( i_action == ACTIONID_JUMP_FORWARD_MEDIUM && b_seekable )
Gildas Bazin's avatar
 
Gildas Bazin committed
445
            {
446
                SET_TIME( "medium", 1 );
Gildas Bazin's avatar
 
Gildas Bazin committed
447
            }
448
            else if( i_action == ACTIONID_JUMP_BACKWARD_LONG && b_seekable )
Gildas Bazin's avatar
 
Gildas Bazin committed
449
            {
450
                SET_TIME( "long", -1 );
Gildas Bazin's avatar
 
Gildas Bazin committed
451
            }
452
            else if( i_action == ACTIONID_JUMP_FORWARD_LONG && b_seekable )
Gildas Bazin's avatar
 
Gildas Bazin committed
453
            {
454 455
                SET_TIME( "long", 1 );
#undef SET_TIME
Gildas Bazin's avatar
 
Gildas Bazin committed
456
            }
457 458 459 460 461 462 463 464
            else if( i_action == ACTIONID_AUDIO_TRACK )
            {
                vlc_value_t val, list, list2;
                int i_count, i;
                var_Get( p_input, "audio-es", &val );
                var_Change( p_input, "audio-es", VLC_VAR_GETCHOICES,
                            &list, &list2 );
                i_count = list.p_list->i_count;
465 466 467 468
                if( i_count <= 1 )
                {
                    continue;
                }
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
                for( i = 0; i < i_count; i++ )
                {
                    if( val.i_int == list.p_list->p_values[i].i_int )
                    {
                        break;
                    }
                }
                /* value of audio-es was not in choices list */
                if( i == i_count )
                {
                    msg_Warn( p_input,
                              "invalid current audio track, selecting 0" );
                    var_Set( p_input, "audio-es",
                             list.p_list->p_values[0] );
                    i = 0;
                }
                else if( i == i_count - 1 )
                {
                    var_Set( p_input, "audio-es",
488 489
                             list.p_list->p_values[1] );
                    i = 1;
490 491 492 493 494 495 496 497 498 499 500
                }
                else
                {
                    var_Set( p_input, "audio-es",
                             list.p_list->p_values[i+1] );
                    i++;
                }
                vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                 _("Audio track: %s"),
                                 list2.p_list->p_values[i].psz_string );
            }
501
            else if( i_action == ACTIONID_SUBTITLE_TRACK )
502 503 504 505
            {
                vlc_value_t val, list, list2;
                int i_count, i;
                var_Get( p_input, "spu-es", &val );
506

507 508 509
                var_Change( p_input, "spu-es", VLC_VAR_GETCHOICES,
                            &list, &list2 );
                i_count = list.p_list->i_count;
510 511
                if( i_count <= 1 )
                {
512 513
                    vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                     _("Subtitle track: %s"), _("N/A") );
514 515
                    continue;
                }
516 517 518 519 520 521 522
                for( i = 0; i < i_count; i++ )
                {
                    if( val.i_int == list.p_list->p_values[i].i_int )
                    {
                        break;
                    }
                }
523
                /* value of spu-es was not in choices list */
524 525
                if( i == i_count )
                {
526 527
                    msg_Warn( p_input,
                              "invalid current subtitle track, selecting 0" );
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
                    var_Set( p_input, "spu-es", list.p_list->p_values[0] );
                    i = 0;
                }
                else if( i == i_count - 1 )
                {
                    var_Set( p_input, "spu-es", list.p_list->p_values[0] );
                    i = 0;
                }
                else
                {
                    var_Set( p_input, "spu-es", list.p_list->p_values[i+1] );
                    i = i + 1;
                }
                vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                 _("Subtitle track: %s"),
                                 list2.p_list->p_values[i].psz_string );
            }
545
            else if( i_action == ACTIONID_ASPECT_RATIO && p_vout )
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
            {
                vlc_value_t val={0}, val_list, text_list;
                var_Get( p_vout, "aspect-ratio", &val );
                if( var_Change( p_vout, "aspect-ratio", VLC_VAR_GETLIST,
                                &val_list, &text_list ) >= 0 )
                {
                    int i;
                    for( i = 0; i < val_list.p_list->i_count; i++ )
                    {
                        if( !strcmp( val_list.p_list->p_values[i].psz_string,
                                     val.psz_string ) )
                        {
                            i++;
                            break;
                        }
                    }
                    if( i == val_list.p_list->i_count ) i = 0;
                    var_SetString( p_vout, "aspect-ratio",
                                   val_list.p_list->p_values[i].psz_string );
                    vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                     _("Aspect ratio: %s"),
                                     text_list.p_list->p_values[i].psz_string );
568 569

                    var_Change( p_vout, "aspect-ratio", VLC_VAR_FREELIST, &val_list, &text_list );
570 571 572
                }
                free( val.psz_string );
            }
573
            else if( i_action == ACTIONID_CROP && p_vout )
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
            {
                vlc_value_t val={0}, val_list, text_list;
                var_Get( p_vout, "crop", &val );
                if( var_Change( p_vout, "crop", VLC_VAR_GETLIST,
                                &val_list, &text_list ) >= 0 )
                {
                    int i;
                    for( i = 0; i < val_list.p_list->i_count; i++ )
                    {
                        if( !strcmp( val_list.p_list->p_values[i].psz_string,
                                     val.psz_string ) )
                        {
                            i++;
                            break;
                        }
                    }
                    if( i == val_list.p_list->i_count ) i = 0;
                    var_SetString( p_vout, "crop",
                                   val_list.p_list->p_values[i].psz_string );
                    vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                     _("Crop: %s"),
                                     text_list.p_list->p_values[i].psz_string );
596 597

                    var_Change( p_vout, "crop", VLC_VAR_FREELIST, &val_list, &text_list );
598 599 600
                }
                free( val.psz_string );
            }
601
            else if( i_action == ACTIONID_DEINTERLACE && p_vout )
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
            {
                vlc_value_t val={0}, val_list, text_list;
                var_Get( p_vout, "deinterlace", &val );
                if( var_Change( p_vout, "deinterlace", VLC_VAR_GETLIST,
                                &val_list, &text_list ) >= 0 )
                {
                    int i;
                    for( i = 0; i < val_list.p_list->i_count; i++ )
                    {
                        if( !strcmp( val_list.p_list->p_values[i].psz_string,
                                     val.psz_string ) )
                        {
                            i++;
                            break;
                        }
                    }
                    if( i == val_list.p_list->i_count ) i = 0;
                    var_SetString( p_vout, "deinterlace",
                                   val_list.p_list->p_values[i].psz_string );
                    vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                     _("Deinterlace mode: %s"),
                                     text_list.p_list->p_values[i].psz_string );
624 625

                    var_Change( p_vout, "deinterlace", VLC_VAR_FREELIST, &val_list, &text_list );
626 627 628
                }
                free( val.psz_string );
            }
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
            else if( ( i_action == ACTIONID_ZOOM || i_action == ACTIONID_UNZOOM ) && p_vout )
            {
                vlc_value_t val={0}, val_list, text_list;
                var_Get( p_vout, "zoom", &val );
                if( var_Change( p_vout, "zoom", VLC_VAR_GETLIST,
                                &val_list, &text_list ) >= 0 )
                {
                    int i;
                    for( i = 0; i < val_list.p_list->i_count; i++ )
                    {
                        if( val_list.p_list->p_values[i].f_float
                           == val.f_float )
                        {
                            if( i_action == ACTIONID_ZOOM )
                                i++;
                            else /* ACTIONID_UNZOOM */
                                i--;
                            break;
                        }
                    }
                    if( i == val_list.p_list->i_count ) i = 0;
                    if( i == -1 ) i = val_list.p_list->i_count-1;
                    var_SetFloat( p_vout, "zoom",
                                  val_list.p_list->p_values[i].f_float );
                    vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                     _("Zoom mode: %s"),
                                text_list.p_list->p_values[i].var.psz_name );
656 657

                    var_Change( p_vout, "zoom", VLC_VAR_FREELIST, &val_list, &text_list );
658 659
                }
            }
660
            else if( i_action == ACTIONID_CROP_TOP && p_vout )
661
                var_IncInteger( p_vout, "crop-top" );
662
            else if( i_action == ACTIONID_UNCROP_TOP && p_vout )
663
                var_DecInteger( p_vout, "crop-top" );
664
            else if( i_action == ACTIONID_CROP_BOTTOM && p_vout )
665
                var_IncInteger( p_vout, "crop-bottom" );
666
            else if( i_action == ACTIONID_UNCROP_BOTTOM && p_vout )
667
                 var_DecInteger( p_vout, "crop-bottom" );
668
            else if( i_action == ACTIONID_CROP_LEFT && p_vout )
669
                 var_IncInteger( p_vout, "crop-left" );
670
            else if( i_action == ACTIONID_UNCROP_LEFT && p_vout )
671
                 var_DecInteger( p_vout, "crop-left" );
672
            else if( i_action == ACTIONID_CROP_RIGHT && p_vout )
673
                 var_IncInteger( p_vout, "crop-right" );
674
            else if( i_action == ACTIONID_UNCROP_RIGHT && p_vout )
675 676
                 var_DecInteger( p_vout, "crop-right" );

Gildas Bazin's avatar
 
Gildas Bazin committed
677
            else if( i_action == ACTIONID_NEXT )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
678
            {
679 680
                vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN, _("Next") );
                playlist_Next( p_playlist );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
681
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
682
            else if( i_action == ACTIONID_PREV )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
683
            {
684 685 686
                vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                 _("Previous") );
                playlist_Prev( p_playlist );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
687
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
688
            else if( i_action == ACTIONID_STOP )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
689
            {
690
                playlist_Stop( p_playlist );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
691
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
692
            else if( i_action == ACTIONID_FASTER )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
693
            {
694
                var_SetVoid( p_input, "rate-faster" );
695 696
                vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                 _("Faster") );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
697
            }
698
            else if( i_action == ACTIONID_SLOWER )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
699
            {
700
                var_SetVoid( p_input, "rate-slower" );
701 702
                vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
                                 _("Slower") );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
703
            }
704
            else if( i_action == ACTIONID_POSITION && b_seekable )
705
            {
706
                DisplayPosition( p_intf, p_vout, p_input );
707 708 709 710 711 712 713 714 715 716
            }
            else if( i_action >= ACTIONID_PLAY_BOOKMARK1 &&
                     i_action <= ACTIONID_PLAY_BOOKMARK10 )
            {
                PlayBookmark( p_intf, i_action - ACTIONID_PLAY_BOOKMARK1 + 1 );
            }
            else if( i_action >= ACTIONID_SET_BOOKMARK1 &&
                     i_action <= ACTIONID_SET_BOOKMARK10 )
            {
                SetBookmark( p_intf, i_action - ACTIONID_SET_BOOKMARK1 + 1 );
717
            }
718 719
            /* Only makes sense with DVD */
            else if( i_action == ACTIONID_TITLE_PREV )
720
                var_SetVoid( p_input, "prev-title" );
721
            else if( i_action == ACTIONID_TITLE_NEXT )
722
                var_SetVoid( p_input, "next-title" );
723
            else if( i_action == ACTIONID_CHAPTER_PREV )
724
                var_SetVoid( p_input, "prev-chapter" );
725
            else if( i_action == ACTIONID_CHAPTER_NEXT )
726
                var_SetVoid( p_input, "next-chapter" );
727
            else if( i_action == ACTIONID_DISC_MENU )
728 729
                var_SetInteger( p_input, "title  0", 2 );

730 731 732 733 734 735
            else if( i_action == ACTIONID_SUBDELAY_DOWN )
            {
                int64_t i_delay = var_GetTime( p_input, "spu-delay" );
                i_delay -= 50000;    /* 50 ms */
                var_SetTime( p_input, "spu-delay", i_delay );
                ClearChannels( p_intf, p_vout );
Clément Stenac's avatar
Clément Stenac committed
736 737
                vout_OSDMessage( p_intf, DEFAULT_CHAN,
                                 _( "Subtitle delay %i ms" ),
738 739 740 741 742 743 744 745
                                 (int)(i_delay/1000) );
            }
            else if( i_action == ACTIONID_SUBDELAY_UP )
            {
                int64_t i_delay = var_GetTime( p_input, "spu-delay" );
                i_delay += 50000;    /* 50 ms */
                var_SetTime( p_input, "spu-delay", i_delay );
                ClearChannels( p_intf, p_vout );
Clément Stenac's avatar
Clément Stenac committed
746 747
                vout_OSDMessage( p_intf, DEFAULT_CHAN,
                                _( "Subtitle delay %i ms" ),
748 749 750 751 752 753 754 755
                                 (int)(i_delay/1000) );
            }
            else if( i_action == ACTIONID_AUDIODELAY_DOWN )
            {
                int64_t i_delay = var_GetTime( p_input, "audio-delay" );
                i_delay -= 50000;    /* 50 ms */
                var_SetTime( p_input, "audio-delay", i_delay );
                ClearChannels( p_intf, p_vout );
Clément Stenac's avatar
Clément Stenac committed
756 757
                vout_OSDMessage( p_intf, DEFAULT_CHAN,
                                _( "Audio delay %i ms" ),
758 759 760 761 762 763 764 765
                                 (int)(i_delay/1000) );
            }
            else if( i_action == ACTIONID_AUDIODELAY_UP )
            {
                int64_t i_delay = var_GetTime( p_input, "audio-delay" );
                i_delay += 50000;    /* 50 ms */
                var_SetTime( p_input, "audio-delay", i_delay );
                ClearChannels( p_intf, p_vout );
Clément Stenac's avatar
Clément Stenac committed
766 767
                vout_OSDMessage( p_intf, DEFAULT_CHAN,
                                _( "Audio delay %i ms" ),
768 769 770 771
                                 (int)(i_delay/1000) );
            }
            else if( i_action == ACTIONID_PLAY )
            {
772 773
                var_Get( p_input, "rate", &val );
                if( val.i_int != INPUT_RATE_DEFAULT )
774
                {
775 776 777 778 779 780 781 782 783
                    /* Return to normal speed */
                    var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT );
                }
                else
                {
                    ClearChannels( p_intf, p_vout );
                    vout_OSDIcon( VLC_OBJECT( p_intf ), DEFAULT_CHAN,
                                  OSD_PLAY_ICON );
                    playlist_Play( p_playlist );
784 785
                }
            }
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
            else if( i_action == ACTIONID_MENU_ON )
            {
                osd_MenuShow( VLC_OBJECT(p_intf) );
            }
            else if( i_action == ACTIONID_MENU_OFF )
            {
                osd_MenuHide( VLC_OBJECT(p_intf) );
            }
            else if( i_action == ACTIONID_MENU_LEFT )
            {
                osd_MenuPrev( VLC_OBJECT(p_intf) );
            }
            else if( i_action == ACTIONID_MENU_RIGHT )
            {
                osd_MenuNext( VLC_OBJECT(p_intf) );
            }
            else if( i_action == ACTIONID_MENU_UP )
            {
                osd_MenuUp( VLC_OBJECT(p_intf) );
            }
            else if( i_action == ACTIONID_MENU_DOWN )
            {
                osd_MenuDown( VLC_OBJECT(p_intf) );
            }
            else if( i_action == ACTIONID_MENU_SELECT )
            {
                osd_MenuActivate( VLC_OBJECT(p_intf) );
            }
814 815 816 817 818 819 820 821 822 823 824 825 826
            else if( i_action == ACTIONID_RECORD )
            {
                if( var_GetBool( p_input, "can-record" ) )
                {
                    const bool b_record = !var_GetBool( p_input, "record" );

                    if( b_record )
                        vout_OSDMessage( p_intf, DEFAULT_CHAN, _("Recording") );
                    else
                        vout_OSDMessage( p_intf, DEFAULT_CHAN, _("Recording done") );
                    var_SetBool( p_input, "record", b_record );
                }
            }
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
827
        }
828 829 830 831
        if( p_vout )
            vlc_object_release( p_vout );
        if( p_input )
            vlc_object_release( p_input );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
832
    }
833
    pl_Release( p_intf );
834
    vlc_restorecancel( canc );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
835 836
}

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
837
static int GetAction( intf_thread_t *p_intf )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
838
{
839 840 841 842 843
    intf_sys_t *p_sys = p_intf->p_sys;
    int i_ret = -1;

    vlc_object_lock( p_intf );
    while( p_sys->i_size == 0 )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
844
    {
845 846 847
        if( !vlc_object_alive( p_intf ) )
            goto out;
        vlc_object_wait( p_intf );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
848
    }
849

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
850
    i_ret = p_sys->p_actions[ 0 ];
851 852
    p_sys->i_size--;
    for( int i = 0; i < p_sys->i_size; i++ )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
853
        p_sys->p_actions[i] = p_sys->p_actions[i + 1];
854 855 856 857 858 859

out:
    vlc_object_unlock( p_intf );
    return i_ret;
}

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
860
static int PutAction( intf_thread_t *p_intf, int i_action )
861 862 863 864 865 866
{
    intf_sys_t *p_sys = p_intf->p_sys;
    int i_ret = VLC_EGENERIC;

    vlc_object_lock( p_intf );
    if ( p_sys->i_size >= BUFFER_SIZE )
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
867
        msg_Warn( p_intf, "event buffer full, dropping key actions" );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
868
    else
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
869
        p_sys->p_actions[p_sys->i_size++] = i_action;
870 871 872 873

    vlc_object_signal_unlocked( p_intf );
    vlc_object_unlock( p_intf );
    return i_ret;
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
874 875 876
}

/*****************************************************************************
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
877
 * SpecialKeyEvent: callback for mouse events
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
878
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
879 880 881
static int SpecialKeyEvent( vlc_object_t *libvlc, char const *psz_var,
                            vlc_value_t oldval, vlc_value_t newval,
                            void *p_data )
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
882 883
{
    intf_thread_t *p_intf = (intf_thread_t *)p_data;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
    int i_action;

    (void)libvlc;
    (void)psz_var;
    (void)oldval;

    /* Special action for mouse event */
    /* FIXME: This should probably be configurable */
    /* FIXME: rework hotkeys handling to allow more than 1 event
     * to trigger one same action */
    switch (newval.i_int & KEY_SPECIAL)
    {
        case KEY_MOUSEWHEELUP:
            i_action = ACTIONID_VOL_UP;
            break;
        case KEY_MOUSEWHEELDOWN:
            i_action = ACTIONID_VOL_DOWN;
            break;
        case KEY_MOUSEWHEELLEFT:
            i_action = ACTIONID_JUMP_BACKWARD_EXTRASHORT;
            break;
        case KEY_MOUSEWHEELRIGHT:
            i_action = ACTIONID_JUMP_FORWARD_EXTRASHORT;
            break;
        default:
          return VLC_SUCCESS;
    }

912 913 914
    if( i_action )
        return PutAction( p_intf, i_action );
    return VLC_SUCCESS;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
915 916 917 918 919 920 921 922 923 924 925 926 927
}

/*****************************************************************************
 * ActionEvent: callback for hotkey actions
 *****************************************************************************/
static int ActionEvent( vlc_object_t *libvlc, char const *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    intf_thread_t *p_intf = (intf_thread_t *)p_data;

    (void)libvlc;
    (void)psz_var;
    (void)oldval;
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
928

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
929
    return PutAction( p_intf, newval.i_int );
Sigmund Augdal Helberg's avatar
Sigmund Augdal Helberg committed
930 931
}

932
static void PlayBookmark( intf_thread_t *p_intf, int i_num )
933
{
934 935
    vlc_value_t val;
    char psz_bookmark_name[11];
936
    playlist_t *p_playlist = pl_Yield( p_intf );
937

938 939 940
    sprintf( psz_bookmark_name, "bookmark%i", i_num );
    var_Create( p_intf, psz_bookmark_name, VLC_VAR_STRING|VLC_VAR_DOINHERIT );
    var_Get( p_intf, psz_bookmark_name, &val );
941

942
    char *psz_bookmark = strdup( val.psz_string );
943 944
    PL_LOCK;
    FOREACH_ARRAY( playlist_item_t *p_item, p_playlist->items )
945 946
        char *psz_uri = input_item_GetURI( p_item->p_input );
        if( !strcmp( psz_bookmark, psz_uri ) )
947
        {
948
            free( psz_uri );
949
            playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, pl_Locked,
950
                              NULL, p_item );
951
            break;
952
        }
953 954
        else
            free( psz_uri );
955
    FOREACH_END();
956
    PL_UNLOCK;
957
    vlc_object_release( p_playlist );
958 959 960 961
}

static void SetBookmark( intf_thread_t *p_intf, int i_num )
{
962 963 964 965 966 967
    playlist_t *p_playlist = pl_Yield( p_intf );
    char psz_bookmark_name[11];
    sprintf( psz_bookmark_name, "bookmark%i", i_num );
    var_Create( p_intf, psz_bookmark_name,
                VLC_VAR_STRING|VLC_VAR_DOINHERIT );
    if( p_playlist->status.p_item )
968
    {
969 970 971 972
        char *psz_uri = input_item_GetURI( p_playlist->status.p_item->p_input );
        config_PutPsz( p_intf, psz_bookmark_name, psz_uri);
        msg_Info( p_intf, "setting playlist bookmark %i to %s", i_num, psz_uri);
        free( psz_uri );
973
        config_SaveConfigFile( p_intf, "hotkeys" );
974
    }
975
    pl_Release( p_intf );
976
}
977

978 979
static void DisplayPosition( intf_thread_t *p_intf, vout_thread_t *p_vout,
                             input_thread_t *p_input )
980 981 982
{
    char psz_duration[MSTRTIME_MAX_SIZE];
    char psz_time[MSTRTIME_MAX_SIZE];
983
    vlc_value_t time, pos;
984 985
    mtime_t i_seconds;

986 987
    if( p_vout == NULL ) return;

988
    ClearChannels( p_intf, p_vout );
989

990 991 992 993 994 995 996 997
    var_Get( p_input, "time", &time );
    i_seconds = time.i_time / 1000000;
    secstotimestr ( psz_time, i_seconds );

    var_Get( p_input, "length", &time );
    if( time.i_time > 0 )
    {
        secstotimestr( psz_duration, time.i_time / 1000000 );
Clément Stenac's avatar
Clément Stenac committed
998
        vout_OSDMessage( p_input, POSITION_TEXT_CHAN, (char *) "%s / %s",
999 1000 1001 1002
                         psz_time, psz_duration );
    }
    else if( i_seconds > 0 )
    {
1003
        vout_OSDMessage( p_input, POSITION_TEXT_CHAN, psz_time );
1004
    }
1005

1006
    if( !p_vout->p_window || p_vout->b_fullscreen )
1007 1008
    {
        var_Get( p_input, "position", &pos );
1009
        vout_OSDSlider( VLC_OBJECT( p_input ), POSITION_WIDGET_CHAN,
1010 1011 1012 1013
                        pos.f_float * 100, OSD_HOR_SLIDER );
    }
}

1014 1015
static void DisplayVolume( intf_thread_t *p_intf, vout_thread_t *p_vout,
                           audio_volume_t i_vol )
1016 1017 1018 1019 1020
{
    if( p_vout == NULL )
    {
        return;
    }
1021
    ClearChannels( p_intf, p_vout );
1022

1023
    if( !p_vout->p_window || p_vout->b_fullscreen )
1024
    {
1025
        vout_OSDSlider( VLC_OBJECT( p_vout ), VOLUME_WIDGET_CHAN,
1026 1027 1028 1029
            i_vol*100/AOUT_VOLUME_MAX, OSD_VERT_SLIDER );
    }
    else
    {
Clément Stenac's avatar
Clément Stenac committed
1030
        vout_OSDMessage( p_vout, VOLUME_TEXT_CHAN, _( "Volume %d%%" ),
1031
                         i_vol*400/AOUT_VOLUME_MAX );
1032
    }
1033
}
1034 1035 1036 1037 1038

static void ClearChannels( intf_thread_t *p_intf, vout_thread_t *p_vout )
{
    int i;

1039
    if( p_vout )
1040
    {
1041
        spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, DEFAULT_CHAN );
1042 1043
        for( i = 0; i < CHANNELS_NUMBER; i++ )
        {
1044 1045
            spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
                         p_intf->p_sys->p_channels[ i ] );
1046
        }