gmyth-stream/libgnomevfs2/modules/gmythstream-method.c
author renatofilho
Thu Apr 12 22:34:28 2007 +0100 (2007-04-12)
branchtrunk
changeset 540 d6f9b0417346
parent 539 c67cec9e6073
child 541 0bf798c3f17e
permissions -rw-r--r--
[svn r545] fixed parse
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
static UriArgs *
morphbr@534
   159
_uri_parse_args (const GnomeVFSURI *uri)
morphbr@534
   160
{
renatofilho@538
   161
renatofilho@538
   162
    gchar *file;
morphbr@534
   163
    UriArgs *info = g_new0 (UriArgs, 1);
renatofilho@538
   164
	GSList *args = NULL;
renatofilho@538
   165
	gchar *c;
renatofilho@538
   166
	GString *entry;
renatofilho@538
   167
	gboolean open = FALSE;
renatofilho@538
   168
	gchar **prop;
renatofilho@538
   169
    GSList* walk;
renatofilho@539
   170
	gchar *uri_str = gnome_vfs_uri_to_string (uri,
renatofilho@538
   171
			GNOME_VFS_URI_HIDE_USER_NAME |
renatofilho@538
   172
			GNOME_VFS_URI_HIDE_PASSWORD |
renatofilho@538
   173
			GNOME_VFS_URI_HIDE_HOST_NAME |
renatofilho@538
   174
			GNOME_VFS_URI_HIDE_HOST_PORT |
renatofilho@539
   175
			GNOME_VFS_URI_HIDE_TOPLEVEL_METHOD);
morphbr@534
   176
renatofilho@539
   177
	file = gnome_vfs_unescape_string (uri_str, "");
renatofilho@538
   178
	c = file;
renatofilho@538
   179
	entry = g_string_new ("");
renatofilho@538
   180
	c = c + 1;
renatofilho@538
   181
	do {
renatofilho@538
   182
		if ((*c == '\"') || (*c == '\'')) {
renatofilho@538
   183
			open = !open;
renatofilho@538
   184
		}
morphbr@534
   185
renatofilho@540
   186
		if (((*c == '?') || (c[1] == '\0')) && !open) {
renatofilho@540
   187
			if (*c != '?')
renatofilho@540
   188
				g_string_append_c (entry, *c);
renatofilho@540
   189
renatofilho@538
   190
			args = g_slist_append (args, g_strdup (entry->str));
renatofilho@538
   191
			entry = g_string_assign (entry, "");
renatofilho@538
   192
		} else {
renatofilho@540
   193
			g_string_append_c (entry, *c);
renatofilho@538
   194
		}
renatofilho@538
   195
		c = c + 1;
renatofilho@538
   196
	} while (*c != '\0');
morphbr@534
   197
renatofilho@538
   198
	g_string_free (entry, TRUE);
renatofilho@538
   199
renatofilho@538
   200
    for (walk = args; walk != NULL; walk = walk->next)
morphbr@534
   201
    {
renatofilho@538
   202
		gchar *arg = (gchar *) walk->data;
renatofilho@538
   203
        prop = g_strsplit(arg, "=", 2);
renatofilho@540
   204
		g_debug ("arg = %s", arg);
morphbr@534
   205
morphbr@534
   206
        if (g_strv_length (prop) == 2) {
renatofilho@538
   207
			if (strcmp (prop[0], "file") == 0) {
renatofilho@538
   208
				info->file_name = g_strdup (prop[1]);
renatofilho@538
   209
			} else if (strcmp (prop[0], "mux") == 0) {
morphbr@534
   210
                info->mux = g_strdup (prop[1]);
morphbr@534
   211
            } else if (strcmp (prop[0], "vcodec") == 0) {
morphbr@534
   212
                info->vcodec = g_strdup (prop[1]);
morphbr@534
   213
            } else if (strcmp (prop[0], "vbitrate") == 0) {
morphbr@534
   214
                info->vbitrate = atoi (prop[1]);
morphbr@534
   215
            } else if (strcmp (prop[0], "fps") == 0) {
morphbr@534
   216
                info->fps = g_strtod (prop[1], NULL);
morphbr@534
   217
            } else if (strcmp (prop[0], "acodec") == 0) {
morphbr@534
   218
                info->acodec = g_strdup (prop[1]);
morphbr@534
   219
            } else if (strcmp (prop[0], "abitrate") == 0) {
morphbr@534
   220
                info->abitrate = atoi (prop[1]);
morphbr@534
   221
            } else if (strcmp (prop[0], "width") == 0) {
morphbr@534
   222
                info->width = atoi (prop[1]);
morphbr@534
   223
            } else if (strcmp (prop[0], "height") == 0) {
morphbr@534
   224
                info->height = atoi (prop[1]);
morphbr@534
   225
            } else if (strcmp (prop[0], "opt") == 0) {
renatofilho@538
   226
                g_debug("DENTRO DE OPT: %s", arg);
renatofilho@538
   227
                //char* v = _parse_opt(walk);
renatofilho@538
   228
                info->opt = g_strdup (arg);
morphbr@534
   229
            }
renatofilho@538
   230
        }
morphbr@534
   231
        g_strfreev (prop);
renatofilho@538
   232
		g_free (arg);
morphbr@534
   233
    }
morphbr@534
   234
    g_free (file);
renatofilho@538
   235
	g_slist_free (args);
morphbr@534
   236
    return info;
morphbr@534
   237
}
morphbr@534
   238
morphbr@534
   239
static GnomeVFSResult
morphbr@534
   240
do_open (GnomeVFSMethod        *method,
morphbr@534
   241
	 GnomeVFSMethodHandle **method_handle,
morphbr@534
   242
	 GnomeVFSURI           *uri,
morphbr@534
   243
	 GnomeVFSOpenMode       mode,
morphbr@534
   244
	 GnomeVFSContext       *context)
morphbr@534
   245
{
morphbr@534
   246
    gmsHandle *handle = gmsHandle_new(uri);
morphbr@534
   247
    UriArgs *args;
morphbr@534
   248
renatofilho@540
   249
    args = _uri_parse_args (uri);
renatofilho@540
   250
morphbr@534
   251
    if (!gmyth_stream_client_connect (handle->stream,
morphbr@534
   252
                                      gnome_vfs_uri_get_host_name  (uri),
morphbr@534
   253
                                      gnome_vfs_uri_get_host_port  (uri))) {
morphbr@534
   254
morphbr@534
   255
        return GNOME_VFS_ERROR_INVALID_FILENAME;
morphbr@534
   256
    }
morphbr@534
   257
morphbr@534
   258
    args = _uri_parse_args (uri);
morphbr@534
   259
morphbr@534
   260
    gint ret = gmyth_stream_client_open_stream (handle->stream,
morphbr@534
   261
                                                args->file_name,
morphbr@534
   262
                                                args->mux,
morphbr@534
   263
                                                args->vcodec,
morphbr@534
   264
                                                args->vbitrate,
morphbr@534
   265
                                                args->fps,
morphbr@534
   266
                                                args->acodec,
morphbr@534
   267
                                                args->abitrate,
morphbr@534
   268
                                                args->width,
morphbr@534
   269
                                                args->height,
morphbr@534
   270
                                                args->opt);
morphbr@534
   271
morphbr@534
   272
    g_free (args);
morphbr@534
   273
morphbr@534
   274
    if (ret == -1) {
morphbr@534
   275
        gmyth_stream_client_disconnect (handle->stream);
morphbr@534
   276
        return GNOME_VFS_ERROR_INVALID_FILENAME;
morphbr@534
   277
    }
morphbr@534
   278
morphbr@534
   279
    handle->fd = gmyth_stream_client_play_stream (handle->stream);
morphbr@534
   280
morphbr@534
   281
    if (handle->fd == -1) {
morphbr@534
   282
        gmyth_stream_client_disconnect (handle->stream);
morphbr@534
   283
        return GNOME_VFS_ERROR_INVALID_FILENAME;
morphbr@534
   284
    }
morphbr@534
   285
morphbr@534
   286
    *method_handle = (GnomeVFSMethodHandle *) handle;
morphbr@534
   287
    return GNOME_VFS_OK;
morphbr@534
   288
}
morphbr@534
   289
morphbr@534
   290
static GnomeVFSResult
morphbr@534
   291
do_read (GnomeVFSMethod       *method,
morphbr@534
   292
	 GnomeVFSMethodHandle *method_handle,
morphbr@534
   293
	 gpointer              buffer,
morphbr@534
   294
	 GnomeVFSFileSize      bytes,
morphbr@534
   295
	 GnomeVFSFileSize     *bytes_read,
morphbr@534
   296
	 GnomeVFSContext      *context)
morphbr@534
   297
{
morphbr@534
   298
morphbr@534
   299
    gint64 total_read = 0;
morphbr@534
   300
    gmsHandle *handle = (gmsHandle *) method_handle;
morphbr@534
   301
morphbr@534
   302
    total_read = recv(handle->fd, buffer, BUFFER_SIZE, 0);
morphbr@534
   303
    *bytes_read = (GnomeVFSFileSize) total_read;
morphbr@534
   304
morphbr@534
   305
    if (total_read < 0) return GNOME_VFS_ERROR_INTERNAL;
morphbr@534
   306
    else return GNOME_VFS_OK;
morphbr@534
   307
morphbr@534
   308
}
morphbr@534
   309
morphbr@534
   310
static GnomeVFSResult
morphbr@534
   311
do_close (GnomeVFSMethod * method,
morphbr@534
   312
          GnomeVFSMethodHandle * method_handle,
morphbr@534
   313
          GnomeVFSContext * context)
morphbr@534
   314
{
morphbr@534
   315
    gmsHandle *handle = (gmsHandle *) method_handle;
morphbr@534
   316
morphbr@534
   317
    gmyth_stream_client_close_stream (handle->stream);
morphbr@534
   318
    gmyth_stream_client_disconnect (handle->stream);
morphbr@534
   319
morphbr@534
   320
    g_free(handle);
morphbr@534
   321
    return GNOME_VFS_OK;
morphbr@534
   322
}
morphbr@534
   323
morphbr@534
   324
morphbr@534
   325
static GnomeVFSResult
morphbr@534
   326
do_get_file_info (GnomeVFSMethod * method,
morphbr@534
   327
		  GnomeVFSURI * uri,
morphbr@534
   328
		  GnomeVFSFileInfo * file_info,
morphbr@534
   329
		  GnomeVFSFileInfoOptions options,
morphbr@534
   330
		  GnomeVFSContext * context)
morphbr@534
   331
{
morphbr@534
   332
    file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
morphbr@534
   333
        GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
morphbr@534
   334
morphbr@534
   335
    file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
morphbr@534
   336
morphbr@534
   337
    file_info->permissions = GNOME_VFS_PERM_USER_READ |
morphbr@534
   338
        GNOME_VFS_PERM_OTHER_READ |
morphbr@534
   339
        GNOME_VFS_PERM_GROUP_READ;
morphbr@534
   340
morphbr@534
   341
    return GNOME_VFS_OK;
morphbr@534
   342
}
morphbr@534
   343
morphbr@534
   344
morphbr@534
   345
static GnomeVFSResult
morphbr@534
   346
do_get_file_info_from_handle (GnomeVFSMethod 		*method,
morphbr@534
   347
                              GnomeVFSMethodHandle 	*method_handle,
morphbr@534
   348
                              GnomeVFSFileInfo 		*file_info,
morphbr@534
   349
                              GnomeVFSFileInfoOptions    options,
morphbr@534
   350
                              GnomeVFSContext 		*context)
morphbr@534
   351
{
morphbr@534
   352
    file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
morphbr@534
   353
        GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
morphbr@534
   354
morphbr@534
   355
    file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
morphbr@534
   356
morphbr@534
   357
    file_info->permissions = GNOME_VFS_PERM_USER_READ |
morphbr@534
   358
        GNOME_VFS_PERM_OTHER_READ |
morphbr@534
   359
        GNOME_VFS_PERM_GROUP_READ;
morphbr@534
   360
morphbr@534
   361
    return GNOME_VFS_OK;
morphbr@534
   362
}
morphbr@534
   363
morphbr@534
   364
morphbr@534
   365
static gboolean
morphbr@534
   366
do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
morphbr@534
   367
{
morphbr@534
   368
    return FALSE;
morphbr@534
   369
}