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;
68 static GnomeVFSResult do_read (GnomeVFSMethod * method,
69 GnomeVFSMethodHandle * method_handle,
71 GnomeVFSFileSize num_bytes,
72 GnomeVFSFileSize * bytes_read,
73 GnomeVFSContext * context);
75 static GnomeVFSResult myth_connection_start (MythtvHandle * method_handle);
76 static void myth_destroy_handle (MythtvHandle * method_handle);
77 static GnomeVFSResult myth_handle_new (GnomeVFSURI * uri,
78 MythtvHandle ** method_handle);
79 static GnomeVFSResult myth_get_file_info (MythtvHandle * myth_handle,
81 GnomeVFSFileInfo * info);
84 myth_handle_new (GnomeVFSURI * uri,
85 MythtvHandle ** method_handle)
90 _GNOME_VFS_METHOD_PARAM_CHECK (*method_handle == NULL);
92 if (gnome_vfs_uri_get_host_name (uri) == NULL) {
93 return GNOME_VFS_ERROR_INVALID_HOST_NAME;
96 *method_handle = g_new0 (MythtvHandle, 1);
97 (*method_handle)->mythtv_version = MYTHTV_VERSION_DEFAULT;
99 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
100 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
102 (*method_handle)->backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
103 (*method_handle)->gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
111 myth_destroy_handle (MythtvHandle * method_handle)
113 //TODO: abort if in tranfer state
115 if (method_handle->backend_info != NULL) {
116 g_object_unref (method_handle->backend_info);
117 method_handle->backend_info = NULL;
120 if (method_handle->channel_name != NULL) {
121 g_free (method_handle->channel_name);
122 method_handle->channel_name = NULL;
125 if (method_handle->livetv != NULL) {
126 g_object_unref (method_handle->livetv);
127 method_handle->livetv = NULL;
130 if (method_handle->file_transfer != NULL) {
131 g_object_unref (method_handle->file_transfer);
132 method_handle->file_transfer = NULL;
135 if (method_handle->gmyth_uri != NULL) {
136 g_object_unref (method_handle->gmyth_uri);
137 method_handle->gmyth_uri = NULL;
140 g_free (method_handle);
143 static GnomeVFSResult
144 myth_get_file_info (MythtvHandle * myth_handle,
146 GnomeVFSFileInfo * info)
149 GMythBackendInfo *backend_info;
151 _GNOME_VFS_METHOD_PARAM_CHECK (info != NULL);
154 if (myth_handle == NULL) {
158 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
159 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
161 backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
162 gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
167 backend_info = g_object_ref (myth_handle->backend_info);
168 gmyth_uri = g_object_ref (myth_handle->gmyth_uri);
171 info->valid_fields = 0;
172 info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
173 GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
174 GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
176 info->type = GNOME_VFS_FILE_TYPE_REGULAR;
178 /* fixme: get from file extension? */
179 info->mime_type = g_strdup ("video/x-nuv");
180 info->permissions = GNOME_VFS_PERM_USER_READ |
181 GNOME_VFS_PERM_OTHER_READ |
182 GNOME_VFS_PERM_GROUP_READ;
185 info->name = g_strdup (gmyth_uri_get_path (gmyth_uri));
187 /* file size for remote files */
188 if (gmyth_uri_is_livetv (gmyth_uri) == FALSE) {
189 GMythFileTransfer *file_transfer = gmyth_file_transfer_new (backend_info);
191 /* Verifies if the file exists */
192 if (!gmyth_util_file_exists (backend_info,
193 gmyth_uri_get_path (gmyth_uri))) {
194 g_object_unref (file_transfer);
195 g_object_unref (backend_info);
196 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
197 return GNOME_VFS_ERROR_NOT_FOUND;
200 if (!gmyth_file_transfer_open (file_transfer, gmyth_uri_get_path (gmyth_uri))) {
201 g_object_unref (file_transfer);
202 g_object_unref (backend_info);
203 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
204 return GNOME_VFS_ERROR_NOT_FOUND;
207 info->size = gmyth_file_transfer_get_filesize (file_transfer);
208 info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SIZE;
209 g_object_unref (file_transfer);
212 g_object_unref (backend_info);
213 g_object_unref (gmyth_uri);
218 static GnomeVFSResult
219 myth_connection_start (MythtvHandle * method_handle)
221 GnomeVFSResult result = GNOME_VFS_OK;
223 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
224 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle->backend_info != NULL);
226 /* Connect to the backend */
227 if (gmyth_uri_is_livetv (method_handle->gmyth_uri) == TRUE) {
228 method_handle->livetv = gmyth_livetv_new (method_handle->backend_info);
229 method_handle->channel_name = gmyth_uri_get_channel_name (method_handle->gmyth_uri);
231 g_debug ("[%s] Channel name = %s\n", __FUNCTION__,
232 method_handle->channel_name);
234 if (method_handle->channel_name != NULL) {
235 if (gmyth_livetv_channel_name_setup (method_handle->livetv,
236 method_handle->channel_name) == FALSE) {
237 result = GNOME_VFS_ERROR_INVALID_URI;
240 } else if (gmyth_livetv_setup (method_handle->livetv) == FALSE) {
241 result = GNOME_VFS_ERROR_INVALID_URI;
246 method_handle->file_transfer =
247 gmyth_livetv_create_file_transfer (method_handle->livetv);
249 if (method_handle->file_transfer == NULL) {
250 result = GNOME_VFS_ERROR_INVALID_URI;
251 g_debug ("MythTV FileTransfer is NULL!\n");
255 if (!gmyth_file_transfer_open (method_handle->file_transfer,
256 method_handle->livetv->uri != NULL ?
257 gmyth_uri_get_path (method_handle->livetv->uri) :
258 method_handle->livetv->proginfo->pathname->str)) {
260 g_debug ("Couldn't open MythTV FileTransfer is NULL!\n");
261 result = GNOME_VFS_ERROR_NOT_OPEN;
266 method_handle->file_transfer =
267 gmyth_file_transfer_new (method_handle->backend_info);
269 /* Verifies if the file exists */
270 if (!gmyth_util_file_exists (method_handle->backend_info,
271 gmyth_uri_get_path (method_handle->gmyth_uri))) {
273 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
277 /* sets the Playback monitor connection */
278 if (!gmyth_file_transfer_open (method_handle->file_transfer,
279 gmyth_uri_get_path (method_handle->gmyth_uri))) {
281 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
282 result = GNOME_VFS_ERROR_NOT_FOUND;
285 } /* if - LiveTV or not? */
287 method_handle->configured = TRUE;
289 if (method_handle->file_transfer == NULL) {
290 result = GNOME_VFS_ERROR_NOT_OPEN;
298 static GnomeVFSResult
299 do_open (GnomeVFSMethod * method,
300 GnomeVFSMethodHandle ** method_handle,
302 GnomeVFSOpenMode mode, GnomeVFSContext * context)
304 MythtvHandle *myth_handle = NULL;
305 GnomeVFSResult result = GNOME_VFS_OK;
307 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
308 _GNOME_VFS_METHOD_PARAM_CHECK (uri != NULL);
310 if (mode & GNOME_VFS_OPEN_WRITE) {
311 return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
314 result = myth_handle_new (uri, &myth_handle);
315 if (result != GNOME_VFS_OK)
318 result = myth_connection_start (myth_handle);
319 if (result != GNOME_VFS_OK) {
320 myth_destroy_handle (myth_handle);
325 *method_handle = (GnomeVFSMethodHandle *) myth_handle;
330 static GnomeVFSResult
331 do_create (GnomeVFSMethod *method,
332 GnomeVFSMethodHandle **method_handle,
334 GnomeVFSOpenMode mode,
337 GnomeVFSContext *context)
339 return GNOME_VFS_ERROR_NOT_SUPPORTED;
342 static GnomeVFSResult
343 do_close (GnomeVFSMethod * method,
344 GnomeVFSMethodHandle * method_handle,
345 GnomeVFSContext * context)
347 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
349 myth_destroy_handle (myth_handle);
355 static GnomeVFSResult
356 do_read (GnomeVFSMethod * method,
357 GnomeVFSMethodHandle * method_handle,
359 GnomeVFSFileSize num_bytes,
360 GnomeVFSFileSize * bytes_read,
361 GnomeVFSContext * context)
363 GnomeVFSResult result;
364 MythtvHandle *myth_handle;
365 gint64 total_read = 0;
366 GByteArray *myth_buffer = g_byte_array_new ();
368 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
370 myth_handle = (MythtvHandle *) method_handle;
371 result = GNOME_VFS_OK;
373 total_read = gmyth_file_transfer_read (myth_handle->file_transfer,
375 num_bytes, gmyth_uri_is_livetv (myth_handle->gmyth_uri));
378 if (total_read == -1) {
379 result = GNOME_VFS_ERROR_IO;
383 if (total_read < num_bytes) {
384 result = GNOME_VFS_ERROR_EOF;
387 if (total_read > 0) {
388 g_memmove (buffer, myth_buffer->data, total_read);
389 g_byte_array_free (myth_buffer, TRUE);
390 myth_handle->offset += total_read;
393 *bytes_read = (GnomeVFSFileSize) total_read;
398 static GnomeVFSResult
399 do_write (GnomeVFSMethod *method,
400 GnomeVFSMethodHandle *method_handle,
401 gconstpointer buffer,
402 GnomeVFSFileSize num_bytes,
403 GnomeVFSFileSize *bytes_written,
404 GnomeVFSContext *context)
406 return GNOME_VFS_ERROR_NOT_SUPPORTED;
409 static GnomeVFSResult
410 do_seek (GnomeVFSMethod *method,
411 GnomeVFSMethodHandle *method_handle,
412 GnomeVFSSeekPosition whence,
413 GnomeVFSFileOffset offset,
414 GnomeVFSContext *context)
416 MythtvHandle *myth_handle;
417 //guint64 whence_p = 0;
418 //gint64 new_offset =0;
420 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
422 myth_handle = (MythtvHandle *) method_handle;
424 g_debug ("seek offset%"G_GINT64_FORMAT" whence %d", offset, whence);
426 return GNOME_VFS_ERROR_NOT_SUPPORTED;
428 if (gmyth_uri_is_livetv (myth_handle->gmyth_uri))
432 case GNOME_VFS_SEEK_START:
435 case GNOME_VFS_SEEK_CURRENT:
436 whence_p = myth_handle->offset;
438 case GNOME_VFS_SEEK_END:
439 return GNOME_VFS_ERROR_NOT_SUPPORTED;
442 new_offset = gmyth_file_transfer_seek (myth_handle->file_transfer, offset, whence_p);
443 if (new_offset != 0) {
444 myth_handle->offset = new_offset;
448 return GNOME_VFS_ERROR_NOT_SUPPORTED;
452 static GnomeVFSResult
453 do_tell (GnomeVFSMethod *method,
454 GnomeVFSMethodHandle *method_handle,
455 GnomeVFSFileSize *offset_return)
457 MythtvHandle *myth_handle = NULL;
459 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
461 myth_handle = (MythtvHandle *) method_handle;
462 *offset_return = myth_handle->offset;
467 static GnomeVFSResult
468 do_truncate_handle (GnomeVFSMethod *method,
469 GnomeVFSMethodHandle *method_handle,
470 GnomeVFSFileSize where,
471 GnomeVFSContext *context)
473 return GNOME_VFS_ERROR_READ_ONLY;
476 static GnomeVFSResult
477 do_open_directory (GnomeVFSMethod *method,
478 GnomeVFSMethodHandle **method_handle,
480 GnomeVFSFileInfoOptions options,
481 GnomeVFSContext *context)
483 return GNOME_VFS_ERROR_NOT_SUPPORTED;
486 static GnomeVFSResult
487 do_close_directory (GnomeVFSMethod *method,
488 GnomeVFSMethodHandle *method_handle,
489 GnomeVFSContext *context)
491 return GNOME_VFS_ERROR_NOT_SUPPORTED;
494 static GnomeVFSResult
495 do_read_directory (GnomeVFSMethod *method,
496 GnomeVFSMethodHandle *method_handle,
497 GnomeVFSFileInfo *file_info,
498 GnomeVFSContext *context)
500 return GNOME_VFS_ERROR_NOT_SUPPORTED;
504 static GnomeVFSResult
505 do_get_file_info (GnomeVFSMethod * method,
507 GnomeVFSFileInfo * file_info,
508 GnomeVFSFileInfoOptions options,
509 GnomeVFSContext * context)
511 return myth_get_file_info (NULL, uri, file_info);
514 static GnomeVFSResult
515 do_get_file_info_from_handle (GnomeVFSMethod *method,
516 GnomeVFSMethodHandle *method_handle,
517 GnomeVFSFileInfo *file_info,
518 GnomeVFSFileInfoOptions options,
519 GnomeVFSContext *context)
521 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
523 return myth_get_file_info (myth_handle, NULL, file_info);
527 do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
532 static GnomeVFSResult
533 do_make_directory (GnomeVFSMethod *method,
536 GnomeVFSContext *context)
538 return GNOME_VFS_ERROR_READ_ONLY;
541 static GnomeVFSResult
542 do_remove_directory (GnomeVFSMethod *method,
544 GnomeVFSContext *context)
546 return GNOME_VFS_ERROR_READ_ONLY;
549 static GnomeVFSResult
550 do_move (GnomeVFSMethod *method,
551 GnomeVFSURI *old_uri,
552 GnomeVFSURI *new_uri,
553 gboolean force_replace,
554 GnomeVFSContext *context)
556 return GNOME_VFS_ERROR_READ_ONLY;
559 static GnomeVFSResult
560 do_unlink (GnomeVFSMethod *method,
562 GnomeVFSContext *context)
564 return GNOME_VFS_ERROR_READ_ONLY;
567 static GnomeVFSResult
568 do_check_same_fs (GnomeVFSMethod *method,
571 gboolean *same_fs_return,
572 GnomeVFSContext *context)
574 return GNOME_VFS_ERROR_NOT_SUPPORTED;
577 static GnomeVFSResult
578 do_set_file_info (GnomeVFSMethod *method,
580 const GnomeVFSFileInfo *info,
581 GnomeVFSSetFileInfoMask mask,
582 GnomeVFSContext *context)
584 return GNOME_VFS_ERROR_READ_ONLY;
587 static GnomeVFSResult
588 do_truncate (GnomeVFSMethod *method,
590 GnomeVFSFileSize where,
591 GnomeVFSContext *context)
593 return GNOME_VFS_ERROR_READ_ONLY;
596 static GnomeVFSResult
597 do_find_directory (GnomeVFSMethod *method,
598 GnomeVFSURI *near_uri,
599 GnomeVFSFindDirectoryKind kind,
600 GnomeVFSURI **result_uri,
601 gboolean create_if_needed,
602 gboolean find_if_needed,
604 GnomeVFSContext *context)
606 return GNOME_VFS_ERROR_NOT_SUPPORTED;
609 static GnomeVFSResult
610 do_create_symbolic_link (GnomeVFSMethod *method,
612 const char *target_reference,
613 GnomeVFSContext *context)
615 return GNOME_VFS_ERROR_READ_ONLY;
618 static GnomeVFSResult
619 do_monitor_add (GnomeVFSMethod *method,
620 GnomeVFSMethodHandle **method_handle_return,
622 GnomeVFSMonitorType monitor_type)
624 return GNOME_VFS_ERROR_NOT_SUPPORTED;
627 static GnomeVFSResult
628 do_monitor_cancel (GnomeVFSMethod *method,
629 GnomeVFSMethodHandle *method_handle)
631 return GNOME_VFS_ERROR_NOT_SUPPORTED;
634 static GnomeVFSResult
635 do_file_control (GnomeVFSMethod *method,
636 GnomeVFSMethodHandle *method_handle,
637 const char *operation,
638 gpointer operation_data,
639 GnomeVFSContext *context)
641 return GNOME_VFS_ERROR_NOT_SUPPORTED;
644 static GnomeVFSMethod method = {
645 sizeof (GnomeVFSMethod),
658 do_get_file_info_from_handle,
668 do_create_symbolic_link,
676 vfs_module_init (const char *method_name, const char *args)
682 vfs_module_shutdown (GnomeVFSMethod * method)