Re: Should MIDIInput use a callback instead of events?

On Tue, Feb 19, 2013 at 7:44 PM, Marcos Caceres <w3c@marcosc.com> wrote:

>
>
> On 19/02/2013, at 10:16 AM, Dominic Cooney <dominicc@chromium.org> wrote:
>
> Hi Marcos, Audiophiles,
>
> On Tue, Feb 19, 2013 at 4:38 PM, Marcos Caceres <w3c@marcosc.com> wrote:
>
>> Hi Dominic!
>>
>> On Tuesday, 19 February 2013 at 06:45, Dominic Cooney wrote:
>>
>> > Greetings Web Audiophiles,
>> >
>> > In reading the Web MIDI spec I note that MIDIInput is declared this way
>> [1]:
>> >
>> > MIDIInput implements EventTarget;
>> >
>> > interface MIDIInput : MIDIPort {
>> > attribute EventHandler onmessage;
>> > };
>> >
>> >
>> > interface MIDIEvent : Event {
>> > readonly attribute double receivedTime;
>> > readonly attribute Uint8Array data;
>> > };
>> >
>> >
>> > There are a number of problems with these definitions.
>> >
>> > 1. MIDIEvent does not specify a constructor, so it is not possible to
>> programmatically create and dispatch a MIDIEvent. That complicates
>> scenarios such as writing unit tests for MIDI input handlers.
>> Yep, we have a bug for this. The Editor has been requesting additional
>> use cases. See:
>> https://github.com/WebAudio/web-midi-api/issues/1
>>
>> Be great if you could also comment there :)
>>
>
> Sure. I will do that. It looks like the testing case is already discussed
> to some extent.
>
>
>> >
>> > 2. As noted in the spec, DOM4 Event objects have a lower-resolution
>> timeStamp. I think it is confusing to have two kinds of timestamps.
>>
>> Yep, I raised the same issue - see discussion at:
>> https://github.com/WebAudio/web-midi-api/issues/4
>>
>> But we didn't find a way around that.
>>
>
> Not using DOM4 Events is one way around it.
>
>
>> > 3. The Event interface [2] and EventTarget interface [3] bring with
>> them a number of concepts that aren’t useful for this application: related
>> targets (ie the currentTarget property), event phases, event propagation
>> (perhaps), bubbling, cancelation, default handling and capturing.
>>
>> Right - despite not participating in a DOM tree, the eventing model still
>> seems appropriate.
>>
>
> I think we misunderstand each other; I think the DOM4 Event model seems
> inappropriate because many concepts are meaningless to Web MIDI. However
> this is admittedly true of other uses of DOM4 Events, such as WebSockets.
> How significant is wiring up multiple listeners to a single MIDIInput?
>
>
> This is still an issue/under-described use case in the spec. I've also
> raised this previously (i.e., are these objects singletons?)
>
>
>
>
>> >
>> > 4. The style of MIDIInput implements EventTarget is not used by recent
>> specs; these universally use X : EventTarget for some interface X. This old
>> style of EventTarget implementation complicates implementation.
>>
>> This is my fault and I've been meaning to file a bug to address this, so
>> thanks for bringing it up. The design of the API did not lend itself to
>> support both EventTarget and MIDIPort because MIDIPort does not inherit
>> from EventTarget. Generally, EventTarget sits at the bottom of the
>> inheritance chain, but that would mean MIDIPort would become an
>> EventTarget. We didn't want to make MIDIOutput unnecessarily become and
>> EventTarget; hence, "implements" EventTarget on MIDIInput seemed the right
>> way to go.
>>
>>  (btw ...it actually does not complicate the implementation - but you are
>> correct in that it's a bit weird - but this is DOM3's fault because it
>> kinda says to do this and it's what browsers have generally done). AFAIK,
>> only FireFox seems to expose the EventTarget interface as per WebIDL (this
>> is something recent) - other browsers don't yet expose EventTarget - like
>> in Chrome, try window.EventTarget … or try searching the prototype chain of
>> any object that inherits EventTarget and you will see it is not there
>> (shock!, I know :)).
>>
>
> I'm familiar with the implementation of EventTarget in Chrome :) Having
> both "implements EventTarget" and ": EventTarget" complicates the
> implementation of wrapping and unwrapping EventTargets. If all EventTargets
> were at the root of the prototype chain, machinery for the JavaScript
> wrappers of EventTargets could be simplified.
>
>
> I agree. As I said, the issue is the current inheritance model. Maybe
> MIDIInput : EventTarget, but implements MIDIPort?
>

That would address my concern.

>
>
>> I don't know how we "fix" this except to make MIDIPort inherit
>> EventTarget. See also for a bit more discussion:
>> http://lists.w3.org/Archives/Public/public-audio/2012OctDec/0658.html
>
>
> Thanks for context; I missed this when searching the list. I see this
> specific question has already been given some consideration.
>
>
>> > One possible benefit of using DOM Events is that it permits wiring up
>> multiple listeners. Is that an intended use case of onmessage?
>> No, that's what .addEventListener() is for. onmessage is just the
>> catchall.
>
>
> I think I wrote that line too quickly. I meant "is that the intended use
> case of the events that are handled by the onmessage handler", etc.
>
>
> I guess the answer is yes.
>
>
>
>> Having a single onmessage is dangerous in that any object can easily
>> override it (so naive library B can break library A - or both library A and
>> B cannot simultaneously rely on onmessage - except if each instance of
>> MIDIInput is unique, but then it just gets complicated). Using
>> addEventListener protects from such conflicts and keeps things relatively
>> simple and safe.
>
>
> Is it likely for two libraries to compete for a given MIDIInput object?
> These are not global objects like window or document.
>
>
> Could be, if they are singletons. Still not clear if they are or not.
> Certainly good candidates to be and I think I implemented them that way in
> my own reference implementation.
>

Thanks for explaining these issues--given singletons and wiring up multiple
handlers as a common case I can see why DOM Events make sense.

>
> > I note that Web Audio’s ScriptProcessorNode has a roughly analogous
>> case: processing buffers of binary audio data in onaudioprocess.
>> ScriptProcessorNode has moved away from using DOM Events.. Given the
>> problems using DOM Events for MIDIInput noted above, I think it would be
>> better for MIDIInput to have a simple callback, perhaps something like:
>>
>> I don't think the above are "problems" - or at least I'm not
>> seeing/understanding explicit problems. The only thing you mentioned was
>> that it "complicates implementation", but it would be great if you could
>> qualify that with some explicit details (today's browsers don't have a
>> problem with implementing EventTarget - all except FireFox do it, AFAIK).
>> WebIDL implements, as I understand it, just says to copy the
>> methods/attributes from one interface onto another without inheriting from
>> it - behaviour stays the same.
>
>
> Here is some elaboration of why "implements EventTarget" is problematic:
>
> "implements EventTarget" is less friendly to web developers, because they
> now must do checks like 'addEventListener' in x && 'dispatchEvent' in x &&
> ... to test whether x is an EventTarget (actually an EventTarget-like
> object.) In comparison, ": EventTarget" means web developers can write x
> instanceof EventTarget which is easy to understand.
>
>
> Sure. But in reality, there is no window.EventTarget except in one
> browser. This even though we've had specifications using EventTarget for
> about 10 years. Adding EventTarget to the proto chain has not yet happened.
> To deal with legacy browsers, you still need to do the above duck typing.
>
>
> Further, if a web developer wants to hook addEventListener (perhaps to
> answer the perennial question of "what EventListeners are registered on
> this object?" in a debugging scenario) in the ": EventTarget" case they can
> replace one property--EventTarget.prototype.addEventListener--and have a
> hook at that operates on all event targets. In the "implements EventTarget"
> case, they have to monkeypatch all interfaces which mix it in.
>
>
> Sure. But that's pretty rare. Also, browsers are starting to provide
> better tools for observing events.
>
>
> Regarding the specifics of what is exposed in Chrome, Firefox, etc.--that
> is where the browser are today. I am working on making Chrome be compatible
> with the relevant specs. This amounts to catching up to Firefox in some
> respects.
>
>
> That's awesome to hear!
>
>
> Having a mixture of "implements EventTarget" and ": EventTarget"
> complicates the implementation of EventTargets in Chrome because the
> machinery which converts to and from EventTargets must treat these cases
> differently. I'm happy to point you to specific FIXMEs and infelicities if
> you want to dig deeper.
>
>
> I know you would prefer that we did away with events altogether, but would
> the solution I proposed above (implements MIDIPort instead of EventTarget)
> work for you?
>

Yes, MIDIInput : EventTarget; MIDIInput implements MIDIPort would work for
me.

>
>
>> > interface MIDIInput {
>> > attribute MIDIInputHandler? onmessage;
>> > }
>> >
>> > callback MIDIInputHandler = void (double receivedTime, Uint8Array data);
>> I personally don't like the above, because (as a JS developer) it would
>> mean having to build my own event dispatcher to then route everything from
>> onmessage to other listeners - I also mentioned the potential for someone
>> else's library to accidentally trash/replace my callback. It is also
>> confusing in that if one finds an "onwhatever" IDL handler attribute on an
>> interface, then it is an expectation that one would also be able to
>> .addEventListener("whatever") on the same interface. Also, if this API
>> grows in the future, it would mean stacking more arguments into the
>> MIDIInputHandler callback (though you are correct in that MIDIEvent will
>> contain a lot of useless garbage inherited from DOM's Event object).
>>
>
> Yes, if this became a callback, it should not be called on*.
>
> Regards,
>
> Dominic
>
>

Received on Wednesday, 20 February 2013 02:46:38 UTC