in between working states, switchting to multi midi out per node
This commit is contained in:
@@ -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
|
||||
CXXINC = -I/usr/lib/gcc/x86_64-pc-linux-gnu/13.3.0/include -Iinclude
|
||||
|
||||
|
||||
@@ -16,17 +16,23 @@ class ConnectionManager{
|
||||
|
||||
Node* next(Node* current, Node* last){
|
||||
std::vector<Connection*> paths;
|
||||
bool last_ok = false;
|
||||
std::vector<Node*> nodes;
|
||||
|
||||
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;
|
||||
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.empty() && last_ok) return last;
|
||||
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()) return nullptr;
|
||||
|
||||
int return_path = 0;
|
||||
|
||||
@@ -18,6 +18,12 @@ class Connection{
|
||||
bool remove = false;
|
||||
bool config = false;
|
||||
|
||||
void flip(){
|
||||
Node* vt = v1;
|
||||
v1 = v2;
|
||||
v2 = vt;
|
||||
}
|
||||
|
||||
void draw(){
|
||||
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);
|
||||
@@ -30,6 +36,7 @@ class Connection{
|
||||
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> 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(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(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();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,8 +37,17 @@ class Vec2D{
|
||||
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& operator=(const Vec2D& vec){
|
||||
if (this == &vec){
|
||||
return *this;
|
||||
|
||||
+25
-8
@@ -53,6 +53,7 @@ enum States {IDLE, CONFIG};
|
||||
struct AppState{
|
||||
int width;
|
||||
int height;
|
||||
int gui_selected_midi_out;
|
||||
States state;
|
||||
} app;
|
||||
|
||||
@@ -195,21 +196,30 @@ int main(){
|
||||
midi.note(s.next->midi_out, 1, 50, 50, 500);
|
||||
s.last = s.next;
|
||||
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);
|
||||
}
|
||||
|
||||
midi.update();
|
||||
EndMode2D();
|
||||
GuiWindowBox((Rectangle){0,0,280,600}, "config");
|
||||
|
||||
if(GuiButton((Rectangle){20, 60, 240, 20}, "button")){
|
||||
// Main Config Window
|
||||
GuiWindowBox((Rectangle){0,0,280,(float)app.height}, "config");
|
||||
{
|
||||
GuiLabel((Rectangle){20, 60, 240, 20}, "MIDI OUT");
|
||||
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){
|
||||
if(n.config){
|
||||
@@ -217,14 +227,21 @@ int main(){
|
||||
int option = n.mode;
|
||||
GuiComboBox((Rectangle){ n.position.x + 20, n.position.y + 40, 220, 20 }, "Round Robin;Random", &option);
|
||||
n.mode = (Distribution)option;
|
||||
std::string toggle_out_ports = "";
|
||||
|
||||
int i = 0;
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+36
-20
@@ -6,6 +6,7 @@
|
||||
#include "raylib.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
|
||||
@@ -15,55 +16,70 @@ struct NoteTimer{
|
||||
int channel;
|
||||
int note;
|
||||
int velocity;
|
||||
int start;
|
||||
int length;
|
||||
float start;
|
||||
int gate;
|
||||
bool erase = false;
|
||||
};
|
||||
|
||||
struct MidiOutPort{
|
||||
libremidi::output_port port;
|
||||
int number;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
struct MidiOut{
|
||||
libremidi::midi_out out;
|
||||
|
||||
};
|
||||
|
||||
class Midi {
|
||||
|
||||
public:
|
||||
Midi() {
|
||||
|
||||
for(const libremidi::input_port& port : obs.get_input_ports()){
|
||||
midi_in_ports.push_back(port);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
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;
|
||||
|
||||
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::output_port> midi_out_ports;
|
||||
std::vector<MidiOutPort> midi_out_ports;
|
||||
|
||||
std::vector<NoteTimer> notes;
|
||||
|
||||
float timer;
|
||||
|
||||
void open_midi_out(int midi_n){
|
||||
std::cout << midi_n << std::endl;
|
||||
|
||||
void open_midi_out(MidiOutPort *out_port){
|
||||
if(!midi_outs.contains(out_port->number)){
|
||||
auto out = std::make_shared<libremidi::midi_out>();
|
||||
out->open_port(midi_out_ports[midi_n]);
|
||||
midi_outs.push_back(out);
|
||||
out->open_port(out_port->port);
|
||||
midi_outs[out_port->number] = 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){
|
||||
if(!midi_outs.empty()){
|
||||
midi_outs[midi_out]->send_message(libremidi::channel_events::note_on(channel, note, velocity));
|
||||
notes.emplace_back(midi_out, channel, note, velocity, GetTime(), length);
|
||||
notes.emplace_back(midi_out, channel, note, velocity, GetTime(), gate);
|
||||
}
|
||||
}
|
||||
|
||||
void update(){
|
||||
float time = GetTime();
|
||||
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));
|
||||
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
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <raylib.h>
|
||||
#include <vector>
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "moveable.h"
|
||||
@@ -21,7 +22,9 @@ class Node : public Movable{
|
||||
bool connecting = false;
|
||||
bool config = false;
|
||||
|
||||
int midi_out = 0;
|
||||
int midi_out = -1;
|
||||
|
||||
std::vector<int> midi_outs;
|
||||
|
||||
int midi_note = 0;
|
||||
int midi_cc = 0;
|
||||
|
||||
Reference in New Issue
Block a user