00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <stdlib.h>
00028
00029 #include <vlc/vlc.h>
00030 #include <vlc/intf.h>
00031
00032 #include "vlc_video.h"
00033 #include "video_output.h"
00034 #include "vlc_image.h"
00035 #include "vlc_spu.h"
00036
00037
00038
00039
00040 static void InitWindowSize( vout_thread_t *, unsigned *, unsigned * );
00041
00042
00043 static int ZoomCallback( vlc_object_t *, char const *,
00044 vlc_value_t, vlc_value_t, void * );
00045 static int CropCallback( vlc_object_t *, char const *,
00046 vlc_value_t, vlc_value_t, void * );
00047 static int AspectCallback( vlc_object_t *, char const *,
00048 vlc_value_t, vlc_value_t, void * );
00049 static int OnTopCallback( vlc_object_t *, char const *,
00050 vlc_value_t, vlc_value_t, void * );
00051 static int FullscreenCallback( vlc_object_t *, char const *,
00052 vlc_value_t, vlc_value_t, void * );
00053 static int SnapshotCallback( vlc_object_t *, char const *,
00054 vlc_value_t, vlc_value_t, void * );
00055
00056
00057
00058
00059
00060
00061
00062
00063 void *vout_RequestWindow( vout_thread_t *p_vout,
00064 int *pi_x_hint, int *pi_y_hint,
00065 unsigned int *pi_width_hint,
00066 unsigned int *pi_height_hint )
00067 {
00068 intf_thread_t *p_intf = NULL;
00069 vlc_list_t *p_list;
00070 void *p_window;
00071 vlc_value_t val;
00072 int i;
00073
00074
00075 if( !var_Type( p_vout, "aspect-ratio" ) ) vout_IntfInit( p_vout );
00076
00077
00078 var_Get( p_vout, "video-x", &val );
00079 *pi_x_hint = val.i_int ;
00080 var_Get( p_vout, "video-y", &val );
00081 *pi_y_hint = val.i_int;
00082
00083 *pi_width_hint = p_vout->i_window_width;
00084 *pi_height_hint = p_vout->i_window_height;
00085
00086
00087 var_Get( p_vout->p_vlc, "drawable", &val );
00088 if( val.i_int ) return (void *)val.i_int;
00089
00090
00091 p_list = vlc_list_find( p_vout, VLC_OBJECT_INTF, FIND_ANYWHERE );
00092 if( !p_list ) return NULL;
00093
00094 for( i = 0; i < p_list->i_count; i++ )
00095 {
00096 p_intf = (intf_thread_t *)p_list->p_values[i].p_object;
00097 if( p_intf->b_block && p_intf->pf_request_window ) break;
00098 p_intf = NULL;
00099 }
00100
00101 if( !p_intf )
00102 {
00103 vlc_list_release( p_list );
00104 return NULL;
00105 }
00106
00107 vlc_object_yield( p_intf );
00108 vlc_list_release( p_list );
00109
00110 p_window = p_intf->pf_request_window( p_intf, p_vout, pi_x_hint, pi_y_hint,
00111 pi_width_hint, pi_height_hint );
00112
00113 if( !p_window ) vlc_object_release( p_intf );
00114 else p_vout->p_parent_intf = p_intf;
00115
00116 return p_window;
00117 }
00118
00119 void vout_ReleaseWindow( vout_thread_t *p_vout, void *p_window )
00120 {
00121 intf_thread_t *p_intf = p_vout->p_parent_intf;
00122
00123 if( !p_intf ) return;
00124
00125 vlc_mutex_lock( &p_intf->object_lock );
00126 if( p_intf->b_dead )
00127 {
00128 vlc_mutex_unlock( &p_intf->object_lock );
00129 return;
00130 }
00131
00132 if( !p_intf->pf_release_window )
00133 {
00134 msg_Err( p_vout, "no pf_release_window");
00135 vlc_mutex_unlock( &p_intf->object_lock );
00136 vlc_object_release( p_intf );
00137 return;
00138 }
00139
00140 p_intf->pf_release_window( p_intf, p_window );
00141
00142 p_vout->p_parent_intf = NULL;
00143 vlc_mutex_unlock( &p_intf->object_lock );
00144 vlc_object_release( p_intf );
00145 }
00146
00147 int vout_ControlWindow( vout_thread_t *p_vout, void *p_window,
00148 int i_query, va_list args )
00149 {
00150 intf_thread_t *p_intf = p_vout->p_parent_intf;
00151 int i_ret;
00152
00153 if( !p_intf ) return VLC_EGENERIC;
00154
00155 vlc_mutex_lock( &p_intf->object_lock );
00156 if( p_intf->b_dead )
00157 {
00158 vlc_mutex_unlock( &p_intf->object_lock );
00159 return VLC_EGENERIC;
00160 }
00161
00162 if( !p_intf->pf_control_window )
00163 {
00164 msg_Err( p_vout, "no pf_control_window");
00165 vlc_mutex_unlock( &p_intf->object_lock );
00166 return VLC_EGENERIC;
00167 }
00168
00169 i_ret = p_intf->pf_control_window( p_intf, p_window, i_query, args );
00170 vlc_mutex_unlock( &p_intf->object_lock );
00171 return i_ret;
00172 }
00173
00174
00175
00176
00177 void vout_IntfInit( vout_thread_t *p_vout )
00178 {
00179 vlc_value_t val, text, old_val;
00180 vlc_bool_t b_force_par = VLC_FALSE;
00181
00182
00183 var_Create( p_vout, "snapshot-path", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
00184 var_Create( p_vout, "snapshot-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
00185 var_Create( p_vout, "width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00186 var_Create( p_vout, "height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00187 var_Create( p_vout, "align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00188 var_Get( p_vout, "align", &val );
00189 p_vout->i_alignment = val.i_int;
00190
00191 var_Create( p_vout, "video-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00192 var_Create( p_vout, "video-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00193
00194
00195 var_Create( p_vout, "zoom", VLC_VAR_FLOAT | VLC_VAR_ISCOMMAND |
00196 VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT );
00197
00198 text.psz_string = _("Zoom");
00199 var_Change( p_vout, "zoom", VLC_VAR_SETTEXT, &text, NULL );
00200
00201 var_Get( p_vout, "zoom", &old_val );
00202 if( old_val.f_float == 0.25 ||
00203 old_val.f_float == 0.5 ||
00204 old_val.f_float == 1 ||
00205 old_val.f_float == 2 )
00206 {
00207 var_Change( p_vout, "zoom", VLC_VAR_DELCHOICE, &old_val, NULL );
00208 }
00209
00210 val.f_float = 0.25; text.psz_string = _("1:4 Quarter");
00211 var_Change( p_vout, "zoom", VLC_VAR_ADDCHOICE, &val, &text );
00212 val.f_float = 0.5; text.psz_string = _("1:2 Half");
00213 var_Change( p_vout, "zoom", VLC_VAR_ADDCHOICE, &val, &text );
00214 val.f_float = 1; text.psz_string = _("1:1 Original");
00215 var_Change( p_vout, "zoom", VLC_VAR_ADDCHOICE, &val, &text );
00216 val.f_float = 2; text.psz_string = _("2:1 Double");
00217 var_Change( p_vout, "zoom", VLC_VAR_ADDCHOICE, &val, &text );
00218
00219 var_Set( p_vout, "zoom", old_val );
00220
00221 var_AddCallback( p_vout, "zoom", ZoomCallback, NULL );
00222
00223
00224 var_Create( p_vout, "crop", VLC_VAR_STRING |
00225 VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT );
00226
00227 text.psz_string = _("Crop");
00228 var_Change( p_vout, "crop", VLC_VAR_SETTEXT, &text, NULL );
00229
00230 val.psz_string = "";
00231 var_Change( p_vout, "crop", VLC_VAR_DELCHOICE, &val, 0 );
00232 val.psz_string = ""; text.psz_string = _("Default");
00233 var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &text );
00234 val.psz_string = "001:1"; text.psz_string = _("1:1");
00235 var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &text );
00236 val.psz_string = "004:3"; text.psz_string = _("4:3");
00237 var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &text );
00238 val.psz_string = "16:9"; text.psz_string = _("16:9");
00239 var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &text );
00240 val.psz_string = "221:100"; text.psz_string = _("221:100");
00241 var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &text );
00242
00243 var_AddCallback( p_vout, "crop", CropCallback, NULL );
00244 var_Get( p_vout, "crop", &old_val );
00245 if( old_val.psz_string && *old_val.psz_string )
00246 var_Change( p_vout, "crop", VLC_VAR_TRIGGER_CALLBACKS, 0, 0 );
00247 if( old_val.psz_string ) free( old_val.psz_string );
00248
00249
00250 var_Create( p_vout, "monitor-par", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
00251 var_Get( p_vout, "monitor-par", &val );
00252 if( val.psz_string && *val.psz_string )
00253 {
00254 char *psz_parser = strchr( val.psz_string, ':' );
00255 unsigned int i_aspect_num = 0, i_aspect_den = 0;
00256 float i_aspect = 0;
00257 if( psz_parser )
00258 {
00259 i_aspect_num = strtol( val.psz_string, 0, 0 );
00260 i_aspect_den = strtol( ++psz_parser, 0, 0 );
00261 }
00262 else
00263 {
00264 i_aspect = atof( val.psz_string );
00265 vlc_ureduce( &i_aspect_num, &i_aspect_den,
00266 i_aspect *VOUT_ASPECT_FACTOR, VOUT_ASPECT_FACTOR, 0 );
00267 }
00268 if( !i_aspect_num || !i_aspect_den ) i_aspect_num = i_aspect_den = 1;
00269
00270 p_vout->i_par_num = i_aspect_num;
00271 p_vout->i_par_den = i_aspect_den;
00272
00273 vlc_ureduce( &p_vout->i_par_num, &p_vout->i_par_den,
00274 p_vout->i_par_num, p_vout->i_par_den, 0 );
00275
00276 msg_Dbg( p_vout, "monitor pixel aspect-ratio overriding: %i:%i",
00277 p_vout->i_par_num, p_vout->i_par_den );
00278 b_force_par = VLC_TRUE;
00279 }
00280 if( val.psz_string ) free( val.psz_string );
00281
00282
00283 var_Create( p_vout, "aspect-ratio", VLC_VAR_STRING |
00284 VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT );
00285
00286 text.psz_string = _("Aspect-ratio");
00287 var_Change( p_vout, "aspect-ratio", VLC_VAR_SETTEXT, &text, NULL );
00288
00289 val.psz_string = "";
00290 var_Change( p_vout, "aspect-ratio", VLC_VAR_DELCHOICE, &val, 0 );
00291 val.psz_string = ""; text.psz_string = _("Default");
00292 var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
00293 val.psz_string = "001:1"; text.psz_string = _("1:1");
00294 var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
00295 val.psz_string = "004:3"; text.psz_string = _("4:3");
00296 var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
00297 val.psz_string = "16:9"; text.psz_string = _("16:9");
00298 var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
00299 val.psz_string = "221:100"; text.psz_string = _("221:100");
00300 var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
00301
00302 var_AddCallback( p_vout, "aspect-ratio", AspectCallback, NULL );
00303 var_Get( p_vout, "aspect-ratio", &old_val );
00304 if( (old_val.psz_string && *old_val.psz_string) || b_force_par )
00305 var_Change( p_vout, "aspect-ratio", VLC_VAR_TRIGGER_CALLBACKS, 0, 0 );
00306 if( old_val.psz_string ) free( old_val.psz_string );
00307
00308
00309 InitWindowSize( p_vout, &p_vout->i_window_width,
00310 &p_vout->i_window_height );
00311
00312
00313 var_Create( p_vout, "video-on-top", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00314 text.psz_string = _("Always on top");
00315 var_Change( p_vout, "video-on-top", VLC_VAR_SETTEXT, &text, NULL );
00316 var_AddCallback( p_vout, "video-on-top", OnTopCallback, NULL );
00317
00318
00319 var_Create( p_vout, "video-deco", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00320
00321
00322 var_Create( p_vout, "fullscreen", VLC_VAR_BOOL );
00323 text.psz_string = _("Fullscreen");
00324 var_Change( p_vout, "fullscreen", VLC_VAR_SETTEXT, &text, NULL );
00325 var_Change( p_vout, "fullscreen", VLC_VAR_INHERITVALUE, &val, NULL );
00326 if( val.b_bool )
00327 {
00328
00329 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00330 }
00331 var_AddCallback( p_vout, "fullscreen", FullscreenCallback, NULL );
00332
00333
00334 var_Create( p_vout, "video-snapshot", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
00335 text.psz_string = _("Snapshot");
00336 var_Change( p_vout, "video-snapshot", VLC_VAR_SETTEXT, &text, NULL );
00337 var_AddCallback( p_vout, "video-snapshot", SnapshotCallback, NULL );
00338
00339
00340 var_Create( p_vout, "mouse-x", VLC_VAR_INTEGER );
00341 var_Create( p_vout, "mouse-y", VLC_VAR_INTEGER );
00342 var_Create( p_vout, "mouse-button-down", VLC_VAR_INTEGER );
00343 var_Create( p_vout, "mouse-moved", VLC_VAR_BOOL );
00344 var_Create( p_vout, "mouse-clicked", VLC_VAR_INTEGER );
00345
00346 var_Create( p_vout, "intf-change", VLC_VAR_BOOL );
00347 val.b_bool = VLC_TRUE;
00348 var_Set( p_vout, "intf-change", val );
00349 }
00350
00351
00352
00353
00354 int vout_Snapshot( vout_thread_t *p_vout, picture_t *p_pic )
00355 {
00356 image_handler_t *p_image = image_HandlerCreate( p_vout );
00357 video_format_t fmt_in = {0}, fmt_out = {0};
00358 char *psz_filename;
00359 subpicture_t *p_subpic;
00360 picture_t *p_pif;
00361 vlc_value_t val, format;
00362 int i_ret;
00363
00364 var_Get( p_vout, "snapshot-path", &val );
00365 if( val.psz_string && !*val.psz_string )
00366 {
00367 free( val.psz_string );
00368 val.psz_string = 0;
00369 }
00370
00371 #if defined(SYS_DARWIN) || defined(SYS_BEOS)
00372 if( !val.psz_string && p_vout->p_vlc->psz_homedir )
00373 {
00374 asprintf( &val.psz_string, "%s/Desktop",
00375 p_vout->p_vlc->psz_homedir );
00376 }
00377
00378 #elif defined(WIN32) && !defined(UNDER_CE)
00379 if( !val.psz_string && p_vout->p_vlc->psz_homedir )
00380 {
00381
00382
00383 char *p_mypicturesdir = NULL;
00384 typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
00385 LPSTR );
00386 #ifndef CSIDL_FLAG_CREATE
00387 # define CSIDL_FLAG_CREATE 0x8000
00388 #endif
00389 #ifndef CSIDL_MYPICTURES
00390 # define CSIDL_MYPICTURES 0x27
00391 #endif
00392 #ifndef SHGFP_TYPE_CURRENT
00393 # define SHGFP_TYPE_CURRENT 0
00394 #endif
00395
00396 HINSTANCE shfolder_dll;
00397 SHGETFOLDERPATH SHGetFolderPath ;
00398
00399
00400 if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL )
00401 {
00402 SHGetFolderPath = (void *)GetProcAddress( shfolder_dll,
00403 _T("SHGetFolderPathA") );
00404 if( SHGetFolderPath != NULL )
00405 {
00406 p_mypicturesdir = (char *)malloc( MAX_PATH );
00407 if( p_mypicturesdir )
00408 {
00409
00410 if( S_OK != SHGetFolderPath( NULL,
00411 CSIDL_MYPICTURES | CSIDL_FLAG_CREATE,
00412 NULL, SHGFP_TYPE_CURRENT,
00413 p_mypicturesdir ) )
00414 {
00415 free( p_mypicturesdir );
00416 p_mypicturesdir = NULL;
00417 }
00418 }
00419 }
00420 FreeLibrary( shfolder_dll );
00421 }
00422
00423 if( p_mypicturesdir == NULL )
00424 {
00425 asprintf( &val.psz_string, "%s/" CONFIG_DIR,
00426 p_vout->p_vlc->psz_homedir );
00427 }
00428 else
00429 {
00430 asprintf( &val.psz_string, p_mypicturesdir );
00431 free( p_mypicturesdir );
00432 }
00433 }
00434
00435 #else
00436 if( !val.psz_string && p_vout->p_vlc->psz_homedir )
00437 {
00438 asprintf( &val.psz_string, "%s/" CONFIG_DIR,
00439 p_vout->p_vlc->psz_homedir );
00440 }
00441 #endif
00442
00443 if( !val.psz_string )
00444 {
00445 msg_Err( p_vout, "no directory specified for snapshots" );
00446 return VLC_EGENERIC;
00447 }
00448 var_Get( p_vout, "snapshot-format", &format );
00449 if( !format.psz_string || !*format.psz_string )
00450 {
00451 if( format.psz_string ) free( format.psz_string );
00452 format.psz_string = strdup( "png" );
00453 }
00454
00455 asprintf( &psz_filename, "%s/vlcsnap-%u.%s", val.psz_string,
00456 (unsigned int)(p_pic->date / 100000) & 0xFFFFFF,
00457 format.psz_string );
00458 free( val.psz_string );
00459 free( format.psz_string );
00460
00461
00462 fmt_in = p_vout->fmt_in;
00463 fmt_out.i_sar_num = fmt_out.i_sar_den = 1;
00464 i_ret = image_WriteUrl( p_image, p_pic, &fmt_in, &fmt_out, psz_filename );
00465 if( i_ret != VLC_SUCCESS )
00466 {
00467 msg_Err( p_vout, "could not create snapshot %s", psz_filename );
00468 free( psz_filename );
00469 image_HandlerDelete( p_image );
00470 return VLC_EGENERIC;
00471 }
00472
00473 msg_Dbg( p_vout, "snapshot taken (%s)", psz_filename );
00474 free( psz_filename );
00475
00476
00477 memset( &fmt_out, 0, sizeof(fmt_out) );
00478 fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
00479 p_pif = image_Convert( p_image, p_pic, &fmt_in, &fmt_out );
00480 image_HandlerDelete( p_image );
00481 if( !p_pif ) return VLC_EGENERIC;
00482
00483 p_subpic = spu_CreateSubpicture( p_vout->p_spu );
00484 if( p_subpic == NULL )
00485 {
00486 p_pif->pf_release( p_pif );
00487 return VLC_EGENERIC;
00488 }
00489
00490 p_subpic->i_channel = 0;
00491 p_subpic->i_start = mdate();
00492 p_subpic->i_stop = mdate() + 4000000;
00493 p_subpic->b_ephemer = VLC_TRUE;
00494 p_subpic->b_fade = VLC_TRUE;
00495 p_subpic->i_original_picture_width = p_vout->render.i_width * 4;
00496 p_subpic->i_original_picture_height = p_vout->render.i_height * 4;
00497
00498 p_subpic->p_region = spu_CreateRegion( p_vout->p_spu, &fmt_out );
00499 vout_CopyPicture( p_image->p_parent, &p_subpic->p_region->picture, p_pif );
00500 p_pif->pf_release( p_pif );
00501
00502 spu_DisplaySubpicture( p_vout->p_spu, p_subpic );
00503
00504 return VLC_SUCCESS;
00505 }
00506
00507
00508
00509
00510 int vout_vaControlDefault( vout_thread_t *p_vout, int i_query, va_list args )
00511 {
00512 switch( i_query )
00513 {
00514 case VOUT_REPARENT:
00515 case VOUT_CLOSE:
00516 if( p_vout->p_parent_intf )
00517 {
00518 vlc_object_release( p_vout->p_parent_intf );
00519 p_vout->p_parent_intf = NULL;
00520 }
00521 return VLC_SUCCESS;
00522 break;
00523
00524 case VOUT_SNAPSHOT:
00525 p_vout->b_snapshot = VLC_TRUE;
00526 return VLC_SUCCESS;
00527 break;
00528
00529 default:
00530 msg_Dbg( p_vout, "control query not supported" );
00531 return VLC_EGENERIC;
00532 }
00533 }
00534
00535
00536
00537
00538
00539
00540
00541 static void InitWindowSize( vout_thread_t *p_vout, unsigned *pi_width,
00542 unsigned *pi_height )
00543 {
00544 vlc_value_t val;
00545 int i_width, i_height;
00546 uint64_t ll_zoom;
00547
00548 #define FP_FACTOR 1000
00549
00550 var_Get( p_vout, "width", &val );
00551 i_width = val.i_int;
00552 var_Get( p_vout, "height", &val );
00553 i_height = val.i_int;
00554 var_Get( p_vout, "zoom", &val );
00555 ll_zoom = (uint64_t)( FP_FACTOR * val.f_float );
00556
00557 if( i_width > 0 && i_height > 0)
00558 {
00559 *pi_width = (int)( i_width * ll_zoom / FP_FACTOR );
00560 *pi_height = (int)( i_height * ll_zoom / FP_FACTOR );
00561 goto initwsize_end;
00562 }
00563 else if( i_width > 0 )
00564 {
00565 *pi_width = (int)( i_width * ll_zoom / FP_FACTOR );
00566 *pi_height = (int)( p_vout->fmt_in.i_visible_height * ll_zoom *
00567 p_vout->fmt_in.i_sar_den * i_width / p_vout->fmt_in.i_sar_num /
00568 FP_FACTOR / p_vout->fmt_in.i_visible_width );
00569 goto initwsize_end;
00570 }
00571 else if( i_height > 0 )
00572 {
00573 *pi_height = (int)( i_height * ll_zoom / FP_FACTOR );
00574 *pi_width = (int)( p_vout->fmt_in.i_visible_width * ll_zoom *
00575 p_vout->fmt_in.i_sar_num * i_height / p_vout->fmt_in.i_sar_den /
00576 FP_FACTOR / p_vout->fmt_in.i_visible_height );
00577 goto initwsize_end;
00578 }
00579
00580 if( p_vout->fmt_in.i_sar_num >= p_vout->fmt_in.i_sar_den )
00581 {
00582 *pi_width = (int)( p_vout->fmt_in.i_visible_width * ll_zoom *
00583 p_vout->fmt_in.i_sar_num / p_vout->fmt_in.i_sar_den / FP_FACTOR );
00584 *pi_height = (int)( p_vout->fmt_in.i_visible_height * ll_zoom
00585 / FP_FACTOR );
00586 }
00587 else
00588 {
00589 *pi_width = (int)( p_vout->fmt_in.i_visible_width * ll_zoom
00590 / FP_FACTOR );
00591 *pi_height = (int)( p_vout->fmt_in.i_visible_height * ll_zoom *
00592 p_vout->fmt_in.i_sar_den / p_vout->fmt_in.i_sar_num / FP_FACTOR );
00593 }
00594
00595 initwsize_end:
00596 msg_Dbg( p_vout, "window size: %dx%d", p_vout->i_window_width,
00597 p_vout->i_window_height );
00598
00599 #undef FP_FACTOR
00600 }
00601
00602
00603
00604
00605 static int ZoomCallback( vlc_object_t *p_this, char const *psz_cmd,
00606 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00607 {
00608 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00609 InitWindowSize( p_vout, &p_vout->i_window_width,
00610 &p_vout->i_window_height );
00611 vout_Control( p_vout, VOUT_SET_ZOOM );
00612 return VLC_SUCCESS;
00613 }
00614
00615 static int CropCallback( vlc_object_t *p_this, char const *psz_cmd,
00616 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00617 {
00618 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00619 int64_t i_aspect_num, i_aspect_den;
00620 unsigned int i_width, i_height;
00621
00622 char *psz_end, *psz_parser = strchr( newval.psz_string, ':' );
00623
00624
00625 p_vout->fmt_in.i_x_offset = p_vout->fmt_render.i_x_offset;
00626 p_vout->fmt_in.i_visible_width = p_vout->fmt_render.i_visible_width;
00627 p_vout->fmt_in.i_y_offset = p_vout->fmt_render.i_y_offset;
00628 p_vout->fmt_in.i_visible_height = p_vout->fmt_render.i_visible_height;
00629
00630 if( !psz_parser ) goto crop_end;
00631
00632 i_aspect_num = strtol( newval.psz_string, &psz_end, 0 );
00633 if( psz_end == newval.psz_string || !i_aspect_num ) goto crop_end;
00634
00635 i_aspect_den = strtol( ++psz_parser, &psz_end, 0 );
00636 if( psz_end == psz_parser || !i_aspect_den ) goto crop_end;
00637
00638 i_width = p_vout->fmt_in.i_sar_den * p_vout->fmt_render.i_visible_height *
00639 i_aspect_num / i_aspect_den / p_vout->fmt_in.i_sar_num;
00640 i_height = p_vout->fmt_render.i_visible_width * p_vout->fmt_in.i_sar_num *
00641 i_aspect_den / i_aspect_num / p_vout->fmt_in.i_sar_den;
00642
00643 if( i_width < p_vout->fmt_render.i_visible_width )
00644 {
00645 p_vout->fmt_in.i_x_offset = p_vout->fmt_render.i_x_offset +
00646 (p_vout->fmt_render.i_visible_width - i_width) / 2;
00647 p_vout->fmt_in.i_visible_width = i_width;
00648 }
00649 else
00650 {
00651 p_vout->fmt_in.i_y_offset = p_vout->fmt_render.i_y_offset +
00652 (p_vout->fmt_render.i_visible_height - i_height) / 2;
00653 p_vout->fmt_in.i_visible_height = i_height;
00654 }
00655
00656 crop_end:
00657 InitWindowSize( p_vout, &p_vout->i_window_width,
00658 &p_vout->i_window_height );
00659
00660 p_vout->i_changes |= VOUT_CROP_CHANGE;
00661
00662 msg_Dbg( p_vout, "cropping picture %ix%i to %i,%i,%ix%i",
00663 p_vout->fmt_in.i_width, p_vout->fmt_in.i_height,
00664 p_vout->fmt_in.i_x_offset, p_vout->fmt_in.i_y_offset,
00665 p_vout->fmt_in.i_visible_width,
00666 p_vout->fmt_in.i_visible_height );
00667
00668 return VLC_SUCCESS;
00669 }
00670
00671 static int AspectCallback( vlc_object_t *p_this, char const *psz_cmd,
00672 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00673 {
00674 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00675 unsigned int i_aspect_num, i_aspect_den, i_sar_num, i_sar_den;
00676 vlc_value_t val;
00677
00678 char *psz_end, *psz_parser = strchr( newval.psz_string, ':' );
00679
00680
00681 p_vout->fmt_in.i_sar_num = p_vout->fmt_render.i_sar_num;
00682 p_vout->fmt_in.i_sar_den = p_vout->fmt_render.i_sar_den;
00683 p_vout->fmt_in.i_aspect = p_vout->fmt_render.i_aspect;
00684 p_vout->render.i_aspect = p_vout->fmt_render.i_aspect;
00685
00686 if( !psz_parser ) goto aspect_end;
00687
00688 i_aspect_num = strtol( newval.psz_string, &psz_end, 0 );
00689 if( psz_end == newval.psz_string || !i_aspect_num ) goto aspect_end;
00690
00691 i_aspect_den = strtol( ++psz_parser, &psz_end, 0 );
00692 if( psz_end == psz_parser || !i_aspect_den ) goto aspect_end;
00693
00694 i_sar_num = i_aspect_num * p_vout->fmt_render.i_visible_height;
00695 i_sar_den = i_aspect_den * p_vout->fmt_render.i_visible_width;
00696 vlc_ureduce( &i_sar_num, &i_sar_den, i_sar_num, i_sar_den, 0 );
00697 p_vout->fmt_in.i_sar_num = i_sar_num;
00698 p_vout->fmt_in.i_sar_den = i_sar_den;
00699 p_vout->fmt_in.i_aspect = i_aspect_num * VOUT_ASPECT_FACTOR / i_aspect_den;
00700 p_vout->render.i_aspect = p_vout->fmt_in.i_aspect;
00701
00702 aspect_end:
00703 if( p_vout->i_par_num && p_vout->i_par_den )
00704 {
00705 p_vout->fmt_in.i_sar_num *= p_vout->i_par_den;
00706 p_vout->fmt_in.i_sar_den *= p_vout->i_par_num;
00707 p_vout->fmt_in.i_aspect = p_vout->fmt_in.i_aspect *
00708 p_vout->i_par_den / p_vout->i_par_num;
00709 p_vout->render.i_aspect = p_vout->fmt_in.i_aspect;
00710 }
00711
00712 p_vout->i_changes |= VOUT_ASPECT_CHANGE;
00713
00714 vlc_ureduce( &i_aspect_num, &i_aspect_den,
00715 p_vout->fmt_in.i_aspect, VOUT_ASPECT_FACTOR, 0 );
00716 msg_Dbg( p_vout, "new aspect-ratio %i:%i, sample aspect-ratio %i:%i",
00717 i_aspect_num, i_aspect_den,
00718 p_vout->fmt_in.i_sar_num, p_vout->fmt_in.i_sar_den );
00719
00720 var_Get( p_vout, "crop", &val );
00721 return CropCallback( p_this, 0, val, val, 0 );
00722
00723 return VLC_SUCCESS;
00724 }
00725
00726 static int OnTopCallback( vlc_object_t *p_this, char const *psz_cmd,
00727 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00728 {
00729 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00730 playlist_t *p_playlist;
00731 vout_Control( p_vout, VOUT_SET_STAY_ON_TOP, newval.b_bool );
00732
00733 p_playlist = (playlist_t *)vlc_object_find( p_this, VLC_OBJECT_PLAYLIST,
00734 FIND_PARENT );
00735 if( p_playlist )
00736 {
00737
00738 var_Create( p_playlist, "video-on-top", VLC_VAR_BOOL );
00739 var_Set( p_playlist, "video-on-top", newval );
00740
00741 vlc_object_release( p_playlist );
00742 }
00743 return VLC_SUCCESS;
00744 }
00745
00746 static int FullscreenCallback( vlc_object_t *p_this, char const *psz_cmd,
00747 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00748 {
00749 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00750 playlist_t *p_playlist;
00751 vlc_value_t val;
00752
00753 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00754
00755 p_playlist = (playlist_t *)vlc_object_find( p_this, VLC_OBJECT_PLAYLIST,
00756 FIND_PARENT );
00757 if( p_playlist )
00758 {
00759
00760 var_Create( p_playlist, "fullscreen", VLC_VAR_BOOL );
00761 var_Set( p_playlist, "fullscreen", newval );
00762
00763 vlc_object_release( p_playlist );
00764 }
00765
00766
00767 var_Get( p_vout, "video-on-top", &val );
00768 if( newval.b_bool && val.b_bool )
00769 {
00770 val.b_bool = VLC_FALSE;
00771 vout_Control( p_vout, VOUT_SET_STAY_ON_TOP, val.b_bool );
00772 }
00773 else if( !newval.b_bool && val.b_bool )
00774 {
00775 vout_Control( p_vout, VOUT_SET_STAY_ON_TOP, val.b_bool );
00776 }
00777
00778 val.b_bool = VLC_TRUE;
00779 var_Set( p_vout, "intf-change", val );
00780 return VLC_SUCCESS;
00781 }
00782
00783 static int SnapshotCallback( vlc_object_t *p_this, char const *psz_cmd,
00784 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00785 {
00786 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00787 vout_Control( p_vout, VOUT_SNAPSHOT );
00788 return VLC_SUCCESS;
00789 }