gmyth/src/gmyth_tvchain.c
author rosfran
Thu Apr 19 23:03:58 2007 +0100 (2007-04-19)
branchtrunk
changeset 578 9e589622f097
parent 467 bc13aaf7561d
child 580 7efc73147f5e
permissions -rw-r--r--
[svn r583] New functions to get the channel list, fixes on the gmyth/gmyth.h references.
leo_sobral@1
     1
/**
leo_sobral@1
     2
 * GMyth Library
leo_sobral@1
     3
 *
leo_sobral@1
     4
 * @file gmyth/gmyth_tvchain.c
leo_sobral@1
     5
 * 
leo_sobral@1
     6
 * @brief <p> This component contains functions for creating and accessing
leo_sobral@1
     7
 * the tvchain functions for live tv playback.
leo_sobral@1
     8
 * 
leo_sobral@1
     9
 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
leo_sobral@1
    10
 * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
leo_sobral@1
    11
 *
leo_sobral@1
    12
 *//*
leo_sobral@1
    13
 * 
leo_sobral@1
    14
 * This program is free software; you can redistribute it and/or modify
leo_sobral@1
    15
 * it under the terms of the GNU Lesser General Public License as published by
leo_sobral@1
    16
 * the Free Software Foundation; either version 2 of the License, or
leo_sobral@1
    17
 * (at your option) any later version.
leo_sobral@1
    18
 *
leo_sobral@1
    19
 * This program is distributed in the hope that it will be useful,
leo_sobral@1
    20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
leo_sobral@1
    21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
leo_sobral@1
    22
 * GNU General Public License for more details.
leo_sobral@1
    23
 *
leo_sobral@1
    24
 * You should have received a copy of the GNU Lesser General Public License
leo_sobral@1
    25
 * along with this program; if not, write to the Free Software
leo_sobral@1
    26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
leo_sobral@1
    27
 */
leo_sobral@213
    28
 
leo_sobral@213
    29
#ifdef HAVE_CONFIG_H
leo_sobral@213
    30
#include "config.h"
leo_sobral@213
    31
#endif
leo_sobral@213
    32
leo_sobral@213
    33
#include "gmyth_tvchain.h"
leo_sobral@1
    34
leo_sobral@1
    35
#include <glib.h>
leo_sobral@1
    36
#include <time.h>
leo_sobral@1
    37
#include <stdio.h>
leo_sobral@1
    38
#include <stdlib.h>
melunko@117
    39
#include <assert.h>
leo_sobral@1
    40
leo_sobral@1
    41
#include "gmyth_epg.h"
leo_sobral@1
    42
#include "gmyth_util.h"
leo_sobral@1
    43
#include "gmyth_query.h"
leo_sobral@1
    44
#include "gmyth_scheduler.h"
renatofilho@131
    45
#include "gmyth_debug.h"
leo_sobral@1
    46
leo_sobral@1
    47
static void gmyth_tvchain_class_init          (GMythTVChainClass *klass);
leo_sobral@1
    48
static void gmyth_tvchain_init                (GMythTVChain *object);
leo_sobral@1
    49
leo_sobral@1
    50
static void gmyth_tvchain_dispose  (GObject *object);
leo_sobral@1
    51
static void gmyth_tvchain_finalize (GObject *object);
leo_sobral@1
    52
leo_sobral@446
    53
static void free_tvchain_entry(gpointer data, gpointer user_data);
leo_sobral@446
    54
leo_sobral@1
    55
G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT)
leo_sobral@1
    56
leo_sobral@1
    57
static void
leo_sobral@1
    58
gmyth_tvchain_class_init (GMythTVChainClass *klass)
leo_sobral@1
    59
{
leo_sobral@1
    60
	GObjectClass *gobject_class;
leo_sobral@1
    61
leo_sobral@1
    62
	gobject_class = (GObjectClass *) klass;
leo_sobral@1
    63
leo_sobral@1
    64
	gobject_class->dispose  = gmyth_tvchain_dispose;
leo_sobral@1
    65
	gobject_class->finalize = gmyth_tvchain_finalize;	
leo_sobral@1
    66
}
leo_sobral@1
    67
leo_sobral@1
    68
static void
leo_sobral@1
    69
gmyth_tvchain_init (GMythTVChain *tvchain)
rosfran@428
    70
{	
leo_sobral@1
    71
	tvchain->tvchain_id = NULL;
leo_sobral@1
    72
leo_sobral@1
    73
	tvchain->cur_chanid = g_string_new ("");
rosfran@214
    74
	tvchain->cur_startts = NULL;
rosfran@428
    75
	
rosfran@428
    76
	tvchain->mutex = g_mutex_new();
leo_sobral@1
    77
}
leo_sobral@1
    78
rosfran@334
    79
GMythTVChain*
rosfran@334
    80
gmyth_tvchain_new ()
rosfran@334
    81
{
rosfran@334
    82
	GMythTVChain *tvchain = GMYTH_TVCHAIN ( g_object_new( GMYTH_TVCHAIN_TYPE, NULL ) );
rosfran@334
    83
rosfran@334
    84
	return tvchain;
rosfran@334
    85
}
rosfran@334
    86
leo_sobral@1
    87
static void
leo_sobral@1
    88
gmyth_tvchain_dispose  (GObject *object)
leo_sobral@1
    89
{
melunko@117
    90
    GMythTVChain *tvchain = GMYTH_TVCHAIN(object);
rosfran@11
    91
leo_sobral@452
    92
    if (tvchain->tvchain_id != NULL) {
leo_sobral@452
    93
        g_string_free( tvchain->tvchain_id, TRUE );
leo_sobral@452
    94
        tvchain->tvchain_id = NULL;
leo_sobral@452
    95
    }
rosfran@428
    96
    
rosfran@428
    97
    if ( tvchain->mutex != NULL ) {
rosfran@428
    98
    	g_mutex_free( tvchain->mutex );
rosfran@428
    99
    	tvchain->mutex = NULL;
melunko@117
   100
    }
rosfran@11
   101
leo_sobral@446
   102
    if (tvchain->tvchain_list != NULL) {
leo_sobral@446
   103
        g_list_foreach (tvchain->tvchain_list, free_tvchain_entry, NULL);
leo_sobral@446
   104
        g_list_free( tvchain->tvchain_list );
melunko@117
   105
    }
rosfran@11
   106
leo_sobral@452
   107
    if (tvchain->cur_chanid != NULL) {
leo_sobral@452
   108
        g_string_free( tvchain->cur_chanid, TRUE );
leo_sobral@452
   109
        tvchain->cur_chanid = NULL;
leo_sobral@452
   110
    }
rosfran@11
   111
melunko@117
   112
    if ( tvchain->backend_info) {
melunko@117
   113
        g_object_unref (tvchain->backend_info);
melunko@117
   114
        tvchain->backend_info = NULL;
melunko@117
   115
    }
melunko@117
   116
melunko@117
   117
melunko@117
   118
    G_OBJECT_CLASS (gmyth_tvchain_parent_class)->dispose (object);
leo_sobral@1
   119
}
leo_sobral@1
   120
leo_sobral@1
   121
static void
leo_sobral@1
   122
gmyth_tvchain_finalize (GObject *object)
leo_sobral@1
   123
{
melunko@117
   124
    g_signal_handlers_destroy (object);
leo_sobral@1
   125
melunko@117
   126
    G_OBJECT_CLASS (gmyth_tvchain_parent_class)->finalize (object);
leo_sobral@1
   127
}
leo_sobral@1
   128
leo_sobral@1
   129
/** Initializes the tvchain and generates the tvchain id.
leo_sobral@1
   130
 * 
leo_sobral@1
   131
 * @param tvchain The GMythTVChain instance.
leo_sobral@1
   132
 * @param hostname The local hostname used to generate the tvchain id.
leo_sobral@1
   133
 */
melunko@117
   134
gboolean
melunko@117
   135
gmyth_tvchain_initialize (GMythTVChain *tvchain, GMythBackendInfo *backend_info)
leo_sobral@1
   136
{
renatofilho@189
   137
    const char *hostname;
leo_sobral@1
   138
melunko@117
   139
    assert (tvchain);
melunko@117
   140
    g_return_val_if_fail (backend_info != NULL, FALSE);
leo_sobral@1
   141
melunko@117
   142
    g_object_ref (backend_info);
melunko@117
   143
    tvchain->backend_info = backend_info;
leo_sobral@1
   144
melunko@117
   145
    hostname = gmyth_backend_info_get_hostname (backend_info);
melunko@117
   146
    
melunko@117
   147
    if (tvchain->tvchain_id == NULL) {
rosfran@214
   148
	    gchar *isodate = NULL;
rosfran@214
   149
    	GTimeVal *cur_time = g_new0( GTimeVal, 1 );
rosfran@223
   150
    	//struct tm* gmyth_util_time_val_to_date ( const GTimeVal* time )
leo_sobral@1
   151
rosfran@214
   152
	    g_get_current_time(cur_time);
leo_sobral@446
   153
    	isodate = gmyth_util_time_to_isoformat_from_time_val_fmt ( "%Y-%m-%dT%H:%M:%S", 
leo_sobral@446
   154
                                                                   cur_time );
leo_sobral@1
   155
rosfran@214
   156
	    tvchain->tvchain_id = g_string_sized_new (7 + strlen (hostname) + strlen(isodate));
renatofilho@189
   157
    	g_string_printf(tvchain->tvchain_id, 
rosfran@214
   158
	    	"live-%s-%s", hostname, isodate);
melunko@117
   159
renatofilho@189
   160
    	gmyth_debug ("[%s] tv_chain_id: %s", __FUNCTION__, tvchain->tvchain_id->str);
melunko@117
   161
leo_sobral@446
   162
	    g_free(isodate);	    
leo_sobral@446
   163
	    g_free( cur_time );
melunko@117
   164
    } else {
rosfran@467
   165
    	gmyth_debug ("[%s] TVchain already initialized", __FUNCTION__);
melunko@117
   166
    }
melunko@117
   167
melunko@117
   168
    return TRUE;
leo_sobral@1
   169
}
leo_sobral@1
   170
leo_sobral@1
   171
/** Gets the tvchain id.
leo_sobral@1
   172
 * 
leo_sobral@1
   173
 * @param tvchain The GMythTVChain instance.
leo_sobral@1
   174
 * @return The tvchain id.
leo_sobral@1
   175
 */
leo_sobral@1
   176
GString*
leo_sobral@1
   177
gmyth_tvchain_get_id (GMythTVChain *tvchain)
leo_sobral@1
   178
{
rosfran@11
   179
	g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_id != NULL, NULL );
rosfran@11
   180
leo_sobral@446
   181
	return tvchain->tvchain_id;
leo_sobral@1
   182
}
leo_sobral@1
   183
leo_sobral@1
   184
/** Reloads all tvchain entries in the database.
leo_sobral@1
   185
 * 
leo_sobral@1
   186
 * @param tvchain The GMythTVChain instance.
leo_sobral@1
   187
 * @return  TRUE if success, or FALSE if error.
leo_sobral@1
   188
 */
leo_sobral@1
   189
gboolean
leo_sobral@1
   190
gmyth_tvchain_reload_all (GMythTVChain *tvchain)
leo_sobral@1
   191
{
leo_sobral@1
   192
	MYSQL_ROW msql_row;
renatofilho@189
   193
	MYSQL_RES *msql_res = NULL;
renatofilho@189
   194
	GMythQuery *gmyth_query = NULL;
rosfran@11
   195
	gboolean ret = TRUE;
renatofilho@189
   196
	GString *stmt_str = NULL;
leo_sobral@1
   197
rosfran@428
   198
	g_mutex_lock( tvchain->mutex );
rosfran@54
   199
	
rosfran@54
   200
	/* gets the initial size of the TVChain entries list */
leo_sobral@1
   201
	guint prev_size = g_list_length (tvchain->tvchain_list);
leo_sobral@1
   202
renatofilho@131
   203
	gmyth_debug ("[%s] chainid: %s", __FUNCTION__, tvchain->tvchain_id->str);
leo_sobral@1
   204
rosfran@11
   205
	if ( tvchain != NULL && tvchain->tvchain_list != NULL ) {
rosfran@11
   206
		g_list_free (tvchain->tvchain_list);
rosfran@11
   207
		tvchain->tvchain_list = NULL;
rosfran@11
   208
	}
leo_sobral@1
   209
rosfran@326
   210
	/* TODO: Reuse gmyth_query already connected from context */
leo_sobral@1
   211
	gmyth_query = gmyth_query_new ();
melunko@117
   212
	if (!gmyth_query_connect (gmyth_query, tvchain->backend_info)) {
rosfran@467
   213
		gmyth_debug ("[%s] Could not connect to db", __FUNCTION__);
rosfran@428
   214
		g_mutex_unlock( tvchain->mutex );
rosfran@11
   215
		ret = FALSE;
rosfran@11
   216
		goto done;
leo_sobral@1
   217
	}
leo_sobral@1
   218
leo_sobral@1
   219
	stmt_str = g_string_new ("");
leo_sobral@1
   220
	g_string_printf (stmt_str, 
leo_sobral@1
   221
			"SELECT chanid, starttime, endtime, discontinuity, "
leo_sobral@1
   222
			"chainpos, hostprefix, cardtype, channame, input "
leo_sobral@1
   223
			"FROM tvchain "
leo_sobral@1
   224
			"WHERE chainid = \"%s\" ORDER BY chainpos;",
leo_sobral@1
   225
			tvchain->tvchain_id->str);
leo_sobral@1
   226
leo_sobral@1
   227
	msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
leo_sobral@1
   228
	if (msql_res != NULL) {
leo_sobral@1
   229
leo_sobral@1
   230
		while ((msql_row = mysql_fetch_row (msql_res)) != NULL) {
leo_sobral@1
   231
			struct LiveTVChainEntry *entry = g_new0 (struct LiveTVChainEntry, 1);
leo_sobral@1
   232
			entry->chanid = g_string_new (msql_row[0]);
rosfran@225
   233
			entry->starttime = gmyth_util_string_to_time_val ((const gchar*) msql_row[1]);
rosfran@225
   234
			entry->endtime = gmyth_util_string_to_time_val ((const gchar*) msql_row[2]);
rosfran@225
   235
			entry->discontinuity = g_ascii_strtoull (msql_row[3], NULL, 10 ) != 0;
leo_sobral@1
   236
			entry->hostprefix = g_string_new (msql_row[5]);
leo_sobral@1
   237
			entry->cardtype = g_string_new (msql_row[6]);
leo_sobral@1
   238
			entry->channum = g_string_new (msql_row[7]);
leo_sobral@1
   239
			entry->inputname = g_string_new (msql_row[8]);
leo_sobral@1
   240
leo_sobral@1
   241
			//m_maxpos = query.value(4).toInt() + 1;
rosfran@467
   242
			gmyth_debug( "[%s] Reading TV chain entry (channel %s): [%s, %s, %s]\n", __FUNCTION__, entry->channum->str, entry->chanid->str, 
rosfran@54
   243
					(gchar*)msql_row[1], (gchar*)msql_row[2] );
rosfran@54
   244
			
rosfran@54
   245
			/* add this to get the actual start timestamp of the last recording */
rosfran@54
   246
			if ( tvchain->cur_startts < entry->starttime )
rosfran@54
   247
				tvchain->cur_startts = entry->starttime;
leo_sobral@1
   248
leo_sobral@1
   249
			tvchain->tvchain_list = g_list_append (tvchain->tvchain_list, entry);			
leo_sobral@1
   250
		}
leo_sobral@1
   251
	} else {
rosfran@467
   252
		gmyth_debug ("gmyth_tvchain_reload_all query error!\n");
rosfran@428
   253
		g_mutex_unlock( tvchain->mutex );
leo_sobral@1
   254
rosfran@11
   255
		ret = FALSE;
rosfran@11
   256
		goto done;
leo_sobral@1
   257
	}
leo_sobral@1
   258
rosfran@428
   259
	g_mutex_unlock( tvchain->mutex );
leo_sobral@1
   260
	
leo_sobral@1
   261
	tvchain->cur_pos = gmyth_tvchain_program_is_at (tvchain, tvchain->cur_chanid, tvchain->cur_startts);
rosfran@467
   262
	gmyth_debug( "[%s] TVChain current position = %d.\n", __FUNCTION__, tvchain->cur_pos );
leo_sobral@1
   263
leo_sobral@1
   264
	if (tvchain->cur_pos < 0)
leo_sobral@1
   265
		tvchain->cur_pos = 0;
leo_sobral@1
   266
leo_sobral@1
   267
	//    if (m_switchid >= 0)
leo_sobral@1
   268
	//        m_switchid = ProgramIsAt(m_switchentry.chanid,m_switchentry.starttime);
leo_sobral@1
   269
leo_sobral@1
   270
	if (prev_size != g_list_length (tvchain->tvchain_list)) {
renatofilho@131
   271
		gmyth_debug ("[%s] Added new recording", __FUNCTION__);
leo_sobral@1
   272
	}	
leo_sobral@1
   273
rosfran@11
   274
done:
rosfran@11
   275
	if ( stmt_str != NULL )
rosfran@225
   276
		g_string_free (stmt_str, TRUE);
leo_sobral@1
   277
rosfran@11
   278
	if ( msql_res != NULL )
rosfran@11
   279
		mysql_free_result (msql_res);
leo_sobral@1
   280
rosfran@11
   281
	if ( gmyth_query != NULL )
rosfran@11
   282
		g_object_unref (gmyth_query);
leo_sobral@1
   283
rosfran@11
   284
	return ret;
leo_sobral@1
   285
}
leo_sobral@1
   286
rosfran@578
   287
/** 
rosfran@578
   288
 * Get all the program info entries in the database.
rosfran@578
   289
 * 
rosfran@578
   290
 * @param tvchain The GMythTVChain instance.
rosfran@578
   291
 * 
rosfran@578
   292
 * @return  A program info listage.
rosfran@578
   293
 */
rosfran@578
   294
GList *
rosfran@578
   295
gmyth_tvchain_get_program_info_list (GMythTVChain *tvchain)
rosfran@578
   296
{
rosfran@578
   297
    GList *prog_list = NULL;
rosfran@578
   298
    MYSQL_ROW msql_row;
rosfran@578
   299
    MYSQL_RES *msql_res = NULL;
rosfran@578
   300
    GMythQuery *gmyth_query = NULL;
rosfran@578
   301
    GString *stmt_str = NULL;
rosfran@578
   302
rosfran@578
   303
    g_mutex_lock( tvchain->mutex );
rosfran@578
   304
    
rosfran@578
   305
    gmyth_query = gmyth_query_new ();
rosfran@578
   306
    if (!gmyth_query_connect (gmyth_query, tvchain->backend_info)) {
rosfran@578
   307
        gmyth_debug ("Could not connect to db.");
rosfran@578
   308
        goto done;
rosfran@578
   309
    }
rosfran@578
   310
rosfran@578
   311
    stmt_str = g_string_new ("");
rosfran@578
   312
    g_string_printf (stmt_str, 
rosfran@578
   313
            "SELECT channum, icon "
rosfran@578
   314
            "FROM channel "
rosfran@578
   315
            "ORDER BY channum;");
rosfran@578
   316
rosfran@578
   317
    msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
rosfran@578
   318
    if (msql_res != NULL) {
rosfran@578
   319
rosfran@578
   320
        while ((msql_row = mysql_fetch_row (msql_res)) != NULL) {
rosfran@578
   321
            GMythProgramInfo *entry = gmyth_program_info_new();
rosfran@578
   322
            entry->channame = g_string_new (msql_row[0]);
rosfran@578
   323
            entry->chansign = g_string_new (msql_row[1]);
rosfran@578
   324
rosfran@578
   325
            gmyth_debug( "Reading TV program info entry (channel %s): [%s - {%s, %s}]\n", entry->channame->str, 
rosfran@578
   326
                    entry->chansign->str, (gchar*)msql_row[0], (gchar*)msql_row[1] );
rosfran@578
   327
            
rosfran@578
   328
            prog_list = g_list_append (prog_list, entry);           
rosfran@578
   329
        }
rosfran@578
   330
    } else {
rosfran@578
   331
        gmyth_debug ("Query error when trying to get the channel list from database!\n");
rosfran@578
   332
        goto done;
rosfran@578
   333
    }
rosfran@578
   334
rosfran@578
   335
done:
rosfran@578
   336
    g_mutex_unlock( tvchain->mutex );
rosfran@578
   337
rosfran@578
   338
    if ( stmt_str != NULL )
rosfran@578
   339
        g_string_free (stmt_str, TRUE);
rosfran@578
   340
rosfran@578
   341
    if ( msql_res != NULL )
rosfran@578
   342
        mysql_free_result (msql_res);
rosfran@578
   343
rosfran@578
   344
    if ( gmyth_query != NULL )
rosfran@578
   345
        g_object_unref (gmyth_query);
rosfran@578
   346
rosfran@578
   347
    return prog_list;
rosfran@578
   348
}
rosfran@578
   349
rosfran@578
   350
/** 
rosfran@578
   351
 * Get all the program info entries in the database, given a channel name.
rosfran@578
   352
 * 
rosfran@578
   353
 * @param tvchain The GMythTVChain instance.
rosfran@578
   354
 * @param channel The channel name.
rosfran@578
   355
 * 
rosfran@578
   356
 * @return  A program info listage, based on a given channel name.
rosfran@578
   357
 */
rosfran@578
   358
GList *
rosfran@578
   359
gmyth_tvchain_get_program_info_from_channel (GMythTVChain *tvchain, const gchar* channel)
rosfran@578
   360
{
rosfran@578
   361
    GList *prog_list = NULL;
rosfran@578
   362
    MYSQL_ROW msql_row;
rosfran@578
   363
    MYSQL_RES *msql_res = NULL;
rosfran@578
   364
    GMythQuery *gmyth_query = NULL;
rosfran@578
   365
    GString *stmt_str = NULL;
rosfran@578
   366
rosfran@578
   367
    g_mutex_lock( tvchain->mutex );
rosfran@578
   368
    
rosfran@578
   369
    gmyth_query = gmyth_query_new ();
rosfran@578
   370
    if (!gmyth_query_connect (gmyth_query, tvchain->backend_info)) {
rosfran@578
   371
        gmyth_debug ("Could not connect to db.");
rosfran@578
   372
        goto done;
rosfran@578
   373
    }
rosfran@578
   374
rosfran@578
   375
    stmt_str = g_string_new ("");
rosfran@578
   376
    g_string_printf (stmt_str, 
rosfran@578
   377
            "SELECT channum, icon "
rosfran@578
   378
            "FROM channel "
rosfran@578
   379
            "WHERE channum = \"%s\" ORDER BY channum;",
rosfran@578
   380
            channel);
rosfran@578
   381
rosfran@578
   382
    msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
rosfran@578
   383
    if (msql_res != NULL) {
rosfran@578
   384
rosfran@578
   385
        while ((msql_row = mysql_fetch_row (msql_res)) != NULL) {
rosfran@578
   386
            GMythProgramInfo *entry = gmyth_program_info_new();
rosfran@578
   387
            entry->channame = g_string_new (msql_row[0]);
rosfran@578
   388
            entry->chansign = g_string_new (msql_row[1]);
rosfran@578
   389
rosfran@578
   390
            gmyth_debug( "Reading TV program info entry (channel %s): [%s - {%s, %s}]\n", entry->channame->str, 
rosfran@578
   391
                    entry->chansign->str, (gchar*)msql_row[0], (gchar*)msql_row[1] );
rosfran@578
   392
            
rosfran@578
   393
            prog_list = g_list_append (prog_list, entry);           
rosfran@578
   394
        }
rosfran@578
   395
    } else {
rosfran@578
   396
        gmyth_debug ("Query error when trying to get the channel list from database!\n");
rosfran@578
   397
        goto done;
rosfran@578
   398
    }
rosfran@578
   399
rosfran@578
   400
done:
rosfran@578
   401
    g_mutex_unlock( tvchain->mutex );
rosfran@578
   402
rosfran@578
   403
    if ( stmt_str != NULL )
rosfran@578
   404
        g_string_free (stmt_str, TRUE);
rosfran@578
   405
rosfran@578
   406
    if ( msql_res != NULL )
rosfran@578
   407
        mysql_free_result (msql_res);
rosfran@578
   408
rosfran@578
   409
    if ( gmyth_query != NULL )
rosfran@578
   410
        g_object_unref (gmyth_query);
rosfran@578
   411
rosfran@578
   412
    return prog_list;
rosfran@578
   413
}
rosfran@578
   414
leo_sobral@1
   415
/** Returns the internal index for the TV chain related to the given
leo_sobral@1
   416
 * channel and start time.
leo_sobral@1
   417
 * 
leo_sobral@1
   418
 * @param tvchain The GMythTVChain instance.
leo_sobral@1
   419
 * @param chanid The channel id.
leo_sobral@1
   420
 * @param startts The program start time.
leo_sobral@1
   421
 */
rosfran@214
   422
gint
rosfran@214
   423
gmyth_tvchain_program_is_at (GMythTVChain *tvchain, GString *chanid, GTimeVal* startts)
leo_sobral@1
   424
{
rosfran@214
   425
	gint count = 0;
leo_sobral@1
   426
	struct LiveTVChainEntry *entry;
leo_sobral@1
   427
	GList *tmp_list = tvchain->tvchain_list;
rosfran@54
   428
	guint list_size = g_list_length (tvchain->tvchain_list);
leo_sobral@1
   429
rosfran@428
   430
	g_mutex_lock( tvchain->mutex );
leo_sobral@1
   431
	
rosfran@54
   432
	for (; tmp_list && ( count < list_size ); tmp_list = tvchain->tvchain_list->next, count++)
leo_sobral@1
   433
	{
leo_sobral@1
   434
		entry = (struct LiveTVChainEntry*) tmp_list->data;
rosfran@214
   435
		if ( !g_strncasecmp (entry->chanid->str, chanid->str, chanid->len)
rosfran@214
   436
				&& entry->starttime == startts )
leo_sobral@1
   437
		{
rosfran@428
   438
			g_mutex_unlock( tvchain->mutex );
leo_sobral@1
   439
			return count;
leo_sobral@1
   440
		}
leo_sobral@1
   441
	}
rosfran@428
   442
	g_mutex_unlock( tvchain->mutex );
leo_sobral@1
   443
leo_sobral@1
   444
	return -1;	
leo_sobral@1
   445
}
leo_sobral@1
   446
leo_sobral@1
   447
/** Get the program info associated to the tvchain.
leo_sobral@1
   448
 * 
leo_sobral@1
   449
 * @param tvchain The GMythTVChain instance.
leo_sobral@1
   450
 * @param index The tvchain index.
leo_sobral@1
   451
 * @return The program info structure.
leo_sobral@1
   452
 */
leo_sobral@1
   453
GMythProgramInfo*
rosfran@214
   454
gmyth_tvchain_get_program_at (GMythTVChain *tvchain, gint index)
leo_sobral@1
   455
{
leo_sobral@1
   456
	struct LiveTVChainEntry *entry;
leo_sobral@1
   457
leo_sobral@1
   458
	entry = gmyth_tvchain_get_entry_at (tvchain, index);
leo_sobral@1
   459
leo_sobral@1
   460
	if (entry)
leo_sobral@1
   461
		return gmyth_tvchain_entry_to_program (tvchain, entry);	
leo_sobral@1
   462
leo_sobral@1
   463
	return NULL;
leo_sobral@1
   464
}
leo_sobral@1
   465
leo_sobral@1
   466
/** Gets a LiveTVChainEntry associated to the tvchain by its index.
leo_sobral@1
   467
 * 
leo_sobral@1
   468
 * @param tvchain The GMythTVChain instance.
leo_sobral@1
   469
 * @param index The tvchain entry index
leo_sobral@1
   470
 * @return The LiveTVchainEntry structure.
leo_sobral@1
   471
 */
leo_sobral@1
   472
struct LiveTVChainEntry*
rosfran@214
   473
gmyth_tvchain_get_entry_at (GMythTVChain *tvchain, gint index)
leo_sobral@1
   474
{
leo_sobral@1
   475
	struct LiveTVChainEntry* chain_entry = NULL;
rosfran@11
   476
rosfran@11
   477
	g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_list != NULL, NULL );
leo_sobral@1
   478
	
rosfran@428
   479
	g_mutex_lock( tvchain->mutex );
leo_sobral@1
   480
	
rosfran@214
   481
	gint size = g_list_length (tvchain->tvchain_list);
rosfran@214
   482
	gint new_index = (index < 0 || index >= size) ? size - 1 : index;
leo_sobral@1
   483
leo_sobral@1
   484
	if (new_index >= 0) 
leo_sobral@1
   485
		chain_entry = (struct LiveTVChainEntry*) g_list_nth_data (tvchain->tvchain_list, new_index);
leo_sobral@1
   486
rosfran@428
   487
	g_mutex_unlock( tvchain->mutex );
leo_sobral@1
   488
	
leo_sobral@1
   489
	if ( chain_entry != NULL ) {
renatofilho@131
   490
		gmyth_debug ("[%s] Got TV Chain entry at %d.\n", __FUNCTION__, new_index );
leo_sobral@1
   491
leo_sobral@1
   492
	} else {
rosfran@467
   493
		gmyth_debug ("[%s] failed to get entry at index %d", __FUNCTION__, index);
leo_sobral@1
   494
	}
leo_sobral@1
   495
leo_sobral@1
   496
	return chain_entry;
leo_sobral@1
   497
}
leo_sobral@1
   498
leo_sobral@1
   499
/** Gets the program info from backend database associated to the tv chain entry.
leo_sobral@1
   500
 * 
leo_sobral@1
   501
 * @param tvchain The GMythTVChain instance.
leo_sobral@1
   502
 * @param entry the LiveTVChainEntry to be converted.
leo_sobral@1
   503
 * @return The progrma info.
leo_sobral@1
   504
 */
leo_sobral@1
   505
GMythProgramInfo*
leo_sobral@1
   506
gmyth_tvchain_entry_to_program (GMythTVChain *tvchain, struct LiveTVChainEntry *entry)
leo_sobral@1
   507
{
leo_sobral@1
   508
	GMythProgramInfo *proginfo = NULL;
leo_sobral@1
   509
rosfran@11
   510
	g_return_val_if_fail( tvchain != NULL, NULL );
rosfran@11
   511
rosfran@223
   512
	if ( !entry || !tvchain ) {
rosfran@467
   513
		gmyth_debug ("gmyth_tvchain_entry_to_program() received NULL argument");
leo_sobral@1
   514
		return NULL;
leo_sobral@1
   515
	}
leo_sobral@1
   516
leo_sobral@1
   517
	GMythScheduler *scheduler = gmyth_scheduler_new ();
leo_sobral@1
   518
melunko@117
   519
	gmyth_scheduler_connect( scheduler, tvchain->backend_info );
leo_sobral@1
   520
	proginfo = gmyth_scheduler_get_recorded (scheduler, 
leo_sobral@1
   521
			entry->chanid, entry->starttime);
leo_sobral@1
   522
	gmyth_scheduler_disconnect( scheduler );
leo_sobral@1
   523
leo_sobral@1
   524
	if (proginfo) {
leo_sobral@1
   525
		proginfo->pathname = g_string_prepend (proginfo->pathname, entry->hostprefix->str);
leo_sobral@1
   526
	} else {
rosfran@467
   527
		gmyth_debug ("tvchain_entry_to_program( chan id = %s, starttime = %ld) failed!", entry->chanid->str, entry->starttime->tv_sec);
leo_sobral@1
   528
	}
leo_sobral@1
   529
leo_sobral@1
   530
	return proginfo;
leo_sobral@1
   531
}
leo_sobral@446
   532
leo_sobral@446
   533
static void
leo_sobral@446
   534
free_tvchain_entry(gpointer data, gpointer user_data)
leo_sobral@446
   535
{
leo_sobral@446
   536
    struct LiveTVChainEntry *entry;
leo_sobral@446
   537
leo_sobral@446
   538
    g_return_if_fail (data != NULL);
leo_sobral@446
   539
leo_sobral@446
   540
    entry = (struct LiveTVChainEntry *) data;
leo_sobral@446
   541
leo_sobral@452
   542
    if (entry->chanid != NULL) {
leo_sobral@452
   543
        g_string_free (entry->chanid, TRUE);
leo_sobral@452
   544
    }
leo_sobral@452
   545
leo_sobral@452
   546
    if (entry->starttime != NULL) {
leo_sobral@452
   547
        g_free (entry->starttime);
leo_sobral@452
   548
    }
leo_sobral@452
   549
leo_sobral@452
   550
    if (entry->endtime != NULL) {
leo_sobral@452
   551
       g_free (entry->endtime);
leo_sobral@452
   552
    }
leo_sobral@452
   553
leo_sobral@452
   554
    if (entry->hostprefix) {
leo_sobral@452
   555
        g_string_free (entry->hostprefix, TRUE);
leo_sobral@452
   556
    }
leo_sobral@452
   557
leo_sobral@452
   558
    if (entry->cardtype) {
leo_sobral@452
   559
        g_string_free (entry->cardtype, TRUE);
leo_sobral@452
   560
    }
leo_sobral@452
   561
leo_sobral@452
   562
    if (entry->channum) {
leo_sobral@452
   563
        g_string_free (entry->channum, TRUE);
leo_sobral@452
   564
    }
leo_sobral@452
   565
leo_sobral@452
   566
    if (entry->inputname) {
leo_sobral@452
   567
        g_string_free (entry->inputname, TRUE);
leo_sobral@452
   568
    }
leo_sobral@446
   569
leo_sobral@446
   570
    g_free(entry);
leo_sobral@446
   571
}