From: Alex Montgomery Date: Sun, 8 May 2011 18:14:17 +0000 (+0100) Subject: cleanup and refactor to prepare for "always on" listen loop X-Git-Tag: v4~9 X-Git-Url: https://repo.or.cz/w/jackctlmmc.git/commitdiff_plain/2ab7295a45b1608713b7b1e619b92392c383b737 cleanup and refactor to prepare for "always on" listen loop --- diff --git a/TODO b/TODO index 3839a2b..5e64376 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,6 @@ - fix XRun on quit - thread-proof / separate the listen loop +- make listen loop "always on" - change verbose to dropdown with output levels: normal, verbose, silent - allow 'output level' to be changed while listening - use XML for settings diff --git a/common.c b/common.c index bc25c51..e7c8695 100644 --- a/common.c +++ b/common.c @@ -19,19 +19,21 @@ #include "common.h" -// common globals +// exported globals int g_quit = 0; // a flag which will be set by our signal handler when it's time to exit +int g_isListening = 0; + +// globals used only here in common.c snd_seq_t* g_seq_ptr = NULL; jack_client_t* g_jack_client = NULL; -int g_isListening = 0; +struct pollfd* g_pollDescriptor = NULL; +int g_numDescriptors = 0; #if LASH_SUPPORT lash_client_t* g_lashc = NULL; void init_lash(int argc, char* argv[]) { - lash_event_t * lash_event_ptr = NULL; - /* LASH setup */ g_lashc = lash_init( lash_extract_args(&argc, &argv), "jackctlmmc", 0, LASH_PROTOCOL_VERSION); @@ -145,8 +147,14 @@ int init_alsa_sequencer(const char* appName) if (ret < 0) printMMCMessage("Error with alsa sequencer initialization, %s\n", snd_strerror(ret)); else // all is well, register the sequencer with whatever name was passed in + { snd_seq_set_client_name(g_seq_ptr, appName); + g_numDescriptors = snd_seq_poll_descriptors_count(g_seq_ptr, POLLIN); + g_pollDescriptor = (struct pollfd *)malloc(g_numDescriptors * sizeof(struct pollfd)); + snd_seq_poll_descriptors(g_seq_ptr, g_pollDescriptor, g_numDescriptors, POLLIN); + } + return ret; } @@ -301,39 +309,32 @@ void handle_midi(uint8_t* midiBuff, MidiSettings* settings) } } -void listen_loop (MidiSettings* settings) +void poll_midi (MidiSettings* settings) { snd_seq_event_t * seq_event_ptr = NULL; - int npfd = snd_seq_poll_descriptors_count(g_seq_ptr, POLLIN); - struct pollfd * pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd)); - snd_seq_poll_descriptors(g_seq_ptr, pfd, npfd, POLLIN); - - while(!g_quit) - { - if (poll(pfd, npfd, 250) > 0 && snd_seq_event_input(g_seq_ptr, &seq_event_ptr) >= 0 && seq_event_ptr->type == SND_SEQ_EVENT_SYSEX) - handle_midi((uint8_t *)seq_event_ptr->data.ext.ptr, settings); + if (poll(g_pollDescriptor, g_numDescriptors, 250) > 0 && snd_seq_event_input(g_seq_ptr, &seq_event_ptr) >= 0 && seq_event_ptr->type == SND_SEQ_EVENT_SYSEX) + handle_midi((uint8_t *)seq_event_ptr->data.ext.ptr, settings); #if LASH_SUPPORT - /* Process LASH events */ + /* Process LASH events */ + { + lash_event_t * lash_event_ptr = NULL; + lash_config_t * lash_config_ptr = NULL; + while ((lash_event_ptr = lash_get_event(g_lashc)) != NULL) { - lash_event_t * lash_event_ptr = NULL; - lash_config_t * lash_config_ptr = NULL; - while ((lash_event_ptr = lash_get_event(g_lashc)) != NULL) - { - process_lash_event(lash_event_ptr); - lash_event_destroy(lash_event_ptr); - } + process_lash_event(lash_event_ptr); + lash_event_destroy(lash_event_ptr); + } - /* Process LASH configs */ - while ((lash_config_ptr = lash_get_config(g_lashc)) != NULL) - { - process_lash_config(lash_config_ptr); - lash_config_destroy(lash_config_ptr); - } + /* Process LASH configs */ + while ((lash_config_ptr = lash_get_config(g_lashc)) != NULL) + { + process_lash_config(lash_config_ptr); + lash_config_destroy(lash_config_ptr); } -#endif } +#endif } void cleanup_globals() @@ -349,8 +350,14 @@ void cleanup_globals() } } + if (g_pollDescriptor) + free(g_pollDescriptor); + if (g_jack_client) { +#if JACK_MIDI_SUPPORT + jack_port_unregister(g_jack_client, g_jackMidiIn); +#endif jack_deactivate(g_jack_client); jack_client_close(g_jack_client); } diff --git a/common.h b/common.h index e8402c5..75ed435 100644 --- a/common.h +++ b/common.h @@ -34,8 +34,6 @@ typedef struct // globals extern int g_quit; -extern snd_seq_t* g_seq_ptr; -extern jack_client_t* g_jack_client; extern int g_isListening; // functions implemented differently by cli and qt frontends @@ -45,7 +43,7 @@ extern void printMMCMessage(const char* message, ...); int init_alsa_sequencer(const char* appName); int init_jack(const char* appName); int activate_jack(); -void listen_loop (MidiSettings* settings); +void poll_midi (MidiSettings* settings); void cleanup_globals(); void handle_midi(uint8_t* midiBuff, MidiSettings* settings); diff --git a/main.c b/main.c index 8eb5c1c..8741a64 100644 --- a/main.c +++ b/main.c @@ -98,7 +98,11 @@ int main(int argc, char *argv[]) // start listening for and handling MMC events, stops when g_quit is true (SIGINT) g_isListening = true; - listen_loop(&settings); + + while (!g_quit) + { + poll_midi(&settings); + } // so we shall quit, eh? ok, cleanup time. otherwise jack would probably produce an xrun on shutdown cleanup(); diff --git a/qt/src/main.cpp b/qt/src/main.cpp index 231f77c..2a68382 100644 --- a/qt/src/main.cpp +++ b/qt/src/main.cpp @@ -23,7 +23,7 @@ #include #include "mainWindow.h" -static MainWindow* mainWindow = NULL; +MainWindow* mainWindow = NULL; int main(int argc, char *argv[]) { diff --git a/qt/src/mainWindow.cpp b/qt/src/mainWindow.cpp index d2658b7..39f7c5f 100644 --- a/qt/src/mainWindow.cpp +++ b/qt/src/mainWindow.cpp @@ -153,7 +153,7 @@ void MainWindow::on_startButton_clicked() startButton->setText("&Stop Listening"); // start the MMC listener thread - sequencerThread = new SequencerThread(this, &m_settings); + sequencerThread = new SequencerThread(this, &m_settings, &m_settingsMutex); diff --git a/qt/src/mainWindow.h b/qt/src/mainWindow.h index 77d8f75..71e1105 100644 --- a/qt/src/mainWindow.h +++ b/qt/src/mainWindow.h @@ -20,7 +20,9 @@ #include "ui_qjackmmc.h" #include "../../config.h" + #include +#include extern "C" { #include "../../common.h" @@ -57,5 +59,6 @@ class MainWindow : public QMainWindow, public Ui::QjackMMC void enableRelevantWidgets(bool isRunning); SequencerThread* sequencerThread; - MidiSettings m_settings; + MidiSettings m_settings; //< shared between threads, Always lock m_settingsMutex when accessing! + QMutex m_settingsMutex; //< guards m_settings }; diff --git a/qt/src/qjackmmc.ui b/qt/src/qjackmmc.ui index 2be5751..ac4d3a0 100644 --- a/qt/src/qjackmmc.ui +++ b/qt/src/qjackmmc.ui @@ -7,7 +7,7 @@ 0 0 419 - 390 + 362 @@ -111,7 +111,7 @@ Check this to schedule QJackMMC with the highest allowable thread priority. - Use &Realtime thread + Use &high priority thread diff --git a/qt/src/sequencerThread.cpp b/qt/src/sequencerThread.cpp index 75b3838..52d7e5c 100644 --- a/qt/src/sequencerThread.cpp +++ b/qt/src/sequencerThread.cpp @@ -19,9 +19,10 @@ ***************************************************************************/ #include "sequencerThread.h" +#include -SequencerThread::SequencerThread(QObject* parent, MidiSettings* settings) - : QThread(parent), m_settings(settings) +SequencerThread::SequencerThread(QObject* parent, MidiSettings* settings, QMutex* settingsMutex) + : QThread(parent), m_settings(settings), m_settingsMutex(settingsMutex) { } @@ -37,7 +38,12 @@ void SequencerThread::listen(bool realTime) void SequencerThread::run () { g_quit = 0; - listen_loop(m_settings); + + while(!g_quit) + { + QMutexLocker settingsLock(m_settingsMutex); + poll_midi(m_settings); + } } void SequencerThread::die() diff --git a/qt/src/sequencerThread.h b/qt/src/sequencerThread.h index f42ab81..4d7a9ca 100644 --- a/qt/src/sequencerThread.h +++ b/qt/src/sequencerThread.h @@ -19,6 +19,7 @@ ***************************************************************************/ #include +class QMutex; extern "C" { #include "../../common.h" @@ -29,7 +30,7 @@ class SequencerThread : public QThread Q_OBJECT public: - SequencerThread(QObject* parent, MidiSettings* settings); + SequencerThread(QObject* parent, MidiSettings* settings, QMutex* settingsMutex); void listen(bool realTime); void die(); @@ -38,4 +39,5 @@ class SequencerThread : public QThread virtual void run (); MidiSettings* m_settings; + QMutex* m_settingsMutex; };