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;
71 static GnomeVFSResult do_read (GnomeVFSMethod * method,
72 GnomeVFSMethodHandle * method_handle,
74 GnomeVFSFileSize num_bytes,
75 GnomeVFSFileSize * bytes_read,
76 GnomeVFSContext * context);
78 static GnomeVFSResult myth_connection_start (MythtvHandle * method_handle);
79 static void myth_destroy_handle (MythtvHandle * method_handle);
80 static GnomeVFSResult myth_handle_new (GnomeVFSURI * uri,
81 MythtvHandle ** method_handle);
82 static GnomeVFSResult myth_get_file_info (MythtvHandle * myth_handle,
84 GnomeVFSFileInfo * info);
87 myth_handle_new (GnomeVFSURI * uri,
88 MythtvHandle ** method_handle)
93 _GNOME_VFS_METHOD_PARAM_CHECK (*method_handle == NULL);
95 if (gnome_vfs_uri_get_host_name (uri) == NULL) {
96 return GNOME_VFS_ERROR_INVALID_HOST_NAME;
99 *method_handle = g_new0 (MythtvHandle, 1);
100 (*method_handle)->mythtv_version = MYTHTV_VERSION_DEFAULT;
102 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
103 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
105 (*method_handle)->backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
106 (*method_handle)->gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
114 myth_destroy_handle (MythtvHandle * method_handle)
116 //TODO: abort if in tranfer state
118 if (method_handle->backend_info != NULL) {
119 g_object_unref (method_handle->backend_info);
120 method_handle->backend_info = NULL;
123 if (method_handle->channel_name != NULL) {
124 g_free (method_handle->channel_name);
125 method_handle->channel_name = NULL;
128 if (method_handle->livetv != NULL) {
129 g_object_unref (method_handle->livetv);
130 method_handle->livetv = NULL;
133 if (method_handle->file != NULL) {
134 g_object_unref (method_handle->file);
135 method_handle->file = NULL;
138 if (method_handle->gmyth_uri != NULL) {
139 g_object_unref (method_handle->gmyth_uri);
140 method_handle->gmyth_uri = NULL;
143 g_free (method_handle);
146 static GnomeVFSResult
147 myth_get_file_info (MythtvHandle * myth_handle,
149 GnomeVFSFileInfo * info)
152 GMythBackendInfo *backend_info;
154 _GNOME_VFS_METHOD_PARAM_CHECK (info != NULL);
157 if (myth_handle == NULL) {
161 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
162 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
164 backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
165 gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
170 backend_info = g_object_ref (myth_handle->backend_info);
171 gmyth_uri = g_object_ref (myth_handle->gmyth_uri);
174 info->valid_fields = 0;
175 info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
176 GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
177 GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
179 info->type = GNOME_VFS_FILE_TYPE_REGULAR;
181 /* fixme: get from file extension? */
182 info->mime_type = g_strdup ("video/x-nuv");
183 info->permissions = GNOME_VFS_PERM_USER_READ |
184 GNOME_VFS_PERM_OTHER_READ |
185 GNOME_VFS_PERM_GROUP_READ;
188 info->name = g_strdup (gmyth_uri_get_path (gmyth_uri));
190 /* file size for remote files */
191 if (gmyth_uri_is_livetv (gmyth_uri) == FALSE) {
192 GMythFile *file = NULL;
193 gboolean ret = FALSE;
195 /* Verifies if the file exists */
196 if (!gmyth_util_file_exists (backend_info,
197 gmyth_uri_get_path (gmyth_uri))) {
198 g_object_unref (file);
199 g_object_unref (backend_info);
200 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
201 return GNOME_VFS_ERROR_NOT_FOUND;
204 if ( gmyth_uri_is_local_file(gmyth_uri) )
206 file = GMYTH_FILE( gmyth_file_local_new(backend_info) );
207 ret = gmyth_file_local_open ( GMYTH_FILE_LOCAL( file ) );
209 file = GMYTH_FILE( gmyth_file_transfer_new(backend_info) );
210 ret = gmyth_file_transfer_open ( GMYTH_FILE_TRANSFER(file), gmyth_uri_get_path (gmyth_uri));
214 g_object_unref (file);
215 g_object_unref (backend_info);
216 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
217 return GNOME_VFS_ERROR_NOT_FOUND;
220 info->size = gmyth_file_get_filesize (file);
221 info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SIZE;
222 g_object_unref (file);
225 g_object_unref (backend_info);
226 g_object_unref (gmyth_uri);
231 static GnomeVFSResult
232 myth_connection_start (MythtvHandle * method_handle)
234 GnomeVFSResult result = GNOME_VFS_OK;
236 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
237 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle->backend_info != NULL);
239 /* Connect to the backend */
240 if (gmyth_uri_is_livetv (method_handle->gmyth_uri) == TRUE) {
241 method_handle->livetv = gmyth_livetv_new (method_handle->backend_info);
242 method_handle->channel_name = gmyth_uri_get_channel_name (method_handle->gmyth_uri);
244 if (method_handle->channel_name != NULL) {
245 if (gmyth_livetv_channel_name_setup (method_handle->livetv,
246 method_handle->channel_name) == FALSE) {
247 result = GNOME_VFS_ERROR_INVALID_URI;
250 } else if (gmyth_livetv_setup (method_handle->livetv) == FALSE) {
251 result = GNOME_VFS_ERROR_INVALID_URI;
256 method_handle->file =
257 GMYTH_FILE( gmyth_livetv_create_file_transfer (method_handle->livetv) );
259 if (method_handle->file == NULL) {
260 result = GNOME_VFS_ERROR_INVALID_URI;
261 g_debug ("MythTV FileTransfer is NULL!\n");
265 if (!gmyth_file_transfer_open ( GMYTH_FILE_TRANSFER(method_handle->file),
266 method_handle->livetv->uri != NULL ?
267 gmyth_uri_get_path (method_handle->livetv->uri) :
268 method_handle->livetv->proginfo->pathname->str)) {
270 g_debug ("Couldn't open MythTV FileTransfer is NULL!\n");
271 result = GNOME_VFS_ERROR_NOT_OPEN;
277 /* Verifies if the file exists */
278 if (!gmyth_util_file_exists (method_handle->backend_info,
279 gmyth_uri_get_path (method_handle->gmyth_uri))) {
281 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
285 if ( gmyth_uri_is_local_file(method_handle->gmyth_uri) )
287 method_handle->file = GMYTH_FILE( gmyth_file_local_new(method_handle->backend_info) );
288 ret = gmyth_file_local_open ( GMYTH_FILE_LOCAL( method_handle->file ) );
290 method_handle->file = GMYTH_FILE( gmyth_file_transfer_new(method_handle->backend_info) );
291 ret = gmyth_file_transfer_open ( GMYTH_FILE_TRANSFER(method_handle->file),
292 gmyth_uri_get_path (method_handle->gmyth_uri));
295 /* sets the Playback monitor connection */
298 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
299 result = GNOME_VFS_ERROR_NOT_FOUND;
302 } /* if - LiveTV or not? */
304 method_handle->configured = TRUE;
306 if (method_handle->file == NULL) {
307 result = GNOME_VFS_ERROR_NOT_OPEN;
315 static GnomeVFSResult
316 do_open (GnomeVFSMethod * method,
317 GnomeVFSMethodHandle ** method_handle,
319 GnomeVFSOpenMode mode, GnomeVFSContext * context)
321 MythtvHandle *myth_handle = NULL;
322 GnomeVFSResult result = GNOME_VFS_OK;
324 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
325 _GNOME_VFS_METHOD_PARAM_CHECK (uri != NULL);
327 if (mode & GNOME_VFS_OPEN_WRITE) {
328 return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
331 result = myth_handle_new (uri, &myth_handle);
332 if (result != GNOME_VFS_OK)
335 result = myth_connection_start (myth_handle);
336 if (result != GNOME_VFS_OK) {
337 myth_destroy_handle (myth_handle);
342 *method_handle = (GnomeVFSMethodHandle *) myth_handle;
347 static GnomeVFSResult
348 do_create (GnomeVFSMethod *method,
349 GnomeVFSMethodHandle **method_handle,
351 GnomeVFSOpenMode mode,
354 GnomeVFSContext *context)
356 return GNOME_VFS_ERROR_NOT_SUPPORTED;
359 static GnomeVFSResult
360 do_close (GnomeVFSMethod * method,
361 GnomeVFSMethodHandle * method_handle,
362 GnomeVFSContext * context)
364 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
366 myth_destroy_handle (myth_handle);
372 static GnomeVFSResult
373 do_read (GnomeVFSMethod * method,
374 GnomeVFSMethodHandle * method_handle,
376 GnomeVFSFileSize num_bytes,
377 GnomeVFSFileSize * bytes_read,
378 GnomeVFSContext * context)
380 GnomeVFSResult retval = GNOME_VFS_OK;
381 MythtvHandle *myth_handle;
382 GMythFileReadResult result;
383 GByteArray *myth_buffer = g_byte_array_new ();
385 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
387 myth_handle = (MythtvHandle *) method_handle;
388 if ( gmyth_uri_is_local_file(myth_handle->gmyth_uri) )
389 result = gmyth_file_local_read ( GMYTH_FILE_LOCAL(myth_handle->file),
391 num_bytes, gmyth_uri_is_livetv (myth_handle->gmyth_uri));
393 result = gmyth_file_transfer_read ( GMYTH_FILE_TRANSFER(myth_handle->file),
395 num_bytes, gmyth_uri_is_livetv (myth_handle->gmyth_uri));
398 if (result == GMYTH_FILE_READ_ERROR) {
399 retval = GNOME_VFS_ERROR_IO;
402 if (result == GMYTH_FILE_READ_EOF) {
403 retval = GNOME_VFS_ERROR_EOF;
406 if (myth_buffer->len > 0) {
407 g_memmove (buffer, myth_buffer->data, myth_buffer->len);
408 *bytes_read = (GnomeVFSFileSize) myth_buffer->len;
409 myth_handle->offset += myth_buffer->len;
410 g_byte_array_free (myth_buffer, TRUE);
416 static GnomeVFSResult
417 do_write (GnomeVFSMethod *method,
418 GnomeVFSMethodHandle *method_handle,
419 gconstpointer buffer,
420 GnomeVFSFileSize num_bytes,
421 GnomeVFSFileSize *bytes_written,
422 GnomeVFSContext *context)
424 return GNOME_VFS_ERROR_NOT_SUPPORTED;
427 static GnomeVFSResult
428 do_seek (GnomeVFSMethod *method,
429 GnomeVFSMethodHandle *method_handle,
430 GnomeVFSSeekPosition whence,
431 GnomeVFSFileOffset offset,
432 GnomeVFSContext *context)
434 MythtvHandle *myth_handle;
435 //guint64 whence_p = 0;
436 //gint64 new_offset =0;
438 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
440 myth_handle = (MythtvHandle *) method_handle;
442 g_debug ("seek offset%"G_GINT64_FORMAT" whence %d", offset, whence);
444 return GNOME_VFS_ERROR_NOT_SUPPORTED;
446 if (gmyth_uri_is_livetv (myth_handle->gmyth_uri))
450 case GNOME_VFS_SEEK_START:
453 case GNOME_VFS_SEEK_CURRENT:
454 whence_p = myth_handle->offset;
456 case GNOME_VFS_SEEK_END:
457 return GNOME_VFS_ERROR_NOT_SUPPORTED;
460 new_offset = gmyth_file_transfer_seek (myth_handle->file, offset, whence_p);
461 if (new_offset != 0) {
462 myth_handle->offset = new_offset;
466 return GNOME_VFS_ERROR_NOT_SUPPORTED;
470 static GnomeVFSResult
471 do_tell (GnomeVFSMethod *method,
472 GnomeVFSMethodHandle *method_handle,
473 GnomeVFSFileSize *offset_return)
475 MythtvHandle *myth_handle = NULL;
477 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
479 myth_handle = (MythtvHandle *) method_handle;
480 *offset_return = myth_handle->offset;
485 static GnomeVFSResult
486 do_truncate_handle (GnomeVFSMethod *method,
487 GnomeVFSMethodHandle *method_handle,
488 GnomeVFSFileSize where,
489 GnomeVFSContext *context)
491 return GNOME_VFS_ERROR_READ_ONLY;
494 static GnomeVFSResult
495 do_open_directory (GnomeVFSMethod *method,
496 GnomeVFSMethodHandle **method_handle,
498 GnomeVFSFileInfoOptions options,
499 GnomeVFSContext *context)
501 return GNOME_VFS_ERROR_NOT_SUPPORTED;
504 static GnomeVFSResult
505 do_close_directory (GnomeVFSMethod *method,
506 GnomeVFSMethodHandle *method_handle,
507 GnomeVFSContext *context)
509 return GNOME_VFS_ERROR_NOT_SUPPORTED;
512 static GnomeVFSResult
513 do_read_directory (GnomeVFSMethod *method,
514 GnomeVFSMethodHandle *method_handle,
515 GnomeVFSFileInfo *file_info,
516 GnomeVFSContext *context)
518 return GNOME_VFS_ERROR_NOT_SUPPORTED;
522 static GnomeVFSResult
523 do_get_file_info (GnomeVFSMethod * method,
525 GnomeVFSFileInfo * file_info,
526 GnomeVFSFileInfoOptions options,
527 GnomeVFSContext * context)
529 return myth_get_file_info (NULL, uri, file_info);
532 static GnomeVFSResult
533 do_get_file_info_from_handle (GnomeVFSMethod *method,
534 GnomeVFSMethodHandle *method_handle,
535 GnomeVFSFileInfo *file_info,
536 GnomeVFSFileInfoOptions options,
537 GnomeVFSContext *context)
539 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
541 return myth_get_file_info (myth_handle, NULL, file_info);
545 do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
550 static GnomeVFSResult
551 do_make_directory (GnomeVFSMethod *method,
554 GnomeVFSContext *context)
556 return GNOME_VFS_ERROR_READ_ONLY;
559 static GnomeVFSResult
560 do_remove_directory (GnomeVFSMethod *method,
562 GnomeVFSContext *context)
564 return GNOME_VFS_ERROR_READ_ONLY;
567 static GnomeVFSResult
568 do_move (GnomeVFSMethod *method,
569 GnomeVFSURI *old_uri,
570 GnomeVFSURI *new_uri,
571 gboolean force_replace,
572 GnomeVFSContext *context)
574 return GNOME_VFS_ERROR_READ_ONLY;
577 static GnomeVFSResult
578 do_unlink (GnomeVFSMethod *method,
580 GnomeVFSContext *context)
582 return GNOME_VFS_ERROR_READ_ONLY;
585 static GnomeVFSResult
586 do_check_same_fs (GnomeVFSMethod *method,
589 gboolean *same_fs_return,
590 GnomeVFSContext *context)
592 return GNOME_VFS_ERROR_NOT_SUPPORTED;
595 static GnomeVFSResult
596 do_set_file_info (GnomeVFSMethod *method,
598 const GnomeVFSFileInfo *info,
599 GnomeVFSSetFileInfoMask mask,
600 GnomeVFSContext *context)
602 return GNOME_VFS_ERROR_READ_ONLY;
605 static GnomeVFSResult
606 do_truncate (GnomeVFSMethod *method,
608 GnomeVFSFileSize where,
609 GnomeVFSContext *context)
611 return GNOME_VFS_ERROR_READ_ONLY;
614 static GnomeVFSResult
615 do_find_directory (GnomeVFSMethod *method,
616 GnomeVFSURI *near_uri,
617 GnomeVFSFindDirectoryKind kind,
618 GnomeVFSURI **result_uri,
619 gboolean create_if_needed,
620 gboolean find_if_needed,
622 GnomeVFSContext *context)
624 return GNOME_VFS_ERROR_NOT_SUPPORTED;
627 static GnomeVFSResult
628 do_create_symbolic_link (GnomeVFSMethod *method,
630 const char *target_reference,
631 GnomeVFSContext *context)
633 return GNOME_VFS_ERROR_READ_ONLY;
636 static GnomeVFSResult
637 do_monitor_add (GnomeVFSMethod *method,
638 GnomeVFSMethodHandle **method_handle_return,
640 GnomeVFSMonitorType monitor_type)
642 return GNOME_VFS_ERROR_NOT_SUPPORTED;
645 static GnomeVFSResult
646 do_monitor_cancel (GnomeVFSMethod *method,
647 GnomeVFSMethodHandle *method_handle)
649 return GNOME_VFS_ERROR_NOT_SUPPORTED;
652 static GnomeVFSResult
653 do_file_control (GnomeVFSMethod *method,
654 GnomeVFSMethodHandle *method_handle,
655 const char *operation,
656 gpointer operation_data,
657 GnomeVFSContext *context)
659 return GNOME_VFS_ERROR_NOT_SUPPORTED;
662 static GnomeVFSMethod method = {
663 sizeof (GnomeVFSMethod),
676 do_get_file_info_from_handle,
686 do_create_symbolic_link,
694 vfs_module_init (const char *method_name, const char *args)
700 vfs_module_shutdown (GnomeVFSMethod * method)