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