wwmm / easyeffects

Limiter, compressor, convolver, equalizer and auto volume and many other plugins for PipeWire applications
GNU General Public License v3.0
6.14k stars 265 forks source link

Plans for EasyEfects 6.2.0 #1243

Closed wwmm closed 2 years ago

wwmm commented 2 years ago

I think it is time to make another structural change. In the last days I started to play with the idea of using gtk4 directly without wrappers(gtkmm4) in the way. I like gtkmm and it has served us well since my initial move away from Python. But there are some things here and there that are not straightforward(or possible) when using gtkmm:

After thinking a little about all of this I created a new branch where I am investigating how things would be if we were using gtk4 directly https://github.com/wwmm/easyeffects/tree/libadwaita. So far so good. I was afraid that I would have to write tons of boilerplate code but with composite templates writing gtk4 directly has been surprisingly simple. No major difficulties or annoyances. At least for now... But I would not say yet that this move to abandon gtkmm is definitely going to happen. It is too soon for that.

Digitalone1 commented 2 years ago

If I can share my opinion, maybe this can wait. I think EasyEffects needs a big step further modifying its code to allow multiple instances of the same plugin. The application is mature enough to do this step.

I wanted to analyze the code and list the things that prevent the multiple instances in order to shape them and finally overtake one of the biggest limit of EasyEffects. It's a great application, I love it, but using only one instance of a plugin is a lack since PulseEffects.

I know it was made to develop the code simpler, but if there's one thing to work on in order to improve the project, I think it is allowing multiple instances, not getting rid of gtkmm or using libadwaita (which can be done the same in the future).

Digitalone1 commented 2 years ago
  • Sometimes having to deal with Glib::ustring and std::string at the same time is annoying because they are not 100% compatible. I understand the reasons why ustring exists but it would have been more comfortable to have std::string as the high level container for chars.

I agree, indeed I changed the type to ustring in many parts of the code to reduce the conversions. If I remember well, ustrings were introduced to manage unicodes strings and avoid issues with localizations. Standars c++ string lybrary could have issues with localized strings.

Maybe this is not true anymore with u8strings introduced with c++20, but I wonder if plain gtk4 is managing standard string library along with full support to localization.

wwmm commented 2 years ago

If I can share my opinion, maybe this can wait. I think EasyEffects needs a big step further modifying its code to allow multiple instances of the same plugin. The application is mature enough to do this step.

Supporting multiple instance is definitely necessary. I totally agree on that. But I do not think we have to wait for this to be implemented in order to move away from gtkmm. The reason is that supporting multiple instances is a lot harder. The difficulties involved in using gtk directly do not come even close. Trust me I have been thinking about multiple plugins instances since this application was written in Python and it always comes down to doing things in a different way in many different places. What I am doing in the libadwaita branch is mostly copy and paste with small adjustments and function calls replacement here and there. It is the same code with new clothes. And not all of our classes will have to be changed. The ones implementing the filters are one example. They will stay the same. And the ones related to the presets will need only to access gsettings through its C API. Nothing particularly hard to do. The "ui" classes are the ones that will have more changes. But even in this case the interface shown to the user will be the same because it is defined in xml files. The changes required for multiple filter instances are a lot deeper than that:

In a few days I will have a small vacation period of 2 weeks before I have to give classes again. I think I will finish the move away from gtkmm before going back to work. We can discuss the multiple instances implementation along the way. I am fine with the idea of "version 7" having also some work in the multiple instances direction. Or maybe its full implementation if we are able to do it.

Digitalone1 commented 2 years ago

Okay. For the strings question, are you sure plain gtk4 handles localization properly without glib ustrings?

wwmm commented 2 years ago

Okay. For the strings question, are you sure plain gtk4 handles localization properly without glib ustrings?

Considering that so many big projects including GNOME use gtk directly it has to be able to handle that. Nautilus and most of the more popular applications from the gtk ecosystem are written in C and are translated to many languages. To many more than we are. What is curious is that usually strings in gtk are just a char *. Look at the signature of the function that gets the text of a label

const char*
gtk_label_get_text (
  GtkLabel* self
)

I think std::string should handle char without problems. If it were a char8_t or char32_t it would make sense to need things like std::u8string. Besides all that in gtkmm docs we can see You can always use std::string instead of Glib::ustring. So it is not clear to me when gtkmm really needs Glib::ustring. Specially when gtk seems to do the same tasks with just a char...

Changing a little the subject I've noticed another thing that will have to be redesigned while replacing some calls to Glib::signal_idleby calls to g_idle_add. For example look at https://github.com/wwmm/easyeffects/blob/55109a91ff63c37f7cb49a27a5ce9f0772bb0dae/src/compressor.cpp#L163. If the plugin class is destroyed the callback that was scheduled to a later time by signal_idle could try to use a pointer to an object that does not exist anymore. There isn't a problem now because without multiple instances this is impossible. We never destroy the plugin class instance.

I will take this opportunity to redesign this in the libadwaita branch. I am thinking about making the calls to g_idle_add after the signals gets to the "ui side". What really has to be executed the main thread is code that access the widgets. We do not need to put the emit inside g_idle_add.

Digitalone1 commented 2 years ago

I am busy in the next two weeks, not sure if I can contribute. I should make just small fixes to the documentation since I asked on LSP github the meaning of release threshold and sidechain reactivity.

From December I'd like to make my proposal about multiple plugin instances.

Anyway, since the last changes about plain GTK4 are something "under the hood", nothing really visible to the user, I suggest to not mark the next release as 7.0.

Version 7.0.0 could be better for something new to the user like multiple instances. I recommend 6.1.5 for last fixes and documentation updated, 6.1.6 for gtkmm drop.

Please notify me about the new release, I'll make a quick check on the translation.

wwmm commented 2 years ago

I am busy in the next two weeks, not sure if I can contribute.

No problems :-)

Version 7.0.0 could be better for something new to the user like multiple instances. I recommend 6.1.5 for last fixes and documentation updated, 6.1.6 for gtkmm drop.

It makes sense. I will call it 6.2.0. Usually when I make big changes to the version number my intention is making people notice big changes were done. But in this case the most some users will see is that the default theme is a little different. Libadwaita applies some customizations to the default gtk css properties.

Please notify me about the new release, I'll make a quick check on the translation.

I think 6.1.5 can be released as soon as you have translations done. Although I have plans to improve things like the drawings that are currently done with Cairo I will wait until gtkmm is removed. Like I said before I expect the switch from Cairo to gtk snapshot and Graphene to be easier once we are using gtk directly.

Digitalone1 commented 2 years ago

I think 6.1.5 can be released as soon as you have translations done. Although I have plans to improve things like the drawings that are currently done with Cairo I will wait until gtkmm is removed.

Maybe I can fix translations tomorrow. I wanted to add new options to pitch plugin, but it's better to wait the gtkmm drop to be completed.

wwmm commented 2 years ago

At this moment I am rewriting setup_listview_selected_plugins and I've noticed one more thing that is going to be a problem when trying to implement multiple filters instances. The filter class has to be created before we try to connect its level meters and other signals to the corresponding interface class. But at this moment both sides react independently to changes in the GSettings plugins array and there is no way to make one receive the changed signal only when the other side is ready... I will see if there is a different way to handle this situation while removing gtkmm...

wwmm commented 2 years ago

and there is no way to make one receive the changed signal only when the other side is ready

But we could try to make another list in the gsettings database that would be used by the graphical interface class and that is updated by the effects class after the plugins have been added to the pipeline.

wwmm commented 2 years ago

Although there is still a lot to be done there is enough code reimplemented directly in gtk4 for a small report on some nice changes that could be done with libadwaita. The stackswitcher in the headerbar does not need to be done through a hack anymore primary menu

As libadwaita gives for free a preferences window that is reasonably easy to implement I have already made the move to it Screenshot from 2021-11-22 22-08-32 Screenshot from 2021-11-22 22-08-41

I also took this opportunity to do something similar to the PipeWire section Screenshot from 2021-11-22 22-09-52 Screenshot from 2021-11-22 22-10-03

The plugins tab has already been moved to gtk4+libadwaita plugins_menu

But I still have to port each plugin interface.

wwmm commented 2 years ago

Under the hoods I decided to split some of the code in more files. effects_base_ui.cpp was getting annoying to deal with because of its size. Now the blocklist menu has its own widget file. Same thing for the menu with the plugins, the apps and the plugins section, etc.

TimB87 commented 2 years ago

Just a comment from a maintainer perspective here. Moving from gtkmm to gtk4 directly sounds great, absolutely. Just from a packaging perspective, that whole mm stuff is just weird. In general though gnome/gtk4/libadwaita really don't seem like a good way for Linux Desktops future, gnome just seems to continue their "our way or no way" path, sadly. I won't make this a political discussion, have you considered QT or any other toolkit possibly?

wwmm commented 2 years ago

have you considered QT or any other toolkit possibly?

From time to time I think about that. But I never take the idea ahead. It is not that it can not be done. But it will require a lot of effort for very minimal gains if any. And I will really miss the popover menus. In some situations it makes sense to put widgets in menus and this is not the kind of thing that seems doable in QT. Or at least not as straightforward as it is in gtk. It may not seem that way for some people but there are some things that come easily in gtk:

Outside of the GTK and QT world I do not see any Linux toolkit that would be good for us.

TimB87 commented 2 years ago

Thanks for the insights :-) This all makes sense and of course, I would never question the choice for gtkmm if it weren't for the topic here, so thanks for asking openly to allow this exchange.

Large heaps of the programs I use on a daily basis are gtk+ based, I have no DE just sway. I'm perfectly fine with gtk it just worries me more and more lately.
CRUX as a distro uses SYS V and there are no ports for systemd and friends available, and last time I checked I wasn't able to compile.. whatever provides gnome desktop portal for pipewire screen sharing (gnome-settings-daemon?), but it hard depends on at least elogind. (and you know how this song goes on 🎶) I am not a ricer, all I need is dark mode :smile: So theming doesn't bother me.

In regards to dbus, I was often told that sd-bus is the only sane way to interact with dbus. I'm glad there is basu for just that :sweat_smile:

client side decorations seems to be no problem on both gtk (mutter) and qt (plasma and kwin it seems) on wayland, I would suppose this translates to "of course it works on x11 as well"?

I have no idea about gsettings and popover menus.

wwmm commented 2 years ago

I have no idea about gsettings and popover menus.

GSettings is a service that handles settings that you can define in xml schemas like this one https://github.com/wwmm/easyeffects/blob/master/data/schemas/com.github.wwmm.easyeffects.compressor.gschema.xml. One interesting thing about it is that you can bind its keys easily to the gtk widgets controls. So if you change the database the window is updated and vice versa. On top of that any program that can interact with GSettings can change our settings while EasyEffects is running. So some people have written scripts that allows them to tweak our settings without having to open our window. Again, it is not that it can't be done in QT. But If I am not mistaken you need some KDE extensions for that. And at least to me the GSettigns way seems easier to use.

Any menu in EasyEffects with controls, like the presets menu, is using popovers. Without them all that functionality you see there would have to be moved to a dialog window or somewhere else in the main window.

I would suppose this translates to "of course it works on x11 as well"?

As someone that came from "the KDE world" I will say that it is more about a philosophical matter than nothing else. Some hardcore QT(KDE) users just hate client side decorations because they consider it breaks style uniformity in their system. Although I can see what they mean and I can agree to some extent I think it is nonsense to just waste space that could be used for something useful because of an argument that is mostly based on style.

Digitalone1 commented 2 years ago

Nice work @wwmm.

Using libadwaita will make things easier about icons? Are we sure they are showing outside Gnome or using another non-Adwaita icon theme? Or we should keep using other icons as a workaround in some places?

wwmm commented 2 years ago

Are we sure they are showing outside Gnome or using another non-Adwaita icon theme? Or we should keep using other icons as a workaround in some places?

Workaround for audio application icons will have to stay. For now what I did about the "exotic" icons like the one for the "plugins tab" and the "list drag" in the plugins list was putting a copy of them inside https://github.com/wwmm/easyeffects/tree/libadwaita/data/icons/scalable/emblems. This way we won't have to worry about people having them or not. And as these icons are svg they won't make much difference in the binary size. For common icons like the ones for microphone and speakers I think we can rely on people having an equivalent installed from somewhere.

Using libadwaita will make things easier about icons?

In short I do not think it will be. But Adwaita seems to handle better the switch between dark and light themes than the default way gtk offers for that.

Digitalone1 commented 2 years ago

For now what I did about the "exotic" icons like the one for the "plugins tab" and the "list drag" in the plugins list was putting a copy of them inside https://github.com/wwmm/easyeffects/tree/libadwaita/data/icons/scalable/emblems.

Okay, so you could remove the workaround for showing different icon names for those.

wwmm commented 2 years ago

@Digitalone1 I forgot to say before something interesting I realized while looking at the libadwaita examples and that we could have been doing on gtkmm too. It is possible to update properties like sensitive and visible based on a toggle/switch state in the xml file!

<property name="visible" bind-source="split_channels" bind-property="active" bind-flags="sync-create" />

In the example above the visibility of the equalizer stackswitcher for left | right channel is updated based on the state of the "Split Channels" toggle button. This is even in the GtkBuilder documentation. I am not sure why it took me years to realize something so useful was possible.

2A4U commented 2 years ago

Feature request: 1) close option minimizes to system tray. 2) system tray or menu only can close easyeffects. 3) presets can be triggered by the system tray icon. 4) hover over system tray icon shows current preset.

vchernin commented 2 years ago

As far as I understand system tray is unlikely today since gtk doesn't have real support for them, but maybe I'm wrong there. Gnome hasn't officially supported any system tray icons for a while now.

Furthermore both libAppIndicator and KStatusNotifierItem are subpar today, one issue is you have to open a lot of Flatpak sandbox holes to get them working.

I saw some talk about a potential new system tray standard to replace the old ones, which would be interesting. But I don't think anything is set in stone today.

It would potentially be a nice feature though. It's handy to quickly control things, and I'm not sure how that can be done without a system tray.

wwmm commented 2 years ago

As far as I understand system tray is unlikely today since gtk doesn't have real support for them

That is right. Support for tray icons were removed in gtk4 as far as I know.

vchernin commented 2 years ago

Since libhandy (precursor to libadwaita) was originally meant for adaptive widgets for phones, I was wondering if this automatically meant libadwaita apps were all adaptive.

Apparently this isn't the case as of the latest commit. equalizer, pipewire info.

I wonder how difficult would it be to make the app more adaptive? This is useful not only for phones, but also if you say have limited monitor space. You could have EasyEffects open, but could compress it more horizontally while it turns into "a mobile app". GNOME Software 41 is a nice demo of adapativity (even if it uses libhandy).

wwmm commented 2 years ago

I was wondering if this automatically meant libadwaita apps were all adaptive

It is not 100% automatically. Some widgets like the stack switcher being used in our headerbar automatically switch modes depending on the available size. But for other things a clever choice of containers has to be made. What may or may not imply some interface redesigning. For example Adwaita offers a way to design an interface where the side panel is automatically hidden depending on the available size. That would help in some cases like the ones in the images you linked. But the changes to the interface xml files will be more than just replacing the name of a few widgets. So I am not focusing on this now.

wwmm commented 2 years ago

Adwaita offers a way to design an interface where the side panel is automatically hidden depending on the available size

But the problem is that solution assumes that it makes sense to show an "Android style back button" in the headerbar. But in our case some of the side panels are deeper in the application. So something a little different than what is done in the Adwaita examples would have to be made.

wwmm commented 2 years ago

If you install the package libadwaita-demos and run adwaita-1-demo you will see in the Flap example what I am talking about. I do not think it makes sense in our case to have a button in the header bar to show/hide the panel when the window width is small. In simpler applications it is fine. But in our case it may be confusing and hard to implement because when we switch sections(input, output, pipewire) that button has to be hidden and/or its associated widget changed.

wwmm commented 2 years ago

It seems gtk 4.6 will have a new behavior that may require some changes to the interface code https://blog.gtk.org/2021/12/03/sizable-news/. I will let this link here to make it easier to find it when needed.

vchernin commented 2 years ago

@wwmm I saw the first libadwaita beta was released, but it depends on gtk 4.5 which won't make it to the Arch repos since it's a development version. But since GTK 4.5/4.6 will include breaking interface changes, should testing of this branch done against libadwaita alpha 4/gtk 4.4 for now?

Keep in mind while the Flatpak can always just bundle everything, non-Flatpak builds might be difficult to package depending on when this branch is released, and when libadwaita beta makes it to repos. I wonder when GTK 4.6 will be released.

wwmm commented 2 years ago

should testing of this branch done against libadwaita alpha 4/gtk 4.4 for now?

For now I think we have no reason to worry. It does not look like we are affected by these changes in a way that will break things.

Digitalone1 commented 2 years ago

I wanted to test the new features, but unfortunately in the last weeks I'm more involved in other working projects. I wanted also to improve the pitch plugin, but I'm afraid I won't have the time for this neither. Maybe in late spring or next summer I should be free to dedicate on EasyEffects.

wwmm commented 2 years ago

No problems :-) As I am doing some things like #1284 at the same time it will take a little more time for this branch to be ready. But it is almost there. 7 plugins interfaces still needing to be rewritten directly in gtk4.

Digitalone1 commented 2 years ago

For the first time I tried the new version. Initially it didn't follow the dark theme, I expected it to appear dark as default since I have adwaita dark as gtk theme in gtk system settings. Not a big issue anyway since I switched it to dark from the internal app settings.

Visually I like more the previous GTK style, but maybe it's a matter of habit and I will find adwaita good while using it in the future. It's not a big issue, for applications like EasyEffects the graphic is not a crucial aspect, it is intended to be run in background most of the time.

Unfortunately the db unit is disappeared from the plugin in/output level bar. I added it because it's more intuitive. Is there a chance to readd it in the future for adwaita?

vchernin commented 2 years ago

Initially it didn't follow the dark theme, I expected it to appear dark as default since I have adwaita dark as gtk theme in gtk system settings.

Libadwaita has support for the freedesktop dark mode preference, which is basically a more robust way of setting dark mode without relying on "dark" being in the gtk theme name. Gnome 42 is planning to include an option in settings for this. So long term it should be better supported, e.g. you won't need gnome tweaks to set dark mode.

https://blogs.gnome.org/alexm/2021/10/04/dark-style-preference/

wwmm commented 2 years ago

I expected it to appear dark as default since I have adwaita dark as gtk theme in gtk system settings.

At this moment we are using ADW_COLOR_SCHEME_FORCE_LIGHT by default https://github.com/wwmm/easyeffects/blob/0c54a96f7bd3a46ba9ad73b20d09f22da4406f5d/src/application_ui.cpp#L64. And when dark mode is enabled we set ADW_COLOR_SCHEME_FORCE_DARK. I am not sure about what is going to happen outside of GNOME 42 if we choose to set prefer instead of force. I imagine that when a user goes to the application menu and enable dark mode he expects the app to become dark independently of whether his desktop is using dark mode or not. We could switch to the prefer variants. But will they really work outside of gnome?

Visually I like more the previous GTK style, but maybe it's a matter of habit and I will find adwaita good while using it in the future.

I have mixed feelings about the libadwaita theme. For some things like the GtkScale I think it is better. But on the vertical spinbuttons I think it is worse. But as time passed by I got more used to it.

Unfortunately the db unit is disappeared from the plugin in/output level bar. I added it because it's more intuitive. Is there a chance to readd it in the future for adwaita?

I totally forgot about them while copying and pasting code. The prepare_scale function is there to do that.

wwmm commented 2 years ago

But on the vertical spinbuttons I think it is worse.

And on the toggle buttons too. I think it should have more contrast between the states.

vchernin commented 2 years ago

I agree the libadwaita look could be improved, personally I think this issue would be nice to have fixed, the contrast can be not great.

I once tried building with gtk 4.5 instead of 4.4, and I noticed the button seperation was a bit clearer. I took a screenshot but now I can't find it...

But will they really work outside of gnome?

From the table linked in that article I think we can reason it out. The system settings page can have 3 choices (rows in the table). The app has four choices (columns in the table).

system \ app force-light prefer-light prefer-dark force-dark
prefer-light light light light dark
default light light dark dark
prefer-dark light dark dark dark

Basically with the current setup on gnome 42, setting dark mode (i.e. prefer-dark) from the system preference will not work since EasyEffects does force-light. Only the EasyEffects toggle will work, which is not ideal.

The way I understand it (I might be wrong), if the desktop they're using doesn't support the preference (e.g. gnome 41), the app will understand that as "default". So given that libadwaita itself includes what is needed to make the dark theme work, a switch that does prefer instead of force should still work.

Trying prefer instead of force should be a testable thing though, since gnome 41 is as oblivous to this preference as any other desktop.

However, maybe this is preferable:

There are also properties to check if the system has a system-wide color scheme preference, to allow apps to keep their dark style switches when running on GNOME 41, but drop them for 42; and, somewhat unrelated, a property to check if the system is currently using high contrast mode instead of it being a theme.

wwmm commented 2 years ago

I have updated the libadwaita branch with the prefer variants. Let's see how this goes.

vchernin commented 2 years ago

I tried it out locally with gtk and libadwaita from main. image

The most noticeable change I found was the title bar has more defined buttons, there weren't any obvious big regressions even running from main.

Note prefer seems to work as intended. On Gnome 41 it still works to set the theme. But with the gtk inspector you can emulate the gnome 42 settings page.

I think this seems reasonable, the system default setting isn't very useful if apps just force the dark/light mode.

wwmm commented 2 years ago

I am confused. Did you test the prefer variants with the master branch? At least the image above does not seem to the from the libadwaita branch.

vchernin commented 2 years ago

It is the EasyEffects libadwaita branch, just built with the latest commit from libadwaita itself (the gnome library) for testing. It looks a little different than with libadwaita alpha 4 but is mostly the same.

wwmm commented 2 years ago

@Digitalone1 I finished removing gtkmm from the multiband compressor. I think I did not forget anything along the way. But if possible try to do some tests when you have time.

wwmm commented 2 years ago

The current libadwaita branch does not have gtkmm and glibmm as a build dependencies anymore. @vchernin let me know if for some reason it still needs them to be compiled.

Digitalone1 commented 2 years ago

@wwmm in the next days I will give it a try.

wwmm commented 2 years ago

I moved the code from the libadwaita branch to the master branch.

vchernin commented 2 years ago

I was able to remove gtkmm and glibmm and it still compiles, nice work!

Digitalone1 commented 2 years ago

I'm testing the new version.

I have updated the libadwaita branch with the prefer variants. Let's see how this goes.

Nothing changes. Still have the light theme as default. Should I expect to have the dark as default on Gnome 42 without having to force the dark theme from EE settings?

For the rest, I'm glad the db unit returned on plugin in/output level

And I don't see any issue so far.

@wwmm before the release tag me here so I can make a translation update.

Digitalone1 commented 2 years ago

I'd like to have app title vertically centered in app info ui when there's no description.

Schermata del 2021-12-16 21-48-34

I think something like that have been already done in PE hiding the description label when it is provided empty. Maybe in the next days I'll work on it reproducing that behavior. ^\s++? regex should be enough to catch meaningless content (even on non-empty strings full of whitespaces).

wwmm commented 2 years ago

Should I expect to have the dark as default on Gnome 42 without having to force the dark theme from EE settings?

I do not know. Maybe instead of having a switch where prefer light / prefer dark are the only options we should have a GtkComboBox with all the possible values and having this setting at its default value.

I'd like to have app title vertically centered in app info ui when there's no description.

I do not remember having changed that part of the xml. Maybe this was on the C++ code side.

vchernin commented 2 years ago

Should I expect to have the dark as default on Gnome 42 without having to force the dark theme from EE settings?

In gnome 42, provided EE is using prefer not force, the dark mode switch in system settings will set dark mode in EE.

I do not know. Maybe instead of having a switch where prefer light / prefer dark are the only options we should have a GtkComboBox with all the possible values and having this setting at its default value.

This could be useful if a user say wanted to set global dark mode, but force EE individually to light. But aside from that use case I don't see a benefit with allowing to set force in EE.