Another happy Audacity user here, great to hear it's going to get a refresh. My only request is that performance is kept top-of-mind - using Audacity is snappy and responsive even on ancient hardware, which makes it just a pleasure to use. UI interactions feel instant. The contrast to a slow Electron app like Slack is night and day.
I've found the exact opposite - Audacity used to be instant, but these days its UI is dog slow. It seems to struggle badly on high-DPI displays: it is almost unusable maximized on both macOS and Linux (X11) if you have a 4K or so display. It feels like it's actively gotten worse on this front.
I'm hoping this is something that improved in 3.0.0, because using Audacity is becoming increasingly impractical. I was just trying to listen to 10 tracks one by one yesterday and even just muting/soloing a track would take about a second; it was horrible. Shrinking the window helps, but it's silly to have a tiny window and scroll around when you have a 4K display.
I kind of suspect this to be a windowing toolkit issue, and originally I thought it was macOS-specific (since I first noticed when I tried to recommend it to friends who use that), but ever since I moved to a 4K screen on Linux I noticed it's bad here too...
The workaround is, well, not using HiDPI mode which is silly. But Audacity doesn't even seem to support HiDPI mode on Linux properly to begin with (the entire UI is small), so that's not it per se... I guess wxGTK just struggles when it has to draw 4x as many pixels?
Those "classic" UI toolkit as raster engines. Both GTK/2/3 and QtWidgets 4/5/6 have OpenGL backends, but they are slower than the raster.
This is because the state machine that drives the draw context is synchronous. Every line, pixels (or anything, really) takes some CPU cycles.
Newer toolkits (QtQuick2, GTK4, Skia-based-ones) are hardware accelerated. They are slower of standard DPI, but much faster on HiDPI.
So, yes, they cannot be as snappy on HiDPI, the number of pixel gets bottlenecked by the single thread performance of the CPU. Those barely grow year-over-year, while the number of pixel went up a cliff overnight.
(sorry, can't reply directly,
marcan_42 comment is too deep in the tree)
> which tells me this isn't a simple pixel pushing problem but rather something more profound in Audacity.
That's probably because of the cursor animation (when you play). Audacity has to redraw the entire track widget each time the needle moves unless they implement special double buffering + special damage area slices. By default, Qt/GTK/wx are too dumb to understand layers properly. They will redraw the entire rectangle if you try to stack things with any transparency or non-rectangle clips. Even with proper double buffering, combining both frame buffers is still done on the CPU. That's 2x4x{width}x{height}x{fps} bytes up load to the GPU per second. for a 4k ARGB8888 video frame @ 60fps, that's like 4GB/s of raw transfer if you rasterize each frames in the CPU.
(disclaimer: former KDE dev)
edit: If you run KWin, you can enable the redraw compositor plugin and see for yourself which area of the window are repainted.
It's not comment depth that keeps the reply link from appearing. I think it's intentional rate-limiting of replies, but only applied to the thread view, not the comment view.
Audacity is the only app that is this bad (I run KDE; my entire desktop is Qt5 so clearly that is not comparable).
I've noticed that the Audacity issue seems proportional to the number of tracks (not how much of the screen they take up) and improves when I zoom in a lot (to the sample level), which tells me this isn't a simple pixel pushing problem but rather something more profound in Audacity. There is obviously something horribly inefficient about how waveforms are being drawn at lower zoom levels.
For comparison, I can run full-screen Ardour with an order of magnitude more tracks and complexity than Audacity and it still performs much better, even if it isn't perfectly smooth.
Audacity uses wxWidgets right now. We've been talking about migration to Qt 6 (and possibly QML for some things) but that would be a big re-platforming effort, still debating. Not sure if we can continue with wxWidgets and do a major UI/UX upgrade though
I have done it several time professionally (Motif, Qt3, GTK, etc, but not wx) to QtWidgets or QtQuick. It's been a while and I pivoted to other industries.
It's a potential project killer, but it can be done. The trick is to wrap all your objects in QObject classes. You keep the old UI code as-is as long as possible.
The first Jedi mind trick is to reverse the event loop. Qt supports GLib2 loops, but only as long as they are created by Qt. So you create a dummy QCoreApplication, start the event loop. Then you coerce GTK into using the glib event loop Qt created.
After that, you populate your QObjects I mentionned above. The `Q_PROPERTY` stuff is the important part. It *has* to be fully implemented for QML to ever work. For Qt5, you need to use Qt containers. This means porting your lists and other C++ types (or glib types) to Qt. For Qt6, I think you can get away with some of that, but not Qt5.
Then, make all the signals work. It is important that all properties have signals. The signals must be reliable. QML heavily relies on events for literally everything. Without events, your UX gets out of sync and crash.
The next part is models. Turn all list with selections to models. Don't try to render stuff using for-loops in QML, this is a terrible idea and will explode in your face. Qt Models are annoying to write (and get repetitive very fast), but reliable list models really greatly simplify the QML code.
When you have all those QObject to reflect your current codebase, you make a companion app. This is a small window (or LAN/Network smartphone UI using QtRemoteObjects).
Now you are ready for the UI. Add little features, one by one. Don't try to do everything at once. Again, as long as you can, keep the wx/GTK window alive and fully functional. Your app will look wierd with 1 wx window and 1 QtQuick window. However, having the fully functional old UI let you press buttons there and see the results being updated in QML. That let you polish/debug your signal/q_property code step by step.
Once you are "done" with your port, strip the UI code from the old codebase. Then refactor/clean the logic and turn it into a library. Then start merging your QObject shims and logic classes into a single class.
If you get there, congradulation, your port is complete. Time to annoy your users with a bunch of changes.
Thanks for the write-up! This is great, good to hear war stories. I've sent it to the devs - if they have any questions about the above, would it be possible to reach out for quick thoughts?
Same username on GitHub (public email there) and Reddit. I admit I am slowly losing the battle with my indox, so better ping on both. I would be glad to provide help where I can.
Love this! Although I will almost certainly never have reason to apply it. (Still good inspiration for any big rewrite, and I'm starting one pretty soon.)
Did anyone actually try to make that run in practice? I don't think GTK supports that. You can't just magically hot-swap Cairo backends externally. Using the GL backend means you provide GL surfaces to Cairo instead of memory.
It runs like crap, that's why it isn't supported. But if really, really want to make it work, you can have your app make a surface, put a cairo surface in it, then render GTK there. I suggest you don't waste any time on this. Mozilla, Google and Samsung had many people _each_ assigned to fix it at some point. The Google gave up, bought Skia. Then Mozilla also gave up and used the now Open Source Skia. Samsung somehow kept poking at it for a few more years until they dissolved their Open Source division and scaled down Tizen. At some point Samsung make a Vulkan backend for unknown reasons.
With Qt 4/5, there is an environment variable, to play with. It sill runs like crap and is now deprecated.
edit: Of course, GTK4 have "real" backends for both Vulkan and OpenGL. They implement scene graphs like QtQuick rather than building a big bitmap like GTK2, GTK3 and QtWidgets.
> But Audacity doesn't even seem to support HiDPI mode on Linux properly to begin with (the entire UI is small), so that's not it per se...
On KDE HiDPI, the audio input/output device selector positions the dropdown boxes according to 100% scaling, but they're sized according to 125% scaling, so they overlap!
Agreed, but thats the tragedy of desktop ui development. Either you get pretty but electron app where loading a few hundred messages grinds it to a halt
Or you get ancient looking Ui
Or you get platform spesific stuff!
Actually Java applications are kinda reasonable compromise
> Actually Java applications are kinda reasonable compromise
As are .NET applications. Yeah, most .NET desktop apps in the wild are technically chock full of Windowsisms, I've found that said apps more often than not Just Work(TM) on e.g. Linux w/ Mono, and alternative toolkits like Avalonia help further.