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 static FILE *fpout = NULL;
85 static gboolean first = TRUE;
89 myth_handle_new (GnomeVFSURI * uri,
90 MythtvHandle ** method_handle)
95 _GNOME_VFS_METHOD_PARAM_CHECK (*method_handle == NULL);
97 if (gnome_vfs_uri_get_host_name (uri) == NULL) {
98 return GNOME_VFS_ERROR_INVALID_HOST_NAME;
101 *method_handle = g_new0 (MythtvHandle, 1);
102 (*method_handle)->mythtv_version = MYTHTV_VERSION_DEFAULT;
104 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
105 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
107 (*method_handle)->backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
108 (*method_handle)->gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
116 myth_destroy_handle (MythtvHandle * method_handle)
118 //TODO: abort if in tranfer state
120 if (method_handle->backend_info != NULL) {
121 g_object_unref (method_handle->backend_info);
122 method_handle->backend_info = NULL;
125 if (method_handle->channel_name != NULL) {
126 g_free (method_handle->channel_name);
127 method_handle->channel_name = NULL;
130 if (method_handle->livetv != NULL) {
131 g_object_unref (method_handle->livetv);
132 method_handle->livetv = NULL;
135 if (method_handle->file_transfer != NULL) {
136 g_object_unref (method_handle->file_transfer);
137 method_handle->file_transfer = NULL;
140 if (method_handle->gmyth_uri != NULL) {
141 g_object_unref (method_handle->gmyth_uri);
142 method_handle->gmyth_uri = NULL;
145 g_free (method_handle);
148 static GnomeVFSResult
149 myth_get_file_info (MythtvHandle * myth_handle,
151 GnomeVFSFileInfo * info)
154 GMythBackendInfo *backend_info;
156 _GNOME_VFS_METHOD_PARAM_CHECK (info != NULL);
158 if (myth_handle == NULL) {
162 tmp_str1 = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
163 tmp_str2 = gnome_vfs_unescape_string (tmp_str1, "");
165 backend_info = gmyth_backend_info_new_with_uri (tmp_str2);
166 gmyth_uri = gmyth_uri_new_with_value (tmp_str2);
171 backend_info = g_object_ref (myth_handle->backend_info);
172 gmyth_uri = g_object_ref (myth_handle->gmyth_uri);
175 info->valid_fields = 0;
176 info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE |
177 GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE |
178 GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
180 info->type = GNOME_VFS_FILE_TYPE_REGULAR;
182 /* fixme: get from file extension? */
183 info->mime_type = g_strdup ("video/x-nuv");
184 info->permissions = GNOME_VFS_PERM_USER_READ |
185 GNOME_VFS_PERM_OTHER_READ |
186 GNOME_VFS_PERM_GROUP_READ;
189 info->name = g_strdup (gmyth_uri_get_path (gmyth_uri));
191 /* file size for remote files */
192 if (gmyth_uri_is_livetv (gmyth_uri) == FALSE) {
193 GMythFileTransfer *file_transfer = gmyth_file_transfer_new (backend_info);
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 (backend_info);
199 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
200 return GNOME_VFS_ERROR_NOT_FOUND;
203 info->size = gmyth_file_transfer_get_filesize (file_transfer);
204 info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_SIZE;
205 g_object_unref (file_transfer);
208 g_object_unref (backend_info);
209 g_object_unref (gmyth_uri);
214 static GnomeVFSResult
215 myth_connection_start (MythtvHandle * method_handle)
217 GnomeVFSResult result = GNOME_VFS_OK;
219 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
220 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle->backend_info != NULL);
222 g_debug ("F: %s L: %d", __FUNCTION__, __LINE__);
224 /* Connect to the backend */
225 if (gmyth_uri_is_livetv (method_handle->gmyth_uri) == TRUE) {
227 g_debug ("F: %s L: %d", __FUNCTION__, __LINE__);
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 g_debug ("[%s] Channel name = %s\n", __FUNCTION__,
233 method_handle->channel_name);
235 if (method_handle->channel_name != NULL) {
236 if (gmyth_livetv_channel_name_setup (method_handle->livetv,
237 method_handle->channel_name) == FALSE) {
238 result = GNOME_VFS_ERROR_INVALID_URI;
241 } else if (gmyth_livetv_setup (method_handle->livetv) == FALSE) {
242 result = GNOME_VFS_ERROR_INVALID_URI;
246 g_debug ("F: %s L: %d", __FUNCTION__, __LINE__);
248 method_handle->file_transfer =
249 gmyth_livetv_create_file_transfer (method_handle->livetv);
251 if (method_handle->file_transfer == NULL) {
252 result = GNOME_VFS_ERROR_INVALID_URI;
253 g_debug ("MythTV FileTransfer is NULL!\n");
257 if (!gmyth_file_transfer_open (method_handle->file_transfer,
258 method_handle->livetv->uri != NULL ?
259 gmyth_uri_get_path (method_handle->livetv->uri) :
260 method_handle->livetv->proginfo->pathname->str)) {
262 g_debug ("Couldn't open MythTV FileTransfer is NULL!\n");
263 result = GNOME_VFS_ERROR_NOT_OPEN;
268 method_handle->file_transfer =
269 gmyth_file_transfer_new (method_handle->backend_info);
271 /* Verifies if the file exists */
272 if (!gmyth_util_file_exists (method_handle->backend_info,
273 gmyth_uri_get_path (method_handle->gmyth_uri))) {
275 g_debug ("NOT FOUND %s/%d", __FUNCTION__, __LINE__);
276 result = GNOME_VFS_ERROR_NOT_FOUND;
280 /* sets the Playback monitor connection */
281 result = gmyth_file_transfer_open (method_handle->file_transfer,
282 gmyth_uri_get_path (method_handle->gmyth_uri));
283 } /* if - LiveTV or not? */
285 method_handle->configured = TRUE;
287 if (method_handle->file_transfer == NULL) {
288 result = GNOME_VFS_ERROR_NOT_OPEN;
291 g_return_val_if_fail (method_handle->file_transfer != NULL,
292 GNOME_VFS_ERROR_NOT_OPEN);
299 static GnomeVFSResult
300 do_open (GnomeVFSMethod * method,
301 GnomeVFSMethodHandle ** method_handle,
303 GnomeVFSOpenMode mode, GnomeVFSContext * context)
305 MythtvHandle *myth_handle = NULL;
306 GnomeVFSResult result = GNOME_VFS_OK;
308 g_debug ("F: %s L: %d", __FUNCTION__, __LINE__);
310 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
311 _GNOME_VFS_METHOD_PARAM_CHECK (uri != NULL);
313 if (mode & GNOME_VFS_OPEN_WRITE) {
314 return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
317 result = myth_handle_new (uri, &myth_handle);
318 if (result != GNOME_VFS_OK)
321 g_debug ("F: %s L: %d", __FUNCTION__, __LINE__);
322 result = myth_connection_start (myth_handle);
323 if (result != GNOME_VFS_OK) {
324 myth_destroy_handle (myth_handle);
328 g_debug ("F: %s L: %d", __FUNCTION__, __LINE__);
330 *method_handle = (GnomeVFSMethodHandle *) myth_handle;
335 static GnomeVFSResult
336 do_create (GnomeVFSMethod *method,
337 GnomeVFSMethodHandle **method_handle,
339 GnomeVFSOpenMode mode,
342 GnomeVFSContext *context)
344 return GNOME_VFS_ERROR_NOT_SUPPORTED;
347 static GnomeVFSResult
348 do_close (GnomeVFSMethod * method,
349 GnomeVFSMethodHandle * method_handle,
350 GnomeVFSContext * context)
352 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
354 myth_destroy_handle (myth_handle);
360 static GnomeVFSResult
361 do_read (GnomeVFSMethod * method,
362 GnomeVFSMethodHandle * method_handle,
364 GnomeVFSFileSize num_bytes,
365 GnomeVFSFileSize * bytes_read,
366 GnomeVFSContext * context)
368 GnomeVFSResult result;
369 MythtvHandle *myth_handle;
370 gint64 total_read = 0;
371 GByteArray *myth_buffer = g_byte_array_new ();
373 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
376 myth_handle = (MythtvHandle *) method_handle;
377 result = GNOME_VFS_OK;
379 g_debug ("Reading %"G_GUINT64_FORMAT" bytes", num_bytes);
381 g_debug ("F: %s L: %d", __FUNCTION__, __LINE__);
383 total_read = gmyth_file_transfer_read (myth_handle->file_transfer,
385 num_bytes, gmyth_uri_is_livetv (myth_handle->gmyth_uri));
388 g_debug ("total read %"G_GINT64_FORMAT, total_read);
390 if (total_read == -1) {
391 result = GNOME_VFS_ERROR_IO;
395 if (total_read < num_bytes) {
396 result = GNOME_VFS_ERROR_EOF;
399 g_debug ("F: %s L: %d", __FUNCTION__, __LINE__);
402 if (total_read > 0) {
403 g_memmove (buffer, myth_buffer->data, total_read);
404 g_byte_array_free (myth_buffer, TRUE);
405 myth_handle->offset += total_read;
407 g_debug ("Nao leu nada");
411 *bytes_read = (GnomeVFSFileSize) total_read;
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 if (gmyth_uri_is_livetv (myth_handle->gmyth_uri))
445 return GNOME_VFS_ERROR_NOT_SUPPORTED;
449 case GNOME_VFS_SEEK_START:
452 case GNOME_VFS_SEEK_CURRENT:
453 whence_p = myth_handle->offset;
455 case GNOME_VFS_SEEK_END:
456 return GNOME_VFS_ERROR_NOT_SUPPORTED;
459 new_offset = gmyth_file_transfer_seek (myth_handle->file_transfer, offset, whence_p);
460 if (new_offset != 0) {
461 myth_handle->offset = new_offset;
465 return GNOME_VFS_ERROR_NOT_SUPPORTED;
468 static GnomeVFSResult
469 do_tell (GnomeVFSMethod *method,
470 GnomeVFSMethodHandle *method_handle,
471 GnomeVFSFileSize *offset_return)
473 MythtvHandle *myth_handle = NULL;
475 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
477 myth_handle = (MythtvHandle *) method_handle;
478 *offset_return = myth_handle->offset;
483 static GnomeVFSResult
484 do_truncate_handle (GnomeVFSMethod *method,
485 GnomeVFSMethodHandle *method_handle,
486 GnomeVFSFileSize where,
487 GnomeVFSContext *context)
489 return GNOME_VFS_ERROR_READ_ONLY;
492 static GnomeVFSResult
493 do_open_directory (GnomeVFSMethod *method,
494 GnomeVFSMethodHandle **method_handle,
496 GnomeVFSFileInfoOptions options,
497 GnomeVFSContext *context)
499 return GNOME_VFS_ERROR_NOT_SUPPORTED;
502 static GnomeVFSResult
503 do_close_directory (GnomeVFSMethod *method,
504 GnomeVFSMethodHandle *method_handle,
505 GnomeVFSContext *context)
507 return GNOME_VFS_ERROR_NOT_SUPPORTED;
510 static GnomeVFSResult
511 do_read_directory (GnomeVFSMethod *method,
512 GnomeVFSMethodHandle *method_handle,
513 GnomeVFSFileInfo *file_info,
514 GnomeVFSContext *context)
516 return GNOME_VFS_ERROR_NOT_SUPPORTED;
520 static GnomeVFSResult
521 do_get_file_info (GnomeVFSMethod * method,
523 GnomeVFSFileInfo * file_info,
524 GnomeVFSFileInfoOptions options,
525 GnomeVFSContext * context)
527 return myth_get_file_info (NULL, uri, file_info);
530 static GnomeVFSResult
531 do_get_file_info_from_handle (GnomeVFSMethod *method,
532 GnomeVFSMethodHandle *method_handle,
533 GnomeVFSFileInfo *file_info,
534 GnomeVFSFileInfoOptions options,
535 GnomeVFSContext *context)
537 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
539 return myth_get_file_info (myth_handle, NULL, file_info);
543 do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
548 static GnomeVFSResult
549 do_make_directory (GnomeVFSMethod *method,
552 GnomeVFSContext *context)
554 return GNOME_VFS_ERROR_READ_ONLY;
557 static GnomeVFSResult
558 do_remove_directory (GnomeVFSMethod *method,
560 GnomeVFSContext *context)
562 return GNOME_VFS_ERROR_READ_ONLY;
565 static GnomeVFSResult
566 do_move (GnomeVFSMethod *method,
567 GnomeVFSURI *old_uri,
568 GnomeVFSURI *new_uri,
569 gboolean force_replace,
570 GnomeVFSContext *context)
572 return GNOME_VFS_ERROR_READ_ONLY;
575 static GnomeVFSResult
576 do_unlink (GnomeVFSMethod *method,
578 GnomeVFSContext *context)
580 return GNOME_VFS_ERROR_READ_ONLY;
583 static GnomeVFSResult
584 do_check_same_fs (GnomeVFSMethod *method,
587 gboolean *same_fs_return,
588 GnomeVFSContext *context)
590 return GNOME_VFS_ERROR_NOT_SUPPORTED;
593 static GnomeVFSResult
594 do_set_file_info (GnomeVFSMethod *method,
596 const GnomeVFSFileInfo *info,
597 GnomeVFSSetFileInfoMask mask,
598 GnomeVFSContext *context)
600 return GNOME_VFS_ERROR_READ_ONLY;
603 static GnomeVFSResult
604 do_truncate (GnomeVFSMethod *method,
606 GnomeVFSFileSize where,
607 GnomeVFSContext *context)
609 return GNOME_VFS_ERROR_READ_ONLY;
612 static GnomeVFSResult
613 do_find_directory (GnomeVFSMethod *method,
614 GnomeVFSURI *near_uri,
615 GnomeVFSFindDirectoryKind kind,
616 GnomeVFSURI **result_uri,
617 gboolean create_if_needed,
618 gboolean find_if_needed,
620 GnomeVFSContext *context)
622 return GNOME_VFS_ERROR_NOT_SUPPORTED;
625 static GnomeVFSResult
626 do_create_symbolic_link (GnomeVFSMethod *method,
628 const char *target_reference,
629 GnomeVFSContext *context)
631 return GNOME_VFS_ERROR_READ_ONLY;
634 static GnomeVFSResult
635 do_monitor_add (GnomeVFSMethod *method,
636 GnomeVFSMethodHandle **method_handle_return,
638 GnomeVFSMonitorType monitor_type)
640 return GNOME_VFS_ERROR_NOT_SUPPORTED;
643 static GnomeVFSResult
644 do_monitor_cancel (GnomeVFSMethod *method,
645 GnomeVFSMethodHandle *method_handle)
647 return GNOME_VFS_ERROR_NOT_SUPPORTED;
650 static GnomeVFSResult
651 do_file_control (GnomeVFSMethod *method,
652 GnomeVFSMethodHandle *method_handle,
653 const char *operation,
654 gpointer operation_data,
655 GnomeVFSContext *context)
657 return GNOME_VFS_ERROR_NOT_SUPPORTED;
660 static GnomeVFSMethod method = {
661 sizeof (GnomeVFSMethod),
674 do_get_file_info_from_handle,
684 do_create_symbolic_link,
692 vfs_module_init (const char *method_name, const char *args)
698 vfs_module_shutdown (GnomeVFSMethod * method)