1.1 --- a/gmyth-stream/client/src/gmyth-stream-client.c Wed Apr 11 18:39:39 2007 +0100
1.2 +++ b/gmyth-stream/client/src/gmyth-stream-client.c Thu Apr 12 20:35:08 2007 +0100
1.3 @@ -4,65 +4,130 @@
1.4
1.5 #include <sys/types.h>
1.6 #include <sys/socket.h>
1.7 +#include <arpa/inet.h>
1.8 #include <netdb.h>
1.9 #include <netinet/in.h>
1.10 #include <unistd.h>
1.11 #include <glib.h>
1.12 #include <glib/gprintf.h>
1.13 #include <string.h>
1.14 -
1.15 +#include <stdlib.h>
1.16
1.17 #include "gmyth-stream-client.h"
1.18
1.19 +#define BUFFER_SIZE 1024
1.20
1.21 #define GMYTH_STREAM_CLIENT_GET_PRIVATE(obj) \
1.22 - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_TYPE_STREAM_CLIENT, GMythStreamClientPrivate))
1.23 + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_TYPE_STREAM_CLIENT,\
1.24 + GMythStreamClientPrivate))
1.25 +
1.26 +
1.27 +typedef struct _sock _socket;
1.28 +struct _sock
1.29 +{
1.30 + gint fd;
1.31 + struct sockaddr_in addr;
1.32 +};
1.33
1.34
1.35 typedef struct _GMythStreamClientPrivate GMythStreamClientPrivate;
1.36 -
1.37 struct _GMythStreamClientPrivate
1.38 {
1.39 - GList *streams;
1.40 - struct hostent *host;
1.41 - gint sock;
1.42 - gboolean connected;
1.43 - struct sockaddr_in addr;
1.44 + const gchar *host;
1.45 + _socket* sock;
1.46 + _socket* sock_stream;
1.47 + gboolean connected;
1.48 };
1.49
1.50 -typedef struct _StreamData StreamData;
1.51
1.52 -struct _StreamData
1.53 -{
1.54 - guint id;
1.55 - guint port;
1.56 - gint s;
1.57 -};
1.58 -
1.59 -static void gmyth_stream_client_class_init (GMythStreamClientClass *klass);
1.60 -static void gmyth_stream_client_init (GMythStreamClient *object);
1.61 -static void gmyth_stream_client_dispose (GObject *object);
1.62 -static void gmyth_stream_client_finalize (GObject *object);
1.63 -static StreamData* gmtyh_stream_client_get_streamdata (GMythStreamClient *self,
1.64 - guint stream_id);
1.65 +static void gmyth_stream_client_class_init (GMythStreamClientClass *klass);
1.66 +static void gmyth_stream_client_init (GMythStreamClient *object);
1.67 +static void gmyth_stream_client_dispose (GObject *object);
1.68 +static void gmyth_stream_client_finalize (GObject *object);
1.69
1.70
1.71 G_DEFINE_TYPE(GMythStreamClient, gmyth_stream_client, G_TYPE_OBJECT)
1.72
1.73 +
1.74 +static _socket*
1.75 +create_socket (const gchar* hostname, gint port)
1.76 +{
1.77 + _socket* sock = (_socket*)g_malloc(sizeof(_socket));
1.78 +
1.79 + sock->fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
1.80 + if (sock->fd == -1) {
1.81 + g_debug ("Fail to create sock");
1.82 + g_free(sock);
1.83 + return NULL;
1.84 + }
1.85 +
1.86 + sock->addr.sin_family = AF_INET;
1.87 + sock->addr.sin_addr.s_addr = inet_addr(hostname);
1.88 + sock->addr.sin_port = htons(port);
1.89 +
1.90 + if (connect (sock->fd, (struct sockaddr *) &(sock->addr), \
1.91 + sizeof (sock->addr)) == -1) {
1.92 + g_debug ("Fail to connect with server");
1.93 + g_free(sock);
1.94 + return NULL;
1.95 + }
1.96 +
1.97 + return sock;
1.98 +}
1.99 +
1.100 +static gint
1.101 +read_message (int socket)
1.102 +{
1.103 + gint64 total_read = 0;
1.104 + gint result = -1;
1.105 + gchar buffer[BUFFER_SIZE];
1.106 + gchar** response;
1.107 +
1.108 + total_read = recv(socket, buffer, BUFFER_SIZE, 0);
1.109 +
1.110 + if (total_read > 0) {
1.111 + response = g_strsplit_set(buffer, " +\n", 8);
1.112 +
1.113 + if ( g_ascii_strcasecmp(response[0], "OK") == 0 ) {
1.114 +
1.115 + int payload = atoi(response[1]);
1.116 +
1.117 + if (payload == 0)
1.118 + result = 0;
1.119 +
1.120 + else if (payload == 1) {
1.121 + total_read = recv(socket, buffer, BUFFER_SIZE, 0);
1.122 +
1.123 + response = g_strsplit_set(buffer, "+\n", 8);
1.124 + result = atoi(response[1]);
1.125 + }
1.126 +
1.127 + }
1.128 +
1.129 + g_strfreev(response);
1.130 + }
1.131 +
1.132 + return result;
1.133 +}
1.134 +
1.135 +
1.136 static void
1.137 gmyth_stream_client_class_init (GMythStreamClientClass *klass)
1.138 {
1.139 - GObjectClass *gobject_class;
1.140 - gobject_class = (GObjectClass *) klass;
1.141 + GObjectClass *gobject_class;
1.142 + gobject_class = (GObjectClass *) klass;
1.143
1.144 - g_type_class_add_private (klass, sizeof (GMythStreamClientPrivate));
1.145 - gobject_class->dispose = gmyth_stream_client_dispose;
1.146 - gobject_class->finalize = gmyth_stream_client_finalize;
1.147 + g_type_class_add_private (klass, sizeof (GMythStreamClientPrivate));
1.148 + gobject_class->dispose = gmyth_stream_client_dispose;
1.149 + gobject_class->finalize = gmyth_stream_client_finalize;
1.150 }
1.151
1.152 static void
1.153 gmyth_stream_client_init (GMythStreamClient *self)
1.154 {
1.155 + GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.156 + priv->sock = NULL;
1.157 + priv->sock_stream = NULL;
1.158 }
1.159
1.160 static void
1.161 @@ -80,33 +145,18 @@
1.162 GMythStreamClient*
1.163 gmyth_stream_client_new ()
1.164 {
1.165 - return GMYTH_STREAM_CLIENT (g_object_new (GMYTH_TYPE_STREAM_CLIENT, NULL));
1.166 + return GMYTH_STREAM_CLIENT (g_object_new (GMYTH_TYPE_STREAM_CLIENT, NULL));
1.167 }
1.168
1.169 gboolean
1.170 gmyth_stream_client_connect (GMythStreamClient *self, const gchar *server, guint port)
1.171 {
1.172 - GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.173 - g_return_val_if_fail (priv->connected == FALSE, TRUE);
1.174 + GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.175 + g_return_val_if_fail (priv->connected == FALSE, TRUE);
1.176
1.177 - priv->sock = socket (PF_INET, SOCK_STREAM, 0);
1.178 - if (priv->sock == -1) {
1.179 - g_debug ("Fail to create sock");
1.180 - return FALSE;
1.181 - }
1.182 -
1.183 - memset(&(priv->addr), 0, sizeof(priv->addr));
1.184 - priv->host = gethostbyname(server);
1.185 - memcpy(&(priv->addr), *(priv->host->h_addr_list), sizeof(struct in_addr));
1.186 - priv->addr.sin_family = AF_INET;
1.187 - priv->addr.sin_port = htons (port);
1.188 -
1.189 - if (connect (priv->sock, (struct sockaddr *) &(priv->addr), sizeof (priv->addr)) == -1) {
1.190 - g_debug ("Fail to connect with server");
1.191 - shutdown (priv->sock, SHUT_RDWR);
1.192 - priv->sock = -1;
1.193 - return FALSE;
1.194 - }
1.195 + priv->host = server;
1.196 + priv->sock = create_socket (server, port);
1.197 + if (priv->sock == NULL) return FALSE;
1.198
1.199 priv->connected = TRUE;
1.200 return TRUE;
1.201 @@ -117,146 +167,85 @@
1.202 {
1.203 GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.204
1.205 - g_return_if_fail (priv->connected == FALSE);
1.206 + g_return_if_fail (priv->connected == TRUE);
1.207
1.208 - GList *lst = priv->streams;
1.209 -
1.210 - for (; lst != NULL; lst = lst->next) {
1.211 - StreamData *data = (StreamData *) lst->data;
1.212 - gmyth_stream_client_close_stream (self, data->id);
1.213 - }
1.214 -
1.215 - close (priv->sock);
1.216 - shutdown (priv->sock, SHUT_RDWR);
1.217 - priv->sock = -1;
1.218 + close (priv->sock->fd);
1.219 + //shutdown (priv->sock->fd, SHUT_RDWR);
1.220 + priv->sock->fd = -1;
1.221 priv->connected = FALSE;
1.222 }
1.223
1.224 -guint
1.225 +gint
1.226 gmyth_stream_client_open_stream (GMythStreamClient *self,
1.227 - const gchar* file_name,
1.228 - const gchar* mux,
1.229 - const gchar* vcodec,
1.230 - guint vbitrate,
1.231 - gdouble fps,
1.232 - const gchar* acodec,
1.233 - guint abitrate,
1.234 - guint width, guint height,
1.235 - guint port,
1.236 - const gchar* opt)
1.237 + const gchar* file_name,
1.238 + const gchar* mux,
1.239 + const gchar* vcodec,
1.240 + guint vbitrate,
1.241 + gdouble fps,
1.242 + const gchar* acodec,
1.243 + guint abitrate,
1.244 + guint width, guint height,
1.245 + const gchar* opt)
1.246 {
1.247 - gchar *cmd;
1.248 - StreamData *data = NULL;
1.249 - GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.250 + gchar *cmd;
1.251 + GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.252
1.253 - g_return_val_if_fail (priv->connected == TRUE, FALSE);
1.254 - g_return_val_if_fail (file_name != NULL, FALSE);
1.255 + g_return_val_if_fail (priv->connected == TRUE, FALSE);
1.256 + g_return_val_if_fail (file_name != NULL, FALSE);
1.257
1.258 - cmd = g_strdup_printf ("SETUP %s %s %s %d %f %s %d %d %d %d %s\n",
1.259 - file_name,
1.260 - (mux == NULL? "X" : mux),
1.261 - (vcodec == NULL ? "X" : vcodec),
1.262 - vbitrate,
1.263 - fps,
1.264 - (acodec == NULL ? "X" : acodec),
1.265 - abitrate,
1.266 - width, height, port,
1.267 - (opt == NULL ? "X" : opt));
1.268 + cmd = g_strdup_printf ("SETUP %s %s %s %d %f %s %d %d %d %s\n",
1.269 + file_name,
1.270 + (mux == NULL ? "X" : mux),
1.271 + (vcodec == NULL ? "X" : vcodec),
1.272 + vbitrate,
1.273 + fps,
1.274 + (acodec == NULL ? "X" : acodec),
1.275 + abitrate,
1.276 + width, height,
1.277 + (opt == NULL ? "X" : opt) );
1.278
1.279 - if (send (priv->sock, cmd, strlen (cmd), MSG_CONFIRM) == -1) {
1.280 - g_free (cmd);
1.281 - return -1;
1.282 - }
1.283 - g_free (cmd);
1.284 + if (send (priv->sock->fd, cmd, strlen (cmd), MSG_CONFIRM) == -1) {
1.285 + g_free (cmd);
1.286 + return -1;
1.287 + }
1.288 + g_free (cmd);
1.289
1.290 + read_message(priv->sock->fd);
1.291
1.292 - data = g_new0 (StreamData, 1);
1.293 - data->port = port;
1.294 - data->id = data->s = socket (PF_INET, SOCK_STREAM, 0);
1.295 -
1.296 -
1.297 - priv->streams = g_list_append (priv->streams, data);
1.298 - return data->id;
1.299 + return 0;
1.300 }
1.301
1.302 -static gchar**
1.303 -_parse_return (int fd)
1.304 +
1.305 +gint
1.306 +gmyth_stream_client_play_stream (GMythStreamClient *self)
1.307 {
1.308 + GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.309
1.310 -}
1.311 + g_return_val_if_fail (priv->connected == TRUE, FALSE);
1.312
1.313 -gboolean
1.314 -gmyth_stream_client_play_stream (GMythStreamClient *self,
1.315 - guint stream_id)
1.316 -{
1.317 - GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.318 - StreamData *data;
1.319 - struct sockaddr_in addr;
1.320 - gchar **retval;
1.321 + if (send (priv->sock->fd, "PLAY\n", 5, 0) == -1) {
1.322 + return -1;
1.323 + }
1.324
1.325 - g_return_val_if_fail (priv->connected == TRUE, FALSE);
1.326 + gint port = read_message(priv->sock->fd);
1.327 + priv->sock_stream = create_socket(priv->host, port);
1.328
1.329 - data = gmtyh_stream_client_get_streamdata (self, stream_id);
1.330 - g_return_val_if_fail (data != NULL, FALSE);
1.331 -
1.332 - if (send (priv->sock, "PLAY\n", 5, MSG_MORE) == -1) {
1.333 - return FALSE;
1.334 - }
1.335 -
1.336 - retval = _read_message (priv->sock);
1.337 -
1.338 - g_usleep (10 * G_USEC_PER_SEC);
1.339 -
1.340 - memset(&addr, 0, sizeof(addr));
1.341 - memcpy(&addr, *(priv->host->h_addr_list), sizeof(struct in_addr));
1.342 - addr.sin_family = AF_INET;
1.343 - addr.sin_port = htons (data->port);
1.344 - g_debug ("request connection on port %d", data->port);
1.345 - if (connect(data->s,(struct sockaddr*) &addr, sizeof(addr)) == -1)
1.346 - g_warning ("Fail to connect to server");
1.347 -
1.348 - return TRUE;
1.349 + return priv->sock_stream->fd;
1.350 }
1.351
1.352 void
1.353 -gmyth_stream_client_pause_stream (GMythStreamClient *self,
1.354 - guint stream_id)
1.355 +gmyth_stream_client_close_stream (GMythStreamClient *self)
1.356 {
1.357 - GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.358 + GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.359 + g_return_if_fail (priv->connected == TRUE);
1.360
1.361 - g_return_if_fail (priv->connected == TRUE);
1.362 + if (send (priv->sock->fd, "STOP\n", 5, 0) == -1) {
1.363 + return;
1.364 + }
1.365
1.366 - if (send (priv->sock, "PAUSE\n", 6, MSG_MORE) == -1) {
1.367 - return;
1.368 - }
1.369 + read_message(priv->sock->fd);
1.370 +
1.371 + close(priv->sock_stream->fd);
1.372 + g_free(priv->sock_stream);
1.373 + priv->sock_stream = NULL;
1.374 }
1.375 -
1.376 -void
1.377 -gmyth_stream_client_close_stream (GMythStreamClient *self,
1.378 - guint stream_id)
1.379 -{
1.380 - GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.381 -
1.382 - g_return_if_fail (priv->connected == TRUE);
1.383 - if (send (priv->sock, "STOP\n", 5, MSG_MORE) == -1) {
1.384 - return;
1.385 - }
1.386 - //TODO: remove from streams list
1.387 -}
1.388 -
1.389 -static StreamData*
1.390 -gmtyh_stream_client_get_streamdata (GMythStreamClient *self,
1.391 - guint stream_id)
1.392 -{
1.393 - GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
1.394 - GList *lst;
1.395 -
1.396 - lst = priv->streams;
1.397 - for (; lst != NULL; lst = lst->next) {
1.398 - StreamData *data = (StreamData *) lst->data;
1.399 - if (data->id == stream_id) {
1.400 - return data;
1.401 - }
1.402 - }
1.403 - return NULL;
1.404 -}