Exemplo n.º 1
0
static void
is_indicator_set_property(GObject *object,
                          guint property_id, const GValue *value, GParamSpec *pspec)
{
  IsIndicator *self = IS_INDICATOR(object);
  IsIndicatorPrivate *priv = self->priv;
  IsManager *manager;

  switch (property_id)
  {
    case PROP_APPLICATION:
      g_assert(!priv->application);
      priv->application = g_object_ref(g_value_get_object(value));
      manager = is_application_get_manager(priv->application);
      g_signal_connect(manager, "sensor-enabled",
                       G_CALLBACK(sensor_enabled), self);
      g_signal_connect(manager, "sensor-disabled",
                       G_CALLBACK(sensor_disabled), self);
      g_signal_connect(manager, "sensor-added",
                       G_CALLBACK(sensor_added), self);
      break;
    case PROP_PRIMARY_SENSOR_PATH:
      is_indicator_set_primary_sensor_path(self, g_value_get_string(value));
      break;
    case PROP_DISPLAY_FLAGS:
      is_indicator_set_display_flags(self, g_value_get_int(value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
      break;
  }
}
Exemplo n.º 2
0
static void
is_max_plugin_deactivate(PeasActivatable *activatable)
{
  IsMaxPlugin *self = IS_MAX_PLUGIN(activatable);
  IsMaxPluginPrivate *priv = self->priv;
  IsManager *manager;
  GSList *sensors, *_list;

  is_debug("max", "dettaching from signals");

  manager = is_application_get_manager(priv->application);

  is_manager_remove_path(manager, MAX_SENSOR_PATH);
  sensors = is_manager_get_enabled_sensors_list(manager);
  for (_list = sensors;
       _list != NULL;
       _list = _list->next)
  {
    IsSensor *sensor = IS_SENSOR(_list->data);
    on_sensor_disabled(manager, sensor, self);
    g_object_unref(sensor);
  }
  g_slist_free(sensors);
  g_signal_handlers_disconnect_by_func(manager,
                                       G_CALLBACK(on_sensor_enabled), self);
  g_signal_handlers_disconnect_by_func(manager,
                                       G_CALLBACK(on_sensor_disabled), self);

}
Exemplo n.º 3
0
static void
is_indicator_dispose(GObject *object)
{
  IsIndicator *self = (IsIndicator *)object;
  IsIndicatorPrivate *priv = self->priv;
  IsManager *manager;
  GSList *sensors, *_list;

  manager = is_application_get_manager(priv->application);
  g_signal_handlers_disconnect_by_func(manager, sensor_enabled, self);
  g_signal_handlers_disconnect_by_func(manager, sensor_disabled, self);
  g_signal_handlers_disconnect_by_func(manager, sensor_added, self);
  /* fake disabling of any sensors */
  sensors = is_manager_get_enabled_sensors_list(manager);
  for (_list = sensors; _list != NULL; _list = _list->next)
  {
    IsSensor *sensor = IS_SENSOR(_list->data);
    _sensor_disabled(IS_SENSOR(_list->data), self);
    g_object_unref(sensor);
  }
  g_slist_free(sensors);

#if !HAVE_APPINDICATOR
  g_object_set_data(G_OBJECT(self), "indicator-menu", NULL);
#endif
  G_OBJECT_CLASS(is_indicator_parent_class)->dispose(object);
}
Exemplo n.º 4
0
static gboolean
fake_add_enable_sensors(IsIndicator *self)
{
  IsManager *manager;
  GSList *sensors, *_list;
  gint i = 0;

  manager = is_application_get_manager(self->priv->application);

  /* fake addition of any sensors */
  sensors = is_manager_get_all_sensors_list(manager);
  for (_list = sensors; _list != NULL; _list = _list->next)
  {
    IsSensor *sensor = IS_SENSOR(_list->data);
    sensor_added(manager, IS_SENSOR(_list->data), self);
    g_object_unref(sensor);
  }
  g_slist_free(sensors);

  /* fake enabling of any sensors */
  sensors = is_manager_get_enabled_sensors_list(manager);
  for (_list = sensors; _list != NULL; _list = _list->next)
  {
    IsSensor *sensor = IS_SENSOR(_list->data);
    sensor_enabled(manager, IS_SENSOR(_list->data), i++,
                   self);
    g_object_unref(sensor);
  }
  g_slist_free(sensors);

  return FALSE;
}
Exemplo n.º 5
0
void is_indicator_set_primary_sensor_path(IsIndicator *self,
    const gchar *path)
{
  IsIndicatorPrivate *priv;

  g_return_if_fail(IS_IS_INDICATOR(self));

  priv = self->priv;

  if (g_strcmp0(priv->primary_sensor_path, path) != 0 &&
      g_strcmp0(path, "") != 0)
  {
    IsSensor *sensor;

    is_debug("indicator", "new primary sensor path %s (previously %s)",
             path, priv->primary_sensor_path);

    /* uncheck current primary sensor label - may be NULL as is
     * already disabled */
    if (priv->primary)
    {
      GtkCheckMenuItem *item;
      item = (GtkCheckMenuItem *)(g_object_get_data(G_OBJECT(priv->primary),
                                  "menu-item"));
      if (item)
      {
        gtk_check_menu_item_set_active(item, FALSE);
      }
      g_object_unref(priv->primary);
    }

    g_free(priv->primary_sensor_path);
    priv->primary_sensor_path = g_strdup(path);

    is_debug("indicator", "Setting primary sensor path to: %s", path);

    /* try and activate this sensor if it exists */
    sensor = is_manager_get_sensor(is_application_get_manager(priv->application),
                                   priv->primary_sensor_path);
    if (sensor)
    {
      GtkCheckMenuItem *item = (GtkCheckMenuItem *)(g_object_get_data(G_OBJECT(sensor),
                               "menu-item"));
      /* take reference from manager */
      priv->primary = sensor;
      if (item)
      {
        gtk_check_menu_item_set_active(item, TRUE);
        update_sensor_menu_item_label(self, sensor,
                                      GTK_MENU_ITEM(item));
      }
    }

    g_object_notify_by_pspec(G_OBJECT(self),
                             properties[PROP_PRIMARY_SENSOR_PATH]);
  }
}
static void
manager_selection_changed(GtkTreeSelection *selection,
			  IsPreferencesDialog *self)
{
	IsSensor *sensor;
	gboolean sensitive = FALSE;

	sensor = is_manager_get_selected_sensor(is_application_get_manager(self->priv->application));
	if (sensor) {
		sensitive = TRUE;
		g_object_unref(sensor);
	}
	gtk_widget_set_sensitive(self->priv->sensor_properties_button,
				 sensitive);
}
Exemplo n.º 7
0
static void
is_fake_plugin_activate(PeasActivatable *activatable)
{
	IsFakePlugin *self = IS_FAKE_PLUGIN(activatable);
	IsFakePluginPrivate *priv = self->priv;
	int i;
	int n_fans = 0;

	/* generate some fake sensors */
	for (i = 0; i < 5; i++) {
		gchar *path;
		gchar *label;
		IsSensor *sensor;

		path = g_strdup_printf("fake/sensor%d", i);
		if (g_rand_boolean(priv->rand)) {
			n_fans++;
			sensor = is_fan_sensor_new(path);
			is_sensor_set_low_value(sensor, 100.0);
			is_sensor_set_high_value(sensor, 5000.0);
			label = g_strdup_printf(_("Fake Fan %d"),
						n_fans);

		} else {
			sensor = is_temperature_sensor_new(path);
			is_sensor_set_icon(sensor, IS_STOCK_CPU);
			label = g_strdup_printf(_("Fake CPU %d"),
						i - n_fans + 1);
		}
		/* no decimal places to display */
		is_sensor_set_digits(sensor, 0);
		is_sensor_set_label(sensor, label);
		/* connect to update-value signal */
		g_signal_connect(sensor, "update-value",
				 G_CALLBACK(update_sensor_value),
				 self);
		is_manager_add_sensor(is_application_get_manager(priv->application),
				      sensor);
		g_free(label);
		g_free(path);
	}
}
Exemplo n.º 8
0
static void
is_max_plugin_activate(PeasActivatable *activatable)
{
  IsMaxPlugin *self = IS_MAX_PLUGIN(activatable);
  IsMaxPluginPrivate *priv = self->priv;
  IsManager *manager;
  GSList *sensors, *_list;
  int i = 0;

  manager = is_application_get_manager(priv->application);

  // create our virtual sensor which mimics the current highest value sensor's
  // value and label
  is_debug("max", "creating virtual sensor");
  priv->sensor = is_sensor_new(MAX_SENSOR_PATH);
  is_sensor_set_label(priv->sensor, "Δ");
  is_sensor_set_icon(priv->sensor, IS_STOCK_CHIP);
  is_sensor_set_value(priv->sensor, 0.0);
  is_sensor_set_units(priv->sensor, "");
  is_sensor_set_digits(priv->sensor, 1);
  is_manager_add_sensor(manager, priv->sensor);

  is_debug("max", "attaching to signals");
  sensors = is_manager_get_enabled_sensors_list(manager);
  for (_list = sensors;
       _list != NULL;
       _list = _list->next)
  {
    IsSensor *sensor = IS_SENSOR(_list->data);
    on_sensor_enabled(manager, sensor, i, self);
    g_object_unref(sensor);
    i++;
  }
  g_slist_free(sensors);
  g_signal_connect(manager, "sensor-enabled",
                   G_CALLBACK(on_sensor_enabled), self);
  g_signal_connect(manager, "sensor-disabled",
                   G_CALLBACK(on_sensor_disabled), self);

}
Exemplo n.º 9
0
static void
is_udisks_plugin_activate(PeasActivatable *activatable)
{
	IsUdisksPlugin *self = IS_UDISKS_PLUGIN(activatable);
	IsUdisksPluginPrivate *priv = self->priv;
	GDBusProxy *proxy;
	GError *error = NULL;
	GVariant *container, *paths;
	GVariantIter iter;
	gchar *path;

	priv->connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
	if (!priv->connection)
	{
		is_warning("udisks", "Failed to open connection to system dbus: %s",
			  error->message);
		g_error_free(error);
		goto out;
	}

	/* This is the proxy which is only used once during the enumeration of
	 * the device object paths
	 */
	proxy = g_dbus_proxy_new_sync(priv->connection,
				      G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
				      G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,

				      NULL,
				      UDISKS_BUS_NAME,
				      UDISKS_OBJECT_PATH,
				      UDISKS_INTERFACE_NAME,
				      NULL, &error);

	if (!proxy) {
		is_warning("udisks", "Error getting proxy to udisks on system bus: %s",
			  error->message);
		g_error_free(error);
		goto out;
	}

	/* The object paths of the disks are enumerated and placed in an array
	 * of object paths
	 */
	container = g_dbus_proxy_call_sync(proxy, "EnumerateDevices", NULL,
				       G_DBUS_CALL_FLAGS_NONE, -1, NULL,
				       &error);
	if (!container) {
		is_warning("udisks", "Failed to enumerate disk devices: %s",
			  error->message);
		g_error_free(error);
		g_object_unref(proxy);
		goto out;
	}

	paths = g_variant_get_child_value(container, 0);
	g_variant_unref(container);

	g_variant_iter_init(&iter, paths);
	while (g_variant_iter_loop(&iter, "o", &path)) {
		/* This proxy is used to get the required data in order to build
		 * up the list of sensors
		 */
		GDBusProxy *sensor_proxy;
		GVariant *model, *smart_available;
		IsSensor *sensor;
		gchar *name, *sensor_path;

		sensor_proxy = g_dbus_proxy_new_sync(priv->connection,
						     G_DBUS_PROXY_FLAGS_NONE,
						     NULL,
						     UDISKS_BUS_NAME,
						     path,
						     UDISKS_DEVICE_INTERFACE_NAME,
						     NULL,
						     &error);

		if (!sensor_proxy) {
			is_debug("udisks", "error getting sensor proxy for disk %s: %s",
				path, error->message);
			g_clear_error(&error);
			g_object_unref(sensor_proxy);
			continue;
		}

		smart_available = g_dbus_proxy_get_cached_property(sensor_proxy,
								   "DriveAtaSmartIsAvailable");
		if (!smart_available) {
			is_debug("udisks", "error getting smart status for disk %s",
				path);
			g_object_unref(sensor_proxy);
			continue;
		}
		if (!g_variant_get_boolean(smart_available)) {
			is_debug("udisks", "drive %s does not support SMART monitoring, ignoring...",
				path);
			g_variant_unref(smart_available);
			g_object_unref(sensor_proxy);
			continue;
		}

		g_variant_unref(smart_available);
		model = g_dbus_proxy_get_cached_property(sensor_proxy,
							 "DriveModel");
		if (!model) {
			is_debug("udisks", "error getting drive model for disk %s",
				path);
			g_clear_error(&error);
			g_object_unref(sensor_proxy);
			continue;
		}
		name = g_path_get_basename(path);
		sensor_path = g_strdup_printf("udisks/%s", name);
		sensor = is_temperature_sensor_new(sensor_path);
		is_sensor_set_label(sensor, g_variant_get_string(model, NULL));
		is_sensor_set_digits(sensor, 0);
		is_sensor_set_icon(sensor, IS_STOCK_DISK);
		/* only update every minute to avoid waking disk too much */
		is_sensor_set_update_interval(sensor, 60);
		g_signal_connect(sensor, "update-value",
				 G_CALLBACK(update_sensor_value), self);
		is_manager_add_sensor(is_application_get_manager(priv->application),
                                      sensor);

		g_free(sensor_path);
		g_free(name);
		g_object_unref(sensor);
		g_object_unref(sensor_proxy);
	}
	g_variant_unref(paths);
	g_object_unref(proxy);

out:
	return;
}
static void
is_nvidia_plugin_activate(PeasActivatable *activatable)
{
	IsNvidiaPlugin *self = IS_NVIDIA_PLUGIN(activatable);
	IsNvidiaPluginPrivate *priv = self->priv;
	Bool ret;
	int event_base, error_base;
	gint n;
	int i;

	/* search for sensors and add them to manager */
	if (!priv->inited) {
		is_warning("nvidia", "not inited, unable to find sensors");
		goto out;
	}

	is_debug("nvidia", "searching for sensors");

	/* check if the NV-CONTROL extension is available on this X
         * server */
	ret = XNVCTRLQueryExtension(priv->display, &event_base, &error_base);
	if (!ret) {
		goto out;
	}

	/* get number of GPUs, then for each GPU get any thermal_sensors and
	   coolers used by it */
	ret = XNVCTRLQueryTargetCount(priv->display,
				      NV_CTRL_TARGET_TYPE_GPU,
				      &n);
	if (!ret) {
		goto out;
	}

	for (i = 0; i < n; i++) {
		guint j;
		char *label = NULL;
		ret = XNVCTRLQueryTargetStringAttribute(priv->display,
							NV_CTRL_TARGET_TYPE_GPU,
							i,
							0,
							NV_CTRL_STRING_PRODUCT_NAME,
							&label);
		for (j = 0; j < G_N_ELEMENTS(map); j++) {
			int32_t *data;
			int len;
			int k;

			ret = XNVCTRLQueryTargetBinaryData(priv->display,
							   NV_CTRL_TARGET_TYPE_GPU,
							   i,
							   0,
							   map[j].gpu_attribute,
							   (unsigned char **)&data,
							   &len);
			if (!ret) {
				continue;
			}
			/* data[0] contains number of sensors, and each sensor
			   indice follows */
			for (k = 1; k <= data[0]; k++) {
				int idx = data[k];
				gint value;
				IsSensor *sensor;
				gchar *path;

				ret = XNVCTRLQueryTargetAttribute(priv->display,
								  map[j].target,
								  idx,
								  0,
								  map[j].attribute,
								  &value);
				if (!ret) {
					continue;
				}

				path = g_strdup_printf("nvidia/%s%d", map[j].description, idx);
				if (map[j].target == NV_CTRL_TARGET_TYPE_COOLER) {
					/* fan sensors are given as a percentage
					   from 0 to 100 */
					sensor = is_sensor_new(path);
					is_sensor_set_icon(sensor, IS_STOCK_FAN);
					is_sensor_set_units(sensor, "%");
					is_sensor_set_low_value(sensor, 0.0);
					is_sensor_set_high_value(sensor, 100.0);
				} else {
					sensor = is_temperature_sensor_new(path);
					is_sensor_set_icon(sensor, IS_STOCK_GPU);
				}
				/* no decimal places to display */
				is_sensor_set_digits(sensor, 0);
				is_sensor_set_label(sensor, label);
				/* connect to update-value signal */
				g_signal_connect(sensor, "update-value",
						 G_CALLBACK(update_sensor_value),
						 self);
				is_manager_add_sensor(is_application_get_manager(priv->application),
                                                      sensor);
				g_free(path);
			}
			free(data);
		}
		free(label);
	}

out:
	return;
}
Exemplo n.º 11
0
static void
is_preferences_dialog_set_property(GObject *object,
                                   guint property_id, const GValue *value, GParamSpec *pspec)
{
  IsPreferencesDialog *self = IS_PREFERENCES_DIALOG(object);
  IsPreferencesDialogPrivate *priv = self->priv;
  GtkWidget *scrolled_window;
  IsManager *manager;
  IsIndicatorDisplayFlags flags;

  switch (property_id)
  {
    case PROP_APPLICATION:
      priv->application = g_object_ref(g_value_get_object(value));
      gtk_widget_set_sensitive(priv->display_icon_check_button, TRUE);
      gtk_widget_set_sensitive(priv->display_label_check_button, TRUE);
      gtk_widget_set_sensitive(priv->display_value_check_button, TRUE);

      flags = g_settings_get_int(self->priv->indicator_settings,
                                 "display-flags");
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->display_icon_check_button),
                                   flags & IS_INDICATOR_DISPLAY_ICON);
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->display_label_check_button),
                                   flags & IS_INDICATOR_DISPLAY_LABEL);
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->display_value_check_button),
                                   flags & IS_INDICATOR_DISPLAY_VALUE);
      g_signal_connect(priv->display_icon_check_button, "toggled",
                       G_CALLBACK(display_icon_toggled),
                       self);
      g_signal_connect(priv->display_label_check_button, "toggled",
                       G_CALLBACK(display_label_toggled),
                       self);
      g_signal_connect(priv->display_value_check_button, "toggled",
                       G_CALLBACK(display_value_toggled),
                       self);
      g_signal_connect(priv->indicator_settings, "changed::display-flags",
                       G_CALLBACK(settings_display_flags_changed),
                       self);
      manager = is_application_get_manager(priv->application);
      g_signal_connect(manager, "row-activated",
                       G_CALLBACK(manager_row_activated), self);
      /* control properties button sensitivity */
      g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(manager)),
                       "changed", G_CALLBACK(manager_selection_changed),
                       self);
      /* set state of autostart checkbutton */
      gtk_widget_set_sensitive(priv->autostart_check_button, TRUE);
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->autostart_check_button),
                                   is_application_get_autostart(priv->application));
      gtk_widget_set_sensitive(priv->celsius_radio_button, TRUE);
      gtk_widget_set_sensitive(priv->fahrenheit_radio_button, TRUE);

      switch (is_application_get_temperature_scale(priv->application))
      {
        case IS_TEMPERATURE_SENSOR_SCALE_CELSIUS:
          gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->celsius_radio_button),
                                       TRUE);
          break;

        case IS_TEMPERATURE_SENSOR_SCALE_FAHRENHEIT:
          gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->fahrenheit_radio_button),
                                       TRUE);
          break;

        case IS_TEMPERATURE_SENSOR_SCALE_INVALID:
        case NUM_IS_TEMPERATURE_SENSOR_SCALE:
        default:
          g_assert_not_reached();
      }
      g_signal_connect(priv->autostart_check_button, "toggled",
                       G_CALLBACK(autostart_toggled), priv->application);
      g_signal_connect(priv->application, "notify::autostart",
                       G_CALLBACK(application_notify_autostart),
                       priv->autostart_check_button);
      scrolled_window = gtk_scrolled_window_new(NULL, NULL);
      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
                                     GTK_POLICY_AUTOMATIC,
                                     GTK_POLICY_AUTOMATIC);
      gtk_container_add(GTK_CONTAINER(scrolled_window),
                        GTK_WIDGET(manager));
      gtk_widget_set_hexpand(scrolled_window, TRUE);
      gtk_widget_set_vexpand(scrolled_window, TRUE);
      gtk_grid_attach(GTK_GRID(priv->grid),
                      scrolled_window,
                      0, 4,
                      3, 1);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
      break;
  }
}
int main(int argc, char **argv)
{
	IsApplication *application;
        GSettings *settings;
        IsManager *manager;
	gchar *plugin_dir;
	PeasEngine *engine;
	PeasExtensionSet *set;
	GError *error = NULL;

	gtk_init(&argc, &argv);

	if (!g_irepository_require(g_irepository_get_default(), "Peas", "1.0",
				   0, &error))
	{
		is_warning("main", "Could not load Peas repository: %s", error->message);
		g_error_free (error);
		error = NULL;
	}

	engine = peas_engine_get_default();
	g_signal_connect(engine, "notify::plugin-list",
			 G_CALLBACK(on_plugin_list_notify), NULL);

	/* add home dir to search path */
	plugin_dir = g_build_filename(g_get_user_config_dir(), PACKAGE,
				      "plugins", NULL);
	peas_engine_add_search_path(engine, plugin_dir, NULL);
	g_free(plugin_dir);

	/* add system path to search path */
	plugin_dir = g_build_filename(LIBDIR, PACKAGE, "plugins", NULL);
	peas_engine_add_search_path(engine, plugin_dir, NULL);
	g_free(plugin_dir);

        /* init notifications */
        is_notify_init();
	application = is_application_new();
        settings = g_settings_new("indicator-sensors.application");
        g_settings_bind(settings, "temperature-scale",
                        application, "temperature-scale",
                        G_SETTINGS_BIND_DEFAULT);

	/* create extension set and set manager as object */
	set = peas_extension_set_new(engine, PEAS_TYPE_ACTIVATABLE,
				     "object", application, NULL);

	/* activate all activatable extensions */
	peas_extension_set_call(set, "activate");

	/* and make sure to activate any ones which are found in the future */
	g_signal_connect(set, "extension-added",
			 G_CALLBACK(on_extension_added), application);
	g_signal_connect(set, "extension-removed",
			  G_CALLBACK(on_extension_removed), application);

        /* since all plugins are now inited show a notification if we detected
         * sensors but none are enabled - TODO: perhaps just open the pref's
         * dialog?? */
        manager = is_application_get_manager(application);
        GSList *sensors = is_manager_get_all_sensors_list(manager);
        if (sensors) {
                gchar **enabled_sensors = is_manager_get_enabled_sensors(manager);
                if (!g_strv_length(enabled_sensors)) {
                        is_notify(IS_NOTIFY_LEVEL_INFO,
                                  _("No Sensors Enabled For Monitoring"),
                                  _("Sensors detected but none are enabled for monitoring. To enable monitoring of sensors open the Preferences window and select the sensors to monitor"));
                }
                g_strfreev(enabled_sensors);
                g_slist_foreach(sensors, (GFunc)g_object_unref, NULL);
                g_slist_free(sensors);
        }

	gtk_main();

        g_object_unref(application);
        is_notify_uninit();

	return 0;
}
static void
is_aticonfig_plugin_activate(PeasActivatable *activatable)
{
	IsATIConfigPlugin *self = IS_ATICONFIG_PLUGIN(activatable);
        IsManager *manager;
        gchar *output = NULL;
	GError *error = NULL;
	GRegex *regex = NULL;
	GMatchInfo *match = NULL;
	gboolean ret;

        manager = is_application_get_manager(self->priv->application);

	/* search for sensors and add them to manager */
	is_debug("aticonfig", "searching for sensors");

	/* call aticonfig with --list-adapters to get available adapters,
	 * then test if each can do temperature and fan speed - if so add
	 * appropriate sensors */
	ret = g_spawn_command_line_sync("aticonfig --list-adapters",
					&output, NULL, NULL, &error);
	if (!ret) {
		is_warning("aticonfig", "Error calling aticonfig to detect available sensors: %s",
			   error->message);
		g_error_free(error);
		goto out;
	}

	regex = g_regex_new("^.*([0-9]+)\\. ([0-9][0-9]:[0-9][0-9]\\.[0-9])\\s*(.*?)\\s*$",
			    G_REGEX_MULTILINE, 0, &error);
	if (!regex) {
		is_warning("aticonfig", "Error compiling regex to detect listed sensors: %s",
			   error->message);
		g_error_free(error);
		goto out;
	}

	ret = g_regex_match(regex, output, 0, &match);
	if (!ret) {
		is_warning("aticonfig", "No sensors found in aticonfig output: %s", output);
		goto out;
	}
	while (g_match_info_matches(match)) {
		gint i;
		gchar *idx, *pci, *name;
		gdouble value;
		gchar *path;
		IsSensor *sensor;

		idx = g_match_info_fetch(match, 1);
		pci = g_match_info_fetch(match, 2);
		name = g_match_info_fetch(match, 3);

		i = g_ascii_strtoull(idx, NULL, 10);
		/* we have an adapter - see if we can get its temperature and
		   fanspeed */
		ret = aticonfig_get_temperature(self, i, &value, &error);
		if (!ret) {
			is_warning("aticonfig", "Error getting temperature for adapter %d: %s",
				   i, error->message);
			g_clear_error(&error);
		} else {
			path = g_strdup_printf("%s%d%s", ATICONFIG_PATH_PREFIX, i, _("Temperature"));
			sensor = is_temperature_sensor_new(path);
			is_sensor_set_label(sensor, name);
			is_sensor_set_icon(sensor, IS_STOCK_GPU);
			g_signal_connect(sensor, "update-value",
					 G_CALLBACK(update_sensor_value),
					 self);
			is_manager_add_sensor(manager, sensor);
			g_object_unref(sensor);
			g_free(path);
		}

		ret = aticonfig_get_fanspeed(self, i, &value, &error);
		if (!ret) {
			is_warning("aticonfig", "Error getting fanpeed for adapter %d: %s",
				   i, error->message);
			g_clear_error(&error);
		} else {
			path = g_strdup_printf("%s%d%s", ATICONFIG_PATH_PREFIX, i, _("Fan"));
			sensor = is_sensor_new(path);
			is_sensor_set_label(sensor, name);
			/* fan sensors are given as a percentage from 0 to 100 */
			is_sensor_set_units(sensor, "%");
			is_sensor_set_low_value(sensor, 0.0);
			is_sensor_set_high_value(sensor, 100.0);
			is_sensor_set_digits(sensor, 0);
			is_sensor_set_icon(sensor, IS_STOCK_FAN);
			g_signal_connect(sensor, "update-value",
					 G_CALLBACK(update_sensor_value),
					 self);
			is_manager_add_sensor(manager, sensor);
			g_object_unref(sensor);
			g_free(path);
		}

		g_free(idx);
		g_free(pci);
		g_free(name);

		g_match_info_next(match, &error);
	}

out:
	g_match_info_free(match);
	if (regex) {
		g_regex_unref(regex);
	}
	g_free(output);
	return;
}