2 * @author Hallyson Melo <hallyson.melo@indt.org.br>
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.
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.
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
25 #include <glib/gprintf.h>
26 #include <glib/gstdio.h>
29 #include <libgnomevfs/gnome-vfs-module.h>
30 #include <libgnomevfs/gnome-vfs-utils.h>
32 #include <gmyth/gmyth_file.h>
33 #include <gmyth/gmyth_file_transfer.h>
34 #include <gmyth/gmyth_file_local.h>
35 #include <gmyth/gmyth_livetv.h>
36 #include <gmyth/gmyth_uri.h>
37 #include <gmyth/gmyth_recorder.h>
38 #include <gmyth/gmyth_backendinfo.h>
39 #include <gmyth/gmyth_util.h>
40 #include <gmyth/gmyth_remote_util.h>
41 #include <gmyth/gmyth_tvchain.h>
42 #include <gmyth/gmyth_programinfo.h>
44 #define GST_MYTHTV_ID_NUM 1
45 #define MYTHTV_VERSION_DEFAULT 30
46 #define MYTHTV_TRANSFER_MAX_WAITS 100
48 /* internal GnomeVFS plug-in buffer size ( 120 Kbytes ) */
49 #define MYTHTV_BUFFER_SIZE 80*1024
50 /* internally sized GnomeVFS plug-in buffer ( 4 Kbytes ) */
51 #define MYTHTV_MAX_VFS_BUFFER_SIZE 4096
52 /* maximum number of bytes to be requested to the MythTV backend ( 64 Kbytes ) */
53 #define MYTHTV_MAX_REQUEST_SIZE 64*1024
58 GMythBackendInfo *backend_info;
60 GMythRecorder *live_recorder;
64 gboolean is_livetv; /* it is, or not a Live TV content transfer */
65 gboolean is_local_file; /* tell if the file is local to the current content transfer */
74 static GnomeVFSResult do_read (GnomeVFSMethod * method,
75 GnomeVFSMethodHandle * method_handle,
77 GnomeVFSFileSize num_bytes,
78 GnomeVFSFileSize * bytes_read,
79 GnomeVFSContext * context);
81 static GnomeVFSResult myth_connection_start (MythtvHandle * method_handle);
82 static void myth_destroy_handle (MythtvHandle * method_handle);
83 static GnomeVFSResult myth_handle_new (GnomeVFSURI * uri,
84 MythtvHandle ** method_handle);
85 static GnomeVFSResult myth_get_file_info (MythtvHandle * myth_handle,
87 GnomeVFSFileInfo * info);
90 myth_handle_new (GnomeVFSURI * uri,
91 MythtvHandle ** method_handle)
96 _GNOME_VFS_METHOD_PARAM_CHECK (*method_handle == NULL);
98 if (gnome_vfs_uri_get_host_name (uri) == NULL) {
99 return GNOME_VFS_ERROR_INVALID_HOST_NAME;
102 *method_handle = g_new0 (MythtvHandle, 1);
103 (*method_handle)->mythtv_version = MYTHTV_VERSION_DEFAULT;
105 (*method_handle)->is_livetv = FALSE;
106 (*method_handle)->is_local_file = FALSE;
108 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
109 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
111 gchar *tmp_str3 = strstr (tmp_str2, ".nuv.avi");
112 if (tmp_str3 != NULL) {
116 (*method_handle)->backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
117 (*method_handle)->gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
125 myth_destroy_handle (MythtvHandle * method_handle)
127 //TODO: abort if in tranfer state
129 if (method_handle->backend_info != NULL) {
130 g_object_unref (method_handle->backend_info);
131 method_handle->backend_info = NULL;
134 if (method_handle->channel_name != NULL) {
135 g_free (method_handle->channel_name);
136 method_handle->channel_name = NULL;
139 if (method_handle->livetv != NULL) {
140 g_object_unref (method_handle->livetv);
141 method_handle->livetv = NULL;
144 if (method_handle->file != NULL) {
145 g_object_unref (method_handle->file);
146 method_handle->file = NULL;
149 if (method_handle->gmyth_uri != NULL) {
150 g_object_unref (method_handle->gmyth_uri);
151 method_handle->gmyth_uri = NULL;
154 g_free (method_handle);
157 static GnomeVFSResult
158 myth_get_file_info (MythtvHandle * myth_handle,
160 GnomeVFSFileInfo * info)
163 GMythBackendInfo *backend_info;
165 _GNOME_VFS_METHOD_PARAM_CHECK (info != NULL);
168 if (myth_handle == NULL) {
172 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
173 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
175 backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
176 gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
181 backend_info = g_object_ref (myth_handle->backend_info);
182 gmyth_uri = g_object_ref (myth_handle->gmyth_uri);
185 info->valid_fields = 0;
186 info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
187 GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
188 GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
190 info->type = GNOME_VFS_FILE_TYPE_REGULAR;
192 /* fixme: get from file extension? */
193 info->mime_type = g_strdup ("video/x-nuv");
194 info->permissions = GNOME_VFS_PERM_USER_READ |
195 GNOME_VFS_PERM_OTHER_READ |
196 GNOME_VFS_PERM_GROUP_READ;
199 info->name = g_strdup (gmyth_uri_get_path (gmyth_uri));
201 /* file size for remote files */
202 if ( ( myth_handle->is_livetv = gmyth_uri_is_livetv (gmyth_uri) ) == FALSE) {
203 GMythFile *file = NULL;
204 gboolean ret = FALSE;
206 /* Verifies if the file exists */
207 if (!gmyth_util_file_exists (backend_info,
208 gmyth_uri_get_path (gmyth_uri))) {
209 g_object_unref (file);
210 g_object_unref (backend_info);
211 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
212 return GNOME_VFS_ERROR_NOT_FOUND;
215 if ( ( myth_handle->is_local_file = gmyth_uri_is_local_file(gmyth_uri) ) == TRUE )
217 file = GMYTH_FILE( gmyth_file_local_new(backend_info) );
218 ret = gmyth_file_local_open ( GMYTH_FILE_LOCAL( file ) );
220 file = GMYTH_FILE( gmyth_file_transfer_new(backend_info) );
221 ret = gmyth_file_transfer_open ( GMYTH_FILE_TRANSFER(file), gmyth_uri_get_path (gmyth_uri));
225 g_object_unref (file);
226 g_object_unref (backend_info);
227 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
228 return GNOME_VFS_ERROR_NOT_FOUND;
231 info->size = gmyth_file_get_filesize (file);
232 info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SIZE;
233 g_object_unref (file);
236 g_object_unref (backend_info);
237 g_object_unref (gmyth_uri);
242 static GnomeVFSResult
243 myth_connection_start (MythtvHandle * method_handle)
245 GnomeVFSResult result = GNOME_VFS_OK;
247 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
248 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle->backend_info != NULL);
250 /* Connect to the backend */
251 if ( ( method_handle->is_livetv = gmyth_uri_is_livetv (method_handle->gmyth_uri) ) == TRUE) {
252 method_handle->livetv = gmyth_livetv_new (method_handle->backend_info);
253 method_handle->channel_name = gmyth_uri_get_channel_name (method_handle->gmyth_uri);
255 if (method_handle->channel_name != NULL) {
256 if (gmyth_livetv_channel_name_setup (method_handle->livetv,
257 method_handle->channel_name) == FALSE) {
258 result = GNOME_VFS_ERROR_INVALID_URI;
261 } else if (gmyth_livetv_setup (method_handle->livetv) == FALSE) {
262 result = GNOME_VFS_ERROR_INVALID_URI;
267 method_handle->file =
268 GMYTH_FILE( gmyth_livetv_create_file_transfer (method_handle->livetv) );
270 if (method_handle->file == NULL) {
271 result = GNOME_VFS_ERROR_INVALID_URI;
272 g_debug ("MythTV FileTransfer is NULL!\n");
276 if (!gmyth_file_transfer_open ( GMYTH_FILE_TRANSFER(method_handle->file),
277 method_handle->livetv->uri != NULL ?
278 gmyth_uri_get_path (method_handle->livetv->uri) :
279 method_handle->livetv->proginfo->pathname->str)) {
281 g_debug ("Couldn't open MythTV FileTransfer is NULL!\n");
282 result = GNOME_VFS_ERROR_NOT_OPEN;
288 /* Verifies if the file exists */
289 if (!gmyth_util_file_exists (method_handle->backend_info,
290 gmyth_uri_get_path (method_handle->gmyth_uri))) {
292 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
296 if ( ( method_handle->is_local_file = gmyth_uri_is_local_file(method_handle->gmyth_uri) ) == TRUE )
298 method_handle->file = GMYTH_FILE( gmyth_file_local_new(method_handle->backend_info) );
299 ret = gmyth_file_local_open ( GMYTH_FILE_LOCAL( method_handle->file ) );
301 method_handle->file = GMYTH_FILE( gmyth_file_transfer_new(method_handle->backend_info) );
302 ret = gmyth_file_transfer_open ( GMYTH_FILE_TRANSFER(method_handle->file),
303 gmyth_uri_get_path (method_handle->gmyth_uri));
306 /* sets the Playback monitor connection */
309 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
310 result = GNOME_VFS_ERROR_NOT_FOUND;
313 } /* if - LiveTV or not? */
315 method_handle->configured = TRUE;
317 if (method_handle->file == NULL) {
318 result = GNOME_VFS_ERROR_NOT_OPEN;
326 static GnomeVFSResult
327 do_open (GnomeVFSMethod * method,
328 GnomeVFSMethodHandle ** method_handle,
330 GnomeVFSOpenMode mode, GnomeVFSContext * context)
332 MythtvHandle *myth_handle = NULL;
333 GnomeVFSResult result = GNOME_VFS_OK;
335 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
336 _GNOME_VFS_METHOD_PARAM_CHECK (uri != NULL);
338 if (mode & GNOME_VFS_OPEN_WRITE) {
339 return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
342 result = myth_handle_new (uri, &myth_handle);
343 if (result != GNOME_VFS_OK)
346 result = myth_connection_start (myth_handle);
347 if (result != GNOME_VFS_OK) {
348 myth_destroy_handle (myth_handle);
353 *method_handle = (GnomeVFSMethodHandle *) myth_handle;
358 static GnomeVFSResult
359 do_create (GnomeVFSMethod *method,
360 GnomeVFSMethodHandle **method_handle,
362 GnomeVFSOpenMode mode,
365 GnomeVFSContext *context)
367 return GNOME_VFS_ERROR_NOT_SUPPORTED;
370 static GnomeVFSResult
371 do_close (GnomeVFSMethod * method,
372 GnomeVFSMethodHandle * method_handle,
373 GnomeVFSContext * context)
375 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
377 myth_destroy_handle (myth_handle);
383 static GnomeVFSResult
384 do_read (GnomeVFSMethod * method,
385 GnomeVFSMethodHandle * method_handle,
387 GnomeVFSFileSize num_bytes,
388 GnomeVFSFileSize * bytes_read,
389 GnomeVFSContext * context)
391 GnomeVFSResult retval = GNOME_VFS_OK;
392 MythtvHandle *myth_handle;
393 GMythFileReadResult result;
394 GByteArray *myth_buffer = g_byte_array_new ();
396 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
398 myth_handle = (MythtvHandle *) method_handle;
399 if ( myth_handle->is_local_file )
400 result = gmyth_file_local_read ( GMYTH_FILE_LOCAL(myth_handle->file),
402 num_bytes, myth_handle->is_livetv );
404 result = gmyth_file_transfer_read ( GMYTH_FILE_TRANSFER(myth_handle->file),
406 num_bytes, myth_handle->is_livetv );
408 if (result == GMYTH_FILE_READ_ERROR) {
409 retval = GNOME_VFS_ERROR_IO;
412 if (result == GMYTH_FILE_READ_EOF) {
413 retval = GNOME_VFS_ERROR_EOF;
416 if (myth_buffer->len > 0) {
417 g_memmove (buffer, myth_buffer->data, myth_buffer->len);
418 *bytes_read = (GnomeVFSFileSize) myth_buffer->len;
419 myth_handle->offset += myth_buffer->len;
420 g_byte_array_free (myth_buffer, TRUE);
426 static GnomeVFSResult
427 do_write (GnomeVFSMethod *method,
428 GnomeVFSMethodHandle *method_handle,
429 gconstpointer buffer,
430 GnomeVFSFileSize num_bytes,
431 GnomeVFSFileSize *bytes_written,
432 GnomeVFSContext *context)
434 return GNOME_VFS_ERROR_NOT_SUPPORTED;
437 static GnomeVFSResult
438 do_seek (GnomeVFSMethod *method,
439 GnomeVFSMethodHandle *method_handle,
440 GnomeVFSSeekPosition whence,
441 GnomeVFSFileOffset offset,
442 GnomeVFSContext *context)
444 MythtvHandle *myth_handle;
445 //guint64 whence_p = 0;
446 //gint64 new_offset =0;
448 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
450 myth_handle = (MythtvHandle *) method_handle;
452 g_debug ("seek offset%"G_GINT64_FORMAT" whence %d", offset, whence);
454 return GNOME_VFS_ERROR_NOT_SUPPORTED;
456 if (gmyth_uri_is_livetv (myth_handle->gmyth_uri))
460 case GNOME_VFS_SEEK_START:
463 case GNOME_VFS_SEEK_CURRENT:
464 whence_p = myth_handle->offset;
466 case GNOME_VFS_SEEK_END:
467 return GNOME_VFS_ERROR_NOT_SUPPORTED;
470 new_offset = gmyth_file_transfer_seek (myth_handle->file, offset, whence_p);
471 if (new_offset != 0) {
472 myth_handle->offset = new_offset;
476 return GNOME_VFS_ERROR_NOT_SUPPORTED;
480 static GnomeVFSResult
481 do_tell (GnomeVFSMethod *method,
482 GnomeVFSMethodHandle *method_handle,
483 GnomeVFSFileSize *offset_return)
485 MythtvHandle *myth_handle = NULL;
487 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
489 myth_handle = (MythtvHandle *) method_handle;
490 *offset_return = myth_handle->offset;
495 static GnomeVFSResult
496 do_truncate_handle (GnomeVFSMethod *method,
497 GnomeVFSMethodHandle *method_handle,
498 GnomeVFSFileSize where,
499 GnomeVFSContext *context)
501 return GNOME_VFS_ERROR_READ_ONLY;
504 static GnomeVFSResult
505 do_open_directory (GnomeVFSMethod *method,
506 GnomeVFSMethodHandle **method_handle,
508 GnomeVFSFileInfoOptions options,
509 GnomeVFSContext *context)
511 return GNOME_VFS_ERROR_NOT_SUPPORTED;
514 static GnomeVFSResult
515 do_close_directory (GnomeVFSMethod *method,
516 GnomeVFSMethodHandle *method_handle,
517 GnomeVFSContext *context)
519 return GNOME_VFS_ERROR_NOT_SUPPORTED;
522 static GnomeVFSResult
523 do_read_directory (GnomeVFSMethod *method,
524 GnomeVFSMethodHandle *method_handle,
525 GnomeVFSFileInfo *file_info,
526 GnomeVFSContext *context)
528 return GNOME_VFS_ERROR_NOT_SUPPORTED;
532 static GnomeVFSResult
533 do_get_file_info (GnomeVFSMethod * method,
535 GnomeVFSFileInfo * file_info,
536 GnomeVFSFileInfoOptions options,
537 GnomeVFSContext * context)
539 return myth_get_file_info (NULL, uri, file_info);
542 static GnomeVFSResult
543 do_get_file_info_from_handle (GnomeVFSMethod *method,
544 GnomeVFSMethodHandle *method_handle,
545 GnomeVFSFileInfo *file_info,
546 GnomeVFSFileInfoOptions options,
547 GnomeVFSContext *context)
549 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
551 return myth_get_file_info (myth_handle, NULL, file_info);
555 do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
560 static GnomeVFSResult
561 do_make_directory (GnomeVFSMethod *method,
564 GnomeVFSContext *context)
566 return GNOME_VFS_ERROR_READ_ONLY;
569 static GnomeVFSResult
570 do_remove_directory (GnomeVFSMethod *method,
572 GnomeVFSContext *context)
574 return GNOME_VFS_ERROR_READ_ONLY;
577 static GnomeVFSResult
578 do_move (GnomeVFSMethod *method,
579 GnomeVFSURI *old_uri,
580 GnomeVFSURI *new_uri,
581 gboolean force_replace,
582 GnomeVFSContext *context)
584 return GNOME_VFS_ERROR_READ_ONLY;
587 static GnomeVFSResult
588 do_unlink (GnomeVFSMethod *method,
590 GnomeVFSContext *context)
592 return GNOME_VFS_ERROR_READ_ONLY;
595 static GnomeVFSResult
596 do_check_same_fs (GnomeVFSMethod *method,
599 gboolean *same_fs_return,
600 GnomeVFSContext *context)
602 return GNOME_VFS_ERROR_NOT_SUPPORTED;
605 static GnomeVFSResult
606 do_set_file_info (GnomeVFSMethod *method,
608 const GnomeVFSFileInfo *info,
609 GnomeVFSSetFileInfoMask mask,
610 GnomeVFSContext *context)
612 return GNOME_VFS_ERROR_READ_ONLY;
615 static GnomeVFSResult
616 do_truncate (GnomeVFSMethod *method,
618 GnomeVFSFileSize where,
619 GnomeVFSContext *context)
621 return GNOME_VFS_ERROR_READ_ONLY;
624 static GnomeVFSResult
625 do_find_directory (GnomeVFSMethod *method,
626 GnomeVFSURI *near_uri,
627 GnomeVFSFindDirectoryKind kind,
628 GnomeVFSURI **result_uri,
629 gboolean create_if_needed,
630 gboolean find_if_needed,
632 GnomeVFSContext *context)
634 return GNOME_VFS_ERROR_NOT_SUPPORTED;
637 static GnomeVFSResult
638 do_create_symbolic_link (GnomeVFSMethod *method,
640 const char *target_reference,
641 GnomeVFSContext *context)
643 return GNOME_VFS_ERROR_READ_ONLY;
646 static GnomeVFSResult
647 do_monitor_add (GnomeVFSMethod *method,
648 GnomeVFSMethodHandle **method_handle_return,
650 GnomeVFSMonitorType monitor_type)
652 return GNOME_VFS_ERROR_NOT_SUPPORTED;
655 static GnomeVFSResult
656 do_monitor_cancel (GnomeVFSMethod *method,
657 GnomeVFSMethodHandle *method_handle)
659 return GNOME_VFS_ERROR_NOT_SUPPORTED;
662 static GnomeVFSResult
663 do_file_control (GnomeVFSMethod *method,
664 GnomeVFSMethodHandle *method_handle,
665 const char *operation,
666 gpointer operation_data,
667 GnomeVFSContext *context)
669 return GNOME_VFS_ERROR_NOT_SUPPORTED;
672 static GnomeVFSMethod method = {
673 sizeof (GnomeVFSMethod),
686 do_get_file_info_from_handle,
696 do_create_symbolic_link,
704 vfs_module_init (const char *method_name, const char *args)
710 vfs_module_shutdown (GnomeVFSMethod * method)