summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <florian.a.jung@web.de>2012-04-06 17:27:15 +0200
committerFlorian Jung <florian.a.jung@web.de>2012-04-06 17:27:15 +0200
commitaec14a264cdb19ccbd9e53596c58da9b60308909 (patch)
tree6d1c96febf7aaac8673698bc0cbbe93903906926
parent829c7f8da9aa285029b9d636edda191b5c2b507b (diff)
improved inter-thread communication.
the in-synth-CLI still partially uses the non-synced communication. TODO!
-rw-r--r--TODO3
-rw-r--r--synth/communication.cpp70
-rw-r--r--synth/communication.h35
-rw-r--r--synth/in_synth_cli.cpp52
-rw-r--r--synth/jack.cpp60
5 files changed, 148 insertions, 72 deletions
diff --git a/TODO b/TODO
index e9c8510..29f49cc 100644
--- a/TODO
+++ b/TODO
@@ -12,10 +12,11 @@ TODO für den synth
(macht notencompiler hoffentlich obsolet)
o evtl wieder AM implementieren: hätte hoffentlich dann keinen
negativen einfluss wenn unbenutzt
- o kommunikation sauber synchronisieren: außerhalb von process()
+ x kommunikation sauber synchronisieren: außerhalb von process()
wird nurnoch ne struct mit funktionspointer und argument-union
in einen ringbuffer geschrieben. der eigentliche call erfolgt
dann in process()
+ o saubere kommunikation bei ALLEN in-synth-CLI-sachen
o defines säubern, schöner anordnen
o frameskipping vlt immer einbauen?
diff --git a/synth/communication.cpp b/synth/communication.cpp
index f21e46f..4f9ce75 100644
--- a/synth/communication.cpp
+++ b/synth/communication.cpp
@@ -1,16 +1,76 @@
#include "communication.h"
-pthread_mutex_t suspend_request_mutex;
-suspend_request_t suspend_request;
+#include <unistd.h>
+#include <iostream>
+
+using namespace std;
+
+jack_ringbuffer_t* request_ringbuf;
+jack_ringbuffer_t* result_ringbuf;
+pthread_mutex_t request_mutex;
+
void init_communication()
{
- pthread_mutex_init(&suspend_request_mutex, NULL);
+ pthread_mutex_init(&request_mutex, NULL);
- suspend_request.done=true;
+ request_ringbuf=jack_ringbuffer_create(sizeof(request_t)+1);
+ result_ringbuf=jack_ringbuffer_create(sizeof(int)+1);
}
void uninit_communication()
{
- pthread_mutex_destroy(&suspend_request_mutex);
+ jack_ringbuffer_free(request_ringbuf);
+ jack_ringbuffer_free(result_ringbuf);
+
+ pthread_mutex_destroy(&request_mutex);
+}
+
+int do_request(request_t request)
+{
+ pthread_mutex_lock(&request_mutex); // only one request at a time
+
+ jack_ringbuffer_write(request_ringbuf, (char*)(&request), sizeof(request_t));
+
+ do // wait for the answer
+ {
+ usleep(10000);
+ } while (jack_ringbuffer_read_space(result_ringbuf)<sizeof(int));
+
+ int result;
+ if (jack_ringbuffer_read(result_ringbuf, (char*)(&result), sizeof(int)) != sizeof(int))
+ cout << "FATAL: short read from result ringbuffer, expect breakage!" << endl; // TODO handle properly
+
+ if (jack_ringbuffer_read_space(result_ringbuf)!=0)
+ cout << "FATAL: result ringbuffer not empty, expect breakage!" << endl; // TODO handle properly
+
+ pthread_mutex_unlock(&request_mutex);
+
+ return result;
+}
+
+bool request_available()
+{
+ return (jack_ringbuffer_read_space(request_ringbuf)>=sizeof(request_t));
+}
+
+request_t get_request()
+{
+ request_t request;
+
+ int len=jack_ringbuffer_read(request_ringbuf, (char*)(&request), sizeof(request_t));
+ if (len==0)
+ cout << "ERROR: no request on the ringbuffer! nothing read, continuing..." << endl;
+ else if (len!=sizeof(request_t))
+ {
+ cout << "possibly FATAL: short read from the request ringbuffer, expect breakage!" << endl;
+ request.type=request_t::NONE;
+ }
+
+ return request;
+}
+
+void request_finished(int result)
+{
+ jack_ringbuffer_write(result_ringbuf, (char*)(&result), sizeof(int));
}
diff --git a/synth/communication.h b/synth/communication.h
index 27f7186..8d11cd4 100644
--- a/synth/communication.h
+++ b/synth/communication.h
@@ -2,21 +2,36 @@
#define __COMMUNICATION_H__
#include <pthread.h>
+#include <jack/ringbuffer.h>
-struct suspend_request_t
+struct 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
+ enum request_type_t { NONE, SUSPEND_PROGRAM, RESUME_PROGRAM, PANIC, RELEASE_ALL };
+ request_type_t type;
+ int prog_or_chan; //if negative, all programs/channels are affected
+
+ request_t()
+ {
+ type=NONE;
+ }
+
+ request_t(request_type_t type_, int poc)
+ {
+ type=type_;
+ prog_or_chan=poc;
+ }
};
+// init/uninit
+void init_communication();
+void uninit_communication();
-extern pthread_mutex_t suspend_request_mutex;
-extern suspend_request_t suspend_request;
-
+// for non-audio-threads. mutex-protected
+int do_request(request_t request);
+// for the audio-thread. NOT mutex-protected
+bool request_available();
+request_t get_request();
+void request_finished(int);
-void init_communication();
-void uninit_communication();
#endif
diff --git a/synth/in_synth_cli.cpp b/synth/in_synth_cli.cpp
index 4d4ef76..069e7bd 100644
--- a/synth/in_synth_cli.cpp
+++ b/synth/in_synth_cli.cpp
@@ -1,7 +1,6 @@
#include <iostream>
#include <string>
#include <signal.h>
-#include <unistd.h>
#include <stdlib.h>
#include "in_synth_cli.h"
@@ -26,33 +25,6 @@ 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)
{
pthread_mutex_lock(&prog_load_mutex);
@@ -61,7 +33,7 @@ void lock_and_load_program(int prg_no, string file)
remove_watch(prg_no);
#endif
- do_request(prg_no, true);
+ do_request(request_t(request_t::SUSPEND_PROGRAM, prg_no));
if (load_program(file,program_settings[prg_no]))
{
@@ -78,7 +50,7 @@ void lock_and_load_program(int prg_no, string file)
for (int i=0;i<N_CHANNELS;++i)
channel[i]->maybe_reload_program(prg_no);
- do_request(prg_no, false);
+ do_request(request_t(request_t::RESUME_PROGRAM, prg_no));
pthread_mutex_unlock(&prog_load_mutex);
}
@@ -89,7 +61,7 @@ void lock_and_load_program_no_watch_updates(int prg_no, string file)
{
pthread_mutex_lock(&prog_load_mutex);
- do_request(prg_no, true);
+ do_request(request_t(request_t::SUSPEND_PROGRAM, prg_no));
if (load_program(file,program_settings[prg_no]))
{
@@ -102,20 +74,20 @@ void lock_and_load_program_no_watch_updates(int prg_no, string file)
for (int i=0;i<N_CHANNELS;++i)
channel[i]->maybe_reload_program(prg_no);
- do_request(prg_no, false);
+ do_request(request_t(request_t::RESUME_PROGRAM, prg_no));
pthread_mutex_unlock(&prog_load_mutex);
}
void lock_and_change_lfo(int lfo_no, float freq)
{
- do_request(-1, true);
+ do_request(request_t(request_t::SUSPEND_PROGRAM, -1));
uninit_lfo(lfo_no);
lfo_freq_hz[lfo_no]=freq;
init_lfo(lfo_no);
- do_request(-1, false);
+ do_request(request_t(request_t::RESUME_PROGRAM, -1));
}
@@ -183,13 +155,12 @@ void do_in_synth_cli()
else if (command=="panic")
{
if ((params=="") || (params=="all"))
- for (int i=0;i<N_CHANNELS;++i)
- channel[i]->panic();
+ do_request(request_t(request_t::PANIC, -1));
else if (isnum(params))
{
num=atoi(params.c_str());
if ((num>=0) && (num<N_CHANNELS))
- channel[num]->panic();
+ do_request(request_t(request_t::PANIC, num));
else
cout << "error: channel-number must be one of 0.."<<N_CHANNELS-1<<endl;
}
@@ -197,17 +168,18 @@ void do_in_synth_cli()
else if (command=="release")
{
if ((params=="") || (params=="all"))
- for (int i=0;i<N_CHANNELS;++i)
- channel[i]->release_all();
+ do_request(request_t(request_t::RELEASE_ALL, -1));
else if (isnum(params))
{
num=atoi(params.c_str());
if ((num>=0) && (num<N_CHANNELS))
- channel[num]->release_all();
+ do_request(request_t(request_t::RELEASE_ALL, num));
else
cout << "error: channel-number must be one of 0.."<<N_CHANNELS-1<<endl;
}
}
+ // TODO: from here, no proper synchronisation with the audio thread
+ // is done. use do_request() everywhere!
else if (command=="kill_program")
{
string prgstr, chanstr;
diff --git a/synth/jack.cpp b/synth/jack.cpp
index c86cbce..882d5fb 100644
--- a/synth/jack.cpp
+++ b/synth/jack.cpp
@@ -34,15 +34,45 @@ void manage_program_lock(int prog, bool lock) //TODO woandershinschieben?
channel[i]->kill_program(prog);
}
-void process_request()
+void process_request(request_t 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);
+ switch (request.type)
+ {
+ case request_t::NONE: break;
+
+ case request_t::SUSPEND_PROGRAM:
+ case request_t::RESUME_PROGRAM:
+ if (request.prog_or_chan==-1)
+ for (int i=0;i<128;++i)
+ manage_program_lock(i,request.type==request_t::SUSPEND_PROGRAM);
+ else
+ manage_program_lock(request.prog_or_chan,request.type==request_t::SUSPEND_PROGRAM);
+
+ break;
+
+ case request_t::PANIC:
+ if (request.prog_or_chan==-1)
+ for (int i=0;i<N_CHANNELS;++i)
+ channel[i]->panic();
+ else
+ channel[request.prog_or_chan]->panic();
+
+ break;
+
+ case request_t::RELEASE_ALL:
+ if (request.prog_or_chan==-1)
+ for (int i=0;i<N_CHANNELS;++i)
+ channel[i]->release_all();
+ else
+ channel[request.prog_or_chan]->release_all();
+
+ break;
+
+ default:
+ cout << "ERROR: bad request, ignoring it." << endl;
+ }
- suspend_request.done=true;
+ request_finished(0);
}
@@ -217,10 +247,10 @@ int xrun_callback(void *notused)
if (history.size() >= xrun_n)
{
- cout << "PANIC -- TOO MANY XRUNs! killing all voices" << endl<<endl;
- for (int i=0;i<N_CHANNELS;++i)
- channel[i]->panic();
-
+ cout << "PANIC -- TOO MANY XRUNs! killing all voices" << flush;
+ do_request(request_t(request_t::PANIC, -1));
+ cout << " (done)" << endl << endl;
+
history.clear();
}
@@ -254,11 +284,9 @@ int process_callback(jack_nframes_t nframes, void *notused)
}
-
- pthread_mutex_lock(&suspend_request_mutex);
- if (suspend_request.done==false)
- process_request();
- pthread_mutex_unlock(&suspend_request_mutex);
+ if (request_available())
+ process_request(get_request());
+