1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 1999-2008 VLC authors and VideoLAN
7 * Author: Laurent Aimar <fenrir _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 *****************************************************************************/
32 #include <vlc_common.h>
34 #include <vlc_modules.h>
35 #include <vlc_interrupt.h>
39 #include "input_internal.h"
41 /* Decode URL (which has had its scheme stripped earlier) to a file path. */
42 char *get_path(const char *location
)
46 /* Prepending "file://" is a bit hackish. But then again, we do not want
47 * to hard-code the list of schemes that use file paths in vlc_uri2path().
49 if (asprintf(&url
, "file://%s", location
) == -1)
52 path
= vlc_uri2path (url
);
57 static void vlc_access_Destroy(stream_t
*access
)
59 module_unneed(access
, access
->p_module
);
60 free(access
->psz_filepath
);
61 free(access
->psz_name
);
66 /*****************************************************************************
68 *****************************************************************************/
69 static stream_t
*access_New(vlc_object_t
*parent
, input_thread_t
*input
,
70 bool preparsing
, const char *mrl
)
72 char *redirv
[MAX_REDIR
];
75 stream_t
*access
= vlc_stream_CommonNew(parent
, vlc_access_Destroy
);
76 if (unlikely(access
== NULL
))
79 access
->p_input
= input
;
80 access
->psz_name
= NULL
;
81 access
->psz_url
= strdup(mrl
);
82 access
->psz_filepath
= NULL
;
83 access
->b_preparsing
= preparsing
;
85 if (unlikely(access
->psz_url
== NULL
))
88 while (redirc
< MAX_REDIR
)
90 char *url
= access
->psz_url
;
91 msg_Dbg(access
, "creating access: %s", url
);
93 const char *p
= strstr(url
, "://");
97 access
->psz_name
= strndup(url
, p
- url
);
98 if (unlikely(access
->psz_name
== NULL
))
101 access
->psz_location
= p
+ 3;
102 access
->psz_filepath
= get_path(access
->psz_location
);
103 if (access
->psz_filepath
!= NULL
)
104 msg_Dbg(access
, " (path: %s)", access
->psz_filepath
);
106 access
->p_module
= module_need(access
, "access", access
->psz_name
,
108 if (access
->p_module
!= NULL
) /* success */
111 free(redirv
[--redirc
]);
113 assert(access
->pf_control
!= NULL
);
117 if (access
->psz_url
== url
) /* failure (no redirection) */
121 msg_Dbg(access
, "redirecting to: %s", access
->psz_url
);
122 redirv
[redirc
++] = url
;
124 for (unsigned j
= 0; j
< redirc
; j
++)
125 if (!strcmp(redirv
[j
], access
->psz_url
))
127 msg_Err(access
, "redirection loop");
131 free(access
->psz_filepath
);
132 free(access
->psz_name
);
133 access
->psz_filepath
= access
->psz_name
= NULL
;
136 msg_Err(access
, "too many redirections");
139 free(redirv
[--redirc
]);
140 free(access
->psz_filepath
);
141 free(access
->psz_name
);
142 stream_CommonDelete(access
);
146 stream_t
*vlc_access_NewMRL(vlc_object_t
*parent
, const char *mrl
)
148 return access_New(parent
, NULL
, false, mrl
);
151 /*****************************************************************************
152 * access_vaDirectoryControlHelper:
153 *****************************************************************************/
154 int access_vaDirectoryControlHelper( stream_t
*p_access
, int i_query
, va_list args
)
156 VLC_UNUSED( p_access
);
160 case STREAM_CAN_SEEK
:
161 case STREAM_CAN_FASTSEEK
:
162 case STREAM_CAN_PAUSE
:
163 case STREAM_CAN_CONTROL_PACE
:
164 *va_arg( args
, bool* ) = false;
166 case STREAM_GET_PTS_DELAY
:
167 *va_arg( args
, int64_t * ) = 0;
169 case STREAM_IS_DIRECTORY
:
177 static int AStreamNoReadDir(stream_t
*s
, input_item_node_t
*p_node
)
179 (void) s
; (void) p_node
;
180 return VLC_EGENERIC
;;
184 static block_t
*AStreamReadBlock(stream_t
*s
, bool *restrict eof
)
186 stream_t
*access
= s
->p_sys
;
187 input_thread_t
*input
= s
->p_input
;
190 if (vlc_stream_Eof(access
))
198 block
= vlc_stream_ReadBlock(access
);
200 if (block
!= NULL
&& input
!= NULL
)
202 struct input_stats
*stats
= input_priv(input
)->stats
;
206 vlc_mutex_lock(&stats
->lock
);
207 input_rate_Add(&stats
->input_bitrate
, block
->i_buffer
);
208 vlc_mutex_unlock(&stats
->lock
);
216 static ssize_t
AStreamReadStream(stream_t
*s
, void *buf
, size_t len
)
218 stream_t
*access
= s
->p_sys
;
219 input_thread_t
*input
= s
->p_input
;
221 if (vlc_stream_Eof(access
))
226 ssize_t val
= vlc_stream_ReadPartial(access
, buf
, len
);
228 if (val
> 0 && input
!= NULL
)
230 struct input_stats
*stats
= input_priv(input
)->stats
;
234 vlc_mutex_lock(&stats
->lock
);
235 input_rate_Add(&stats
->input_bitrate
, val
);
236 vlc_mutex_unlock(&stats
->lock
);
244 static int AStreamReadDir(stream_t
*s
, input_item_node_t
*p_node
)
246 stream_t
*access
= s
->p_sys
;
248 return access
->pf_readdir(access
, p_node
);
252 static int AStreamSeek(stream_t
*s
, uint64_t offset
)
254 stream_t
*access
= s
->p_sys
;
256 return vlc_stream_Seek(access
, offset
);
259 static int AStreamControl(stream_t
*s
, int cmd
, va_list args
)
261 stream_t
*access
= s
->p_sys
;
263 return vlc_stream_vaControl(access
, cmd
, args
);
266 static void AStreamDestroy(stream_t
*s
)
268 stream_t
*access
= s
->p_sys
;
270 vlc_stream_Delete(access
);
273 stream_t
*stream_AccessNew(vlc_object_t
*parent
, input_thread_t
*input
,
274 bool preparsing
, const char *url
)
276 stream_t
*s
= vlc_stream_CommonNew(parent
, AStreamDestroy
);
277 if (unlikely(s
== NULL
))
280 stream_t
*access
= access_New(VLC_OBJECT(s
), input
, preparsing
, url
);
283 stream_CommonDelete(s
);
288 s
->psz_url
= strdup(access
->psz_url
);
290 const char *cachename
;
292 if (access
->pf_block
!= NULL
)
294 s
->pf_block
= AStreamReadBlock
;
295 cachename
= "prefetch,cache_block";
298 if (access
->pf_read
!= NULL
)
300 s
->pf_read
= AStreamReadStream
;
301 cachename
= "prefetch,cache_read";
308 if (access
->pf_readdir
!= NULL
)
309 s
->pf_readdir
= AStreamReadDir
;
311 s
->pf_readdir
= AStreamNoReadDir
;
313 s
->pf_seek
= AStreamSeek
;
314 s
->pf_control
= AStreamControl
;
317 if (cachename
!= NULL
)
318 s
= stream_FilterChainNew(s
, cachename
);
319 return stream_FilterAutoNew(s
);