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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * input.c: input thread
  3.  *****************************************************************************
  4.  * Copyright (C) 1998-2004 VideoLAN
  5.  * $Id: input.c 9039 2004-10-22 13:49:14Z massiot $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *          Laurent Aimar <fenrir@via.ecp.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <stdlib.h>
  28. #include <ctype.h>
  29. #include <vlc/vlc.h>
  30. #include <vlc/input.h>
  31. #include <vlc/decoder.h>
  32. #include <vlc/vout.h>
  33. #include "input_internal.h"
  34. #include "stream_output.h"
  35. #include "vlc_interface.h"
  36. #include "vlc_meta.h"
  37. /*****************************************************************************
  38.  * Local prototypes
  39.  *****************************************************************************/
  40. static  int Run  ( input_thread_t *p_input );
  41. static  int Init ( input_thread_t *p_input );
  42. static void Error( input_thread_t *p_input );
  43. static void End  ( input_thread_t *p_input );
  44. static inline int ControlPopNoLock( input_thread_t *, int *, vlc_value_t * );
  45. static void       ControlReduce( input_thread_t * );
  46. static vlc_bool_t Control( input_thread_t *, int, vlc_value_t );
  47. static int  UpdateFromAccess( input_thread_t * );
  48. static int  UpdateFromDemux( input_thread_t * );
  49. static void UpdateItemLength( input_thread_t *, int64_t i_length );
  50. static void ParseOption( input_thread_t *p_input, const char *psz_option );
  51. static void DecodeUrl  ( char * );
  52. static void MRLSplit( input_thread_t *, char *, char **, char **, char ** );
  53. static void MRLSections( input_thread_t *, char *, int *, int *, int *, int *);
  54. static input_source_t *InputSourceNew( input_thread_t *);
  55. static int  InputSourceInit( input_thread_t *, input_source_t *,
  56.                              char *, char *psz_forced_demux );
  57. static void InputSourceClean( input_thread_t *, input_source_t * );
  58. static void SlaveDemux( input_thread_t *p_input );
  59. static void SlaveSeek( input_thread_t *p_input );
  60. static vlc_meta_t *InputMetaUser( input_thread_t *p_input );
  61. /*****************************************************************************
  62.  * input_CreateThread: creates a new input thread
  63.  *****************************************************************************
  64.  * This function creates a new input, and returns a pointer
  65.  * to its description. On error, it returns NULL.
  66.  *
  67.  * Variables for _public_ use:
  68.  * * Get and Set:
  69.  *  - state
  70.  *  - rate,rate-slower, rate-faster
  71.  *  - position, position-offset
  72.  *  - time, time-offset
  73.  *  - title,title-next,title-prev
  74.  *  - chapter,chapter-next, chapter-prev
  75.  *  - program, audio-es, video-es, spu-es
  76.  *  - audio-delay, spu-delay
  77.  *  - bookmark
  78.  * * Get only:
  79.  *  - length
  80.  *  - bookmarks
  81.  *  - seekable (if you can seek, it doesn't say if 'bar display' has be shown or not, for that check position != 0.0)
  82.  * * For intf callback upon changes
  83.  *  - intf-change
  84.  * TODO explain when Callback is called
  85.  * TODO complete this list (?)
  86.  *****************************************************************************/
  87. input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
  88.                                       input_item_t *p_item )
  89. {
  90.     input_thread_t *p_input;                        /* thread descriptor */
  91.     vlc_value_t val;
  92.     int i;
  93.     /* Allocate descriptor */
  94.     p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
  95.     if( p_input == NULL )
  96.     {
  97.         msg_Err( p_parent, "out of memory" );
  98.         return NULL;
  99.     }
  100.     /* Init Common fields */
  101.     p_input->b_eof = VLC_FALSE;
  102.     p_input->b_can_pace_control = VLC_TRUE;
  103.     p_input->i_start = 0;
  104.     p_input->i_time  = 0;
  105.     p_input->i_stop  = 0;
  106.     p_input->i_title = 0;
  107.     p_input->title   = NULL;
  108.     p_input->i_title_offset = p_input->i_seekpoint_offset = 0;
  109.     p_input->i_state = INIT_S;
  110.     p_input->i_rate  = INPUT_RATE_DEFAULT;
  111.     p_input->i_bookmark = 0;
  112.     p_input->bookmark = NULL;
  113.     p_input->p_es_out = NULL;
  114.     p_input->p_sout  = NULL;
  115.     p_input->b_out_pace_control = VLC_FALSE;
  116.     p_input->i_pts_delay = 0;
  117.     /* Init Input fields */
  118.     p_input->input.p_item = p_item;
  119.     p_input->input.p_access = NULL;
  120.     p_input->input.p_stream = NULL;
  121.     p_input->input.p_demux  = NULL;
  122.     p_input->input.b_title_demux = VLC_FALSE;
  123.     p_input->input.i_title  = 0;
  124.     p_input->input.title    = NULL;
  125.     p_input->input.i_title_offset = p_input->input.i_seekpoint_offset = 0;
  126.     p_input->input.b_can_pace_control = VLC_TRUE;
  127.     p_input->input.b_eof = VLC_FALSE;
  128.     p_input->input.i_cr_average = 0;
  129.     /* No slave */
  130.     p_input->i_slave = 0;
  131.     p_input->slave   = NULL;
  132.     /* Init control buffer */
  133.     vlc_mutex_init( p_input, &p_input->lock_control );
  134.     p_input->i_control = 0;
  135.     /* Parse input options */
  136.     vlc_mutex_lock( &p_item->lock );
  137.     for( i = 0; i < p_item->i_options; i++ )
  138.     {
  139. //        msg_Dbg( p_input, "option: %s", p_item->ppsz_options[i] );
  140.         ParseOption( p_input, p_item->ppsz_options[i] );
  141.     }
  142.     vlc_mutex_unlock( &p_item->lock );
  143.     /* Create Object Variables for private use only */
  144.     input_ConfigVarInit( p_input );
  145.     /* Create Objects variables for public Get and Set */
  146.     input_ControlVarInit( p_input );
  147.     p_input->input.i_cr_average = var_GetInteger( p_input, "cr-average" );
  148.     /* TODO */
  149.     var_Get( p_input, "bookmarks", &val );
  150.     if( val.psz_string )
  151.     {
  152.         /* FIXME: have a common cfg parsing routine used by sout and others */
  153.         char *psz_parser, *psz_start, *psz_end;
  154.         psz_parser = val.psz_string;
  155.         while( (psz_start = strchr( psz_parser, '{' ) ) )
  156.         {
  157.             seekpoint_t seekpoint;
  158.             char backup;
  159.             psz_start++;
  160.             psz_end = strchr( psz_start, '}' );
  161.             if( !psz_end ) break;
  162.             psz_parser = psz_end + 1;
  163.             backup = *psz_parser;
  164.             *psz_parser = 0;
  165.             *psz_end = ',';
  166.             seekpoint.psz_name = 0;
  167.             seekpoint.i_byte_offset = 0;
  168.             seekpoint.i_time_offset = 0;
  169.             while( (psz_end = strchr( psz_start, ',' ) ) )
  170.             {
  171.                 *psz_end = 0;
  172.                 if( !strncmp( psz_start, "name=", 5 ) )
  173.                 {
  174.                     seekpoint.psz_name = psz_start + 5;
  175.                 }
  176.                 else if( !strncmp( psz_start, "bytes=", 6 ) )
  177.                 {
  178.                     seekpoint.i_byte_offset = atoll(psz_start + 6);
  179.                 }
  180.                 else if( !strncmp( psz_start, "time=", 5 ) )
  181.                 {
  182.                     seekpoint.i_time_offset = atoll(psz_start + 5) * 1000000;
  183.                 }
  184.                 psz_start = psz_end + 1;
  185.             }
  186.             msg_Dbg( p_input, "adding bookmark: %s, bytes="I64Fd", time="I64Fd,
  187.                      seekpoint.psz_name, seekpoint.i_byte_offset,
  188.                      seekpoint.i_time_offset );
  189.             input_Control( p_input, INPUT_ADD_BOOKMARK, &seekpoint );
  190.             *psz_parser = backup;
  191.         }
  192.         free( val.psz_string );
  193.     }
  194.     /* Now we can attach our new input */
  195.     vlc_object_attach( p_input, p_parent );
  196.     /* Create thread and wait for its readiness. */
  197.     if( vlc_thread_create( p_input, "input", Run,
  198.                            VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
  199.     {
  200.         msg_Err( p_input, "cannot create input thread" );
  201.         vlc_object_detach( p_input );
  202.         vlc_object_destroy( p_input );
  203.         return NULL;
  204.     }
  205.     return p_input;
  206. }
  207. /*****************************************************************************
  208.  * input_StopThread: mark an input thread as zombie
  209.  *****************************************************************************
  210.  * This function should not return until the thread is effectively cancelled.
  211.  *****************************************************************************/
  212. void input_StopThread( input_thread_t *p_input )
  213. {
  214.     vlc_list_t *p_list;
  215.     int i;
  216.     /* Set die for input */
  217.     p_input->b_die = VLC_TRUE;
  218.     /* We cannot touch p_input fields directly (we can from another thread),
  219.      * so use the vlc_object_find way, it's perfectly safe */
  220.     /* Set die for all access */
  221.     p_list = vlc_list_find( p_input, VLC_OBJECT_ACCESS, FIND_CHILD );
  222.     for( i = 0; i < p_list->i_count; i++ )
  223.     {
  224.         p_list->p_values[i].p_object->b_die = VLC_TRUE;
  225.     }
  226.     vlc_list_release( p_list );
  227.     /* Set die for all stream */
  228.     p_list = vlc_list_find( p_input, VLC_OBJECT_STREAM, FIND_CHILD );
  229.     for( i = 0; i < p_list->i_count; i++ )
  230.     {
  231.         p_list->p_values[i].p_object->b_die = VLC_TRUE;
  232.     }
  233.     vlc_list_release( p_list );
  234.     /* Set die for all demux */
  235.     p_list = vlc_list_find( p_input, VLC_OBJECT_DEMUX, FIND_CHILD );
  236.     for( i = 0; i < p_list->i_count; i++ )
  237.     {
  238.         p_list->p_values[i].p_object->b_die = VLC_TRUE;
  239.     }
  240.     vlc_list_release( p_list );
  241.     input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
  242. }
  243. /*****************************************************************************
  244.  * input_DestroyThread: mark an input thread as zombie
  245.  *****************************************************************************
  246.  * This function should not return until the thread is effectively cancelled.
  247.  *****************************************************************************/
  248. void input_DestroyThread( input_thread_t *p_input )
  249. {
  250.     /* Join the thread */
  251.     vlc_thread_join( p_input );
  252.     /* Delete input lock (only after thread joined) */
  253.     vlc_mutex_destroy( &p_input->lock_control );
  254.     /* TODO: maybe input_DestroyThread should also delete p_input instead
  255.      * of the playlist but I'm not sure if it's possible */
  256. }
  257. /*****************************************************************************
  258.  * Run: main thread loop
  259.  *****************************************************************************
  260.  * Thread in charge of processing the network packets and demultiplexing.
  261.  *
  262.  * TODO:
  263.  *  read subtitle support (XXX take care of spu-delay in the right way).
  264.  *  multi-input support (XXX may be done with subs)
  265.  *****************************************************************************/
  266. static int Run( input_thread_t *p_input )
  267. {
  268.     int64_t i_intf_update = 0;
  269.     /* Signal that the thread is launched */
  270.     vlc_thread_ready( p_input );
  271.     if( Init( p_input ) )
  272.     {
  273.         /* If we failed, wait before we are killed, and exit */
  274.         p_input->b_error = VLC_TRUE;
  275.         Error( p_input );
  276.         /* Tell we're dead */
  277.         p_input->b_dead = VLC_TRUE;
  278.         return 0;
  279.     }
  280.     /* Main loop */
  281.     while( !p_input->b_die && !p_input->b_error && !p_input->input.b_eof )
  282.     {
  283.         vlc_bool_t b_force_update = VLC_FALSE;
  284.         int i_ret;
  285.         int i_type;
  286.         vlc_value_t val;
  287.         /* Do the read */
  288.         if( p_input->i_state != PAUSE_S  )
  289.         {
  290.             if( p_input->i_stop <= 0 || p_input->i_time < p_input->i_stop )
  291.                 i_ret=p_input->input.p_demux->pf_demux(p_input->input.p_demux);
  292.             else
  293.                 i_ret = 0;  /* EOF */
  294.             if( i_ret > 0 )
  295.             {
  296.                 /* TODO */
  297.                 if( p_input->input.b_title_demux &&
  298.                     p_input->input.p_demux->info.i_update )
  299.                 {
  300.                     i_ret = UpdateFromDemux( p_input );
  301.                     b_force_update = VLC_TRUE;
  302.                 }
  303.                 else if( !p_input->input.b_title_demux &&
  304.                           p_input->input.p_access &&
  305.                           p_input->input.p_access->info.i_update )
  306.                 {
  307.                     i_ret = UpdateFromAccess( p_input );
  308.                     b_force_update = VLC_TRUE;
  309.                 }
  310.             }
  311.             if( i_ret == 0 )    /* EOF */
  312.             {
  313.                 vlc_value_t repeat;
  314.                 var_Get( p_input, "input-repeat", &repeat );
  315.                 if( repeat.i_int == 0 )
  316.                 {
  317.                     /* End of file - we do not set b_die because only the
  318.                      * playlist is allowed to do so. */
  319.                     msg_Dbg( p_input, "EOF reached" );
  320.                     p_input->input.b_eof = VLC_TRUE;
  321.                 }
  322.                 else
  323.                 {
  324.                     msg_Dbg( p_input, "repeating the same input (%d)",
  325.                              repeat.i_int );
  326.                     if( repeat.i_int > 0 )
  327.                     {
  328.                         repeat.i_int--;
  329.                         var_Set( p_input, "input-repeat", repeat );
  330.                     }
  331.                     /* Seek to start title/seekpoint */
  332.                     val.i_int = p_input->input.i_title_start -
  333.                         p_input->input.i_title_offset;
  334.                     if( val.i_int < 0 || val.i_int >= p_input->input.i_title )
  335.                         val.i_int = 0;
  336.                     input_ControlPush( p_input,
  337.                                        INPUT_CONTROL_SET_TITLE, &val );
  338.                     val.i_int = p_input->input.i_seekpoint_start -
  339.                         p_input->input.i_seekpoint_offset;
  340.                     if( val.i_int > 0 /* TODO: check upper boundary */ )
  341.                         input_ControlPush( p_input,
  342.                                            INPUT_CONTROL_SET_SEEKPOINT, &val );
  343.                     /* Seek to start position */
  344.                     if( p_input->i_start > 0 )
  345.                     {
  346.                         val.i_time = p_input->i_start;
  347.                         input_ControlPush( p_input, INPUT_CONTROL_SET_TIME,
  348.                                            &val );
  349.                     }
  350.                     else
  351.                     {
  352.                         val.f_float = 0.0;
  353.                         input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION,
  354.                                            &val );
  355.                     }
  356.                 }
  357.             }
  358.             else if( i_ret < 0 )
  359.             {
  360.                 p_input->b_error = VLC_TRUE;
  361.             }
  362.             if( i_ret > 0 && p_input->i_slave > 0 )
  363.             {
  364.                 SlaveDemux( p_input );
  365.             }
  366.         }
  367.         else
  368.         {
  369.             /* Small wait */
  370.             msleep( 10*1000 );
  371.         }
  372.         /* Handle control */
  373.         vlc_mutex_lock( &p_input->lock_control );
  374.         ControlReduce( p_input );
  375.         while( !ControlPopNoLock( p_input, &i_type, &val ) )
  376.         {
  377.             msg_Dbg( p_input, "control type=%d", i_type );
  378.             if( Control( p_input, i_type, val ) )
  379.                 b_force_update = VLC_TRUE;
  380.         }
  381.         vlc_mutex_unlock( &p_input->lock_control );
  382.         if( b_force_update || i_intf_update < mdate() )
  383.         {
  384.             vlc_value_t val;
  385.             double f_pos;
  386.             int64_t i_time, i_length;
  387.             /* update input status variables */
  388.             if( !demux2_Control( p_input->input.p_demux,
  389.                                  DEMUX_GET_POSITION, &f_pos ) )
  390.             {
  391.                 val.f_float = (float)f_pos;
  392.                 var_Change( p_input, "position", VLC_VAR_SETVALUE, &val, NULL );
  393.             }
  394.             if( !demux2_Control( p_input->input.p_demux,
  395.                                  DEMUX_GET_TIME, &i_time ) )
  396.             {
  397.                 p_input->i_time = i_time;
  398.                 val.i_time = i_time;
  399.                 var_Change( p_input, "time", VLC_VAR_SETVALUE, &val, NULL );
  400.             }
  401.             if( !demux2_Control( p_input->input.p_demux,
  402.                                  DEMUX_GET_LENGTH, &i_length ) )
  403.             {
  404.                 vlc_value_t old_val;
  405.                 var_Get( p_input, "length", &old_val );
  406.                 val.i_time = i_length;
  407.                 var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
  408.                 if( old_val.i_time != val.i_time )
  409.                 {
  410.                     UpdateItemLength( p_input, i_length );
  411.                 }
  412.             }
  413.             var_SetBool( p_input, "intf-change", VLC_TRUE );
  414.             i_intf_update = mdate() + I64C(150000);
  415.         }
  416.     }
  417.     if( !p_input->b_eof && !p_input->b_error && p_input->input.b_eof )
  418.     {
  419.         /* We have finish to demux data but not to play them */
  420.         while( !p_input->b_die )
  421.         {
  422.             if( input_EsOutDecodersEmpty( p_input->p_es_out ) )
  423.                 break;
  424.             msg_Dbg( p_input, "waiting decoder fifos to empty" );
  425.             msleep( INPUT_IDLE_SLEEP );
  426.         }
  427.         /* We have finished */
  428.         p_input->b_eof = VLC_TRUE;
  429.     }
  430.     /* Wait we are asked to die */
  431.     if( !p_input->b_die )
  432.     {
  433.         Error( p_input );
  434.     }
  435.     /* Clean up */
  436.     End( p_input );
  437.     return 0;
  438. }
  439. /*****************************************************************************
  440.  * Init: init the input Thread
  441.  *****************************************************************************/
  442. static int Init( input_thread_t * p_input )
  443. {
  444.     char *psz;
  445.     char *psz_subtitle;
  446.     vlc_value_t val;
  447.     double f_fps;
  448.     vlc_meta_t *p_meta, *p_meta_user;
  449.     int i_es_out_mode;
  450.     int i, i_delay;
  451.     /* Initialize optional stream output. (before access/demuxer) */
  452.     psz = var_GetString( p_input, "sout" );
  453.     if( *psz )
  454.     {
  455.         p_input->p_sout = sout_NewInstance( p_input, psz );
  456.         if( p_input->p_sout == NULL )
  457.         {
  458.             msg_Err( p_input, "cannot start stream output instance, aborting" );
  459.             free( psz );
  460.             return VLC_EGENERIC;
  461.         }
  462.     }
  463.     free( psz );
  464.     /* Create es out */
  465.     p_input->p_es_out = input_EsOutNew( p_input );
  466.     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_FALSE );
  467.     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
  468.     if( InputSourceInit( p_input, &p_input->input,
  469.                          p_input->input.p_item->psz_uri, NULL ) )
  470.     {
  471.         goto error;
  472.     }
  473.     /* Create global title (from master) */
  474.     p_input->i_title = p_input->input.i_title;
  475.     p_input->title   = p_input->input.title;
  476.     p_input->i_title_offset = p_input->input.i_title_offset;
  477.     p_input->i_seekpoint_offset = p_input->input.i_seekpoint_offset;
  478.     if( p_input->i_title > 0 )
  479.     {
  480.         /* Setup variables */
  481.         input_ControlVarNavigation( p_input );
  482.         input_ControlVarTitle( p_input, 0 );
  483.     }
  484.     /* Global flag */
  485.     p_input->b_can_pace_control = p_input->input.b_can_pace_control;
  486.     p_input->b_can_pause        = p_input->input.b_can_pause;
  487.     /* Fix pts delay */
  488.     if( p_input->i_pts_delay <= 0 )
  489.         p_input->i_pts_delay = DEFAULT_PTS_DELAY;
  490.     /* If the desynchronisation requested by the user is < 0, we need to
  491.      * cache more data. */
  492.     var_Get( p_input, "audio-desync", &val );
  493.     if( val.i_int < 0 ) p_input->i_pts_delay -= (val.i_int * 1000);
  494.     /* Update cr_average depending on the caching */
  495.     p_input->input.i_cr_average *= (10 * p_input->i_pts_delay / 200000);
  496.     p_input->input.i_cr_average /= 10;
  497.     if( p_input->input.i_cr_average <= 0 ) p_input->input.i_cr_average = 1;
  498.     /* Load master infos */
  499.     /* Init length */
  500.     if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_LENGTH,
  501.                          &val.i_time ) && val.i_time > 0 )
  502.     {
  503.         var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
  504.         UpdateItemLength( p_input, val.i_time );
  505.     }
  506.     /* Start title/chapter */
  507.     val.i_int = p_input->input.i_title_start -
  508.         p_input->input.i_title_offset;
  509.     if( val.i_int > 0 && val.i_int < p_input->input.i_title )
  510.         input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val );
  511.     val.i_int = p_input->input.i_seekpoint_start -
  512.         p_input->input.i_seekpoint_offset;
  513.     if( val.i_int > 0 /* TODO: check upper boundary */ )
  514.         input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val );
  515.     /* Start time*/
  516.     /* Set start time */
  517.     p_input->i_start = (int64_t)var_GetInteger( p_input, "start-time" ) *
  518.                        I64C(1000000);
  519.     p_input->i_stop  = (int64_t)var_GetInteger( p_input, "stop-time" ) *
  520.                        I64C(1000000);
  521.     if( p_input->i_start > 0 )
  522.     {
  523.         if( p_input->i_start >= val.i_time )
  524.         {
  525.             msg_Warn( p_input, "invalid start-time ignored" );
  526.         }
  527.         else
  528.         {
  529.             vlc_value_t s;
  530.             msg_Dbg( p_input, "start-time: %ds",
  531.                      (int)( p_input->i_start / I64C(1000000) ) );
  532.             s.i_time = p_input->i_start;
  533.             input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &s );
  534.         }
  535.     }
  536.     if( p_input->i_stop > 0 && p_input->i_stop <= p_input->i_start )
  537.     {
  538.         msg_Warn( p_input, "invalid stop-time ignored" );
  539.         p_input->i_stop = 0;
  540.     }
  541.     /* Load subtitles */
  542.     /* Get fps and set it if not already set */
  543.     if( !demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) &&
  544.         f_fps > 1.0 )
  545.     {
  546.         vlc_value_t fps;
  547.         float f_requested_fps;
  548.         var_Create( p_input, "sub-original-fps", VLC_VAR_FLOAT );
  549.         var_SetFloat( p_input, "sub-original-fps", f_fps );
  550.         f_requested_fps = var_CreateGetFloat( p_input, "sub-fps" );
  551.         if( f_requested_fps != f_fps )
  552.         {
  553.             var_Create( p_input, "sub-fps", VLC_VAR_FLOAT| VLC_VAR_DOINHERIT );
  554.             var_SetFloat( p_input, "sub-fps", f_requested_fps );
  555.         }
  556.     }
  557.     i_delay = var_CreateGetInteger( p_input, "sub-delay" );
  558.     if( i_delay != 0 )
  559.     {
  560.         var_SetTime( p_input, "spu-delay", (mtime_t)i_delay * 100000 );
  561.     }
  562.     /* Look for and add subtitle files */
  563.     psz_subtitle = var_GetString( p_input, "sub-file" );
  564.     if( *psz_subtitle )
  565.     {
  566.         input_source_t *sub;
  567.         vlc_value_t count;
  568.         vlc_value_t list;
  569.         msg_Dbg( p_input, "forced subtitle: %s", psz_subtitle );
  570.         var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &count, NULL );
  571.         /* */
  572.         sub = InputSourceNew( p_input );
  573.         if( !InputSourceInit( p_input, sub, psz_subtitle, "subtitle" ) )
  574.         {
  575.             TAB_APPEND( p_input->i_slave, p_input->slave, sub );
  576.             /* Select the ES */
  577.             if( !var_Change( p_input, "spu-es", VLC_VAR_GETLIST, &list, NULL ) )
  578.             {
  579.                 if( count.i_int == 0 )
  580.                     count.i_int++;  /* if it was first one, there is disable too */
  581.                 if( count.i_int < list.p_list->i_count )
  582.                 {
  583.                     input_ControlPush( p_input, INPUT_CONTROL_SET_ES,
  584.                                        &list.p_list->p_values[count.i_int] );
  585.                 }
  586.                 var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL );
  587.             }
  588.         }
  589.     }
  590.     var_Get( p_input, "sub-autodetect-file", &val );
  591.     if( val.b_bool )
  592.     {
  593.         char *psz_autopath = var_GetString( p_input, "sub-autodetect-path" );
  594.         char **subs = subtitles_Detect( p_input, psz_autopath,
  595.                                         p_input->input.p_item->psz_uri );
  596.         input_source_t *sub;
  597.         for( i = 0; subs[i] != NULL; i++ )
  598.         {
  599.             if( strcmp( psz_subtitle, subs[i] ) )
  600.             {
  601.                 sub = InputSourceNew( p_input );
  602.                 if( !InputSourceInit( p_input, sub, subs[i], "subtitle" ) )
  603.                 {
  604.                     TAB_APPEND( p_input->i_slave, p_input->slave, sub );
  605.                 }
  606.             }
  607.             free( subs[i] );
  608.         }
  609.         free( subs );
  610.         free( psz_autopath );
  611.     }
  612.     free( psz_subtitle );
  613.     /* Look for slave */
  614.     psz = var_GetString( p_input, "input-slave" );
  615.     if( *psz )
  616.     {
  617.         char *psz_delim = strchr( psz, '#' );
  618.         for( ;; )
  619.         {
  620.             input_source_t *slave;
  621.             if( psz_delim )
  622.             {
  623.                 *psz_delim++ = '';
  624.             }
  625.             if( *psz == '' )
  626.             {
  627.                 if( psz_delim )
  628.                     continue;
  629.                 else
  630.                     break;
  631.             }
  632.             msg_Dbg( p_input, "adding slave '%s'", psz );
  633.             slave = InputSourceNew( p_input );
  634.             if( !InputSourceInit( p_input, slave, psz, NULL ) )
  635.             {
  636.                 TAB_APPEND( p_input->i_slave, p_input->slave, slave );
  637.             }
  638.             if( !psz_delim )
  639.                 break;
  640.         }
  641.     }
  642.     free( psz );
  643.     /* Set up es_out */
  644.     es_out_Control( p_input->p_es_out, ES_OUT_SET_ACTIVE, VLC_TRUE );
  645.     i_es_out_mode = ES_OUT_MODE_AUTO;
  646.     val.p_list = NULL;
  647.     if( p_input->p_sout )
  648.     {
  649.         var_Get( p_input, "sout-all", &val );
  650.         if ( val.b_bool )
  651.         {
  652.             i_es_out_mode = ES_OUT_MODE_ALL;
  653.             val.p_list = NULL;
  654.         }
  655.         else
  656.         {
  657.             var_Get( p_input, "programs", &val );
  658.             if ( val.p_list && val.p_list->i_count )
  659.             {
  660.                 i_es_out_mode = ES_OUT_MODE_PARTIAL;
  661.                 /* Note : we should remove the "program" callback. */
  662.             }
  663.             else
  664.                 var_Change( p_input, "programs", VLC_VAR_FREELIST, &val, NULL );
  665.         }
  666.     }
  667.     es_out_Control( p_input->p_es_out, ES_OUT_SET_MODE, i_es_out_mode );
  668.     /* Inform the demuxer about waited group (needed only for DVB) */
  669.     if( i_es_out_mode == ES_OUT_MODE_ALL )
  670.     {
  671.         demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, -1, NULL );
  672.     }
  673.     else if( i_es_out_mode == ES_OUT_MODE_PARTIAL )
  674.     {
  675.         demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, -1,
  676.                         val.p_list );
  677.     }
  678.     else
  679.     {
  680.         demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP,
  681.                        (int) var_GetInteger( p_input, "program" ), NULL );
  682.     }
  683.     if( p_input->p_sout )
  684.     {
  685.         if( p_input->p_sout->i_out_pace_nocontrol > 0 )
  686.         {
  687.             p_input->b_out_pace_control = VLC_FALSE;
  688.         }
  689.         else
  690.         {
  691.             p_input->b_out_pace_control = VLC_TRUE;
  692.         }
  693.         msg_Dbg( p_input, "starting in %s mode",
  694.                  p_input->b_out_pace_control ? "asynch" : "synch" );
  695.     }
  696.     /* Get meta data from users */
  697.     p_meta_user = InputMetaUser( p_input );
  698.     /* Get meta data from master input */
  699.     if( demux2_Control( p_input->input.p_demux, DEMUX_GET_META, &p_meta ) )
  700.         p_meta = NULL;
  701.     /* Merge them */
  702.     if( p_meta == NULL )
  703.     {
  704.         p_meta = p_meta_user;
  705.     }
  706.     else if( p_meta_user )
  707.     {
  708.         vlc_meta_Merge( p_meta, p_meta_user );
  709.         vlc_meta_Delete( p_meta_user );
  710.     }
  711.     /* Get meta data from slave input */
  712.     for( i = 0; i < p_input->i_slave; i++ )
  713.     {
  714.         vlc_meta_t *p_meta_slave;
  715.         if( !demux2_Control( p_input->slave[i]->p_demux, DEMUX_GET_META, &p_meta_slave ) )
  716.         {
  717.             if( p_meta == NULL )
  718.             {
  719.                 p_meta = p_meta_slave;
  720.             }
  721.             else if( p_meta_slave )
  722.             {
  723.                 vlc_meta_Merge( p_meta, p_meta_slave );
  724.                 vlc_meta_Delete( p_meta_slave );
  725.             }
  726.         }
  727.     }
  728.     if( p_meta && p_meta->i_meta > 0 )
  729.     {
  730.         msg_Dbg( p_input, "meta information:" );
  731.         for( i = 0; i < p_meta->i_meta; i++ )
  732.         {
  733.             msg_Dbg( p_input, "  - '%s' = '%s'",
  734.                     _(p_meta->name[i]), p_meta->value[i] );
  735.             if( !strcmp(p_meta->name[i], VLC_META_TITLE) && p_meta->value[i] )
  736.                 input_Control( p_input, INPUT_SET_NAME, p_meta->value[i] );
  737.             if( !strcmp( p_meta->name[i], VLC_META_AUTHOR ) )
  738.                 input_Control( p_input, INPUT_ADD_INFO, _("General"),
  739.                                _("Author"), p_meta->value[i] );
  740.             input_Control( p_input, INPUT_ADD_INFO, _("Meta-information"),
  741.                           _(p_meta->name[i]), "%s", p_meta->value[i] );
  742.         }
  743.         for( i = 0; i < p_meta->i_track; i++ )
  744.         {
  745.             vlc_meta_t *tk = p_meta->track[i];
  746.             int j;
  747.             if( tk->i_meta > 0 )
  748.             {
  749.                 char *psz_cat = malloc( strlen(_("Stream")) + 10 );
  750.                 msg_Dbg( p_input, "  - track[%d]:", i );
  751.                 sprintf( psz_cat, "%s %d", _("Stream"), i );
  752.                 for( j = 0; j < tk->i_meta; j++ )
  753.                 {
  754.                     msg_Dbg( p_input, "     - '%s' = '%s'", _(tk->name[j]),
  755.                              tk->value[j] );
  756.                     input_Control( p_input, INPUT_ADD_INFO, psz_cat,
  757.                                    _(tk->name[j]), "%s", tk->value[j] );
  758.                 }
  759.             }
  760.         }
  761.         if( p_input->p_sout && p_input->p_sout->p_meta == NULL )
  762.         {
  763.             p_input->p_sout->p_meta = p_meta;
  764.         }
  765.         else
  766.         {
  767.             vlc_meta_Delete( p_meta );
  768.         }
  769.     }
  770.     else if( p_meta ) vlc_meta_Delete( p_meta );
  771.     msg_Dbg( p_input, "`%s' sucessfully opened",
  772.              p_input->input.p_item->psz_uri );
  773.     /* initialization is complete */
  774.     p_input->i_state = PLAYING_S;
  775.     val.i_int = PLAYING_S;
  776.     var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
  777.     return VLC_SUCCESS;
  778. error:
  779.     if( p_input->p_es_out )
  780.         input_EsOutDelete( p_input->p_es_out );
  781.     if( p_input->p_sout )
  782.         sout_DeleteInstance( p_input->p_sout );
  783.     /* Mark them deleted */
  784.     p_input->input.p_demux = NULL;
  785.     p_input->input.p_stream = NULL;
  786.     p_input->input.p_access = NULL;
  787.     p_input->p_es_out = NULL;
  788.     p_input->p_sout = NULL;
  789.     return VLC_EGENERIC;
  790. }
  791. /*****************************************************************************
  792.  * Error: RunThread() error loop
  793.  *****************************************************************************
  794.  * This function is called when an error occurred during thread main's loop.
  795.  *****************************************************************************/
  796. static void Error( input_thread_t *p_input )
  797. {
  798.     while( !p_input->b_die )
  799.     {
  800.         /* Sleep a while */
  801.         msleep( INPUT_IDLE_SLEEP );
  802.     }
  803. }
  804. /*****************************************************************************
  805.  * End: end the input thread
  806.  *****************************************************************************/
  807. static void End( input_thread_t * p_input )
  808. {
  809.     vlc_value_t val;
  810.     int i;
  811.     msg_Dbg( p_input, "closing input" );
  812.     /* We are at the end */
  813.     p_input->i_state = END_S;
  814.     val.i_int = END_S;
  815.     var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
  816.     /* Clean control variables */
  817.     input_ControlVarClean( p_input );
  818.     /* Clean up master */
  819.     InputSourceClean( p_input, &p_input->input );
  820.     /* Delete slave */
  821.     for( i = 0; i < p_input->i_slave; i++ )
  822.     {
  823.         InputSourceClean( p_input, p_input->slave[i] );
  824.         free( p_input->slave[i] );
  825.     }
  826.     if( p_input->slave ) free( p_input->slave );
  827.     /* Unload all modules */
  828.     if( p_input->p_es_out )
  829.         input_EsOutDelete( p_input->p_es_out );
  830.     /* Close optional stream output instance */
  831.     if( p_input->p_sout )
  832.     {
  833.         vlc_object_t *p_pl =
  834.             vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
  835.         vlc_value_t keep;
  836.         if( var_Get( p_input, "sout-keep", &keep ) >= 0 && keep.b_bool && p_pl )
  837.         {
  838.             /* attach sout to the playlist */
  839.             msg_Warn( p_input, "keeping sout" );
  840.             vlc_object_detach( p_input->p_sout );
  841.             vlc_object_attach( p_input->p_sout, p_pl );
  842.         }
  843.         else
  844.         {
  845.             msg_Warn( p_input, "destroying sout" );
  846.             sout_DeleteInstance( p_input->p_sout );
  847.         }
  848.         if( p_pl )
  849.             vlc_object_release( p_pl );
  850.     }
  851.     /* Tell we're dead */
  852.     p_input->b_dead = VLC_TRUE;
  853. }
  854. /*****************************************************************************
  855.  * Control
  856.  *****************************************************************************/
  857. static inline int ControlPopNoLock( input_thread_t *p_input,
  858.                                     int *pi_type, vlc_value_t *p_val )
  859. {
  860.     if( p_input->i_control <= 0 )
  861.     {
  862.         return VLC_EGENERIC;
  863.     }
  864.     *pi_type = p_input->control[0].i_type;
  865.     *p_val   = p_input->control[0].val;
  866.     p_input->i_control--;
  867.     if( p_input->i_control > 0 )
  868.     {
  869.         int i;
  870.         for( i = 0; i < p_input->i_control; i++ )
  871.         {
  872.             p_input->control[i].i_type = p_input->control[i+1].i_type;
  873.             p_input->control[i].val    = p_input->control[i+1].val;
  874.         }
  875.     }
  876.     return VLC_SUCCESS;
  877. }
  878. static void ControlReduce( input_thread_t *p_input )
  879. {
  880.     int i;
  881.     for( i = 1; i < p_input->i_control; i++ )
  882.     {
  883.         const int i_lt = p_input->control[i-1].i_type;
  884.         const int i_ct = p_input->control[i].i_type;
  885.         /* XXX We can't merge INPUT_CONTROL_SET_ES */
  886.         msg_Dbg( p_input, "[%d/%d] l=%d c=%d", i, p_input->i_control,
  887.                  i_lt, i_ct );
  888.         if( i_lt == i_ct &&
  889.             ( i_ct == INPUT_CONTROL_SET_STATE ||
  890.               i_ct == INPUT_CONTROL_SET_RATE ||
  891.               i_ct == INPUT_CONTROL_SET_POSITION ||
  892.               i_ct == INPUT_CONTROL_SET_TIME ||
  893.               i_ct == INPUT_CONTROL_SET_PROGRAM ||
  894.               i_ct == INPUT_CONTROL_SET_TITLE ||
  895.               i_ct == INPUT_CONTROL_SET_SEEKPOINT ||
  896.               i_ct == INPUT_CONTROL_SET_BOOKMARK ) )
  897.         {
  898.             int j;
  899.             msg_Dbg( p_input, "merged at %d", i );
  900.             /* Remove the i-1 */
  901.             for( j = i; j <  p_input->i_control; j++ )
  902.                 p_input->control[j-1] = p_input->control[j];
  903.             p_input->i_control--;
  904.         }
  905.         else
  906.         {
  907.             /* TODO but that's not that important
  908.                 - merge SET_X with SET_X_CMD
  909.                 - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before a SET_TITLE
  910.                 - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before another among them
  911.                 - ?
  912.                 */
  913.         }
  914.     }
  915. }
  916. static vlc_bool_t Control( input_thread_t *p_input, int i_type,
  917.                            vlc_value_t val )
  918. {
  919.     vlc_bool_t b_force_update = VLC_FALSE;
  920.     switch( i_type )
  921.     {
  922.         case INPUT_CONTROL_SET_DIE:
  923.             msg_Dbg( p_input, "control: INPUT_CONTROL_SET_DIE proceed" );
  924.             /* Mark all submodules to die */
  925.             if( p_input->input.p_access )
  926.                 p_input->input.p_access->b_die = VLC_TRUE;
  927.             if( p_input->input.p_stream )
  928.                 p_input->input.p_stream->b_die = VLC_TRUE;
  929.             p_input->input.p_demux->b_die = VLC_TRUE;
  930.             p_input->b_die = VLC_TRUE;
  931.             break;
  932.         case INPUT_CONTROL_SET_POSITION:
  933.         case INPUT_CONTROL_SET_POSITION_OFFSET:
  934.         {
  935.             double f_pos;
  936.             if( i_type == INPUT_CONTROL_SET_POSITION )
  937.             {
  938.                 f_pos = val.f_float;
  939.             }
  940.             else
  941.             {
  942.                 /* Should not fail */
  943.                 demux2_Control( p_input->input.p_demux,
  944.                                 DEMUX_GET_POSITION, &f_pos );
  945.                 f_pos += val.f_float;
  946.             }
  947.             if( f_pos < 0.0 ) f_pos = 0.0;
  948.             if( f_pos > 1.0 ) f_pos = 1.0;
  949.             if( demux2_Control( p_input->input.p_demux, DEMUX_SET_POSITION,
  950.                                 f_pos ) )
  951.             {
  952.                 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION(_OFFSET) "
  953.                          "%2.1f%% failed", f_pos * 100 );
  954.             }
  955.             else
  956.             {
  957.                 if( p_input->i_slave > 0 )
  958.                     SlaveSeek( p_input );
  959.                 input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
  960.                 es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
  961.                 b_force_update = VLC_TRUE;
  962.             }
  963.             break;
  964.         }
  965.         case INPUT_CONTROL_SET_TIME:
  966.         case INPUT_CONTROL_SET_TIME_OFFSET:
  967.         {
  968.             int64_t i_time;
  969.             int i_ret;
  970.             if( i_type == INPUT_CONTROL_SET_TIME )
  971.             {
  972.                 i_time = val.i_time;
  973.             }
  974.             else
  975.             {
  976.                 /* Should not fail */
  977.                 demux2_Control( p_input->input.p_demux,
  978.                                 DEMUX_GET_TIME, &i_time );
  979.                 i_time += val.i_time;
  980.             }
  981.             if( i_time < 0 ) i_time = 0;
  982.             i_ret = demux2_Control( p_input->input.p_demux,
  983.                                     DEMUX_SET_TIME, i_time );
  984.             if( i_ret )
  985.             {
  986.                 int64_t i_length;
  987.                 /* Emulate it with a SET_POS */
  988.                 demux2_Control( p_input->input.p_demux,
  989.                                 DEMUX_GET_LENGTH, &i_length );
  990.                 if( i_length > 0 )
  991.                 {
  992.                     double f_pos = (double)i_time / (double)i_length;
  993.                     i_ret = demux2_Control( p_input->input.p_demux,
  994.                                             DEMUX_SET_POSITION, f_pos );
  995.                 }
  996.             }
  997.             if( i_ret )
  998.             {
  999.                 msg_Err( p_input, "INPUT_CONTROL_SET_TIME(_OFFSET) "I64Fd
  1000.                          " failed", i_time );
  1001.             }
  1002.             else
  1003.             {
  1004.                 if( p_input->i_slave > 0 )
  1005.                     SlaveSeek( p_input );
  1006.                 input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
  1007.                 es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
  1008.                 b_force_update = VLC_TRUE;
  1009.             }
  1010.             break;
  1011.         }
  1012.         case INPUT_CONTROL_SET_STATE:
  1013.             if( ( val.i_int == PLAYING_S && p_input->i_state == PAUSE_S ) ||
  1014.                 ( val.i_int == PAUSE_S && p_input->i_state == PAUSE_S ) )
  1015.             {
  1016.                 int i_ret;
  1017.                 if( p_input->input.p_access )
  1018.                     i_ret = access2_Control( p_input->input.p_access,
  1019.                                              ACCESS_SET_PAUSE_STATE, VLC_FALSE );
  1020.                 else
  1021.                     i_ret = demux2_Control( p_input->input.p_demux,
  1022.                                             DEMUX_SET_PAUSE_STATE, VLC_FALSE );
  1023.                 if( i_ret )
  1024.                 {
  1025.                     /* FIXME What to do ? */
  1026.                     msg_Warn( p_input, "cannot unset pause -> EOF" );
  1027.                     input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
  1028.                 }
  1029.                 b_force_update = VLC_TRUE;
  1030.                 /* Switch to play */
  1031.                 p_input->i_state = PLAYING_S;
  1032.                 val.i_int = PLAYING_S;
  1033.                 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
  1034.                 /* Reset clock */
  1035.                 es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
  1036.             }
  1037.             else if( val.i_int == PAUSE_S && p_input->i_state == PLAYING_S &&
  1038.                      p_input->b_can_pause )
  1039.             {
  1040.                 int i_ret;
  1041.                 if( p_input->input.p_access )
  1042.                     i_ret = access2_Control( p_input->input.p_access,
  1043.                                              ACCESS_SET_PAUSE_STATE, VLC_TRUE );
  1044.                 else
  1045.                     i_ret = demux2_Control( p_input->input.p_demux,
  1046.                                             DEMUX_SET_PAUSE_STATE, VLC_TRUE );
  1047.                 b_force_update = VLC_TRUE;
  1048.                 if( i_ret )
  1049.                 {
  1050.                     msg_Warn( p_input, "cannot set pause state" );
  1051.                     val.i_int = p_input->i_state;
  1052.                 }
  1053.                 else
  1054.                 {
  1055.                     val.i_int = PAUSE_S;
  1056.                 }
  1057.                 /* Switch to new state */
  1058.                 p_input->i_state = val.i_int;
  1059.                 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
  1060.             }
  1061.             else if( val.i_int == PAUSE_S && !p_input->b_can_pause )
  1062.             {
  1063.                 b_force_update = VLC_TRUE;
  1064.                 /* Correct "state" value */
  1065.                 val.i_int = p_input->i_state;
  1066.                 var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
  1067.             }
  1068.             else if( val.i_int != PLAYING_S && val.i_int != PAUSE_S )
  1069.             {
  1070.                 msg_Err( p_input, "invalid state in INPUT_CONTROL_SET_STATE" );
  1071.             }
  1072.             break;
  1073.         case INPUT_CONTROL_SET_RATE:
  1074.         case INPUT_CONTROL_SET_RATE_SLOWER:
  1075.         case INPUT_CONTROL_SET_RATE_FASTER:
  1076.         {
  1077.             int i_rate;
  1078.             if( i_type == INPUT_CONTROL_SET_RATE_SLOWER )
  1079.                 i_rate = p_input->i_rate * 2;
  1080.             else if( i_type == INPUT_CONTROL_SET_RATE_FASTER )
  1081.                 i_rate = p_input->i_rate / 2;
  1082.             else
  1083.                 i_rate = val.i_int;
  1084.             if( i_rate < INPUT_RATE_MIN )
  1085.             {
  1086.                 msg_Dbg( p_input, "cannot set rate faster" );
  1087.                 i_rate = INPUT_RATE_MIN;
  1088.             }
  1089.             else if( i_rate > INPUT_RATE_MAX )
  1090.             {
  1091.                 msg_Dbg( p_input, "cannot set rate slower" );
  1092.                 i_rate = INPUT_RATE_MAX;
  1093.             }
  1094.             if( i_rate != INPUT_RATE_DEFAULT &&
  1095.                 ( !p_input->b_can_pace_control ||
  1096.                   ( p_input->p_sout && !p_input->b_out_pace_control ) ) )
  1097.             {
  1098.                 msg_Dbg( p_input, "cannot change rate" );
  1099.                 i_rate = INPUT_RATE_DEFAULT;
  1100.             }
  1101.             if( i_rate != p_input->i_rate )
  1102.             {
  1103.                 p_input->i_rate  = i_rate;
  1104.                 val.i_int = i_rate;
  1105.                 var_Change( p_input, "rate", VLC_VAR_SETVALUE, &val, NULL );
  1106.                 /* We haven't send data to decoder when rate != default */
  1107.                 if( i_rate == INPUT_RATE_DEFAULT )
  1108.                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_TRUE );
  1109.                 /* Reset clock */
  1110.                 es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
  1111.                 b_force_update = VLC_TRUE;
  1112.             }
  1113.             break;
  1114.         }
  1115.         case INPUT_CONTROL_SET_PROGRAM:
  1116.             /* No need to force update, es_out does it if needed */
  1117.             es_out_Control( p_input->p_es_out,
  1118.                             ES_OUT_SET_GROUP, val.i_int );
  1119.             demux2_Control( p_input->input.p_demux, DEMUX_SET_GROUP, val.i_int,
  1120.                             NULL );
  1121.             break;
  1122.         case INPUT_CONTROL_SET_ES:
  1123.             /* No need to force update, es_out does it if needed */
  1124.             es_out_Control( p_input->p_es_out, ES_OUT_SET_ES,
  1125.                             input_EsOutGetFromID( p_input->p_es_out,
  1126.                                                   val.i_int ) );
  1127.             break;
  1128.         case INPUT_CONTROL_SET_AUDIO_DELAY:
  1129.             input_EsOutSetDelay( p_input->p_es_out,
  1130.                                  AUDIO_ES, val.i_time );
  1131.             var_Change( p_input, "audio-delay", VLC_VAR_SETVALUE, &val, NULL );
  1132.             break;
  1133.         case INPUT_CONTROL_SET_SPU_DELAY:
  1134.             input_EsOutSetDelay( p_input->p_es_out,
  1135.                                  SPU_ES, val.i_time );
  1136.             var_Change( p_input, "spu-delay", VLC_VAR_SETVALUE, &val, NULL );
  1137.             break;
  1138.         case INPUT_CONTROL_SET_TITLE:
  1139.         case INPUT_CONTROL_SET_TITLE_NEXT:
  1140.         case INPUT_CONTROL_SET_TITLE_PREV:
  1141.             if( p_input->input.b_title_demux &&
  1142.                 p_input->input.i_title > 0 )
  1143.             {
  1144.                 /* TODO */
  1145.                 /* FIXME handle demux title */
  1146.                 demux_t *p_demux = p_input->input.p_demux;
  1147.                 int i_title;
  1148.                 if( i_type == INPUT_CONTROL_SET_TITLE_PREV )
  1149.                     i_title = p_demux->info.i_title - 1;
  1150.                 else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
  1151.                     i_title = p_demux->info.i_title + 1;
  1152.                 else
  1153.                     i_title = val.i_int;
  1154.                 if( i_title >= 0 && i_title < p_input->input.i_title )
  1155.                 {
  1156.                     demux2_Control( p_demux, DEMUX_SET_TITLE, i_title );
  1157.                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
  1158.                     es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
  1159.                     input_ControlVarTitle( p_input, i_title );
  1160.                 }
  1161.             }
  1162.             else if( p_input->input.i_title > 0 )
  1163.             {
  1164.                 access_t *p_access = p_input->input.p_access;
  1165.                 int i_title;
  1166.                 if( i_type == INPUT_CONTROL_SET_TITLE_PREV )
  1167.                     i_title = p_access->info.i_title - 1;
  1168.                 else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
  1169.                     i_title = p_access->info.i_title + 1;
  1170.                 else
  1171.                     i_title = val.i_int;
  1172.                 if( i_title >= 0 && i_title < p_input->input.i_title )
  1173.                 {
  1174.                     access2_Control( p_access, ACCESS_SET_TITLE, i_title );
  1175.                     stream_AccessReset( p_input->input.p_stream );
  1176.                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
  1177.                     es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
  1178.                 }
  1179.             }
  1180.             break;
  1181.         case INPUT_CONTROL_SET_SEEKPOINT:
  1182.         case INPUT_CONTROL_SET_SEEKPOINT_NEXT:
  1183.         case INPUT_CONTROL_SET_SEEKPOINT_PREV:
  1184.             if( p_input->input.b_title_demux &&
  1185.                 p_input->input.i_title > 0 )
  1186.             {
  1187.                 demux_t *p_demux = p_input->input.p_demux;
  1188.                 int i_seekpoint;
  1189.                 if( i_type == INPUT_CONTROL_SET_SEEKPOINT_PREV )
  1190.                     i_seekpoint = p_demux->info.i_seekpoint - 1;
  1191.                 else if( i_type == INPUT_CONTROL_SET_SEEKPOINT_NEXT )
  1192.                     i_seekpoint = p_demux->info.i_seekpoint + 1;
  1193.                 else
  1194.                     i_seekpoint = val.i_int;
  1195.                 if( i_seekpoint >= 0 && i_seekpoint <
  1196.                     p_input->input.title[p_demux->info.i_title]->i_seekpoint )
  1197.                 {
  1198.                     demux2_Control( p_demux, DEMUX_SET_SEEKPOINT, i_seekpoint );
  1199.                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
  1200.                     es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
  1201.                 }
  1202.             }
  1203.             else if( p_input->input.i_title > 0 )
  1204.             {
  1205.                 access_t *p_access = p_input->input.p_access;
  1206.                 int i_seekpoint;
  1207.                 if( i_type == INPUT_CONTROL_SET_SEEKPOINT_PREV )
  1208.                     i_seekpoint = p_access->info.i_seekpoint - 1;
  1209.                 else if( i_type == INPUT_CONTROL_SET_TITLE_NEXT )
  1210.                     i_seekpoint = p_access->info.i_seekpoint + 1;
  1211.                 else
  1212.                     i_seekpoint = val.i_int;
  1213.                 if( i_seekpoint >= 0 && i_seekpoint <
  1214.                     p_input->input.title[p_access->info.i_title]->i_seekpoint )
  1215.                 {
  1216.                     access2_Control( p_access, ACCESS_SET_SEEKPOINT, i_seekpoint );
  1217.                     stream_AccessReset( p_input->input.p_stream );
  1218.                     input_EsOutDiscontinuity( p_input->p_es_out, VLC_FALSE );
  1219.                     es_out_Control( p_input->p_es_out, ES_OUT_RESET_PCR );
  1220.                 }
  1221.             }
  1222.             break;
  1223.         case INPUT_CONTROL_SET_BOOKMARK:
  1224.         default:
  1225.             msg_Err( p_input, "not yet implemented" );
  1226.             break;
  1227.     }
  1228.     return b_force_update;
  1229. }
  1230. /*****************************************************************************
  1231.  * UpdateFromDemux:
  1232.  *****************************************************************************/
  1233. static int UpdateFromDemux( input_thread_t *p_input )
  1234. {
  1235.     demux_t *p_demux = p_input->input.p_demux;
  1236.     vlc_value_t v;
  1237.     if( p_demux->info.i_update & INPUT_UPDATE_TITLE )
  1238.     {
  1239.         v.i_int = p_demux->info.i_title;
  1240.         var_Change( p_input, "title", VLC_VAR_SETVALUE, &v, NULL );
  1241.         input_ControlVarTitle( p_input, p_demux->info.i_title );
  1242.         p_demux->info.i_update &= ~INPUT_UPDATE_TITLE;
  1243.     }
  1244.     if( p_demux->info.i_update & INPUT_UPDATE_SEEKPOINT )
  1245.     {
  1246.         v.i_int = p_demux->info.i_seekpoint;
  1247.         var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &v, NULL);
  1248.         p_demux->info.i_update &= ~INPUT_UPDATE_SEEKPOINT;
  1249.     }
  1250.     p_demux->info.i_update &= ~INPUT_UPDATE_SIZE;
  1251.     /* Hmmm only works with master input */
  1252.     if( p_input->input.p_demux == p_demux )
  1253.     {
  1254.         int i_title_end = p_input->input.i_title_end -
  1255.             p_input->input.i_title_offset;
  1256.         int i_seekpoint_end = p_input->input.i_seekpoint_end -
  1257.             p_input->input.i_seekpoint_offset;
  1258.         if( i_title_end >= 0 && i_seekpoint_end >= 0 )
  1259.         {
  1260.             if( p_demux->info.i_title > i_title_end ||
  1261.                 ( p_demux->info.i_title == i_title_end &&
  1262.                   p_demux->info.i_seekpoint > i_seekpoint_end ) ) return 0;
  1263.         }
  1264.         else if( i_seekpoint_end >=0 )
  1265.         {
  1266.             if( p_demux->info.i_seekpoint > i_seekpoint_end ) return 0;
  1267.         }
  1268.         else if( i_title_end >= 0 )
  1269.         {
  1270.             if( p_demux->info.i_title > i_title_end ) return 0;
  1271.         }
  1272.     }
  1273.     return 1;
  1274. }
  1275. /*****************************************************************************
  1276.  * UpdateFromAccess:
  1277.  *****************************************************************************/
  1278. static int UpdateFromAccess( input_thread_t *p_input )
  1279. {
  1280.     access_t *p_access = p_input->input.p_access;
  1281.     vlc_value_t v;
  1282.     if( p_access->info.i_update & INPUT_UPDATE_TITLE )
  1283.     {
  1284.         v.i_int = p_access->info.i_title;
  1285.         var_Change( p_input, "title", VLC_VAR_SETVALUE, &v, NULL );
  1286.         input_ControlVarTitle( p_input, p_access->info.i_title );
  1287.         stream_AccessUpdate( p_input->input.p_stream );
  1288.         p_access->info.i_update &= ~INPUT_UPDATE_TITLE;
  1289.     }
  1290.     if( p_access->info.i_update & INPUT_UPDATE_SEEKPOINT )
  1291.     {
  1292.         v.i_int = p_access->info.i_seekpoint;
  1293.         var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &v, NULL);
  1294.         p_access->info.i_update &= ~INPUT_UPDATE_SEEKPOINT;
  1295.     }
  1296.     p_access->info.i_update &= ~INPUT_UPDATE_SIZE;
  1297.     /* Hmmm only works with master input */
  1298.     if( p_input->input.p_access == p_access )
  1299.     {
  1300.         int i_title_end = p_input->input.i_title_end -
  1301.             p_input->input.i_title_offset;
  1302.         int i_seekpoint_end = p_input->input.i_seekpoint_end -
  1303.             p_input->input.i_seekpoint_offset;
  1304.         if( i_title_end >= 0 && i_seekpoint_end >=0 )
  1305.         {
  1306.             if( p_access->info.i_title > i_title_end ||
  1307.                 ( p_access->info.i_title == i_title_end &&
  1308.                   p_access->info.i_seekpoint > i_seekpoint_end ) ) return 0;
  1309.         }
  1310.         else if( i_seekpoint_end >=0 )
  1311.         {
  1312.             if( p_access->info.i_seekpoint > i_seekpoint_end ) return 0;
  1313.         }
  1314.         else if( i_title_end >= 0 )
  1315.         {
  1316.             if( p_access->info.i_title > i_title_end ) return 0;
  1317.         }
  1318.     }
  1319.     return 1;
  1320. }
  1321. /*****************************************************************************
  1322.  * UpdateItemLength:
  1323.  *****************************************************************************/
  1324. static void UpdateItemLength( input_thread_t *p_input, int64_t i_length )
  1325. {
  1326.     char psz_buffer[MSTRTIME_MAX_SIZE];
  1327.     vlc_mutex_lock( &p_input->input.p_item->lock );
  1328.     p_input->input.p_item->i_duration = i_length;
  1329.     vlc_mutex_unlock( &p_input->input.p_item->lock );
  1330.     input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Duration"),
  1331.                    msecstotimestr( psz_buffer, i_length / 1000 ) );
  1332. }
  1333. /*****************************************************************************
  1334.  * InputSourceNew:
  1335.  *****************************************************************************/
  1336. static input_source_t *InputSourceNew( input_thread_t *p_input )
  1337. {
  1338.     input_source_t *in = malloc( sizeof( input_source_t ) );
  1339.     in->p_item   = NULL;
  1340.     in->p_access = NULL;
  1341.     in->p_stream = NULL;
  1342.     in->p_demux  = NULL;
  1343.     in->b_title_demux = VLC_FALSE;
  1344.     in->i_title  = 0;
  1345.     in->title    = NULL;
  1346.     in->b_can_pace_control = VLC_TRUE;
  1347.     in->b_eof = VLC_FALSE;
  1348.     in->i_cr_average = 0;
  1349.     return in;
  1350. }
  1351. /*****************************************************************************
  1352.  * InputSourceInit:
  1353.  *****************************************************************************/
  1354. static int InputSourceInit( input_thread_t *p_input,
  1355.                             input_source_t *in, char *psz_mrl,
  1356.                             char *psz_forced_demux )
  1357. {
  1358.     char *psz_dup = strdup( psz_mrl );
  1359.     char *psz_access;
  1360.     char *psz_demux;
  1361.     char *psz_path;
  1362.     vlc_value_t val;
  1363.     /* Split uri */
  1364.     MRLSplit( p_input, psz_dup, &psz_access, &psz_demux, &psz_path );
  1365.     msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
  1366.              psz_mrl, psz_access, psz_demux, psz_path );
  1367.     /* Hack to allow udp://@:port syntax */
  1368.     if( !psz_access ||
  1369.         (strncmp( psz_access, "udp", 3 ) && strncmp( psz_access, "rtp", 3 )) )
  1370.     /* Find optional titles and seekpoints */
  1371.     MRLSections( p_input, psz_path, &in->i_title_start, &in->i_title_end,
  1372.                  &in->i_seekpoint_start, &in->i_seekpoint_end );
  1373.     if( psz_forced_demux && *psz_forced_demux )
  1374.         psz_demux = psz_forced_demux;
  1375.     /* Try access_demux if no demux given */
  1376.     if( *psz_demux == '' )
  1377.     {
  1378.         in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
  1379.                                   NULL, p_input->p_es_out );
  1380.     }
  1381.     if( in->p_demux )
  1382.     {
  1383.         int64_t i_pts_delay;
  1384.         /* Get infos from access_demux */
  1385.         demux2_Control( in->p_demux,
  1386.                         DEMUX_GET_PTS_DELAY, &i_pts_delay );
  1387.         p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
  1388.         in->b_title_demux = VLC_TRUE;
  1389.         if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
  1390.                             &in->title, &in->i_title,
  1391.                             &in->i_title_offset, &in->i_seekpoint_offset ) )
  1392.         {
  1393.             in->i_title = 0;
  1394.             in->title   = NULL;
  1395.         }
  1396.         demux2_Control( in->p_demux, DEMUX_CAN_CONTROL_PACE,
  1397.                         &in->b_can_pace_control );
  1398.         demux2_Control( in->p_demux, DEMUX_CAN_PAUSE,
  1399.                         &in->b_can_pause );
  1400.         /* FIXME todo
  1401.         demux2_Control( in->p_demux, DEMUX_CAN_SEEK,
  1402.                         &val.b_bool );
  1403.         */
  1404.     }
  1405.     else
  1406.     {
  1407.         int64_t i_pts_delay;
  1408.         /* Now try a real access */
  1409.         in->p_access = access2_New( p_input, psz_access, psz_demux, psz_path );
  1410.         /* Access failed, URL encoded ? */
  1411.         if( in->p_access == NULL && strchr( psz_path, '%' ) )
  1412.         {
  1413.             DecodeUrl( psz_path );
  1414.             msg_Dbg( p_input, "retying with access `%s' demux `%s' path `%s'",
  1415.                      psz_access, psz_demux, psz_path );
  1416.             in->p_access = access2_New( p_input,
  1417.                                         psz_access, psz_demux, psz_path );
  1418.         }
  1419. #ifndef WIN32      /* Remove this gross hack from the win32 build as colons
  1420.                         * are forbidden in filenames on Win32. */
  1421.         /* Maybe we got something like: /Volumes/toto:titi/gabu.mpg */
  1422.         if( in->p_access == NULL &&
  1423.             *psz_access == '' && ( *psz_demux || *psz_path ) )
  1424.         {
  1425.             free( psz_dup );
  1426.             psz_dup = strdup( psz_mrl );
  1427.             psz_access = "";
  1428.             psz_demux = "";
  1429.             psz_path = psz_dup;
  1430.             in->p_access = access2_New( p_input,
  1431.                                         psz_access, psz_demux, psz_path );
  1432.         }
  1433. #endif
  1434.         if( in->p_access == NULL )
  1435.         {
  1436.             msg_Err( p_input, "no suitable access module for `%s'", psz_mrl );
  1437.             goto error;
  1438.         }
  1439.         /* Get infos from access */
  1440.         access2_Control( in->p_access,
  1441.                          ACCESS_GET_PTS_DELAY, &i_pts_delay );
  1442.         p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
  1443.         in->b_title_demux = VLC_FALSE;
  1444.         if( access2_Control( in->p_access, ACCESS_GET_TITLE_INFO,
  1445.                              &in->title, &in->i_title,
  1446.                              &in->i_title_offset, &in->i_seekpoint_offset ) )
  1447.         {
  1448.             in->i_title = 0;
  1449.             in->title   = NULL;
  1450.         }
  1451.         access2_Control( in->p_access, ACCESS_CAN_CONTROL_PACE,
  1452.                          &in->b_can_pace_control );
  1453.         access2_Control( in->p_access, ACCESS_CAN_PAUSE,
  1454.                          &in->b_can_pause );
  1455.         access2_Control( in->p_access, ACCESS_CAN_SEEK,
  1456.                          &val.b_bool );
  1457.         var_Set( p_input, "seekable", val );
  1458.         /* Create the stream_t */
  1459.         in->p_stream = stream_AccessNew( in->p_access );
  1460.         if( in->p_stream == NULL )
  1461.         {
  1462.             msg_Warn( p_input, "cannot create a stream_t from access" );
  1463.             goto error;
  1464.         }
  1465.         /* Open a demuxer */
  1466.         if( *psz_demux == '' && *in->p_access->psz_demux )
  1467.         {
  1468.             psz_demux = in->p_access->psz_demux;
  1469.         }
  1470.         in->p_demux = demux2_New( p_input, psz_access, psz_demux, psz_path,
  1471.                                   in->p_stream, p_input->p_es_out );
  1472.         if( in->p_demux == NULL )
  1473.         {
  1474.             msg_Err( p_input, "no suitable demux module for `%s/%s://%s'",
  1475.                      psz_access, psz_demux, psz_path );
  1476.             goto error;
  1477.         }
  1478.         /* TODO get title from demux */
  1479.         if( in->i_title <= 0 )
  1480.         {
  1481.             if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
  1482.                                 &in->title, &in->i_title,
  1483.                                 &in->i_title_offset, &in->i_seekpoint_offset ))
  1484.             {
  1485.                 in->i_title = 0;
  1486.                 in->title   = NULL;
  1487.             }
  1488.             else
  1489.             {
  1490.                 in->b_title_demux = VLC_TRUE;
  1491.             }
  1492.         }
  1493.     }
  1494.     free( psz_dup );
  1495.     return VLC_SUCCESS;
  1496. error:
  1497.     if( in->p_demux )
  1498.         demux2_Delete( in->p_demux );
  1499.     if( in->p_stream )
  1500.         stream_AccessDelete( in->p_stream );
  1501.     if( in->p_access )
  1502.         access2_Delete( in->p_access );
  1503.     free( psz_dup );
  1504.     return VLC_EGENERIC;
  1505. }
  1506. /*****************************************************************************
  1507.  * InputSourceClean:
  1508.  *****************************************************************************/
  1509. static void InputSourceClean( input_thread_t *p_input, input_source_t *in )
  1510. {
  1511.     if( in->p_demux )
  1512.         demux2_Delete( in->p_demux );
  1513.     if( in->p_stream )
  1514.         stream_AccessDelete( in->p_stream );
  1515.     if( in->p_access )
  1516.         access2_Delete( in->p_access );
  1517.     if( in->i_title > 0 )
  1518.     {
  1519.         int i;
  1520.         for( i = 0; i < in->i_title; i++ )
  1521.         {
  1522.             vlc_input_title_Delete( in->title[i] );
  1523.         }
  1524.         free( in->title );
  1525.     }
  1526. }
  1527. static void SlaveDemux( input_thread_t *p_input )
  1528. {
  1529.     int64_t i_time;
  1530.     int i;
  1531.     if( demux2_Control( p_input->input.p_demux, DEMUX_GET_TIME, &i_time ) )
  1532.     {
  1533.         msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
  1534.         return;
  1535.     }
  1536.     for( i = 0; i < p_input->i_slave; i++ )
  1537.     {
  1538.         input_source_t *in = p_input->slave[i];
  1539.         int i_ret = 1;
  1540.         if( in->b_eof )
  1541.             continue;
  1542.         if( demux2_Control( in->p_demux, DEMUX_SET_NEXT_DEMUX_TIME, i_time ) )
  1543.         {
  1544.             for( ;; )
  1545.             {
  1546.                 int64_t i_stime;
  1547.                 if( demux2_Control( in->p_demux, DEMUX_GET_TIME, &i_stime ) )
  1548.                 {
  1549.                     msg_Err( p_input, "slave[%d] doesn't like "
  1550.                              "DEMUX_GET_TIME -> EOF", i );
  1551.                     i_ret = 0;
  1552.                     break;
  1553.                 }
  1554.                 if( i_stime >= i_time )
  1555.                     break;
  1556.                 if( ( i_ret = in->p_demux->pf_demux( in->p_demux ) ) <= 0 )
  1557.                     break;
  1558.             }
  1559.         }
  1560.         else
  1561.         {
  1562.             i_ret = in->p_demux->pf_demux( in->p_demux );
  1563.         }
  1564.         if( i_ret <= 0 )
  1565.         {
  1566.             msg_Dbg( p_input, "slave %d EOF", i );
  1567.             in->b_eof = VLC_TRUE;
  1568.         }
  1569.     }
  1570. }
  1571. static void SlaveSeek( input_thread_t *p_input )
  1572. {
  1573.     int64_t i_time;
  1574.     int i;
  1575.     if( demux2_Control( p_input->input.p_demux, DEMUX_GET_TIME, &i_time ) )
  1576.     {
  1577.         msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" );
  1578.         return;
  1579.     }
  1580.     for( i = 0; i < p_input->i_slave; i++ )
  1581.     {
  1582.         input_source_t *in = p_input->slave[i];
  1583.         if( demux2_Control( in->p_demux, DEMUX_SET_TIME, i_time ) )
  1584.         {
  1585.             msg_Err( p_input, "seek failed for slave %d -> EOF", i );
  1586.             in->b_eof = VLC_TRUE;
  1587.         }
  1588.     }
  1589. }
  1590. /*****************************************************************************
  1591.  * InputMetaUser:
  1592.  *****************************************************************************/
  1593. static vlc_meta_t *InputMetaUser( input_thread_t *p_input )
  1594. {
  1595.     vlc_meta_t *p_meta;
  1596.     vlc_value_t val;
  1597.     if( ( p_meta = vlc_meta_New() ) == NULL )
  1598.         return NULL;
  1599.     /* Get meta information from user */
  1600. #define GET_META( c, s ) 
  1601.     var_Get( p_input, (s), &val );  
  1602.     if( *val.psz_string )       
  1603.         vlc_meta_Add( p_meta, c, val.psz_string ); 
  1604.     free( val.psz_string )
  1605.     GET_META( VLC_META_TITLE, "meta-title" );
  1606.     GET_META( VLC_META_AUTHOR, "meta-author" );
  1607.     GET_META( VLC_META_ARTIST, "meta-artist" );
  1608.     GET_META( VLC_META_GENRE, "meta-genre" );
  1609.     GET_META( VLC_META_COPYRIGHT, "meta-copyright" );
  1610.     GET_META( VLC_META_DESCRIPTION, "meta-description" );
  1611.     GET_META( VLC_META_DATE, "meta-date" );
  1612.     GET_META( VLC_META_URL, "meta-url" );
  1613. #undef GET_META
  1614.     return p_meta;
  1615. }
  1616. /*****************************************************************************
  1617.  * DecodeUrl: decode a given encoded url
  1618.  *****************************************************************************/
  1619. static void DecodeUrl( char *psz )
  1620. {
  1621.     char *dup = strdup( psz );
  1622.     char *p = dup;
  1623.     while( *p )
  1624.     {
  1625.         if( *p == '%' )
  1626.         {
  1627.             char val[3];
  1628.             p++;
  1629.             if( !*p )
  1630.             {
  1631.                 break;
  1632.             }
  1633.             val[0] = *p++;
  1634.             val[1] = *p++;
  1635.             val[2] = '';
  1636.             *psz++ = strtol( val, NULL, 16 );
  1637.         }
  1638.         else if( *p == '+' )
  1639.         {
  1640.             *psz++ = ' ';
  1641.             p++;
  1642.         }
  1643.         else
  1644.         {
  1645.             *psz++ = *p++;
  1646.         }
  1647.     }
  1648.     *psz++  ='';
  1649.     free( dup );
  1650. }
  1651. /*****************************************************************************
  1652.  * ParseOption: parses the options for the input
  1653.  *****************************************************************************
  1654.  * This function parses the input (config) options and creates their associated
  1655.  * object variables.
  1656.  * Options are of the form "[no[-]]foo[=bar]" where foo is the option name and
  1657.  * bar is the value of the option.
  1658.  *****************************************************************************/
  1659. static void ParseOption( input_thread_t *p_input, const char *psz_option )
  1660. {
  1661.     char *psz_name = (char *)psz_option;
  1662.     char *psz_value = strchr( psz_option, '=' );
  1663.     int  i_name_len, i_type;
  1664.     vlc_bool_t b_isno = VLC_FALSE;
  1665.     vlc_value_t val;
  1666.     if( psz_value ) i_name_len = psz_value - psz_option;
  1667.     else i_name_len = strlen( psz_option );
  1668.     /* It's too much of an hassle to remove the ':' when we parse
  1669.      * the cmd line :) */
  1670.     if( i_name_len && *psz_name == ':' )
  1671.     {
  1672.         psz_name++;
  1673.         i_name_len--;
  1674.     }
  1675.     if( i_name_len == 0 ) return;
  1676.     psz_name = strndup( psz_name, i_name_len );
  1677.     if( psz_value ) psz_value++;
  1678.     i_type = config_GetType( p_input, psz_name );
  1679.     if( !i_type && !psz_value )
  1680.     {
  1681.         /* check for "no-foo" or "nofoo" */
  1682.         if( !strncmp( psz_name, "no-", 3 ) )
  1683.         {
  1684.             memmove( psz_name, psz_name + 3, strlen(psz_name) + 1 - 3 );
  1685.         }
  1686.         else if( !strncmp( psz_name, "no", 2 ) )
  1687.         {
  1688.             memmove( psz_name, psz_name + 2, strlen(psz_name) + 1 - 2 );
  1689.         }
  1690.         else goto cleanup;           /* Option doesn't exist */
  1691.         b_isno = VLC_TRUE;
  1692.         i_type = config_GetType( p_input, psz_name );
  1693.         if( !i_type ) goto cleanup;  /* Option doesn't exist */
  1694.     }
  1695.     else if( !i_type ) goto cleanup; /* Option doesn't exist */
  1696.     if( ( i_type != VLC_VAR_BOOL ) &&
  1697.         ( !psz_value || !*psz_value ) ) goto cleanup; /* Invalid value */
  1698.     /* Create the variable in the input object.
  1699.      * Children of the input object will be able to retreive this value
  1700.      * thanks to the inheritance property of the object variables. */
  1701.     var_Create( p_input, psz_name, i_type );
  1702.     switch( i_type )
  1703.     {
  1704.     case VLC_VAR_BOOL:
  1705.         val.b_bool = !b_isno;
  1706.         break;
  1707.     case VLC_VAR_INTEGER:
  1708.         val.i_int = atoi( psz_value );
  1709.         break;
  1710.     case VLC_VAR_FLOAT:
  1711.         val.f_float = atof( psz_value );
  1712.         break;
  1713.     case VLC_VAR_STRING:
  1714.     case VLC_VAR_MODULE:
  1715.     case VLC_VAR_FILE:
  1716.     case VLC_VAR_DIRECTORY:
  1717.         val.psz_string = psz_value;
  1718.         break;
  1719.     default:
  1720.         goto cleanup;
  1721.         break;
  1722.     }
  1723.     var_Set( p_input, psz_name, val );
  1724.     msg_Dbg( p_input, "set input option: %s to %s", psz_name, psz_value ? psz_value : ( val.b_bool ? "true" : "false") );
  1725.   cleanup:
  1726.     if( psz_name ) free( psz_name );
  1727.     return;
  1728. }
  1729. /*****************************************************************************
  1730.  * MRLSplit: parse the access, demux and url part of the
  1731.  *           Media Resource Locator.
  1732.  *****************************************************************************/
  1733. static void MRLSplit( input_thread_t *p_input, char *psz_dup,
  1734.                       char **ppsz_access, char **ppsz_demux, char **ppsz_path )
  1735. {
  1736.     char *psz_access = NULL;
  1737.     char *psz_demux  = NULL;
  1738.     char *psz_path   = NULL;
  1739.     char *psz, *psz_check;
  1740.     psz = strchr( psz_dup, ':' );
  1741.     /* '@' not allowed in access/demux part */
  1742.     psz_check = strchr( psz_dup, '@' );
  1743.     if( psz_check && psz_check < psz ) psz = 0;
  1744. #if defined( WIN32 ) || defined( UNDER_CE )
  1745.     if( psz - psz_dup == 1 )
  1746.     {
  1747.         msg_Warn( p_input, "drive letter %c: found in source", *psz_dup );
  1748.         psz_path = psz_dup;
  1749.     }
  1750.     else
  1751. #endif
  1752.     if( psz )
  1753.     {
  1754.         *psz++ = '';
  1755.         if( psz[0] == '/' && psz[1] == '/' ) psz += 2;
  1756.         psz_path = psz;
  1757.         psz = strchr( psz_dup, '/' );
  1758.         if( psz )
  1759.         {
  1760.             *psz++ = '';
  1761.             psz_demux = psz;
  1762.         }
  1763.         psz_access = psz_dup;
  1764.     }
  1765.     else
  1766.     {
  1767.         psz_path = psz_dup;
  1768.     }
  1769.     if( !psz_access ) *ppsz_access = "";
  1770.     else *ppsz_access = psz_access;
  1771.     if( !psz_demux ) *ppsz_demux = "";
  1772.     else *ppsz_demux = psz_demux;
  1773.     if( !psz_path ) *ppsz_path = "";
  1774.     else *ppsz_path = psz_path;
  1775. }
  1776. /*****************************************************************************
  1777.  * MRLSections: parse title and seekpoint info from the Media Resource Locator.
  1778.  *
  1779.  * Syntax:
  1780.  * [url][@[title-start][:chapter-start][-[title-end][:chapter-end]]]
  1781.  *****************************************************************************/
  1782. static void MRLSections( input_thread_t *p_input, char *psz_source,
  1783.                          int *pi_title_start, int *pi_title_end,
  1784.                          int *pi_chapter_start, int *pi_chapter_end )
  1785. {
  1786.     char *psz, *psz_end, *psz_next, *psz_check;
  1787.     *pi_title_start = *pi_title_end = -1;
  1788.     *pi_chapter_start = *pi_chapter_end = -1;
  1789.     /* Start by parsing titles and chapters */
  1790.     if( !psz_source || !( psz = strrchr( psz_source, '@' ) ) ) return;
  1791.     /* Check we are really dealing with a title/chapter section */
  1792.     psz_check = psz + 1;
  1793.     if( !*psz_check ) return;
  1794.     if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 );
  1795.     if( *psz_check != ':' && *psz_check != '-' && *psz_check ) return;
  1796.     if( *psz_check == ':' && ++psz_check )
  1797.         if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 );
  1798.     if( *psz_check != '-' && *psz_check ) return;
  1799.     if( *psz_check == '-' && ++psz_check )
  1800.         if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 );
  1801.     if( *psz_check != ':' && *psz_check ) return;
  1802.     if( *psz_check == ':' && ++psz_check )
  1803.         if( isdigit(*psz_check) ) strtol( psz_check, &psz_check, 0 );
  1804.     if( *psz_check ) return;
  1805.     /* Separate start and end */
  1806.     *psz++ = 0;
  1807.     if( ( psz_end = strchr( psz, '-' ) ) ) *psz_end++ = 0;
  1808.     /* Look for the start title */
  1809.     *pi_title_start = strtol( psz, &psz_next, 0 );
  1810.     if( !*pi_title_start && psz == psz_next ) *pi_title_start = -1;
  1811.     *pi_title_end = *pi_title_start;
  1812.     psz = psz_next;
  1813.     /* Look for the start chapter */
  1814.     if( *psz ) psz++;
  1815.     *pi_chapter_start = strtol( psz, &psz_next, 0 );
  1816.     if( !*pi_chapter_start && psz == psz_next ) *pi_chapter_start = -1;
  1817.     *pi_chapter_end = *pi_chapter_start;
  1818.     if( psz_end )
  1819.     {
  1820.         /* Look for the end title */
  1821.         *pi_title_end = strtol( psz_end, &psz_next, 0 );
  1822.         if( !*pi_title_end && psz_end == psz_next ) *pi_title_end = -1;
  1823.         psz_end = psz_next;
  1824.         /* Look for the end chapter */
  1825.         if( *psz_end ) psz_end++;
  1826.         *pi_chapter_end = strtol( psz_end, &psz_next, 0 );
  1827.         if( !*pi_chapter_end && psz_end == psz_next ) *pi_chapter_end = -1;
  1828.     }
  1829.     msg_Dbg( p_input, "source=`%s' title=%d/%d seekpoint=%d/%d",
  1830.              psz_source, *pi_title_start, *pi_chapter_start,
  1831.              *pi_title_end, *pi_chapter_end );
  1832. }