4 * @file gmyth/gmyth_tvchain.c
6 * @brief <p> This component contains functions for creating and accessing
7 * the tvchain functions for live tv playback.
9 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
10 * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
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.
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.
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
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"
40 static void gmyth_tvchain_class_init (GMythTVChainClass *klass);
41 static void gmyth_tvchain_init (GMythTVChain *object);
43 static void gmyth_tvchain_dispose (GObject *object);
44 static void gmyth_tvchain_finalize (GObject *object);
46 G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT)
48 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
51 gmyth_tvchain_class_init (GMythTVChainClass *klass)
53 GObjectClass *gobject_class;
55 gobject_class = (GObjectClass *) klass;
57 gobject_class->dispose = gmyth_tvchain_dispose;
58 gobject_class->finalize = gmyth_tvchain_finalize;
62 gmyth_tvchain_init (GMythTVChain *tvchain)
64 tvchain->tvchain_id = NULL;
66 tvchain->cur_chanid = g_string_new ("");
67 tvchain->cur_startts = 0;
71 gmyth_tvchain_dispose (GObject *object)
73 GMythTVChain *tvchain = GMYTH_TVCHAIN(object);
75 if ( tvchain->tvchain_id != NULL ) {
76 g_string_free( tvchain->tvchain_id, TRUE );
77 tvchain->tvchain_id = NULL;
80 if ( tvchain->tvchain_list != NULL ) {
81 g_list_free( tvchain->tvchain_list );
82 tvchain->tvchain_list = NULL;
85 if ( tvchain->cur_chanid != NULL ) {
86 g_string_free( tvchain->cur_chanid, TRUE );
87 tvchain->cur_chanid = NULL;
90 G_OBJECT_CLASS (gmyth_tvchain_parent_class)->dispose (object);
94 gmyth_tvchain_finalize (GObject *object)
96 g_signal_handlers_destroy (object);
98 G_OBJECT_CLASS (gmyth_tvchain_parent_class)->finalize (object);
101 /** Initializes the tvchain and generates the tvchain id.
103 * @param tvchain The GMythTVChain instance.
104 * @param hostname The local hostname used to generate the tvchain id.
107 gmyth_tvchain_initialize (GMythTVChain *tvchain, GString *hostname)
109 if (tvchain->tvchain_id == NULL) {
114 isodate = gmyth_util_time_to_isoformat (cur_time);
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);
120 g_print("tv_chain_id: %s\n", tvchain->tvchain_id->str);
122 g_string_free(isodate, TRUE);
125 g_warning ("[%s] TVchain already initialized", __FUNCTION__);
129 /** Gets the tvchain id.
131 * @param tvchain The GMythTVChain instance.
132 * @return The tvchain id.
135 gmyth_tvchain_get_id (GMythTVChain *tvchain)
137 g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_id != NULL, NULL );
139 return g_string_new (tvchain->tvchain_id->str);
142 /** Reloads all tvchain entries in the database.
144 * @param tvchain The GMythTVChain instance.
145 * @return TRUE if success, or FALSE if error.
148 gmyth_tvchain_reload_all (GMythTVChain *tvchain)
152 GMythQuery *gmyth_query;
157 g_static_mutex_lock( &mutex );
159 guint prev_size = g_list_length (tvchain->tvchain_list);
161 g_debug ("[%s] chainid: %s", __FUNCTION__, tvchain->tvchain_id->str);
163 if ( tvchain != NULL && tvchain->tvchain_list != NULL ) {
164 g_list_free (tvchain->tvchain_list);
165 tvchain->tvchain_list = NULL;
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 );
179 stmt_str = g_string_new ("");
180 g_string_printf (stmt_str,
181 "SELECT chanid, starttime, endtime, discontinuity, "
182 "chainpos, hostprefix, cardtype, channame, input "
184 "WHERE chainid = \"%s\" ORDER BY chainpos;",
185 tvchain->tvchain_id->str);
187 msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
188 if (msql_res != NULL) {
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]);
201 //m_maxpos = query.value(4).toInt() + 1;
203 tvchain->tvchain_list = g_list_append (tvchain->tvchain_list, entry);
206 g_warning ("gmyth_tvchain_reload_all query error!\n");
207 g_static_mutex_unlock( &mutex );
213 g_static_mutex_unlock( &mutex );
215 tvchain->cur_pos = gmyth_tvchain_program_is_at (tvchain, tvchain->cur_chanid, tvchain->cur_startts);
217 if (tvchain->cur_pos < 0)
218 tvchain->cur_pos = 0;
220 // if (m_switchid >= 0)
221 // m_switchid = ProgramIsAt(m_switchentry.chanid,m_switchentry.starttime);
223 if (prev_size != g_list_length (tvchain->tvchain_list)) {
224 g_debug ("[%s] Added new recording", __FUNCTION__);
228 if ( stmt_str != NULL )
229 g_string_free (stmt_str, TRUE);
231 if ( msql_res != NULL )
232 mysql_free_result (msql_res);
234 if ( gmyth_query != NULL )
235 g_object_unref (gmyth_query);
240 /** Returns the internal index for the TV chain related to the given
241 * channel and start time.
243 * @param tvchain The GMythTVChain instance.
244 * @param chanid The channel id.
245 * @param startts The program start time.
248 gmyth_tvchain_program_is_at (GMythTVChain *tvchain, GString *chanid, time_t startts)
251 struct LiveTVChainEntry *entry;
252 GList *tmp_list = tvchain->tvchain_list;
254 g_static_mutex_lock( &mutex );
256 for (; tmp_list; tmp_list = tvchain->tvchain_list->next, ++count)
258 entry = (struct LiveTVChainEntry*) tmp_list->data;
259 if (!g_strncasecmp (entry->chanid->str, chanid->str, chanid->len)
260 && entry->starttime == startts)
262 g_static_mutex_unlock( &mutex );
266 g_static_mutex_unlock( &mutex );
271 /** Get the program info associated to the tvchain.
273 * @param tvchain The GMythTVChain instance.
274 * @param index The tvchain index.
275 * @return The program info structure.
278 gmyth_tvchain_get_program_at (GMythTVChain *tvchain, int index)
280 struct LiveTVChainEntry *entry;
282 entry = gmyth_tvchain_get_entry_at (tvchain, index);
285 return gmyth_tvchain_entry_to_program (tvchain, entry);
290 /** Gets a LiveTVChainEntry associated to the tvchain by its index.
292 * @param tvchain The GMythTVChain instance.
293 * @param index The tvchain entry index
294 * @return The LiveTVchainEntry structure.
296 struct LiveTVChainEntry*
297 gmyth_tvchain_get_entry_at (GMythTVChain *tvchain, int index)
299 struct LiveTVChainEntry* chain_entry = NULL;
301 g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_list != NULL, NULL );
303 g_static_mutex_lock( &mutex );
305 int size = g_list_length (tvchain->tvchain_list);
306 int new_index = (index < 0 || index >= size) ? size - 1 : index;
309 chain_entry = (struct LiveTVChainEntry*) g_list_nth_data (tvchain->tvchain_list, new_index);
311 g_static_mutex_unlock( &mutex );
313 if ( chain_entry != NULL ) {
314 g_debug ("[%s] Got TV Chain entry at %d.\n", __FUNCTION__, new_index );
317 g_warning ("[%s] failed to get entry at index %d", __FUNCTION__, index);
323 /** Gets the program info from backend database associated to the tv chain entry.
325 * @param tvchain The GMythTVChain instance.
326 * @param entry the LiveTVChainEntry to be converted.
327 * @return The progrma info.
330 gmyth_tvchain_entry_to_program (GMythTVChain *tvchain, struct LiveTVChainEntry *entry)
332 GMythProgramInfo *proginfo = NULL;
334 g_return_val_if_fail( tvchain != NULL, NULL );
336 if (!entry || !tvchain) {
337 g_warning ("gmyth_tvchain_entry_to_program() received NULL argument");
341 GMythScheduler *scheduler = gmyth_scheduler_new ();
343 gmyth_scheduler_connect( scheduler );
344 proginfo = gmyth_scheduler_get_recorded (scheduler,
345 entry->chanid, entry->starttime);
346 gmyth_scheduler_disconnect( scheduler );
349 proginfo->pathname = g_string_prepend (proginfo->pathname, entry->hostprefix->str);
351 g_warning ("tvchain_entry_to_program(%s, %ld) failed!", entry->chanid->str, entry->starttime);