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