gmyth-stream/client/src/gmyth-stream-client.c
branchtrunk
changeset 553 424babd6b788
parent 520 92acf23b87f0
child 569 644a526d4086
     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	Mon Apr 16 16:02:22 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 -}