renatofilho@487: #ifdef HAVE_CONFIG_H renatofilho@487: #include "config.h" renatofilho@487: #endif renatofilho@487: renatofilho@487: #include renatofilho@487: #include morphbr@534: #include renatofilho@487: #include renatofilho@487: #include renatofilho@487: #include renatofilho@487: #include renatofilho@487: #include renatofilho@487: #include morphbr@534: #include renatofilho@520: renatofilho@487: #include "gmyth-stream-client.h" renatofilho@487: morphbr@534: #define BUFFER_SIZE 1024 renatofilho@487: renatofilho@487: #define GMYTH_STREAM_CLIENT_GET_PRIVATE(obj) \ morphbr@534: (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_TYPE_STREAM_CLIENT,\ morphbr@534: GMythStreamClientPrivate)) morphbr@534: morphbr@534: morphbr@534: typedef struct _sock _socket; morphbr@534: struct _sock morphbr@534: { morphbr@534: gint fd; morphbr@534: struct sockaddr_in addr; morphbr@534: }; renatofilho@487: renatofilho@487: renatofilho@487: typedef struct _GMythStreamClientPrivate GMythStreamClientPrivate; renatofilho@487: struct _GMythStreamClientPrivate renatofilho@487: { morphbr@534: const gchar *host; morphbr@534: _socket* sock; morphbr@534: _socket* sock_stream; morphbr@534: gboolean connected; renatofilho@487: }; renatofilho@487: renatofilho@487: morphbr@534: static void gmyth_stream_client_class_init (GMythStreamClientClass *klass); morphbr@534: static void gmyth_stream_client_init (GMythStreamClient *object); morphbr@534: static void gmyth_stream_client_dispose (GObject *object); morphbr@534: static void gmyth_stream_client_finalize (GObject *object); renatofilho@520: renatofilho@487: renatofilho@487: G_DEFINE_TYPE(GMythStreamClient, gmyth_stream_client, G_TYPE_OBJECT) renatofilho@487: morphbr@534: morphbr@534: static _socket* morphbr@534: create_socket (const gchar* hostname, gint port) morphbr@534: { morphbr@534: _socket* sock = (_socket*)g_malloc(sizeof(_socket)); morphbr@534: morphbr@534: sock->fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); morphbr@534: if (sock->fd == -1) { morphbr@534: g_debug ("Fail to create sock"); morphbr@534: g_free(sock); morphbr@534: return NULL; morphbr@534: } morphbr@534: morphbr@534: sock->addr.sin_family = AF_INET; morphbr@534: sock->addr.sin_addr.s_addr = inet_addr(hostname); morphbr@534: sock->addr.sin_port = htons(port); morphbr@534: morphbr@534: if (connect (sock->fd, (struct sockaddr *) &(sock->addr), \ morphbr@534: sizeof (sock->addr)) == -1) { morphbr@534: g_debug ("Fail to connect with server"); morphbr@534: g_free(sock); morphbr@534: return NULL; morphbr@534: } morphbr@534: morphbr@534: return sock; morphbr@534: } morphbr@534: morphbr@534: static gint morphbr@534: read_message (int socket) morphbr@534: { morphbr@534: gint64 total_read = 0; morphbr@534: gint result = -1; morphbr@534: gchar buffer[BUFFER_SIZE]; morphbr@534: gchar** response; morphbr@534: morphbr@534: total_read = recv(socket, buffer, BUFFER_SIZE, 0); morphbr@534: morphbr@534: if (total_read > 0) { morphbr@534: response = g_strsplit_set(buffer, " +\n", 8); morphbr@534: morphbr@534: if ( g_ascii_strcasecmp(response[0], "OK") == 0 ) { morphbr@534: morphbr@534: int payload = atoi(response[1]); morphbr@534: morphbr@534: if (payload == 0) morphbr@534: result = 0; morphbr@534: morphbr@534: else if (payload == 1) { morphbr@534: total_read = recv(socket, buffer, BUFFER_SIZE, 0); morphbr@534: morphbr@534: response = g_strsplit_set(buffer, "+\n", 8); morphbr@534: result = atoi(response[1]); morphbr@534: } morphbr@534: morphbr@534: } morphbr@534: morphbr@534: g_strfreev(response); morphbr@534: } morphbr@534: morphbr@534: return result; morphbr@534: } morphbr@534: morphbr@534: renatofilho@487: static void renatofilho@487: gmyth_stream_client_class_init (GMythStreamClientClass *klass) renatofilho@520: { morphbr@534: GObjectClass *gobject_class; morphbr@534: gobject_class = (GObjectClass *) klass; renatofilho@487: morphbr@534: g_type_class_add_private (klass, sizeof (GMythStreamClientPrivate)); morphbr@534: gobject_class->dispose = gmyth_stream_client_dispose; morphbr@534: gobject_class->finalize = gmyth_stream_client_finalize; renatofilho@487: } renatofilho@487: renatofilho@487: static void renatofilho@487: gmyth_stream_client_init (GMythStreamClient *self) renatofilho@487: { morphbr@534: GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); morphbr@534: priv->sock = NULL; morphbr@534: priv->sock_stream = NULL; renatofilho@487: } renatofilho@487: renatofilho@520: static void renatofilho@487: gmyth_stream_client_dispose (GObject *object) renatofilho@487: { renatofilho@487: gmyth_stream_client_disconnect (GMYTH_STREAM_CLIENT (object)); renatofilho@487: } renatofilho@487: renatofilho@487: renatofilho@520: static void renatofilho@487: gmyth_stream_client_finalize (GObject *object) renatofilho@487: { renatofilho@487: } renatofilho@487: renatofilho@520: GMythStreamClient* renatofilho@520: gmyth_stream_client_new () renatofilho@487: { morphbr@534: return GMYTH_STREAM_CLIENT (g_object_new (GMYTH_TYPE_STREAM_CLIENT, NULL)); renatofilho@487: } renatofilho@487: renatofilho@487: gboolean renatofilho@487: gmyth_stream_client_connect (GMythStreamClient *self, const gchar *server, guint port) renatofilho@487: { morphbr@534: GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); morphbr@534: g_return_val_if_fail (priv->connected == FALSE, TRUE); renatofilho@487: morphbr@534: priv->host = server; morphbr@534: priv->sock = create_socket (server, port); morphbr@534: if (priv->sock == NULL) return FALSE; renatofilho@487: renatofilho@487: priv->connected = TRUE; renatofilho@487: return TRUE; renatofilho@487: } renatofilho@487: renatofilho@487: void renatofilho@487: gmyth_stream_client_disconnect (GMythStreamClient *self) renatofilho@487: { renatofilho@487: GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); renatofilho@520: morphbr@534: g_return_if_fail (priv->connected == TRUE); renatofilho@487: morphbr@534: close (priv->sock->fd); morphbr@534: //shutdown (priv->sock->fd, SHUT_RDWR); morphbr@534: priv->sock->fd = -1; renatofilho@520: priv->connected = FALSE; renatofilho@487: } renatofilho@487: morphbr@534: gint renatofilho@487: gmyth_stream_client_open_stream (GMythStreamClient *self, morphbr@534: const gchar* file_name, morphbr@534: const gchar* mux, morphbr@534: const gchar* vcodec, morphbr@534: guint vbitrate, morphbr@534: gdouble fps, morphbr@534: const gchar* acodec, morphbr@534: guint abitrate, morphbr@534: guint width, guint height, morphbr@534: const gchar* opt) renatofilho@487: { morphbr@534: gchar *cmd; morphbr@534: GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); renatofilho@520: morphbr@534: g_return_val_if_fail (priv->connected == TRUE, FALSE); morphbr@534: g_return_val_if_fail (file_name != NULL, FALSE); renatofilho@487: morphbr@534: cmd = g_strdup_printf ("SETUP %s %s %s %d %f %s %d %d %d %s\n", morphbr@534: file_name, morphbr@534: (mux == NULL ? "X" : mux), morphbr@534: (vcodec == NULL ? "X" : vcodec), morphbr@534: vbitrate, morphbr@534: fps, morphbr@534: (acodec == NULL ? "X" : acodec), morphbr@534: abitrate, morphbr@534: width, height, morphbr@534: (opt == NULL ? "X" : opt) ); renatofilho@520: morphbr@534: if (send (priv->sock->fd, cmd, strlen (cmd), MSG_CONFIRM) == -1) { morphbr@534: g_free (cmd); morphbr@534: return -1; morphbr@534: } morphbr@534: g_free (cmd); renatofilho@487: morphbr@534: read_message(priv->sock->fd); renatofilho@520: morphbr@534: return 0; renatofilho@520: } renatofilho@520: morphbr@534: morphbr@534: gint morphbr@534: gmyth_stream_client_play_stream (GMythStreamClient *self) renatofilho@520: { morphbr@534: GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); renatofilho@520: morphbr@534: g_return_val_if_fail (priv->connected == TRUE, FALSE); renatofilho@487: morphbr@534: if (send (priv->sock->fd, "PLAY\n", 5, 0) == -1) { morphbr@534: return -1; morphbr@534: } renatofilho@520: morphbr@534: gint port = read_message(priv->sock->fd); morphbr@534: priv->sock_stream = create_socket(priv->host, port); renatofilho@520: morphbr@534: return priv->sock_stream->fd; renatofilho@520: } renatofilho@487: renatofilho@487: void morphbr@534: gmyth_stream_client_close_stream (GMythStreamClient *self) renatofilho@487: { morphbr@534: GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); morphbr@534: g_return_if_fail (priv->connected == TRUE); renatofilho@520: morphbr@534: if (send (priv->sock->fd, "STOP\n", 5, 0) == -1) { morphbr@534: return; morphbr@534: } renatofilho@520: morphbr@534: read_message(priv->sock->fd); morphbr@534: morphbr@534: close(priv->sock_stream->fd); morphbr@534: g_free(priv->sock_stream); morphbr@534: priv->sock_stream = NULL; renatofilho@487: }