#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include "gmyth-stream-client.h" #define GMYTH_STREAM_CLIENT_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_TYPE_STREAM_CLIENT, GMythStreamClientPrivate)) typedef struct _GMythStreamClientPrivate GMythStreamClientPrivate; struct _GMythStreamClientPrivate { GList *streams; struct hostent *host; gint sock; gboolean connected; struct sockaddr_in addr; }; typedef struct _StreamData StreamData; struct _StreamData { guint id; guint port; gint s; }; static void gmyth_stream_client_class_init (GMythStreamClientClass *klass); static void gmyth_stream_client_init (GMythStreamClient *object); static void gmyth_stream_client_dispose (GObject *object); static void gmyth_stream_client_finalize (GObject *object); static StreamData* gmtyh_stream_client_get_streamdata (GMythStreamClient *self, guint stream_id); G_DEFINE_TYPE(GMythStreamClient, gmyth_stream_client, G_TYPE_OBJECT) static void gmyth_stream_client_class_init (GMythStreamClientClass *klass) { GObjectClass *gobject_class; gobject_class = (GObjectClass *) klass; g_type_class_add_private (klass, sizeof (GMythStreamClientPrivate)); gobject_class->dispose = gmyth_stream_client_dispose; gobject_class->finalize = gmyth_stream_client_finalize; } static void gmyth_stream_client_init (GMythStreamClient *self) { } static void gmyth_stream_client_dispose (GObject *object) { gmyth_stream_client_disconnect (GMYTH_STREAM_CLIENT (object)); } static void gmyth_stream_client_finalize (GObject *object) { } GMythStreamClient* gmyth_stream_client_new () { return GMYTH_STREAM_CLIENT (g_object_new (GMYTH_TYPE_STREAM_CLIENT, NULL)); } gboolean gmyth_stream_client_connect (GMythStreamClient *self, const gchar *server, guint port) { GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); g_return_val_if_fail (priv->connected == FALSE, TRUE); priv->sock = socket (PF_INET, SOCK_STREAM, 0); if (priv->sock == -1) { g_debug ("Fail to create sock"); return FALSE; } memset(&(priv->addr), 0, sizeof(priv->addr)); priv->host = gethostbyname(server); memcpy(&(priv->addr), *(priv->host->h_addr_list), sizeof(struct in_addr)); priv->addr.sin_family = AF_INET; priv->addr.sin_port = htons (port); if (connect (priv->sock, (struct sockaddr *) &(priv->addr), sizeof (priv->addr)) == -1) { g_debug ("Fail to connect with server"); shutdown (priv->sock, SHUT_RDWR); priv->sock = -1; return FALSE; } priv->connected = TRUE; return TRUE; } void gmyth_stream_client_disconnect (GMythStreamClient *self) { GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); g_return_if_fail (priv->connected == FALSE); GList *lst = priv->streams; for (; lst != NULL; lst = lst->next) { StreamData *data = (StreamData *) lst->data; gmyth_stream_client_close_stream (self, data->id); } close (priv->sock); shutdown (priv->sock, SHUT_RDWR); priv->sock = -1; priv->connected = FALSE; } guint gmyth_stream_client_open_stream (GMythStreamClient *self, const gchar* file_name, const gchar* mux, const gchar* vcodec, guint vbitrate, gdouble fps, const gchar* acodec, guint abitrate, guint width, guint height, guint port, const gchar* opt) { gchar *cmd; StreamData *data = NULL; GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); g_return_val_if_fail (priv->connected == TRUE, FALSE); g_return_val_if_fail (file_name != NULL, FALSE); cmd = g_strdup_printf ("SETUP %s %s %s %d %f %s %d %d %d %d %s\n", file_name, (mux == NULL? "X" : mux), (vcodec == NULL ? "X" : vcodec), vbitrate, fps, (acodec == NULL ? "X" : acodec), abitrate, width, height, port, (opt == NULL ? "X" : opt)); if (send (priv->sock, cmd, strlen (cmd), MSG_CONFIRM) == -1) { g_free (cmd); return -1; } g_free (cmd); data = g_new0 (StreamData, 1); data->port = port; data->id = data->s = socket (PF_INET, SOCK_STREAM, 0); priv->streams = g_list_append (priv->streams, data); return data->id; } static gchar** _parse_return (int fd) { } gboolean gmyth_stream_client_play_stream (GMythStreamClient *self, guint stream_id) { GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); StreamData *data; struct sockaddr_in addr; gchar **retval; g_return_val_if_fail (priv->connected == TRUE, FALSE); data = gmtyh_stream_client_get_streamdata (self, stream_id); g_return_val_if_fail (data != NULL, FALSE); if (send (priv->sock, "PLAY\n", 5, MSG_MORE) == -1) { return FALSE; } retval = _read_message (priv->sock); g_usleep (10 * G_USEC_PER_SEC); memset(&addr, 0, sizeof(addr)); memcpy(&addr, *(priv->host->h_addr_list), sizeof(struct in_addr)); addr.sin_family = AF_INET; addr.sin_port = htons (data->port); g_debug ("request connection on port %d", data->port); if (connect(data->s,(struct sockaddr*) &addr, sizeof(addr)) == -1) g_warning ("Fail to connect to server"); return TRUE; } void gmyth_stream_client_pause_stream (GMythStreamClient *self, guint stream_id) { GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); g_return_if_fail (priv->connected == TRUE); if (send (priv->sock, "PAUSE\n", 6, MSG_MORE) == -1) { return; } } void gmyth_stream_client_close_stream (GMythStreamClient *self, guint stream_id) { GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); g_return_if_fail (priv->connected == TRUE); if (send (priv->sock, "STOP\n", 5, MSG_MORE) == -1) { return; } //TODO: remove from streams list } static StreamData* gmtyh_stream_client_get_streamdata (GMythStreamClient *self, guint stream_id) { GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self); GList *lst; lst = priv->streams; for (; lst != NULL; lst = lst->next) { StreamData *data = (StreamData *) lst->data; if (data->id == stream_id) { return data; } } return NULL; }