vout_intf.c 21.9 KB
Newer Older
Gildas Bazin's avatar
Gildas Bazin committed
1 2 3
/*****************************************************************************
 * vout_intf.c : video output interface
 *****************************************************************************
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2000-2007 VLC authors and VideoLAN
Gildas Bazin's avatar
Gildas Bazin committed
5 6 7
 *
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
8 9 10
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
Gildas Bazin's avatar
Gildas Bazin committed
11 12 13 14
 * (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
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
15 16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
Gildas Bazin's avatar
Gildas Bazin committed
17
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
18 19 20
 * You should have received a copy of the GNU Lesser 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.
Gildas Bazin's avatar
Gildas Bazin committed
21 22 23 24 25
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
26

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

31
#include <vlc_common.h>
32 33

#include <stdio.h>
Gildas Bazin's avatar
Gildas Bazin committed
34
#include <stdlib.h>                                                /* free() */
35
#include <assert.h>
Gildas Bazin's avatar
Gildas Bazin committed
36

37
#include <vlc_block.h>
38
#include <vlc_modules.h>
Gildas Bazin's avatar
Gildas Bazin committed
39

40
#include <vlc_vout.h>
41
#include <vlc_vout_osd.h>
42 43
#include <vlc_strings.h>
#include <vlc_charset.h>
44
#include "vout_internal.h"
45

Gildas Bazin's avatar
Gildas Bazin committed
46 47 48
/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
49
/* Object variables callbacks */
50 51
static int CropCallback( vlc_object_t *, char const *,
                         vlc_value_t, vlc_value_t, void * );
52 53
static int CropBorderCallback( vlc_object_t *, char const *,
                               vlc_value_t, vlc_value_t, void * );
54 55
static int AspectCallback( vlc_object_t *, char const *,
                           vlc_value_t, vlc_value_t, void * );
56 57 58 59
static int AutoScaleCallback( vlc_object_t *, char const *,
                              vlc_value_t, vlc_value_t, void * );
static int ZoomCallback( vlc_object_t *, char const *,
                         vlc_value_t, vlc_value_t, void * );
60
static int AboveCallback( vlc_object_t *, char const *,
61
                          vlc_value_t, vlc_value_t, void * );
62 63
static int WallPaperCallback( vlc_object_t *, char const *,
                              vlc_value_t, vlc_value_t, void * );
64 65
static int FullscreenCallback( vlc_object_t *, char const *,
                               vlc_value_t, vlc_value_t, void * );
66 67
static int SnapshotCallback( vlc_object_t *, char const *,
                             vlc_value_t, vlc_value_t, void * );
68 69
static int VideoFilterCallback( vlc_object_t *, char const *,
                                vlc_value_t, vlc_value_t, void * );
70
static int SubSourceCallback( vlc_object_t *, char const *,
71
                              vlc_value_t, vlc_value_t, void * );
72 73
static int SubFilterCallback( vlc_object_t *, char const *,
                              vlc_value_t, vlc_value_t, void * );
74 75
static int SubMarginCallback( vlc_object_t *, char const *,
                              vlc_value_t, vlc_value_t, void * );
76 77
static int ViewpointCallback( vlc_object_t *, char const *,
                              vlc_value_t, vlc_value_t, void * );
78 79 80 81

/*****************************************************************************
 * vout_IntfInit: called during the vout creation to initialise misc things.
 *****************************************************************************/
82 83 84
static const struct
{
    double f_value;
85
    char psz_label[13];
86 87 88 89 90
} p_zoom_values[] = {
    { 0.25, N_("1:4 Quarter") },
    { 0.5, N_("1:2 Half") },
    { 1, N_("1:1 Original") },
    { 2, N_("2:1 Double") },
91
};
92 93 94

static const struct
{
95 96
    char psz_value[8];
    char psz_label[8];
97 98 99
} p_crop_values[] = {
    { "", N_("Default") },
    { "16:10", "16:10" },
100
    { "16:9", "16:9" },
101
    { "4:3", "4:3" },
102
    { "185:100", "1.85:1" },
103 104 105
    { "221:100", "2.21:1" },
    { "235:100", "2.35:1" },
    { "239:100", "2.39:1" },
106 107 108
    { "5:3", "5:3" },
    { "5:4", "5:4" },
    { "1:1", "1:1" },
109
};
110 111 112

static const struct
{
113 114
    char psz_value[8];
    char psz_label[8];
115 116 117
} p_aspect_ratio_values[] = {
    { "", N_("Default") },
    { "16:9", "16:9" },
118 119
    { "4:3", "4:3" },
    { "1:1", "1:1" },
120 121
    { "16:10", "16:10" },
    { "221:100", "2.21:1" },
122 123
    { "235:100", "2.35:1" },
    { "239:100", "2.39:1" },
124
    { "5:4", "5:4" },
125
};
126 127 128 129

static void AddCustomRatios( vout_thread_t *p_vout, const char *psz_var,
                             char *psz_list )
{
130 131 132 133 134
    assert( psz_list );

    char *psz_cur = psz_list;
    char *psz_next;
    while( psz_cur && *psz_cur )
135
    {
136 137 138
        vlc_value_t val, text;
        psz_next = strchr( psz_cur, ',' );
        if( psz_next )
139
        {
140 141
            *psz_next = '\0';
            psz_next++;
142
        }
143 144 145 146
        val.psz_string = psz_cur;
        text.psz_string = psz_cur;
        var_Change( p_vout, psz_var, VLC_VAR_ADDCHOICE, &val, &text);
        psz_cur = psz_next;
147 148 149
    }
}

150 151
void vout_IntfInit( vout_thread_t *p_vout )
{
152
    vlc_value_t val, text;
153
    char *psz_buf;
154 155

    /* Create a few object variables we'll need later on */
156 157 158
    var_Create( p_vout, "snapshot-num", VLC_VAR_INTEGER );
    var_SetInteger( p_vout, "snapshot-num", 1 );

159 160
    var_Create( p_vout, "width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_vout, "height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
161
    var_Create( p_vout, "align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
162

163 164
    var_Create( p_vout, "mouse-hide-timeout",
                VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
165

166 167 168 169 170
    /* Add variables to manage scaling video */
    var_Create( p_vout, "autoscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
                | VLC_VAR_ISCOMMAND );
    text.psz_string = _("Autoscale video");
    var_Change( p_vout, "autoscale", VLC_VAR_SETTEXT, &text, NULL );
171
    var_AddCallback( p_vout, "autoscale", AutoScaleCallback, NULL );
172

173
    var_Create( p_vout, "zoom", VLC_VAR_FLOAT | VLC_VAR_ISCOMMAND |
174
                VLC_VAR_DOINHERIT );
175 176 177

    text.psz_string = _("Zoom");
    var_Change( p_vout, "zoom", VLC_VAR_SETTEXT, &text, NULL );
178

179
    for( size_t i = 0; i < ARRAY_SIZE(p_zoom_values); i++ )
180
    {
181
        val.f_float = p_zoom_values[i].f_value;
182
        text.psz_string = vlc_gettext( p_zoom_values[i].psz_label );
183
        var_Change( p_vout, "zoom", VLC_VAR_ADDCHOICE, &val, &text );
184 185 186
    }

    var_AddCallback( p_vout, "zoom", ZoomCallback, NULL );
187

188
    /* Crop offset vars */
189 190 191 192
    var_Create( p_vout, "crop-left", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
    var_Create( p_vout, "crop-top", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
    var_Create( p_vout, "crop-right", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
    var_Create( p_vout, "crop-bottom", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
193

194 195 196 197
    var_AddCallback( p_vout, "crop-left", CropBorderCallback, NULL );
    var_AddCallback( p_vout, "crop-top", CropBorderCallback, NULL );
    var_AddCallback( p_vout, "crop-right", CropBorderCallback, NULL );
    var_AddCallback( p_vout, "crop-bottom", CropBorderCallback, NULL );
198

199
    /* Crop object var */
200
    var_Create( p_vout, "crop", VLC_VAR_STRING | VLC_VAR_ISCOMMAND |
201
                VLC_VAR_DOINHERIT );
202 203 204 205

    text.psz_string = _("Crop");
    var_Change( p_vout, "crop", VLC_VAR_SETTEXT, &text, NULL );

206
    for( size_t i = 0; i < ARRAY_SIZE(p_crop_values); i++ )
207
    {
208 209 210
        val.psz_string = (char*)p_crop_values[i].psz_value;
        text.psz_string = _( p_crop_values[i].psz_label );
        var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &text );
211
    }
212 213

    /* Add custom crop ratios */
214 215 216 217 218 219
    psz_buf = var_CreateGetNonEmptyString( p_vout, "custom-crop-ratios" );
    if( psz_buf )
    {
        AddCustomRatios( p_vout, "crop", psz_buf );
        free( psz_buf );
    }
220

221
    var_AddCallback( p_vout, "crop", CropCallback, NULL );
222 223

    /* Monitor pixel aspect-ratio */
224
    var_Create( p_vout, "monitor-par", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
225 226

    /* Aspect-ratio object var */
227
    var_Create( p_vout, "aspect-ratio", VLC_VAR_STRING | VLC_VAR_ISCOMMAND |
228
                VLC_VAR_DOINHERIT );
229

Christoph Miebach's avatar
Christoph Miebach committed
230
    text.psz_string = _("Aspect ratio");
231 232
    var_Change( p_vout, "aspect-ratio", VLC_VAR_SETTEXT, &text, NULL );

233
    for( size_t i = 0; i < ARRAY_SIZE(p_aspect_ratio_values); i++ )
234
    {
235 236 237
        val.psz_string = (char*)p_aspect_ratio_values[i].psz_value;
        text.psz_string = _( p_aspect_ratio_values[i].psz_label );
        var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
238
    }
239 240

    /* Add custom aspect ratios */
241 242 243 244 245 246
    psz_buf = var_CreateGetNonEmptyString( p_vout, "custom-aspect-ratios" );
    if( psz_buf )
    {
        AddCustomRatios( p_vout, "aspect-ratio", psz_buf );
        free( psz_buf );
    }
247

248
    var_AddCallback( p_vout, "aspect-ratio", AspectCallback, NULL );
249

250
    /* Add a variable to indicate if the window should be on top of others */
251 252
    var_Create( p_vout, "video-on-top", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
                | VLC_VAR_ISCOMMAND );
253 254
    text.psz_string = _("Always on top");
    var_Change( p_vout, "video-on-top", VLC_VAR_SETTEXT, &text, NULL );
255
    var_AddCallback( p_vout, "video-on-top", AboveCallback, NULL );
256

257 258 259 260 261
    /* Add a variable to indicate if the window should be below all others */
    var_Create( p_vout, "video-wallpaper", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
    var_AddCallback( p_vout, "video-wallpaper", WallPaperCallback,
                     (void *)(uintptr_t)VOUT_WINDOW_STATE_BELOW );

262 263 264
    /* Add a variable to indicate whether we want window decoration or not */
    var_Create( p_vout, "video-deco", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );

265
    /* Add a fullscreen variable */
266 267
    var_Create( p_vout, "fullscreen",
                VLC_VAR_BOOL | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
268 269
    text.psz_string = _("Fullscreen");
    var_Change( p_vout, "fullscreen", VLC_VAR_SETTEXT, &text, NULL );
270
    var_AddCallback( p_vout, "fullscreen", FullscreenCallback, NULL );
271

272 273 274 275 276 277
    /* Add a snapshot variable */
    var_Create( p_vout, "video-snapshot", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
    text.psz_string = _("Snapshot");
    var_Change( p_vout, "video-snapshot", VLC_VAR_SETTEXT, &text, NULL );
    var_AddCallback( p_vout, "video-snapshot", SnapshotCallback, NULL );

278 279 280 281 282
    /* Add a video-filter variable */
    var_Create( p_vout, "video-filter",
                VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
    var_AddCallback( p_vout, "video-filter", VideoFilterCallback, NULL );

283 284
    /* Add a sub-source variable */
    var_Create( p_vout, "sub-source",
285
                VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
286
    var_AddCallback( p_vout, "sub-source", SubSourceCallback, NULL );
287

288 289 290 291 292
    /* Add a sub-filter variable */
    var_Create( p_vout, "sub-filter",
                VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
    var_AddCallback( p_vout, "sub-filter", SubFilterCallback, NULL );

293 294 295 296 297
    /* Add sub-margin variable */
    var_Create( p_vout, "sub-margin",
                VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
    var_AddCallback( p_vout, "sub-margin", SubMarginCallback, NULL );

298 299
    /* Mouse coordinates */
    var_Create( p_vout, "mouse-button-down", VLC_VAR_INTEGER );
300 301
    var_Create( p_vout, "mouse-moved", VLC_VAR_COORDS );
    var_Create( p_vout, "mouse-clicked", VLC_VAR_COORDS );
302

303 304 305
    /* Device orientation */
    var_Create( p_vout, "viewpoint-moved", VLC_VAR_ADDRESS );

306
    /* Viewpoint */
307
    var_Create( p_vout, "viewpoint", VLC_VAR_ADDRESS  );
308
    var_AddCallback( p_vout, "viewpoint", ViewpointCallback, NULL );
309
    var_Create( p_vout, "viewpoint-changeable", VLC_VAR_BOOL );
310

311 312 313 314 315 316 317 318 319 320
    vout_IntfReinit( p_vout );
}

void vout_IntfReinit( vout_thread_t *p_vout )
{
    var_TriggerCallback( p_vout, "zoom" );
    var_TriggerCallback( p_vout, "crop" );
    var_TriggerCallback( p_vout, "aspect-ratio" );

    var_TriggerCallback( p_vout, "video-on-top" );
321
    var_TriggerCallback( p_vout, "video-wallpaper" );
322 323 324 325 326

    var_TriggerCallback( p_vout, "video-filter" );
    var_TriggerCallback( p_vout, "sub-source" );
    var_TriggerCallback( p_vout, "sub-filter" );
    var_TriggerCallback( p_vout, "sub-margin" );
327 328
}

329 330 331
/*****************************************************************************
 * vout_Snapshot: generates a snapshot.
 *****************************************************************************/
332 333 334 335
/**
 * This function will inject a subpicture into the vout with the provided
 * picture
 */
336
static int VoutSnapshotPip( vout_thread_t *p_vout, picture_t *p_pic )
337
{
338 339
    subpicture_t *p_subpic = subpicture_NewFromPicture( VLC_OBJECT(p_vout),
                                                        p_pic, VLC_CODEC_YUVA );
340
    if( !p_subpic )
341
        return VLC_EGENERIC;
342

343
    /* FIXME SPU_DEFAULT_CHANNEL is not good (used by the text) but
344
     * hardcoded 0 doesn't seem right */
345 346
    p_subpic->i_channel = 0;
    p_subpic->i_start = mdate();
347
    p_subpic->i_stop  = p_subpic->i_start + 4000000;
348 349
    p_subpic->b_ephemer = true;
    p_subpic->b_fade = true;
350 351 352 353

    /* Reduce the picture to 1/4^2 of the screen */
    p_subpic->i_original_picture_width  *= 4;
    p_subpic->i_original_picture_height *= 4;
354

355
    vout_PutSubpicture( p_vout, p_subpic );
356 357
    return VLC_SUCCESS;
}
358 359 360 361 362 363 364

/**
 * This function will display the name and a PIP of the provided snapshot
 */
static void VoutOsdSnapshot( vout_thread_t *p_vout, picture_t *p_pic, const char *psz_filename )
{
    msg_Dbg( p_vout, "snapshot taken (%s)", psz_filename );
365
    vout_OSDMessage( p_vout, VOUT_SPU_CHANNEL_OSD, "%s", psz_filename );
366

367
    if( var_InheritBool( p_vout, "snapshot-preview" ) )
368
    {
369
        if( VoutSnapshotPip( p_vout, p_pic ) )
370
            msg_Warn( p_vout, "Failed to display snapshot" );
371
    }
372
}
373

374 375 376
/**
 * This function will handle a snapshot request
 */
377 378
static void VoutSaveSnapshot( vout_thread_t *p_vout )
{
379 380 381
    char *psz_path = var_InheritString( p_vout, "snapshot-path" );
    char *psz_format = var_InheritString( p_vout, "snapshot-format" );
    char *psz_prefix = var_InheritString( p_vout, "snapshot-prefix" );
382

383 384 385 386 387 388
    /* */
    picture_t *p_picture;
    block_t *p_image;

    /* 500ms timeout
     * XXX it will cause trouble with low fps video (< 2fps) */
389
    if( vout_GetSnapshot( p_vout, &p_image, &p_picture, NULL, psz_format, 500*1000 ) )
390
    {
391 392 393 394 395
        p_picture = NULL;
        p_image = NULL;
        goto exit;
    }

396
    if( !psz_path )
397
    {
398
        psz_path = vout_snapshot_GetDirectory();
399 400
        if( !psz_path )
        {
401 402
            msg_Err( p_vout, "no path specified for snapshots" );
            goto exit;
403
        }
404
    }
405

406 407
    vout_snapshot_save_cfg_t cfg;
    memset( &cfg, 0, sizeof(cfg) );
408
    cfg.is_sequential = var_InheritBool( p_vout, "snapshot-sequential" );
409 410 411 412 413
    cfg.sequence = var_GetInteger( p_vout, "snapshot-num" );
    cfg.path = psz_path;
    cfg.format = psz_format;
    cfg.prefix_fmt = psz_prefix;

414
    char *psz_filename;
415 416
    int  i_sequence;
    if (vout_snapshot_SaveImage( &psz_filename, &i_sequence,
417
                                 p_image, p_vout, &cfg ) )
418
        goto exit;
419 420
    if( cfg.is_sequential )
        var_SetInteger( p_vout, "snapshot-num", i_sequence + 1 );
421

422
    VoutOsdSnapshot( p_vout, p_picture, psz_filename );
423

424
    /* signal creation of a new snapshot file */
425
    var_SetString( p_vout->obj.libvlc, "snapshot-file", psz_filename );
426

427
    free( psz_filename );
428 429 430 431 432 433 434 435 436

exit:
    if( p_image )
        block_Release( p_image );
    if( p_picture )
        picture_Release( p_picture );
    free( psz_prefix );
    free( psz_format );
    free( psz_path );
437 438
}

439 440 441
/*****************************************************************************
 * Object variables callbacks
 *****************************************************************************/
442 443
static int CropCallback( vlc_object_t *object, char const *cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *data )
444
{
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
    vout_thread_t *vout = (vout_thread_t *)object;
    VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
    unsigned num, den;
    unsigned y, x;
    unsigned width, height;
    unsigned left, top, right, bottom;

    if (sscanf(newval.psz_string, "%u:%u", &num, &den) == 2) {
        vout_ControlChangeCropRatio(vout, num, den);
    } else if (sscanf(newval.psz_string, "%ux%u+%u+%u",
                      &width, &height, &x, &y) == 4) {
        vout_ControlChangeCropWindow(vout, x, y, width, height);
    } else if (sscanf(newval.psz_string, "%u+%u+%u+%u",
                    &left, &top, &right, &bottom) == 4) {
        vout_ControlChangeCropBorder(vout, left, top, right, bottom);
    } else if (*newval.psz_string == '\0') {
        vout_ControlChangeCropRatio(vout, 0, 0);
    } else {
        msg_Err(object, "Unknown crop format (%s)", newval.psz_string);
464 465 466 467
    }
    return VLC_SUCCESS;
}

468 469
static int CropBorderCallback(vlc_object_t *object, char const *cmd,
                              vlc_value_t oldval, vlc_value_t newval, void *data)
470
{
471
    char buf[4 * 21];
472

473 474 475 476 477 478 479 480
    snprintf(buf, sizeof (buf), "%"PRIu64"+%"PRIu64"+%"PRIu64"+%"PRIu64,
             var_GetInteger(object, "crop-left"),
             var_GetInteger(object, "crop-top"),
             var_GetInteger(object, "crop-right"),
             var_GetInteger(object, "crop-bottom"));
    var_SetString(object, "crop", buf);

    VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data); VLC_UNUSED(newval);
481 482
    return VLC_SUCCESS;
}
483

484 485 486 487 488 489 490 491
static int AspectCallback( vlc_object_t *object, char const *cmd,
                         vlc_value_t oldval, vlc_value_t newval, void *data )
{
    vout_thread_t *vout = (vout_thread_t *)object;
    VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
    unsigned num, den;

    if (sscanf(newval.psz_string, "%u:%u", &num, &den) == 2 &&
492
        (num != 0) == (den != 0))
493 494 495 496
        vout_ControlChangeSampleAspectRatio(vout, num, den);
    else if (*newval.psz_string == '\0')
        vout_ControlChangeSampleAspectRatio(vout, 0, 0);
    return VLC_SUCCESS;
497 498
}

499 500
static int AutoScaleCallback( vlc_object_t *obj, char const *name,
                              vlc_value_t prev, vlc_value_t cur, void *data )
501
{
502 503 504 505 506 507
    vout_thread_t *p_vout = (vout_thread_t *)obj;

    (void) name; (void) prev; (void) data;
    vout_ControlChangeDisplayFilled( p_vout, cur.b_bool );
    return VLC_SUCCESS;
}
508

509 510
static int ZoomCallback( vlc_object_t *obj, char const *name,
                         vlc_value_t prev, vlc_value_t cur, void *data )
511 512
{
    vout_thread_t *p_vout = (vout_thread_t *)obj;
513

514 515
    (void) name; (void) prev; (void) data;
    vout_ControlChangeZoom( p_vout, 1000 * cur.f_float, 1000 );
516
    return VLC_SUCCESS;
517 518
}

519 520
static int AboveCallback( vlc_object_t *obj, char const *name,
                          vlc_value_t prev, vlc_value_t cur, void *data )
521
{
522 523 524
    vout_ControlChangeWindowState( (vout_thread_t *)obj,
        cur.b_bool ? VOUT_WINDOW_STATE_ABOVE : VOUT_WINDOW_STATE_NORMAL );
    (void) name; (void) prev; (void) data;
525 526
    return VLC_SUCCESS;
}
527

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
static int WallPaperCallback( vlc_object_t *obj, char const *name,
                              vlc_value_t prev, vlc_value_t cur, void *data )
{
    vout_thread_t *vout = (vout_thread_t *)obj;

    if( cur.b_bool )
    {
        vout_ControlChangeWindowState( vout, VOUT_WINDOW_STATE_BELOW );
        vout_ControlChangeFullscreen( vout, true );
    }
    else
    {
        var_TriggerCallback( obj, "fullscreen" );
        var_TriggerCallback( obj, "video-on-top" );
    }
    (void) name; (void) prev; (void) data;
    return VLC_SUCCESS;
}

547 548 549 550
static int FullscreenCallback( vlc_object_t *p_this, char const *psz_cmd,
                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
    vout_thread_t *p_vout = (vout_thread_t *)p_this;
551
    (void)psz_cmd; (void)p_data;
552

553 554
    if( oldval.b_bool != newval.b_bool )
        vout_ControlChangeFullscreen( p_vout, newval.b_bool );
555 556
    return VLC_SUCCESS;
}
557 558 559 560

static int SnapshotCallback( vlc_object_t *p_this, char const *psz_cmd,
                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
561
    vout_thread_t *p_vout = (vout_thread_t *)p_this;
562 563
    VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
    VLC_UNUSED(newval); VLC_UNUSED(p_data);
564 565

    VoutSaveSnapshot( p_vout );
566 567
    return VLC_SUCCESS;
}
568

569 570 571 572 573 574 575 576 577 578
static int VideoFilterCallback( vlc_object_t *p_this, char const *psz_cmd,
                                vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
    vout_thread_t *p_vout = (vout_thread_t *)p_this;
    VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);

    vout_ControlChangeFilters( p_vout, newval.psz_string );
    return VLC_SUCCESS;
}

579
static int SubSourceCallback( vlc_object_t *p_this, char const *psz_cmd,
580 581 582 583 584
                              vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
    vout_thread_t *p_vout = (vout_thread_t *)p_this;
    VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);

585
    vout_ControlChangeSubSources( p_vout, newval.psz_string );
586 587 588
    return VLC_SUCCESS;
}

589 590 591 592 593 594 595 596 597 598
static int SubFilterCallback( vlc_object_t *p_this, char const *psz_cmd,
                              vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
    vout_thread_t *p_vout = (vout_thread_t *)p_this;
    VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);

    vout_ControlChangeSubFilters( p_vout, newval.psz_string );
    return VLC_SUCCESS;
}

599 600 601 602 603 604 605 606 607 608
static int SubMarginCallback( vlc_object_t *p_this, char const *psz_cmd,
                              vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
    vout_thread_t *p_vout = (vout_thread_t *)p_this;
    VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);

    vout_ControlChangeSubMargin( p_vout, newval.i_int );
    return VLC_SUCCESS;
}

609 610 611 612 613 614 615 616 617 618
static int ViewpointCallback( vlc_object_t *p_this, char const *psz_cmd,
                              vlc_value_t oldval, vlc_value_t newval, void *p_data)
{
    vout_thread_t *p_vout = (vout_thread_t *)p_this;
    VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);

    if( newval.p_address != NULL )
        vout_ControlChangeViewpoint( p_vout, newval.p_address );
    return VLC_SUCCESS;
}