-
Hi, I'm not sure if this is an issue or operator error (perfectly willing to stipulate it could be the latter if that's the reality). I'd really like to follow the "press button, generate listeners" pattern with an Input's addListener for "noteon" and channels = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16] (I'll deal with EventEmitter.ANY_EVENT separately). Well that almost works: I get 16 listeners for "noteon" (they're all enabled). And I get 16 calls to the listener callback when running, presumably one per channel. The problem: Each call in the callback's MessageEvent.message.channel has a value of 1. I was expecting a value of 1 - 16 depending on the listener instance making the callback. So I have no way of binding the specific instantiated listener to the appropriate callback instance. And I can't set an argument value in addListener(...) to the channel I want each instance to care about because it's the same arguments for each instantiation since I'm asking WEBMIDI.js to handle the instance creation for me, plus I'd have to inject the argument after the instances are created. Yes I'm lazy - I was thinking of one call to Input.addListener() with an injected argument as opposed to 16 calls to InputChannel.addListener(...). But is InputChannel.addLister(...) the way I have to go? The idea: Is there a way of injecting extra arguments after the creation of the instances in Input.addListener(...)? Update: I've worked around this by creating the listener one channel at a time - and it's doing what I want. But I still suggest it's cleaner and should be possible to do the "per instance" injecting of an argument with multiple channels. Plus I'm still not not sure why I was getting 16 invocations of the listener for channel 1 when I specified 1 - 16 (yes I know undefined does the same thing) Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 7 replies
-
Do you have a small working example that demonstrates the problem? I just tried it on my side and it works fine. |
Beta Was this translation helpful? Give feedback.
-
I appreciate you taking the time to prepare an example but it looks much larger than necessary to demonstrate an issue that sounded quite specific in your first message. Honestly, at this point, I'm just not sure what you are asking or what the problem is. Perhaps you could break it down and identify what the result is in contrast to what you expected it to be? |
Beta Was this translation helpful? Give feedback.
-
Okay, I think I now understand what you want to do. Let me break this down because there is a lot to unpack. When you add a listener, you can pass an objects with additional options. One of the options is an array of arguments to pass to the function that is called when the event is triggered. You can put anything you want in this array. For example: const opts = {arguments: ["foo", "bar"]}
WebMidi.inputs[1].addListener("noteon", (e, arg1, arg2) => console.log(arg1, arg2), opts); This would print Now, if I understood you correctly, you want to modify these arguments after the listener is created. This is also possible. Here's how you would do it: const opts = {arguments: ["foo", "bar"]}
const listeners = WebMidi.inputs[1].addListener("noteon", (e, arg1, arg2) => console.log(arg1, arg2), opts);
listeners[0].arguments = ["Hello", "World!"]; This would print Your question is: But if it's an array of Listener objects, what index of that array applies to which channel? The answer is that the listeners are created in numerical order. So, As you already know, the message payload does not include the additional arguments. This is by design. The arguments are simply passed as additional parameters to the callback function. In any case, you can still retrieve the arguments within the callback. I hope this makes things clearer. |
Beta Was this translation helpful? Give feedback.
-
In all honesty, I did not go through your entire code. However, I believe the situation can be illustrated with these 5 lines: const opts = {channels: [3, 5], arguments: ["foo", "bar"]};
const listeners = WebMidi.inputs[1].addListener("noteon", (e, arg1, arg2) => console.log(arg1, arg2), opts);
listeners[1].arguments = ["Hello", "World!"];
console.log(listeners[0].arguments);
console.log(listeners[1].arguments); When I run this code, I get the following in the console:
Is this not what you are getting? |
Beta Was this translation helpful? Give feedback.
-
I added a mention in the documentation to clarify that the array of listeners returned by |
Beta Was this translation helpful? Give feedback.
-
I went back to your code and I think I spotted the problem. The problem is that you are not replacing the const opts = {channels: [3, 5], arguments: ["foo", "bar"]};
const listeners = WebMidi.inputs[1].addListener("noteon", (e, arg1, arg2) => console.log(arg1, arg2), opts);
listeners[1].arguments[0] = "Hello";
listeners[1].arguments[1] = "World!";
console.log(listeners[0].arguments);
console.log(listeners[1].arguments); In this case, the result will be: Hello World!
Hello World! This simply illustrates that all listeners are passed the same reference to the original If you want to change the value for a single listener, you need to overwrite the reference with a reference to a new array. |
Beta Was this translation helpful? Give feedback.
I went back to your code and I think I spotted the problem. The problem is that you are not replacing the
arguments
array but rather mutating a single value inside it. It is akin to doing this (going back to my previous example):In this case, the result will be:
This simply illustrates that all listeners are passed the same reference to the original
a…