81
77
static int TitlePositionCallback( vlc_object_t *, char const *,
82
78
vlc_value_t, vlc_value_t, void * );
85
* Creates a video output window.
86
* On Unix systems, this is an X11 drawable (handle).
87
* On Windows, this is a Win32 window (handle).
88
* Video output plugins are supposed to called this function and display the
89
* video within the resulting window, while in windowed mode.
91
* @param p_vout video output thread to create a window for
92
* @param psz_cap VLC module capability (window system type)
93
* @param pi_x_hint pointer to store the recommended horizontal position [OUT]
94
* @param pi_y_hint pointer to store the recommended vertical position [OUT]
95
* @param pi_width_hint pointer to store the recommended width [OUT]
96
* @param pi_height_hint pointer to store the recommended height [OUT]
98
* @return a vout_window_t object, or NULL in case of failure.
99
* The window is released with vout_ReleaseWindow().
101
vout_window_t *vout_RequestWindow( vout_thread_t *p_vout, const char *psz_cap,
102
int *pi_x_hint, int *pi_y_hint,
103
unsigned int *pi_width_hint,
104
unsigned int *pi_height_hint )
106
/* Get requested coordinates */
107
*pi_x_hint = var_GetInteger( p_vout, "video-x" );
108
*pi_y_hint = var_GetInteger( p_vout, "video-y" );
110
*pi_width_hint = p_vout->i_window_width;
111
*pi_height_hint = p_vout->i_window_height;
113
vout_window_t *wnd = vlc_custom_create (VLC_OBJECT(p_vout), sizeof (*wnd),
114
VLC_OBJECT_GENERIC, "window");
119
wnd->width = *pi_width_hint;
120
wnd->height = *pi_height_hint;
121
wnd->pos_x = *pi_x_hint;
122
wnd->pos_y = *pi_y_hint;
123
vlc_object_attach (wnd, p_vout);
125
wnd->module = module_need (wnd, psz_cap, NULL, false);
126
if (wnd->module == NULL)
128
msg_Dbg (wnd, "no \"%s\" window provider available", psz_cap);
129
vlc_object_release (wnd);
132
*pi_width_hint = wnd->width;
133
*pi_height_hint = wnd->height;
134
*pi_x_hint = wnd->pos_x;
135
*pi_y_hint = wnd->pos_y;
140
* Releases a window handle obtained with vout_RequestWindow().
141
* @param p_vout video output thread that allocated the window
142
* (if this is NULL; this fnction is a no-op).
144
void vout_ReleaseWindow( vout_window_t *wnd )
149
assert (wnd->module);
150
module_unneed (wnd, wnd->module);
152
vlc_object_release (wnd);
155
int vout_ControlWindow( vout_window_t *wnd, int i_query, va_list args )
160
assert (wnd->control);
161
return wnd->control (wnd, i_query, args);
164
80
/*****************************************************************************
165
81
* vout_IntfInit: called during the vout creation to initialise misc things.
166
82
*****************************************************************************/
442
365
var_AddCallback( p_vout, "video-snapshot", SnapshotCallback, NULL );
444
367
/* Mouse coordinates */
445
var_Create( p_vout, "mouse-x", VLC_VAR_INTEGER );
446
var_Create( p_vout, "mouse-y", VLC_VAR_INTEGER );
447
368
var_Create( p_vout, "mouse-button-down", VLC_VAR_INTEGER );
448
var_Create( p_vout, "mouse-moved", VLC_VAR_BOOL );
449
var_Create( p_vout, "mouse-clicked", VLC_VAR_BOOL );
369
var_Create( p_vout, "mouse-moved", VLC_VAR_COORDS );
370
var_Create( p_vout, "mouse-clicked", VLC_VAR_COORDS );
371
var_Create( p_vout, "mouse-object", VLC_VAR_BOOL );
451
373
var_Create( p_vout, "intf-change", VLC_VAR_BOOL );
452
374
var_SetBool( p_vout, "intf-change", true );
462
384
static int VoutSnapshotPip( vout_thread_t *p_vout, picture_t *p_pic )
464
video_format_t fmt_in = p_pic->format;
465
video_format_t fmt_out;
467
subpicture_t *p_subpic;
470
memset( &fmt_out, 0, sizeof(fmt_out) );
472
fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
475
image_handler_t *p_image = image_HandlerCreate( p_vout );
479
p_pip = image_Convert( p_image, p_pic, &fmt_in, &fmt_out );
481
image_HandlerDelete( p_image );
486
p_subpic = subpicture_New();
386
subpicture_t *p_subpic = subpicture_NewFromPicture( VLC_OBJECT(p_vout),
387
p_pic, VLC_CODEC_YUVA );
489
picture_Release( p_pip );
391
/* FIXME DEFAULT_CHAN is not good (used by the text) but
392
* hardcoded 0 doesn't seem right */
493
393
p_subpic->i_channel = 0;
494
394
p_subpic->i_start = mdate();
495
p_subpic->i_stop = mdate() + 4000000;
395
p_subpic->i_stop = p_subpic->i_start + 4000000;
496
396
p_subpic->b_ephemer = true;
497
397
p_subpic->b_fade = true;
498
p_subpic->i_original_picture_width = fmt_out.i_width * 4;
499
p_subpic->i_original_picture_height = fmt_out.i_height * 4;
500
fmt_out.i_aspect = 0;
502
fmt_out.i_sar_den = 0;
504
p_subpic->p_region = subpicture_region_New( &fmt_out );
505
if( p_subpic->p_region )
507
picture_Release( p_subpic->p_region->p_picture );
508
p_subpic->p_region->p_picture = p_pip;
512
picture_Release( p_pip );
399
/* Reduce the picture to 1/4^2 of the screen */
400
p_subpic->i_original_picture_width *= 4;
401
p_subpic->i_original_picture_height *= 4;
515
403
spu_DisplaySubpicture( p_vout->p_spu, p_subpic );
516
404
return VLC_SUCCESS;
519
* This function will return the default directory used for snapshots
521
static char *VoutSnapshotGetDefaultDirectory( void )
523
char *psz_path = NULL;
524
#if defined(__APPLE__) || defined(SYS_BEOS)
526
if( asprintf( &psz_path, "%s/Desktop",
527
config_GetHomeDir() ) == -1 )
530
#elif defined(WIN32) && !defined(UNDER_CE)
532
/* Get the My Pictures folder path */
533
char *p_mypicturesdir = NULL;
534
typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
536
#ifndef CSIDL_FLAG_CREATE
537
# define CSIDL_FLAG_CREATE 0x8000
539
#ifndef CSIDL_MYPICTURES
540
# define CSIDL_MYPICTURES 0x27
542
#ifndef SHGFP_TYPE_CURRENT
543
# define SHGFP_TYPE_CURRENT 0
546
HINSTANCE shfolder_dll;
547
SHGETFOLDERPATH SHGetFolderPath ;
549
/* load the shfolder dll to retrieve SHGetFolderPath */
550
if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL )
552
wchar_t wdir[PATH_MAX];
553
SHGetFolderPath = (void *)GetProcAddress( shfolder_dll,
554
_T("SHGetFolderPathW") );
555
if ((SHGetFolderPath != NULL )
556
&& SUCCEEDED (SHGetFolderPath (NULL,
557
CSIDL_MYPICTURES | CSIDL_FLAG_CREATE,
558
NULL, SHGFP_TYPE_CURRENT,
560
p_mypicturesdir = FromWide (wdir);
562
FreeLibrary( shfolder_dll );
565
if( p_mypicturesdir == NULL )
566
psz_path = strdup( config_GetHomeDir() );
568
psz_path = p_mypicturesdir;
572
/* XXX: This saves in the data directory. Shouldn't we try saving
573
* to psz_homedir/Desktop or something nicer ? */
574
char *psz_datadir = config_GetUserDataDir();
577
if( asprintf( &psz_path, "%s", psz_datadir ) == -1 )
587
* This function will save a video snapshot to a file
589
static int VoutWriteSnapshot( vout_thread_t *p_vout, char **ppsz_filename,
590
const block_t *p_image,
591
const char *psz_path,
592
const char *psz_format,
593
const char *psz_prefix_fmt )
597
DIR *p_path = utf8_opendir( psz_path );
600
/* The use specified a directory path */
604
char *psz_prefix = NULL;
606
psz_prefix = str_format( p_vout, psz_prefix_fmt );
609
psz_prefix = strdup( "vlcsnap-" );
614
if( var_GetBool( p_vout, "snapshot-sequential" ) )
616
int i_num = var_GetInteger( p_vout, "snapshot-num" );
621
if( asprintf( &psz_filename, "%s" DIR_SEP "%s%05d.%s",
622
psz_path, psz_prefix, i_num++, psz_format ) < 0 )
627
if( utf8_stat( psz_filename, &st ) )
629
free( psz_filename );
632
var_SetInteger( p_vout, "snapshot-num", i_num );
637
time_t lcurtime = time( NULL ) ;
639
if( !localtime_r( &lcurtime, &curtime ) )
641
const unsigned int i_id = (p_image->i_pts / 100000) & 0xFFFFFF;
643
msg_Warn( p_vout, "failed to get current time. Falling back to legacy snapshot naming" );
645
if( asprintf( &psz_filename, "%s" DIR_SEP "%s%u.%s",
646
psz_path, psz_prefix, i_id, psz_format ) < 0 )
651
/* suffix with the last decimal digit in 10s of seconds resolution
653
const int i_id = (p_image->i_pts / (100*1000)) & 0xFF;
654
char psz_curtime[128];
656
if( !strftime( psz_curtime, sizeof(psz_curtime), "%Y-%m-%d-%Hh%Mm%Ss", &curtime ) )
657
strcpy( psz_curtime, "error" );
659
if( asprintf( &psz_filename, "%s" DIR_SEP "%s%s%1u.%s",
660
psz_path, psz_prefix, psz_curtime, i_id, psz_format ) < 0 )
668
/* The user specified a full path name (including file name) */
669
psz_filename = str_format( p_vout, psz_path );
670
path_sanitize( psz_filename );
676
/* Save the snapshot */
677
FILE *p_file = utf8_fopen( psz_filename, "wb" );
680
msg_Err( p_vout, "Failed to open '%s'", psz_filename );
681
free( psz_filename );
684
if( fwrite( p_image->p_buffer, p_image->i_buffer, 1, p_file ) != 1 )
686
msg_Err( p_vout, "Failed to write to '%s'", psz_filename );
688
free( psz_filename );
695
*ppsz_filename = psz_filename;
697
free( psz_filename );
702
msg_Err( p_vout, "could not save snapshot" );
707
408
* This function will display the name and a PIP of the provided snapshot
492
vout_snapshot_save_cfg_t cfg;
493
memset( &cfg, 0, sizeof(cfg) );
494
cfg.is_sequential = var_GetBool( p_vout, "snapshot-sequential" );
495
cfg.sequence = var_GetInteger( p_vout, "snapshot-num" );
497
cfg.format = psz_format;
498
cfg.prefix_fmt = psz_prefix;
810
500
char *psz_filename;
811
if( VoutWriteSnapshot( p_vout, &psz_filename,
813
psz_path, psz_format, psz_prefix ) )
502
if (vout_snapshot_SaveImage( &psz_filename, &i_sequence,
503
p_image, VLC_OBJECT(p_vout), &cfg ) )
505
if( cfg.is_sequential )
506
var_SetInteger( p_vout, "snapshot-num", i_sequence + 1 );
816
508
VoutOsdSnapshot( p_vout, p_picture, psz_filename );
818
/* Generate a media player event - Right now just trigger a global libvlc var
819
CHECK: Could not find a more local object. The goal is to communicate
820
vout_thread with libvlc_media_player or its input_thread */
821
var_SetString( p_vout->p_libvlc, "vout-snapshottaken", psz_filename );
510
/* signal creation of a new snapshot file */
511
var_SetString( p_vout->p_libvlc, "snapshot-file", psz_filename );
822
513
free( psz_filename );
836
527
*****************************************************************************/
838
void vout_EnableFilter( vout_thread_t *p_vout, char *psz_name,
529
void vout_EnableFilter( vout_thread_t *p_vout, const char *psz_name,
839
530
bool b_add, bool b_setconfig )
841
532
char *psz_parser;
842
char *psz_string = config_GetPsz( p_vout, "vout-filter" );
534
const char *psz_filter_type;
536
/* FIXME temporary hack */
537
const char *psz_module_name = psz_name;
538
if( !strcmp( psz_name, "magnify" ) ||
539
!strcmp( psz_name, "puzzle" ) ||
540
!strcmp( psz_name, "logo" ) ||
541
!strcmp( psz_name, "wall" ) ||
542
!strcmp( psz_name, "clone" ) )
543
psz_module_name = "video_filter_wrapper";
545
module_t *p_obj = module_find( psz_module_name );
548
msg_Err( p_vout, "Unable to find filter module \"%s\".", psz_name );
552
if( module_provides( p_obj, "video filter" ) )
554
psz_filter_type = "vout-filter";
556
else if( module_provides( p_obj, "video filter2" ) )
558
psz_filter_type = "video-filter";
560
else if( module_provides( p_obj, "sub filter" ) )
562
psz_filter_type = "sub-filter";
566
module_release( p_obj );
567
msg_Err( p_vout, "Unknown video filter type." );
570
module_release( p_obj );
572
if( !strcmp( psz_filter_type, "sub-filter") )
573
psz_string = var_GetString( vout_GetSpu( p_vout ), psz_filter_type );
575
psz_string = var_GetString( p_vout, psz_filter_type );
844
577
/* Todo : Use some generic chain manipulation functions */
845
578
if( !psz_string ) psz_string = strdup("");
1166
907
vlc_ureduce( &i_sar_num, &i_sar_den, i_sar_num, i_sar_den, 0 );
1167
908
p_vout->fmt_in.i_sar_num = i_sar_num;
1168
909
p_vout->fmt_in.i_sar_den = i_sar_den;
1169
p_vout->fmt_in.i_aspect = i_aspect_num * VOUT_ASPECT_FACTOR / i_aspect_den;
1170
p_vout->render.i_aspect = p_vout->fmt_in.i_aspect;
910
p_vout->render.i_aspect = i_aspect_num * VOUT_ASPECT_FACTOR / i_aspect_den;
1173
913
if( p_vout->p->i_par_num && p_vout->p->i_par_den )
1175
915
p_vout->fmt_in.i_sar_num *= p_vout->p->i_par_den;
1176
916
p_vout->fmt_in.i_sar_den *= p_vout->p->i_par_num;
1177
p_vout->fmt_in.i_aspect = p_vout->fmt_in.i_aspect *
1178
p_vout->p->i_par_den / p_vout->p->i_par_num;
1179
p_vout->render.i_aspect = p_vout->fmt_in.i_aspect;
917
p_vout->render.i_aspect = (int64_t)p_vout->fmt_in.i_sar_num *
918
p_vout->fmt_in.i_width *
920
p_vout->fmt_in.i_sar_den /
921
p_vout->fmt_in.i_height;
1182
924
p_vout->i_changes |= VOUT_ASPECT_CHANGE;
1184
vlc_ureduce( &i_aspect_num, &i_aspect_den,
1185
p_vout->fmt_in.i_aspect, VOUT_ASPECT_FACTOR, 0 );
1186
926
msg_Dbg( p_vout, "new aspect-ratio %i:%i, sample aspect-ratio %i:%i",
1187
i_aspect_num, i_aspect_den,
927
p_vout->fmt_in.i_sar_num * p_vout->fmt_in.i_width,
928
p_vout->fmt_in.i_sar_den * p_vout->fmt_in.i_height,
1188
929
p_vout->fmt_in.i_sar_num, p_vout->fmt_in.i_sar_den );
1190
931
if( var_Get( p_vout, "crop", &val ) )