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