gmyth-stream/client/src/gmyth-stream-client.c
author melunko
Wed May 16 17:04:46 2007 +0100 (2007-05-16)
branchtrunk
changeset 670 85d9b58f86b0
parent 534 cb1c3e2988b9
permissions -rw-r--r--
[svn r676] new file transfer flag fixed
renatofilho@487
     1
#ifdef HAVE_CONFIG_H
renatofilho@487
     2
#include "config.h"
renatofilho@487
     3
#endif
renatofilho@487
     4
renatofilho@487
     5
#include <sys/types.h>
renatofilho@487
     6
#include <sys/socket.h>
morphbr@534
     7
#include <arpa/inet.h>
renatofilho@487
     8
#include <netdb.h>
renatofilho@487
     9
#include <netinet/in.h>
renatofilho@487
    10
#include <unistd.h>
renatofilho@487
    11
#include <glib.h>
renatofilho@487
    12
#include <glib/gprintf.h>
renatofilho@487
    13
#include <string.h>
morphbr@534
    14
#include <stdlib.h>
renatofilho@520
    15
renatofilho@487
    16
#include "gmyth-stream-client.h"
renatofilho@487
    17
morphbr@534
    18
#define BUFFER_SIZE 1024
renatofilho@487
    19
renatofilho@487
    20
#define GMYTH_STREAM_CLIENT_GET_PRIVATE(obj) \
morphbr@534
    21
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_TYPE_STREAM_CLIENT,\
morphbr@534
    22
 GMythStreamClientPrivate))
morphbr@534
    23
morphbr@534
    24
morphbr@534
    25
typedef struct _sock _socket;
morphbr@534
    26
struct _sock
morphbr@534
    27
{
morphbr@534
    28
    gint fd;
morphbr@534
    29
    struct sockaddr_in addr;
morphbr@534
    30
};
renatofilho@487
    31
renatofilho@487
    32
renatofilho@487
    33
typedef struct _GMythStreamClientPrivate GMythStreamClientPrivate;
renatofilho@487
    34
struct _GMythStreamClientPrivate
renatofilho@487
    35
{
morphbr@534
    36
    const gchar *host;
morphbr@534
    37
    _socket* sock;
morphbr@534
    38
    _socket* sock_stream;
morphbr@534
    39
    gboolean connected;
renatofilho@487
    40
};
renatofilho@487
    41
renatofilho@487
    42
morphbr@534
    43
static void gmyth_stream_client_class_init (GMythStreamClientClass *klass);
morphbr@534
    44
static void gmyth_stream_client_init	   (GMythStreamClient *object);
morphbr@534
    45
static void gmyth_stream_client_dispose    (GObject *object);
morphbr@534
    46
static void gmyth_stream_client_finalize   (GObject *object);
renatofilho@520
    47
renatofilho@487
    48
renatofilho@487
    49
G_DEFINE_TYPE(GMythStreamClient, gmyth_stream_client, G_TYPE_OBJECT)
renatofilho@487
    50
morphbr@534
    51
morphbr@534
    52
static _socket*
morphbr@534
    53
create_socket (const gchar* hostname, gint port)
morphbr@534
    54
{
morphbr@534
    55
    _socket* sock = (_socket*)g_malloc(sizeof(_socket));
morphbr@534
    56
morphbr@534
    57
    sock->fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
morphbr@534
    58
    if (sock->fd == -1) {
morphbr@534
    59
        g_debug ("Fail to create sock");
morphbr@534
    60
        g_free(sock);
morphbr@534
    61
        return NULL;
morphbr@534
    62
    }
morphbr@534
    63
morphbr@534
    64
    sock->addr.sin_family = AF_INET;
morphbr@534
    65
    sock->addr.sin_addr.s_addr = inet_addr(hostname);
morphbr@534
    66
    sock->addr.sin_port = htons(port);
morphbr@534
    67
morphbr@534
    68
    if (connect (sock->fd, (struct sockaddr *) &(sock->addr), \
morphbr@534
    69
                 sizeof (sock->addr)) == -1) {
morphbr@534
    70
        g_debug ("Fail to connect with server");
morphbr@534
    71
        g_free(sock);
morphbr@534
    72
        return NULL;
morphbr@534
    73
    }
morphbr@534
    74
morphbr@534
    75
    return sock;
morphbr@534
    76
}
morphbr@534
    77
morphbr@534
    78
static gint
morphbr@534
    79
read_message (int socket)
morphbr@534
    80
{
morphbr@534
    81
    gint64 total_read = 0;
morphbr@534
    82
    gint result = -1;
morphbr@534
    83
    gchar buffer[BUFFER_SIZE];
morphbr@534
    84
    gchar** response;
morphbr@534
    85
morphbr@534
    86
    total_read = recv(socket, buffer, BUFFER_SIZE, 0);
morphbr@534
    87
morphbr@534
    88
    if (total_read > 0) {
morphbr@534
    89
        response = g_strsplit_set(buffer, " +\n", 8);
morphbr@534
    90
morphbr@534
    91
        if ( g_ascii_strcasecmp(response[0], "OK") == 0 ) {
morphbr@534
    92
morphbr@534
    93
            int payload = atoi(response[1]);
morphbr@534
    94
morphbr@534
    95
            if (payload == 0)
morphbr@534
    96
                result = 0;
morphbr@534
    97
morphbr@534
    98
            else if (payload == 1) {
morphbr@534
    99
                total_read = recv(socket, buffer, BUFFER_SIZE, 0);
morphbr@534
   100
morphbr@534
   101
                response = g_strsplit_set(buffer, "+\n", 8);
morphbr@534
   102
                result = atoi(response[1]);
morphbr@534
   103
            }
morphbr@534
   104
morphbr@534
   105
        }
morphbr@534
   106
morphbr@534
   107
        g_strfreev(response);
morphbr@534
   108
    }
morphbr@534
   109
morphbr@534
   110
    return result;
morphbr@534
   111
}
morphbr@534
   112
morphbr@534
   113
renatofilho@487
   114
static void
renatofilho@487
   115
gmyth_stream_client_class_init (GMythStreamClientClass *klass)
renatofilho@520
   116
{
morphbr@534
   117
    GObjectClass *gobject_class;
morphbr@534
   118
    gobject_class = (GObjectClass *) klass;
renatofilho@487
   119
morphbr@534
   120
    g_type_class_add_private (klass, sizeof (GMythStreamClientPrivate));
morphbr@534
   121
    gobject_class->dispose  = gmyth_stream_client_dispose;
morphbr@534
   122
    gobject_class->finalize = gmyth_stream_client_finalize;
renatofilho@487
   123
}
renatofilho@487
   124
renatofilho@487
   125
static void
renatofilho@487
   126
gmyth_stream_client_init (GMythStreamClient *self)
renatofilho@487
   127
{
morphbr@534
   128
    GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
morphbr@534
   129
    priv->sock = NULL;
morphbr@534
   130
    priv->sock_stream = NULL;
renatofilho@487
   131
}
renatofilho@487
   132
renatofilho@520
   133
static void
renatofilho@487
   134
gmyth_stream_client_dispose (GObject *object)
renatofilho@487
   135
{
renatofilho@487
   136
    gmyth_stream_client_disconnect (GMYTH_STREAM_CLIENT (object));
renatofilho@487
   137
}
renatofilho@487
   138
renatofilho@487
   139
renatofilho@520
   140
static void
renatofilho@487
   141
gmyth_stream_client_finalize (GObject *object)
renatofilho@487
   142
{
renatofilho@487
   143
}
renatofilho@487
   144
renatofilho@520
   145
GMythStreamClient*
renatofilho@520
   146
gmyth_stream_client_new ()
renatofilho@487
   147
{
morphbr@534
   148
    return GMYTH_STREAM_CLIENT (g_object_new (GMYTH_TYPE_STREAM_CLIENT, NULL));
renatofilho@487
   149
}
renatofilho@487
   150
renatofilho@487
   151
gboolean
renatofilho@487
   152
gmyth_stream_client_connect (GMythStreamClient *self, const gchar *server, guint port)
renatofilho@487
   153
{
morphbr@534
   154
    GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
morphbr@534
   155
    g_return_val_if_fail (priv->connected == FALSE, TRUE);
renatofilho@487
   156
morphbr@534
   157
    priv->host = server;
morphbr@534
   158
    priv->sock = create_socket (server, port);
morphbr@534
   159
    if (priv->sock == NULL) return FALSE;
renatofilho@487
   160
renatofilho@487
   161
    priv->connected = TRUE;
renatofilho@487
   162
    return TRUE;
renatofilho@487
   163
}
renatofilho@487
   164
renatofilho@487
   165
void
renatofilho@487
   166
gmyth_stream_client_disconnect (GMythStreamClient *self)
renatofilho@487
   167
{
renatofilho@487
   168
    GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
renatofilho@520
   169
morphbr@534
   170
    g_return_if_fail (priv->connected == TRUE);
renatofilho@487
   171
morphbr@534
   172
    close (priv->sock->fd);
morphbr@534
   173
    //shutdown (priv->sock->fd, SHUT_RDWR);
morphbr@569
   174
    g_free(priv->sock);
morphbr@569
   175
    priv->sock = NULL;
renatofilho@520
   176
    priv->connected = FALSE;
renatofilho@487
   177
}
renatofilho@487
   178
morphbr@534
   179
gint
renatofilho@487
   180
gmyth_stream_client_open_stream (GMythStreamClient *self,
morphbr@534
   181
                                 const gchar* file_name,
morphbr@534
   182
                                 const gchar* mux,
morphbr@534
   183
                                 const gchar* vcodec,
morphbr@534
   184
                                 guint vbitrate,
morphbr@534
   185
                                 gdouble fps,
morphbr@534
   186
                                 const gchar* acodec,
morphbr@534
   187
                                 guint abitrate,
morphbr@534
   188
                                 guint width, guint height,
morphbr@534
   189
                                 const gchar* opt)
renatofilho@487
   190
{
morphbr@534
   191
    gchar *cmd;
morphbr@534
   192
    GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
renatofilho@520
   193
morphbr@534
   194
    g_return_val_if_fail (priv->connected == TRUE, FALSE);
morphbr@534
   195
    g_return_val_if_fail (file_name != NULL, FALSE);
renatofilho@487
   196
morphbr@534
   197
    cmd = g_strdup_printf ("SETUP %s %s %s %d %f %s %d %d %d %s\n",
morphbr@534
   198
                           file_name,
morphbr@534
   199
                           (mux == NULL ? "X" : mux),
morphbr@534
   200
                           (vcodec == NULL ? "X" : vcodec),
morphbr@534
   201
                           vbitrate,
morphbr@534
   202
                           fps,
morphbr@534
   203
                           (acodec == NULL ? "X" : acodec),
morphbr@534
   204
                           abitrate,
morphbr@534
   205
                           width, height,
morphbr@534
   206
                           (opt == NULL ? "X" : opt) );
renatofilho@520
   207
morphbr@534
   208
    if (send (priv->sock->fd, cmd, strlen (cmd), MSG_CONFIRM) == -1) {
morphbr@534
   209
        g_free (cmd);
morphbr@534
   210
        return -1;
morphbr@534
   211
    }
morphbr@534
   212
    g_free (cmd);
renatofilho@487
   213
morphbr@534
   214
    read_message(priv->sock->fd);
renatofilho@520
   215
morphbr@534
   216
    return 0;
renatofilho@520
   217
}
renatofilho@520
   218
morphbr@534
   219
morphbr@534
   220
gint
morphbr@534
   221
gmyth_stream_client_play_stream (GMythStreamClient *self)
renatofilho@520
   222
{
morphbr@534
   223
    GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
renatofilho@520
   224
morphbr@534
   225
    g_return_val_if_fail (priv->connected == TRUE, FALSE);
renatofilho@487
   226
morphbr@534
   227
    if (send (priv->sock->fd, "PLAY\n", 5, 0) == -1) {
morphbr@534
   228
        return -1;
morphbr@534
   229
    }
renatofilho@520
   230
morphbr@534
   231
    gint port = read_message(priv->sock->fd);
morphbr@534
   232
    priv->sock_stream = create_socket(priv->host, port);
renatofilho@520
   233
morphbr@534
   234
    return priv->sock_stream->fd;
renatofilho@520
   235
}
renatofilho@487
   236
renatofilho@487
   237
void
morphbr@534
   238
gmyth_stream_client_close_stream (GMythStreamClient *self)
renatofilho@487
   239
{
morphbr@534
   240
    GMythStreamClientPrivate *priv = GMYTH_STREAM_CLIENT_GET_PRIVATE (self);
morphbr@534
   241
    g_return_if_fail (priv->connected == TRUE);
renatofilho@520
   242
morphbr@534
   243
    if (send (priv->sock->fd, "STOP\n", 5, 0) == -1) {
morphbr@534
   244
        return;
morphbr@534
   245
    }
renatofilho@520
   246
morphbr@534
   247
    read_message(priv->sock->fd);
morphbr@534
   248
morphbr@534
   249
    close(priv->sock_stream->fd);
morphbr@534
   250
    g_free(priv->sock_stream);
morphbr@534
   251
    priv->sock_stream = NULL;
renatofilho@487
   252
}