gmyth/src/gmyth_livetv.c
author renatofilho
Tue Nov 28 21:04:14 2006 +0000 (2006-11-28)
branchtrunk
changeset 131 d1ae310096bd
parent 117 b90cf50ca3dc
child 203 a43fed947ec8
permissions -rwxr-xr-x
[svn r132] implemented debug function
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_livetv.c
     5  * 
     6  * @brief <p> GMythLiveTV starts a remote TV session with the MythTV backend.
     7  *
     8  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
     9  * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
    10  *
    11  *//*
    12  * 
    13  * This program is free software; you can redistribute it and/or modify
    14  * it under the terms of the GNU Lesser General Public License as published by
    15  * the Free Software Foundation; either version 2 of the License, or
    16  * (at your option) any later version.
    17  *
    18  * This program is distributed in the hope that it will be useful,
    19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    21  * GNU General Public License for more details.
    22  *
    23  * You should have received a copy of the GNU Lesser General Public License
    24  * along with this program; if not, write to the Free Software
    25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    26  */
    27  
    28 #include "gmyth_remote_util.h"
    29 #include "gmyth_tvchain.h"
    30 #include "gmyth_socket.h"
    31 #include "gmyth_debug.h"
    32 
    33 #include "gmyth_livetv.h"
    34 #include "gmyth_file_transfer.h"
    35 
    36 static void gmyth_livetv_class_init          (GMythLiveTVClass *klass);
    37 static void gmyth_livetv_init                (GMythLiveTV *object);
    38 
    39 static void gmyth_livetv_dispose  (GObject *object);
    40 static void gmyth_livetv_finalize (GObject *object);
    41 
    42 static gint tvchain_curr_index = -1; 
    43 
    44 #define GMYTHTV_RECORDER_HEADER         "QUERY_RECORDER"
    45 
    46 
    47 G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT)
    48 
    49 static void
    50 gmyth_livetv_class_init (GMythLiveTVClass *klass)
    51 {
    52 	GObjectClass *gobject_class;
    53 
    54 	gobject_class = (GObjectClass *) klass;
    55 
    56 	gobject_class->dispose  = gmyth_livetv_dispose;
    57 	gobject_class->finalize = gmyth_livetv_finalize;	
    58 }
    59 
    60 static void
    61 gmyth_livetv_init (GMythLiveTV *livetv)
    62 {
    63 	livetv->backend_hostname = NULL;
    64 	livetv->backend_port = 0;
    65 	livetv->local_hostname = NULL;
    66 
    67 	livetv->recorder = NULL;
    68 	livetv->tvchain = NULL;
    69 	livetv->proginfo = NULL;
    70 }
    71 
    72 static void
    73 gmyth_livetv_dispose  (GObject *object)
    74 {
    75 
    76 	G_OBJECT_CLASS (gmyth_livetv_parent_class)->dispose (object);
    77 }
    78 
    79 static void
    80 gmyth_livetv_finalize (GObject *object)
    81 {
    82 	g_signal_handlers_destroy (object);
    83 
    84 	GMythLiveTV *livetv = GMYTH_LIVETV (object);
    85 
    86 	gmyth_debug ("[%s] Finalizing livetv", __FUNCTION__);
    87 
    88 	if ( livetv->recorder != NULL ) {
    89 		g_object_unref (livetv->recorder);
    90 		livetv->recorder = NULL;
    91 	}
    92 
    93 	if ( livetv->tvchain != NULL ) {
    94 		g_object_unref (livetv->tvchain);
    95 		livetv->tvchain = NULL;
    96 	}
    97 
    98 	if ( livetv->proginfo != NULL ) {
    99 		g_object_unref (livetv->proginfo);
   100 		livetv->proginfo = NULL;
   101 	}
   102 
   103 	G_OBJECT_CLASS ( gmyth_livetv_parent_class )->finalize ( object );
   104 }
   105 
   106 GMythLiveTV*
   107 gmyth_livetv_new ()
   108 {
   109 	GMythLiveTV *livetv = GMYTH_LIVETV ( g_object_new( GMYTH_LIVETV_TYPE, NULL ) );
   110 
   111 	return livetv;
   112 }
   113 
   114 gboolean
   115 gmyth_livetv_setup ( GMythLiveTV *livetv, GMythBackendInfo *backend_info )
   116 {
   117 	gboolean res = TRUE;
   118 	char *hostname;
   119 
   120 	GMythSocket *socket = gmyth_socket_new ();
   121 
   122 	// FIME: Implement this at gmyth_socket
   123 	res = gmyth_socket_connect_to_backend (socket, backend_info->hostname,
   124 			backend_info->port, TRUE);
   125 	if (!res) {
   126 		g_warning ("[%s] LiveTV can not connect to backend", __FUNCTION__);	
   127 		res = FALSE;
   128 		goto error;
   129 	}
   130 
   131 	livetv->is_livetv = TRUE;
   132 
   133 	hostname = gmyth_backend_info_get_hostname(backend_info);
   134 	livetv->backend_hostname = g_string_new (hostname);
   135 	livetv->backend_port = gmyth_backend_info_get_port (backend_info);
   136 
   137 	livetv->local_hostname  = gmyth_socket_get_local_hostname ( );
   138 
   139 	if ( livetv->local_hostname == NULL ) {
   140 		res = FALSE;
   141 		goto error;
   142 	}
   143 
   144 	// Gets the recorder num
   145 	livetv->recorder = remote_request_next_free_recorder (socket, -1);
   146 	gmyth_socket_close_connection (socket);
   147 
   148 	if ( livetv->recorder == NULL ) {
   149 		g_warning ("[%s] None remote encoder available", __FUNCTION__);
   150 		res = FALSE;
   151 		goto error;
   152 	}
   153 
   154 	// Creates livetv chain handler
   155 	livetv->tvchain = GMYTH_TVCHAIN ( g_object_new(GMYTH_TVCHAIN_TYPE, NULL) );
   156 	gmyth_tvchain_initialize ( livetv->tvchain, backend_info );
   157 
   158 	if ( livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL ) {
   159 		res = FALSE;
   160 		goto error;
   161 	}
   162 
   163 	// Init remote encoder. Opens its control socket.
   164 	res = gmyth_recorder_setup(livetv->recorder);
   165 	if ( !res ) {
   166 		g_warning ("[%s] Fail while setting remote encoder\n", __FUNCTION__);
   167 		res = FALSE;
   168 		goto error;
   169 	}
   170 
   171 #if 0
   172   gint ch = 1011;
   173   gint idx = 0;  
   174   for ( ; idx < 5; idx++ ) {
   175   	if ( gmyth_recorder_check_channel( livetv->recorder, ch ) ) {
   176 	  	if ( gmyth_recorder_set_channel( livetv->recorder, ch ) ) {
   177 	  		g_print( "[%s] Channel changed!!! [%d].\n", __FUNCTION__, ch );
   178 	  		break;
   179 	  	}
   180   	}
   181   	++ch;
   182   }
   183 #endif
   184 
   185 	// Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly)
   186 	res = gmyth_recorder_spawntv ( livetv->recorder,
   187 			gmyth_tvchain_get_id(livetv->tvchain) );
   188 	if (!res) {
   189 		g_warning ("[%s] Fail while spawn tv\n", __FUNCTION__);
   190 		res = FALSE;
   191 		goto error;
   192 	}
   193 
   194 	// Reload all TV chain from Mysql database.
   195 	gmyth_tvchain_reload_all (livetv->tvchain);
   196 
   197 	if ( livetv->tvchain == NULL ) {
   198 		res = FALSE;
   199 		goto error;
   200 	}
   201 
   202 	// Get program info from database using chanid and starttime
   203 	livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, tvchain_curr_index++ );
   204 	if ( livetv->proginfo == NULL ) {
   205 		g_warning ("[%s] LiveTV not successfully started.\n", __FUNCTION__ );
   206 		res = FALSE;
   207 		goto error;
   208 	} else {
   209 		gmyth_debug ("[%s] GMythLiveTV: All requests to backend to start TV were OK.\n", __FUNCTION__ );
   210 	}
   211 
   212 	return res;
   213 
   214 error:
   215 	g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
   216 	if ( livetv->backend_hostname != NULL ) {
   217 		g_string_free( livetv->backend_hostname, TRUE );
   218 		res = FALSE;
   219 	}
   220 
   221 	if ( livetv->local_hostname != NULL ) {
   222 		g_string_free( livetv->local_hostname, TRUE );
   223 		res = FALSE;
   224 	}
   225 
   226 	if ( livetv->recorder != NULL ) {
   227 		g_object_unref (livetv->recorder);
   228 		livetv->recorder = NULL;
   229 	}
   230 
   231 	if ( livetv->tvchain != NULL ) {
   232 		g_object_unref (livetv->tvchain);
   233 		livetv->tvchain = NULL;
   234 	}
   235 
   236 	if ( livetv->proginfo != NULL ) {
   237 		g_object_unref (livetv->proginfo);
   238 		livetv->proginfo = NULL;
   239 	}
   240 
   241 	return res;
   242 
   243 }
   244 
   245 gboolean
   246 gmyth_livetv_next_program_chain ( GMythLiveTV *livetv )
   247 {
   248 	gboolean res = TRUE;
   249 	
   250 	// Reload all TV chain from Mysql database.
   251 	gmyth_tvchain_reload_all (livetv->tvchain);
   252 
   253 	if ( livetv->tvchain == NULL ) {
   254 		res = FALSE;
   255 		goto error;
   256 	}
   257 
   258 	// Get program info from database using chanid and starttime
   259 	livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, -1 );
   260 	if ( livetv->proginfo == NULL ) {
   261 		g_warning ("[%s] LiveTV not successfully started on the next program chain.\n", __FUNCTION__ );
   262 		res = FALSE;
   263 		goto error;
   264 	} else {
   265 		gmyth_debug ("[%s] GMythLiveTV: All requests to backend to start TV were OK, TV chain changed.\n", __FUNCTION__ );
   266 	}
   267 
   268 	return res;
   269 
   270 error:
   271 	g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
   272 	if ( livetv->backend_hostname != NULL ) {
   273 		g_string_free( livetv->backend_hostname, TRUE );
   274 		res = FALSE;
   275 	}
   276 
   277 	if ( livetv->local_hostname != NULL ) {
   278 		g_string_free( livetv->local_hostname, TRUE );
   279 		res = FALSE;
   280 	}
   281 
   282 	if ( livetv->recorder != NULL ) {
   283 		g_object_unref (livetv->recorder);
   284 		livetv->recorder = NULL;
   285 	}
   286 
   287 	if ( livetv->tvchain != NULL ) {
   288 		g_object_unref (livetv->tvchain);
   289 		livetv->tvchain = NULL;
   290 	}
   291 
   292 	if ( livetv->proginfo != NULL ) {
   293 		g_object_unref (livetv->proginfo);
   294 		livetv->proginfo = NULL;
   295 	}
   296 
   297 	return res;
   298 
   299 }
   300 
   301 // FIXME: How to proceed differently between livetv and recorded content
   302 void
   303 gmyth_livetv_stop_playing (GMythLiveTV *livetv) 
   304 {
   305 	gmyth_debug ("[%s] Stopping the LiveTV...\n", __FUNCTION__);
   306 
   307 	if (livetv->is_livetv) {
   308 		if (!gmyth_recorder_stop_livetv (livetv->recorder)) {
   309 			g_warning ("[%s] Error while stoping remote encoder", __FUNCTION__);	
   310 		}
   311 	}
   312 }
   313 
   314 // FIXME: put here just a wrapper function to call gmyth_recorder_is_recording()...
   315 gboolean
   316 gmyth_livetv_is_recording ( GMythLiveTV *livetv )
   317 {
   318   gboolean ret = TRUE;
   319 
   320   GMythStringList *str_list = gmyth_string_list_new ();
   321   GString *message = g_string_new ("");
   322 
   323   gmyth_debug ( "[%s]\n", __FUNCTION__ );
   324   //g_static_mutex_lock (&mutex);
   325   //
   326   g_string_printf( message, "%s %d", GMYTHTV_RECORDER_HEADER,
   327       /* FIXME file_transfer->rec_id >= 0 ? file_transfer->rec_id : file_transfer->card_id );*/
   328         livetv->recorder->recorder_num);
   329   gmyth_string_list_append_string (str_list, message);
   330   gmyth_string_list_append_string (str_list, g_string_new ("IS_RECORDING"));
   331 
   332   gmyth_socket_sendreceive_stringlist ( livetv->recorder->myth_socket, str_list );
   333 
   334   if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 )
   335   {
   336     GString *str = NULL;
   337     if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strcmp( str->str, "bad" )!= 0 ) {
   338       gint is_rec = gmyth_string_list_get_int( str_list, 0 );
   339       if ( is_rec != 0 )
   340         ret = TRUE;
   341       else
   342         ret = FALSE;
   343     }
   344   }
   345   g_print( "[%s] %s, stream is %s being recorded!\n", __FUNCTION__, ret ? "YES" : "NO", ret ? "" : "NOT" );
   346   //g_static_mutex_unlock (&mutex);
   347 
   348   if ( str_list != NULL )
   349     g_object_unref (str_list);
   350 
   351   return ret;
   352 
   353 }
   354 
   355 
   356 gboolean
   357 gmyth_livetv_is_playing (GMythLiveTV *livetv)
   358 {
   359 	return TRUE;
   360 }
   361 
   362 void
   363 gmyth_livetv_start_playing (GMythLiveTV *livetv)
   364 {
   365 
   366 	// TODO
   367 
   368 }
   369