Within the GameController API, is continuously polling of navigator.getGamepads() required? - gamepad-api

EDITED at end!
Within the GameController API, is continuously polling of navigator.getGamepads() required?
I ask because my single call to this function returns a length = 0.
According to my Mac’s Bluetooth System Preferences my Nimbus+ game pad is connected.
Given that, should I use isetInterval` and wait for a length > 0?
EDIT begins here:
Macintosh with Monterey OS 12.4:
Safari (15.5) reports length = 0
Firefox (102.0b6) reports length = 0
Chrome (102.0.5005.115) reports length = 4,
but each in the array being = null

You first wait for the gamepad to be connected, which typically requires "waking" the gamepad by pressing one of its buttons:
window.addEventListener('gamepadconnected', (event) => {
console.log('✅ 🎮 A gamepad was connected:', event.gamepad);
});
Once the gamepad is connected, you start your game loop:
const pollGamepad = () => {
// Always call `navigator.getGamepads()` inside of
// the game loop, not outside.
const gamepads = navigator.getGamepads();
for (const gamepad of gamepads) {
// Disregard empty slots.
if (!gamepad) {
continue;
}
// Process the gamepad state.
console.log(gamepad);
}
// Call yourself upon the next animation frame.
// (Typically this happens every 60 times per second.)
window.requestAnimationFrame(pollGamepad);
};
// Kick off the initial game loop iteration.
pollGamepad();
You should stop polling when the gamepad gets disconnected, which you'll be informed of via an event:
window.addEventListener('gamepaddisconnected', (event) => {
console.log('❌ 🎮 A gamepad was disconnected:', event.gamepad);
});

Related

Code very slow when sending OSC or MQTT messages inside an MIDI event listener in Node js

First time posting here so sorry if the question is too vague or missing info. Anyway:
I'm trying to send OSC (open sound control) or MQTT messages when I hit specific notes on my midi controller. When I try to send a OSC message when I get a midi input, I get this unpredictable high latency, varying from about 200-300 milliseconds up to 10 seconds. Here is my test-code:
var easymidi = require('easymidi');
var osc = require("osc");
easymidi.getInputs().forEach((midiDevice)=> {
if (midiDevice.includes('Maschine')){
inputMidi = midiDevice
console.log(`Midi device input found: ${inputMidi}`)
}
})
var inputMikro = new easymidi.Input(inputMidi)
var rmeOSC = new osc.UDPPort ({
remoteAddress: "192.168.10.148",
remotePort: 9001
});
rmeOSC.open();
inputMikro.on('cc', function (msg) {
if (msg.controller == 7){
// This is instant
console.log(msg)
// This is what becomes unpredictable and slow
rmeOSC.send({
address: "/1/mastervolume",
args: [
{
type: "f",
value: msg.value / 127
}
]
});
}
}
I've tried to zero in what makes it slow. When just logging to console inside inputMikro.on('cc', ... ) event listener, it's instant. If I send that midi data to another midi device in that same event listener (also using easymidi library), it's also instant. But sending OSC or MQTT messages there creates that unpredictable latency. I've also tried setting an interval every 20 to send OSC just to make sure it's not a limitation of the OSC library in itself:
var vol = 0
var sendOsc = (()=>{
vol++
if (vol == 127){
vol = 0
}
rmeOSC.send({
address: "/1/mastervolume",
args: [
{
type: "f",
value: vol / 127
}
]
});
})
setInterval(sendOsc, 20)
That works great, same with MQTT. I also tried creating a separate volume variable with an event listener that listens for changes in that variable, and update that variable inside the inputMikro.on('cc', ... ) listener. Same there, if i just log to console whenever that variable changes, it's instant, but if I try to send OSC or MQTT messages when the variable changes, I get that latency.
I'm out of ideas and have no idea what's going on. I'd very much appreciate any insight on how I can fix this. I hope my question is clear enough.

How to manually stop getDisplayMedia stream to end screen capture?

I'm interested in getting a screenshot from the user and I'm using the getDisplayMedia API to capture the user's screen:
const constraints = { video: true, audio: false };
if (navigator.mediaDevices["getDisplayMedia"]) {
navigator.mediaDevices["getDisplayMedia"](constraints).then(startStream).catch(error);
} else {
navigator.getDisplayMedia(constraints).then(startStream).catch(error);
}
When executed, the browser prompts the user if they want to share their display. After the user accepts the prompt, the provided callback receives a MediaStream. For visualization, I'm binding it directly to a element:
const startStream = (stream: MediaStream) => {
this.video.nativeElement.srcObject = stream;
};
This is simple and very effective so far. Nevertheless, I'm only interested in a single frame and I'd therefore like to manually stop the stream as soon as I've processed it.
What I tried is to remove the video element from the DOM, but Chrome keeps displaying a message that the screen is currently captured. So this only affected the video element but not the stream itself:
I've looked at the Screen Capture API article on MDN but couldn't find any hints on how to stop the stream.
How do I end the stream properly so that the prompt stops as well?
Rather than stopping the stream itself, you can stop its tracks.
Iterate over the tracks using the getTracks method and call stop() on each of them:
stream.getTracks()
.forEach(track => track.stop())
As soon as all tracks are stopped, Chrome's capturing prompt disappears as well.
start screen capture sample code:
async function startCapture() {
logElem.innerHTML = "";
try {
videoElem.srcObject = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
dumpOptionsInfo();
} catch(err) {
console.error("Error: " + err);
}
}
stop screen capture sample code:
function stopCapture(evt) {
let tracks = videoElem.srcObject.getTracks();
tracks.forEach(track => track.stop());
videoElem.srcObject = null;
}
more info: MDN - Stopping display capture

Alexa - Perform background tasks during audioPlayer.Play

How is it possible to carry out any background tasks while Alexa is playing something with audioPlayer.Play?
The below plays an audio stream, but I need to perform other tasks in the background without intervention while the stream is playing. I know it is possible because other Skills can do it.
var handlers = {
'LaunchRequest': function() {
this.emit('Play');
},
'Play': function() {
this.response.speak('Sure.').
audioPlayerPlay(
'REPLACE_ALL',
stream.url,
stream.url,
null,
0);
this.emit(':responseReady');
}
}
Does anyone know or have any suggestions? From what I can see, once it starts playing the stream, I cannot get it to do anything unless I interrupt the stream to command another intent?
Alexa has a few built in requests that she sends to your skill throughout the lifecycle of an Audio stream for just this purpose! They are as follows:
AudioPlayer.PlaybackStarted - Sent when a new audio item begins playing.
AudioPlayer.PlaybackNearlyFinished - Sent when an audio item is almost over (most commonly used by a skill service to handle queuing the next item.)
AudioPlayer.PlaybackFinished - Sent when an audio item ends.
There are a couple of other ones too that you can read about here, but my guess is these will do just fine for what you need.
To use them, just set up handlers in your code for any of these requests and perform any tasks you need to there!
I don't know node.js at all, but my guess is the end result will look relatively close to this:
var handlers = {
'LaunchRequest': function() { /* your launch request code from above */ }
'Play': function() { /* your play code from above */ }
'AudioPlayer.PlaybackNearlyFinished': function() {
// Perform any background tasks here
}
}

Sleeping in action script 2 using getTimer() method

How can I correctly perform something like sleep function using getTimer()? I need to do an action every 15 seconds. The code below doesn't work. I compile it with mtasc compiler on Linux.
class Tuto
{
static var lastMsg = 0;
static var msgInt = 15000;
static function main(mc)
{
if(getTimer() > lastMsg + msgInt)
{
trace("something");
lastMsg = getTimer();
}
}
}
The main instruction will be executed just once. You have to build some kind of loop or rely on the tick events sent by the player to execute your code continuously.
The basic options are:
while (true) { doSomething() }
this will execute forever, but remember that the flashplayer is single threaded so while that runs everything else will be frozen, UI and user inputs included. this is only "good" if you are building some heavy-processing tool that has no need of interacting with the user.
setInterval(doSomething, 15000)
this creates an interval that will call your function every X milliseconds. This is the simplest option and probably what you're looking for.
addEventListener(Event.ENTER_FRAME, doSomething)
this registers a listener for the ENTER_FRAME event of the Flash Player, which will be dispatched 30 times per second (by default). Inside that function you can check the current time with getTimer() and decide if it's time to execute your logic.

How to create an interruptible loop in node.js

Disclaimer: I'm a Node.js newbie and the following description may be lengthy...
I'm currently trying to teach myself Node.js for a little project I'm after. The project idea is the following: a RaspberryPI runs a Node.js application which allows me to control the colors of an RGB LED strip. The application should be able to set both a static color and also run color wheels that smoothly change colors.
My idea is now to create several Node.js scripts:
A "controller" that does the client communication, sets static colors or is able to start a color wheel
"client scripts" that each run a color wheel. At most one of them would be "alive", started/stopped by the "controller"
I've been able to create a little script that forks another script and is able to stop that script using child.send as follows:
controller.js
var fork = require('child_process').fork,
test2 = fork(__dirname + '/test2.js');
setTimeout(function() { test2.send({func: 'quit'}); }, 5000);
This forks the test2.js script and after 5 seconds sends a quit message that quits test2.js.
test2.js
function runLoop()
{
console.log("Hello");
setTimeout(runLoop, 1000);
}
process.on('message', function(m) {
if (m.func === 'quit')
{
process.exit(0);
}
});
setTimeout(runLoop, 1000);
This "client script" prints "Hello" every second until the controller sends the quit message.
This works pretty well - after 5 seconds the scripts finish gracefully.
My question is now: If I implement a color wheel, I'll need a possibly endless loop that changes the colors of the LED strip. Would the above (with shorter timer values of course - I need something like 10ms here) be a feasible way of implementing an interruptible loop or is there some neater mechanism I don't know of yet?
If you're using setTimeout, you shouldn't even need to fork a new process. Here's how I would write your example:
var ntrvl = setInterval(function() { console.log('Hello'); }, 1000);
setTimeout(function() { clearInterval(ntrvl); }, 5000);
... very simple. With setTimeout and setInterval, you're using asynchronous functions, so you will not block the event loop. When the timer is up, it runs your code, then waits for the next event. You should be able to control all of your "clients", you'll have bandwidth for far more than you'll actually need, all in the same process in this way, concurrently.
All you need to be wary of is that you're not blocking the script. If you attempt to perform any action synchronously (which means that the script will wait for the action to complete before performing the next command), then you need to make sure it runs quickly. If you have to run processor/time intensive tasks synchronously, that's when you'll need to fork a new process.
You're making the life complicated. Your global architecture is as follows:
external trigger --> listener ----------> code that changes color
(ie. web client) (ie. web server)
With that in mind you don't need to fork any process, you can control the LED strip within a single process. Somewhere in your code you'll have an object similar to this:
//"led" is the module that allows you to change the color of a led (suppose 4 leds)
var led = require ("led-controller");
var ColorChanger = module.exports = function (){
this._intervalId = null;
};
ColorChanger.prototype.setColor = function (hex){
//Color in hexadecimal
//Cancel any current interval
cancelInterval (this._intervalId);
led.color (0, hex);
led.color (1, hex);
led.color (2, hex);
led.color (3, hex);
};
ColorChanger.prototype.wheel = function (hex, ms){
//Color in hexadecimal
//"ms" is the time interval between leds going on and off
//Cancel any current interval
cancelInterval (this._intervalId);
//Shutdown all the leds
led.off (0);
led.off (1);
led.off (2);
led.off (3);
//Activate the first led
led.color (0, hex);
//Current active led
var curr = 0;
this._intervalId = setInterval (function (){
//Each "ms" the current led will go off and the next will go on
led.off (curr);
//Next led to activate
curr = ++curr%4;
led.color (curr, hex);
}, ms);
};
Then the listener module uses the ColorChanger.
var ColorChanger = require ("./color-changer");
var changer = new ColorChanger ();
//Set all the leds to red
changer.setColor ("#FF0000");
//Each 10ms one led goes green and the previous is turned off, in an endless loop
changer.wheel ("#00FF00", 10);

Resources