Closed jussi-kalliokoski closed 11 years ago
Original comment by Chris Wilson on W3C Bugzilla. Tue, 25 Dec 2012 23:20:35 GMT
1) The separation between these is because they are, in fact, two different lists (inputs and outputs), and they're fundamentally different objects; one can only read, one can only write. Merging these entirely will, I think, tend to be confusing, as output ports will have an onmessage handler, and input ports will have a send() method, even though they are orphans that don't do anything. I'm not very comfortable with that, as I think the guard rails (guide rails?) of having the methods only where appropriate is good.
On why there are three methods to get an input/output - personally, I'd ditch the MIDIPort version, but I do want to keep the index version, as (if you look at most of my demos), it's fairly common to show a dropdown to select ports, and index is an easy way to do that. No, it won't persist over sessions, but it doesn't need to. In fact, if you were persisting over sessions, I'd expect an app to pop "pick your port" dialog that is index-based, and then persist the ID.
Original comment by Jussi Kalliokoski on W3C Bugzilla. Tue, 25 Dec 2012 23:48:44 GMT
(In reply to comment #1)
1) The separation between these is because they are, in fact, two different lists (inputs and outputs), and they're fundamentally different objects; one can only read, one can only write. Merging these entirely will, I think, tend to be confusing, as output ports will have an onmessage handler, and input ports will have a send() method, even though they are orphans that don't do anything. I'm not very comfortable with that, as I think the guard rails (guide rails?) of having the methods only where appropriate is good.
On why there are three methods to get an input/output - personally, I'd ditch the MIDIPort version, but I do want to keep the index version, as (if you look at most of my demos), it's fairly common to show a dropdown to select ports, and index is an easy way to do that. No, it won't persist over sessions, but it doesn't need to. In fact, if you were persisting over sessions, I'd expect an app to pop "pick your port" dialog that is index-based, and then persist the ID.
I agree with Chris, the port types (input, output) are very different, and having the MIDIPort interface as separate from those two helps with the fact that you don't have to capture the devices when you enumerate (e.g. winmm grants only one program exclusive, and exclusive only, access per MIDI device).
As for the getInput/getOutput merging, I'm quite fine with reducing the overloads to just the ID, the use case Chris mentioned is as simple and better handled with IDs anyway, to be more resilient to live hardware changes:
inputSelect = document.createElement('select') document.body.appendChild(inputSelect)
midiaccess.enumerateInputs().forEach((input) => { var elem = document.createElement('option') elem.value = input.id elem.innerHTML = input.name inputSelect.appendChild(elem) })
inputSelect.onchange = function () { var input = midiaccess.getInput(this.value) }
But I'm not sure it's a good idea to merge the two different methods, unless we want to add a mandatory constraint that the fingerprint/ID needs to be different for input devices and output devices. It would be especially annoying if faced with a UA that doesn't have enough data to give reliable fingerprints, an application would've stored a fingerprint and assumed that the method would return an output port, but was given an input port instead, resulting in an error if it tried to send anything to it.
Original comment by Marcos Caceres on W3C Bugzilla. Wed, 26 Dec 2012 00:14:20 GMT
(In reply to comment #2)
I agree with Chris, the port types (input, output) are very different, and having the MIDIPort interface as separate from those two helps with the fact that you don't have to capture the devices when you enumerate (e.g. winmm grants only one program exclusive, and exclusive only, access per MIDI device).
Ok, my objection was purely based on having to add more objects to the global scope (i.e., all WebIDL interfaces end up on the Window object... but c'est la vie). From an authoring perspective, it makes little difference and Chris' is right in that it may avoid some confusion.
As for the getInput/getOutput merging, I'm quite fine with reducing the overloads to just the ID, the use case Chris mentioned is as simple and better handled with IDs anyway, to be more resilient to live hardware changes:
inputSelect = document.createElement('select') document.body.appendChild(inputSelect)
midiaccess.enumerateInputs().forEach((input) => { var elem = document.createElement('option') elem.value = input.id elem.innerHTML = input.name inputSelect.appendChild(elem) })
inputSelect.onchange = function () { var input = midiaccess.getInput(this.value) }
But I'm not sure it's a good idea to merge the two different methods, unless we want to add a mandatory constraint that the fingerprint/ID needs to be different for input devices and output devices.
I'm of the opinion that one should go for "the ideal" solution first, then backtrack if it fails. In this case, it would mean getting some implementation experience to see if we can get unique fingerprints.
It would be especially annoying if faced with a UA that doesn't have enough data to give reliable fingerprints, an application would've stored a fingerprint and assumed that the method would return an output port, but was given an input port instead, resulting in an error if it tried to send anything to it.
Agreed. But as I said above, at this stage in the standardisation game, it does not hurt to see if that problem can be solved somehow.
Having said that, we should add a big red note to the spec asking implementers for feedback exactly about this.
Original comment by Marcos Caceres on W3C Bugzilla. Wed, 26 Dec 2012 15:27:24 GMT
(In reply to comment #3)
(In reply to comment #2)
It would be especially annoying if faced with a UA that doesn't have enough data to give reliable fingerprints, an application would've stored a fingerprint and assumed that the method would return an output port, but was given an input port instead, resulting in an error if it tried to send anything to it.
Agreed. But as I said above, at this stage in the standardisation game, it does not hurt to see if that problem can be solved somehow.
Having said that, we should add a big red note to the spec asking implementers for feedback exactly about this.
Just wanted to record a random thought here:
getPort(DOMString id, optional MIDIPortType type);
As in: var port = midi.getPort("12e23f3", "input");
Original comment by Chris Wilson on W3C Bugzilla. Wed, 26 Dec 2012 17:00:30 GMT
(In reply to comment #4)
Just wanted to record a random thought here:
getPort(DOMString id, optional MIDIPortType type);
As in: var port = midi.getPort("12e23f3", "input");
But why would you do that? For any given id, the type is predetermined (and fixed). If you were going down this path (of collapsing Input and Output together), I would expect:
interface MIDIAccess {
sequence
Original comment by Marcos Caceres on W3C Bugzilla. Wed, 26 Dec 2012 17:10:32 GMT
(In reply to comment #5)
(In reply to comment #4)
Just wanted to record a random thought here:
getPort(DOMString id, optional MIDIPortType type);
As in: var port = midi.getPort("12e23f3", "input");
But why would you do that? For any given id, the type is predetermined (and fixed).
Jussi said that the fingerprint might not be reliable (i.e., an input and and output would have the same fingerprint): "It would be especially annoying if faced with a UA that doesn't have enough data to give reliable fingerprints, an application would've stored a fingerprint and assumed that the method would return an output port, but was given an input port instead, resulting in an error if it tried to send anything to it."
If you were going down this path (of collapsing Input and Output together), I would expect:
interface MIDIAccess { sequence
listInputs (); sequence listOutputs (); MIDIPort getPort (MIDIPort or DOMString or short target); };
Sorry to again be a dumbass, but I really don't understand why you send a MIDIPort to get a MIDIPort? Can you please explain the logic there?
Original comment by Chris Wilson on W3C Bugzilla. Wed, 26 Dec 2012 17:29:52 GMT
(In reply to comment #6)
(In reply to comment #5)
(In reply to comment #4)
Just wanted to record a random thought here:
getPort(DOMString id, optional MIDIPortType type);
As in: var port = midi.getPort("12e23f3", "input");
But why would you do that? For any given id, the type is predetermined (and fixed).
Jussi said that the fingerprint might not be reliable (i.e., an input and and output would have the same fingerprint): "It would be especially annoying if faced with a UA that doesn't have enough data to give reliable fingerprints, an application would've stored a fingerprint and assumed that the method would return an output port, but was given an input port instead, resulting in an error if it tried to send anything to it."
I don't believe the system would ever confuse an input and an output fingerprint. In my shim implementation, I'll simply prepend "i" or "o" to identify. The confusion potential with fingerprints is across sessions, when you have multiple ports with the same name in the system, when the indices change (e.g. when a device is added or removed from the system) - For example, I have two Novation Launchpads (not an uncommon thing). If I add a controller that ends up (according to the OS) showing up in the list of interfaces before those, suddenly one of those might be at index 5 instead of 4 - and the other one is at index 4, and looks just like the other one used to in terms of name, manufacturer, index... everything that persists.
MIDIPort getPort (MIDIPort or DOMString or short target);
Sorry to again be a dumbass, but I really don't understand why you send a MIDIPort to get a MIDIPort? Can you please explain the logic there?
I would be happy to drop it. I was simply copying out of the current spec. I think index (short) and id (string) are sufficient.
The MIDIPort type as a param predates the index; Jussi's original proposal had MIDIPort, I believe.
Original comment by Jussi Kalliokoski on W3C Bugzilla. Wed, 26 Dec 2012 18:12:03 GMT
(In reply to comment #7)
I don't believe the system would ever confuse an input and an output fingerprint. In my shim implementation, I'll simply prepend "i" or "o" to identify. The confusion potential with fingerprints is across sessions, when you have multiple ports with the same name in the system, when the indices change (e.g. when a device is added or removed from the system) - For example, I have two Novation Launchpads (not an uncommon thing). If I add a controller that ends up (according to the OS) showing up in the list of interfaces before those, suddenly one of those might be at index 5 instead of 4 - and the other one is at index 4, and looks just like the other one used to in terms of name, manufacturer, index... everything that persists.
You're probably right, it seems unlikely that the IDs would get confused. Sounds good, I'm fine with going ahead and merging the methods.
Original comment by Chris Wilson on W3C Bugzilla. Wed, 26 Dec 2012 19:05:00 GMT
(In reply to comment #8)
You're probably right, it seems unlikely that the IDs would get confused. Sounds good, I'm fine with going ahead and merging the methods.
I don't think merging the methods is the right thing to do, as you can't use indices then. I just meant that if you DID have a getPort, it doesn't need a type if it's using ONLY fingerprint (or MIDIPort).
Further feedback: Ryoya Kawai of Yamaha mentioned that they did not particularly favor the merging of input/output querying to getPorts, but that they found the getInput/getInputs (i.e. one letter difference between method names) confusing. They had liked enumerateInputs/Outputs, but I explained that it's not an enumeration as per Marcos' feedback; perhaps we should change to listInputs()/listOutputs().
Bump: should we change to listInputs/listOutputs?
(sorry, it's been a while and I'm trying to get my brain back into this space)
FWIW, I would prefer just ".inputs" and ".outputs" (attributes, instead of methods). Rationale: The word "list" is redundant in that it implies "get" and also the return type (which is a list). Also, given the getting the lists is performed synchronously, and no argument is passed to either method, then they could just be attributes.
I also never got an answer to this question:
MIDIPort getPort (MIDIPort or DOMString or short target);
Sorry to again be a dumbass, but I really don't understand why you send a MIDIPort to get a MIDIPort? Can you please explain the logic there?
@cwilso, above you said you would be happy to drop that, but I'm still not sure what the intent was
MIDIPort getPort() is NOT a part of the spec - it's MIDIInput getInput() or MIDIOutput getOutput() (i.e. the result of the "get" call is not a MIDIPort, it's specifically an input or output object). The getInput/getOutput is what registers a port, and tells the underlying system it should be listening (in the case of an input) or preparing to send (in the case of an output). Otherwise, the underlying system has to listen to all devices, or specifically track the devices with an event handler on message, in order to know what to register for. Let me talk it over with the developer.
.inputs/.outputs would also somewhat imply that numeric indicies are the right way to index the LIVE list (note that the resulting sequence from getInputs/getOutputs is NOT live, so you can index through it).
I meant I would be happy to drop passing a MIDIPort into getInput/getOutput to receive a MIDIInput/MIDIOutput (rather than an ID or an index), since you could just pass in the ID from the MIDIPort anyway.
I'm happy with whatever you choose to do here.
I'd be really happy to just get rid of all the overloads on these methods, I believe IDs will cater for all use cases well enough without adding to the mental load of the API.
At least, I feel we should remove short type overload against getInput and GetOutput. There are two reasons.
Because of reason 1, I'll implement it in Chromium without short overload functions tentatively. Any thoughts?
Takashi-san - I'd like to just change the signatures completely and go with inputs[] and outputs[]. Is that okay with you?
On Wed, May 1, 2013 at 8:01 AM, Takashi Toyoshima notifications@github.comwrote:
At least, I feel we should remove short type overload against getInput and GetOutput. There are two reasons.
1.
WebIDL doesn't allow short and DOMString overloads (See, also another thread at crbug https://code.google.com/p/chromium/issues/detail?id=235884) 2.
getInput(short index) needs to hold a snapshot of MIDIInput sequence when a user call getInputs() What's happen when a user call getInputs() multiple times? Maybe only the last sequence is valid for short index access. But, it's confusing, redundant, and make implementation complicated.
Because of reason 1, I'll implement it in Chromium without short overload functions tentatively. Any thoughts?
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17285662 .
I'd like to just change the signatures completely and go with inputs[] and outputs[].
That doesn't sound like a good idea, with attributes I believe that you should have a really good justification for breaking the promise of object.attribute === object.attribute
which we can't keep without unnecessarily complicating the implementation.
Like said earlier, I'd prefer we just used IDs.
Can you explain the complexity?
I'm fine dropping Port; I don't like dropping index. inputs[] outputs[] takes care of that.
On Wed, May 1, 2013 at 10:14 AM, Jussi Kalliokoski <notifications@github.com
wrote:
I'd like to just change the signatures completely and go with inputs[] and outputs[].
That doesn't sound like a good idea, with attributes I believe that you should have a really good justification for breaking the promise of object.attribute === object.attribute which we can't keep without unnecessarily complicating the implementation.
Like said earlier, I'd prefer we just used IDs.
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17292759 .
Can you explain the complexity?
In order to make sure that the attribute stays the same during the comparison operation, we'd have to mandate that inputs[]
and outputs[]
stay the same until the event loop is freed again, and that's complicated to implement. This is similar to the issue of Web Audio API AudioParam .value changing while it's being read, although we're looking at a much more stable situation.
What's the use case for getting by index that isn't covered by getting by ID?
Can't you just make it a sequence?
sequence is actually what I meant, not array.
Jussi: I find it confusing in practice that you get a list of MIDIPorts, then you have to ask to "convert" one into a MIDIInput or MIDIOutput; it would be far far easier to just access them.
So yeah, I misspoke -
Sequence
On Wed, May 1, 2013 at 11:08 AM, Marcos Caceres notifications@github.comwrote:
Can't you just make it a sequence?
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17296478 .
It would mean going back to having a function ( inputs(), outputs() )
Just to clarify, those would go back to being methods if we use a sequence because WebIDL doesn't allow attributes to return sequences. I personally think that is ok.
Err. Could you please send that again without the HTML links? (see on Github)
Cleaned up for you.
interface MIDIAccess : EventTarget {
sequence<MIDIInput> inputs ();
sequence<MIDIOutput> outputs ();
attribute EventHandler onconnect;
attribute EventHandler ondisconnect;
MIDIMessageEvent createMessageEvent(optional Uint8Array data, optional double receivedTime);
MIDIConnectionEvent createConnectionEvent (MIDIPort port);
};
Um, what are these two?
MIDIMessageEvent createMessageEvent(optional Uint8Array data, optional double receivedTime);
MIDIConnectionEvent createConnectionEvent (MIDIPort port);
Those are the synthesizing of message and connection events you said I had to add?
On Wed, May 1, 2013 at 11:21 AM, Marcos Caceres notifications@github.comwrote:
Um, what are these two?
MIDIMessageEvent createMessageEvent(optional Uint8Array data, optional double receivedTime); MIDIConnectionEvent createConnectionEvent (MIDIPort port);
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17297153 .
Oh, no. Sorry for the misunderstanding! The MIDIMessageEvent themselves gain a constructor, we don't need helper methods on the MIDIAccess interface.
Sorry, my mistake. Will fix.
On Wed, May 1, 2013 at 11:24 AM, Marcos Caceres notifications@github.comwrote:
Oh, no. Sorry for the misunderstanding! The MIDIMessageEvent themselves gain a constructor, we don't need helper methods on the MIDIAccess interface.
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17297318 .
So for MIDIMessageEvent:
[Constructor(DOMString type, optional MIDIMessageEventInit eventInitDict)]
interface MIDIMessageEvent{
readonly attribute Uint8Array data;
readonly attribute double receivedTime;
}
dictionary MIDIMessageEventInit{
Uint8Array data;
double receivedTime;
}
And for MIDIConnectionEvent:
[Constructor(DOMString type, optional MIDIConnectionEventInit eventInitDict)]
MIDIConnectionEvent{
readonly attribute MIDIPort port;
}
dictionary MIDIConnectionEventInit{
MIDIPort port;
}
Jussi: I find it confusing in practice that you get a list of MIDIPorts, then you have to ask to "convert" one into a MIDIInput or MIDIOutput; it would be far far easier to just access them.
Hmm? It's not like sites should ever access them directly anyway. The sites have no way of knowing what the MIDI device at a given index is designed to do, so the site needs to ask the user which port to use anyway, at which point the site already needs more info than just the port indices. I'd really like to make it inconvenient to access ports by ID to avoid developers just going with getOutput(0) because they're too lazy to implement a user interface for that, then someone goes to a website that tries to play music but instead does weird things to the users lighting system.
Marcos, why would this be
[Constructor(DOMString type, optional MIDIMessageEventInit eventInitDict)]
instead of
[Constructor(optional Uint8Array data, optional double receivedTime)]
?
Is this just to enable extensibility later?
On Wed, May 1, 2013 at 11:32 AM, Marcos Caceres notifications@github.comwrote:
So for MIDIMessageEvent:
[Constructor(DOMString type, optional MIDIMessageEventInit eventInitDict)] interface MIDIMessageEvent{ readonly attribute Uint8Array data; readonly attribute double receivedTime; } dictionary MIDIMessageEventInit{ Uint8Array data; double receivedTime; }
And for MIDIConnectionEvent:
[Constructor(DOMString type, optional MIDIConnectionEventInit eventInitDict)] MIDIConnectionEvent{ readonly attribute MIDIPort port; } dictionary MIDIConnectionEventInit{ MIDIPort port; }
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17297786 .
I have an aversion to magic opaque handles, when the user (developer) scenario is a collection (sequence).
Yes, it's always going to be bad practice to be lazy and latch the first device. You will always be able to be lazy, though:
midi. getOutput( midi. getOutputs()[0] );
On Wed, May 1, 2013 at 11:37 AM, Jussi Kalliokoski <notifications@github.com
wrote:
Jussi: I find it confusing in practice that you get a list of MIDIPorts, then you have to ask to "convert" one into a MIDIInput or MIDIOutput; it would be far far easier to just access them.
Hmm? It's not like sites should ever access them directly anyway. The sites have no way of knowing what the MIDI device at a given index is designed to do, so the site needs to ask the user which port to use anyway, at which point the site already needs more info than just the port indices. I'd really like to make it inconvenient to access ports by ID to avoid developers just going with getOutput(0) because they're too lazy to implement a user interface for that, then someone goes to a website that tries to play music but instead does weird things to the users lighting system.
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17298090 .
You will always be able to be lazy, though: midi. getOutput( midi. getOutputs()[0] );
Actually, what I want is
midi.getOutput( midi.getOutputs()[0].id );
Why add a convenience helper for a bad thing when the bad thing is already pretty easy to do?
The UAs are free to cater better options to lazy developers though, such as providing a UI for the user to select a preferred MIDI playback device and then always giving that device an ID "default", then the developer can just do:
try {
outputPort = midi.getOutput( 'default' ) ;
} catch (e) {
// Ask the user which device she wants to use for playback.
}
Why not get rid of the MIDIPort instantiation (and the re-querying to call getOutput()) altogether, and just expose a sequence of MIDIOutputs?
You're trying to prevent people from being lazy, which is just boiling the ocean as far as I'm concerned. And please, let's NOT do the "UA for default MIDI device" - that never really worked in Windows with MIDIMapper, either. Just let the app authors solve it as they want to.
On Wed, May 1, 2013 at 12:16 PM, Jussi Kalliokoski <notifications@github.com
wrote:
You will always be able to be lazy, though: midi. getOutput( midi. getOutputs()[0] );
Actually, what I want is
midi.getOutput( midi.getOutputs()[0].id );
Why add a convenience helper for a bad thing when the bad thing is already pretty easy to do?
The UAs are free to cater better options to lazy developers though, such as providing a UI for the user to select a preferred MIDI playback device and then always giving that device an ID "default", then the developer can just do:
try { outputPort = midi.getOutput( 'default' ) ; } catch (e) { // Ask the user which device she wants to use for playback. }
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17300328 .
Why not get rid of the MIDIPort instantiation (and the re-querying to call getOutput()) altogether, and just expose a sequence of MIDIOutputs?
I thought we were over this already? This is not an option unless the UA is supposed to take exclusive control over all MIDI devices on the computer.
You're trying to prevent people from being lazy, which is just boiling the ocean as far as I'm concerned.
I'm not. I just don't see the point of catering special things to their will to cut corners and provide a worse user experience.
And please, let's NOT do the "UA for default MIDI device" - that never really worked in Windows with MIDIMapper, either. Just let the app authors solve it as they want to.
Like said, UAs are free to do this currently, I'm not saying we should spec this.
Why exclusive control? Just because one app has requested access to a port should not prevent other devices from accessing them.
on default device - I would be upset if a UA decided to make a special magic value of what was supposed to be an opaque identifier.
On Wed, May 1, 2013 at 12:38 PM, Jussi Kalliokoski <notifications@github.com
wrote:
Why not get rid of the MIDIPort instantiation (and the re-querying to call getOutput()) altogether, and just expose a sequence of MIDIOutputs?
I thought we were over this already? This is not an option unless the UA is supposed to take exclusive control over all MIDI devices on the computer.
You're trying to prevent people from being lazy, which is just boiling the ocean as far as I'm concerned.
I'm not. I just don't see the point of catering special things to their will to cut corners and provide a worse user experience.
And please, let's NOT do the "UA for default MIDI device" - that never really worked in Windows with MIDIMapper, either. Just let the app authors solve it as they want to.
Like said, UAs are free to do this currently, I'm not saying we should spec this.
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17301574 .
Why exclusive control? Just because one app has requested access to a port should not prevent other devices from accessing them.
But with winmm it does exactly that.
on default device - I would be upset if a UA decided to make a special magic value of what was supposed to be an opaque identifier.
To be clear, I don't think that is a good idea, but if we want to serve lazy developers, I think that's the best way to do it.
Well, then, a Windows implementation will have to release hooks when they're not in use (when no event listeners are registered for Inputs, when not actively sending for output). Nasty, but frankly it's killing a bunch of scenarios otherwise (multiple channels with different apps using IO). I do this in demos today - one app responding to drum pads, different app responding to keys on same input device.
On Wed, May 1, 2013 at 12:46 PM, Jussi Kalliokoski <notifications@github.com
wrote:
Why exclusive control? Just because one app has requested access to a port should not prevent other devices from accessing them.
But with winmm it does exactly that.
on default device - I would be upset if a UA decided to make a special magic value of what was supposed to be an opaque identifier.
To be clear, I don't think that is a good idea, but if we want to serve lazy developers, I think that's the best way to do it.
— Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-17302042 .
I'm back to the discussion. If I understand correctly, the latest proposal is this one?
interface MIDIAccess : EventTarget {
sequence<MIDIInput> inputs ();
sequence<MIDIOutput> outputs ();
attribute EventHandler onconnect;
attribute EventHandler ondisconnect;
};
Yes. Sound good?
On Thu, May 23, 2013 at 5:18 AM, Takashi Toyoshima <notifications@github.com
wrote:
I'm back to the discussion. If I understand correctly, the latest proposal is this one?
interface MIDIAccess : EventTarget { sequence
inputs (); sequence outputs (); attribute EventHandler onconnect; attribute EventHandler ondisconnect; }; — Reply to this email directly or view it on GitHubhttps://github.com/WebAudio/web-midi-api/issues/2#issuecomment-18339515 .
yeah, sgtm.
Update:
Option 1): Sequence cannot be used in an attribute. However, [](aka Array) can, so MIDIAccess can be handled this way. So, the definition could be:
interface MIDIAccess : EventTarget {
readonly attribute MIDIInput[] inputs;
readonly attribute MIDIOutput[] outputs;
attribute EventHandler onconnect;
attribute EventHandler ondisconnect;
};
However, it's questionable whether Windows can handle non-exclusive access to MIDI devices, and this approach sort of presumes that the implementation doesn't need to explicitly take control of a given interface it's interested in (since it has all of them "ready" in the array at all times once the MIDIAccess is granted). If this is a problem on Windows (we don't want the Web MIDI implementation to have to grab all MIDI devices exclusively, obviously), then we may have to stick with:
Option 2) (what's in the spec right now:)
interface MIDIAccess : EventTarget {
sequence<MIDIPort> getInputs ();
sequence<MIDIPort> getOutputs ();
MIDIInput getInput (MIDIPort or DOMString or short target);
MIDIOutput getOutput (MIDIPort or DOMString or short target);
attribute EventHandler onconnect;
attribute EventHandler ondisconnect;
};
Downside of this is the confusing getInput()/getInputs() dichotomy, and the overhead of having an instantiated MIDIPort that you can't just use (i.e. you call getInputs, but you can't set .onmidimessage of getInputs()[0].)
Thoughts? Can I get confirmation/denial of Windows' exclusivity?
I haven't had my morning cup of coffee yet, but what about just:
sequence<MIDIInput> inputs (optional (DOMString[] or DOMString) id);
sequence<MIDIOutput> outputs (optional (DOMString[] or DOMString) id);
When the value is missing, it returns everything. When the value is one or more matching ids, it returns a sequence with the matching objects. If a wrong id is supplied, then a NotFoundError
is thrown.
The slightly sucky bit is having to unwrap an array with a single value, but it does provide some flexibility when performing look ups for multiple midi objects.... you could even combine the above into:
emum MIDIIO{ "inputs", "outputs"}
sequence<MIDIPort> get (MIDIIO type, optional (DOMString[] or DOMString) id);
Then you get:
var in = midi.get("inputs", id)[0];
var ins = midi.get("inputs")
var outs = midi.get("outputs", ["xyz", "zya"]);
That seems like even more goofiness. Or maybe I've had one too many cups of coffee.
:smile: ... at a minimum, we have agreement to only use a DOMString ID, right?
I'm not sure what that means. Not use a MIDIPort reference, sure - but I still think indexing an array/sequence is going to be how most devs do it. I guess if it's always a sequence returned, that would be handled.
Sorry, what I mean is that "short" is gone from getInput(), getOutput() - and that there is no need to pass a MIDIPort to those functions.
If we still have getInput(), then I would want an index to work there. If we have only getInputs(), that returns an array or a sequence, then it's not an issue.
The methods getInput() and getOutput() effectively do the same thing (evident also by the amount of duplicate text in the spec); as such, they should be merged. Furthermore, it's not clear (in the spec) as why there are 3 different ways to get a MIDIPort. I would like to suggest that these two methods be merged into a single method and the way to be one way to get a MIDIPort: by its ID… hence getPort(id) or getPortById(id);
Consider:
var port = midiAccess.getInputs()[x];
Additionally, the ordering of the ports may or may not be consistent after each session, so saying getInput(number) is inherently unreliable. Also, it's kinda unhelpful is you want to, for instance, get the last available port. This is because midiAccess has no length property. The only way to get the length is to first call getInputs(), and get the length from there… but then you already have the list of inputs, in so you don't then need to call getInput( number ), because it's already the same as inputs[number].
var favInstrument = midiAccess.getInput(localStorage.fav) if(favInstrument){ … } Also, if target is is not found, just return null. Please don't throw an exception. Throwing exceptions should be done in "exceptional" circumstances, not on simple lookups.