/** * GMyth Library * * @file gmyth/gmyth_epg.c * * @brief

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