[vlc-devel] [PATCH 2/6] Add support for pf_readdir access modules in Streams

Rémi Denis-Courmont remi at remlab.net
Sat Jun 21 10:54:06 CEST 2014


Le vendredi 20 juin 2014, 19:53:04 Julien 'Lta' BALLET a écrit :
> From: Julien 'Lta' BALLET <contact at lta.io>
> 
> ---
>  include/vlc_stream.h |  9 ++++---
>  src/input/stream.c   | 71
> ++++++++++++++++++++++++++++++++++++++++++++-------- src/libvlccore.sym   |
>  1 +
>  3 files changed, 67 insertions(+), 14 deletions(-)
> 
> diff --git a/include/vlc_stream.h b/include/vlc_stream.h
> index 10a98ef..db247bc 100644
> --- a/include/vlc_stream.h
> +++ b/include/vlc_stream.h
> @@ -65,9 +65,10 @@ struct stream_t
>      stream_t *p_source;
> 
>      /* */
> -    int      (*pf_read)   ( stream_t *, void *p_read, unsigned int i_read
> ); -    int      (*pf_peek)   ( stream_t *, const uint8_t **pp_peek,
> unsigned int i_peek ); -    int      (*pf_control)( stream_t *, int
> i_query, va_list );
> +    int         (*pf_read)   ( stream_t *, void *p_read, unsigned int
> i_read ); +    int         (*pf_peek)   ( stream_t *, const uint8_t
> **pp_peek, unsigned int i_peek ); +    int         (*pf_readdir)( stream_t
> *, input_item_node_t * ); +    int         (*pf_control)( stream_t *, int
> i_query, va_list );
> 
>      /* */
>      void     (*pf_destroy)( stream_t *);
> @@ -92,6 +93,7 @@ enum stream_query_e
>      STREAM_CAN_FASTSEEK,        /**< arg1= bool *   res=cannot fail*/
>      STREAM_CAN_PAUSE,           /**< arg1= bool *   res=cannot fail*/
>      STREAM_CAN_CONTROL_PACE,    /**< arg1= bool *   res=cannot fail*/
> +    STREAM_IS_DIRECTORY,        /**< arg1= bool *   res=cannot fail*/
> 
>      /* */
>      STREAM_SET_POSITION,        /**< arg1= uint64_t       res=can fail  */
> @@ -132,6 +134,7 @@ VLC_API int stream_Control( stream_t *s, int i_query,
> ... ); VLC_API block_t * stream_Block( stream_t *s, int i_size );
>  VLC_API block_t * stream_BlockRemaining( stream_t *s, int i_max_size );
>  VLC_API char * stream_ReadLine( stream_t * );
> +VLC_API int stream_ReadDir( stream_t *, input_item_node_t * );
> 
>  /**
>   * Get the current position in a stream
> diff --git a/src/input/stream.c b/src/input/stream.c
> index 18e77e2..a5d041c 100644
> --- a/src/input/stream.c
> +++ b/src/input/stream.c
> @@ -116,7 +116,8 @@ typedef struct
>  typedef enum
>  {
>      STREAM_METHOD_BLOCK,
> -    STREAM_METHOD_STREAM
> +    STREAM_METHOD_STREAM,
> +    STREAM_METHOD_READDIR
>  } stream_read_method_t;
> 
>  struct stream_sys_t
> @@ -197,6 +198,9 @@ static int  AStreamSeekStream( stream_t *s, uint64_t
> i_pos ); static void AStreamPrebufferStream( stream_t *s );
>  static int  AReadStream( stream_t *s, void *p_read, unsigned int i_read );
> 
> +/* ReadDir */
> +static int AStreamReadDir( stream_t *s, input_item_node_t *p_node );
> +
>  /* Common */
>  static int AStreamControl( stream_t *s, int i_query, va_list );
>  static void AStreamDestroy( stream_t *s );
> @@ -285,8 +289,9 @@ stream_t *stream_AccessNew( access_t *p_access, char
> **ppsz_list ) return NULL;
>      }
> 
> -    s->pf_read   = NULL;    /* Set up later */
> -    s->pf_peek   = NULL;
> +    s->pf_read    = NULL;    /* Set up later */
> +    s->pf_peek    = NULL;
> +    s->pf_readdir = NULL;
>      s->pf_control = AStreamControl;
>      s->pf_destroy = AStreamDestroy;
> 
> @@ -294,8 +299,10 @@ stream_t *stream_AccessNew( access_t *p_access, char
> **ppsz_list ) p_sys->p_access = p_access;
>      if( p_access->pf_block )
>          p_sys->method = STREAM_METHOD_BLOCK;
> -    else
> +    else if( p_access->pf_read )
>          p_sys->method = STREAM_METHOD_STREAM;
> +    else
> +        p_sys->method = STREAM_METHOD_READDIR;
> 
>      p_sys->i_pos = p_access->info.i_pos;
> 
> @@ -385,12 +392,10 @@ stream_t *stream_AccessNew( access_t *p_access, char
> **ppsz_list ) goto error;
>          }
>      }
> -    else
> +    else if ( p_sys->method == STREAM_METHOD_STREAM )
>      {
>          int i;
> 
> -        assert( p_sys->method == STREAM_METHOD_STREAM );
> -
>          msg_Dbg( s, "Using stream method for AStream*" );
> 
>          s->pf_read = AStreamReadStream;
> @@ -426,6 +431,11 @@ stream_t *stream_AccessNew( access_t *p_access, char
> **ppsz_list ) goto error;
>          }
>      }
> +    else
> +    {
> +        assert( p_sys->method == STREAM_METHOD_READDIR );
> +        s->pf_readdir = AStreamReadDir;
> +    }
> 
>      return s;
> 
> @@ -434,7 +444,7 @@ error:
>      {
>          /* Nothing yet */
>      }
> -    else
> +    else if( p_sys->method == STREAM_METHOD_STREAM )
>      {
>          free( p_sys->stream.p_buffer );
>      }
> @@ -456,7 +466,7 @@ static void AStreamDestroy( stream_t *s )
> 
>      if( p_sys->method == STREAM_METHOD_BLOCK )
>          block_ChainRelease( p_sys->block.p_first );
> -    else
> +    else if( p_sys->method == STREAM_METHOD_STREAM )
>          free( p_sys->stream.p_buffer );
> 
>      free( p_sys->p_peek );
> @@ -637,6 +647,13 @@ static int AStreamControl( stream_t *s, int i_query,
> va_list args ) return ret;
>          }
> 
> +        case STREAM_IS_DIRECTORY:
> +        {
> +            bool *pb_canreaddir = va_arg( args, bool * );
> +            *pb_canreaddir = p_sys->method == STREAM_METHOD_READDIR;
> +            return VLC_SUCCESS;
> +        }
> +
>          case STREAM_SET_RECORD_STATE:
>          default:
>              msg_Err( s, "invalid stream_vaControl query=0x%x", i_query );
> @@ -1473,6 +1490,10 @@ char *stream_ReadLine( stream_t *s )
>      char *p_line = NULL;
>      int i_line = 0, i_read = 0;
> 
> +    /* Let's fail quickly if this is a readdir access */
> +    if( s->pf_read == NULL )
> +        return NULL;
> +
>      for( ;; )
>      {
>          char *psz_eol;
> @@ -1830,6 +1851,15 @@ static int ASeek( stream_t *s, uint64_t i_pos )
>      return p_access->pf_seek( p_access, i_pos );
>  }
> 
> +int AStreamReadDir( stream_t *s, input_item_node_t *p_node )
> +{
> +    access_t *p_access = s->p_sys->p_access;
> +
> +    if( p_access->pf_readdir != NULL )
> +        return p_access->pf_readdir( p_access, p_node );
> +    else
> +        return VLC_ENOITEM;
> +}

I would define a callback that just returns an error instead of checking for 
NULL. It can even be used for all cases, but I guess that's a matter of taste:

int AStreamGenericError(/* ... */)
{
    return VLC_EGENERIC;
}

> 
>  /**
>   * Try to read "i_read" bytes into a buffer pointed by "p_read".  If
> @@ -1841,7 +1871,10 @@ static int ASeek( stream_t *s, uint64_t i_pos )
>   */
>  int stream_Read( stream_t *s, void *p_read, int i_read )
>  {
> -    return s->pf_read( s, p_read, i_read );
> +    if( likely( s->pf_read != NULL) )
> +        return s->pf_read( s, p_read, i_read );
> +    else
> +        return VLC_EGENERIC;
>  }

Ditto.

> 
>  /**
> @@ -1859,7 +1892,10 @@ int stream_Read( stream_t *s, void *p_read, int
> i_read ) */
>  int stream_Peek( stream_t *s, const uint8_t **pp_peek, int i_peek )
>  {
> -    return s->pf_peek( s, pp_peek, i_peek );
> +    if( likely( s->pf_peek != NULL ) )
> +        return s->pf_peek( s, pp_peek, i_peek );
> +    else
> +        return VLC_EGENERIC;
>  }

Ditto.

> 
>  /**
> @@ -1962,3 +1998,16 @@ block_t *stream_BlockRemaining( stream_t *s, int
> i_max_size ) return p_block;
>  }
> 
> +/**
> + * Returns a node containing all the input_item of the directory pointer by
> + * this stream. returns VLC_SUCCESS on success.
> + */
> +int stream_ReadDir( stream_t *s, input_item_node_t *p_node )
> +{
> +    if( s->pf_readdir )
> +    {
> +        return s->pf_readdir( s, p_node );
> +    }
> +    else
> +        return VLC_ENOITEM;
> +}

Ditto.

> diff --git a/src/libvlccore.sym b/src/libvlccore.sym
> index e583c21..7b40435 100644
> --- a/src/libvlccore.sym
> +++ b/src/libvlccore.sym
> @@ -402,6 +402,7 @@ stream_Read
>  stream_ReadLine
>  stream_UrlNew
>  stream_vaControl
> +stream_ReadDir
>  str_format_meta
>  str_format_time
>  str_duration

But it seems fine anyway.

-- 
Rémi Denis-Courmont
http://www.remlab.net/




More information about the vlc-devel mailing list