From e32591388a18c8226e61b8f88b031ed7c88ca153 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Mon, 10 Jan 2011 20:20:10 +0100 Subject: Improved in-synth-cli, still TODO The CLI can now prepare loading a note without actually loading it --- synth/Makefile | 2 +- synth/channel.cpp | 157 +++++++++++++++++++++++++++--------------------- synth/channel.h | 1 + synth/communication.cpp | 16 +++++ synth/communication.h | 22 +++++++ synth/globals.cpp | 1 + synth/globals.h | 1 + synth/in_synth_cli.cpp | 55 +++++++++++++++-- synth/jack.cpp | 35 ++++++++++- synth/main.cpp | 9 ++- 10 files changed, 221 insertions(+), 78 deletions(-) create mode 100644 synth/communication.cpp create mode 100644 synth/communication.h diff --git a/synth/Makefile b/synth/Makefile index 5a308e3..2f16297 100644 --- a/synth/Makefile +++ b/synth/Makefile @@ -3,7 +3,7 @@ CFLAGS=-Wall -g CXXFLAGS=$(CFLAGS) LDFLAGS=-lm `pkg-config --cflags --libs jack` -OBJ=channel.o cli.o defines.o envelope.o filter.o globals.o jack.o load.o main.o note.o note_skel.o parser.o programs.o readwave.o util.o note_loader.o in_synth_cli.o +OBJ=channel.o cli.o defines.o envelope.o filter.o globals.o jack.o load.o main.o note.o note_skel.o parser.o programs.o readwave.o util.o note_loader.o in_synth_cli.o communication.o BIN=synth DEPENDFILE = .depend diff --git a/synth/channel.cpp b/synth/channel.cpp index fe28e7d..dbfcc48 100644 --- a/synth/channel.cpp +++ b/synth/channel.cpp @@ -100,82 +100,86 @@ void Channel::note_on(int note, int vel) { pressed_keys.insert(note); - if ( (n_voices==1) && (!notes.empty()) ) //we're in monomode - { - //no need to create a new note; reuse the existing - NoteSkel *n; //i'm lazy - n= *(notes.begin()); - - if (n->get_program() != program) + if (program_lock[program]==false) + { + if ( (n_voices==1) && (!notes.empty()) ) //we're in monomode { - //if the program has changed, kill the previous note and - //create a new one - n->destroy(); - notes.clear(); + //no need to create a new note; reuse the existing + NoteSkel *n; //i'm lazy + n= *(notes.begin()); - NoteSkel *newnote=NULL; - if (curr_prg.create_func==NULL) - newnote = new Note(note,(float)vel/128.0, - curr_prg, - portamento_frames, pitchbend, - program, - curr_vol_factor); - else - newnote = curr_prg.create_func(note,(float)vel/128.0, - curr_prg, - portamento_frames, pitchbend, - program, - curr_vol_factor); - - notes.push_back(newnote); - } - else //program did not change - { - //if not still active, don't do portamento - n->set_note(note,n->still_active()); - n->set_vel((float)vel/128.0); - if ((legato_pedal_pressed==false) || !n->still_active()) n->reattack(); - n->set_vol_factor(curr_vol_factor); - //no need to push back. would become #1 instead of #1 + if (n->get_program() != program) + { + //if the program has changed, kill the previous note and + //create a new one + n->destroy(); + notes.clear(); + + NoteSkel *newnote=NULL; + if (curr_prg.create_func==NULL) + newnote = new Note(note,(float)vel/128.0, + curr_prg, + portamento_frames, pitchbend, + program, + curr_vol_factor); + else + newnote = curr_prg.create_func(note,(float)vel/128.0, + curr_prg, + portamento_frames, pitchbend, + program, + curr_vol_factor); + + notes.push_back(newnote); + } + else //program did not change + { + //if not still active, don't do portamento + n->set_note(note,n->still_active()); + n->set_vel((float)vel/128.0); + if ((legato_pedal_pressed==false) || !n->still_active()) n->reattack(); + n->set_vol_factor(curr_vol_factor); + //no need to push back. would become #1 instead of #1 + } } - } - else //we're in polymode - { - bool neednewnote=true; - //if (always_reattack) always_reattack is always true when in polymode - for (it=notes.begin(); it!=notes.end(); it++) - if ( ((*it)->get_note()==note) && ((*it)->get_program()==program) ) - { - neednewnote=false; - (*it)->reattack(); - (*it)->set_vel((float)vel/128.0); - (*it)->set_vol_factor(curr_vol_factor); - notes.push_back(*it); //reorder notes - notes.erase(it); - break; - } - - if (neednewnote) + else //we're in polymode { - NoteSkel *newnote=NULL; - if (curr_prg.create_func==NULL) - newnote = new Note(note,(float)vel/128.0, - curr_prg, - portamento_frames, pitchbend, - program, - curr_vol_factor); - else - newnote = curr_prg.create_func(note,(float)vel/128.0, - curr_prg, - portamento_frames, pitchbend, - program, - curr_vol_factor); - - notes.push_back(newnote); - } + bool neednewnote=true; + //if (always_reattack) always_reattack is always true when in polymode + for (it=notes.begin(); it!=notes.end(); it++) + if ( ((*it)->get_note()==note) && ((*it)->get_program()==program) ) + { + neednewnote=false; + (*it)->reattack(); + (*it)->set_vel((float)vel/128.0); + (*it)->set_vol_factor(curr_vol_factor); + notes.push_back(*it); //reorder notes + notes.erase(it); + break; + } + + if (neednewnote) + { + NoteSkel *newnote=NULL; + if (curr_prg.create_func==NULL) + newnote = new Note(note,(float)vel/128.0, + curr_prg, + portamento_frames, pitchbend, + program, + curr_vol_factor); + else + newnote = curr_prg.create_func(note,(float)vel/128.0, + curr_prg, + portamento_frames, pitchbend, + program, + curr_vol_factor); + + notes.push_back(newnote); + } - apply_voice_limit(); + apply_voice_limit(); + } } + // else (if the program is locked) simply ignore the note-on } else //note off { @@ -418,6 +422,19 @@ void Channel::panic() } } +void Channel::kill_program(int prog) +{ + list::iterator it; + for (it=notes.begin(); it!=notes.end();) + if ((*it)->get_program()==prog) + { + (*it)->destroy(); + it=notes.erase(it); + } + else + it++; +} + void Channel::release_all() { list::iterator it; diff --git a/synth/channel.h b/synth/channel.h index 9727ab8..c0eee5c 100644 --- a/synth/channel.h +++ b/synth/channel.h @@ -28,6 +28,7 @@ class Channel void cleanup(); void release_all(); void panic(); + void kill_program(int prog); void set_real_portamento_frames(); void set_portamento_time(int val); void set_portamento(int val); diff --git a/synth/communication.cpp b/synth/communication.cpp new file mode 100644 index 0000000..f21e46f --- /dev/null +++ b/synth/communication.cpp @@ -0,0 +1,16 @@ +#include "communication.h" + +pthread_mutex_t suspend_request_mutex; +suspend_request_t suspend_request; + +void init_communication() +{ + pthread_mutex_init(&suspend_request_mutex, NULL); + + suspend_request.done=true; +} + +void uninit_communication() +{ + pthread_mutex_destroy(&suspend_request_mutex); +} diff --git a/synth/communication.h b/synth/communication.h new file mode 100644 index 0000000..27f7186 --- /dev/null +++ b/synth/communication.h @@ -0,0 +1,22 @@ +#ifndef __COMMUNICATION_H__ +#define __COMMUNICATION_H__ + +#include + +struct suspend_request_t +{ + int prog; //if negative, all programs are affected + bool suspend; //true->suspend, false->use them again + bool done; //must be set to false by the requester, + //must be set to true after processing by the requestee +}; + + +extern pthread_mutex_t suspend_request_mutex; +extern suspend_request_t suspend_request; + + + +void init_communication(); +void uninit_communication(); +#endif diff --git a/synth/globals.cpp b/synth/globals.cpp index 6a84353..427eebe 100644 --- a/synth/globals.cpp +++ b/synth/globals.cpp @@ -54,6 +54,7 @@ string programfile[128]; program_t *program_settings; +bool program_lock[128]; Channel *channel[N_CHANNELS]; diff --git a/synth/globals.h b/synth/globals.h index ffc1de5..b91efef 100644 --- a/synth/globals.h +++ b/synth/globals.h @@ -65,6 +65,7 @@ extern string programfile[128]; extern program_t *program_settings; +extern bool program_lock[128]; extern Channel *channel[N_CHANNELS]; diff --git a/synth/in_synth_cli.cpp b/synth/in_synth_cli.cpp index 7aa1d8e..4334978 100644 --- a/synth/in_synth_cli.cpp +++ b/synth/in_synth_cli.cpp @@ -1,9 +1,13 @@ #include #include #include +#include +#include #include "in_synth_cli.h" #include "util.h" +#include "communication.h" +#include "globals.h" using namespace std; @@ -14,16 +18,53 @@ void signal_handler(int sig) cout << endl << PROMPT << flush; } +void do_request(int prg_no, bool susp) +{ + pthread_mutex_lock(&suspend_request_mutex); + + suspend_request.prog=prg_no; + suspend_request.suspend=susp; + suspend_request.done=false; + + pthread_mutex_unlock(&suspend_request_mutex); + + + + while (true) + { + usleep(100000); + + pthread_mutex_lock(&suspend_request_mutex); + if (suspend_request.done) + { + pthread_mutex_unlock(&suspend_request_mutex); + break; + } + else + pthread_mutex_unlock(&suspend_request_mutex); + } +} + +void lock_and_load_program(int prg_no, string file) +{ + do_request(prg_no, true); + + //TODO load the program + usleep(5000000); + + do_request(prg_no, false); +} + void do_in_synth_cli() { string input; string command; string params; + int num; if (signal(2,signal_handler)==SIG_ERR) - { - cout << "WARNING: failed to set signal handler!" << endl; - } + output_warning("WARNING: failed to set signal handler in the in-synth-cli. pressing enter will\n" + " kill the synth, so be careful. this is not fatal"); while (true) @@ -43,7 +84,8 @@ void do_in_synth_cli() cout << "error: expected program-number, found '"<kill_program(prog); +} + +void process_request() +{ + if (suspend_request.prog==-1) + for (int i=0;i<128;i++) + manage_program_lock(i,suspend_request.suspend); + else + manage_program_lock(suspend_request.prog,suspend_request.suspend); + + suspend_request.done=true; +} + + + void maybe_calc_stuff() //TODO woandershinschieben? lfo.cpp oder so? { static int lfocnt=0; @@ -263,6 +286,17 @@ int process_callback(jack_nframes_t nframes, void *notused) return 0; } + + + pthread_mutex_lock(&suspend_request_mutex); + if (suspend_request.done==false) + process_request(); + pthread_mutex_unlock(&suspend_request_mutex); + + + + + for (i=0;i