00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdlib.h>
00025 #include <vlc/vlc.h>
00026 #include <vlc/input.h>
00027
00028 #include "input_internal.h"
00029 #include "vlc_playlist.h"
00030
00031
00032 static void UpdateBookmarksOption( input_thread_t * );
00033 static void NotifyPlaylist( input_thread_t * );
00034
00035
00036
00037
00044 int input_Control( input_thread_t *p_input, int i_query, ... )
00045 {
00046 va_list args;
00047 int i_result;
00048
00049 va_start( args, i_query );
00050 i_result = input_vaControl( p_input, i_query, args );
00051 va_end( args );
00052
00053 return i_result;
00054 }
00055
00056 int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
00057 {
00058 seekpoint_t *p_bkmk, ***ppp_bkmk;
00059 int i_bkmk = 0;
00060 int *pi_bkmk;
00061
00062 int i_int, *pi_int;
00063 double f, *pf;
00064 int64_t i_64, *pi_64;
00065
00066 char *psz;
00067 vlc_value_t val;
00068
00069 switch( i_query )
00070 {
00071 case INPUT_GET_POSITION:
00072 pf = (double*)va_arg( args, double * );
00073 *pf = var_GetFloat( p_input, "position" );
00074 return VLC_SUCCESS;
00075
00076 case INPUT_SET_POSITION:
00077 f = (double)va_arg( args, double );
00078 return var_SetFloat( p_input, "position", f );
00079
00080 case INPUT_GET_LENGTH:
00081 pi_64 = (int64_t*)va_arg( args, int64_t * );
00082 *pi_64 = var_GetTime( p_input, "length" );
00083 return VLC_SUCCESS;
00084
00085 case INPUT_GET_TIME:
00086 pi_64 = (int64_t*)va_arg( args, int64_t * );
00087 *pi_64 = var_GetTime( p_input, "time" );
00088 return VLC_SUCCESS;
00089
00090 case INPUT_SET_TIME:
00091 i_64 = (int64_t)va_arg( args, int64_t );
00092 return var_SetTime( p_input, "time", i_64 );
00093
00094 case INPUT_GET_RATE:
00095 pi_int = (int*)va_arg( args, int * );
00096 *pi_int = var_GetInteger( p_input, "rate" );
00097 return VLC_SUCCESS;
00098
00099 case INPUT_SET_RATE:
00100 i_int = (int)va_arg( args, int );
00101 return var_SetInteger( p_input, "rate", i_int );
00102
00103 case INPUT_GET_STATE:
00104 pi_int = (int*)va_arg( args, int * );
00105 *pi_int = var_GetInteger( p_input, "state" );
00106 return VLC_SUCCESS;
00107
00108 case INPUT_SET_STATE:
00109 i_int = (int)va_arg( args, int );
00110 return var_SetInteger( p_input, "state", i_int );
00111
00112 case INPUT_GET_AUDIO_DELAY:
00113 pi_64 = (int64_t*)va_arg( args, int64_t * );
00114 *pi_64 = var_GetTime( p_input, "audio-delay" );
00115 return VLC_SUCCESS;
00116
00117 case INPUT_GET_SPU_DELAY:
00118 pi_64 = (int64_t*)va_arg( args, int64_t * );
00119 *pi_64 = var_GetTime( p_input, "spu-delay" );
00120 return VLC_SUCCESS;
00121
00122 case INPUT_SET_AUDIO_DELAY:
00123 i_64 = (int64_t)va_arg( args, int64_t );
00124 return var_SetTime( p_input, "audio-delay", i_64 );
00125
00126 case INPUT_SET_SPU_DELAY:
00127 i_64 = (int64_t)va_arg( args, int64_t );
00128 return var_SetTime( p_input, "spu-delay", i_64 );
00129
00130 case INPUT_ADD_INFO:
00131 {
00132
00133
00134 char *psz_cat = (char *)va_arg( args, char * );
00135 char *psz_name = (char *)va_arg( args, char * );
00136 char *psz_format = (char *)va_arg( args, char * );
00137
00138 info_category_t *p_cat;
00139 info_t *p_info;
00140 int i;
00141
00142 vlc_mutex_lock( &p_input->input.p_item->lock );
00143 for( i = 0; i < p_input->input.p_item->i_categories; i++ )
00144 {
00145 if( !strcmp( p_input->input.p_item->pp_categories[i]->psz_name,
00146 psz_cat ) ) break;
00147 }
00148
00149 if( i == p_input->input.p_item->i_categories )
00150 {
00151 p_cat = malloc( sizeof( info_category_t ) );
00152 if( !p_cat )
00153 {
00154 vlc_mutex_lock( &p_input->input.p_item->lock );
00155 return VLC_EGENERIC;
00156 }
00157 p_cat->psz_name = strdup( psz_cat );
00158 p_cat->i_infos = 0;
00159 p_cat->pp_infos = NULL;
00160 INSERT_ELEM( p_input->input.p_item->pp_categories,
00161 p_input->input.p_item->i_categories,
00162 p_input->input.p_item->i_categories, p_cat );
00163 }
00164
00165 p_cat = p_input->input.p_item->pp_categories[i];
00166
00167 for( i = 0; i < p_cat->i_infos; i++ )
00168 {
00169 if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
00170 {
00171 if( p_cat->pp_infos[i]->psz_value )
00172 free( p_cat->pp_infos[i]->psz_value );
00173 break;
00174 }
00175 }
00176
00177 if( i == p_cat->i_infos )
00178 {
00179 p_info = malloc( sizeof( info_t ) );
00180 if( !p_info )
00181 {
00182 vlc_mutex_lock( &p_input->input.p_item->lock );
00183 return VLC_EGENERIC;
00184 }
00185
00186 INSERT_ELEM( p_cat->pp_infos, p_cat->i_infos,
00187 p_cat->i_infos, p_info );
00188 p_info->psz_name = strdup( psz_name );
00189 }
00190
00191 p_info = p_cat->pp_infos[i];
00192 vasprintf( &p_info->psz_value, psz_format, args );
00193
00194 vlc_mutex_unlock( &p_input->input.p_item->lock );
00195
00196 NotifyPlaylist( p_input );
00197 }
00198 return VLC_SUCCESS;
00199
00200 case INPUT_DEL_INFO:
00201 {
00202 char *psz_cat = (char *)va_arg( args, char * );
00203 char *psz_name = (char *)va_arg( args, char * );
00204
00205 info_category_t *p_cat = NULL;
00206 int i;
00207
00208 vlc_mutex_lock( &p_input->input.p_item->lock );
00209 for( i = 0; i < p_input->input.p_item->i_categories; i++ )
00210 {
00211 if( !strcmp( p_input->input.p_item->pp_categories[i]->psz_name,
00212 psz_cat ) )
00213 {
00214 p_cat = p_input->input.p_item->pp_categories[i];
00215 break;
00216 }
00217 }
00218 if( p_cat == NULL )
00219 {
00220 vlc_mutex_unlock( &p_input->input.p_item->lock );
00221 return VLC_EGENERIC;
00222 }
00223
00224 for( i = 0; i < p_cat->i_infos; i++ )
00225 {
00226 if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
00227 {
00228 free( p_cat->pp_infos[i]->psz_name );
00229 if( p_cat->pp_infos[i]->psz_value )
00230 free( p_cat->pp_infos[i]->psz_value );
00231 free( p_cat->pp_infos[i] );
00232 REMOVE_ELEM( p_cat->pp_infos, p_cat->i_infos, i );
00233 break;
00234 }
00235 }
00236 vlc_mutex_unlock( &p_input->input.p_item->lock );
00237
00238 if( i >= p_cat->i_infos )
00239 return VLC_EGENERIC;
00240
00241 NotifyPlaylist( p_input );
00242 }
00243 return VLC_SUCCESS;
00244
00245
00246 case INPUT_GET_INFO:
00247 {
00248 char *psz_cat = (char *)va_arg( args, char * );
00249 char *psz_name = (char *)va_arg( args, char * );
00250 char **ppsz_value = (char **)va_arg( args, char ** );
00251 int i_ret = VLC_EGENERIC;
00252 *ppsz_value = NULL;
00253
00254 *ppsz_value = vlc_input_item_GetInfo( p_input->input.p_item,
00255 psz_cat, psz_name );
00256 return i_ret;
00257 }
00258
00259 case INPUT_SET_NAME:
00260 {
00261 char *psz_name = (char *)va_arg( args, char * );
00262
00263 if( !psz_name ) return VLC_EGENERIC;
00264
00265 vlc_mutex_lock( &p_input->input.p_item->lock );
00266 if( p_input->input.p_item->psz_name )
00267 free( p_input->input.p_item->psz_name );
00268 p_input->input.p_item->psz_name = strdup( psz_name );
00269 vlc_mutex_unlock( &p_input->input.p_item->lock );
00270
00271 NotifyPlaylist( p_input );
00272
00273 return VLC_SUCCESS;
00274 }
00275
00276 case INPUT_ADD_BOOKMARK:
00277 p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
00278 p_bkmk = vlc_seekpoint_Duplicate( p_bkmk );
00279
00280 vlc_mutex_lock( &p_input->input.p_item->lock );
00281 if( !p_bkmk->psz_name )
00282 {
00283 asprintf( &p_bkmk->psz_name, _("Bookmark %i"),
00284 p_input->i_bookmark );
00285 }
00286
00287 TAB_APPEND( p_input->i_bookmark, p_input->bookmark, p_bkmk );
00288
00289
00290 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
00291 {
00292 vlc_value_t val, text;
00293 int i;
00294
00295 for( i = 0; i < p_input->i_bookmark; i++ )
00296 {
00297 val.i_int = i;
00298 text.psz_string = p_input->bookmark[i]->psz_name;
00299 var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
00300 &val, &text );
00301 }
00302 }
00303 vlc_mutex_unlock( &p_input->input.p_item->lock );
00304
00305 UpdateBookmarksOption( p_input );
00306
00307 return VLC_SUCCESS;
00308
00309 case INPUT_CHANGE_BOOKMARK:
00310 p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
00311 i_bkmk = (int)va_arg( args, int );
00312
00313 vlc_mutex_lock( &p_input->input.p_item->lock );
00314 if( i_bkmk < p_input->i_bookmark )
00315 {
00316 vlc_value_t val, text;
00317 int i;
00318
00319 p_input->bookmark[i_bkmk] = p_bkmk;
00320
00321
00322 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
00323 for( i = 0; i < p_input->i_bookmark; i++ )
00324 {
00325 val.i_int = i;
00326 text.psz_string = p_input->bookmark[i]->psz_name;
00327 var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
00328 &val, &text );
00329 }
00330 }
00331 vlc_mutex_unlock( &p_input->input.p_item->lock );
00332
00333 UpdateBookmarksOption( p_input );
00334
00335 return VLC_SUCCESS;
00336
00337 case INPUT_DEL_BOOKMARK:
00338 i_bkmk = (int)va_arg( args, int );
00339
00340 vlc_mutex_lock( &p_input->input.p_item->lock );
00341 if( i_bkmk < p_input->i_bookmark )
00342 {
00343 vlc_value_t val, text;
00344 int i;
00345
00346 p_bkmk = p_input->bookmark[i_bkmk];
00347 TAB_REMOVE( p_input->i_bookmark, p_input->bookmark,
00348 p_bkmk );
00349 vlc_seekpoint_Delete( p_bkmk );
00350
00351
00352 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
00353 for( i = 0; i < p_input->i_bookmark; i++ )
00354 {
00355 val.i_int = i;
00356 text.psz_string = p_input->bookmark[i]->psz_name;
00357 var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
00358 &val, &text );
00359 }
00360 vlc_mutex_unlock( &p_input->input.p_item->lock );
00361
00362 UpdateBookmarksOption( p_input );
00363
00364 return VLC_SUCCESS;
00365 }
00366 vlc_mutex_unlock( &p_input->input.p_item->lock );
00367
00368 return VLC_EGENERIC;
00369
00370 case INPUT_GET_BOOKMARKS:
00371 ppp_bkmk = (seekpoint_t ***)va_arg( args, seekpoint_t *** );
00372 pi_bkmk = (int *)va_arg( args, int * );
00373
00374 vlc_mutex_lock( &p_input->input.p_item->lock );
00375 if( p_input->i_bookmark )
00376 {
00377 int i;
00378
00379 *pi_bkmk = p_input->i_bookmark;
00380 *ppp_bkmk = malloc( sizeof(seekpoint_t *) *
00381 p_input->i_bookmark );
00382 for( i = 0; i < p_input->i_bookmark; i++ )
00383 {
00384 (*ppp_bkmk)[i] =
00385 vlc_seekpoint_Duplicate(p_input->bookmark[i]);
00386 }
00387
00388 vlc_mutex_unlock( &p_input->input.p_item->lock );
00389 return VLC_SUCCESS;
00390 }
00391 else
00392 {
00393 *ppp_bkmk = NULL;
00394 *pi_bkmk = 0;
00395
00396 vlc_mutex_unlock( &p_input->input.p_item->lock );
00397 return VLC_EGENERIC;
00398 }
00399 break;
00400
00401 case INPUT_CLEAR_BOOKMARKS:
00402
00403 vlc_mutex_lock( &p_input->input.p_item->lock );
00404 if( p_input->i_bookmark )
00405 {
00406 int i;
00407
00408 for( i = p_input->i_bookmark - 1; i >= 0; i-- )
00409 {
00410 p_bkmk = p_input->bookmark[i];
00411 TAB_REMOVE( p_input->i_bookmark, p_input->bookmark,
00412 p_bkmk );
00413 vlc_seekpoint_Delete( p_bkmk );
00414 }
00415 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
00416 }
00417 vlc_mutex_unlock( &p_input->input.p_item->lock );
00418
00419 UpdateBookmarksOption( p_input );
00420
00421 return VLC_SUCCESS;
00422
00423 case INPUT_SET_BOOKMARK:
00424 i_bkmk = (int)va_arg( args, int );
00425
00426 vlc_mutex_lock( &p_input->input.p_item->lock );
00427 if( i_bkmk >= 0 && i_bkmk < p_input->i_bookmark )
00428 {
00429 vlc_value_t pos;
00430 int i_ret;
00431
00432 if( p_input->bookmark[i_bkmk]->i_time_offset != -1 )
00433 {
00434 pos.i_time = p_input->bookmark[i_bkmk]->i_time_offset;
00435 i_ret = var_Set( p_input, "time", pos );
00436 }
00437 else if( p_input->bookmark[i_bkmk]->i_byte_offset != -1 )
00438 {
00439
00440 if( stream_Size( p_input->input.p_stream ) == 0 )
00441 {
00442 vlc_mutex_unlock( &p_input->input.p_item->lock );
00443 return VLC_EGENERIC;
00444 }
00445 pos.f_float = !p_input->input.p_stream ? 0 :
00446 p_input->bookmark[i_bkmk]->i_byte_offset /
00447 stream_Size( p_input->input.p_stream );
00448 i_ret = var_Set( p_input, "position", pos );
00449 }
00450 else
00451 {
00452 pos.f_float = 0;
00453 i_ret = var_Set( p_input, "position", pos );
00454 }
00455
00456 vlc_mutex_unlock( &p_input->input.p_item->lock );
00457 return i_ret;
00458 }
00459 else
00460 {
00461 vlc_mutex_unlock( &p_input->input.p_item->lock );
00462 return VLC_EGENERIC;
00463 }
00464
00465 break;
00466
00467 case INPUT_ADD_OPTION:
00468 {
00469 char *psz_option = (char *)va_arg( args, char * );
00470 char *psz_value = (char *)va_arg( args, char * );
00471 int i;
00472
00473 vlc_mutex_lock( &p_input->input.p_item->lock );
00474
00475 for( i = 0; i < p_input->input.p_item->i_options; i++ )
00476 {
00477 if( !strncmp( p_input->input.p_item->ppsz_options[i],
00478 psz_option, strlen( psz_option ) ) &&
00479 p_input->input.p_item->ppsz_options[i][strlen(psz_option)]
00480 == '=' )
00481 {
00482 free( p_input->input.p_item->ppsz_options[i] );
00483 break;
00484 }
00485 }
00486 if( i == p_input->input.p_item->i_options )
00487 {
00488 p_input->input.p_item->i_options++;
00489 p_input->input.p_item->ppsz_options =
00490 realloc( p_input->input.p_item->ppsz_options,
00491 p_input->input.p_item->i_options *
00492 sizeof(char **) );
00493 }
00494
00495 asprintf( &p_input->input.p_item->ppsz_options[i],
00496 "%s=%s", psz_option, psz_value ) ;
00497 vlc_mutex_unlock( &p_input->input.p_item->lock );
00498
00499 return VLC_SUCCESS;
00500 }
00501
00502 case INPUT_GET_BYTE_POSITION:
00503 pi_64 = (int64_t*)va_arg( args, int64_t * );
00504 *pi_64 = !p_input->input.p_stream ? 0 :
00505 stream_Tell( p_input->input.p_stream );
00506 return VLC_SUCCESS;
00507
00508 case INPUT_SET_BYTE_SIZE:
00509 pi_64 = (int64_t*)va_arg( args, int64_t * );
00510 *pi_64 = !p_input->input.p_stream ? 0 :
00511 stream_Size( p_input->input.p_stream );
00512 return VLC_SUCCESS;
00513
00514 case INPUT_ADD_SLAVE:
00515 psz = (char*)va_arg( args, char * );
00516 if( psz && *psz )
00517 {
00518 val.psz_string = strdup( psz );
00519 input_ControlPush( p_input, INPUT_CONTROL_ADD_SLAVE, &val );
00520 }
00521 return VLC_SUCCESS;
00522
00523 default:
00524 msg_Err( p_input, "unknown query in input_vaControl" );
00525 return VLC_EGENERIC;
00526 }
00527 }
00528
00529 static void NotifyPlaylist( input_thread_t *p_input )
00530 {
00531 playlist_t *p_playlist =
00532 (playlist_t *)vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
00533 FIND_PARENT );
00534 if( p_playlist )
00535 {
00536 var_SetInteger( p_playlist, "item-change", p_playlist->i_index );
00537 vlc_object_release( p_playlist );
00538 }
00539 }
00540
00541 static void UpdateBookmarksOption( input_thread_t *p_input )
00542 {
00543 int i, i_len = 0;
00544 char *psz_value = NULL, *psz_next = NULL;
00545
00546 vlc_mutex_lock( &p_input->input.p_item->lock );
00547 for( i = 0; i < p_input->i_bookmark; i++ )
00548 {
00549 asprintf( &psz_value, "{name=%s,bytes="I64Fd",time="I64Fd"}",
00550 p_input->bookmark[i]->psz_name,
00551 p_input->bookmark[i]->i_byte_offset,
00552 p_input->bookmark[i]->i_time_offset/1000000 );
00553 i_len += strlen( psz_value );
00554 free( psz_value );
00555 }
00556 for( i = 0; i < p_input->i_bookmark; i++ )
00557 {
00558 if( !i ) psz_value = psz_next = malloc( i_len + p_input->i_bookmark );
00559
00560 sprintf( psz_next, "{name=%s,bytes="I64Fd",time="I64Fd"}",
00561 p_input->bookmark[i]->psz_name,
00562 p_input->bookmark[i]->i_byte_offset,
00563 p_input->bookmark[i]->i_time_offset/1000000 );
00564
00565 psz_next += strlen( psz_next );
00566 if( i < p_input->i_bookmark - 1)
00567 {
00568 *psz_next = ','; psz_next++;
00569 }
00570 }
00571 vlc_mutex_unlock( &p_input->input.p_item->lock );
00572
00573 input_Control( p_input, INPUT_ADD_OPTION, "bookmarks",
00574 psz_value ? psz_value : "" );
00575 }