]> git.sesse.net Git - vlc/blob - modules/access/file.c
* ./evc/plugins.vcp.in: fixed plugin entry points for WinCE.
[vlc] / modules / access / file.c
1 /*****************************************************************************
2  * file.c: file input (file: access plug-in)
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: file.c,v 1.4 2002/11/20 13:37:35 sam Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
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 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/input.h>
29
30 #include <stdlib.h>
31 #include <string.h>
32 #ifdef HAVE_SYS_TYPES_H
33 #   include <sys/types.h>
34 #endif
35 #ifdef HAVE_SYS_STAT_H
36 #   include <sys/stat.h>
37 #endif
38 #ifdef HAVE_ERRNO_H
39 #   include <errno.h>
40 #endif
41 #ifdef HAVE_FCNTL_H
42 #   include <fcntl.h>
43 #endif
44
45 #ifdef HAVE_UNISTD_H
46 #   include <unistd.h>
47 #elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
48 #   include <io.h>
49 #endif
50
51 /*****************************************************************************
52  * Exported prototypes
53  *****************************************************************************/
54 static int     Open   ( vlc_object_t * );
55 static void    Close  ( vlc_object_t * );
56
57 static void    Seek   ( input_thread_t *, off_t );
58 static ssize_t Read   ( input_thread_t *, byte_t *, size_t );
59
60 /*****************************************************************************
61  * Module descriptor
62  *****************************************************************************/
63 vlc_module_begin();
64     set_description( _("Standard filesystem file reading") );
65     set_capability( "access", 50 );
66     add_shortcut( "file" );
67     add_shortcut( "stream" );
68     set_callbacks( Open, Close );
69 vlc_module_end();
70  
71 /*****************************************************************************
72  * Open: open the file
73  *****************************************************************************/
74 static int Open( vlc_object_t *p_this )
75 {
76     input_thread_t *    p_input = (input_thread_t *)p_this;
77     char *              psz_name = p_input->psz_name;
78 #ifdef HAVE_SYS_STAT_H
79     int                 i_stat;
80     struct stat         stat_info;                                              
81 #endif
82     input_socket_t *    p_access_data;
83     vlc_bool_t          b_stdin;
84
85     p_input->i_mtu = 0;
86
87     b_stdin = psz_name[0] == '-' && psz_name[1] == '\0';
88
89 #ifdef HAVE_SYS_STAT_H
90     if( !b_stdin && (i_stat = stat( psz_name, &stat_info )) == (-1) )
91     {
92 #   ifdef HAVE_ERRNO_H
93         msg_Err( p_input, "cannot stat() file `%s' (%s)",
94                           psz_name, strerror(errno));
95 #   else
96         msg_Err( p_input, "cannot stat() file `%s'", psz_name );
97 #   endif
98         return VLC_EGENERIC;
99     }
100 #endif
101
102     p_input->pf_read = Read;
103     p_input->pf_set_program = input_SetProgram;
104     p_input->pf_set_area = NULL;
105     p_input->pf_seek = Seek;
106
107     vlc_mutex_lock( &p_input->stream.stream_lock );
108
109     if( *p_input->psz_access && !strncmp( p_input->psz_access, "stream", 7 ) )
110     {
111         /* stream:%s */
112         p_input->stream.b_pace_control = 0;
113         p_input->stream.b_seekable = 0;
114         p_input->stream.p_selected_area->i_size = 0;
115     }
116     else
117     {
118         /* file:%s or %s */
119         p_input->stream.b_pace_control = 1;
120
121         if( b_stdin )
122         {
123             p_input->stream.b_seekable = 0;
124             p_input->stream.p_selected_area->i_size = 0;
125         }
126 #ifdef HAVE_SYS_STAT_H
127         else if( S_ISREG(stat_info.st_mode) || S_ISCHR(stat_info.st_mode)
128                   || S_ISBLK(stat_info.st_mode) )
129         {
130             p_input->stream.b_seekable = 1;
131             p_input->stream.p_selected_area->i_size = stat_info.st_size;
132         }
133         else if( S_ISFIFO(stat_info.st_mode)
134 #   if !defined( SYS_BEOS ) && !defined( WIN32 )
135                   || S_ISSOCK(stat_info.st_mode)
136 #   endif
137                )
138         {
139             p_input->stream.b_seekable = 0;
140             p_input->stream.p_selected_area->i_size = 0;
141         }
142         else
143         {
144             vlc_mutex_unlock( &p_input->stream.stream_lock );
145             msg_Err( p_input, "unknown file type for `%s'", psz_name );
146             return VLC_EGENERIC;
147         }
148 #endif
149     }
150  
151     p_input->stream.p_selected_area->i_tell = 0;
152     p_input->stream.i_method = INPUT_METHOD_FILE;
153     vlc_mutex_unlock( &p_input->stream.stream_lock );
154  
155     msg_Dbg( p_input, "opening file `%s'", psz_name );
156     p_access_data = malloc( sizeof(input_socket_t) );
157     p_input->p_access_data = (void *)p_access_data;
158     if( p_access_data == NULL )
159     {
160         msg_Err( p_input, "out of memory" );
161         return VLC_ENOMEM;
162     }
163
164     if( b_stdin )
165     {
166         p_access_data->i_handle = 0;
167     }
168     else
169     {
170 #ifdef UNDER_CE
171         wchar_t psz_filename[MAX_PATH];
172         MultiByteToWideChar( CP_ACP, 0, psz_name, -1, psz_filename, MAX_PATH );
173
174         p_access_data->i_handle = (int)CreateFile( psz_filename,
175             GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 
176             FILE_ATTRIBUTE_NORMAL, NULL );
177
178         if( (HANDLE)p_access_data->i_handle == INVALID_HANDLE_VALUE )
179         {
180             msg_Err( p_input, "cannot open file %s", psz_name );
181             free( p_access_data );
182             return VLC_EGENERIC;
183         }
184 #else
185         p_access_data->i_handle = open( psz_name,
186                                         /*O_NONBLOCK | O_LARGEFILE*/ 0 );
187         if( p_access_data->i_handle == -1 )
188         {
189 #   ifdef HAVE_ERRNO_H
190             msg_Err( p_input, "cannot open file %s (%s)", psz_name,
191                               strerror(errno) );
192 #   else
193             msg_Err( p_input, "cannot open file %s", psz_name );
194 #   endif
195             free( p_access_data );
196             return VLC_EGENERIC;
197         }
198 #endif
199     }
200
201     return VLC_SUCCESS;
202 }
203
204 /*****************************************************************************
205  * Close: close the target
206  *****************************************************************************/
207 static void Close( vlc_object_t * p_this )
208 {
209     input_thread_t * p_input = (input_thread_t *)p_this;
210     input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
211
212     msg_Info( p_input, "closing `%s/%s://%s'", 
213               p_input->psz_access, p_input->psz_demux, p_input->psz_name );
214  
215 #ifdef UNDER_CE
216     CloseHandle( (HANDLE)p_access_data->i_handle );
217 #else
218     close( p_access_data->i_handle );
219 #endif
220
221     free( p_access_data );
222 }
223
224 /*****************************************************************************
225  * Read: standard read on a file descriptor.
226  *****************************************************************************/
227 static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
228 {
229     input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
230     ssize_t i_ret;
231  
232 #ifdef UNDER_CE
233     if( !ReadFile( (HANDLE)p_access_data->i_handle, p_buffer, i_len,
234                    (LPDWORD)&i_ret, NULL ) )
235     {
236         i_ret = -1;
237     }
238 #else
239     i_ret = read( p_access_data->i_handle, p_buffer, i_len );
240 #endif
241  
242     if( i_ret < 0 )
243     {
244 #   ifdef HAVE_ERRNO_H
245         msg_Err( p_input, "read failed (%s)", strerror(errno) );
246 #   else
247         msg_Err( p_input, "read failed" );
248 #   endif
249     }
250  
251     return i_ret;
252 }
253
254 /*****************************************************************************
255  * Seek: seek to a specific location in a file
256  *****************************************************************************/
257 static void Seek( input_thread_t * p_input, off_t i_pos )
258 {
259 #define S p_input->stream
260     input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
261
262     lseek( p_access_data->i_handle, i_pos, SEEK_SET );
263
264     vlc_mutex_lock( &S.stream_lock );
265     S.p_selected_area->i_tell = i_pos;
266     if( S.p_selected_area->i_tell > S.p_selected_area->i_size )
267     {
268         msg_Err( p_input, "seeking too far" );
269         S.p_selected_area->i_tell = S.p_selected_area->i_size;
270     }
271     else if( S.p_selected_area->i_tell < 0 )
272     {
273         msg_Err( p_input, "seeking too early" );
274         S.p_selected_area->i_tell = 0;
275     }
276     vlc_mutex_unlock( &S.stream_lock );
277 #undef S
278 }
279