00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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
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
00103
00104
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
00145
00146
00147
00148 if( !strcmp( psz_unescaped, psz_expand_tilde ) )
00149 {
00150
00151
00152
00153
00154
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
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
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
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
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
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
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
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
00377 p_access->info.b_eof = VLC_FALSE;
00378
00379
00380 return VLC_SUCCESS;
00381 }
00382
00383
00384
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
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 }