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
59 GMythBackendInfo *backend_info;
61 GMythRecorder *live_recorder;
65 gboolean is_livetv; /* it is, or not a Live TV content transfer */
66 gboolean is_local_file; /* tell if the file is local to the current content transfer */
75 static GnomeVFSResult do_read(GnomeVFSMethod * method,
76 GnomeVFSMethodHandle * method_handle,
78 GnomeVFSFileSize num_bytes,
79 GnomeVFSFileSize * bytes_read,
80 GnomeVFSContext * context);
82 static GnomeVFSResult myth_connection_start(MythtvHandle * method_handle);
83 static void myth_destroy_handle(MythtvHandle * method_handle);
84 static GnomeVFSResult myth_handle_new(GnomeVFSURI * uri,
85 MythtvHandle ** method_handle);
86 static GnomeVFSResult myth_get_file_info(MythtvHandle * myth_handle,
88 GnomeVFSFileInfo * info);
91 myth_handle_new(GnomeVFSURI * uri, MythtvHandle ** method_handle)
96 _GNOME_VFS_METHOD_PARAM_CHECK(*method_handle == NULL);
98 if (gnome_vfs_uri_get_host_name(uri) == NULL)
100 return GNOME_VFS_ERROR_INVALID_HOST_NAME;
103 *method_handle = g_new0(MythtvHandle, 1);
104 (*method_handle)->mythtv_version = MYTHTV_VERSION_DEFAULT;
106 (*method_handle)->is_livetv = FALSE;
107 (*method_handle)->is_local_file = FALSE;
109 tmp_str1 = gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE);
110 tmp_str2 = gnome_vfs_unescape_string(tmp_str1, "");
112 gchar *tmp_str3 = strstr(tmp_str2, ".nuv.avi");
113 if (tmp_str3 != NULL)
118 (*method_handle)->backend_info = gmyth_backend_info_new_with_uri(tmp_str2);
119 (*method_handle)->gmyth_uri = gmyth_uri_new_with_value(tmp_str2);
127 myth_destroy_handle(MythtvHandle * method_handle)
129 //TODO: abort if in tranfer state
131 if (method_handle->backend_info != NULL)
133 g_object_unref(method_handle->backend_info);
134 method_handle->backend_info = NULL;
137 if (method_handle->channel_name != NULL)
139 g_free(method_handle->channel_name);
140 method_handle->channel_name = NULL;
143 if (method_handle->livetv != NULL)
145 g_object_unref(method_handle->livetv);
146 method_handle->livetv = NULL;
149 if (method_handle->file != NULL)
151 g_object_unref(method_handle->file);
152 method_handle->file = NULL;
155 if (method_handle->gmyth_uri != NULL)
157 g_object_unref(method_handle->gmyth_uri);
158 method_handle->gmyth_uri = NULL;
161 g_free(method_handle);
164 static GnomeVFSResult
165 myth_get_file_info(MythtvHandle * myth_handle,
166 GnomeVFSURI * uri, GnomeVFSFileInfo * info)
169 GMythBackendInfo *backend_info;
173 _GNOME_VFS_METHOD_PARAM_CHECK(info != NULL);
175 g_debug("%s - %d", __FUNCTION__, __LINE__);
177 if (myth_handle == NULL)
182 tmp_str1 = gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE);
183 tmp_str2 = gnome_vfs_unescape_string(tmp_str1, "");
185 backend_info = gmyth_backend_info_new_with_uri(tmp_str2);
186 gmyth_uri = gmyth_uri_new_with_value(tmp_str2);
193 backend_info = g_object_ref(myth_handle->backend_info);
194 gmyth_uri = g_object_ref(myth_handle->gmyth_uri);
197 info->valid_fields = 0;
198 info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
199 GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
200 GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
202 info->type = GNOME_VFS_FILE_TYPE_REGULAR;
204 /* fixme: get from file extension? */
205 info->mime_type = g_strdup("video/x-nuv");
206 info->permissions = GNOME_VFS_PERM_USER_READ |
207 GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_GROUP_READ;
209 info->name = g_strdup(gmyth_uri_get_path(gmyth_uri));
211 /* file size for remote files */
212 is_livetv = gmyth_uri_is_livetv(gmyth_uri);
214 if (is_livetv == FALSE)
216 GMythFile *file = NULL;
217 gboolean ret = FALSE;
219 /* Verifies if the file exists */
220 if (!gmyth_util_file_exists(backend_info,
221 gmyth_uri_get_path(gmyth_uri)))
223 g_object_unref(file);
224 g_object_unref(backend_info);
225 g_debug("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
226 return GNOME_VFS_ERROR_NOT_FOUND;
229 is_local = gmyth_uri_is_local_file(gmyth_uri);
230 if (is_local == TRUE)
232 file = GMYTH_FILE(gmyth_file_local_new(backend_info));
233 ret = gmyth_file_local_open(GMYTH_FILE_LOCAL(file));
237 file = GMYTH_FILE(gmyth_file_transfer_new(backend_info));
238 ret = gmyth_file_transfer_open(GMYTH_FILE_TRANSFER(file),
239 gmyth_uri_get_path(gmyth_uri));
244 g_object_unref(file);
245 g_object_unref(backend_info);
246 g_debug("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
247 return GNOME_VFS_ERROR_NOT_FOUND;
250 info->size = gmyth_file_get_filesize(file);
251 info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SIZE;
252 g_object_unref(file);
255 g_object_unref(backend_info);
256 g_object_unref(gmyth_uri);
261 static GnomeVFSResult
262 myth_connection_start(MythtvHandle * method_handle)
264 GnomeVFSResult result = GNOME_VFS_OK;
266 _GNOME_VFS_METHOD_PARAM_CHECK(method_handle != NULL);
267 _GNOME_VFS_METHOD_PARAM_CHECK(method_handle->backend_info != NULL);
269 /* Connect to the backend */
270 if ((method_handle->is_livetv =
271 gmyth_uri_is_livetv(method_handle->gmyth_uri)) == TRUE)
273 method_handle->livetv = gmyth_livetv_new(method_handle->backend_info);
274 method_handle->channel_name =
275 gmyth_uri_get_channel_name(method_handle->gmyth_uri);
277 if (method_handle->channel_name != NULL)
279 if (gmyth_livetv_channel_name_setup(method_handle->livetv,
280 method_handle->channel_name) ==
283 result = GNOME_VFS_ERROR_INVALID_URI;
287 else if (gmyth_livetv_setup(method_handle->livetv) == FALSE)
289 result = GNOME_VFS_ERROR_INVALID_URI;
294 method_handle->file =
295 GMYTH_FILE(gmyth_livetv_create_file_transfer(method_handle->livetv));
297 if (method_handle->file == NULL)
299 result = GNOME_VFS_ERROR_INVALID_URI;
300 g_debug("MythTV FileTransfer is NULL!\n");
304 if (!gmyth_file_transfer_open(GMYTH_FILE_TRANSFER(method_handle->file),
305 method_handle->livetv->uri != NULL ?
306 gmyth_uri_get_path(method_handle->livetv->
307 uri) : method_handle->
308 livetv->proginfo->pathname->str))
311 g_debug("Couldn't open MythTV FileTransfer is NULL!\n");
312 result = GNOME_VFS_ERROR_NOT_OPEN;
319 /* Verifies if the file exists */
320 if (!gmyth_util_file_exists(method_handle->backend_info,
321 gmyth_uri_get_path(method_handle->
325 g_debug("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
329 if ((method_handle->is_local_file =
330 gmyth_uri_is_local_file(method_handle->gmyth_uri)) == TRUE)
332 method_handle->file =
333 GMYTH_FILE(gmyth_file_local_new(method_handle->backend_info));
334 ret = gmyth_file_local_open(GMYTH_FILE_LOCAL(method_handle->file));
338 method_handle->file =
339 GMYTH_FILE(gmyth_file_transfer_new(method_handle->backend_info));
341 gmyth_file_transfer_open(GMYTH_FILE_TRANSFER(method_handle->file),
342 gmyth_uri_get_path(method_handle->
346 /* sets the Playback monitor connection */
350 g_debug("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
351 result = GNOME_VFS_ERROR_NOT_FOUND;
354 } /* if - LiveTV or not? */
356 method_handle->configured = TRUE;
358 if (method_handle->file == NULL)
360 result = GNOME_VFS_ERROR_NOT_OPEN;
368 static GnomeVFSResult
369 do_open(GnomeVFSMethod * method,
370 GnomeVFSMethodHandle ** method_handle,
371 GnomeVFSURI * uri, GnomeVFSOpenMode mode, GnomeVFSContext * context)
373 MythtvHandle *myth_handle = NULL;
374 GnomeVFSResult result = GNOME_VFS_OK;
376 _GNOME_VFS_METHOD_PARAM_CHECK(method_handle != NULL);
377 _GNOME_VFS_METHOD_PARAM_CHECK(uri != NULL);
379 if (mode & GNOME_VFS_OPEN_WRITE)
381 return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
384 result = myth_handle_new(uri, &myth_handle);
385 if (result != GNOME_VFS_OK)
388 result = myth_connection_start(myth_handle);
389 if (result != GNOME_VFS_OK)
391 myth_destroy_handle(myth_handle);
396 *method_handle = (GnomeVFSMethodHandle *) myth_handle;
401 static GnomeVFSResult
402 do_create(GnomeVFSMethod * method,
403 GnomeVFSMethodHandle ** method_handle,
405 GnomeVFSOpenMode mode,
406 gboolean exclusive, guint perm, GnomeVFSContext * context)
408 return GNOME_VFS_ERROR_NOT_SUPPORTED;
411 static GnomeVFSResult
412 do_close(GnomeVFSMethod * method,
413 GnomeVFSMethodHandle * method_handle, GnomeVFSContext * context)
415 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
417 myth_destroy_handle(myth_handle);
423 static GnomeVFSResult
424 do_read(GnomeVFSMethod * method,
425 GnomeVFSMethodHandle * method_handle,
427 GnomeVFSFileSize num_bytes,
428 GnomeVFSFileSize * bytes_read, GnomeVFSContext * context)
430 GnomeVFSResult retval = GNOME_VFS_OK;
431 MythtvHandle *myth_handle;
432 GMythFileReadResult result;
433 GByteArray *myth_buffer = g_byte_array_new();
435 _GNOME_VFS_METHOD_PARAM_CHECK(method_handle != NULL);
437 myth_handle = (MythtvHandle *) method_handle;
438 if (myth_handle->is_local_file)
439 result = gmyth_file_local_read(GMYTH_FILE_LOCAL(myth_handle->file),
441 num_bytes, myth_handle->is_livetv);
443 result = gmyth_file_transfer_read(GMYTH_FILE_TRANSFER(myth_handle->file),
445 num_bytes, myth_handle->is_livetv);
447 if (result == GMYTH_FILE_READ_ERROR)
449 retval = GNOME_VFS_ERROR_IO;
452 if (result == GMYTH_FILE_READ_EOF)
454 retval = GNOME_VFS_ERROR_EOF;
457 if (myth_buffer->len > 0)
459 g_memmove(buffer, myth_buffer->data, myth_buffer->len);
460 *bytes_read = (GnomeVFSFileSize) myth_buffer->len;
461 myth_handle->offset += myth_buffer->len;
462 g_byte_array_free(myth_buffer, TRUE);
468 static GnomeVFSResult
469 do_write(GnomeVFSMethod * method,
470 GnomeVFSMethodHandle * method_handle,
471 gconstpointer buffer,
472 GnomeVFSFileSize num_bytes,
473 GnomeVFSFileSize * bytes_written, GnomeVFSContext * context)
475 return GNOME_VFS_ERROR_NOT_SUPPORTED;
478 static GnomeVFSResult
479 do_seek(GnomeVFSMethod * method,
480 GnomeVFSMethodHandle * method_handle,
481 GnomeVFSSeekPosition whence,
482 GnomeVFSFileOffset offset, GnomeVFSContext * context)
484 MythtvHandle *myth_handle;
485 guint64 whence_p = 0;
486 gint64 new_offset = 0;
488 _GNOME_VFS_METHOD_PARAM_CHECK(method_handle != NULL);
490 myth_handle = (MythtvHandle *) method_handle;
492 g_debug("seek offset %" G_GINT64_FORMAT " whence %d", offset, whence);
494 if (gmyth_uri_is_livetv(myth_handle->gmyth_uri))
495 return GNOME_VFS_ERROR_NOT_SUPPORTED;
499 case GNOME_VFS_SEEK_START:
502 case GNOME_VFS_SEEK_CURRENT:
503 whence_p = myth_handle->offset;
505 case GNOME_VFS_SEEK_END:
506 return GNOME_VFS_ERROR_NOT_SUPPORTED;
509 new_offset = gmyth_file_transfer_seek(myth_handle->file, offset, whence_p);
512 myth_handle->offset = new_offset;
516 return GNOME_VFS_ERROR_NOT_SUPPORTED;
519 static GnomeVFSResult
520 do_tell(GnomeVFSMethod * method,
521 GnomeVFSMethodHandle * method_handle,
522 GnomeVFSFileSize * offset_return)
524 MythtvHandle *myth_handle = NULL;
526 _GNOME_VFS_METHOD_PARAM_CHECK(method_handle != NULL);
528 myth_handle = (MythtvHandle *) method_handle;
529 *offset_return = myth_handle->offset;
534 static GnomeVFSResult
535 do_truncate_handle(GnomeVFSMethod * method,
536 GnomeVFSMethodHandle * method_handle,
537 GnomeVFSFileSize where, GnomeVFSContext * context)
539 return GNOME_VFS_ERROR_READ_ONLY;
542 static GnomeVFSResult
543 do_open_directory(GnomeVFSMethod * method,
544 GnomeVFSMethodHandle ** method_handle,
546 GnomeVFSFileInfoOptions options, GnomeVFSContext * context)
548 return GNOME_VFS_ERROR_NOT_SUPPORTED;
551 static GnomeVFSResult
552 do_close_directory(GnomeVFSMethod * method,
553 GnomeVFSMethodHandle * method_handle,
554 GnomeVFSContext * context)
556 return GNOME_VFS_ERROR_NOT_SUPPORTED;
559 static GnomeVFSResult
560 do_read_directory(GnomeVFSMethod * method,
561 GnomeVFSMethodHandle * method_handle,
562 GnomeVFSFileInfo * file_info, GnomeVFSContext * context)
564 return GNOME_VFS_ERROR_NOT_SUPPORTED;
568 static GnomeVFSResult
569 do_get_file_info(GnomeVFSMethod * method,
571 GnomeVFSFileInfo * file_info,
572 GnomeVFSFileInfoOptions options, GnomeVFSContext * context)
574 return myth_get_file_info(NULL, uri, file_info);
577 static GnomeVFSResult
578 do_get_file_info_from_handle(GnomeVFSMethod * method,
579 GnomeVFSMethodHandle * method_handle,
580 GnomeVFSFileInfo * file_info,
581 GnomeVFSFileInfoOptions options,
582 GnomeVFSContext * context)
584 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
586 return myth_get_file_info(myth_handle, NULL, file_info);
590 do_is_local(GnomeVFSMethod * method, const GnomeVFSURI * uri)
595 static GnomeVFSResult
596 do_make_directory(GnomeVFSMethod * method,
597 GnomeVFSURI * uri, guint perm, GnomeVFSContext * context)
599 return GNOME_VFS_ERROR_READ_ONLY;
602 static GnomeVFSResult
603 do_remove_directory(GnomeVFSMethod * method,
604 GnomeVFSURI * uri, GnomeVFSContext * context)
606 return GNOME_VFS_ERROR_READ_ONLY;
609 static GnomeVFSResult
610 do_move(GnomeVFSMethod * method,
611 GnomeVFSURI * old_uri,
612 GnomeVFSURI * new_uri,
613 gboolean force_replace, GnomeVFSContext * context)
615 return GNOME_VFS_ERROR_READ_ONLY;
618 static GnomeVFSResult
619 do_unlink(GnomeVFSMethod * method,
620 GnomeVFSURI * uri, GnomeVFSContext * context)
622 return GNOME_VFS_ERROR_READ_ONLY;
625 static GnomeVFSResult
626 do_check_same_fs(GnomeVFSMethod * method,
629 gboolean * same_fs_return, GnomeVFSContext * context)
631 return GNOME_VFS_ERROR_NOT_SUPPORTED;
634 static GnomeVFSResult
635 do_set_file_info(GnomeVFSMethod * method,
637 const GnomeVFSFileInfo * info,
638 GnomeVFSSetFileInfoMask mask, GnomeVFSContext * context)
640 return GNOME_VFS_ERROR_READ_ONLY;
643 static GnomeVFSResult
644 do_truncate(GnomeVFSMethod * method,
646 GnomeVFSFileSize where, GnomeVFSContext * context)
648 return GNOME_VFS_ERROR_READ_ONLY;
651 static GnomeVFSResult
652 do_find_directory(GnomeVFSMethod * method,
653 GnomeVFSURI * near_uri,
654 GnomeVFSFindDirectoryKind kind,
655 GnomeVFSURI ** result_uri,
656 gboolean create_if_needed,
657 gboolean find_if_needed,
658 guint permissions, GnomeVFSContext * context)
660 return GNOME_VFS_ERROR_NOT_SUPPORTED;
663 static GnomeVFSResult
664 do_create_symbolic_link(GnomeVFSMethod * method,
666 const char *target_reference,
667 GnomeVFSContext * context)
669 return GNOME_VFS_ERROR_READ_ONLY;
672 static GnomeVFSResult
673 do_monitor_add(GnomeVFSMethod * method,
674 GnomeVFSMethodHandle ** method_handle_return,
675 GnomeVFSURI * uri, GnomeVFSMonitorType monitor_type)
677 return GNOME_VFS_ERROR_NOT_SUPPORTED;
680 static GnomeVFSResult
681 do_monitor_cancel(GnomeVFSMethod * method,
682 GnomeVFSMethodHandle * method_handle)
684 return GNOME_VFS_ERROR_NOT_SUPPORTED;
687 static GnomeVFSResult
688 do_file_control(GnomeVFSMethod * method,
689 GnomeVFSMethodHandle * method_handle,
690 const char *operation,
691 gpointer operation_data, GnomeVFSContext * context)
693 return GNOME_VFS_ERROR_NOT_SUPPORTED;
696 static GnomeVFSMethod method = {
697 sizeof(GnomeVFSMethod),
710 do_get_file_info_from_handle,
720 do_create_symbolic_link,
728 vfs_module_init(const char *method_name, const char *args)
734 vfs_module_shutdown(GnomeVFSMethod * method)