diff --git a/index.html b/index.html index 3855720..fc21584 100644 --- a/index.html +++ b/index.html @@ -132,9 +132,9 @@

Introduction

- This specification aims to make remote playback devices such as + This specification aims to make remote playback devices such as connected TVs, projectors or audio-only speakers, available to the Web and - takes into account displays that are attached using wired (HDMI, DVI, + takes into account playback devices that are attached using wired (HDMI, DVI, or similar) and wireless technologies (Miracast, Chromecast, DLNA, AirPlay, or similar).

@@ -146,15 +146,15 @@

to improve the perceived quality and impact of the played media.

- At its core, this specification enables a page that acts as the controller + At its core, this specification enables a page that acts as the browsing context to initiate and control remote playback of a particular media element on a selected remote playback device. How the remoting is initiated and controlled is left to the UA in order to allow the use of remote playback devices that can be attached in a wide variety of ways. For example, when a remote playback device is attached using HDMI or Miracast, the same UA that acts as the - controller renders the remote media. Instead of playing the media on the same + browsing context renders the remote media. Instead of playing the media on the same device, however, it can use whatever means the operating system provides for using - the external remote playback device. In such a case, both the controller and + the external remote playback device. In such a case, both the browsing context and the media player run on the same UA and the operating system is used to route the player output to the remote playback device. This is commonly referred to as the media mirroring case. This specification imposes no requirements on the @@ -162,14 +162,14 @@

If the remote playback device is able to play the media and - communicate with the controller but is unable to fetch the - media, the controller needs to fetch the media data and pass + communicate with the browsing context but is unable to fetch the + media, the browsing context needs to fetch the media data and pass it on to the remote playback device for rendering. This is commonly referred to as media remoting case.

If the remote playback device is able to fetch and play the media and - communicate with the controller, the controller does not + communicate with the browsing context, the browsing context does not need to fetch or render the remoted media. In this case, the UA acts as a proxy that requests the remote playback device to play the media itself by passing the necessary data like the media source. This is commonly referred to as the media flinging case. @@ -197,9 +197,10 @@

Dependencies

  • HTMLMediaElement, media element, - - selecting media resource and - media resource + selecting media resource, + current source and + media resource
  • browsing context and @@ -238,6 +239,12 @@

    Dependencies

  • InvalidAccessError
  • +
  • + InvalidStateError +
  • +
  • + NotAllowedError +
  • NotFoundError
  • @@ -267,30 +274,23 @@

    <!-- player.html --> <!-- The video element with custom controls that supports remote playback. --> <video id="videoElement" src="https://example.org/media.ext" /> -<button id="remotePlaybackBtn" style="display: none;">Play remotely</button> +<button id="deviceBtn" style="display: none;">Pick device</button> <script> - // The "Play remotely" button is visible if at least one remote playback device is available. - // It is also hidden when the remote playback is happening. - var remotePlaybackBtn = document.getElementById("remotePlaybackBtn"); + // The "Pick device" button is visible if at least one remote playback device is available. + var deviceBtn = document.getElementById("deviceBtn"); var videoElem = document.getElementById("videoElement"); - // Show or hide the remote playback button depending on device availability. - function handleAvailabilityChange(available) { - remotePlaybackBtn.style.display = available ? "inline" : "none"; - }; - // Promise is fulfilled as soon as the remote playback device availability is known. - videoElem.remote.getAvailability().then(function(availability) { - // availability.value may be kept up-to-date by the controlling UA as long - // as the availability object is alive. It is advised for web developers - // to discard the object as soon as it's not needed. - handleAvailabilityChange(availability.value); - availability.onchange = function() { handleAvailabilityChange(this.value); }; - }).catch(function() { + function availabilityCallback(available) { + // Show or hide the device picker button depending on device availability. + deviceBtn.style.display = available ? "inline" : "none"; + } + + videoElem.watchAvailability(availabilityCallback).catch(function() { // Availability monitoring is not supported by the platform, so discovery of // remote playback devices will happen only after remote.connect() is called. // Pretend the devices are available for simplicity; or, one could implement // a third state for the button. - handleAvailabilityChange(true); + deviceBtn.style.display = "inline"; }); </script> @@ -302,11 +302,11 @@

     <!-- player.html -->
     <script>
    -  remotePlaybackBtn.onclick = function() {
    -    // Start remote playback.
    -    videoElem.remote.connect()
    +  devicesBtn.onclick = function() {
    +    // Request the user to select a remote playback device.
    +    videoElem.remote.prompt()
           // Update the UI and monitor the connected state.
    -      .then(switchToRemoteUI);
    +      .then(updateRemotePlaybackState);
           // Otherwise, the user cancelled the selection UI or no screens were found.
       };
     <script>
    @@ -319,27 +319,33 @@ 

     <!-- player.html -->
     <script>
    -  // The remote playback may be initiated by the user agent.
    -  if (videoElem.remote.state != 'disconnected')
    +  // The remote playback may be initiated by the user agent,
    +  // so check the initial state to sync the UI with it.
    +  if (videoElem.remote.state == "disconnected")
    +    switchToLocalUI();
    +  else
         switchToRemoteUI();
    -  videoElem.remote.onstatechange = function(evt) {
    -    if (videoElem.remote.state != 'disconnected')
    -      switchToRemoteUI();
    -    else
    -      switchToLocalUI();
    -  };
    +
    +  videoElem.remote.onconnecting = switchToRemoteUI;
    +  videoElem.remote.onconnect = swithToRemoteUI;
    +  videoElem.remote.ondisconnect = switchToLocalUI;
     
       // Handles both 'connecting' and 'connected' state. Calling more than once
       // is a no-op.
       function switchToRemoteUI() {
    -    remotePlaybackBtn.style.display = 'none';
         // Indicate that the state is 'connecting' or 'connected' to the user.
    -    // For example, hide the video element with bigger overlay controls.
    +    // For example, hide the video element as only controls are needed.
    +    videoElem.style.display = "none";
    +
    +    // Stop monitoring the availability of remote playback devices.
    +    videoElem.remote.cancelWatchAvailability();
       };
     
       function switchToLocalUI() {
    -    remotePlaybackBtn.style.display = 'inline';
    -    // Hide the overlay controls and show the video element.
    +    // Show the video element.
    +    videoElem.style.display = "inline";
    +    // Start watching the device availability again.
    +    videoElem.remote.watchAvailability(availabilityCallback);
       };
     <script>
             
    @@ -350,22 +356,57 @@

    API

    Common idioms

    - A controlling browsing context (or controller for short) is a - browsing context that has initiated remote playback - by calling connect() or via user agent interface triggered action. + A local playback device is the device the browsing context is running on along with the default + video/audio outputs the device has. +

    + A local playback device might have extra outputs, like an external display or + speakers/headphones. As long as the switch of what output to use happens outside of the user agent on + the system level, the playback is considered to happen on a local playback device for the purpose of + this spec. +
    +

    +

    + A remote playback device is any other device + but the local playback device that the browsing context can use to play media on. +

    +

    + A media element state is the set of all single media element properties + observable by the page and/or the user via the user agent implementation. The new properties introduced + by this spec are not considered part of the media element state for convenience. +

    + For example, the paused attribute or the pause/resume button reflecting that state on the default + controls of the media element would be a part of media element state. +
    +

    +

    + A local playback state is the user agent implementation of media element state + for the particular media element for playback on the local playback device. +

    +

    + A remote playback state is the user agent implementation of media element state + for the particular media element for playback on the certain remote playback device. +

    +

    + For a good user experience it is important that the media element state + doesn't change unexpectedly when the state changes. + It is also important that remote playback state is in sync with the media element state so when + the media is paused on the remote playback device it looks paused to both the user and the page.

    RemotePlayback interface

               interface RemotePlayback : EventTarget {
    -            Promise<RemotePlaybackAvailability> getAvailability();
    +            Promise<long> watchAvailability(RemotePlaybackAvailabilityCallback callback);
    +            Promise<void> cancelWatchAvailability(optional long id);
     
                 readonly attribute RemotePlaybackState state;
     
    -            attribute EventHandler onstatechange;
    +            attribute EventHandler onconnecting;
    +            attribute EventHandler onconnect;
    +            attribute EventHandler ondisconnect;
     
    -            Promise<boolean> connect();
    +            Promise<void> prompt();
               };
     
               enum RemotePlaybackState {
    @@ -373,28 +414,323 @@ 

    RemotePlayback interface

    "connected", "disconnected" }; + + callback RemotePlaybackAvailabilityCallback = void(boolean available);

    - Initiate remote playback + Observing remote playback device availability +

    +

    + A RemotePlaybackAvailabilityCallback is the way for the page to obtain the + remote playback device availability for the correspodning media element. If the user + agent can monitor the list of available remote playback devices in the background (without + a pending request to prompt()), the + RemotePlaybackAvailabilityCallback behavior defined below MUST be implemented by + the user agent. Otherwise, the promise returned by watchAvailability() + MUST be rejected with NotSupportedError. +

    +
    +
    + The set of availability callbacks +
    +

    + The user agent MUST keep track of the set of + availability callbacks registered with each media element + through the watchAvailability() method. The + set of availability callbacks for each RemotePlayback object is represented as a set of tuples + (callbackId, callback), initially empty, where: +

      +
    1. + callbackId is an id unique to the RemotePlayback object; +
    2. +
    3. + callback is a RemotePlaybackAvailabilityCallback object; +
    4. +
    +

    +

    + Since there's one and only one RemotePlayback object per each media element, set of + availability callbacks of a media element is the same set as the set of availability + callbacks of the RemotePlayback object referred to by the element's remote property. +

    +

    + The combined set of all sets of availability callbacks of + all RemotePlayback objects known to the browsing context is referred to as + global set of availability callbacks. +

    +
    +
    +
    + The list of available remote playback devices +
    +

    + The user agent MUST keep a list of available remote playback devices. + This list contains remote playback devices and is populated based on an implementation + specific discovery mechanism. It is set to the most recent result of the algorithm to monitor + the list of available remote playback devices. +

    +

    + The user agent MAY not support running the algorithm to monitor the list of available remote + playback devices continuously, for example, because of platform or power consumption restrictions. + In this case the promise returned by watchAvailability() + MUST be rejected with NotSupportedError, the global set of availability callbacks will be empty + and the algorithm to monitor the list of available remote playback devices will only run as part + of the initiate remote playback algorithm. +

    +

    + When the global set of availability callbacks is not empty, the user agent MUST monitor the + list of available remote playback devices continuously, so that pages can keep track of the last + value received via the registered callbacks to offer remote playback only when there are available devices. +

    +

    + User agents SHOULD NOT monitor the list of available remote playback devices when possible, to satisfy the + + power saving non-functional requirement. For example, the user agent MAY not run the + monitoring algorithm when the global set of availability callbacks is empty or each page that has + media elements with non-empty set of availability callbacks is not in + the foreground. +

    +

    + Some remote playback devices may only be able to play a subset of + media resources because of functional, security or hardware limitations. + Examples are set-top boxes, smart TVs or networked speakers capable of rendering only certain formats of video + and/or audio. We say that such a device is a compatible remote playback device for a + media resource if the user agent can reasonably guarantee that + the remote playback of the media specified by the resource will succeed on that device. +

    +

    + The media resources of a media element, that were considered by the user agent + to find a compatible remote playback device, are called the availability sources set. +

    +

    + The media resource of a media element, that is used to initiate remote playback + on the selected remote playback device is called remote playback source. Remote + playback source MUST belong to availability sources set. +

    +

    + The mechanism of picking the availability sources set and the remote playback source + is implementation-specific. For example, the user agent MUST either use the + currentSrc of the media element for both availability monitoring + and remote playback or use all the media resources associated with the media element as the + availability sources set and pick one of the resources as the remote playback source + after user selects the remote playback device. +

    +

    + Remote playback is said to be unavailable for the media element if the + list of available remote playback devices is empty or none of them is compatible + with any source from availability sources set for the media element. The remote playback is + said to be available otherwise. A boolean set to false if the remote + playback is unavailable for the media element or true if it is available + is called availability for the media element. +

    +
    +
    +
    + Getting the remote playback devices availability information +
    +

    + When the watchAvailability() method is + called, the user agent MUST run the following steps: +

    +
    +
    + Input +
    +
    + callback, the callback that will get fired with availability information. +
    +
    + Output +
    +
    + promise, a promise. +
    +
    +
      +
    1. + Let promise be a new promise. +
    2. +
    3. + Return promise, and run the following steps below: +
    4. +
    5. + If the disableRemotePlayback attribute is present + for the media element, reject the promise with InvalidStateError + and abort all the remaining steps. +
    6. +
    7. + If the user agent is unable to monitor the list of available + remote playback devices for the entire lifetime of the browsing context + (for instance, because the user has disabled this feature), then run the following + steps in parallel: +
        +
      1. + Fulfill promise. +
      2. +
      3. + Queue a task to invoke the callback with false as its + argument. +
      4. +
      5. Abort all remaining steps. +
      6. +
      +
    8. +
    9. If the user agent is unable to continuously monitor the list + of available remote playback devices but can do it for a short period of time + when initiating remote playback, then: +
        +
      1. + Reject promise with a NotSupportedError + exception. +
      2. +
      3. Abort all remaining steps. +
      4. +
      +
    10. +
    11. + Let callbackId be a number unique to the media element that will identify the + callback. +
    12. +
    13. + Create a tuple (callbackId, callback) and add it to the + set of availability callbacks for this media element. +
    14. +
    15. + Fulfill promise with the callbackId and run the following steps in parallel: +
        +
      1. + Queue a task to invoke the callback with the current availability for the + media element. +
      2. +
      3. + Run the algorithm to monitor the list of available remote playback devices. +
      4. +
      +
    16. +
    +
    +
    +
    + Monitoring the list of available remote playback devices +
    +

    + If the set of availability callbacks is non-empty, or there is + a pending request to initiate remote playback, + the user agent MUST monitor the list of available remote playback devices by + running the following steps: +

    +
      +
    1. + Retrieve available remote playback devices (using an implementation specific mechanism) + and let newDevices be this list. +
    2. +
    3. + For each media element known to the browsing context: +
        +
      1. + If the disableRemotePlayback attribute is present + for mediaElement, abort all the remaining steps for this tuple and continue to the next + one. +
      2. +
      3. + Set newAvailabilityValue to the value of availability for the media element + calculated using the newDevices list instead of the list of available remote playback + devices. +
      4. +
      5. + If the current availability is not equal to newAvailabilityValue, then + for each (callbackId, callback) of the element's + set of availability callbacks: +
          +
        1. + Queue a task to invoke callback with newAvailabilityValue as its argument. +
        2. +
        +
      6. +
      +
    4. +
    5. + Set the list of available remote playback devices to the value of newDevices. +
    6. +
    +
    +
    +
    + Stop observing remote playback devices availability +
    +

    + When a cancelWatchAvailability() method is called, + the user agent MUST run the following steps: +

    +
    +
    + Input +
    +
    + id, the callback identifier. +
    +
    + Output +
    +
    + promise, a promise. +
    +
    +
      +
    1. + Let promise be a new promise. +
    2. +
    3. + Return promise, and run the following steps below: +
    4. +
    5. + If the disableRemotePlayback attribute is present + for the media element, reject promise with InvalidStateError + and abort all the remaining steps. +
    6. +
    7. + If the parameter id is undefined, clear the set of availability callbacks. +
    8. +
    9. + Otherwise, if id matches the callbackId for any entry in the + set of availability callbacks, remove the entry from the set. +
    10. +
    11. + Otherwise, reject promise with NotFoundError and abort all the remaining steps. +
    12. +
    13. + If the set of availability callbacks is now empty and there is no pending request to + initiate remote playback, cancel any pending task + to monitor the list of available remote playback devices for power saving purposes. +
    14. +
    15. + Fulfill promise. +
    16. +
    +
    + The mechanism used to monitor remote playback devices availability and determine the + compatibility of a remote playback device with the selected availability sources set + is left to the user agent. +
    +
    +
    +
    +

    + Prompt user for changing remote playback statee

    - When the connect() - method is called, the user agent MUST run the following - steps to initiate remote playback: + When the prompt() + method is called, the user agent MUST run the following steps:

    Input
    - remote, the RemotePlayback object - associated with the media element. -
    -
    - mediaSourceList, the list of all media sources attributed to media element. - It includes sources set via srcObject, src attributes and <source> - elements at the moment connect() was called. + None, but the algorithm references the media element, its remote + property and its availability sources set.
    Output @@ -405,118 +741,118 @@

    1. - If the state of remote is anything other than - disconnected, return a - promise rejected with an OperationError exception and - abort all remaining steps. + Let promise be a new promise. +
    2. +
    3. + Return promise and continue running these steps + in parallel. +
    4. +
    5. + If the disableRemotePlayback attribute is present + for the media element, reject the promise with InvalidStateError + and abort all the remaining steps.
    6. If there is already an unsettled promise from a previous - call to connect for the same + call to prompt for the same media element or even for the same browsing context, - the user agent MAY return a promise rejected with an OperationError + the user agent MAY reject promise with an OperationError exception and abort all remaining steps.
      - The rationale here is that the user agent might use the UI - for the remote playback device selection that's modal - to either the media element or the browsing context. - In such a case, the second call to connect() - would not be able to show any UI for device selection. + The rationale here is that the user agent might use the UI that's modal to either the + media element or the browsing context. + In such a case, the second call to prompt() + would not be able to show any UI.
    7. - OPTIONALLY, if the user agent knows a priori that playing any source from mediaSourceList - remotely is not supported by the user agent or any of remote playback device types supported - by the user agent, return a promise rejected with a NotSupportedError and abort all remaining steps. + OPTIONALLY, if the user agent knows a priori that showing the UI for this particular media + element is not feasible, reject promise with a NotSupportedError and abort all + remaining steps.
      An example of such scenario could be when the user agent only supports media flinging case while the media element's source is not a URL that could be passed over to any remote playback device.
    8. - If the algorithm isn't allowed to show a popup, return a - promise rejected with an InvalidAccessError exception - and abort these steps. -
    9. -
    10. - Let promise be a new promise. -
    11. -
    12. - Return promise and continue running these steps - in parallel. + If the algorithm isn't allowed to show a popup, reject promise + with an InvalidAccessError exception and abort these steps.
    13. - If the user agent is not + If the user agent needs to show the list of available remote playback devices and + is not monitoring the list of available remote playback devices, run the steps to monitor the list of available remote playback devices in parallel.
    14. -
    15. - Request user permission for the use of a remote playback device - and selection of one remote playback device. -
    16. If the list of available remote playback devices is empty and will remain so before the request for user permission is completed, reject promise with a NotFoundError exception and abort all remaining steps.
    17. - If no member in the list of available remote playback devices is a - compatible remote playback device for any source from - the mediaSourceList, reject promise with + If the state is disconnected and + availability for the media element is false, reject promise with a NotSupportedError exception and abort all remaining steps.
    18. - If the user denied permission to use a device, fulfill - promise with false, and abort - all remaining steps. -
    19. -
    20. - Otherwise, the user granted permission to use a device; - let device be that device. -
    21. -
    22. - Set the state of the remote object to - connecting. -
    23. -
    24. - Fulfill promise with true. -
    25. -
    26. - Queue a task to fire a simple event with - the name statechange, - that uses the change event interface at remote. - The event must not bubble, must not be cancelable, and has no - default action. -
    27. -
    28. - If any of the following steps fails, abort all remaining steps - and stop remote playback for remote. + If the user picked a remote playback device device to + initiate remote playback with, the user agent MUST run the following steps: +
        +
      1. + Set the state of the remote object to + connecting. +
      2. +
      3. + Fulfill promise. +
      4. +
      5. + Queue a task to fire a simple event with the name connecting at the + remote property of the media element. + The event must not bubble, must not be cancelable, and has no default action. +
      6. +
      7. + Establish a connection with the remote playback device device for the media element. +
      8. +
      +

      + By picking a remote playback device the user grants permission to use the device. +

    29. - Establish a connection with the remote playback device device for remote. + Otherwise, if the user chose to disconnect from the remote playback device device, + the user agent MUST run the following steps: +
        +
      1. + Fulfill promise. +
      2. +
      3. + Run the disconnect from remote playback device algorithm for the device. +
      4. +
    30. - Using an implementation specific mechanism start remote playback of - the remote playback source from mediaSourceList on device. + Otherwise, the user is considered to deny permission to use the device, so reject + promise with NotAllowedError exception and hide the UI shown by the user agent
    - The details of implementing the permission request and device - selection are left to the user agent; for example it may show the - user a dialog and allow the user to select an available device - (granting permission), or cancel the selection (denying - permission). + The details of implementing the UI and device selection are left to the user agent; + for example it MAY show the user a dialog and allow the user to select an available device + (granting permission), or cancel the selection (denying permission).
    - The algorithm to select the remote playback source for a selected device + The algorithm to select the remote playback source for a selected device depends on the user agent and supported remote playback device types. For example, in case of media mirroring the user agent can simply follow the HTMLMediaElement's resource selection algorithm. However, if media remoting or media flinging is used, - the best media source depends on the selected remote playback device fetch and playback capabilities. + the best media source can depend on the selected remote playback device fetch and + playback capabilities.
    -

    The state attribute

    +

    + The state attribute +

    The state attribute represents the RemotePlayback connection's current state. It can take one of @@ -528,20 +864,19 @@

    The state attribute

    connecting means that the user agent is attempting to initiate remote playback with the selected remote playback device. This is the initial state when the promise returned by - connect() is fulfilled with true. + prompt() is fulfilled with true. The local playback of the media element continues in this - state and media commands still take effect on the local playback. + state and media commands still take effect on the local playback state.
  • connected means that the transition from local to remote playback has finished - and all media commands now take effect on the playback state of the remote playback device. + and all media commands now take effect on the remote playback state.
  • disconnected means that the remote playback has not been initiated, has failed to initiate or has been - stopped. All media commands will take effect on the local - playback in this state. The remote playback can be - initiated through a call to connect(). + stopped. All media commands will take effect on the local playback state. The remote playback + can be initiated through a call to prompt().
  • @@ -559,8 +894,6 @@

    remote, the RemotePlayback object that is to be connected. - The remote playback state of remote must be - connecting.
    device, the remote playback device to connect to. @@ -568,17 +901,26 @@

    1. - Request connection of remote to device. + If the state of remote is not equal to + connecting, abort all the remaining steps. +
    2. +
    3. + Request connection of remote to device. The implementation of this step is specific + to the user agent.
    4. If connection completes successfully, queue a task to run the following steps:
      1. - Set the remote playback state of remote to + Set the state of remote to connected.
      2. - Fire a simple event named statechange at remote. + Fire a simple event named connect at remote. +
      3. +
      4. + Synchronize the current media element state with the remote playback state. + Implementation is specific to user agent.
    5. @@ -590,7 +932,7 @@

      disconnected.
    6. - Fire a simple event named statechange at remote. + Fire a simple event named disconnect at remote.
    @@ -599,12 +941,8 @@

    The mechanism that is used to connect the user agent with the remote playback device and play the remote playback source is an implementation choice of the user agent. The connection will likely have to provide a two-way messaging abstraction capable of carrying media commands to - the remote playback device and receiving media playback state in order to keep the remoted - media element state in sync, unless media mirroring is used. - -
    - If the connection step does not complete successfully, the user - agent may choose to re-execute the connection algorithm at a later time. + the remote playback device and receiving media playback state in order to keep the media element state and + remote playback state in sync (unless media mirroring is used).

    @@ -621,23 +959,21 @@

    Media commands and media playback state

    MUST send all the media commands issued on the HTMLMediaElement object with which the RemotePlayback object is associated to the remote playback device in order - to change the state of the remotely played media. + to change the remote playback state vs the local playback state.

    - Similarly, the user agent MUST reflect all status updates - received from the remote playback device on the - HTMLMediaElement's state. + Similarly, the user agent MUST reflect all updates of the remote playback state + received from the remote playback device on the media element state.

    - If sending any command fails, the user agent MUST stop - remote playback, effectively disconnecting from the remote - playback device. + If sending any command fails, the user agent MAY disconnect from + remote playback device.

    -

    Stopping remote playback

    +

    Disconnecting from remote playback device

    - When the user agent is to stop remote playback, + When the user agent is to disconnect from remote playback device, it MUST do the following:

    @@ -647,31 +983,40 @@

    Stopping remote playback

    remote, the RemotePlayback object representing the playback to be stopped.
    +
    + device, the remote playback device to disconnect from. +
    1. - If the state of remote is not - connected, abort all remaining steps. + If the state of remote is + disconnected, abort all remaining steps.
    2. Queue a task to run the following steps:
      1. - Request stopping the playback of the media from the remote playback device. + Request disconnection of remote from the device. Implementation + is user agent specific.
      2. Change the remote's state to disconnected.
      3. - Fire an event with the name statechange at remote. + Fire an event with the name disconnect at remote. +
      4. +
      5. + Synchronize the current media element state with the local playback state. + Implementation is specific to user agent.
    - The remote playback device might not stop remote playback of the media when requested by the user agent + The remote playback device might not actually stop playback of the media when requested by the user agent since it's implementation specific and depends on the device in question. In such case stopping remote playback - merely means the user agent disconnecting from the remote playback device. + merely means the user agent literally only disconnecting from the remote playback device and the + media element switching to the disconnected state.
    @@ -697,265 +1042,32 @@

    - onstatechange + onconnecting + + + connecting + + + + + onconnect + + + connect + + + + + ondisconnect - statechange + disconnect

    -
    -

    RemotePlaybackAvailability interface

    -
    -          interface RemotePlaybackAvailability : EventTarget {
    -            readonly attribute boolean value;
    -            attribute EventHandler onchange;
    -          };
    -        
    -

    - A RemotePlaybackAvailability object is associated with available remote playback devices - and represents the remote playback device availability for the media element. If the user - agent can monitor the list of available remote playback devices in the background (without - a pending request to connect()), the - RemotePlaybackAvailability object MUST be implemented by the user agent. Otherwise, the - promise returned by getAvailability() MUST be rejected with NotSupportedError. -

    -

    - The value attribute MUST return the last value it was set to. - The value is updated by the monitor the list of available remote playback devices algorithm. -

    -

    - The onchange attribute is an event handler which - corresponding event handler event type is change. -

    -
    -

    - The set of availability objects -

    -

    - The user agent MUST keep track of the set of - availability objects requested through the getAvailability() method. The - set of availability objects is represented as a set of - tuples (availability, availabilitySource), - initially empty, where: -

    -
      -
    1. - availability is a live RemotePlaybackAvailability object; -
    2. -
    3. - availabilitySource is the remote playback source of the media element - when getAvailability() is called to - create availability. -
    4. -
    -
    -
    -

    - The list of available remote playback devices -

    -

    - The user agent MUST keep a list of available - remote playback devices. This current list of remote playback devices - may be used for initiating remote playback, and is - populated based on an implementation specific discovery mechanism. - It is set to the most recent result of the algorithm to monitor - the list of available remote playback devices. -

    -

    - While there are live RemotePlaybackAvailability objects, the - user agent MAY monitor the list of available remote playback devices continuously, - so that pages can use the value property of a - RemotePlaybackAvailability object to offer remote playback only - when there are available devices. However, the user agent - may not support continuous availability monitoring; for example, - because of platform or power consumption restrictions. In this case - the promise returned by getAvailability() - MUST be rejected with NotSupportedError and the algorithm to monitor - the list of available remote playback devices will only run as part of the - initiate remote playback algorithm. -

    -

    - When there are no live RemotePlaybackAvailability objects - (that is, the set of availability objects is empty), user - agents SHOULD NOT monitor the list of available remote playback devices to satisfy the - - power saving non-functional requirement. To further save power, - the user agent MAY also keep track of whether the page - holding a RemotePlaybackAvailability object is in the - foreground. Using this information, implementation specific - discovery of remote playback devices can be resumed or - suspended. -

    -

    - Some remote playback devices may only be able to display a - subset of Web content because of functional, security or hardware - limitations. Examples are set-top boxes, smart TVs or networked - speakers capable of rendering only certain formats of video and/or audio. - We say that such a device is a compatible remote playback device for a - media resource if the user agent can reasonably guarantee that - the remote playback of the media specified by the resource will succeed on that device. -

    -
    -
    -

    - Getting the remote playback devices availability information -

    -

    - When the getAvailability() method is - called, the user agent MUST run the following steps: -

    -
    -
    - Input -
    -
    - mediaSourceList, a list of sources attributed to the media element. -
    -
    - Output -
    -
    - promise, a promise. -
    -
    -
      -
    1. - Let promise be a new promise. -
    2. -
    3. - Return promise, and run the following steps below: -
    4. -
    5. If the user agent is unable to monitor the list of available - remote playback devices for the entire lifetime of the browsing context - (for instance, because the user has disabled this feature), then: -
        -
      1. - Fulfill promise with a new - RemotePlaybackAvailability object with its - value property set to false. -
      2. -
      3. Abort all remaining steps. -
      4. -
      -
    6. -
    7. If the user agent is unable to continuously monitor the list - of available remote playback devices but can do it for a short period of time - when initiating remote playback, then: -
        -
      1. - Reject promise with a NotSupportedError - exception. -
      2. -
      3. Abort all remaining steps. -
      4. -
      -
    8. -
    9. - If there exists a tuple (availability, - availabilitySource) in the set of availability - objects where availabilitySource is present in mediaSourceList, - then: -
        -
      1. - Fulfill promise with availability. -
      2. -
      3. - Abort all remaining steps. -
      4. -
      -
    10. -
    11. - Let availability be a new RemotePlaybackAvailability - object with its value property set to - false if the list of available remote playback devices - is empty or none of them is compatible with any source from mediaSourceList, - true otherwise. -
    12. -
    13. - For each availabilitySource in mediaSourceList, create a tuple - (availability, availabilitySource) and add it to the - set of availability objects. -
    14. -
    15. - Run the algorithm to monitor the list of available remote playback devices. -
    16. -
    17. - Fulfill promise with availability. -
    18. -
    -
    -
    -

    - Monitoring the list of available remote playback devices -

    -

    - If the set of availability objects is non-empty, or there is - a pending request to initiate remote playback, - the user agent MUST monitor the list of available remote playback devices by - running the following steps: -

    -
      -
    1. - Retrieve available remote playback devices (using an implementation specific mechanism) - and let newDevices be this list. -
    2. -
    3. - For each member (availability, availabilitySource) - of the set of availability objects: -
        -
      1. - Set previousAvailabilityValue to the value of availability's value property. -
      2. -
      3. - Let newAvailabilityValue be true if newDevices is not empty - and at least one device in newDevices is a compatible remote playback device - for availabilitySource. Otherwise, set newAvailabilityValue to false. -
      4. -
      5. - If previousAvailabilityValue is not equal to newAvailabilityValue, then - queue a task to run the following steps: -
          -
        1. - Set availability's value property to newAvailabilityValue. -
        2. -
        3. - Fire a simple event named change at availability. -
        4. -
        -
      6. -
      -
    4. -
    5. - Set the list of available remote playback devices to the value of newDevices. -
    6. -
    -

    - When a RemotePlaybackAvailability object is no longer alive - (in other words, is eligible for garbage collection), the user agent - SHOULD run the following steps: -

    -
      -
    1. - Find and remove any entry (availability, availabilitySource) in the - set of availability objects for the newly deceased availability. -
    2. -
    3. - If the set of availability objects is now empty and there is no pending request to - initiate remote playback, cancel any pending task - to monitor the list of available remote playback devices for power saving purposes. -
    4. -
    -
    - The mechanism used to monitor remote playback devices availability and determine the - compatibility of a remote playback device with a given media element source is left to the user agent. -
    -
    -

    Extension to the HTMLMediaElement

    @@ -982,6 +1094,12 @@

    Disabling remote playback

    media element, the user agent MUST NOT play the media remotely or present any UI to do so.

    +

    + When the disableRemotePlayback attribute is added to the media element and + its state is not disconnected, the user agent MUST run the + disconnect from remote playback device algorithm for the remote playback device the media + element is connected or connecting to. +