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