Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

gnomevfs.c

00001 /*****************************************************************************
00002  * gnomevfs.c: GnomeVFS input
00003  *****************************************************************************
00004  * Copyright (C) 2005 the VideoLAN team
00005  * $Id: gnomevfs.c 12714 2005-09-30 17:18:45Z bigben $
00006  *
00007  * Authors: Benjamin Pracht <bigben -AT- videolan -DOT- org>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <vlc/vlc.h>
00028 #include <vlc/input.h>
00029 #include <libgnomevfs/gnome-vfs.h>
00030 
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <stdio.h>
00034 
00035 #include "charset.h"
00036 #include "network.h"
00037 
00038 /*****************************************************************************
00039  * Module descriptor
00040  *****************************************************************************/
00041 static int  Open ( vlc_object_t * );
00042 static void Close( vlc_object_t * );
00043 
00044 #define CACHING_TEXT N_("Caching value in ms")
00045 #define CACHING_LONGTEXT N_( \
00046     "Allows you to modify the default caching value for GnomeVFS streams."\
00047     "This value should be set in millisecond units." )
00048 
00049 vlc_module_begin();
00050     set_description( _("GnomeVFS filesystem file input") );
00051     set_shortname( _("GnomeVFS") );
00052     set_category( CAT_INPUT );
00053     set_subcategory( SUBCAT_INPUT_ACCESS );
00054     add_integer( "gnomevfs-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
00055     set_capability( "access2", 10 );
00056     add_shortcut( "gnomevfs" );
00057     set_callbacks( Open, Close );
00058 vlc_module_end();
00059 
00060 
00061 /*****************************************************************************
00062  * Exported prototypes
00063  *****************************************************************************/
00064 static int  Seek( access_t *, int64_t );
00065 static int  Read( access_t *, uint8_t *, int );
00066 static int  Control( access_t *, int, va_list );
00067 
00068 struct access_sys_t
00069 {
00070     unsigned int i_nb_reads;
00071     char *psz_name;
00072 
00073     GnomeVFSHandle *p_handle;
00074     GnomeVFSFileInfo *p_file_info;
00075 
00076     vlc_bool_t b_local;
00077     vlc_bool_t b_seekable;
00078     vlc_bool_t b_pace_control;
00079 };
00080 
00081 /*****************************************************************************
00082  * Open: open the file
00083  *****************************************************************************/
00084 static int Open( vlc_object_t *p_this )
00085 {
00086     access_t       *p_access = (access_t*)p_this;
00087     access_sys_t   *p_sys = NULL;
00088     char           *psz_name = NULL;
00089     char           *psz = NULL;
00090     char           *psz_uri = NULL;
00091     char           *psz_unescaped = NULL;
00092     char           *psz_expand_tilde = NULL;
00093     GnomeVFSURI    *p_uri = NULL;
00094     GnomeVFSResult  i_ret;
00095     GnomeVFSHandle *p_handle = NULL;
00096     if( !(gnome_vfs_init()) )
00097     {
00098         msg_Warn( p_access, "couldn't initilize GnomeVFS" );
00099         return VLC_EGENERIC;
00100     }
00101 
00102     /* FIXME
00103        Since GnomeVFS segfaults on exit if we initialize it without trying to
00104        open a file with a valid protocol, try to open at least file:// */
00105     gnome_vfs_open( &p_handle, "file://", 5 );
00106 
00107     p_access->pf_read = Read;
00108     p_access->pf_block = NULL;
00109     p_access->pf_seek = Seek;
00110     p_access->pf_control = Control;
00111     p_access->info.i_update = 0;
00112     p_access->info.i_size = 0;
00113     p_access->info.i_pos = 0;
00114     p_access->info.b_eof = VLC_FALSE;
00115     p_access->info.i_title = 0;
00116     p_access->info.i_seekpoint = 0;
00117 
00118     p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
00119     if( !p_sys )
00120         return VLC_ENOMEM;
00121 
00122     p_sys->p_handle = p_handle;
00123     p_sys->i_nb_reads = 0;
00124     p_sys->b_pace_control = VLC_TRUE;
00125 
00126     if( strcmp( "gnomevfs", p_access->psz_access ) &&
00127                                             *(p_access->psz_access) != '\0')
00128     {
00129         psz_name = malloc( strlen( p_access->psz_access ) +
00130                                             strlen( p_access->psz_path ) + 4 );
00131         sprintf( psz_name, "%s://%s", p_access->psz_access,
00132                                                     p_access->psz_path );
00133     }
00134     else
00135     {
00136         psz_name = strdup( p_access->psz_path );
00137     }
00138     psz = ToLocale( psz_name );
00139     psz_expand_tilde = gnome_vfs_expand_initial_tilde( psz );
00140     LocaleFree( psz );
00141 
00142     psz_unescaped = gnome_vfs_make_uri_from_shell_arg( psz_expand_tilde );
00143 
00144    /* gnome_vfs_make_uri_from_shell_arg will only escape the uri
00145       for relative paths. So we need to use
00146       gnome_vfs_escape_host_and_path_string in other cases. */
00147 
00148     if( !strcmp( psz_unescaped, psz_expand_tilde ) )
00149     {
00150     /* Now we are sure that we have a complete valid unescaped URI beginning
00151        with the protocol. We want to escape it. However, gnomevfs's escaping
00152        function are broken and will try to escape characters un the username/
00153        password field. So parse the URI with vlc_UrlParse ans only escape the
00154        path */
00155 
00156         vlc_url_t url;
00157         char *psz_escaped_path;
00158         char *psz_path_begin;
00159 
00160         vlc_UrlParse( &url, psz_unescaped, 0 );
00161         psz_escaped_path = gnome_vfs_escape_path_string( url.psz_path );
00162 
00163         if( psz_escaped_path )
00164         {
00165     /* Now let's reconstruct a valid URI from all that stuff */
00166             psz_path_begin = psz_unescaped + strlen( psz_unescaped )
00167                                            - strlen( url.psz_path );
00168             *psz_path_begin = '\0';
00169             psz_uri = malloc( strlen( psz_unescaped ) +
00170                                         strlen( psz_escaped_path ) + 1 );
00171             sprintf( psz_uri, "%s%s",psz_unescaped, psz_escaped_path );
00172 
00173             g_free( psz_escaped_path );
00174             g_free( psz_unescaped );
00175         }
00176         else
00177         {
00178             psz_uri = psz_unescaped;
00179         }
00180     }
00181     else
00182     {
00183         psz_uri = psz_unescaped;
00184     }
00185 
00186     g_free( psz_expand_tilde );
00187     p_uri = gnome_vfs_uri_new( psz_uri );
00188     if( p_uri )
00189     {
00190         p_sys->p_file_info = gnome_vfs_file_info_new();
00191         i_ret = gnome_vfs_get_file_info_uri( p_uri,
00192                                                 p_sys->p_file_info, 8 ); 
00193 
00194         if( i_ret )
00195         {
00196             msg_Err( p_access, "cannot get file info for uri %s (%s)", 
00197                                 psz_uri, gnome_vfs_result_to_string( i_ret ) );
00198             gnome_vfs_file_info_unref( p_sys->p_file_info );
00199             gnome_vfs_uri_unref( p_uri);
00200             free( p_sys );
00201             g_free( psz_uri );
00202             free( psz_name );
00203             return VLC_EGENERIC;
00204         }
00205     }
00206     else
00207     {
00208         msg_Warn( p_access, "cannot parse MRL %s or unsupported protocol", psz_name );
00209         g_free( psz_uri );
00210         free( p_sys );
00211         free( psz_name );
00212         return VLC_EGENERIC;
00213     }
00214 
00215     msg_Dbg( p_access, "opening file `%s'", psz_uri );
00216     i_ret = gnome_vfs_open( &(p_sys->p_handle), psz_uri, 5 );
00217     if( i_ret )
00218     {
00219         msg_Warn( p_access, "cannot open file %s: %s", psz_uri,
00220                                 gnome_vfs_result_to_string( i_ret ) );
00221 
00222         gnome_vfs_uri_unref( p_uri);
00223         g_free( psz_uri );
00224         free( p_sys ); 
00225         free( psz_name );
00226         return VLC_EGENERIC;
00227     }
00228 
00229     if (GNOME_VFS_FILE_INFO_LOCAL( p_sys->p_file_info ))
00230     {
00231         p_sys->b_local = VLC_TRUE;
00232     }
00233 
00234     if( p_sys->p_file_info->type == GNOME_VFS_FILE_TYPE_REGULAR || 
00235         p_sys->p_file_info->type == GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE ||
00236         p_sys->p_file_info->type == GNOME_VFS_FILE_TYPE_BLOCK_DEVICE )
00237     {
00238         p_sys->b_seekable = VLC_TRUE;
00239         p_access->info.i_size = (int64_t)(p_sys->p_file_info->size);
00240     }
00241     else if( p_sys->p_file_info->type == GNOME_VFS_FILE_TYPE_FIFO
00242               || p_sys->p_file_info->type == GNOME_VFS_FILE_TYPE_SOCKET )
00243     {
00244         p_sys->b_seekable = VLC_FALSE;
00245     }
00246     else
00247     {
00248         msg_Err( p_access, "unknown file type for `%s'", psz_name );
00249         return VLC_EGENERIC;
00250     }
00251 
00252     if( p_sys->b_seekable && !p_access->info.i_size )
00253     {
00254         /* FIXME that's bad because all others access will be probed */
00255         msg_Err( p_access, "file %s is empty, aborting", psz_name );
00256         gnome_vfs_file_info_unref( p_sys->p_file_info );
00257         gnome_vfs_uri_unref( p_uri);
00258         free( p_sys );
00259         g_free( psz_uri );
00260         free( psz_name );
00261         return VLC_EGENERIC;
00262     }
00263 
00264     /* Update default_pts to a suitable value for file access */
00265     var_Create( p_access, "gnomevfs-caching",
00266                                     VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00267 
00268     g_free( psz_uri );
00269     p_sys->psz_name = psz_name;
00270     gnome_vfs_uri_unref( p_uri);
00271     return VLC_SUCCESS;
00272 }
00273 
00274 /*****************************************************************************
00275  * Close: close the target
00276  *****************************************************************************/
00277 static void Close( vlc_object_t * p_this )
00278 {
00279     access_t     *p_access = (access_t*)p_this;
00280     access_sys_t *p_sys = p_access->p_sys;
00281     int i_result;
00282 
00283     i_result = gnome_vfs_close( p_sys->p_handle );
00284     if( i_result )
00285     {
00286          msg_Err( p_access, "cannot close %s: %s", p_sys->psz_name,
00287                                 gnome_vfs_result_to_string( i_result ) );
00288     }
00289 
00290     gnome_vfs_file_info_unref( p_sys->p_file_info );
00291 
00292     free( p_sys->psz_name );
00293     free( p_sys );
00294 }
00295 
00296 /*****************************************************************************
00297  * Read: standard read on a file descriptor.
00298  *****************************************************************************/
00299 static int Read( access_t *p_access, uint8_t *p_buffer, int i_len )
00300 {
00301     access_sys_t *p_sys = p_access->p_sys;
00302     GnomeVFSFileSize i_read_len;
00303     int i_ret;
00304 
00305     i_ret = gnome_vfs_read( p_sys->p_handle, p_buffer,
00306                                   (GnomeVFSFileSize)i_len, &i_read_len );
00307     if( i_ret )
00308     {
00309         p_access->info.b_eof = VLC_TRUE;
00310         if( i_ret != GNOME_VFS_ERROR_EOF )
00311         {
00312             msg_Err( p_access, "read failed (%s)",
00313                                     gnome_vfs_result_to_string( i_ret ) );
00314         }
00315     }
00316     else
00317     {
00318         p_sys->i_nb_reads++;
00319         if( p_access->info.i_size != 0 &&
00320             (p_sys->i_nb_reads % INPUT_FSTAT_NB_READS) == 0 &&
00321             p_sys->b_local )
00322         {
00323             gnome_vfs_file_info_clear( p_sys->p_file_info );
00324             i_ret = gnome_vfs_get_file_info_from_handle( p_sys->p_handle,
00325                                                 p_sys->p_file_info, 8 );
00326             if( i_ret )
00327             {
00328                 msg_Warn( p_access, "couldn't get file properties again (%s)",
00329                                         gnome_vfs_result_to_string( i_ret ) );
00330             }
00331             else
00332             {
00333                 p_access->info.i_size = (int64_t)(p_sys->p_file_info->size);
00334             }
00335         }
00336     }
00337 
00338     p_access->info.i_pos += (int64_t)i_read_len;
00339 
00340     /* Some Acces (http) never return EOF and loop on the file */
00341     if( p_access->info.i_pos > p_access->info.i_size )
00342     {
00343         p_access->info.b_eof = VLC_TRUE;
00344         return 0;
00345     }
00346     return (int)i_read_len;
00347 }
00348 
00349 /*****************************************************************************
00350  * Seek: seek to a specific location in a file
00351  *****************************************************************************/
00352 static int Seek( access_t *p_access, int64_t i_pos )
00353 {
00354     access_sys_t *p_sys = p_access->p_sys;
00355     int i_ret;
00356 
00357     i_ret = gnome_vfs_seek( p_sys->p_handle, GNOME_VFS_SEEK_START,
00358                                             (GnomeVFSFileOffset)i_pos);
00359     if ( !i_ret )
00360     {
00361         p_access->info.i_pos = i_pos;
00362     }
00363     else
00364     {
00365         GnomeVFSFileSize i_offset;
00366         msg_Err( p_access, "cannot seek (%s)",
00367                                         gnome_vfs_result_to_string( i_ret ) );
00368         i_ret = gnome_vfs_tell( p_sys->p_handle, &i_offset );
00369         if( !i_ret )
00370         {
00371             msg_Err( p_access, "cannot tell the current position (%s)",
00372                                         gnome_vfs_result_to_string( i_ret ) );
00373             return VLC_EGENERIC;
00374         }
00375     }
00376     /* Reset eof */
00377     p_access->info.b_eof = VLC_FALSE;
00378 
00379     /* FIXME */
00380     return VLC_SUCCESS;
00381 }
00382 
00383 /*****************************************************************************
00384  * Control:
00385  *****************************************************************************/
00386 static int Control( access_t *p_access, int i_query, va_list args )
00387 {
00388     access_sys_t *p_sys = p_access->p_sys;
00389     vlc_bool_t   *pb_bool;
00390     int          *pi_int;
00391     int64_t      *pi_64;
00392 
00393     switch( i_query )
00394     {
00395         /* */
00396         case ACCESS_CAN_SEEK:
00397         case ACCESS_CAN_FASTSEEK:
00398             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
00399             *pb_bool = p_sys->b_seekable;
00400             break;
00401 
00402         case ACCESS_CAN_PAUSE:
00403         case ACCESS_CAN_CONTROL_PACE:
00404             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
00405             *pb_bool = p_sys->b_pace_control;
00406             break;
00407 
00408         /* */
00409         case ACCESS_GET_MTU:
00410             pi_int = (int*)va_arg( args, int * );
00411             *pi_int = 0;
00412             break;
00413 
00414         case ACCESS_GET_PTS_DELAY:
00415             pi_64 = (int64_t*)va_arg( args, int64_t * );
00416             *pi_64 = var_GetInteger( p_access,
00417                                         "gnomevfs-caching" ) * I64C(1000);
00418             break;
00419 
00420         /* */
00421         case ACCESS_SET_PAUSE_STATE:
00422             /* Nothing to do */
00423             break;
00424 
00425         case ACCESS_GET_TITLE_INFO:
00426         case ACCESS_SET_TITLE:
00427         case ACCESS_SET_SEEKPOINT:
00428         case ACCESS_SET_PRIVATE_ID_STATE:
00429         case ACCESS_GET_META:
00430             return VLC_EGENERIC;
00431 
00432         default:
00433             msg_Warn( p_access, "unimplemented query in control" );
00434             return VLC_EGENERIC;
00435 
00436     }
00437     return VLC_SUCCESS;
00438 }

Generated on Tue Dec 20 10:14:25 2005 for vlc-0.8.4a by  doxygen 1.4.2