2024-10-22 01:55:31 +02:00
# pragma once
# include "datatypes.h"
2024-10-30 14:55:24 +01:00
# include "graph-manager.h"
2024-11-01 02:38:47 +01:00
# include "midi-node.h"
2024-11-21 02:03:32 +01:00
# include "node.h"
2024-10-22 01:55:31 +02:00
# include "signal.h"
# include "midi.h"
# include <chrono>
2024-11-01 02:38:47 +01:00
# include <memory>
2024-10-22 01:55:31 +02:00
# include <thread>
2024-11-03 03:48:49 +01:00
using namespace VISEQ : : GRAPH ;
2024-10-22 01:55:31 +02:00
2024-11-03 03:48:49 +01:00
namespace VISEQ : : SIGNAL {
typedef std : : shared_ptr < Signal > SPTR_Signal ;
typedef std : : vector < SPTR_Signal > VEC_SPTR_Signal ;
2024-11-30 02:54:40 +01:00
class SignalManager : public std : : enable_shared_from_this < SignalManager > {
2024-11-03 03:48:49 +01:00
public :
SignalManager ( ) { }
2024-12-04 01:43:06 +01:00
SignalManager ( std : : shared_ptr < GraphManager > gm , std : : mutex * mutex ) : mutex ( mutex ) , gm ( gm ) { }
2024-11-03 03:48:49 +01:00
2024-11-30 02:54:40 +01:00
std : : shared_ptr < SignalManager > getPtr ( ) {
return shared_from_this ( ) ;
}
2024-11-03 03:48:49 +01:00
VISEQ : : MIDI : : Midi midi ;
std : : mutex * mutex ;
2024-12-04 01:43:06 +01:00
std : : shared_ptr < GraphManager > gm ;
2024-11-03 03:48:49 +01:00
VEC_SPTR_Signal signals ;
2024-10-22 01:55:31 +02:00
2024-11-04 01:00:59 +01:00
VEC_SPTR_Signal erase_signals ;
2024-11-03 03:48:49 +01:00
bool loop = true ;
bool play = false ;
2024-10-22 01:55:31 +02:00
2024-11-03 03:48:49 +01:00
void pause ( ) {
play = false ;
}
2024-11-01 02:38:47 +01:00
2024-11-03 03:48:49 +01:00
void stop ( ) {
play = false ;
reset ( ) ;
}
2024-10-25 02:43:41 +02:00
2024-11-03 03:48:49 +01:00
void start ( ) {
play = true ;
}
void reset ( ) {
for ( auto & s : signals ) {
2024-12-03 01:25:49 +01:00
s - > position = s - > start . lock ( ) - > position + Vec2Df { 0.1 , 0.1 } ;
2024-11-03 03:48:49 +01:00
s - > next = s - > start ;
s - > last = s - > start ;
}
gm - > reset ( ) ;
}
2024-10-25 02:43:41 +02:00
2024-11-03 03:48:49 +01:00
void startSignalThread ( ) {
std : : thread t1 ( & SignalManager : : updateSignals , this ) ;
t1 . detach ( ) ;
}
void stopSignalThread ( ) {
loop = false ;
}
2024-10-25 02:43:41 +02:00
2024-12-03 01:25:49 +01:00
void addSignalAtNode ( WPTR_Node node ) {
2024-11-03 03:48:49 +01:00
Color c = { ( unsigned char ) ( 20 + ( rand ( ) % 200 ) ) , 100 , ( unsigned char ) ( 20 + ( int ) ( rand ( ) % 200 ) ) , 200 } ;
2024-12-03 01:25:49 +01:00
signals . emplace_back ( std : : make_shared < Signal > ( node . lock ( ) - > position + Vec2Df { 0.5f , 0.5f } , 8.0f , 0 , c ) ) ; // position + 1 or else it does not render. why? no idea!
2024-11-03 03:48:49 +01:00
signals . back ( ) - > next = node ;
signals . back ( ) - > last = node ;
signals . back ( ) - > start = node ;
2024-10-25 02:43:41 +02:00
}
2024-11-03 03:48:49 +01:00
2024-12-04 01:43:06 +01:00
void rerouteSignal ( VEC_SPTR_Node nodes , VEC_WPTR_Node adjacent_nodes ) {
2024-12-03 01:25:49 +01:00
auto reroute_signals = signals | RANGE_FILTER ( [ nodes ] ( SIGNAL : : SPTR_Signal s ) { return std : : ranges : : contains ( nodes , s - > next . lock ( ) ) ; } ) ;
2024-11-21 02:03:32 +01:00
for ( auto s : reroute_signals ) {
float dist = 10000000 ;
SPTR_Node next_node ;
for ( auto n : adjacent_nodes ) {
2024-12-04 01:43:06 +01:00
if ( n . lock ( ) - > position . dist ( s - > position ) < dist ) {
dist = n . lock ( ) - > position . dist ( s - > position ) ;
next_node = n . lock ( ) ;
2024-11-21 02:03:32 +01:00
}
}
s - > next = next_node ;
s - > last = next_node ;
}
}
void rebaseSignal ( VEC_SPTR_Node nodes ) {
2024-12-03 01:25:49 +01:00
auto rebase_signals = signals | RANGE_FILTER ( [ nodes ] ( SIGNAL : : SPTR_Signal s ) { return std : : ranges : : contains ( nodes , s - > start . lock ( ) ) ; } ) ;
2024-11-21 02:03:32 +01:00
for ( auto s : rebase_signals ) {
s - > start = s - > next ;
}
}
2024-11-04 01:00:59 +01:00
void removeSignal ( std : : shared_ptr < Signal > s ) {
erase_signals . push_back ( s ) ;
2024-11-03 03:48:49 +01:00
}
void 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 ) {
2024-12-03 01:25:49 +01:00
s - > direction = ( s - > next . lock ( ) - > position - s - > position ) . norm ( ) ;
2024-11-03 03:48:49 +01:00
s - > update ( diff . count ( ) ) ;
2024-12-03 01:25:49 +01:00
if ( s - > position . dist ( s - > next . lock ( ) - > position ) < 0.6f ) {
WPTR_Node next_node = gm - > next ( s - > next , s - > last ) ;
s - > next . lock ( ) - > trigger ( ) ;
2024-11-03 03:48:49 +01:00
2024-12-03 01:25:49 +01:00
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 ( ) ) ;
2024-11-03 03:48:49 +01:00
for ( auto & m : midinode - > midi_outs ) {
if ( m . second . enabled ) {
2024-11-04 01:00:59 +01:00
if ( midinode - > send_note ) midi . note ( m . second . i , midinode - > midi_note_channel , ( int ) Clamp ( midinode - > midi_note + s - > midi_note_offset , 0 , 127 ) , midinode - > midi_velocity , midinode - > midi_gate ) ;
if ( midinode - > send_cc ) midi . cc ( m . second . i , midinode - > midi_cc_channel , midinode - > midi_cc , ( int ) Clamp ( midinode - > midi_cc_value + s - > midi_cc_offset , 0 , 127 ) ) ;
2024-11-03 03:48:49 +01:00
if ( midinode - > send_pitch_bend ) midi . pitch_bend ( m . second . i , midinode - > midi_pitch_bend_channel , midinode - > midi_pitch_bend ) ;
}
2024-10-28 02:07:47 +01:00
}
2024-11-03 03:48:49 +01:00
s - > last = s - > next ;
s - > next = next_node ;
2024-10-25 02:43:41 +02:00
}
2024-10-22 01:55:31 +02:00
}
}
}
2024-11-03 03:48:49 +01:00
midi . update ( ) ;
mutex - > unlock ( ) ;
last = std : : chrono : : high_resolution_clock : : now ( ) ;
2024-10-22 01:55:31 +02:00
}
}
}
2024-11-03 03:48:49 +01:00
void drawSignals ( Vec2Df mouse_pos , Camera2D camera ) {
2024-11-04 01:00:59 +01:00
mutex - > lock ( ) ;
if ( ! erase_signals . empty ( ) ) {
for ( auto s : erase_signals ) {
std : : erase ( signals , s ) ;
}
erase_signals . clear ( ) ;
}
2024-11-03 03:48:49 +01:00
for ( auto s : signals ) {
s - > draw ( mouse_pos , camera ) ;
}
2024-11-04 01:00:59 +01:00
mutex - > unlock ( ) ;
2024-10-22 01:55:31 +02:00
}
2024-12-04 01:43:06 +01:00
NLOHMANN_DEFINE_TYPE_INTRUSIVE ( SignalManager , signals )
2024-11-07 00:56:33 +01:00
2024-11-03 03:48:49 +01:00
} ;
}