[svn r381] Solved minor problem with the time value.
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
27 #include <libgnomevfs/gnome-vfs-module.h>
28 #include <libgnomevfs/gnome-vfs-utils.h>
30 #include <gmyth/gmyth_file_transfer.h>
31 #include <gmyth/gmyth_livetv.h>
32 #include <gmyth/gmyth_uri.h>
33 #include <gmyth/gmyth_recorder.h>
34 #include <gmyth/gmyth_backendinfo.h>
35 #include <gmyth/gmyth_util.h>
36 #include <gmyth/gmyth_remote_util.h>
37 #include <gmyth/gmyth_tvchain.h>
38 #include <gmyth/gmyth_programinfo.h>
40 #define GST_MYTHTV_ID_NUM 1
41 #define MYTHTV_VERSION_DEFAULT 30
42 #define MYTHTV_TRANSFER_MAX_WAITS 100
44 /* internal GnomeVFS plug-in buffer size ( 120 Kbytes ) */
45 #define MYTHTV_BUFFER_SIZE 1024*80
46 /* internally sized GnomeVFS plug-in buffer ( 4 Kbytes ) */
47 #define MYTHTV_MAX_VFS_BUFFER_SIZE 4096
48 /* maximum number of bytes to be requested to the MythTV backend ( 64 Kbytes ) */
49 #define MYTHTV_MAX_REQUEST_SIZE 1024*64
51 static GnomeVFSResult do_read (GnomeVFSMethod * method,
52 GnomeVFSMethodHandle * method_handle,
54 GnomeVFSFileSize num_bytes,
55 GnomeVFSFileSize * bytes_read,
56 GnomeVFSContext * context);
59 GMythFileTransfer *file_transfer;
75 //static MythtvHandle *myth_handle = NULL;
78 do_open (GnomeVFSMethod * method,
79 GnomeVFSMethodHandle ** method_handle,
81 GnomeVFSOpenMode mode, GnomeVFSContext * context)
83 MythtvHandle *myth_handle = NULL;
84 GMythBackendInfo *backend_info = NULL;
85 GMythURI *gmyth_uri = NULL;
88 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
89 _GNOME_VFS_METHOD_PARAM_CHECK (uri != NULL);
91 if (mode & GNOME_VFS_OPEN_WRITE) {
92 return GNOME_VFS_ERROR_NOT_PERMITTED;
95 if (gnome_vfs_uri_get_host_name (uri) == NULL) {
96 return GNOME_VFS_ERROR_INVALID_HOST_NAME;
99 if ((NULL == myth_handle) || !myth_handle->configured) {
100 myth_handle = g_new0 (MythtvHandle, 1);
102 myth_handle->configured = FALSE;
104 myth_handle->is_livetv = FALSE;
106 /* Initialize mythtv handler */
107 myth_handle->file_transfer = NULL;
108 myth_handle->livetv = NULL;
109 myth_handle->mythtv_version = MYTHTV_VERSION_DEFAULT;
110 myth_handle->bytes_read = 0;
111 myth_handle->content_size = (GnomeVFSFileSize) - 1;
113 /* Creates and fills out the backend info structure */
115 gmyth_backend_info_new_with_uri
116 (gnome_vfs_unescape_string
117 (gnome_vfs_uri_to_string
118 (uri, GNOME_VFS_URI_HIDE_NONE), ""));
120 /* creates an instance of */
122 gmyth_uri_new_with_value (gnome_vfs_unescape_string
123 (gnome_vfs_uri_to_string
125 GNOME_VFS_URI_HIDE_NONE),
128 myth_handle->is_livetv = gmyth_uri_is_livetv (gmyth_uri);
130 /* Connect to the backend */
131 if (gmyth_uri != NULL && myth_handle->is_livetv == TRUE) {
133 if (NULL == myth_handle->livetv) {
134 myth_handle->livetv = gmyth_livetv_new ();
136 myth_handle->channel_name =
137 gmyth_uri_get_channel_name (gmyth_uri);
139 g_debug ("[%s] Channel name = %s\n",
141 myth_handle->channel_name);
143 if (myth_handle->channel_name != NULL) {
144 if (gmyth_livetv_channel_name_setup
145 (myth_handle->livetv,
146 myth_handle->channel_name,
147 backend_info) == FALSE) {
148 g_object_unref (gmyth_uri);
152 if (gmyth_livetv_setup
153 (myth_handle->livetv,
154 backend_info) == FALSE) {
155 g_object_unref (gmyth_uri);
161 if (NULL == myth_handle->file_transfer) {
162 myth_handle->file_transfer =
163 gmyth_livetv_create_file_transfer
164 (myth_handle->livetv);
166 if (NULL == myth_handle->file_transfer) {
169 ("MythTV FileTransfer is NULL!\n");
170 return GNOME_VFS_ERROR_NOT_OPEN;
173 if (!gmyth_file_transfer_open
174 (myth_handle->file_transfer,
175 myth_handle->livetv->uri !=
177 gmyth_uri_get_path (myth_handle->
180 myth_handle->livetv->proginfo->
183 ("Couldn't open MythTV FileTransfer is NULL!\n");
184 g_object_unref (myth_handle->
186 myth_handle->file_transfer = NULL;
190 /* if - FileTransfer is NULL, or not */
193 if (NULL == myth_handle->file_transfer) {
195 myth_handle->file_transfer =
196 gmyth_file_transfer_new (backend_info);
198 /* Verifies if the file exists */
199 if (!gmyth_util_file_exists
201 gmyth_uri_get_path (gmyth_uri))) {
202 g_object_unref (backend_info);
206 /* sets the Playback monitor connection */
208 gmyth_file_transfer_open (myth_handle->
215 } /* if - LiveTV or not? */
218 g_debug ("MythTV FileTransfer open error.\n");
219 return GNOME_VFS_ERROR_NOT_OPEN;
222 myth_handle->configured = TRUE;
224 g_object_unref (backend_info);
226 if (gmyth_uri != NULL)
227 g_object_unref (gmyth_uri);
229 myth_handle->buffer =
230 g_byte_array_sized_new (MYTHTV_BUFFER_SIZE);
231 myth_handle->buffer_remain = 0;
233 g_return_val_if_fail (myth_handle->file_transfer != NULL,
234 GNOME_VFS_ERROR_NOT_OPEN);
236 if ( /*myth_handle->file_transfer->filesize <= 0 && */
237 myth_handle->is_livetv) {
238 myth_handle->content_size =
239 gmyth_recorder_get_file_position (myth_handle->
243 myth_handle->content_size =
244 myth_handle->file_transfer->filesize;
248 /* if - configured or not? */
249 *method_handle = (GnomeVFSMethodHandle *) myth_handle;
254 static GnomeVFSResult
255 do_read (GnomeVFSMethod * method,
256 GnomeVFSMethodHandle * method_handle,
258 GnomeVFSFileSize num_bytes,
259 GnomeVFSFileSize * bytes_read, GnomeVFSContext * context)
261 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
262 GnomeVFSFileSize bytes_to_read = num_bytes;
264 if (!myth_handle->is_livetv
265 && (myth_handle->bytes_read >= myth_handle->content_size))
266 return GNOME_VFS_ERROR_EOF;
268 /* fixme: change this to min math function */
269 if ((myth_handle->content_size > 0)) {
270 if (!myth_handle->is_livetv &&
272 (myth_handle->content_size -
273 myth_handle->bytes_read))) {
275 myth_handle->content_size -
276 myth_handle->bytes_read;
280 /* Loop sending the Myth File Transfer request:
281 * Retry whilst authentication fails and we supply it. */
282 if ((myth_handle->buffer_remain =
283 myth_handle->buffer->len) < bytes_to_read) {
286 while (MYTHTV_BUFFER_SIZE != myth_handle->buffer_remain) {
288 /* resize buffer length request to no more than MYTHTV_MAX_REQUEST_SIZE */
289 if ((MYTHTV_BUFFER_SIZE -
290 myth_handle->buffer_remain) <=
291 MYTHTV_MAX_REQUEST_SIZE)
294 myth_handle->buffer_remain;
296 buffer_size = MYTHTV_MAX_REQUEST_SIZE;
298 GByteArray *tmp_buffer = g_byte_array_new ();
301 ("Asking %d bytes (there is %d bytes in the buffer)\n",
302 buffer_size, myth_handle->buffer_remain);
305 gmyth_file_transfer_read (myth_handle->
310 if (!myth_handle->is_livetv && len < 0) {
311 g_byte_array_free (tmp_buffer, TRUE);
312 g_debug ("Fail to read bytes");
313 return GNOME_VFS_ERROR_IO;
315 /*else if (len == 0) {
316 g_byte_array_free (tmp_buffer, TRUE);
317 g_warning ("End of file probably achieved");
318 return GNOME_VFS_ERROR_EOF;
320 myth_handle->buffer =
321 g_byte_array_append (myth_handle->buffer,
322 tmp_buffer->data, len);
324 myth_handle->buffer_remain += len;
326 if (tmp_buffer != NULL) {
327 g_byte_array_free (tmp_buffer, TRUE);
330 } /* while - iterates until fills the internal buffer */
333 /* if - got from the network, or not */
336 myth_handle->buffer_remain) ? myth_handle->
337 buffer_remain : bytes_to_read;
338 /* gets the first buffer_size bytes from the byte array buffer variable */
340 g_memmove (buffer, myth_handle->buffer->data, bytes_to_read);
342 myth_handle->bytes_read += bytes_to_read;
343 myth_handle->buffer_remain -= bytes_to_read;
345 /* flushs the newly buffer got from byte array */
346 myth_handle->buffer =
347 g_byte_array_remove_range (myth_handle->buffer, 0,
350 ("Got from %llu bytes from internal buffer. (there are %d bytes in the buffer, from a total of %llu dispatched.)\n",
351 bytes_to_read, myth_handle->buffer_remain,
352 myth_handle->bytes_read);
354 *bytes_read = bytes_to_read;
359 static GnomeVFSResult
360 do_close (GnomeVFSMethod * method,
361 GnomeVFSMethodHandle * method_handle, GnomeVFSContext * context)
364 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
366 //if ( NULL == myth_handle || myth_handle->configured ) {
368 if (myth_handle->file_transfer != NULL) {
369 g_object_unref (myth_handle->file_transfer);
370 myth_handle->file_transfer = NULL;
373 if (myth_handle->is_livetv && myth_handle->livetv != NULL) {
374 g_object_unref (myth_handle->livetv);
375 myth_handle->livetv = NULL;
378 if (myth_handle->buffer) {
379 g_byte_array_free (myth_handle->buffer, TRUE);
380 myth_handle->buffer = NULL;
383 myth_handle->configured = FALSE;
385 g_free (myth_handle);
394 static GnomeVFSResult
395 do_get_file_info (GnomeVFSMethod * method,
397 GnomeVFSFileInfo * file_info,
398 GnomeVFSFileInfoOptions options,
399 GnomeVFSContext * context)
401 GMythFileTransfer *file_transfer = NULL;
402 GMythRecorder *recorder = NULL;
403 GMythTVChain *tvchain = NULL;
404 GMythBackendInfo *backend_info = NULL;
405 GMythURI *gmyth_uri = NULL;
406 GMythSocket *socket = NULL;
407 gboolean is_livetv = FALSE;
411 /* Creates and fills out the backend info structure */
413 gmyth_backend_info_new_with_uri (gnome_vfs_unescape_string
414 (gnome_vfs_uri_to_string
416 GNOME_VFS_URI_HIDE_NONE),
419 /* creates an instance of */
421 gmyth_uri_new_with_value (gnome_vfs_unescape_string
422 (gnome_vfs_uri_to_string
423 (uri, GNOME_VFS_URI_HIDE_NONE),
426 is_livetv = gmyth_uri_is_livetv (gmyth_uri);
428 file_info->valid_fields = file_info->valid_fields
429 | GNOME_VFS_FILE_INFO_FIELDS_TYPE
430 | GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE
431 | GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
432 file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
433 /* fixme: get from file extension? */
434 file_info->mime_type = g_strdup ("video/x-nuv");
435 file_info->permissions =
436 GNOME_VFS_PERM_USER_READ |
437 GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_GROUP_READ;
439 g_debug ("gnome_vfs_uri == %s | gmyth_uri == %s.\n",
440 gnome_vfs_uri_get_path (uri),
441 gmyth_uri_get_path (gmyth_uri));
443 /* Connect to the backend */
444 if (gmyth_uri != NULL && is_livetv == TRUE) {
446 /* start to get file info from LiveTV remote encoder */
447 socket = gmyth_socket_new ();
449 /* FIME: Implement this at gmyth_socket */
451 gmyth_socket_connect_to_backend (socket,
457 g_debug ("[%s] LiveTV can not connect to backend",
463 if (gmyth_remote_util_get_free_recorder_count (socket) <=
465 g_debug ("No free remote encoder available.");
470 /* Gets the recorder num */
471 recorder = remote_request_next_free_recorder (socket, -1);
473 if ( socket != NULL )
474 g_object_unref (socket);
476 if (recorder == NULL) {
477 g_debug ("[%s] None remote encoder available",
483 /* Init remote encoder. Opens its control socket. */
484 res = gmyth_recorder_setup (recorder);
487 ("[%s] Fail while setting remote encoder\n",
493 /* Creates livetv chain handler */
494 tvchain = gmyth_tvchain_new ();
495 gmyth_tvchain_initialize (tvchain, backend_info);
497 if (tvchain == NULL || tvchain->tvchain_id == NULL) {
501 /* Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly) */
502 res = gmyth_recorder_spawntv (recorder,
506 g_warning ("[%s] Fail while spawn tv\n",
515 GMythProgramInfo *prog_info =
516 gmyth_recorder_get_current_program_info (recorder);
518 if (prog_info != NULL) {
520 g_debug ("path = %s", prog_info->pathname->str);
524 (prog_info->pathname->str, "/"));
527 file_info->name = g_strdup ("LiveTV.nuv");
529 gmyth_recorder_get_file_position (recorder);
532 if (recorder != NULL)
533 g_object_unref (recorder);
535 if (prog_info != NULL)
536 g_object_unref (prog_info);
539 g_object_unref (tvchain);
541 file_info->size = (GnomeVFSFileSize) - 1;
545 /* start to get file info from remote file encoder */
546 file_transfer = gmyth_file_transfer_new (backend_info);
548 /* Verifies if the file exists */
549 if (!gmyth_util_file_exists
550 (backend_info, gmyth_uri_get_path (gmyth_uri))) {
551 g_object_unref (backend_info);
552 return GNOME_VFS_ERROR_NOT_FOUND;
555 /* sets the Playback monitor connection */
557 gmyth_file_transfer_open (file_transfer,
561 file_info->name = g_strdup (gnome_vfs_uri_get_path (uri));
563 } /* if - LiveTV or not? */
566 g_debug ("MythTV FileTransfer open error\n");
567 return GNOME_VFS_ERROR_NOT_OPEN;
570 if (ret == TRUE && file_transfer != NULL) {
572 gmyth_file_transfer_get_filesize (file_transfer);
574 g_object_unref (file_transfer);
577 file_info->block_count = GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT;
578 file_info->io_block_size =
579 GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE;
583 g_object_unref (backend_info);
586 return GNOME_VFS_ERROR_IO;
592 do_is_local (GnomeVFSMethod * method, const GnomeVFSURI * uri)
597 static GnomeVFSMethod method = {
598 sizeof (GnomeVFSMethod),
629 vfs_module_init (const char *method_name, const char *args)
635 vfs_module_shutdown (GnomeVFSMethod * method)