gmyth/src/gmyth_scheduler.c
author renatofilho
Fri Dec 21 14:07:54 2007 +0000 (2007-12-21)
branchtrunk
changeset 886 781db4177ba2
parent 865 3eeb6b565018
child 890 6b565181036e
permissions -rw-r--r--
[svn r892] create help function: gmyth_scheduler_add_schedule_program
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_scheduler.c
     5  *
     6  * @brief <p> The scheduler encapsulates all functions for browsing, scheduling
     7  * and modifying the recorded content.
     8  *
     9  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
    10  * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
    11  *
    12  *
    13  * This program is free software; you can redistribute it and/or modify
    14  * it under the terms of the GNU Lesser General Public License as published by
    15  * the Free Software Foundation; either version 2 of the License, or
    16  * (at your option) any later version.
    17  *
    18  * This program is distributed in the hope that it will be useful,
    19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    21  * GNU General Public License for more details.
    22  *
    23  * You should have received a copy of the GNU Lesser General Public License
    24  * along with this program; if not, write to the Free Software
    25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    26  */
    27 
    28 #ifdef HAVE_CONFIG_H
    29 #include "config.h"
    30 #endif
    31 
    32 #include <assert.h>
    33 
    34 #include <glib/gprintf.h>
    35 
    36 #include "gmyth_scheduler.h"
    37 #include "gmyth_util.h"
    38 #include "gmyth_query.h"
    39 #include "gmyth_socket.h"
    40 #include "gmyth_debug.h"
    41 
    42 static void     gmyth_scheduler_class_init(GMythSchedulerClass * klass);
    43 static void     gmyth_scheduler_init(GMythScheduler * object);
    44 
    45 static void     gmyth_scheduler_dispose(GObject * object);
    46 static void     gmyth_scheduler_finalize(GObject * object);
    47 
    48 static gboolean update_backend(GMythScheduler * scheduler, gint record_id);
    49 
    50 G_DEFINE_TYPE(GMythScheduler, gmyth_scheduler, G_TYPE_OBJECT)
    51     static void     gmyth_scheduler_class_init(GMythSchedulerClass * klass)
    52 {
    53     GObjectClass   *gobject_class;
    54 
    55     gobject_class = (GObjectClass *) klass;
    56 
    57     gobject_class->dispose = gmyth_scheduler_dispose;
    58     gobject_class->finalize = gmyth_scheduler_finalize;
    59 }
    60 
    61 static void
    62 gmyth_scheduler_init(GMythScheduler * sched)
    63 {
    64     sched->recordid = 0;
    65     sched->type = 0;
    66     sched->search = 0;
    67     sched->profile = g_string_new("");
    68 
    69     sched->dupin = 0;
    70     sched->dupmethod = 0;
    71     sched->autoexpire = 0;
    72     sched->autotranscode = 0;
    73     sched->transcoder = 0;
    74 
    75     sched->autocommflag = 0;
    76     sched->autouserjob1 = 0;
    77     sched->autouserjob2 = 0;
    78     sched->autouserjob3 = 0;
    79     sched->autouserjob4 = 0;
    80 
    81     sched->startoffset = 0;
    82     sched->endoffset = 0;
    83     sched->maxepisodes = 0;
    84     sched->maxnewest = 0;
    85 
    86     sched->recpriority = 0;
    87     sched->recgroup = g_string_new("");
    88     sched->playgroup = g_string_new("");
    89 
    90     sched->prefinput = 0;
    91     sched->inactive = 0;
    92 
    93     sched->search_type = g_string_new("");
    94     sched->search_what = g_string_new("");
    95 
    96     sched->msqlquery = gmyth_query_new();
    97 }
    98 
    99 static void
   100 gmyth_scheduler_dispose(GObject * object)
   101 {
   102     GMythScheduler *scheduler = GMYTH_SCHEDULER(object);
   103 
   104     if (scheduler->backend_info) {
   105         g_object_unref(scheduler->backend_info);
   106         scheduler->backend_info = NULL;
   107     }
   108 
   109     if (scheduler->msqlquery) {
   110         g_object_unref(scheduler->msqlquery);
   111         scheduler->msqlquery = NULL;
   112     }
   113 
   114     g_string_free(scheduler->profile, TRUE);
   115     g_string_free(scheduler->recgroup, TRUE);
   116     g_string_free(scheduler->playgroup, TRUE);
   117     g_string_free(scheduler->search_type, TRUE);
   118     g_string_free(scheduler->search_what, TRUE);
   119 
   120     G_OBJECT_CLASS(gmyth_scheduler_parent_class)->dispose(object);
   121 }
   122 
   123 static void
   124 gmyth_scheduler_finalize(GObject * object)
   125 {
   126     g_signal_handlers_destroy(object);
   127 
   128     G_OBJECT_CLASS(gmyth_scheduler_parent_class)->finalize(object);
   129 }
   130 
   131 /** Creates a new instance of GMythScheduler.
   132  * 
   133  * @return a new instance of GMythScheduler.
   134  */
   135 GMythScheduler *
   136 gmyth_scheduler_new()
   137 {
   138     GMythScheduler *scheduler =
   139         GMYTH_SCHEDULER(g_object_new(GMYTH_SCHEDULER_TYPE, NULL));
   140 
   141     return scheduler;
   142 }
   143 
   144 gboolean
   145 gmyth_scheduler_connect(GMythScheduler * scheduler,
   146                         GMythBackendInfo * backend_info)
   147 {
   148     return gmyth_scheduler_connect_with_timeout(scheduler, backend_info,
   149                                                 0);
   150 }
   151 
   152 /** Connects to the Mysql database in the backend. The backend address
   153  * is loaded from the GMythSettings instance.
   154  *
   155  * @param scheduler the GMythScheduler instance to be connected.
   156  * @return true if connection was success, false if failed.
   157  */
   158 gboolean
   159 gmyth_scheduler_connect_with_timeout(GMythScheduler * scheduler,
   160                                      GMythBackendInfo * backend_info,
   161                                      guint timeout)
   162 {
   163     assert(scheduler);
   164     g_return_val_if_fail(backend_info != NULL, FALSE);
   165 
   166     if (scheduler->backend_info)
   167         g_object_unref(scheduler->backend_info);
   168 
   169     scheduler->backend_info = g_object_ref(backend_info);
   170 
   171     if (scheduler->msqlquery == NULL) {
   172         g_warning("[%s] GMythScheduler db initializing", __FUNCTION__);
   173         scheduler->msqlquery = gmyth_query_new();
   174     }
   175 
   176     if (!gmyth_query_connect_with_timeout(scheduler->msqlquery,
   177                                           scheduler->backend_info,
   178                                           timeout)) {
   179         g_warning("[%s] Error while connecting to db", __FUNCTION__);
   180         return FALSE;
   181     }
   182 
   183     return TRUE;
   184 }
   185 
   186 /** Disconnects from the Mysql database in the backend.
   187  *
   188  * @param scheduler the GMythScheduler instance to be disconnected
   189  * @return true if disconnection was success, false if failed.
   190  */
   191 gboolean
   192 gmyth_scheduler_disconnect(GMythScheduler * scheduler)
   193 {
   194     assert(scheduler);
   195 
   196     if (scheduler->msqlquery != NULL) {
   197         gmyth_query_disconnect(scheduler->msqlquery);
   198     }
   199 
   200     return TRUE;
   201 }
   202 
   203 /** Retrieves from the backend Mysql database the list of recording schedules.
   204  * 
   205  * @param scheduler The GMythScheduler instance.
   206  * @param schedule_list the GList pointer to be filled with the loaded list of ScheduleInfo items.
   207  * @return The amount of schedules retrieved from database, or -1 if error.
   208  */
   209 gint
   210 gmyth_scheduler_get_schedule_list(GMythScheduler * scheduler,
   211                                   GList ** schedule_list)
   212 {
   213     ScheduleInfo   *schedule;
   214     MYSQL_RES      *msql_res;
   215     GString        *query_str = g_string_new("");
   216     gchar          *date_time = NULL;
   217 
   218     assert(scheduler);
   219 
   220     g_string_printf(query_str,
   221                     "SELECT recordid,programid,chanid,starttime,startdate,"
   222                     "endtime,enddate,title,subtitle,description,category,type,parentid,seriesid FROM record;");
   223 
   224     if (scheduler->msqlquery == NULL) {
   225         g_warning("[%s] Scheduler db connection not initialized",
   226                   __FUNCTION__);
   227         return -1;
   228     }
   229     msql_res =
   230         gmyth_query_process_statement(scheduler->msqlquery,
   231                                       query_str->str);
   232 
   233     if (msql_res == NULL) {
   234         g_warning("DB retrieval of schedule list failed");
   235         return -1;
   236     } else {
   237         MYSQL_ROW       row;
   238 
   239         *schedule_list = NULL;
   240 
   241         while ((row = mysql_fetch_row(msql_res)) != NULL) {
   242             schedule = g_new0(ScheduleInfo, 1);
   243             gint type = 0;
   244 
   245             schedule->schedule_id =
   246                 (guint) g_ascii_strtoull(row[0], NULL, 10);
   247             schedule->program_id = g_string_new (row[1]);
   248             schedule->channel_id = g_string_new (row[2]);
   249 
   250             /*
   251              * generate a time_t from a time and a date db field 
   252              */
   253             date_time = g_strdup_printf("%sT%s", row[4], row[3]);
   254             schedule->start_time =
   255                 gmyth_util_string_to_time_val(date_time);
   256             g_free(date_time);
   257 
   258             /*
   259              * generate a time_t from a time and a date db field 
   260              */
   261             date_time = g_strdup_printf("%sT%s", row[6], row[5]);
   262             schedule->end_time = gmyth_util_string_to_time_val(date_time);
   263             g_free(date_time);
   264 
   265             schedule->title = g_string_new(row[7]);
   266             schedule->subtitle = g_string_new(row[8]);
   267             schedule->description = g_string_new(row[9]);
   268             schedule->category = g_string_new(row[10]);
   269             type = g_ascii_strtoull (row[11], NULL, 10);
   270             if (type == 4) {
   271                 schedule->type = GMYTH_SCHEDULE_ALL_OCCURRENCES;
   272             } else if (type == 1) {
   273                 schedule->type = GMYTH_SCHEDULE_ONE_OCCURRENCE;
   274             } else if (type == 8) {
   275                 schedule->type = GMYTH_SCHEDULE_EXCEPTION;
   276                 schedule->parentid = (gint) g_ascii_strtoull (row[12], NULL, 10);
   277             }
   278 
   279             schedule->seriesid = g_string_new (row[13]);
   280 
   281             (*schedule_list) = g_list_append(*(schedule_list), schedule);
   282         }
   283     }
   284 
   285     mysql_free_result(msql_res);
   286     g_string_free(query_str, TRUE);
   287 
   288     return (*schedule_list == NULL) ? 0 : g_list_length(*schedule_list);
   289 }
   290 
   291 /** Retrieves from the backend Mysql database the list of recorded programs.
   292  * 
   293  * @param scheduler The GMythScheduler instance.
   294  * @param recorded_list the GList pointer to be filled with the loaded RecordInfo items.
   295  * @return The amount of recorded retrieved from database, or -1 if error.
   296  */
   297 gint
   298 gmyth_scheduler_get_recorded_list(GMythScheduler * scheduler,
   299                                   GList ** recorded_list)
   300 {
   301     RecordedInfo   *record;
   302     MYSQL_RES      *msql_res;
   303     GString        *query_str = g_string_new("");
   304 
   305     assert(scheduler);
   306 
   307     g_string_printf(query_str,
   308                     "SELECT recordid,programid,chanid,starttime,progstart,"
   309                     "endtime,progend,title,subtitle,description,category,"
   310                     "filesize,basename,seriesid FROM recorded WHERE recgroup != 'LiveTV'");
   311 
   312     if (scheduler->msqlquery == NULL) {
   313         g_warning("[%s] Scheduler db connection not initialized",
   314                   __FUNCTION__);
   315         return -1;
   316     }
   317 
   318     msql_res =
   319         gmyth_query_process_statement(scheduler->msqlquery,
   320                                       query_str->str);
   321 
   322     if (msql_res == NULL) {
   323         g_warning("DB retrieval of recording list failed");
   324         return -1;
   325     } else {
   326         MYSQL_ROW       row;
   327 
   328         (*recorded_list) = NULL;
   329 
   330         while ((row = mysql_fetch_row(msql_res)) != NULL) {
   331             record = g_new0(RecordedInfo, 1);
   332 
   333             record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10);
   334             record->program_id =
   335                 (guint) g_ascii_strtoull(row[1], NULL, 10);
   336             record->channel_id = g_string_new (row[2]);
   337             record->start_time = gmyth_util_string_to_time_val(row[3]);
   338             record->end_time = gmyth_util_string_to_time_val(row[5]);
   339 
   340             record->title = g_string_new(row[7]);
   341             record->subtitle = g_string_new(row[8]);
   342             record->description = g_string_new(row[9]);
   343             record->category = g_string_new(row[10]);
   344             record->filesize = g_ascii_strtoull(row[11], NULL, 10);
   345             record->basename = g_string_new(row[12]);
   346             record->seriesid = g_string_new(row[13]);
   347 
   348             (*recorded_list) = g_list_append((*recorded_list), record);
   349         }
   350     }
   351 
   352     mysql_free_result(msql_res);
   353     g_string_free(query_str, TRUE);
   354 
   355     return (*recorded_list == NULL) ? 0 : g_list_length(*recorded_list);
   356 }
   357 
   358 RecordedInfo*
   359 gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler,
   360                                    const gchar* basename)
   361 {
   362     RecordedInfo   *record = NULL;
   363     MYSQL_RES      *msql_res;
   364     GString        *query_str = g_string_new("");
   365 
   366     assert(scheduler);
   367 
   368     g_string_printf(query_str,
   369                     "SELECT recordid,programid,chanid,starttime,progstart,"
   370                     "endtime,progend,title,subtitle,description,category,"
   371                     "filesize,basename,seriesid FROM recorded "
   372                     "WHERE recgroup != 'LiveTV' AND basename = '%s'", basename);
   373 
   374     if (scheduler->msqlquery == NULL) {
   375         g_warning("[%s] Scheduler db connection not initialized", 
   376                         __FUNCTION__);
   377         return NULL;
   378     }
   379 
   380     msql_res =
   381         gmyth_query_process_statement(scheduler->msqlquery,
   382                                       query_str->str);
   383 
   384     if (msql_res == NULL) {
   385         g_warning("DB retrieval of recording list failed");
   386         return NULL;
   387     } else {
   388         MYSQL_ROW       row;
   389         row = mysql_fetch_row(msql_res);
   390         if (row != NULL) {
   391             record = g_new0(RecordedInfo, 1);
   392             record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10);
   393             record->program_id = (guint) g_ascii_strtoull(row[1], NULL, 10);
   394             record->channel_id = g_string_new (row[2]);
   395             record->start_time = gmyth_util_string_to_time_val(row[3]);
   396             record->end_time = gmyth_util_string_to_time_val(row[5]);
   397             record->title = g_string_new(row[7]);
   398             record->subtitle = g_string_new(row[8]);
   399             record->description = g_string_new(row[9]);
   400             record->category = g_string_new(row[10]);
   401             record->filesize = g_ascii_strtoull(row[11], NULL, 10);
   402             record->basename = g_string_new(row[12]);
   403             record->seriesid = g_string_new(row[13]);
   404         }
   405     }
   406 
   407     mysql_free_result(msql_res);
   408     g_string_free(query_str, TRUE);
   409 
   410     return record;
   411 }
   412 
   413 
   414 static void
   415 _set_value(GMythQuery * myth_query, char *field, gchar * value,
   416            gint rec_id)
   417 {
   418     gchar          *query =
   419         g_strdup_printf
   420         ("UPDATE record SET recordid = %d, %s = \"%s\" WHERE recordid = %d;",
   421          rec_id, field, value, rec_id);
   422 
   423     gmyth_query_process_statement(myth_query, query);
   424     g_free(query);
   425 }
   426 
   427 static void
   428 _set_int_value(GMythQuery * myth_query, char *field, gint value,
   429                gint rec_id)
   430 {
   431     gchar *str_value = g_strdup_printf("%d", value);
   432 
   433     _set_value(myth_query, field, str_value, rec_id);
   434     g_free(str_value);
   435 }
   436 
   437 ScheduleInfo*
   438 gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler,
   439                                       GMythProgramInfo *program,
   440                                       GMythScheduleType type)
   441 {
   442     ScheduleInfo *info;
   443 
   444     info = g_new0 (ScheduleInfo, 1);
   445     info->program_id = g_string_new (program->programid->str);
   446     info->channel_id = g_string_new (program->chanid->str);
   447     info->start_time = g_new0 (GTimeVal, 1);
   448     *info->start_time = *program->startts;
   449     info->end_time = g_new0 (GTimeVal, 1);
   450     *info->end_time = *program->endts;
   451     info->seriesid = g_string_new (program->seriesid->str);
   452     info->title = g_string_new (program->title->str);
   453     info->subtitle = g_string_new (program->subtitle->str);
   454     info->description = g_string_new (program->description->str);
   455     info->category = g_string_new (program->category->str);
   456     info->type = type;
   457 
   458     if (gmyth_scheduler_add_schedule_full (scheduler, info, type))
   459     {
   460         if (!program->recstartts)
   461             program->recstartts = g_new0 (GTimeVal, 1);
   462         *program->recstartts = *info->start_time;
   463 
   464         if (!program->recendts)
   465             program->recendts = g_new0 (GTimeVal, 1);
   466         *program->recendts = *info->end_time;
   467 
   468         program->recordid = info->schedule_id;
   469         return info;
   470     }
   471 
   472     gmyth_schedule_info_free (info);
   473     return NULL;
   474 }
   475 
   476 
   477 gboolean
   478 gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler,
   479                              ScheduleInfo * schedule_info, GMythScheduleType type)
   480 {
   481     MYSQL_RES      *msql_res;
   482     gchar          *query_str = "INSERT record (recordid) VALUE (0);";
   483     gchar          *station = NULL;
   484     gulong          rec_id;
   485 
   486     assert(scheduler);
   487 
   488     if (scheduler->msqlquery == NULL) {
   489         g_warning("[%s] Scheduler db connection not initialized",
   490                   __FUNCTION__);
   491         return FALSE;
   492     }
   493 
   494     msql_res =
   495         gmyth_query_process_statement_with_increment(scheduler->msqlquery,
   496                                                      query_str, &rec_id);
   497     mysql_free_result(msql_res);
   498 
   499     // Retrieves the station info
   500     query_str =
   501         g_strdup_printf
   502         ("SELECT callsign FROM channel WHERE chanid = \"%s\";",
   503          schedule_info->channel_id->str);
   504     msql_res =
   505         gmyth_query_process_statement(scheduler->msqlquery, query_str);
   506     if (msql_res == NULL) {
   507         g_warning("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__);
   508         return FALSE;
   509     } else {
   510         MYSQL_ROW       row;
   511 
   512         if ((row = mysql_fetch_row(msql_res)) != NULL) {
   513             station = g_strdup(row[0]);
   514         }
   515     }
   516     mysql_free_result(msql_res);
   517     g_free(query_str);
   518 
   519     // _set_value (field, value, id);
   520     _set_value(scheduler->msqlquery, "chanid",
   521                schedule_info->channel_id->str, rec_id);
   522     _set_value(scheduler->msqlquery, "station", station, rec_id);
   523     _set_value(scheduler->msqlquery, "title", schedule_info->title->str,
   524                rec_id);
   525     // / subtitle, description 
   526     _set_value(scheduler->msqlquery, "starttime",
   527                gmyth_util_time_to_string_only_time(schedule_info->
   528                                                    start_time), rec_id);
   529     _set_value(scheduler->msqlquery, "startdate",
   530                gmyth_util_time_to_string_only_date(schedule_info->
   531                                                    start_time), rec_id);
   532     _set_value(scheduler->msqlquery, "endtime",
   533                gmyth_util_time_to_string_only_time(schedule_info->
   534                                                    end_time), rec_id);
   535     _set_value(scheduler->msqlquery, "enddate",
   536                gmyth_util_time_to_string_only_date(schedule_info->
   537                                                    end_time), rec_id);
   538     // / category, series id, program id
   539     // _set_value (scheduler->msqlquery, "findday",
   540     // (gmyth_util_time_val_to_date( schedule_info->start_time
   541     // ))->tm_wday, rec_id);
   542     // _set_value (scheduler->msqlquery, "findtime",
   543     // gmyth_util_time_to_string_only_time( schedule_info->start_time),
   544     // rec_id);
   545     // _set_int_value (scheduler->msqlquery, "findid",
   546     // (gint)(schedule_info->start_time->tv_sec/60/60/24 + 719528),
   547     // rec_id);
   548 
   549     _set_value(scheduler->msqlquery, "seriesid",
   550                schedule_info->seriesid->str, rec_id);
   551     _set_value(scheduler->msqlquery, "parentid", "0", rec_id);
   552     _set_value(scheduler->msqlquery, "search", "0", rec_id);
   553 
   554     if (type == GMYTH_SCHEDULE_ALL_OCCURRENCES) {
   555         _set_int_value(scheduler->msqlquery, "type", 3, rec_id);
   556     } else if (type == GMYTH_SCHEDULE_ONE_OCCURRENCE) {
   557         _set_int_value(scheduler->msqlquery, "type", 1, rec_id);
   558     } else if (type == GMYTH_SCHEDULE_EXCEPTION) {
   559         _set_int_value(scheduler->msqlquery, "type", 8, rec_id);
   560         _set_int_value(scheduler->msqlquery, "parentid", schedule_info->parentid,
   561 		       rec_id);
   562     }
   563 
   564     _set_value(scheduler->msqlquery, "recpriority", "0", rec_id);
   565     _set_value(scheduler->msqlquery, "startoffset", "0", rec_id);
   566     _set_value(scheduler->msqlquery, "endoffset", "0", rec_id);
   567     _set_value(scheduler->msqlquery, "dupmethod", "6", rec_id); // ?
   568     _set_value(scheduler->msqlquery, "dupin", "15", rec_id);    // ?
   569 
   570     _set_value(scheduler->msqlquery, "prefinput", "0", rec_id);
   571     _set_value(scheduler->msqlquery, "inactive", "0", rec_id);
   572     _set_value(scheduler->msqlquery, "profile", "Default", rec_id);
   573     _set_value(scheduler->msqlquery, "recgroup", "Default", rec_id);
   574     _set_value(scheduler->msqlquery, "storagegroup", "Default", rec_id);
   575     _set_value(scheduler->msqlquery, "playgroup", "Default", rec_id);
   576     _set_value(scheduler->msqlquery, "autoexpire", "1", rec_id);
   577     _set_value(scheduler->msqlquery, "maxepisodes", "0", rec_id);
   578     _set_value(scheduler->msqlquery, "maxnewest", "0", rec_id);
   579     _set_value(scheduler->msqlquery, "autocommflag", "1", rec_id);
   580     _set_value(scheduler->msqlquery, "autotranscode", "0", rec_id);
   581     _set_value(scheduler->msqlquery, "transcoder", "0", rec_id);
   582 
   583     _set_value(scheduler->msqlquery, "autouserjob1", "0", rec_id);
   584     _set_value(scheduler->msqlquery, "autouserjob2", "0", rec_id);
   585     _set_value(scheduler->msqlquery, "autouserjob3", "0", rec_id);
   586     _set_value(scheduler->msqlquery, "autouserjob4", "0", rec_id);
   587 
   588     schedule_info->schedule_id = rec_id;
   589 
   590     /* Notify the backend of changes */
   591     return update_backend(scheduler, rec_id);
   592 }
   593 
   594 /** Requests the Mysql database in the backend to add a new schedule.
   595  * 
   596  * @param scheduler the GMythScheduler instance.
   597  * @param schedule_info the ScheduleInfo with recording schedule information
   598  * to be added. record_id = -1 to add a new schedule, otherwise this
   599  * function will update the schedule in the db
   600  * @return gboolean returns FALSE if some error occurs, TRUE otherwise
   601  */
   602 gboolean
   603 gmyth_scheduler_add_schedule (GMythScheduler * scheduler,
   604                              ScheduleInfo * schedule_info)
   605 {
   606     return gmyth_scheduler_add_schedule_full (scheduler, schedule_info, 
   607                                               GMYTH_SCHEDULE_ONE_OCCURRENCE);
   608 }
   609 
   610 /** Requests the Mysql database in the backend to remove an existing schedule.
   611  * 
   612  * @param scheduler the GMythScheduler instance.
   613  * @param schedule_id The schedule's record id to be removed
   614  * @return gboolean TRUE if success, FALSE if error
   615  */
   616 gboolean
   617 gmyth_scheduler_delete_schedule(GMythScheduler * scheduler, gint schedule_id)
   618 {
   619 
   620     MYSQL_RES      *msql_res;
   621     GString        *query_str = NULL;
   622 
   623     g_return_val_if_fail (scheduler != NULL, FALSE);
   624 
   625 
   626     if (scheduler->msqlquery == NULL) {
   627         g_warning("[%s] Scheduler db connection not initialized",
   628                   __FUNCTION__);
   629         return FALSE;
   630     }
   631 
   632     query_str = g_string_new("");
   633     g_string_printf(query_str,
   634                     "DELETE FROM record WHERE recordid=%d", schedule_id);
   635 
   636     msql_res =
   637         gmyth_query_process_statement(scheduler->msqlquery,
   638                                       query_str->str);
   639 
   640 
   641     mysql_free_result(msql_res);
   642     g_string_free(query_str, TRUE);
   643 
   644     // Notify the backend of the changes
   645     return update_backend(scheduler, schedule_id);
   646 }
   647 
   648 /*
   649  * Add an exception program to be removed from the schedule list, when programs
   650  * where scheduled with the GMYTH_SCHEDULE_ALL_OCCURRENCES option.
   651  * @param scheduler the GMythScheduler instance.
   652  * @param schedule_id the schedule id of the all occurrence schedule to be changed
   653  * @param exception_info the ScheduleInfo to be removed from all schedule occurrences
   654  * @return TRUE if success, FALSE if any error happens
   655  */
   656 gboolean
   657 gmyth_scheduler_add_exception (GMythScheduler *scheduler, gint schedule_id,
   658 			       ScheduleInfo *exception_info)
   659 {
   660     gboolean res;
   661 
   662     g_return_val_if_fail (scheduler != NULL, FALSE);
   663     g_return_val_if_fail (exception_info != NULL, FALSE);
   664 
   665     exception_info->parentid = schedule_id;
   666     res = gmyth_scheduler_add_schedule_full (scheduler, exception_info, GMYTH_SCHEDULE_EXCEPTION);
   667 
   668     return res;
   669 }
   670 
   671 /** Requests the Mysql database in the backend to remove an existing recorded item.
   672  * 
   673  * @param scheduler the GMythScheduler instance.
   674  * @param record_id The recorded item id to be removed
   675  * @return gboolean TRUE if success, FALSE if error
   676  */
   677 gboolean
   678 gmyth_scheduler_delete_recorded(GMythScheduler * scheduler, gint record_id)
   679 {
   680 
   681     MYSQL_RES      *msql_res;
   682 
   683     GString        *query_str = g_string_new("");
   684 
   685     assert(scheduler);
   686 
   687     if (scheduler->msqlquery == NULL) {
   688         g_warning("[%s] Scheduler db connection not initialized",
   689                   __FUNCTION__);
   690         return FALSE;
   691     }
   692     // ========================================
   693     g_string_printf(query_str,
   694                     "DELETE FROM recorded WHERE recordid=%d", record_id);
   695 
   696     // FIXME: Mythtv implementation runs also: DELETE FROM oldfind WHERE
   697     // recordid = x
   698 
   699     msql_res =
   700         gmyth_query_process_statement(scheduler->msqlquery,
   701                                       query_str->str);
   702 
   703     mysql_free_result(msql_res);
   704     g_string_free(query_str, TRUE);
   705 
   706     // Notify the backend of the changes
   707     return update_backend(scheduler, record_id);
   708 }
   709 
   710 
   711 gboolean gmyth_scheduler_was_recorded_before(GMythScheduler* scheduler, gint channel_id,
   712                                              time_t start_time)
   713 {
   714     MYSQL_RES      *msql_res;
   715     GString        *query_str = g_string_new("");
   716 
   717     assert(scheduler);
   718     g_string_printf(query_str, "SELECT callsign FROM channel "
   719                     "WHERE chanid = \"%d\"", channel_id);
   720 
   721     msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
   722 
   723     if (msql_res) {
   724         MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
   725         if (msql_row) {
   726             GString* callsign = g_string_new(msql_row[0]);
   727             GString* startts = gmyth_util_time_to_string(start_time);
   728             g_string_printf(query_str, "SELECT * FROM oldrecorded "
   729                             "WHERE station = \"%s\" AND starttime = \"%s\"",
   730                             callsign->str, startts->str);
   731             msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
   732             g_string_free(callsign, TRUE);
   733             g_string_free(startts, TRUE);
   734             g_string_free(query_str, TRUE);
   735             if (mysql_fetch_row(msql_res)) return TRUE;
   736         }
   737     }
   738     return FALSE;
   739 }
   740 
   741 
   742 gboolean gmyth_scheduler_reactivate_schedule(GMythScheduler* scheduler, gint channel_id,
   743                                              time_t start_time)
   744 
   745 {
   746     MYSQL_RES      *msql_res;
   747     GString        *query_str = g_string_new("");
   748 
   749     assert(scheduler);
   750     g_string_printf(query_str, "SELECT callsign FROM channel "
   751                     "WHERE chanid = \"%d\"", channel_id);
   752 
   753     msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
   754     if (msql_res) {
   755         MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
   756         if (msql_row) {
   757             GString* callsign = g_string_new(msql_row[0]);
   758             GString* startts = gmyth_util_time_to_string(start_time);
   759             g_string_printf(query_str, "UPDATE oldrecorded SET reactivate = 1 "
   760                             "WHERE station = \"%s\" AND starttime = \"%s\"",
   761                             callsign->str, startts->str);
   762             gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
   763             g_string_free(callsign, TRUE);
   764             g_string_free(startts, TRUE);
   765             g_string_free(query_str, TRUE);
   766             return TRUE;
   767         }
   768 
   769     }
   770 
   771     return FALSE;
   772 }
   773 
   774 
   775 /*
   776  * This should only be used in special situations. We do not know the time that
   777  * the recording was set. We just know that it is an "ongoing" record and then
   778  * we have to use this to get it's info. It's always the oldest one -> first on list
   779  *
   780  */
   781 GMythProgramInfo*
   782 gmyth_scheduler_get_recorded_on_time(GMythScheduler* scheduler,
   783                                      guint channel_id)
   784 {
   785     MYSQL_RES      *msql_res;
   786     GMythProgramInfo *proginfo = NULL;
   787     GString        *query_str = g_string_new("");
   788 
   789     assert(scheduler);
   790 
   791     g_string_printf(query_str,
   792                     "SELECT recorded.chanid,starttime,endtime,title,"
   793                     "subtitle,description,channel.channum,"
   794                     "channel.callsign,channel.name,channel.commfree,"
   795                     "channel.outputfilters,seriesid,programid,filesize,"
   796                     "lastmodified,stars,previouslyshown,originalairdate,"
   797                     "hostname,recordid,transcoder,playgroup,"
   798                     "recorded.recpriority,progstart,progend,basename,recgroup,"
   799                     "category,findid,duplicate "
   800                     "FROM recorded " "LEFT JOIN channel "
   801                     "ON recorded.chanid = channel.chanid "
   802                     "WHERE recorded.chanid = %d "
   803                     "ORDER BY starttime DESC", channel_id);
   804 
   805     msql_res =
   806         gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
   807 
   808     if (msql_res) {
   809         MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
   810 
   811         if (msql_row) {
   812             proginfo = gmyth_program_info_new();
   813 
   814             proginfo->chanid = g_string_new(msql_row[0]);
   815             proginfo->recstartts = gmyth_util_string_to_time_val(msql_row[1]);
   816             proginfo->recendts = gmyth_util_string_to_time_val(msql_row[2]);
   817 
   818             proginfo->title = g_string_new(msql_row[3]);
   819             proginfo->subtitle = g_string_new(msql_row[4]);
   820             proginfo->description = g_string_new(msql_row[5]);
   821 
   822             proginfo->chanstr = g_string_new(msql_row[6]);
   823             proginfo->chansign = g_string_new(msql_row[7]);
   824             proginfo->channame = g_string_new(msql_row[8]);
   825             proginfo->chancommfree = (gint) g_ascii_strtoull(msql_row[9], NULL, 10);
   826             proginfo->chanOutputFilters = g_string_new(msql_row[10]);
   827             proginfo->seriesid = g_string_new(msql_row[11]);
   828             proginfo->programid = g_string_new(msql_row[12]);
   829             proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10);
   830 
   831             proginfo->lastmodified = gmyth_util_string_to_time_val(msql_row[14]);
   832             proginfo->stars = g_ascii_strtod(msql_row[15], NULL);
   833             proginfo->repeat = (gint)g_ascii_strtoull(msql_row[16], NULL, 10);
   834 
   835             if (msql_row[17] == NULL) {
   836                 proginfo->originalAirDate = 0;
   837                 proginfo->hasAirDate = FALSE;
   838             } else {
   839                 proginfo->originalAirDate = gmyth_util_string_to_time_val(msql_row[17]);
   840                 proginfo->hasAirDate = TRUE;
   841             }
   842 
   843             proginfo->hostname = g_string_new(msql_row[18]);
   844             proginfo->recordid = (gint) g_ascii_strtoull(msql_row[19], NULL, 10);
   845             proginfo->transcoder = (gint) g_ascii_strtoull(msql_row[20], NULL, 10);
   846 
   847             proginfo->playgroup = g_string_new(msql_row[21]);
   848             proginfo->recpriority = (gint) g_ascii_strtoull(msql_row[22], NULL, 10);
   849 
   850             proginfo->startts = gmyth_util_string_to_time_val(msql_row[23]);
   851             proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]);
   852             proginfo->pathname = g_string_new(g_strdup(msql_row[25]));
   853             proginfo->recgroup = g_string_new(msql_row[26]);
   854             proginfo->category = g_string_new(msql_row[27]);
   855             proginfo->findid = (gint) g_ascii_strtoull(msql_row[28], NULL, 10);
   856 
   857             proginfo->recpriority2 = 0;
   858 
   859             g_string_printf(query_str,
   860                             "SELECT dupmethod,dupin,parentid,type "
   861                             "FROM record WHERE recordid = \"%d\"", proginfo->recordid);
   862 
   863             msql_res =
   864                 gmyth_query_process_statement(scheduler->msqlquery,
   865                                               query_str->str);
   866 
   867             if (msql_res) {
   868                 MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
   869 
   870                 if (msql_row) {
   871                     proginfo->dupmethod = (gint) g_ascii_strtoull(msql_row[0], NULL, 10);
   872                     proginfo->dupin = (gint) g_ascii_strtoull(msql_row[1], NULL, 10);
   873                     proginfo->parentid = (gint) g_ascii_strtoull(msql_row[2], NULL, 10);
   874                     proginfo->rectype = 0;
   875                 }
   876             }
   877 
   878 
   879             g_string_printf(query_str,
   880                             "SELECT sourceid,cardid,cardinputid,shareable "
   881                             "FROM cardinput");
   882 
   883             msql_res =
   884                 gmyth_query_process_statement(scheduler->msqlquery,
   885                                               query_str->str);
   886 
   887             if (msql_res) {
   888                 MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
   889 
   890                 if (msql_row) {
   891                     proginfo->sourceid = 0;
   892                     proginfo->cardid = 0;
   893                     proginfo->inputid = 0;
   894                     if (msql_row[3] != NULL && g_ascii_strcasecmp("Y", msql_row[3]) == 0)
   895                         proginfo->shareable = 1;
   896                     else
   897                         proginfo->shareable = 0;
   898                 }
   899             }
   900 
   901 
   902 
   903         }
   904     }
   905 
   906     g_string_free(query_str, TRUE);
   907     return proginfo;
   908 }
   909 
   910 /** Retrieves an existing recorded item information from database. The information
   911  * is used to fill the returned GMythProgramInfo.
   912  * 
   913  * @param scheduler The GMythScheduler instance.
   914  * @param channel The channel associated to the record
   915  * @param starttime The record start time
   916  * @return A GMythProgramInfo struct with the requested record item
   917  * information, or NULL if error.
   918  */
   919 GMythProgramInfo *
   920 gmyth_scheduler_get_recorded(GMythScheduler * scheduler,
   921                              GString * channel, GTimeVal * starttime)
   922 {
   923     MYSQL_RES      *msql_res;
   924     GMythProgramInfo *proginfo = NULL;
   925     GString        *query_str = g_string_new("");
   926     gchar          *time_str =
   927         gmyth_util_time_to_string_from_time_val(starttime);
   928 
   929     assert(scheduler);
   930 
   931     gmyth_debug("[%s] channel: %s", __FUNCTION__, channel->str);
   932 
   933     if (scheduler->msqlquery == NULL) {
   934         g_warning("[%s] Scheduler db connection not initialized",
   935                   __FUNCTION__);
   936         return NULL;
   937     }
   938 
   939     g_string_printf(query_str,
   940                     "SELECT recorded.chanid,starttime,endtime,title, "
   941                     "subtitle,description,channel.channum, "
   942                     "channel.callsign,channel.name,channel.commfree, "
   943                     "channel.outputfilters,seriesid,programid,filesize, "
   944                     "lastmodified,stars,previouslyshown,originalairdate, "
   945                     "hostname,recordid,transcoder,playgroup, "
   946                     "recorded.recpriority,progstart,progend,basename,recgroup "
   947                     "FROM recorded " "LEFT JOIN channel "
   948                     "ON recorded.chanid = channel.chanid "
   949                     "WHERE recorded.chanid = \"%s\" "
   950                     "AND starttime = \"%s\" ;", channel->str, time_str);
   951 
   952     msql_res =
   953         gmyth_query_process_statement(scheduler->msqlquery,
   954                                       query_str->str);
   955 
   956     if (msql_res /* && query.size() > 0 */ ) {
   957         MYSQL_ROW       msql_row = mysql_fetch_row(msql_res);
   958 
   959         if (msql_row) {
   960             proginfo = gmyth_program_info_new();
   961 
   962             proginfo->chanid = g_string_new(msql_row[0]);
   963             proginfo->startts =
   964                 gmyth_util_string_to_time_val(msql_row[23]);
   965             proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]);
   966             proginfo->recstartts =
   967                 gmyth_util_string_to_time_val(msql_row[1]);
   968             proginfo->recendts =
   969                 gmyth_util_string_to_time_val(msql_row[2]);
   970             proginfo->title = g_string_new(msql_row[3]);
   971             proginfo->subtitle = g_string_new(msql_row[4]);
   972             proginfo->description = g_string_new(msql_row[5]);
   973 
   974             proginfo->chanstr = g_string_new(msql_row[6]);
   975             proginfo->chansign = g_string_new(msql_row[7]);
   976             proginfo->channame = g_string_new(msql_row[0]);
   977             proginfo->chancommfree =
   978                 (gint) g_ascii_strtoull(msql_row[9], NULL, 10);
   979             proginfo->chanOutputFilters = g_string_new(msql_row[10]);
   980             proginfo->seriesid = g_string_new(msql_row[11]);
   981             proginfo->programid = g_string_new(msql_row[12]);
   982             proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10);
   983 
   984             proginfo->lastmodified =
   985                 gmyth_util_string_to_time_val(msql_row[14]);
   986             proginfo->stars = g_ascii_strtod(msql_row[15], NULL);
   987             proginfo->repeat =
   988                 (gint) g_ascii_strtoull(msql_row[16], NULL, 10);
   989 
   990             if (msql_row[17] == NULL) {
   991                 proginfo->originalAirDate = 0;
   992                 proginfo->hasAirDate = FALSE;
   993             } else {
   994                 proginfo->originalAirDate =
   995                     gmyth_util_string_to_time_val(msql_row[17]);
   996                 proginfo->hasAirDate = TRUE;
   997             }
   998 
   999             proginfo->hostname = g_string_new(msql_row[18]);
  1000             proginfo->recordid =
  1001                 (gint) g_ascii_strtoull(msql_row[19], NULL, 10);
  1002             proginfo->transcoder =
  1003                 (gint) g_ascii_strtoull(msql_row[20], NULL, 10);
  1004             // proginfo->spread = -1;
  1005             // proginfo->programflags = proginfo->getProgramFlags();
  1006 
  1007             proginfo->recgroup = g_string_new(msql_row[26]);
  1008             proginfo->playgroup = g_string_new(msql_row[21]);
  1009             proginfo->recpriority =
  1010                 (gint) g_ascii_strtoull(msql_row[22], NULL, 10);
  1011 
  1012             proginfo->pathname = g_string_new(g_strdup(msql_row[25]));
  1013 
  1014             gmyth_debug("One program info loaded from mysql database\n");
  1015         }
  1016     }
  1017 
  1018     mysql_free_result(msql_res);
  1019     g_string_free(query_str, TRUE);
  1020     g_free(time_str);
  1021 
  1022     return proginfo;
  1023 }
  1024 
  1025 gboolean
  1026 gmyth_scheduler_stop_recording (GMythScheduler * scheduler,
  1027                                 gint channel_id)
  1028 {
  1029     GMythProgramInfo *program;
  1030     GMythSocket    *socket;
  1031     gboolean        res = FALSE;
  1032     GMythStringList *slist;
  1033 
  1034     socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info);
  1035     program = gmyth_scheduler_get_recorded_on_time (scheduler, channel_id);
  1036 
  1037     if (program) {
  1038         slist = gmyth_string_list_new();
  1039         gmyth_string_list_append_char_array(slist, "STOP_RECORDING");
  1040 
  1041         gmyth_string_list_append_string(slist, program->title);        /* 0 */
  1042         gmyth_string_list_append_string(slist, program->subtitle);     /* 1 */
  1043         gmyth_string_list_append_string(slist, program->description);  /* 2 */
  1044         gmyth_string_list_append_string(slist, program->category);     /* 3 */
  1045         gmyth_string_list_append_string(slist, program->chanid);       /* 4 */
  1046         gmyth_string_list_append_string(slist, program->chanstr);      /* 5 */
  1047         gmyth_string_list_append_string(slist, program->chansign);     /* 6 */
  1048         gmyth_string_list_append_string(slist, program->channame);     /* 7 */
  1049         gmyth_string_list_append_string(slist, program->pathname);     /* 8 */
  1050         gmyth_string_list_append_int64(slist, program->filesize);      /* 9 */
  1051 
  1052         if (program->startts)
  1053             gmyth_string_list_append_int(slist, program->startts->tv_sec); /* 10 */
  1054         else
  1055             gmyth_string_list_append_int(slist, 0);
  1056 
  1057         if (program->endts)
  1058             gmyth_string_list_append_int(slist, program->endts->tv_sec);   /* 11 */
  1059         else
  1060             gmyth_string_list_append_int(slist, 0);
  1061 
  1062         gmyth_string_list_append_int(slist, program->duplicate);   /* 12 */
  1063         gmyth_string_list_append_int(slist, program->shareable);   /* 13 */
  1064         gmyth_string_list_append_int(slist, program->findid);      /* 14 */
  1065         gmyth_string_list_append_string(slist, program->hostname); /* 15 */
  1066         gmyth_string_list_append_int(slist, program->sourceid);    /* 16 */
  1067         gmyth_string_list_append_int(slist, program->cardid);      /* 17 */
  1068         gmyth_string_list_append_int(slist, program->inputid);     /* 18 */
  1069         gmyth_string_list_append_int(slist, program->recpriority); /* 19 */
  1070 
  1071         // recstatus == recording
  1072         gmyth_string_list_append_int(slist, -3);                   /* 20 */
  1073 
  1074         gmyth_string_list_append_int(slist, program->recordid);    /* 21 */
  1075         gmyth_string_list_append_int(slist, program->rectype);     /* 22 */
  1076         gmyth_string_list_append_int(slist, program->dupin);       /* 23 */
  1077         gmyth_string_list_append_int(slist, program->dupmethod);   /* 24 */
  1078 
  1079 
  1080         //fixme
  1081         program->recstartts->tv_sec -= (60*60);
  1082 
  1083         gmyth_string_list_append_int(slist, 
  1084                                      program->recstartts != NULL ?
  1085                                      program->recstartts->tv_sec : 0);   /* 26 */
  1086 
  1087         gmyth_string_list_append_int(slist, 
  1088                                      program->recendts != NULL ?
  1089                                      program->recendts->tv_sec : 0);    /* 27 */
  1090 
  1091         gmyth_string_list_append_int(slist, program->repeat);       /* 28 */
  1092         gmyth_string_list_append_int(slist, program->programflags); /* 29 */
  1093 
  1094         gmyth_string_list_append_char_array(slist, 
  1095                                             program->recgroup != NULL ?
  1096                                             program->recgroup->str : "Default");  /* 30 */
  1097 
  1098         gmyth_string_list_append_int(slist, program->chancommfree);         /* 31 */
  1099         gmyth_string_list_append_string(slist, program->chanOutputFilters); /* 32 */
  1100         gmyth_string_list_append_string(slist, program->seriesid);          /* 33 */
  1101         gmyth_string_list_append_string(slist, program->programid);         /* 34 */
  1102 
  1103         gmyth_string_list_append_int(slist,
  1104                                      program->lastmodified != NULL ?
  1105                                      program->lastmodified->tv_sec : 0);   /* 35 */
  1106 
  1107         gmyth_string_list_append_float(slist, program->stars); /* 36 */
  1108 
  1109         gmyth_string_list_append_int(slist,
  1110                                      program->originalAirDate != NULL ?
  1111                                      program->originalAirDate->tv_sec : 0); /* 37 */
  1112 
  1113         gmyth_string_list_append_int(slist, program->hasAirDate);  /* 38 */
  1114 
  1115         gmyth_string_list_append_char_array(slist,
  1116                                             program->playgroup != NULL ?
  1117                                             program->playgroup->str : "Default");  /* 39 */
  1118 
  1119         gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */
  1120         gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */
  1121 
  1122         gmyth_socket_sendreceive_stringlist(socket, slist);
  1123         res = (gmyth_string_list_get_int(slist, 0) == 1);
  1124 
  1125         g_object_unref (program);
  1126         g_object_unref (slist);
  1127     }
  1128 
  1129     g_object_unref (socket);
  1130     return res;
  1131 }
  1132 
  1133 
  1134 /** Notifies the backend of an update in the db.
  1135  * 
  1136  * @param record_id the id of the modified recording.
  1137  */
  1138 // fixme: put void and discovery record_id inside
  1139 static gboolean
  1140 update_backend (GMythScheduler * scheduler, 
  1141                 gint record_id)  
  1142 {
  1143     GMythSocket    *socket;
  1144     GMythStringList *strlist = gmyth_string_list_new();
  1145     GString        *datastr = g_string_new("RESCHEDULE_RECORDINGS ");
  1146     gboolean        ret = FALSE;
  1147 
  1148     g_string_append_printf(datastr, "%d", record_id);
  1149     gmyth_string_list_append_string(strlist, datastr);
  1150 
  1151     socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info);
  1152     if (socket != NULL) { 
  1153         ret = (gmyth_socket_sendreceive_stringlist(socket, strlist) > 0);
  1154         g_object_unref (socket);
  1155     } else {
  1156         g_warning("[%s] Connection to backend failed!", __FUNCTION__);
  1157     }
  1158 
  1159     g_string_free(datastr, TRUE);
  1160     g_object_unref(strlist);
  1161     return ret;
  1162 }
  1163 
  1164 void
  1165 gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info,
  1166                                           GByteArray * data)
  1167 {
  1168 }
  1169 
  1170 void
  1171 gmyth_recorded_info_free(RecordedInfo * info)
  1172 {
  1173     if (info->channel_id)
  1174         g_string_free (info->channel_id, TRUE);
  1175 
  1176     if (info->title != NULL)
  1177         g_string_free(info->title, TRUE);
  1178 
  1179     if (info->subtitle != NULL)
  1180         g_string_free(info->subtitle, TRUE);
  1181 
  1182     if (info->description != NULL)
  1183         g_string_free(info->description, TRUE);
  1184 
  1185     if (info->category != NULL)
  1186         g_string_free(info->category, TRUE);
  1187 
  1188     if (info->basename != NULL)
  1189         g_string_free(info->basename, TRUE);
  1190 
  1191     if (info != NULL)
  1192         g_free(info->start_time);
  1193 
  1194     if (info != NULL)
  1195         g_free(info->end_time);
  1196 
  1197     g_free(info);
  1198 }
  1199 
  1200 static void
  1201 free_recorded_info_item(gpointer data, gpointer user_data)
  1202 {
  1203     RecordedInfo   *info = (RecordedInfo *) data;
  1204 
  1205     gmyth_recorded_info_free(info);
  1206 }
  1207 
  1208 void
  1209 gmyth_recorded_info_list_free(GList * list)
  1210 {
  1211     g_return_if_fail(list != NULL);
  1212 
  1213     g_list_foreach(list, free_recorded_info_item, NULL);
  1214     g_list_free(list);
  1215 }
  1216 
  1217 void
  1218 gmyth_schedule_info_free(ScheduleInfo * info)
  1219 {
  1220 
  1221     g_return_if_fail(info != NULL);
  1222 
  1223     if (info->channel_id)
  1224         g_string_free (info->channel_id, TRUE);
  1225 
  1226     if (info->title != NULL)
  1227         g_string_free(info->title, TRUE);
  1228 
  1229     if (info->subtitle != NULL)
  1230         g_string_free(info->subtitle, TRUE);
  1231 
  1232     if (info->description != NULL)
  1233         g_string_free(info->description, TRUE);
  1234 
  1235     if (info->category != NULL)
  1236         g_string_free(info->category, TRUE);
  1237 
  1238     if (info != NULL)
  1239         g_free(info->start_time);
  1240 
  1241     if (info != NULL)
  1242         g_free(info->end_time);
  1243 
  1244     g_free(info);
  1245 }
  1246 
  1247 static void
  1248 free_schedule_info_item(gpointer data, gpointer user_data)
  1249 {
  1250     ScheduleInfo   *info = (ScheduleInfo *) data;
  1251 
  1252     gmyth_schedule_info_free(info);
  1253 }
  1254 
  1255 void
  1256 gmyth_schedule_info_list_free(GList * list)
  1257 {
  1258     g_return_if_fail(list != NULL);
  1259 
  1260     g_list_foreach(list, free_schedule_info_item, NULL);
  1261     g_list_free(list);
  1262 }