renatofilho@320: /** renatofilho@320: * GMyth Library renatofilho@320: * renatofilho@320: * @file gmyth/gmyth_livetv.c renatofilho@320: * renatofilho@320: * @brief

GMythLiveTV starts a remote TV session with the MythTV backend. renatofilho@320: * renatofilho@320: * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. renatofilho@320: * @author Rosfran Lins Borges renatofilho@320: * renatofilho@320: *//* renatofilho@320: * renatofilho@320: * This program is free software; you can redistribute it and/or modify renatofilho@320: * it under the terms of the GNU Lesser General Public License as published by renatofilho@320: * the Free Software Foundation; either version 2 of the License, or renatofilho@320: * (at your option) any later version. renatofilho@320: * renatofilho@320: * This program is distributed in the hope that it will be useful, renatofilho@320: * but WITHOUT ANY WARRANTY; without even the implied warranty of renatofilho@320: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the renatofilho@320: * GNU General Public License for more details. renatofilho@320: * renatofilho@320: * You should have received a copy of the GNU Lesser General Public License renatofilho@320: * along with this program; if not, write to the Free Software renatofilho@320: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA renatofilho@320: */ renatofilho@320: renatofilho@320: #ifdef HAVE_CONFIG_H renatofilho@320: #include "config.h" renatofilho@320: #endif renatofilho@320: renatofilho@320: #include "gmyth_livetv.h" renatofilho@320: #include "gmyth_remote_util.h" renatofilho@320: #include "gmyth_tvchain.h" renatofilho@320: #include "gmyth_socket.h" renatofilho@320: #include "gmyth_backendinfo.h" renatofilho@320: #include "gmyth_debug.h" renatofilho@320: renatofilho@320: #include "gmyth_file_transfer.h" renatofilho@320: #include "gmyth_monitor_handler.h" renatofilho@320: renatofilho@320: static void gmyth_livetv_class_init (GMythLiveTVClass *klass); renatofilho@320: static void gmyth_livetv_init (GMythLiveTV *object); renatofilho@320: renatofilho@320: static void gmyth_livetv_dispose (GObject *object); renatofilho@320: static void gmyth_livetv_finalize (GObject *object); renatofilho@320: renatofilho@320: static gint tvchain_curr_index = -1; renatofilho@320: renatofilho@320: static GStaticMutex lock = G_STATIC_MUTEX_INIT; renatofilho@320: renatofilho@320: #define GMYTHTV_TRANSFER_MAX_WAITS 100 renatofilho@320: renatofilho@320: G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT) renatofilho@320: renatofilho@320: static void renatofilho@320: gmyth_livetv_class_init (GMythLiveTVClass *klass) renatofilho@320: { renatofilho@320: GObjectClass *gobject_class; renatofilho@320: renatofilho@320: gobject_class = (GObjectClass *) klass; renatofilho@320: renatofilho@320: gobject_class->dispose = gmyth_livetv_dispose; renatofilho@320: gobject_class->finalize = gmyth_livetv_finalize; renatofilho@320: } renatofilho@320: renatofilho@320: static void renatofilho@320: gmyth_livetv_init (GMythLiveTV *livetv) renatofilho@320: { renatofilho@320: livetv->backend_info = NULL; renatofilho@320: livetv->local_hostname = NULL; renatofilho@320: livetv->file_transfer = NULL; renatofilho@320: livetv->setup_done = FALSE; renatofilho@320: renatofilho@320: livetv->recorder = NULL; renatofilho@320: livetv->tvchain = NULL; renatofilho@320: livetv->proginfo = NULL; renatofilho@320: livetv->uri = NULL; renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: static void renatofilho@320: gmyth_livetv_dispose (GObject *object) renatofilho@320: { renatofilho@320: G_OBJECT_CLASS (gmyth_livetv_parent_class)->dispose (object); renatofilho@320: } renatofilho@320: renatofilho@320: static void renatofilho@320: gmyth_livetv_finalize (GObject *object) renatofilho@320: { renatofilho@320: g_signal_handlers_destroy (object); renatofilho@320: renatofilho@320: GMythLiveTV *livetv = GMYTH_LIVETV (object); renatofilho@320: renatofilho@320: gmyth_debug ("Finalizing livetv"); renatofilho@320: renatofilho@320: if ( livetv->monitor != NULL ) { renatofilho@320: g_object_unref (livetv->monitor); renatofilho@320: livetv->monitor = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->recorder != NULL ) { renatofilho@320: g_object_unref (livetv->recorder); renatofilho@320: livetv->recorder = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->tvchain != NULL ) { renatofilho@320: g_object_unref (livetv->tvchain); renatofilho@320: livetv->tvchain = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->proginfo != NULL ) { renatofilho@320: g_object_unref (livetv->proginfo); renatofilho@320: livetv->proginfo = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->file_transfer != NULL ) { renatofilho@320: g_object_unref (livetv->file_transfer); renatofilho@320: livetv->file_transfer = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->backend_info != NULL ) { renatofilho@320: g_object_unref (livetv->backend_info); renatofilho@320: livetv->backend_info = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->uri != NULL ) renatofilho@320: { renatofilho@320: g_object_unref (livetv->uri); renatofilho@320: livetv->uri = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: G_OBJECT_CLASS ( gmyth_livetv_parent_class )->finalize ( object ); renatofilho@320: } renatofilho@320: renatofilho@320: GMythLiveTV* renatofilho@320: gmyth_livetv_new () renatofilho@320: { renatofilho@320: GMythLiveTV *livetv = GMYTH_LIVETV ( g_object_new( GMYTH_LIVETV_TYPE, NULL ) ); renatofilho@320: renatofilho@320: return livetv; renatofilho@320: } renatofilho@320: renatofilho@320: static void renatofilho@320: gmyth_livetv_monitor_signal_handler( GMythMonitorHandler *monitor, gint msg_code, renatofilho@320: gchar* message, gpointer user_data ) renatofilho@320: { renatofilho@320: GMythLiveTV *live_tv = GMYTH_LIVETV ( user_data ); renatofilho@320: //g_object_ref( live_tv ); renatofilho@320: renatofilho@320: gmyth_debug( "LIVETV Signal handler ( msg = %s, code = %d, live_tv param = %s, user_data = %s )\n", message, msg_code, live_tv != NULL ? "" : renatofilho@320: "NULL", user_data != NULL ? "" : "NULL" ); renatofilho@320: renatofilho@320: if ( NULL == live_tv ) renatofilho@320: { renatofilho@320: gmyth_debug( "LiveTV_obj is equals to NULL!!!" ); renatofilho@320: return; renatofilho@320: } renatofilho@320: renatofilho@320: switch ( msg_code ) renatofilho@320: { renatofilho@320: renatofilho@320: case GMYTH_BACKEND_PROGRAM_INFO_CHANGED: renatofilho@320: { renatofilho@320: gmyth_debug( "LIVETV Program Changed request received [ msg = %s ]. Watching if the new "\ renatofilho@320: "TV Chain ID is the same as the old one...\n", message ); renatofilho@320: if ( g_ascii_strcasecmp ( message, (gmyth_tvchain_get_id( live_tv->tvchain ))->str ) != 0 ) { renatofilho@320: gmyth_debug( "OK!!! MOVED to the next program chain [actual == %s]!", renatofilho@320: (gmyth_tvchain_get_id( live_tv->tvchain ))->str ); renatofilho@320: /* advertises the FileTransfer about the program info changed */ renatofilho@320: if ( live_tv->file_transfer != NULL ) renatofilho@320: { renatofilho@320: gmyth_debug( "Emitting signal to the FileTransfer... [ \"program-info-changed \" ]" ); renatofilho@320: renatofilho@320: gmyth_file_transfer_emit_program_info_changed_signal( live_tv->file_transfer, renatofilho@320: msg_code, (gpointer)live_tv ); renatofilho@320: renatofilho@320: //gmyth_livetv_monitor_handler_stop( live_tv ); renatofilho@320: } else renatofilho@320: gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); renatofilho@320: } renatofilho@320: } renatofilho@320: case GMYTH_BACKEND_DONE_RECORDING: renatofilho@320: { renatofilho@320: gmyth_debug( "LIVETV Program Changed request received [ msg = %s ]. Watching if the new "\ renatofilho@320: "TV Chain ID is the same as the old one...\n", message ); renatofilho@320: if ( g_ascii_strcasecmp ( message, (gmyth_tvchain_get_id( live_tv->tvchain ))->str ) != 0 ) { renatofilho@320: gmyth_debug( "OK!!! MOVED to the next program chain [actual == %s]!", renatofilho@320: (gmyth_tvchain_get_id( live_tv->tvchain ))->str ); renatofilho@320: /* advertises the FileTransfer about the program info changed */ renatofilho@320: if ( live_tv->file_transfer != NULL ) renatofilho@320: { renatofilho@320: gmyth_debug( "Emitting signal to the FileTransfer... [ \"program-info-changed \" ]" ); renatofilho@320: renatofilho@320: gmyth_file_transfer_emit_program_info_changed_signal( live_tv->file_transfer, renatofilho@320: msg_code, (gpointer)live_tv ); renatofilho@320: renatofilho@320: //gmyth_livetv_monitor_handler_stop( live_tv ); renatofilho@320: } else renatofilho@320: gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); renatofilho@320: } renatofilho@320: renatofilho@320: break; renatofilho@320: } renatofilho@320: default: renatofilho@320: break; renatofilho@320: } /* switch (Monitor Handler messages) */ renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: gboolean renatofilho@320: gmyth_livetv_monitor_handler_start( GMythLiveTV *livetv ) renatofilho@320: { renatofilho@320: gboolean res = TRUE; renatofilho@320: renatofilho@320: if ( livetv->monitor != NULL ) renatofilho@320: { renatofilho@320: g_object_unref( livetv->monitor ); renatofilho@320: livetv->monitor = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: livetv->monitor = gmyth_monitor_handler_new ( ); renatofilho@320: renatofilho@320: res = gmyth_monitor_handler_open (livetv->monitor, livetv->backend_info->hostname, renatofilho@320: livetv->backend_info->port ); renatofilho@320: renatofilho@320: if ( res == TRUE ) renatofilho@320: { renatofilho@320: gmyth_debug("Connect MythTV Monitor event socket! Trying to start the message handler..."); renatofilho@320: renatofilho@320: res = gmyth_monitor_handler_start ( livetv->monitor ); renatofilho@320: renatofilho@320: if (res) renatofilho@320: { renatofilho@320: gmyth_debug("MythTV Monitor event socket connected and listening!"); renatofilho@320: g_signal_connect ( G_OBJECT (livetv->monitor), "backend-events-handler", renatofilho@320: (GCallback)gmyth_livetv_monitor_signal_handler, renatofilho@320: livetv ); renatofilho@320: } renatofilho@320: else renatofilho@320: { renatofilho@320: gmyth_debug("Problems when trying to start MythTV Monitor event socket!"); renatofilho@320: goto error; renatofilho@320: } renatofilho@320: } renatofilho@320: renatofilho@320: error: renatofilho@320: return res; renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: void renatofilho@320: gmyth_livetv_monitor_handler_stop( GMythLiveTV *livetv ) renatofilho@320: { renatofilho@320: renatofilho@320: if ( livetv->monitor != NULL ) renatofilho@320: { renatofilho@320: g_object_unref( livetv->monitor ); renatofilho@320: livetv->monitor = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: renatofilho@320: /* renatofilho@320: static gchar* renatofilho@320: gmyth_livetv_create_remote_url( GMythLiveTV *livetv ) renatofilho@320: { renatofilho@320: gchar *uri = g_strdup(""); renatofilho@320: gmyth_backend_info_get_remote_h renatofilho@320: renatofilho@320: //gmyth_backend(livetv->backend_info) renatofilho@320: renatofilho@320: return uri; renatofilho@320: } renatofilho@320: */ renatofilho@320: renatofilho@320: static gboolean renatofilho@320: gmyth_livetv_setup_recorder_channel_name ( GMythLiveTV *livetv, gchar* channel, GMythBackendInfo *backend_info ) renatofilho@320: { renatofilho@320: gboolean res = TRUE; renatofilho@320: renatofilho@320: GMythSocket *socket = gmyth_socket_new (); renatofilho@320: renatofilho@320: livetv->backend_info = backend_info; renatofilho@320: renatofilho@320: g_static_mutex_lock( &lock ); renatofilho@320: renatofilho@320: // FIME: Implement this at gmyth_socket renatofilho@320: res = gmyth_socket_connect_to_backend (socket, livetv->backend_info->hostname, renatofilho@320: livetv->backend_info->port, TRUE); renatofilho@320: if (!res) { renatofilho@320: g_warning ("[%s] LiveTV can not connect to backend", __FUNCTION__); renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: livetv->is_livetv = TRUE; renatofilho@320: renatofilho@320: livetv->local_hostname = gmyth_socket_get_local_hostname (); renatofilho@320: renatofilho@320: if ( livetv->local_hostname == NULL ) { renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: // Gets the recorder num renatofilho@320: livetv->recorder = remote_request_next_free_recorder (socket, -1); renatofilho@320: gmyth_socket_close_connection (socket); renatofilho@320: renatofilho@320: if ( livetv->recorder == NULL ) { renatofilho@320: g_warning ("[%s] None remote encoder available", __FUNCTION__); renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: // Init remote encoder. Opens its control socket. renatofilho@320: res = gmyth_recorder_setup(livetv->recorder); renatofilho@320: if ( !res ) { renatofilho@320: g_warning ("[%s] Fail while setting remote encoder\n", __FUNCTION__); renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: // Creates livetv chain handler renatofilho@320: livetv->tvchain = GMYTH_TVCHAIN ( g_object_new(GMYTH_TVCHAIN_TYPE, NULL) ); renatofilho@320: gmyth_tvchain_initialize ( livetv->tvchain, livetv->backend_info ); renatofilho@320: renatofilho@320: if ( livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL ) { renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: // Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly) renatofilho@320: res = gmyth_recorder_spawntv ( livetv->recorder, renatofilho@320: gmyth_tvchain_get_id(livetv->tvchain) ); renatofilho@320: if (!res) { renatofilho@320: g_warning ("[%s] Fail while spawn tv\n", __FUNCTION__); renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: if ( res == TRUE ) { renatofilho@320: /* loop finished, set the max tries variable to zero again... */ renatofilho@320: gint wait_to_transfer = 0; renatofilho@320: renatofilho@320: while (wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS && renatofilho@320: (gmyth_recorder_is_recording (livetv->recorder) == FALSE)) renatofilho@320: g_usleep (500); renatofilho@320: renatofilho@320: /* IS_RECORDING again, just like the MythTV backend does... */ renatofilho@320: gmyth_recorder_is_recording (livetv->recorder); renatofilho@320: renatofilho@320: if ( channel != NULL ) renatofilho@320: { renatofilho@320: /* Pauses remote encoder. */ renatofilho@320: res = gmyth_recorder_pause_recording(livetv->recorder); renatofilho@320: if ( !res ) { renatofilho@320: g_warning ("[%s] Fail while pausing remote encoder\n", __FUNCTION__); renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: if ( gmyth_recorder_check_channel_name( livetv->recorder, channel ) ) renatofilho@320: { renatofilho@320: if ( gmyth_recorder_set_channel_name( livetv->recorder, channel ) ) renatofilho@320: { renatofilho@320: g_print( "[%s] Channel changed!!! [%s].\n", __FUNCTION__, channel ); renatofilho@320: } renatofilho@320: } renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: sleep (9); /* FIXME: this is evil (tpm) */ renatofilho@320: } renatofilho@320: renatofilho@320: /* DEBUG message */ renatofilho@320: GMythProgramInfo* prog_info = gmyth_recorder_get_current_program_info( livetv->recorder ); renatofilho@320: renatofilho@320: if ( NULL == prog_info ) renatofilho@320: { renatofilho@320: gmyth_debug( "ProgramInfo is equals to NULL!!!" ); renatofilho@320: renatofilho@320: return FALSE; renatofilho@320: } renatofilho@320: /* prints program info data text */ renatofilho@320: gmyth_debug( "New ProgramInfo...\n" ); renatofilho@320: gmyth_program_info_print( prog_info ); renatofilho@320: /* DEBUG message */ renatofilho@320: gmyth_debug( "Old ProgramInfo...\n" ); renatofilho@320: gmyth_program_info_print( livetv->proginfo ); renatofilho@320: renatofilho@320: /* check if the program chain could be obtained from the MythTV protocol message */ renatofilho@320: if ( prog_info != NULL ) renatofilho@320: { renatofilho@320: livetv->proginfo = prog_info; renatofilho@320: /* testing change channel */ renatofilho@320: //gmyth_recorder_spawntv_no_tvchain( livetv->recorder ); renatofilho@320: } else { renatofilho@320: renatofilho@320: /* check for the program info in the TV program chain could be obtained renatofilho@320: from the MythTV MySQL database */ renatofilho@320: renatofilho@320: /* Reload all TV chain from Mysql database. */ renatofilho@320: gmyth_tvchain_reload_all (livetv->tvchain); renatofilho@320: renatofilho@320: if ( livetv->tvchain == NULL ) { renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: /* Get program info from database using chanid and starttime */ renatofilho@320: livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, tvchain_curr_index++ ); renatofilho@320: if ( livetv->proginfo == NULL ) { renatofilho@320: g_warning ("[%s] LiveTV not successfully started.\n", __FUNCTION__ ); renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } else { renatofilho@320: res = TRUE; renatofilho@320: gmyth_debug ("GMythLiveTV: All requests to backend to start TV were OK. [%s]\n", livetv->proginfo->pathname->str ); renatofilho@320: } renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: livetv->uri = (GMythURI*)gmyth_backend_info_get_uri( backend_info ); renatofilho@320: renatofilho@320: g_static_mutex_unlock( &lock ); renatofilho@320: renatofilho@320: if ( !gmyth_livetv_monitor_handler_start( livetv ) ) renatofilho@320: { renatofilho@320: res = FALSE; renatofilho@320: gmyth_debug( "LiveTV MONITOR handler error on setup!" ); renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: livetv->setup_done = TRUE; renatofilho@320: renatofilho@320: return res; renatofilho@320: renatofilho@320: error: renatofilho@320: g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ ); renatofilho@320: renatofilho@320: if ( livetv->local_hostname != NULL ) { renatofilho@320: g_string_free( livetv->local_hostname, FALSE ); renatofilho@320: res = FALSE; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->recorder != NULL ) { renatofilho@320: g_object_unref (livetv->recorder); renatofilho@320: livetv->recorder = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->tvchain != NULL ) { renatofilho@320: g_object_unref (livetv->tvchain); renatofilho@320: livetv->tvchain = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->proginfo != NULL ) { renatofilho@320: g_object_unref (livetv->proginfo); renatofilho@320: livetv->proginfo = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->monitor != NULL ) { renatofilho@320: g_object_unref (livetv->monitor); renatofilho@320: livetv->monitor = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: return res; renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: static gboolean renatofilho@320: gmyth_livetv_setup_recorder ( GMythLiveTV *livetv, gint channel, GMythBackendInfo *backend_info ) renatofilho@320: { renatofilho@320: return gmyth_livetv_setup_recorder_channel_name ( livetv, ( channel != -1 ) ? renatofilho@320: g_strdup_printf( "%d", channel ) : NULL, backend_info ); renatofilho@320: } renatofilho@320: renatofilho@320: gboolean renatofilho@320: gmyth_livetv_channel_setup ( GMythLiveTV *livetv, gint channel, GMythBackendInfo *backend_info ) renatofilho@320: { renatofilho@320: return gmyth_livetv_setup_recorder ( livetv, channel, backend_info ); renatofilho@320: } renatofilho@320: renatofilho@320: gboolean renatofilho@320: gmyth_livetv_channel_name_setup ( GMythLiveTV *livetv, gchar* channel, GMythBackendInfo *backend_info ) renatofilho@320: { renatofilho@320: return gmyth_livetv_setup_recorder_channel_name ( livetv, channel, backend_info ); renatofilho@320: } renatofilho@320: renatofilho@320: gboolean renatofilho@320: gmyth_livetv_setup ( GMythLiveTV *livetv, GMythBackendInfo *backend_info ) renatofilho@320: { renatofilho@320: return gmyth_livetv_setup_recorder ( livetv, -1, backend_info ); renatofilho@320: } renatofilho@320: renatofilho@320: gboolean renatofilho@320: gmyth_livetv_next_program_chain ( GMythLiveTV *livetv ) renatofilho@320: { renatofilho@320: gboolean res = TRUE; renatofilho@320: GMythProgramInfo *prog_info = NULL; renatofilho@320: renatofilho@320: if ( !livetv->setup_done ) renatofilho@320: { renatofilho@320: gmyth_debug ( "Call the setup function first!" ); renatofilho@320: res= FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: //if ( !gmyth_livetv_monitor_handler_start( livetv ) ) renatofilho@320: // goto error; renatofilho@320: prog_info = gmyth_recorder_get_current_program_info( livetv->recorder ); renatofilho@320: renatofilho@320: if ( NULL == prog_info ) renatofilho@320: { renatofilho@320: gmyth_debug( "ProgramInfo is equals to NULL!!!" ); renatofilho@320: renatofilho@320: return FALSE; renatofilho@320: } renatofilho@320: /* prints program info data text */ renatofilho@320: gmyth_program_info_print( prog_info ); renatofilho@320: renatofilho@320: if ( prog_info != NULL ) { renatofilho@320: res = TRUE; renatofilho@320: livetv->proginfo = prog_info; renatofilho@320: gmyth_debug ("GMythLiveTV: All requests to backend to start TV were OK, program info changed."); renatofilho@320: } else { renatofilho@320: g_warning ("[%s] LiveTV not successfully started on the next program chain.\n", __FUNCTION__ ); renatofilho@320: res = FALSE; renatofilho@320: goto error; renatofilho@320: } renatofilho@320: renatofilho@320: livetv->setup_done = TRUE; renatofilho@320: renatofilho@320: return res; renatofilho@320: renatofilho@320: error: renatofilho@320: g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ ); renatofilho@320: renatofilho@320: if ( livetv->local_hostname != NULL ) { renatofilho@320: g_string_free( livetv->local_hostname, FALSE ); renatofilho@320: res = FALSE; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->recorder != NULL ) { renatofilho@320: g_object_unref (livetv->recorder); renatofilho@320: livetv->recorder = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->tvchain != NULL ) { renatofilho@320: g_object_unref (livetv->tvchain); renatofilho@320: livetv->tvchain = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->proginfo != NULL ) { renatofilho@320: g_object_unref (livetv->proginfo); renatofilho@320: livetv->proginfo = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: return res; renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: GMythFileTransfer * renatofilho@320: gmyth_livetv_create_file_transfer( GMythLiveTV *livetv ) renatofilho@320: { renatofilho@320: //GMythURI* uri = NULL; renatofilho@320: renatofilho@320: if ( NULL == livetv ) renatofilho@320: goto done; renatofilho@320: renatofilho@320: if ( !livetv->setup_done ) renatofilho@320: { renatofilho@320: gmyth_debug( "Error: You must do the LiveTV setup, just before generating the FileTransfer from LiveTV source!" ); renatofilho@320: goto done; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->proginfo != NULL ) renatofilho@320: gmyth_debug( "URI path = %s.\n", livetv->proginfo->pathname->str ); renatofilho@320: else renatofilho@320: gmyth_debug( "URI path = %s.\n", livetv->uri->uri->str ); renatofilho@320: renatofilho@320: g_static_mutex_lock( &lock ); renatofilho@320: renatofilho@320: if ( livetv->file_transfer != NULL ) renatofilho@320: { renatofilho@320: /*gmyth_file_transfer_close( livetv->file_transfer );*/ renatofilho@320: g_object_unref( livetv->file_transfer ); renatofilho@320: livetv->file_transfer = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: livetv->file_transfer = gmyth_file_transfer_new( livetv->backend_info ); renatofilho@320: renatofilho@320: if ( NULL == livetv->file_transfer ) renatofilho@320: { renatofilho@320: gmyth_debug( "Error: couldn't create the FileTransfer from LiveTV source!" ); renatofilho@320: goto done; renatofilho@320: } renatofilho@320: renatofilho@320: if ( livetv->uri != NULL ) renatofilho@320: { renatofilho@320: if ( livetv->uri->path != NULL ) renatofilho@320: { renatofilho@320: g_string_free( livetv->uri->path, FALSE ); renatofilho@320: livetv->uri->path = NULL; renatofilho@320: } renatofilho@320: livetv->uri->path = g_string_new( g_strrstr( livetv->proginfo->pathname->str, "/" ) ); renatofilho@320: } else { renatofilho@320: livetv->uri = gmyth_uri_new_with_value( livetv->proginfo->pathname->str ); renatofilho@320: } renatofilho@320: renatofilho@320: if ( NULL == livetv->uri ) renatofilho@320: { renatofilho@320: gmyth_debug( "Couldn't parse the URI to start LiveTV! [ uri = %s ]", livetv->proginfo->pathname->str ); renatofilho@320: goto done; renatofilho@320: } renatofilho@320: renatofilho@320: if ( !gmyth_file_transfer_open( livetv->file_transfer, livetv->uri != NULL ? gmyth_uri_get_path(livetv->uri) : renatofilho@320: livetv->proginfo->pathname->str ) ) renatofilho@320: { renatofilho@320: gmyth_debug( "Error: couldn't open the FileTransfer from LiveTV source!" ); renatofilho@320: g_object_unref( livetv->file_transfer ); renatofilho@320: livetv->file_transfer = NULL; renatofilho@320: goto done; renatofilho@320: } renatofilho@320: renatofilho@320: g_static_mutex_unlock( &lock ); renatofilho@320: renatofilho@320: done: renatofilho@320: /* renatofilho@320: if ( uri != NULL ) renatofilho@320: { renatofilho@320: g_object_unref( uri ); renatofilho@320: uri = NULL; renatofilho@320: } renatofilho@320: */ renatofilho@320: renatofilho@320: return livetv->file_transfer; renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: /* FIXME: How to proceed differently between livetv and recorded content */ renatofilho@320: void renatofilho@320: gmyth_livetv_stop_playing (GMythLiveTV *livetv) renatofilho@320: { renatofilho@320: gmyth_debug ("Stopping the LiveTV...\n"); renatofilho@320: renatofilho@320: if (livetv->is_livetv) { renatofilho@320: if ( !gmyth_recorder_stop_livetv (livetv->recorder) ) { renatofilho@320: g_warning ("[%s] Error while stoping remote encoder", __FUNCTION__); renatofilho@320: } renatofilho@320: } renatofilho@320: } renatofilho@320: renatofilho@320: gboolean renatofilho@320: gmyth_livetv_is_playing (GMythLiveTV *livetv) renatofilho@320: { renatofilho@320: return TRUE; renatofilho@320: } renatofilho@320: renatofilho@320: void renatofilho@320: gmyth_livetv_start_playing (GMythLiveTV *livetv) renatofilho@320: { renatofilho@320: renatofilho@320: // TODO renatofilho@320: renatofilho@320: } renatofilho@320: