renatofilho@320: /** renatofilho@320: * GMyth Library renatofilho@320: * renatofilho@320: * @file gmyth/gmyth_epg.c renatofilho@320: * renatofilho@320: * @brief

GMythEPG class provides access to the program and channel data renatofilho@320: * from the Electronic Program Guide (EPG) of the Mythtv backend. renatofilho@320: * renatofilho@320: * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. renatofilho@320: * @author Leonardo Sobral Cunha renatofilho@320: * renatofilho@320: *//* renatofilho@320: * renatofilho@320: * This program is free software; you can redistribute it and/or modify renatofilho@320: * it under the terms of the GNU Lesser General Public License as published by renatofilho@320: * the Free Software Foundation; either version 2 of the License, or renatofilho@320: * (at your option) any later version. renatofilho@320: * renatofilho@320: * This program is distributed in the hope that it will be useful, renatofilho@320: * but WITHOUT ANY WARRANTY; without even the implied warranty of renatofilho@320: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the renatofilho@320: * GNU General Public License for more details. renatofilho@320: * renatofilho@320: * You should have received a copy of the GNU Lesser General Public License renatofilho@320: * along with this program; if not, write to the Free Software renatofilho@320: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA renatofilho@320: */ renatofilho@320: renatofilho@320: #ifdef HAVE_CONFIG_H renatofilho@320: #include "config.h" renatofilho@320: #endif renatofilho@320: renatofilho@320: #include renatofilho@320: #include renatofilho@320: #include renatofilho@320: #include renatofilho@320: renatofilho@320: #include "gmyth_epg.h" renatofilho@320: #include "gmyth_programinfo.h" renatofilho@320: #include "gmyth_util.h" renatofilho@320: #include "gmyth_debug.h" renatofilho@320: renatofilho@320: static void gmyth_epg_class_init (GMythEPGClass *klass); renatofilho@320: static void gmyth_epg_init (GMythEPG *object); renatofilho@320: renatofilho@320: static void gmyth_epg_dispose (GObject *object); renatofilho@320: static void gmyth_epg_finalize (GObject *object); renatofilho@320: renatofilho@320: G_DEFINE_TYPE(GMythEPG, gmyth_epg, G_TYPE_OBJECT) renatofilho@320: renatofilho@320: static void renatofilho@320: gmyth_epg_class_init (GMythEPGClass *klass) renatofilho@320: { renatofilho@320: GObjectClass *gobject_class = G_OBJECT_CLASS (klass); renatofilho@320: renatofilho@320: gobject_class->dispose = gmyth_epg_dispose; renatofilho@320: gobject_class->finalize = gmyth_epg_finalize; renatofilho@320: } renatofilho@320: renatofilho@320: static void renatofilho@320: gmyth_epg_init (GMythEPG *gmyth_epg) renatofilho@320: { renatofilho@320: renatofilho@320: } renatofilho@320: renatofilho@320: static void renatofilho@320: gmyth_epg_dispose (GObject *object) renatofilho@320: { renatofilho@320: //GMythEPG *gmyth_epg = GMYTH_EPG(object); renatofilho@320: renatofilho@320: G_OBJECT_CLASS (gmyth_epg_parent_class)->dispose (object); renatofilho@320: } renatofilho@320: renatofilho@320: static void renatofilho@320: gmyth_epg_finalize (GObject *object) renatofilho@320: { renatofilho@320: g_signal_handlers_destroy (object); renatofilho@320: renatofilho@320: G_OBJECT_CLASS (gmyth_epg_parent_class)->finalize (object); renatofilho@320: } renatofilho@320: renatofilho@320: /** renatofilho@320: * Creates a new instance of GMythEPG. renatofilho@320: * renatofilho@320: * @return a new instance of GMythEPG. renatofilho@320: */ renatofilho@320: GMythEPG* renatofilho@320: gmyth_epg_new (void) renatofilho@320: { renatofilho@320: GMythEPG *epg = GMYTH_EPG (g_object_new(GMYTH_EPG_TYPE, NULL)); renatofilho@320: renatofilho@320: return epg; renatofilho@320: } renatofilho@320: renatofilho@320: /** Connects to the Mysql database in the backend. The backend address renatofilho@320: * is loaded from the GMythSettings instance. renatofilho@320: * renatofilho@320: * @param gmyth_epg the GMythEPG instance to be connected. renatofilho@320: * @return true if connection was success, false if failed. renatofilho@320: */ renatofilho@320: gboolean renatofilho@320: gmyth_epg_connect (GMythEPG *gmyth_epg, GMythBackendInfo *backend_info) renatofilho@320: { renatofilho@320: assert(gmyth_epg); renatofilho@320: renatofilho@320: if (gmyth_epg->sqlquery == NULL) { renatofilho@320: gmyth_debug ("[%s] Creating gmyth_query", __FUNCTION__); renatofilho@320: gmyth_epg->sqlquery = gmyth_query_new ( ); renatofilho@320: } renatofilho@320: renatofilho@320: if (!gmyth_query_connect(gmyth_epg->sqlquery, backend_info)) { renatofilho@320: g_warning ("[%s] Error while connecting to db", __FUNCTION__); renatofilho@320: return FALSE; renatofilho@320: } renatofilho@320: renatofilho@320: return TRUE; renatofilho@320: } renatofilho@320: renatofilho@320: /** Disconnects from the Mysql database in the backend. renatofilho@320: * renatofilho@320: * @param gmyth_epg the GMythEPG instance to be disconnected renatofilho@320: * @return true if disconnection was success, false if failed. renatofilho@320: */ renatofilho@320: gboolean renatofilho@320: gmyth_epg_disconnect (GMythEPG *gmyth_epg) renatofilho@320: { renatofilho@320: assert(gmyth_epg); renatofilho@320: renatofilho@320: if (gmyth_epg->sqlquery != NULL) { renatofilho@320: g_object_unref (gmyth_epg->sqlquery); renatofilho@320: gmyth_epg->sqlquery = NULL; renatofilho@320: } renatofilho@320: renatofilho@320: return TRUE; renatofilho@320: } renatofilho@320: renatofilho@320: /** Retrieves the available list of channels from the backend Mysql database. renatofilho@320: * renatofilho@320: * @param gmyth_epg the GMythEPG instance. renatofilho@320: * @param glist_ptr the GList pointer to be filled with the loaded list address. renatofilho@320: * @return The amount of channels retrieved from database, or -1 if error. renatofilho@320: */ renatofilho@320: gint renatofilho@320: gmyth_epg_get_channel_list (GMythEPG *gmyth_epg, GList **glist_ptr) renatofilho@320: { renatofilho@320: MYSQL_RES *msql_res; renatofilho@320: renatofilho@320: assert(gmyth_epg); renatofilho@320: renatofilho@320: msql_res = gmyth_query_process_statement (gmyth_epg->sqlquery, renatofilho@320: "SELECT chanid, channum, name FROM channel;"); renatofilho@320: renatofilho@320: (*glist_ptr) = NULL; renatofilho@320: renatofilho@320: if (msql_res == NULL) { renatofilho@320: g_warning ("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__); renatofilho@320: return -1; renatofilho@320: } else { renatofilho@320: MYSQL_ROW row; renatofilho@320: GMythChannelInfo *channel_info; renatofilho@320: renatofilho@320: while ((row = mysql_fetch_row (msql_res)) != NULL){ renatofilho@320: renatofilho@320: channel_info = g_new0(GMythChannelInfo, 1); renatofilho@320: channel_info->channel_ID = g_ascii_strtoull (row[0], NULL, 10); renatofilho@320: channel_info->channel_num = g_string_new (row[1]); renatofilho@320: channel_info->channel_name = g_string_new (row[2]); renatofilho@320: renatofilho@320: gmyth_channel_info_print(channel_info); renatofilho@320: renatofilho@320: (*glist_ptr) = g_list_append ((*glist_ptr), channel_info); renatofilho@320: } renatofilho@320: } renatofilho@320: mysql_free_result (msql_res); renatofilho@320: return (!(*glist_ptr)) ? 0 : g_list_length (*glist_ptr); renatofilho@320: } renatofilho@320: renatofilho@320: /** renatofilho@320: * Retrieves the available list of channels from the backend Mysql database. renatofilho@320: * renatofilho@320: * @param gmyth_epg the GMythEPG instance. renatofilho@320: * @param proglist the GList pointer to be filled with the loaded list. renatofilho@320: * @param chan_num the channel num on which to search for program. renatofilho@320: * @param starttime the start time to search for programs. renatofilho@320: * @param endtime the end time to search for programs. renatofilho@320: * @return The amount of channels retrieved from database, or -1 if error. renatofilho@320: */ renatofilho@320: gint renatofilho@320: gmyth_epg_get_program_list (GMythEPG *gmyth_epg, GList **proglist, renatofilho@320: const gint chan_num, GTimeVal *starttime, GTimeVal *endtime) renatofilho@320: { renatofilho@320: renatofilho@320: gchar *startts = gmyth_util_time_to_string_from_time_val(starttime); renatofilho@320: gchar *endts = gmyth_util_time_to_string_from_time_val(endtime); renatofilho@320: MYSQL_ROW row; renatofilho@320: GString *querystr; renatofilho@320: renatofilho@320: assert(gmyth_epg); renatofilho@320: renatofilho@320: querystr = g_string_new( renatofilho@320: "SELECT DISTINCT program.chanid, program.starttime, program.endtime, " renatofilho@320: " program.title, program.subtitle, program.description, " renatofilho@320: " program.category, channel.channum, channel.callsign, " renatofilho@320: " channel.name, program.previouslyshown, channel.commfree, " renatofilho@320: " channel.outputfilters, program.seriesid, program.programid, " renatofilho@320: " program.airdate, program.stars, program.originalairdate, " renatofilho@320: " program.category_type, oldrecstatus.recordid, " renatofilho@320: " oldrecstatus.rectype, oldrecstatus.recstatus, " renatofilho@320: " oldrecstatus.findid " renatofilho@320: "FROM program " renatofilho@320: "LEFT JOIN channel ON program.chanid = channel.chanid " renatofilho@320: "LEFT JOIN oldrecorded AS oldrecstatus ON " renatofilho@320: " program.title = oldrecstatus.title AND " renatofilho@320: " channel.callsign = oldrecstatus.station AND " renatofilho@320: " program.starttime = oldrecstatus.starttime " renatofilho@320: ); renatofilho@320: renatofilho@320: g_string_append_printf (querystr, renatofilho@320: "WHERE program.chanid = %d " renatofilho@320: " AND program.endtime >= '%s' " renatofilho@320: " AND program.starttime <= '%s' " renatofilho@320: " AND program.manualid = 0 ", renatofilho@320: chan_num, startts, endts); renatofilho@320: renatofilho@320: if (!g_strrstr(querystr->str, " GROUP BY ")) renatofilho@320: querystr = g_string_append(querystr, renatofilho@320: " GROUP BY program.starttime, channel.channum, " renatofilho@320: " channel.callsign, program.title "); renatofilho@320: renatofilho@320: if (!g_strrstr(querystr->str, " LIMIT ")) renatofilho@320: querystr = g_string_append(querystr, " LIMIT 1000 "); renatofilho@320: renatofilho@320: MYSQL_RES *res_set = renatofilho@320: gmyth_query_process_statement(gmyth_epg->sqlquery, querystr->str); renatofilho@320: renatofilho@320: if (res_set == NULL) { renatofilho@320: g_warning ("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__); renatofilho@320: return -1; renatofilho@320: } renatofilho@320: renatofilho@320: (*proglist) = NULL; renatofilho@320: while ((row = mysql_fetch_row (res_set)) != NULL) { renatofilho@320: renatofilho@320: GMythProgramInfo *p = gmyth_program_info_new (); renatofilho@320: p->chanid = g_string_new (row[0]); renatofilho@320: renatofilho@320: p->startts = gmyth_util_string_to_time_val (row[1]); renatofilho@320: p->endts = gmyth_util_string_to_time_val (row[2]); renatofilho@320: renatofilho@320: p->recstartts = g_new0 (GTimeVal, 1); renatofilho@320: p->recstartts->tv_sec = p->startts->tv_sec; renatofilho@320: p->recstartts->tv_usec = p->startts->tv_usec; renatofilho@320: renatofilho@320: p->recendts = g_new0 (GTimeVal, 1); renatofilho@320: p->recendts->tv_sec = p->endts->tv_sec; renatofilho@320: p->recendts->tv_usec = p->endts->tv_usec; renatofilho@320: renatofilho@320: p->lastmodified = g_new0 (GTimeVal, 1); renatofilho@320: p->lastmodified->tv_sec = p->startts->tv_sec; renatofilho@320: p->lastmodified->tv_usec = p->startts->tv_usec; renatofilho@320: renatofilho@320: p->title = g_string_new (row[3]); renatofilho@320: p->subtitle = g_string_new (row[4]); renatofilho@320: p->description = g_string_new (row[5]); renatofilho@320: p->category = g_string_new (row[6]); renatofilho@320: p->chanstr = g_string_new (row[7]); renatofilho@320: p->chansign = g_string_new (row[8]); renatofilho@320: p->channame = g_string_new (row[9]); renatofilho@320: p->repeat = g_ascii_strtoull(row[10], NULL, 10); renatofilho@320: p->chancommfree = g_ascii_strtoull(row[11], NULL, 10); renatofilho@320: p->chanOutputFilters = g_string_new (row[12]); renatofilho@320: p->seriesid = g_string_new (row[13]); renatofilho@320: p->programid = g_string_new (row[14]); renatofilho@320: p->year = g_string_new (row[15]); renatofilho@320: p->stars = g_ascii_strtod(row[16], NULL); renatofilho@320: renatofilho@320: if (!row[17] || !strcmp(row[17], "")) { renatofilho@320: p->originalAirDate = 0; renatofilho@320: p->hasAirDate = FALSE; renatofilho@320: } else { renatofilho@320: p->originalAirDate = gmyth_util_string_to_time_val (row[17]); renatofilho@320: p->hasAirDate = TRUE; renatofilho@320: } renatofilho@320: renatofilho@320: p->catType = g_string_new (row[18]); renatofilho@320: renatofilho@320: *proglist = g_list_append((*proglist), p); renatofilho@320: renatofilho@320: #if 0 renatofilho@320: gmyth_program_info_print(p); renatofilho@320: #endif renatofilho@320: } renatofilho@320: renatofilho@320: /* deallocate */ renatofilho@320: mysql_free_result (res_set); renatofilho@320: g_string_free(querystr, TRUE); renatofilho@320: renatofilho@320: return TRUE; renatofilho@320: }