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