libgnomevfs2-mythtv/modules/mythtv-method.c
author melunko
Mon Mar 19 17:11:23 2007 +0000 (2007-03-19)
branchtrunk
changeset 412 60a60397ffdf
parent 405 aff8c0341462
child 441 f310d1d086b5
permissions -rwxr-xr-x
[svn r417] Added some documentation. Some string memory leak resolved. Memory handling errors in GMythStringlist solved. Some improvements in gmyth_jobqueue. Some other fixes
     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 ) {
   311 				if ( len < 0 ) {
   312 					g_byte_array_free (tmp_buffer, TRUE);
   313 					g_debug ("Fail to read bytes");
   314 					return GNOME_VFS_ERROR_IO;
   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 			} /* if */
   321 			
   322 			myth_handle->buffer =
   323 			    g_byte_array_append (myth_handle->buffer,
   324 						 tmp_buffer->data, len);
   325 
   326 			myth_handle->buffer_remain += len;
   327 
   328 			if (tmp_buffer != NULL) {
   329 				g_byte_array_free (tmp_buffer, TRUE);
   330 				tmp_buffer = NULL;
   331 			}
   332 		}		/* while - iterates until fills the internal buffer */
   333 
   334 	}
   335 	/* if - got from the network, or not */
   336 	bytes_to_read =
   337 	    (bytes_to_read >
   338 	     myth_handle->buffer_remain) ? myth_handle->
   339 	    buffer_remain : bytes_to_read;
   340 	/* gets the first buffer_size bytes from the byte array buffer variable */
   341 
   342 	g_memmove (buffer, myth_handle->buffer->data, bytes_to_read);
   343 
   344 	myth_handle->bytes_read += bytes_to_read;
   345 	myth_handle->buffer_remain -= bytes_to_read;
   346 
   347 	/* flushs the newly buffer got from byte array */
   348 	myth_handle->buffer =
   349 	    g_byte_array_remove_range (myth_handle->buffer, 0,
   350 				       bytes_to_read);
   351 	g_debug
   352 	    ("Got from %llu bytes from internal buffer. (there are %d bytes in the buffer, from a total of %llu dispatched.)\n",
   353 	     bytes_to_read, myth_handle->buffer_remain,
   354 	     myth_handle->bytes_read);
   355 
   356 	*bytes_read = bytes_to_read;
   357 
   358 	return GNOME_VFS_OK;
   359 }
   360 
   361 static GnomeVFSResult
   362 do_close (GnomeVFSMethod * method,
   363 	  GnomeVFSMethodHandle * method_handle, GnomeVFSContext * context)
   364 {
   365 
   366 	MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
   367 
   368 	//if ( NULL == myth_handle || myth_handle->configured ) {
   369 
   370 	if (myth_handle->file_transfer != NULL) {
   371 		g_object_unref (myth_handle->file_transfer);
   372 		myth_handle->file_transfer = NULL;
   373 	}
   374 
   375 	if (myth_handle->is_livetv && myth_handle->livetv != NULL) {
   376 		g_object_unref (myth_handle->livetv);
   377 		myth_handle->livetv = NULL;
   378 	}
   379 
   380 	if (myth_handle->buffer) {
   381 		g_byte_array_free (myth_handle->buffer, TRUE);
   382 		myth_handle->buffer = NULL;
   383 	}
   384 
   385 	myth_handle->configured = FALSE;
   386 
   387 	g_free (myth_handle);
   388 
   389 	myth_handle = NULL;
   390 
   391 	// }
   392 
   393 	return GNOME_VFS_OK;
   394 }
   395 
   396 static GnomeVFSResult
   397 do_get_file_info (GnomeVFSMethod * method,
   398 		  GnomeVFSURI * uri,
   399 		  GnomeVFSFileInfo * file_info,
   400 		  GnomeVFSFileInfoOptions options,
   401 		  GnomeVFSContext * context)
   402 {
   403 	GMythFileTransfer *file_transfer = NULL;
   404 	GMythRecorder *recorder = NULL;
   405 	GMythTVChain *tvchain = NULL;
   406 	GMythBackendInfo *backend_info = NULL;
   407 	GMythURI *gmyth_uri = NULL;
   408 	GMythSocket *socket = NULL;
   409 	gboolean is_livetv = FALSE;
   410 	gboolean ret = TRUE;
   411 	gboolean res = TRUE;
   412 
   413 	/* Creates and fills out the backend info structure */
   414 	backend_info =
   415 	    gmyth_backend_info_new_with_uri (gnome_vfs_unescape_string
   416 					     (gnome_vfs_uri_to_string
   417 					      (uri,
   418 					       GNOME_VFS_URI_HIDE_NONE),
   419 					      ""));
   420 
   421 	/* creates an instance of */
   422 	gmyth_uri =
   423 	    gmyth_uri_new_with_value (gnome_vfs_unescape_string
   424 				      (gnome_vfs_uri_to_string
   425 				       (uri, GNOME_VFS_URI_HIDE_NONE),
   426 				       ""));
   427 
   428 	is_livetv = gmyth_uri_is_livetv (gmyth_uri);
   429 
   430 	file_info->valid_fields = file_info->valid_fields
   431 	    | GNOME_VFS_FILE_INFO_FIELDS_TYPE
   432 	    | GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE
   433 	    | GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
   434 	file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
   435 	/* fixme: get from file extension? */
   436 	file_info->mime_type = g_strdup ("video/x-nuv");
   437 	file_info->permissions =
   438 	    GNOME_VFS_PERM_USER_READ |
   439 	    GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_GROUP_READ;
   440 
   441 	g_debug ("gnome_vfs_uri == %s | gmyth_uri == %s.\n",
   442 		 gnome_vfs_uri_get_path (uri),
   443 		 gmyth_uri_get_path (gmyth_uri));
   444 
   445 	/* Connect to the backend */
   446 	if (gmyth_uri != NULL && is_livetv == TRUE) {
   447 
   448 		/* start to get file info from LiveTV remote encoder */
   449 		socket = gmyth_socket_new ();
   450 
   451 		/* FIME: Implement this at gmyth_socket */
   452 		res =
   453 		    gmyth_socket_connect_to_backend (socket,
   454 						     backend_info->
   455 						     hostname,
   456 						     backend_info->port,
   457 						     TRUE);
   458 		if (!res) {
   459 			g_debug ("[%s] LiveTV can not connect to backend",
   460 				 __FUNCTION__);
   461 			res = FALSE;
   462 			goto error;
   463 		}
   464 
   465 		if (gmyth_remote_util_get_free_recorder_count (socket) <=
   466 		    0) {
   467 			g_debug ("No free remote encoder available.");
   468 			res = FALSE;
   469 			goto error;
   470 		}
   471 
   472 		/* Gets the recorder num */
   473 		recorder = remote_request_next_free_recorder (socket, -1);
   474 
   475 		if ( socket != NULL )
   476 			g_object_unref (socket);
   477 
   478 		if (recorder == NULL) {
   479 			g_debug ("[%s] None remote encoder available",
   480 				 __FUNCTION__);
   481 			res = FALSE;
   482 			goto error;
   483 		}
   484 
   485 		/* Init remote encoder. Opens its control socket. */
   486 		res = gmyth_recorder_setup (recorder);
   487 		if (!res) {
   488 			g_debug
   489 			    ("[%s] Fail while setting remote encoder\n",
   490 			     __FUNCTION__);
   491 			res = FALSE;
   492 			goto error;
   493 		}
   494 
   495 		/* Creates livetv chain handler */
   496 		tvchain = gmyth_tvchain_new ();
   497 		gmyth_tvchain_initialize (tvchain, backend_info);
   498 
   499 		if (tvchain == NULL || tvchain->tvchain_id == NULL) {
   500 			res = FALSE;
   501 			goto error;
   502 		}
   503 		/* Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly) */
   504 		res = gmyth_recorder_spawntv (recorder,
   505 					      gmyth_tvchain_get_id
   506 					      (tvchain));
   507 		if (!res) {
   508 			g_warning ("[%s] Fail while spawn tv\n",
   509 				   __FUNCTION__);
   510 			res = FALSE;
   511 			goto error;
   512 		}
   513 		
   514 		sleep(1);
   515 
   516 		/* DEBUG message */
   517 		GMythProgramInfo *prog_info =
   518 		    gmyth_recorder_get_current_program_info (recorder);
   519 
   520 		if (prog_info != NULL) {
   521 
   522 			g_debug ("path = %s", prog_info->pathname->str);
   523 
   524 			file_info->name =
   525 			    g_strdup (g_strrstr
   526 				      (prog_info->pathname->str, "/"));
   527 
   528 		} else {
   529 			file_info->name = g_strdup ("LiveTV.nuv");
   530 			file_info->size =
   531 			    gmyth_recorder_get_file_position (recorder);
   532 		}
   533 
   534 		if (recorder != NULL)
   535 			g_object_unref (recorder);
   536 
   537 		if (prog_info != NULL)
   538 			g_object_unref (prog_info);
   539 
   540 		if (tvchain != NULL)
   541 			g_object_unref (tvchain);
   542 
   543 		file_info->size = (GnomeVFSFileSize) - 1;
   544 
   545 	} else {
   546 
   547 		/* start to get file info from remote file encoder */
   548 		file_transfer = gmyth_file_transfer_new (backend_info);
   549 
   550 		/* Verifies if the file exists */
   551 		if (!gmyth_util_file_exists
   552 		    (backend_info, gmyth_uri_get_path (gmyth_uri))) {
   553 			g_object_unref (backend_info);
   554 			return GNOME_VFS_ERROR_NOT_FOUND;
   555 		}
   556 
   557 		/* sets the Playback monitor connection */
   558 		ret =
   559 		    gmyth_file_transfer_open (file_transfer,
   560 					      gmyth_uri_get_path
   561 					      (gmyth_uri));
   562 
   563 		file_info->name = g_strdup (gnome_vfs_uri_get_path (uri));
   564 
   565 	}			/* if - LiveTV or not? */
   566 
   567 	if (ret == FALSE) {
   568 		g_debug ("MythTV FileTransfer open error\n");
   569 		return GNOME_VFS_ERROR_NOT_OPEN;
   570 	}
   571 
   572 	if (ret == TRUE && file_transfer != NULL) {
   573 		file_info->size =
   574 		    gmyth_file_transfer_get_filesize (file_transfer);
   575 		if (file_transfer)
   576 			g_object_unref (file_transfer);
   577 	}
   578 
   579 	file_info->block_count = GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT;
   580 	file_info->io_block_size =
   581 	    GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE;
   582 
   583       error:
   584 	if (backend_info)
   585 		g_object_unref (backend_info);
   586 
   587 	if (!res)
   588 		return GNOME_VFS_ERROR_IO;
   589 
   590 	return GNOME_VFS_OK;
   591 }
   592 
   593 static gboolean
   594 do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
   595 {
   596 	return FALSE;
   597 }
   598 
   599 static GnomeVFSMethod method = {
   600 	sizeof (GnomeVFSMethod),
   601 	do_open,
   602 	NULL,
   603 	do_close,
   604 	do_read,
   605 	NULL,
   606 	NULL,
   607 	NULL,
   608 	NULL,
   609 	NULL,
   610 	NULL,
   611 	NULL,
   612 	do_get_file_info,
   613 	NULL,
   614 	do_is_local,
   615 	NULL,
   616 	NULL,
   617 	NULL,
   618 	NULL,
   619 	NULL,
   620 	NULL,
   621 	NULL,
   622 	NULL,
   623 	NULL,
   624 	NULL,
   625 	NULL,
   626 	NULL,
   627 };
   628 
   629 
   630 GnomeVFSMethod *
   631 vfs_module_init (const char *method_name, const char *args)
   632 {
   633 	return &method;
   634 }
   635 
   636 void
   637 vfs_module_shutdown (GnomeVFSMethod * method)
   638 {
   639 }