frontend: Refactor and update Audio Mixer
Description
Moves a bunch of logic out of OBSBasic into a central AudioMixer class, refactors a bunch of code to clean up, and adds a pile of new functionality to the mixer.
Adds a new MenuCheckbox widget for having a checkbox toggle inside a QMenu that does not close the menu after clicking.
The primary addition in this PR is a new audio monitoring toggle button in the mixer itself. Other features have also been added such as the ability to show Hidden sources, Inactive sources, adjust how they get sorted, and an easier way to toggle the layout.
PR also depends on #12734 for icon coloring.
Motivation and Context
With the fixes made as part of #12175, it is now far more reasonable for us to expose audio monitoring more directly to users. It is often very desirable to be able to toggle on monitoring for things like Media Sources or some Video Devices such as capture cards.
I elected to also clean up the Audio Mixer code a bunch while working on this feature addition, and add some other additional features and UI adjustments.
There is more that I want to do and clean up still but I'm trying to keep this PR at least moderately reasonable.
How Has This Been Tested?
Tested muting and monitoring on multiple audio sources both via the Mixer dock, the Advanced Audio Properties window, as well as a separate Audio Mixer window utilizing the same widget, to test that things are properly encapsulated and not kept in any local widget state.
Types of changes
- New feature (non-breaking change which adds functionality)
- Code cleanup (non-breaking change which makes code smaller or more readable)
Checklist:
- [x] My code has been run through clang-format.
- [x] I have read the contributing document.
- [x] My code is not on the master branch.
- [x] The code has been tested.
- [x] All commit messages are properly formatted and commits squashed where appropriate.
- [ ] I have included updates to all appropriate documentation.
Small request for this redesign, if it's feasible and easy enough: can you add one more checkbox to the menu to show sources that are inactive, but present on the previewed screen? Of course it only makes sense in the studio mode, but it would be a great help when you need to adjust levels of a source that will become active with next transition, but without having to find it in the list of all available sources.
Small request for this redesign, if it's feasible and easy enough: can you add one more checkbox to the menu to show sources that are inactive, but present on the previewed screen? Of course it only makes sense in the studio mode, but it would be a great help when you need to adjust levels of a source that will become active with next transition, but without having to find it in the list of all available sources.
This was in fact not straightforward but I added it as default behaviour
This PR causes ugly pixelated rendering of VolumeMeter text on Linux at 125% DPI scale (and probably Windows as well).
I think you're rendering the text off-screen (backgroundCache?) and blitting on-screen. Unfortunately this may not be easily fixable, because Qt 6 lays out widgets in integer virtual pixels (unless you set a rounding policy, which may cause layout errors when changing DPI at runtime), and you don't know how many physical pixels the QImage/Pixmap will appear on-screen due to position-dependent rounding.
Looking at the QPixmap docs, I found https://doc.qt.io/qt-6/qpainter.html#drawing-high-resolution-versions-of-pixmaps-and-images:
High resolution versions of pixmaps have a device pixel ratio value larger than 1 (see QImageReader, QPixmap::devicePixelRatio()). Should it match the value of the underlying QPaintDevice, it is drawn directly onto the device with no additional transformation applied.
One interesting possible strategy is "multiply size by DPI, round to nearest pixel, then set the QPixmap DPR to the screen, then blit to the widget". If you can convince Qt to not scale it at all (haven't tested), you could get exact rendering, possibly with one pixel cut off or missing at the edges :(
Still waiting for Qt to add https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/devicePixelContentBoxSize 🦗 VS Code faced a similar problem with their terminal at https://github.com/xtermjs/xterm.js/issues/2662#issuecomment-1030163539 and https://github.com/xtermjs/xterm.js/pull/3926
This PR causes ugly pixelated rendering of VolumeMeter text on Linux at 125% DPI scale (and probably Windows as well).
Thanks for catching this. I'm travelling this week but hopefully the fix will be as simple as adjusting the Pixmap size to be
size() * devicePixelRatioF()) instead of just size()
My final TODOs on this are now completed, so this is ready for review. I expect there to be a fair bit of cleanup still for me to do once someone with fresh eyes can look over all of this.
Not sure why (the inner workings of Qt are a mystery), but the text in this PR even with devicePixelRatioF() is less sharp in the PR's Flatpak build than Arch Linux's native build. But the pixelation issue is gone.
Both on master and this PR, the vertical lines jump between 1 and 2 pixels wide while resized. There's not much we can trivially do to fix this (antialiasing changes the appearance and makes adjacent rectangles leak background in between), and at least it's not a regression in this aspect.
Not sure why (the inner workings of Qt are a mystery), but the text in this PR even with
devicePixelRatioF()is less sharp in the PR's Flatpak build than Arch Linux's native build. But the pixelation issue is gone.
This may be partially due to the font size being smaller
Also I would undraft this PR !
I’m using HTML in the source names, but it’s no longer being reflected in the audio mixer.
Example:
<font color="#ffaaff">test</font>
This PR
Version 32.0.2
I learned how to add color to source names from this video: https://www.youtube.com/watch?v=nh0dhJR8P3g
things I noticed when scrolling through. Definitely make sure to revert the obs-browser changes.
God I hate that rebasing does that