libgnomevfs2-mythtv/modules/mythtv-method.c
author melunko
Fri Nov 24 21:43:04 2006 +0000 (2006-11-24)
branchtrunk
changeset 112 a99f881ed02f
parent 48 a30f59f76bda
child 116 e3cedfae0f2e
permissions -rwxr-xr-x
[svn r113] A lot of changes at gmyth_socket.c and gmyth_filetransfer. From now on, file transfer dont handle the monitor socket, and the QUERY_RECORDER messages - dont call spawn livetv, dont call get_file_position, is_recording, etc. These are gmyth_livetv responsibility. File transfer now has the _new, _open, _seek, and _close methods, just like gnomevfs does.
     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_file_transfer.h"
    31 
    32 #define GST_MYTHTV_ID_NUM               1
    33 #define MYTHTV_VERSION_DEFAULT          30
    34 
    35 #define MYTHTV_BUFFER_SIZE		1024*64
    36 
    37 static GnomeVFSResult do_read (GnomeVFSMethod *method,
    38                                GnomeVFSMethodHandle *method_handle,
    39                                gpointer buffer,
    40                                GnomeVFSFileSize num_bytes,
    41                                GnomeVFSFileSize *bytes_read,
    42                                GnomeVFSContext *context);
    43 
    44 typedef struct {
    45     GMythFileTransfer *file_transfer;
    46     
    47     gint mythtv_version;
    48     guint64 content_size;
    49     guint64 bytes_read;
    50 
    51     guint8 *buffer;
    52     gsize buffer_offset;
    53     gsize buffer_remain;
    54 } MythtvHandle;
    55 
    56 
    57 
    58 static GnomeVFSResult
    59 do_open (GnomeVFSMethod *method,
    60          GnomeVFSMethodHandle **method_handle,
    61          GnomeVFSURI *uri,
    62          GnomeVFSOpenMode mode,
    63          GnomeVFSContext *context)
    64 {
    65 
    66     const gchar *user, *password, *host, *transfer_uri;
    67     MythtvHandle *myth_handle;
    68 
    69     GString *uri_str;
    70     guint port;
    71     gchar *path;
    72     gboolean ret;
    73 
    74     _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
    75     _GNOME_VFS_METHOD_PARAM_CHECK (uri != NULL);
    76 
    77     g_debug ("[%s] Calling do_open function", __FUNCTION__);
    78 	    
    79     myth_handle = g_new0 (MythtvHandle, 1);
    80 
    81     if (mode & GNOME_VFS_OPEN_WRITE) {
    82         return GNOME_VFS_ERROR_NOT_PERMITTED;
    83     }
    84 
    85     if ((host = gnome_vfs_uri_get_host_name (uri)) == NULL) {
    86 	return GNOME_VFS_ERROR_INVALID_HOST_NAME;
    87     }
    88 
    89     /* Parse URI */
    90     path = gnome_vfs_unescape_string (uri->text, NULL);
    91     port = gnome_vfs_uri_get_host_port (uri);
    92     user = gnome_vfs_uri_get_user_name (uri);
    93     password = gnome_vfs_uri_get_password (uri);
    94 
    95     transfer_uri = gnome_vfs_uri_to_string (uri, 
    96 		    GNOME_VFS_URI_HIDE_USER_NAME | GNOME_VFS_URI_HIDE_PASSWORD);
    97    
    98     /* Initialize mythtv handler*/
    99     myth_handle->file_transfer = NULL;
   100     myth_handle->mythtv_version = MYTHTV_VERSION_DEFAULT;
   101     myth_handle->bytes_read = 0;
   102     myth_handle->content_size = -1;
   103 
   104     /* Connect to the backend */
   105     myth_handle->file_transfer = gmyth_file_transfer_new ();
   106 
   107     g_return_val_if_fail (myth_handle->file_transfer != NULL, GNOME_VFS_ERROR_NOT_OPEN);
   108 
   109     /* sets the Playback monitor connection */
   110     uri_str = g_string_new (transfer_uri);
   111     ret = gmyth_file_transfer_open (myth_handle->file_transfer, uri_str);
   112     if (ret == FALSE) {
   113         g_printerr ("Mythtv FileTransfer open error\n");
   114         return GNOME_VFS_ERROR_NOT_OPEN;
   115     }
   116     g_string_free (uri_str, TRUE);
   117 
   118     // TODO: Verify if file exists in the backend
   119 
   120     myth_handle->content_size = myth_handle->file_transfer->filesize;
   121     
   122     myth_handle->buffer = g_malloc0 (MYTHTV_BUFFER_SIZE);
   123     myth_handle->buffer_offset = 0;
   124     myth_handle->buffer_remain = 0;
   125 
   126     *method_handle = (GnomeVFSMethodHandle *) myth_handle;
   127 
   128     return GNOME_VFS_OK;
   129 }
   130 
   131 static GnomeVFSResult
   132 do_read (GnomeVFSMethod *method,
   133          GnomeVFSMethodHandle *method_handle,
   134          gpointer buffer,
   135          GnomeVFSFileSize num_bytes,
   136          GnomeVFSFileSize *bytes_read,
   137          GnomeVFSContext *context)
   138 {
   139     MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
   140     GnomeVFSFileSize bytes_to_read;
   141 
   142     g_debug ("do_read(): file size: %llu, already read: %llu, requested: %llu, buffer_offset: %du, buffer_remain: %du", 
   143 		    myth_handle->content_size, myth_handle->bytes_read, num_bytes, 
   144 		    myth_handle->buffer_offset, myth_handle->buffer_remain);
   145 
   146     *bytes_read = 0;
   147 
   148     if (myth_handle->bytes_read >= myth_handle->content_size)
   149         return GNOME_VFS_ERROR_EOF;
   150 
   151     // fixme: change this to min math function
   152     if (num_bytes > myth_handle->content_size - myth_handle->bytes_read)
   153 	    bytes_to_read = myth_handle->content_size - myth_handle->bytes_read;
   154     else
   155 	    bytes_to_read = num_bytes;
   156 
   157     /* Loop sending the Myth File Transfer request:
   158     * Retry whilst authentication fails and we supply it. */
   159 
   160     if (bytes_to_read > myth_handle->buffer_remain ) {
   161 	guint8 *tmp_buffer = g_malloc0 (MYTHTV_BUFFER_SIZE);
   162 	gint len;
   163 
   164 	if (myth_handle->buffer_remain > (MYTHTV_BUFFER_SIZE >> 1)) {
   165 	    // Avoid overlap creating another buffer, in the case the remaining data is bigger than half buffer size
   166 	    tmp_buffer = g_malloc0 (MYTHTV_BUFFER_SIZE);
   167 	    memcpy (tmp_buffer, myth_handle->buffer + myth_handle->buffer_offset, myth_handle->buffer_remain);
   168 	    g_free (myth_handle->buffer);
   169 	    myth_handle->buffer = tmp_buffer;
   170 	} else {
   171 	    memcpy (myth_handle->buffer, myth_handle->buffer + myth_handle->buffer_offset, myth_handle->buffer_remain);
   172 	}
   173 
   174 	g_debug ("Reading %d data from backend", MYTHTV_BUFFER_SIZE- myth_handle->buffer_remain);
   175 	
   176         len = gmyth_file_transfer_read( myth_handle->file_transfer,
   177 	            myth_handle->buffer + myth_handle->buffer_remain, 
   178 		    MYTHTV_BUFFER_SIZE- myth_handle->buffer_remain, TRUE );
   179 
   180 	if (len < 0)
   181 	    return GNOME_VFS_ERROR_IO;
   182 
   183 	myth_handle->buffer_offset = 0;
   184 	myth_handle->buffer_remain += len;
   185 	
   186     }
   187     
   188     bytes_to_read = (bytes_to_read > myth_handle->buffer_remain) ? myth_handle->buffer_remain : bytes_to_read;
   189 
   190     g_debug ("Returning %du bytes to gnomevfs", (int) bytes_to_read);
   191     memcpy (buffer, myth_handle->buffer + myth_handle->buffer_offset, bytes_to_read);
   192   
   193     myth_handle->bytes_read += bytes_to_read;
   194     myth_handle->buffer_offset += bytes_to_read;
   195     myth_handle->buffer_remain -= bytes_to_read;
   196     *bytes_read = bytes_to_read;
   197   
   198     return GNOME_VFS_OK;
   199 }
   200 
   201 static GnomeVFSResult
   202 do_close (GnomeVFSMethod *method,
   203           GnomeVFSMethodHandle *method_handle,
   204           GnomeVFSContext *context)
   205 {
   206 
   207     MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
   208 
   209     if (myth_handle->file_transfer) {
   210 	gmyth_file_transfer_close (myth_handle->file_transfer);
   211         g_object_unref (myth_handle->file_transfer);
   212 	myth_handle->file_transfer = NULL;
   213     }
   214 
   215     g_free (myth_handle);
   216 
   217     return GNOME_VFS_OK;
   218 }
   219 
   220 static GnomeVFSResult
   221 do_get_file_info (GnomeVFSMethod *method,
   222                   GnomeVFSURI *uri,
   223                   GnomeVFSFileInfo *file_info,
   224                   GnomeVFSFileInfoOptions options,
   225                   GnomeVFSContext *context)
   226 {
   227     file_info->name = g_strdup ("fixme.txt");
   228     file_info->valid_fields = file_info->valid_fields
   229         | GNOME_VFS_FILE_INFO_FIELDS_TYPE
   230         | GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE
   231         | GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
   232     file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
   233     // fixme: get from file extension?
   234     file_info->mime_type = g_strdup ("video/x-nuv");
   235     file_info->permissions =
   236         GNOME_VFS_PERM_USER_READ |
   237         GNOME_VFS_PERM_OTHER_READ |
   238         GNOME_VFS_PERM_GROUP_READ;
   239 
   240     return GNOME_VFS_OK;
   241 }
   242 
   243 static gboolean
   244 do_is_local (GnomeVFSMethod *method,
   245              const GnomeVFSURI *uri)
   246 {
   247 	return FALSE;
   248 }
   249 
   250 static GnomeVFSMethod method = {
   251 	sizeof (GnomeVFSMethod),
   252 	do_open,
   253 	NULL,
   254 	do_close,
   255 	do_read,
   256 	NULL,
   257 	NULL,
   258 	NULL,
   259 	NULL,
   260 	NULL,
   261 	NULL,
   262 	NULL,
   263 	do_get_file_info,
   264 	NULL,
   265 	do_is_local,
   266 	NULL,
   267 	NULL,
   268 	NULL,
   269 	NULL,
   270 	NULL,
   271 	NULL,
   272 	NULL,
   273 	NULL,
   274 	NULL,
   275 	NULL,
   276 	NULL,
   277 	NULL,
   278 };
   279 
   280 
   281 GnomeVFSMethod *
   282 vfs_module_init (const char *method_name, const char *args)
   283 {
   284 	return &method;
   285 }
   286 
   287 void
   288 vfs_module_shutdown (GnomeVFSMethod *method)
   289 {
   290 }