obsproject / obs-studio

OBS Studio - Free and open source software for live streaming and screen recording
https://obsproject.com
GNU General Public License v2.0
59.83k stars 7.93k forks source link

Source audio mute doesn't work with VoiceOver screen reader on macOS #6200

Open nebeker opened 2 years ago

nebeker commented 2 years ago

Operating System Info

Other

Other OS

macOS 12.3

OBS Studio Version

27.2.2

OBS Studio Version (Other)

No response

OBS Studio Log URL

https://obsproject.com/logs/U1Tpoa9RarzCDlAq

OBS Studio Crash Log URL

No response

Expected Behavior

When using VoiceOver, activating the mute checkbox on a source with CTRL+OPT+Space should mute an audio source.

Current Behavior

Checkbox changes state, visual icon goes from grey speaker with waves to red speaker with X, but source is not muted. Meter remains colored.

Steps to Reproduce

  1. Open OBS
  2. Start VoiceOver - CMD+F5
  3. Move VoiceOver to "mute [source name] audio unchecked checkbox" - CTRL+OPT+Right arrow multiple times
  4. Activate checkbox - CTRL+OPT+Space

Anything else we should know?

The current workaround is to simulate a mouse click, by pressing CTRIL+OPT+CMD+5 to move the mouse cursor to the checkbox and then CTRL+OPT+SHIFT+Space to simulate the click action. This is a workaround, not a typical or recommended usage pattern. This is a result of the mute action being bound to mousePressEvent, instead of the standard stateChanged provided by QCheckBox. This bug is present in all QCheckBox based controls.

nebeker commented 2 years ago

To clarify, this bug also affects the start/stop streaming/recording/camera buttons, which are also checkboxes. Semantically, they should be buttons, but I assume they were based on checkboxes to inherit the text state behavior. This is not only confusing for a screen reader user, but also leads to this unintended behavior.

RytoEX commented 2 years ago

This is a result of the mute action being bound to mousePressEvent, instead of the standard stateChanged provided by QCheckBox.

To clarify, we do not use the mousePressEvent. The mute QCheckBox is linked to the clicked signal inherited from QAbstractButton (QAbstractButton::clicked()). While it may be possible to use QCheckbox::stateChanged() or QAbstractButton::toggled(), we suspect this is not a simple find-replace since the mute checkbox can respond to OBS hotkeys which could toggle the checkbox and cause the checkbox to emit those signals. Anyone who is trying to resolve this should be mindful of that when writing and testing a solution.

To clarify, this bug also affects the start/stop streaming/recording/camera buttons, which are also checkboxes. Semantically, they should be buttons, but I assume they were based on checkboxes to inherit the text state behavior. This is not only confusing for a screen reader user, but also leads to this unintended behavior.

These buttons are not checkboxes. They are QPushButtons:

They do, however, have the property "checkable" set to true, as observed here and above:

As far as I know, "checkable" simply allows the button to act as a toggle rather than a button with no state.

What exactly is the "unintended behavior" that you're experiencing with these buttons? Have you checked through Qt's QTBUGs for anything that matches the behavior that you're seeing? I know there are multiple QTBUGs specifically related to VoiceOver, but I'm not aware of anything related to QPushButtons and the checkable property, off the top of my head. Not to say there isn't buggy or unexpected behavior with checkable QPushButtons and VoiceOver, but it would be helpful if such an issue were tracked on Qt's side.

nebeker commented 2 years ago

Interesting. I'm not familiar with the code base, or Qt, really, so I'm not surprised I din't get that quite right. That was my conclusion from going over the code for an hour or so.

I also made an incorrect assumption about the other buttons, based on the way they're announced by VoiceOver (ie. "start streaming unchecked checkbox"). Either way, I can't reproduce the behavior of the mute control. These were an afterthought and I didn't test them, like I did with that control. Sorry for wasting your time on them.

Going over the docs for QAbstractButton::clicked() it's not clear to me whether or not this is triggered by the keyboard, but turning on Full Keyboard Access [System Preferences - Accessibility - Keyboard] and tabbing to the mute control and hitting space reproduces the same unintended behavior I noticed with VoiceOver: the checkbox is checked, but the source isn't muted. That might be an easier way to verify and test this.

As far as user impact goes, keyboard users (sighted or blind) can't mute audio sources the same way mouse users can and, worse still, might thing they have, because the checkbox does change state.

Regarding upstream Qt bugs, I'm not sure that would come into play, because the checkboxes are working as intended: they change state when activated by the mouse or keyboard and surely send the stateChanged signal.

By the way, can this get the "Accessibility" tag?

And thanks for looking into this and providing those clarifications.

RytoEX commented 2 years ago

Going over the docs for QAbstractButton::clicked() it's not clear to me whether or not this is triggered by the keyboard, but turning on Full Keyboard Access [System Preferences - Accessibility - Keyboard] and tabbing to the mute control and hitting space reproduces the same unintended behavior I noticed with VoiceOver: the checkbox is checked, but the source isn't muted. That might be an easier way to verify and test this.

Regarding upstream Qt bugs, I'm not sure that would come into play, because the checkboxes are working as intended: they change state when activated by the mouse or keyboard and surely send the stateChanged signal.

On Windows 10, while running Narrator, pressing space bar while the mute checkbox for a source in the Audio Mixer is highlighted causes Narrator to read out that the mute checkbox has been checked. The audio from that mixer source will mute immediately in the output (file written to disk, in this case). It's possible that there is a Qt issue regarding VoiceOver or QAbstractButton::clicked() or a platform implementation difference between Windows and macOS where space bar (or CTRL+OPT+Space) activates QAbstractButton::clicked() on one but not the other.

As far as I can tell, if the UI for the mute checkbox has updated, the code to mute the source must have run. Have you checked the resulting output (a video file and/or stream) to see if the source's audio is actually muted in the output? I'm curious if this is just a visual issue with the volume meter not updating to grayscale.

nebeker commented 2 years ago

As far as I can tell, if the UI for the mute checkbox has updated, the code to mute the source must have run. Have you checked the resulting output (a video file and/or stream) to see if the source's audio is actually muted in the output? I'm curious if this is just a visual issue with the volume meter not updating to grayscale.

I figured this out, while a totally blind friend was testing live, on stream. They then recorded to disk and got the same results. I then recorded to disk myself and got the same results.

It sounds like it could be a platform specific issue, but it turns out it doesn't affect other buttons, so I think it's scoped to the checkbox controls. Are any other controls based on checkboxes, so I could test them?

I'd urge you to have this tested on macOS, either with VO or with keyboard full access. I don't expect you to take my word for it - I would want to verify a bug report too - but testing on Windows will not help.

RytoEX commented 2 years ago

It sounds like it could be a platform specific issue, but it turns out it doesn't affect other buttons, so I think it's scoped to the checkbox controls. Are any other controls based on checkboxes, so I could test them?

From a brief code search, it seems that the Visibility and Locked buttons in the Sources list (the eye and lock icons) are actually derived from QCheckBox. There are checkboxes in the Advanced Audio Properties dialog, as well as throughout the Settings dialog.

I'd urge you to have this tested on macOS, either with VO or with keyboard full access. I don't expect you to take my word for it - I would want to verify a bug report too - but testing on Windows will not help.

I do not have a Mac to test on, so that will have to fall to someone else.

I manually examined the code paths for how the muting is handled. I tested on Windows specifically to provide an observation of contrasting behavior on a different platform. This serves multiple purposes, such as isolating the scope of the issue by removing a platform from testing and debugging, and also to point out that this may yet be a Qt issue that is specific to macOS, because all of the code I examined is otherwise the same for all platforms. I asked clarifying questions to further clarify and narrow the scope of the issue being examined.

nebeker commented 2 years ago

(...) it seems that the Visibility and Locked buttons in the Sources list (the eye and lock icons) are actually derived from QCheckBox.

OK, I can't get to those by tabbing and with VoiceOver, I can get to the sources, but not the checkboxes. That's actually really surprising to me.

There are checkboxes in the Advanced Audio Properties dialog

I can't get to these with VoiceOver (same as #2502), but tabbing and arrowing there, visually works, and they seem to be working.

as well as throughout the Settings dialog.

These seem to work.

It looks like this might be the only checkbox with extended behavior, since the other act and look like regular form checkboxes.

I manually examined the code paths for how the muting is handled. I tested on Windows specifically to provide an observation of contrasting behavior on a different platform. This serves multiple purposes, such as isolating the scope of the issue by removing a platform from testing and debugging, and also to point out that this may yet be a Qt issue that is specific to macOS, because all of the code I examined is otherwise the same for all platforms. I asked clarifying questions to further clarify and narrow the scope of the issue being examined.

Gotcha, that's excellent. Again, thanks for taking the time to dig into this.

gxalpha commented 1 year ago

Small update on the situation here:

nebeker commented 5 hours ago

Still present: macOS 15.0.1 (24A348) OBS Studio - 30.2.3