1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gmyth-stream/libgnomevfs2/modules/gmythstream-method.c Thu Apr 12 20:59:54 2007 +0100
1.3 @@ -0,0 +1,354 @@
1.4 +/*
1.5 + * @author Artur Duque de Souza <souza.artur@indt.org.br>
1.6 + *
1.7 + * This program is free software; you can redistribute it and/or modify
1.8 + * it under the terms of the GNU Lesser General Public License as published by
1.9 + * the Free Software Foundation; either version 2 of the License, or
1.10 + * (at your option) any later version.
1.11 + *
1.12 + * This program is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 + * GNU General Public License for more details.
1.16 + *
1.17 + m * You should have received a copy of the GNU Lesser General Public License
1.18 + * along with this program; if not, write to the Free Software
1.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.20 + */
1.21 +
1.22 +#ifdef HAVE_CONFIG_H
1.23 +#include <config.h>
1.24 +#endif
1.25 +
1.26 +#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
1.27 +#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
1.28 +#include <stdlib.h> /* for atoi() and exit() */
1.29 +#include <string.h> /* for memset() */
1.30 +#include <unistd.h> /* for close() */
1.31 +#include <errno.h>
1.32 +
1.33 +#include <glib.h>
1.34 +#include <glib/gprintf.h>
1.35 +#include <glib/gstdio.h>
1.36 +#include <gmyth-stream-client.h>
1.37 +
1.38 +#include <libgnomevfs/gnome-vfs-module.h>
1.39 +#include <libgnomevfs/gnome-vfs-utils.h>
1.40 +
1.41 +#define BUFFER_SIZE 4096
1.42 +
1.43 +typedef struct {
1.44 + gint port;
1.45 + gchar* hostname;
1.46 +
1.47 + GMythStreamClient *stream;
1.48 + gint fd;
1.49 +} gmsHandle;
1.50 +
1.51 +typedef struct {
1.52 + gchar *file_name;
1.53 + gchar *mux;
1.54 + gchar *vcodec;
1.55 + guint vbitrate;
1.56 + gdouble fps;
1.57 + gchar *acodec;
1.58 + guint abitrate;
1.59 + guint width;
1.60 + guint height;
1.61 + guint port;
1.62 + gchar *opt;
1.63 +} UriArgs;
1.64 +
1.65 +
1.66 +static gmsHandle* gmsHandle_new(GnomeVFSURI *uri);
1.67 +
1.68 +static GnomeVFSResult
1.69 +do_open (GnomeVFSMethod *method,
1.70 + GnomeVFSMethodHandle **method_handle,
1.71 + GnomeVFSURI *uri,
1.72 + GnomeVFSOpenMode mode,
1.73 + GnomeVFSContext *context);
1.74 +
1.75 +static GnomeVFSResult
1.76 +do_read (GnomeVFSMethod *method,
1.77 + GnomeVFSMethodHandle *method_handle,
1.78 + gpointer buffer,
1.79 + GnomeVFSFileSize bytes,
1.80 + GnomeVFSFileSize *bytes_read,
1.81 + GnomeVFSContext *context);
1.82 +
1.83 +static GnomeVFSResult
1.84 +do_close (GnomeVFSMethod * method,
1.85 + GnomeVFSMethodHandle * method_handle,
1.86 + GnomeVFSContext * context);
1.87 +
1.88 +static GnomeVFSResult
1.89 +do_get_file_info (GnomeVFSMethod * method,
1.90 + GnomeVFSURI * uri,
1.91 + GnomeVFSFileInfo * file_info,
1.92 + GnomeVFSFileInfoOptions options,
1.93 + GnomeVFSContext * context);
1.94 +
1.95 +
1.96 +static GnomeVFSResult
1.97 +do_get_file_info_from_handle (GnomeVFSMethod *method,
1.98 + GnomeVFSMethodHandle *method_handle,
1.99 + GnomeVFSFileInfo *file_info,
1.100 + GnomeVFSFileInfoOptions options,
1.101 + GnomeVFSContext *context);
1.102 +
1.103 +
1.104 +static gboolean
1.105 +do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri);
1.106 +
1.107 +
1.108 +static gmsHandle* gmsHandle_new(GnomeVFSURI *uri)
1.109 +{
1.110 + gmsHandle* handler = (gmsHandle*)g_malloc0(sizeof(gmsHandle));
1.111 +
1.112 + handler->hostname = (gchar*)gnome_vfs_uri_get_host_name(uri);
1.113 + handler->port = gnome_vfs_uri_get_host_port(uri);
1.114 + handler->stream = gmyth_stream_client_new ();
1.115 +
1.116 + return handler;
1.117 +}
1.118 +
1.119 +static GnomeVFSMethod method = {
1.120 + sizeof (GnomeVFSMethod),
1.121 + do_open, /* open */
1.122 + NULL, /* create */
1.123 + do_close, /* close */
1.124 + do_read, /* read */
1.125 + NULL, /* write */
1.126 + NULL, /* seek */
1.127 + NULL, /* tell */
1.128 + NULL, /* truncate_handle */
1.129 + NULL, /* open_directory */
1.130 + NULL, /* close_directory */
1.131 + NULL, /* read_directory */
1.132 + do_get_file_info, /* get_file_info */
1.133 + do_get_file_info_from_handle, /* get_file_info_from_handle */
1.134 + do_is_local, /* is_local */
1.135 + NULL, /* make_directory */
1.136 + NULL, /* remove_directory */
1.137 + NULL, /* move */
1.138 + NULL, /* unlink */
1.139 + NULL, /* check_same_fs */
1.140 + NULL, /* set_file_info */
1.141 + NULL, /* truncate */
1.142 + NULL, /* find_directory */
1.143 + NULL, /* create_symbolic_link */
1.144 + NULL, /* monitor_add */
1.145 + NULL, /* monitor_cancel */
1.146 + NULL /* file_control */
1.147 +};
1.148 +
1.149 +GnomeVFSMethod *
1.150 +vfs_module_init (const char *method_name, const char *args)
1.151 +{
1.152 + return &method;
1.153 +}
1.154 +
1.155 +void
1.156 +vfs_module_shutdown (GnomeVFSMethod* method)
1.157 +{
1.158 + return;
1.159 +}
1.160 +
1.161 +char* _parse_opt(char* opt)
1.162 +{
1.163 + char** list = g_strsplit(opt, "opt=", 2);
1.164 + char** opts = g_strsplit(list[1], "+", 32);
1.165 + char* value = "";
1.166 + char* aux;
1.167 + gint i = 0;
1.168 +
1.169 + for (aux = opts[0]; aux != NULL; aux = opts[++i])
1.170 + value = g_strdup_printf("%s %s", value, aux);
1.171 +
1.172 + g_free(aux);
1.173 + g_strfreev(list);
1.174 + g_strfreev(opts);
1.175 + return value;
1.176 +}
1.177 +
1.178 +static UriArgs *
1.179 +_uri_parse_args (const GnomeVFSURI *uri)
1.180 +{
1.181 + gchar *file = gnome_vfs_unescape_string (uri->text, NULL);
1.182 + gchar **lst = g_strsplit (file, "?", 0);
1.183 + UriArgs *info = g_new0 (UriArgs, 1);
1.184 + gint i = 1;
1.185 +
1.186 + gchar** prop = NULL;
1.187 + prop = g_strsplit_set(lst[0], "/=", 3);
1.188 +
1.189 + info->file_name = g_strdup_printf ("%s://%s",\
1.190 + prop[1],prop[2]);
1.191 + g_strfreev(prop);
1.192 +
1.193 + gchar* walk;
1.194 + for (walk = lst[1]; walk != NULL; walk = lst[++i])
1.195 + {
1.196 + prop = g_strsplit(walk, "=", 2);
1.197 +
1.198 + if (g_strv_length (prop) == 2) {
1.199 + if (strcmp (prop[0], "mux") == 0) {
1.200 + info->mux = g_strdup (prop[1]);
1.201 + } else if (strcmp (prop[0], "vcodec") == 0) {
1.202 + info->vcodec = g_strdup (prop[1]);
1.203 + } else if (strcmp (prop[0], "vbitrate") == 0) {
1.204 + info->vbitrate = atoi (prop[1]);
1.205 + } else if (strcmp (prop[0], "fps") == 0) {
1.206 + info->fps = g_strtod (prop[1], NULL);
1.207 + } else if (strcmp (prop[0], "acodec") == 0) {
1.208 + info->acodec = g_strdup (prop[1]);
1.209 + } else if (strcmp (prop[0], "abitrate") == 0) {
1.210 + info->abitrate = atoi (prop[1]);
1.211 + } else if (strcmp (prop[0], "width") == 0) {
1.212 + info->width = atoi (prop[1]);
1.213 + } else if (strcmp (prop[0], "height") == 0) {
1.214 + info->height = atoi (prop[1]);
1.215 + } else if (strcmp (prop[0], "opt") == 0) {
1.216 + g_debug("DENTRO DE OPT: %s", walk);
1.217 + char* v = _parse_opt(walk);
1.218 + info->opt = g_strdup (v);
1.219 + }
1.220 + }
1.221 + g_strfreev (prop);
1.222 + }
1.223 +
1.224 + g_free (file);
1.225 + g_strfreev (lst);
1.226 + return info;
1.227 +}
1.228 +
1.229 +static GnomeVFSResult
1.230 +do_open (GnomeVFSMethod *method,
1.231 + GnomeVFSMethodHandle **method_handle,
1.232 + GnomeVFSURI *uri,
1.233 + GnomeVFSOpenMode mode,
1.234 + GnomeVFSContext *context)
1.235 +{
1.236 + gmsHandle *handle = gmsHandle_new(uri);
1.237 + UriArgs *args;
1.238 +
1.239 + if (!gmyth_stream_client_connect (handle->stream,
1.240 + gnome_vfs_uri_get_host_name (uri),
1.241 + gnome_vfs_uri_get_host_port (uri))) {
1.242 +
1.243 + return GNOME_VFS_ERROR_INVALID_FILENAME;
1.244 + }
1.245 +
1.246 + args = _uri_parse_args (uri);
1.247 +
1.248 + gint ret = gmyth_stream_client_open_stream (handle->stream,
1.249 + args->file_name,
1.250 + args->mux,
1.251 + args->vcodec,
1.252 + args->vbitrate,
1.253 + args->fps,
1.254 + args->acodec,
1.255 + args->abitrate,
1.256 + args->width,
1.257 + args->height,
1.258 + args->opt);
1.259 +
1.260 + g_free (args);
1.261 +
1.262 + if (ret == -1) {
1.263 + gmyth_stream_client_disconnect (handle->stream);
1.264 + return GNOME_VFS_ERROR_INVALID_FILENAME;
1.265 + }
1.266 +
1.267 + handle->fd = gmyth_stream_client_play_stream (handle->stream);
1.268 +
1.269 + if (handle->fd == -1) {
1.270 + gmyth_stream_client_disconnect (handle->stream);
1.271 + return GNOME_VFS_ERROR_INVALID_FILENAME;
1.272 + }
1.273 +
1.274 + *method_handle = (GnomeVFSMethodHandle *) handle;
1.275 + return GNOME_VFS_OK;
1.276 +}
1.277 +
1.278 +static GnomeVFSResult
1.279 +do_read (GnomeVFSMethod *method,
1.280 + GnomeVFSMethodHandle *method_handle,
1.281 + gpointer buffer,
1.282 + GnomeVFSFileSize bytes,
1.283 + GnomeVFSFileSize *bytes_read,
1.284 + GnomeVFSContext *context)
1.285 +{
1.286 +
1.287 + gint64 total_read = 0;
1.288 + gmsHandle *handle = (gmsHandle *) method_handle;
1.289 +
1.290 + total_read = recv(handle->fd, buffer, BUFFER_SIZE, 0);
1.291 + *bytes_read = (GnomeVFSFileSize) total_read;
1.292 +
1.293 + if (total_read < 0) return GNOME_VFS_ERROR_INTERNAL;
1.294 + else return GNOME_VFS_OK;
1.295 +
1.296 +}
1.297 +
1.298 +static GnomeVFSResult
1.299 +do_close (GnomeVFSMethod * method,
1.300 + GnomeVFSMethodHandle * method_handle,
1.301 + GnomeVFSContext * context)
1.302 +{
1.303 + gmsHandle *handle = (gmsHandle *) method_handle;
1.304 +
1.305 + gmyth_stream_client_close_stream (handle->stream);
1.306 + gmyth_stream_client_disconnect (handle->stream);
1.307 +
1.308 + g_free(handle);
1.309 + return GNOME_VFS_OK;
1.310 +}
1.311 +
1.312 +
1.313 +static GnomeVFSResult
1.314 +do_get_file_info (GnomeVFSMethod * method,
1.315 + GnomeVFSURI * uri,
1.316 + GnomeVFSFileInfo * file_info,
1.317 + GnomeVFSFileInfoOptions options,
1.318 + GnomeVFSContext * context)
1.319 +{
1.320 + file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
1.321 + GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
1.322 +
1.323 + file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
1.324 +
1.325 + file_info->permissions = GNOME_VFS_PERM_USER_READ |
1.326 + GNOME_VFS_PERM_OTHER_READ |
1.327 + GNOME_VFS_PERM_GROUP_READ;
1.328 +
1.329 + return GNOME_VFS_OK;
1.330 +}
1.331 +
1.332 +
1.333 +static GnomeVFSResult
1.334 +do_get_file_info_from_handle (GnomeVFSMethod *method,
1.335 + GnomeVFSMethodHandle *method_handle,
1.336 + GnomeVFSFileInfo *file_info,
1.337 + GnomeVFSFileInfoOptions options,
1.338 + GnomeVFSContext *context)
1.339 +{
1.340 + file_info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
1.341 + GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
1.342 +
1.343 + file_info->type = GNOME_VFS_FILE_TYPE_SOCKET;
1.344 +
1.345 + file_info->permissions = GNOME_VFS_PERM_USER_READ |
1.346 + GNOME_VFS_PERM_OTHER_READ |
1.347 + GNOME_VFS_PERM_GROUP_READ;
1.348 +
1.349 + return GNOME_VFS_OK;
1.350 +}
1.351 +
1.352 +
1.353 +static gboolean
1.354 +do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
1.355 +{
1.356 + return FALSE;
1.357 +}