diff -r 28c358053693 -r 8aa32fa19a8f branches/gmyth-0.1b/src/gmyth_scheduler.c --- a/branches/gmyth-0.1b/src/gmyth_scheduler.c Wed Feb 14 23:06:17 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,667 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_scheduler.c - * - * @brief

The scheduler encapsulates all functions for browsing, scheduling - * and modifying the recorded content. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Alexsandro Jose Virginio dos Santos - * - *//* - * - * 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 "gmyth_scheduler.h" -#include "gmyth_util.h" -#include "gmyth_query.h" -#include "gmyth_socket.h" -#include "gmyth_debug.h" - -static void gmyth_scheduler_class_init (GMythSchedulerClass *klass); -static void gmyth_scheduler_init (GMythScheduler *object); - -static void gmyth_scheduler_dispose (GObject *object); -static void gmyth_scheduler_finalize (GObject *object); - -static gint get_record_id_from_database (GMythScheduler *scheduler); -static void update_backend (GMythScheduler *scheduler, gint record_id); - -G_DEFINE_TYPE(GMythScheduler, gmyth_scheduler, G_TYPE_OBJECT) - -static void -gmyth_scheduler_class_init (GMythSchedulerClass *klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_scheduler_dispose; - gobject_class->finalize = gmyth_scheduler_finalize; -} - -static void -gmyth_scheduler_init (GMythScheduler *sched) -{ - sched->recordid =0; - sched->type = 0; - sched->search = 0; - sched->profile = g_string_new(""); - - sched->dupin = 0; - sched->dupmethod = 0; - sched->autoexpire = 0; - sched->autotranscode = 0; - sched->transcoder = 0; - - sched->autocommflag = 0; - sched->autouserjob1 = 0; - sched->autouserjob2 = 0; - sched->autouserjob3 = 0; - sched->autouserjob4 = 0; - - sched->startoffset = 0; - sched->endoffset = 0; - sched->maxepisodes = 0; - sched->maxnewest = 0; - - sched->recpriority = 0; - sched->recgroup = 0; - sched->playgroup = 0; - - sched->prefinput = 0; - sched->inactive = 0; - - sched->searchType = g_string_new(""); - sched->searchForWhat = g_string_new(""); - - sched->msqlquery = gmyth_query_new (); -} - -static void -gmyth_scheduler_dispose (GObject *object) -{ - GMythScheduler *scheduler = GMYTH_SCHEDULER (object); - - if (scheduler->backend_info) { - g_object_unref (scheduler->backend_info); - scheduler->backend_info = NULL; - } - - G_OBJECT_CLASS (gmyth_scheduler_parent_class)->dispose (object); -} - -static void -gmyth_scheduler_finalize (GObject *object) -{ - g_signal_handlers_destroy (object); - - G_OBJECT_CLASS (gmyth_scheduler_parent_class)->finalize (object); -} - -/** Creates a new instance of GMythScheduler. - * - * @return a new instance of GMythScheduler. - */ -GMythScheduler* -gmyth_scheduler_new () -{ - GMythScheduler *scheduler = - GMYTH_SCHEDULER (g_object_new(GMYTH_SCHEDULER_TYPE, NULL)); - - return scheduler; -} - -gboolean -gmyth_scheduler_connect (GMythScheduler *scheduler, GMythBackendInfo *backend_info) -{ - return gmyth_scheduler_connect_with_timeout (scheduler, backend_info, 0); -} - -/** Connects to the Mysql database in the backend. The backend address - * is loaded from the GMythSettings instance. - * - * @param scheduler the GMythScheduler instance to be connected. - * @return true if connection was success, false if failed. - */ -gboolean -gmyth_scheduler_connect_with_timeout (GMythScheduler *scheduler, - GMythBackendInfo *backend_info, guint timeout) -{ - assert(scheduler); - g_return_val_if_fail (backend_info != NULL, FALSE); - - g_object_ref (backend_info); - scheduler->backend_info = backend_info; - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] GMythScheduler db initializing", __FUNCTION__); - scheduler->msqlquery = gmyth_query_new (); - } - - if (!gmyth_query_connect_with_timeout (scheduler->msqlquery, - scheduler->backend_info, timeout)) { - g_warning ("[%s] Error while connecting to db", __FUNCTION__); - return FALSE; - } - - return TRUE; -} - -/** Disconnects from the Mysql database in the backend. - * - * @param scheduler the GMythScheduler instance to be disconnected - * @return true if disconnection was success, false if failed. - */ -gboolean -gmyth_scheduler_disconnect (GMythScheduler *scheduler) -{ - assert(scheduler); - - if (scheduler->msqlquery != NULL) { - gmyth_query_disconnect (scheduler->msqlquery); - g_object_unref (scheduler->msqlquery); - } - - return TRUE; -} - -/** Retrieves from the backend Mysql database the list of recording schedules. - * - * @param scheduler The GMythScheduler instance. - * @param schedule_list the GList pointer to be filled with the loaded list of ScheduleInfo items. - * @return The amount of schedules retrieved from database, or -1 if error. - */ -gint -gmyth_scheduler_get_schedule_list ( GMythScheduler *scheduler, GList **schedule_list) -{ - ScheduleInfo *schedule; - MYSQL_RES *msql_res; - GString *query_str = g_string_new (""); - gchar *date_time = NULL; - - assert(scheduler); - - g_string_printf (query_str, - "SELECT recordid,programid,chanid,starttime,startdate," - "endtime,enddate,title,subtitle,description,category FROM record;"); - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); - return -1; - } - msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); - - if (msql_res == NULL) { - g_warning ("DB retrieval of schedule list failed"); - return -1; - } else { - MYSQL_ROW row; - *schedule_list = NULL; - - while((row = mysql_fetch_row (msql_res)) != NULL) { - schedule = g_new0(ScheduleInfo, 1); - - schedule->record_id = g_ascii_strtoull (row[0], NULL, 10); - schedule->program_id = g_ascii_strtoull (row[1], NULL, 10); - schedule->channel_id = g_ascii_strtoull (row[2], NULL, 10); - - /* generate a time_t from a time and a date db field */ - g_sprintf (date_time, "%sT%s", row[4], row[3]); - - schedule->start_time = gmyth_util_string_to_time_val (date_time); - - /* generate a time_t from a time and a date db field */ - g_sprintf (date_time, "%sT%s", row[6], row[5]); - - schedule->end_time = gmyth_util_string_to_time_val (date_time); - - schedule->title = g_string_new (row[7]); - schedule->subtitle = g_string_new (row[8]); - schedule->description = g_string_new (row[9]); - schedule->category = g_string_new (row[10]); - - (*schedule_list) = g_list_append (*(schedule_list), schedule); - } - } - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - g_free(date_time); - - return (*schedule_list == NULL) ? 0 : g_list_length (*schedule_list); -} - -/** Retrieves from the backend Mysql database the list of recorded programs. - * - * @param scheduler The GMythScheduler instance. - * @param recorded_list the GList pointer to be filled with the loaded RecordInfo items. - * @return The amount of recorded retrieved from database, or -1 if error. - */ -gint -gmyth_scheduler_get_recorded_list (GMythScheduler *scheduler, GList **recorded_list) -{ - RecordedInfo *record; - MYSQL_RES *msql_res; - GString *query_str = g_string_new (""); - - assert(scheduler); - - g_string_printf (query_str, - "SELECT recordid,programid,chanid,starttime,progstart," - "endtime,progend,title,subtitle,description,category,filesize,basename FROM recorded WHERE recgroup != 'LiveTV'"); - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); - return -1; - } - - msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); - - if (msql_res == NULL) { - g_warning ("DB retrieval of recording list failed"); - return -1; - } else { - MYSQL_ROW row; - *recorded_list = NULL; - - while((row = mysql_fetch_row (msql_res))!=NULL){ - record = g_new0(RecordedInfo, 1); - - record->record_id = (guint) g_ascii_strtoull (row[0], NULL, 10); - record->program_id = (guint) g_ascii_strtoull (row[1], NULL, 10); - record->channel_id = (guint) g_ascii_strtoull (row[2], NULL, 10); - - record->start_time = gmyth_util_string_to_time_val (row[3]); - record->end_time = gmyth_util_string_to_time_val (row[5]); - - record->title = g_string_new (row[7]); - record->subtitle = g_string_new (row[8]); - record->description = g_string_new (row[9]); - record->category = g_string_new (row[10]); - record->filesize = g_ascii_strtoull (row[11], NULL, 10); - record->basename = g_string_new (row[12]); - - *recorded_list = g_list_append (*recorded_list, record); - } - } - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - - return (*recorded_list == NULL) ? 0 : g_list_length (*recorded_list); -} - -/** Requests the Mysql database in the backend to add a new schedule. - * - * @param scheduler the GMythScheduler instance. - * @param schedule_info the ScheduleInfo with recording schedule information - * to be added. record_id = -1 to add a new schedule, otherwise this - * function will update the schedule in the db - * @return gboolean returns FALSE if some error occurs, TRUE otherwise - */ -gboolean -gmyth_scheduler_add_schedule (GMythScheduler *scheduler, - ScheduleInfo *schedule_info) -{ - //GTimeVal *start_tm; - //GTimeVal *end_tm; - - MYSQL_RES *msql_res; - GString *query_str = g_string_new (""); - - gchar *date_time = NULL; - - assert(scheduler); - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); - return FALSE; - } - - //TODO: verify if this funtion realy does what it should do! - g_string_printf (query_str, "REPLACE INTO record " - "(recordid, type, chanid, starttime, " - "startdate, endtime, enddate, title," - "profile, recpriority, maxnewest, inactive, " - "maxepisodes, autoexpire, startoffset, endoffset, " - "recgroup, dupmethod, dupin, station, " - "autocommflag, findday, findtime, findid, " - "search, autotranscode, transcoder, tsdefault, " - "autouserjob1, autouserjob2, autouserjob3, autouserjob4) " - " values ( %d, 1, %d, \"%s\"," //recordid, type, chanid, starttime - " \"%s\", \"%s\", \"%s\", \"%s\"," - //startdate, endtime, enddate, title - "DEFAULT, 0, 0, 0, " //profile, recpriority, maxnewest, inactive - "0, 1, 0, 0, " //maxepisodes, autoexpire, startoffset, endoffset - "DEFAULT, 6, 15, %d, " //recgroup, dupmethod, dupin, station - "1, %d, \"%s\", %d, " //autocommflag, findday, findtime, findid - "5, 0, 29, 1, " //search, autotranscode, transcoder, tsdefault - "0, 0, 0, 0 );", //autouserjob1, autouserjob2, autouserjob3, autouserjob4 - schedule_info->record_id, schedule_info->channel_id, - gmyth_util_time_to_string_only_time( schedule_info->start_time ), - gmyth_util_time_to_string_only_date( schedule_info->start_time ), - gmyth_util_time_to_string_only_time( schedule_info->end_time ), - gmyth_util_time_to_string_only_date( schedule_info->end_time ), - schedule_info->title->str, //title - schedule_info->channel_id,//station - (gmyth_util_time_val_to_date( schedule_info->start_time ))->tm_wday, //findday - gmyth_util_time_to_string_only_time( schedule_info->start_time ), //findtime - (gint)(schedule_info->start_time->tv_sec/60/60/24 + 719528)//findid - ); - - gmyth_debug ( "Sending query to MySQL = %s.", query_str->str ); - - msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); - - /* FIXME: currently no way to detect db error in UPDATE, REPLACES! - if (msql_res == NULL) { - g_warning ("DB retrieval of recording list failed"); - return -1; - }*/ - - /* TODO: verify record_id = -1 semantics */ - if (schedule_info->record_id <= 0) - schedule_info->record_id = get_record_id_from_database(scheduler); - - /* Notify the backend of changes */ - update_backend(scheduler, schedule_info->record_id); - - /* free allocated memory */ - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - - return 1; -} - -/** Requests the Mysql database in the backend to remove an existing schedule. - * - * @param scheduler the GMythScheduler instance. - * @param record_id The schedule's record id to be removed - * @return gboolean TRUE if success, FALSE if error - */ -gboolean -gmyth_scheduler_delete_schedule (GMythScheduler *scheduler, gint record_id) -{ - - MYSQL_RES *msql_res; - GString *query_str = g_string_new (""); - - assert(scheduler); - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); - return FALSE; - } - - //======================================== - g_string_printf (query_str, - "DELETE FROM record WHERE recordid=%d", record_id); - - msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); - - if (msql_res == NULL) { - g_warning ("[%s] Error while trying to delete a schedule in the database", __FUNCTION__); - return FALSE; - } - - update_backend(scheduler, record_id);// Notify the backend of the changes - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - - return TRUE; -} - -/** Requests the Mysql database in the backend to remove an existing recorded item. - * - * @param scheduler the GMythScheduler instance. - * @param record_id The recorded item id to be removed - * @return gboolean TRUE if success, FALSE if error - */ -gboolean -gmyth_scheduler_delete_recorded (GMythScheduler *scheduler, gint record_id) -{ - - MYSQL_RES *msql_res; - - GString *query_str = g_string_new (""); - - assert(scheduler); - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); - return FALSE; - } - - //======================================== - g_string_printf (query_str, - "DELETE FROM recorded WHERE recordid=%d", record_id); - - msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); - - update_backend(scheduler, record_id);// Notify the backend of the changes - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - - return TRUE; -} - -/** Retrieves an existing recorded item information from database. The information - * is used to fill the returned GMythProgramInfo. - * - * @param scheduler The GMythScheduler instance. - * @param channel The channel associated to the record - * @param starttime The record start time - * @return A GMythProgramInfo struct with the requested record item - * information, or NULL if error. - */ -GMythProgramInfo* -gmyth_scheduler_get_recorded (GMythScheduler *scheduler, - GString *channel, GTimeVal* starttime) -{ - MYSQL_RES *msql_res; - GMythProgramInfo *proginfo = NULL; - GString *query_str = g_string_new(""); - gchar *time_str = gmyth_util_time_to_string_from_time_val (starttime); - - assert(scheduler); - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); - return NULL; - } - - g_string_printf (query_str, "SELECT recorded.chanid,starttime,endtime,title, " - "subtitle,description,channel.channum, " - "channel.callsign,channel.name,channel.commfree, " - "channel.outputfilters,seriesid,programid,filesize, " - "lastmodified,stars,previouslyshown,originalairdate, " - "hostname,recordid,transcoder,playgroup, " - "recorded.recpriority,progstart,progend,basename,recgroup " - "FROM recorded " - "LEFT JOIN channel " - "ON recorded.chanid = channel.chanid " - "WHERE recorded.chanid = \"%s\" " - "AND starttime = \"%s\" ;", - channel->str, time_str); - - msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); - - if (msql_res /*&& query.size() > 0*/) { - - MYSQL_ROW msql_row = mysql_fetch_row (msql_res); - if (msql_row) { - - proginfo = gmyth_program_info_new(); - - proginfo->chanid = g_string_new (msql_row[0]); - proginfo->startts = gmyth_util_string_to_time_val (msql_row[23]); - proginfo->endts = gmyth_util_string_to_time_val (msql_row[24]); - proginfo->recstartts = gmyth_util_string_to_time_val (msql_row[1]); - proginfo->recendts = gmyth_util_string_to_time_val (msql_row[2]); - proginfo->title = g_string_new (msql_row[3]); - proginfo->subtitle = g_string_new (msql_row[4]); - proginfo->description = g_string_new (msql_row[5]); - - proginfo->chanstr = g_string_new (msql_row[6]); - proginfo->chansign = g_string_new (msql_row[7]); - proginfo->channame = g_string_new (msql_row[0]); - proginfo->chancommfree = g_ascii_strtoull (msql_row[9], NULL, 10); - proginfo->chanOutputFilters = g_string_new (msql_row[10]); - proginfo->seriesid = g_string_new (msql_row[11]); - proginfo->programid = g_string_new (msql_row[12]); - proginfo->filesize = g_ascii_strtoull (msql_row[13], NULL, 10); - - proginfo->lastmodified = gmyth_util_string_to_time_val (msql_row[14]); - - proginfo->stars = g_ascii_strtod (msql_row[15], NULL); - proginfo->repeat = g_ascii_strtoull (msql_row[16], NULL, 10); - - if (msql_row[17] == NULL) { - proginfo->originalAirDate = 0; - proginfo->hasAirDate = FALSE; - } else { - proginfo->originalAirDate = gmyth_util_string_to_time_val (msql_row[17]); - proginfo->hasAirDate = TRUE; - } - - proginfo->hostname = g_string_new (msql_row[18]); - proginfo->recordid = g_ascii_strtoull (msql_row[19], NULL, 10); - proginfo->transcoder = g_ascii_strtoull (msql_row[20], NULL, 10); - - //proginfo->spread = -1; - //proginfo->programflags = proginfo->getProgramFlags(); - - proginfo->recgroup = g_string_new (msql_row[26]); - proginfo->playgroup = g_string_new (msql_row[21]); - proginfo->recpriority = g_ascii_strtoull (msql_row[22], NULL, 10); - - proginfo->pathname = g_string_new (msql_row[25]); - - gmyth_debug ("One program info loaded from mysql database\n"); - } - } - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - g_free(time_str); - - return proginfo; -} - -/** Retrieves the next record id. - * - * @param scheduler The GMythScheduler instance. - * @return gint record_id if success, -1 otherwise - */ -static gint -get_record_id_from_database (GMythScheduler *scheduler) -{ - gint record_id; - - assert(scheduler); - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); - return 0; - } - - record_id = mysql_insert_id (scheduler->msqlquery->conn); - - return record_id; -} - -/** Notifies the backend of an update in the db. - * - * @param record_id the id of the modified recording. - */ -static void -update_backend(GMythScheduler *scheduler, gint record_id)//fixme: put void and discovery record_id inside -{ - GMythSocket *socket; - GMythStringList *strlist = gmyth_string_list_new (); - GString *datastr = g_string_new ("RESCHEDULE_RECORDINGS "); - - g_string_append_printf (datastr, "%d", record_id); - gmyth_string_list_append_string (strlist, datastr); - - socket = gmyth_socket_new (); - if (gmyth_socket_connect (socket, scheduler->backend_info->hostname, - scheduler->backend_info->port)) { - gmyth_socket_sendreceive_stringlist (socket, strlist); - } else { - g_warning ("[%s] Connection to backend failed!", __FUNCTION__); - } - - g_string_free(datastr, TRUE); - g_object_unref(strlist); -} - -void -gmyth_scheduler_recorded_info_get_preview (RecordedInfo *info, GByteArray* data) -{ -} - -void -gmyth_scheduler_recorded_info_free (RecordedInfo *info) -{ - if (info->title != NULL) - g_string_free (info->title, TRUE); - - if (info->subtitle != NULL) - g_string_free (info->subtitle, TRUE); - - if (info->description != NULL) - g_string_free (info->description, TRUE); - - if (info->category != NULL) - g_string_free (info->category, TRUE); - - if (info->basename != NULL) - g_string_free (info->basename, TRUE); - - g_free (info); -} - -void -gmyth_scheduler_schedule_info_free (ScheduleInfo *info) -{ - if (info->title != NULL) - g_string_free (info->title, TRUE); - - if (info->subtitle != NULL) - g_string_free (info->subtitle, TRUE); - - if (info->description != NULL) - g_string_free (info->description, TRUE); - - if (info->category != NULL) - g_string_free (info->category, TRUE); - - g_free (info); -} -