diff options
Diffstat (limited to 'packages/gstreamer/gst-plugins')
-rw-r--r-- | packages/gstreamer/gst-plugins/.mtn2git_empty | 0 | ||||
-rw-r--r-- | packages/gstreamer/gst-plugins/gst-plugins-0.8.7-httpsrc1.patch | 853 |
2 files changed, 853 insertions, 0 deletions
diff --git a/packages/gstreamer/gst-plugins/.mtn2git_empty b/packages/gstreamer/gst-plugins/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/gstreamer/gst-plugins/.mtn2git_empty diff --git a/packages/gstreamer/gst-plugins/gst-plugins-0.8.7-httpsrc1.patch b/packages/gstreamer/gst-plugins/gst-plugins-0.8.7-httpsrc1.patch index e69de29bb2..59b9ebbf73 100644 --- a/packages/gstreamer/gst-plugins/gst-plugins-0.8.7-httpsrc1.patch +++ b/packages/gstreamer/gst-plugins/gst-plugins-0.8.7-httpsrc1.patch @@ -0,0 +1,853 @@ +diff -urN gst-plugins-0.8.7/gst/tcp/gsthttpclientsrc.c gst-plugins-0.8.7-httpsrc1/gst/tcp/gsthttpclientsrc.c +--- gst-plugins-0.8.7/gst/tcp/gsthttpclientsrc.c 1969-12-31 19:00:00.000000000 -0500 ++++ gst-plugins-0.8.7-httpsrc1/gst/tcp/gsthttpclientsrc.c 2005-03-02 11:08:24.546323513 -0500 +@@ -0,0 +1,655 @@ ++/* GStreamer ++ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> ++ * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this library; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ */ ++ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include <gst/gst-i18n-plugin.h> ++#include "gsttcp.h" ++#include "gsthttpclientsrc.h" ++#include <string.h> /* memset */ ++#include <unistd.h> ++#include <sys/types.h> ++#include <sys/socket.h> ++#include <netinet/in.h> ++#include <arpa/inet.h> ++#include <sys/ioctl.h> ++#include <netdb.h> ++ ++#ifdef HAVE_FIONREAD_IN_SYS_FILIO ++#include <sys/filio.h> ++#endif ++ ++GST_DEBUG_CATEGORY (httpclientsrc_debug); ++#define GST_CAT_DEFAULT httpclientsrc_debug ++ ++#define MAX_READ_SIZE 4 * 1024 ++ ++/* elementfactory information */ ++static GstElementDetails gst_httpclientsrc_details = ++GST_ELEMENT_DETAILS ("HTTP Client source", ++ "Source/Network", ++ "Receive data as a client over the network via HTTP", ++ "Jamey Hicks <jamey dot hicks at hp dot com> based on tcpclientsrc by Thomas Vander Stichele <thomas at apestaart dot org>"); ++ ++/* HttpclientSrc signals and args */ ++enum ++{ ++ LAST_SIGNAL ++}; ++ ++enum ++{ ++ ARG_0, ++ ARG_LOCATION, ++ ARG_METHOD, ++ ARG_PROTOCOL ++}; ++ ++#define HTTP_DEFAULT_METHOD "GET" ++ ++static void gst_httpclientsrc_base_init (gpointer g_class); ++static void gst_httpclientsrc_class_init (GstHttpclientSrc * klass); ++static void gst_httpclientsrc_init (GstHttpclientSrc * httpclientsrc); ++ ++static GstCaps *gst_httpclientsrc_getcaps (GstPad * pad); ++ ++static GstData *gst_httpclientsrc_get (GstPad * pad); ++static GstElementStateReturn gst_httpclientsrc_change_state (GstElement * ++ element); ++ ++static void gst_httpclientsrc_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec); ++static void gst_httpclientsrc_get_property (GObject * object, guint prop_id, ++ GValue * value, GParamSpec * pspec); ++static void gst_httpclientsrc_set_clock (GstElement * element, GstClock * clock); ++ ++static GstElementClass *parent_class = NULL; ++ ++/*static guint gst_httpclientsrc_signals[LAST_SIGNAL] = { 0 }; */ ++ ++GType ++gst_httpclientsrc_get_type (void) ++{ ++ static GType httpclientsrc_type = 0; ++ ++ ++ if (!httpclientsrc_type) { ++ static const GTypeInfo httpclientsrc_info = { ++ sizeof (GstHttpclientSrcClass), ++ gst_httpclientsrc_base_init, ++ NULL, ++ (GClassInitFunc) gst_httpclientsrc_class_init, ++ NULL, ++ NULL, ++ sizeof (GstHttpclientSrc), ++ 0, ++ (GInstanceInitFunc) gst_httpclientsrc_init, ++ NULL ++ }; ++ ++ httpclientsrc_type = ++ g_type_register_static (GST_TYPE_ELEMENT, "GstHttpclientSrc", ++ &httpclientsrc_info, 0); ++ } ++ return httpclientsrc_type; ++} ++ ++static void ++gst_httpclientsrc_base_init (gpointer g_class) ++{ ++ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); ++ ++ gst_element_class_set_details (element_class, &gst_httpclientsrc_details); ++} ++ ++static void ++gst_httpclientsrc_class_init (GstHttpclientSrc * klass) ++{ ++ GObjectClass *gobject_class; ++ GstElementClass *gstelement_class; ++ ++ gobject_class = (GObjectClass *) klass; ++ gstelement_class = (GstElementClass *) klass; ++ ++ parent_class = g_type_class_ref (GST_TYPE_ELEMENT); ++ ++ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOCATION, ++ g_param_spec_string ("location", "Source Location (URL)", ++ "URL of the data to read", NULL, G_PARAM_READWRITE)); ++ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_METHOD, ++ g_param_spec_string ("method", "HTTP METHOD, defaults to GET", ++ "Method of the read request", NULL, G_PARAM_READWRITE)); ++ g_object_class_install_property (gobject_class, ARG_PROTOCOL, ++ g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in", ++ GST_TYPE_TCP_PROTOCOL_TYPE, GST_TCP_PROTOCOL_TYPE_NONE, ++ G_PARAM_READWRITE)); ++ ++ gobject_class->set_property = gst_httpclientsrc_set_property; ++ gobject_class->get_property = gst_httpclientsrc_get_property; ++ ++ gstelement_class->change_state = gst_httpclientsrc_change_state; ++ gstelement_class->set_clock = gst_httpclientsrc_set_clock; ++ ++ GST_DEBUG_CATEGORY_INIT (httpclientsrc_debug, "httpclientsrc", 0, ++ "HTTP Client Source"); ++} ++ ++static void ++gst_httpclientsrc_set_clock (GstElement * element, GstClock * clock) ++{ ++ GstHttpclientSrc *httpclientsrc; ++ ++ httpclientsrc = GST_HTTPCLIENTSRC (element); ++ ++ httpclientsrc->clock = clock; ++} ++ ++static void ++gst_httpclientsrc_init (GstHttpclientSrc * this) ++{ ++ /* create the src pad */ ++ this->srcpad = gst_pad_new ("src", GST_PAD_SRC); ++ gst_element_add_pad (GST_ELEMENT (this), this->srcpad); ++ gst_pad_set_get_function (this->srcpad, gst_httpclientsrc_get); ++ gst_pad_set_getcaps_function (this->srcpad, gst_httpclientsrc_getcaps); ++ ++ this->port = TCP_DEFAULT_PORT; ++ this->method = g_strdup(HTTP_DEFAULT_METHOD); ++ this->location = NULL; ++ this->host = NULL; ++ this->clock = NULL; ++ this->sock_fd = -1; ++ this->protocol = GST_TCP_PROTOCOL_TYPE_NONE; ++ this->curoffset = 0; ++ this->caps = NULL; ++ ++ GST_FLAG_UNSET (this, GST_HTTPCLIENTSRC_OPEN); ++} ++ ++static GstCaps * ++gst_httpclientsrc_getcaps (GstPad * pad) ++{ ++ GstHttpclientSrc *src; ++ GstCaps *caps = NULL; ++ ++ src = GST_HTTPCLIENTSRC (GST_OBJECT_PARENT (pad)); ++ ++ if (!GST_FLAG_IS_SET (src, GST_HTTPCLIENTSRC_OPEN)) ++ caps = gst_caps_new_any (); ++ else if (src->caps) ++ caps = gst_caps_copy (src->caps); ++ else ++ caps = gst_caps_new_any (); ++ GST_DEBUG_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps); ++ g_assert (GST_IS_CAPS (caps)); ++ return caps; ++} ++ ++static GstData * ++gst_httpclientsrc_get (GstPad * pad) ++{ ++ GstHttpclientSrc *src; ++ size_t readsize; ++ int ret; ++ ++ GstData *data = NULL; ++ GstBuffer *buf = NULL; ++ ++ g_return_val_if_fail (pad != NULL, NULL); ++ g_return_val_if_fail (GST_IS_PAD (pad), NULL); ++ src = GST_HTTPCLIENTSRC (GST_OBJECT_PARENT (pad)); ++ g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_HTTPCLIENTSRC_OPEN), NULL); ++ ++ /* try to negotiate here */ ++ if (!gst_pad_is_negotiated (pad)) { ++ if (GST_PAD_LINK_FAILED (gst_pad_renegotiate (pad))) { ++ GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), GST_ERROR_SYSTEM); ++ gst_buffer_unref (buf); ++ return GST_DATA (gst_event_new (GST_EVENT_EOS)); ++ } ++ } ++ ++ /* if we have a left over buffer after a discont, return that */ ++ if (src->buffer_after_discont) { ++ buf = src->buffer_after_discont; ++ GST_LOG_OBJECT (src, ++ "Returning buffer after discont of size %d, ts %" ++ GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ++ ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT, ++ GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), ++ GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), ++ GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf)); ++ src->buffer_after_discont = NULL; ++ return GST_DATA (buf); ++ } ++ ++ /* read the buffer header if we're using a protocol */ ++ switch (src->protocol) { ++ fd_set testfds; ++ ++ case GST_TCP_PROTOCOL_TYPE_NONE: ++ /* do a blocking select on the socket */ ++ FD_ZERO (&testfds); ++ FD_SET (src->sock_fd, &testfds); ++ ret = select (src->sock_fd + 1, &testfds, (fd_set *) 0, (fd_set *) 0, 0); ++ /* no action (0) is an error too in our case */ ++ if (ret <= 0) { ++ GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ++ ("select failed: %s", g_strerror (errno))); ++ return GST_DATA (gst_event_new (GST_EVENT_EOS)); ++ } ++ ++ /* ask how much is available for reading on the socket */ ++ ret = ioctl (src->sock_fd, FIONREAD, &readsize); ++ if (ret < 0) { ++ GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ++ ("ioctl failed: %s", g_strerror (errno))); ++ return GST_DATA (gst_event_new (GST_EVENT_EOS)); ++ } ++ GST_LOG_OBJECT (src, "ioctl says %d bytes available", readsize); ++ buf = gst_buffer_new_and_alloc (readsize); ++ break; ++ case GST_TCP_PROTOCOL_TYPE_GDP: ++ if (!(data = gst_tcp_gdp_read_header (GST_ELEMENT (src), src->sock_fd))) { ++ GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ++ ("Could not read data header through GDP")); ++ return GST_DATA (gst_event_new (GST_EVENT_EOS)); ++ } ++ if (GST_IS_EVENT (data)) ++ return data; ++ buf = GST_BUFFER (data); ++ ++ GST_LOG_OBJECT (src, "Going to read data from socket into buffer %p", ++ buf); ++ /* use this new buffer to read data into */ ++ readsize = GST_BUFFER_SIZE (buf); ++ break; ++ default: ++ g_warning ("Unhandled protocol type"); ++ break; ++ } ++ ++ GST_LOG_OBJECT (src, "Reading %d bytes", readsize); ++ ret = gst_tcp_socket_read (src->sock_fd, GST_BUFFER_DATA (buf), readsize); ++ if (ret < 0) { ++ GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); ++ gst_buffer_unref (buf); ++ return GST_DATA (gst_event_new (GST_EVENT_EOS)); ++ } ++ ++ /* if we read 0 bytes, and we're blocking, we hit eos */ ++ if (ret == 0) { ++ GST_DEBUG ("blocking read returns 0, EOS"); ++ gst_buffer_unref (buf); ++ gst_element_set_eos (GST_ELEMENT (src)); ++ return GST_DATA (gst_event_new (GST_EVENT_EOS)); ++ } ++ ++ readsize = ret; ++ GST_BUFFER_SIZE (buf) = readsize; ++ GST_BUFFER_MAXSIZE (buf) = readsize; ++ ++ /* FIXME: we could decide to set OFFSET and OFFSET_END for non-protocol ++ * streams to mean the bytes processed */ ++ ++ /* if this is our first buffer, we need to send a discont with the ++ * given timestamp or the current offset, and store the buffer for ++ * the next iteration through the get loop */ ++ if (src->send_discont) { ++ GstClockTime timestamp; ++ GstEvent *event; ++ ++ src->send_discont = FALSE; ++ src->buffer_after_discont = buf; ++ /* if the timestamp is valid, send a timed discont ++ * taking into account the incoming buffer's timestamps */ ++ timestamp = GST_BUFFER_TIMESTAMP (buf); ++ if (GST_CLOCK_TIME_IS_VALID (timestamp)) { ++ GST_DEBUG_OBJECT (src, ++ "sending discontinuous with timestamp %" GST_TIME_FORMAT, ++ GST_TIME_ARGS (timestamp)); ++ event = ++ gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, timestamp, NULL); ++ return GST_DATA (event); ++ } ++ /* otherwise, send an offset discont */ ++ GST_DEBUG_OBJECT (src, "sending discontinuous with offset %d", ++ src->curoffset); ++ event = ++ gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, src->curoffset, ++ NULL); ++ return GST_DATA (event); ++ } ++ ++ src->curoffset += readsize; ++ GST_LOG_OBJECT (src, ++ "Returning buffer from _get of size %d, ts %" ++ GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT ++ ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT, ++ GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), ++ GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), ++ GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf)); ++ return GST_DATA (buf); ++} ++ ++static void ++gst_httpclientsrc_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec) ++{ ++ GstHttpclientSrc *httpclientsrc; ++ ++ ++ /* it's not null if we got it, but it might not be ours */ ++ g_return_if_fail (GST_IS_HTTPCLIENTSRC (object)); ++ httpclientsrc = GST_HTTPCLIENTSRC (object); ++ ++ GST_DEBUG_OBJECT (httpclientsrc, "setting property %d", prop_id); ++ ++ switch (prop_id) { ++ case ARG_LOCATION: { ++ gchar *pathstart = NULL; ++ gchar *location = NULL; ++ gchar *hostport = NULL; ++ gchar *portstart = NULL; ++ int locationlen; ++ g_free (httpclientsrc->location); ++ g_free (httpclientsrc->host); ++ g_free (httpclientsrc->path); ++ httpclientsrc->location = location = g_strdup (g_value_get_string (value)); ++ GST_DEBUG_OBJECT (httpclientsrc, "setting location=%s", location); ++ ++ if (strncmp(location, "http://", 7) != 0) ++ return; ++ locationlen = strlen(location); ++ hostport = location + 7; ++ GST_DEBUG_OBJECT (httpclientsrc, " hostport=%s", hostport); ++ ++ pathstart = strchr(hostport, '/'); ++ GST_DEBUG_OBJECT (httpclientsrc, " pathstart=%s", pathstart); ++ ++ if (pathstart) { ++ httpclientsrc->path = g_strdup(pathstart); ++ } else { ++ httpclientsrc->path = g_strdup("/"); ++ pathstart = location+locationlen; ++ } ++ hostport = g_strndup(hostport, pathstart - hostport); ++ portstart = strrchr(hostport, ':'); ++ GST_DEBUG_OBJECT (httpclientsrc, " hostport=%s portstart=%s", hostport, portstart); ++ if (portstart != NULL) { ++ httpclientsrc->host = g_strndup(hostport, portstart - hostport); ++ httpclientsrc->port = strtoul(portstart+1, NULL, 0); ++ g_free(hostport); ++ } else { ++ httpclientsrc->host = hostport; ++ httpclientsrc->port = 80; ++ } ++ GST_DEBUG_OBJECT (httpclientsrc, " host=%s port=%d path=%s", httpclientsrc->host, httpclientsrc->port, httpclientsrc->path); ++ } break; ++ case ARG_METHOD: ++ g_free (httpclientsrc->method); ++ httpclientsrc->method = g_strdup (g_value_get_string (value)); ++ break; ++ case ARG_PROTOCOL: ++ httpclientsrc->protocol = g_value_get_enum (value); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++gst_httpclientsrc_get_property (GObject * object, guint prop_id, GValue * value, ++ GParamSpec * pspec) ++{ ++ GstHttpclientSrc *httpclientsrc; ++ ++ g_return_if_fail (GST_IS_HTTPCLIENTSRC (object)); ++ httpclientsrc = GST_HTTPCLIENTSRC (object); ++ ++ switch (prop_id) { ++ case ARG_LOCATION: ++ g_value_set_string (value, httpclientsrc->location); ++ break; ++ case ARG_METHOD: ++ g_value_set_string (value, httpclientsrc->method); ++ break; ++ case ARG_PROTOCOL: ++ g_value_set_enum (value, httpclientsrc->protocol); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++/* create a socket for connecting to remote server */ ++static gboolean ++gst_httpclientsrc_init_receive (GstHttpclientSrc * this) ++{ ++ int ret; ++ gchar ip[256]; ++ struct addrinfo *addrinfo, *top_addrinfo; ++ int addr_family; ++ gchar *request = NULL; ++ ++ GST_DEBUG_OBJECT (this, "getaddrinfo %s", this->host); ++ ret = getaddrinfo(this->host, "http", NULL, &addrinfo); ++ top_addrinfo = addrinfo; ++ ++ retry: ++ this->addr_family = addr_family = addrinfo->ai_family; ++ this->server_addrlen = addrinfo->ai_addrlen; ++ memset(&this->server_sockaddr, 0, sizeof(this->server_sockaddr)); ++ memcpy(&this->server_sockaddr, addrinfo->ai_addr, addrinfo->ai_addrlen); ++ ++ /* create receiving client socket */ ++ GST_DEBUG_OBJECT (this, "opening receiving client socket to %s:%d\n", ++ this->host, this->port); ++ if ((this->sock_fd = socket (this->addr_family, SOCK_STREAM, 0)) == -1) { ++ GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM); ++ return FALSE; ++ } ++ GST_DEBUG_OBJECT (this, "opened receiving client socket with fd %d", ++ this->sock_fd); ++ ++ /* look up name if we need to */ ++ GST_DEBUG_OBJECT (this, "IP address for host %s is %s", this->host, ip); ++ ++ /* fill in port */ ++ switch (this->addr_family) { ++ case AF_INET: ++ ((struct sockaddr_in *)&this->server_sockaddr)->sin_port = htons(this->port); ++ inet_ntop(this->addr_family, &(((struct sockaddr_in *)&this->server_sockaddr)->sin_addr), ip, sizeof(ip)); ++ break; ++ case AF_INET6: ++ ((struct sockaddr_in6 *)&this->server_sockaddr)->sin6_port = htons(this->port); ++ inet_ntop(this->addr_family, &(((struct sockaddr_in6 *)&this->server_sockaddr)->sin6_addr), ip, sizeof(ip)); ++ break; ++ } ++ if (this->addr_family == AF_INET6) { ++ int offset = 0; ++ int i; ++ struct in6_addr *in6_addr = &(((struct sockaddr_in6 *)&this->server_sockaddr)->sin6_addr); ++ for (i = 0; i < sizeof(struct in6_addr); i++) { ++ int b = in6_addr->s6_addr[i]; ++ offset += sprintf(ip+offset, ":%02x", b); ++ } ++ } ++ ++ /* connect to server */ ++ GST_DEBUG_OBJECT (this, "connecting to server family=%d ip=%s port=%d sockaddrlen=%d", ++ this->addr_family, ip, this->port, this->server_addrlen); ++ ret = connect (this->sock_fd, (struct sockaddr *) &this->server_sockaddr, this->server_addrlen); ++ ++ if (ret) { ++ switch (errno) { ++ case ECONNREFUSED: ++ GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, ++ (_("Connection to %s:%d refused."), this->host, this->port), ++ (NULL)); ++ if (addrinfo->ai_next == NULL) ++ return FALSE; ++ break; ++ default: ++ GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), ++ ("connect to %s:%d failed: %s", this->host, this->port, ++ g_strerror (errno))); ++ if (addrinfo->ai_next == NULL) ++ return FALSE; ++ break; ++ } ++ addrinfo = addrinfo->ai_next; ++ if (addrinfo) { ++ GST_DEBUG_OBJECT(this, "retrying with addrinfo %p", addrinfo); ++ goto retry; ++ } ++ } ++ ++ /* send request and headers */ ++ request = g_strdup_printf("%s %s HTTP/1.0\r\nHost: %s\r\n\r\n", ++ this->method, this->path, this->host); ++ GST_DEBUG_OBJECT(this, "sending request %s", request); ++ if (gst_tcp_socket_write(this->sock_fd, request, strlen(request)) < 0) { ++ GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), ++ ("sending HTTP request to %s failed: %s", this->location, ++ g_strerror (errno))); ++ return FALSE; ++ } ++ g_free(request); ++ ++ ++ /* receive and discard headers */ ++ { ++ char responseline[12]; ++ int rc; ++ /* receive response line (HTTP/1.x NNN) */ ++ if ((rc = gst_tcp_socket_read(this->sock_fd, responseline, sizeof(responseline))) < 0) { ++ GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), ++ ("reading HTTP response from %s failed: %s", this->location, ++ g_strerror (errno))); ++ return FALSE; ++ } ++ GST_DEBUG_OBJECT(this, "got %d byte response %s", rc, responseline); ++ ++ enum response_state { ++ RESPONSE_CHAR, ++ RESPONSE_CR, ++ RESPONSE_CRLF, ++ RESPONSE_CRLFCR, ++ RESPONSE_END_OF_HEADERS /* saw crlfcrlf */ ++ } response_state = RESPONSE_CHAR; ++ while (response_state != RESPONSE_END_OF_HEADERS) { ++ gchar ch; ++ if (gst_tcp_socket_read(this->sock_fd, &ch, sizeof(ch)) < 0) { ++ GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), ++ ("reading HTTP response from %s failed: %s", this->location, ++ g_strerror (errno))); ++ return FALSE; ++ } ++ switch (ch) { ++ case '\n': ++ switch (response_state) { ++ case RESPONSE_CR: response_state = RESPONSE_CRLF; break; ++ case RESPONSE_CRLFCR: response_state = RESPONSE_END_OF_HEADERS; break; ++ default: response_state = RESPONSE_CHAR; ++ } break; ++ case '\r': ++ switch (response_state) { ++ case RESPONSE_CRLF: response_state = RESPONSE_CRLFCR; break; ++ default: response_state = RESPONSE_CR; ++ } break; ++ default: ++ response_state = RESPONSE_CHAR; ++ } ++ } ++ } ++ ++ this->send_discont = TRUE; ++ this->buffer_after_discont = NULL; ++ GST_FLAG_SET (this, GST_HTTPCLIENTSRC_OPEN); ++ ++ /* get the caps if we're using GDP */ ++ if (this->protocol == GST_TCP_PROTOCOL_TYPE_GDP) { ++ /* if we haven't received caps yet, we should get them first */ ++ if (!this->caps_received) { ++ GstCaps *caps; ++ ++ GST_DEBUG_OBJECT (this, "getting caps through GDP"); ++ if (!(caps = gst_tcp_gdp_read_caps (GST_ELEMENT (this), this->sock_fd))) { ++ GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), ++ ("Could not read caps through GDP")); ++ return FALSE; ++ } ++ if (!GST_IS_CAPS (caps)) { ++ GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), ++ ("Could not read caps through GDP")); ++ return FALSE; ++ } ++ GST_DEBUG_OBJECT (this, "Received caps through GDP: %" GST_PTR_FORMAT, ++ caps); ++ this->caps_received = TRUE; ++ this->caps = caps; ++ } ++ } ++ return TRUE; ++} ++ ++static void ++gst_httpclientsrc_close (GstHttpclientSrc * this) ++{ ++ if (this->sock_fd != -1) { ++ close (this->sock_fd); ++ this->sock_fd = -1; ++ } ++ this->caps_received = FALSE; ++ if (this->caps) { ++ gst_caps_free (this->caps); ++ this->caps = NULL; ++ } ++ GST_FLAG_UNSET (this, GST_HTTPCLIENTSRC_OPEN); ++} ++ ++static GstElementStateReturn ++gst_httpclientsrc_change_state (GstElement * element) ++{ ++ g_return_val_if_fail (GST_IS_HTTPCLIENTSRC (element), GST_STATE_FAILURE); ++ ++ if (GST_STATE_PENDING (element) == GST_STATE_NULL) { ++ if (GST_FLAG_IS_SET (element, GST_HTTPCLIENTSRC_OPEN)) ++ gst_httpclientsrc_close (GST_HTTPCLIENTSRC (element)); ++ } else { ++ if (!GST_FLAG_IS_SET (element, GST_HTTPCLIENTSRC_OPEN)) { ++ if (!gst_httpclientsrc_init_receive (GST_HTTPCLIENTSRC (element))) ++ return GST_STATE_FAILURE; ++ } ++ } ++ ++ if (GST_ELEMENT_CLASS (parent_class)->change_state) ++ return GST_ELEMENT_CLASS (parent_class)->change_state (element); ++ ++ return GST_STATE_SUCCESS; ++} +diff -urN gst-plugins-0.8.7/gst/tcp/gsthttpclientsrc.h gst-plugins-0.8.7-httpsrc1/gst/tcp/gsthttpclientsrc.h +--- gst-plugins-0.8.7/gst/tcp/gsthttpclientsrc.h 1969-12-31 19:00:00.000000000 -0500 ++++ gst-plugins-0.8.7-httpsrc1/gst/tcp/gsthttpclientsrc.h 2005-03-02 09:47:01.640623151 -0500 +@@ -0,0 +1,98 @@ ++/* GStreamer ++ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> ++ * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this library; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ */ ++ ++ ++#ifndef __GST_HTTPCLIENTSRC_H__ ++#define __GST_HTTPCLIENTSRC_H__ ++ ++#include <gst/gst.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++#include <netdb.h> /* sockaddr_in */ ++#include <netinet/in.h> /* sockaddr_in */ ++#include <unistd.h> ++#include "gsttcp.h" ++ ++#define GST_TYPE_HTTPCLIENTSRC \ ++ (gst_httpclientsrc_get_type()) ++#define GST_HTTPCLIENTSRC(obj) \ ++ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_HTTPCLIENTSRC,GstHttpclientSrc)) ++#define GST_HTTPCLIENTSRC_CLASS(klass) \ ++ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_HTTPCLIENTSRC,GstHttpclientSrc)) ++#define GST_IS_HTTPCLIENTSRC(obj) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_HTTPCLIENTSRC)) ++#define GST_IS_HTTPCLIENTSRC_CLASS(obj) \ ++ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_HTTPCLIENTSRC)) ++ ++typedef struct _GstHttpclientSrc GstHttpclientSrc; ++typedef struct _GstHttpclientSrcClass GstHttpclientSrcClass; ++ ++typedef enum GstHttpclientSrcFlags { ++ GST_HTTPCLIENTSRC_OPEN = GST_ELEMENT_FLAG_LAST, ++ ++ GST_HTTPCLIENTSRC_FLAG_LAST, ++} GstHttpclientSrcFlags; ++ ++struct _GstHttpclientSrc { ++ GstElement element; ++ ++ /* pad */ ++ GstPad *srcpad; ++ ++ /* server information */ ++ int port; ++ int addr_family; ++ gchar *method; ++ gchar *host; ++ gchar *path; ++ gchar *location; /* url */ ++ struct sockaddr_storage server_sockaddr; ++ int server_addrlen; ++ ++ /* socket */ ++ int sock_fd; ++ ++ /* number of bytes we've gotten */ ++ off_t curoffset; ++ ++ GstTCPProtocolType protocol; /* protocol used for reading data */ ++ gboolean caps_received; /* if we have received caps yet */ ++ GstCaps *caps; ++ GstClock *clock; ++ ++ gboolean send_discont; /* TRUE when we need to send a discont */ ++ GstBuffer *buffer_after_discont; /* temporary storage for buffer */ ++}; ++ ++struct _GstHttpclientSrcClass { ++ GstElementClass parent_class; ++}; ++ ++GType gst_httpclientsrc_get_type (void); ++ ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif /* __GST_HTTPCLIENTSRC_H__ */ +diff -urN gst-plugins-0.8.7/gst/tcp/gsttcpplugin.c gst-plugins-0.8.7-httpsrc1/gst/tcp/gsttcpplugin.c +--- gst-plugins-0.8.7/gst/tcp/gsttcpplugin.c 2004-11-05 12:15:10.000000000 -0500 ++++ gst-plugins-0.8.7-httpsrc1/gst/tcp/gsttcpplugin.c 2005-03-02 09:59:33.003801791 -0500 +@@ -23,6 +23,7 @@ + + #include "gsttcpsrc.h" + #include "gsttcpsink.h" ++#include "gsthttpclientsrc.h" + #include "gsttcpclientsrc.h" + #include "gsttcpclientsink.h" + #include "gsttcpserversrc.h" +@@ -59,6 +60,9 @@ + if (!gst_element_register (plugin, "multifdsink", GST_RANK_NONE, + GST_TYPE_MULTIFDSINK)) + return FALSE; ++ if (!gst_element_register (plugin, "httpclientsrc", GST_RANK_NONE, ++ GST_TYPE_HTTPCLIENTSRC)) ++ return FALSE; + + GST_DEBUG_CATEGORY_INIT (tcp_debug, "tcp", 0, "TCP calls"); + +diff -urN gst-plugins-0.8.7/gst/tcp/Makefile.am gst-plugins-0.8.7-httpsrc1/gst/tcp/Makefile.am +--- gst-plugins-0.8.7/gst/tcp/Makefile.am 2004-11-02 02:41:44.000000000 -0500 ++++ gst-plugins-0.8.7-httpsrc1/gst/tcp/Makefile.am 2005-03-02 09:29:30.125528594 -0500 +@@ -18,6 +18,7 @@ + gsttcp.c \ + gstfdset.c \ + gstmultifdsink.c \ ++ gsthttpclientsrc.c \ + gsttcpclientsrc.c gsttcpclientsink.c \ + gsttcpserversrc.c gsttcpserversink.c + +@@ -35,6 +36,7 @@ + gsttcp.h \ + gstfdset.h \ + gstmultifdsink.h \ ++ gsthttpclientsrc.h \ + gsttcpclientsrc.h gsttcpclientsink.h \ + gsttcpserversrc.h gsttcpserversink.h + +diff -urN gst-plugins-0.8.7/gst/tcp/Makefile.in gst-plugins-0.8.7-httpsrc1/gst/tcp/Makefile.in +--- gst-plugins-0.8.7/gst/tcp/Makefile.in 2005-01-05 05:47:55.000000000 -0500 ++++ gst-plugins-0.8.7-httpsrc1/gst/tcp/Makefile.in 2005-03-02 09:33:30.515512648 -0500 +@@ -99,7 +99,8 @@ + am_libgsttcp_la_OBJECTS = libgsttcp_la-gsttcpplugin.lo \ + libgsttcp_la-gsttcpsrc.lo libgsttcp_la-gsttcpsink.lo \ + libgsttcp_la-gsttcp.lo libgsttcp_la-gstfdset.lo \ +- libgsttcp_la-gstmultifdsink.lo libgsttcp_la-gsttcpclientsrc.lo \ ++ libgsttcp_la-gstmultifdsink.lo libgsttcp_la-gsthttpclientsrc.lo \ ++ libgsttcp_la-gsttcpclientsrc.lo \ + libgsttcp_la-gsttcpclientsink.lo \ + libgsttcp_la-gsttcpserversrc.lo \ + libgsttcp_la-gsttcpserversink.lo +@@ -730,6 +731,7 @@ + gsttcp.c \ + gstfdset.c \ + gstmultifdsink.c \ ++ gsthttpclientsrc.c \ + gsttcpclientsrc.c gsttcpclientsink.c \ + gsttcpserversrc.c gsttcpserversink.c + +@@ -747,7 +749,7 @@ + gsttcp.h \ + gstfdset.h \ + gstmultifdsink.h \ +- gsttcpclientsrc.h gsttcpclientsink.h \ ++ gsthttpclientsrc.h gsttcpclientsrc.h gsttcpclientsink.h \ + gsttcpserversrc.h gsttcpserversink.h + + CLEANFILES = $(BUILT_SOURCES) +@@ -844,6 +846,7 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcp.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpclientsink.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpplugin.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpserversink.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgsttcp_la-gsttcpserversrc.Plo@am__quote@ +@@ -913,6 +916,13 @@ + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsttcp_la_CFLAGS) $(CFLAGS) -c -o libgsttcp_la-gstmultifdsink.lo `test -f 'gstmultifdsink.c' || echo '$(srcdir)/'`gstmultifdsink.c + ++libgsttcp_la-gsthttpclientsrc.lo: gsthttpclientsrc.c ++@am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsttcp_la_CFLAGS) $(CFLAGS) -MT libgsttcp_la-gsthttpclientsrc.lo -MD -MP -MF "$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Tpo" -c -o libgsttcp_la-gsthttpclientsrc.lo `test -f 'gsthttpclientsrc.c' || echo '$(srcdir)/'`gsthttpclientsrc.c; \ ++@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Tpo" "$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Plo"; else rm -f "$(DEPDIR)/libgsttcp_la-gsthttpclientsrc.Tpo"; exit 1; fi ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gsthttpclientsrc.c' object='libgsttcp_la-gsthttpclientsrc.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsttcp_la_CFLAGS) $(CFLAGS) -c -o libgsttcp_la-gsthttpclientsrc.lo `test -f 'gsthttpclientsrc.c' || echo '$(srcdir)/'`gsthttpclientsrc.c ++ + libgsttcp_la-gsttcpclientsrc.lo: gsttcpclientsrc.c + @am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgsttcp_la_CFLAGS) $(CFLAGS) -MT libgsttcp_la-gsttcpclientsrc.lo -MD -MP -MF "$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Tpo" -c -o libgsttcp_la-gsttcpclientsrc.lo `test -f 'gsttcpclientsrc.c' || echo '$(srcdir)/'`gsttcpclientsrc.c; \ + @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Tpo" "$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Plo"; else rm -f "$(DEPDIR)/libgsttcp_la-gsttcpclientsrc.Tpo"; exit 1; fi |