control.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:18k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * control.c
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2004 VideoLAN
  5.  * $Id: control.c 8473 2004-08-20 15:09:43Z sam $
  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. #include <stdlib.h>
  24. #include <vlc/vlc.h>
  25. #include <vlc/input.h>
  26. #include "input_internal.h"
  27. #include "vlc_playlist.h"
  28. static void UpdateBookmarksOption( input_thread_t * );
  29. static void NotifyPlaylist( input_thread_t * );
  30. /****************************************************************************
  31.  * input_Control
  32.  ****************************************************************************/
  33. /**
  34.  * Control function for inputs.
  35.  * param p_input input handle
  36.  * param i_query query type
  37.  * return VLC_SUCCESS if ok
  38.  */
  39. int input_Control( input_thread_t *p_input, int i_query, ...  )
  40. {
  41.     va_list args;
  42.     int     i_result;
  43.     va_start( args, i_query );
  44.     i_result = input_vaControl( p_input, i_query, args );
  45.     va_end( args );
  46.     return i_result;
  47. }
  48. int input_vaControl( input_thread_t *p_input, int i_query, va_list args )
  49. {
  50.     seekpoint_t *p_bkmk, ***ppp_bkmk;
  51.     int i_bkmk = 0;
  52.     int *pi_bkmk;
  53.     int i_int, *pi_int;
  54.     double f, *pf;
  55.     int64_t i_64, *pi_64;
  56.     switch( i_query )
  57.     {
  58.         case INPUT_GET_POSITION:
  59.             pf = (double*)va_arg( args, double * );
  60.             *pf = var_GetFloat( p_input, "position" );
  61.             return VLC_SUCCESS;
  62.         case INPUT_SET_POSITION:
  63.             f = (double)va_arg( args, double );
  64.             return var_SetFloat( p_input, "position", f );
  65.         case INPUT_GET_LENGTH:
  66.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  67.             *pi_64 = var_GetTime( p_input, "length" );
  68.             return VLC_SUCCESS;
  69.         case INPUT_GET_TIME:
  70.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  71.             *pi_64 = var_GetTime( p_input, "time" );
  72.             return VLC_SUCCESS;
  73.         case INPUT_SET_TIME:
  74.             i_64 = (int64_t)va_arg( args, int64_t );
  75.             return var_SetTime( p_input, "time", i_64 );
  76.         case INPUT_GET_RATE:
  77.             pi_int = (int*)va_arg( args, int * );
  78.             *pi_int = var_GetInteger( p_input, "rate" );
  79.             return VLC_SUCCESS;
  80.         case INPUT_SET_RATE:
  81.             i_int = (int)va_arg( args, int );
  82.             return var_SetInteger( p_input, "rate", i_int );
  83.         case INPUT_GET_STATE:
  84.             pi_int = (int*)va_arg( args, int * );
  85.             *pi_int = var_GetInteger( p_input, "state" );
  86.             return VLC_SUCCESS;
  87.         case INPUT_SET_STATE:
  88.             i_int = (int)va_arg( args, int );
  89.             return var_SetInteger( p_input, "state", i_int );
  90.         case INPUT_GET_AUDIO_DELAY:
  91.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  92.             *pi_64 = var_GetTime( p_input, "audio-delay" );
  93.             return VLC_SUCCESS;
  94.         case INPUT_GET_SPU_DELAY:
  95.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  96.             *pi_64 = var_GetTime( p_input, "spu-delay" );
  97.             return VLC_SUCCESS;
  98.         case INPUT_SET_AUDIO_DELAY:
  99.             i_64 = (int64_t)va_arg( args, int64_t );
  100.             return var_SetTime( p_input, "audio-delay", i_64 );
  101.         case INPUT_SET_SPU_DELAY:
  102.             i_64 = (int64_t)va_arg( args, int64_t );
  103.             return var_SetTime( p_input, "spu-delay", i_64 );
  104.         case INPUT_ADD_INFO:
  105.         {
  106.             char *psz_cat = (char *)va_arg( args, char * );
  107.             char *psz_name = (char *)va_arg( args, char * );
  108.             char *psz_format = (char *)va_arg( args, char * );
  109.             info_category_t *p_cat;
  110.             info_t *p_info;
  111.             int i;
  112.             vlc_mutex_lock( &p_input->input.p_item->lock );
  113.             for( i = 0; i < p_input->input.p_item->i_categories; i++ )
  114.             {
  115.                 if( !strcmp( p_input->input.p_item->pp_categories[i]->psz_name,
  116.                              psz_cat ) ) break;
  117.             }
  118.             if( i == p_input->input.p_item->i_categories )
  119.             {
  120.                 p_cat = malloc( sizeof( info_category_t ) );
  121.                 if( !p_cat )
  122.                 {
  123.                     vlc_mutex_lock( &p_input->input.p_item->lock );
  124.                     return VLC_EGENERIC;
  125.                 }
  126.                 p_cat->psz_name = strdup( psz_cat );
  127.                 p_cat->i_infos = 0;
  128.                 p_cat->pp_infos = NULL;
  129.                 INSERT_ELEM( p_input->input.p_item->pp_categories,
  130.                              p_input->input.p_item->i_categories,
  131.                              p_input->input.p_item->i_categories, p_cat );
  132.             }
  133.             p_cat = p_input->input.p_item->pp_categories[i];
  134.             for( i = 0; i < p_cat->i_infos; i++ )
  135.             {
  136.                 if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
  137.                 {
  138.                     if( p_cat->pp_infos[i]->psz_value )
  139.                         free( p_cat->pp_infos[i]->psz_value );
  140.                     break;
  141.                 }
  142.             }
  143.             if( i == p_cat->i_infos )
  144.             {
  145.                 p_info = malloc( sizeof( info_t ) );
  146.                 if( !p_info )
  147.                 {
  148.                     vlc_mutex_lock( &p_input->input.p_item->lock );
  149.                     return VLC_EGENERIC;
  150.                 }
  151.                 INSERT_ELEM( p_cat->pp_infos, p_cat->i_infos,
  152.                              p_cat->i_infos, p_info );
  153.                 p_info->psz_name = strdup( psz_name );
  154.             }
  155.             p_info = p_cat->pp_infos[i];
  156.             vasprintf( &p_info->psz_value, psz_format, args );
  157.             vlc_mutex_unlock( &p_input->input.p_item->lock );
  158.             NotifyPlaylist( p_input );
  159.         }
  160.         return VLC_SUCCESS;
  161.         case INPUT_GET_INFO:
  162.         {
  163.             char *psz_cat = (char *)va_arg( args, char * );
  164.             char *psz_name = (char *)va_arg( args, char * );
  165.             char **ppsz_value = (char **)va_arg( args, char ** );
  166.             int i_ret = VLC_EGENERIC;
  167.             int i;
  168.             *ppsz_value = NULL;
  169.             vlc_mutex_lock( &p_input->input.p_item->lock );
  170.             for( i = 0; i < p_input->input.p_item->i_categories; i++ )
  171.             {
  172.                 if( !strcmp( p_input->input.p_item->pp_categories[i]->psz_name,
  173.                              psz_cat ) ) break;
  174.             }
  175.             if( i != p_input->input.p_item->i_categories )
  176.             {
  177.                 info_category_t *p_cat;
  178.                 p_cat = p_input->input.p_item->pp_categories[i];
  179.                 for( i = 0; i < p_cat->i_infos; i++ )
  180.                 {
  181.                     if( !strcmp( p_cat->pp_infos[i]->psz_name, psz_name ) )
  182.                     {
  183.                         if( p_cat->pp_infos[i]->psz_value )
  184.                         {
  185.                             *ppsz_value =strdup(p_cat->pp_infos[i]->psz_value);
  186.                             i_ret = VLC_SUCCESS;
  187.                         }
  188.                         break;
  189.                     }
  190.                 }
  191.             }
  192.             vlc_mutex_unlock( &p_input->input.p_item->lock );
  193.             return i_ret;
  194.         }
  195.         case INPUT_SET_NAME:
  196.         {
  197.             char *psz_name = (char *)va_arg( args, char * );
  198.             if( !psz_name ) return VLC_EGENERIC;
  199.             vlc_mutex_lock( &p_input->input.p_item->lock );
  200.             if( p_input->input.p_item->psz_name )
  201.                 free( p_input->input.p_item->psz_name );
  202.             p_input->input.p_item->psz_name = strdup( psz_name );
  203.             vlc_mutex_unlock( &p_input->input.p_item->lock );
  204.             NotifyPlaylist( p_input );
  205.             return VLC_SUCCESS;
  206.         }
  207.         case INPUT_ADD_BOOKMARK:
  208.             p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
  209.             p_bkmk = vlc_seekpoint_Duplicate( p_bkmk );
  210.             vlc_mutex_lock( &p_input->input.p_item->lock );
  211.             if( !p_bkmk->psz_name )
  212.             {
  213.                  asprintf( &p_bkmk->psz_name, _("Bookmark %i"),
  214.                            p_input->i_bookmark );
  215.             }
  216.             TAB_APPEND( p_input->i_bookmark, p_input->bookmark, p_bkmk );
  217.             /* Reflect the changes on the object var */
  218.             var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
  219.             {
  220.                 vlc_value_t val, text;
  221.                 int i;
  222.                 for( i = 0; i < p_input->i_bookmark; i++ )
  223.                 {
  224.                     val.i_int = i;
  225.                     text.psz_string = p_input->bookmark[i]->psz_name;
  226.                     var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
  227.                                 &val, &text );
  228.                 }
  229.             }
  230.             vlc_mutex_unlock( &p_input->input.p_item->lock );
  231.             UpdateBookmarksOption( p_input );
  232.             return VLC_SUCCESS;
  233.             break;
  234.         case INPUT_CHANGE_BOOKMARK:
  235.             p_bkmk = (seekpoint_t *)va_arg( args, seekpoint_t * );
  236.             i_bkmk = (int)va_arg( args, int );
  237.             vlc_mutex_lock( &p_input->input.p_item->lock );
  238.             if( i_bkmk < p_input->i_bookmark )
  239.             {
  240.                 vlc_value_t val, text;
  241.                 int i;
  242.                 p_input->bookmark[i_bkmk] = p_bkmk;
  243.                 /* Reflect the changes on the object var */
  244.                 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
  245.                 for( i = 0; i < p_input->i_bookmark; i++ )
  246.                 {
  247.                     val.i_int = i;
  248.                     text.psz_string = p_input->bookmark[i]->psz_name;
  249.                     var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
  250.                                 &val, &text );
  251.                 }
  252.             }
  253.             vlc_mutex_unlock( &p_input->input.p_item->lock );
  254.             UpdateBookmarksOption( p_input );
  255.             return VLC_SUCCESS;
  256.             break;
  257.         case INPUT_DEL_BOOKMARK:
  258.             i_bkmk = (int)va_arg( args, int );
  259.             vlc_mutex_lock( &p_input->input.p_item->lock );
  260.             if( i_bkmk < p_input->i_bookmark )
  261.             {
  262.                 vlc_value_t val, text;
  263.                 int i;
  264.                 p_bkmk = p_input->bookmark[i_bkmk];
  265.                 TAB_REMOVE( p_input->i_bookmark, p_input->bookmark,
  266.                             p_bkmk );
  267.                 vlc_seekpoint_Delete( p_bkmk );
  268.                 /* Reflect the changes on the object var */
  269.                 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
  270.                 for( i = 0; i < p_input->i_bookmark; i++ )
  271.                 {
  272.                     val.i_int = i;
  273.                     text.psz_string = p_input->bookmark[i]->psz_name;
  274.                     var_Change( p_input, "bookmark", VLC_VAR_ADDCHOICE,
  275.                                 &val, &text );
  276.                 }
  277.                 vlc_mutex_unlock( &p_input->input.p_item->lock );
  278.                 UpdateBookmarksOption( p_input );
  279.                 return VLC_SUCCESS;
  280.             }
  281.             vlc_mutex_unlock( &p_input->input.p_item->lock );
  282.             return VLC_EGENERIC;
  283.             break;
  284.         case INPUT_GET_BOOKMARKS:
  285.             ppp_bkmk = (seekpoint_t ***)va_arg( args, seekpoint_t *** );
  286.             pi_bkmk = (int *)va_arg( args, int * );
  287.             vlc_mutex_lock( &p_input->input.p_item->lock );
  288.             if( p_input->i_bookmark )
  289.             {
  290.                 int i;
  291.                 *pi_bkmk = p_input->i_bookmark;
  292.                 *ppp_bkmk = malloc( sizeof(seekpoint_t *) *
  293.                                     p_input->i_bookmark );
  294.                 for( i = 0; i < p_input->i_bookmark; i++ )
  295.                 {
  296.                     (*ppp_bkmk)[i] =
  297.                         vlc_seekpoint_Duplicate(p_input->bookmark[i]);
  298.                 }
  299.                 vlc_mutex_unlock( &p_input->input.p_item->lock );
  300.                 return VLC_SUCCESS;
  301.             }
  302.             else
  303.             {
  304.                 *ppp_bkmk = NULL;
  305.                 *pi_bkmk = 0;
  306.                 vlc_mutex_unlock( &p_input->input.p_item->lock );
  307.                 return VLC_EGENERIC;
  308.             }
  309.             break;
  310.         case INPUT_CLEAR_BOOKMARKS:
  311.             vlc_mutex_lock( &p_input->input.p_item->lock );
  312.             if( p_input->i_bookmark )
  313.             {
  314.                 int i;
  315.                 for( i = p_input->i_bookmark - 1; i >= 0; i-- )
  316.                 {
  317.                     p_bkmk = p_input->bookmark[i];
  318.                     TAB_REMOVE( p_input->i_bookmark, p_input->bookmark,
  319.                                 p_bkmk );
  320.                     vlc_seekpoint_Delete( p_bkmk );
  321.                 }
  322.                 var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES, 0, 0 );
  323.             }
  324.             vlc_mutex_unlock( &p_input->input.p_item->lock );
  325.             UpdateBookmarksOption( p_input );
  326.             return VLC_SUCCESS;
  327.             break;
  328.         case INPUT_SET_BOOKMARK:
  329.             i_bkmk = (int)va_arg( args, int );
  330.             vlc_mutex_lock( &p_input->input.p_item->lock );
  331.             if( i_bkmk >= 0 && i_bkmk < p_input->i_bookmark )
  332.             {
  333.                 vlc_value_t pos;
  334.                 int i_ret;
  335.                 if( p_input->bookmark[i_bkmk]->i_time_offset )
  336.                 {
  337.                     pos.i_time = p_input->bookmark[i_bkmk]->i_time_offset;
  338.                     i_ret = var_Set( p_input, "time", pos );
  339.                 }
  340.                 else if( p_input->bookmark[i_bkmk]->i_byte_offset )
  341.                 {
  342.                     pos.f_float = !p_input->input.p_stream ? 0 :
  343.                         p_input->bookmark[i_bkmk]->i_byte_offset /
  344.                         stream_Size( p_input->input.p_stream );
  345.                     i_ret = var_Set( p_input, "position", pos );
  346.                 }
  347.                 else
  348.                 {
  349.                     pos.f_float = 0;
  350.                     i_ret = var_Set( p_input, "position", pos );
  351.                 }
  352.                 vlc_mutex_unlock( &p_input->input.p_item->lock );
  353.                 return i_ret;
  354.             }
  355.             else
  356.             {
  357.                 vlc_mutex_unlock( &p_input->input.p_item->lock );
  358.                 return VLC_EGENERIC;
  359.             }
  360.             break;
  361.         case INPUT_ADD_OPTION:
  362.         {
  363.             char *psz_option = (char *)va_arg( args, char * );
  364.             char *psz_value = (char *)va_arg( args, char * );
  365.             int i;
  366.             vlc_mutex_lock( &p_input->input.p_item->lock );
  367.             /* Check if option already exists */            
  368.             for( i = 0; i < p_input->input.p_item->i_options; i++ )
  369.             {
  370.                 if( !strncmp( p_input->input.p_item->ppsz_options[i],
  371.                               psz_option, strlen( psz_option ) ) &&
  372.                     p_input->input.p_item->ppsz_options[i][strlen(psz_option)]
  373.                       == '=' )
  374.                 {
  375.                     free( p_input->input.p_item->ppsz_options[i] );
  376.                     break;
  377.                 }
  378.             }
  379.             if( i == p_input->input.p_item->i_options )
  380.             {
  381.                 p_input->input.p_item->i_options++;
  382.                 p_input->input.p_item->ppsz_options =
  383.                     realloc( p_input->input.p_item->ppsz_options,
  384.                              p_input->input.p_item->i_options *
  385.                              sizeof(char **) );
  386.             }
  387.             asprintf( &p_input->input.p_item->ppsz_options[i],
  388.                       "%s=%s", psz_option, psz_value ) ;
  389.             vlc_mutex_unlock( &p_input->input.p_item->lock );
  390.             return VLC_SUCCESS;
  391.             break;
  392.         }
  393.         case INPUT_GET_BYTE_POSITION:
  394.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  395.             *pi_64 = !p_input->input.p_stream ? 0 :
  396.                 stream_Tell( p_input->input.p_stream );
  397.             return VLC_SUCCESS;
  398.             break;
  399.         case INPUT_SET_BYTE_SIZE:
  400.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  401.             *pi_64 = !p_input->input.p_stream ? 0 :
  402.                 stream_Size( p_input->input.p_stream );
  403.             return VLC_SUCCESS;
  404.             break;
  405.         default:
  406.             msg_Err( p_input, "unknown query in input_vaControl" );
  407.             return VLC_EGENERIC;
  408.     }
  409. }
  410. static void NotifyPlaylist( input_thread_t *p_input )
  411. {
  412.     playlist_t *p_playlist =
  413.         (playlist_t *)vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
  414.                                        FIND_PARENT );
  415.     if( p_playlist )
  416.     {
  417.         var_SetInteger( p_playlist, "item-change", p_playlist->i_index );
  418.         vlc_object_release( p_playlist );
  419.     }
  420. }
  421. static void UpdateBookmarksOption( input_thread_t *p_input )
  422. {
  423.     int i, i_len = 0;
  424.     char *psz_value = NULL, *psz_next = NULL;
  425.     vlc_mutex_lock( &p_input->input.p_item->lock );
  426.     for( i = 0; i < p_input->i_bookmark; i++ )
  427.     {
  428.         asprintf( &psz_value, "{name=%s,bytes="I64Fd",time="I64Fd"}",
  429.                   p_input->bookmark[i]->psz_name,
  430.                   p_input->bookmark[i]->i_byte_offset,
  431.                   p_input->bookmark[i]->i_time_offset/1000000 );
  432.         i_len += strlen( psz_value );
  433.         free( psz_value );
  434.     }
  435.     for( i = 0; i < p_input->i_bookmark; i++ )
  436.     {
  437.         if( !i ) psz_value = psz_next = malloc( i_len + p_input->i_bookmark );
  438.         sprintf( psz_next, "{name=%s,bytes="I64Fd",time="I64Fd"}",
  439.                  p_input->bookmark[i]->psz_name,
  440.                  p_input->bookmark[i]->i_byte_offset,
  441.                  p_input->bookmark[i]->i_time_offset/1000000 );
  442.         psz_next += strlen( psz_next );
  443.         if( i < p_input->i_bookmark - 1)
  444.         {
  445.             *psz_next = ','; psz_next++;
  446.         }
  447.     }
  448.     vlc_mutex_unlock( &p_input->input.p_item->lock );
  449.     input_Control( p_input, INPUT_ADD_OPTION, "bookmarks",
  450.                    psz_value ? psz_value : "" );
  451. }