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