gmyth-dbus/src/gmyth-dbus-server.c
author renatofilho
Mon Oct 29 19:56:35 2007 +0000 (2007-10-29)
branchtrunk
changeset 877 7fd8198b93aa
parent 876 007c65343f31
child 878 016b3410871d
permissions -rw-r--r--
[svn r883] implemented error propagation
     1 /**
     2  * GMyth Library
     3  *
     4  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
     5  * @author Renato Filho  <renato.filho@indt.org.br>
     6  *
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU Lesser General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  *
    18  * You should have received a copy of the GNU Lesser General Public License
    19  * along with this program; if not, write to the Free Software
    20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    21  */
    22 
    23 
    24 #ifdef HAVE_CONFIG_H
    25 #include "config.h"
    26 #endif
    27 
    28 
    29 #include <glib/gi18n.h>
    30 #include <gmyth/gmyth.h>
    31 #include <dbus/dbus-glib-bindings.h>
    32 
    33 #include "gmyth-dbus-common.h"
    34 #include "gmyth-dbus-server.h"
    35 
    36 #define MYTH_DEFAULT_DB             "mythconverg"
    37 
    38 enum
    39 {
    40     GMYTH_DBUS_ERROR_MYTHTV,
    41     GMYTH_DBUS_ERROR_CONNECTION,
    42     GMYTH_DBUS_ERROR_EPG,
    43     GMYTH_DBUS_ERROR_SCHEDULE
    44 };
    45 
    46 #define GMYTH_DBUS_ERROR gmyth_dbus_error_quark ()
    47 
    48 GQuark
    49 gmyth_dbus_error_quark (void)
    50 {
    51       return g_quark_from_static_string ("gmyth-dbus-error-quark");
    52 }
    53 
    54 typedef struct _GMythDbusServerPrivate GMythDbusServerPrivate;
    55 
    56 struct _GMythDbusServerPrivate
    57 {
    58     GMythBackendInfo *myth_backend;
    59     gboolean         connected;
    60     GMythEPG         *myth_epg;
    61     GMythScheduler   *myth_scheduler;
    62 };
    63 
    64 #define GMYTH_DBUS_SERVER_GET_PRIVATE(o) \
    65     (G_TYPE_INSTANCE_GET_PRIVATE ((o), GMYTH_DBUS_SERVER_TYPE, GMythDbusServerPrivate))
    66 
    67 static void gmyth_dbus_server_class_init (GMythDbusServerClass *klass);
    68 static void gmyth_dbus_server_init       (GMythDbusServer *self);
    69 static void gmyth_dbus_server_dispose    (GObject *object);
    70 static void gmyth_dbus_server_finalize   (GObject *object);
    71 
    72 /* Dbus */
    73 static gboolean gmyth_dbus_server_connect           (GObject *obj,
    74                                                      const gchar *host,
    75                                                      guint port,
    76                                                      const gchar *user,
    77                                                      const gchar *password,
    78                                                      gboolean *result,
    79                                                      GError **error);
    80 static gboolean gmyth_dbus_server_get_channel_list  (GObject *obj,
    81                                                      GPtrArray **channels,
    82                                                      GError **error);
    83 static gboolean gmyth_dbus_server_get_channel_info  (GObject *obj,
    84                                                      gint channel_id,
    85                                                      GValueArray **info,
    86                                                      GError **error);
    87 static gboolean gmyth_dbus_server_file_exists       (GObject *obj,
    88                                                      const gchar *file_name,
    89                                                      gboolean *exists,
    90                                                      GError **error);
    91 static gboolean gmyth_dbus_server_get_recorded_list (GObject *obj,
    92                                                      GPtrArray **channels,
    93                                                      GError **error);
    94 static gboolean gmyth_dbus_server_get_recorded_info (GObject *obj,
    95                                                      const gchar *basename,
    96                                                      GValueArray **info,
    97                                                      GError **error);
    98 static gboolean gmyth_dbus_server_get_program_list  (GObject *obj,
    99                                                      gint channel_id,
   100                                                      const gchar *start_time,
   101                                                      const gchar *end_time,
   102                                                      GPtrArray **program_list,
   103                                                      GError **error);
   104 static gboolean gmyth_dbus_server_get_schedule_list (GObject *obj,
   105                                                      GPtrArray **schedule_list,
   106                                                      GError **error);
   107 static gboolean gmyth_dbus_server_connected         (GObject *obj,
   108                                                      gboolean *status,
   109                                                      GError **error);
   110 static gboolean gmyth_dbus_server_disconnect        (GObject *obj,
   111                                                      GError **error);
   112 static gboolean gmyth_dbus_server_get_server_info   (GObject *obj,
   113                                                      guint64 *total_space,
   114                                                      guint64 *used_space,
   115                                                      guint64 *free_space,
   116                                                      GError **error);
   117 static gboolean gmyth_dbus_server_get_thumbnail     (GObject *obj,
   118                                                      const gchar *uri,
   119                                                      GByteArray **image,
   120                                                      GError **error);
   121 static gboolean gmyth_dbus_server_get_channel_icon  (GObject *obj,
   122                                                      guint channel_id,
   123                                                      GByteArray **icon,
   124                                                      GError **error);
   125 static gboolean gmyth_dbus_server_stop_recording    (GObject *obj,
   126                                                      guint channel_id,
   127                                                      gboolean *result,
   128                                                      GError **error);
   129 static gboolean gmyth_dbus_server_add_schedule      (GObject *obj,
   130                                                      guint channel_id,
   131                                                      guint program_id,
   132                                                      const gchar *start_time,
   133                                                      const gchar *end_time,
   134                                                      gboolean recurring,
   135                                                      const gchar *description,
   136                                                      guint *schedule_id,
   137                                                      GError **error);
   138 static gboolean gmyth_dbus_server_add_exception     (GObject *obj,
   139                                                      guint schedule_id,
   140                                                      guint channel_id,
   141                                                      guint program_id,
   142                                                      const gchar *start_time,
   143                                                      const gchar *end_time,
   144                                                      const gchar *description,
   145                                                      GError **error);
   146 static gboolean gmyth_dbus_server_remove_schedule   (GObject *obj,
   147                                                      guint schedule_id,
   148                                                      GError **error);
   149 
   150 
   151 #include "gmyth-dbus-server-glue.h"
   152 
   153 
   154 G_DEFINE_TYPE (GMythDbusServer, gmyth_dbus_server, G_TYPE_OBJECT);
   155 
   156 static void
   157 gmyth_dbus_server_class_init (GMythDbusServerClass *klass)
   158 {
   159     GObjectClass *object_class = G_OBJECT_CLASS (klass);
   160 
   161     g_type_class_add_private (klass, sizeof (GMythDbusServerPrivate));
   162 
   163     object_class->dispose = gmyth_dbus_server_dispose;
   164     object_class->finalize = gmyth_dbus_server_finalize;
   165 
   166     dbus_g_object_type_install_info (GMYTH_DBUS_SERVER_TYPE,
   167                                      &dbus_glib_gmyth_dbus_server_object_info);
   168 }
   169 
   170 static void
   171 gmyth_dbus_server_init (GMythDbusServer *self)
   172 {
   173 }
   174 
   175 static void
   176 gmyth_dbus_server_dispose (GObject *object)
   177 {
   178     G_OBJECT_CLASS (gmyth_dbus_server_parent_class)->dispose (object);
   179 }
   180 
   181 static void
   182 gmyth_dbus_server_finalize (GObject *object)
   183 {
   184     G_OBJECT_CLASS (gmyth_dbus_server_parent_class)->finalize (object);
   185 }
   186 
   187 static gboolean
   188 gmyth_dbus_server_connect_epg (GMythDbusServer *server, GError **error)
   189 {
   190     GMythDbusServerPrivate *priv;
   191     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (server);
   192 
   193     if (!priv->connected)
   194     {
   195         g_set_error (error,
   196                      GMYTH_DBUS_ERROR,
   197                      GMYTH_DBUS_ERROR_CONNECTION,
   198                      _("Not connected"));
   199 
   200         return FALSE;
   201     }
   202 
   203     if (!priv->myth_epg)
   204     {
   205         priv->myth_epg = gmyth_epg_new();
   206         if (!gmyth_epg_connect (priv->myth_epg, priv->myth_backend))
   207         {
   208             g_object_unref (priv->myth_epg);
   209             priv->myth_epg = NULL;
   210 
   211             g_set_error (error,
   212                          GMYTH_DBUS_ERROR,
   213                          GMYTH_DBUS_ERROR_EPG,
   214                          _("Fail to connect with EPG"));
   215 
   216             return FALSE;
   217         }
   218     }
   219 
   220     return TRUE;
   221 }
   222 
   223 static gboolean
   224 gmyth_dbus_server_connect_scheduler (GMythDbusServer *server,
   225                                      GError **error)
   226 {
   227     GMythDbusServerPrivate *priv;
   228     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (server);
   229 
   230     if (!priv->connected)
   231     {
   232         g_set_error (error,
   233                      GMYTH_DBUS_ERROR,
   234                      GMYTH_DBUS_ERROR_CONNECTION,
   235                      _("Not connected"));
   236 
   237         return FALSE;
   238     }
   239 
   240     if (!priv->myth_scheduler)
   241     {
   242         priv->myth_scheduler = gmyth_scheduler_new ();
   243         if (!gmyth_scheduler_connect (priv->myth_scheduler,
   244                                       priv->myth_backend))
   245         {
   246             g_object_unref (priv->myth_scheduler);
   247             priv->myth_scheduler = NULL;
   248 
   249             g_set_error (error,
   250                          GMYTH_DBUS_ERROR,
   251                          GMYTH_DBUS_ERROR_SCHEDULE,
   252                          _("Fail to connect with Schedule"));
   253 
   254             return FALSE;
   255         }
   256     }
   257 
   258     return TRUE;
   259 }
   260 
   261 static gboolean
   262 gmyth_dbus_server_connect  (GObject *obj,
   263                             const gchar *host,
   264                             guint port,
   265                             const gchar *user,
   266                             const gchar *password,
   267                             gboolean *result,
   268                             GError **error)
   269 {
   270     GMythSocket *s;
   271     GMythDbusServerPrivate *priv;
   272 
   273     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   274 
   275     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   276 
   277     if (priv->connected)
   278     {
   279         gmyth_dbus_server_disconnect (obj, NULL);
   280     }
   281 
   282     priv->myth_backend = gmyth_backend_info_new_full (host,
   283                                                       user,
   284                                                       password,
   285                                                       MYTH_DEFAULT_DB,
   286                                                       port);
   287 
   288     s = gmyth_backend_info_get_connected_socket (priv->myth_backend);
   289     if (s)
   290     {
   291         g_object_unref (s);
   292         *result = TRUE;
   293     }
   294     else
   295     {
   296         g_object_unref (priv->myth_backend);
   297         priv->myth_backend = NULL;
   298         *result = FALSE;
   299 
   300         g_set_error (error,
   301                      GMYTH_DBUS_ERROR,
   302                      GMYTH_DBUS_ERROR_CONNECTION,
   303                      _("Fail to connect with backend"));
   304     }
   305 
   306     priv->connected = *result;
   307     return *result;
   308 }
   309 
   310 static gboolean
   311 gmyth_dbus_server_connected (GObject *obj,
   312                              gboolean *status,
   313                              GError **error)
   314 {
   315     GMythDbusServerPrivate *priv;
   316 
   317     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   318 
   319     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   320 
   321     if (priv->myth_backend)
   322         *status = TRUE;
   323     else
   324         *status = FALSE;
   325     return TRUE;
   326 }
   327 
   328 static gboolean
   329 gmyth_dbus_server_disconnect (GObject *obj,
   330                               GError **error)
   331 {
   332     GMythDbusServerPrivate *priv;
   333 
   334     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   335 
   336     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   337 
   338     if (priv->myth_epg)
   339     {
   340         g_object_unref (priv->myth_epg);
   341         priv->myth_epg = NULL;
   342     }
   343 
   344 
   345     if (priv->myth_backend)
   346     {
   347         g_object_unref (priv->myth_backend);
   348         priv->myth_backend = NULL;
   349     }
   350 
   351     if (priv->myth_scheduler)
   352     {
   353         g_object_unref (priv->myth_scheduler);
   354         priv->myth_scheduler = NULL;
   355     }
   356 
   357 
   358     return TRUE;
   359 }
   360 
   361 static gboolean
   362 gmyth_dbus_server_get_server_info (GObject *obj,
   363                                    guint64 *total_space,
   364                                    guint64 *used_space,
   365                                    guint64 *free_space,
   366                                    GError **error)
   367 {
   368     GMythBackendDetails *details;
   369     GMythDbusServerPrivate *priv;
   370     gboolean ret = FALSE;
   371     GMythSocket *socket;
   372 
   373     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   374     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   375 
   376     g_return_val_if_fail (priv->myth_backend != NULL, FALSE);
   377 
   378     socket = gmyth_backend_info_get_connected_socket (priv->myth_backend);
   379 
   380     if (!socket)
   381     {
   382         g_set_error (error,
   383                      GMYTH_DBUS_ERROR,
   384                      GMYTH_DBUS_ERROR_MYTHTV,
   385                      _("MythTv not avaliable"));
   386         return FALSE;
   387 
   388     }
   389 
   390     details = NULL;
   391     gmyth_util_get_backend_details (socket,
   392                                     &details);
   393     if (details)
   394     {
   395         *total_space = details->total_space;
   396         *used_space = details->used_space;
   397         *free_space = *total_space - *used_space;
   398         gmyth_util_backend_details_free (details);
   399 
   400         ret = TRUE;
   401     }
   402     else
   403     {
   404         g_set_error (error,
   405                      GMYTH_DBUS_ERROR,
   406                      GMYTH_DBUS_ERROR_MYTHTV,
   407                      _("Fail to get MythTv details"));
   408     }
   409 
   410     g_object_unref (socket);
   411 
   412     return ret;
   413 }
   414 
   415 
   416 static void
   417 gmyth_dbus_server_parse_channel_info (GMythChannelInfo *info,
   418                                       GValue *val)
   419 {
   420     dbus_g_type_struct_set (val,
   421                             0, info->channel_ID,
   422                             1, info->channel_num->str,
   423                             2, info->channel_name->str,
   424                             3, info->channel_icon->str,
   425                             G_MAXUINT);
   426 }
   427 
   428 static gboolean 
   429 gmyth_dbus_server_get_channel_info  (GObject *obj,
   430                                      gint channel_id,
   431                                      GValueArray **info,
   432                                      GError **error)
   433 {
   434     GType ch_type;
   435     GMythChannelInfo *ch_info;
   436     GMythDbusServerPrivate *priv;
   437 
   438     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   439     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   440 
   441     g_return_val_if_fail (priv->myth_backend != NULL, FALSE);
   442 
   443     if (!gmyth_dbus_server_connect_epg (GMYTH_DBUS_SERVER (obj), error))
   444     {
   445         return FALSE;
   446     }
   447 
   448     ch_type = GMYTH_DBUS_CHANNEL_G_TYPE;
   449 
   450     ch_info = gmyth_epg_get_channel_info (priv->myth_epg, channel_id);
   451     if (ch_info)
   452     {
   453         GValue v = { 0, };
   454         g_value_init (&v, ch_type);
   455         g_value_take_boxed (&v, dbus_g_type_specialized_construct (ch_type));
   456         gmyth_dbus_server_parse_channel_info (ch_info, &v);
   457 
   458         *info = g_value_get_boxed (&v);
   459         return TRUE;
   460     }
   461     else
   462     {
   463         g_set_error (error,
   464                      GMYTH_DBUS_ERROR,
   465                      GMYTH_DBUS_ERROR_EPG,
   466                      _("no channel info avaliable"));
   467     }
   468 
   469     return FALSE;
   470 }
   471 
   472 
   473 static gboolean
   474 gmyth_dbus_server_get_channel_list (GObject *obj,
   475                                     GPtrArray **channels,
   476                                     GError **error)
   477 {
   478     GList *lst;
   479     GList *walk;
   480     int len;
   481     GType ch_type;
   482     GMythDbusServerPrivate *priv;
   483 
   484     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   485     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   486 
   487     g_return_val_if_fail (priv->myth_backend != NULL, FALSE);
   488     if (!gmyth_dbus_server_connect_epg (GMYTH_DBUS_SERVER (obj), error))
   489         return FALSE;
   490 
   491 
   492     lst = NULL;
   493     len = gmyth_epg_get_channel_list (priv->myth_epg, &lst);
   494 
   495     *channels = g_ptr_array_sized_new (len);
   496     ch_type = GMYTH_DBUS_CHANNEL_G_TYPE;
   497 
   498     for (walk = lst; walk != NULL; walk = walk->next)
   499     {
   500         GValue ch = { 0, };
   501         GMythChannelInfo *data;
   502 
   503         data = (GMythChannelInfo *) walk->data;
   504 
   505         g_value_init (&ch, ch_type);
   506         g_value_take_boxed (&ch, dbus_g_type_specialized_construct (ch_type));
   507         gmyth_dbus_server_parse_channel_info (data, &ch);
   508         g_ptr_array_add (*channels, g_value_get_boxed (&ch));
   509     }
   510 
   511     gmyth_free_channel_list (lst);
   512     return TRUE;
   513 }
   514 
   515 static gboolean
   516 gmyth_dbus_server_file_exists (GObject *obj,
   517                                const gchar *file_name,
   518                                gboolean *exists,
   519                                GError **error)
   520 {
   521     GMythDbusServerPrivate *priv;
   522     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   523     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   524 
   525     g_return_val_if_fail (priv->myth_backend, FALSE);
   526 
   527     *exists = gmyth_util_file_exists (priv->myth_backend, file_name);
   528 
   529     return TRUE;
   530 }
   531 
   532 static gboolean
   533 gmyth_dbus_server_get_program_list (GObject *obj,
   534                                     gint channel_id,
   535                                     const gchar *start_time,
   536                                     const gchar *end_time,
   537                                     GPtrArray **programs,
   538                                     GError **error)
   539 {
   540     GList *list;
   541     GList *walk;
   542     gint len;
   543     GType program_type;
   544     GTimeVal start_time_val;
   545     GTimeVal end_time_val;
   546     GMythDbusServerPrivate *priv;
   547 
   548     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   549     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   550 
   551     g_return_val_if_fail (priv->myth_backend, FALSE);
   552     if (!gmyth_dbus_server_connect_epg (GMYTH_DBUS_SERVER (obj), error))
   553         return FALSE;
   554 
   555     g_time_val_from_iso8601 (start_time, &start_time_val);
   556     g_time_val_from_iso8601 (end_time, &end_time_val);
   557 
   558     list = NULL;
   559     len = gmyth_epg_get_program_list (priv->myth_epg,
   560                                       &list,
   561                                       channel_id,
   562                                       &start_time_val,
   563                                       &end_time_val);
   564 
   565     *programs = g_ptr_array_sized_new (len);
   566     program_type = GMYTH_DBUS_PROGRAM_G_TYPE;
   567 
   568     for (walk = list; walk != NULL; walk = walk->next)
   569     {
   570         GValue program = { 0, };
   571         gchar *start_str;
   572         gchar *end_str;
   573         GMythProgramInfo *data;
   574 
   575         data = (GMythProgramInfo *) walk->data;
   576 
   577         if (!data)
   578             continue;
   579 
   580         g_value_init (&program, program_type);
   581         g_value_take_boxed (&program,
   582                             dbus_g_type_specialized_construct (program_type));
   583 
   584         start_str = g_time_val_to_iso8601 (data->startts);
   585         end_str = g_time_val_to_iso8601 (data->endts);
   586 
   587         dbus_g_type_struct_set (&program,
   588                                 0, data->chanid->str,
   589                                 1, start_str,
   590                                 2, end_str,
   591                                 3, data->title->str,
   592                                 4, data->subtitle->str,
   593                                 5, data->description->str,
   594                                 6, data->category->str,
   595                                 G_MAXUINT);
   596 
   597         g_ptr_array_add (*programs, g_value_get_boxed (&program));
   598         g_free (start_str);
   599         g_free (end_str);
   600     }
   601 
   602     if (list)
   603         gmyth_free_program_list (list);
   604 
   605     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   606     return TRUE;
   607 }
   608 
   609 static void
   610 gmyth_dbus_server_parse_recorded_info (RecordedInfo *info,
   611                                        GValue *val)
   612 {
   613     gchar *start_str;
   614     gchar *end_str;
   615 
   616     start_str = g_time_val_to_iso8601 (info->start_time);
   617     end_str = g_time_val_to_iso8601 (info->end_time);
   618 
   619     dbus_g_type_struct_set (val,
   620                             0, info->record_id,
   621                             1, info->program_id,
   622                             2, info->channel_id,
   623                             3, start_str,
   624                             4, end_str,
   625                             5, info->title->str,
   626                             6, info->subtitle->str,
   627                             7, info->description->str,
   628                             8, info->category->str,
   629                             9, info->basename->str,
   630                             10, info->filesize,
   631                             G_MAXUINT);
   632     g_free (start_str);
   633     g_free (end_str);
   634 }
   635 
   636 static gboolean
   637 gmyth_dbus_server_get_recorded_info (GObject *obj,
   638                                      const gchar *basename,
   639                                      GValueArray **info,
   640                                      GError **error)
   641 {
   642     GType record_type;
   643     GMythDbusServerPrivate *priv;
   644     RecordedInfo *record_info;
   645 
   646 
   647     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   648     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   649 
   650     g_return_val_if_fail (priv->myth_backend, FALSE);
   651 
   652     if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error))
   653         return FALSE;
   654 
   655     record_type = GMYTH_DBUS_RECORD_G_TYPE;
   656 
   657     record_info = gmyth_scheduler_get_recorded_info (priv->myth_scheduler,
   658                                                      basename);
   659 
   660     if (record_info)
   661     {
   662         GValue r = { 0, };
   663 
   664         g_value_init (&r, record_type);
   665         g_value_take_boxed (&r,
   666                             dbus_g_type_specialized_construct (record_type));
   667 
   668         gmyth_dbus_server_parse_recorded_info (record_info, &r);
   669         gmyth_recorded_info_free (record_info);
   670 
   671         *info = g_value_get_boxed (&r);
   672 
   673         return TRUE;
   674     }
   675     else
   676     {
   677         g_set_error (error,
   678                      GMYTH_DBUS_ERROR,
   679                      GMYTH_DBUS_ERROR_EPG,
   680                      _("no record info avaliable"));
   681 
   682     }
   683 
   684     return FALSE;
   685 }
   686 
   687 
   688 static gboolean
   689 gmyth_dbus_server_get_recorded_list (GObject *obj,
   690                                      GPtrArray **records,
   691                                      GError **error)
   692 {
   693     GList *list;
   694     GList *walk;
   695     gint len;
   696     GType record_type;
   697     GMythDbusServerPrivate *priv;
   698 
   699     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   700     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   701 
   702     g_return_val_if_fail (priv->myth_backend != NULL, FALSE);
   703     if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error))
   704         return FALSE;
   705 
   706 
   707     len = gmyth_scheduler_get_recorded_list (priv->myth_scheduler,
   708                                              &list);
   709 
   710     record_type = GMYTH_DBUS_RECORD_G_TYPE;
   711     *records = g_ptr_array_sized_new (len);
   712 
   713     for (walk = list; walk != NULL; walk = walk->next)
   714     {
   715         GValue record = { 0, };
   716         RecordedInfo *data;
   717 
   718         data = (RecordedInfo *) walk->data;
   719 
   720         g_value_init (&record, record_type);
   721         g_value_take_boxed (&record,
   722                             dbus_g_type_specialized_construct (record_type));
   723 
   724         gmyth_dbus_server_parse_recorded_info (data, &record);
   725 
   726         g_ptr_array_add (*records, g_value_get_boxed (&record));
   727         //g_value_unset (&record);
   728     }
   729 
   730     gmyth_recorded_info_list_free (list);
   731 
   732     return TRUE;
   733 
   734 }
   735 
   736 static gboolean
   737 gmyth_dbus_server_get_schedule_list (GObject *obj,
   738                                      GPtrArray **schedules,
   739                                      GError **error)
   740 {
   741     GList *list;
   742     GList *walk;
   743     gint len;
   744     GType schedule_type;
   745     GMythDbusServerPrivate *priv;
   746 
   747     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   748     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   749 
   750     g_return_val_if_fail (priv->myth_backend, FALSE);
   751     if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error))
   752         return FALSE;
   753 
   754 
   755     len = gmyth_scheduler_get_schedule_list (priv->myth_scheduler,
   756                                              &list);
   757 
   758     *schedules = g_ptr_array_sized_new (len);
   759     schedule_type = GMYTH_DBUS_SCHEDULE_G_TYPE;
   760 
   761     for (walk = list; walk != NULL; walk = walk->next)
   762     {
   763         GValue schedule = { 0, };
   764         ScheduleInfo *data;
   765         gchar *start_str_time;
   766         gchar *end_str_time;
   767 
   768         data = (ScheduleInfo *) walk->data;
   769 
   770         g_value_init (&schedule, schedule_type);
   771         g_value_take_boxed (&schedule,
   772                             dbus_g_type_specialized_construct (schedule_type));
   773 
   774         start_str_time = g_time_val_to_iso8601 (data->start_time);
   775         end_str_time = g_time_val_to_iso8601 (data->end_time);
   776 
   777         dbus_g_type_struct_set (&schedule,
   778                             0, data->schedule_id,
   779                             1, data->program_id,
   780                             2, data->channel_id,
   781                             3, start_str_time,
   782                             4, end_str_time,
   783                             5, data->title->str,
   784                             6, data->subtitle->str,
   785                             7, data->description->str,
   786                             8, data->category->str,
   787                             9, data->type,
   788                             G_MAXUINT);
   789 
   790         g_ptr_array_add (*schedules, g_value_get_boxed (&schedule));
   791 
   792         g_free (start_str_time);
   793         g_free (end_str_time);
   794     }
   795 
   796     gmyth_schedule_info_list_free (list);
   797 
   798     return TRUE;
   799 }
   800 
   801 
   802 static gboolean
   803 gmyth_dbus_server_get_thumbnail (GObject *obj,
   804                                 const gchar *uri,
   805                                 GByteArray **image,
   806                                 GError **error)
   807 {
   808     GMythFileTransfer *file_transfer;
   809     glong filesize;
   810     GMythFileReadResult result;
   811     GMythDbusServerPrivate *priv;
   812 
   813     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   814 
   815     file_transfer = NULL;
   816 
   817     g_return_val_if_fail (priv->myth_backend, FALSE);
   818 
   819     if (!gmyth_util_file_exists (priv->myth_backend, uri))
   820     {
   821         g_set_error (error,
   822                      GMYTH_DBUS_ERROR,
   823                      GMYTH_DBUS_ERROR_MYTHTV,
   824                      _("File not exists"));
   825 
   826         goto fail;
   827     }
   828 
   829     file_transfer = gmyth_file_transfer_new (priv->myth_backend);
   830 
   831     if (!gmyth_file_transfer_open (file_transfer, uri))
   832     {
   833         g_set_error (error,
   834                      GMYTH_DBUS_ERROR,
   835                      GMYTH_DBUS_ERROR_MYTHTV,
   836                      _("Fail to open file"));
   837         goto fail;
   838     }
   839 
   840     filesize = gmyth_file_transfer_get_filesize (file_transfer);
   841     if (filesize <= 0)
   842         goto fail;
   843 
   844     *image = g_byte_array_new ();
   845     result = gmyth_file_transfer_read (file_transfer, *image, filesize, FALSE);
   846     if (result == GMYTH_FILE_READ_ERROR)
   847     {
   848         g_set_error (error,
   849                      GMYTH_DBUS_ERROR,
   850                      GMYTH_DBUS_ERROR_MYTHTV,
   851                      _("Fail to read file"));
   852 
   853        goto fail;
   854     }
   855 
   856     gmyth_file_transfer_close (file_transfer);
   857     g_object_unref (file_transfer);
   858 
   859     if (filesize > (*image)->len)
   860     {
   861         g_set_error (error,
   862                      GMYTH_DBUS_ERROR,
   863                      GMYTH_DBUS_ERROR_MYTHTV,
   864                      _("Empty file"));
   865 
   866         goto fail;
   867     }
   868 
   869     return TRUE;
   870 
   871 fail:
   872     if (*image)
   873         g_byte_array_free (*image, TRUE);
   874     g_object_unref(file_transfer);
   875     return FALSE;
   876 }
   877 
   878 static gboolean
   879 gmyth_dbus_server_get_channel_icon (GObject *obj,
   880                                     guint channel_id,
   881                                     GByteArray **icon,
   882                                     GError **error)
   883 {
   884     GMythChannelInfo *channel = NULL;
   885     guint8 *icon_data;
   886     guint icon_length;
   887     GMythDbusServerPrivate *priv;
   888 
   889     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   890     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   891     g_return_val_if_fail (priv->myth_backend, FALSE);
   892 
   893     channel = gmyth_epg_get_channel_info (priv->myth_epg,
   894                                          (gint) channel_id);
   895 
   896     *icon = NULL;
   897 
   898     if (channel == NULL)
   899     {
   900         g_set_error (error,
   901                      GMYTH_DBUS_ERROR,
   902                      GMYTH_DBUS_ERROR_MYTHTV,
   903                      _("Invalid channel"));
   904 
   905         return FALSE;
   906     }
   907 
   908     if (!gmyth_epg_channel_has_icon(priv->myth_epg, channel))
   909     {
   910         gmyth_channel_info_free (channel);
   911         g_set_error (error,
   912                      GMYTH_DBUS_ERROR,
   913                      GMYTH_DBUS_ERROR_MYTHTV,
   914                      _("Channel does not have icon available"));
   915 
   916         return FALSE;
   917     }
   918 
   919     icon_data = NULL;
   920     icon_length = 0;
   921     if (!gmyth_epg_channel_get_icon (priv->myth_epg,
   922                                      channel,
   923                                      &icon_data,
   924                                      &icon_length)) 
   925     {
   926         gmyth_channel_info_free (channel);
   927         g_set_error (error,
   928                      GMYTH_DBUS_ERROR,
   929                      GMYTH_DBUS_ERROR_MYTHTV,
   930                      _("Could not get channel icon for channel id = %u"),
   931                      channel_id);
   932         return FALSE;
   933     }
   934 
   935     *icon = g_byte_array_sized_new (icon_length);
   936     *icon = g_byte_array_append (*icon, icon_data, icon_length);
   937 
   938     g_free (icon_data);
   939     gmyth_channel_info_free(channel);
   940     return TRUE;
   941 }
   942 
   943 
   944 static gboolean
   945 gmyth_dbus_server_stop_recording (GObject *obj,
   946                                   guint channel_id,
   947                                   gboolean *result,
   948                                   GError **error)
   949 {
   950     gboolean ret = FALSE;
   951     GMythDbusServerPrivate *priv;
   952 
   953     g_debug ("%s:%d", __FUNCTION__, __LINE__);
   954     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
   955 
   956     g_return_val_if_fail (priv->myth_backend, FALSE);
   957     if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error))
   958         return FALSE;
   959 
   960     ret = gmyth_scheduler_stop_recording (priv->myth_scheduler,
   961                                           channel_id);
   962 
   963     return ret;
   964 }
   965 
   966 static ScheduleInfo*
   967 gmyth_dbus_server_new_schedule_info (const gchar* description,
   968                                      guint channel_id,
   969                                      guint program_id,
   970                                      GTimeVal *start_vtime,
   971                                      GTimeVal *end_vtime)
   972 {
   973     ScheduleInfo   *new_sched_info;
   974 
   975     new_sched_info = g_new0(ScheduleInfo, 1);
   976 
   977     /* record_id == -1 for generating a new id */
   978     new_sched_info->schedule_id = -1;
   979 
   980     new_sched_info->channel_id = channel_id;
   981     new_sched_info->program_id = program_id;
   982     new_sched_info->start_time = g_new0 (GTimeVal, 1);
   983     *new_sched_info->start_time = *start_vtime;
   984     new_sched_info->end_time = g_new0 (GTimeVal, 1);
   985     *new_sched_info->end_time = *end_vtime;
   986 
   987     /* TODO: there is no frequency field */
   988     /*new_sched_info->frequency = -1;*/
   989 
   990     if (description != NULL) {
   991         /* FIXME: description parameter is used as title and description */
   992         new_sched_info->title = g_string_new(description);
   993         new_sched_info->description = g_string_new(description);
   994     }
   995 
   996     return new_sched_info;
   997 }
   998 
   999 static gboolean
  1000 gmyth_dbus_server_add_schedule (GObject *obj,
  1001                                 guint channel_id,
  1002                                 guint program_id,
  1003                                 const gchar *start_time,
  1004                                 const gchar *end_time,
  1005                                 gboolean recurring,
  1006                                 const gchar *description,
  1007                                 guint *schedule_id,
  1008                                 GError **error)
  1009 {
  1010     ScheduleInfo *sch_info;
  1011     GTimeVal start_vtime;
  1012     GTimeVal end_vtime;
  1013     GMythDbusServerPrivate *priv;
  1014 
  1015     g_debug ("%s:%d", __FUNCTION__, __LINE__);
  1016     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
  1017 
  1018     *schedule_id = 0;
  1019 
  1020     g_return_val_if_fail (priv->myth_backend, FALSE);
  1021 
  1022     if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error))
  1023         return FALSE;
  1024 
  1025 
  1026     g_time_val_from_iso8601 (start_time, &start_vtime);
  1027     g_time_val_from_iso8601 (end_time, &end_vtime);
  1028     sch_info = gmyth_dbus_server_new_schedule_info (description,
  1029                                                     channel_id,
  1030                                                     program_id,
  1031                                                     &start_vtime,
  1032                                                     &end_vtime);
  1033     if (sch_info != NULL) {
  1034         GMythScheduleType type;
  1035         GTimeVal t_now;
  1036         gboolean has_record;
  1037 
  1038         type = (recurring ?
  1039                 GMYTH_SCHEDULE_ALL_OCCURRENCES :
  1040                 GMYTH_SCHEDULE_ONE_OCCURRENCE);
  1041 
  1042         g_get_current_time (&t_now);
  1043 
  1044         has_record = gmyth_scheduler_was_recorded_before (priv->myth_scheduler, 
  1045                                                           channel_id,
  1046                                                           (time_t) start_vtime.tv_sec);
  1047 
  1048 
  1049         if ((t_now.tv_sec >= start_vtime.tv_sec)
  1050             && (t_now.tv_sec <= end_vtime.tv_sec) && has_record)
  1051         {
  1052             GMythSocket    *socket;
  1053             gboolean        res = FALSE;
  1054 
  1055             socket = gmyth_backend_info_get_connected_socket (priv->myth_backend);
  1056             res = gmyth_scheduler_reactivate_schedule(priv->myth_scheduler,
  1057                                                       channel_id,
  1058                                                       (time_t) start_vtime.tv_sec);
  1059             if (res) {
  1060                 GMythStringList *slist = gmyth_string_list_new();
  1061 
  1062                 gmyth_string_list_append_char_array(slist, "RESCHEDULE_RECORDINGS 0");
  1063                 gmyth_socket_sendreceive_stringlist(socket, slist);
  1064                 res = (gmyth_string_list_get_int(slist, 0) == 1);
  1065                 g_object_unref(slist);
  1066             }
  1067 
  1068             g_object_unref(socket);
  1069             return res;
  1070         }
  1071         else
  1072         {
  1073             if (!gmyth_scheduler_add_schedule_full (priv->myth_scheduler,
  1074                                                     sch_info,
  1075                                                     type))
  1076             {
  1077                 g_warning("Could not add schedule entry");
  1078                 return FALSE;
  1079             }
  1080 
  1081             (*schedule_id) = sch_info->schedule_id;
  1082             gmyth_schedule_info_free (sch_info);
  1083             return TRUE;
  1084         }
  1085     }
  1086     return FALSE;
  1087 }
  1088 
  1089 static gboolean
  1090 gmyth_dbus_server_add_exception (GObject *obj,
  1091                                  guint schedule_id,
  1092                                  guint channel_id,
  1093                                  guint program_id,
  1094                                  const gchar *start_time,
  1095                                  const gchar *end_time,
  1096                                  const gchar *description,
  1097                                  GError **error)
  1098 {
  1099     ScheduleInfo *sch_info;
  1100     GTimeVal start_vtime;
  1101     GTimeVal end_vtime;
  1102     GMythDbusServerPrivate *priv;
  1103 
  1104     g_debug ("%s:%d", __FUNCTION__, __LINE__);
  1105     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
  1106 
  1107     g_return_val_if_fail (priv->myth_backend, FALSE);
  1108 
  1109     if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error))
  1110         return FALSE;
  1111 
  1112     g_time_val_from_iso8601 (start_time, &start_vtime);
  1113     g_time_val_from_iso8601 (end_time, &end_vtime);
  1114 
  1115     sch_info = gmyth_dbus_server_new_schedule_info (description,
  1116                                                    channel_id,
  1117                                                    program_id,
  1118                                                    &start_vtime,
  1119                                                    &end_vtime);
  1120     if (sch_info != NULL)
  1121     {
  1122        if (!gmyth_scheduler_add_exception (priv->myth_scheduler,
  1123                                            schedule_id,
  1124                                            sch_info))
  1125        {
  1126            g_warning ("Could not add schedule exception");
  1127            gmyth_schedule_info_free (sch_info);
  1128            return FALSE;
  1129        }
  1130 
  1131        gmyth_schedule_info_free (sch_info);
  1132        return TRUE;
  1133     }
  1134     return FALSE;
  1135 }
  1136 
  1137 static gboolean
  1138 gmyth_dbus_server_remove_schedule (GObject *obj,
  1139                                    guint schedule_id,
  1140                                    GError **error)
  1141 {
  1142     GMythDbusServerPrivate *priv;
  1143 
  1144     g_debug ("%s:%d", __FUNCTION__, __LINE__);
  1145     priv = GMYTH_DBUS_SERVER_GET_PRIVATE (obj);
  1146 
  1147     g_return_val_if_fail (priv->myth_backend, FALSE);
  1148 
  1149     if (!gmyth_dbus_server_connect_scheduler (GMYTH_DBUS_SERVER (obj), error))
  1150         return FALSE;
  1151 
  1152     return gmyth_scheduler_delete_schedule (priv->myth_scheduler, schedule_id);
  1153 }
  1154 
  1155 GMythDbusServer*
  1156 gmyth_dbus_server_start_dbus_service (void)
  1157 {
  1158     GError *error = NULL;
  1159     DBusGProxy *proxy;
  1160     DBusGConnection *bus;
  1161     guint request_ret;
  1162     GMythDbusServer *self;
  1163 
  1164     self = g_object_new (GMYTH_DBUS_SERVER_TYPE, NULL);
  1165     g_return_val_if_fail (self, FALSE);
  1166 
  1167     /* TODO: should verify if this service was already started */
  1168 
  1169     /* connect to session bus */
  1170     bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
  1171     if (bus == NULL) 
  1172     {
  1173         g_warning ("Could not connect to dbus: %s", error->message);
  1174         g_error_free (error);
  1175         goto fail;
  1176     }
  1177 
  1178     /* register dbus object */
  1179     dbus_g_connection_register_g_object (bus,
  1180         GMYTH_DBUS_SERVER_PATH, G_OBJECT (self));
  1181 
  1182     proxy = dbus_g_proxy_new_for_name (bus, DBUS_SERVICE_DBUS,
  1183                                        DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
  1184 
  1185     /* registering download manager service */
  1186     if (!org_freedesktop_DBus_request_name (proxy, GMYTH_DBUS_SERVER_IFACE,
  1187                                             0, &request_ret, &error)) 
  1188     {
  1189         g_warning ("Unable to register dbus service: %d %s",
  1190                    error->code, error->message);
  1191         g_error_free (error);
  1192         goto fail;
  1193     }
  1194 
  1195     if (request_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) 
  1196     {
  1197         g_warning ("Got result code %u from requesting name", request_ret);
  1198         goto fail;
  1199     }
  1200 
  1201     return self;
  1202 
  1203 fail:
  1204     g_object_unref (self);
  1205     return NULL;
  1206 }
  1207