[whatwg] Thoughts on the media stream bootstrap mechanism

Lachlan Hunt lachlan.hunt at lachy.id.au
Wed Mar 16 09:58:02 PDT 2011


On 2011-03-15 16:24, Rich Tibbett wrote:
> We want to replace the success callback with a 'connect' event and the
> error callback with an 'error' event. We would also like to introduce
> a 'disconnect' event as mentioned in point 3) above.
>
> The IDL is as follows:
>
> [NoInterfaceObject]
> interface Device {
>    const unsigned short WAITING = 0;
>    const unsigned short CONNECTED = 1;
>    const unsigned short DISCONNECTED = 2;
>    const unsigned short ERROR = 3;
>    readonly attribute unsigned short readyState;
>
>    // event handler attributes
>             attribute Function onconnect;
>             attribute Function ondisconnect;
>             attribute Function onerror;
>
>    readonly attribute any data;
>
>    void disconnect();
> }
>
> // Specific Device Classes with independent constructors
>
> [Constructor(in DOMString options)]
> interface UserMedia : Device {}

For me, this event model approach seems more natural and fits with 
pre-existing design patterns used for other APIs, better than the 
callback approach does.  But even so, I thought I'd do a side by side 
comparison of the code to accomplish a simple tasks.

In both cases, this variable is declared:

var v = document.querySelector("video");

---

/* Callback model: */

var s; // For keeping a reference to the stream available for later use.

navigator.getUserMedia("audio,video", success, error);

function success(stream) {
   s = stream; // Store it for later use
   v.src = s;

   s.onplay  = play; // Assume these functions are defined somewhere
   s.onpause = pause;
   s.onended = ended;
}

function error(e) {
   // Permission denied...
}

---

/* Event model: */

var m = new UserMedia("audio,video");

m.onconnect = function(evt) {
   v.src = this.data;

   this.onplay  = play; // Assume these functions are defined somewhere
   this.onpause = pause;
   this.onended = ended;
}

m.onerror = function(evt) {
   // Permission denied
}

---

Based on this simple comparison, it's clear that the neither model 
requires significantly more verbose code than the other model, no there 
doesn't seem to be any real disadvantage from an authoring perspective.

The event model has the advantage of being able to scale up to handle 
more events in the future, such as handling disconnections or the user 
switching cameras or microphones.  (e.g. The user want switches from 
their computer's built in microphone to a USB headset.)  For the 
callback model to handle that, it would require adding more callback 
functions.

One problem with both models is that they don't easily distinguish 
between different input devices, which is a problem because both the 
proposed Device interface and the Stream/GeneratedStream interfaces can 
potentially represent multiple Devices/Streams (this is the case when 
"audio,video" is passed as the type).

This creates a problem when a user, for example, unplugs or revokes 
permission for one of the devices or streams but not the other, 
triggering either an error or disconnect event, it's not clear how the 
script can identify which specific device was disconnected.  Both 
interfaces also use a single readyState variable to represent the state 
of potentially multiple devices/streams, which seems problematic for the 
same reason.

Finally, the object passed to the error callback/event currently only 
has a PERMISSION_DENIED error code. It might be worth investigating the 
need for other codes like PERMISSION_REVOKED, DEVICE_REMOVED, etc. as 
well, to handle the case where permission was granted, but then the user 
later changed their mind or unplugged the device.  (It's possible that 
the proposed ondisconnect event in the event model could be handled as 
an error event with an appropriate code, though I'm not sure if that's 
better or worse than separate event.)

-- 
Lachlan Hunt - Opera Software
http://lachy.id.au/
http://www.opera.com/



More information about the whatwg mailing list