gmyth-stream/libgnomevfs2/modules/gmythstream-method.c
author melunko
Thu Apr 12 20:59:54 2007 +0100 (2007-04-12)
branchtrunk
changeset 535 861b177c521d
child 538 05e6ab23f892
permissions -rw-r--r--
[svn r540] debian/control updated to gmythstream
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
morphbr@534
    23
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
morphbr@534
    24
#include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
morphbr@534
    25
#include <stdlib.h>     /* for atoi() and exit() */
morphbr@534
    26
#include <string.h>     /* for memset() */
morphbr@534
    27
#include <unistd.h>     /* for close() */
morphbr@534
    28
#include <errno.h>
morphbr@534
    29
morphbr@534
    30
#include <glib.h>
morphbr@534
    31
#include <glib/gprintf.h>
morphbr@534
    32
#include <glib/gstdio.h>
morphbr@534
    33
#include <gmyth-stream-client.h>
morphbr@534
    34
morphbr@534
    35
#include <libgnomevfs/gnome-vfs-module.h>
morphbr@534
    36
#include <libgnomevfs/gnome-vfs-utils.h>
morphbr@534
    37
morphbr@534
    38
#define BUFFER_SIZE 4096
morphbr@534
    39
morphbr@534
    40
typedef struct {
morphbr@534
    41
    gint port;
morphbr@534
    42
    gchar* hostname;
morphbr@534
    43
morphbr@534
    44
    GMythStreamClient *stream;
morphbr@534
    45
    gint fd;
morphbr@534
    46
} gmsHandle;
morphbr@534
    47
morphbr@534
    48
typedef struct {
morphbr@534
    49
    gchar *file_name;
morphbr@534
    50
    gchar *mux;
morphbr@534
    51
    gchar *vcodec;
morphbr@534
    52
    guint vbitrate;
morphbr@534
    53
    gdouble fps;
morphbr@534
    54
    gchar *acodec;
morphbr@534
    55
    guint abitrate;
morphbr@534
    56
    guint width;
morphbr@534
    57
    guint height;
morphbr@534
    58
    guint port;
morphbr@534
    59
    gchar *opt;
morphbr@534
    60
} UriArgs;
morphbr@534
    61
morphbr@534
    62
morphbr@534
    63
static gmsHandle* gmsHandle_new(GnomeVFSURI *uri);
morphbr@534
    64
morphbr@534
    65
static GnomeVFSResult
morphbr@534
    66
do_open (GnomeVFSMethod        *method,
morphbr@534
    67
	 GnomeVFSMethodHandle **method_handle,
morphbr@534
    68
	 GnomeVFSURI           *uri,
morphbr@534
    69
	 GnomeVFSOpenMode       mode,
morphbr@534
    70
	 GnomeVFSContext       *context);
morphbr@534
    71
morphbr@534
    72
static GnomeVFSResult
morphbr@534
    73
do_read (GnomeVFSMethod       *method,
morphbr@534
    74
	 GnomeVFSMethodHandle *method_handle,
morphbr@534
    75
	 gpointer              buffer,
morphbr@534
    76
	 GnomeVFSFileSize      bytes,
morphbr@534
    77
	 GnomeVFSFileSize     *bytes_read,
morphbr@534
    78
	 GnomeVFSContext      *context);
morphbr@534
    79
morphbr@534
    80
static GnomeVFSResult
morphbr@534
    81
do_close (GnomeVFSMethod * method,
morphbr@534
    82
          GnomeVFSMethodHandle * method_handle,
morphbr@534
    83
          GnomeVFSContext * context);
morphbr@534
    84
morphbr@534
    85
static GnomeVFSResult
morphbr@534
    86
do_get_file_info (GnomeVFSMethod * method,
morphbr@534
    87
		  GnomeVFSURI * uri,
morphbr@534
    88
		  GnomeVFSFileInfo * file_info,
morphbr@534
    89
		  GnomeVFSFileInfoOptions options,
morphbr@534
    90
		  GnomeVFSContext * context);
morphbr@534
    91
morphbr@534
    92
morphbr@534
    93
static GnomeVFSResult
morphbr@534
    94
do_get_file_info_from_handle (GnomeVFSMethod 		*method,
morphbr@534
    95
                              GnomeVFSMethodHandle 	*method_handle,
morphbr@534
    96
                              GnomeVFSFileInfo 		*file_info,
morphbr@534
    97
                              GnomeVFSFileInfoOptions    options,
morphbr@534
    98
                              GnomeVFSContext 		*context);
morphbr@534
    99
morphbr@534
   100
morphbr@534
   101
static gboolean
morphbr@534
   102
do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri);
morphbr@534
   103
morphbr@534
   104
morphbr@534
   105
static gmsHandle* gmsHandle_new(GnomeVFSURI *uri)
morphbr@534
   106
{
morphbr@534
   107
    gmsHandle* handler = (gmsHandle*)g_malloc0(sizeof(gmsHandle));
morphbr@534
   108
morphbr@534
   109
    handler->hostname = (gchar*)gnome_vfs_uri_get_host_name(uri);
morphbr@534
   110
    handler->port = gnome_vfs_uri_get_host_port(uri);
morphbr@534
   111
    handler->stream = gmyth_stream_client_new ();
morphbr@534
   112
morphbr@534
   113
    return handler;
morphbr@534
   114
}
morphbr@534
   115
morphbr@534
   116
static GnomeVFSMethod method = {
morphbr@534
   117
    sizeof (GnomeVFSMethod),
morphbr@534
   118
    do_open,                       /* open */
morphbr@534
   119
    NULL,                          /* create */
morphbr@534
   120
    do_close,                      /* close */
morphbr@534
   121
    do_read,                       /* read */
morphbr@534
   122
    NULL,                          /* write */
morphbr@534
   123
    NULL,                          /* seek */
morphbr@534
   124
    NULL,                          /* tell */
morphbr@534
   125
    NULL,                          /* truncate_handle */
morphbr@534
   126
    NULL,                          /* open_directory */
morphbr@534
   127
    NULL,                          /* close_directory */
morphbr@534
   128
    NULL,                          /* read_directory */
morphbr@534
   129
    do_get_file_info,              /* get_file_info */
morphbr@534
   130
    do_get_file_info_from_handle,  /* get_file_info_from_handle */
morphbr@534
   131
    do_is_local,                   /* is_local */
morphbr@534
   132
    NULL,                          /* make_directory */
morphbr@534
   133
    NULL,                          /* remove_directory */
morphbr@534
   134
    NULL,                          /* move */
morphbr@534
   135
    NULL,                          /* unlink */
morphbr@534
   136
    NULL,                          /* check_same_fs */
morphbr@534
   137
    NULL,                          /* set_file_info */
morphbr@534
   138
    NULL,                          /* truncate */
morphbr@534
   139
    NULL,                          /* find_directory */
morphbr@534
   140
    NULL,                          /* create_symbolic_link */
morphbr@534
   141
    NULL,                          /* monitor_add */
morphbr@534
   142
    NULL,                          /* monitor_cancel */
morphbr@534
   143
    NULL                           /* file_control */
morphbr@534
   144
};
morphbr@534
   145
morphbr@534
   146
GnomeVFSMethod *
morphbr@534
   147
vfs_module_init (const char *method_name, const char *args)
morphbr@534
   148
{
morphbr@534
   149
    return &method;
morphbr@534
   150
}
morphbr@534
   151
morphbr@534
   152
void
morphbr@534
   153
vfs_module_shutdown (GnomeVFSMethod* method)
morphbr@534
   154
{
morphbr@534
   155
    return;
morphbr@534
   156
}
morphbr@534
   157
morphbr@534
   158
char* _parse_opt(char* opt)
morphbr@534
   159
{
morphbr@534
   160
    char** list = g_strsplit(opt, "opt=", 2);
morphbr@534
   161
    char** opts = g_strsplit(list[1], "+", 32);
morphbr@534
   162
    char* value = "";
morphbr@534
   163
    char* aux;
morphbr@534
   164
    gint i = 0;
morphbr@534
   165
morphbr@534
   166
    for (aux = opts[0]; aux != NULL; aux = opts[++i])
morphbr@534
   167
        value = g_strdup_printf("%s %s", value, aux);
morphbr@534
   168
morphbr@534
   169
    g_free(aux);
morphbr@534
   170
    g_strfreev(list);
morphbr@534
   171
    g_strfreev(opts);
morphbr@534
   172
    return value;
morphbr@534
   173
}
morphbr@534
   174
morphbr@534
   175
static UriArgs *
morphbr@534
   176
_uri_parse_args (const GnomeVFSURI *uri)
morphbr@534
   177
{
morphbr@534
   178
    gchar *file = gnome_vfs_unescape_string (uri->text, NULL);
morphbr@534
   179
    gchar **lst = g_strsplit (file, "?", 0);
morphbr@534
   180
    UriArgs *info = g_new0 (UriArgs, 1);
morphbr@534
   181
    gint i = 1;
morphbr@534
   182
morphbr@534
   183
    gchar** prop = NULL;
morphbr@534
   184
    prop = g_strsplit_set(lst[0], "/=", 3);
morphbr@534
   185
morphbr@534
   186
    info->file_name = g_strdup_printf ("%s://%s",\
morphbr@534
   187
                                       prop[1],prop[2]);
morphbr@534
   188
    g_strfreev(prop);
morphbr@534
   189
morphbr@534
   190
    gchar* walk;
morphbr@534
   191
    for (walk = lst[1]; walk != NULL; walk = lst[++i])
morphbr@534
   192
    {
morphbr@534
   193
        prop = g_strsplit(walk, "=", 2);
morphbr@534
   194
morphbr@534
   195
        if (g_strv_length (prop) == 2) {
morphbr@534
   196
            if (strcmp (prop[0], "mux") == 0) {
morphbr@534
   197
                info->mux = g_strdup (prop[1]);
morphbr@534
   198
            } else if (strcmp (prop[0], "vcodec") == 0) {
morphbr@534
   199
                info->vcodec = g_strdup (prop[1]);
morphbr@534
   200
            } else if (strcmp (prop[0], "vbitrate") == 0) {
morphbr@534
   201
                info->vbitrate = atoi (prop[1]);
morphbr@534
   202
            } else if (strcmp (prop[0], "fps") == 0) {
morphbr@534
   203
                info->fps = g_strtod (prop[1], NULL);
morphbr@534
   204
            } else if (strcmp (prop[0], "acodec") == 0) {
morphbr@534
   205
                info->acodec = g_strdup (prop[1]);
morphbr@534
   206
            } else if (strcmp (prop[0], "abitrate") == 0) {
morphbr@534
   207
                info->abitrate = atoi (prop[1]);
morphbr@534
   208
            } else if (strcmp (prop[0], "width") == 0) {
morphbr@534
   209
                info->width = atoi (prop[1]);
morphbr@534
   210
            } else if (strcmp (prop[0], "height") == 0) {
morphbr@534
   211
                info->height = atoi (prop[1]);
morphbr@534
   212
            } else if (strcmp (prop[0], "opt") == 0) {
morphbr@534
   213
                g_debug("DENTRO DE OPT: %s", walk);
morphbr@534
   214
                char* v = _parse_opt(walk);
morphbr@534
   215
                info->opt = g_strdup (v);
morphbr@534
   216
            }
morphbr@534
   217
            }
morphbr@534
   218
        g_strfreev (prop);
morphbr@534
   219
    }
morphbr@534
   220
morphbr@534
   221
    g_free (file);
morphbr@534
   222
    g_strfreev (lst);
morphbr@534
   223
    return info;
morphbr@534
   224
}
morphbr@534
   225
morphbr@534
   226
static GnomeVFSResult
morphbr@534
   227
do_open (GnomeVFSMethod        *method,
morphbr@534
   228
	 GnomeVFSMethodHandle **method_handle,
morphbr@534
   229
	 GnomeVFSURI           *uri,
morphbr@534
   230
	 GnomeVFSOpenMode       mode,
morphbr@534
   231
	 GnomeVFSContext       *context)
morphbr@534
   232
{
morphbr@534
   233
    gmsHandle *handle = gmsHandle_new(uri);
morphbr@534
   234
    UriArgs *args;
morphbr@534
   235
morphbr@534
   236
    if (!gmyth_stream_client_connect (handle->stream,
morphbr@534
   237
                                      gnome_vfs_uri_get_host_name  (uri),
morphbr@534
   238
                                      gnome_vfs_uri_get_host_port  (uri))) {
morphbr@534
   239
morphbr@534
   240
        return GNOME_VFS_ERROR_INVALID_FILENAME;
morphbr@534
   241
    }
morphbr@534
   242
morphbr@534
   243
    args = _uri_parse_args (uri);
morphbr@534
   244
morphbr@534
   245
    gint ret = gmyth_stream_client_open_stream (handle->stream,
morphbr@534
   246
                                                args->file_name,
morphbr@534
   247
                                                args->mux,
morphbr@534
   248
                                                args->vcodec,
morphbr@534
   249
                                                args->vbitrate,
morphbr@534
   250
                                                args->fps,
morphbr@534
   251
                                                args->acodec,
morphbr@534
   252
                                                args->abitrate,
morphbr@534
   253
                                                args->width,
morphbr@534
   254
                                                args->height,
morphbr@534
   255
                                                args->opt);
morphbr@534
   256
morphbr@534
   257
    g_free (args);
morphbr@534
   258
morphbr@534
   259
    if (ret == -1) {
morphbr@534
   260
        gmyth_stream_client_disconnect (handle->stream);
morphbr@534
   261
        return GNOME_VFS_ERROR_INVALID_FILENAME;
morphbr@534
   262
    }
morphbr@534
   263
morphbr@534
   264
    handle->fd = gmyth_stream_client_play_stream (handle->stream);
morphbr@534
   265
morphbr@534
   266
    if (handle->fd == -1) {
morphbr@534
   267
        gmyth_stream_client_disconnect (handle->stream);
morphbr@534
   268
        return GNOME_VFS_ERROR_INVALID_FILENAME;
morphbr@534
   269
    }
morphbr@534
   270
morphbr@534
   271
    *method_handle = (GnomeVFSMethodHandle *) handle;
morphbr@534
   272
    return GNOME_VFS_OK;
morphbr@534
   273
}
morphbr@534
   274
morphbr@534
   275
static GnomeVFSResult
morphbr@534
   276
do_read (GnomeVFSMethod       *method,
morphbr@534
   277
	 GnomeVFSMethodHandle *method_handle,
morphbr@534
   278
	 gpointer              buffer,
morphbr@534
   279
	 GnomeVFSFileSize      bytes,
morphbr@534
   280
	 GnomeVFSFileSize     *bytes_read,
morphbr@534
   281
	 GnomeVFSContext      *context)
morphbr@534
   282
{
morphbr@534
   283
morphbr@534
   284
    gint64 total_read = 0;
morphbr@534
   285
    gmsHandle *handle = (gmsHandle *) method_handle;
morphbr@534
   286
morphbr@534
   287
    total_read = recv(handle->fd, buffer, BUFFER_SIZE, 0);
morphbr@534
   288
    *bytes_read = (GnomeVFSFileSize) total_read;
morphbr@534
   289
morphbr@534
   290
    if (total_read < 0) return GNOME_VFS_ERROR_INTERNAL;
morphbr@534
   291
    else return GNOME_VFS_OK;
morphbr@534
   292
morphbr@534
   293
}
morphbr@534
   294
morphbr@534
   295
static GnomeVFSResult
morphbr@534
   296
do_close (GnomeVFSMethod * method,
morphbr@534
   297
          GnomeVFSMethodHandle * method_handle,
morphbr@534
   298
          GnomeVFSContext * context)
morphbr@534
   299
{
morphbr@534
   300
    gmsHandle *handle = (gmsHandle *) method_handle;
morphbr@534
   301
morphbr@534
   302
    gmyth_stream_client_close_stream (handle->stream);
morphbr@534
   303
    gmyth_stream_client_disconnect (handle->stream);
morphbr@534
   304
morphbr@534
   305
    g_free(handle);
morphbr@534
   306
    return GNOME_VFS_OK;
morphbr@534
   307
}
morphbr@534
   308
morphbr@534
   309
morphbr@534
   310
static GnomeVFSResult
morphbr@534
   311
do_get_file_info (GnomeVFSMethod * method,
morphbr@534
   312
		  GnomeVFSURI * uri,
morphbr@534
   313
		  GnomeVFSFileInfo * file_info,
morphbr@534
   314
		  GnomeVFSFileInfoOptions options,
morphbr@534
   315
		  GnomeVFSContext * context)
morphbr@534
   316
{
morphbr@534
   317
    file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
morphbr@534
   318
        GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
morphbr@534
   319
morphbr@534
   320
    file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
morphbr@534
   321
morphbr@534
   322
    file_info->permissions = GNOME_VFS_PERM_USER_READ |
morphbr@534
   323
        GNOME_VFS_PERM_OTHER_READ |
morphbr@534
   324
        GNOME_VFS_PERM_GROUP_READ;
morphbr@534
   325
morphbr@534
   326
    return GNOME_VFS_OK;
morphbr@534
   327
}
morphbr@534
   328
morphbr@534
   329
morphbr@534
   330
static GnomeVFSResult
morphbr@534
   331
do_get_file_info_from_handle (GnomeVFSMethod 		*method,
morphbr@534
   332
                              GnomeVFSMethodHandle 	*method_handle,
morphbr@534
   333
                              GnomeVFSFileInfo 		*file_info,
morphbr@534
   334
                              GnomeVFSFileInfoOptions    options,
morphbr@534
   335
                              GnomeVFSContext 		*context)
morphbr@534
   336
{
morphbr@534
   337
    file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
morphbr@534
   338
        GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
morphbr@534
   339
morphbr@534
   340
    file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
morphbr@534
   341
morphbr@534
   342
    file_info->permissions = GNOME_VFS_PERM_USER_READ |
morphbr@534
   343
        GNOME_VFS_PERM_OTHER_READ |
morphbr@534
   344
        GNOME_VFS_PERM_GROUP_READ;
morphbr@534
   345
morphbr@534
   346
    return GNOME_VFS_OK;
morphbr@534
   347
}
morphbr@534
   348
morphbr@534
   349
morphbr@534
   350
static gboolean
morphbr@534
   351
do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
morphbr@534
   352
{
morphbr@534
   353
    return FALSE;
morphbr@534
   354
}