Commit be692ac9 authored by Guido Gunther's avatar Guido Gunther Committed by Guido Gunther
Browse files

Add initial torch support



Add a simple torch quick setting.
Signed-off-by: Guido Gunther's avatarGuido Günther <guido.gunther@puri.sm>
parent 1309dcfa
Pipeline #59587 passed with stages
in 42 minutes and 39 seconds
......@@ -101,6 +101,8 @@
<xi:include href="xml/toplevel.xml"/>
<xi:include href="xml/toplevel-manager.xml"/>
<xi:include href="xml/toplevel-thumbnail.xml"/>
<xi:include href="xml/torch-info.xml"/>
<xi:include href="xml/torch-manager.xml"/>
<xi:include href="xml/wifiinfo.xml"/>
<xi:include href="xml/wifimanager.xml"/>
<xi:include href="xml/wwaninfo.xml"/>
......
......@@ -46,6 +46,7 @@ src/system-prompt.c
src/system-prompter.c
src/toplevel.c
src/toplevel-manager.c
src/torch-info.c
src/ui/activity.ui
src/ui/app-grid-button.ui
src/ui/app-grid.ui
......
......@@ -142,6 +142,10 @@ libphosh_sources = [
'toplevel-manager.h',
'toplevel-thumbnail.c',
'toplevel-thumbnail.h',
'torch-info.c',
'torch-info.h',
'torch-manager.c',
'torch-manager.h',
'toplevel.c',
'toplevel.h',
'wifiinfo.c',
......
......@@ -16,6 +16,7 @@
#include "quick-setting.h"
#include "settings/brightness.h"
#include "settings/gvc-channel-bar.h"
#include "torch-info.h"
#include "wwan/phosh-wwan-mm.h"
#include "rotateinfo.h"
#include "feedbackinfo.h"
......@@ -151,6 +152,20 @@ battery_setting_clicked_cb (PhoshSettings *self)
g_signal_emit (self, signals[SETTING_DONE], 0);
}
static void
torch_setting_clicked_cb (PhoshSettings *self)
{
PhoshShell *shell;
PhoshTorchManager *manager;
shell = phosh_shell_get_default ();
g_return_if_fail (PHOSH_IS_SHELL (shell));
manager = phosh_shell_get_torch_manager (shell);
g_return_if_fail (PHOSH_IS_TORCH_MANAGER (manager));
phosh_torch_manager_toggle (manager);
}
static void
change_volume (PhoshSettings *self,
int steps)
......@@ -502,6 +517,7 @@ phosh_settings_class_init (PhoshSettingsClass *klass)
g_type_ensure (PHOSH_TYPE_MEDIA_PLAYER);
g_type_ensure (PHOSH_TYPE_QUICK_SETTING);
g_type_ensure (PHOSH_TYPE_ROTATE_INFO);
g_type_ensure (PHOSH_TYPE_TORCH_INFO);
gtk_widget_class_bind_template_child (widget_class, PhoshSettings, box_settings);
gtk_widget_class_bind_template_child (widget_class, PhoshSettings, list_notifications);
......@@ -515,6 +531,7 @@ phosh_settings_class_init (PhoshSettingsClass *klass)
gtk_widget_class_bind_template_callback (widget_class, feedback_setting_long_pressed_cb);
gtk_widget_class_bind_template_callback (widget_class, on_media_player_raised);
gtk_widget_class_bind_template_callback (widget_class, rotation_setting_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, torch_setting_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, wifi_setting_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, wwan_setting_clicked_cb);
}
......
......@@ -47,6 +47,7 @@
#include "screen-saver-manager.h"
#include "session.h"
#include "system-prompter.h"
#include "torch-manager.h"
#include "util.h"
#include "wifiinfo.h"
#include "wwaninfo.h"
......@@ -97,6 +98,7 @@ typedef struct
PhoshFeedbackManager *feedback_manager;
PhoshBtManager *bt_manager;
PhoshWWan *wwan;
PhoshTorchManager *torch_manager;
/* sensors */
PhoshSensorProxyManager *sensor_proxy_manager;
......@@ -328,6 +330,7 @@ phosh_shell_dispose (GObject *object)
g_clear_object (&priv->notification_banner);
/* dispose managers in opposite order of declaration */
g_clear_object (&priv->torch_manager);
g_clear_object (&priv->wwan);
g_clear_object (&priv->bt_manager);
g_clear_object (&priv->feedback_manager);
......@@ -874,6 +877,21 @@ phosh_shell_get_wwan (PhoshShell *self)
}
PhoshTorchManager *
phosh_shell_get_torch_manager (PhoshShell *self)
{
PhoshShellPrivate *priv;
g_return_val_if_fail (PHOSH_IS_SHELL (self), NULL);
priv = phosh_shell_get_instance_private (self);
if (!priv->torch_manager)
priv->torch_manager = phosh_torch_manager_new ();
g_return_val_if_fail (PHOSH_IS_TORCH_MANAGER (priv->torch_manager), NULL);
return priv->torch_manager;
}
/**
* Returns the usable area in pixels usable by a client on the phone
* display
......
......@@ -8,14 +8,15 @@
#pragma once
#include "bt-manager.h"
#include "feedback-manager.h"
#include "lockscreen-manager.h"
#include "monitor-manager.h"
#include "monitor/monitor.h"
#include "lockscreen-manager.h"
#include "osk-manager.h"
#include "toplevel-manager.h"
#include "torch-manager.h"
#include "wifimanager.h"
#include "bt-manager.h"
#include "wwan/phosh-wwan-iface.h"
#include <gtk/gtk.h>
......@@ -52,6 +53,7 @@ PhoshWifiManager *phosh_shell_get_wifi_manager (PhoshShell *self);
PhoshFeedbackManager *phosh_shell_get_feedback_manager (PhoshShell *self);
PhoshBtManager *phosh_shell_get_bt_manager (PhoshShell *self);
PhoshWWan *phosh_shell_get_wwan (PhoshShell *self);
PhoshTorchManager *phosh_shell_get_torch_manager (PhoshShell *self);
void phosh_shell_fade_out (PhoshShell *self, guint timeout);
void phosh_shell_enable_power_save (PhoshShell *self, gboolean enable);
gboolean phosh_shell_started_by_display_manager(PhoshShell *self);
......
/*
* Copyright (C) 2020 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Author: Guido Günther <agx@sigxcpu.org>
*/
#define G_LOG_DOMAIN "phosh-torch-info"
#include "config.h"
#include "shell.h"
#include "torch-info.h"
#include "torch-manager.h"
/**
* SECTION:torch-info
* @short_description: A widget to display the torch status
* @Title: PhoshTorchInfo
*
* #PhoshTorchInfo displays the current torch status based on information
* from #PhoshTorchManager. To figure out if the widget should be shown
* the #PhoshTorchInfo:enabled property can be useful.
*/
enum {
PROP_0,
PROP_ENABLED,
PROP_PRESENT,
PROP_LAST_PROP
};
static GParamSpec *props[PROP_LAST_PROP];
struct _PhoshTorchInfo {
PhoshStatusIcon parent;
gboolean enabled;
gboolean present;
PhoshTorchManager *torch;
};
G_DEFINE_TYPE (PhoshTorchInfo, phosh_torch_info, PHOSH_TYPE_STATUS_ICON);
static void
phosh_torch_info_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
PhoshTorchInfo *self = PHOSH_TORCH_INFO (object);
switch (property_id) {
case PROP_ENABLED:
g_value_set_boolean (value, self->enabled);
break;
case PROP_PRESENT:
g_value_set_boolean (value, self->present);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
update_info (PhoshTorchInfo *self, GParamSpec *pspec, PhoshTorchManager *torch)
{
g_return_if_fail (PHOSH_IS_TORCH_INFO (self));
if (phosh_torch_manager_get_enabled (self->torch)) {
g_autofree char *str = NULL;
double frac = phosh_torch_manager_get_scaled_brightness (self->torch);
str = g_strdup_printf ("%d%%", (int)(frac * 100.0));
phosh_status_icon_set_info (PHOSH_STATUS_ICON (self), str);
} else {
phosh_status_icon_set_info (PHOSH_STATUS_ICON (self), _("Torch"));
}
}
static void
on_torch_enabled (PhoshTorchInfo *self, GParamSpec *pspec, PhoshTorchManager *torch)
{
gboolean enabled;
g_debug ("Updating torch status");
g_return_if_fail (PHOSH_IS_TORCH_INFO (self));
g_return_if_fail (PHOSH_IS_TORCH_MANAGER (torch));
enabled = phosh_torch_manager_get_enabled (torch);
if (self->enabled == enabled)
return;
self->enabled = enabled;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ENABLED]);
}
static void
on_torch_present (PhoshTorchInfo *self, GParamSpec *pspec, PhoshTorchManager *torch)
{
gboolean present;
g_return_if_fail (PHOSH_IS_TORCH_INFO (self));
g_return_if_fail (PHOSH_IS_TORCH_MANAGER (torch));
present = phosh_torch_manager_get_present (torch);
if (self->present == present)
return;
self->present = present;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PRESENT]);
}
static gboolean
on_idle (PhoshTorchInfo *self)
{
g_object_bind_property (self->torch, "icon-name", self, "icon-name",
G_BINDING_SYNC_CREATE);
g_signal_connect_swapped (self->torch,
"notify::brightness",
G_CALLBACK (update_info),
self);
update_info (self, NULL, self->torch);
/* We don't use a binding for self->enabled so we can keep
the property r/o */
g_signal_connect_swapped (self->torch,
"notify::enabled",
G_CALLBACK (on_torch_enabled),
self);
on_torch_enabled (self, NULL, self->torch);
g_signal_connect_swapped (self->torch,
"notify::present",
G_CALLBACK (on_torch_present),
self);
on_torch_present (self, NULL, self->torch);
return FALSE;
}
static void
phosh_torch_info_constructed (GObject *object)
{
PhoshTorchInfo *self = PHOSH_TORCH_INFO (object);
PhoshShell *shell;
G_OBJECT_CLASS (phosh_torch_info_parent_class)->constructed (object);
shell = phosh_shell_get_default ();
self->torch = g_object_ref (phosh_shell_get_torch_manager (shell));
if (self->torch == NULL) {
g_warning ("Failed to get torch manager");
return;
}
g_idle_add ((GSourceFunc) on_idle, self);
}
static void
phosh_torch_info_dispose (GObject *object)
{
PhoshTorchInfo *self = PHOSH_TORCH_INFO (object);
if (self->torch) {
g_signal_handlers_disconnect_by_data (self->torch, self);
g_clear_object (&self->torch);
}
G_OBJECT_CLASS (phosh_torch_info_parent_class)->dispose (object);
}
static void
phosh_torch_info_class_init (PhoshTorchInfoClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = phosh_torch_info_constructed;
object_class->dispose = phosh_torch_info_dispose;
object_class->get_property = phosh_torch_info_get_property;
props[PROP_ENABLED] =
g_param_spec_boolean ("enabled",
"enabled",
"Whether the torch is enabled",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
props[PROP_PRESENT] =
g_param_spec_boolean ("present",
"Present",
"Whether torch hardware is present",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, PROP_LAST_PROP, props);
}
static void
phosh_torch_info_init (PhoshTorchInfo *self)
{
}
GtkWidget *
phosh_torch_info_new (void)
{
return g_object_new (PHOSH_TYPE_TORCH_INFO, NULL);
}
/*
* Copyright (C) 2020 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#include <gtk/gtk.h>
#include "status-icon.h"
G_BEGIN_DECLS
#define PHOSH_TYPE_TORCH_INFO (phosh_torch_info_get_type ())
G_DECLARE_FINAL_TYPE (PhoshTorchInfo, phosh_torch_info, PHOSH, TORCH_INFO, PhoshStatusIcon)
GtkWidget * phosh_torch_info_new (void);
G_END_DECLS
/*
* Copyright (C) 2020 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Author: Guido Günther <agx@sigxcpu.org>
*/
#define G_LOG_DOMAIN "phosh-torch-manager"
#include "config.h"
#include "torch-manager.h"
#include "shell.h"
#include "dbus/upower-torch-dbus.h"
#define BUS_NAME "org.freedesktop.UPower"
#define OBJECT_PATH "/org/freedesktop/UPower/Torch"
#define TORCH_DISABLED_ICON "torch-disabled-symbolic"
#define TORCH_ENABLED_ICON "torch-enabled-symbolic"
/**
* SECTION:torch-manager
* @short_description: Interacts with torch via UPower
* @Title: PhoshTorchManager
*
* #PhoshTorchManager tracks the torch status and
* allows to set the brightness.
*/
enum {
PROP_0,
PROP_ICON_NAME,
PROP_ENABLED,
PROP_PRESENT,
PROP_BRIGHTNESS,
PROP_LAST_PROP
};
static GParamSpec *props[PROP_LAST_PROP];
struct _PhoshTorchManager {
GObject parent;
/* Whether upower sees a torch device */
gboolean present;
const char *icon_name;
int brightness;
int max_brightness;
int last_brightness;
PhoshUPowerDBusTorch *proxy;
};
G_DEFINE_TYPE (PhoshTorchManager, phosh_torch_manager, G_TYPE_OBJECT);
static void
on_brightness_set (PhoshUPowerDBusTorch *proxy,
GAsyncResult *res,
PhoshTorchManager *self)
{
g_autoptr (GError) err = NULL;
if (!phosh_upower_dbus_torch_call_set_brightness_finish (proxy, res, &err)) {
g_warning ("Failed to set torch brighness: %s", err->message);
}
g_object_unref (self);
}
static void
set_brightness (PhoshTorchManager *self, int brightness)
{
phosh_upower_dbus_torch_call_set_brightness (self->proxy, brightness,
NULL,
(GAsyncReadyCallback) on_brightness_set,
g_object_ref (self));
}
static void
phosh_torch_manager_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
PhoshTorchManager *self = PHOSH_TORCH_MANAGER (object);
switch (property_id) {
case PROP_ICON_NAME:
g_value_set_string (value, self->icon_name);
break;
case PROP_PRESENT:
g_value_set_boolean (value, self->present);
break;
case PROP_ENABLED:
g_value_set_boolean (value, !!self->brightness);
break;
case PROP_BRIGHTNESS:
g_value_set_int (value, self->brightness);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
on_torch_brightness_changed (PhoshTorchManager *self,
GParamSpec *pspec,
PhoshUPowerDBusTorch *proxy)
{
int brightness;
const char *icon_name;
g_autoptr (GError) err = NULL;
g_return_if_fail (PHOSH_IS_TORCH_MANAGER (self));
g_return_if_fail (PHOSH_UPOWER_DBUS_IS_TORCH (proxy));
brightness = phosh_upower_dbus_torch_get_brightness (proxy);
if (brightness == self->brightness)
return;
g_debug ("Torch brightness: %d", brightness);
g_object_freeze_notify (G_OBJECT (self));
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_BRIGHTNESS]);
if (!!self->brightness != !!brightness)
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ENABLED]);
self->brightness = brightness;
icon_name = self->brightness ? TORCH_ENABLED_ICON : TORCH_DISABLED_ICON;
if (icon_name != self->icon_name) {
self->icon_name = icon_name;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_NAME]);
}
g_object_thaw_notify (G_OBJECT (self));
}
static void
on_get_max_brightness_finished (PhoshUPowerDBusTorch *proxy,
GAsyncResult *res,
PhoshTorchManager *self)
{
g_autoptr (GError) err = NULL;
gboolean present = TRUE;
int value;
if (phosh_upower_dbus_torch_call_get_max_brightness_finish (proxy, &value, res, &err)) {
self->max_brightness = value;
} else {
g_debug ("Failed to get torch brightness: %s", err->message);
present = FALSE;
}
if (self->present != present) {
self->present = present;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PRESENT]);
}
g_debug ("Torch present: %d", self->present);
g_object_unref (self);
}
static void
on_name_owner_changed (PhoshTorchManager *self,
GParamSpec *pspec,
PhoshUPowerDBusTorch *proxy)
{
g_autofree char *owner = NULL;
gboolean present;
g_return_if_fail (PHOSH_IS_TORCH_MANAGER (self));
g_return_if_fail (G_IS_DBUS_PROXY (proxy));
owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy));
present = owner ? TRUE : FALSE;
/* Name owner went away */
if (!present && self->present) {
self->present = present;
g_debug ("Torch present: %d", self->present);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_PRESENT]);
return;
}
/* Check max brightness as indicator if we can drive that DBus interface */
phosh_upower_dbus_torch_call_get_max_brightness (
proxy, NULL, (GAsyncReadyCallback)on_get_max_brightness_finished,
g_object_ref (self));
}
static void
phosh_torch_manager_class_init (PhoshTorchManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = phosh_torch_manager_get_property;
props[PROP_ICON_NAME] =
g_param_spec_string ("icon-name",
"icon name",
"The torch icon name",
"torch-disabled-symbolic",
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_ENABLED] =
g_param_spec_boolean ("enabled",
"enabled",
"Whether torch is enabled",
FALSE,
G_PARAM_READABLE |
G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_STRINGS);
props[PROP_PRESENT] =
g_param_spec_boolean ("present",
"Present",
"Whether a torch led is present",
FALSE,
G_PARAM_READABLE |
G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_STRINGS);
props[PROP_BRIGHTNESS] =
g_param_spec_int ("brightness",
"Brightness",
"The torch brightness",
0,
G_MAXINT,
0,
G_PARAM_READABLE |
G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, PROP_LAST_PROP, props);
}