Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DeviceManager: Remember previously selected devices #192

Merged
merged 7 commits into from Jun 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions data/io.elementary.desktop.wingpanel.sound.gschema.xml
Expand Up @@ -11,5 +11,9 @@
<default>[]</default>
<summary>Last played title of the default media player.</summary>
</key>
<key type="a{si}" name="preferred-devices">
<default>[]</default>
<summary>Previously used audio devices.</summary>
</key>
</schema>
</schemalist>
14 changes: 14 additions & 0 deletions src/Services/PulseAudioManager.vala
Expand Up @@ -512,6 +512,16 @@ public class Sound.PulseAudioManager : GLib.Object {
relevant_ports += port;
}

// See DeviceManagerWidget.vala for the preferred-devices implementation
var preferred_devices = Sound.Indicator.settings.get_value ("preferred-devices");
var preferred_device_map = new Gee.HashMap<string, int32> ();
var preferred_expiry = (int32)(GLib.get_real_time () / 1000000) - (86400 * 7); // Expire unused after 7 days
foreach (var dev in preferred_devices) {
var name = dev.get_child_value (0).get_string ();
var last_used = dev.get_child_value (1).get_int32 ();
preferred_device_map.set (name, last_used);
}

// add new / update devices
foreach (var port in relevant_ports) {
bool is_input = (PulseAudio.Direction.INPUT in port.direction);
Expand All @@ -531,6 +541,10 @@ public class Sound.PulseAudioManager : GLib.Object {
device.card_active_profile_name = card_active_profile_name;
device.input = is_input;
device.is_priority = port.priority == (is_input? highest_input_priority : highest_output_priority);
// Any connected device previously selected in 7 days is also considered priority and will be displayed
if (id in preferred_device_map.keys && preferred_device_map[id] > preferred_expiry) {
device.is_priority = true;
}
var card_description = card.proplist.gets (PulseAudio.Proplist.PROP_DEVICE_DESCRIPTION);
device.display_name = @"$(card_description): $(port.description)";
device.form_factor = port.proplist.gets (PulseAudio.Proplist.PROP_DEVICE_FORM_FACTOR);
Expand Down
3 changes: 2 additions & 1 deletion src/Widgets/DeviceItem.vala
Expand Up @@ -29,7 +29,7 @@ public class DeviceItem : Gtk.ListBoxRow {
public Gtk.ListBoxRow row { get; construct; }
public string display_name { get; construct; }
public string icon_name { get; construct; }
public bool is_priority { get; construct; }
public bool is_priority { get; set construct; }
public bool is_default { get; construct; }

public DeviceItem (string display_name, bool is_default, bool is_priority, string icon_name, Gtk.ListBoxRow? row) {
Expand Down Expand Up @@ -84,6 +84,7 @@ public class DeviceItem : Gtk.ListBoxRow {

public void set_default () {
radio_button.active = true;
is_priority = true;
update_visible (true);
}

Expand Down
36 changes: 36 additions & 0 deletions src/Widgets/DeviceManagerWidget.vala
Expand Up @@ -67,6 +67,7 @@ public class Sound.Widgets.DeviceManagerWidget : Gtk.Grid {

device_item.activated.connect (() => {
pam.set_default_device.begin (device);
update_preferred_devices (device);
});

device.removed.connect (() => {
Expand All @@ -77,12 +78,47 @@ public class Sound.Widgets.DeviceManagerWidget : Gtk.Grid {

device.defaulted.connect (() => {
device_item.set_default ();
update_preferred_devices (device);
update_showable ();
});

update_showable ();
}

/**
* Preferred devices are stored as:
* {
* device_a: last_used_unix_timestamp,
* device_b: last_used_unix_timestamp
* }
* If a device hasn't been selected in 7 days, it is removed from preferred devices.
* Device selection happens when the user selects the device, and when the plugin
* is initialized.
*/
private void update_preferred_devices (Device device) {
VariantBuilder builder = new VariantBuilder (new VariantType ("a{si}"));
var preferred_devices = Sound.Indicator.settings.get_value ("preferred-devices");
int32 now = (int32)(GLib.get_real_time () / 1000000);
int32 preferred_expiry = now - (86400 * 7); // Expire unused after 7 days

builder.add ("{si}", device.id, now);
foreach (var dev in preferred_devices) {
var name = dev.get_child_value (0).get_string ();
var last_used = dev.get_child_value (1).get_int32 ();
if (name == device.id) {
continue;
}
if (last_used < preferred_expiry) {
continue;
}
builder.add ("{si}", name, last_used);
}
Variant dictionary = builder.end ();

device.is_priority = true;
Sound.Indicator.settings.set_value ("preferred-devices", dictionary);
}

private uint n_visible_items () {
uint n = 0;
foreach (unowned var device in device_list.get_children ()) {
Expand Down