libgnomevfs2-mythtv/modules/mythtv-method.c
author rosfran
Thu Mar 01 20:07:46 2007 +0000 (2007-03-01)
branchtrunk
changeset 382 438858a187f9
parent 368 8b8394c61142
child 405 aff8c0341462
permissions -rwxr-xr-x
[svn r387] Added comment on gstgnomevfssrc plug-in usage.
     1 /*
     2  * @author Hallyson Melo <hallyson.melo@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  * 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 <string.h>
    24 #include <glib.h>
    25 #include <math.h>
    26 
    27 #include <libgnomevfs/gnome-vfs-module.h>
    28 #include <libgnomevfs/gnome-vfs-utils.h>
    29 
    30 #include <gmyth/gmyth_file_transfer.h>
    31 #include <gmyth/gmyth_livetv.h>
    32 #include <gmyth/gmyth_uri.h>
    33 #include <gmyth/gmyth_recorder.h>
    34 #include <gmyth/gmyth_backendinfo.h>
    35 #include <gmyth/gmyth_util.h>
    36 #include <gmyth/gmyth_remote_util.h>
    37 #include <gmyth/gmyth_tvchain.h>
    38 #include <gmyth/gmyth_programinfo.h>
    39 
    40 #define GST_MYTHTV_ID_NUM               1
    41 #define MYTHTV_VERSION_DEFAULT          30
    42 #define MYTHTV_TRANSFER_MAX_WAITS       100
    43 
    44 /* internal GnomeVFS plug-in buffer size ( 120 Kbytes ) */
    45 #define MYTHTV_BUFFER_SIZE							1024*80
    46 /* internally sized GnomeVFS plug-in buffer ( 4 Kbytes ) */
    47 #define MYTHTV_MAX_VFS_BUFFER_SIZE			4096
    48 /* maximum number of bytes to be requested to the MythTV backend ( 64 Kbytes ) */
    49 #define MYTHTV_MAX_REQUEST_SIZE					1024*64
    50 
    51 static GnomeVFSResult do_read (GnomeVFSMethod * method,
    52 			       GnomeVFSMethodHandle * method_handle,
    53 			       gpointer buffer,
    54 			       GnomeVFSFileSize num_bytes,
    55 			       GnomeVFSFileSize * bytes_read,
    56 			       GnomeVFSContext * context);
    57 
    58 typedef struct {
    59 	GMythFileTransfer *file_transfer;
    60 	GMythLiveTV *livetv;
    61 	gchar *channel_name;
    62 
    63 	gint mythtv_version;
    64 	gint64 content_size;
    65 	guint64 bytes_read;
    66 
    67 	GByteArray *buffer;
    68 	gsize buffer_remain;
    69 	gboolean is_livetv;
    70 
    71 	gboolean configured;
    72 
    73 } MythtvHandle;
    74 
    75 //static MythtvHandle *myth_handle = NULL;
    76 
    77 static GnomeVFSResult
    78 do_open (GnomeVFSMethod * method,
    79 	 GnomeVFSMethodHandle ** method_handle,
    80 	 GnomeVFSURI * uri,
    81 	 GnomeVFSOpenMode mode, GnomeVFSContext * context)
    82 {
    83 	MythtvHandle *myth_handle = NULL;
    84 	GMythBackendInfo *backend_info = NULL;
    85 	GMythURI *gmyth_uri = NULL;
    86 	gboolean ret = TRUE;
    87 
    88 	_GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
    89 	_GNOME_VFS_METHOD_PARAM_CHECK (uri != NULL);
    90 
    91 	if (mode & GNOME_VFS_OPEN_WRITE) {
    92 		return GNOME_VFS_ERROR_NOT_PERMITTED;
    93 	}
    94 
    95 	if (gnome_vfs_uri_get_host_name (uri) == NULL) {
    96 		return GNOME_VFS_ERROR_INVALID_HOST_NAME;
    97 	}
    98 
    99 	if ((NULL == myth_handle) || !myth_handle->configured) {
   100 		myth_handle = g_new0 (MythtvHandle, 1);
   101 
   102 		myth_handle->configured = FALSE;
   103 
   104 		myth_handle->is_livetv = FALSE;
   105 
   106 		/* Initialize mythtv handler */
   107 		myth_handle->file_transfer = NULL;
   108 		myth_handle->livetv = NULL;
   109 		myth_handle->mythtv_version = MYTHTV_VERSION_DEFAULT;
   110 		myth_handle->bytes_read = 0;
   111 		myth_handle->content_size = (GnomeVFSFileSize) - 1;
   112 
   113 		/* Creates and fills out the backend info structure */
   114 		backend_info =
   115 		    gmyth_backend_info_new_with_uri
   116 		    (gnome_vfs_unescape_string
   117 		     (gnome_vfs_uri_to_string
   118 		      (uri, GNOME_VFS_URI_HIDE_NONE), ""));
   119 
   120 		/* creates an instance of  */
   121 		gmyth_uri =
   122 		    gmyth_uri_new_with_value (gnome_vfs_unescape_string
   123 					      (gnome_vfs_uri_to_string
   124 					       (uri,
   125 						GNOME_VFS_URI_HIDE_NONE),
   126 					       ""));
   127 
   128 		myth_handle->is_livetv = gmyth_uri_is_livetv (gmyth_uri);
   129 
   130 		/* Connect to the backend */
   131 		if (gmyth_uri != NULL && myth_handle->is_livetv == TRUE) {
   132 
   133 			if (NULL == myth_handle->livetv) {
   134 				myth_handle->livetv = gmyth_livetv_new ();
   135 
   136 				myth_handle->channel_name =
   137 				    gmyth_uri_get_channel_name (gmyth_uri);
   138 
   139 				g_debug ("[%s] Channel name = %s\n",
   140 					 __FUNCTION__,
   141 					 myth_handle->channel_name);
   142 
   143 				if (myth_handle->channel_name != NULL) {
   144 					if (gmyth_livetv_channel_name_setup
   145 					    (myth_handle->livetv,
   146 					     myth_handle->channel_name,
   147 					     backend_info) == FALSE) {
   148 						g_object_unref (gmyth_uri);
   149 						ret = FALSE;
   150 					}
   151 				} else {
   152 					if (gmyth_livetv_setup
   153 					    (myth_handle->livetv,
   154 					     backend_info) == FALSE) {
   155 						g_object_unref (gmyth_uri);
   156 						ret = FALSE;
   157 					}
   158 				}
   159 			}
   160 
   161 			if (NULL == myth_handle->file_transfer) {
   162 				myth_handle->file_transfer =
   163 				    gmyth_livetv_create_file_transfer
   164 				    (myth_handle->livetv);
   165 
   166 				if (NULL == myth_handle->file_transfer) {
   167 					ret = FALSE;
   168 					g_debug
   169 					    ("MythTV FileTransfer is NULL!\n");
   170 					return GNOME_VFS_ERROR_NOT_OPEN;
   171 				}
   172 
   173 				if (!gmyth_file_transfer_open
   174 				    (myth_handle->file_transfer,
   175 				     myth_handle->livetv->uri !=
   176 				     NULL ?
   177 				     gmyth_uri_get_path (myth_handle->
   178 							 livetv->
   179 							 uri) :
   180 				     myth_handle->livetv->proginfo->
   181 				     pathname->str)) {
   182 					g_debug
   183 					    ("Couldn't open MythTV FileTransfer is NULL!\n");
   184 					g_object_unref (myth_handle->
   185 							file_transfer);
   186 					myth_handle->file_transfer = NULL;
   187 					ret = FALSE;
   188 				}
   189 			}
   190 			/* if - FileTransfer is NULL, or not */
   191 		} else {
   192 
   193 			if (NULL == myth_handle->file_transfer) {
   194 
   195 				myth_handle->file_transfer =
   196 				    gmyth_file_transfer_new (backend_info);
   197 
   198 				/* Verifies if the file exists */
   199 				if (!gmyth_util_file_exists
   200 				    (backend_info,
   201 				     gmyth_uri_get_path (gmyth_uri))) {
   202 					g_object_unref (backend_info);
   203 					ret = FALSE;
   204 				}
   205 
   206 				/* sets the Playback monitor connection */
   207 				ret =
   208 				    gmyth_file_transfer_open (myth_handle->
   209 							      file_transfer,
   210 							      gmyth_uri_get_path
   211 							      (gmyth_uri));
   212 
   213 			}
   214 
   215 		}		/* if - LiveTV or not? */
   216 
   217 		if (ret == FALSE) {
   218 			g_debug ("MythTV FileTransfer open error.\n");
   219 			return GNOME_VFS_ERROR_NOT_OPEN;
   220 		}
   221 
   222 		myth_handle->configured = TRUE;
   223 
   224 		g_object_unref (backend_info);
   225 
   226 		if (gmyth_uri != NULL)
   227 			g_object_unref (gmyth_uri);
   228 
   229 		myth_handle->buffer =
   230 		    g_byte_array_sized_new (MYTHTV_BUFFER_SIZE);
   231 		myth_handle->buffer_remain = 0;
   232 
   233 		g_return_val_if_fail (myth_handle->file_transfer != NULL,
   234 				      GNOME_VFS_ERROR_NOT_OPEN);
   235 
   236 		if ( /*myth_handle->file_transfer->filesize <= 0 && */
   237 		    myth_handle->is_livetv) {
   238 			myth_handle->content_size =
   239 			    gmyth_recorder_get_file_position (myth_handle->
   240 							      livetv->
   241 							      recorder);
   242 		} else {
   243 			myth_handle->content_size =
   244 			    myth_handle->file_transfer->filesize;
   245 		}
   246 
   247 	}
   248 	/* if - configured or not? */
   249 	*method_handle = (GnomeVFSMethodHandle *) myth_handle;
   250 
   251 	return GNOME_VFS_OK;
   252 }
   253 
   254 static GnomeVFSResult
   255 do_read (GnomeVFSMethod * method,
   256 	 GnomeVFSMethodHandle * method_handle,
   257 	 gpointer buffer,
   258 	 GnomeVFSFileSize num_bytes,
   259 	 GnomeVFSFileSize * bytes_read, GnomeVFSContext * context)
   260 {
   261 	MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
   262 	GnomeVFSFileSize bytes_to_read = num_bytes;
   263 
   264 	if (!myth_handle->is_livetv
   265 	    && (myth_handle->bytes_read >= myth_handle->content_size))
   266 		return GNOME_VFS_ERROR_EOF;
   267 
   268 	/* fixme: change this to min math function */
   269 	if ((myth_handle->content_size > 0)) {
   270 		if (!myth_handle->is_livetv &&
   271 		    (num_bytes >
   272 		     (myth_handle->content_size -
   273 		      myth_handle->bytes_read))) {
   274 			bytes_to_read =
   275 			    myth_handle->content_size -
   276 			    myth_handle->bytes_read;
   277 		}
   278 	}
   279 
   280 	/* Loop sending the Myth File Transfer request:
   281 	 * Retry whilst authentication fails and we supply it. */
   282 	if ((myth_handle->buffer_remain =
   283 	     myth_handle->buffer->len) < bytes_to_read) {
   284 		gint buffer_size;
   285 
   286 		while (MYTHTV_BUFFER_SIZE != myth_handle->buffer_remain) {
   287 
   288 			/* resize buffer length request to no more than MYTHTV_MAX_REQUEST_SIZE */
   289 			if ((MYTHTV_BUFFER_SIZE -
   290 			     myth_handle->buffer_remain) <=
   291 			    MYTHTV_MAX_REQUEST_SIZE)
   292 				buffer_size =
   293 				    MYTHTV_BUFFER_SIZE -
   294 				    myth_handle->buffer_remain;
   295 			else
   296 				buffer_size = MYTHTV_MAX_REQUEST_SIZE;
   297 
   298 			GByteArray *tmp_buffer = g_byte_array_new ();
   299 
   300 			g_debug
   301 			    ("Asking %d bytes (there is %d bytes in the buffer)\n",
   302 			     buffer_size, myth_handle->buffer_remain);
   303 
   304 			gint len =
   305 			    gmyth_file_transfer_read (myth_handle->
   306 						      file_transfer,
   307 						      tmp_buffer,
   308 						      buffer_size, TRUE);
   309 
   310 			if (!myth_handle->is_livetv && len < 0) {
   311 				g_byte_array_free (tmp_buffer, TRUE);
   312 				g_debug ("Fail to read bytes");
   313 				return GNOME_VFS_ERROR_IO;
   314 			}
   315 			/*else if (len == 0) {
   316 			   g_byte_array_free (tmp_buffer, TRUE);
   317 			   g_warning ("End of file probably achieved");
   318 			   return GNOME_VFS_ERROR_EOF;
   319 			   } */
   320 			myth_handle->buffer =
   321 			    g_byte_array_append (myth_handle->buffer,
   322 						 tmp_buffer->data, len);
   323 
   324 			myth_handle->buffer_remain += len;
   325 
   326 			if (tmp_buffer != NULL) {
   327 				g_byte_array_free (tmp_buffer, TRUE);
   328 				tmp_buffer = NULL;
   329 			}
   330 		}		/* while - iterates until fills the internal buffer */
   331 
   332 	}
   333 	/* if - got from the network, or not */
   334 	bytes_to_read =
   335 	    (bytes_to_read >
   336 	     myth_handle->buffer_remain) ? myth_handle->
   337 	    buffer_remain : bytes_to_read;
   338 	/* gets the first buffer_size bytes from the byte array buffer variable */
   339 
   340 	g_memmove (buffer, myth_handle->buffer->data, bytes_to_read);
   341 
   342 	myth_handle->bytes_read += bytes_to_read;
   343 	myth_handle->buffer_remain -= bytes_to_read;
   344 
   345 	/* flushs the newly buffer got from byte array */
   346 	myth_handle->buffer =
   347 	    g_byte_array_remove_range (myth_handle->buffer, 0,
   348 				       bytes_to_read);
   349 	g_debug
   350 	    ("Got from %llu bytes from internal buffer. (there are %d bytes in the buffer, from a total of %llu dispatched.)\n",
   351 	     bytes_to_read, myth_handle->buffer_remain,
   352 	     myth_handle->bytes_read);
   353 
   354 	*bytes_read = bytes_to_read;
   355 
   356 	return GNOME_VFS_OK;
   357 }
   358 
   359 static GnomeVFSResult
   360 do_close (GnomeVFSMethod * method,
   361 	  GnomeVFSMethodHandle * method_handle, GnomeVFSContext * context)
   362 {
   363 
   364 	MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
   365 
   366 	//if ( NULL == myth_handle || myth_handle->configured ) {
   367 
   368 	if (myth_handle->file_transfer != NULL) {
   369 		g_object_unref (myth_handle->file_transfer);
   370 		myth_handle->file_transfer = NULL;
   371 	}
   372 
   373 	if (myth_handle->is_livetv && myth_handle->livetv != NULL) {
   374 		g_object_unref (myth_handle->livetv);
   375 		myth_handle->livetv = NULL;
   376 	}
   377 
   378 	if (myth_handle->buffer) {
   379 		g_byte_array_free (myth_handle->buffer, TRUE);
   380 		myth_handle->buffer = NULL;
   381 	}
   382 
   383 	myth_handle->configured = FALSE;
   384 
   385 	g_free (myth_handle);
   386 
   387 	myth_handle = NULL;
   388 
   389 	// }
   390 
   391 	return GNOME_VFS_OK;
   392 }
   393 
   394 static GnomeVFSResult
   395 do_get_file_info (GnomeVFSMethod * method,
   396 		  GnomeVFSURI * uri,
   397 		  GnomeVFSFileInfo * file_info,
   398 		  GnomeVFSFileInfoOptions options,
   399 		  GnomeVFSContext * context)
   400 {
   401 	GMythFileTransfer *file_transfer = NULL;
   402 	GMythRecorder *recorder = NULL;
   403 	GMythTVChain *tvchain = NULL;
   404 	GMythBackendInfo *backend_info = NULL;
   405 	GMythURI *gmyth_uri = NULL;
   406 	GMythSocket *socket = NULL;
   407 	gboolean is_livetv = FALSE;
   408 	gboolean ret = TRUE;
   409 	gboolean res = TRUE;
   410 
   411 	/* Creates and fills out the backend info structure */
   412 	backend_info =
   413 	    gmyth_backend_info_new_with_uri (gnome_vfs_unescape_string
   414 					     (gnome_vfs_uri_to_string
   415 					      (uri,
   416 					       GNOME_VFS_URI_HIDE_NONE),
   417 					      ""));
   418 
   419 	/* creates an instance of */
   420 	gmyth_uri =
   421 	    gmyth_uri_new_with_value (gnome_vfs_unescape_string
   422 				      (gnome_vfs_uri_to_string
   423 				       (uri, GNOME_VFS_URI_HIDE_NONE),
   424 				       ""));
   425 
   426 	is_livetv = gmyth_uri_is_livetv (gmyth_uri);
   427 
   428 	file_info->valid_fields = file_info->valid_fields
   429 	    | GNOME_VFS_FILE_INFO_FIELDS_TYPE
   430 	    | GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE
   431 	    | GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
   432 	file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
   433 	/* fixme: get from file extension? */
   434 	file_info->mime_type = g_strdup ("video/x-nuv");
   435 	file_info->permissions =
   436 	    GNOME_VFS_PERM_USER_READ |
   437 	    GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_GROUP_READ;
   438 
   439 	g_debug ("gnome_vfs_uri == %s | gmyth_uri == %s.\n",
   440 		 gnome_vfs_uri_get_path (uri),
   441 		 gmyth_uri_get_path (gmyth_uri));
   442 
   443 	/* Connect to the backend */
   444 	if (gmyth_uri != NULL && is_livetv == TRUE) {
   445 
   446 		/* start to get file info from LiveTV remote encoder */
   447 		socket = gmyth_socket_new ();
   448 
   449 		/* FIME: Implement this at gmyth_socket */
   450 		res =
   451 		    gmyth_socket_connect_to_backend (socket,
   452 						     backend_info->
   453 						     hostname,
   454 						     backend_info->port,
   455 						     TRUE);
   456 		if (!res) {
   457 			g_debug ("[%s] LiveTV can not connect to backend",
   458 				 __FUNCTION__);
   459 			res = FALSE;
   460 			goto error;
   461 		}
   462 
   463 		if (gmyth_remote_util_get_free_recorder_count (socket) <=
   464 		    0) {
   465 			g_debug ("No free remote encoder available.");
   466 			res = FALSE;
   467 			goto error;
   468 		}
   469 
   470 		/* Gets the recorder num */
   471 		recorder = remote_request_next_free_recorder (socket, -1);
   472 
   473 		if ( socket != NULL )
   474 			g_object_unref (socket);
   475 
   476 		if (recorder == NULL) {
   477 			g_debug ("[%s] None remote encoder available",
   478 				 __FUNCTION__);
   479 			res = FALSE;
   480 			goto error;
   481 		}
   482 
   483 		/* Init remote encoder. Opens its control socket. */
   484 		res = gmyth_recorder_setup (recorder);
   485 		if (!res) {
   486 			g_debug
   487 			    ("[%s] Fail while setting remote encoder\n",
   488 			     __FUNCTION__);
   489 			res = FALSE;
   490 			goto error;
   491 		}
   492 
   493 		/* Creates livetv chain handler */
   494 		tvchain = gmyth_tvchain_new ();
   495 		gmyth_tvchain_initialize (tvchain, backend_info);
   496 
   497 		if (tvchain == NULL || tvchain->tvchain_id == NULL) {
   498 			res = FALSE;
   499 			goto error;
   500 		}
   501 		/* Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly) */
   502 		res = gmyth_recorder_spawntv (recorder,
   503 					      gmyth_tvchain_get_id
   504 					      (tvchain));
   505 		if (!res) {
   506 			g_warning ("[%s] Fail while spawn tv\n",
   507 				   __FUNCTION__);
   508 			res = FALSE;
   509 			goto error;
   510 		}
   511 		
   512 		sleep(1);
   513 
   514 		/* DEBUG message */
   515 		GMythProgramInfo *prog_info =
   516 		    gmyth_recorder_get_current_program_info (recorder);
   517 
   518 		if (prog_info != NULL) {
   519 
   520 			g_debug ("path = %s", prog_info->pathname->str);
   521 
   522 			file_info->name =
   523 			    g_strdup (g_strrstr
   524 				      (prog_info->pathname->str, "/"));
   525 
   526 		} else {
   527 			file_info->name = g_strdup ("LiveTV.nuv");
   528 			file_info->size =
   529 			    gmyth_recorder_get_file_position (recorder);
   530 		}
   531 
   532 		if (recorder != NULL)
   533 			g_object_unref (recorder);
   534 
   535 		if (prog_info != NULL)
   536 			g_object_unref (prog_info);
   537 
   538 		if (tvchain != NULL)
   539 			g_object_unref (tvchain);
   540 
   541 		file_info->size = (GnomeVFSFileSize) - 1;
   542 
   543 	} else {
   544 
   545 		/* start to get file info from remote file encoder */
   546 		file_transfer = gmyth_file_transfer_new (backend_info);
   547 
   548 		/* Verifies if the file exists */
   549 		if (!gmyth_util_file_exists
   550 		    (backend_info, gmyth_uri_get_path (gmyth_uri))) {
   551 			g_object_unref (backend_info);
   552 			return GNOME_VFS_ERROR_NOT_FOUND;
   553 		}
   554 
   555 		/* sets the Playback monitor connection */
   556 		ret =
   557 		    gmyth_file_transfer_open (file_transfer,
   558 					      gmyth_uri_get_path
   559 					      (gmyth_uri));
   560 
   561 		file_info->name = g_strdup (gnome_vfs_uri_get_path (uri));
   562 
   563 	}			/* if - LiveTV or not? */
   564 
   565 	if (ret == FALSE) {
   566 		g_debug ("MythTV FileTransfer open error\n");
   567 		return GNOME_VFS_ERROR_NOT_OPEN;
   568 	}
   569 
   570 	if (ret == TRUE && file_transfer != NULL) {
   571 		file_info->size =
   572 		    gmyth_file_transfer_get_filesize (file_transfer);
   573 		if (file_transfer)
   574 			g_object_unref (file_transfer);
   575 	}
   576 
   577 	file_info->block_count = GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT;
   578 	file_info->io_block_size =
   579 	    GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE;
   580 
   581       error:
   582 	if (backend_info)
   583 		g_object_unref (backend_info);
   584 
   585 	if (!res)
   586 		return GNOME_VFS_ERROR_IO;
   587 
   588 	return GNOME_VFS_OK;
   589 }
   590 
   591 static gboolean
   592 do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
   593 {
   594 	return FALSE;
   595 }
   596 
   597 static GnomeVFSMethod method = {
   598 	sizeof (GnomeVFSMethod),
   599 	do_open,
   600 	NULL,
   601 	do_close,
   602 	do_read,
   603 	NULL,
   604 	NULL,
   605 	NULL,
   606 	NULL,
   607 	NULL,
   608 	NULL,
   609 	NULL,
   610 	do_get_file_info,
   611 	NULL,
   612 	do_is_local,
   613 	NULL,
   614 	NULL,
   615 	NULL,
   616 	NULL,
   617 	NULL,
   618 	NULL,
   619 	NULL,
   620 	NULL,
   621 	NULL,
   622 	NULL,
   623 	NULL,
   624 	NULL,
   625 };
   626 
   627 
   628 GnomeVFSMethod *
   629 vfs_module_init (const char *method_name, const char *args)
   630 {
   631 	return &method;
   632 }
   633 
   634 void
   635 vfs_module_shutdown (GnomeVFSMethod * method)
   636 {
   637 }