/** * GMyth Library * * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. * @author Renato Filho * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "gmyth-dbus-common.h" #include "gmyth-dbus-server.h" #define MYTH_DEFAULT_DB "mythconverg" enum { SHUTDOWN, LAST_SIGNAL }; enum { GMYTH_DBUS_ERROR_MYTHTV, GMYTH_DBUS_ERROR_CONNECTION, GMYTH_DBUS_ERROR_EPG, GMYTH_DBUS_ERROR_SCHEDULE }; #define GMYTH_DBUS_ERROR gmyth_dbus_error_quark () GQuark gmyth_dbus_error_quark (void) { return g_quark_from_static_string ("gmyth-dbus-error-quark"); } typedef struct _GMythDbusServerPrivate GMythDbusServerPrivate; struct _GMythDbusServerPrivate { GMythBackendInfo *myth_backend; gboolean connected; GMythEPG *myth_epg; GMythScheduler *myth_scheduler; guint shutdown_cb_id; }; #define GMYTH_DBUS_SERVER_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GMYTH_DBUS_SERVER_TYPE, GMythDbusServerPrivate)) static void gmyth_dbus_server_class_init (GMythDbusServerClass *klass); static void gmyth_dbus_server_init (GMythDbusServer *self); static void gmyth_dbus_server_dispose (GObject *object); static void gmyth_dbus_server_finalize (GObject *object); static void gmyth_dbus_server_cancel_shutdown (GMythDbusServer *self); static gboolean gmyth_dbus_server_shutdown_cb (GMythDbusServer *self); /* Dbus */ static gboolean gmyth_dbus_server_connect (GObject *obj, const gchar *host, gint port, const gchar *user, const gchar *password, GError **error); static gboolean gmyth_dbus_server_check_db_connection (GObject *self, const gchar *host, gint port, const gchar *user, const gchar *password, GError **error); static gboolean gmyth_dbus_server_check_server_connection (GObject *obj, const gchar *host, gint port, GError **error); static gboolean gmyth_dbus_server_get_channel_list (GObject *obj, GPtrArray **channels, GError **error); static gboolean gmyth_dbus_server_get_channel_info (GObject *obj, gint channel_id, GValueArray **info, GError **error); static gboolean gmyth_dbus_server_file_exists (GObject *obj, const gchar *file_name, gboolean *exists, GError **error); static gboolean gmyth_dbus_server_get_recorded_list (GObject *obj, GPtrArray **channels, GError **error); static gboolean gmyth_dbus_server_get_recorded_info (GObject *obj, const gchar *basename, GValueArray **info, GError **error); static gboolean gmyth_dbus_server_get_program_list (GObject *obj, gint channel_id, const gchar *start_time, const gchar *end_time, GPtrArray **program_list, GError **error); static gboolean gmyth_dbus_server_get_schedule_list (GObject *obj, GPtrArray **schedule_list, GError **error); static gboolean gmyth_dbus_server_connected (GObject *obj, gboolean *status, GError **error); static gboolean gmyth_dbus_server_disconnect (GObject *obj, GError **error); static void gmyth_dbus_server_internal_disconnect (GObject *obj, GError **error); static gboolean gmyth_dbus_server_get_server_info (GObject *obj, guint64 *total_space, guint64 *used_space, guint64 *free_space, GError **error); static gboolean gmyth_dbus_server_get_thumbnail (GObject *obj, const gchar *uri, GByteArray **image, GError **error); static gboolean gmyth_dbus_server_get_channel_icon (GObject *obj, guint channel_id, GByteArray **icon, GError **error); static gboolean gmyth_dbus_server_stop_recording (GObject *obj, guint channel_id, gboolean *result, GError **error); static gboolean gmyth_dbus_server_add_schedule (GObject *obj, gint channel_id, const gchar *program_id, const gchar *start_time, const gchar *end_time, gboolean recurring, const gchar *description, guint *schedule_id, GError **error); static gboolean gmyth_dbus_server_add_exception (GObject *obj, guint schedule_id, gint channel_id, const gchar *program_id, const gchar *start_time, const gchar *end_time, const gchar *description, GError **error); static gboolean gmyth_dbus_server_remove_schedule (GObject *obj, guint schedule_id, GError **error); #include "gmyth-dbus-server-glue.h" static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (GMythDbusServer, gmyth_dbus_server, G_TYPE_OBJECT); static void gmyth_dbus_server_class_init (GMythDbusServerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (GMythDbusServerPrivate)); object_class->dispose = gmyth_dbus_server_dispose; object_class->finalize = gmyth_dbus_server_finalize; signals[SHUTDOWN] = g_signal_new ("shutdown", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); dbus_g_object_type_install_info (GMYTH_DBUS_SERVER_TYPE, &dbus_glib_gmyth_dbus_server_object_info); } static void gmyth_dbus_server_init (GMythDbusServer *self) { } static void gmyth_dbus_server_dispose (GObject *object) { G_OBJECT_CLASS (gmyth_dbus_server_parent_class)->dispose (object); } static void gmyth_dbus_server_finalize (GObject *object) { G_OBJECT_CLASS (gmyth_dbus_server_parent_class)->finalize (object); } static gboolean gmyth_dbus_server_connect_epg (GMythDbusServer *server, GError **error) { GMythDbusServerPrivate *priv; priv = GMYTH_DBUS_SERVER_GET_PRIVATE (server); if (!priv->connected) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_CONNECTION, _("Not connected")); gmyth_debug ("Not connected with MythTV Server"); return FALSE; } if (!priv->myth_epg) { priv->myth_epg = gmyth_epg_new(); if (!gmyth_epg_connect (priv->myth_epg, priv->myth_backend)) { g_object_unref (priv->myth_epg); priv->myth_epg = NULL; g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_EPG, _("Fail to connect with EPG")); gmyth_debug ("Fail to connected with EPG"); return FALSE; } } gmyth_debug ("Connected EPG"); return TRUE; } static gboolean gmyth_dbus_server_connect_scheduler (GMythDbusServer *server, GError **error) { GMythDbusServerPrivate *priv; priv = GMYTH_DBUS_SERVER_GET_PRIVATE (server); if (!priv->connected) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_CONNECTION, _("Not connected")); gmyth_debug ("Not connected with MythTV Server"); return FALSE; } if (!priv->myth_scheduler) { priv->myth_scheduler = gmyth_scheduler_new (); if (!gmyth_scheduler_connect (priv->myth_scheduler, priv->myth_backend)) { g_object_unref (priv->myth_scheduler); priv->myth_scheduler = NULL; g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_SCHEDULE, _("Fail to connect with Schedule")); gmyth_debug (_("Fail to connect with Schedule")); return FALSE; } } gmyth_debug ("Connected with Schedule"); return TRUE; } static gboolean gmyth_dbus_server_connect (GObject *obj, const gchar *host, gint port, const gchar *user, const gchar *password, GError **error) { GMythSocket *s; GMythDbusServerPrivate *priv; gmyth_debug (""); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); if (priv->connected) { gmyth_debug ("Release Old connection"); gmyth_dbus_server_internal_disconnect (obj, NULL); } gmyth_dbus_server_cancel_shutdown (GMYTH_DBUS_SERVER (obj)); priv->myth_backend = gmyth_backend_info_new_full (host, user, password, MYTH_DEFAULT_DB, port); s = gmyth_backend_info_get_connected_socket (priv->myth_backend); if (s) { gmyth_debug ("Connected"); priv->connected = TRUE; g_object_unref (s); } else { gmyth_debug ("Fail to connect with MythTVServer"); priv->connected = FALSE; g_object_unref (priv->myth_backend); priv->myth_backend = NULL; g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_CONNECTION, _("Fail to connect with backend")); } return priv->connected; } static gboolean gmyth_dbus_server_connected (GObject *obj, gboolean *status, GError **error) { GMythDbusServerPrivate *priv; gmyth_debug (""); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); if (priv->myth_backend) *status = TRUE; else *status = FALSE; return TRUE; } static gboolean gmyth_dbus_server_disconnect (GObject *obj, GError **error) { GMythDbusServerPrivate *priv; priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); if (priv->connected) { gmyth_dbus_server_internal_disconnect (obj, error); priv->shutdown_cb_id = g_timeout_add (60000, (GSourceFunc) gmyth_dbus_server_shutdown_cb, obj); } return TRUE; } static void gmyth_dbus_server_internal_disconnect (GObject *obj, GError **error) { GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); if (priv->myth_epg) { g_object_unref (priv->myth_epg); priv->myth_epg = NULL; } if (priv->myth_backend) { g_object_unref (priv->myth_backend); priv->myth_backend = NULL; } if (priv->myth_scheduler) { g_object_unref (priv->myth_scheduler); priv->myth_scheduler = NULL; } priv->connected = FALSE; } static gboolean gmyth_dbus_server_get_server_info (GObject *obj, guint64 *total_space, guint64 *used_space, guint64 *free_space, GError **error) { GMythBackendDetails *details; GMythDbusServerPrivate *priv; gboolean ret = FALSE; GMythSocket *socket; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend != NULL, FALSE); socket = gmyth_backend_info_get_connected_socket (priv->myth_backend); if (!socket) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_MYTHTV, _("MythTv not avaliable")); return FALSE; } details = NULL; gmyth_util_get_backend_details (socket, &details); if (details) { *total_space = details->total_space; *used_space = details->used_space; *free_space = *total_space - *used_space; gmyth_util_backend_details_free (details); ret = TRUE; } else { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_MYTHTV, _("Fail to get MythTv details")); } g_object_unref (socket); return ret; } static void gmyth_dbus_server_parse_channel_info (GMythChannelInfo *info, GValue *val) { dbus_g_type_struct_set (val, 0, info->channel_ID, 1, info->channel_num->str, 2, info->channel_name->str, 3, info->channel_icon->str, G_MAXUINT); } static gboolean gmyth_dbus_server_get_channel_info (GObject *obj, gint channel_id, GValueArray **info, GError **error) { GType ch_type; GMythChannelInfo *ch_info; GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend != NULL, FALSE); if (!gmyth_dbus_server_connect_epg (GMYTH_DBUS_SERVER (obj), error)) { return FALSE; } ch_type = GMYTH_DBUS_CHANNEL_G_TYPE; ch_info = gmyth_epg_get_channel_info (priv->myth_epg, channel_id); if (ch_info) { GValue v = { 0, }; g_value_init (&v, ch_type); g_value_take_boxed (&v, dbus_g_type_specialized_construct (ch_type)); gmyth_dbus_server_parse_channel_info (ch_info, &v); *info = g_value_get_boxed (&v); return TRUE; } else { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_EPG, _("no channel info avaliable")); } return FALSE; } static gboolean gmyth_dbus_server_get_channel_list (GObject *obj, GPtrArray **channels, GError **error) { GList *lst; GList *walk; int len; GType ch_type; GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend != NULL, FALSE); if (!gmyth_dbus_server_connect_epg (GMYTH_DBUS_SERVER (obj), error)) return FALSE; lst = NULL; len = gmyth_epg_get_channel_list (priv->myth_epg, &lst); *channels = g_ptr_array_sized_new (len); ch_type = GMYTH_DBUS_CHANNEL_G_TYPE; for (walk = lst; walk != NULL; walk = walk->next) { GValue ch = { 0, }; GMythChannelInfo *data; data = (GMythChannelInfo *) walk->data; g_value_init (&ch, ch_type); g_value_take_boxed (&ch, dbus_g_type_specialized_construct (ch_type)); gmyth_dbus_server_parse_channel_info (data, &ch); g_ptr_array_add (*channels, g_value_get_boxed (&ch)); } gmyth_free_channel_list (lst); return TRUE; } static gboolean gmyth_dbus_server_file_exists (GObject *obj, const gchar *file_name, gboolean *exists, GError **error) { GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend, FALSE); *exists = gmyth_util_file_exists (priv->myth_backend, file_name); return TRUE; } static gboolean gmyth_dbus_server_get_program_list (GObject *obj, gint channel_id, const gchar *start_time, const gchar *end_time, GPtrArray **programs, GError **error) { GList *list; GList *walk; gint len; GType program_type; GTimeVal start_time_val; GTimeVal end_time_val; GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend, FALSE); if (!gmyth_dbus_server_connect_epg (GMYTH_DBUS_SERVER (obj), error)) return FALSE; g_time_val_from_iso8601 (start_time, &start_time_val); g_time_val_from_iso8601 (end_time, &end_time_val); list = NULL; len = gmyth_epg_get_program_list (priv->myth_epg, &list, channel_id, &start_time_val, &end_time_val); *programs = g_ptr_array_sized_new (len); program_type = GMYTH_DBUS_PROGRAM_G_TYPE; for (walk = list; walk != NULL; walk = walk->next) { GValue program = { 0, }; gchar *start_str; gchar *end_str; GMythProgramInfo *data; data = (GMythProgramInfo *) walk->data; if (!data) continue; g_value_init (&program, program_type); g_value_take_boxed (&program, dbus_g_type_specialized_construct (program_type)); start_str = g_time_val_to_iso8601 (data->startts); end_str = g_time_val_to_iso8601 (data->endts); dbus_g_type_struct_set (&program, 0, data->channel_id, 1, start_str, 2, end_str, 3, data->title->str, 4, data->subtitle->str, 5, data->description->str, 6, data->category->str, G_MAXUINT); g_ptr_array_add (*programs, g_value_get_boxed (&program)); g_free (start_str); g_free (end_str); } if (list) gmyth_free_program_list (list); g_debug ("%s:%d", __FUNCTION__, __LINE__); return TRUE; } static void gmyth_dbus_server_parse_recorded_info (RecordedInfo *info, GValue *val) { gchar *start_str; gchar *end_str; start_str = g_time_val_to_iso8601 (info->start_time); end_str = g_time_val_to_iso8601 (info->end_time); dbus_g_type_struct_set (val, 0, info->record_id, 1, info->program_id->str, 2, info->channel_id, 3, start_str, 4, end_str, 5, info->title->str, 6, info->subtitle->str, 7, info->description->str, 8, info->category->str, 9, info->basename->str, 10, info->filesize, G_MAXUINT); g_free (start_str); g_free (end_str); } static gboolean gmyth_dbus_server_get_recorded_info (GObject *obj, const gchar *basename, GValueArray **info, GError **error) { GType record_type; GMythDbusServerPrivate *priv; RecordedInfo *record_info; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend, FALSE); if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error)) return FALSE; record_type = GMYTH_DBUS_RECORD_G_TYPE; record_info = gmyth_scheduler_get_recorded_info (priv->myth_scheduler, basename); if (record_info) { GValue r = { 0, }; g_value_init (&r, record_type); g_value_take_boxed (&r, dbus_g_type_specialized_construct (record_type)); gmyth_dbus_server_parse_recorded_info (record_info, &r); gmyth_recorded_info_free (record_info); *info = g_value_get_boxed (&r); return TRUE; } else { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_EPG, _("no record info avaliable")); } return FALSE; } static gboolean gmyth_dbus_server_get_recorded_list (GObject *obj, GPtrArray **records, GError **error) { GList *list; GList *walk; gint len; GType record_type; GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend != NULL, FALSE); if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error)) return FALSE; len = gmyth_scheduler_get_recorded_list (priv->myth_scheduler, &list); record_type = GMYTH_DBUS_RECORD_G_TYPE; *records = g_ptr_array_sized_new (len); for (walk = list; walk != NULL; walk = walk->next) { GValue record = { 0, }; RecordedInfo *data; data = (RecordedInfo *) walk->data; g_value_init (&record, record_type); g_value_take_boxed (&record, dbus_g_type_specialized_construct (record_type)); gmyth_dbus_server_parse_recorded_info (data, &record); g_ptr_array_add (*records, g_value_get_boxed (&record)); //g_value_unset (&record); } gmyth_recorded_info_list_free (list); return TRUE; } static gboolean gmyth_dbus_server_get_schedule_list (GObject *obj, GPtrArray **schedules, GError **error) { GList *list; GList *walk; gint len; GType schedule_type; GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend, FALSE); if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error)) return FALSE; len = gmyth_scheduler_get_schedule_list (priv->myth_scheduler, &list); *schedules = g_ptr_array_sized_new (len); schedule_type = GMYTH_DBUS_SCHEDULE_G_TYPE; for (walk = list; walk != NULL; walk = walk->next) { GValue schedule = { 0, }; ScheduleInfo *data; gchar *start_str_time; gchar *end_str_time; data = (ScheduleInfo *) walk->data; g_value_init (&schedule, schedule_type); g_value_take_boxed (&schedule, dbus_g_type_specialized_construct (schedule_type)); start_str_time = g_time_val_to_iso8601 (data->start_time); end_str_time = g_time_val_to_iso8601 (data->end_time); dbus_g_type_struct_set (&schedule, 0, data->schedule_id, 1, data->program_id->str, 2, data->channel_id, 3, start_str_time, 4, end_str_time, 5, data->title->str, 6, data->subtitle->str, 7, data->description->str, 8, data->category->str, 9, data->type, G_MAXUINT); g_ptr_array_add (*schedules, g_value_get_boxed (&schedule)); g_free (start_str_time); g_free (end_str_time); } gmyth_schedule_info_list_free (list); return TRUE; } static gboolean gmyth_dbus_server_get_thumbnail (GObject *obj, const gchar *uri, GByteArray **image, GError **error) { GMythFileTransfer *file_transfer; glong filesize; GMythFileReadResult result; GMythDbusServerPrivate *priv; priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); file_transfer = NULL; g_return_val_if_fail (priv->myth_backend, FALSE); if (!gmyth_util_file_exists (priv->myth_backend, uri)) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_MYTHTV, _("File not exists")); goto fail; } file_transfer = gmyth_file_transfer_new (priv->myth_backend); if (!gmyth_file_transfer_open (file_transfer, uri)) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_MYTHTV, _("Fail to open file")); goto fail; } filesize = gmyth_file_transfer_get_filesize (file_transfer); if (filesize <= 0) goto fail; *image = g_byte_array_new (); result = gmyth_file_transfer_read (file_transfer, *image, filesize, FALSE); if (result == GMYTH_FILE_READ_ERROR) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_MYTHTV, _("Fail to read file")); goto fail; } gmyth_file_transfer_close (file_transfer); g_object_unref (file_transfer); if (filesize > (*image)->len) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_MYTHTV, _("Empty file")); goto fail; } return TRUE; fail: if (*image) g_byte_array_free (*image, TRUE); g_object_unref(file_transfer); return FALSE; } static gboolean gmyth_dbus_server_get_channel_icon (GObject *obj, guint channel_id, GByteArray **icon, GError **error) { GMythChannelInfo *channel = NULL; guint8 *icon_data; guint icon_length; GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend, FALSE); channel = gmyth_epg_get_channel_info (priv->myth_epg, (gint) channel_id); *icon = NULL; if (channel == NULL) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_MYTHTV, _("Invalid channel")); return FALSE; } if (!gmyth_epg_channel_has_icon(priv->myth_epg, channel)) { gmyth_channel_info_free (channel); g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_MYTHTV, _("Channel does not have icon available")); return FALSE; } icon_data = NULL; icon_length = 0; if (!gmyth_epg_channel_get_icon (priv->myth_epg, channel, &icon_data, &icon_length)) { gmyth_channel_info_free (channel); g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_MYTHTV, _("Could not get channel icon for channel id = %u"), channel_id); return FALSE; } *icon = g_byte_array_sized_new (icon_length); *icon = g_byte_array_append (*icon, icon_data, icon_length); g_free (icon_data); gmyth_channel_info_free(channel); return TRUE; } static gboolean gmyth_dbus_server_stop_recording (GObject *obj, guint channel_id, gboolean *result, GError **error) { gboolean ret = FALSE; GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend, FALSE); if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error)) return FALSE; ret = gmyth_scheduler_stop_recording (priv->myth_scheduler, channel_id); return ret; } static ScheduleInfo* gmyth_dbus_server_new_schedule_info (const gchar* description, guint channel_id, const gchar* program_id, GTimeVal *start_vtime, GTimeVal *end_vtime) { ScheduleInfo *new_sched_info; new_sched_info = g_new0(ScheduleInfo, 1); /* record_id == -1 for generating a new id */ new_sched_info->schedule_id = -1; new_sched_info->channel_id = channel_id; new_sched_info->program_id = g_string_new (program_id); new_sched_info->start_time = g_new0 (GTimeVal, 1); *new_sched_info->start_time = *start_vtime; new_sched_info->end_time = g_new0 (GTimeVal, 1); *new_sched_info->end_time = *end_vtime; /* TODO: there is no frequency field */ /*new_sched_info->frequency = -1;*/ if (description != NULL) { /* FIXME: description parameter is used as title and description */ new_sched_info->title = g_string_new(description); new_sched_info->description = g_string_new(description); } return new_sched_info; } static gboolean gmyth_dbus_server_add_schedule (GObject *obj, gint channel_id, const gchar *program_id, const gchar *start_time, const gchar *end_time, gboolean recurring, const gchar *description, guint *schedule_id, GError **error) { ScheduleInfo *sch_info; GTimeVal start_vtime; GTimeVal end_vtime; GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); *schedule_id = 0; g_return_val_if_fail (priv->myth_backend, FALSE); if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error)) return FALSE; g_time_val_from_iso8601 (start_time, &start_vtime); g_time_val_from_iso8601 (end_time, &end_vtime); sch_info = gmyth_dbus_server_new_schedule_info (description, channel_id, program_id, &start_vtime, &end_vtime); if (sch_info != NULL) { GMythScheduleType type; GTimeVal t_now; gboolean has_record; type = (recurring ? GMYTH_SCHEDULE_ALL_OCCURRENCES : GMYTH_SCHEDULE_ONE_OCCURRENCE); g_get_current_time (&t_now); has_record = gmyth_scheduler_was_recorded_before (priv->myth_scheduler, channel_id, (time_t) start_vtime.tv_sec); if ((t_now.tv_sec >= start_vtime.tv_sec) && (t_now.tv_sec <= end_vtime.tv_sec) && has_record) { GMythSocket *socket; gboolean res = FALSE; socket = gmyth_backend_info_get_connected_socket (priv->myth_backend); res = gmyth_scheduler_reactivate_schedule(priv->myth_scheduler, channel_id, (time_t) start_vtime.tv_sec); if (res) { GMythStringList *slist = gmyth_string_list_new(); gmyth_string_list_append_char_array(slist, "RESCHEDULE_RECORDINGS 0"); gmyth_socket_sendreceive_stringlist(socket, slist); res = (gmyth_string_list_get_int(slist, 0) == 1); g_object_unref(slist); } g_object_unref(socket); return res; } else { if (!gmyth_scheduler_add_schedule_full (priv->myth_scheduler, sch_info, type)) { g_warning("Could not add schedule entry"); return FALSE; } (*schedule_id) = sch_info->schedule_id; gmyth_schedule_info_free (sch_info); return TRUE; } } return FALSE; } static gboolean gmyth_dbus_server_add_exception (GObject *obj, guint schedule_id, gint channel_id, const gchar *program_id, const gchar *start_time, const gchar *end_time, const gchar *description, GError **error) { ScheduleInfo *sch_info; GTimeVal start_vtime; GTimeVal end_vtime; GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend, FALSE); if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error)) return FALSE; g_time_val_from_iso8601 (start_time, &start_vtime); g_time_val_from_iso8601 (end_time, &end_vtime); sch_info = gmyth_dbus_server_new_schedule_info (description, channel_id, program_id, &start_vtime, &end_vtime); if (sch_info != NULL) { if (!gmyth_scheduler_add_exception (priv->myth_scheduler, schedule_id, sch_info)) { g_warning ("Could not add schedule exception"); gmyth_schedule_info_free (sch_info); return FALSE; } gmyth_schedule_info_free (sch_info); return TRUE; } return FALSE; } static gboolean gmyth_dbus_server_remove_schedule (GObject *obj, guint schedule_id, GError **error) { GMythDbusServerPrivate *priv; g_debug ("%s:%d", __FUNCTION__, __LINE__); priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj); g_return_val_if_fail (priv->myth_backend, FALSE); if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error)) return FALSE; return gmyth_scheduler_delete_schedule (priv->myth_scheduler, schedule_id); } GMythDbusServer* gmyth_dbus_server_start_dbus_service (void) { GError *error = NULL; DBusGProxy *proxy; DBusGConnection *bus; guint request_ret; GMythDbusServer *self; self = g_object_new (GMYTH_DBUS_SERVER_TYPE, NULL); g_return_val_if_fail (self, FALSE); /* TODO: should verify if this service was already started */ /* connect to session bus */ bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); if (bus == NULL) { g_warning ("Could not connect to dbus: %s", error->message); g_error_free (error); goto fail; } /* register dbus object */ dbus_g_connection_register_g_object (bus, GMYTH_DBUS_SERVER_PATH, G_OBJECT (self)); proxy = dbus_g_proxy_new_for_name (bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); /* registering download manager service */ if (!org_freedesktop_DBus_request_name (proxy, GMYTH_DBUS_SERVER_IFACE, 0, &request_ret, &error)) { g_warning ("Unable to register dbus service: %d %s", error->code, error->message); g_error_free (error); goto fail; } if (request_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { g_warning ("Got result code %u from requesting name", request_ret); goto fail; } return self; fail: g_object_unref (self); return NULL; } static void gmyth_dbus_server_cancel_shutdown (GMythDbusServer *self) { GMythDbusServerPrivate *priv; priv = GMYTH_DBUS_SERVER_GET_PRIVATE (self); if (priv->shutdown_cb_id) { g_source_remove (priv->shutdown_cb_id); priv->shutdown_cb_id = 0; } } static gboolean gmyth_dbus_server_shutdown_cb (GMythDbusServer *self) { GMythDbusServerPrivate *priv; priv = GMYTH_DBUS_SERVER_GET_PRIVATE (self); priv->shutdown_cb_id = 0; g_signal_emit (self, signals[SHUTDOWN], 0); return FALSE; } static gboolean gmyth_dbus_server_check_db_connection (GObject *obj, const gchar *host, gint port, const gchar *user, const gchar *password, GError **error) { GMythQuery *query = gmyth_query_new (); GMythBackendInfo *binfo; gboolean ret; gmyth_debug (""); binfo = gmyth_backend_info_new_full (host, user, password, MYTH_DEFAULT_DB, port); ret = gmyth_query_connect_with_timeout (query, binfo, 2 /*seconds*/); gmyth_query_disconnect (query); g_object_unref (query); g_object_unref (binfo); if (!ret) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_CONNECTION, _("Fail to connect with backend database")); } return ret; } static gboolean gmyth_dbus_server_check_server_connection (GObject *obj, const gchar *host, gint port, GError **error) { GMythSocket *msocket = gmyth_socket_new (); gboolean ret; gmyth_debug (""); g_debug ("Checking server connection"); ret = gmyth_socket_connect_with_timeout (msocket, host, port, 2); g_debug ("Return %s", ret ? "ok" : "bad"); gmyth_socket_close_connection (msocket); g_object_unref (msocket); if (!ret) { g_set_error (error, GMYTH_DBUS_ERROR, GMYTH_DBUS_ERROR_CONNECTION, _("Fail to connect with backend")); } return ret; }