Back to index

libindicator  12.10.0
indicator-service-manager.c
Go to the documentation of this file.
00001 /*
00002 An object used to manage services.  Either start them or
00003 just connect to them.
00004 
00005 Copyright 2009 Canonical Ltd.
00006 
00007 Authors:
00008     Ted Gould <ted@canonical.com>
00009 
00010 This library is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 version 3.0 as published by the Free Software Foundation.
00013 
00014 This library is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License version 3.0 for more details.
00018 
00019 You should have received a copy of the GNU General Public
00020 License along with this library. If not, see
00021 <http://www.gnu.org/licenses/>.
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include "config.h"
00026 #endif
00027 
00028 #include <stdlib.h>
00029 #include <gio/gio.h>
00030 
00031 #include "indicator-service-manager.h"
00032 #include "gen-indicator-service.xml.h"
00033 #include "dbus-shared.h"
00034 
00035 /* Private Stuff */
00044 typedef struct _IndicatorServiceManagerPrivate IndicatorServiceManagerPrivate;
00045 struct _IndicatorServiceManagerPrivate {
00046        gchar * name;
00047        GDBusProxy * service_proxy;
00048        GCancellable * service_proxy_cancel;
00049        guint name_watcher;
00050        gboolean connected;
00051        guint this_service_version;
00052        guint restart_count;
00053        gint restart_source;
00054        GCancellable * watch_cancel;
00055 };
00056 
00057 /* Signals Stuff */
00058 enum {
00059        CONNECTION_CHANGE,
00060        LAST_SIGNAL
00061 };
00062 
00063 static guint signals[LAST_SIGNAL] = { 0 };
00064 
00065 /* If this env variable is set, we don't restart */
00066 #define TIMEOUT_ENV_NAME   "INDICATOR_SERVICE_RESTART_DISABLE"
00067 #define TIMEOUT_MULTIPLIER 100 /* In ms */
00068 /* What to reset the restart_count to if we know that we're
00069    in a recoverable error condition, but waiting a little bit
00070    will probably make things better.  5 ~= 3 sec. */
00071 #define TIMEOUT_A_LITTLE_WHILE  5
00072 
00073 /* Properties */
00074 /* Enum for the properties so that they can be quickly
00075    found and looked up. */
00076 enum {
00077        PROP_0,
00078        PROP_NAME,
00079        PROP_VERSION
00080 };
00081 
00082 /* The strings so that they can be slowly looked up. */
00083 #define PROP_NAME_S                    "name"
00084 #define PROP_VERSION_S                 "version"
00085 
00086 /* GDBus Stuff */
00087 static GDBusNodeInfo *            node_info = NULL;
00088 static GDBusInterfaceInfo *       interface_info = NULL;
00089 
00090 /* GObject Stuff */
00091 #define INDICATOR_SERVICE_MANAGER_GET_PRIVATE(o) \
00092 (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManagerPrivate))
00093 
00094 static void indicator_service_manager_class_init (IndicatorServiceManagerClass *klass);
00095 static void indicator_service_manager_init       (IndicatorServiceManager *self);
00096 static void indicator_service_manager_dispose    (GObject *object);
00097 static void indicator_service_manager_finalize   (GObject *object);
00098 
00099 /* Prototypes */
00100 static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
00101 static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
00102 static void start_service (IndicatorServiceManager * service);
00103 static void start_service_again (IndicatorServiceManager * manager);
00104 static void unwatch (GDBusProxy * proxy);
00105 static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
00106 static void service_proxy_name_changed (GDBusConnection * connection, const gchar * sender_name, const gchar * object_path, const gchar * interface_name, const gchar * signal_name, GVariant * parameters, gpointer user_data);
00107 
00108 G_DEFINE_TYPE (IndicatorServiceManager, indicator_service_manager, G_TYPE_OBJECT);
00109 
00110 /* Build all of our signals and proxies and tie everything
00111    all together.  Lovely. */
00112 static void
00113 indicator_service_manager_class_init (IndicatorServiceManagerClass *klass)
00114 {
00115        GObjectClass *object_class = G_OBJECT_CLASS (klass);
00116 
00117        g_type_class_add_private (klass, sizeof (IndicatorServiceManagerPrivate));
00118 
00119        object_class->dispose = indicator_service_manager_dispose;
00120        object_class->finalize = indicator_service_manager_finalize;
00121 
00122        /* Property funcs */
00123        object_class->set_property = set_property;
00124        object_class->get_property = get_property;
00125 
00134        signals[CONNECTION_CHANGE] = g_signal_new (INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE,
00135                                          G_TYPE_FROM_CLASS(klass),
00136                                          G_SIGNAL_RUN_LAST,
00137                                          G_STRUCT_OFFSET (IndicatorServiceManagerClass, connection_change),
00138                                          NULL, NULL,
00139                                          g_cclosure_marshal_VOID__BOOLEAN,
00140                                          G_TYPE_NONE, 1, G_TYPE_BOOLEAN, G_TYPE_NONE);
00141 
00142        /* Properties */
00143        g_object_class_install_property(object_class, PROP_NAME,
00144                                        g_param_spec_string(PROP_NAME_S,
00145                                                            "The DBus name for the service to monitor",
00146                                                            "This is the name that should be used to start a service.",
00147                                                            NULL,
00148                                                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
00149        g_object_class_install_property(object_class, PROP_VERSION,
00150                                        g_param_spec_uint(PROP_VERSION_S,
00151                                                          "The version of the service that we're expecting.",
00152                                                          "A number to check and reject a service if it gives us the wrong number.  This should match across the manager and the service",
00153                                                          0, G_MAXUINT, 0,
00154                                                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
00155 
00156        /* Setting up the DBus interfaces */
00157        if (node_info == NULL) {
00158               GError * error = NULL;
00159 
00160               node_info = g_dbus_node_info_new_for_xml(_indicator_service, &error);
00161               if (error != NULL) {
00162                      g_error("Unable to parse Indicator Service Interface description: %s", error->message);
00163                      g_error_free(error);
00164               }
00165        }
00166 
00167        if (interface_info == NULL) {
00168               interface_info = g_dbus_node_info_lookup_interface(node_info, INDICATOR_SERVICE_INTERFACE);
00169 
00170               if (interface_info == NULL) {
00171                      g_error("Unable to find interface '" INDICATOR_SERVICE_INTERFACE "'");
00172               }
00173        }
00174 
00175        return;
00176 }
00177 
00178 /* This inits all the variable and sets up the proxy
00179    to dbus.  It doesn't look for the service as at this
00180    point we don't know it's name. */
00181 static void
00182 indicator_service_manager_init (IndicatorServiceManager *self)
00183 {
00184        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(self);
00185 
00186        /* Get the private variables in a decent state */
00187        priv->name = NULL;
00188        priv->service_proxy = NULL;
00189        priv->service_proxy_cancel = NULL;
00190        priv->name_watcher = 0;
00191        priv->connected = FALSE;
00192        priv->this_service_version = 0;
00193        priv->restart_count = 0;
00194        priv->restart_source = 0;
00195        priv->watch_cancel = NULL;
00196 
00197        return;
00198 }
00199 
00200 /* If we're connected this provides all the signals to say
00201    that we're about to not be.  Then it takes down the proxies
00202    and tells the service that we're not interested in being
00203    its friend anymore either. */
00204 static void
00205 indicator_service_manager_dispose (GObject *object)
00206 {
00207        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(object);
00208 
00209        /* Removing the idle task to restart if it exists. */
00210        if (priv->restart_source != 0) {
00211               g_source_remove(priv->restart_source);
00212        }
00213        /* Block any restart calls */
00214        priv->restart_source = -1;
00215 
00216        /* If we were connected we need to make sure to
00217           tell people that it's no longer the case. */
00218        if (priv->connected) {
00219               priv->connected = FALSE;
00220               g_signal_emit(object, signals[CONNECTION_CHANGE], 0, FALSE, TRUE);
00221        }
00222 
00223        if (priv->name_watcher != 0) {
00224               g_dbus_connection_signal_unsubscribe(g_dbus_proxy_get_connection(priv->service_proxy),
00225                                                    priv->name_watcher);
00226               priv->name_watcher = 0;
00227        }
00228 
00229        /* If we're still getting the proxy, stop looking so we
00230           can then clean up some more. */
00231        if (priv->service_proxy_cancel != NULL) {
00232               g_cancellable_cancel(priv->service_proxy_cancel);
00233               g_object_unref(priv->service_proxy_cancel);
00234               priv->service_proxy_cancel = NULL;
00235        }
00236 
00237        /* If we've sent a watch, cancel looking for the reply before
00238           sending the unwatch */
00239        if (priv->watch_cancel != NULL) {
00240               g_cancellable_cancel(priv->watch_cancel);
00241               g_object_unref(priv->watch_cancel);
00242               priv->watch_cancel = NULL;
00243        }
00244 
00245        /* If we have a proxy, tell it we're shutting down.  Just
00246           to be polite about it. */
00247        if (priv->service_proxy != NULL) {
00248               unwatch(priv->service_proxy);
00249        }
00250 
00251        /* Destory our service proxy, we won't need it. */
00252        if (priv->service_proxy != NULL) {
00253               g_object_unref(G_OBJECT(priv->service_proxy));
00254               priv->service_proxy = NULL;
00255        }
00256 
00257        /* Let's see if our parents want to do anything. */
00258        G_OBJECT_CLASS (indicator_service_manager_parent_class)->dispose (object);
00259        return;
00260 }
00261 
00262 /* Ironically, we don't allocate a lot of memory ourselves. */
00263 static void
00264 indicator_service_manager_finalize (GObject *object)
00265 {
00266        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(object);
00267 
00268        if (priv->name != NULL) {
00269               g_free(priv->name);
00270               priv->name = NULL;
00271        }
00272 
00273        G_OBJECT_CLASS (indicator_service_manager_parent_class)->finalize (object);
00274        return;
00275 }
00276 
00277 /* Either copies the name into the private variable or
00278    sets the version.  Do it wrong and it'll get upset. */
00279 static void
00280 set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
00281 {
00282        IndicatorServiceManager * self = INDICATOR_SERVICE_MANAGER(object);
00283        g_return_if_fail(self != NULL);
00284 
00285        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(self);
00286        g_return_if_fail(priv != NULL);
00287 
00288        switch (prop_id) {
00289        /* *********************** */
00290        case PROP_NAME:
00291               if (priv->name != NULL) {
00292                      g_error("Name can not be set twice!");
00293                      return;
00294               }
00295               priv->name = g_value_dup_string(value);
00296               start_service(self);
00297               break;
00298        /* *********************** */
00299        case PROP_VERSION:
00300               priv->this_service_version = g_value_get_uint(value);
00301               break;
00302        /* *********************** */
00303        default:
00304               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
00305               break;
00306        }
00307 
00308        return;
00309 }
00310 
00311 /* Grabs the values from the private variables and
00312    puts them into the value. */
00313 static void
00314 get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
00315 {
00316        IndicatorServiceManager * self = INDICATOR_SERVICE_MANAGER(object);
00317        g_return_if_fail(self != NULL);
00318 
00319        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(self);
00320        g_return_if_fail(priv != NULL);
00321 
00322        switch (prop_id) {
00323        /* *********************** */
00324        case PROP_NAME:
00325               g_value_set_string(value, priv->name);
00326               break;
00327        /* *********************** */
00328        case PROP_VERSION:
00329               g_value_set_uint(value, priv->this_service_version);
00330               break;
00331        /* *********************** */
00332        default:
00333               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
00334               break;
00335        }
00336 
00337        return;
00338 }
00339 
00340 /* Small little function to make a long function call a little
00341    bit cleaner. */
00342 static void
00343 unwatch (GDBusProxy * proxy)
00344 {
00345        g_dbus_proxy_call(proxy,
00346                          "UnWatch",
00347                          NULL,   /* parameters */
00348                          G_DBUS_CALL_FLAGS_NONE,
00349                          -1,     /* timeout */
00350                          NULL,   /* cancelable */
00351                          NULL,   /* callback */
00352                          NULL);  /* user data */
00353        return;
00354 }
00355 
00356 /* A callback from telling a service that we want to watch
00357    it.  It gives us the service API version and the version
00358    of the other APIs it supports.  We check both of those.
00359    If they don't match then we unwatch it.  Otherwise, we
00360    signal a connection change to tell the rest of the world
00361    that we have a service now.  */
00362 static void
00363 watch_cb (GObject * object, GAsyncResult * res, gpointer user_data)
00364 {
00365        GError * error = NULL;
00366        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(user_data);
00367 
00368        GVariant * params = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error);
00369 
00370        if (error != NULL) {
00371               g_warning("Unable to set watch on '%s': '%s'", priv->name, error->message);
00372               g_error_free(error);
00373               start_service_again(INDICATOR_SERVICE_MANAGER(user_data));
00374               return;
00375        }
00376 
00377        guint service_api_version;
00378        guint this_service_version;
00379 
00380        g_variant_get(params, "(uu)", &service_api_version, &this_service_version);
00381        g_variant_unref(params);
00382 
00383        /* We've done it, now let's stop counting. */
00384        /* Note: we're not checking versions.  Because, the hope is that
00385           the guy holding the name we want with the wrong version will
00386           drop and we can start another service quickly. */
00387        priv->restart_count = 0;
00388 
00389        if (service_api_version != INDICATOR_SERVICE_VERSION) {
00390               g_warning("Service is using a different version of the service interface.  Expecting %d and got %d.", INDICATOR_SERVICE_VERSION, service_api_version);
00391               unwatch(priv->service_proxy);
00392 
00393               /* Let's make us wait a little while, then try again */
00394               priv->restart_count = TIMEOUT_A_LITTLE_WHILE;
00395               start_service_again(INDICATOR_SERVICE_MANAGER(user_data));
00396               return;
00397        }
00398 
00399        if (this_service_version != priv->this_service_version) {
00400               g_warning("Service is using a different API version than the manager.  Expecting %d and got %d.", priv->this_service_version, this_service_version);
00401               unwatch(priv->service_proxy);
00402 
00403               /* Let's make us wait a little while, then try again */
00404               priv->restart_count = TIMEOUT_A_LITTLE_WHILE;
00405               start_service_again(INDICATOR_SERVICE_MANAGER(user_data));
00406               return;
00407        }
00408 
00409        if (!priv->connected) {
00410               priv->connected = TRUE;
00411               g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, TRUE, TRUE);
00412        }
00413 
00414        return;
00415 }
00416 
00417 /* The function that handles getting us connected to the service.
00418    In many cases it will start the service, but if the service
00419    is already there it just allocates the service proxy and acts
00420    like it was no big deal. */
00421 static void
00422 start_service (IndicatorServiceManager * service)
00423 {
00424        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(service);
00425 
00426        g_return_if_fail(priv->name != NULL);
00427 
00428        if (priv->service_proxy_cancel != NULL) {
00429               /* A service proxy is being gotten currently */
00430               return;
00431        }
00432 
00433        if (priv->service_proxy != NULL) {
00434               g_object_unref(priv->service_proxy);
00435               priv->service_proxy = NULL;
00436        }
00437 
00438        priv->service_proxy_cancel = g_cancellable_new();
00439 
00440        g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION,
00441                                 G_DBUS_PROXY_FLAGS_NONE,
00442                                 interface_info,
00443                                 priv->name,
00444                                 INDICATOR_SERVICE_OBJECT,
00445                                 INDICATOR_SERVICE_INTERFACE,
00446                                 priv->service_proxy_cancel,
00447                                 service_proxy_cb,
00448                                 service);
00449 
00450        return;
00451 }
00452 
00453 /* Callback from trying to create the proxy for the service, this
00454    could include starting the service.  Sometime it'll fail and
00455    we'll try to start that dang service again! */
00456 static void
00457 service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
00458 {
00459        GError * error = NULL;
00460 
00461        IndicatorServiceManager * service = INDICATOR_SERVICE_MANAGER(user_data);
00462        g_return_if_fail(service != NULL);
00463 
00464        GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
00465 
00466        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(user_data);
00467 
00468        if (priv->service_proxy_cancel != NULL) {
00469               g_object_unref(priv->service_proxy_cancel);
00470               priv->service_proxy_cancel = NULL;
00471        }
00472 
00473        if (error != NULL) {
00474               /* Unable to create the proxy, eh, let's try again
00475                  in a bit */
00476               g_error_free(error);
00477               start_service_again(service);
00478               return;
00479        }
00480 
00481        gchar * name = g_dbus_proxy_get_name_owner(proxy);
00482        if (name == NULL) {
00483               /* Hmm, since creating the proxy should start it, it seems very
00484                  odd that it wouldn't have an owner at this point.  But, all
00485                  we can do is try again. */
00486               g_object_unref(proxy);
00487               start_service_again(service);
00488               return;
00489        }
00490        g_free(name);
00491 
00492        /* Okay, we're good to grab the proxy at this point, we're
00493           sure that it's ours. */
00494        priv->service_proxy = proxy;
00495 
00496        /* Signal for drop */
00497        priv->name_watcher = g_dbus_connection_signal_subscribe(
00498                                           g_dbus_proxy_get_connection(proxy),
00499                                           "org.freedesktop.DBus",
00500                                           "org.freedesktop.DBus",
00501                                           "NameOwnerChanged",
00502                                           "/org/freedesktop/DBus",
00503                                           g_dbus_proxy_get_name(proxy),
00504                                           G_DBUS_SIGNAL_FLAGS_NONE,
00505                                           service_proxy_name_changed,
00506                                           user_data,
00507                                           NULL);
00508 
00509        /* Build cancelable if we need it */
00510        if (priv->watch_cancel == NULL) {
00511               priv->watch_cancel = g_cancellable_new();
00512        }
00513 
00514        /* Send watch */
00515        g_dbus_proxy_call(priv->service_proxy,
00516                          "Watch",
00517                          NULL, /* params */
00518                          G_DBUS_CALL_FLAGS_NONE,
00519                          -1,
00520                          priv->watch_cancel,
00521                          watch_cb,
00522                          user_data);
00523 
00524        return;
00525 }
00526 
00527 /* Responds to the name owner changing of the proxy, this
00528    usually means the service died.  We're dropping the proxy
00529    and recreating it so that it'll restart the service. */
00530 static void
00531 service_proxy_name_changed (GDBusConnection * connection, const gchar * sender_name,
00532                             const gchar * object_path, const gchar * interface_name,
00533                             const gchar * signal_name, GVariant * parameters,
00534                             gpointer user_data)
00535 
00536 {
00537        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(user_data);
00538 
00539        const gchar * new_name = NULL;
00540        const gchar * prev_name = NULL;
00541        g_variant_get(parameters, "(&s&s&s)", NULL, &prev_name, &new_name);
00542 
00543        if (new_name == NULL || new_name[0] == 0) {
00544               if (priv->connected) {
00545                      priv->connected = FALSE;
00546                      g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, FALSE, TRUE);
00547               }
00548 
00549               start_service_again(INDICATOR_SERVICE_MANAGER(user_data));
00550        } else {
00551               /* If we weren't connected before, we are now.  Let's tell the
00552                  world! */
00553               if (!priv->connected) {
00554                      priv->connected = TRUE;
00555                      g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, TRUE, TRUE);
00556               }
00557 
00558               /* If the names are both valid, and they're not the same, it means that
00559                  we've actually changed.  So we need to tell the new guy that we're
00560                  watching them */
00561               if (new_name != NULL && prev_name != NULL && new_name[0] != 0 && prev_name != 0 && g_strcmp0(prev_name, new_name) != 0) {
00562                      /* Send watch */
00563                      g_dbus_proxy_call(priv->service_proxy,
00564                                        "Watch",
00565                                        NULL, /* params */
00566                                        G_DBUS_CALL_FLAGS_NONE,
00567                                        -1,
00568                                        priv->watch_cancel,
00569                                        watch_cb,
00570                                        user_data);
00571               }
00572        }
00573 
00574        return;
00575 }
00576 
00577 /* The callback that starts the service for real after
00578    the timeout as determined in 'start_service_again'.
00579    This could be in the idle or a timer. */
00580 static gboolean
00581 start_service_again_cb (gpointer data)
00582 {
00583        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(data);
00584        priv->restart_count++;
00585        g_debug("Restarting service '%s' count %d", priv->name, priv->restart_count);
00586        start_service(INDICATOR_SERVICE_MANAGER(data));
00587        priv->restart_source = 0;
00588        return FALSE;
00589 }
00590 
00591 /* This function tries to start a new service, perhaps
00592    after a timeout that it determines.  The real issue
00593    here is that it throttles restarting if we're not
00594    being successful. */
00595 static void
00596 start_service_again (IndicatorServiceManager * manager)
00597 {
00598        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(manager);
00599 
00600        /* If we've already got a restart source running then
00601           let's not do this again. */
00602        if (priv->restart_source != 0) {
00603               return;
00604        }
00605 
00606        /* Allow the restarting to be disabled */
00607        if (g_getenv(TIMEOUT_ENV_NAME)) {
00608               return;
00609        }
00610 
00611        if (priv->restart_count == 0) {
00612               /* First time, do it in idle */
00613               g_idle_add(start_service_again_cb, manager);
00614        } else {
00615               /* Not our first time 'round the block.  Let's slow this down. */
00616               if (priv->restart_count > 16)
00617                      priv->restart_count = 16; /* Not more than 1024x */
00618               priv->restart_source = g_timeout_add((1 << priv->restart_count) * TIMEOUT_MULTIPLIER, start_service_again_cb, manager);
00619        }
00620 
00621        return;
00622 }
00623 
00624 /* API */
00625 
00638 IndicatorServiceManager *
00639 indicator_service_manager_new (const gchar * dbus_name)
00640 {
00641        GObject * obj = g_object_new(INDICATOR_SERVICE_MANAGER_TYPE,
00642                                     PROP_NAME_S, dbus_name,
00643                                     NULL);
00644 
00645        return INDICATOR_SERVICE_MANAGER(obj);
00646 }
00647 
00662 IndicatorServiceManager *
00663 indicator_service_manager_new_version (const gchar * dbus_name, guint version)
00664 {
00665        GObject * obj = g_object_new(INDICATOR_SERVICE_MANAGER_TYPE,
00666                                     PROP_NAME_S, dbus_name,
00667                                     PROP_VERSION_S, version,
00668                                     NULL);
00669 
00670        return INDICATOR_SERVICE_MANAGER(obj);
00671 }
00672 
00682 gboolean
00683 indicator_service_manager_connected (IndicatorServiceManager * sm)
00684 {
00685        g_return_val_if_fail(INDICATOR_IS_SERVICE_MANAGER(sm), FALSE);
00686        IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(sm);
00687        return priv->connected;
00688 }
00689 
00701 void
00702 indicator_service_manager_set_refresh (IndicatorServiceManager * sm, guint time_in_ms)
00703 {
00704 
00705        return;
00706 }