gmyth/src/gmyth_livetv.c
author renatofilho
Wed Mar 28 21:26:42 2007 +0100 (2007-03-28)
branchtrunk
changeset 468 f4c6061f6f39
parent 467 bc13aaf7561d
child 469 28879368706b
permissions -rwxr-xr-x
[svn r473] memory leek fix
rosfran@68
     1
/**
rosfran@68
     2
 * GMyth Library
rosfran@68
     3
 *
rosfran@68
     4
 * @file gmyth/gmyth_livetv.c
rosfran@68
     5
 * 
rosfran@68
     6
 * @brief <p> GMythLiveTV starts a remote TV session with the MythTV backend.
rosfran@68
     7
 *
rosfran@68
     8
 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
rosfran@68
     9
 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
rosfran@68
    10
 *
rosfran@68
    11
 *//*
rosfran@68
    12
 * 
rosfran@68
    13
 * This program is free software; you can redistribute it and/or modify
rosfran@68
    14
 * it under the terms of the GNU Lesser General Public License as published by
rosfran@68
    15
 * the Free Software Foundation; either version 2 of the License, or
rosfran@68
    16
 * (at your option) any later version.
rosfran@68
    17
 *
rosfran@68
    18
 * This program is distributed in the hope that it will be useful,
rosfran@68
    19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rosfran@68
    20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rosfran@68
    21
 * GNU General Public License for more details.
rosfran@68
    22
 *
rosfran@68
    23
 * You should have received a copy of the GNU Lesser General Public License
rosfran@68
    24
 * along with this program; if not, write to the Free Software
rosfran@68
    25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
rosfran@68
    26
 */
leo_sobral@213
    27
  
leo_sobral@213
    28
#ifdef HAVE_CONFIG_H
leo_sobral@213
    29
#include "config.h"
leo_sobral@213
    30
#endif
leo_sobral@213
    31
rosfran@240
    32
#include "gmyth_livetv.h" 
rosfran@42
    33
#include "gmyth_remote_util.h"
rosfran@42
    34
#include "gmyth_tvchain.h"
melunko@117
    35
#include "gmyth_socket.h"
rosfran@307
    36
#include "gmyth_backendinfo.h"
renatofilho@131
    37
#include "gmyth_debug.h"
rosfran@41
    38
rosfran@42
    39
#include "gmyth_file_transfer.h"
rosfran@216
    40
#include "gmyth_monitor_handler.h"
rosfran@41
    41
rosfran@428
    42
#include "gmyth_common.h"
rosfran@428
    43
rosfran@41
    44
static void gmyth_livetv_class_init          (GMythLiveTVClass *klass);
rosfran@41
    45
static void gmyth_livetv_init                (GMythLiveTV *object);
rosfran@41
    46
rosfran@41
    47
static void gmyth_livetv_dispose  (GObject *object);
rosfran@41
    48
static void gmyth_livetv_finalize (GObject *object);
rosfran@41
    49
rosfran@41
    50
static gint tvchain_curr_index = -1; 
rosfran@41
    51
rosfran@358
    52
/*static GStaticMutex lock = G_STATIC_MUTEX_INIT;*/
melunko@107
    53
rosfran@288
    54
#define GMYTHTV_TRANSFER_MAX_WAITS	    100
melunko@107
    55
rosfran@41
    56
G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT)
rosfran@41
    57
rosfran@41
    58
static void
rosfran@41
    59
gmyth_livetv_class_init (GMythLiveTVClass *klass)
rosfran@41
    60
{
rosfran@41
    61
	GObjectClass *gobject_class;
rosfran@41
    62
rosfran@41
    63
	gobject_class = (GObjectClass *) klass;
rosfran@41
    64
rosfran@41
    65
	gobject_class->dispose  = gmyth_livetv_dispose;
rosfran@41
    66
	gobject_class->finalize = gmyth_livetv_finalize;	
rosfran@41
    67
}
rosfran@41
    68
rosfran@41
    69
static void
rosfran@41
    70
gmyth_livetv_init (GMythLiveTV *livetv)
rosfran@41
    71
{
leo_sobral@437
    72
    livetv->monitor = NULL;
rosfran@216
    73
	livetv->backend_info = NULL;
rosfran@41
    74
	livetv->local_hostname = NULL;
rosfran@216
    75
	livetv->file_transfer = NULL;
rosfran@216
    76
	livetv->setup_done = FALSE;
rosfran@337
    77
	
rosfran@337
    78
	livetv->socket = NULL;
rosfran@65
    79
	livetv->recorder = NULL;
rosfran@41
    80
	livetv->tvchain = NULL;
rosfran@41
    81
	livetv->proginfo = NULL;
rosfran@307
    82
	livetv->uri = NULL;
rosfran@358
    83
	
leo_sobral@437
    84
	livetv->mutex = g_mutex_new();
rosfran@41
    85
}
rosfran@41
    86
rosfran@41
    87
static void
rosfran@41
    88
gmyth_livetv_dispose  (GObject *object)
rosfran@336
    89
{	
rosfran@41
    90
	GMythLiveTV *livetv = GMYTH_LIVETV (object);
rosfran@41
    91
leo_sobral@437
    92
    if (livetv->disposed) {
leo_sobral@437
    93
        /* If dispose did already run, return. */
leo_sobral@437
    94
        return;
leo_sobral@437
    95
    }
leo_sobral@437
    96
    
leo_sobral@437
    97
    /* Make sure dispose does not run twice. */
leo_sobral@437
    98
    livetv->disposed = TRUE;
leo_sobral@437
    99
rosfran@216
   100
	if ( livetv->monitor != NULL ) {
rosfran@216
   101
		g_object_unref (livetv->monitor);
rosfran@216
   102
		livetv->monitor = NULL;
rosfran@216
   103
	}
rosfran@337
   104
	
rosfran@65
   105
	if ( livetv->recorder != NULL ) {
rosfran@65
   106
		g_object_unref (livetv->recorder);
rosfran@65
   107
		livetv->recorder = NULL;
rosfran@41
   108
	}
rosfran@41
   109
rosfran@337
   110
	if ( livetv->socket != NULL ) {
rosfran@337
   111
		g_object_unref (livetv->socket);
rosfran@337
   112
		livetv->socket = NULL;
rosfran@337
   113
	}
rosfran@337
   114
	
rosfran@41
   115
	if ( livetv->tvchain != NULL ) {
rosfran@41
   116
		g_object_unref (livetv->tvchain);
rosfran@41
   117
		livetv->tvchain = NULL;
rosfran@41
   118
	}
rosfran@41
   119
rosfran@41
   120
	if ( livetv->proginfo != NULL ) {
rosfran@41
   121
		g_object_unref (livetv->proginfo);
rosfran@41
   122
		livetv->proginfo = NULL;
rosfran@41
   123
	}
rosfran@216
   124
	
leo_sobral@437
   125
	if ( livetv->file_transfer != NULL ) {
rosfran@216
   126
		g_object_unref (livetv->file_transfer);
rosfran@216
   127
		livetv->file_transfer = NULL;
rosfran@216
   128
	}
rosfran@216
   129
	
rosfran@216
   130
	if ( livetv->backend_info != NULL ) {
rosfran@216
   131
		g_object_unref (livetv->backend_info);
rosfran@216
   132
		livetv->backend_info = NULL;
rosfran@216
   133
	}
rosfran@307
   134
	
leo_sobral@437
   135
	if ( livetv->uri != NULL ) {
rosfran@307
   136
		g_object_unref (livetv->uri);
rosfran@307
   137
		livetv->uri = NULL;
rosfran@307
   138
	}
rosfran@336
   139
	
leo_sobral@437
   140
	if ( livetv->mutex != NULL ) {
rosfran@358
   141
		g_mutex_free (livetv->mutex);
rosfran@358
   142
		livetv->mutex = NULL;
rosfran@358
   143
	}
leo_sobral@452
   144
    
leo_sobral@452
   145
    if ( livetv->local_hostname != NULL ) {
leo_sobral@452
   146
        g_string_free (livetv->local_hostname, TRUE);
leo_sobral@452
   147
        livetv->local_hostname = NULL;
leo_sobral@452
   148
    }
leo_sobral@437
   149
rosfran@336
   150
	G_OBJECT_CLASS (gmyth_livetv_parent_class)->dispose (object);
rosfran@336
   151
}
rosfran@336
   152
rosfran@336
   153
static void
rosfran@336
   154
gmyth_livetv_finalize (GObject *object)
rosfran@336
   155
{
rosfran@336
   156
	g_signal_handlers_destroy (object);
rosfran@336
   157
rosfran@41
   158
	G_OBJECT_CLASS ( gmyth_livetv_parent_class )->finalize ( object );
rosfran@41
   159
}
rosfran@41
   160
rosfran@428
   161
/**
rosfran@428
   162
 * Creates a new GMythLiveTV instance
rosfran@428
   163
 * 
rosfran@428
   164
 * @return a newly allocated GMythLiveTV instance
rosfran@428
   165
 */
rosfran@41
   166
GMythLiveTV*
leo_sobral@437
   167
gmyth_livetv_new (GMythBackendInfo *backend_info)
rosfran@41
   168
{
rosfran@41
   169
	GMythLiveTV *livetv = GMYTH_LIVETV ( g_object_new( GMYTH_LIVETV_TYPE, NULL ) );
leo_sobral@437
   170
    
leo_sobral@437
   171
	livetv->backend_info = backend_info;
leo_sobral@437
   172
    g_object_ref (livetv->backend_info);
leo_sobral@437
   173
rosfran@41
   174
	return livetv;
rosfran@41
   175
}
rosfran@41
   176
rosfran@428
   177
/**
rosfran@428
   178
 * The GObject signal handler function, from which all status messages 
rosfran@428
   179
 * from the Monitor Handler will be advertized, all time it receives
rosfran@428
   180
 * LiveTV status messages from the MythTV backend
rosfran@428
   181
 * 
rosfran@428
   182
 * @param monitor a GMythMonitorHandler instance
rosfran@428
   183
 * @param msg_code the MythTV's server numeric status code
rosfran@428
   184
 * @param message the message's string description
rosfran@428
   185
 * @param user_data pointer to the GMythLiveTV instance
rosfran@428
   186
 */
rosfran@212
   187
static void
rosfran@212
   188
gmyth_livetv_monitor_signal_handler( GMythMonitorHandler *monitor, gint msg_code, 
rosfran@232
   189
							gchar* message, gpointer user_data )
rosfran@212
   190
{
rosfran@233
   191
	GMythLiveTV *live_tv = GMYTH_LIVETV ( user_data );
rosfran@216
   192
	
rosfran@232
   193
	gmyth_debug( "LIVETV Signal handler ( msg = %s, code = %d, live_tv param = %s, user_data = %s )\n", message, msg_code, live_tv != NULL ? "" : 
rosfran@220
   194
					"NULL", user_data != NULL ? "" : "NULL" );
rosfran@216
   195
	
rosfran@232
   196
	if ( NULL == live_tv )
rosfran@232
   197
	{
rosfran@232
   198
		gmyth_debug( "LiveTV_obj is equals to NULL!!!" );
rosfran@232
   199
		return;
rosfran@232
   200
	}		
rosfran@216
   201
	
rosfran@216
   202
	switch ( msg_code ) 
rosfran@216
   203
	{
rosfran@216
   204
		
rosfran@216
   205
		case GMYTH_BACKEND_PROGRAM_INFO_CHANGED:
rosfran@216
   206
		{
rosfran@234
   207
			gmyth_debug( "LIVETV Program Changed request received [ msg = %s ]. Watching if the new "\
rosfran@234
   208
				"TV Chain ID is the same as the old one...\n", message );
rosfran@234
   209
			if ( g_ascii_strcasecmp ( message, (gmyth_tvchain_get_id( live_tv->tvchain ))->str ) != 0 ) {				
rosfran@234
   210
				gmyth_debug( "OK!!! MOVED to the next program chain [actual == %s]!", 
rosfran@234
   211
										(gmyth_tvchain_get_id( live_tv->tvchain ))->str );
rosfran@234
   212
				/* advertises the FileTransfer about the program info changed */
rosfran@234
   213
				if ( live_tv->file_transfer != NULL )
rosfran@234
   214
				{
rosfran@234
   215
					gmyth_debug( "Emitting signal to the FileTransfer... [ \"program-info-changed \" ]" );
rosfran@234
   216
					
rosfran@234
   217
					gmyth_file_transfer_emit_program_info_changed_signal( live_tv->file_transfer,
rosfran@435
   218
		             msg_code, (gpointer)(live_tv->recorder) );
rosfran@234
   219
		             
rosfran@435
   220
					/* gmyth_livetv_monitor_handler_stop( live_tv ); */
rosfran@234
   221
				} else
rosfran@234
   222
					gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");				
rosfran@234
   223
			}
rosfran@399
   224
			break;
rosfran@298
   225
		}
rosfran@298
   226
		case GMYTH_BACKEND_DONE_RECORDING:
rosfran@298
   227
		{
rosfran@298
   228
			gmyth_debug( "LIVETV Program Changed request received [ msg = %s ]. Watching if the new "\
rosfran@298
   229
				"TV Chain ID is the same as the old one...\n", message );
rosfran@298
   230
			if ( g_ascii_strcasecmp ( message, (gmyth_tvchain_get_id( live_tv->tvchain ))->str ) != 0 ) {				
rosfran@298
   231
				gmyth_debug( "OK!!! MOVED to the next program chain [actual == %s]!", 
rosfran@298
   232
										(gmyth_tvchain_get_id( live_tv->tvchain ))->str );
rosfran@298
   233
				/* advertises the FileTransfer about the program info changed */
rosfran@298
   234
				if ( live_tv->file_transfer != NULL )
rosfran@298
   235
				{
rosfran@342
   236
					gmyth_debug( "Emitting signal to the FileTransfer... [ \"backend-done-recording\" ]" );
rosfran@298
   237
					
rosfran@298
   238
					gmyth_file_transfer_emit_program_info_changed_signal( live_tv->file_transfer,
rosfran@435
   239
		             msg_code, (gpointer)(live_tv->recorder) );
rosfran@298
   240
		             
rosfran@298
   241
				} else
rosfran@298
   242
					gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");				
rosfran@298
   243
			}
rosfran@399
   244
			break;
rosfran@374
   245
		}
rosfran@374
   246
		case GMYTH_BACKEND_STOP_LIVETV:
rosfran@374
   247
		{
rosfran@374
   248
			gmyth_debug( "LIVETV Stop LiveTV request received [ msg = %s ]. Going out the "\
rosfran@374
   249
				"LiveTV...\n", message );
rosfran@374
   250
			/* stops the LiveTV */
rosfran@374
   251
			if ( live_tv != NULL )
rosfran@374
   252
			{
rosfran@374
   253
				gmyth_debug( "Going out the LiveTV... [ \"quit-livetv\" ]" );
rosfran@374
   254
				
leo_sobral@437
   255
				g_object_unref( live_tv );
rosfran@374
   256
			} else
rosfran@374
   257
				gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");				
rosfran@298
   258
			
rosfran@216
   259
			break;
rosfran@216
   260
		}
rosfran@216
   261
		default:
rosfran@220
   262
			break;		
rosfran@220
   263
	} /* switch (Monitor Handler messages) */
rosfran@220
   264
	
rosfran@220
   265
}
rosfran@220
   266
rosfran@428
   267
/**
rosfran@428
   268
 * Starts the Monitor Handler to this GMythLiveTV session, in order
rosfran@428
   269
 * to receive the status messages from the MythTV's backend server 
rosfran@428
   270
 * 
rosfran@428
   271
 * @param live_tv the GMythLiveTV instance
rosfran@428
   272
 * 
rosfran@428
   273
 * @return <code>true</code> if the Monitor Handler start-up process
rosfran@428
   274
 * 	   had been concluded succcesfully 
rosfran@428
   275
 */
rosfran@220
   276
gboolean
rosfran@220
   277
gmyth_livetv_monitor_handler_start( GMythLiveTV *livetv )
rosfran@220
   278
{
rosfran@220
   279
	gboolean res = TRUE;
rosfran@220
   280
	
rosfran@220
   281
	if ( livetv->monitor != NULL )
rosfran@220
   282
	{
rosfran@220
   283
		g_object_unref( livetv->monitor );
rosfran@220
   284
		livetv->monitor	= NULL;
rosfran@216
   285
	}
rosfran@216
   286
	
rosfran@220
   287
  livetv->monitor = gmyth_monitor_handler_new ( );
rosfran@220
   288
  
rosfran@220
   289
  res = gmyth_monitor_handler_open (livetv->monitor, livetv->backend_info->hostname, 
rosfran@220
   290
  				livetv->backend_info->port );
rosfran@220
   291
  
rosfran@220
   292
  if ( res == TRUE )
rosfran@220
   293
  {
rosfran@220
   294
  	gmyth_debug("Connect MythTV Monitor event socket! Trying to start the message handler...");
rosfran@220
   295
  	
rosfran@220
   296
  	res = gmyth_monitor_handler_start ( livetv->monitor );
rosfran@220
   297
  	
rosfran@220
   298
  	if (res)
rosfran@220
   299
  	{
rosfran@220
   300
  		gmyth_debug("MythTV Monitor event socket connected and listening!");
rosfran@220
   301
  		g_signal_connect ( G_OBJECT (livetv->monitor), "backend-events-handler",
rosfran@220
   302
                  (GCallback)gmyth_livetv_monitor_signal_handler,
rosfran@220
   303
                  livetv );
rosfran@220
   304
  	}
rosfran@220
   305
  	else
rosfran@220
   306
  	{
rosfran@220
   307
  		gmyth_debug("Problems when trying to start MythTV Monitor event socket!");
rosfran@220
   308
  		goto error;  		
rosfran@220
   309
  	}
rosfran@220
   310
  }
rosfran@220
   311
  
rosfran@220
   312
error:
rosfran@220
   313
	return res;
rosfran@220
   314
  
rosfran@212
   315
}
rosfran@212
   316
rosfran@428
   317
/**
rosfran@428
   318
 * Stops the Monitor Handler to this GMythLiveTV session, in order
rosfran@428
   319
 * to stop receiving the status messages from the MythTV's backend server 
rosfran@428
   320
 * 
rosfran@428
   321
 * @param live_tv the GMythLiveTV instance
rosfran@428
   322
 * 
rosfran@428
   323
 * @return <code>true</code> if the Monitor Handler shutdown process
rosfran@428
   324
 * 	   had been concluded succcesfully 
rosfran@428
   325
 */
rosfran@220
   326
void
rosfran@220
   327
gmyth_livetv_monitor_handler_stop( GMythLiveTV *livetv )
rosfran@220
   328
{
rosfran@220
   329
	
rosfran@220
   330
  if ( livetv->monitor != NULL )
rosfran@220
   331
  {
rosfran@220
   332
  	g_object_unref( livetv->monitor );
rosfran@220
   333
  	livetv->monitor = NULL;
rosfran@220
   334
  } 
rosfran@220
   335
  
rosfran@326
   336
}
rosfran@307
   337
rosfran@428
   338
#if 0
rosfran@307
   339
static gchar*
rosfran@307
   340
gmyth_livetv_create_remote_url( GMythLiveTV *livetv )
rosfran@307
   341
{
rosfran@307
   342
	gchar *uri = g_strdup("");
rosfran@307
   343
	gmyth_backend_info_get_remote_h
rosfran@307
   344
	
rosfran@307
   345
	//gmyth_backend(livetv->backend_info)
rosfran@307
   346
	
rosfran@307
   347
	return uri;
rosfran@307
   348
}
rosfran@428
   349
#endif
rosfran@307
   350
rosfran@428
   351
/**
rosfran@428
   352
 * Configures the GMythLiveTV session, sends SPAWN_LIVETV message, 
rosfran@428
   353
 * sets the channel name, and gets the first program info about the
rosfran@428
   354
 * actual recording 
rosfran@428
   355
 * 
rosfran@428
   356
 * @param live_tv the GMythLiveTV instance
rosfran@428
   357
 * @param channel the channel name (the chan_name field, from the tvchain table)
rosfran@428
   358
 * @param backend_info the GMythBackendInfo describing the remote server
rosfran@428
   359
 * 
rosfran@428
   360
 * @return <code>true</code> if the LiveTV's recorder instance configuration 
rosfran@428
   361
 * 				had been concluded succcesfully 
rosfran@428
   362
 */
rosfran@237
   363
static gboolean
leo_sobral@437
   364
gmyth_livetv_setup_recorder_channel_name (GMythLiveTV *livetv, gchar* channel)
rosfran@41
   365
{
rosfran@41
   366
	gboolean res = TRUE;
leo_sobral@437
   367
    
leo_sobral@437
   368
    g_return_val_if_fail (livetv != NULL, FALSE);
leo_sobral@437
   369
    
rosfran@356
   370
	if ( NULL == livetv->socket ) {
rosfran@337
   371
		livetv->socket = gmyth_socket_new ();
rosfran@343
   372
		
rosfran@343
   373
		/* FIME: Implement this at gmyth_socket */
rosfran@343
   374
		res = gmyth_socket_connect_to_backend (livetv->socket, livetv->backend_info->hostname,
rosfran@343
   375
				livetv->backend_info->port, TRUE);
rosfran@343
   376
		if (!res) {
rosfran@467
   377
			gmyth_debug ("[%s] LiveTV can not connect to backend", __FUNCTION__);	
rosfran@343
   378
			res = FALSE;
rosfran@343
   379
			goto error;
rosfran@343
   380
		}
rosfran@356
   381
	}
rosfran@216
   382
	
rosfran@358
   383
	g_mutex_lock( livetv->mutex );
rosfran@287
   384
	
melunko@117
   385
	livetv->is_livetv = TRUE;
rosfran@203
   386
	
rosfran@229
   387
	livetv->local_hostname  = gmyth_socket_get_local_hostname ();
rosfran@41
   388
rosfran@41
   389
	if ( livetv->local_hostname == NULL ) {
rosfran@41
   390
		res = FALSE;
rosfran@41
   391
		goto error;
rosfran@41
   392
	}
rosfran@322
   393
	
rosfran@356
   394
	if  ( livetv->recorder != NULL )
rosfran@356
   395
	{
rosfran@356
   396
		g_object_unref( livetv->recorder );
rosfran@356
   397
		livetv->recorder= NULL;
rosfran@356
   398
	} 
rosfran@356
   399
	
rosfran@337
   400
	if ( gmyth_remote_util_get_free_recorder_count (livetv->socket) <= 0 ) {
rosfran@428
   401
		
rosfran@428
   402
#ifdef GMYTH_USE_DEBUG
rosfran@358
   403
		gmyth_debug ("No free remote encoder available.");
rosfran@428
   404
#endif
rosfran@358
   405
		res = FALSE;
rosfran@358
   406
		goto error;
rosfran@322
   407
	}
rosfran@428
   408
rosfran@322
   409
	/* Gets the recorder num */
rosfran@337
   410
	livetv->recorder = remote_request_next_free_recorder (livetv->socket, -1);
rosfran@343
   411
	gmyth_socket_close_connection (livetv->socket);
rosfran@41
   412
rosfran@337
   413
	if ( NULL == livetv->recorder ) {
rosfran@467
   414
		gmyth_debug ("[%s] None remote encoder available", __FUNCTION__);
rosfran@41
   415
		res = FALSE;
rosfran@41
   416
		goto error;
rosfran@41
   417
	}
rosfran@279
   418
	
rosfran@326
   419
	/* Init remote encoder. Opens its control socket. */
rosfran@287
   420
	res = gmyth_recorder_setup(livetv->recorder);
rosfran@287
   421
	if ( !res ) {
rosfran@467
   422
		gmyth_debug ("[%s] Fail while setting remote encoder\n", __FUNCTION__);
rosfran@287
   423
		res = FALSE;
rosfran@287
   424
		goto error;
rosfran@287
   425
	}
rosfran@287
   426
	
rosfran@326
   427
	/* Creates livetv chain handler */
rosfran@334
   428
	livetv->tvchain = gmyth_tvchain_new();
rosfran@282
   429
	gmyth_tvchain_initialize ( livetv->tvchain, livetv->backend_info );
rosfran@282
   430
rosfran@282
   431
	if ( livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL ) {
rosfran@282
   432
		res = FALSE;
rosfran@282
   433
		goto error;
rosfran@282
   434
	}
rosfran@282
   435
	
rosfran@282
   436
	// Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly)
rosfran@282
   437
	res = gmyth_recorder_spawntv ( livetv->recorder,
rosfran@282
   438
			gmyth_tvchain_get_id(livetv->tvchain) );
rosfran@282
   439
	if (!res) {
rosfran@467
   440
		gmyth_debug ("[%s] Fail while spawn tv\n", __FUNCTION__);
rosfran@41
   441
		res = FALSE;
rosfran@41
   442
		goto error;
rosfran@41
   443
	}
rosfran@288
   444
	
rosfran@288
   445
  if ( res == TRUE ) {
rosfran@288
   446
    /* loop finished, set the max tries variable to zero again... */
rosfran@288
   447
    gint wait_to_transfer = 0;
rosfran@288
   448
rosfran@288
   449
    while (wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS &&
rosfran@292
   450
        (gmyth_recorder_is_recording (livetv->recorder) == FALSE))
rosfran@399
   451
      g_usleep (300);
rosfran@288
   452
rosfran@307
   453
		if ( channel != NULL ) 
rosfran@288
   454
		{
rosfran@288
   455
			/* Pauses remote encoder. */
rosfran@288
   456
			res = gmyth_recorder_pause_recording(livetv->recorder);
rosfran@288
   457
			if ( !res ) {
rosfran@467
   458
				gmyth_debug ("[%s] Fail while pausing remote encoder\n", __FUNCTION__);
rosfran@288
   459
				res = FALSE;
rosfran@288
   460
				goto error;
rosfran@288
   461
			}
rosfran@288
   462
	
rosfran@307
   463
	  	if ( gmyth_recorder_check_channel_name( livetv->recorder, channel ) )
rosfran@288
   464
	  	{
rosfran@307
   465
		  	if ( gmyth_recorder_set_channel_name( livetv->recorder, channel ) )
rosfran@288
   466
		  	{
rosfran@326
   467
		  		gmyth_debug( "Channel changed!!! [%s].\n", channel );
rosfran@288
   468
		  	}
rosfran@288
   469
	  	}
rosfran@288
   470
	
rosfran@326
   471
		} /* if - changes the channel number */
rosfran@288
   472
		
renatofilho@468
   473
    sleep (5);                  /* FIXME: this is evil (tpm) */
rosfran@288
   474
  }
rosfran@302
   475
  
rosfran@302
   476
  /* DEBUG message */  
rosfran@302
   477
	GMythProgramInfo* prog_info = gmyth_recorder_get_current_program_info( livetv->recorder );
rosfran@302
   478
	
rosfran@302
   479
	if ( NULL == prog_info )
rosfran@302
   480
	{
rosfran@302
   481
		gmyth_debug( "ProgramInfo is equals to NULL!!!" );
rosfran@302
   482
		
rosfran@321
   483
    gint i;
rosfran@321
   484
    gchar *channame = NULL;
rosfran@321
   485
rosfran@326
   486
    gmyth_debug( "Problem getting current proginfo!\n" );
rosfran@321
   487
rosfran@321
   488
    /*
rosfran@321
   489
     * mythbackend must not be tuned in to a channel, so keep
rosfran@321
   490
     * changing channels until we find a valid one, or until
rosfran@321
   491
     * we decide to give up.
rosfran@321
   492
     */
rosfran@321
   493
    for (i=1; i<1000; i++) {
rosfran@321
   494
			if ( channame != NULL )
rosfran@321
   495
				g_free(channame);
rosfran@321
   496
      channame = g_strdup_printf( "%d", i );
rosfran@321
   497
      if (gmyth_recorder_set_channel_name(livetv->recorder, channame) < 0) {
rosfran@321
   498
      	continue;
rosfran@321
   499
      }
rosfran@321
   500
      prog_info = gmyth_recorder_get_next_program_info(livetv->recorder, BROWSE_DIRECTION_UP);
rosfran@321
   501
      if (prog_info != NULL)
rosfran@321
   502
      	break;
rosfran@321
   503
    }
rosfran@326
   504
rosfran@326
   505
	} /* if - Program Info */
rosfran@326
   506
	
rosfran@302
   507
	/* prints program info data text */ 
melunko@412
   508
#ifdef GMYTH_USE_DEBUG	
rosfran@307
   509
	gmyth_debug( "New ProgramInfo...\n" );
rosfran@302
   510
	gmyth_program_info_print( prog_info );
melunko@412
   511
#endif	
melunko@412
   512
rosfran@307
   513
	/* check if the program chain could be obtained from the MythTV protocol message */
rosfran@307
   514
	if ( prog_info != NULL )
rosfran@307
   515
	{
rosfran@428
   516
#ifdef GMYTH_USE_DEBUG
melunko@412
   517
		gmyth_debug( "Program Info: %s\n", gmyth_program_info_to_string( prog_info ) );
rosfran@428
   518
#endif
rosfran@310
   519
		livetv->proginfo = prog_info;
rosfran@310
   520
		/* testing change channel */
rosfran@310
   521
		//gmyth_recorder_spawntv_no_tvchain( livetv->recorder );
rosfran@307
   522
	} else {
rosfran@307
   523
		
rosfran@307
   524
		/* check for the program info in the TV program chain could be obtained 
rosfran@307
   525
		   from the MythTV MySQL database */
rosfran@288
   526
rosfran@307
   527
		/* Reload all TV chain from Mysql database. */
rosfran@307
   528
		gmyth_tvchain_reload_all (livetv->tvchain);
rosfran@307
   529
	
rosfran@307
   530
		if ( livetv->tvchain == NULL ) {
rosfran@307
   531
			res = FALSE;
rosfran@307
   532
			goto error;
rosfran@307
   533
		}
rosfran@307
   534
		
rosfran@307
   535
		/* Get program info from database using chanid and starttime */
rosfran@307
   536
		livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, tvchain_curr_index++ );
rosfran@307
   537
		if ( livetv->proginfo == NULL ) {
rosfran@467
   538
			gmyth_debug ("[%s] LiveTV not successfully started.\n", __FUNCTION__ );
rosfran@307
   539
			res = FALSE;
rosfran@307
   540
			goto error;
rosfran@307
   541
		} else {
rosfran@307
   542
			res = TRUE;
rosfran@307
   543
			gmyth_debug ("GMythLiveTV: All requests to backend to start TV were OK. [%s]\n", livetv->proginfo->pathname->str );
rosfran@307
   544
		}
rosfran@307
   545
		
rosfran@41
   546
	}
rosfran@288
   547
	
leo_sobral@437
   548
	livetv->uri = (GMythURI*)gmyth_backend_info_get_uri( livetv->backend_info );
rosfran@296
   549
	
rosfran@358
   550
	g_mutex_unlock( livetv->mutex );
rosfran@282
   551
renatofilho@468
   552
/*
rosfran@225
   553
	if ( !gmyth_livetv_monitor_handler_start( livetv ) )
rosfran@225
   554
	{
rosfran@225
   555
		res = FALSE;
rosfran@237
   556
		gmyth_debug( "LiveTV MONITOR handler error on setup!" );
rosfran@225
   557
		goto error;		
rosfran@225
   558
	}
renatofilho@468
   559
*/
rosfran@225
   560
	
rosfran@216
   561
	livetv->setup_done = TRUE;
rosfran@216
   562
	
rosfran@41
   563
	return res;
rosfran@41
   564
rosfran@41
   565
error:
rosfran@467
   566
	gmyth_debug( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
rosfran@54
   567
leo_sobral@437
   568
    res = FALSE;
leo_sobral@437
   569
leo_sobral@437
   570
    g_string_free( livetv->local_hostname, TRUE );
rosfran@54
   571
rosfran@65
   572
	if ( livetv->recorder != NULL ) {
rosfran@65
   573
		g_object_unref (livetv->recorder);
rosfran@65
   574
		livetv->recorder = NULL;
rosfran@54
   575
	}
rosfran@54
   576
rosfran@54
   577
	if ( livetv->tvchain != NULL ) {
rosfran@54
   578
		g_object_unref (livetv->tvchain);
rosfran@54
   579
		livetv->tvchain = NULL;
rosfran@54
   580
	}
rosfran@54
   581
rosfran@54
   582
	if ( livetv->proginfo != NULL ) {
rosfran@54
   583
		g_object_unref (livetv->proginfo);
rosfran@54
   584
		livetv->proginfo = NULL;
rosfran@54
   585
	}
rosfran@54
   586
rosfran@220
   587
	if ( livetv->monitor != NULL ) {
rosfran@220
   588
		g_object_unref (livetv->monitor);
rosfran@220
   589
		livetv->monitor = NULL;
rosfran@220
   590
	}
rosfran@220
   591
rosfran@54
   592
	return res;
rosfran@54
   593
rosfran@54
   594
}
rosfran@54
   595
rosfran@428
   596
/**
rosfran@428
   597
 * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
rosfran@428
   598
 * sets the channel name, and gets the first program info about the
rosfran@428
   599
 * actual recording 
rosfran@428
   600
 * 
rosfran@428
   601
 * @param live_tv the GMythLiveTV instance
rosfran@428
   602
 * @param channel the channel name, in numerical format
rosfran@428
   603
 * @param backend_info the GMythBackendInfo describing the remote server
rosfran@428
   604
 * 
rosfran@428
   605
 * @return <code>true</code> if the LiveTV's recorder instance configuration 
rosfran@428
   606
 * 				had been concluded succcesfully 
rosfran@428
   607
 */
rosfran@307
   608
static gboolean
leo_sobral@437
   609
gmyth_livetv_setup_recorder ( GMythLiveTV *livetv, gint channel)
rosfran@307
   610
{
rosfran@307
   611
	return gmyth_livetv_setup_recorder_channel_name ( livetv, ( channel != -1 ) ? 
leo_sobral@437
   612
				g_strdup_printf( "%d", channel ) : NULL );
rosfran@307
   613
}
rosfran@307
   614
rosfran@428
   615
/**
rosfran@428
   616
 * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
rosfran@428
   617
 * sets the channel name (numerical format), and gets the first program info about the
rosfran@428
   618
 * actual recording 
rosfran@428
   619
 * 
rosfran@428
   620
 * @param live_tv the GMythLiveTV instance
rosfran@428
   621
 * @param channel the channel name, in numerical format
rosfran@428
   622
 * @param backend_info the GMythBackendInfo describing the remote server
rosfran@428
   623
 * 
rosfran@428
   624
 * @return <code>true</code> if the LiveTV's recorder instance configuration 
rosfran@428
   625
 * 				had been concluded succcesfully 
rosfran@428
   626
 */
rosfran@54
   627
gboolean
leo_sobral@437
   628
gmyth_livetv_channel_setup ( GMythLiveTV *livetv, gint channel )
rosfran@237
   629
{
leo_sobral@437
   630
	return gmyth_livetv_setup_recorder ( livetv, channel );
rosfran@237
   631
}
rosfran@237
   632
rosfran@428
   633
/**
rosfran@428
   634
 * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
rosfran@428
   635
 * sets the channel name (string format), and gets the first program info about the
rosfran@428
   636
 * actual recording 
rosfran@428
   637
 * 
rosfran@428
   638
 * @param live_tv the GMythLiveTV instance
rosfran@428
   639
 * @param channel the channel name, in numerical format
rosfran@428
   640
 * @param backend_info the GMythBackendInfo describing the remote server
rosfran@428
   641
 * 
rosfran@428
   642
 * @return <code>true</code> if the LiveTV's recorder instance configuration 
rosfran@428
   643
 * 				had been concluded succcesfully 
rosfran@428
   644
 */
rosfran@237
   645
gboolean
leo_sobral@437
   646
gmyth_livetv_channel_name_setup ( GMythLiveTV *livetv, gchar* channel )
rosfran@307
   647
{
leo_sobral@437
   648
	return gmyth_livetv_setup_recorder_channel_name ( livetv, channel );
rosfran@307
   649
}
rosfran@307
   650
rosfran@428
   651
/**
rosfran@428
   652
 * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
rosfran@428
   653
 * and gets the first program info about the actual recording
rosfran@428
   654
 * (doesn't changes the channel). 
rosfran@428
   655
 * 
rosfran@428
   656
 * @param live_tv the GMythLiveTV instance
rosfran@428
   657
 * @param backend_info the GMythBackendInfo describing the remote server
rosfran@428
   658
 * 
rosfran@428
   659
 * @return <code>true</code> if the LiveTV's recorder instance configuration 
rosfran@428
   660
 * 				had been concluded succcesfully 
rosfran@428
   661
 */
rosfran@307
   662
gboolean
leo_sobral@437
   663
gmyth_livetv_setup ( GMythLiveTV *livetv )
rosfran@237
   664
{
leo_sobral@437
   665
	return gmyth_livetv_setup_recorder ( livetv, -1 );
rosfran@237
   666
}
rosfran@237
   667
rosfran@428
   668
/**
rosfran@428
   669
 * Gets the next program info from this GMythLiveTV session.
rosfran@428
   670
 * 
rosfran@428
   671
 * @param live_tv the GMythLiveTV instance
rosfran@428
   672
 * 
rosfran@428
   673
 * @return <code>true</code> if the next program info could be got 
rosfran@428
   674
 */
rosfran@237
   675
gboolean
rosfran@54
   676
gmyth_livetv_next_program_chain ( GMythLiveTV *livetv )
rosfran@54
   677
{
rosfran@54
   678
	gboolean res = TRUE;
rosfran@302
   679
	GMythProgramInfo *prog_info = NULL;
rosfran@54
   680
	
rosfran@216
   681
	if ( !livetv->setup_done )
rosfran@216
   682
	{
rosfran@216
   683
		gmyth_debug ( "Call the setup function first!" );
rosfran@216
   684
		goto error;		
rosfran@216
   685
	}
rosfran@216
   686
	
rosfran@342
   687
	gmyth_debug( "Current ProgramInfo...\n" );
rosfran@342
   688
	prog_info = gmyth_recorder_get_current_program_info( livetv->recorder );
rosfran@321
   689
	
rosfran@342
   690
	if ( prog_info != NULL )
rosfran@302
   691
	{
rosfran@342
   692
		livetv->proginfo = prog_info;
rosfran@342
   693
	} else {
leo_sobral@437
   694
		gmyth_debug( "ProgramInfo equals to NULL!!! Getting the next program info..." );
rosfran@342
   695
		prog_info = gmyth_recorder_get_next_program_info( livetv->recorder, BROWSE_DIRECTION_RIGHT );
rosfran@342
   696
		livetv->proginfo = prog_info;		
rosfran@302
   697
	}
rosfran@302
   698
	/* prints program info data text */ 
melunko@424
   699
#ifdef GMYTH_USE_DEBUG
rosfran@302
   700
	gmyth_program_info_print( prog_info );
melunko@424
   701
#endif
rosfran@54
   702
rosfran@302
   703
	if ( prog_info != NULL ) {		
rosfran@302
   704
		res = TRUE;
rosfran@307
   705
		livetv->proginfo = prog_info;
rosfran@302
   706
		gmyth_debug ("GMythLiveTV: All requests to backend to start TV were OK, program info changed.");
rosfran@302
   707
	} else {
rosfran@467
   708
		gmyth_debug ("[%s] LiveTV not successfully started on the next program chain.\n", __FUNCTION__ );
rosfran@54
   709
		goto error;
rosfran@54
   710
	}
rosfran@220
   711
	
rosfran@220
   712
	livetv->setup_done = TRUE;
rosfran@54
   713
rosfran@54
   714
	return res;
rosfran@54
   715
rosfran@54
   716
error:
rosfran@467
   717
	gmyth_debug( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
rosfran@41
   718
leo_sobral@437
   719
    res = FALSE;
leo_sobral@437
   720
    
leo_sobral@437
   721
    g_string_free( livetv->local_hostname, TRUE );
rosfran@41
   722
rosfran@65
   723
	if ( livetv->recorder != NULL ) {
rosfran@65
   724
		g_object_unref (livetv->recorder);
rosfran@65
   725
		livetv->recorder = NULL;
rosfran@41
   726
	}
rosfran@41
   727
rosfran@41
   728
	if ( livetv->tvchain != NULL ) {
rosfran@41
   729
		g_object_unref (livetv->tvchain);
rosfran@41
   730
		livetv->tvchain = NULL;
rosfran@41
   731
	}
rosfran@41
   732
rosfran@41
   733
	if ( livetv->proginfo != NULL ) {
rosfran@41
   734
		g_object_unref (livetv->proginfo);
rosfran@41
   735
		livetv->proginfo = NULL;
rosfran@41
   736
	}
rosfran@41
   737
rosfran@41
   738
	return res;
rosfran@41
   739
}
rosfran@41
   740
rosfran@428
   741
/**
rosfran@428
   742
 * Creates a File Transfer session, using all configuration information
rosfran@428
   743
 * got from the actual program info.
rosfran@428
   744
 * 
rosfran@428
   745
 * @param live_tv the GMythLiveTV instance
rosfran@428
   746
 * 
rosfran@428
   747
 * @return the actual GMythFileTransfer instance, generated using the
rosfran@428
   748
 * 		data got from the actual program info.
rosfran@428
   749
 */
rosfran@216
   750
GMythFileTransfer *
rosfran@216
   751
gmyth_livetv_create_file_transfer( GMythLiveTV *livetv )
rosfran@216
   752
{
rosfran@307
   753
	//GMythURI* uri = NULL;
rosfran@216
   754
	
rosfran@307
   755
	if ( NULL == livetv )
rosfran@216
   756
		goto done;
rosfran@216
   757
	
rosfran@216
   758
	if ( !livetv->setup_done )
rosfran@216
   759
	{
rosfran@216
   760
		gmyth_debug( "Error: You must do the LiveTV setup, just before generating the FileTransfer from LiveTV source!" );
rosfran@216
   761
		goto done;
rosfran@307
   762
	}
rosfran@307
   763
	
rosfran@428
   764
#ifdef GMYTH_USE_DEBUG
rosfran@307
   765
	if ( livetv->proginfo != NULL )
rosfran@321
   766
  	gmyth_debug( "URI path (from program info) = %s.\n", livetv->proginfo->pathname->str );
rosfran@307
   767
  else
rosfran@428
   768
  	gmyth_debug( "URI path (from URI) = %s.\n", livetv->uri->uri->str );
rosfran@428
   769
#endif
rosfran@292
   770
  
rosfran@358
   771
  g_mutex_lock( livetv->mutex );
rosfran@302
   772
  
rosfran@302
   773
  if ( livetv->file_transfer != NULL )
rosfran@302
   774
  {
rosfran@307
   775
  	/*gmyth_file_transfer_close( livetv->file_transfer );*/
rosfran@302
   776
  	g_object_unref( livetv->file_transfer );
rosfran@302
   777
  	livetv->file_transfer = NULL;
rosfran@302
   778
  }  	
rosfran@216
   779
rosfran@321
   780
  if ( livetv->uri != NULL )  
rosfran@216
   781
  {
rosfran@321
   782
  	/* 
rosfran@307
   783
  	if ( livetv->uri->path != NULL )
rosfran@307
   784
  	{
rosfran@307
   785
  		g_string_free( livetv->uri->path, FALSE );
rosfran@307
   786
  		livetv->uri->path = NULL;
rosfran@307
   787
  	}
rosfran@321
   788
  	*/
rosfran@428
   789
#ifdef GMYTH_USE_DEBUG
rosfran@428
   790
  	gmyth_debug( "URI is not NULL, creating from the ProgramInfo pathname... (%s)", livetv->proginfo->pathname->str );
rosfran@428
   791
#endif
rosfran@321
   792
  	livetv->uri->path = g_string_erase(livetv->uri->path, 0, -1);
rosfran@307
   793
  	livetv->uri->path = g_string_new( g_strrstr( livetv->proginfo->pathname->str, "/" ) );
rosfran@307
   794
  } else {
rosfran@428
   795
#ifdef GMYTH_USE_DEBUG
rosfran@321
   796
  	gmyth_debug( "URI is NULL, creating from the ProgramInfo pathname... (%s)", livetv->proginfo->pathname->str );
rosfran@428
   797
#endif
rosfran@307
   798
  	livetv->uri = gmyth_uri_new_with_value( livetv->proginfo->pathname->str );
rosfran@307
   799
  }
rosfran@307
   800
  	
rosfran@307
   801
  if ( NULL == livetv->uri )
rosfran@229
   802
  {  	
rosfran@229
   803
  	gmyth_debug( "Couldn't parse the URI to start LiveTV! [ uri = %s ]", livetv->proginfo->pathname->str );
rosfran@229
   804
  	goto done;  	
rosfran@216
   805
  }
leo_sobral@437
   806
 
rosfran@321
   807
	livetv->file_transfer = gmyth_file_transfer_new( livetv->backend_info );
rosfran@321
   808
rosfran@321
   809
  if ( NULL == livetv->file_transfer ) 
rosfran@321
   810
  {
rosfran@321
   811
  	gmyth_debug( "Error: couldn't create the FileTransfer from LiveTV source!" );
rosfran@321
   812
    goto done;
rosfran@321
   813
  }
rosfran@378
   814
  
leo_sobral@437
   815
    g_object_ref( livetv->file_transfer );
leo_sobral@437
   816
rosfran@428
   817
  /* gmyth_file_transfer_settimeout( livetv->file_transfer, TRUE ); */
rosfran@292
   818
	
rosfran@428
   819
  g_mutex_unlock( livetv->mutex );
rosfran@216
   820
rosfran@216
   821
done:
rosfran@307
   822
	/*
rosfran@216
   823
	if ( uri != NULL )
rosfran@216
   824
	{
rosfran@216
   825
		g_object_unref( uri );
rosfran@216
   826
		uri = NULL;
rosfran@307
   827
	}
rosfran@307
   828
	*/	
rosfran@216
   829
	
rosfran@216
   830
	return livetv->file_transfer;
rosfran@216
   831
	
rosfran@216
   832
}
rosfran@216
   833
rosfran@428
   834
/**
rosfran@428
   835
 * Stops this LiveTV session.
rosfran@428
   836
 * 
rosfran@428
   837
 * @param live_tv the GMythLiveTV instance
rosfran@428
   838
 */
rosfran@41
   839
void
rosfran@41
   840
gmyth_livetv_stop_playing (GMythLiveTV *livetv) 
rosfran@41
   841
{
melunko@278
   842
	gmyth_debug ("Stopping the LiveTV...\n");
rosfran@41
   843
rosfran@41
   844
	if (livetv->is_livetv) {
rosfran@220
   845
		if ( !gmyth_recorder_stop_livetv (livetv->recorder) ) {
rosfran@428
   846
			gmyth_debug ("[%s] Error while stoping remote encoder", __FUNCTION__);	
rosfran@41
   847
		}
rosfran@356
   848
		
rosfran@356
   849
		if ( !gmyth_recorder_finish_recording(livetv->recorder) ) {
rosfran@428
   850
			gmyth_debug ("[%s] Error while finishing recording on remote encoder", __FUNCTION__);	
rosfran@356
   851
		}
rosfran@41
   852
	}
rosfran@41
   853
}
rosfran@41
   854
melunko@107
   855
gboolean
rosfran@41
   856
gmyth_livetv_is_playing (GMythLiveTV *livetv)
rosfran@41
   857
{
rosfran@41
   858
	return TRUE;
rosfran@41
   859
}
rosfran@41
   860
rosfran@41
   861
void
rosfran@41
   862
gmyth_livetv_start_playing (GMythLiveTV *livetv)
rosfran@41
   863
{
rosfran@41
   864
rosfran@41
   865
	// TODO
rosfran@41
   866
rosfran@41
   867
}
rosfran@41
   868