gmyth/src/libgmyth/gmyth_tvchain.c
author rosfran
Tue Sep 26 15:23:49 2006 +0100 (2006-09-26)
branchtrunk
changeset 11 79e798d40577
parent 1 ffdf467315ec
permissions -rw-r--r--
[svn r12] Do some code cleaning, freeing buffer.
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_tvchain.c
     5  * 
     6  * @brief <p> This component contains functions for creating and accessing
     7  * the tvchain functions for live tv playback.
     8  * 
     9  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
    10  * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
    11  *
    12  *//*
    13  * 
    14  * This program is free software; you can redistribute it and/or modify
    15  * it under the terms of the GNU Lesser General Public License as published by
    16  * the Free Software Foundation; either version 2 of the License, or
    17  * (at your option) any later version.
    18  *
    19  * This program is distributed in the hope that it will be useful,
    20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    22  * GNU General Public License for more details.
    23  *
    24  * You should have received a copy of the GNU Lesser General Public License
    25  * along with this program; if not, write to the Free Software
    26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    27  */
    28 
    29 #include <glib.h>
    30 #include <time.h>
    31 #include <stdio.h>
    32 #include <stdlib.h>
    33 
    34 #include "gmyth_epg.h"
    35 #include "gmyth_tvchain.h"
    36 #include "gmyth_util.h"
    37 #include "gmyth_query.h"
    38 #include "gmyth_scheduler.h"
    39 
    40 static void gmyth_tvchain_class_init          (GMythTVChainClass *klass);
    41 static void gmyth_tvchain_init                (GMythTVChain *object);
    42 
    43 static void gmyth_tvchain_dispose  (GObject *object);
    44 static void gmyth_tvchain_finalize (GObject *object);
    45 
    46 G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT)
    47 
    48 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
    49 
    50 static void
    51 gmyth_tvchain_class_init (GMythTVChainClass *klass)
    52 {
    53 	GObjectClass *gobject_class;
    54 
    55 	gobject_class = (GObjectClass *) klass;
    56 
    57 	gobject_class->dispose  = gmyth_tvchain_dispose;
    58 	gobject_class->finalize = gmyth_tvchain_finalize;	
    59 }
    60 
    61 static void
    62 gmyth_tvchain_init (GMythTVChain *tvchain)
    63 {
    64 	tvchain->tvchain_id = NULL;
    65 
    66 	tvchain->cur_chanid = g_string_new ("");
    67 	tvchain->cur_startts = 0;
    68 }
    69 
    70 static void
    71 gmyth_tvchain_dispose  (GObject *object)
    72 {
    73 	GMythTVChain *tvchain = GMYTH_TVCHAIN(object);
    74 
    75 	if ( tvchain->tvchain_id != NULL ) {
    76 		g_string_free( tvchain->tvchain_id, TRUE );
    77 		tvchain->tvchain_id = NULL;
    78 	}
    79 
    80 	if ( tvchain->tvchain_list != NULL ) {
    81 		g_list_free( tvchain->tvchain_list );
    82 		tvchain->tvchain_list = NULL;
    83 	}
    84 
    85 	if ( tvchain->cur_chanid != NULL ) {
    86 		g_string_free( tvchain->cur_chanid, TRUE );
    87 		tvchain->cur_chanid = NULL;
    88 	}
    89 
    90 	G_OBJECT_CLASS (gmyth_tvchain_parent_class)->dispose (object);
    91 }
    92 
    93 static void
    94 gmyth_tvchain_finalize (GObject *object)
    95 {
    96 	g_signal_handlers_destroy (object);
    97 
    98 	G_OBJECT_CLASS (gmyth_tvchain_parent_class)->finalize (object);
    99 }
   100 
   101 /** Initializes the tvchain and generates the tvchain id.
   102  * 
   103  * @param tvchain The GMythTVChain instance.
   104  * @param hostname The local hostname used to generate the tvchain id.
   105  */
   106 void
   107 gmyth_tvchain_initialize (GMythTVChain *tvchain, GString *hostname)
   108 {
   109 	if (tvchain->tvchain_id == NULL) {
   110 		GString *isodate;
   111 		time_t cur_time;
   112 
   113 		time(&cur_time);
   114 		isodate = gmyth_util_time_to_isoformat (cur_time);
   115 
   116 		tvchain->tvchain_id = g_string_sized_new(7 + hostname->len + isodate->len);
   117 		g_string_printf(tvchain->tvchain_id, 
   118 				"live-%s-%s", hostname->str, isodate->str);
   119 
   120 		g_print("tv_chain_id: %s\n", tvchain->tvchain_id->str);
   121 
   122 		g_string_free(isodate, TRUE);
   123 
   124 	} else {
   125 		g_warning ("[%s] TVchain already initialized", __FUNCTION__);
   126 	}
   127 }
   128 
   129 /** Gets the tvchain id.
   130  * 
   131  * @param tvchain The GMythTVChain instance.
   132  * @return The tvchain id.
   133  */
   134 GString*
   135 gmyth_tvchain_get_id (GMythTVChain *tvchain)
   136 {
   137 	g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_id != NULL, NULL );
   138 
   139 	return g_string_new (tvchain->tvchain_id->str);
   140 }
   141 
   142 /** Reloads all tvchain entries in the database.
   143  * 
   144  * @param tvchain The GMythTVChain instance.
   145  * @return  TRUE if success, or FALSE if error.
   146  */
   147 gboolean
   148 gmyth_tvchain_reload_all (GMythTVChain *tvchain)
   149 {
   150 	MYSQL_ROW msql_row;
   151 	MYSQL_RES *msql_res;
   152 	GMythQuery *gmyth_query;
   153 	gboolean ret = TRUE;
   154 
   155 	GString *stmt_str;
   156 
   157 	g_static_mutex_lock( &mutex );
   158 
   159 	guint prev_size = g_list_length (tvchain->tvchain_list);
   160 
   161 	g_debug ("[%s] chainid: %s", __FUNCTION__, tvchain->tvchain_id->str);
   162 
   163 	if ( tvchain != NULL && tvchain->tvchain_list != NULL ) {
   164 		g_list_free (tvchain->tvchain_list);
   165 		tvchain->tvchain_list = NULL;
   166 	}
   167 
   168 	// TODO: Reuse gmyth_query already connected from context
   169 	gmyth_query = gmyth_query_new ();
   170 	if (!gmyth_query_connect (gmyth_query)) {
   171 		g_warning ("[%s] Could not connect to db", __FUNCTION__);
   172 		g_static_mutex_unlock( &mutex );
   173 
   174 		ret = FALSE;
   175 
   176 		goto done;
   177 	}
   178 
   179 	stmt_str = g_string_new ("");
   180 	g_string_printf (stmt_str, 
   181 			"SELECT chanid, starttime, endtime, discontinuity, "
   182 			"chainpos, hostprefix, cardtype, channame, input "
   183 			"FROM tvchain "
   184 			"WHERE chainid = \"%s\" ORDER BY chainpos;",
   185 			tvchain->tvchain_id->str);
   186 
   187 	msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
   188 	if (msql_res != NULL) {
   189 
   190 		while ((msql_row = mysql_fetch_row (msql_res)) != NULL) {
   191 			struct LiveTVChainEntry *entry = g_new0 (struct LiveTVChainEntry, 1);
   192 			entry->chanid = g_string_new (msql_row[0]);
   193 			entry->starttime = gmyth_util_string_to_time (g_string_new ((gchar*)msql_row[1]));
   194 			entry->endtime = gmyth_util_string_to_time (g_string_new (msql_row[2]));
   195 			entry->discontinuity = atoi (msql_row[3]) != 0;
   196 			entry->hostprefix = g_string_new (msql_row[5]);
   197 			entry->cardtype = g_string_new (msql_row[6]);
   198 			entry->channum = g_string_new (msql_row[7]);
   199 			entry->inputname = g_string_new (msql_row[8]);
   200 
   201 			//m_maxpos = query.value(4).toInt() + 1;
   202 
   203 			tvchain->tvchain_list = g_list_append (tvchain->tvchain_list, entry);			
   204 		}
   205 	} else {
   206 		g_warning ("gmyth_tvchain_reload_all query error!\n");
   207 		g_static_mutex_unlock( &mutex );
   208 
   209 		ret = FALSE;
   210 		goto done;
   211 	}
   212 
   213 	g_static_mutex_unlock( &mutex );
   214 	
   215 	tvchain->cur_pos = gmyth_tvchain_program_is_at (tvchain, tvchain->cur_chanid, tvchain->cur_startts);
   216 
   217 	if (tvchain->cur_pos < 0)
   218 		tvchain->cur_pos = 0;
   219 
   220 	//    if (m_switchid >= 0)
   221 	//        m_switchid = ProgramIsAt(m_switchentry.chanid,m_switchentry.starttime);
   222 
   223 	if (prev_size != g_list_length (tvchain->tvchain_list)) {
   224 		g_debug ("[%s] Added new recording", __FUNCTION__);
   225 	}	
   226 
   227 done:
   228 	if ( stmt_str != NULL )
   229 		g_string_free (stmt_str, TRUE);
   230 
   231 	if ( msql_res != NULL )
   232 		mysql_free_result (msql_res);
   233 
   234 	if ( gmyth_query != NULL )
   235 		g_object_unref (gmyth_query);
   236 
   237 	return ret;
   238 }
   239 
   240 /** Returns the internal index for the TV chain related to the given
   241  * channel and start time.
   242  * 
   243  * @param tvchain The GMythTVChain instance.
   244  * @param chanid The channel id.
   245  * @param startts The program start time.
   246  */
   247 int
   248 gmyth_tvchain_program_is_at (GMythTVChain *tvchain, GString *chanid, time_t startts)
   249 {
   250 	int count = 0;
   251 	struct LiveTVChainEntry *entry;
   252 	GList *tmp_list = tvchain->tvchain_list;
   253 
   254 	g_static_mutex_lock( &mutex );
   255 	
   256 	for (; tmp_list; tmp_list = tvchain->tvchain_list->next, ++count)
   257 	{
   258 		entry = (struct LiveTVChainEntry*) tmp_list->data;
   259 		if (!g_strncasecmp (entry->chanid->str, chanid->str, chanid->len)
   260 				&& entry->starttime == startts)
   261 		{
   262 			g_static_mutex_unlock( &mutex );
   263 			return count;
   264 		}
   265 	}
   266 	g_static_mutex_unlock( &mutex );
   267 
   268 	return -1;	
   269 }
   270 
   271 /** Get the program info associated to the tvchain.
   272  * 
   273  * @param tvchain The GMythTVChain instance.
   274  * @param index The tvchain index.
   275  * @return The program info structure.
   276  */
   277 GMythProgramInfo*
   278 gmyth_tvchain_get_program_at (GMythTVChain *tvchain, int index)
   279 {
   280 	struct LiveTVChainEntry *entry;
   281 
   282 	entry = gmyth_tvchain_get_entry_at (tvchain, index);
   283 
   284 	if (entry)
   285 		return gmyth_tvchain_entry_to_program (tvchain, entry);	
   286 
   287 	return NULL;
   288 }
   289 
   290 /** Gets a LiveTVChainEntry associated to the tvchain by its index.
   291  * 
   292  * @param tvchain The GMythTVChain instance.
   293  * @param index The tvchain entry index
   294  * @return The LiveTVchainEntry structure.
   295  */
   296 struct LiveTVChainEntry*
   297 gmyth_tvchain_get_entry_at (GMythTVChain *tvchain, int index)
   298 {
   299 	struct LiveTVChainEntry* chain_entry = NULL;
   300 
   301 	g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_list != NULL, NULL );
   302 	
   303 	g_static_mutex_lock( &mutex );
   304 	
   305 	int size = g_list_length (tvchain->tvchain_list);
   306 	int new_index = (index < 0 || index >= size) ? size - 1 : index;
   307 
   308 	if (new_index >= 0) 
   309 		chain_entry = (struct LiveTVChainEntry*) g_list_nth_data (tvchain->tvchain_list, new_index);
   310 
   311 	g_static_mutex_unlock( &mutex );
   312 	
   313 	if ( chain_entry != NULL ) {
   314 		g_debug ("[%s] Got TV Chain entry at %d.\n", __FUNCTION__, new_index );
   315 
   316 	} else {
   317 		g_warning ("[%s] failed to get entry at index %d", __FUNCTION__, index);
   318 	}
   319 
   320 	return chain_entry;
   321 }
   322 
   323 /** Gets the program info from backend database associated to the tv chain entry.
   324  * 
   325  * @param tvchain The GMythTVChain instance.
   326  * @param entry the LiveTVChainEntry to be converted.
   327  * @return The progrma info.
   328  */
   329 GMythProgramInfo*
   330 gmyth_tvchain_entry_to_program (GMythTVChain *tvchain, struct LiveTVChainEntry *entry)
   331 {
   332 	GMythProgramInfo *proginfo = NULL;
   333 
   334 	g_return_val_if_fail( tvchain != NULL, NULL );
   335 
   336 	if (!entry || !tvchain) {
   337 		g_warning ("gmyth_tvchain_entry_to_program() received NULL argument");
   338 		return NULL;
   339 	}
   340 
   341 	GMythScheduler *scheduler = gmyth_scheduler_new ();
   342 
   343 	gmyth_scheduler_connect( scheduler );
   344 	proginfo = gmyth_scheduler_get_recorded (scheduler, 
   345 			entry->chanid, entry->starttime);
   346 	gmyth_scheduler_disconnect( scheduler );
   347 
   348 	if (proginfo) {
   349 		proginfo->pathname = g_string_prepend (proginfo->pathname, entry->hostprefix->str);
   350 	} else {
   351 		g_warning ("tvchain_entry_to_program(%s, %ld) failed!", entry->chanid->str, entry->starttime);
   352 	}
   353 
   354 	return proginfo;
   355 }