summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <flo@thinkpad.(none)>2011-01-10 20:20:10 +0100
committerFlorian Jung <flo@thinkpad.(none)>2011-01-10 20:20:10 +0100
commite32591388a18c8226e61b8f88b031ed7c88ca153 (patch)
tree999f6653d0cfac3153679a8352c28f4e92805306
parentb34cab5dd6d4ac16a6a58589397a3d82df38b826 (diff)
Improved in-synth-cli, still TODO
The CLI can now prepare loading a note without actually loading it
-rw-r--r--synth/Makefile2
-rw-r--r--synth/channel.cpp157
-rw-r--r--synth/channel.h1
-rw-r--r--synth/communication.cpp16
-rw-r--r--synth/communication.h22
-rw-r--r--synth/globals.cpp1
-rw-r--r--synth/globals.h1
-rw-r--r--synth/in_synth_cli.cpp55
-rw-r--r--synth/jack.cpp35
-rw-r--r--synth/main.cpp9
10 files changed, 221 insertions, 78 deletions
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<NoteSkel*>::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<NoteSkel*>::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 <pthread.h>
+
+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 <iostream>
#include <string>
#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
#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 '"<<params<<"'"<<endl;
else
{
- //TODO: load program
+ num=atoi(params.c_str());
+ lock_and_load_program(num, programfile[num]);
}
}
else if (command=="load")
@@ -58,7 +100,10 @@ void do_in_synth_cli()
cout << "error: expected program-file to load, found nothing"<<endl;
else
{
- //TODO: load program
+ num=atoi(params.c_str());
+ lock_and_load_program(num, file);
+
+ programfile[num]=file;
}
}
else if (command!="")
diff --git a/synth/jack.cpp b/synth/jack.cpp
index 0c98855..fbf1ea0 100644
--- a/synth/jack.cpp
+++ b/synth/jack.cpp
@@ -9,6 +9,7 @@
#include "globals.h"
#include "jack.h"
+#include "communication.h"
using namespace std;
@@ -23,6 +24,28 @@ jack_port_t *out_port2[N_CHANNELS];
jack_client_t *jack_client = NULL;
+void manage_program_lock(int prog, bool lock) //TODO woandershinschieben?
+{
+ program_lock[prog]=lock;
+
+ if (lock)
+ for (int i=0;i<N_CHANNELS;i++)
+ channel[i]->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<N_CHANNELS;i++)
{
outbuf[i]=(jack_default_audio_sample_t*) jack_port_get_buffer(out_port[i], nframes);
@@ -500,4 +534,3 @@ int process_callback(jack_nframes_t nframes, void *notused)
return 0;
}
-
diff --git a/synth/main.cpp b/synth/main.cpp
index 8bcfe39..d063d41 100644
--- a/synth/main.cpp
+++ b/synth/main.cpp
@@ -14,6 +14,7 @@
#include "globals.h"
#include "note_loader.h"
#include "in_synth_cli.h"
+#include "communication.h"
using namespace std;
@@ -24,6 +25,8 @@ void dump_options();
int main(int argc, char** argv)
{
+ init_communication();
+
for (int i=0;i<N_LFOS;i++)
lfo_freq_hz[i]=0;
@@ -103,6 +106,8 @@ int main(int argc, char** argv)
for (i=0;i<128;i++)
{
+ program_lock[i]=false;
+
if (programfile[i]!="")
{
try
@@ -177,7 +182,9 @@ int main(int argc, char** argv)
void cleanup()
{
exit_jack();
-
+
+ uninit_communication();
+
for (int i=0;i<N_CHANNELS;i++)
{
delete channel[i];