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