in between working states, switchting to multi midi out per node

This commit is contained in:
Sebastian
2024-10-19 17:41:31 +02:00
parent 0d942b6677
commit ee8d50fc0a
7 changed files with 104 additions and 43 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
CXX = g++-13 CXX = g++
CXXFLAGS = -std=c++20 -Wall -g -fno-omit-frame-pointer -gdwarf-4 -Og -DLIBREMIDI_ALSA=1 -Wnarrowing CXXFLAGS = -std=c++20 -Wall -g -fno-omit-frame-pointer -gdwarf-4 -Og -DLIBREMIDI_ALSA=1 -Wnarrowing
CXXINC = -I/usr/lib/gcc/x86_64-pc-linux-gnu/13.3.0/include -Iinclude CXXINC = -I/usr/lib/gcc/x86_64-pc-linux-gnu/13.3.0/include -Iinclude
+10 -4
View File
@@ -16,17 +16,23 @@ class ConnectionManager{
Node* next(Node* current, Node* last){ Node* next(Node* current, Node* last){
std::vector<Connection*> paths; std::vector<Connection*> paths;
bool last_ok = false; std::vector<Node*> nodes;
for(auto& p : connections){ for(auto& p : connections){
if(((p.v1 == current && p.v1_v2) || (p.v2 == current && p.v2_v1)) && (p.v1 != last || p.v2 != last)) { if(((p.v1 == current && p.v1_v2) || (p.v2 == current && p.v2_v1))) {
p.active = false; p.active = false;
paths.push_back(&p); paths.push_back(&p);
nodes.push_back( p.v1 == current ? p.v2 : p.v1 );
} }
if(((p.v1 == last && p.v2_v1) || (p.v2 == last && p.v1_v2))) last_ok = true; }
if(paths.size() == 2) {
Node* next = nodes[0] == last ? nodes[1] : nodes[0];
if(paths[0]->v1 == next || paths[0]->v2 == next) paths[0]->active = true;
if(paths[1]->v1 == next || paths[1]->v2 == next) paths[1]->active = true;
return next;
} }
if(paths.empty() && last_ok) return last;
if(paths.empty()) return nullptr; if(paths.empty()) return nullptr;
int return_path = 0; int return_path = 0;
+10
View File
@@ -18,6 +18,12 @@ class Connection{
bool remove = false; bool remove = false;
bool config = false; bool config = false;
void flip(){
Node* vt = v1;
v1 = v2;
v2 = vt;
}
void draw(){ void draw(){
Vec2D<float> v1_position = v1->position - ((v1->position - v2->position)).norm() * (v1->radius + 10.0f); Vec2D<float> v1_position = v1->position - ((v1->position - v2->position)).norm() * (v1->radius + 10.0f);
Vec2D<float> v2_position = v2->position - ((v2->position - v1->position)).norm() * (v2->radius + 10.0f); Vec2D<float> v2_position = v2->position - ((v2->position - v1->position)).norm() * (v2->radius + 10.0f);
@@ -30,6 +36,7 @@ class Connection{
Vec2D<float> to_from_handle = v2->position - ((v2->position - v1->position)).norm() * (v2->radius + 35); Vec2D<float> to_from_handle = v2->position - ((v2->position - v1->position)).norm() * (v2->radius + 35);
Vec2D<float> middle_handle = v2->position - ((v2->position - v1->position))*0.5f; Vec2D<float> middle_handle = v2->position - ((v2->position - v1->position))*0.5f;
Vec2D<float> config_handle = v2->position - ((v2->position - v1->position))*0.66f; Vec2D<float> config_handle = v2->position - ((v2->position - v1->position))*0.66f;
Vec2D<float> flip_handle = (v1_position - v2_position).norm().orth()*20.0f;
if(ViButton(from_to_handle.x, from_to_handle.y, 8.0f, v1_v2 ? (Color){232, 125, 62, 255} : (Color){232, 50, 32, 255} )) v1_v2 = !v1_v2; if(ViButton(from_to_handle.x, from_to_handle.y, 8.0f, v1_v2 ? (Color){232, 125, 62, 255} : (Color){232, 50, 32, 255} )) v1_v2 = !v1_v2;
if(ViButton(to_from_handle.x, to_from_handle.y, 8.0f, v2_v1 ? (Color){232, 125, 62, 255} : (Color){232, 50, 32, 255} )) v2_v1 = !v2_v1; if(ViButton(to_from_handle.x, to_from_handle.y, 8.0f, v2_v1 ? (Color){232, 125, 62, 255} : (Color){232, 50, 32, 255} )) v2_v1 = !v2_v1;
@@ -37,5 +44,8 @@ class Connection{
if(ViButton(middle_handle.x, middle_handle.y, 8.0f, (Color){232, 50, 32, 255} )) remove = true; if(ViButton(middle_handle.x, middle_handle.y, 8.0f, (Color){232, 50, 32, 255} )) remove = true;
if(ViButton(config_handle.x, config_handle.y, 8.0f, (Color){158, 134, 200, 255})) config = !config; if(ViButton(config_handle.x, config_handle.y, 8.0f, (Color){158, 134, 200, 255})) config = !config;
if(ViButton(config_handle.x + flip_handle.x, config_handle.y + flip_handle.y, 8.0f, (Color){158, 0, 200, 255})) flip();
} }
}; };
+9
View File
@@ -37,7 +37,16 @@ class Vec2D{
return (x*v.x) + (y*v.y); return (x*v.x) + (y*v.y);
}; };
Vec2D orth(Vec2D &v){
return Vec2D(-v.y, v.x);
};
Vec2D orth(){
return Vec2D(-y, x);
};
Vec2D norm() { return *this / length();}; Vec2D norm() { return *this / length();};
Vec2D& operator=(const Vec2D& vec){ Vec2D& operator=(const Vec2D& vec){
if (this == &vec){ if (this == &vec){
+30 -13
View File
@@ -53,6 +53,7 @@ enum States {IDLE, CONFIG};
struct AppState{ struct AppState{
int width; int width;
int height; int height;
int gui_selected_midi_out;
States state; States state;
} app; } app;
@@ -195,36 +196,52 @@ int main(){
midi.note(s.next->midi_out, 1, 50, 50, 500); midi.note(s.next->midi_out, 1, 50, 50, 500);
s.last = s.next; s.last = s.next;
s.next = n; s.next = n;
//std::cout << s.last << " " << s.next << std::endl;
//midi_out.send_message(libremidi::channel_events::control_change(2, 10, 50));
} }
} }
s.draw(&mouse_pos); s.draw(&mouse_pos);
} }
midi.update();
EndMode2D(); EndMode2D();
GuiWindowBox((Rectangle){0,0,280,600}, "config");
// Main Config Window
if(GuiButton((Rectangle){20, 60, 240, 20}, "button")){ GuiWindowBox((Rectangle){0,0,280,(float)app.height}, "config");
signals.emplace_back(Signal(nodes.front().position.x + 1, nodes.front().position.y + 1, 5.0f, 2.0f)); // position + 1 or else it does not render. why? no idea! {
signals.back().next = &nodes[0]; GuiLabel((Rectangle){20, 60, 240, 20}, "MIDI OUT");
signals.back().last = &nodes[0]; int i = 0;
for(auto& mo : midi.midi_out_ports){
GuiCheckBox((Rectangle){20, 80 + i*20.0f, 20, 20}, mo.port.port_name.c_str(), &mo.enabled);
i++;
}
if(GuiButton((Rectangle){20, 100 + (float)midi.midi_out_ports.size()*20, 240, 20}, "OPEN PORT")) midi.open_midi_out(app.gui_selected_midi_out);
if(GuiButton((Rectangle){20, 60, 240, 20}, "ADD SIGNAL")){
signals.emplace_back(Signal(nodes.front().position.x + 1, nodes.front().position.y + 1, 5.0f, 2.0f)); // position + 1 or else it does not render. why? no idea!
signals.back().next = &nodes[0];
signals.back().last = &nodes[0];
}
} }
for(auto& n : nodes){ for(auto& n : nodes){
if(n.config){ if(n.config){
n.config = !GuiWindowBox((Rectangle){n.position.x + 10, n.position.y + 10,240,300}, "config"); n.config = !GuiWindowBox((Rectangle){n.position.x + 10, n.position.y + 10,240,300}, "config");
int option = n.mode; int option = n.mode;
GuiComboBox((Rectangle){ n.position.x + 20, n.position.y + 40, 220, 20 }, "Round Robin;Random", &option); GuiComboBox((Rectangle){ n.position.x + 20, n.position.y + 40, 220, 20 }, "Round Robin;Random", &option);
n.mode = (Distribution)option; n.mode = (Distribution)option;
std::string toggle_out_ports = "";
int i = 0;
for(auto& mo : midi.midi_out_ports){ for(auto& mo : midi.midi_out_ports){
toggle_out_ports += mo.port_name + "\n"; GuiCheckBox((Rectangle){20, 80 + i*20.0f, 20, 20}, mo.port.port_name.c_str(), &mo.enabled);
i++;
}
std::string toggle_out_ports = "";
for(auto& mo : midi.midi_outs){
toggle_out_ports += midi.midi_out_ports[mo.first].port.port_name + "\n";
} }
toggle_out_ports = toggle_out_ports.substr(0, toggle_out_ports.size()-2); toggle_out_ports = toggle_out_ports.substr(0, toggle_out_ports.size()-2);
GuiLabel((Rectangle){n.position.x + 20, n.position.y + 60, 220, 20}, "MIDI OUT"); GuiLabel((Rectangle){n.position.x + 20, n.position.y + 60, 220, 20}, "MIDI OUT");
GuiToggleGroup((Rectangle){n.position.x + 20, n.position.y + 80, 220, 20}, toggle_out_ports.c_str(), &n.midi_out); GuiToggleGroup((Rectangle){n.position.x + 20, n.position.y + 80, 220, 20}, toggle_out_ports.c_str(), &n.midi_out);
if(GuiButton((Rectangle){n.position.x + 20, n.position.y + 100 + midi.midi_out_ports.size()*20, 220, 20}, "OPEN PORT")) midi.open_midi_out(n.midi_out);
} }
} }
+40 -24
View File
@@ -6,6 +6,7 @@
#include "raylib.h" #include "raylib.h"
#include <iostream> #include <iostream>
#include <map>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
@@ -15,55 +16,70 @@ struct NoteTimer{
int channel; int channel;
int note; int note;
int velocity; int velocity;
int start; float start;
int length; int gate;
bool erase = false;
}; };
struct MidiOutPort{
libremidi::output_port port;
int number;
bool enabled;
};
struct MidiOut{
libremidi::midi_out out;
};
class Midi { class Midi {
public: public:
Midi() { Midi() {
int i = 0;
for(const libremidi::input_port& port : obs.get_input_ports()){
midi_in_ports.push_back(port);
}
for(const libremidi::output_port& port : obs.get_output_ports()){ for(const libremidi::output_port& port : obs.get_output_ports()){
midi_out_ports.push_back(port); midi_out_ports.push_back({port, i, false});
i++;
} }
std::cout << midi_out_ports.size() << std::endl;
} }
libremidi::observer obs; libremidi::observer obs;
std::vector<std::shared_ptr<libremidi::midi_out>> midi_outs; std::map<int, std::shared_ptr<libremidi::midi_out>> midi_outs;
std::vector<libremidi::input_port> midi_in_ports; std::vector<libremidi::input_port> midi_in_ports;
std::vector<libremidi::output_port> midi_out_ports; std::vector<MidiOutPort> midi_out_ports;
std::vector<NoteTimer> notes; std::vector<NoteTimer> notes;
float timer; float timer;
void open_midi_out(int midi_n){ void open_midi_out(MidiOutPort *out_port){
std::cout << midi_n << std::endl; if(!midi_outs.contains(out_port->number)){
auto out = std::make_shared<libremidi::midi_out>();
auto out = std::make_shared<libremidi::midi_out>(); out->open_port(out_port->port);
out->open_port(midi_out_ports[midi_n]); midi_outs[out_port->number] = out;
midi_outs.push_back(out); }
} }
void note(int midi_out, int channel, int note, int velocity, int length){ void note(int midi_out, int channel, int note, int velocity, int gate){
midi_outs[midi_out]->send_message(libremidi::channel_events::note_on(channel, note, velocity)); if(!midi_outs.empty()){
notes.emplace_back(midi_out, channel, note, velocity, GetTime(), length); midi_outs[midi_out]->send_message(libremidi::channel_events::note_on(channel, note, velocity));
notes.emplace_back(midi_out, channel, note, velocity, GetTime(), gate);
}
} }
void update(){ void update(){
float time = GetTime(); float time = GetTime();
for( auto it = notes.begin(); it != notes.end(); ++it){ for(auto it = notes.begin(); it != notes.end(); ++it){
if(time - it->start > ((float)it->length / 1000.0f)){ if(time - it->start >= (float)it->gate / 1000.0f){
midi_outs[it->midi_out]->send_message(libremidi::channel_events::note_off(it->channel, it->note, it->velocity)); midi_outs[it->midi_out]->send_message(libremidi::channel_events::note_off(it->channel, it->note, it->velocity));
notes.erase(it); it->erase = true;
}
}
std::erase_if(notes, [](const auto& item){return item.erase;});
for(auto& p : midi_out_ports){
if(p.enabled) {
open_midi_out(&p);
} }
} }
} }
+4 -1
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <raylib.h> #include <raylib.h>
#include <vector>
#include "datatypes.h" #include "datatypes.h"
#include "moveable.h" #include "moveable.h"
@@ -21,7 +22,9 @@ class Node : public Movable{
bool connecting = false; bool connecting = false;
bool config = false; bool config = false;
int midi_out = 0; int midi_out = -1;
std::vector<int> midi_outs;
int midi_note = 0; int midi_note = 0;
int midi_cc = 0; int midi_cc = 0;