summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2008-12-09 14:51:44 +0100
committerBenjamin Otte <otte@gnome.org>2008-12-16 15:16:38 +0100
commit28729e8096d5f24f5923d0e16ac957354d852d6b (patch)
treebe39d825d44c3f7db2201db1e184b62b8a340120
parent1152a1385217cc070888a2e6a86c85bda253bad6 (diff)
make this stuff work without channels
-rw-r--r--swfdec/Makefile.am8
-rw-r--r--swfdec/swfdec_net_connection.c18
-rw-r--r--swfdec/swfdec_net_stream.c27
-rw-r--r--swfdec/swfdec_net_stream.h5
-rw-r--r--swfdec/swfdec_rtmp_channel.c214
-rw-r--r--swfdec/swfdec_rtmp_channel.h81
-rw-r--r--swfdec/swfdec_rtmp_connection.c272
-rw-r--r--swfdec/swfdec_rtmp_connection.h22
-rw-r--r--swfdec/swfdec_rtmp_control_channel.c187
-rw-r--r--swfdec/swfdec_rtmp_control_channel.h56
-rw-r--r--swfdec/swfdec_rtmp_packet.c7
-rw-r--r--swfdec/swfdec_rtmp_packet.h4
-rw-r--r--swfdec/swfdec_rtmp_rpc.c78
-rw-r--r--swfdec/swfdec_rtmp_rpc.h13
-rw-r--r--swfdec/swfdec_rtmp_rpc_channel.c319
-rw-r--r--swfdec/swfdec_rtmp_rpc_channel.h70
-rw-r--r--swfdec/swfdec_rtmp_socket.c52
-rw-r--r--swfdec/swfdec_rtmp_video_channel.c99
-rw-r--r--swfdec/swfdec_rtmp_video_channel.h52
19 files changed, 339 insertions, 1245 deletions
diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index b64264bb..fc65e9df 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -131,18 +131,14 @@ libswfdec_source_files = \
swfdec_renderer.c \
swfdec_resource.c \
swfdec_ringbuffer.c \
- swfdec_rtmp_channel.c \
- swfdec_rtmp_control_channel.c \
swfdec_rtmp_connection.c \
swfdec_rtmp_handshake.c \
swfdec_rtmp_header.c \
swfdec_rtmp_packet.c \
- swfdec_rtmp_rpc_channel.c \
swfdec_rtmp_rpc.c \
swfdec_rtmp_socket.c \
swfdec_rtmp_socket_rtmp.c \
swfdec_rtmp_stream.c \
- swfdec_rtmp_video_channel.c \
swfdec_sandbox.c \
swfdec_script.c \
swfdec_selection.c \
@@ -333,18 +329,14 @@ noinst_HEADERS = \
swfdec_renderer_internal.h \
swfdec_resource.h \
swfdec_ringbuffer.h \
- swfdec_rtmp_channel.h \
- swfdec_rtmp_control_channel.h \
swfdec_rtmp_connection.h \
swfdec_rtmp_handshake.h \
swfdec_rtmp_header.h \
swfdec_rtmp_packet.h \
- swfdec_rtmp_rpc_channel.h \
swfdec_rtmp_rpc.h \
swfdec_rtmp_socket.h \
swfdec_rtmp_socket_rtmp.h \
swfdec_rtmp_stream.h \
- swfdec_rtmp_video_channel.h \
swfdec_sandbox.h \
swfdec_script_internal.h \
swfdec_shape.h \
diff --git a/swfdec/swfdec_net_connection.c b/swfdec/swfdec_net_connection.c
index 1d0479a6..73a4ce72 100644
--- a/swfdec/swfdec_net_connection.c
+++ b/swfdec/swfdec_net_connection.c
@@ -35,7 +35,7 @@
#include "swfdec_debug.h"
#include "swfdec_internal.h"
#include "swfdec_player_internal.h"
-#include "swfdec_rtmp_rpc_channel.h"
+#include "swfdec_rtmp_rpc.h"
#include "swfdec_sandbox.h"
/*** AS CODE ***/
@@ -81,13 +81,25 @@ swfdec_net_connection_do_call (SwfdecAsContext *cx, SwfdecAsObject *object,
{
SwfdecRtmpConnection *conn;
SwfdecAsObject *ret_cb = NULL;
+ SwfdecRtmpPacket *packet;
SwfdecAsValue name;
SWFDEC_AS_CHECK (SWFDEC_TYPE_RTMP_CONNECTION, &conn, "v|O", &name, &ret_cb);
- swfdec_rtmp_rpc_channel_send (SWFDEC_RTMP_RPC_CHANNEL (
- swfdec_rtmp_connection_get_rpc_channel (conn)), name,
+ if (!swfdec_rtmp_connection_is_connected (conn)) {
+ SWFDEC_WARNING ("NetConnection.call does not work on closed connections.");
+ return;
+ }
+
+ swfdec_rtmp_rpc_send (conn->rpc, name,
ret_cb, MAX (2, argc) - 2, argv + 2);
+ /* FIXME: This should be done by some smart API */
+ packet = swfdec_rtmp_rpc_pop (conn->rpc, FALSE);
+ if (packet) {
+ packet->header.channel = 3;
+ packet->header.stream = 0;
+ swfdec_rtmp_connection_send (conn, packet);
+ }
}
SWFDEC_AS_NATIVE (2100, 3, swfdec_net_connection_do_addHeader)
diff --git a/swfdec/swfdec_net_stream.c b/swfdec/swfdec_net_stream.c
index 163a9e89..41a66e87 100644
--- a/swfdec/swfdec_net_stream.c
+++ b/swfdec/swfdec_net_stream.c
@@ -26,8 +26,6 @@
#include "swfdec_as_frame_internal.h"
#include "swfdec_as_internal.h"
#include "swfdec_debug.h"
-#include "swfdec_rtmp_rpc_channel.h"
-#include "swfdec_rtmp_video_channel.h"
/*** NET STREAM ***/
@@ -47,14 +45,7 @@ swfdec_net_stream_mark (SwfdecGcObject *object)
static void
swfdec_net_stream_dispose (GObject *object)
{
- SwfdecNetStream *stream = SWFDEC_NET_STREAM (object);
-
- swfdec_rtmp_channel_unregister (stream->rpc_channel);
- g_object_unref (stream->rpc_channel);
- swfdec_rtmp_channel_unregister (stream->video_channel);
- g_object_unref (stream->video_channel);
- swfdec_rtmp_channel_unregister (stream->audio_channel);
- g_object_unref (stream->audio_channel);
+ //SwfdecNetStream *stream = SWFDEC_NET_STREAM (object);
G_OBJECT_CLASS (swfdec_net_stream_parent_class)->dispose (object);
}
@@ -157,12 +148,6 @@ swfdec_net_stream_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
stream = g_object_new (SWFDEC_TYPE_NET_STREAM, "context", cx, NULL);
stream->conn = conn;
swfdec_as_object_set_relay (o, SWFDEC_AS_RELAY (stream));
- stream->rpc_channel = swfdec_rtmp_rpc_channel_new (conn);
- swfdec_rtmp_rpc_channel_set_target (SWFDEC_RTMP_RPC_CHANNEL (stream->rpc_channel),
- swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (stream)));
- stream->video_channel = swfdec_rtmp_video_channel_new (conn);
- /* FIXME: new class for audio plz */
- stream->audio_channel = swfdec_rtmp_rpc_channel_new (conn);
}
SWFDEC_AS_NATIVE (2101, 201, swfdec_net_stream_onCreate)
@@ -172,7 +157,7 @@ swfdec_net_stream_onCreate (SwfdecAsContext *cx, SwfdecAsObject *object,
{
SwfdecNetStream *stream;
SwfdecAsObject *o;
- guint stream_id, channel_id;
+ guint stream_id;
SWFDEC_AS_CHECK (0, NULL, "oi", &o, &stream_id);
@@ -180,11 +165,7 @@ swfdec_net_stream_onCreate (SwfdecAsContext *cx, SwfdecAsObject *object,
return;
stream = SWFDEC_NET_STREAM (o->relay);
- stream->stream_id = stream_id;
- channel_id = 4 + ((stream_id - 1) * 5);
- swfdec_rtmp_channel_register (stream->rpc_channel, channel_id, stream_id);
- swfdec_rtmp_channel_register (stream->video_channel, channel_id + 1, stream_id);
- swfdec_rtmp_channel_register (stream->audio_channel, channel_id + 2, stream_id);
+ stream->stream = stream_id;
}
SWFDEC_AS_NATIVE (2101, 202, swfdec_net_stream_send_connection)
@@ -202,8 +183,10 @@ swfdec_net_stream_send_connection (SwfdecAsContext *cx, SwfdecAsObject *object,
return;
stream = SWFDEC_NET_STREAM (o->relay);
+#if 0
swfdec_rtmp_rpc_channel_send (SWFDEC_RTMP_RPC_CHANNEL (
stream->rpc_channel), name,
ret_cb, MAX (3, argc) - 3, argv + 3);
+#endif
}
diff --git a/swfdec/swfdec_net_stream.h b/swfdec/swfdec_net_stream.h
index 89297b85..7ece9fc7 100644
--- a/swfdec/swfdec_net_stream.h
+++ b/swfdec/swfdec_net_stream.h
@@ -39,10 +39,7 @@ struct _SwfdecNetStream {
SwfdecAsRelay relay;
SwfdecRtmpConnection * conn; /* the connection in use */
- guint stream_id; /* id of this stream */
- SwfdecRtmpChannel * rpc_channel; /* channel used for RPC */
- SwfdecRtmpChannel * video_channel; /* channel used for video */
- SwfdecRtmpChannel * audio_channel; /* channel used for audio */
+ guint stream; /* id of this stream */
};
struct _SwfdecNetStreamClass {
diff --git a/swfdec/swfdec_rtmp_channel.c b/swfdec/swfdec_rtmp_channel.c
deleted file mode 100644
index ea927613..00000000
--- a/swfdec/swfdec_rtmp_channel.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/* Swfdec
- * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "swfdec_rtmp_channel.h"
-
-#include "swfdec_debug.h"
-#include "swfdec_rtmp_socket.h"
-
-/*** SwfdecRtmpChannel ***/
-
-enum {
- PROP_0,
- PROP_CONNECTION
-};
-
-G_DEFINE_ABSTRACT_TYPE (SwfdecRtmpChannel, swfdec_rtmp_channel, G_TYPE_OBJECT)
-
-static void
-swfdec_rtmp_channel_get_property (GObject *object, guint param_id, GValue *value,
- GParamSpec * pspec)
-{
- SwfdecRtmpChannel *channel = SWFDEC_RTMP_CHANNEL (object);
-
- switch (param_id) {
- case PROP_CONNECTION:
- g_value_set_object (value, channel->conn);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- }
-}
-
-static void
-swfdec_rtmp_channel_set_property (GObject *object, guint param_id, const GValue *value,
- GParamSpec * pspec)
-{
- SwfdecRtmpChannel *channel = SWFDEC_RTMP_CHANNEL (object);
-
- switch (param_id) {
- case PROP_CONNECTION:
- channel->conn = g_value_get_object (value);
- g_assert (channel->conn != NULL);
- swfdec_rtmp_channel_get_time (channel, &channel->timestamp);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- }
-}
-
-static void
-swfdec_rtmp_channel_dispose (GObject *object)
-{
- SwfdecRtmpChannel *channel = SWFDEC_RTMP_CHANNEL (object);
-
- if (channel->recv_queue) {
- swfdec_buffer_queue_unref (channel->recv_queue);
- channel->recv_queue = NULL;
- }
- if (channel->send_queue) {
- swfdec_buffer_queue_unref (channel->send_queue);
- channel->send_queue = NULL;
- }
-
- G_OBJECT_CLASS (swfdec_rtmp_channel_parent_class)->dispose (object);
-}
-
-static void
-swfdec_rtmp_channel_class_init (SwfdecRtmpChannelClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = swfdec_rtmp_channel_dispose;
- object_class->get_property = swfdec_rtmp_channel_get_property;
- object_class->set_property = swfdec_rtmp_channel_set_property;
-
- g_object_class_install_property (object_class, PROP_CONNECTION,
- g_param_spec_object ("connection", "connection", "RTMP connection this channel belongs to",
- SWFDEC_TYPE_RTMP_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-}
-
-static void
-swfdec_rtmp_channel_init (SwfdecRtmpChannel *channel)
-{
- swfdec_rtmp_header_invalidate (&channel->recv_cache);
- channel->recv_queue = swfdec_buffer_queue_new ();
- swfdec_rtmp_header_invalidate (&channel->send_cache);
- channel->send_queue = swfdec_buffer_queue_new ();
-}
-
-SwfdecBuffer *
-swfdec_rtmp_channel_next_buffer (SwfdecRtmpChannel *channel)
-{
- SwfdecRtmpChannelClass *klass;
- SwfdecRtmpPacket *packet;
- SwfdecRtmpHeader header;
- SwfdecBuffer *buffer;
- SwfdecBots *bots;
- guint i;
-
- g_return_val_if_fail (SWFDEC_IS_RTMP_CHANNEL (channel), NULL);
- g_return_val_if_fail (swfdec_rtmp_channel_is_registered (channel), NULL);
-
- buffer = swfdec_buffer_queue_pull_buffer (channel->send_queue);
- if (buffer)
- return buffer;
-
- klass = SWFDEC_RTMP_CHANNEL_GET_CLASS (channel);
- swfdec_rtmp_header_copy (&header, &channel->send_cache);
- packet = klass->send (channel);
- if (packet == NULL)
- return NULL;
-
- buffer = packet->buffer;
- bots = swfdec_bots_new ();
- header.channel = channel->channel_id;
- header.type = packet->header.type;
- header.timestamp = packet->header.timestamp;
- header.size = buffer->length;
- header.stream = channel->stream_id;
-
- swfdec_rtmp_header_write (&header, bots,
- swfdec_rtmp_header_diff (&header, &channel->send_cache));
- swfdec_rtmp_header_copy (&channel->send_cache, &header);
-
- for (i = 0; i < buffer->length; i += SWFDEC_RTMP_BLOCK_SIZE) {
- if (i != 0) {
- /* write a continuation header */
- bots = swfdec_bots_new ();
- swfdec_rtmp_header_write (&header, bots, SWFDEC_RTMP_HEADER_1_BYTE);
- }
- swfdec_bots_put_data (bots, buffer->data + i, MIN (SWFDEC_RTMP_BLOCK_SIZE, buffer->length - i));
- swfdec_buffer_queue_push (channel->send_queue, swfdec_bots_close (bots));
- }
- swfdec_rtmp_packet_free (packet);
-
- return swfdec_buffer_queue_pull_buffer (channel->send_queue);
-}
-
-static int
-swfdec_rtmp_channel_compare (gconstpointer a, gconstpointer b)
-{
- SwfdecRtmpChannel *ca = (SwfdecRtmpChannel *) a;
- SwfdecRtmpChannel *cb = (SwfdecRtmpChannel *) b;
-
- return cb->channel_id - ca->channel_id;
-}
-
-void
-swfdec_rtmp_channel_register (SwfdecRtmpChannel *channel,
- guint channel_id, guint stream_id)
-{
- SwfdecRtmpConnection *conn;
-
- g_return_if_fail (SWFDEC_IS_RTMP_CHANNEL (channel));
- g_return_if_fail (!swfdec_rtmp_channel_is_registered (channel));
- g_return_if_fail (channel_id > 1);
-
- if (channel_id >= 65536 + 64) {
- SWFDEC_FIXME ("figure out how huge ids (like %u) are handled. Channel registration failed", channel_id);
- return;
- }
- SWFDEC_DEBUG ("registering %s as channel %u for stream %u", G_OBJECT_TYPE_NAME (channel),
- channel_id, stream_id);
-
- conn = channel->conn;
- conn->channels = g_list_insert_sorted (conn->channels, channel,
- swfdec_rtmp_channel_compare);
- channel->channel_id = channel_id;
- channel->stream_id = stream_id;
- g_object_ref (channel);
-
- swfdec_rtmp_socket_send (channel->conn->socket);
-}
-
-void
-swfdec_rtmp_channel_unregister (SwfdecRtmpChannel *channel)
-{
- g_return_if_fail (SWFDEC_IS_RTMP_CHANNEL (channel));
-
- if (!swfdec_rtmp_channel_is_registered (channel))
- return;
-
- if (channel->conn->last_send->data == channel) {
- channel->conn->last_send = channel->conn->last_send->next ?
- channel->conn->last_send->next : channel->conn->last_send->prev;
- }
- channel->conn->channels = g_list_remove (channel->conn->channels, channel);
- channel->channel_id = 0;
- channel->stream_id = 0;
- g_object_unref (channel);
-}
-
diff --git a/swfdec/swfdec_rtmp_channel.h b/swfdec/swfdec_rtmp_channel.h
deleted file mode 100644
index 4fa985a9..00000000
--- a/swfdec/swfdec_rtmp_channel.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Swfdec
- * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifndef _SWFDEC_RTMP_CHANNEL_H_
-#define _SWFDEC_RTMP_CHANNEL_H_
-
-#include <swfdec/swfdec_rtmp_connection.h>
-#include <swfdec/swfdec_rtmp_header.h>
-#include <swfdec/swfdec_rtmp_packet.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _SwfdecRtmpChannelClass SwfdecRtmpChannelClass;
-
-#define SWFDEC_TYPE_RTMP_CHANNEL (swfdec_rtmp_channel_get_type())
-#define SWFDEC_IS_RTMP_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_RTMP_CHANNEL))
-#define SWFDEC_IS_RTMP_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_RTMP_CHANNEL))
-#define SWFDEC_RTMP_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_RTMP_CHANNEL, SwfdecRtmpChannel))
-#define SWFDEC_RTMP_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_RTMP_CHANNEL, SwfdecRtmpChannelClass))
-#define SWFDEC_RTMP_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_RTMP_CHANNEL, SwfdecRtmpChannelClass))
-
-struct _SwfdecRtmpChannel {
- GObject object;
-
- SwfdecRtmpConnection * conn; /* Connection this channel belongs to */
- guint channel_id; /* channel id inside connection or 0 if no connection */
- guint stream_id; /* stream id inside connection */
-
- GTimeVal timestamp; /* timestamp for various uses - set when constructing */
- SwfdecRtmpHeader recv_cache; /* cached header info for receiving data */
- SwfdecBufferQueue * recv_queue; /* Queue of semi-assembled packages when receiving */
- SwfdecRtmpHeader send_cache; /* cached header info for sending data */
- SwfdecBufferQueue * send_queue; /* Queue of outgoing waiting for delivery */
-};
-
-struct _SwfdecRtmpChannelClass {
- GObjectClass object_class;
-
- void (* mark) (SwfdecRtmpChannel * channel);
- void (* receive) (SwfdecRtmpChannel * channel,
- const SwfdecRtmpHeader *header,
- SwfdecBuffer * buffer);
- SwfdecRtmpPacket * (* send) (SwfdecRtmpChannel * channel);
-};
-
-GType swfdec_rtmp_channel_get_type (void);
-
-SwfdecBuffer * swfdec_rtmp_channel_next_buffer (SwfdecRtmpChannel * channel);
-
-#define swfdec_rtmp_channel_get_time(channel, tv) (swfdec_as_context_get_time (swfdec_gc_object_get_context ((channel)->conn), tv))
-#define swfdec_rtmp_channel_is_registered(channel) ((channel)->channel_id > 0)
-#define swfdec_rtmp_channel_send(channel) G_STMT_START{\
- if (swfdec_rtmp_channel_is_registered(channel)) \
- swfdec_rtmp_socket_send (channel->conn->socket); \
-}G_STMT_END
-void swfdec_rtmp_channel_register (SwfdecRtmpChannel * channel,
- guint channel_id,
- guint stream_id);
-void swfdec_rtmp_channel_unregister (SwfdecRtmpChannel * channel);
-
-
-
-G_END_DECLS
-#endif
diff --git a/swfdec/swfdec_rtmp_connection.c b/swfdec/swfdec_rtmp_connection.c
index fcf3418c..208cc632 100644
--- a/swfdec/swfdec_rtmp_connection.c
+++ b/swfdec/swfdec_rtmp_connection.c
@@ -28,34 +28,180 @@
#include "swfdec_as_strings.h"
#include "swfdec_bots.h"
#include "swfdec_debug.h"
-#include "swfdec_rtmp_control_channel.h"
+#include "swfdec_sandbox.h"
#include "swfdec_rtmp_handshake.h"
-#include "swfdec_rtmp_rpc_channel.h"
+#include "swfdec_rtmp_rpc.h"
#include "swfdec_rtmp_socket.h"
#include "swfdec_rtmp_stream.h"
+#include "swfdec_utils.h"
/*** SwfdecRtmpStream ***/
static void
+swfdec_rtmp_connection_push_control (SwfdecRtmpConnection *conn,
+ SwfdecRtmpPacket *packet)
+{
+ g_return_if_fail (packet->header.channel == 2);
+
+ if (g_queue_is_empty (conn->control_packets)) {
+ g_queue_push_tail (conn->control_packets, NULL);
+ swfdec_rtmp_connection_send (conn, packet);
+ } else {
+ g_queue_push_tail (conn->control_packets, packet);
+ }
+}
+
+static void
+swfdec_rtmp_connection_handle_chunk_size (SwfdecRtmpConnection *conn, SwfdecBuffer *buffer)
+{
+ SwfdecBits bits;
+ guint new_size;
+
+ swfdec_bits_init (&bits, buffer);
+ new_size = swfdec_bits_get_bu32 (&bits);
+ SWFDEC_INFO ("altering read chunk size %u => %u", conn->read_size, new_size);
+ conn->read_size = new_size;
+ if (swfdec_bits_left (&bits)) {
+ SWFDEC_FIXME ("%u bytes left after chunk size", swfdec_bits_left (&bits) / 8);
+ }
+}
+
+static void
+swfdec_rtmp_connection_handle_ping (SwfdecRtmpConnection *conn, SwfdecBuffer *buffer)
+{
+ SwfdecBits bits;
+ guint type, target;
+
+ swfdec_bits_init (&bits, buffer);
+ type = swfdec_bits_get_bu16 (&bits);
+ target = swfdec_bits_get_bu32 (&bits);
+ SWFDEC_FIXME ("handle ping type %u for target %u", type, target);
+}
+
+static void
+swfdec_rtmp_connection_handle_server_bandwidth (SwfdecRtmpConnection *conn,
+ const SwfdecRtmpHeader *org_header, SwfdecBuffer *buffer)
+{
+ SwfdecBits bits;
+ SwfdecBots *bots;
+ guint new_bandwidth;
+ SwfdecRtmpPacket *packet;
+ GTimeVal tv;
+ long diff;
+
+ swfdec_bits_init (&bits, buffer);
+ new_bandwidth = swfdec_bits_get_bu32 (&bits);
+ SWFDEC_INFO ("new server bandwidth set: %u => %u",
+ conn->server_bandwidth, new_bandwidth);
+ conn->server_bandwidth = new_bandwidth;
+
+ /* I guess this is for telling the server to throttle if we know our bandwidth is smaller */
+ bots = swfdec_bots_new ();
+ swfdec_bots_put_bu32 (bots, new_bandwidth);
+ buffer = swfdec_bots_close (bots);
+ /* send diff between the timestamp that the server sent and our current time.
+ * FIXME: Is that correct? */
+ swfdec_as_context_get_time (swfdec_gc_object_get_context (conn), &tv);
+ diff = swfdec_time_val_diff (&conn->connect_time, &tv);
+ packet = swfdec_rtmp_packet_new (2, 0, SWFDEC_RTMP_PACKET_SERVER_BANDWIDTH,
+ org_header->timestamp - diff, buffer);
+ swfdec_buffer_unref (buffer);
+
+ swfdec_rtmp_connection_push_control (conn, packet);
+}
+
+static void
+swfdec_rtmp_connection_handle_client_bandwidth (SwfdecRtmpConnection *conn, SwfdecBuffer *buffer)
+{
+ SwfdecBits bits;
+ guint magic;
+
+ swfdec_bits_init (&bits, buffer);
+ conn->client_bandwidth = swfdec_bits_get_bu32 (&bits);
+ magic = swfdec_bits_get_u8 (&bits);
+ SWFDEC_INFO ("client bandwidth is %u, magic value set to %u",
+ conn->client_bandwidth, magic);
+}
+
+static void
swfdec_rtmp_connection_rtmp_stream_receive (SwfdecRtmpStream *stream,
const SwfdecRtmpHeader *header, SwfdecBuffer *buffer)
{
SwfdecRtmpConnection *conn = SWFDEC_RTMP_CONNECTION (stream);
- SwfdecRtmpChannel *channel = swfdec_rtmp_connection_get_channel (conn, header->channel);
- SwfdecRtmpChannelClass *klass;
-
- if (channel == NULL) {
- SWFDEC_FIXME ("woot, no channel %u", header->channel);
- return;
+
+ switch ((guint) header->type) {
+ case SWFDEC_RTMP_PACKET_SIZE:
+ swfdec_rtmp_connection_handle_chunk_size (conn, buffer);
+ break;
+ case SWFDEC_RTMP_PACKET_PING:
+ swfdec_rtmp_connection_handle_ping (conn, buffer);
+ break;
+ case SWFDEC_RTMP_PACKET_SERVER_BANDWIDTH:
+ swfdec_rtmp_connection_handle_server_bandwidth (conn, header, buffer);
+ break;
+ case SWFDEC_RTMP_PACKET_CLIENT_BANDWIDTH:
+ swfdec_rtmp_connection_handle_client_bandwidth (conn, buffer);
+ break;
+ case SWFDEC_RTMP_PACKET_INVOKE:
+ swfdec_sandbox_use (conn->sandbox);
+ if (swfdec_rtmp_rpc_receive (conn->rpc, buffer)) {
+ SwfdecRtmpPacket *packet = swfdec_rtmp_rpc_pop (conn->rpc, FALSE);
+ if (packet) {
+ packet->header.channel = 3;
+ packet->header.stream = 0;
+ swfdec_rtmp_connection_send (conn, packet);
+ }
+ }
+ swfdec_sandbox_unuse (conn->sandbox);
+ break;
+ default:
+ SWFDEC_FIXME ("what to do with header type %u (channel %u)?", header->type,
+ header->channel);
+ break;
+ }
+}
+
+static SwfdecRtmpPacket *
+swfdec_rtmp_connection_rtmp_stream_sent (SwfdecRtmpStream *stream,
+ const SwfdecRtmpPacket *packet)
+{
+ SwfdecRtmpConnection *conn = SWFDEC_RTMP_CONNECTION (stream);
+ SwfdecRtmpPacket *result = NULL;
+
+ switch (packet->header.channel) {
+ case 2:
+ {
+ GList *list;
+ if (g_queue_pop_head (conn->control_packets) != NULL) {
+ g_assert_not_reached ();
+ }
+ list = g_queue_peek_head_link (conn->control_packets);
+ if (list) {
+ result = list->data;
+ list->data = NULL;
+ }
+ }
+ break;
+ case 3:
+ result = swfdec_rtmp_rpc_pop (conn->rpc, TRUE);
+ if (result) {
+ result->header.channel = 3;
+ result->header.stream = 0;
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
}
- klass = SWFDEC_RTMP_CHANNEL_GET_CLASS (channel);
- klass->receive (channel, header, buffer);
+
+ return result;
}
static void
swfdec_rtmp_connection_rtmp_stream_init (SwfdecRtmpStreamInterface *iface)
{
iface->receive = swfdec_rtmp_connection_rtmp_stream_receive;
+ iface->sent = swfdec_rtmp_connection_rtmp_stream_sent;
}
/*** SwfdecRtmpConnection ***/
@@ -67,18 +213,22 @@ static void
swfdec_rtmp_connection_mark (SwfdecGcObject *object)
{
SwfdecRtmpConnection *conn = SWFDEC_RTMP_CONNECTION (object);
- GList *walk;
- for (walk = conn->channels; walk; walk = walk->next) {
- SwfdecRtmpChannel *channel = walk->data;
- SwfdecRtmpChannelClass *klass = SWFDEC_RTMP_CHANNEL_GET_CLASS (channel);
- if (klass->mark)
- klass->mark (channel);
- }
+ swfdec_rtmp_rpc_mark (conn->rpc);
SWFDEC_GC_OBJECT_CLASS (swfdec_rtmp_connection_parent_class)->mark (object);
}
+/* This function is necessary because we use packet->buffer->length as our write counter */
+static void
+swfdec_rtmp_connection_packets_free (gpointer packetp)
+{
+ SwfdecRtmpPacket *packet = packetp;
+
+ packet->buffer->length = packet->header.size;
+ swfdec_rtmp_packet_free (packet);
+}
+
static void
swfdec_rtmp_connection_dispose (GObject *object)
{
@@ -98,6 +248,20 @@ swfdec_rtmp_connection_dispose (GObject *object)
g_hash_table_destroy (conn->streams);
conn->streams = NULL;
}
+ if (conn->packets) {
+ g_queue_foreach (conn->packets, (GFunc) swfdec_rtmp_connection_packets_free, NULL);
+ g_queue_free (conn->packets);
+ conn->packets = NULL;
+ }
+ if (conn->control_packets) {
+ g_queue_foreach (conn->control_packets, (GFunc) swfdec_rtmp_packet_free, NULL);
+ g_queue_free (conn->control_packets);
+ conn->control_packets = NULL;
+ }
+ if (conn->rpc) {
+ swfdec_rtmp_rpc_free (conn->rpc);
+ conn->rpc = NULL;
+ }
G_OBJECT_CLASS (swfdec_rtmp_connection_parent_class)->dispose (object);
}
@@ -119,6 +283,10 @@ swfdec_rtmp_connection_init (SwfdecRtmpConnection *conn)
conn->incoming = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify) swfdec_rtmp_packet_free);
conn->streams = g_hash_table_new (g_direct_hash, g_direct_equal);
+ conn->packets = g_queue_new ();
+
+ conn->control_packets = g_queue_new ();
+ conn->rpc = swfdec_rtmp_rpc_new (conn, SWFDEC_AS_RELAY (conn));
conn->read_size = SWFDEC_RTMP_BLOCK_SIZE;
conn->write_size = SWFDEC_RTMP_BLOCK_SIZE;
@@ -129,8 +297,6 @@ swfdec_rtmp_connection_init (SwfdecRtmpConnection *conn)
void
swfdec_rtmp_connection_connect (SwfdecRtmpConnection *conn, const SwfdecURL *url)
{
- SwfdecRtmpChannel *channel;
-
g_return_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn));
swfdec_rtmp_connection_close (conn);
@@ -145,16 +311,9 @@ swfdec_rtmp_connection_connect (SwfdecRtmpConnection *conn, const SwfdecURL *url
if (conn->error)
return;
+ swfdec_as_context_get_time (swfdec_gc_object_get_context (conn), &conn->connect_time);
+ conn->rpc->last_send = conn->connect_time;
conn->handshake = swfdec_rtmp_handshake_new (conn);
-
- channel = swfdec_rtmp_control_channel_new (conn);
- swfdec_rtmp_channel_register (channel, 2, 0);
- g_object_unref (channel);
- channel = swfdec_rtmp_rpc_channel_new (conn);
- swfdec_rtmp_channel_register (channel, 3, 0);
- g_object_unref (channel);
- conn->last_send = conn->channels;
-
swfdec_rtmp_socket_send (conn->socket);
}
@@ -163,17 +322,13 @@ swfdec_rtmp_connection_close (SwfdecRtmpConnection *conn)
{
g_return_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn));
- while (conn->channels)
- swfdec_rtmp_channel_unregister (conn->channels->data);
+ if (!swfdec_rtmp_connection_is_connected (conn))
+ return;
- if (conn->socket) {
- g_object_unref (conn->socket);
- conn->socket = NULL;
- }
- if (conn->url) {
- swfdec_url_free (conn->url);
- conn->url = NULL;
- }
+ g_object_unref (conn->socket);
+ conn->socket = NULL;
+ swfdec_url_free (conn->url);
+ conn->url = NULL;
}
void
@@ -217,27 +372,6 @@ swfdec_rtmp_connection_on_status (SwfdecRtmpConnection *conn, SwfdecAsValue valu
swfdec_as_relay_call (SWFDEC_AS_RELAY (conn), SWFDEC_AS_STR_onStatus, 1, &value, NULL);
}
-SwfdecRtmpChannel *
-swfdec_rtmp_connection_get_channel (SwfdecRtmpConnection *conn, guint id)
-{
- SwfdecRtmpChannel *channel;
- GList *walk;
-
- g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL);
- g_return_val_if_fail (conn->channels != NULL, NULL);
-
- for (walk = conn->channels; walk; walk = walk->next) {
- channel = walk->data;
- if (channel->channel_id < id)
- continue;
- if (channel->channel_id == id)
- return channel;
- return NULL;
- }
-
- return NULL;
-}
-
void
swfdec_rtmp_register_stream (SwfdecRtmpConnection *conn,
guint id, SwfdecRtmpStream *stream)
@@ -263,3 +397,23 @@ swfdec_rtmp_unregister_stream (SwfdecRtmpConnection *conn, guint id)
g_assert_not_reached ();
}
}
+
+void
+swfdec_rtmp_connection_send (SwfdecRtmpConnection *conn, SwfdecRtmpPacket *packet)
+{
+ gboolean send;
+
+ g_return_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn));
+ g_return_if_fail (packet != NULL);
+ /* FIXME: I'd like a g_return_if_fail (packet->channel is not already sent),
+ * but that requires a g_queue_find_custom () and that's slow */
+
+ g_assert (packet->header.size == packet->buffer->length);
+ packet->buffer->length = 0;
+ send = g_queue_is_empty (conn->packets);
+ g_queue_push_tail (conn->packets, packet);
+ g_print ("pushed channel %u - %u packets now\n", packet->header.channel,
+ g_queue_get_length (conn->packets));
+ if (send)
+ swfdec_rtmp_socket_send (conn->socket);
+}
diff --git a/swfdec/swfdec_rtmp_connection.h b/swfdec/swfdec_rtmp_connection.h
index 2a900dfa..13fbd7fa 100644
--- a/swfdec/swfdec_rtmp_connection.h
+++ b/swfdec/swfdec_rtmp_connection.h
@@ -23,6 +23,7 @@
#include <swfdec/swfdec.h>
#include <swfdec/swfdec_as_relay.h>
#include <swfdec/swfdec_rtmp_header.h>
+#include <swfdec/swfdec_rtmp_packet.h>
#include <swfdec/swfdec_types.h>
G_BEGIN_DECLS
@@ -32,8 +33,8 @@ G_BEGIN_DECLS
#define SWFDEC_RTMP_BLOCK_SIZE 128
/* forward declarations */
-typedef struct _SwfdecRtmpChannel SwfdecRtmpChannel;
typedef struct _SwfdecRtmpHandshake SwfdecRtmpHandshake;
+typedef struct _SwfdecRtmpRpc SwfdecRtmpRpc;
typedef struct _SwfdecRtmpSocket SwfdecRtmpSocket;
typedef struct _SwfdecRtmpStream SwfdecRtmpStream;
@@ -53,15 +54,20 @@ struct _SwfdecRtmpConnection {
SwfdecURL * url; /* URL in use by this connection */
SwfdecSandbox * sandbox; /* sandbox we execute functions in or NULL */
SwfdecRtmpSocket * socket; /* socket we're using for read/write */
- GList * channels; /* list of channels in use by this connection (ordered by channel) */
- GList * last_send; /* list entry of last channel sent to */
SwfdecRtmpHandshake * handshake; /* structure used for doing initial handshake or NULL */
char * error; /* NULL or debug string for error message */
GHashTable * incoming; /* channel id => incoming packets */
GHashTable * streams; /* stream id => stream */
+ GQueue * packets; /* queue of packets in send order */
+ GTimeVal connect_time; /* time at which this connectioon was opened */
+
+ GQueue * control_packets;/* packets waiting to be sent on queue 2 */
+ SwfdecRtmpRpc * rpc; /* queue for rpc */
guint read_size; /* size of a block of data when reading */
guint write_size; /* size of a block of data when writing */
+ guint server_bandwidth; /* ??? */
+ guint client_bandwidth; /* ??? */
};
struct _SwfdecRtmpConnectionClass {
@@ -70,15 +76,16 @@ struct _SwfdecRtmpConnectionClass {
GType swfdec_rtmp_connection_get_type (void);
+#define swfdec_rtmp_connection_is_connected(conn) ((conn)->socket != NULL)
void swfdec_rtmp_connection_connect (SwfdecRtmpConnection * conn,
const SwfdecURL * url);
void swfdec_rtmp_connection_close (SwfdecRtmpConnection * conn);
void swfdec_rtmp_connection_receive (SwfdecRtmpConnection * conn,
SwfdecBufferQueue * queue);
-void swfdec_rtmp_connection_send (SwfdecRtmpConnection * conn);
-SwfdecRtmpChannel * swfdec_rtmp_connection_get_channel (SwfdecRtmpConnection * conn,
- guint id);
+void swfdec_rtmp_connection_send (SwfdecRtmpConnection * conn,
+ SwfdecRtmpPacket * packet);
+
void swfdec_rtmp_connection_error (SwfdecRtmpConnection * conn,
const char * error,
...) G_GNUC_PRINTF (2, 3);
@@ -94,9 +101,6 @@ void swfdec_rtmp_register_stream (SwfdecRtmpConnection * conn,
void swfdec_rtmp_unregister_stream (SwfdecRtmpConnection * conn,
guint id);
-#define swfdec_rtmp_connection_get_command_channel(conn) (swfdec_rtmp_connection_get_channel (conn, 2))
-#define swfdec_rtmp_connection_get_rpc_channel(conn) (swfdec_rtmp_connection_get_channel (conn, 3))
-
G_END_DECLS
#endif
diff --git a/swfdec/swfdec_rtmp_control_channel.c b/swfdec/swfdec_rtmp_control_channel.c
deleted file mode 100644
index 013862aa..00000000
--- a/swfdec/swfdec_rtmp_control_channel.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* Swfdec
- * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "swfdec_rtmp_control_channel.h"
-
-#include "swfdec_debug.h"
-#include "swfdec_rtmp_socket.h"
-#include "swfdec_utils.h"
-
-/*** SwfdecRtmpControlChannel ***/
-
-G_DEFINE_TYPE (SwfdecRtmpControlChannel, swfdec_rtmp_control_channel, SWFDEC_TYPE_RTMP_CHANNEL)
-
-static void
-swfdec_rtmp_control_channel_push (SwfdecRtmpControlChannel *control,
- SwfdecRtmpPacket *packet)
-{
- gboolean empty = g_queue_is_empty (control->send_packets);
-
- g_queue_push_tail (control->send_packets, packet);
-
- if (empty)
- swfdec_rtmp_channel_send (SWFDEC_RTMP_CHANNEL (control));
-}
-
-static void
-swfdec_rtmp_control_channel_handle_chunk_size (SwfdecRtmpChannel *channel, SwfdecBuffer *buffer)
-{
- SwfdecBits bits;
-
- swfdec_bits_init (&bits, buffer);
- channel->conn->read_size = swfdec_bits_get_bu32 (&bits);
- SWFDEC_INFO ("setting read chunk size to %u", channel->conn->read_size);
- if (swfdec_bits_left (&bits)) {
- SWFDEC_FIXME ("%u bytes left after chunk size", swfdec_bits_left (&bits) / 8);
- }
-}
-
-static void
-swfdec_rtmp_control_channel_handle_ping (SwfdecRtmpChannel *channel, SwfdecBuffer *buffer)
-{
- SwfdecBits bits;
- guint type, target;
-
- swfdec_bits_init (&bits, buffer);
- type = swfdec_bits_get_bu16 (&bits);
- target = swfdec_bits_get_bu32 (&bits);
- SWFDEC_FIXME ("handle ping type %u for target %u", type, target);
-}
-
-static void
-swfdec_rtmp_control_channel_handle_server_bandwidth (SwfdecRtmpChannel *channel,
- const SwfdecRtmpHeader *org_header, SwfdecBuffer *buffer)
-{
- SwfdecRtmpControlChannel *control = SWFDEC_RTMP_CONTROL_CHANNEL (channel);
- SwfdecBits bits;
- SwfdecBots *bots;
- guint new_bandwidth;
- SwfdecRtmpPacket *packet;
- GTimeVal tv;
- long diff;
-
- swfdec_bits_init (&bits, buffer);
- new_bandwidth = swfdec_bits_get_bu32 (&bits);
- SWFDEC_INFO ("new server bandwidth set: %u => %u",
- control->server_bandwidth, new_bandwidth);
- control->server_bandwidth = new_bandwidth;
-
- /* I guess this is for telling the server to throttle if we know our bandwidth is smaller */
- bots = swfdec_bots_new ();
- swfdec_bots_put_bu32 (bots, new_bandwidth);
- buffer = swfdec_bots_close (bots);
- /* send diff between the timestamp that the server sent and our current time.
- * FIXME: Is that correct? */
- swfdec_rtmp_channel_get_time (channel, &tv);
- diff = swfdec_time_val_diff (&channel->timestamp, &tv);
- packet = swfdec_rtmp_packet_new (SWFDEC_RTMP_PACKET_SERVER_BANDWIDTH,
- org_header->timestamp - diff, buffer);
- swfdec_buffer_unref (buffer);
-
- swfdec_rtmp_control_channel_push (control, packet);
-}
-
-static void
-swfdec_rtmp_control_channel_handle_client_bandwidth (SwfdecRtmpChannel *channel, SwfdecBuffer *buffer)
-{
- SwfdecRtmpControlChannel *control = SWFDEC_RTMP_CONTROL_CHANNEL (channel);
- SwfdecBits bits;
- guint magic;
-
- swfdec_bits_init (&bits, buffer);
- control->client_bandwidth = swfdec_bits_get_bu32 (&bits);
- magic = swfdec_bits_get_u8 (&bits);
- SWFDEC_INFO ("client bandwidth is %u, magic value set to %u",
- control->client_bandwidth, magic);
-}
-
-static void
-swfdec_rtmp_control_channel_receive (SwfdecRtmpChannel *channel,
- const SwfdecRtmpHeader *header, SwfdecBuffer *buffer)
-{
- switch ((guint) header->type) {
- case SWFDEC_RTMP_PACKET_SIZE:
- swfdec_rtmp_control_channel_handle_chunk_size (channel, buffer);
- break;
- case SWFDEC_RTMP_PACKET_PING:
- swfdec_rtmp_control_channel_handle_ping (channel, buffer);
- break;
- case SWFDEC_RTMP_PACKET_SERVER_BANDWIDTH:
- swfdec_rtmp_control_channel_handle_server_bandwidth (channel, header, buffer);
- break;
- case SWFDEC_RTMP_PACKET_CLIENT_BANDWIDTH:
- swfdec_rtmp_control_channel_handle_client_bandwidth (channel, buffer);
- break;
- default:
- SWFDEC_FIXME ("what to do with header type %u?", header->type);
- break;
- }
-}
-
-static SwfdecRtmpPacket *
-swfdec_rtmp_control_channel_send (SwfdecRtmpChannel *channel)
-{
- SwfdecRtmpControlChannel *control = SWFDEC_RTMP_CONTROL_CHANNEL (channel);
-
- return g_queue_pop_head (control->send_packets);
-}
-
-static void
-swfdec_rtmp_control_channel_dispose (GObject *object)
-{
- SwfdecRtmpControlChannel *control = SWFDEC_RTMP_CONTROL_CHANNEL (object);
-
- if (control->send_packets) {
- g_queue_foreach (control->send_packets, (GFunc) swfdec_rtmp_packet_free, NULL);
- g_queue_free (control->send_packets);
- control->send_packets = NULL;
- }
-
- G_OBJECT_CLASS (swfdec_rtmp_control_channel_parent_class)->dispose (object);
-}
-
-static void
-swfdec_rtmp_control_channel_class_init (SwfdecRtmpControlChannelClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- SwfdecRtmpChannelClass *channel_class = SWFDEC_RTMP_CHANNEL_CLASS (klass);
-
- object_class->dispose = swfdec_rtmp_control_channel_dispose;
-
- channel_class->receive = swfdec_rtmp_control_channel_receive;
- channel_class->send = swfdec_rtmp_control_channel_send;
-}
-
-static void
-swfdec_rtmp_control_channel_init (SwfdecRtmpControlChannel *control)
-{
- control->send_packets = g_queue_new ();
-}
-
-SwfdecRtmpChannel *
-swfdec_rtmp_control_channel_new (SwfdecRtmpConnection *conn)
-{
- g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL);
-
- return g_object_new (SWFDEC_TYPE_RTMP_CONTROL_CHANNEL, "connection", conn, NULL);
-}
diff --git a/swfdec/swfdec_rtmp_control_channel.h b/swfdec/swfdec_rtmp_control_channel.h
deleted file mode 100644
index 5a56bc6f..00000000
--- a/swfdec/swfdec_rtmp_control_channel.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Swfdec
- * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifndef _SWFDEC_RTMP_CONTROL_CHANNEL_H_
-#define _SWFDEC_RTMP_CONTROL_CHANNEL_H_
-
-#include <swfdec/swfdec_rtmp_channel.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _SwfdecRtmpControlChannel SwfdecRtmpControlChannel;
-typedef struct _SwfdecRtmpControlChannelClass SwfdecRtmpControlChannelClass;
-
-#define SWFDEC_TYPE_RTMP_CONTROL_CHANNEL (swfdec_rtmp_control_channel_get_type())
-#define SWFDEC_IS_RTMP_CONTROL_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL))
-#define SWFDEC_IS_RTMP_CONTROL_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL))
-#define SWFDEC_RTMP_CONTROL_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL, SwfdecRtmpControlChannel))
-#define SWFDEC_RTMP_CONTROL_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL, SwfdecRtmpControlChannelClass))
-#define SWFDEC_RTMP_CONTROL_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL, SwfdecRtmpControlChannelClass))
-
-struct _SwfdecRtmpControlChannel {
- SwfdecRtmpChannel channel;
-
- GQueue * send_packets; /* packets that still need to be sent */
- guint server_bandwidth;
- guint client_bandwidth;
-};
-
-struct _SwfdecRtmpControlChannelClass {
- SwfdecRtmpChannelClass channel_class;
-};
-
-GType swfdec_rtmp_control_channel_get_type (void);
-
-SwfdecRtmpChannel * swfdec_rtmp_control_channel_new (SwfdecRtmpConnection * conn);
-
-
-G_END_DECLS
-#endif
diff --git a/swfdec/swfdec_rtmp_packet.c b/swfdec/swfdec_rtmp_packet.c
index ae3d1332..be2c2a8e 100644
--- a/swfdec/swfdec_rtmp_packet.c
+++ b/swfdec/swfdec_rtmp_packet.c
@@ -30,16 +30,19 @@ swfdec_rtmp_packet_new_empty (void)
}
SwfdecRtmpPacket *
-swfdec_rtmp_packet_new (SwfdecRtmpPacketType type, guint timestamp,
- SwfdecBuffer *buffer)
+swfdec_rtmp_packet_new (guint channel, guint stream, SwfdecRtmpPacketType type,
+ guint timestamp, SwfdecBuffer *buffer)
{
SwfdecRtmpPacket *packet;
g_return_val_if_fail (buffer != NULL, NULL);
packet = swfdec_rtmp_packet_new_empty ();
+ packet->header.channel = channel;
+ packet->header.stream = stream;
packet->header.type = type;
packet->header.timestamp = timestamp;
+ packet->header.size = buffer->length;
packet->buffer = swfdec_buffer_ref (buffer);
return packet;
diff --git a/swfdec/swfdec_rtmp_packet.h b/swfdec/swfdec_rtmp_packet.h
index 96482f04..eee13ccc 100644
--- a/swfdec/swfdec_rtmp_packet.h
+++ b/swfdec/swfdec_rtmp_packet.h
@@ -34,7 +34,9 @@ struct _SwfdecRtmpPacket {
};
SwfdecRtmpPacket * swfdec_rtmp_packet_new_empty (void);
-SwfdecRtmpPacket * swfdec_rtmp_packet_new (SwfdecRtmpPacketType type,
+SwfdecRtmpPacket * swfdec_rtmp_packet_new (guint channel,
+ guint stream,
+ SwfdecRtmpPacketType type,
guint timestamp,
SwfdecBuffer * buffer);
void swfdec_rtmp_packet_free (SwfdecRtmpPacket * packet);
diff --git a/swfdec/swfdec_rtmp_rpc.c b/swfdec/swfdec_rtmp_rpc.c
index 984552a6..45481819 100644
--- a/swfdec/swfdec_rtmp_rpc.c
+++ b/swfdec/swfdec_rtmp_rpc.c
@@ -77,7 +77,7 @@ swfdec_rtmp_rpc_do_send (SwfdecRtmpRpc *rpc, SwfdecAsValue name,
buffer = swfdec_rtmp_rpc_encode (swfdec_gc_object_get_context (rpc->conn),
name, id, special, argc, argv);
- packet = swfdec_rtmp_packet_new (SWFDEC_RTMP_PACKET_INVOKE,
+ packet = swfdec_rtmp_packet_new (0, 0, SWFDEC_RTMP_PACKET_INVOKE,
swfdec_rtmp_rpc_update_last_send (rpc), buffer);
swfdec_buffer_unref (buffer);
empty = g_queue_is_empty (rpc->packets);
@@ -137,7 +137,7 @@ swfdec_rtmp_rpc_receive_reply (SwfdecRtmpRpc *rpc,
}
}
-static void
+static gboolean
swfdec_rtmp_rpc_receive_call (SwfdecRtmpRpc *rpc, SwfdecAmfContext *cx,
SwfdecAsValue val, SwfdecBits *bits)
{
@@ -149,7 +149,7 @@ swfdec_rtmp_rpc_receive_call (SwfdecRtmpRpc *rpc, SwfdecAmfContext *cx,
name = swfdec_as_value_to_string (context, val);
if (!swfdec_amf_decode (cx, bits, &val)) {
SWFDEC_ERROR ("could not decode reply id");
- return;
+ return FALSE;
}
id = swfdec_as_value_to_integer (context, val);
@@ -160,64 +160,69 @@ swfdec_rtmp_rpc_receive_call (SwfdecRtmpRpc *rpc, SwfdecAmfContext *cx,
if (!swfdec_amf_decode (cx, bits, &args[i])) {
SWFDEC_ERROR ("could not decode argument %u", i);
- return;
+ return FALSE;
}
}
- swfdec_as_object_call (rpc->target, name, i, args, &val);
+ swfdec_as_relay_call (rpc->target, name, i, args, &val);
g_free (args);
/* send reply */
if (id) {
swfdec_rtmp_rpc_do_send (rpc, SWFDEC_AS_VALUE_FROM_STRING (SWFDEC_AS_STR__result),
id, val, 0, NULL);
+ return TRUE;
+ } else {
+ return FALSE;
}
}
-void
-swfdec_rtmp_rpc_receive (SwfdecRtmpRpc *rpc,
- const SwfdecRtmpHeader *header, SwfdecBuffer *buffer)
+gboolean
+swfdec_rtmp_rpc_receive (SwfdecRtmpRpc *rpc, SwfdecBuffer *buffer)
{
SwfdecAmfContext *cx;
SwfdecAsContext *context;
SwfdecAsValue val;
SwfdecBits bits;
+ gboolean result;
context = swfdec_gc_object_get_context (rpc->conn);
cx = swfdec_amf_context_new (context);
g_assert (context->global);
+ swfdec_bits_init (&bits, buffer);
- switch ((guint) header->type) {
- case SWFDEC_RTMP_PACKET_INVOKE:
- swfdec_bits_init (&bits, buffer);
- if (!swfdec_amf_decode (cx, &bits, &val)) {
- SWFDEC_ERROR ("could not decode call name");
- break;
- }
- if (SWFDEC_AS_VALUE_IS_STRING (val) &&
- SWFDEC_AS_VALUE_GET_STRING (val) == SWFDEC_AS_STR__result) {
- swfdec_rtmp_rpc_receive_reply (rpc, cx, &bits);
- } else {
- swfdec_rtmp_rpc_receive_call (rpc, cx, val, &bits);
- }
- if (swfdec_bits_left (&bits)) {
- SWFDEC_FIXME ("%u bytes left after invoke on channel %u (stream %u)",
- swfdec_bits_left (&bits) / 8, header->channel, header->stream);
- }
- break;
- default:
- SWFDEC_FIXME ("channel %u: what to do with header type %u?",
- header->channel, header->type);
- break;
+ if (!swfdec_amf_decode (cx, &bits, &val)) {
+ SWFDEC_ERROR ("could not decode call name");
+ return FALSE;
+ }
+ if (SWFDEC_AS_VALUE_IS_STRING (val) &&
+ SWFDEC_AS_VALUE_GET_STRING (val) == SWFDEC_AS_STR__result) {
+ swfdec_rtmp_rpc_receive_reply (rpc, cx, &bits);
+ result = FALSE;
+ } else {
+ result = swfdec_rtmp_rpc_receive_call (rpc, cx, val, &bits);
}
swfdec_amf_context_free (cx);
+
+ if (swfdec_bits_left (&bits)) {
+ SWFDEC_FIXME ("%u bytes left after invoke", swfdec_bits_left (&bits) / 8);
+ }
+
+ return result;
}
SwfdecRtmpPacket *
-swfdec_rtmp_rpc_pop (SwfdecRtmpRpc *rpc)
+swfdec_rtmp_rpc_pop (SwfdecRtmpRpc *rpc, gboolean pull_if_pending)
{
+ SwfdecRtmpPacket *packet;
+
g_return_val_if_fail (rpc != NULL, NULL);
- return g_queue_pop_head (rpc->packets);
+ if (!pull_if_pending && rpc->packet_pending)
+ return NULL;
+
+ packet = g_queue_pop_head (rpc->packets);
+ rpc->packet_pending = (packet != NULL);
+ return packet;
}
void
@@ -239,19 +244,18 @@ swfdec_rtmp_rpc_send (SwfdecRtmpRpc *rpc, SwfdecAsValue name,
}
SwfdecRtmpRpc *
-swfdec_rtmp_rpc_new (SwfdecRtmpConnection *conn, SwfdecAsObject *target)
+swfdec_rtmp_rpc_new (SwfdecRtmpConnection *conn, SwfdecAsRelay *target)
{
SwfdecRtmpRpc *rpc;
g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL);
- g_return_val_if_fail (target != NULL, NULL);
+ g_return_val_if_fail (SWFDEC_IS_AS_RELAY (target), NULL);
- rpc = g_slice_new (SwfdecRtmpRpc);
+ rpc = g_slice_new0 (SwfdecRtmpRpc);
rpc->conn = conn;
rpc->target = target;
rpc->pending = g_hash_table_new (g_direct_hash, g_direct_equal);
rpc->packets = g_queue_new ();
- swfdec_as_context_get_time (swfdec_gc_object_get_context (conn), &rpc->last_send);
return rpc;
}
@@ -269,7 +273,7 @@ swfdec_rtmp_rpc_mark (SwfdecRtmpRpc *rpc)
swfdec_as_object_mark (value);
}
- swfdec_as_object_mark (rpc->target);
+ swfdec_gc_object_mark (rpc->target);
}
void
diff --git a/swfdec/swfdec_rtmp_rpc.h b/swfdec/swfdec_rtmp_rpc.h
index 2dd5a80b..3ca46e61 100644
--- a/swfdec/swfdec_rtmp_rpc.h
+++ b/swfdec/swfdec_rtmp_rpc.h
@@ -26,19 +26,18 @@
G_BEGIN_DECLS
-typedef struct _SwfdecRtmpRpc SwfdecRtmpRpc;
-
struct _SwfdecRtmpRpc {
SwfdecRtmpConnection * conn; /* connection to use */
- SwfdecAsObject * target; /* object to call received calls on */
+ SwfdecAsRelay * target; /* object to call received calls on */
guint id; /* last id used for RPC call */
GHashTable * pending; /* int => SwfdecAsObject mapping of calls having pending replies */
GQueue * packets; /* outstanding SwfdecRtmpPackets */
+ gboolean packet_pending; /* if a packet is known to be pending */
GTimeVal last_send; /* time the last call was sent */
};
SwfdecRtmpRpc * swfdec_rtmp_rpc_new (SwfdecRtmpConnection * conn,
- SwfdecAsObject * target);
+ SwfdecAsRelay * target);
void swfdec_rtmp_rpc_free (SwfdecRtmpRpc * rpc);
void swfdec_rtmp_rpc_mark (SwfdecRtmpRpc * rpc);
@@ -49,14 +48,14 @@ SwfdecBuffer * swfdec_rtmp_rpc_encode (SwfdecAsContext * context,
guint argc,
const SwfdecAsValue * argv);
-SwfdecRtmpPacket * swfdec_rtmp_rpc_pop (SwfdecRtmpRpc * rpc);
+SwfdecRtmpPacket * swfdec_rtmp_rpc_pop (SwfdecRtmpRpc * rpc,
+ gboolean pull_if_pending);
void swfdec_rtmp_rpc_send (SwfdecRtmpRpc * rpc,
SwfdecAsValue name,
SwfdecAsObject * reply_to,
guint argc,
const SwfdecAsValue * argv);
-void swfdec_rtmp_rpc_receive (SwfdecRtmpRpc * rpc,
- const SwfdecRtmpHeader *header,
+gboolean swfdec_rtmp_rpc_receive (SwfdecRtmpRpc * rpc,
SwfdecBuffer * buffer);
diff --git a/swfdec/swfdec_rtmp_rpc_channel.c b/swfdec/swfdec_rtmp_rpc_channel.c
deleted file mode 100644
index 47b7973f..00000000
--- a/swfdec/swfdec_rtmp_rpc_channel.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/* Swfdec
- * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "swfdec_rtmp_rpc_channel.h"
-
-#include "swfdec_amf.h"
-#include "swfdec_as_strings.h"
-#include "swfdec_debug.h"
-#include "swfdec_rtmp_handshake.h"
-#include "swfdec_rtmp_socket.h"
-#include "swfdec_sandbox.h"
-#include "swfdec_utils.h"
-
-/*** SwfdecRtmpRpcChannel ***/
-
-G_DEFINE_TYPE (SwfdecRtmpRpcChannel, swfdec_rtmp_rpc_channel, SWFDEC_TYPE_RTMP_CHANNEL)
-
-static guint
-swfdec_rtmp_rpc_channel_update_last_send (SwfdecRtmpChannel *channel)
-{
- GTimeVal tv;
- long diff;
-
- swfdec_rtmp_channel_get_time (channel, &tv);
- diff = swfdec_time_val_diff (&channel->timestamp, &tv);
- channel->timestamp = tv;
- return diff;
-}
-
-static void
-swfdec_rtmp_rpc_channel_do_send (SwfdecRtmpRpcChannel *rpc, SwfdecAsValue name,
- guint id, SwfdecAsValue special, guint argc, const SwfdecAsValue *argv)
-{
- SwfdecRtmpChannel *channel;
- SwfdecAsContext *context;
- SwfdecRtmpPacket *packet;
- SwfdecAmfContext *cx;
- SwfdecBuffer *buffer;
- SwfdecBots *bots;
- gboolean empty;
- guint i;
-
- channel = SWFDEC_RTMP_CHANNEL (rpc);
- context = swfdec_gc_object_get_context (channel->conn);
-
- /* prepare buffer to encode */
- cx = swfdec_amf_context_new (context);
- bots = swfdec_bots_new ();
- swfdec_amf_encode (cx, bots, name);
- swfdec_amf_encode (cx, bots, swfdec_as_value_from_number (context, id));
- swfdec_amf_encode (cx, bots, special);
- for (i = 0; i < argc; i++) {
- swfdec_amf_encode (cx, bots, argv[i]);
- }
- buffer = swfdec_bots_close (bots);
- swfdec_amf_context_free (cx);
-
- packet = swfdec_rtmp_packet_new (SWFDEC_RTMP_PACKET_INVOKE,
- swfdec_rtmp_rpc_channel_update_last_send (channel), buffer);
- empty = g_queue_is_empty (rpc->packets);
- g_queue_push_tail (rpc->packets, packet);
- if (empty)
- swfdec_rtmp_channel_send (channel);
-}
-
-static void
-swfdec_rtmp_rpc_channel_receive_reply (SwfdecRtmpChannel *channel,
- SwfdecAmfContext *cx, SwfdecBits *bits)
-{
- SwfdecAsContext *context = swfdec_gc_object_get_context (channel->conn);
- SwfdecAsObject *reply_to;
- SwfdecAsValue val[2], tmp;
- guint id, i;
-
- if (!swfdec_amf_decode (cx, bits, &tmp)) {
- SWFDEC_ERROR ("could not decode reply id");
- return;
- }
- id = swfdec_as_value_to_integer (context, tmp);
-
- for (i = 0; swfdec_bits_left (bits) && i < 2; i++) {
- if (!swfdec_amf_decode (cx, bits, &val[i])) {
- SWFDEC_ERROR ("could not decode reply value");
- return;
- }
- }
- if (swfdec_bits_left (bits)) {
- SWFDEC_FIXME ("more than 2 values in a reply?");
- }
-
- if (id == 1 && channel->conn->handshake) {
- SwfdecRtmpConnection *conn = channel->conn;
-
- /* FIXME: Do something with the result value */
-
- if (i >= 2) {
- swfdec_rtmp_connection_on_status (conn, val[1]);
- } else {
- SWFDEC_ERROR ("no 2nd argument in connect reply");
- }
-
- swfdec_rtmp_handshake_free (conn->handshake);
- conn->handshake = NULL;
- swfdec_rtmp_socket_send (conn->socket);
- } else {
- if (!SWFDEC_AS_VALUE_IS_NULL (val[0])) {
- SWFDEC_FIXME ("first argument in reply is not null?");
- }
- reply_to = g_hash_table_lookup (SWFDEC_RTMP_RPC_CHANNEL (channel)->pending,
- GUINT_TO_POINTER (id));
- if (reply_to == NULL) {
- SWFDEC_ERROR ("no object to send a reply to");
- return;
- }
- g_hash_table_steal (SWFDEC_RTMP_RPC_CHANNEL (channel)->pending, GUINT_TO_POINTER (id));
- swfdec_as_object_call (reply_to, SWFDEC_AS_STR_onResult, 1, &val[1], NULL);
- }
-}
-
-static void
-swfdec_rtmp_rpc_channel_receive_call (SwfdecRtmpChannel *channel,
- SwfdecAmfContext *cx, SwfdecAsValue val, SwfdecBits *bits)
-{
- SwfdecAsContext *context = swfdec_gc_object_get_context (channel->conn);
- SwfdecRtmpRpcChannel *rpc = SWFDEC_RTMP_RPC_CHANNEL (channel);
- const char *name;
- guint id, i;
- SwfdecAsValue *args;
-
- name = swfdec_as_value_to_string (context, val);
- if (!swfdec_amf_decode (cx, bits, &val)) {
- SWFDEC_ERROR ("could not decode reply id");
- return;
- }
- id = swfdec_as_value_to_integer (context, val);
-
- args = NULL;
- for (i = 0; swfdec_bits_left (bits); i++) {
- if ((i % 4) == 0)
- args = g_realloc (args, sizeof (SwfdecAsValue) * (i + 4));
-
- if (!swfdec_amf_decode (cx, bits, &args[i])) {
- SWFDEC_ERROR ("could not decode argument %u", i);
- return;
- }
- }
- swfdec_as_object_call (rpc->target, name, i, args, &val);
- g_free (args);
-
- /* send reply */
- if (id) {
- swfdec_rtmp_rpc_channel_do_send (rpc,
- SWFDEC_AS_VALUE_FROM_STRING (SWFDEC_AS_STR__result), id, val, 0, NULL);
- }
-}
-
-static void
-swfdec_rtmp_rpc_channel_receive (SwfdecRtmpChannel *channel,
- const SwfdecRtmpHeader *header, SwfdecBuffer *buffer)
-{
- SwfdecAsContext *context;
- SwfdecAmfContext *cx;
- SwfdecAsValue val;
- SwfdecBits bits;
-
- context = swfdec_gc_object_get_context (channel->conn);
- cx = swfdec_amf_context_new (context);
- swfdec_sandbox_use (channel->conn->sandbox);
- switch ((guint) header->type) {
- case SWFDEC_RTMP_PACKET_INVOKE:
- swfdec_bits_init (&bits, buffer);
- if (!swfdec_amf_decode (cx, &bits, &val)) {
- SWFDEC_ERROR ("could not decode call name");
- break;
- }
- if (SWFDEC_AS_VALUE_IS_STRING (val) &&
- SWFDEC_AS_VALUE_GET_STRING (val) == SWFDEC_AS_STR__result) {
- swfdec_rtmp_rpc_channel_receive_reply (channel, cx, &bits);
- } else {
- swfdec_rtmp_rpc_channel_receive_call (channel, cx, val, &bits);
- }
- break;
- default:
- SWFDEC_FIXME ("channel %u: what to do with header type %u?",
- channel->channel_id, header->type);
- break;
- }
- swfdec_sandbox_unuse (channel->conn->sandbox);
- swfdec_amf_context_free (cx);
-}
-
-static SwfdecRtmpPacket *
-swfdec_rtmp_rpc_channel_send_vfunc (SwfdecRtmpChannel *channel)
-{
- return g_queue_pop_head (SWFDEC_RTMP_RPC_CHANNEL (channel)->packets);
-}
-
-static void
-swfdec_rtmp_rpc_channel_mark (SwfdecRtmpChannel *channel)
-{
- SwfdecRtmpRpcChannel *rpc = SWFDEC_RTMP_RPC_CHANNEL (channel);
- GHashTableIter iter;
- gpointer value;
-
- for (g_hash_table_iter_init (&iter, rpc->pending);
- g_hash_table_iter_next (&iter, NULL, &value);) {
- swfdec_as_object_mark (value);
- }
-
- swfdec_as_object_mark (rpc->target);
-}
-
-static void
-swfdec_rtmp_rpc_channel_dispose (GObject *object)
-{
- SwfdecRtmpRpcChannel *rpc = SWFDEC_RTMP_RPC_CHANNEL (object);
-
- if (rpc->pending) {
- g_hash_table_destroy (rpc->pending);
- rpc->pending = NULL;
- }
- if (rpc->packets) {
- g_queue_foreach (rpc->packets, (GFunc) swfdec_rtmp_packet_free, NULL);
- g_queue_free (rpc->packets);
- rpc->packets = NULL;
- }
-
-
- G_OBJECT_CLASS (swfdec_rtmp_rpc_channel_parent_class)->dispose (object);
-}
-
-static void
-swfdec_rtmp_rpc_channel_class_init (SwfdecRtmpRpcChannelClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- SwfdecRtmpChannelClass *channel_class = SWFDEC_RTMP_CHANNEL_CLASS (klass);
-
- object_class->dispose = swfdec_rtmp_rpc_channel_dispose;
-
- channel_class->mark = swfdec_rtmp_rpc_channel_mark;
- channel_class->receive = swfdec_rtmp_rpc_channel_receive;
- channel_class->send = swfdec_rtmp_rpc_channel_send_vfunc;
-}
-
-static void
-swfdec_rtmp_rpc_channel_init (SwfdecRtmpRpcChannel *rpc)
-{
- rpc->pending = g_hash_table_new (g_direct_hash, g_direct_equal);
- rpc->packets = g_queue_new ();
-}
-
-void
-swfdec_rtmp_rpc_channel_send_connect (SwfdecRtmpRpcChannel *rpc,
- SwfdecAsValue connect)
-{
- swfdec_rtmp_rpc_channel_do_send (rpc, SWFDEC_AS_VALUE_FROM_STRING (SWFDEC_AS_STR_connect),
- ++rpc->id, connect, 0, NULL);
-}
-
-void
-swfdec_rtmp_rpc_channel_send (SwfdecRtmpRpcChannel *rpc,
- SwfdecAsValue name, SwfdecAsObject *reply_to,
- guint argc, const SwfdecAsValue *argv)
-{
- guint id;
-
- g_return_if_fail (SWFDEC_IS_RTMP_RPC_CHANNEL (rpc));
- g_return_if_fail (argc == 0 || argv != NULL);
-
- if (reply_to) {
- id = ++rpc->id;
- g_hash_table_insert (rpc->pending, GUINT_TO_POINTER (id), reply_to);
- } else {
- id = 0;
- }
- swfdec_rtmp_rpc_channel_do_send (rpc, name, id, SWFDEC_AS_VALUE_NULL, argc, argv);
-}
-
-SwfdecRtmpChannel *
-swfdec_rtmp_rpc_channel_new (SwfdecRtmpConnection *conn)
-{
- SwfdecRtmpRpcChannel *rpc;
- g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL);
-
- rpc = g_object_new (SWFDEC_TYPE_RTMP_RPC_CHANNEL, "connection", conn, NULL);
- rpc->target = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (conn));
-
- return SWFDEC_RTMP_CHANNEL (rpc);
-}
-
-void
-swfdec_rtmp_rpc_channel_set_target (SwfdecRtmpRpcChannel *rpc, SwfdecAsObject *object)
-{
- g_return_if_fail (SWFDEC_IS_RTMP_RPC_CHANNEL (rpc));
- g_return_if_fail (object != NULL);
-
- rpc->target = object;
-}
-
diff --git a/swfdec/swfdec_rtmp_rpc_channel.h b/swfdec/swfdec_rtmp_rpc_channel.h
deleted file mode 100644
index b4b69b1e..00000000
--- a/swfdec/swfdec_rtmp_rpc_channel.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Swfdec
- * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifndef _SWFDEC_RTMP_RPC_CHANNEL_H_
-#define _SWFDEC_RTMP_RPC_CHANNEL_H_
-
-#include <swfdec/swfdec_ringbuffer.h>
-#include <swfdec/swfdec_rtmp_channel.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _SwfdecRtmpRpcChannel SwfdecRtmpRpcChannel;
-typedef struct _SwfdecRtmpRpcChannelClass SwfdecRtmpRpcChannelClass;
-
-#define SWFDEC_TYPE_RTMP_RPC_CHANNEL (swfdec_rtmp_rpc_channel_get_type())
-#define SWFDEC_IS_RTMP_RPC_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_RTMP_RPC_CHANNEL))
-#define SWFDEC_IS_RTMP_RPC_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_RTMP_RPC_CHANNEL))
-#define SWFDEC_RTMP_RPC_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_RTMP_RPC_CHANNEL, SwfdecRtmpRpcChannel))
-#define SWFDEC_RTMP_RPC_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_RTMP_RPC_CHANNEL, SwfdecRtmpRpcChannelClass))
-#define SWFDEC_RTMP_RPC_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_RTMP_RPC_CHANNEL, SwfdecRtmpRpcChannelClass))
-
-struct _SwfdecRtmpRpcChannel {
- SwfdecRtmpChannel channel;
-
- SwfdecAsObject * target; /* object to call received calls on */
- guint id; /* last id used for RPC call */
- GHashTable * pending; /* int => SwfdecAsObject mapping of calls having pending replies */
- GQueue * packets; /* outstanding packets */
- GTimeVal last_send; /* time the last call was sent */
-};
-
-struct _SwfdecRtmpRpcChannelClass {
- SwfdecRtmpChannelClass channel_class;
-};
-
-GType swfdec_rtmp_rpc_channel_get_type (void);
-
-SwfdecRtmpChannel * swfdec_rtmp_rpc_channel_new (SwfdecRtmpConnection * conn);
-
-void swfdec_rtmp_rpc_channel_send_connect (SwfdecRtmpRpcChannel * rpc,
- SwfdecAsValue connect);
-void swfdec_rtmp_rpc_channel_send (SwfdecRtmpRpcChannel * rpc,
- SwfdecAsValue name,
- SwfdecAsObject * reply_to,
- guint argc,
- const SwfdecAsValue * argv);
-
-void swfdec_rtmp_rpc_channel_set_target (SwfdecRtmpRpcChannel * rpc,
- SwfdecAsObject * object);
-
-
-G_END_DECLS
-#endif
diff --git a/swfdec/swfdec_rtmp_socket.c b/swfdec/swfdec_rtmp_socket.c
index 11dfbca2..7bacb34b 100644
--- a/swfdec/swfdec_rtmp_socket.c
+++ b/swfdec/swfdec_rtmp_socket.c
@@ -27,7 +27,6 @@
#include "swfdec_debug.h"
#include "swfdec_player_internal.h"
-#include "swfdec_rtmp_channel.h"
#include "swfdec_rtmp_handshake.h"
#include "swfdec_rtmp_stream.h"
/* socket implementations for swfdec_rtmp_socket_new() */
@@ -121,9 +120,8 @@ SwfdecBuffer *
swfdec_rtmp_socket_next_buffer (SwfdecRtmpSocket *socket)
{
SwfdecRtmpConnection *conn;
- SwfdecRtmpChannel *channel;
- SwfdecBuffer *buffer;
- GList *walk;
+ SwfdecRtmpPacket *packet;
+ SwfdecBots *bots;
g_return_val_if_fail (SWFDEC_IS_RTMP_SOCKET (socket), NULL);
@@ -132,18 +130,42 @@ swfdec_rtmp_socket_next_buffer (SwfdecRtmpSocket *socket)
if (G_UNLIKELY (conn->handshake))
return swfdec_rtmp_handshake_next_buffer (conn->handshake);
- walk = conn->last_send;
- g_assert (walk);
- do {
- walk = walk->next ? walk->next : conn->channels;
- channel = walk->data;
- buffer = swfdec_rtmp_channel_next_buffer (channel);
- if (buffer != NULL) {
- conn->last_send = walk;
- return buffer;
+ bots = swfdec_bots_new ();
+next_packet:
+ packet = g_queue_pop_head (conn->packets);
+ if (packet == NULL)
+ return NULL;
+ if (packet->header.size == packet->buffer->length) {
+ SwfdecRtmpStream *stream;
+ SwfdecRtmpPacket *next;
+
+ stream = g_hash_table_lookup (conn->streams, GUINT_TO_POINTER (packet->header.stream));
+ if (stream == NULL) {
+ swfdec_rtmp_packet_free (packet);
+ goto next_packet;
+ }
+ next = swfdec_rtmp_stream_sent (stream, packet);
+ if (next == NULL) {
+ swfdec_rtmp_packet_free (packet);
+ goto next_packet;
}
- } while (walk != conn->last_send);
- return NULL;
+ swfdec_rtmp_header_write (&next->header, bots,
+ swfdec_rtmp_header_diff (&next->header, &packet->header));
+ swfdec_rtmp_packet_free (packet);
+ packet = next;
+ packet->buffer->length = 0;
+ } else if (packet->buffer->length == 0) {
+ swfdec_rtmp_header_write (&packet->header, bots, SWFDEC_RTMP_HEADER_12_BYTES);
+ } else {
+ swfdec_rtmp_header_write (&packet->header, bots, SWFDEC_RTMP_HEADER_1_BYTE);
+ }
+ swfdec_bots_put_data (bots, packet->buffer->data + packet->buffer->length,
+ MIN (conn->write_size, packet->header.size - packet->buffer->length));
+ packet->buffer->length += conn->write_size;
+ packet->buffer->length = MIN (packet->buffer->length, packet->header.size);
+
+ g_queue_push_tail (conn->packets, packet);
+ return swfdec_bots_close (bots);
}
void
diff --git a/swfdec/swfdec_rtmp_video_channel.c b/swfdec/swfdec_rtmp_video_channel.c
deleted file mode 100644
index 1f8697f8..00000000
--- a/swfdec/swfdec_rtmp_video_channel.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Swfdec
- * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "swfdec_rtmp_video_channel.h"
-
-#include "swfdec_debug.h"
-#include "swfdec_rtmp_socket.h"
-#include "swfdec_video_provider.h"
-
-/*** VIDEO PROVIDER INTERFACE ***/
-
-static cairo_surface_t *
-swfdec_rtmp_video_channel_get_image (SwfdecVideoProvider *prov,
- SwfdecRenderer *renderer, guint *width, guint *height)
-{
- return NULL;
-}
-
-static void
-swfdec_rtmp_video_channel_get_size (SwfdecVideoProvider *prov, guint *width, guint *height)
-{
-}
-
-static void
-swfdec_rtmp_video_channel_video_provider_init (SwfdecVideoProviderInterface *iface)
-{
- iface->get_image = swfdec_rtmp_video_channel_get_image;
- iface->get_size = swfdec_rtmp_video_channel_get_size;
-}
-
-/*** SwfdecRtmpVideoChannel ***/
-
-G_DEFINE_TYPE_WITH_CODE (SwfdecRtmpVideoChannel, swfdec_rtmp_video_channel, SWFDEC_TYPE_RTMP_CHANNEL,
- G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_VIDEO_PROVIDER, swfdec_rtmp_video_channel_video_provider_init))
-
-static void
-swfdec_rtmp_video_channel_receive (SwfdecRtmpChannel *channel,
- const SwfdecRtmpHeader *header, SwfdecBuffer *buffer)
-{
-}
-
-static SwfdecRtmpPacket *
-swfdec_rtmp_video_channel_send (SwfdecRtmpChannel *channel)
-{
- return NULL;
-}
-
-static void
-swfdec_rtmp_video_channel_dispose (GObject *object)
-{
- //SwfdecRtmpVideoChannel *conn = SWFDEC_RTMP_VIDEO_CHANNEL (object);
-
- G_OBJECT_CLASS (swfdec_rtmp_video_channel_parent_class)->dispose (object);
-}
-
-static void
-swfdec_rtmp_video_channel_class_init (SwfdecRtmpVideoChannelClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- SwfdecRtmpChannelClass *channel_class = SWFDEC_RTMP_CHANNEL_CLASS (klass);
-
- object_class->dispose = swfdec_rtmp_video_channel_dispose;
-
- channel_class->receive = swfdec_rtmp_video_channel_receive;
- channel_class->send = swfdec_rtmp_video_channel_send;
-}
-
-static void
-swfdec_rtmp_video_channel_init (SwfdecRtmpVideoChannel *command)
-{
-}
-
-SwfdecRtmpChannel *
-swfdec_rtmp_video_channel_new (SwfdecRtmpConnection *conn)
-{
- g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL);
-
- return g_object_new (SWFDEC_TYPE_RTMP_VIDEO_CHANNEL, "connection", conn, NULL);
-}
diff --git a/swfdec/swfdec_rtmp_video_channel.h b/swfdec/swfdec_rtmp_video_channel.h
deleted file mode 100644
index 49f0b15a..00000000
--- a/swfdec/swfdec_rtmp_video_channel.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Swfdec
- * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifndef _SWFDEC_RTMP_VIDEO_CHANNEL_H_
-#define _SWFDEC_RTMP_VIDEO_CHANNEL_H_
-
-#include <swfdec/swfdec_rtmp_channel.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _SwfdecRtmpVideoChannel SwfdecRtmpVideoChannel;
-typedef struct _SwfdecRtmpVideoChannelClass SwfdecRtmpVideoChannelClass;
-
-#define SWFDEC_TYPE_RTMP_VIDEO_CHANNEL (swfdec_rtmp_video_channel_get_type())
-#define SWFDEC_IS_RTMP_VIDEO_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL))
-#define SWFDEC_IS_RTMP_VIDEO_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL))
-#define SWFDEC_RTMP_VIDEO_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL, SwfdecRtmpVideoChannel))
-#define SWFDEC_RTMP_VIDEO_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL, SwfdecRtmpVideoChannelClass))
-#define SWFDEC_RTMP_VIDEO_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL, SwfdecRtmpVideoChannelClass))
-
-struct _SwfdecRtmpVideoChannel {
- SwfdecRtmpChannel channel;
-};
-
-struct _SwfdecRtmpVideoChannelClass {
- SwfdecRtmpChannelClass channel_class;
-};
-
-GType swfdec_rtmp_video_channel_get_type (void);
-
-SwfdecRtmpChannel * swfdec_rtmp_video_channel_new (SwfdecRtmpConnection * conn);
-
-
-G_END_DECLS
-#endif