add blend mode tests
[swfdec.git] / swfdec-gtk / swfdec_gtk_socket.c
blob3a902d77b2b04b0093e85cdb72e793fdd3a5ee18
1 /* Swfdec
2 * Copyright (C) 2006 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_gtk_socket.h"
25 #include <libsoup/soup.h>
26 #include <libsoup/soup-address.h>
28 /*** GTK-DOC ***/
30 /**
31 * SECTION:SwfdecGtkSocket
32 * @title: SwfdecGtkSocket
33 * @short_description: a socket implementation integrating into the Gtk main loop
34 * @see_also: #SwfdecSocket, #SwfdecGtkPlayer
36 * #SwfdecGtkSocket is a #SwfdecSocket that is a socket implementation that
37 * uses libsoup and integrates with the Gtk main loop. It is used by default
38 * by the #SwfecGtkPlayer.
41 /**
42 * SwfdecGtkSocket:
44 * This is the object used to represent a socket. It is completely private.
47 struct _SwfdecGtkSocket
49 SwfdecSocket socket;
51 SoupSocket * sock; /* libsoup socket we're using */
54 struct _SwfdecGtkSocketClass {
55 SwfdecSocketClass socket_class;
58 /*** SwfdecGtkSocket ***/
60 G_DEFINE_TYPE (SwfdecGtkSocket, swfdec_gtk_socket, SWFDEC_TYPE_SOCKET)
62 static void
63 swfdec_gtk_socket_close (SwfdecStream *stream)
65 SwfdecGtkSocket *gtk = SWFDEC_GTK_SOCKET (stream);
67 soup_socket_disconnect (gtk->sock);
70 static void
71 swfdec_gtk_socket_do_disconnect (SoupSocket *sock, SwfdecGtkSocket *gtk)
73 swfdec_stream_close (SWFDEC_STREAM (gtk));
76 static void
77 swfdec_gtk_socket_do_read (SoupSocket *sock, SwfdecGtkSocket *gtk)
79 #define SWFDEC_GTK_SOCKET_BLOCK_SIZE 1024
80 SwfdecBuffer *buffer;
81 SoupSocketIOStatus status;
82 gsize len;
83 GError *error = NULL;
85 do {
86 buffer = swfdec_buffer_new (SWFDEC_GTK_SOCKET_BLOCK_SIZE);
87 status = soup_socket_read (sock, buffer->data,
88 SWFDEC_GTK_SOCKET_BLOCK_SIZE, &len, NULL, &error);
89 buffer->length = len;
90 switch (status) {
91 case SOUP_SOCKET_OK:
92 swfdec_stream_push (SWFDEC_STREAM (gtk), buffer);
93 break;
94 case SOUP_SOCKET_WOULD_BLOCK:
95 case SOUP_SOCKET_EOF:
96 swfdec_buffer_unref (buffer);
97 break;
98 case SOUP_SOCKET_ERROR:
99 swfdec_buffer_unref (buffer);
100 swfdec_stream_error (SWFDEC_STREAM (gtk), "%s", error->message);
101 g_error_free (error);
102 break;
103 default:
104 g_warning ("unhandled status code %u from soup_socket_read()", (guint) status);
105 break;
107 } while (status == SOUP_SOCKET_OK);
110 static void
111 swfdec_gtk_socket_writable (SoupSocket *sock, SwfdecGtkSocket *gtk)
113 swfdec_socket_signal_writable (SWFDEC_SOCKET (gtk));
116 static void
117 swfdec_gtk_socket_do_connect (SoupSocket *sock, guint status, gpointer gtk)
119 if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
120 swfdec_stream_open (gtk);
121 // need to read here, since readable signal will only be launched once the
122 // socket has been read until it's empty once
123 swfdec_gtk_socket_do_read (sock, gtk);
124 } else {
125 swfdec_stream_error (gtk, "error connecting");
129 static void
130 swfdec_gtk_socket_connect (SwfdecSocket *sock_, SwfdecPlayer *player,
131 const char *hostname, guint port)
133 SwfdecGtkSocket *sock = SWFDEC_GTK_SOCKET (sock_);
134 SoupAddress *addr;
136 addr = soup_address_new (hostname, port);
137 sock->sock = soup_socket_new (
138 SOUP_SOCKET_FLAG_NONBLOCKING, TRUE,
139 SOUP_SOCKET_REMOTE_ADDRESS, addr, NULL);
140 g_signal_connect (sock->sock, "disconnected",
141 G_CALLBACK (swfdec_gtk_socket_do_disconnect), sock);
142 g_signal_connect (sock->sock, "readable",
143 G_CALLBACK (swfdec_gtk_socket_do_read), sock);
144 g_signal_connect (sock->sock, "writable",
145 G_CALLBACK (swfdec_gtk_socket_writable), sock);
146 soup_socket_connect_async (sock->sock, NULL, swfdec_gtk_socket_do_connect, sock);
149 static gsize
150 swfdec_gtk_socket_send (SwfdecSocket *sock, SwfdecBuffer *buffer)
152 SwfdecGtkSocket *gtk = SWFDEC_GTK_SOCKET (sock);
153 SoupSocketIOStatus status;
154 GError *error = NULL;
155 gsize len;
157 status = soup_socket_write (gtk->sock, buffer->data, buffer->length,
158 &len, NULL, &error);
159 switch (status) {
160 case SOUP_SOCKET_OK:
161 case SOUP_SOCKET_WOULD_BLOCK:
162 case SOUP_SOCKET_EOF:
163 break;
164 case SOUP_SOCKET_ERROR:
165 swfdec_stream_error (SWFDEC_STREAM (gtk), "%s", error->message);
166 g_error_free (error);
167 return 0;
168 default:
169 g_warning ("unhandled status code %u from soup_socket_read()", (guint) status);
170 break;
172 return len;
175 static void
176 swfdec_gtk_socket_dispose (GObject *object)
178 SwfdecGtkSocket *gtk = SWFDEC_GTK_SOCKET (object);
180 if (gtk->sock) {
181 g_signal_handlers_disconnect_matched (gtk->sock, G_SIGNAL_MATCH_DATA,
182 0, 0, NULL, NULL, gtk);
183 g_object_unref (gtk->sock);
184 gtk->sock = NULL;
187 G_OBJECT_CLASS (swfdec_gtk_socket_parent_class)->dispose (object);
190 static void
191 swfdec_gtk_socket_class_init (SwfdecGtkSocketClass *klass)
193 GObjectClass *object_class = G_OBJECT_CLASS (klass);
194 SwfdecStreamClass *stream_class = SWFDEC_STREAM_CLASS (klass);
195 SwfdecSocketClass *socket_class = SWFDEC_SOCKET_CLASS (klass);
197 object_class->dispose = swfdec_gtk_socket_dispose;
199 stream_class->close = swfdec_gtk_socket_close;
201 socket_class->connect = swfdec_gtk_socket_connect;
202 socket_class->send = swfdec_gtk_socket_send;
205 static void
206 swfdec_gtk_socket_init (SwfdecGtkSocket *gtk)