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