Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FA22: Conga changes! #106

Open
wants to merge 1 commit into
base: fuego-2022
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions audio/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class AudioInput extends EventEmitter {
constructor(options) {
super();
// this._sampleRate = options._sampleRate || 48000;
const deviceIndex = options.deviceIndex || null;
const deviceIndex = options.deviceIndex ?? null;
const profile = options.profile || null;
this._args = [ '-u' ];
if (!profile) {
Expand All @@ -27,7 +27,7 @@ class AudioInput extends EventEmitter {
const profilePath = options.profilePath || 'audioprofile.pstats';
this._args.push('-m', 'cProfile', '-o', profilePath, mainScript);
}
if (deviceIndex) {
if (deviceIndex !== undefined) {
this._args.push('-d', deviceIndex.toString());
}
this._subprocess = null;
Expand Down
13 changes: 13 additions & 0 deletions server/setups/shape-mappings/fuego2022.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ module.exports = function getShapes() {
inv(_.range(T2, T2+SIDE_TRIANGULO))
]);


// Totems
const totemL1 = _.range(T4_end, T4_end+150);
const totemL2 = _.range(T4_end+150, T4_end+150*2);
Expand Down Expand Up @@ -152,12 +153,24 @@ module.exports = function getShapes() {
const wingsLeft = _.flatten([totemL1, totemL2, V1L, V2L]);
const wingsX = _.flatten([totemL1, totemL2, X, totemR1, totemR2]);

const arc = _.flatten([
inv(_.range(quiebre_abajo, T2)),
_.range(T2, T2+SIDE_TRIANGULO),
inv(_.range(T3, T3+SIDE_TRIANGULO)),
_.range(T4 + quiebre_abajo, T4_end)
]);

const right_mini_w = _.flatten([


]);
return {
Warro,
WarroOnly,
allOfIt,
all,
mini_w,
arc,
pataLeft,
pataRight,
reloj,
Expand Down
1 change: 1 addition & 0 deletions server/src/LightController.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const savedPresets = require(savedPresetsFilePath)
// TODO: move this to some configuration file
const programNames = [
"mix",
"congaCelebration",
"congaShooting2",
"congaScore",
"congaShooting",
Expand Down
30 changes: 15 additions & 15 deletions server/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ require('./hackProgramReloadOnRestart')(controller);
controller.start();

console.log('Available audio devices:\n', listDevices());
//
const audioInput = new AudioInput({deviceIndex: null});

const audioInput = new AudioInput({deviceIndex: 0,});
audioInput.on('audioframe', audioEmitter.updateFrame.bind(audioEmitter));

// const audioInput2 = new AudioInput({deviceIndex: 3,});
// audioInput2.on('audioframe', (frame) => {
// audioEmitter.frame2 = frame;
// });
// audioInput2.start();
//
// // Second audio input test
// audioInput.on('audioframe', (frame) => {
// audioEmitter.currentFrame = frame;
// audioEmitter.ready = true;
// audioEmitter.emit('audioframe', audioEmitter.currentFrame);
// });
const audioInput2 = new AudioInput({deviceIndex: 2,});
audioInput2.on('audioframe', (frame) => {
audioEmitter.frame2 = frame;
});
audioInput2.start();

// Second audio input test
audioInput.on('audioframe', (frame) => {
audioEmitter.currentFrame = {... frame, ... _.mapKeys(audioEmitter.frame2, (v,k) => 'mic2_'+k)};
audioEmitter.ready = true;
audioEmitter.emit('audioframe', audioEmitter.currentFrame);
});
audioInput.start();


startServer(controller);
startServer(controller);
20 changes: 19 additions & 1 deletion server/src/light-programs/conga-utils/GlobalGame.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const ColorUtils = require("./../utils/ColorUtils");

class Game {
constructor() {
this.score = [0,0];
this.player1Color = ColorUtils.HSVtoRGB(400, 1, 1);
this.player2Color = ColorUtils.HSVtoRGB(400+0.33, 1, 1);
}

addPoint(playerIndex, points = 1) {
Expand All @@ -14,8 +18,22 @@ class Game {
restart() {
this.score = [0,0];
}

winner(){
let winner = false;
if (this.score[0] == this.max()){
winner = 1;
}
else if(this.score[1] == this.max()){
winner = 2;
}
if(winner){
this.restart();
}
return winner;
}
}

module.exports = {
game: new Game()
}
}
135 changes: 135 additions & 0 deletions server/src/light-programs/programs/congaCelebration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
const LightProgram = require("./../base-programs/LightProgram");
const ColorUtils = require("./../utils/ColorUtils");
const GlobalGame = require("./../conga-utils/GlobalGame");
const _ = require("lodash");
const programsByShape = require("./../base-programs/ProgramsByShape");

module.exports = class CongaCelebratiton extends LightProgram {
init() {
this.past = null;
this.celebrate = 0;
this.winner = false;
this.colors = new Array(this.numberOfLeds).fill(ColorUtils.HSVtoRGB(0, 0, this.config.brillo));
// Shallow copy of schedule
this.programs = _.map(this.config.programs, config => this.getProgramInstanceFromParam(config));
}

getProgramInstanceFromParam({programName, config, shape}) {
let p = null;
// For performance, only use programsByShape if there is a shape
if(shape) {
const programClass = this.lightController.programs[programName].generator;
const byShapeClass = programsByShape({[shape]: [programClass, config || {}]});
p = new byShapeClass(this.config, this.geometry, this.shapeMapping, this.lightController);
} else {
p = this.lightController.instanciateProgram(programName);
p.updateConfig({...p.config, ...config})
}

p.init();
return p;
}

getCelebrationBaseColors() {



}

drawFrame(draw, audio) {
this.colors = new Array(this.numberOfLeds).fill(ColorUtils.HSVtoRGB(0, 0, this.config.brillo/100));
let winner = GlobalGame.game.winner();
let combinedColors = this.colors;
if (winner && (this.celebrate == 0 || winner != this.winner)){
this.winner = winner;
this.celebrate = this.config.celebrationDurationInFrames;
}
if (this.celebrate > 0){
let winnerColor = this.winner == 1 ? GlobalGame.game.player1Color : GlobalGame.game.player2Color;
this.colors = new Array(this.numberOfLeds).fill(winnerColor);
this.celebrate--;
}
if(!this.config.animateOnlyOnCelebration || this.celebrate > 0){
combinedColors = this.colors;

this.extraTime = (this.extraTime || 0) + Math.random() * 10;

for (const prog of this.programs) {
// Done by ProgramScheduler, has to be replicated here
prog.timeInMs = this.timeInMs;
let globalBrightness = prog.config.globalBrightness || 0;
prog.drawFrame((colors) => {
for (let i = 0; i < this.numberOfLeds; i++) {
let [r, g, b, a] = combinedColors[i]
const [r2, g2, b2, a2] = colors[i];
if (this.config.multiply) {
// globalBrightness of 0 means "the layer does not darken the other layer"
r = r * ((r2+(255-r2)*(1-globalBrightness)) || 0) / 255;
g = g * ((g2+(255-g2)*(1-globalBrightness)) || 0) / 255;
b = b * ((b2+(255-b2)*(1-globalBrightness)) || 0) / 255;
a = a + (a2 || 0)
} else {
r += (r2 || 0) * globalBrightness;
g += (g2 || 0) * globalBrightness;
b += (b2 || 0) * globalBrightness;
a += a2 || 0;
}
combinedColors[i] = [r, g, b, a];
}
}, audio)
}
}
draw(combinedColors);
}

updateConfig(newConfig) {
// TODO: backwards compatibility with previous version of mix
if(newConfig.a && newConfig.b) {
let {a, b, ... other} = newConfig;
newConfig = {... other, programs: [a, b]}
}

// Override LightProgram version to decide when a program init needs to be called
if (this.programs) {
let updated = newConfig.programs;
let oldConfigs = this.config.programs;

this.programs = _.map(updated, (newProgDef, i) => {
let oldProgDef = oldConfigs[i];

let subprogram = null;

// Detect if the selected program type is the same or it changed
if (oldProgDef && oldProgDef.programName === newProgDef.programName && oldProgDef.shape === newProgDef.shape) {
subprogram = this.programs[i]
subprogram.updateConfig({ ... subprogram.config, ... newProgDef.config })
} else {
subprogram = this.getProgramInstanceFromParam(newProgDef)
}

// Detect if a different preset was selected and apply the default+preset program config
if(oldProgDef && oldProgDef.presetName !== newProgDef.presetName && newProgDef.presetName) {
const presets = this.lightController.getProgramPresets(newProgDef.programName);
const defaults = this.lightController.getProgramDefaultParams(newProgDef.programName);
newProgDef.config = presets[newProgDef.presetName];
subprogram.updateConfig({ ... defaults, ... presets[newProgDef.presetName] })
}

return subprogram
});
}

super.updateConfig(newConfig)
}

// Override and extend config Schema
static configSchema() {
let res = super.configSchema();
res.brillo = { type: Number, min: 0, max: 1, step: 0.01, default: 0.5 };
res.celebrationDurationInFrames = { type: Number, min: 0, max: 200, step: 5, default: 500 };
res.animateOnlyOnCelebration = {type: Boolean, default: false};
res.programs = {type: 'programs', default: [{programName: 'circles'}]};
res.multiply = {type: Boolean, default: false};
return res;
}
};
Loading