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_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>
42 #define GST_MYTHTV_ID_NUM 1
43 #define MYTHTV_VERSION_DEFAULT 30
44 #define MYTHTV_TRANSFER_MAX_WAITS 100
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
54 GMythFileTransfer *file_transfer;
56 GMythBackendInfo *backend_info;
58 GMythRecorder *live_recorder;
69 static GnomeVFSResult do_read (GnomeVFSMethod * method,
70 GnomeVFSMethodHandle * method_handle,
72 GnomeVFSFileSize num_bytes,
73 GnomeVFSFileSize * bytes_read,
74 GnomeVFSContext * context);
76 static GnomeVFSResult myth_connection_start (MythtvHandle * method_handle);
77 static void myth_destroy_handle (MythtvHandle * method_handle);
78 static GnomeVFSResult myth_handle_new (GnomeVFSURI * uri,
79 MythtvHandle ** method_handle);
80 static GnomeVFSResult myth_get_file_info (MythtvHandle * myth_handle,
82 GnomeVFSFileInfo * info);
85 myth_handle_new (GnomeVFSURI * uri,
86 MythtvHandle ** method_handle)
91 _GNOME_VFS_METHOD_PARAM_CHECK (*method_handle == NULL);
93 if (gnome_vfs_uri_get_host_name (uri) == NULL) {
94 return GNOME_VFS_ERROR_INVALID_HOST_NAME;
97 *method_handle = g_new0 (MythtvHandle, 1);
98 (*method_handle)->mythtv_version = MYTHTV_VERSION_DEFAULT;
100 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
101 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
103 (*method_handle)->backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
104 (*method_handle)->gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
112 myth_destroy_handle (MythtvHandle * method_handle)
114 //TODO: abort if in tranfer state
116 if (method_handle->backend_info != NULL) {
117 g_object_unref (method_handle->backend_info);
118 method_handle->backend_info = NULL;
121 if (method_handle->channel_name != NULL) {
122 g_free (method_handle->channel_name);
123 method_handle->channel_name = NULL;
126 if (method_handle->livetv != NULL) {
127 g_object_unref (method_handle->livetv);
128 method_handle->livetv = NULL;
131 if (method_handle->file_transfer != NULL) {
132 g_object_unref (method_handle->file_transfer);
133 method_handle->file_transfer = NULL;
136 if (method_handle->gmyth_uri != NULL) {
137 g_object_unref (method_handle->gmyth_uri);
138 method_handle->gmyth_uri = NULL;
141 g_free (method_handle);
144 static GnomeVFSResult
145 myth_get_file_info (MythtvHandle * myth_handle,
147 GnomeVFSFileInfo * info)
150 GMythBackendInfo *backend_info;
152 _GNOME_VFS_METHOD_PARAM_CHECK (info != NULL);
155 if (myth_handle == NULL) {
159 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
160 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
162 backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
163 gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
168 backend_info = g_object_ref (myth_handle->backend_info);
169 gmyth_uri = g_object_ref (myth_handle->gmyth_uri);
172 info->valid_fields = 0;
173 info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
174 GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
175 GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
177 info->type = GNOME_VFS_FILE_TYPE_REGULAR;
179 /* fixme: get from file extension? */
180 info->mime_type = g_strdup ("video/x-nuv");
181 info->permissions = GNOME_VFS_PERM_USER_READ |
182 GNOME_VFS_PERM_OTHER_READ |
183 GNOME_VFS_PERM_GROUP_READ;
186 info->name = g_strdup (gmyth_uri_get_path (gmyth_uri));
188 /* file size for remote files */
189 if (gmyth_uri_is_livetv (gmyth_uri) == FALSE) {
190 GMythFileTransfer *file_transfer = gmyth_file_transfer_new (backend_info);
192 /* Verifies if the file exists */
193 if (!gmyth_util_file_exists (backend_info,
194 gmyth_uri_get_path (gmyth_uri))) {
195 g_object_unref (file_transfer);
196 g_object_unref (backend_info);
197 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
198 return GNOME_VFS_ERROR_NOT_FOUND;
201 if (!gmyth_file_transfer_open (file_transfer, gmyth_uri_get_path (gmyth_uri))) {
202 g_object_unref (file_transfer);
203 g_object_unref (backend_info);
204 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
205 return GNOME_VFS_ERROR_NOT_FOUND;
208 info->size = gmyth_file_transfer_get_filesize (file_transfer);
209 info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SIZE;
210 g_object_unref (file_transfer);
213 g_object_unref (backend_info);
214 g_object_unref (gmyth_uri);
219 static GnomeVFSResult
220 myth_connection_start (MythtvHandle * method_handle)
222 GnomeVFSResult result = GNOME_VFS_OK;
224 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
225 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle->backend_info != NULL);
227 /* Connect to the backend */
228 if (gmyth_uri_is_livetv (method_handle->gmyth_uri) == TRUE) {
229 method_handle->livetv = gmyth_livetv_new (method_handle->backend_info);
230 method_handle->channel_name = gmyth_uri_get_channel_name (method_handle->gmyth_uri);
232 if (method_handle->channel_name != NULL) {
233 if (gmyth_livetv_channel_name_setup (method_handle->livetv,
234 method_handle->channel_name) == FALSE) {
235 result = GNOME_VFS_ERROR_INVALID_URI;
238 } else if (gmyth_livetv_setup (method_handle->livetv) == FALSE) {
239 result = GNOME_VFS_ERROR_INVALID_URI;
244 method_handle->file_transfer =
245 gmyth_livetv_create_file_transfer (method_handle->livetv);
247 if (method_handle->file_transfer == NULL) {
248 result = GNOME_VFS_ERROR_INVALID_URI;
249 g_debug ("MythTV FileTransfer is NULL!\n");
253 if (!gmyth_file_transfer_open (method_handle->file_transfer,
254 method_handle->livetv->uri != NULL ?
255 gmyth_uri_get_path (method_handle->livetv->uri) :
256 method_handle->livetv->proginfo->pathname->str)) {
258 g_debug ("Couldn't open MythTV FileTransfer is NULL!\n");
259 result = GNOME_VFS_ERROR_NOT_OPEN;
264 method_handle->file_transfer =
265 gmyth_file_transfer_new (method_handle->backend_info);
267 /* Verifies if the file exists */
268 if (!gmyth_util_file_exists (method_handle->backend_info,
269 gmyth_uri_get_path (method_handle->gmyth_uri))) {
271 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
275 /* sets the Playback monitor connection */
276 if (!gmyth_file_transfer_open (method_handle->file_transfer,
277 gmyth_uri_get_path (method_handle->gmyth_uri))) {
279 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
280 result = GNOME_VFS_ERROR_NOT_FOUND;
283 } /* if - LiveTV or not? */
285 method_handle->configured = TRUE;
287 if (method_handle->file_transfer == NULL) {
288 result = GNOME_VFS_ERROR_NOT_OPEN;
296 static GnomeVFSResult
297 do_open (GnomeVFSMethod * method,
298 GnomeVFSMethodHandle ** method_handle,
300 GnomeVFSOpenMode mode, GnomeVFSContext * context)
302 MythtvHandle *myth_handle = NULL;
303 GnomeVFSResult result = GNOME_VFS_OK;
305 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
306 _GNOME_VFS_METHOD_PARAM_CHECK (uri != NULL);
308 if (mode & GNOME_VFS_OPEN_WRITE) {
309 return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
312 result = myth_handle_new (uri, &myth_handle);
313 if (result != GNOME_VFS_OK)
316 result = myth_connection_start (myth_handle);
317 if (result != GNOME_VFS_OK) {
318 myth_destroy_handle (myth_handle);
323 *method_handle = (GnomeVFSMethodHandle *) myth_handle;
328 static GnomeVFSResult
329 do_create (GnomeVFSMethod *method,
330 GnomeVFSMethodHandle **method_handle,
332 GnomeVFSOpenMode mode,
335 GnomeVFSContext *context)
337 return GNOME_VFS_ERROR_NOT_SUPPORTED;
340 static GnomeVFSResult
341 do_close (GnomeVFSMethod * method,
342 GnomeVFSMethodHandle * method_handle,
343 GnomeVFSContext * context)
345 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
347 myth_destroy_handle (myth_handle);
353 static GnomeVFSResult
354 do_read (GnomeVFSMethod * method,
355 GnomeVFSMethodHandle * method_handle,
357 GnomeVFSFileSize num_bytes,
358 GnomeVFSFileSize * bytes_read,
359 GnomeVFSContext * context)
361 GnomeVFSResult retval = GNOME_VFS_OK;
362 MythtvHandle *myth_handle;
363 GMythFileTransferReadResult result;
364 GByteArray *myth_buffer = g_byte_array_new ();
366 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
368 myth_handle = (MythtvHandle *) method_handle;
369 result = gmyth_file_transfer_read (myth_handle->file_transfer,
371 num_bytes, gmyth_uri_is_livetv (myth_handle->gmyth_uri));
374 if (result == GMYTH_FILE_TRANSFER_READ_ERROR) {
375 retval = GNOME_VFS_ERROR_IO;
378 if (result == GMYTH_FILE_TRANSFER_READ_EOF) {
379 retval = GNOME_VFS_ERROR_EOF;
382 if (myth_buffer->len > 0) {
383 g_memmove (buffer, myth_buffer->data, myth_buffer->len);
384 *bytes_read = (GnomeVFSFileSize) myth_buffer->len;
385 myth_handle->offset += myth_buffer->len;
386 g_byte_array_free (myth_buffer, TRUE);
393 static GnomeVFSResult
394 do_write (GnomeVFSMethod *method,
395 GnomeVFSMethodHandle *method_handle,
396 gconstpointer buffer,
397 GnomeVFSFileSize num_bytes,
398 GnomeVFSFileSize *bytes_written,
399 GnomeVFSContext *context)
401 return GNOME_VFS_ERROR_NOT_SUPPORTED;
404 static GnomeVFSResult
405 do_seek (GnomeVFSMethod *method,
406 GnomeVFSMethodHandle *method_handle,
407 GnomeVFSSeekPosition whence,
408 GnomeVFSFileOffset offset,
409 GnomeVFSContext *context)
411 MythtvHandle *myth_handle;
412 //guint64 whence_p = 0;
413 //gint64 new_offset =0;
415 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
417 myth_handle = (MythtvHandle *) method_handle;
419 g_debug ("seek offset%"G_GINT64_FORMAT" whence %d", offset, whence);
421 return GNOME_VFS_ERROR_NOT_SUPPORTED;
423 if (gmyth_uri_is_livetv (myth_handle->gmyth_uri))
427 case GNOME_VFS_SEEK_START:
430 case GNOME_VFS_SEEK_CURRENT:
431 whence_p = myth_handle->offset;
433 case GNOME_VFS_SEEK_END:
434 return GNOME_VFS_ERROR_NOT_SUPPORTED;
437 new_offset = gmyth_file_transfer_seek (myth_handle->file_transfer, offset, whence_p);
438 if (new_offset != 0) {
439 myth_handle->offset = new_offset;
443 return GNOME_VFS_ERROR_NOT_SUPPORTED;
447 static GnomeVFSResult
448 do_tell (GnomeVFSMethod *method,
449 GnomeVFSMethodHandle *method_handle,
450 GnomeVFSFileSize *offset_return)
452 MythtvHandle *myth_handle = NULL;
454 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
456 myth_handle = (MythtvHandle *) method_handle;
457 *offset_return = myth_handle->offset;
462 static GnomeVFSResult
463 do_truncate_handle (GnomeVFSMethod *method,
464 GnomeVFSMethodHandle *method_handle,
465 GnomeVFSFileSize where,
466 GnomeVFSContext *context)
468 return GNOME_VFS_ERROR_READ_ONLY;
471 static GnomeVFSResult
472 do_open_directory (GnomeVFSMethod *method,
473 GnomeVFSMethodHandle **method_handle,
475 GnomeVFSFileInfoOptions options,
476 GnomeVFSContext *context)
478 return GNOME_VFS_ERROR_NOT_SUPPORTED;
481 static GnomeVFSResult
482 do_close_directory (GnomeVFSMethod *method,
483 GnomeVFSMethodHandle *method_handle,
484 GnomeVFSContext *context)
486 return GNOME_VFS_ERROR_NOT_SUPPORTED;
489 static GnomeVFSResult
490 do_read_directory (GnomeVFSMethod *method,
491 GnomeVFSMethodHandle *method_handle,
492 GnomeVFSFileInfo *file_info,
493 GnomeVFSContext *context)
495 return GNOME_VFS_ERROR_NOT_SUPPORTED;
499 static GnomeVFSResult
500 do_get_file_info (GnomeVFSMethod * method,
502 GnomeVFSFileInfo * file_info,
503 GnomeVFSFileInfoOptions options,
504 GnomeVFSContext * context)
506 return myth_get_file_info (NULL, uri, file_info);
509 static GnomeVFSResult
510 do_get_file_info_from_handle (GnomeVFSMethod *method,
511 GnomeVFSMethodHandle *method_handle,
512 GnomeVFSFileInfo *file_info,
513 GnomeVFSFileInfoOptions options,
514 GnomeVFSContext *context)
516 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
518 return myth_get_file_info (myth_handle, NULL, file_info);
522 do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
527 static GnomeVFSResult
528 do_make_directory (GnomeVFSMethod *method,
531 GnomeVFSContext *context)
533 return GNOME_VFS_ERROR_READ_ONLY;
536 static GnomeVFSResult
537 do_remove_directory (GnomeVFSMethod *method,
539 GnomeVFSContext *context)
541 return GNOME_VFS_ERROR_READ_ONLY;
544 static GnomeVFSResult
545 do_move (GnomeVFSMethod *method,
546 GnomeVFSURI *old_uri,
547 GnomeVFSURI *new_uri,
548 gboolean force_replace,
549 GnomeVFSContext *context)
551 return GNOME_VFS_ERROR_READ_ONLY;
554 static GnomeVFSResult
555 do_unlink (GnomeVFSMethod *method,
557 GnomeVFSContext *context)
559 return GNOME_VFS_ERROR_READ_ONLY;
562 static GnomeVFSResult
563 do_check_same_fs (GnomeVFSMethod *method,
566 gboolean *same_fs_return,
567 GnomeVFSContext *context)
569 return GNOME_VFS_ERROR_NOT_SUPPORTED;
572 static GnomeVFSResult
573 do_set_file_info (GnomeVFSMethod *method,
575 const GnomeVFSFileInfo *info,
576 GnomeVFSSetFileInfoMask mask,
577 GnomeVFSContext *context)
579 return GNOME_VFS_ERROR_READ_ONLY;
582 static GnomeVFSResult
583 do_truncate (GnomeVFSMethod *method,
585 GnomeVFSFileSize where,
586 GnomeVFSContext *context)
588 return GNOME_VFS_ERROR_READ_ONLY;
591 static GnomeVFSResult
592 do_find_directory (GnomeVFSMethod *method,
593 GnomeVFSURI *near_uri,
594 GnomeVFSFindDirectoryKind kind,
595 GnomeVFSURI **result_uri,
596 gboolean create_if_needed,
597 gboolean find_if_needed,
599 GnomeVFSContext *context)
601 return GNOME_VFS_ERROR_NOT_SUPPORTED;
604 static GnomeVFSResult
605 do_create_symbolic_link (GnomeVFSMethod *method,
607 const char *target_reference,
608 GnomeVFSContext *context)
610 return GNOME_VFS_ERROR_READ_ONLY;
613 static GnomeVFSResult
614 do_monitor_add (GnomeVFSMethod *method,
615 GnomeVFSMethodHandle **method_handle_return,
617 GnomeVFSMonitorType monitor_type)
619 return GNOME_VFS_ERROR_NOT_SUPPORTED;
622 static GnomeVFSResult
623 do_monitor_cancel (GnomeVFSMethod *method,
624 GnomeVFSMethodHandle *method_handle)
626 return GNOME_VFS_ERROR_NOT_SUPPORTED;
629 static GnomeVFSResult
630 do_file_control (GnomeVFSMethod *method,
631 GnomeVFSMethodHandle *method_handle,
632 const char *operation,
633 gpointer operation_data,
634 GnomeVFSContext *context)
636 return GNOME_VFS_ERROR_NOT_SUPPORTED;
639 static GnomeVFSMethod method = {
640 sizeof (GnomeVFSMethod),
653 do_get_file_info_from_handle,
663 do_create_symbolic_link,
671 vfs_module_init (const char *method_name, const char *args)
677 vfs_module_shutdown (GnomeVFSMethod * method)