access: bluray: change overlay state on release
[vlc.git] / src / input / access.c
blobf6ddbea338d5cab0b6962fde49df458f47324be7
1 /*****************************************************************************
2 * access.c
3 *****************************************************************************
4 * Copyright (C) 1999-2008 VLC authors and VideoLAN
5 * $Id$
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 *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include <vlc_common.h>
33 #include <vlc_url.h>
34 #include <vlc_modules.h>
35 #include <vlc_interrupt.h>
37 #include <libvlc.h>
38 #include "stream.h"
39 #include "input_internal.h"
41 struct vlc_access_private
43 module_t *module;
46 struct vlc_access_stream_private
48 input_thread_t *input;
51 /* Decode URL (which has had its scheme stripped earlier) to a file path. */
52 char *get_path(const char *location)
54 char *url, *path;
56 /* Prepending "file://" is a bit hackish. But then again, we do not want
57 * to hard-code the list of schemes that use file paths in vlc_uri2path().
59 if (asprintf(&url, "file://%s", location) == -1)
60 return NULL;
62 path = vlc_uri2path (url);
63 free (url);
64 return path;
67 static void vlc_access_Destroy(stream_t *access)
69 struct vlc_access_private *priv = vlc_stream_Private(access);
71 module_unneed(access, priv->module);
72 free(access->psz_filepath);
73 free(access->psz_name);
76 #define MAX_REDIR 5
78 static stream_t *accessNewAttachment(vlc_object_t *parent,
79 input_thread_t *input, const char *mrl)
81 if (!input)
82 return NULL;
84 input_attachment_t *attachment = input_GetAttachment(input, mrl + 13);
85 if (!attachment)
86 return NULL;
87 stream_t *stream = vlc_stream_AttachmentNew(parent, attachment);
88 if (!stream)
90 vlc_input_attachment_Delete(attachment);
91 return NULL;
93 stream->psz_url = strdup(mrl);
94 if (!stream->psz_url)
96 vlc_stream_Delete(stream);
97 return NULL;
99 stream->psz_location = stream->psz_url + 13;
100 return stream;
103 /*****************************************************************************
104 * access_New:
105 *****************************************************************************/
106 static stream_t *access_New(vlc_object_t *parent, input_thread_t *input,
107 es_out_t *out, bool preparsing, const char *mrl)
109 struct vlc_access_private *priv;
110 char *redirv[MAX_REDIR];
111 unsigned redirc = 0;
113 if (strncmp(mrl, "attachment://", 13) == 0)
114 return accessNewAttachment(parent, input, mrl);
116 stream_t *access = vlc_stream_CustomNew(parent, vlc_access_Destroy,
117 sizeof (*priv), "access");
118 if (unlikely(access == NULL))
119 return NULL;
121 access->p_input_item = input ? input_GetItem(input) : NULL;
122 access->out = out;
123 access->psz_name = NULL;
124 access->psz_url = strdup(mrl);
125 access->psz_filepath = NULL;
126 access->b_preparsing = preparsing;
127 priv = vlc_stream_Private(access);
129 if (unlikely(access->psz_url == NULL))
130 goto error;
132 while (redirc < MAX_REDIR)
134 char *url = access->psz_url;
135 msg_Dbg(access, "creating access: %s", url);
137 const char *p = strstr(url, "://");
138 if (p == NULL)
139 goto error;
141 access->psz_name = strndup(url, p - url);
142 if (unlikely(access->psz_name == NULL))
143 goto error;
145 access->psz_location = p + 3;
146 access->psz_filepath = get_path(access->psz_location);
147 if (access->psz_filepath != NULL)
148 msg_Dbg(access, " (path: %s)", access->psz_filepath);
150 priv->module = module_need(access, "access", access->psz_name, true);
151 if (priv->module != NULL) /* success */
153 while (redirc > 0)
154 free(redirv[--redirc]);
156 assert(access->pf_control != NULL);
157 return access;
160 if (access->psz_url == url) /* failure (no redirection) */
161 goto error;
163 /* redirection */
164 msg_Dbg(access, "redirecting to: %s", access->psz_url);
165 redirv[redirc++] = url;
167 for (unsigned j = 0; j < redirc; j++)
168 if (!strcmp(redirv[j], access->psz_url))
170 msg_Err(access, "redirection loop");
171 goto error;
174 free(access->psz_filepath);
175 free(access->psz_name);
176 access->psz_filepath = access->psz_name = NULL;
179 msg_Err(access, "too many redirections");
180 error:
181 while (redirc > 0)
182 free(redirv[--redirc]);
183 free(access->psz_filepath);
184 free(access->psz_name);
185 stream_CommonDelete(access);
186 return NULL;
189 stream_t *vlc_access_NewMRL(vlc_object_t *parent, const char *mrl)
191 return access_New(parent, NULL, NULL, false, mrl);
194 /*****************************************************************************
195 * access_vaDirectoryControlHelper:
196 *****************************************************************************/
197 int access_vaDirectoryControlHelper( stream_t *p_access, int i_query, va_list args )
199 VLC_UNUSED( p_access );
201 switch( i_query )
203 case STREAM_CAN_SEEK:
204 case STREAM_CAN_FASTSEEK:
205 case STREAM_CAN_PAUSE:
206 case STREAM_CAN_CONTROL_PACE:
207 *va_arg( args, bool* ) = false;
208 break;
209 case STREAM_GET_PTS_DELAY:
210 *va_arg( args, vlc_tick_t * ) = 0;
211 break;
212 default:
213 return VLC_EGENERIC;
215 return VLC_SUCCESS;
218 /* Block access */
219 static block_t *AStreamReadBlock(stream_t *s, bool *restrict eof)
221 stream_t *access = s->p_sys;
222 block_t * block;
224 if (vlc_stream_Eof(access))
226 *eof = true;
227 return NULL;
229 if (vlc_killed())
230 return NULL;
232 block = vlc_stream_ReadBlock(access);
234 if (block != NULL)
236 struct vlc_access_stream_private *priv = vlc_stream_Private(s);
237 struct input_stats *stats =
238 priv->input ? input_priv(priv->input)->stats : NULL;
239 if (stats != NULL)
240 input_rate_Add(&stats->input_bitrate, block->i_buffer);
243 return block;
246 /* Read access */
247 static ssize_t AStreamReadStream(stream_t *s, void *buf, size_t len)
249 stream_t *access = s->p_sys;
251 if (vlc_stream_Eof(access))
252 return 0;
253 if (vlc_killed())
254 return -1;
256 ssize_t val = vlc_stream_ReadPartial(access, buf, len);
258 if (val > 0)
260 struct vlc_access_stream_private *priv = vlc_stream_Private(s);
261 struct input_stats *stats =
262 priv->input ? input_priv(priv->input)->stats : NULL;
263 if (stats != NULL)
264 input_rate_Add(&stats->input_bitrate, val);
267 return val;
270 /* Common */
271 static int AStreamSeek(stream_t *s, uint64_t offset)
273 stream_t *access = s->p_sys;
275 return vlc_stream_Seek(access, offset);
278 static int AStreamControl(stream_t *s, int cmd, va_list args)
280 stream_t *access = s->p_sys;
282 return vlc_stream_vaControl(access, cmd, args);
285 static void AStreamDestroy(stream_t *s)
287 stream_t *access = s->p_sys;
289 vlc_stream_Delete(access);
292 stream_t *stream_AccessNew(vlc_object_t *parent, input_thread_t *input,
293 es_out_t *out, bool preparsing, const char *url)
295 stream_t *access = access_New(parent, input, out, preparsing, url);
296 if (access == NULL)
297 return NULL;
299 stream_t *s;
301 if (access->pf_block != NULL || access->pf_read != NULL)
303 struct vlc_access_stream_private *priv;
304 s = vlc_stream_CustomNew(VLC_OBJECT(access), AStreamDestroy,
305 sizeof(*priv), "stream");
307 if (unlikely(s == NULL))
309 vlc_stream_Delete(access);
310 return NULL;
312 priv = vlc_stream_Private(s);
313 priv->input = input;
315 s->p_input_item = input ? input_GetItem(input) : NULL;
316 s->psz_url = strdup(access->psz_url);
318 if (access->pf_block != NULL)
319 s->pf_block = AStreamReadBlock;
320 if (access->pf_read != NULL)
321 s->pf_read = AStreamReadStream;
323 s->pf_seek = AStreamSeek;
324 s->pf_control = AStreamControl;
325 s->p_sys = access;
327 s = stream_FilterChainNew(s, "prefetch,cache");
329 else
330 s = access;
332 return s;