4 * @file gmyth/gmyth_scheduler.c
6 * @brief <p> The scheduler encapsulates all functions for browsing, scheduling
7 * and modifying the recorded content.
9 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
10 * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
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.
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.
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
34 #include <glib/gprintf.h>
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"
42 static void gmyth_scheduler_class_init(GMythSchedulerClass * klass);
43 static void gmyth_scheduler_init(GMythScheduler * object);
45 static void gmyth_scheduler_dispose(GObject * object);
46 static void gmyth_scheduler_finalize(GObject * object);
48 static gboolean update_backend(GMythScheduler * scheduler, gint record_id);
50 G_DEFINE_TYPE(GMythScheduler, gmyth_scheduler, G_TYPE_OBJECT)
51 static void gmyth_scheduler_class_init(GMythSchedulerClass * klass)
53 GObjectClass *gobject_class;
55 gobject_class = (GObjectClass *) klass;
57 gobject_class->dispose = gmyth_scheduler_dispose;
58 gobject_class->finalize = gmyth_scheduler_finalize;
62 gmyth_scheduler_init(GMythScheduler * sched)
67 sched->profile = g_string_new("");
71 sched->autoexpire = 0;
72 sched->autotranscode = 0;
73 sched->transcoder = 0;
75 sched->autocommflag = 0;
76 sched->autouserjob1 = 0;
77 sched->autouserjob2 = 0;
78 sched->autouserjob3 = 0;
79 sched->autouserjob4 = 0;
81 sched->startoffset = 0;
83 sched->maxepisodes = 0;
86 sched->recpriority = 0;
87 sched->recgroup = g_string_new("");
88 sched->playgroup = g_string_new("");
93 sched->search_type = g_string_new("");
94 sched->search_what = g_string_new("");
96 sched->msqlquery = gmyth_query_new();
100 gmyth_scheduler_dispose(GObject * object)
102 GMythScheduler *scheduler = GMYTH_SCHEDULER(object);
104 if (scheduler->backend_info) {
105 g_object_unref(scheduler->backend_info);
106 scheduler->backend_info = NULL;
109 if (scheduler->msqlquery) {
110 g_object_unref(scheduler->msqlquery);
111 scheduler->msqlquery = NULL;
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);
120 G_OBJECT_CLASS(gmyth_scheduler_parent_class)->dispose(object);
124 gmyth_scheduler_finalize(GObject * object)
126 g_signal_handlers_destroy(object);
128 G_OBJECT_CLASS(gmyth_scheduler_parent_class)->finalize(object);
131 /** Creates a new instance of GMythScheduler.
133 * @return a new instance of GMythScheduler.
136 gmyth_scheduler_new()
138 GMythScheduler *scheduler =
139 GMYTH_SCHEDULER(g_object_new(GMYTH_SCHEDULER_TYPE, NULL));
145 gmyth_scheduler_connect(GMythScheduler * scheduler,
146 GMythBackendInfo * backend_info)
148 return gmyth_scheduler_connect_with_timeout(scheduler, backend_info,
152 /** Connects to the Mysql database in the backend. The backend address
153 * is loaded from the GMythSettings instance.
155 * @param scheduler the GMythScheduler instance to be connected.
156 * @return true if connection was success, false if failed.
159 gmyth_scheduler_connect_with_timeout(GMythScheduler * scheduler,
160 GMythBackendInfo * backend_info,
164 g_return_val_if_fail(backend_info != NULL, FALSE);
166 if (scheduler->backend_info)
167 g_object_unref(scheduler->backend_info);
169 scheduler->backend_info = g_object_ref(backend_info);
171 if (scheduler->msqlquery == NULL) {
172 g_warning("[%s] GMythScheduler db initializing", __FUNCTION__);
173 scheduler->msqlquery = gmyth_query_new();
176 if (!gmyth_query_connect_with_timeout(scheduler->msqlquery,
177 scheduler->backend_info,
179 g_warning("[%s] Error while connecting to db", __FUNCTION__);
186 /** Disconnects from the Mysql database in the backend.
188 * @param scheduler the GMythScheduler instance to be disconnected
189 * @return true if disconnection was success, false if failed.
192 gmyth_scheduler_disconnect(GMythScheduler * scheduler)
196 if (scheduler->msqlquery != NULL) {
197 gmyth_query_disconnect(scheduler->msqlquery);
203 /** Retrieves from the backend Mysql database the list of recording schedules.
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.
210 gmyth_scheduler_get_schedule_list(GMythScheduler * scheduler,
211 GList ** schedule_list)
213 ScheduleInfo *schedule;
215 GString *query_str = g_string_new("");
216 gchar *date_time = NULL;
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;");
224 if (scheduler->msqlquery == NULL) {
225 g_warning("[%s] Scheduler db connection not initialized",
230 gmyth_query_process_statement(scheduler->msqlquery,
233 if (msql_res == NULL) {
234 g_warning("DB retrieval of schedule list failed");
239 *schedule_list = NULL;
241 while ((row = mysql_fetch_row(msql_res)) != NULL) {
242 schedule = g_new0(ScheduleInfo, 1);
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]);
251 * generate a time_t from a time and a date db field
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);
259 * generate a time_t from a time and a date db field
261 date_time = g_strdup_printf("%sT%s", row[6], row[5]);
262 schedule->end_time = gmyth_util_string_to_time_val(date_time);
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);
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);
279 schedule->seriesid = g_string_new (row[13]);
281 (*schedule_list) = g_list_append(*(schedule_list), schedule);
285 mysql_free_result(msql_res);
286 g_string_free(query_str, TRUE);
288 return (*schedule_list == NULL) ? 0 : g_list_length(*schedule_list);
291 /** Retrieves from the backend Mysql database the list of recorded programs.
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.
298 gmyth_scheduler_get_recorded_list(GMythScheduler * scheduler,
299 GList ** recorded_list)
301 RecordedInfo *record;
303 GString *query_str = g_string_new("");
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'");
312 if (scheduler->msqlquery == NULL) {
313 g_warning("[%s] Scheduler db connection not initialized",
319 gmyth_query_process_statement(scheduler->msqlquery,
322 if (msql_res == NULL) {
323 g_warning("DB retrieval of recording list failed");
328 (*recorded_list) = NULL;
330 while ((row = mysql_fetch_row(msql_res)) != NULL) {
331 record = g_new0(RecordedInfo, 1);
333 record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10);
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]);
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]);
348 (*recorded_list) = g_list_append((*recorded_list), record);
352 mysql_free_result(msql_res);
353 g_string_free(query_str, TRUE);
355 return (*recorded_list == NULL) ? 0 : g_list_length(*recorded_list);
359 gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler,
360 const gchar* basename)
362 RecordedInfo *record = NULL;
364 GString *query_str = g_string_new("");
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);
374 if (scheduler->msqlquery == NULL) {
375 g_warning("[%s] Scheduler db connection not initialized",
381 gmyth_query_process_statement(scheduler->msqlquery,
384 if (msql_res == NULL) {
385 g_warning("DB retrieval of recording list failed");
389 row = mysql_fetch_row(msql_res);
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]);
407 mysql_free_result(msql_res);
408 g_string_free(query_str, TRUE);
415 _set_value(GMythQuery * myth_query, char *field, gchar * value,
420 ("UPDATE record SET recordid = %d, %s = \"%s\" WHERE recordid = %d;",
421 rec_id, field, value, rec_id);
423 gmyth_query_process_statement(myth_query, query);
428 _set_int_value(GMythQuery * myth_query, char *field, gint value,
431 gchar *str_value = g_strdup_printf("%d", value);
433 _set_value(myth_query, field, str_value, rec_id);
438 gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler,
439 GMythProgramInfo *program,
440 GMythScheduleType type)
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);
458 if (gmyth_scheduler_add_schedule_full (scheduler, info, type))
460 if (!program->recstartts)
461 program->recstartts = g_new0 (GTimeVal, 1);
462 *program->recstartts = *info->start_time;
464 if (!program->recendts)
465 program->recendts = g_new0 (GTimeVal, 1);
466 *program->recendts = *info->end_time;
468 program->recordid = info->schedule_id;
472 gmyth_schedule_info_free (info);
478 gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler,
479 ScheduleInfo * schedule_info, GMythScheduleType type)
482 gchar *query_str = "INSERT record (recordid) VALUE (0);";
483 gchar *station = NULL;
488 if (scheduler->msqlquery == NULL) {
489 g_warning("[%s] Scheduler db connection not initialized",
495 gmyth_query_process_statement_with_increment(scheduler->msqlquery,
497 mysql_free_result(msql_res);
499 // Retrieves the station info
502 ("SELECT callsign FROM channel WHERE chanid = \"%s\";",
503 schedule_info->channel_id->str);
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__);
512 if ((row = mysql_fetch_row(msql_res)) != NULL) {
513 station = g_strdup(row[0]);
516 mysql_free_result(msql_res);
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,
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->
535 _set_value(scheduler->msqlquery, "enddate",
536 gmyth_util_time_to_string_only_date(schedule_info->
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),
545 // _set_int_value (scheduler->msqlquery, "findid",
546 // (gint)(schedule_info->start_time->tv_sec/60/60/24 + 719528),
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);
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,
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); // ?
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);
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);
588 schedule_info->schedule_id = rec_id;
590 /* Notify the backend of changes */
591 return update_backend(scheduler, rec_id);
594 /** Requests the Mysql database in the backend to add a new schedule.
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
603 gmyth_scheduler_add_schedule (GMythScheduler * scheduler,
604 ScheduleInfo * schedule_info)
606 return gmyth_scheduler_add_schedule_full (scheduler, schedule_info,
607 GMYTH_SCHEDULE_ONE_OCCURRENCE);
610 /** Requests the Mysql database in the backend to remove an existing schedule.
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
617 gmyth_scheduler_delete_schedule(GMythScheduler * scheduler, gint schedule_id)
621 GString *query_str = NULL;
623 g_return_val_if_fail (scheduler != NULL, FALSE);
626 if (scheduler->msqlquery == NULL) {
627 g_warning("[%s] Scheduler db connection not initialized",
632 query_str = g_string_new("");
633 g_string_printf(query_str,
634 "DELETE FROM record WHERE recordid=%d", schedule_id);
637 gmyth_query_process_statement(scheduler->msqlquery,
641 mysql_free_result(msql_res);
642 g_string_free(query_str, TRUE);
644 // Notify the backend of the changes
645 return update_backend(scheduler, schedule_id);
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
657 gmyth_scheduler_add_exception (GMythScheduler *scheduler, gint schedule_id,
658 ScheduleInfo *exception_info)
662 g_return_val_if_fail (scheduler != NULL, FALSE);
663 g_return_val_if_fail (exception_info != NULL, FALSE);
665 exception_info->parentid = schedule_id;
666 res = gmyth_scheduler_add_schedule_full (scheduler, exception_info, GMYTH_SCHEDULE_EXCEPTION);
671 /** Requests the Mysql database in the backend to remove an existing recorded item.
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
678 gmyth_scheduler_delete_recorded(GMythScheduler * scheduler, gint record_id)
683 GString *query_str = g_string_new("");
687 if (scheduler->msqlquery == NULL) {
688 g_warning("[%s] Scheduler db connection not initialized",
692 // ========================================
693 g_string_printf(query_str,
694 "DELETE FROM recorded WHERE recordid=%d", record_id);
696 // FIXME: Mythtv implementation runs also: DELETE FROM oldfind WHERE
700 gmyth_query_process_statement(scheduler->msqlquery,
703 mysql_free_result(msql_res);
704 g_string_free(query_str, TRUE);
706 // Notify the backend of the changes
707 return update_backend(scheduler, record_id);
711 gboolean gmyth_scheduler_was_recorded_before(GMythScheduler* scheduler, gint channel_id,
715 GString *query_str = g_string_new("");
718 g_string_printf(query_str, "SELECT callsign FROM channel "
719 "WHERE chanid = \"%d\"", channel_id);
721 msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
724 MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
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;
742 gboolean gmyth_scheduler_reactivate_schedule(GMythScheduler* scheduler, gint channel_id,
747 GString *query_str = g_string_new("");
750 g_string_printf(query_str, "SELECT callsign FROM channel "
751 "WHERE chanid = \"%d\"", channel_id);
753 msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
755 MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
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);
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
782 gmyth_scheduler_get_recorded_on_time(GMythScheduler* scheduler,
786 GMythProgramInfo *proginfo = NULL;
787 GString *query_str = g_string_new("");
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);
806 gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
809 MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
812 proginfo = gmyth_program_info_new();
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]);
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]);
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);
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);
835 if (msql_row[17] == NULL) {
836 proginfo->originalAirDate = 0;
837 proginfo->hasAirDate = FALSE;
839 proginfo->originalAirDate = gmyth_util_string_to_time_val(msql_row[17]);
840 proginfo->hasAirDate = TRUE;
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);
847 proginfo->playgroup = g_string_new(msql_row[21]);
848 proginfo->recpriority = (gint) g_ascii_strtoull(msql_row[22], NULL, 10);
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);
857 proginfo->recpriority2 = 0;
859 g_string_printf(query_str,
860 "SELECT dupmethod,dupin,parentid,type "
861 "FROM record WHERE recordid = \"%d\"", proginfo->recordid);
864 gmyth_query_process_statement(scheduler->msqlquery,
868 MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
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;
879 g_string_printf(query_str,
880 "SELECT sourceid,cardid,cardinputid,shareable "
884 gmyth_query_process_statement(scheduler->msqlquery,
888 MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
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;
897 proginfo->shareable = 0;
906 g_string_free(query_str, TRUE);
910 /** Retrieves an existing recorded item information from database. The information
911 * is used to fill the returned GMythProgramInfo.
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.
920 gmyth_scheduler_get_recorded(GMythScheduler * scheduler,
921 GString * channel, GTimeVal * starttime)
924 GMythProgramInfo *proginfo = NULL;
925 GString *query_str = g_string_new("");
927 gmyth_util_time_to_string_from_time_val(starttime);
931 gmyth_debug("[%s] channel: %s", __FUNCTION__, channel->str);
933 if (scheduler->msqlquery == NULL) {
934 g_warning("[%s] Scheduler db connection not initialized",
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);
953 gmyth_query_process_statement(scheduler->msqlquery,
956 if (msql_res /* && query.size() > 0 */ ) {
957 MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
960 proginfo = gmyth_program_info_new();
962 proginfo->chanid = g_string_new(msql_row[0]);
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]);
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]);
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);
984 proginfo->lastmodified =
985 gmyth_util_string_to_time_val(msql_row[14]);
986 proginfo->stars = g_ascii_strtod(msql_row[15], NULL);
988 (gint) g_ascii_strtoull(msql_row[16], NULL, 10);
990 if (msql_row[17] == NULL) {
991 proginfo->originalAirDate = 0;
992 proginfo->hasAirDate = FALSE;
994 proginfo->originalAirDate =
995 gmyth_util_string_to_time_val(msql_row[17]);
996 proginfo->hasAirDate = TRUE;
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();
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);
1012 proginfo->pathname = g_string_new(g_strdup(msql_row[25]));
1014 gmyth_debug("One program info loaded from mysql database\n");
1018 mysql_free_result(msql_res);
1019 g_string_free(query_str, TRUE);
1026 gmyth_scheduler_stop_recording (GMythScheduler * scheduler,
1029 GMythProgramInfo *program;
1030 GMythSocket *socket;
1031 gboolean res = FALSE;
1032 GMythStringList *slist;
1034 socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info);
1035 program = gmyth_scheduler_get_recorded_on_time (scheduler, channel_id);
1038 slist = gmyth_string_list_new();
1039 gmyth_string_list_append_char_array(slist, "STOP_RECORDING");
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 */
1052 if (program->startts)
1053 gmyth_string_list_append_int(slist, program->startts->tv_sec); /* 10 */
1055 gmyth_string_list_append_int(slist, 0);
1058 gmyth_string_list_append_int(slist, program->endts->tv_sec); /* 11 */
1060 gmyth_string_list_append_int(slist, 0);
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 */
1071 // recstatus == recording
1072 gmyth_string_list_append_int(slist, -3); /* 20 */
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 */
1081 program->recstartts->tv_sec -= (60*60);
1083 gmyth_string_list_append_int(slist,
1084 program->recstartts != NULL ?
1085 program->recstartts->tv_sec : 0); /* 26 */
1087 gmyth_string_list_append_int(slist,
1088 program->recendts != NULL ?
1089 program->recendts->tv_sec : 0); /* 27 */
1091 gmyth_string_list_append_int(slist, program->repeat); /* 28 */
1092 gmyth_string_list_append_int(slist, program->programflags); /* 29 */
1094 gmyth_string_list_append_char_array(slist,
1095 program->recgroup != NULL ?
1096 program->recgroup->str : "Default"); /* 30 */
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 */
1103 gmyth_string_list_append_int(slist,
1104 program->lastmodified != NULL ?
1105 program->lastmodified->tv_sec : 0); /* 35 */
1107 gmyth_string_list_append_float(slist, program->stars); /* 36 */
1109 gmyth_string_list_append_int(slist,
1110 program->originalAirDate != NULL ?
1111 program->originalAirDate->tv_sec : 0); /* 37 */
1113 gmyth_string_list_append_int(slist, program->hasAirDate); /* 38 */
1115 gmyth_string_list_append_char_array(slist,
1116 program->playgroup != NULL ?
1117 program->playgroup->str : "Default"); /* 39 */
1119 gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */
1120 gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */
1122 gmyth_socket_sendreceive_stringlist(socket, slist);
1123 res = (gmyth_string_list_get_int(slist, 0) == 1);
1125 g_object_unref (program);
1126 g_object_unref (slist);
1129 g_object_unref (socket);
1134 /** Notifies the backend of an update in the db.
1136 * @param record_id the id of the modified recording.
1138 // fixme: put void and discovery record_id inside
1140 update_backend (GMythScheduler * scheduler,
1143 GMythSocket *socket;
1144 GMythStringList *strlist = gmyth_string_list_new();
1145 GString *datastr = g_string_new("RESCHEDULE_RECORDINGS ");
1146 gboolean ret = FALSE;
1148 g_string_append_printf(datastr, "%d", record_id);
1149 gmyth_string_list_append_string(strlist, datastr);
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);
1156 g_warning("[%s] Connection to backend failed!", __FUNCTION__);
1159 g_string_free(datastr, TRUE);
1160 g_object_unref(strlist);
1165 gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info,
1171 gmyth_recorded_info_free(RecordedInfo * info)
1173 if (info->channel_id)
1174 g_string_free (info->channel_id, TRUE);
1176 if (info->title != NULL)
1177 g_string_free(info->title, TRUE);
1179 if (info->subtitle != NULL)
1180 g_string_free(info->subtitle, TRUE);
1182 if (info->description != NULL)
1183 g_string_free(info->description, TRUE);
1185 if (info->category != NULL)
1186 g_string_free(info->category, TRUE);
1188 if (info->basename != NULL)
1189 g_string_free(info->basename, TRUE);
1192 g_free(info->start_time);
1195 g_free(info->end_time);
1201 free_recorded_info_item(gpointer data, gpointer user_data)
1203 RecordedInfo *info = (RecordedInfo *) data;
1205 gmyth_recorded_info_free(info);
1209 gmyth_recorded_info_list_free(GList * list)
1211 g_return_if_fail(list != NULL);
1213 g_list_foreach(list, free_recorded_info_item, NULL);
1218 gmyth_schedule_info_free(ScheduleInfo * info)
1221 g_return_if_fail(info != NULL);
1223 if (info->channel_id)
1224 g_string_free (info->channel_id, TRUE);
1226 if (info->title != NULL)
1227 g_string_free(info->title, TRUE);
1229 if (info->subtitle != NULL)
1230 g_string_free(info->subtitle, TRUE);
1232 if (info->description != NULL)
1233 g_string_free(info->description, TRUE);
1235 if (info->category != NULL)
1236 g_string_free(info->category, TRUE);
1239 g_free(info->start_time);
1242 g_free(info->end_time);
1248 free_schedule_info_item(gpointer data, gpointer user_data)
1250 ScheduleInfo *info = (ScheduleInfo *) data;
1252 gmyth_schedule_info_free(info);
1256 gmyth_schedule_info_list_free(GList * list)
1258 g_return_if_fail(list != NULL);
1260 g_list_foreach(list, free_schedule_info_item, NULL);