WebAPI/AudioChannels

From MozillaWiki
Jump to navigation Jump to search

This API introduces the concept of a hierarchy of audio channels. The channels are prioritized as to allow "silencing all channels with priority lower than X".

The problems that we are trying to solve are:

  • When the user answers a phone call, the sound from all apps should be silenced
  • The alarm clock shouldn't be muted even if normal audio is muted. This to prevent the user oversleeping due to having muted the phone the previous day.
  • When the user leaves an app, under normal circumstances the app should be muted.
  • Some apps need to be able to opt in to not getting muted when the user leaves the app, such as the music player app or the radio app.
  • When the volume keys are used it should change the volume for different audio types depending on context. For example while in the alarm app, the volume keys should adjust the alarm volume and not the "normal" volume.
  • When a video app starts playing audio, background music should be muted while video is playing.

See also: https://etherpad.mozilla.org/sound-stream-types

The channels are:

  • normal: UI sounds, web content, music, radio
  • content: music, video.
  • notification: New email, incoming SMS
  • alarm: Alarm clock, calendar alarms
  • telephony: Phone calls, voip calls.
  • ringer: Incoming phone calls.
  • publicnotification: Forced camera shutter sounds. This will not be in V1.

Whenever an audio channel is used, or lower priority channels are automatically paused. The only exception to this is that "normal" and "content" has the same priority which means that if the "content" channel is used, it's simply mixed with audio from the "normal" channel.

If two apps try to use the "content" channel at the same time, the foreground app wins. If both of the apps are background apps, then the last app to try to use the channel wins.

We'll have separate mute and volume settings per channel. We'll additionally have a volume and mute setting for a "headphones" channel. The "headphones" channel is used both for normal headphones as well as for bluetooth headsets.

For now all sounds are directed through headphones/headset when they are plugged in. We discussed possibly making the alarm sound through both headphones and speaker, but we deemed this a non-v1 feature. Whenever

For now all audio channels except "telephony" never use the built-in earpiece. I.e. they always use the speaker or headphones/headset. We might introduce using the built-in earpiece for "normal" sounds in a future version.

When the volume up/down buttons on a bluetooth headset is pressed, we'll treat that exactly as when the on-device volume up/down buttons are pressed.

Application API

interface AudioChannelManager : EventTarget {
 // We might not need this headphones section for v1. 
 readonly attribute boolean headphones;
 attribute EventHandler onheadphoneschange; // Always fired before audio start playing through the new channel

 attribute boolean telephonySpeaker; // Not in V1
}

We'll additionally introduce a new attribute "mozchannel" on <audio> and <video> which selects which audio channel will be used for any played audio.

partial interface HTMLMediaElement {
 attribute DOMString mozchannel; // Or are we using some other name?

 readonly attribute boolean mozchannelpaused; // Returns true if this element is currently paused due to the channel being paused.
 // Should these events only fire if the element is currently played?
 attribute EventTarget onmozchannelpaused;
 attribute EventTarget onmozchannelunpaused;
}


For apps that want to keep being able to play audio when the user leaves the app, the app can call requestWakeLock("audio") to grab an "audio" wakelock. As long as the app holds the "audio" wakelock its mozchannelpaused property won't change due to the user leaving the app.

The mozchannelpaused property can change both as a result of an app being put in the background, or as a result of the channel being paused due to a higher priority channel being used.

Open questions

Do we need the ability to mute a channel without actually playing audio in it? It might be nice to enable muting a channel half a second before starting to use it. Not a v1 feature most likely.

Should we use canceling of events rather than a wakelock to allow audio to keep playing in the background?

System and Browser API changes

We need to add settings for controlling the volume of each of the channels.

We need the ability for the system app to get information about which audio channel is currently used, if any. This is so that it can adjust the appropriate audio channel when the user presses the volume buttons.

If headphones or a headset is plugged in, the volume buttons should always change the volume of the "headphones" channel.

In order to support a "audio" wakelock we should extend the browser API with two things. First off, we should add the ability to enumerate the set of locks that are being held by any page inside the <iframe mozbrowser>. As well as an event that is fired whenever that list changes.

Second, we should add an API to pause/ununpause the contents of the <iframe mozbrowser>. When a <iframe mozbrowser> is paused or unpaused, we'd change the mozchannelpaused property on all media elements inside the browser.

Security model

In order to get access to anything more than the "normal" channel, the application needs to enumerate these channels in the permissions property in the app manifest. So something like:

permissions: {
  ...
  audio: {
    channels: ["notification", "alarm"]
  },
  ...
}

This would enable the app to play sound through both the "notification" channel and the "alarm" channel.

I'm not sure if we need to have prompts if non-privileged apps try to use channels beyond the "normal" or "content" channels.