[svn r339] GObject's dispose methods organization, and reviewed clean-up actions.
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>
39 #define GST_MYTHTV_ID_NUM 1
40 #define MYTHTV_VERSION_DEFAULT 30
41 #define MYTHTV_TRANSFER_MAX_WAITS 100
43 #define MYTHTV_BUFFER_SIZE 1024*64
45 static GnomeVFSResult do_read (GnomeVFSMethod *method,
46 GnomeVFSMethodHandle *method_handle,
48 GnomeVFSFileSize num_bytes,
49 GnomeVFSFileSize *bytes_read,
50 GnomeVFSContext *context);
53 GMythFileTransfer *file_transfer;
66 do_open (GnomeVFSMethod *method,
67 GnomeVFSMethodHandle **method_handle,
69 GnomeVFSOpenMode mode,
70 GnomeVFSContext *context)
72 MythtvHandle *myth_handle;
73 GMythBackendInfo *backend_info;
74 GMythURI *gmyth_uri = NULL;
76 gboolean is_livetv = FALSE;
78 _GNOME_VFS_METHOD_PARAM_CHECK (method_handle != NULL);
79 _GNOME_VFS_METHOD_PARAM_CHECK (uri != NULL);
81 myth_handle = g_new0 (MythtvHandle, 1);
83 if (mode & GNOME_VFS_OPEN_WRITE) {
84 return GNOME_VFS_ERROR_NOT_PERMITTED;
87 if (gnome_vfs_uri_get_host_name (uri) == NULL) {
88 return GNOME_VFS_ERROR_INVALID_HOST_NAME;
91 /* Initialize mythtv handler*/
92 myth_handle->file_transfer = NULL;
93 myth_handle->livetv = NULL;
94 myth_handle->mythtv_version = MYTHTV_VERSION_DEFAULT;
95 myth_handle->bytes_read = 0;
96 myth_handle->content_size = (GnomeVFSFileSize) - 1;
98 /* Creates and fills out the backend info structure */
99 backend_info = gmyth_backend_info_new_with_uri (
100 gnome_vfs_unescape_string( gnome_vfs_uri_to_string( uri, GNOME_VFS_URI_HIDE_NONE ), "" ) );
102 /* creates an instance of */
103 gmyth_uri = gmyth_uri_new_with_value(
104 gnome_vfs_unescape_string( gnome_vfs_uri_to_string( uri, GNOME_VFS_URI_HIDE_NONE ), "" ) );
106 is_livetv = gmyth_uri_is_livetv( gmyth_uri );
108 /* Connect to the backend */
109 if ( gmyth_uri != NULL && is_livetv == TRUE ) {
110 myth_handle->livetv = gmyth_livetv_new ();
112 myth_handle->channel_name = gmyth_uri_get_channel_name( gmyth_uri );
114 g_print( "[%s] Channel name = %s", __FUNCTION__, myth_handle->channel_name );
116 if ( myth_handle->channel_name != NULL ) {
117 if (gmyth_livetv_channel_name_setup (myth_handle->livetv, myth_handle->channel_name,
118 backend_info) == FALSE) {
119 g_object_unref( gmyth_uri );
123 if ( gmyth_livetv_setup (myth_handle->livetv, backend_info) == FALSE ) {
124 g_object_unref( gmyth_uri );
129 myth_handle->file_transfer = gmyth_livetv_create_file_transfer (myth_handle->livetv);
131 if (NULL == myth_handle->file_transfer) {
133 g_warning ("MythTV FileTransfer is NULL!\n");
134 return GNOME_VFS_ERROR_NOT_OPEN;
137 if ( !gmyth_file_transfer_open( myth_handle->file_transfer, myth_handle->livetv->uri != NULL ?
138 gmyth_uri_get_path(myth_handle->livetv->uri) :
139 myth_handle->livetv->proginfo->pathname->str ) )
141 g_object_unref( myth_handle->file_transfer );
142 myth_handle->file_transfer = NULL;
148 myth_handle->file_transfer = gmyth_file_transfer_new (backend_info);
150 /* Verifies if the file exists */
151 if (!gmyth_util_file_exists (backend_info, gmyth_uri_get_path (gmyth_uri))) {
152 g_object_unref (backend_info);
156 /* sets the Playback monitor connection */
157 ret = gmyth_file_transfer_open ( myth_handle->file_transfer,
158 gmyth_uri_get_path (gmyth_uri) );
160 } /* if - LiveTV or not? */
163 g_warning ("MythTV FileTransfer open error.\n");
164 return GNOME_VFS_ERROR_NOT_OPEN;
167 g_object_unref (backend_info);
169 //if ( gmyth_uri != NULL )
170 // g_object_unref( gmyth_uri );
172 g_return_val_if_fail (myth_handle->file_transfer != NULL, GNOME_VFS_ERROR_NOT_OPEN);
174 if ( myth_handle->file_transfer->filesize < 0 && is_livetv ) {
175 myth_handle->content_size = (GnomeVFSFileSize) 0;
176 myth_handle->content_size = gmyth_recorder_get_file_position( myth_handle->livetv->recorder );
178 myth_handle->content_size = myth_handle->file_transfer->filesize;
180 myth_handle->buffer = g_byte_array_sized_new (MYTHTV_BUFFER_SIZE);
181 myth_handle->buffer_remain = 0;
183 *method_handle = (GnomeVFSMethodHandle *) myth_handle;
188 static GnomeVFSResult
189 do_read (GnomeVFSMethod *method,
190 GnomeVFSMethodHandle *method_handle,
192 GnomeVFSFileSize num_bytes,
193 GnomeVFSFileSize *bytes_read,
194 GnomeVFSContext *context)
196 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
197 GnomeVFSFileSize bytes_to_read;
201 if (myth_handle->bytes_read >= myth_handle->content_size)
202 return GNOME_VFS_ERROR_EOF;
204 // fixme: change this to min math function
205 if (myth_handle->content_size > 0 && num_bytes > ( myth_handle->content_size - myth_handle->bytes_read ))
206 bytes_to_read = myth_handle->content_size - myth_handle->bytes_read;
208 bytes_to_read = num_bytes;
210 /* Loop sending the Myth File Transfer request:
211 * Retry whilst authentication fails and we supply it. */
212 //if (myth_handle->buffer_remain < MYTHTV_BUFFER_SIZE) {
213 if ( ( myth_handle->buffer_remain = myth_handle->buffer->len ) < MYTHTV_BUFFER_SIZE ) {
214 GByteArray *tmp_buffer = g_byte_array_new();
216 printf ("XXXXXXXXXXXXXX Pedindo %d %d\n", MYTHTV_BUFFER_SIZE, myth_handle->buffer_remain);
218 gint len = gmyth_file_transfer_read (myth_handle->file_transfer,
219 tmp_buffer, MYTHTV_BUFFER_SIZE - myth_handle->buffer_remain, TRUE);
222 g_byte_array_free (tmp_buffer, TRUE);
223 g_print ("Fail to read bytes");
224 return GNOME_VFS_ERROR_IO;
225 } /*else if (len == 0) {
226 g_byte_array_free (tmp_buffer, TRUE);
227 g_warning ("End of file probably achieved");
228 return GNOME_VFS_ERROR_EOF;
231 myth_handle->buffer = g_byte_array_append (myth_handle->buffer,
232 tmp_buffer->data, len);
234 myth_handle->buffer_remain += len;
236 g_byte_array_free (tmp_buffer, TRUE);
240 bytes_to_read = (bytes_to_read > myth_handle->buffer_remain) ? myth_handle->buffer_remain : bytes_to_read;
241 /* gets the first buffer_size bytes from the byte array buffer variable */
243 g_memmove (buffer, myth_handle->buffer->data, bytes_to_read);
245 myth_handle->bytes_read += bytes_to_read;
246 myth_handle->buffer_remain -= bytes_to_read;
248 /* flushs the newly buffer got from byte array */
249 myth_handle->buffer = g_byte_array_remove_range (myth_handle->buffer, 0, bytes_to_read);
250 *bytes_read = bytes_to_read;
255 static GnomeVFSResult
256 do_close (GnomeVFSMethod *method,
257 GnomeVFSMethodHandle *method_handle,
258 GnomeVFSContext *context)
261 MythtvHandle *myth_handle = (MythtvHandle *) method_handle;
263 if (myth_handle->file_transfer) {
264 gmyth_file_transfer_close (myth_handle->file_transfer);
265 g_object_unref (myth_handle->file_transfer);
266 myth_handle->file_transfer = NULL;
269 if (myth_handle->livetv) {
270 g_object_unref (myth_handle->livetv);
271 myth_handle->livetv = NULL;
274 if (myth_handle->buffer) {
275 g_byte_array_free (myth_handle->buffer, TRUE);
276 myth_handle->buffer = NULL;
279 g_free (myth_handle);
284 static GnomeVFSResult
285 do_get_file_info (GnomeVFSMethod *method,
287 GnomeVFSFileInfo *file_info,
288 GnomeVFSFileInfoOptions options,
289 GnomeVFSContext *context)
291 GMythFileTransfer *file_transfer = NULL;
292 GMythRecorder *recorder = NULL;
293 GMythTVChain *tvchain = NULL;
294 GMythBackendInfo *backend_info = NULL;
295 GMythURI *gmyth_uri = NULL;
296 GMythSocket *socket = NULL;
297 gboolean is_livetv = FALSE;
300 /* Creates and fills out the backend info structure */
301 backend_info = gmyth_backend_info_new_with_uri (
302 gnome_vfs_unescape_string( gnome_vfs_uri_to_string( uri, GNOME_VFS_URI_HIDE_NONE ), "" ) );
304 /* creates an instance of */
305 gmyth_uri = gmyth_uri_new_with_value(
306 gnome_vfs_unescape_string( gnome_vfs_uri_to_string( uri, GNOME_VFS_URI_HIDE_NONE ), "" ) );
308 is_livetv = gmyth_uri_is_livetv( gmyth_uri );
310 file_info->valid_fields = file_info->valid_fields
311 | GNOME_VFS_FILE_INFO_FIELDS_TYPE
312 | GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE
313 | GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
314 file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
315 /* fixme: get from file extension? */
316 file_info->mime_type = g_strdup ("video/x-nuv");
317 file_info->permissions =
318 GNOME_VFS_PERM_USER_READ |
319 GNOME_VFS_PERM_OTHER_READ |
320 GNOME_VFS_PERM_GROUP_READ;
322 g_print( "gnome_vfs_uri == %s | gmyth_uri == %s.\n",
323 gnome_vfs_uri_get_path (uri),
324 gmyth_uri_get_path (gmyth_uri) );
326 /* Connect to the backend */
327 if ( gmyth_uri != NULL && is_livetv == TRUE ) {
331 /* start to get file info from LiveTV remote encoder */
333 socket = gmyth_socket_new ();
335 /* FIME: Implement this at gmyth_socket */
336 res = gmyth_socket_connect_to_backend (socket, backend_info->hostname,
337 backend_info->port, TRUE);
339 g_print ("[%s] LiveTV can not connect to backend", __FUNCTION__);
344 if ( gmyth_remote_util_get_free_recorder_count (socket) <= 0 ) {
345 g_print ("No free remote encoder available.");
350 /* Gets the recorder num */
351 recorder = remote_request_next_free_recorder (socket, -1);
353 if ( socket != NULL )
354 g_object_unref (socket);
356 if ( recorder == NULL ) {
357 g_print ("[%s] None remote encoder available", __FUNCTION__);
362 /* Init remote encoder. Opens its control socket. */
363 res = gmyth_recorder_setup(recorder);
365 g_print ("[%s] Fail while setting remote encoder\n", __FUNCTION__);
370 /* Creates livetv chain handler */
371 tvchain = gmyth_tvchain_new();
372 gmyth_tvchain_initialize ( tvchain, backend_info );
374 if ( tvchain == NULL || tvchain->tvchain_id == NULL ) {
375 g_print ("[%s] TVChain couldn't be initialized.\n", __FUNCTION__);
380 // Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly)
381 res = gmyth_recorder_spawntv ( recorder,
382 gmyth_tvchain_get_id(tvchain) );
384 g_print ("[%s] Fail while spawn tv\n", __FUNCTION__);
389 gchar* channel_name = gmyth_uri_get_channel_name( gmyth_uri );
392 /* loop finished, set the max tries variable to zero again... */
393 gint wait_to_transfer = 0;
395 while ( wait_to_transfer++ < MYTHTV_TRANSFER_MAX_WAITS &&
396 (gmyth_recorder_is_recording (recorder) == FALSE) )
399 /* IS_RECORDING again, just like the MythTV backend does... */
400 gmyth_recorder_is_recording (recorder);
402 if ( channel_name != NULL )
404 /* Pauses remote encoder. */
405 res = gmyth_recorder_pause_recording(recorder);
407 g_print ("[%s] Fail while pausing remote encoder\n", __FUNCTION__);
412 if ( gmyth_recorder_check_channel_name( recorder, channel_name ) )
414 if ( !gmyth_recorder_set_channel_name( recorder, channel_name ) )
416 g_warning( "Channel will not changes to: [%s].\n", channel_name );
420 } /* if - changes the channel number */
427 GMythProgramInfo* prog_info = gmyth_recorder_get_current_program_info( recorder );
428 //gmyth_debug( "New ProgramInfo...\n" );
429 gmyth_program_info_print( prog_info );
431 if ( prog_info != NULL )
434 g_print( "path = %s", prog_info->pathname->str );
436 file_info->name = g_strdup ( g_strrstr( prog_info->pathname->str, "/" ) );
439 size = gmyth_recorder_get_file_position( recorder );
442 //GMythProgramInfo *prog_info = gmyth_recorder_get_current_program_info ( recorder );
443 file_info->size = prog_info->filesize;
446 file_info->size = size;
449 file_info->size = gmyth_recorder_get_file_position( recorder );
452 if ( tvchain != NULL)
453 g_object_unref (tvchain);
455 if ( recorder != NULL )
456 gmyth_recorder_close (recorder);
458 if ( prog_info != NULL )
459 g_object_unref( prog_info );
463 /* start to get file info from remote file encoder */
464 file_transfer = gmyth_file_transfer_new (backend_info);
466 /* Verifies if the file exists */
467 if (!gmyth_util_file_exists (backend_info, gmyth_uri_get_path (gmyth_uri))) {
468 g_object_unref (backend_info);
469 return GNOME_VFS_ERROR_NOT_FOUND;
472 /* sets the Playback monitor connection */
473 ret = gmyth_file_transfer_open ( file_transfer, gmyth_uri_get_path (gmyth_uri) );
475 file_info->name = g_strdup ( gnome_vfs_uri_get_path (uri) );
478 } /* if - LiveTV or not? */
481 g_debug ("MythTV FileTransfer open error\n");
482 return GNOME_VFS_ERROR_NOT_OPEN;
485 if ( ret == TRUE && file_transfer != NULL ) {
486 file_info->size = gmyth_file_transfer_get_filesize (file_transfer);
488 gmyth_file_transfer_close (file_transfer);
491 file_info->block_count = GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT;
492 file_info->io_block_size = GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE;
496 g_object_unref (backend_info);
502 do_is_local (GnomeVFSMethod *method,
503 const GnomeVFSURI *uri)
508 static GnomeVFSMethod method = {
509 sizeof (GnomeVFSMethod),
540 vfs_module_init (const char *method_name, const char *args)
546 vfs_module_shutdown (GnomeVFSMethod *method)