[rhythmbox] daap: use souphttpsrc instead of our own HTTP client code
- From: Jonathan Matthew <jmatthew src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [rhythmbox] daap: use souphttpsrc instead of our own HTTP client code
- Date: Wed, 30 Dec 2009 03:06:49 +0000 (UTC)
commit 4072afad6f912d9e90616c3a63b28a1ec13592ec
Author: Jay L. T. Cornwall <jay jcornwall me uk>
Date: Wed Dec 30 13:03:34 2009 +1000
daap: use souphttpsrc instead of our own HTTP client code
This converts our DAAP source element into a bin containing a
souphttpsrc element, using the extra-headers property to set the DAAP
headers (which don't really do anything any more anyway).
rb_daap_connection_get_headers now returns a GstStructure, since that's
what souphttpsrc takes.
plugins/daap/rb-daap-connection.c | 51 ++--
plugins/daap/rb-daap-connection.h | 6 +-
plugins/daap/rb-daap-source.c | 7 +-
plugins/daap/rb-daap-source.h | 7 +-
plugins/daap/rb-daap-src.c | 626 +++++--------------------------------
5 files changed, 117 insertions(+), 580 deletions(-)
---
diff --git a/plugins/daap/rb-daap-connection.c b/plugins/daap/rb-daap-connection.c
index 1237a47..5a2a66b 100644
--- a/plugins/daap/rb-daap-connection.c
+++ b/plugins/daap/rb-daap-connection.c
@@ -1656,16 +1656,15 @@ rb_daap_connection_do_something (RBDAAPConnection *connection)
return FALSE;
}
-char *
+GstStructure *
rb_daap_connection_get_headers (RBDAAPConnection *connection,
- const gchar *uri,
- gint64 bytes)
+ const gchar *uri)
{
RBDAAPConnectionPrivate *priv = connection->priv;
- GString *headers;
+ GstStructure *headers;
char hash[33] = {0};
char *norb_daap_uri = (char *)uri;
- char *s;
+ char *request_id_str;
priv->request_id++;
@@ -1678,37 +1677,39 @@ rb_daap_connection_get_headers (RBDAAPConnection *connection,
(guchar*)hash,
priv->request_id);
- headers = g_string_new ("Accept: */*\r\n"
- "Cache-Control: no-cache\r\n"
- "User-Agent: " RB_DAAP_USER_AGENT "\r\n"
- "Accept-Language: en-us, en;q=5.0\r\n"
- "Client-DAAP-Access-Index: 2\r\n"
- "Client-DAAP-Version: 3.0\r\n");
- g_string_append_printf (headers,
- "Client-DAAP-Validation: %s\r\n"
- "Client-DAAP-Request-ID: %d\r\n"
- "Connection: close\r\n",
- hash, priv->request_id);
+ request_id_str = g_strdup_printf ("%d", priv->request_id);
+ headers = gst_structure_new ("extra-headers",
+ "Accept", G_TYPE_STRING, "*/*",
+ "Cache-Control", G_TYPE_STRING, "no-cache",
+ "User-Agent", G_TYPE_STRING, RB_DAAP_USER_AGENT,
+ "Accept-Language", G_TYPE_STRING, "en-us, en;q=5.0",
+ "Client-DAAP-Access-Index", G_TYPE_STRING, "2",
+ "Client-DAAP-Version", G_TYPE_STRING, "3.0",
+ "Client-DAAP-Validation", G_TYPE_STRING, hash,
+ "Client-DAAP-Request-ID", G_TYPE_STRING, request_id_str,
+ "Connection", G_TYPE_STRING, "close",
+ NULL);
+ g_free (request_id_str);
if (priv->password_protected) {
char *user_pass;
char *token;
+ char *auth_str;
user_pass = g_strdup_printf ("%s:%s", priv->username, priv->password);
token = g_base64_encode ((guchar *)user_pass, strlen (user_pass));
- g_string_append_printf (headers, "Authentication: Basic %s\r\n", token);
+ auth_str = g_strdup_printf ("Basic %s", token);
+
+ gst_structure_set (headers,
+ "Authentication", G_TYPE_STRING, auth_str,
+ NULL);
+
+ g_free (auth_str);
g_free (token);
g_free (user_pass);
}
- if (bytes != 0) {
- g_string_append_printf (headers,"Range: bytes=%"G_GINT64_FORMAT"-\r\n", bytes);
- }
-
- s = headers->str;
- g_string_free (headers, FALSE);
-
- return s;
+ return headers;
}
GSList *
diff --git a/plugins/daap/rb-daap-connection.h b/plugins/daap/rb-daap-connection.h
index 11235ca..07f7c59 100644
--- a/plugins/daap/rb-daap-connection.h
+++ b/plugins/daap/rb-daap-connection.h
@@ -33,6 +33,7 @@
#include <glib.h>
#include <glib-object.h>
+#include <gst/gst.h>
#include "rhythmdb.h"
G_BEGIN_DECLS
@@ -109,9 +110,8 @@ void rb_daap_connection_disconnect (RBDAAPConnection *
RBDAAPConnectionCallback callback,
gpointer user_data);
-char * rb_daap_connection_get_headers (RBDAAPConnection *connection,
- const char *uri,
- gint64 bytes);
+GstStructure * rb_daap_connection_get_headers (RBDAAPConnection *connection,
+ const char *uri);
GSList * rb_daap_connection_get_playlists (RBDAAPConnection *connection);
diff --git a/plugins/daap/rb-daap-source.c b/plugins/daap/rb-daap-source.c
index 309e7aa..5e59e0a 100644
--- a/plugins/daap/rb-daap-source.c
+++ b/plugins/daap/rb-daap-source.c
@@ -726,17 +726,16 @@ rb_daap_source_show_popup (RBSource *source)
return TRUE;
}
-char *
+GstStructure *
rb_daap_source_get_headers (RBDAAPSource *source,
- const char *uri,
- gint64 bytes)
+ const char *uri)
{
/* If there is no connection then bail */
if (source->priv->connection == NULL) {
return NULL;
}
- return rb_daap_connection_get_headers (source->priv->connection, uri, bytes);
+ return rb_daap_connection_get_headers (source->priv->connection, uri);
}
static char *
diff --git a/plugins/daap/rb-daap-source.h b/plugins/daap/rb-daap-source.h
index 914bd82..3e92ab1 100644
--- a/plugins/daap/rb-daap-source.h
+++ b/plugins/daap/rb-daap-source.h
@@ -34,6 +34,8 @@
#include "rb-browser-source.h"
#include "rb-plugin.h"
+#include <gst/gst.h>
+
G_BEGIN_DECLS
#define RB_TYPE_DAAP_SOURCE (rb_daap_source_get_type ())
@@ -67,9 +69,8 @@ RBSource * rb_daap_source_new (RBShell *shell,
void rb_daap_source_disconnect (RBDAAPSource *daap_source);
-gchar * rb_daap_source_get_headers (RBDAAPSource *source,
- const gchar *uri,
- gint64 bytes);
+GstStructure * rb_daap_source_get_headers (RBDAAPSource *source,
+ const gchar *uri);
G_END_DECLS
diff --git a/plugins/daap/rb-daap-src.c b/plugins/daap/rb-daap-src.c
index c581cd1..60f66af 100644
--- a/plugins/daap/rb-daap-src.c
+++ b/plugins/daap/rb-daap-src.c
@@ -30,35 +30,11 @@
#include "config.h"
-#include <string.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/ioctl.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <ctype.h>
-
-#include <libsoup/soup.h>
-
-#include <glib/gi18n.h>
#include <gst/gst.h>
-#include <gst/base/gstbasesrc.h>
-#include <gst/base/gstpushsrc.h>
+#include <string.h>
-#include "rb-daap-source.h"
-#include "rb-daap-src.h"
-#include "rb-debug.h"
#include "rb-daap-plugin.h"
-
-/* needed for portability to some systems, e.g. Solaris */
-#ifndef MSG_NOSIGNAL
-#define MSG_NOSIGNAL 0
-#endif
-
+#include "rb-daap-src.h"
#define RB_TYPE_DAAP_SRC (rb_daap_src_get_type())
#define RB_DAAP_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),RB_TYPE_DAAP_SRC,RBDAAPSrc))
@@ -66,38 +42,23 @@
#define RB_IS_DAAP_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),RB_TYPE_DAAP_SRC))
#define RB_IS_DAAP_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),RB_TYPE_DAAP_SRC))
-#define RESPONSE_BUFFER_SIZE (4096)
-
typedef struct _RBDAAPSrc RBDAAPSrc;
typedef struct _RBDAAPSrcClass RBDAAPSrcClass;
struct _RBDAAPSrc
{
- GstPushSrc parent;
+ GstBin parent;
/* uri */
gchar *daap_uri;
- /* connection */
- int sock_fd;
- gchar *buffer_base;
- gchar *buffer;
- guint buffer_size;
- guint32 bytes_per_read;
- gboolean chunked;
- gboolean first_chunk;
-
- gint64 size;
-
- /* Seek stuff */
- gint64 curoffset;
- gint64 seek_bytes;
- gboolean do_seek;
+ GstElement *souphttpsrc;
+ GstPad *ghostpad;
};
struct _RBDAAPSrcClass
{
- GstPushSrcClass parent_class;
+ GstBinClass parent_class;
};
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
@@ -134,9 +95,9 @@ _do_init (GType daap_src_type)
&urihandler_info);
}
-GST_BOILERPLATE_FULL (RBDAAPSrc, rb_daap_src, GstElement, GST_TYPE_PUSH_SRC, _do_init);
+GST_BOILERPLATE_FULL (RBDAAPSrc, rb_daap_src, GstBin, GST_TYPE_BIN, _do_init);
-static void rb_daap_src_finalize (GObject *object);
+static void rb_daap_src_dispose (GObject *object);
static void rb_daap_src_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -146,12 +107,7 @@ static void rb_daap_src_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
-static gboolean rb_daap_src_start (GstBaseSrc *bsrc);
-static gboolean rb_daap_src_stop (GstBaseSrc *bsrc);
-static gboolean rb_daap_src_is_seekable (GstBaseSrc *bsrc);
-static gboolean rb_daap_src_get_size (GstBaseSrc *src, guint64 *size);
-static gboolean rb_daap_src_do_seek (GstBaseSrc *src, GstSegment *segment);
-static GstFlowReturn rb_daap_src_create (GstPushSrc *psrc, GstBuffer **outbuf);
+static GstStateChangeReturn rb_daap_src_change_state (GstElement *element, GstStateChange transition);
void
rb_daap_src_set_plugin (RBPlugin *plugin)
@@ -164,8 +120,6 @@ enum
{
PROP_0,
PROP_LOCATION,
- PROP_SEEKABLE,
- PROP_BYTESPERREAD
};
static void
@@ -181,20 +135,15 @@ static void
rb_daap_src_class_init (RBDAAPSrcClass *klass)
{
GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSrcClass *gstbasesrc_class;
- GstPushSrcClass *gstpushsrc_class;
+ GstElementClass *element_class;
gobject_class = G_OBJECT_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
- gstbasesrc_class = (GstBaseSrcClass *) klass;
- gstpushsrc_class = (GstPushSrcClass *) klass;
-
- parent_class = g_type_class_ref (GST_TYPE_PUSH_SRC);
-
+ gobject_class->dispose = rb_daap_src_dispose;
gobject_class->set_property = rb_daap_src_set_property;
gobject_class->get_property = rb_daap_src_get_property;
- gobject_class->finalize = rb_daap_src_finalize;
+
+ element_class = GST_ELEMENT_CLASS (klass);
+ element_class->change_state = rb_daap_src_change_state;
g_object_class_install_property (gobject_class, PROP_LOCATION,
g_param_spec_string ("location",
@@ -202,40 +151,53 @@ rb_daap_src_class_init (RBDAAPSrcClass *klass)
"location of the file to read",
NULL,
G_PARAM_READWRITE));
-
- gstbasesrc_class->start = GST_DEBUG_FUNCPTR (rb_daap_src_start);
- gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (rb_daap_src_stop);
- gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (rb_daap_src_is_seekable);
- gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (rb_daap_src_get_size);
- gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (rb_daap_src_do_seek);
-
- gstpushsrc_class->create = GST_DEBUG_FUNCPTR (rb_daap_src_create);
}
static void
rb_daap_src_init (RBDAAPSrc *src, RBDAAPSrcClass *klass)
{
+ GstPad *pad;
+
+ /* create actual source */
+ src->souphttpsrc = gst_element_factory_make ("souphttpsrc", NULL);
+ if (src->souphttpsrc == NULL) {
+ g_warning ("couldn't create souphttpsrc element");
+ return;
+ }
+
+ gst_bin_add (GST_BIN (src), src->souphttpsrc);
+ gst_object_ref (src->souphttpsrc);
+
+ /* create ghost pad */
+ pad = gst_element_get_pad (src->souphttpsrc, "src");
+ src->ghostpad = gst_ghost_pad_new ("src", pad);
+ gst_element_add_pad (GST_ELEMENT (src), src->ghostpad);
+ gst_object_ref (src->ghostpad);
+ gst_object_unref (pad);
+
src->daap_uri = NULL;
- src->sock_fd = -1;
- src->curoffset = 0;
- src->bytes_per_read = 4096 * 2;
}
static void
-rb_daap_src_finalize (GObject *object)
+rb_daap_src_dispose (GObject *object)
{
RBDAAPSrc *src;
src = RB_DAAP_SRC (object);
- g_free (src->daap_uri);
- src->daap_uri = NULL;
+ if (src->ghostpad) {
+ gst_object_unref (src->ghostpad);
+ src->ghostpad = NULL;
+ }
- if (src->sock_fd != -1) {
- close (src->sock_fd);
- src->sock_fd = -1;
+ if (src->souphttpsrc) {
+ gst_object_unref (src->souphttpsrc);
+ src->souphttpsrc = NULL;
}
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ g_free (src->daap_uri);
+ src->daap_uri = NULL;
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
@@ -279,481 +241,55 @@ rb_daap_src_get_property (GObject *object,
}
}
-static gint
-rb_daap_src_write (RBDAAPSrc *src, const guchar *buf, size_t count)
-{
- size_t bytes_written = 0;
-
- while (bytes_written < count) {
- ssize_t wrote = send (src->sock_fd, buf + bytes_written, count - bytes_written, MSG_NOSIGNAL);
-
- if (wrote < 0) {
- GST_WARNING ("error while writing: %s", g_strerror (errno));
- return wrote;
- }
- if (wrote == 0)
- break;
-
- bytes_written += wrote;
- }
-
- GST_DEBUG_OBJECT (src, "wrote %d bytes succesfully", bytes_written);
- return bytes_written;
-}
-
-static gint
-rb_daap_src_read (RBDAAPSrc *src, guchar *buf, size_t count)
-{
- size_t bytes_read = 0;
-
- if (src->buffer_size > 0) {
- bytes_read = count;
- if (bytes_read > src->buffer_size)
- bytes_read = src->buffer_size;
-
- GST_DEBUG_OBJECT (src, "reading %d bytes from buffer", bytes_read);
- memcpy (buf, src->buffer, bytes_read);
- src->buffer += bytes_read;
- src->buffer_size -= bytes_read;
-
- if (src->buffer_size == 0) {
- g_free (src->buffer_base);
- src->buffer_base = NULL;
- src->buffer = NULL;
- }
- }
-
- while (bytes_read < count) {
- ssize_t ret = read (src->sock_fd, buf + bytes_read, count - bytes_read);
-
- if (ret < 0) {
- GST_WARNING ("error while reading: %s", g_strerror (errno));
- return ret;
- }
- if (ret == 0)
- break;
- bytes_read += ret;
- }
-
- GST_DEBUG_OBJECT (src, "read %d bytes succesfully", bytes_read);
- return bytes_read;
-}
-
-static gboolean
-_expect_char (RBDAAPSrc *src, guchar expected)
+GstStateChangeReturn
+rb_daap_src_change_state (GstElement *element, GstStateChange transition)
{
- guchar ch;
- if (rb_daap_src_read (src, &ch, sizeof (ch)) <= 0)
- return FALSE;
- if (ch != expected) {
- GST_DEBUG_OBJECT (src, "Expected char %d next, but got %d", expected, ch);
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-rb_daap_src_read_chunk_size (RBDAAPSrc *src, gboolean first_chunk, gint64 *chunk_size)
-{
- gchar chunk_buf[30];
- gchar ch;
- gint i = 0;
- memset (&chunk_buf, 0, sizeof (chunk_buf));
-
- GST_DEBUG_OBJECT (src, "reading next chunk size; first_chunk = %d", first_chunk);
- if (!first_chunk) {
- if (!_expect_char (src, '\r') ||
- !_expect_char (src, '\n')) {
- return FALSE;
- }
- }
-
- while (1) {
- if (rb_daap_src_read (src, (guchar *)&ch, sizeof(ch)) <= 0)
- return FALSE;
-
- if (ch == '\r') {
- if (!_expect_char (src, '\n')) {
- return FALSE;
+ RBDAAPSrc *src = RB_DAAP_SRC (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ {
+ const char *http = "http";
+ char *httpuri;
+ GstStructure *headers;
+ RBDAAPSource *source;
+
+ /* Retrieve extra headers for the HTTP connection. */
+ source = rb_daap_plugin_find_source_for_uri (daap_plugin, src->daap_uri);
+ if (source == NULL) {
+ g_warning ("Unable to lookup source for URI: %s", src->daap_uri);
+ return GST_STATE_CHANGE_FAILURE;
}
- *chunk_size = strtoul (chunk_buf, NULL, 16);
- if (*chunk_size == 0) {
- /* EOS */
- GST_DEBUG_OBJECT (src, "got EOS chunk");
- return TRUE;
- } else if (*chunk_size == ULONG_MAX) {
- /* overflow */
- GST_DEBUG_OBJECT (src, "HTTP chunk size overflowed");
- return FALSE;
- }
-
- GST_DEBUG_OBJECT (src, "got HTTP chunk size %lu", *chunk_size);
- return TRUE;
- } else if (isxdigit (ch)) {
- chunk_buf[i++] = ch;
- } else {
- GST_DEBUG_OBJECT (src, "HTTP chunk size included illegal character %c", ch);
- return FALSE;
- }
- }
-
- g_assert_not_reached ();
-}
-
-static void
-_split_uri (const gchar *daap_uri, gchar **host, guint *port, gchar **path)
-{
- gint locationlen;
- const gchar *pathstart = NULL;
- const gchar *hostport = NULL;
- const gchar *portstart = NULL;
-
- locationlen = strlen (daap_uri);
- hostport = daap_uri + 7;
- pathstart = strchr (hostport, '/');
-
- if (pathstart) {
- *path = g_strdup (pathstart);
- } else {
- *path = g_strdup ("/");
- pathstart = daap_uri + locationlen;
- }
-
- portstart = strrchr (hostport, ':');
- if (portstart) {
- *host = g_strndup (hostport, portstart - hostport);
- *port = strtoul (portstart + 1, NULL, 0);
- } else {
- *host = g_strndup (hostport, pathstart - hostport);
- *port = 3869;
- }
-}
-
-static gboolean
-rb_daap_src_open (RBDAAPSrc *src)
-{
- int ret;
- struct sockaddr *server;
- int server_len;
- RBDAAPSource *source;
- gchar *headers;
- gchar *host;
- guint port;
- gchar *path;
- SoupMessageHeaders *header_table;
- gchar *request;
- gchar *response;
- gchar *end_headers;
- size_t readsize;
- gboolean ok = TRUE;
- guint http_status;
- gchar *http_status_phrase = NULL;
- gboolean parse_result;
- SoupAddress *addr;
- SoupAddressFamily addr_family;
-
- if (src->buffer_base) {
- g_free (src->buffer_base);
- src->buffer_base = NULL;
- src->buffer = NULL;
- src->buffer_size = 0;
- }
-
- rb_debug ("Connecting to DAAP source: %s", src->daap_uri);
-
- _split_uri (src->daap_uri, &host, &port, &path);
- GST_DEBUG_OBJECT (src, "resolving server %s", host);
- addr = soup_address_new (host, port);
- if (soup_address_resolve_sync (addr, NULL) != SOUP_STATUS_OK) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Resolving %s failed", host));
- return FALSE;
- }
-
- server = soup_address_get_sockaddr (addr, &server_len);
- if (server == NULL) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Getting socket address from %s failed", host));
- return FALSE;
- }
-
- g_object_get (addr, "family", &addr_family, NULL);
-
- /* connect */
- src->sock_fd = socket (addr_family, SOCK_STREAM, 0);
- if (src->sock_fd == -1) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM);
- return FALSE;
- }
-
- GST_DEBUG_OBJECT (src, "connecting to server %s:%d", host, port);
- ret = connect (src->sock_fd, server, server_len);
- if (ret) {
- if (errno == ECONNREFUSED) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
- (_("Connection to %s:%d refused."), host, port),
- (NULL));
- } else {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Connect to %s:%d failed: %s", host, port,
- g_strerror (errno)));
- }
- g_free (host);
- g_free (path);
- return FALSE;
- }
-
- g_object_unref (addr);
-
- /* construct request */
- source = rb_daap_plugin_find_source_for_uri (daap_plugin, src->daap_uri);
- if (source == NULL) {
- g_warning ("Unable to lookup source for URI: %s", src->daap_uri);
- return FALSE;
- }
-
- /* The following can fail if the source is no longer connected */
- headers = rb_daap_source_get_headers (source, src->daap_uri, src->seek_bytes);
- if (headers == NULL) {
- g_free (host);
- g_free (path);
- return FALSE;
- }
-
- request = g_strdup_printf ("GET %s HTTP/1.1\r\nHost: %s\r\n%s\r\n",
- path, host, headers);
- g_free (headers);
- g_free (host);
- g_free (path);
-
- /* send request */
- GST_DEBUG_OBJECT (src, "Sending HTTP request:\n%s", request);
- if (rb_daap_src_write (src, (guchar *)request, strlen (request)) <= 0) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Sending HTTP request to %s failed: %s",
- src->daap_uri, g_strerror (errno)));
- g_free (request);
- return FALSE;
- }
- g_free (request);
-
- /* read response */
- response = g_malloc0 (RESPONSE_BUFFER_SIZE + 1);
- readsize = rb_daap_src_read (src, (guchar *)response, RESPONSE_BUFFER_SIZE);
- if (readsize <= 0) {
- g_free (response);
- GST_DEBUG_OBJECT (src, "Error while reading HTTP response header");
- return FALSE;
- }
- response[readsize] = '\0';
- GST_DEBUG_OBJECT (src, "Got HTTP response:\n%s", response);
-
- end_headers = strstr (response, "\r\n\r\n");
- if (!end_headers) {
- /* this means the DAAP server returned more than 4k of headers.
- * not terribly likely.
- */
- g_free (response);
- GST_DEBUG_OBJECT (src, "HTTP response header way too long");
- return FALSE;
- }
-
- header_table = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
- parse_result = soup_headers_parse_response (response,
- ((end_headers+2) - response),
- header_table,
- NULL,
- &http_status,
- &http_status_phrase);
-
- if (parse_result) {
- if (http_status == 200 || http_status == 206) {
- const char *enc_str = NULL;
- const char *len_str = NULL;
- enc_str = soup_message_headers_get (header_table, "Transfer-Encoding");
- len_str = soup_message_headers_get (header_table, "Content-Length");
-
- if (enc_str) {
- if (g_ascii_strcasecmp (enc_str, "chunked") == 0) {
- src->chunked = TRUE;
- } else {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Unknown HTTP transfer encoding \"%s\"", enc_str));
- }
- } else {
- src->chunked = FALSE;
- if (len_str) {
- char *e;
- src->size = strtoul (len_str, &e, 10);
- if (e == len_str) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Couldn't read HTTP content length \"%s\"", len_str));
- ok = FALSE;
- }
- } else {
- GST_DEBUG_OBJECT (src, "Response doesn't have a content length");
- src->size = 0;
- }
+ /* The following can fail if the source is no longer connected */
+ headers = rb_daap_source_get_headers (source, src->daap_uri);
+ if (headers == NULL) {
+ return GST_STATE_CHANGE_FAILURE;
}
- } else {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
- ("HTTP error: %s", http_status_phrase),
- (NULL));
- ok = FALSE;
- }
- } else {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Unable to parse HTTP response"));
- ok = FALSE;
- }
- g_free (http_status_phrase);
-
- soup_message_headers_free (header_table);
-
- end_headers += 4;
-
- /* copy remaining data into a new buffer */
- if (ok) {
- src->buffer_size = readsize - (end_headers - response);
- src->buffer_base = g_malloc0 (src->buffer_size);
- src->buffer = src->buffer_base;
- memcpy (src->buffer_base, response + (readsize - src->buffer_size), src->buffer_size);
- }
- g_free (response);
-
- return ok;
-}
-
-static gboolean
-rb_daap_src_start (GstBaseSrc *bsrc)
-{
- RBDAAPSrc *src = RB_DAAP_SRC (bsrc);
- if (src->sock_fd != -1) {
- close (src->sock_fd);
- }
-
- src->curoffset = 0;
+ g_object_set (src->souphttpsrc, "extra-headers", headers, NULL);
+ gst_structure_free (headers);
- if (rb_daap_src_open (src)) {
- src->buffer = src->buffer_base;
- src->curoffset = src->seek_bytes;
- if (src->chunked) {
- src->first_chunk = TRUE;
- src->size = 0;
- }
- return TRUE;
- } else {
- return FALSE;
- }
-}
+ /* Set daap://... URI as http:// on souphttpsrc to ready connection. */
+ httpuri = g_strdup (src->daap_uri);
+ strncpy (httpuri, http, 4);
-static gboolean
-rb_daap_src_stop (GstBaseSrc *bsrc)
-{
- /* don't do anything - this seems to get called during setup, but
- * we don't get started again afterwards.
- */
- return TRUE;
-}
-
-static GstFlowReturn
-rb_daap_src_create (GstPushSrc *psrc, GstBuffer **outbuf)
-{
- RBDAAPSrc *src;
- size_t readsize;
- GstBuffer *buf = NULL;
-
- src = RB_DAAP_SRC (psrc);
- if (src->do_seek) {
- if (src->sock_fd != -1) {
- close (src->sock_fd);
- src->sock_fd = -1;
- }
- if (!rb_daap_src_start (GST_BASE_SRC (src)))
- return GST_FLOW_ERROR;
- src->do_seek = FALSE;
- }
-
- /* get a new chunk, if we need one */
- if (src->chunked && src->size == 0) {
- if (!rb_daap_src_read_chunk_size (src, src->first_chunk, &src->size)) {
- return GST_FLOW_ERROR;
- } else if (src->size == 0) {
- /* EOS */
- return GST_FLOW_UNEXPECTED;
+ g_object_set (src->souphttpsrc, "location", httpuri, NULL);
+ g_free (httpuri);
+ break;
}
- src->first_chunk = FALSE;
- }
- readsize = src->bytes_per_read;
- if (src->chunked && readsize > src->size)
- readsize = src->size;
-
- buf = gst_buffer_new_and_alloc (readsize);
-
- GST_LOG_OBJECT (src, "Reading %d bytes", readsize);
- readsize = rb_daap_src_read (src, GST_BUFFER_DATA (buf), readsize);
- if (readsize < 0) {
- GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
- gst_buffer_unref (buf);
- return GST_FLOW_ERROR;
- }
-
- if (readsize == 0) {
- GST_DEBUG ("blocking read returns 0, EOS");
- gst_buffer_unref (buf);
- return GST_FLOW_UNEXPECTED;
- }
-
- if (src->chunked)
- src->size -= readsize;
-
- GST_BUFFER_OFFSET (buf) = src->curoffset;
- GST_BUFFER_SIZE (buf) = readsize;
- GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
- 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));
- *outbuf = buf;
- return GST_FLOW_OK;
-}
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ break;
-gboolean
-rb_daap_src_is_seekable (GstBaseSrc *bsrc)
-{
- return TRUE;
-}
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
-gboolean
-rb_daap_src_do_seek (GstBaseSrc *bsrc, GstSegment *segment)
-{
- RBDAAPSrc *src = RB_DAAP_SRC (bsrc);
- if (segment->format == GST_FORMAT_BYTES) {
- src->do_seek = TRUE;
- src->seek_bytes = segment->start;
- return TRUE;
- } else {
- return FALSE;
+ default:
+ break;
}
-}
-gboolean
-rb_daap_src_get_size (GstBaseSrc *bsrc, guint64 *size)
-{
- RBDAAPSrc *src = RB_DAAP_SRC (bsrc);
- if (src->chunked == FALSE && src->size > 0) {
- *size = src->size;
- return TRUE;
- }
- return FALSE;
+ return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]