2026-01-05 02:56:30 +01:00
# include "signal-manager.h"
# include "datatypes.h"
# include "midi-node.h"
# include "node.h"
# include "signal.h"
# include "midi.h"
# include <chrono>
# include <memory>
# include <thread>
2026-01-12 00:16:36 +01:00
namespace VISEQ : : SIGNAL {
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
void SignalManager : : pause ( ) {
play = false ;
}
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
void SignalManager : : stop ( ) {
play = false ;
reset ( ) ;
}
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
void SignalManager : : start ( ) {
play = true ;
}
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
void SignalManager : : reset ( ) {
for ( auto & s : signals ) {
s - > position = s - > start . lock ( ) - > position + Vec2Df { 0.1 , 0.1 } ;
s - > next = s - > start ;
s - > last = s - > start ;
}
gm - > reset ( ) ;
2026-01-05 02:56:30 +01:00
}
2026-01-12 00:16:36 +01:00
void SignalManager : : startSignalThread ( ) {
std : : thread t1 ( & SignalManager : : updateSignals , this ) ;
t1 . detach ( ) ;
}
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
void SignalManager : : stopSignalThread ( ) {
loop = false ;
}
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
void SignalManager : : addSignalAtNode ( WPTR_Node node ) {
Color c = { ( unsigned char ) ( 20 + ( rand ( ) % 200 ) ) , 100 , ( unsigned char ) ( 20 + ( int ) ( rand ( ) % 200 ) ) , 200 } ;
signals . emplace_back ( std : : make_shared < Signal > ( node . lock ( ) - > position + Vec2Df { 0.5f , 0.5f } , 8.0f , 480 , c ) ) ; // position + 1 or else it does not render. why? no idea!
signals . back ( ) - > next = node ;
signals . back ( ) - > last = node ;
signals . back ( ) - > start = node ;
}
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
void SignalManager : : rerouteSignal ( VEC_SPTR_Node nodes , VEC_WPTR_Node adjacent_nodes ) {
auto reroute_signals = signals | RANGE_FILTER ( [ nodes ] ( SIGNAL : : SPTR_Signal s ) { return std : : ranges : : contains ( nodes , s - > next . lock ( ) ) ; } ) ;
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
for ( auto s : reroute_signals ) {
float dist = 10000000 ;
SPTR_Node next_node ;
for ( auto n : adjacent_nodes ) {
if ( n . lock ( ) - > position . dist ( s - > position ) < dist ) {
dist = n . lock ( ) - > position . dist ( s - > position ) ;
next_node = n . lock ( ) ;
}
2026-01-05 02:56:30 +01:00
}
2026-01-12 00:16:36 +01:00
s - > next = next_node ;
s - > last = next_node ;
2026-01-05 02:56:30 +01:00
}
2026-01-12 00:16:36 +01:00
}
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
void SignalManager : : rebaseSignal ( VEC_SPTR_Node nodes ) {
auto rebase_signals = signals | RANGE_FILTER ( [ nodes ] ( SIGNAL : : SPTR_Signal s ) { return std : : ranges : : contains ( nodes , s - > start . lock ( ) ) ; } ) ;
for ( auto s : rebase_signals ) {
s - > start = s - > next ;
}
2026-01-05 02:56:30 +01:00
}
2026-01-12 00:16:36 +01:00
void SignalManager : : removeSignal ( std : : shared_ptr < Signal > s ) {
erase_signals . push_back ( s ) ;
}
2026-01-05 02:56:30 +01:00
2026-01-12 00:16:36 +01:00
void SignalManager : : updateSignals ( ) {
auto last = std : : chrono : : high_resolution_clock : : now ( ) ;
while ( loop ) {
std : : chrono : : duration < double , std : : micro > diff = std : : chrono : : high_resolution_clock : : now ( ) - last ;
if ( ( int ) diff . count ( ) > = 250 ) {
mutex - > lock ( ) ;
if ( play ) {
for ( auto & s : signals ) {
s - > direction = ( s - > next . lock ( ) - > position - s - > position ) . norm ( ) ;
s - > update ( diff . count ( ) ) ;
if ( s - > position . dist ( s - > next . lock ( ) - > position ) < 0.6f ) {
WPTR_Node next_node = gm - > next ( s - > next , s - > last ) ;
s - > next . lock ( ) - > trigger ( ) ;
if ( next_node . lock ( ) ! = s - > next . lock ( ) & & ! next_node . expired ( ) & & s - > next . lock ( ) - > getNodeType ( ) = = NodeType : : MIDINODE ) {
auto midinode = std : : dynamic_pointer_cast < MidiNode > ( s - > next . lock ( ) ) ;
for ( auto & m : midinode - > midi_outs ) {
if ( m . second . enabled ) {
if ( midinode - > send_note ) midi . note ( m . second . i , midinode - > getNotes ( ) . channel , ( int ) Clamp ( midinode - > getNotes ( ) . note + s - > midi_note_offset , 0 , 127 ) , midinode - > getNotes ( ) . velocity , midinode - > getNotes ( ) . gate ) ;
if ( midinode - > send_cc ) midi . cc ( m . second . i , midinode - > getCC ( ) . channel , midinode - > getCC ( ) . control , ( int ) Clamp ( midinode - > getCC ( ) . value + s - > midi_cc_offset , 0 , 127 ) ) ;
if ( midinode - > send_pitch_bend ) midi . pitch_bend ( m . second . i , midinode - > getPitchBend ( ) . channel , midinode - > getPitchBend ( ) . value ) ;
}
2026-01-05 02:56:30 +01:00
}
2026-01-12 00:16:36 +01:00
s - > last = s - > next ;
s - > next = next_node ;
2026-01-05 02:56:30 +01:00
}
}
}
}
2026-01-12 00:16:36 +01:00
midi . update ( ) ;
mutex - > unlock ( ) ;
last = std : : chrono : : high_resolution_clock : : now ( ) ;
2026-01-05 02:56:30 +01:00
}
}
}
2026-01-12 00:16:36 +01:00
void SignalManager : : drawSignals ( Vec2Df mouse_pos , Camera2D camera ) {
mutex - > lock ( ) ;
if ( ! erase_signals . empty ( ) ) {
for ( auto s : erase_signals ) {
std : : erase ( signals , s ) ;
}
erase_signals . clear ( ) ;
}
for ( auto s : signals ) {
s - > draw ( mouse_pos , camera ) ;
2026-01-05 02:56:30 +01:00
}
2026-01-12 00:16:36 +01:00
mutex - > unlock ( ) ;
2026-01-05 02:56:30 +01:00
}
2026-01-12 00:16:36 +01:00
void to_json ( json & j , const std : : shared_ptr < SignalManager > & G ) {
j = * G ;
}
void from_json ( const json & j , std : : shared_ptr < SignalManager > & G ) {
G . reset ( new SignalManager ( j . get < SignalManager > ( ) ) ) ;
2026-01-05 02:56:30 +01:00
}
}