2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include <sys/types.h>
29 #include <gsthttpsrc.h>
32 GstElementDetails gst_httpsrc_details = {
35 "Read data from an HTTP stream",
37 "Erik Walthinsen <omega@cse.ogi.edu>",
41 /* HttpSrc signals and args */
54 static void gst_httpsrc_class_init (GstHttpSrcClass *klass);
55 static void gst_httpsrc_init (GstHttpSrc *httpsrc);
57 static void gst_httpsrc_set_arg (GtkObject *object, GtkArg *arg, guint id);
58 static void gst_httpsrc_get_arg (GtkObject *object, GtkArg *arg, guint id);
59 static GstElementStateReturn gst_httpsrc_change_state (GstElement *element);
61 static GstBuffer * gst_httpsrc_get (GstPad *pad);
63 static gboolean gst_httpsrc_open_url (GstHttpSrc *src);
64 static void gst_httpsrc_close_url (GstHttpSrc *src);
67 static GstElementClass *parent_class = NULL;
68 //static guint gst_httpsrc_signals[LAST_SIGNAL] = { 0 };
71 gst_httpsrc_get_type (void)
73 static GtkType httpsrc_type = 0;
76 static const GtkTypeInfo httpsrc_info = {
79 sizeof(GstHttpSrcClass),
80 (GtkClassInitFunc)gst_httpsrc_class_init,
81 (GtkObjectInitFunc)gst_httpsrc_init,
82 (GtkArgSetFunc)gst_httpsrc_set_arg,
83 (GtkArgGetFunc)gst_httpsrc_get_arg,
84 (GtkClassInitFunc)NULL,
86 httpsrc_type = gtk_type_unique (GST_TYPE_ELEMENT, &httpsrc_info);
92 gst_httpsrc_class_init (GstHttpSrcClass *klass)
94 GtkObjectClass *gtkobject_class;
95 GstElementClass *gstelement_class;
97 gtkobject_class = (GtkObjectClass*)klass;
98 gstelement_class = (GstElementClass*)klass;
100 parent_class = gtk_type_class (GST_TYPE_ELEMENT);
103 gtk_object_add_arg_type ("GstHttpSrc::location", GTK_TYPE_STRING,
104 GTK_ARG_READWRITE, ARG_LOCATION);
105 gtk_object_add_arg_type ("GstHttpSrc::bytesperread", GTK_TYPE_INT,
106 GTK_ARG_READWRITE, ARG_BYTESPERREAD);
108 gtkobject_class->set_arg = gst_httpsrc_set_arg;
109 gtkobject_class->get_arg = gst_httpsrc_get_arg;
111 gstelement_class->change_state = gst_httpsrc_change_state;
114 static void gst_httpsrc_init(GstHttpSrc *httpsrc) {
115 httpsrc->srcpad = gst_pad_new("src",GST_PAD_SRC);
116 gst_pad_set_get_function(httpsrc->srcpad,gst_httpsrc_get);
117 gst_element_add_pad(GST_ELEMENT(httpsrc),httpsrc->srcpad);
120 httpsrc->request = NULL;
122 httpsrc->curoffset = 0;
123 httpsrc->bytes_per_read = 4096;
127 gst_httpsrc_get(GstPad *pad)
133 g_return_val_if_fail (pad != NULL, NULL);
134 src = GST_HTTPSRC(gst_pad_get_parent(pad));
136 buf = gst_buffer_new();
137 GST_BUFFER_DATA(buf) = (gpointer)malloc(src->bytes_per_read);
138 readbytes = read(src->fd,GST_BUFFER_DATA(buf),src->bytes_per_read);
140 if (readbytes == 0) {
141 gst_element_signal_eos(GST_ELEMENT(src));
145 if (readbytes < src->bytes_per_read) {
146 // FIXME: set the buffer's EOF bit here
148 GST_BUFFER_OFFSET(buf) = src->curoffset;
149 GST_BUFFER_SIZE(buf) = readbytes;
150 src->curoffset += readbytes;
156 gst_httpsrc_open_url (GstHttpSrc *httpsrc)
160 g_return_val_if_fail (!GST_FLAG_IS_SET (httpsrc, GST_HTTPSRC_OPEN), FALSE);
161 g_return_val_if_fail (httpsrc->url != NULL, FALSE);
163 httpsrc->request = ghttp_request_new ();
165 ghttp_set_uri (httpsrc->request, httpsrc->url);
166 ghttp_set_sync (httpsrc->request, ghttp_async);
167 ghttp_set_header (httpsrc->request, "User-Agent", "GstHttpSrc");
168 ghttp_prepare (httpsrc->request);
170 /* process everything up to the actual data stream */
171 /* FIXME: should be in preroll, but hey */
173 while ((ghttp_get_status (httpsrc->request).proc != ghttp_proc_response)
175 status = ghttp_process (httpsrc->request);
178 /* get the fd so we can read data ourselves */
179 httpsrc->fd = ghttp_get_socket (httpsrc->request);
181 GST_FLAG_SET (httpsrc, GST_HTTPSRC_OPEN);
186 /* unmap and close the file */
188 gst_httpsrc_close_url (GstHttpSrc *src)
190 g_return_if_fail (GST_FLAG_IS_SET (src, GST_HTTPSRC_OPEN));
191 g_return_if_fail (src->fd > 0);
196 GST_FLAG_UNSET (src, GST_HTTPSRC_OPEN);
200 gst_httpsrc_set_arg (GtkObject *object, GtkArg *arg, guint id)
204 /* it's not null if we got it, but it might not be ours */
205 g_return_if_fail (GST_IS_HTTPSRC (object));
207 src = GST_HTTPSRC (object);
211 /* the element must not be playing in order to do this */
212 g_return_if_fail (GST_STATE (src) < GST_STATE_PLAYING);
214 if (src->url) g_free (src->url);
215 /* clear the url if we get a NULL (is that possible?) */
216 if (GTK_VALUE_STRING (*arg) == NULL) {
217 gst_element_set_state (GST_ELEMENT (object),GST_STATE_NULL);
219 /* otherwise set the new url */
221 src->url = g_strdup (GTK_VALUE_STRING (*arg));
224 case ARG_BYTESPERREAD:
225 src->bytes_per_read = GTK_VALUE_INT (*arg);
233 gst_httpsrc_get_arg (GtkObject *object, GtkArg *arg, guint id)
237 /* it's not null if we got it, but it might not be ours */
238 g_return_if_fail (GST_IS_HTTPSRC (object));
240 httpsrc = GST_HTTPSRC (object);
244 GTK_VALUE_STRING (*arg) = httpsrc->url;
246 case ARG_BYTESPERREAD:
247 GTK_VALUE_INT (*arg) = httpsrc->bytes_per_read;
250 arg->type = GTK_TYPE_INVALID;
255 static GstElementStateReturn
256 gst_httpsrc_change_state (GstElement *element)
258 g_return_val_if_fail (GST_IS_HTTPSRC (element), GST_STATE_FAILURE);
260 if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
261 if (GST_FLAG_IS_SET (element, GST_HTTPSRC_OPEN))
262 gst_httpsrc_close_url (GST_HTTPSRC (element));
264 if (!GST_FLAG_IS_SET (element, GST_HTTPSRC_OPEN)) {
265 if (!gst_httpsrc_open_url (GST_HTTPSRC (element)))
266 return GST_STATE_FAILURE;
270 if (GST_ELEMENT_CLASS (parent_class)->change_state)
271 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
273 return GST_STATE_SUCCESS;