Allow <audio> to play without user interaction in accordance to autoplay setting

Since 2018, Chromium by default requires at least one user interaction with a page in order for sound to play. That's not what an Anki user expects.

So this commit undoes this by setting the policy accordingly if the deck's settings have autoplay set, so that files in <audio> tags (if they further have the autoplay attribute set / are jscripted accordingly) are treated the same as ones in [sound:…] elements. OFC, it's obviously not a good idea to mix both on one card.

(AnkiDroid's WebView has already been unconditionally ignoring the requirement since forever.)
This commit is contained in:
Andreas Reis 2020-10-14 02:10:16 +02:00
parent e68a40f13e
commit 54f51da944
4 changed files with 13 additions and 0 deletions

View file

@ -491,12 +491,14 @@ class CardLayout(QDialog):
self.have_autoplayed = True
if c.autoplay():
AnkiWebView.setPlaybackRequiresGesture(False)
if self.pform.preview_front.isChecked():
audio = c.question_av_tags()
else:
audio = c.answer_av_tags()
av_player.play_tags(audio)
else:
AnkiWebView.setPlaybackRequiresGesture(True)
av_player.clear_queue_and_maybe_interrupt()
self.updateCardNames()

View file

@ -184,6 +184,7 @@ class Previewer(QDialog):
bodyclass = theme_manager.body_classes_for_card_ord(c.ord)
if c.autoplay():
AnkiWebView.setPlaybackRequiresGesture(False)
if self._show_both_sides:
# if we're showing both sides at once, remove any audio
# from the answer that's appeared on the question already
@ -198,6 +199,7 @@ class Previewer(QDialog):
audio = c.answer_av_tags()
av_player.play_tags(audio)
else:
AnkiWebView.setPlaybackRequiresGesture(True)
av_player.clear_queue_and_maybe_interrupt()
txt = self.mw.prepare_card_text_for_display(txt)

View file

@ -23,6 +23,7 @@ from aqt.sound import av_player, getAudio, play_clicked_audio
from aqt.theme import theme_manager
from aqt.toolbar import BottomBar
from aqt.utils import askUserDialog, downArrow, qtMenuShortcutWorkaround, tooltip
from aqt.webview import AnkiWebView
class ReviewerBottomBar:
@ -183,10 +184,12 @@ class Reviewer:
q = c.q()
# play audio?
if c.autoplay():
AnkiWebView.setPlaybackRequiresGesture(False)
sounds = c.question_av_tags()
gui_hooks.reviewer_will_play_question_sounds(c, sounds)
av_player.play_tags(sounds)
else:
AnkiWebView.setPlaybackRequiresGesture(True)
av_player.clear_queue_and_maybe_interrupt()
sounds = []
gui_hooks.reviewer_will_play_question_sounds(c, sounds)

View file

@ -340,6 +340,12 @@ class AnkiWebView(QWebEngineView):
newFactor = desiredScale / qtIntScale
return max(1, newFactor)
@staticmethod
def setPlaybackRequiresGesture(value: bool) -> None:
QWebEngineSettings.globalSettings().setAttribute(
QWebEngineSettings.PlaybackRequiresUserGesture, value
)
def _getQtIntScale(self, screen) -> int:
# try to detect if Qt has scaled the screen
# - qt will round the scale factor to a whole number, so a dpi of 125% = 1x,