Skip to content

Conversation

@AKArien
Copy link

@AKArien AKArien commented Nov 2, 2025

The widget allows for control of the indivual volumes for sinks, sources and output streams, as well as selection of the default for the first two.
Upon changes to a volume, it pops up an interactible slider for the volume that changed.
Has mute on middle click, scroll to change volume and reduced view on right click
Has the following settings :

  • Popup on change : enable or disable the « popup on change » behavior
  • Assignment of full mixer, reduced view and mute between left, middle and right click
  • Timeout of popups
  • Scroll sensitivity
  • Reduced view / « quick action » target between : last changed volume, default sink, default source

@AKArien AKArien marked this pull request as draft November 2, 2025 11:41
@AKArien AKArien changed the title (DRAFT) Added wireplumber mixer widget Added wireplumber mixer widget Nov 3, 2025
@AKArien AKArien marked this pull request as ready for review November 3, 2025 12:43
@AKArien AKArien marked this pull request as draft November 4, 2025 15:24
@AKArien
Copy link
Author

AKArien commented Nov 4, 2025

Actually, the audio sources controls seem very broken. Re-marking as draft.

@AKArien
Copy link
Author

AKArien commented Nov 6, 2025

Should be good !'m not running into bugs in my own use anymore.
The one thing i’m not quite happy about is the hacky way of « keeping the popover out but swapping it’s content » on click by closing it right before, so it gets opened again by the click event (line 469/490).
It might also help with readability to split it into multiple files ?

@AKArien AKArien marked this pull request as ready for review November 6, 2025 16:29
Copy link
Collaborator

@NamorNiradnug NamorNiradnug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thank for your PR! Please consider fixing the issues.


static std::vector<WayfireWireplumber*> widgets;

static void init_wp();
Copy link
Collaborator

@NamorNiradnug NamorNiradnug Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not define static functions and objects in headers. These functions should go into wireplumber.cpp.

Also I don't like the global variable above...

Copy link
Author

@AKArien AKArien Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I don't like the global variable above...

As far as i see, the alternative is connect the signals with the WayfireWireplumber as user data, for each widget ? Is that better or worse ?

#include <gtkmm.h>
#include <iostream>
#include <glibmm.h>
#include "gio/gio.h"
Copy link
Collaborator

@NamorNiradnug NamorNiradnug Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use <...> for library headers.

mute_conn = button.signal_toggled().connect(
[this, id] ()
{
GVariantBuilder gvb = G_VARIANT_BUILDER_INIT(G_VARIANT_TYPE_VARDICT);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use Glib::Variant instead of C glib functions.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I’m sorry but for some reason i can’t seem to figure it out… Do you know how to do it ?
My best shot is something like this :

        auto dict = Glib::VariantDict::create();
        dict->insert_value_variant("mute", Glib::Variant<bool>::create(button.get_active()));
        gboolean res FALSE;
        g_signal_emit_by_name(WpCommon::mixer_api, "set-volume", id, dict->gobj(), &res);

But it aborts on a type info check assertion and i seem to phenomenally fail at looking anything up.

return;
}

std::map<VolumeLevel, std::string> icon_name_from_state = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

icon_name_from_state can be made static const.


WfWpControl*WfWpControl::copy()
{
WfWpControl *copy = new WfWpControl(object, parent);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not return objects by raw pointers. Either use std::unique_ptr or return by value.

Also why don't you just use the default copy constructor? Ah, because there are callbacks that store a pointer to the object. Then you probably want to make the object non-movable.

if (g_strcmp0(type, "Audio/Sink") == 0)
{
which_box = &(widget->sinks_box);
control = new WfWpControlDevice(obj, widget);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't manage memory with new/delete.

Probably objects_to_control should own the objects through std::unique_ptr.

{
// adds a new widget to the appropriate section

WpPipewireObject *obj = (WpPipewireObject*)object;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto *


WpPipewireObject *obj = (WpPipewireObject*)object;

const gchar *type = wp_pipewire_object_get_property(obj, PW_KEY_MEDIA_CLASS);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::string_view

WfOption<std::string> str_wp_right_click_action{"panel/wp_right_click_action"};
WfOption<std::string> str_wp_middle_click_action{"panel/wp_middle_click_action"};

if ((std::string)str_face_choice == (std::string)"last_change")
Copy link
Collaborator

@NamorNiradnug NamorNiradnug Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't cast a string constant to std::string for comparison. std::string has operator== with const char *.

Also please use .value() method of WfOption instead casting it to std::string: it looks better and would allow to optimize unnecessary copy if value() would return a reference instead of copy (it currently doesn't, but I think we should fix it).

reload_config();

// boxes hierarchy and labeling
auto r1 = Gtk::Orientation::HORIZONTAL;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use such aliases. It decreases code readability.

@ammen99
Copy link
Member

ammen99 commented Nov 15, 2025

It might also help with readability to split it into multiple files ?

Feel free to do so if you find it better. We already do that for window-list, simply create a subdirectory and place all files in it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants