1 /*****************************************************************************
2 * gnomevfs.c: GnomeVFS input
3 *****************************************************************************
4 * Copyright (C) 2005 VLC authors and VideoLAN
7 * Authors: Benjamin Pracht <bigben -AT- videolan -DOT- org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_access.h>
36 #include <libgnomevfs/gnome-vfs.h>
40 /*****************************************************************************
42 *****************************************************************************/
43 static int Open ( vlc_object_t
* );
44 static void Close( vlc_object_t
* );
47 set_description( N_("GnomeVFS input") )
48 set_shortname( "GnomeVFS" )
49 set_category( CAT_INPUT
)
50 set_subcategory( SUBCAT_INPUT_ACCESS
)
51 set_capability( "access", 10 )
52 add_shortcut( "gnomevfs" )
53 set_callbacks( Open
, Close
)
57 /*****************************************************************************
59 *****************************************************************************/
60 static int Seek( access_t
*, uint64_t );
61 static ssize_t
Read( access_t
*, uint8_t *, size_t );
62 static int Control( access_t
*, int, va_list );
68 GnomeVFSHandle
*p_handle
;
69 GnomeVFSFileInfo
*p_file_info
;
76 /* NOTE: we do not handle memory errors in this plugin.
77 * Underlying glib does not, so there is no point in doing it here either. */
79 /*****************************************************************************
81 *****************************************************************************/
82 static int Open( vlc_object_t
*p_this
)
84 access_t
*p_access
= (access_t
*)p_this
;
85 access_sys_t
*p_sys
= NULL
;
86 char *psz_name
= NULL
;
88 char *psz_unescaped
= NULL
;
89 char *psz_expand_tilde
= NULL
;
90 GnomeVFSURI
*p_uri
= NULL
;
92 GnomeVFSHandle
*p_handle
= NULL
;
93 if( !(gnome_vfs_init()) )
95 msg_Warn( p_access
, "couldn't initilize GnomeVFS" );
100 Since GnomeVFS segfaults on exit if we initialize it without trying to
101 open a file with a valid protocol, try to open at least file:// */
102 gnome_vfs_open( &p_handle
, "file://", 5 );
104 STANDARD_READ_ACCESS_INIT
;
106 p_sys
->p_handle
= p_handle
;
107 p_sys
->b_pace_control
= true;
109 if( strcmp( "gnomevfs", p_access
->psz_access
) &&
110 *(p_access
->psz_access
) != '\0')
112 asprintf( &psz_name
, "%s://%s", p_access
->psz_access
,
113 p_access
->psz_location
);
117 psz_name
= strdup( p_access
->psz_location
);
119 psz_expand_tilde
= gnome_vfs_expand_initial_tilde( psz_name
);
121 psz_unescaped
= gnome_vfs_make_uri_from_shell_arg( psz_expand_tilde
);
123 /* gnome_vfs_make_uri_from_shell_arg will only escape the uri
124 for relative paths. So we need to use
125 gnome_vfs_escape_host_and_path_string in other cases. */
127 if( !strcmp( psz_unescaped
, psz_expand_tilde
) )
129 /* Now we are sure that we have a complete valid unescaped URI beginning
130 with the protocol. We want to escape it. However, gnomevfs's escaping
131 function are broken and will try to escape characters un the username/
132 password field. So parse the URI with vlc_UrlParse ans only escape the
136 char *psz_escaped_path
;
137 char *psz_path_begin
;
139 vlc_UrlParse( &url
, psz_unescaped
, 0 );
140 psz_escaped_path
= gnome_vfs_escape_path_string( url
.psz_path
);
142 if( psz_escaped_path
)
144 /* Now let's reconstruct a valid URI from all that stuff */
145 psz_path_begin
= psz_unescaped
+ strlen( psz_unescaped
)
146 - strlen( url
.psz_path
);
147 *psz_path_begin
= '\0';
148 asprintf( &psz_uri
, "%s%s", psz_unescaped
, psz_escaped_path
);
150 g_free( psz_escaped_path
);
151 g_free( psz_unescaped
);
155 psz_uri
= psz_unescaped
;
160 psz_uri
= psz_unescaped
;
163 g_free( psz_expand_tilde
);
164 p_uri
= gnome_vfs_uri_new( psz_uri
);
167 p_sys
->p_file_info
= gnome_vfs_file_info_new();
168 i_ret
= gnome_vfs_get_file_info_uri( p_uri
,
169 p_sys
->p_file_info
, 8 );
173 msg_Warn( p_access
, "cannot get file info for uri %s (%s)",
174 psz_uri
, gnome_vfs_result_to_string( i_ret
) );
175 gnome_vfs_file_info_unref( p_sys
->p_file_info
);
176 gnome_vfs_uri_unref( p_uri
);
185 msg_Warn( p_access
, "cannot parse MRL %s or unsupported protocol", psz_name
);
192 msg_Dbg( p_access
, "opening file `%s'", psz_uri
);
193 i_ret
= gnome_vfs_open( &(p_sys
->p_handle
), psz_uri
, 5 );
196 msg_Warn( p_access
, "cannot open file %s: %s", psz_uri
,
197 gnome_vfs_result_to_string( i_ret
) );
199 gnome_vfs_uri_unref( p_uri
);
206 if (GNOME_VFS_FILE_INFO_LOCAL( p_sys
->p_file_info
))
208 p_sys
->b_local
= true;
211 if( p_sys
->p_file_info
->type
== GNOME_VFS_FILE_TYPE_REGULAR
||
212 p_sys
->p_file_info
->type
== GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE
||
213 p_sys
->p_file_info
->type
== GNOME_VFS_FILE_TYPE_BLOCK_DEVICE
)
215 p_sys
->b_seekable
= true;
217 else if( p_sys
->p_file_info
->type
== GNOME_VFS_FILE_TYPE_FIFO
218 || p_sys
->p_file_info
->type
== GNOME_VFS_FILE_TYPE_SOCKET
)
220 p_sys
->b_seekable
= false;
224 msg_Err( p_access
, "unknown file type for `%s'", psz_name
);
228 if( p_sys
->b_seekable
&& !p_sys
->p_file_info
->size
)
230 /* FIXME that's bad because all others access will be probed */
231 msg_Warn( p_access
, "file %s is empty, aborting", psz_name
);
232 gnome_vfs_file_info_unref( p_sys
->p_file_info
);
233 gnome_vfs_uri_unref( p_uri
);
241 p_sys
->psz_name
= psz_name
;
242 gnome_vfs_uri_unref( p_uri
);
246 /*****************************************************************************
247 * Close: close the target
248 *****************************************************************************/
249 static void Close( vlc_object_t
* p_this
)
251 access_t
*p_access
= (access_t
*)p_this
;
252 access_sys_t
*p_sys
= p_access
->p_sys
;
255 i_result
= gnome_vfs_close( p_sys
->p_handle
);
258 msg_Err( p_access
, "cannot close %s: %s", p_sys
->psz_name
,
259 gnome_vfs_result_to_string( i_result
) );
262 gnome_vfs_file_info_unref( p_sys
->p_file_info
);
264 free( p_sys
->psz_name
);
268 /*****************************************************************************
269 * Read: standard read on a file descriptor.
270 *****************************************************************************/
271 static ssize_t
Read( access_t
*p_access
, uint8_t *p_buffer
, size_t i_len
)
273 access_sys_t
*p_sys
= p_access
->p_sys
;
274 GnomeVFSFileSize i_read_len
;
277 i_ret
= gnome_vfs_read( p_sys
->p_handle
, p_buffer
,
278 (GnomeVFSFileSize
)i_len
, &i_read_len
);
281 p_access
->info
.b_eof
= true;
282 if( i_ret
!= GNOME_VFS_ERROR_EOF
)
284 msg_Err( p_access
, "read failed (%s)",
285 gnome_vfs_result_to_string( i_ret
) );
289 p_access
->info
.i_pos
+= (int64_t)i_read_len
;
290 if( p_access
->info
.i_pos
>= p_sys
->p_file_info
->size
291 && p_sys
->p_file_info
->size
!= 0 && p_sys
->b_local
)
293 gnome_vfs_file_info_clear( p_sys
->p_file_info
);
294 i_ret
= gnome_vfs_get_file_info_from_handle( p_sys
->p_handle
,
295 p_sys
->p_file_info
, 8 );
297 msg_Warn( p_access
, "couldn't get file properties again (%s)",
298 gnome_vfs_result_to_string( i_ret
) );
300 return (int)i_read_len
;
303 /*****************************************************************************
304 * Seek: seek to a specific location in a file
305 *****************************************************************************/
306 static int Seek( access_t
*p_access
, uint64_t i_pos
)
308 access_sys_t
*p_sys
= p_access
->p_sys
;
311 i_ret
= gnome_vfs_seek( p_sys
->p_handle
, GNOME_VFS_SEEK_START
,
312 (GnomeVFSFileOffset
)i_pos
);
315 p_access
->info
.i_pos
= i_pos
;
319 GnomeVFSFileSize i_offset
;
320 msg_Err( p_access
, "cannot seek (%s)",
321 gnome_vfs_result_to_string( i_ret
) );
322 i_ret
= gnome_vfs_tell( p_sys
->p_handle
, &i_offset
);
325 msg_Err( p_access
, "cannot tell the current position (%s)",
326 gnome_vfs_result_to_string( i_ret
) );
331 p_access
->info
.b_eof
= false;
337 /*****************************************************************************
339 *****************************************************************************/
340 static int Control( access_t
*p_access
, int i_query
, va_list args
)
342 access_sys_t
*p_sys
= p_access
->p_sys
;
348 case ACCESS_CAN_SEEK
:
349 case ACCESS_CAN_FASTSEEK
:
350 pb_bool
= (bool*)va_arg( args
, bool* );
351 *pb_bool
= p_sys
->b_seekable
;
354 case ACCESS_CAN_PAUSE
:
355 case ACCESS_CAN_CONTROL_PACE
:
356 pb_bool
= (bool*)va_arg( args
, bool* );
357 *pb_bool
= p_sys
->b_pace_control
;
360 case ACCESS_GET_SIZE
:
361 *va_arg( args
, uint64_t * ) = p_sys
->p_file_info
->size
;
364 case ACCESS_GET_PTS_DELAY
:
365 pi_64
= (int64_t*)va_arg( args
, int64_t * );
366 *pi_64
= DEFAULT_PTS_DELAY
; /* FIXME */
369 case ACCESS_SET_PAUSE_STATE
: