sound: Move alert chooser to a separate window

This commit is contained in:
Marco Melorio 2023-01-14 19:49:39 +01:00 committed by Georges Basile Stavracas Neto
parent 092cef515d
commit 98c8a7787c
8 changed files with 221 additions and 124 deletions

View file

@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
/*
* Copyright (C) 2018 Canonical Ltd.
* Copyright (C) 2023 Marco Melorio
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -20,28 +20,24 @@
#include <gsound.h>
#include "config.h"
#include "cc-alert-chooser.h"
#include "cc-sound-resources.h"
#include "cc-alert-chooser-window.h"
#define KEY_SOUNDS_SCHEMA "org.gnome.desktop.sound"
struct _CcAlertChooser
struct _CcAlertChooserWindow
{
GtkBox parent_instance;
GtkWindow parent_instance;
GtkToggleButton *click_button;
GtkToggleButton *hum_button;
GtkToggleButton *string_button;
GtkToggleButton *swing_button;
GtkCheckButton *click_button;
GtkCheckButton *string_button;
GtkCheckButton *swing_button;
GtkCheckButton *hum_button;
GSoundContext *context;
GSettings *sound_settings;
};
static void clicked_cb (CcAlertChooser *self,
GtkToggleButton *button);
G_DEFINE_TYPE (CcAlertChooser, cc_alert_chooser, GTK_TYPE_BOX)
G_DEFINE_TYPE (CcAlertChooserWindow, cc_alert_chooser_window, GTK_TYPE_WINDOW)
#define CUSTOM_THEME_NAME "__custom"
@ -145,7 +141,7 @@ update_dir_mtime (const char *dir_path)
}
static void
set_custom_theme (CcAlertChooser *self,
set_custom_theme (CcAlertChooserWindow *self,
const gchar *name)
{
g_autofree gchar *dir_path = NULL;
@ -198,7 +194,7 @@ set_custom_theme (CcAlertChooser *self,
}
static void
select_sound (CcAlertChooser *self,
play_sound (CcAlertChooserWindow *self,
const gchar *name)
{
g_autofree gchar *path = NULL;
@ -211,81 +207,80 @@ select_sound (CcAlertChooser *self,
{
g_warning ("Failed to play alert sound %s: %s", path, error->message);
}
set_custom_theme (self, name);
}
static void
set_button (CcAlertChooser *self,
GtkToggleButton *button,
activate_cb (CcAlertChooserWindow *self)
{
if (gtk_check_button_get_active (self->click_button))
play_sound (self, "click");
else if (gtk_check_button_get_active (self->string_button))
play_sound (self, "string");
else if (gtk_check_button_get_active (self->swing_button))
play_sound (self, "swing");
else if (gtk_check_button_get_active (self->hum_button))
play_sound (self, "hum");
}
static void
toggled_cb (CcAlertChooserWindow *self)
{
if (gtk_check_button_get_active (self->click_button))
set_custom_theme (self, "click");
else if (gtk_check_button_get_active (self->string_button))
set_custom_theme (self, "string");
else if (gtk_check_button_get_active (self->swing_button))
set_custom_theme (self, "swing");
else if (gtk_check_button_get_active (self->hum_button))
set_custom_theme (self, "hum");
}
static void
set_button_active (CcAlertChooserWindow *self,
GtkCheckButton *button,
gboolean active)
{
g_signal_handlers_block_by_func (button, clicked_cb, self);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active);
g_signal_handlers_unblock_by_func (button, clicked_cb, self);
g_signal_handlers_block_by_func (button, toggled_cb, self);
gtk_check_button_set_active (button, active);
g_signal_handlers_unblock_by_func (button, toggled_cb, self);
}
static void
clicked_cb (CcAlertChooser *self,
GtkToggleButton *button)
cc_alert_chooser_window_dispose (GObject *object)
{
if (button == self->click_button)
select_sound (self, "click");
else if (button == self->hum_button)
select_sound (self, "hum");
else if (button == self->string_button)
select_sound (self, "string");
else if (button == self->swing_button)
select_sound (self, "swing");
set_button (self, button, TRUE);
if (button != self->click_button)
set_button (self, self->click_button, FALSE);
if (button != self->hum_button)
set_button (self, self->hum_button, FALSE);
if (button != self->string_button)
set_button (self, self->string_button, FALSE);
if (button != self->swing_button)
set_button (self, self->swing_button, FALSE);
}
static void
cc_alert_chooser_dispose (GObject *object)
{
CcAlertChooser *self = CC_ALERT_CHOOSER (object);
CcAlertChooserWindow *self = CC_ALERT_CHOOSER_WINDOW (object);
g_clear_object (&self->context);
g_clear_object (&self->sound_settings);
G_OBJECT_CLASS (cc_alert_chooser_parent_class)->dispose (object);
G_OBJECT_CLASS (cc_alert_chooser_window_parent_class)->dispose (object);
}
void
cc_alert_chooser_class_init (CcAlertChooserClass *klass)
cc_alert_chooser_window_class_init (CcAlertChooserWindowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = cc_alert_chooser_dispose;
object_class->dispose = cc_alert_chooser_window_dispose;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-alert-chooser.ui");
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-alert-chooser-window.ui");
gtk_widget_class_bind_template_child (widget_class, CcAlertChooser, click_button);
gtk_widget_class_bind_template_child (widget_class, CcAlertChooser, hum_button);
gtk_widget_class_bind_template_child (widget_class, CcAlertChooser, string_button);
gtk_widget_class_bind_template_child (widget_class, CcAlertChooser, swing_button);
gtk_widget_class_bind_template_child (widget_class, CcAlertChooserWindow, click_button);
gtk_widget_class_bind_template_child (widget_class, CcAlertChooserWindow, string_button);
gtk_widget_class_bind_template_child (widget_class, CcAlertChooserWindow, swing_button);
gtk_widget_class_bind_template_child (widget_class, CcAlertChooserWindow, hum_button);
gtk_widget_class_bind_template_callback (widget_class, clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, activate_cb);
gtk_widget_class_bind_template_callback (widget_class, toggled_cb);
}
void
cc_alert_chooser_init (CcAlertChooser *self)
cc_alert_chooser_window_init (CcAlertChooserWindow *self)
{
g_autofree gchar *alert_name = NULL;
g_autoptr(GError) error = NULL;
g_resources_register (cc_sound_get_resource ());
gtk_widget_init_template (GTK_WIDGET (self));
self->context = gsound_context_new (NULL, &error);
@ -308,13 +303,38 @@ cc_alert_chooser_init (CcAlertChooser *self)
}
if (g_strcmp0 (alert_name, "click") == 0)
set_button (self, self->click_button, TRUE);
set_button_active (self, self->click_button, TRUE);
else if (g_strcmp0 (alert_name, "hum") == 0)
set_button (self, self->hum_button, TRUE);
set_button_active (self, self->hum_button, TRUE);
else if (g_strcmp0 (alert_name, "string") == 0)
set_button (self, self->string_button, TRUE);
set_button_active (self, self->string_button, TRUE);
else if (g_strcmp0 (alert_name, "swing") == 0)
set_button (self, self->swing_button, TRUE);
set_button_active (self, self->swing_button, TRUE);
else if (alert_name != NULL)
g_warning ("Current alert sound has unknown name %s", alert_name);
}
CcAlertChooserWindow *
cc_alert_chooser_window_new (void)
{
return g_object_new (CC_TYPE_ALERT_CHOOSER_WINDOW, NULL);
}
const gchar *
get_selected_alert_display_name (void)
{
g_autofree gchar *alert_name = NULL;
alert_name = get_alert_name ();
if (g_strcmp0 (alert_name, "click") == 0)
return _("Click");
else if (g_strcmp0 (alert_name, "hum") == 0)
return _("Hum");
else if (g_strcmp0 (alert_name, "string") == 0)
return _("String");
else if (g_strcmp0 (alert_name, "swing") == 0)
return _("Swing");
else
return _("Unknown");
}

View file

@ -1,6 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2018 Canonical Ltd.
/*
* Copyright (C) 2023 Marco Melorio
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -22,7 +21,11 @@
G_BEGIN_DECLS
#define CC_TYPE_ALERT_CHOOSER (cc_alert_chooser_get_type ())
G_DECLARE_FINAL_TYPE (CcAlertChooser, cc_alert_chooser, CC, ALERT_CHOOSER, GtkBox)
#define CC_TYPE_ALERT_CHOOSER_WINDOW (cc_alert_chooser_window_get_type ())
G_DECLARE_FINAL_TYPE (CcAlertChooserWindow, cc_alert_chooser_window, CC, ALERT_CHOOSER_WINDOW, GtkWindow)
CcAlertChooserWindow *cc_alert_chooser_window_new (void);
const gchar *get_selected_alert_display_name (void);
G_END_DECLS

View file

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CcAlertChooserWindow" parent="GtkWindow">
<property name="title" translatable="yes">Alert Sound</property>
<property name="modal">True</property>
<property name="default-width">360</property>
<property name="titlebar">
<object class="GtkHeaderBar">
<style>
<class name="flat"/>
</style>
</object>
</property>
<property name="child">
<object class="AdwPreferencesPage">
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">Click</property>
<property name="activatable-widget">click_button</property>
<child>
<object class="GtkCheckButton" id="click_button">
<property name="valign">center</property>
<signal name="activate" handler="activate_cb" swapped="yes"/>
<signal name="toggled" handler="toggled_cb" swapped="yes"/>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">String</property>
<property name="activatable-widget">string_button</property>
<child>
<object class="GtkCheckButton" id="string_button">
<property name="valign">center</property>
<property name="group">click_button</property>
<signal name="activate" handler="activate_cb" swapped="yes"/>
<signal name="toggled" handler="toggled_cb" swapped="yes"/>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">Swing</property>
<property name="activatable-widget">swing_button</property>
<child>
<object class="GtkCheckButton" id="swing_button">
<property name="valign">center</property>
<property name="group">click_button</property>
<signal name="activate" handler="activate_cb" swapped="yes"/>
<signal name="toggled" handler="toggled_cb" swapped="yes"/>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">Hum</property>
<property name="activatable-widget">hum_button</property>
<child>
<object class="GtkCheckButton" id="hum_button">
<property name="valign">center</property>
<property name="group">click_button</property>
<signal name="activate" handler="activate_cb" swapped="yes"/>
<signal name="toggled" handler="toggled_cb" swapped="yes"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</template>
</interface>

View file

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<template class="CcAlertChooser" parent="GtkBox">
<property name="homogeneous">True</property>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkToggleButton" id="click_button">
<property name="visible">True</property>
<property name="label" translatable="yes">Click</property>
<signal name="clicked" handler="clicked_cb" object="CcAlertChooser" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="string_button">
<property name="visible">True</property>
<property name="group">click_button</property>
<property name="label" translatable="yes">String</property>
<signal name="clicked" handler="clicked_cb" object="CcAlertChooser" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="swing_button">
<property name="visible">True</property>
<property name="group">click_button</property>
<property name="label" translatable="yes">Swing</property>
<signal name="clicked" handler="clicked_cb" object="CcAlertChooser" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="hum_button">
<property name="visible">True</property>
<property name="group">click_button</property>
<property name="label" translatable="yes">Hum</property>
<signal name="clicked" handler="clicked_cb" object="CcAlertChooser" swapped="yes"/>
</object>
</child>
</template>
</interface>

View file

@ -30,7 +30,7 @@
#include <pulse/pulseaudio.h>
#include <gvc-mixer-control.h>
#include "cc-alert-chooser.h"
#include "cc-alert-chooser-window.h"
#include "cc-balance-slider.h"
#include "cc-device-combo-box.h"
#include "cc-fade-slider.h"
@ -65,6 +65,7 @@ struct _CcSoundPanel
CcVolumeSlider *output_volume_slider;
GtkListBoxRow *subwoofer_row;
CcSubwooferSlider *subwoofer_slider;
GtkLabel *alert_sound_label;
GvcMixerControl *mixer_control;
GSettings *sound_settings;
@ -80,6 +81,13 @@ enum
#define KEY_SOUNDS_SCHEMA "org.gnome.desktop.sound"
static void
update_alert_sound_label (CcSoundPanel *self)
{
const gchar *alert_name = get_selected_alert_display_name ();
gtk_label_set_label (self->alert_sound_label, alert_name);
}
static void
allow_amplified_changed_cb (CcSoundPanel *self)
{
@ -229,6 +237,26 @@ volume_levels_activated_cb (CcSoundPanel *self)
gtk_window_present (GTK_WINDOW (volume_levels));
}
static void
alert_sound_activated_cb (CcSoundPanel *self)
{
CcAlertChooserWindow *alert_chooser;
GtkWindow *toplevel;
CcShell *shell;
shell = cc_panel_get_shell (CC_PANEL (self));
toplevel = GTK_WINDOW (cc_shell_get_toplevel (shell));
alert_chooser = cc_alert_chooser_window_new ();
gtk_window_set_transient_for (GTK_WINDOW (alert_chooser), toplevel);
g_signal_connect_object (alert_chooser, "destroy",
G_CALLBACK (update_alert_sound_label),
self, G_CONNECT_SWAPPED);
gtk_window_present (GTK_WINDOW (alert_chooser));
}
static const char *
cc_sound_panel_get_help_uri (CcPanel *panel)
{
@ -276,13 +304,14 @@ cc_sound_panel_class_init (CcSoundPanelClass *klass)
gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_volume_slider);
gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, subwoofer_row);
gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, subwoofer_slider);
gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, alert_sound_label);
gtk_widget_class_bind_template_callback (widget_class, input_device_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, output_device_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, test_output_configuration_button_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, volume_levels_activated_cb);
gtk_widget_class_bind_template_callback (widget_class, alert_sound_activated_cb);
g_type_ensure (CC_TYPE_ALERT_CHOOSER);
g_type_ensure (CC_TYPE_BALANCE_SLIDER);
g_type_ensure (CC_TYPE_DEVICE_COMBO_BOX);
g_type_ensure (CC_TYPE_FADE_SLIDER);
@ -325,4 +354,6 @@ cc_sound_panel_init (CcSoundPanel *self)
G_CALLBACK (input_device_update_cb),
self,
G_CONNECT_SWAPPED);
update_alert_sound_label (self);
}

View file

@ -340,13 +340,19 @@
</child>
</object>
</child>
</object>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes">Alert Sound</property>
<property name="activatable">True</property>
<signal name="activated" handler="alert_sound_activated_cb" swapped="yes"/>
<child>
<object class="GtkLabel" id="alert_sound_label"/>
</child>
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="CcAlertChooser">
<property name="hexpand">True</property>
<object class="GtkImage">
<property name="icon-name">go-next-symbolic</property>
</object>
</child>
</object>
</child>
</object>

View file

@ -24,7 +24,7 @@ cflags += [
]
sources = files(
'cc-alert-chooser.c',
'cc-alert-chooser-window.c',
'cc-balance-slider.c',
'cc-device-combo-box.c',
'cc-fade-slider.c',
@ -49,7 +49,7 @@ resource_data = files(
'icons/audio-speaker-right-back.svg',
'icons/audio-speaker-right-side.svg',
'icons/audio-speaker-right.svg',
'cc-alert-chooser.ui',
'cc-alert-chooser-window.ui',
'cc-balance-slider.ui',
'cc-device-combo-box.ui',
'cc-fade-slider.ui',

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/control-center/sound">
<file preprocess="xml-stripblanks">cc-alert-chooser.ui</file>
<file preprocess="xml-stripblanks">cc-alert-chooser-window.ui</file>
<file preprocess="xml-stripblanks">cc-balance-slider.ui</file>
<file preprocess="xml-stripblanks">cc-device-combo-box.ui</file>
<file preprocess="xml-stripblanks">cc-fade-slider.ui</file>