diff --git a/.github/workflows/auto-publish.yml b/.github/workflows/auto-publish.yml
new file mode 100644
index 0000000..4ca6ca9
--- /dev/null
+++ b/.github/workflows/auto-publish.yml
@@ -0,0 +1,36 @@
+# Workflow based on the main w3c/spec-prod action example:
+# https://github.com/w3c/spec-prod/#basic-usage
+
+name: Build, Validate, Deploy and Publish
+
+on:
+ # Worflow runs on pull requests where it makes sure that the spec can still be
+ # generated, that markup is valid and that there are no broken links, as
+ # well as on pushes to the default branch where it also deploys the generated
+ # spec to the gh-pages branch and publishes the result to /TR.
+ # The "workflow_dispatch" hook allows admins to also trigger the workflow
+ # manually from GitHub's UI.
+ pull_request: {}
+ push:
+ branches: [main]
+ workflow_dispatch:
+
+jobs:
+ main:
+ runs-on: ubuntu-20.04
+ steps:
+ # See doc at https://github.com/actions/checkout#checkout-v2
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ # See doc at https://github.com/w3c/spec-prod/#spec-prod
+ # The action only deploys the generated spec to the gh-pages branch when
+ # the workflow was triggered by a push to the default branch.
+ - name: Build and validate index.html, push to gh-pages branch if needed
+ uses: w3c/spec-prod@v2
+ with:
+ GH_PAGES_BRANCH: gh-pages
+ W3C_ECHIDNA_TOKEN: ${{ secrets.ECHIDNA_TOKEN }}
+ W3C_WG_DECISION_URL: https://github.com/w3c/media-wg/issues/27
+ W3C_BUILD_OVERRIDE: |
+ status: WD
diff --git a/.github/workflows/tidy.yaml b/.github/workflows/tidy.yaml
new file mode 100644
index 0000000..7fb7a22
--- /dev/null
+++ b/.github/workflows/tidy.yaml
@@ -0,0 +1,21 @@
+name: Tidy document
+on:
+ workflow_dispatch: {}
+ push:
+ branches:
+ - gh-pages
+ paths:
+ - index.html
+
+jobs:
+ tidy:
+ name: Tidy up
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v4
+ - run: make
+ - uses: peter-evans/create-pull-request@v6
+ with:
+ title: "Tidied up source"
+ commit-message: "chore(index.bs): tidy up"
+ branch: tidy
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 7a24eaa..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-language: generic
-
-script: bash ./deploy.sh
-
-branches:
- only:
- - master
-
-env:
- global:
- - ENCRYPTION_LABEL: 9b5128ce1dd6
- - COMMIT_AUTHOR_EMAIL: travis-ci@w3.org
diff --git a/README.md b/README.md
index 7cc31ed..f55ecaf 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Media Session Standard
+# Media Session API
https://w3c.github.io/mediasession/
diff --git a/deploy.sh b/deploy.sh
deleted file mode 100644
index 56f8c09..0000000
--- a/deploy.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/bash
-set -e # Exit with nonzero exit code if anything fails
-
-SOURCE_BRANCH="master"
-TARGET_BRANCH="gh-pages"
-
-# Pull requests and commits to other branches shouldn't try to deploy, just build to verify
-if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then
- echo "Skipping deploy; just doing a build."
- curl https://api.csswg.org/bikeshed/ -f -F file=@index.bs > index.html;
- exit 0
-fi
-
-# Save some useful information
-REPO=`git config remote.origin.url`
-SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
-SHA=`git rev-parse --verify HEAD`
-
-# Clone the existing gh-pages for this repo into out/
-# Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply)
-git clone $REPO out
-cd out
-git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
-cd ..
-
-# Clean out existing contents
-rm -rf out/* || exit 0
-
-# Re-format.
-
-./format.py index.bs
-
-# Re-generating.
-curl https://api.csswg.org/bikeshed/ -f -F file=@index.bs > out/index.html;
-
-# Now let's go have some fun with the cloned repo
-cd out
-git config user.name "Travis CI"
-git config user.email "$COMMIT_AUTHOR_EMAIL"
-
-# If there are no changes to the compiled out (e.g. this is a README update) then just bail.
-if [[ -z $(git status -s) ]]; then
- echo "No changes to the output on this push; exiting."
- exit 0
-fi
-
-# Commit the "changes", i.e. the new version.
-# The delta will show diffs between new and old versions.
-git add .
-git commit -m "Deploy to GitHub Pages: ${SHA}"
-
-# Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc
-ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
-ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
-ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
-ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
-openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../deploy_key.enc -out deploy_key -d
-chmod 600 deploy_key
-eval `ssh-agent -s`
-ssh-add deploy_key
-
-# Now that we're all set up, we can push.
-git push $SSH_REPO $TARGET_BRANCH
diff --git a/deploy_key.enc b/deploy_key.enc
deleted file mode 100644
index 4c0b312..0000000
Binary files a/deploy_key.enc and /dev/null differ
diff --git a/explainer.md b/explainer.md
index 142a186..0e37c4a 100644
--- a/explainer.md
+++ b/explainer.md
@@ -106,9 +106,10 @@ interface MediaSession : EventTarget {
### The `MediaMetadata` interface
-A `MediaMetadata` object can contain media metadata like title, artist, album
-and album art. To set the metadata for a `MediaSession`, the page should create
-a `MediaMetadata` object and assign it to a `MediaSession` object:
+A `MediaMetadata` object can contain media metadata like title, artist, album,
+artwork, and video chapter information. To set the metadata for a `MediaSession`,
+the page should create a `MediaMetadata` object and assign it to a `MediaSession`
+object:
```javascript
navigator.mediaSession.metadata = new MediaMetadata(/* MediaMetadata constructor */);
@@ -123,6 +124,7 @@ interface MediaMetadata {
attribute DOMString artist;
attribute DOMString album;
attribute FrozenArray
- In order to make play and
- pause actions work properly,
- the user agent SHOULD be able to determine if a browsing context of
- the active media session is playing media or not, which is called
- the guessed playback state. The RECOMMENDED way for determining
- the guessed playback state is to monitor the media elements whose
- node document's browsing context is the browsing context. The
- browsing context's guessed playback state is playing if any of them is
- potentially playing and not muted, and is paused otherwise. Other information
- SHOULD also be considered, such as WebAudio and plugins.
+ In order to make {{MediaSessionAction/play}} and
+ {{MediaSessionAction/pause}} actions work properly, the user agent SHOULD
+ be able to determine if a [=/browsing context=] of the active media
+ session is playing media or not, which is called the guessed
+ playback state. The RECOMMENDED way for determining the guessed
+ playback state is to monitor the media elements whose node document's
+ [=Document/browsing context=] is the [=/browsing context=]. The
+ [=/browsing context=]'s guessed playback state is
+ {{MediaSessionPlaybackState/"playing"}} if any of them is
+ [=media element/potentially playing=] and not [=media element/muted=],
+ and is {{MediaSessionPlaybackState/"paused"}} otherwise. Other
+ information SHOULD also be considered, such as WebAudio and plugins.
- The playbackState attribute specifies
- the declared playback state from the browsing context. The
- state is combined with the guessed playback state to compute the
+ The {{MediaSession/playbackState}} attribute specifies the declared
+ playback state from the [=/browsing context=]. The state is combined
+ with the guessed playback state to compute the
actual playback state, which is a finalized state and will be
- used for
- play and
- pause actions.
+ used for {{MediaSessionAction/play}} and {{MediaSessionAction/pause}}
+ actions.
The actual playback state is computed in the following way:
The {{MediaSession/playbackState}} attribute could be useful when the page
wants to do some preparation steps when the media is paused but it allows
- the preparation steps to be interrupted by pause action. See Setting playbackState for example.
+ the preparation steps to be interrupted by {{MediaSessionAction/pause}}
+ action. See Setting playbackState
+ for example.
@@ -304,7 +215,7 @@ conforming IDL fragments, as described in the Web IDL specification. [[!WEBIDL]]
There could be multiple {{MediaSession}} objects existing at the same time
since the user agent could have multiple tabs, each tab could contain a
top-level browsing context and multiple nested browsing
- contexts, and each browsing context could have a {{MediaSession}}
+ contexts, and each [=/browsing context=] could have a {{MediaSession}}
object.
The user agent MUST select at most one of the {{MediaSession}} objects to
@@ -315,10 +226,10 @@ conforming IDL fragments, as described in the Web IDL specification. [[!WEBIDL]]
routing. It only takes effect for the active media session.
It is RECOMMENDED that the user agent selects the active media
- session by managing audio focus. A tab or browsing context
- is said to have audio focus if it is currently playing audio or
- the user expects to control the media in it. The AudioFocus API targets this
- area and could be used once it's finished.
+ session by managing audio focus. A tab or [=Window/browsing
+ context=] is said to have audio focus if it is currently playing
+ audio or the user expects to control the media in it. The AudioFocus API
+ targets this area and could be used once it's finished.
Whenever the active media session is changed, the user agent MUST run
the media session actions update algorithm and the update metadata
@@ -330,10 +241,9 @@ conforming IDL fragments, as described in the Web IDL specification. [[!WEBIDL]]
The media metadata for the active media session MAY be displayed in
the platform UI depending on platform conventions. Whenever the active
- media session changes or setting
-Title: Media Session Standard
+Title: Media Session
Repository: w3c/mediasession
Status: ED
-ED: https://w3c.github.io/mediasession
+ED: https://w3c.github.io/mediasession/
+TR: https://www.w3.org/TR/mediasession/
Shortname: mediasession
-Level: 1
-Editor: Mounir Lamouri, w3cid 45389, Google Inc., mlamouri@google.com
-Editor: Becca Hughes, w3cid 103353, Google Inc., beccahughes@google.com
+Level: None
+Editor: Tommy Steimel, w3cid 135774, Google Inc., steimel@google.com
+Editor: Youenn Fablet, w3cid 96458, Apple Inc., youenn@apple.com
+Former Editor: Mounir Lamouri, w3cid 45389, Google Inc., mlamouri@google.com
+Former Editor: Becca Hughes, w3cid 103353, Google Inc., beccahughes@google.com
Former Editor: Zhiqiang Zhang, Google Inc., zqzhang@google.com
Former Editor: Rich Tibbett, Opera, richt@opera.com
+Markup Shorthands: markdown yes
Group: mediawg
Logo: https://resources.whatwg.org/logo-mediasession.svg
Abstract: This specification enables web developers to show customized media
@@ -17,12 +21,8 @@ Abstract: metadata on platform UI, customize available platform media
Abstract: controls, and access platform media keys such as hardware keys found
Abstract: on keyboards, headsets, remote controls, and software keys found in
Abstract: notification areas and on lock screens of mobile devices.
-!Participate: We are on GitHub
-!Participate: File an issue
-!Participate: Open issues
!Version History: https://github.com/w3c/mediasession/commits
Ignored Vars: context, media, session
-Boilerplate: omit conformance, omit feedback-header
+
+spec:html; type:element; text:link
+
+
urlPrefix: https://html.spec.whatwg.org/multipage/; spec: HTML
type: dfn
- urlPrefix: infrastructure.html
- text: case-sensitive; url: #case-sensitivity-and-string-comparison
- text: ASCII case-insensitive; url: #ascii-case-insensitive
- text: in parallel
- text: unordered set of unique space-separated tokens; url: #unordered-set-of-unique-space-separated-tokens
- text: document base url
- text: MIME type
- urlPrefix: embedded-content.html
- text: media element
- text: muted; url: #concept-media-muted
- text: pause event; url: #event-media-pause
- text: play event; url: #event-media-play
- text: potentially playing
- urlPrefix: browsers.html
- text: browsing context
- text: top-level browsing context
- text: nested browsing context
urlPrefix: webappapis.html
- text: API base URL
text: entry settings object
- text: queue a task
- text: task
- text: task source
- urlPrefix: semantics.html
- text: link; for: HTMLLinkElement; url:#the-link-element
urlPrefix: interaction.html
- text: triggered by user activation
- type: attribute
- urlPrefix: semantics.html
- text: sizes; for: HTMLLinkElement; url: #attr-link-sizes;
-urlPrefix: https://url.spec.whatwg.org/; spec: URL
- type: dfn; urlPrefix: #concept-
- text: url parser
- type: dfn
- text: absolute URL; url: #syntax-url-absolute
- text: relative URL; url: #syntax-url-relative
-urlPrefix: https://fetch.spec.whatwg.org/; spec: FETCH
- type: dfn; urlPrefix: #concept-
- text: fetch
- text: request
- text: context; url: request-context
- text: context frame type; url: request-context-frame-type
- text: internal response
- text: origin; url: request-origin
- text: referrer; url: request-referrer
- text: response
- text: response type
- text: url; url: request-url
- type: dfn;
- text: force Origin header flag
-urlPrefix: https://www.w3.org/TR/appmanifest/; spec: appmanifest
- type: dfn
- text: image object; url: #dfn-image-object
-urlPrefix: https://heycam.github.io/webidl/
- type: exception
- text: TypeError
-urlPrefix: https://tc39.github.io/ecma262/#sec-object.; type: dfn
- text: freeze
+ text: activation notification
Introduction
@@ -117,49 +67,11 @@ urlPrefix: https://tc39.github.io/ecma262/#sec-object.; type: dfn
Media is used extensively today, and the Web is one of the primary means of
consuming media content. Many platforms can display media metadata, such as
-title, artist, album and album art on various UI elements such as notification,
-media control center, device lockscreen and wearable devices. This specification
-aims to enable web pages to specify the media metadata to be displayed in
-platform UI, and respond to media controls which may come from platform UI or
-media keys, thereby improving the user experience.
-
-Conformance
-
-All diagrams, examples, and notes in this specification are non-normative, as
-are all sections explicitly marked non-normative. Everything else in this
-specification is normative.
-
-The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
-"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this
-document are to be interpreted as described in RFC 2119. For readability, these
-words do not appear in all uppercase letters in this specification. [[!RFC2119]]
-
-Requirements phrased in the imperative as part of algorithms (such as "strip any
-leading space characters" or "return false and terminate these steps") are to be
-interpreted with the meaning of the key word ("must", "should", "may", etc) used
-in introducing the algorithm.
-
-Conformance requirements phrased as algorithms or specific steps may be
-implemented in any manner, so long as the end result is equivalent. (In
-particular, the algorithms defined in this specification are intended to be easy
-to follow, and not intended to be performant.)
-
-User agents may impose implementation-specific limits on otherwise unconstrained
-inputs, e.g. to prevent denial of service attacks, to guard against running out
-of memory, or to work around platform-specific limitations.
-
-When a method or an attribute is said to call another method or attribute, the
-user agent must invoke its internal API for that attribute or method so that
-e.g. the author can't change the behavior by overriding attributes or methods
-with custom properties or functions in JavaScript.
-
-Unless otherwise stated, string comparisons are done in a case-sensitive
-manner.
-
-Dependencies
-
-The IDL fragments in this specification must be interpreted as required for
-conforming IDL fragments, as described in the Web IDL specification. [[!WEBIDL]]
+title, artist, album and album art on various UI elements such as notifications,
+media control center, device lockscreen, and wearable devices. This
+specification aims to enable web pages to specify the media metadata to be
+displayed in platform UI, and respond to media controls that may come from
+platform UI or media keys, thereby improving the user experience.
Security and Privacy
@@ -245,37 +157,36 @@ conforming IDL fragments, as described in the Web IDL specification. [[!WEBIDL]]
Playback State
metadata
of the active media
- session, the user agent MUST run the update metadata
- algorithm. The steps are as follows:
+ media session changes or setting {{MediaSession/metadata}} of the
+ active media session, the user agent MUST run the update
+ metadata algorithm. The steps are as follows:
@@ -365,30 +275,27 @@ conforming IDL fragments, as described in the Web IDL specification. [[!WEBIDL]]
existing algorithm execution instances.
metadata
of the
+ If the {{MediaSession/metadata}} of the
active media session is an empty metadata, unset the media
metadata presented to the platform, and terminate these steps.
metadata
for the
+ Update the media metadata presented to the platform to match the
+ {{MediaSession/metadata}} for the
active media session.
artwork
of the active media
- session is empty, then terminate these steps.
+ If metadata's {{MediaMetadata/artwork}} of the active
+ media session is empty, then terminate these steps.
artwork
of the active
- media session.
+ preferred artwork image from metadata's
+ {{MediaMetadata/artwork}} of the active media session.
- A media session action - source is a source that might produce a media session action. - Such a source can be the platform or the UI surfaces created by the user - agent. + A media session action source is a source that might produce a + media session action. Such a source can be the platform or the UI + surfaces created by the user agent. +
++ A media session action source has an optional + target which should be the + recipient of any media session action created by the + media session action source. If a media session action + source's + target is `null`, the active + media session is the recipient of all + media session action source's actions.
@@ -425,45 +341,72 @@ conforming IDL fragments, as described in the Web IDL specification. [[!WEBIDL]] which can have one of the following value:
null
, remove action
+ If handler is `null`, remove action
from the supported media session actions for {{MediaSession}}
and abort these steps.
When the user agent is notified by a media session action source - that a + named source that a media session action named action has been triggered, - the user agent MUST run the handle media session action steps - as follows and consider it triggered by user activation: + the user agent MUST queue a task, using the [=user interaction task + source=], to run the following + handle media session action steps:
null
, abort these
- steps.
+ Let session be source's target.
+ null
, abort these
- steps.
+ If the active media session is `null`, abort these steps.
+ A user agent MAY implement a default handler for the togglemicrophone, togglecamera, or hangup media session actions if none was + provided for the active media session. +
++ A user agent MAY expose microphone and camera state to web pages via + {{MediaStreamTrack}}'s {{MediaStreamTrack/muted}} attribute in addition + to {{MediaSessionAction/togglemicrophone}} or + {{MediaSessionAction/togglecamera}} [=media session action=]. In that + case, the user agent MUST execute the corresponding + {{MediaSessionActionHandler}} before running, as different tasks, the + steps defined to [$set a track's muted state$]. +
+
A page should only register a {{MediaSessionActionHandler}} for a media
session action when it can handle the action given that the user agent
@@ -640,7 +599,7 @@ conforming IDL fragments, as described in the Web IDL specification. [[!WEBIDL]]
A user agent MAY display the current playback position and
@@ -673,7 +632,7 @@ conforming IDL fragments, as described in the Web IDL specification. [[!WEBIDL]]
The RECOMMENDED way to determine the position state is to monitor
the media elements whose node document's browsing context is the
- browsing context.
+ [=/browsing context=].
@@ -745,10 +704,16 @@ enum MediaSessionAction {
"nexttrack",
"skipad",
"stop",
- "seekto"
+ "seekto",
+ "togglemicrophone",
+ "togglecamera",
+ "hangup",
+ "previousslide",
+ "nextslide",
+ "enterpictureinpicture"
};
-callback MediaSessionActionHandler = void(MediaSessionActionDetails details);
+callback MediaSessionActionHandler = undefined(MediaSessionActionDetails details);
[Exposed=Window]
interface MediaSession {
@@ -756,9 +721,13 @@ interface MediaSession {
attribute MediaSessionPlaybackState playbackState;
- void setActionHandler(MediaSessionAction action, MediaSessionActionHandler? handler);
+ undefined setActionHandler(MediaSessionAction action, MediaSessionActionHandler? handler);
+
+ undefined setPositionState(optional MediaPositionState state = {});
- void setPositionState(optional MediaPositionState? state);
+ Promise<undefined> setMicrophoneActive(boolean active);
+
+ Promise<undefined> setCameraActive(boolean active);
};
@@ -770,7 +739,7 @@ interface MediaSession {
A {{MediaSession}} has an associated metadata
- object represented by a {{MediaMetadata}}. It is initially
@@ -781,24 +750,21 @@ interface MediaSession {
The
The
@@ -826,66 +792,67 @@ interface MediaSession {
The {{MediaSessionPlaybackState}} enum is used to indicate whether a
- browsing context is playing media or not, the values are described as
+ [=/browsing context=] is playing media or not, the values are described as
follows:
Position State
+ Position State
null
.
+ object represented by a {{MediaMetadata}}. It is initially `null`.
metadata
attribute
- reflects the {{MediaSession}}'s metadata. On getting,
- it MUST return the {{MediaSession}}'s metadata. On
- setting, it MUST run the following steps with value being the new
- value being set:
+ reflects the {{MediaSession}}'s {{MediaSession/metadata}}. On getting, it MUST
+ return the {{MediaSession}}'s {{MediaSession/metadata}}. On setting, it MUST
+ run the following steps with value being the new value being set:
null
, set its media session to
- null
.
+ If the {{MediaSession}}'s {{MediaSession/metadata}} is not `null`, set its
+ [=MediaMetadata/media session=] to `null`.
null
, set its media session to the
- current {{MediaSession}}.
+ If the {{MediaSession}}'s {{MediaSession/metadata}} is not `null`, set its
+ [=MediaMetadata/media session=] to the current {{MediaSession}}.
playbackState
attribute represents the declared playback state of the media
- session, by which the session declares whether its browsing context
+ session, by which the session declares whether its [=/browsing context=]
is playing media or not. The initial value is none. On setting, the user agent MUST set
the IDL attribute to the new value if it is a valid
{{MediaSessionPlaybackState}} value. On getting, the user agent MUST return
the last valid value that was set. The {{MediaSession/playbackState}}
- attribute is a hint for the user agent to determine whether the browsing
- context is playing or paused.
+ attribute is a hint for the user agent to determine whether the [=/browsing
+ context=] is playing or paused.
- The setActionHandler() method, when - invoked, MUST run the update action handler algorithm with + The setActionHandler(action, handler) + method, when invoked, MUST run the update action handler algorithm with action and handler on the {{MediaSession}}.
- The setPositionState() method, when invoked - MUST perform the following steps: + The setPositionState(|state|) method, when + invoked MUST perform the following steps:
NaN
, throw a TypeError.
+ The setMicrophoneActive(active) method
+ indicates to the user agent the microphone capture state desired by the page
+ (e.g. if the microphone is considered "inactive" by the page since it is no
+ longer sending audio through a call, the page can invoke
+ setMicrophoneActive(false)
). When invoked, it MUST perform the
+ following steps:
+
+ Similarly, the setCameraActive(active) + method indicates to the user agent the camera capture state desired by the + page. When invoked, it MUST perform the following steps: +
+ The update capture state algorithm, when invoked with + document, active and captureKind, MUST + perform the following steps: +
true
and document's
+ [=Document/visibility state=] is not "visible", the user agent MAY return
+ [=a promise rejected with=] InvalidStateError.
+ true
if the user agent
+ implements a policy of pausing all input sources of type
+ captureKind in response to UI and false
+ otherwise.
+ true
, run the following
+ substeps:
+ false
if the user
+ agent is currently [=pausing all input sources=] of type
+ captureKind
+ and true
otherwise.
+ undefined
and abort these steps.
+ true
, the user agent MAY wait
+ to proceed, for instance to prompt the user.
+ undefined
.true
, run the following
+ substeps:
+ true
if
+ active is
+ false
and false
otherwise.+ Both the setMicrophoneActive(active) and setCameraActive(active) + methods can reject based on user agent specific heuristics. This might in + particular happen when the web page asks to activate (aka unmute) microphone + or camera. The user agent could decide to require [=transient activation=] in + that case. It might also require user input through a prompt to make the + actual decision. +
+ ++ The user agent MAY display UI which invokes handlers for + media session actions. +
+@@ -903,7 +1003,8 @@ interface MediaMetadata { attribute DOMString title; attribute DOMString artist; attribute DOMString album; - attribute FrozenArray<object> artwork; + attribute FrozenArray<MediaImage> artwork; + [SameObject] readonly attribute FrozenArray<ChapterInformation> chapterInfo; }; dictionary MediaMetadataInit { @@ -911,6 +1012,7 @@ dictionary MediaMetadataInit { DOMString artist = ""; DOMString album = ""; sequence<MediaImage> artwork = []; + sequence<ChapterInformationInit> chapterInfo = []; };@@ -937,21 +1039,27 @@ dictionary MediaMetadataInit { but a list of type {{MediaImage}} internally. +
+ A {{MediaMetadata}} has an associated list of + chapter information. +
+
A {{MediaMetadata}} is said to be an empty metadata if it is equal
- to null
or all the following conditions are true:
+ to `null` or all the following conditions are true:
0
.0
.
- The MediaMetadata(init)
+ The MediaMetadata(init)
constructor, when invoked, MUST run the following steps:
- The title
attribute
- reflects the {{MediaMetadata}}'s title. On getting,
- it MUST return the {{MediaMetadata}}'s title. On
- setting, it MUST set the {{MediaMetadata}}'s title to
- the given value.
+ The title attribute reflects the
+ {{MediaMetadata}}'s title. On getting, it MUST return
+ the {{MediaMetadata}}'s title. On setting, it MUST
+ set the {{MediaMetadata}}'s title to the given value.
- The artist
attribute
- reflects the {{MediaMetadata}}'s artist. On getting,
- it MUST return the {{MediaMetadata}}'s artist. On
- setting, it MUST set the {{MediaMetadata}}'s artist
+ The artist attribute reflects the
+ {{MediaMetadata}}'s artist. On getting, it MUST
+ return the {{MediaMetadata}}'s artist. On setting, it
+ MUST set the {{MediaMetadata}}'s artist
to the given value.
- The album
attribute
- reflects the {{MediaMetadata}}'s album. On getting,
- it MUST return the {{MediaMetadata}}'s album. On
- setting, it MUST set the {{MediaMetadata}}'s album to
- the given value.
+ The album attribute reflects the
+ {{MediaMetadata}}'s album. On getting, it MUST return
+ the {{MediaMetadata}}'s album. On setting, it MUST
+ set the {{MediaMetadata}}'s album to the given value.
- The artwork
+ The artwork
attribute reflects the {{MediaMetadata}}'s artwork
images. On getting, it MUST return the result of the following steps:
+[Exposed=Window] +interface ChapterInformation { + readonly attribute DOMString title; + readonly attribute double startTime; + [SameObject] readonly attribute FrozenArray<MediaImage> artwork; +}; + +dictionary ChapterInformationInit { + DOMString title = ""; + double startTime = 0; + sequence<MediaImage> artwork = []; +}; + ++ +
+ A {{ChapterInformation}} object is a representation of metadata for an + individual chapter, such as the title of the section, its timestamp, and + screenshot image data of this section, that can be used by user agents to + provide a customized user interface. +
+ ++ A {{ChapterInformation}} can have an associated + media metadata. +
+ ++ A {{ChapterInformation}} has an associated title + which is DOMString. +
+ ++ A {{ChapterInformation}} has an associated + startTime which is double. +
+ ++ A {{ChapterInformation}} has an associated list of + artwork images. +
+ ++ To create a {{ChapterInformation}} with init, run the + following steps: + +
+ The title attribute reflects the + {{ChapterInformation}}'s title. On getting, it + MUST return the {{ChapterInformation}}'s title. +
+ ++ The startTime attribute reflects + the {{ChapterInformation}}'s startTime in + seconds. On getting, it MUST return the {{ChapterInformation}}'s startTime. +
+ ++ The artwork + attribute reflects the {{ChapterInformation}}'s artwork images. On getting, it MUST return the + {{ChapterInformation}}'s + artwork images. +
+@@ -1147,22 +1369,21 @@ dictionary MediaImage { };-The {{MediaImage}} dictionary members are inspired by the image objects in Web App Manifest. +
The {{MediaImage}} dictionary members are inspired by +{{ImageResource}} in [[IMAGE-RESOURCE]].
The src dictionary member is used -to specify the {{MediaImage}} object's source. It is -a URL from which the user agent can fetch the image's data. +to specify the {{MediaImage}} object's source. It is a URL from which the user agent can fetch +the image's data. The sizes dictionary member is used to specify the {{MediaImage}} object's {{MediaImage/sizes}}. It follows the -spec ofsizes
attribute in
-the HTML
-link
element, which is a string
-consisting of an unordered set of unique space-separated tokens which are
-ASCII case-insensitive that represents the dimensions of an image. Each
-keyword is either an ASCII case-insensitive match for the string "any",
-or a value that consists of two valid non-negative integers that do not have a
+spec of <{link/sizes}> attribute in the HTML <{link}> element, which is a string
+consisting of an [=unordered set of unique space-separated tokens=] which are
+[=ASCII case-insensitive=] that represents the dimensions of an image. Each
+keyword is either an [=ASCII case-insensitive=] match for the string "any", or a
+value that consists of two valid non-negative integers that do not have a
leading U+0030 DIGIT ZERO (0) character and that are separated by a single
U+0078 LATIN SMALL LETTER X or U+0058 LATIN CAPITAL LETTER X character. The
keywords represent icon sizes in raw pixels (as opposed to CSS pixels). When
@@ -1183,7 +1404,7 @@ dictionary
dictionary MediaPositionState { - double duration; + unrestricted double duration; double playbackRate; double position; }; @@ -1221,38 +1442,81 @@ dictionary MediaSessionActionDetails { }; dictionary MediaSessionSeekActionDetails : MediaSessionActionDetails { - double? seekOffset; + double seekOffset; }; dictionary MediaSessionSeekToActionDetails : MediaSessionActionDetails { required double seekTime; - boolean? fastSeek; + boolean fastSeek; }; + +dictionary MediaSessionCaptureActionDetails : MediaSessionActionDetails { + boolean isActivating; +}; +The {{MediaSessionActionHandler}} MUST be run with the details -parameter which is represented by a dictionary inherited from -{{MediaSessionActionDetails}}. - -The action dictionary -member -is used to specify the action that the {{MediaSessionActionHandler}} is -associated with. +parameter whose dictionary type is: +
false
if the user agent is about
+to [=pausing all input sources|pause all input sources=] related to the capture
+[=media session action|action=] and true
otherwise. This
+dictionary member MUST be present if the user agent implements a policy
+of [=pausing all input sources=].
-The fastSeek
-dictionary member MAY be provided and will be true if the
-seekto action is being called
-multiple times as part of a sequence and this is not the last call in that
-sequence.
+navigator.mediaSession.metadata = new MediaMetadata({ @@ -1287,23 +1556,32 @@ sequence. {src: "podcast.png", sizes: "128x128", type: "image/png"}, {src: "podcast_hd.png", sizes: "256x256", type: "image/png"}, {src: "podcast.ico", sizes: "128x128 256x256", type: "image/x-icon"} + ], + chapterInfo: [ + {title: "Chapter 1", startTime: 0, artwork: [ + {src: "chapter1_a.jpg", sizes: "128x128", type: "image/jpeg"}, + {src: "chapter1_b.png", sizes: "256x256", type: "image/png"} + ]}, + {title: "Chapter 2", startTime: 120, artwork: [ + {src: "chapter2_a.jpg", sizes: "128x128", type: "image/jpeg"}, + {src: "chapter2_b.png", sizes: "256x256", type: "image/png"} + ]} ] });For example, if the user agent wants to use an image as icon, it may choose -
"podcast.jpg"
or "podcast.png"
for a
- low-pixel-density screen, and "podcast_hd.jpg"
- or "podcast_hd.png"
for a high-pixel-density screen. If the user
- agent wants to use an image for lockscreen background,
- "podcast_xhd.jpg"
will be preferred.
+ `"podcast.jpg"` or `"podcast.png"` for a low-pixel-density screen, and
+ `"podcast_hd.jpg"` or `"podcast_hd.png"` for a high-pixel-density screen. If
+ the user agent wants to use an image for lockscreen background,
+ `"podcast_xhd.jpg"` will be preferred.
@@ -1346,7 +1624,7 @@ sequence. var audio = document.createElement("audio"); audio.src = tracks[trackId]; - void updatePlayingMedia() { + function updatePlayingMedia() { audio.src = tracks[trackId]; // Update metadata (omitted) } @@ -1454,6 +1732,67 @@ sequence.
+ var isMicrophoneActive = false; + var isCameraActive = false; + + navigator.mediaSession.setMicrophoneActive(isMicrophoneActive); + navigator.mediaSession.setCameraActive(isCameraActive); + + navigator.mediaSession.setActionHandler("togglemicrophone", function() { + if (isMicrophoneActive) { + // Mute the microphone. Implementation omitted. + } else { + // Unmute the microphone. Implementation omitted. + } + isMicrophoneActive = !isMicrophoneActive; + navigator.mediaSession.setMicrophoneActive(isMicrophoneActive); + }); + + navigator.mediaSession.setActionHandler("togglecamera", function() { + if (isCameraActive) { + // Disable the camera. Implementation omitted. + } else { + // Enable the camera. Implementation omitted. + } + isCameraActive = !isCameraActive; + navigator.mediaSession.setCameraActive(isCameraActive); + }); + + navigator.mediaSession.setActionHandler("hangup", function() { + // End the call. Implementation omitted. + }); ++
+ var currentSlideIndex = 0; + + navigator.mediaSession.setActionHandler("previousslide", function() { + currentSlideIndex--; + // Set current slide. Implementation omitted. + }); + + navigator.mediaSession.setActionHandler("nextslide", function() { + currentSlideIndex++; + // Set current slide. Implementation omitted. + }); ++
+ navigator.mediaSession.setActionHandler("enterpictureinpicture", function() { + remoteVideo.requestPictureInPicture(); + }); ++