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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * directory.c: expands a directory (directory: access plug-in)
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2004 VideoLAN
  5.  * $Id: directory.c 8953 2004-10-07 22:52:10Z hartman $
  6.  *
  7.  * Authors: Derk-Jan Hartman <thedj@users.sourceforge.net>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <vlc/vlc.h>
  27. #include <vlc/input.h>
  28. #include <vlc_playlist.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #ifdef HAVE_SYS_TYPES_H
  32. #   include <sys/types.h>
  33. #endif
  34. #ifdef HAVE_SYS_STAT_H
  35. #   include <sys/stat.h>
  36. #endif
  37. #ifdef HAVE_ERRNO_H
  38. #   include <errno.h>
  39. #endif
  40. #ifdef HAVE_FCNTL_H
  41. #   include <fcntl.h>
  42. #endif
  43. #ifdef HAVE_UNISTD_H
  44. #   include <unistd.h>
  45. #elif defined( WIN32 ) && !defined( UNDER_CE )
  46. #   include <io.h>
  47. #endif
  48. #if (!defined( WIN32 ) || defined(__MINGW32__))
  49. /* Mingw has its own version of dirent */
  50. #   include <dirent.h>
  51. #endif
  52. /*****************************************************************************
  53.  * Module descriptor
  54.  *****************************************************************************/
  55. static int  Open ( vlc_object_t * );
  56. static void Close( vlc_object_t * );
  57. static int  DemuxOpen ( vlc_object_t * );
  58. #define RECURSIVE_TEXT N_("Subdirectory behavior")
  59. #define RECURSIVE_LONGTEXT N_( 
  60.         "Select whether subdirectories must be expanded.n" 
  61.         "none: subdirectories do not appear in the playlist.n" 
  62.         "collapse: subdirectories appear but are expanded on first play.n" 
  63.         "expand: all subdirectories are expanded.n" )
  64. static char *psz_recursive_list[] = { "none", "collapse", "expand" };
  65. static char *psz_recursive_list_text[] = { N_("none"), N_("collapse"),
  66.                                            N_("expand") };
  67. vlc_module_begin();
  68.     set_description( _("Standard filesystem directory input") );
  69.     set_capability( "access2", 55 );
  70.     add_shortcut( "directory" );
  71.     add_shortcut( "dir" );
  72.     add_string( "recursive", "expand" , NULL, RECURSIVE_TEXT,
  73.                 RECURSIVE_LONGTEXT, VLC_FALSE );
  74.       change_string_list( psz_recursive_list, psz_recursive_list_text, 0 );
  75.     set_callbacks( Open, Close );
  76.     add_submodule();
  77.         set_description( "Directory EOF");
  78.         set_capability( "demux2", 0 );
  79.         add_shortcut( "directory" );
  80.         set_callbacks( DemuxOpen, NULL );
  81. vlc_module_end();
  82. /*****************************************************************************
  83.  * Local prototypes, constants, structures
  84.  *****************************************************************************/
  85. #define MODE_EXPAND 0
  86. #define MODE_COLLAPSE 1
  87. #define MODE_NONE 2
  88. static int Read( access_t *, uint8_t *, int );
  89. static int ReadNull( access_t *, uint8_t *, int );
  90. static int Control( access_t *, int, va_list );
  91. static int Demux( demux_t *p_demux );
  92. static int DemuxControl( demux_t *p_demux, int i_query, va_list args );
  93. static int ReadDir( playlist_t *, char *psz_name, int i_mode, int *pi_pos );
  94. /*****************************************************************************
  95.  * Open: open the directory
  96.  *****************************************************************************/
  97. static int Open( vlc_object_t *p_this )
  98. {
  99.     access_t *p_access = (access_t*)p_this;
  100. #ifdef HAVE_SYS_STAT_H
  101.     struct stat stat_info;
  102.     if( ( stat( p_access->psz_path, &stat_info ) == -1 ) ||
  103.         !S_ISDIR( stat_info.st_mode ) )
  104. #else
  105.     if( strcmp( p_access->psz_access, "dir") &&
  106.         strcmp( p_access->psz_access, "directory") )
  107. #endif
  108.     {
  109.         return VLC_EGENERIC;
  110.     }
  111.     p_access->pf_read  = Read;
  112.     p_access->pf_block = NULL;
  113.     p_access->pf_seek  = NULL;
  114.     p_access->pf_control= Control;
  115.     /* Force a demux */
  116.     p_access->psz_demux = strdup( "directory" );
  117.     return VLC_SUCCESS;
  118. }
  119. /*****************************************************************************
  120.  * Close: close the target
  121.  *****************************************************************************/
  122. static void Close( vlc_object_t * p_this )
  123. {
  124. }
  125. /*****************************************************************************
  126.  * ReadNull: read the directory
  127.  *****************************************************************************/
  128. static int ReadNull( access_t *p_access, uint8_t *p_buffer, int i_len)
  129. {
  130.     /* Return fake data */
  131.     memset( p_buffer, 0, i_len );
  132.     return i_len;
  133. }
  134. /*****************************************************************************
  135.  * Read: read the directory
  136.  *****************************************************************************/
  137. static int Read( access_t *p_access, uint8_t *p_buffer, int i_len)
  138. {
  139.     char *psz_name = NULL;
  140.     char *psz;
  141.     int  i_mode, i_pos;
  142.     playlist_t *p_playlist =
  143.         (playlist_t *) vlc_object_find( p_access,
  144.                                         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
  145.     if( !p_playlist )
  146.     {
  147.         msg_Err( p_access, "can't find playlist" );
  148.         goto end;
  149.     }
  150.     /* Remove the ending '/' char */
  151.     psz_name = strdup( p_access->psz_path );
  152.     if( psz_name == NULL )
  153.         goto end;
  154.     if( (psz_name[strlen(psz_name)-1] == '/') ||
  155.         (psz_name[strlen(psz_name)-1] == '\') )
  156.     {
  157.         psz_name[strlen(psz_name)-1] = '';
  158.     }
  159.     /* Initialize structure */
  160.     psz = var_CreateGetString( p_access, "recursive" );
  161.     if( *psz == '' || !strncmp( psz, "none" , 4 )  )
  162.     {
  163.         i_mode = MODE_NONE;
  164.     }
  165.     else if( !strncmp( psz, "collapse", 8 )  )
  166.     {
  167.         i_mode = MODE_COLLAPSE;
  168.     }
  169.     else
  170.     {
  171.         i_mode = MODE_EXPAND;
  172.     }
  173.     free( psz );
  174.     /* Make sure we are deleted when we are done */
  175.     p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
  176.     /* The playlist position we will use for the add */
  177.     i_pos = p_playlist->i_index + 1;
  178.     msg_Dbg( p_access, "opening directory `%s'", psz_name );
  179.     if( ReadDir( p_playlist, psz_name , i_mode, &i_pos ) != VLC_SUCCESS )
  180.     {
  181.         goto end;
  182.     }
  183. end:
  184.     if( psz_name ) free( psz_name );
  185.     vlc_object_release( p_playlist );
  186.     /* Return fake data forever */
  187.     p_access->pf_read = ReadNull;
  188.     return ReadNull( p_access, p_buffer, i_len );
  189. }
  190. /*****************************************************************************
  191.  * DemuxOpen:
  192.  *****************************************************************************/
  193. static int Control( access_t *p_access, int i_query, va_list args )
  194. {
  195.     vlc_bool_t   *pb_bool;
  196.     int          *pi_int;
  197.     int64_t      *pi_64;
  198.     switch( i_query )
  199.     {
  200.         /* */
  201.         case ACCESS_CAN_SEEK:
  202.         case ACCESS_CAN_FASTSEEK:
  203.         case ACCESS_CAN_PAUSE:
  204.         case ACCESS_CAN_CONTROL_PACE:
  205.             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
  206.             *pb_bool = VLC_FALSE;    /* FIXME */
  207.             break;
  208.         /* */
  209.         case ACCESS_GET_MTU:
  210.             pi_int = (int*)va_arg( args, int * );
  211.             *pi_int = 0;
  212.             break;
  213.         case ACCESS_GET_PTS_DELAY:
  214.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  215.             *pi_64 = DEFAULT_PTS_DELAY * 1000;
  216.             break;
  217.         /* */
  218.         case ACCESS_SET_PAUSE_STATE:
  219.         case ACCESS_GET_TITLE_INFO:
  220.         case ACCESS_SET_TITLE:
  221.         case ACCESS_SET_SEEKPOINT:
  222.         case ACCESS_SET_PRIVATE_ID_STATE:
  223.             return VLC_EGENERIC;
  224.         default:
  225.             msg_Warn( p_access, "unimplemented query in control" );
  226.             return VLC_EGENERIC;
  227.     }
  228.     return VLC_SUCCESS;
  229. }
  230. /*****************************************************************************
  231.  * DemuxOpen:
  232.  *****************************************************************************/
  233. static int DemuxOpen ( vlc_object_t *p_this )
  234. {
  235.     demux_t *p_demux = (demux_t*)p_this;
  236.     if( strcmp( p_demux->psz_demux, "directory" ) )
  237.         return VLC_EGENERIC;
  238.     p_demux->pf_demux   = Demux;
  239.     p_demux->pf_control = DemuxControl;
  240.     return VLC_SUCCESS;
  241. }
  242. /*****************************************************************************
  243.  * Demux: EOF
  244.  *****************************************************************************/
  245. static int Demux( demux_t *p_demux )
  246. {
  247.     return 0;
  248. }
  249. /*****************************************************************************
  250.  * DemuxControl:
  251.  *****************************************************************************/
  252. static int DemuxControl( demux_t *p_demux, int i_query, va_list args )
  253. {
  254.     return demux2_vaControlHelper( p_demux->s,
  255.                                    0, 0, 0, 1,
  256.                                    i_query, args );
  257. }
  258. /*****************************************************************************
  259.  * ReadDir: read a directory and add its content to the list
  260.  *****************************************************************************/
  261. static int ReadDir( playlist_t *p_playlist,
  262.                     char *psz_name , int i_mode, int *pi_position )
  263. {
  264.     DIR *                       p_current_dir;
  265.     struct dirent *             p_dir_content;
  266.     /* Open the dir */
  267.     p_current_dir = opendir( psz_name );
  268.     if( p_current_dir == NULL )
  269.     {
  270.         /* something went bad, get out of here ! */
  271. #   ifdef HAVE_ERRNO_H
  272.         msg_Warn( p_playlist, "cannot open directory `%s' (%s)",
  273.                   psz_name, strerror(errno));
  274. #   else
  275.         msg_Warn( p_playlist, "cannot open directory `%s'", psz_name );
  276. #   endif
  277.         return VLC_EGENERIC;
  278.     }
  279.     /* get the first directory entry */
  280.     p_dir_content = readdir( p_current_dir );
  281.     /* while we still have entries in the directory */
  282.     while( p_dir_content != NULL )
  283.     {
  284.         int i_size_entry = strlen( psz_name ) +
  285.                            strlen( p_dir_content->d_name ) + 2;
  286.         char *psz_uri = (char *)malloc( sizeof(char)*i_size_entry);
  287.         sprintf( psz_uri, "%s/%s", psz_name, p_dir_content->d_name );
  288.         /* if it starts with '.' then forget it */
  289.         if( p_dir_content->d_name[0] != '.' )
  290.         {
  291. #if defined( S_ISDIR )
  292.             struct stat stat_data;
  293.             stat( psz_uri, &stat_data );
  294.             if( S_ISDIR(stat_data.st_mode) && i_mode != MODE_COLLAPSE )
  295. #elif defined( DT_DIR )
  296.             if( ( p_dir_content->d_type & DT_DIR ) && i_mode != MODE_COLLAPSE )
  297. #else
  298.             if( 0 )
  299. #endif
  300.             {
  301.                 if( i_mode == MODE_NONE )
  302.                 {
  303.                     msg_Dbg( p_playlist, "Skipping subdirectory %s", psz_uri );
  304.                     p_dir_content = readdir( p_current_dir );
  305.                     continue;
  306.                 }
  307.                 else if(i_mode == MODE_EXPAND )
  308.                 {
  309.                     msg_Dbg(p_playlist, "Reading subdirectory %s", psz_uri );
  310.                     if( ReadDir( p_playlist, psz_uri , MODE_EXPAND, pi_position )
  311.                                  != VLC_SUCCESS )
  312.                     {
  313.                         return VLC_EGENERIC;
  314.                     }
  315.                 }
  316.             }
  317.             else
  318.             {
  319.                 playlist_Add( p_playlist, psz_uri, p_dir_content->d_name,
  320.                           PLAYLIST_INSERT, *pi_position );
  321.                 (*pi_position)++;
  322.             }
  323.         }
  324.         free( psz_uri );
  325.         p_dir_content = readdir( p_current_dir );
  326.     }
  327.     closedir( p_current_dir );
  328.     return VLC_SUCCESS;
  329. }