gmyth-stream/libgnomevfs2/modules/gmythstream-method.c
author renatofilho
Thu May 10 22:09:33 2007 +0100 (2007-05-10)
branchtrunk
changeset 643 653976fae5dd
parent 544 bf01a0d21980
child 754 cb885ee44618
permissions -rw-r--r--
[svn r649] gmythuri is livetv fixed
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@544
   158
char* _parse_opt(char* opt)
morphbr@544
   159
{
morphbr@544
   160
    char** list = g_strsplit(opt, "opt=", 2);
morphbr@544
   161
    char** opts = g_strsplit(list[1], "+", 32);
morphbr@544
   162
    char* value = "";
morphbr@544
   163
    char* aux;
morphbr@544
   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 *
morphbr@534
   176
_uri_parse_args (const GnomeVFSURI *uri)
morphbr@534
   177
{
morphbr@544
   178
    gchar *file = gnome_vfs_unescape_string (uri->text, NULL);
renatofilho@538
   179
morphbr@544
   180
    gchar **list = g_strsplit(file, "\'", 3);
morphbr@544
   181
    gchar **prefix = g_strsplit_set(list[0], "/=", 3);
morphbr@544
   182
    gchar **lst = g_strsplit (list[2], "?", 0);
morphbr@544
   183
morphbr@534
   184
    UriArgs *info = g_new0 (UriArgs, 1);
morphbr@544
   185
    gint i = 1;
morphbr@534
   186
morphbr@544
   187
    gchar** prop = NULL;
morphbr@544
   188
    prop = g_strsplit_set(lst[0], "/=", 3);
morphbr@534
   189
morphbr@544
   190
    info->file_name = g_strdup_printf ("%s://%s",\
morphbr@544
   191
                                       prefix[1],list[1]);
morphbr@534
   192
morphbr@544
   193
    //g_debug("FILENAME: [%s]", info->file_name);
renatofilho@538
   194
morphbr@544
   195
    g_strfreev(prop);
morphbr@544
   196
morphbr@544
   197
    gchar* walk;
morphbr@544
   198
    for (walk = lst[1]; walk != NULL; walk = lst[++i])
morphbr@534
   199
    {
morphbr@544
   200
        prop = g_strsplit(walk, "=", 2);
morphbr@534
   201
morphbr@534
   202
        if (g_strv_length (prop) == 2) {
morphbr@544
   203
            if (strcmp (prop[0], "mux") == 0) {
morphbr@534
   204
                info->mux = g_strdup (prop[1]);
morphbr@534
   205
            } else if (strcmp (prop[0], "vcodec") == 0) {
morphbr@534
   206
                info->vcodec = g_strdup (prop[1]);
morphbr@534
   207
            } else if (strcmp (prop[0], "vbitrate") == 0) {
morphbr@534
   208
                info->vbitrate = atoi (prop[1]);
morphbr@534
   209
            } else if (strcmp (prop[0], "fps") == 0) {
morphbr@534
   210
                info->fps = g_strtod (prop[1], NULL);
morphbr@534
   211
            } else if (strcmp (prop[0], "acodec") == 0) {
morphbr@534
   212
                info->acodec = g_strdup (prop[1]);
morphbr@534
   213
            } else if (strcmp (prop[0], "abitrate") == 0) {
morphbr@534
   214
                info->abitrate = atoi (prop[1]);
morphbr@534
   215
            } else if (strcmp (prop[0], "width") == 0) {
morphbr@534
   216
                info->width = atoi (prop[1]);
morphbr@534
   217
            } else if (strcmp (prop[0], "height") == 0) {
morphbr@534
   218
                info->height = atoi (prop[1]);
morphbr@534
   219
            } else if (strcmp (prop[0], "opt") == 0) {
morphbr@544
   220
                info->opt = g_strdup (_parse_opt(walk));
morphbr@534
   221
            }
renatofilho@538
   222
        }
morphbr@534
   223
        g_strfreev (prop);
morphbr@534
   224
    }
morphbr@544
   225
morphbr@534
   226
    g_free (file);
morphbr@544
   227
    g_strfreev (list);
morphbr@544
   228
    g_strfreev (prefix);
morphbr@544
   229
    g_strfreev (lst);
morphbr@534
   230
    return info;
morphbr@534
   231
}
morphbr@534
   232
morphbr@534
   233
static GnomeVFSResult
morphbr@534
   234
do_open (GnomeVFSMethod        *method,
morphbr@534
   235
	 GnomeVFSMethodHandle **method_handle,
morphbr@534
   236
	 GnomeVFSURI           *uri,
morphbr@534
   237
	 GnomeVFSOpenMode       mode,
morphbr@534
   238
	 GnomeVFSContext       *context)
morphbr@534
   239
{
morphbr@534
   240
    gmsHandle *handle = gmsHandle_new(uri);
morphbr@534
   241
    UriArgs *args;
morphbr@534
   242
morphbr@534
   243
    if (!gmyth_stream_client_connect (handle->stream,
morphbr@534
   244
                                      gnome_vfs_uri_get_host_name  (uri),
morphbr@534
   245
                                      gnome_vfs_uri_get_host_port  (uri))) {
morphbr@534
   246
renatofilho@556
   247
        return GNOME_VFS_ERROR_HOST_NOT_FOUND;
morphbr@534
   248
    }
morphbr@534
   249
morphbr@534
   250
    args = _uri_parse_args (uri);
morphbr@534
   251
morphbr@534
   252
    gint ret = gmyth_stream_client_open_stream (handle->stream,
morphbr@534
   253
                                                args->file_name,
morphbr@534
   254
                                                args->mux,
morphbr@534
   255
                                                args->vcodec,
morphbr@534
   256
                                                args->vbitrate,
morphbr@534
   257
                                                args->fps,
morphbr@534
   258
                                                args->acodec,
morphbr@534
   259
                                                args->abitrate,
morphbr@534
   260
                                                args->width,
morphbr@534
   261
                                                args->height,
morphbr@534
   262
                                                args->opt);
morphbr@534
   263
morphbr@534
   264
    g_free (args);
morphbr@534
   265
morphbr@534
   266
    if (ret == -1) {
morphbr@534
   267
        gmyth_stream_client_disconnect (handle->stream);
renatofilho@556
   268
        return GNOME_VFS_ERROR_HOST_NOT_FOUND;
morphbr@534
   269
    }
morphbr@534
   270
morphbr@534
   271
    handle->fd = gmyth_stream_client_play_stream (handle->stream);
morphbr@534
   272
morphbr@534
   273
    if (handle->fd == -1) {
morphbr@534
   274
        gmyth_stream_client_disconnect (handle->stream);
renatofilho@556
   275
        return GNOME_VFS_ERROR_HOST_NOT_FOUND;
morphbr@534
   276
    }
morphbr@534
   277
morphbr@534
   278
    *method_handle = (GnomeVFSMethodHandle *) handle;
morphbr@534
   279
    return GNOME_VFS_OK;
morphbr@534
   280
}
morphbr@534
   281
morphbr@534
   282
static GnomeVFSResult
morphbr@534
   283
do_read (GnomeVFSMethod       *method,
morphbr@534
   284
	 GnomeVFSMethodHandle *method_handle,
morphbr@534
   285
	 gpointer              buffer,
morphbr@534
   286
	 GnomeVFSFileSize      bytes,
morphbr@534
   287
	 GnomeVFSFileSize     *bytes_read,
morphbr@534
   288
	 GnomeVFSContext      *context)
morphbr@534
   289
{
morphbr@534
   290
morphbr@534
   291
    gint64 total_read = 0;
morphbr@534
   292
    gmsHandle *handle = (gmsHandle *) method_handle;
morphbr@534
   293
morphbr@544
   294
    //g_debug("waiting something");
morphbr@544
   295
morphbr@534
   296
    total_read = recv(handle->fd, buffer, BUFFER_SIZE, 0);
morphbr@544
   297
    //g_debug("COULD READ: %d bytes", total_read);
morphbr@534
   298
    *bytes_read = (GnomeVFSFileSize) total_read;
morphbr@534
   299
morphbr@544
   300
    //if (total_read < 0) g_debug("ERROR!!!!!!!!!!!!!!!!");
morphbr@544
   301
morphbr@534
   302
    if (total_read < 0) return GNOME_VFS_ERROR_INTERNAL;
morphbr@534
   303
    else return GNOME_VFS_OK;
morphbr@534
   304
morphbr@534
   305
}
morphbr@534
   306
morphbr@534
   307
static GnomeVFSResult
morphbr@534
   308
do_close (GnomeVFSMethod * method,
morphbr@534
   309
          GnomeVFSMethodHandle * method_handle,
morphbr@534
   310
          GnomeVFSContext * context)
morphbr@534
   311
{
morphbr@534
   312
    gmsHandle *handle = (gmsHandle *) method_handle;
morphbr@534
   313
morphbr@544
   314
    g_debug("close close close");
morphbr@544
   315
morphbr@534
   316
    gmyth_stream_client_close_stream (handle->stream);
morphbr@534
   317
    gmyth_stream_client_disconnect (handle->stream);
morphbr@534
   318
morphbr@534
   319
    g_free(handle);
morphbr@534
   320
    return GNOME_VFS_OK;
morphbr@534
   321
}
morphbr@534
   322
morphbr@534
   323
morphbr@534
   324
static GnomeVFSResult
morphbr@534
   325
do_get_file_info (GnomeVFSMethod * method,
morphbr@534
   326
		  GnomeVFSURI * uri,
morphbr@534
   327
		  GnomeVFSFileInfo * file_info,
morphbr@534
   328
		  GnomeVFSFileInfoOptions options,
morphbr@534
   329
		  GnomeVFSContext * context)
morphbr@534
   330
{
morphbr@534
   331
    file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
morphbr@534
   332
        GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
morphbr@534
   333
morphbr@534
   334
    file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
morphbr@534
   335
morphbr@534
   336
    file_info->permissions = GNOME_VFS_PERM_USER_READ |
morphbr@534
   337
        GNOME_VFS_PERM_OTHER_READ |
morphbr@534
   338
        GNOME_VFS_PERM_GROUP_READ;
morphbr@534
   339
morphbr@534
   340
    return GNOME_VFS_OK;
morphbr@534
   341
}
morphbr@534
   342
morphbr@534
   343
morphbr@534
   344
static GnomeVFSResult
morphbr@534
   345
do_get_file_info_from_handle (GnomeVFSMethod 		*method,
morphbr@534
   346
                              GnomeVFSMethodHandle 	*method_handle,
morphbr@534
   347
                              GnomeVFSFileInfo 		*file_info,
morphbr@534
   348
                              GnomeVFSFileInfoOptions    options,
morphbr@534
   349
                              GnomeVFSContext 		*context)
morphbr@534
   350
{
morphbr@534
   351
    file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
morphbr@534
   352
        GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
morphbr@534
   353
morphbr@534
   354
    file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
morphbr@534
   355
morphbr@534
   356
    file_info->permissions = GNOME_VFS_PERM_USER_READ |
morphbr@534
   357
        GNOME_VFS_PERM_OTHER_READ |
morphbr@534
   358
        GNOME_VFS_PERM_GROUP_READ;
morphbr@534
   359
morphbr@534
   360
    return GNOME_VFS_OK;
morphbr@534
   361
}
morphbr@534
   362
morphbr@534
   363
morphbr@534
   364
static gboolean
morphbr@534
   365
do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
morphbr@534
   366
{
morphbr@534
   367
    return FALSE;
morphbr@534
   368
}