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