]> git.sesse.net Git - vlc/blob - src/input/control.c
* all: rework of the input.
[vlc] / src / input / control.c
1 /*****************************************************************************
2  * control.c
3  *****************************************************************************
4  * Copyright (C) 1999-2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <stdlib.h>
25 #include <vlc/vlc.h>
26 #include <vlc/input.h>
27
28 #include "input_internal.h"
29 #include "vlc_playlist.h"
30
31
32 static void UpdateBookmarksOption( input_thread_t * );
33
34 /****************************************************************************
35  * input_Control
36  ****************************************************************************/
37 /**
38  * Control function for inputs.
39  * \param p_input input handle
40  * \param i_query query type
41  * \return VLC_SUCESS if ok
42  */
43 int input_Control( input_thread_t *p_input, int i_query, ...  )
44 {
45     va_list args;
46     int     i_result;
47
48     va_start( args, i_query );
49     i_result = input_vaControl( p_input, i_query, args );
50     va_end( args );
51
52     return i_result;
53 }
54
55 int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
56 {
57     seekpoint_t *p_bkmk, ***ppp_bkmk;
58     int i_bkmk = 0;
59     int *pi_bkmk;
60     int i, *pi;
61     vlc_value_t val, text;
62     char *psz_option, *psz_value;
63     int i_int, *pi_int;
64     double f, *pf;
65     int64_t i_64, *pi_64;
66
67     switch( i_query )
68     {
69         case INPUT_GET_POSITION:
70             pf = (double*)va_arg( args, double * );
71             *pf = var_GetFloat( p_input, "position" );
72             return VLC_SUCCESS;
73
74         case INPUT_SET_POSITION:
75             f = (double)va_arg( args, double );
76             return var_SetFloat( p_input, "position", f );
77
78         case INPUT_GET_LENGTH:
79             pi_64 = (int64_t*)va_arg( args, int64_t * );
80             *pi_64 = var_GetTime( p_input, "length" );
81             return VLC_SUCCESS;
82
83         case INPUT_GET_TIME:
84             pi_64 = (int64_t*)va_arg( args, int64_t * );
85             *pi_64 = var_GetTime( p_input, "time" );
86             return VLC_SUCCESS;
87
88         case INPUT_SET_TIME:
89             i_64 = (int64_t)va_arg( args, int64_t );
90             return var_SetTime( p_input, "time", i_64 );
91
92         case INPUT_GET_RATE:
93             pi_int = (int*)va_arg( args, int * );
94             *pi_int = var_GetInteger( p_input, "rate" );
95             return VLC_SUCCESS;
96
97         case INPUT_SET_RATE:
98             i_int = (int)va_arg( args, int );
99             return var_SetInteger( p_input, "rate", i_int );
100
101         case INPUT_GET_STATE:
102             pi_int = (int*)va_arg( args, int * );
103             *pi_int = var_GetInteger( p_input, "state" );
104             return VLC_SUCCESS;
105
106         case INPUT_SET_STATE:
107             i_int = (int)va_arg( args, int );
108             return var_SetInteger( p_input, "state", i_int );
109
110 #if 0
111         case INPUT_ADD_OPTION:
112         {
113             psz_option = (char *)va_arg( args, char * );
114             psz_value = (char *)va_arg( args, char * );
115             i_ret = VLC_EGENERIC;
116
117             vlc_mutex_lock( &p_input->p_item->lock );
118             /* Check if option already exists */
119             for( i = 0; i < p_input->p_item->i_options; i++ )
120             {
121                 if( !strncmp( p_input->p_item->ppsz_options[i], psz_option,
122                               strlen( psz_option ) ) &&
123                     p_input->p_item->ppsz_options[i][strlen(psz_option)]
124                       == '=' )
125                 {
126                     free( p_input->p_item->ppsz_options[i] );
127                     break;
128                 }
129             }
130             if( i == p_input->p_item->i_options )
131             {
132                 p_input->p_item->i_options++;
133                 p_input->p_item->ppsz_options =
134                     realloc( p_input->p_item->ppsz_options,
135                              p_input->p_item->i_options * sizeof(char **) );
136             }
137
138             asprintf( &p_input->p_item->ppsz_options[i],
139                       "%s=%s", psz_option, psz_value ) ;
140             vlc_mutex_unlock( &p_input->p_item->lock );
141
142             i_ret = VLC_SUCCESS;
143             break;
144         }
145
146         case INPUT_SET_NAME:
147         {
148             char *psz_name = (char *)va_arg( args, char * );
149             i_ret = VLC_EGENERIC;
150             if( !psz_name ) break;
151             vlc_mutex_lock( &p_input->p_item->lock );
152             if( p_input->p_item->psz_name ) free( p_input->p_item->psz_name );
153             p_input->p_item->psz_name = strdup( psz_name );
154             vlc_mutex_unlock( &p_input->p_item->lock );
155             i_ret = VLC_SUCCESS;
156
157             /* Notify playlist */
158             {
159                 vlc_value_t val;
160                 playlist_t *p_playlist =
161                 (playlist_t *)vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
162                                                FIND_PARENT );
163                 if( p_playlist )
164                 {
165                     val.i_int = p_playlist->i_index;
166                     vlc_mutex_unlock( &p_input->stream.stream_lock );
167                     var_Set( p_playlist, "item-change", val );
168                     vlc_mutex_lock( &p_input->stream.stream_lock );
169                     vlc_object_release( p_playlist );
170                 }
171             }
172             break;
173         }
174
175         case INPUT_ADD_INFO:
176         {
177             char *psz_cat = (char *)va_arg( args, char * );
178             char *psz_name = (char *)va_arg( args, char * );
179             char *psz_format = (char *)va_arg( args, char * );
180
181             info_category_t *p_cat;
182             info_t *p_info;
183             int i;
184
185             i_ret = VLC_EGENERIC;
186
187             vlc_mutex_lock( &p_input->p_item->lock );
188             for( i = 0; i < p_input->p_item->i_categories; i++ )
189             {
190                 if( !strcmp( p_input->p_item->pp_categories[i]->psz_name,
191                              psz_cat ) )
192                     break;
193             }
194
195             if( i == p_input->p_item->i_categories )
196             {
197                 p_cat = malloc( sizeof( info_category_t ) );
198                 if( !p_cat ) break;
199                 p_cat->psz_name = strdup( psz_cat );
200                 p_cat->i_infos = 0;
201                 p_cat->pp_infos = NULL;
202                 INSERT_ELEM( p_input->p_item->pp_categories,
203                              p_input->p_item->i_categories,
204                              p_input->p_item->i_categories, p_cat );
205             }
206
207             p_cat = p_input->p_item->pp_categories[i];
208
209             for( i = 0; i < p_cat->i_infos; i++ )
210             {
211                 if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
212                 {
213                     if( p_cat->pp_infos[i]->psz_value )
214                         free( p_cat->pp_infos[i]->psz_value );
215                     break;
216                 }
217             }
218
219             if( i == p_cat->i_infos )
220             {
221                 p_info = malloc( sizeof( info_t ) );
222                 if( !p_info ) break;
223                 INSERT_ELEM( p_cat->pp_infos, p_cat->i_infos,
224                              p_cat->i_infos, p_info );
225                 p_info->psz_name = strdup( psz_name );
226             }
227
228             p_info = p_cat->pp_infos[i];
229             vasprintf( &p_info->psz_value, psz_format, args );
230
231             vlc_mutex_unlock( &p_input->p_item->lock );
232
233             i_ret = VLC_SUCCESS;
234
235             /* Notify playlist */
236             {
237                 vlc_value_t val;
238                 playlist_t *p_playlist =
239                 (playlist_t *)vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
240                                                FIND_PARENT );
241                 if( p_playlist )
242                 {
243                     val.i_int = p_playlist->i_index;
244                     vlc_mutex_unlock( &p_input->stream.stream_lock );
245                     var_Set( p_playlist, "item-change", val );
246                     vlc_mutex_lock( &p_input->stream.stream_lock );
247                     vlc_object_release( p_playlist );
248                 }
249             }
250         }
251         break;
252
253         case INPUT_GET_INFO:
254         {
255             char *psz_cat = (char *)va_arg( args, char * );
256             char *psz_name = (char *)va_arg( args, char * );
257             char **ppsz_value = (char **)va_arg( args, char ** );
258             int i;
259
260             i_ret = VLC_EGENERIC;
261             *ppsz_value = NULL;
262
263             vlc_mutex_lock( &p_input->p_item->lock );
264             for( i = 0; i < p_input->p_item->i_categories; i++ )
265             {
266                 if( !strcmp( p_input->p_item->pp_categories[i]->psz_name,
267                              psz_cat ) )
268                     break;
269             }
270
271             if( i != p_input->p_item->i_categories )
272             {
273                 info_category_t *p_cat;
274                 p_cat = p_input->p_item->pp_categories[i];
275
276                 for( i = 0; i < p_cat->i_infos; i++ )
277                 {
278                     if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
279                     {
280                         if( p_cat->pp_infos[i]->psz_value )
281                         {
282                             *ppsz_value =strdup(p_cat->pp_infos[i]->psz_value);
283                             i_ret = VLC_SUCCESS;
284                         }
285                         break;
286                     }
287                 }
288             }
289             vlc_mutex_unlock( &p_input->p_item->lock );
290         }
291         break;
292
293         case INPUT_ADD_BOOKMARK:
294             p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
295             p_bkmk = vlc_seekpoint_Duplicate( p_bkmk );
296             if( !p_bkmk->psz_name )
297             {
298                  asprintf( &p_bkmk->psz_name, _("Bookmark %i"),
299                            p_input->i_bookmarks );
300             }
301             TAB_APPEND( p_input->i_bookmarks, p_input->pp_bookmarks, p_bkmk );
302
303             /* Reflect the changes on the object var */
304             var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
305             {
306                 int i;
307                 for( i = 0; i < p_input->i_bookmarks; i++ )
308                 {
309                     val.i_int = i;
310                     text.psz_string = p_input->pp_bookmarks[i]->psz_name;
311                     var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
312                                 &val, &text );
313                 }
314             }
315
316             UpdateBookmarksOption( p_input );
317
318             i_ret = VLC_SUCCESS;
319             break;
320
321         case INPUT_CHANGE_BOOKMARK:
322              p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
323              i_bkmk = (int)va_arg( args, int );
324
325              if( i_bkmk < p_input->i_bookmarks )
326              {
327                  p_input->pp_bookmarks[i_bkmk] = p_bkmk;
328
329                  /* Reflect the changes on the object var */
330                  var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
331                  for( i = 0; i < p_input->i_bookmarks; i++ )
332                  {
333                      val.i_int = i;
334                      text.psz_string = p_input->pp_bookmarks[i]->psz_name;
335                      var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
336                                  &val, &text );
337                  }
338              }
339              UpdateBookmarksOption( p_input );
340
341              i_ret = VLC_SUCCESS;
342              break;
343
344         case INPUT_DEL_BOOKMARK:
345             i_bkmk = (int)va_arg( args, int );
346             if( i_bkmk < p_input->i_bookmarks )
347             {
348                 int i;
349                 p_bkmk = p_input->pp_bookmarks[i_bkmk];
350                 TAB_REMOVE( p_input->i_bookmarks, p_input->pp_bookmarks,
351                             p_bkmk );
352                 vlc_seekpoint_Delete( p_bkmk );
353
354                 /* Reflect the changes on the object var */
355                 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
356                 for( i = 0; i < p_input->i_bookmarks; i++ )
357                 {
358                     val.i_int = i;
359                     text.psz_string = p_input->pp_bookmarks[i]->psz_name;
360                     var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
361                                 &val, &text );
362                 }
363
364                 UpdateBookmarksOption( p_input );
365
366                 i_ret = VLC_SUCCESS;
367             }
368             else i_ret = VLC_EGENERIC;
369             break;
370
371         case INPUT_GET_BOOKMARKS:
372             ppp_bkmk = (seekpoint_t ***)va_arg( args, seekpoint_t *** );
373             pi_bkmk = (int *)va_arg( args, int * );
374             if( p_input->i_bookmarks )
375             {
376                 int i;
377
378                 *pi_bkmk = p_input->i_bookmarks;
379                 *ppp_bkmk = malloc( sizeof(seekpoint_t *) *
380                               p_input->i_bookmarks );
381                 for( i = 0; i < p_input->i_bookmarks; i++ )
382                 {
383                     (*ppp_bkmk)[i] =
384                         vlc_seekpoint_Duplicate(p_input->pp_bookmarks[i]);
385                 }
386                 i_ret = VLC_SUCCESS;
387             }
388             else
389             {
390                 *ppp_bkmk = NULL;
391                 *pi_bkmk = 0;
392                 i_ret = VLC_EGENERIC;
393             }
394             break;
395
396         case INPUT_CLEAR_BOOKMARKS:
397             if( p_input->i_bookmarks )
398             {
399                 int i;
400
401                 for( i = p_input->i_bookmarks - 1; i >= 0; i-- )
402                 {
403                     p_bkmk = p_input->pp_bookmarks[i];
404                     TAB_REMOVE( p_input->i_bookmarks, p_input->pp_bookmarks,
405                                 p_bkmk );
406                     vlc_seekpoint_Delete( p_bkmk );
407                 }
408                 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
409             }
410
411             UpdateBookmarksOption( p_input );
412
413             i_ret = VLC_SUCCESS;
414             break;
415
416         case INPUT_SET_BOOKMARK:
417             i_bkmk = (int)va_arg( args, int );
418             if( i_bkmk >= 0 && i_bkmk < p_input->i_bookmarks )
419             {
420                 vlc_value_t pos;
421                 vlc_mutex_unlock( &p_input->stream.stream_lock );
422                 if( p_input->pp_bookmarks[i_bkmk]->i_byte_offset ||
423                     ( !p_input->pp_bookmarks[i_bkmk]->i_byte_offset &&
424                       !p_input->pp_bookmarks[i_bkmk]->i_time_offset ) )
425                 {
426                     pos.f_float = p_input->pp_bookmarks[i_bkmk]->i_byte_offset/
427                         (double)p_input->stream.p_selected_area->i_size;
428                     i_ret = var_Set( p_input, "position", pos );
429                 }
430                 else if( p_input->pp_bookmarks[i_bkmk]->i_time_offset )
431                 {
432                     pos.i_time = p_input->pp_bookmarks[i_bkmk]->i_time_offset;
433                     i_ret = var_Set( p_input, "time", pos );
434                 }
435                 vlc_mutex_lock( &p_input->stream.stream_lock );
436             }
437             else
438             {
439                 i_ret = VLC_EGENERIC;
440             }
441             break;
442
443         case INPUT_GET_SUBDELAY:
444             pi = (int*)va_arg( args, int *);
445             /* We work on the first subtitle */
446             if( p_input->p_sys != NULL )
447             {
448                 if( p_input->p_sys->i_sub > 0 )
449                 {
450                     i_ret = var_Get( (vlc_object_t *)p_input->p_sys->sub[0],
451                                       "sub-delay", &val );
452                     *pi = val.i_int;
453                 }
454                 else
455                 {
456                     msg_Dbg( p_input,"no subtitle track");
457                     i_ret = VLC_EGENERIC;
458                 }
459             }
460             else
461             {
462                 i_ret = VLC_EGENERIC;
463             }
464             break;
465
466         case INPUT_SET_SUBDELAY:
467             i = (int)va_arg( args, int );
468             /* We work on the first subtitle */
469             if( p_input->p_sys )
470             {
471                 if( p_input->p_sys->i_sub > 0 )
472                 {
473                     val.i_int = i;
474                     i_ret = var_Set( (vlc_object_t *)p_input->p_sys->sub[0],
475                                       "sub-delay", val );
476                 }
477                 else
478                 {
479                     msg_Dbg( p_input,"no subtitle track");
480                     i_ret = VLC_EGENERIC;
481                 }
482             }
483             else
484             {
485                 i_ret = VLC_EGENERIC;
486             }
487             break;
488 #endif
489         case INPUT_GET_BOOKMARKS:
490         case INPUT_CLEAR_BOOKMARKS:
491         case INPUT_ADD_BOOKMARK:
492         case INPUT_CHANGE_BOOKMARK:
493         case INPUT_DEL_BOOKMARK:
494         case INPUT_SET_BOOKMARK:
495         case INPUT_ADD_OPTION:
496         case INPUT_ADD_INFO:
497         case INPUT_GET_INFO:
498         case INPUT_SET_NAME:
499         case INPUT_GET_SUBDELAY:
500         case INPUT_SET_SUBDELAY:
501             /* FIXME */
502             msg_Err( p_input, "unimplemented query in input_vaControl" );
503         default:
504             msg_Err( p_input, "unknown query in input_vaControl" );
505             return VLC_EGENERIC;
506     }
507 }
508
509 static void UpdateBookmarksOption( input_thread_t *p_input )
510 {
511     int i, i_len = 0;
512     char *psz_value = NULL, *psz_next = NULL;
513     /* FIXME */
514 #if 0
515     vlc_mutex_unlock( &p_input->stream.stream_lock );
516
517     for( i = 0; i < p_input->i_bookmarks; i++ )
518     {
519         asprintf( &psz_value, "{name=%s,bytes="I64Fd",time="I64Fd"}",
520                   p_input->pp_bookmarks[i]->psz_name,
521                   p_input->pp_bookmarks[i]->i_byte_offset,
522                   p_input->pp_bookmarks[i]->i_time_offset/1000000 );
523         i_len += strlen( psz_value );
524         free( psz_value );
525     }
526     for( i = 0; i < p_input->i_bookmarks; i++ )
527     {
528         if( !i ) psz_value = psz_next = malloc( i_len + p_input->i_bookmarks );
529
530         sprintf( psz_next, "{name=%s,bytes="I64Fd",time="I64Fd"}",
531                  p_input->pp_bookmarks[i]->psz_name,
532                  p_input->pp_bookmarks[i]->i_byte_offset,
533                  p_input->pp_bookmarks[i]->i_time_offset/1000000 );
534
535         psz_next += strlen( psz_next );
536         if( i < p_input->i_bookmarks - 1)
537         {
538             *psz_next = ','; psz_next++;
539         }
540     }
541     input_Control( p_input, INPUT_ADD_OPTION, "bookmarks",
542                    psz_value ? psz_value : "" );
543
544     vlc_mutex_lock( &p_input->stream.stream_lock );
545 #endif
546 }