Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

control.c

00001 /*****************************************************************************
00002  * control.c
00003  *****************************************************************************
00004  * Copyright (C) 1999-2004 the VideoLAN team
00005  * $Id: control.c 12438 2005-08-31 20:37:23Z gbazin $
00006  *
00007  * Authors: Gildas Bazin <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
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  * input_Control
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             /* FIXME : Impossible to use vlc_input_item_AddInfo because of
00133              * the ... problem ? */
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             /* Reflect the changes on the object var */
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                 /* Reflect the changes on the object var */
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                 /* Reflect the changes on the object var */
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                     // don't crash on bookmarks in live streams
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             /* Check if option already exists */
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 }

Generated on Tue Dec 20 10:14:59 2005 for vlc-0.8.4a by  doxygen 1.4.2