gmyth-stream/libgnomevfs2/modules/gmythstream-method.c
author renatofilho
Wed Aug 15 13:33:12 2007 +0100 (2007-08-15)
branchtrunk
changeset 803 b1d0964060b3
parent 556 7dfd742a02eb
permissions -rw-r--r--
[svn r809] fixed bugs on transcode
morphbr@534
     1
/*
morphbr@534
     2
 * @author Artur Duque de Souza <souza.artur@indt.org.br>
morphbr@534
     3
 *
morphbr@534
     4
 * This program is free software; you can redistribute it and/or modify
morphbr@534
     5
 * it under the terms of the GNU Lesser General Public License as published by
morphbr@534
     6
 * the Free Software Foundation; either version 2 of the License, or
morphbr@534
     7
 * (at your option) any later version.
morphbr@534
     8
 *
morphbr@534
     9
 * This program is distributed in the hope that it will be useful,
morphbr@534
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
morphbr@534
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
morphbr@534
    12
 * GNU General Public License for more details.
morphbr@534
    13
 *
morphbr@534
    14
 m * You should have received a copy of the GNU Lesser General Public License
morphbr@534
    15
 * along with this program; if not, write to the Free Software
morphbr@534
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
morphbr@534
    17
 */
morphbr@534
    18
morphbr@534
    19
#ifdef HAVE_CONFIG_H
morphbr@534
    20
#include <config.h>
morphbr@534
    21
#endif
morphbr@534
    22
renatofilho@754
    23
#include <sys/socket.h>         /* for socket(), connect(), send(), and
renatofilho@754
    24
                                 * recv() */
renatofilho@754
    25
#include <arpa/inet.h>          /* for sockaddr_in and inet_addr() */
renatofilho@754
    26
#include <stdlib.h>             /* for atoi() and exit() */
renatofilho@754
    27
#include <string.h>             /* for memset() */
renatofilho@754
    28
#include <unistd.h>             /* for close() */
morphbr@534
    29
#include <errno.h>
morphbr@534
    30
morphbr@534
    31
#include <glib.h>
morphbr@534
    32
#include <glib/gprintf.h>
morphbr@534
    33
#include <glib/gstdio.h>
morphbr@534
    34
#include <gmyth-stream-client.h>
morphbr@534
    35
morphbr@534
    36
#include <libgnomevfs/gnome-vfs-module.h>
morphbr@534
    37
#include <libgnomevfs/gnome-vfs-utils.h>
morphbr@534
    38
morphbr@534
    39
#define BUFFER_SIZE 4096
morphbr@534
    40
morphbr@534
    41
typedef struct {
renatofilho@754
    42
    gint            port;
renatofilho@754
    43
    gchar          *hostname;
morphbr@534
    44
morphbr@534
    45
    GMythStreamClient *stream;
renatofilho@754
    46
    gint            fd;
morphbr@534
    47
} gmsHandle;
morphbr@534
    48
morphbr@534
    49
typedef struct {
renatofilho@754
    50
    gchar          *file_name;
renatofilho@754
    51
    gchar          *mux;
renatofilho@754
    52
    gchar          *vcodec;
renatofilho@754
    53
    guint           vbitrate;
renatofilho@754
    54
    gdouble         fps;
renatofilho@754
    55
    gchar          *acodec;
renatofilho@754
    56
    guint           abitrate;
renatofilho@754
    57
    guint           width;
renatofilho@754
    58
    guint           height;
renatofilho@754
    59
    guint           port;
renatofilho@754
    60
    gchar          *opt;
morphbr@534
    61
} UriArgs;
morphbr@534
    62
morphbr@534
    63
renatofilho@754
    64
static gmsHandle *gmsHandle_new(GnomeVFSURI * uri);
morphbr@534
    65
renatofilho@754
    66
static          GnomeVFSResult
renatofilho@754
    67
do_open(GnomeVFSMethod * method,
renatofilho@754
    68
        GnomeVFSMethodHandle ** method_handle,
renatofilho@754
    69
        GnomeVFSURI * uri,
renatofilho@754
    70
        GnomeVFSOpenMode mode, GnomeVFSContext * context);
morphbr@534
    71
renatofilho@754
    72
static          GnomeVFSResult
renatofilho@754
    73
do_read(GnomeVFSMethod * method,
renatofilho@754
    74
        GnomeVFSMethodHandle * method_handle,
renatofilho@754
    75
        gpointer buffer,
renatofilho@754
    76
        GnomeVFSFileSize bytes,
renatofilho@754
    77
        GnomeVFSFileSize * bytes_read, GnomeVFSContext * context);
morphbr@534
    78
renatofilho@754
    79
static          GnomeVFSResult
renatofilho@754
    80
do_close(GnomeVFSMethod * method,
renatofilho@754
    81
         GnomeVFSMethodHandle * method_handle, GnomeVFSContext * context);
morphbr@534
    82
renatofilho@754
    83
static          GnomeVFSResult
renatofilho@754
    84
do_get_file_info(GnomeVFSMethod * method,
renatofilho@754
    85
                 GnomeVFSURI * uri,
renatofilho@754
    86
                 GnomeVFSFileInfo * file_info,
renatofilho@754
    87
                 GnomeVFSFileInfoOptions options,
renatofilho@754
    88
                 GnomeVFSContext * context);
morphbr@534
    89
morphbr@534
    90
renatofilho@754
    91
static          GnomeVFSResult
renatofilho@754
    92
do_get_file_info_from_handle(GnomeVFSMethod * method,
renatofilho@754
    93
                             GnomeVFSMethodHandle * method_handle,
renatofilho@754
    94
                             GnomeVFSFileInfo * file_info,
renatofilho@754
    95
                             GnomeVFSFileInfoOptions options,
renatofilho@754
    96
                             GnomeVFSContext * context);
morphbr@534
    97
morphbr@534
    98
renatofilho@754
    99
static          gboolean
renatofilho@754
   100
do_is_local(GnomeVFSMethod * method, const GnomeVFSURI * uri);
morphbr@534
   101
morphbr@534
   102
renatofilho@754
   103
static gmsHandle *
renatofilho@754
   104
gmsHandle_new(GnomeVFSURI * uri)
morphbr@534
   105
{
renatofilho@754
   106
    gmsHandle      *handler = (gmsHandle *) g_malloc0(sizeof(gmsHandle));
morphbr@534
   107
renatofilho@754
   108
    handler->hostname = (gchar *) gnome_vfs_uri_get_host_name(uri);
morphbr@534
   109
    handler->port = gnome_vfs_uri_get_host_port(uri);
renatofilho@754
   110
    handler->stream = gmyth_stream_client_new();
morphbr@534
   111
morphbr@534
   112
    return handler;
morphbr@534
   113
}
morphbr@534
   114
morphbr@534
   115
static GnomeVFSMethod method = {
renatofilho@754
   116
    sizeof(GnomeVFSMethod),
renatofilho@754
   117
    do_open,                    /* open */
renatofilho@754
   118
    NULL,                       /* create */
renatofilho@754
   119
    do_close,                   /* close */
renatofilho@754
   120
    do_read,                    /* read */
renatofilho@754
   121
    NULL,                       /* write */
renatofilho@754
   122
    NULL,                       /* seek */
renatofilho@754
   123
    NULL,                       /* tell */
renatofilho@754
   124
    NULL,                       /* truncate_handle */
renatofilho@754
   125
    NULL,                       /* open_directory */
renatofilho@754
   126
    NULL,                       /* close_directory */
renatofilho@754
   127
    NULL,                       /* read_directory */
renatofilho@754
   128
    do_get_file_info,           /* get_file_info */
renatofilho@754
   129
    do_get_file_info_from_handle,   /* get_file_info_from_handle */
renatofilho@754
   130
    do_is_local,                /* is_local */
renatofilho@754
   131
    NULL,                       /* make_directory */
renatofilho@754
   132
    NULL,                       /* remove_directory */
renatofilho@754
   133
    NULL,                       /* move */
renatofilho@754
   134
    NULL,                       /* unlink */
renatofilho@754
   135
    NULL,                       /* check_same_fs */
renatofilho@754
   136
    NULL,                       /* set_file_info */
renatofilho@754
   137
    NULL,                       /* truncate */
renatofilho@754
   138
    NULL,                       /* find_directory */
renatofilho@754
   139
    NULL,                       /* create_symbolic_link */
renatofilho@754
   140
    NULL,                       /* monitor_add */
renatofilho@754
   141
    NULL,                       /* monitor_cancel */
renatofilho@754
   142
    NULL                        /* file_control */
morphbr@534
   143
};
morphbr@534
   144
morphbr@534
   145
GnomeVFSMethod *
renatofilho@754
   146
vfs_module_init(const char *method_name, const char *args)
morphbr@534
   147
{
morphbr@534
   148
    return &method;
morphbr@534
   149
}
morphbr@534
   150
morphbr@534
   151
void
renatofilho@754
   152
vfs_module_shutdown(GnomeVFSMethod * method)
morphbr@534
   153
{
morphbr@534
   154
    return;
morphbr@534
   155
}
morphbr@534
   156
renatofilho@754
   157
char           *
renatofilho@754
   158
_parse_opt(char *opt)
morphbr@544
   159
{
renatofilho@754
   160
    char          **list = g_strsplit(opt, "opt=", 2);
renatofilho@754
   161
    char          **opts = g_strsplit(list[1], "+", 32);
renatofilho@754
   162
    char           *value = "";
renatofilho@754
   163
    char           *aux;
renatofilho@754
   164
    gint            i = 0;
morphbr@544
   165
morphbr@544
   166
    for (aux = opts[0]; aux != NULL; aux = opts[++i])
morphbr@544
   167
        value = g_strdup_printf("%s %s", value, aux);
morphbr@544
   168
morphbr@544
   169
    g_free(aux);
morphbr@544
   170
    g_strfreev(list);
morphbr@544
   171
    g_strfreev(opts);
morphbr@544
   172
    return value;
morphbr@544
   173
}
morphbr@544
   174
morphbr@534
   175
static UriArgs *
renatofilho@754
   176
_uri_parse_args(const GnomeVFSURI * uri)
morphbr@534
   177
{
renatofilho@754
   178
    gchar          *file = gnome_vfs_unescape_string(uri->text, NULL);
renatofilho@538
   179
renatofilho@754
   180
    gchar         **list = g_strsplit(file, "\'", 3);
renatofilho@754
   181
    gchar         **prefix = g_strsplit_set(list[0], "/=", 3);
renatofilho@754
   182
    gchar         **lst = g_strsplit(list[2], "?", 0);
morphbr@544
   183
renatofilho@754
   184
    UriArgs        *info = g_new0(UriArgs, 1);
renatofilho@754
   185
    gint            i = 1;
morphbr@534
   186
renatofilho@754
   187
    gchar         **prop = NULL;
morphbr@544
   188
    prop = g_strsplit_set(lst[0], "/=", 3);
morphbr@534
   189
renatofilho@754
   190
    info->file_name = g_strdup_printf("%s://%s", prefix[1], list[1]);
morphbr@534
   191
renatofilho@754
   192
    // g_debug("FILENAME: [%s]", info->file_name);
renatofilho@538
   193
morphbr@544
   194
    g_strfreev(prop);
morphbr@544
   195
renatofilho@754
   196
    gchar          *walk;
renatofilho@754
   197
    for (walk = lst[1]; walk != NULL; walk = lst[++i]) {
morphbr@544
   198
        prop = g_strsplit(walk, "=", 2);
morphbr@534
   199
renatofilho@754
   200
        if (g_strv_length(prop) == 2) {
renatofilho@754
   201
            if (strcmp(prop[0], "mux") == 0) {
renatofilho@754
   202
                info->mux = g_strdup(prop[1]);
renatofilho@754
   203
            } else if (strcmp(prop[0], "vcodec") == 0) {
renatofilho@754
   204
                info->vcodec = g_strdup(prop[1]);
renatofilho@754
   205
            } else if (strcmp(prop[0], "vbitrate") == 0) {
renatofilho@754
   206
                info->vbitrate = atoi(prop[1]);
renatofilho@754
   207
            } else if (strcmp(prop[0], "fps") == 0) {
renatofilho@754
   208
                info->fps = g_strtod(prop[1], NULL);
renatofilho@754
   209
            } else if (strcmp(prop[0], "acodec") == 0) {
renatofilho@754
   210
                info->acodec = g_strdup(prop[1]);
renatofilho@754
   211
            } else if (strcmp(prop[0], "abitrate") == 0) {
renatofilho@754
   212
                info->abitrate = atoi(prop[1]);
renatofilho@754
   213
            } else if (strcmp(prop[0], "width") == 0) {
renatofilho@754
   214
                info->width = atoi(prop[1]);
renatofilho@754
   215
            } else if (strcmp(prop[0], "height") == 0) {
renatofilho@754
   216
                info->height = atoi(prop[1]);
renatofilho@754
   217
            } else if (strcmp(prop[0], "opt") == 0) {
renatofilho@754
   218
                info->opt = g_strdup(_parse_opt(walk));
morphbr@534
   219
            }
renatofilho@538
   220
        }
renatofilho@754
   221
        g_strfreev(prop);
morphbr@534
   222
    }
morphbr@544
   223
renatofilho@754
   224
    g_free(file);
renatofilho@754
   225
    g_strfreev(list);
renatofilho@754
   226
    g_strfreev(prefix);
renatofilho@754
   227
    g_strfreev(lst);
morphbr@534
   228
    return info;
morphbr@534
   229
}
morphbr@534
   230
renatofilho@754
   231
static          GnomeVFSResult
renatofilho@754
   232
do_open(GnomeVFSMethod * method,
renatofilho@754
   233
        GnomeVFSMethodHandle ** method_handle,
renatofilho@754
   234
        GnomeVFSURI * uri,
renatofilho@754
   235
        GnomeVFSOpenMode mode, GnomeVFSContext * context)
morphbr@534
   236
{
renatofilho@754
   237
    gmsHandle      *handle = gmsHandle_new(uri);
renatofilho@754
   238
    UriArgs        *args;
morphbr@534
   239
renatofilho@754
   240
    if (!gmyth_stream_client_connect(handle->stream,
renatofilho@754
   241
                                     gnome_vfs_uri_get_host_name(uri),
renatofilho@754
   242
                                     gnome_vfs_uri_get_host_port(uri))) {
morphbr@534
   243
renatofilho@556
   244
        return GNOME_VFS_ERROR_HOST_NOT_FOUND;
morphbr@534
   245
    }
morphbr@534
   246
renatofilho@754
   247
    args = _uri_parse_args(uri);
morphbr@534
   248
renatofilho@754
   249
    gint            ret = gmyth_stream_client_open_stream(handle->stream,
renatofilho@754
   250
                                                          args->file_name,
renatofilho@754
   251
                                                          args->mux,
renatofilho@754
   252
                                                          args->vcodec,
renatofilho@754
   253
                                                          args->vbitrate,
renatofilho@754
   254
                                                          args->fps,
renatofilho@754
   255
                                                          args->acodec,
renatofilho@754
   256
                                                          args->abitrate,
renatofilho@754
   257
                                                          args->width,
renatofilho@754
   258
                                                          args->height,
renatofilho@754
   259
                                                          args->opt);
morphbr@534
   260
renatofilho@754
   261
    g_free(args);
morphbr@534
   262
morphbr@534
   263
    if (ret == -1) {
renatofilho@754
   264
        gmyth_stream_client_disconnect(handle->stream);
renatofilho@556
   265
        return GNOME_VFS_ERROR_HOST_NOT_FOUND;
morphbr@534
   266
    }
morphbr@534
   267
renatofilho@754
   268
    handle->fd = gmyth_stream_client_play_stream(handle->stream);
morphbr@534
   269
morphbr@534
   270
    if (handle->fd == -1) {
renatofilho@754
   271
        gmyth_stream_client_disconnect(handle->stream);
renatofilho@556
   272
        return GNOME_VFS_ERROR_HOST_NOT_FOUND;
morphbr@534
   273
    }
morphbr@534
   274
morphbr@534
   275
    *method_handle = (GnomeVFSMethodHandle *) handle;
morphbr@534
   276
    return GNOME_VFS_OK;
morphbr@534
   277
}
morphbr@534
   278
renatofilho@754
   279
static          GnomeVFSResult
renatofilho@754
   280
do_read(GnomeVFSMethod * method,
renatofilho@754
   281
        GnomeVFSMethodHandle * method_handle,
renatofilho@754
   282
        gpointer buffer,
renatofilho@754
   283
        GnomeVFSFileSize bytes,
renatofilho@754
   284
        GnomeVFSFileSize * bytes_read, GnomeVFSContext * context)
morphbr@534
   285
{
morphbr@534
   286
renatofilho@754
   287
    gint64          total_read = 0;
renatofilho@754
   288
    gmsHandle      *handle = (gmsHandle *) method_handle;
morphbr@534
   289
renatofilho@754
   290
    // g_debug("waiting something");
morphbr@544
   291
morphbr@534
   292
    total_read = recv(handle->fd, buffer, BUFFER_SIZE, 0);
renatofilho@754
   293
    // g_debug("COULD READ: %d bytes", total_read);
morphbr@534
   294
    *bytes_read = (GnomeVFSFileSize) total_read;
morphbr@534
   295
renatofilho@754
   296
    // if (total_read < 0) g_debug("ERROR!!!!!!!!!!!!!!!!");
morphbr@544
   297
renatofilho@754
   298
    if (total_read < 0)
renatofilho@754
   299
        return GNOME_VFS_ERROR_INTERNAL;
renatofilho@754
   300
    else
renatofilho@754
   301
        return GNOME_VFS_OK;
morphbr@534
   302
morphbr@534
   303
}
morphbr@534
   304
renatofilho@754
   305
static          GnomeVFSResult
renatofilho@754
   306
do_close(GnomeVFSMethod * method,
renatofilho@754
   307
         GnomeVFSMethodHandle * method_handle, GnomeVFSContext * context)
morphbr@534
   308
{
renatofilho@754
   309
    gmsHandle      *handle = (gmsHandle *) method_handle;
morphbr@534
   310
morphbr@544
   311
    g_debug("close close close");
morphbr@544
   312
renatofilho@754
   313
    gmyth_stream_client_close_stream(handle->stream);
renatofilho@754
   314
    gmyth_stream_client_disconnect(handle->stream);
morphbr@534
   315
morphbr@534
   316
    g_free(handle);
morphbr@534
   317
    return GNOME_VFS_OK;
morphbr@534
   318
}
morphbr@534
   319
morphbr@534
   320
renatofilho@754
   321
static          GnomeVFSResult
renatofilho@754
   322
do_get_file_info(GnomeVFSMethod * method,
renatofilho@754
   323
                 GnomeVFSURI * uri,
renatofilho@754
   324
                 GnomeVFSFileInfo * file_info,
renatofilho@754
   325
                 GnomeVFSFileInfoOptions options,
renatofilho@754
   326
                 GnomeVFSContext * context)
morphbr@534
   327
{
morphbr@534
   328
    file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
morphbr@534
   329
        GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
morphbr@534
   330
morphbr@534
   331
    file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
morphbr@534
   332
morphbr@534
   333
    file_info->permissions = GNOME_VFS_PERM_USER_READ |
renatofilho@754
   334
        GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_GROUP_READ;
morphbr@534
   335
morphbr@534
   336
    return GNOME_VFS_OK;
morphbr@534
   337
}
morphbr@534
   338
morphbr@534
   339
renatofilho@754
   340
static          GnomeVFSResult
renatofilho@754
   341
do_get_file_info_from_handle(GnomeVFSMethod * method,
renatofilho@754
   342
                             GnomeVFSMethodHandle * method_handle,
renatofilho@754
   343
                             GnomeVFSFileInfo * file_info,
renatofilho@754
   344
                             GnomeVFSFileInfoOptions options,
renatofilho@754
   345
                             GnomeVFSContext * context)
morphbr@534
   346
{
morphbr@534
   347
    file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
morphbr@534
   348
        GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
morphbr@534
   349
morphbr@534
   350
    file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
morphbr@534
   351
morphbr@534
   352
    file_info->permissions = GNOME_VFS_PERM_USER_READ |
renatofilho@754
   353
        GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_GROUP_READ;
morphbr@534
   354
morphbr@534
   355
    return GNOME_VFS_OK;
morphbr@534
   356
}
morphbr@534
   357
morphbr@534
   358
renatofilho@754
   359
static          gboolean
renatofilho@754
   360
do_is_local(GnomeVFSMethod * method, const GnomeVFSURI * uri)
morphbr@534
   361
{
morphbr@534
   362
    return FALSE;
morphbr@534
   363
}