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