Skip to content

Commit

Permalink
web: Put audioSession specification in more appropriate location
Browse files Browse the repository at this point in the history
  • Loading branch information
danielhjacobs committed Dec 1, 2024
1 parent 718e1e0 commit 16ba548
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 49 deletions.
90 changes: 49 additions & 41 deletions web/packages/core/src/internal/player/inner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ declare global {
*/
webkitRequestFullScreen?: (options: unknown) => unknown;
}
interface AudioSession {
type?: string;
}
}

/**
Expand Down Expand Up @@ -1629,49 +1632,54 @@ export class InnerPlayer {
isAudioContextUnmuted = true;
return;
}
if ("audioSession" in navigator) {
// On browsers which support it (Safari 16.4+), we can specify https://www.w3.org/TR/audio-session/#audio-session-types
(navigator.audioSession as AudioSession).type = "playback";
} else {
// This is a workaround for iOS versions without audioSession support
this.container.addEventListener(
"click",
() => {
if (isAudioContextUnmuted) {
return;
}

this.container.addEventListener(
"click",
() => {
if (isAudioContextUnmuted) {
return;
}

const audioContext = this.instance?.audio_context();
if (!audioContext) {
return;
}
const audioContext = this.instance?.audio_context();
if (!audioContext) {
return;
}

const audio = new Audio();
audio.src = (() => {
// Returns a seven samples long 8 bit mono WAVE file.
// This is required to prevent the AudioContext from desyncing and crashing.
const arrayBuffer = new ArrayBuffer(10);
const dataView = new DataView(arrayBuffer);
const sampleRate = audioContext.sampleRate;
dataView.setUint32(0, sampleRate, true);
dataView.setUint32(4, sampleRate, true);
dataView.setUint16(8, 1, true);
const missingCharacters = window
.btoa(
String.fromCharCode(...new Uint8Array(arrayBuffer)),
)
.slice(0, 13);
return `data:audio/wav;base64,UklGRisAAABXQVZFZm10IBAAAAABAAEA${missingCharacters}AgAZGF0YQcAAACAgICAgICAAAA=`;
})();

audio.load();
audio
.play()
.then(() => {
isAudioContextUnmuted = true;
})
.catch((err) => {
console.warn(`Failed to play dummy sound: ${err}`);
});
},
{ once: true },
);
const audio = new Audio();
audio.src = (() => {
// Returns a seven samples long 8 bit mono WAVE file.
// This is required to prevent the AudioContext from desyncing and crashing.
const arrayBuffer = new ArrayBuffer(10);
const dataView = new DataView(arrayBuffer);
const sampleRate = audioContext.sampleRate;
dataView.setUint32(0, sampleRate, true);
dataView.setUint32(4, sampleRate, true);
dataView.setUint16(8, 1, true);
const missingCharacters = window
.btoa(
String.fromCharCode(...new Uint8Array(arrayBuffer)),
)
.slice(0, 13);
return `data:audio/wav;base64,UklGRisAAABXQVZFZm10IBAAAAABAAEA${missingCharacters}AgAZGF0YQcAAACAgICAgICAAAA=`;
})();

audio.load();
audio
.play()
.then(() => {
isAudioContextUnmuted = true;
})
.catch((err) => {
console.warn(`Failed to play dummy sound: ${err}`);
});
},
{ once: true },
);
}
}

/**
Expand Down
8 changes: 0 additions & 8 deletions web/packages/core/src/plugin-polyfill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,6 @@ declare global {
interface MimeTypeArray {
install?: (mimeType: MimeType) => void;
}
interface AudioSession {
type?: string;
}
}

/**
Expand All @@ -247,11 +244,6 @@ declare global {
* @param plugin The plugin to install
*/
export function installPlugin(plugin: RufflePlugin): void {
// This code is not polyfill related, but while messing with the navigator API,
// we can specify https://www.w3.org/TR/audio-session/#audio-session-types
if ("audioSession" in navigator) {
(navigator.audioSession as AudioSession).type = "playback";
}
if (navigator.plugins.namedItem("Shockwave Flash")) {
return;
}
Expand Down

0 comments on commit 16ba548

Please sign in to comment.