From 5acf1f33d6bb62803f7d2e1faa03fc948f272ab9 Mon Sep 17 00:00:00 2001 From: Harry van Haaren Date: Thu, 3 Nov 2016 20:09:06 +0000 Subject: [PATCH 01/15] clip save implemented, fixes #121 --- src/avtk/clipselector.cxx | 19 ++++++++++++++ src/diskwriter.cxx | 52 ++++++++++++++++++++++----------------- src/diskwriter.hxx | 6 +++-- src/event.hxx | 3 ++- src/eventhandlerdsp.cxx | 14 +++++++++++ src/eventhandlergui.cxx | 13 ++++++++-- src/gui.cxx | 34 +++++++++++++++++++++++++ src/gui.hxx | 6 ++++- src/looperclip.hxx | 2 ++ 9 files changed, 121 insertions(+), 28 deletions(-) diff --git a/src/avtk/clipselector.cxx b/src/avtk/clipselector.cxx index 5b2b64d..b6690b9 100644 --- a/src/avtk/clipselector.cxx +++ b/src/avtk/clipselector.cxx @@ -19,6 +19,8 @@ #include "clipselector.hxx" +#include + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #include "../gui.hxx" @@ -292,6 +294,7 @@ int ClipSelector::handle(int event) Fl_Menu_Item rclick_menu[] = { { "Load" }, + { "Save" }, { "Special"}, { "Beats", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER }, {"1 "}, @@ -317,6 +320,22 @@ int ClipSelector::handle(int event) { gui->selectLoadSample( ID, clipNum ); } + else if ( strcmp(m->label(), "Save") == 0 ) + { + //gui->saveBufferPath = "/tmp/test.wav"; + char* tmp = gui->selectSavePath(); + if(tmp && strlen(tmp)) { + if( access( tmp, F_OK ) != -1 ) { + int overwrite = fl_choice("Overwrite file?","Cancel","Overwrite",0); + if (!overwrite) { + return 0; + } + } + gui->saveBufferPath = tmp; + free(tmp); + gui->selectSaveSample( ID, clipNum ); + } + } else if ( strcmp(m->label(), "1 ") == 0 ) { EventLooperLoopLength e = EventLooperLoopLength(ID, clipNum ,1); writeToDspRingbuffer( &e ); diff --git a/src/diskwriter.cxx b/src/diskwriter.cxx index 78fa79c..7193596 100644 --- a/src/diskwriter.cxx +++ b/src/diskwriter.cxx @@ -308,34 +308,42 @@ int DiskWriter::writeControllerFile( Controller* c ) return LUPPP_RETURN_OK; } -int DiskWriter::writeAudioBuffer(int track, int scene, AudioBuffer* ab ) +int DiskWriter::writeAudioBuffer(int track, int scene, AudioBuffer* ab, + const char *gui_path) { - if ( !foldersCreated ) + stringstream path; + if ( gui_path && strlen(gui_path) ) { + printf("saving single buffer to %s\n", gui_path); + path << gui_path; + } + else if ( foldersCreated ) + { + stringstream filename; + filename << "t_" << track << "_s_" << scene << ".wav"; + + // store the clip in clipData, we will write the session JSON for it in writeSession + clipData.push_back( ClipData( track, scene, filename.str() ) ); + + // add the AudioBuffer metadata to the sample JSON node + cJSON* sampleClip = cJSON_CreateObject(); + cJSON_AddItemToObject(audioJson, filename.str().c_str(), sampleClip ); + cJSON_AddNumberToObject(sampleClip,"beats", ab->getBeats() ); + + // get pretty name from GUI + std::string clipName = gui->getTrack(track)->getClipSelector()->clipName( scene ); + cJSON_AddItemToObject ( sampleClip, "name", cJSON_CreateString( clipName.c_str() )); + + // write the AudioBuffer contents to /audio/ as .wav + // or alternatively t__s_.wav + + path << audioDir << "/" << filename.str(); + } + else { LUPPP_WARN("%s", "Session folders not created yet, while trying to write audioBuffers."); return LUPPP_RETURN_ERROR; } - stringstream filename; - filename << "t_" << track << "_s_" << scene << ".wav"; - - // store the clip in clipData, we will write the session JSON for it in writeSession - clipData.push_back( ClipData( track, scene, filename.str() ) ); - - // add the AudioBuffer metadata to the sample JSON node - cJSON* sampleClip = cJSON_CreateObject(); - cJSON_AddItemToObject(audioJson, filename.str().c_str(), sampleClip ); - cJSON_AddNumberToObject(sampleClip,"beats", ab->getBeats() ); - - // get pretty name from GUI - std::string clipName = gui->getTrack(track)->getClipSelector()->clipName( scene ); - cJSON_AddItemToObject ( sampleClip, "name", cJSON_CreateString( clipName.c_str() )); - - // write the AudioBuffer contents to /audio/ as .wav - // or alternatively t__s_.wav - - stringstream path; - path << audioDir << "/" << filename.str(); SndfileHandle outfile( path.str(), SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_FLOAT, 1, gui->samplerate ); diff --git a/src/diskwriter.hxx b/src/diskwriter.hxx index 3cc23e7..14c252c 100644 --- a/src/diskwriter.hxx +++ b/src/diskwriter.hxx @@ -59,8 +59,10 @@ class DiskWriter /// sets up session write path etc void initialize( std::string path, std::string sessionName ); - /// writes a single audio buffer to disk - int writeAudioBuffer(int track, int scene, AudioBuffer* ab ); + /// writes a single audio buffer to disk for saving whole state. + // When gui_path is set, it only saves a single AB* to that path + int writeAudioBuffer(int track, int scene, AudioBuffer* ab, + const char* gui_path = 0); /// flush the JSON to disk, finalizing the save int writeSession(); diff --git a/src/event.hxx b/src/event.hxx index 74d08ca..539c15a 100644 --- a/src/event.hxx +++ b/src/event.hxx @@ -663,8 +663,9 @@ class EventStateSaveBuffer : public EventBase int scene; // pointer to the AudioBuffer to be saved AudioBuffer* ab; + bool no_dealloc; - EventStateSaveBuffer(): track(0), scene(0), ab(0) {} + EventStateSaveBuffer(): track(0), scene(0), ab(0), no_dealloc(0) {} EventStateSaveBuffer(int t, int s, AudioBuffer* a): track(t), scene(s), ab(a) {} }; diff --git a/src/eventhandlerdsp.cxx b/src/eventhandlerdsp.cxx index 2cd6a0d..7a0783d 100644 --- a/src/eventhandlerdsp.cxx +++ b/src/eventhandlerdsp.cxx @@ -104,6 +104,20 @@ void handleDspEvents() jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateReset) ); jack->getState()->reset(); } break; } + case Event::STATE_SAVE_BUFFER: { + if ( availableRead >= sizeof(EventStateReset) ) { + EventStateSaveBuffer ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventStateSaveBuffer) ); + printf("jack got save buffer in %d, %d\n", ev.track, ev.scene); + LooperClip* lc = jack->getLooper(ev.track)->getClip(ev.scene); + if(!lc) break; + EventStateSaveBuffer e; + e.track = ev.track; + e.scene = ev.scene; + e.ab = lc->getAudioBuffer(); + e.no_dealloc = 1; + writeToGuiRingbuffer( &e ); + } break; } // ========= MASTER === case Event::MASTER_VOL: { diff --git a/src/eventhandlergui.cxx b/src/eventhandlergui.cxx index d60ea2c..b529b9e 100644 --- a/src/eventhandlergui.cxx +++ b/src/eventhandlergui.cxx @@ -181,8 +181,17 @@ void handleGuiEvents() cout << "EventSaveBuffer: " << ev.track << " " << ev.scene << " " << ev.ab->getID() << endl; #endif gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab ); - // de allocate the AudioBuffer - delete ev.ab; + // de allocate the AudioBuffer only if reqested + if(!ev.no_dealloc) { + gui->getDiskWriter()->writeAudioBuffer( ev.track, ev.scene, ev.ab ); + delete ev.ab; + } else + { + gui->getDiskWriter()->writeAudioBuffer(ev.track, ev.scene, ev.ab, + gui->saveBufferPath.c_str()); + gui->saveBufferPath = ""; + } + } break; } case Event::STATE_SAVE_FINISH: { diff --git a/src/gui.cxx b/src/gui.cxx index 50ba96d..d7fec92 100644 --- a/src/gui.cxx +++ b/src/gui.cxx @@ -252,6 +252,40 @@ void Gui::selectLoadController(Fl_Widget* w, void*) } +void Gui::selectSaveSample( int track, int scene ) +{ + EventStateSaveBuffer e; + e.track = track, + e.scene = scene, + writeToDspRingbuffer( &e ); +} + +char * +Gui::selectSavePath() +{ + string path; + Fl_Native_File_Chooser fnfc; + fnfc.title("Save filename?"); + fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + + std::string defLoadPath = gui->getDiskReader()->getLastLoadedSamplePath(); + fnfc.directory( defLoadPath.c_str() ); // default directory to use + + // Show native chooser + switch ( fnfc.show() ) { + case -1: /*printf("ERROR: %s\n", fnfc.errmsg()); */ break; // ERROR + case 1: /*(printf("CANCEL\n"); */ break; // CANCEL + default: /*printf("Loading directory: %s\n", fnfc.filename()); */ + path = fnfc.filename(); + break; + } + + if ( strcmp( path.c_str(), "" ) == 0 ) + return 0; + + return strdup(path.c_str()); +} + void Gui::selectLoadSample( int track, int scene ) { // FIXME: refactor diff --git a/src/gui.hxx b/src/gui.hxx index 77178d0..a2a011b 100644 --- a/src/gui.hxx +++ b/src/gui.hxx @@ -76,6 +76,8 @@ class Gui /// used to load samples into the grid void selectLoadSample( int track, int clip ); + void selectSaveSample( int track, int clip ); + char* selectSavePath(); /// allows the user to select a Controller definition static void selectLoadController(Fl_Widget* w, void*); @@ -91,7 +93,9 @@ class Gui /// current special clip: int specialTrack; int specialScene; - + + // save a particular sample to path + std::string saveBufferPath; private: vector controllerVector; diff --git a/src/looperclip.hxx b/src/looperclip.hxx index 269d6ba..a419ba4 100644 --- a/src/looperclip.hxx +++ b/src/looperclip.hxx @@ -82,6 +82,8 @@ class LooperClip : public Stately //Return the nr of samples holding actual audio. This is less then getBufferLength(); long getActualAudioLength(); size_t audioBufferSize(); + + AudioBuffer* getAudioBuffer() {return _buffer;} /// set clip state void queuePlay(bool=true); From d96b2692679017a17d0b250e7401129b388b2828 Mon Sep 17 00:00:00 2001 From: rcaneill Date: Tue, 15 Nov 2016 11:14:05 +0100 Subject: [PATCH 02/15] Create akai_apc_key25.ctrl Control file for the Akai APC Key25 --- resources/controllers/akai_apc_key25.ctrl | 947 ++++++++++++++++++++++ 1 file changed, 947 insertions(+) create mode 100644 resources/controllers/akai_apc_key25.ctrl diff --git a/resources/controllers/akai_apc_key25.ctrl b/resources/controllers/akai_apc_key25.ctrl new file mode 100644 index 0000000..e41781d --- /dev/null +++ b/resources/controllers/akai_apc_key25.ctrl @@ -0,0 +1,947 @@ +{ + "name": "AKAI_APCkey25", + "author": "Romain Caneill", + "link": "", + "inputBindings": [{ + " __COMMMENT__ ###############################" : "track 0", + "action": "grid:event", + "status": 144, + "data": 32, + "track": 0, + "scene": 0 + }, + { + "action": "grid:event", + "status": 144, + "data": 24, + "track": 0, + "scene": 1 + }, + { + "action": "grid:event", + "status": 144, + "data": 16, + "track": 0, + "scene": 2 + }, + { + "action": "grid:event", + "status": 144, + "data": 8, + "track": 0, + "scene": 3 + }, + { + "action": "grid:event", + "status": 144, + "data": 0, + "track": 0, + "scene": 4 + }, + { + "action": "track:volume", + "status": 176, + "data": 48, + "track": 0, + "send": 1, + "active": 0 + }, + { + "action": "track:send_active", + "status": 144, + "data": 64, + "track": 0, + "send": 0, + "active": 1 + }, + { + "action": "track:send_active", + "status": 128, + "data": 64, + "track": 0, + "send": 0, + "active": 0 + }, + { + " __COMMMENT__ ###############################" : "track 1", + "action": "grid:event", + "status": 144, + "data": 33, + "track": 1, + "scene": 0 + }, + { + "action": "grid:event", + "status": 144, + "data": 25, + "track": 1, + "scene": 1 + }, + { + "action": "grid:event", + "status": 144, + "data": 17, + "track": 1, + "scene": 2 + }, + { + "action": "grid:event", + "status": 144, + "data": 9, + "track": 1, + "scene": 3 + }, + { + "action": "grid:event", + "status": 144, + "data": 1, + "track": 1, + "scene": 4 + }, + { + "action": "track:volume", + "status": 176, + "data": 49, + "track": 1 + }, + { + "action": "track:send_active", + "status": 144, + "data": 65, + "track": 1, + "send": 0, + "active": 1 + }, + { + "action": "track:send_active", + "status": 128, + "data": 65, + "track": 1, + "send": 0, + "active": 0 + }, + { + " __COMMMENT__ ###############################" : "track 2", + "action": "grid:event", + "status": 144, + "data": 34, + "track": 2, + "scene": 0 + }, + { + "action": "grid:event", + "status": 144, + "data": 26, + "track": 2, + "scene": 1 + }, + { + "action": "grid:event", + "status": 144, + "data": 18, + "track": 2, + "scene": 2 + }, + { + "action": "grid:event", + "status": 144, + "data": 10, + "track": 2, + "scene": 3 + }, + { + "action": "grid:event", + "status": 144, + "data": 2, + "track": 2, + "scene": 4 + }, + { + "action": "track:volume", + "status": 176, + "data": 50, + "track": 2 + }, + { + "action": "track:send_active", + "status": 144, + "data": 66, + "track": 2, + "send": 0, + "active": 1 + }, + { + "action": "track:send_active", + "status": 128, + "data": 66, + "track": 2, + "send": 0, + "active": 0 + }, + { + " __COMMMENT__ ###############################" : "track 3", + "action": "grid:event", + "status": 144, + "data": 35, + "track": 3, + "scene": 0 + }, + { + "action": "grid:event", + "status": 144, + "data": 27, + "track": 3, + "scene": 1 + }, + { + "action": "grid:event", + "status": 144, + "data": 19, + "track": 3, + "scene": 2 + }, + { + "action": "grid:event", + "status": 144, + "data": 11, + "track": 3, + "scene": 3 + }, + { + "action": "grid:event", + "status": 144, + "data": 3, + "track": 3, + "scene": 4 + }, + { + "action": "track:volume", + "status": 176, + "data": 51, + "track": 3 + }, + { + "action": "track:send_active", + "status": 144, + "data": 67, + "track": 3, + "send": 0, + "active": 1 + }, + { + "action": "track:send_active", + "status": 128, + "data": 67, + "track": 3, + "send": 0, + "active": 0 + }, + { + " __COMMMENT__ ###############################" : "track 4", + "action": "grid:event", + "status": 144, + "data": 36, + "track": 4, + "scene": 0 + }, + { + "action": "grid:event", + "status": 144, + "data": 28, + "track": 4, + "scene": 1 + }, + { + "action": "grid:event", + "status": 144, + "data": 20, + "track": 4, + "scene": 2 + }, + { + "action": "grid:event", + "status": 144, + "data": 12, + "track": 4, + "scene": 3 + }, + { + "action": "grid:event", + "status": 144, + "data": 4, + "track": 4, + "scene": 4 + }, + { + "action": "track:volume", + "status": 176, + "data": 52, + "track": 4 + }, + { + "action": "track:send_active", + "status": 144, + "data": 68, + "track": 4, + "send": 0, + "active": 1 + }, + { + "action": "track:send_active", + "status": 128, + "data": 68, + "track": 4, + "send": 0, + "active": 0 + }, + { + " __COMMMENT__ ###############################" : "track 5", + "action": "grid:event", + "status": 144, + "data": 37, + "track": 5, + "scene": 0 + }, + { + "action": "grid:event", + "status": 144, + "data": 29, + "track": 5, + "scene": 1 + }, + { + "action": "grid:event", + "status": 144, + "data": 21, + "track": 5, + "scene": 2 + }, + { + "action": "grid:event", + "status": 144, + "data": 13, + "track": 5, + "scene": 3 + }, + { + "action": "grid:event", + "status": 144, + "data": 5, + "track": 5, + "scene": 4 + }, + { + "action": "track:volume", + "status": 176, + "data": 53, + "track": 5 + }, + { + "action": "track:send_active", + "status": 144, + "data": 69, + "track": 5, + "send": 0, + "active": 1 + }, + { + "action": "track:send_active", + "status": 128, + "data": 69, + "track": 5, + "send": 0, + "active": 0 + }, + { + " __COMMMENT__ ###############################" : "track 6", + "action": "grid:event", + "status": 144, + "data": 38, + "track": 6, + "scene": 0 + }, + { + "action": "grid:event", + "status": 144, + "data": 30, + "track": 6, + "scene": 1 + }, + { + "action": "grid:event", + "status": 144, + "data": 22, + "track": 6, + "scene": 2 + }, + { + "action": "grid:event", + "status": 144, + "data": 14, + "track": 6, + "scene": 3 + }, + { + "action": "grid:event", + "status": 144, + "data": 6, + "track": 6, + "scene": 4 + }, + { + "action": "track:volume", + "status": 176, + "data": 54, + "track": 6 + }, + { + "action": "track:send_active", + "status": 144, + "data": 70, + "track": 6, + "send": 0, + "active": 1 + }, + { + "action": "track:send_active", + "status": 128, + "data": 70, + "track": 6, + "send": 0, + "active": 0 + }, + { + " __COMMMENT__ ###############################" : "track 7", + "action": "grid:event", + "status": 144, + "data": 39, + "track": 7, + "scene": 0 + }, + { + "action": "grid:event", + "status": 144, + "data": 31, + "track": 7, + "scene": 1 + }, + { + "action": "grid:event", + "status": 144, + "data": 23, + "track": 7, + "scene": 2 + }, + { + "action": "grid:event", + "status": 144, + "data": 15, + "track": 7, + "scene": 3 + }, + { + "action": "grid:event", + "status": 144, + "data": 7, + "track": 7, + "scene": 4 + }, + { + "action": "track:volume", + "status": 176, + "data": 55, + "track": 7 + }, + { + "action": "track:send_active", + "status": 144, + "data": 71, + "track": 7, + "send": 0, + "active": 1 + }, + { + "action": "track:send_active", + "status": 128, + "data": 71, + "track": 7, + "send": 0, + "active": 0 + }, + { + " __COMMMENT__ ###############################" : "lauch scenes", + "action": "grid:launch_scene", + "status": 144, + "data": 82, + "scene": 0 + }, { + "action": "grid:launch_scene", + "status": 144, + "data": 83, + "scene": 1 + }, { + "action": "grid:launch_scene", + "status": 144, + "data": 84, + "scene": 2 + }, { + "action": "grid:launch_scene", + "status": 144, + "data": 85, + "scene": 3 + }, { + "action": "grid:launch_scene", + "status": 144, + "data": 86, + "scene": 4 + }], + + +"outputBindings": [{ + " __COMMMENT__ ###############################" : "track 0", + "action" : "grid:clip_state", + "status" : 144, + "data" : 32, + "track" : 0, + "scene" : 0, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 24, + "track" : 0, + "scene" : 1, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 16, + "track" : 0, + "scene" : 2, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 8, + "track" : 0, + "scene" : 3, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 0, + "track" : 0, + "scene" : 4, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + +{ + " __COMMMENT__ ###############################" : "track 0", + "action" : "grid:clip_state", + "status" : 144, + "data" : 33, + "track" : 1, + "scene" : 0, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 25, + "track" : 1, + "scene" : 1, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 17, + "track" : 1, + "scene" : 2, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 9, + "track" : 1, + "scene" : 3, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 1, + "track" : 1, + "scene" : 4, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + +{ + " __COMMMENT__ ###############################" : "track 0", + "action" : "grid:clip_state", + "status" : 144, + "data" : 34, + "track" : 2, + "scene" : 0, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 26, + "track" : 2, + "scene" : 1, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 18, + "track" : 2, + "scene" : 2, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 10, + "track" : 2, + "scene" : 3, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 2, + "track" : 2, + "scene" : 4, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + +{ + " __COMMMENT__ ###############################" : "track 0", + "action" : "grid:clip_state", + "status" : 144, + "data" : 35, + "track" : 3, + "scene" : 0, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 27, + "track" : 3, + "scene" : 1, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 19, + "track" : 3, + "scene" : 2, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 11, + "track" : 3, + "scene" : 3, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 3, + "track" : 3, + "scene" : 4, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + +{ + " __COMMMENT__ ###############################" : "track 0", + "action" : "grid:clip_state", + "status" : 144, + "data" : 36, + "track" : 4, + "scene" : 0, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 28, + "track" : 4, + "scene" : 1, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 20, + "track" : 4, + "scene" : 2, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 12, + "track" : 4, + "scene" : 3, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 4, + "track" : 4, + "scene" : 4, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + +{ + " __COMMMENT__ ###############################" : "track 0", + "action" : "grid:clip_state", + "status" : 144, + "data" : 37, + "track" : 5, + "scene" : 0, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 29, + "track" : 5, + "scene" : 1, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 21, + "track" : 5, + "scene" : 2, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 13, + "track" : 5, + "scene" : 3, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 5, + "track" : 5, + "scene" : 4, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + +{ + " __COMMMENT__ ###############################" : "track 0", + "action" : "grid:clip_state", + "status" : 144, + "data" : 38, + "track" : 6, + "scene" : 0, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 30, + "track" : 6, + "scene" : 1, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 22, + "track" : 6, + "scene" : 2, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 14, + "track" : 6, + "scene" : 3, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 6, + "track" : 6, + "scene" : 4, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + +{ + " __COMMMENT__ ###############################" : "track 0", + "action" : "grid:clip_state", + "status" : 144, + "data" : 39, + "track" : 7, + "scene" : 0, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 31, + "track" : 7, + "scene" : 1, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 23, + "track" : 7, + "scene" : 2, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 15, + "track" : 7, + "scene" : 3, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }, + { + + "action" : "grid:clip_state", + "status" : 144, + "data" : 7, + "track" : 7, + "scene" : 4, + "state" : { + "empty" : 0, "stopped" : 5, "playing" : 1, "recording" : 3, + "queueStopped" : 6, "queuePlaying" : 2, "queueRecording" : 4} + }] +} From b922e5ebbe4825f16d5cd010b7a3b268fe473ce7 Mon Sep 17 00:00:00 2001 From: Gerald Date: Fri, 30 Sep 2016 23:05:41 +0200 Subject: [PATCH 03/15] Started per track sends/returns --- src/buffers.hxx | 18 ++++++++++++++++++ src/jack.hxx | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/buffers.hxx b/src/buffers.hxx index 53e6d17..3100b2d 100644 --- a/src/buffers.hxx +++ b/src/buffers.hxx @@ -62,6 +62,24 @@ class Buffers TRACK_5, TRACK_6, TRACK_7, + //Per track sends/returns + JACK_SEND_TRACK_0, + JACK_SEND_TRACK_1, + JACK_SEND_TRACK_2, + JACK_SEND_TRACK_3, + JACK_SEND_TRACK_4, + JACK_SEND_TRACK_5, + JACK_SEND_TRACK_6, + JACK_SEND_TRACK_7, + JACK_RETURN_TRACK_0, + JACK_RETURN_TRACK_1, + JACK_RETURN_TRACK_2, + JACK_RETURN_TRACK_3, + JACK_RETURN_TRACK_4, + JACK_RETURN_TRACK_5, + JACK_RETURN_TRACK_6, + JACK_RETURN_TRACK_7, + BUFFER_COUNT, }; diff --git a/src/jack.hxx b/src/jack.hxx index f02d901..2935593 100644 --- a/src/jack.hxx +++ b/src/jack.hxx @@ -164,6 +164,8 @@ class Jack jack_port_t* sendOutput; jack_port_t* masterMidiInput; + + vector trackJackOutputPorts; // JACK callback int process (jack_nframes_t); From 28cbe8e6388fb7f42a2242c1cf422288dd4bc21c Mon Sep 17 00:00:00 2001 From: Gerald Date: Mon, 3 Oct 2016 19:43:13 +0200 Subject: [PATCH 04/15] Added per track sends and returns via JackSendReturn (subclass of AudioProcessor) --- src/buffers.hxx | 16 ++++++++++++++ src/jack.cxx | 19 ++++++++++++++-- src/jack.hxx | 3 ++- src/jacksendreturn.cxx | 38 ++++++++++++++++++++++++++++++++ src/jacksendreturn.hxx | 49 ++++++++++++++++++++++++++++++++++++++++++ src/looper.cxx | 2 +- src/trackoutput.cxx | 2 +- 7 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 src/jacksendreturn.cxx create mode 100644 src/jacksendreturn.hxx diff --git a/src/buffers.hxx b/src/buffers.hxx index 3100b2d..315af58 100644 --- a/src/buffers.hxx +++ b/src/buffers.hxx @@ -63,6 +63,14 @@ class Buffers TRACK_6, TRACK_7, //Per track sends/returns + SEND_TRACK_0, + SEND_TRACK_1, + SEND_TRACK_2, + SEND_TRACK_3, + SEND_TRACK_4, + SEND_TRACK_5, + SEND_TRACK_6, + SEND_TRACK_7, JACK_SEND_TRACK_0, JACK_SEND_TRACK_1, JACK_SEND_TRACK_2, @@ -71,6 +79,14 @@ class Buffers JACK_SEND_TRACK_5, JACK_SEND_TRACK_6, JACK_SEND_TRACK_7, + RETURN_TRACK_0, + RETURN_TRACK_1, + RETURN_TRACK_2, + RETURN_TRACK_3, + RETURN_TRACK_4, + RETURN_TRACK_5, + RETURN_TRACK_6, + RETURN_TRACK_7, JACK_RETURN_TRACK_0, JACK_RETURN_TRACK_1, JACK_RETURN_TRACK_2, diff --git a/src/jack.cxx b/src/jack.cxx index c0d9b79..252e996 100644 --- a/src/jack.cxx +++ b/src/jack.cxx @@ -33,7 +33,7 @@ #include "trackoutput.hxx" #include "timemanager.hxx" #include "controllerupdater.hxx" - +#include "jacksendreturn.hxx" #include "dsp/dsp_reverb.hxx" #include "dsp/dsp_dbmeter.hxx" @@ -201,9 +201,14 @@ Jack::Jack( std::string name ) : * In this case, the track's Looper instance. **/ loopers.push_back( new Looper(i) ); - trackOutputs.push_back( new TrackOutput(i, loopers.back() ) ); + + + tracksendreturns.push_back(new JackSendReturn(i,loopers.back(),client)); + trackOutputs.push_back( new TrackOutput(i, tracksendreturns.back() ) ); buffers.audio[Buffers::TRACK_0 + i] = new float[ buffers.nframes ]; + buffers.audio[Buffers::SEND_TRACK_0+i]=new float[buffers.nframes]; + buffers.audio[Buffers::RETURN_TRACK_0+i]=new float[buffers.nframes]; timeManager->registerObserver( loopers.back() ); } @@ -264,6 +269,12 @@ Jack::~Jack() delete inputMeter; delete masterMeter; + for(int i = 0; i < NTRACKS; i++) + { + delete [] buffers.audio[Buffers::TRACK_0+i]; + delete [] buffers.audio[Buffers::SEND_TRACK_0+i]; + delete [] buffers.audio[Buffers::RETURN_TRACK_0+i]; + } } void Jack::activate() @@ -543,7 +554,11 @@ void Jack::clearInternalBuffers(int nframes) memset(buffers.audio[Buffers::MASTER_OUT_L],0,sizeof(float)*nframes); memset(buffers.audio[Buffers::MASTER_OUT_R],0,sizeof(float)*nframes); for(int i=0;i loopers; + vector tracksendreturns; vector trackOutputs; vector midiIO; diff --git a/src/jacksendreturn.cxx b/src/jacksendreturn.cxx new file mode 100644 index 0000000..b66f42f --- /dev/null +++ b/src/jacksendreturn.cxx @@ -0,0 +1,38 @@ +#include "jacksendreturn.hxx" +#include "jack.hxx" +extern Jack* jack; +JackSendReturn::JackSendReturn(int trackid, AudioProcessor *prev, jack_client_t *client) + :m_trackid(trackid), m_previousProcessor(prev) +{ + char name[50]; + sprintf(name, "Send_track_%d\0",trackid); + m_sendport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput,0); + sprintf(name, "Return_track_%d\0",trackid); + m_returnport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0); +} + +void JackSendReturn::process(unsigned int nframes, Buffers *buffers) +{ + //Reset send buffer + memset(buffers->audio[Buffers::SEND_TRACK_0+m_trackid],0,nframes*sizeof(float)); + + //Process previous AudioProcessor + m_previousProcessor->process(nframes,buffers); + float* send=(float*)jack_port_get_buffer(m_sendport,(jack_nframes_t)nframes); + float* ret=(float*)jack_port_get_buffer(m_returnport,(jack_nframes_t)nframes); + + //Copy result of previous AudioProcessor to send port + memcpy(send,buffers->audio[Buffers::SEND_TRACK_0+m_trackid],nframes*sizeof(float)); + + //Get connection status + bool connected=jack_port_connected(m_returnport); + //Is return port connected? + //Yes then grab the audio data from the connected port + //No: get the audio from the previous AudioProcessor + if(connected) + memcpy(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid],ret,nframes*sizeof(float)); + else + memcpy(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid], + buffers->audio[Buffers::SEND_TRACK_0+m_trackid],nframes*sizeof(float)); + +} diff --git a/src/jacksendreturn.hxx b/src/jacksendreturn.hxx new file mode 100644 index 0000000..3d31ca2 --- /dev/null +++ b/src/jacksendreturn.hxx @@ -0,0 +1,49 @@ +/* + * Author: Gerald Mwangi 2016 + * gerald.mwangi@gmx.de + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef JACKSENDREUTRN_H +#define JACKSENDRETURN_H +#include "buffers.hxx" +#include "audioprocessor.hxx" +#include + +/// JackSendReturn: This class provides per track send and return jack ports +/// The send port always sends the output of the previous AudioProcesser +/// The content of the return channel depends on whether the return jack port is connected: +/// If it is connected it receives what ever audio comes into it. +/// If it is not connected, it receives the output of the previous AudioProcessor (it gets what goes into the send port) +class JackSendReturn: public AudioProcessor +{ +public: + //Constructor: the registration of the jack send/return is done here + JackSendReturn(int trackid,AudioProcessor* prev,jack_client_t* client); + + //The process callback + virtual void process(unsigned int nframes, Buffers* buffers); + +private: + jack_port_t* m_sendport; + jack_port_t* m_returnport; + int m_trackid; + AudioProcessor* m_previousProcessor; +}; + + + + +#endif diff --git a/src/looper.cxx b/src/looper.cxx index b6458aa..34d3e9d 100644 --- a/src/looper.cxx +++ b/src/looper.cxx @@ -136,7 +136,7 @@ void Looper::process(unsigned int nframes, Buffers* buffers) playSpeed = float(actualFrames) / targetFrames; } - float* out = buffers->audio[Buffers::TRACK_0 + track]; + float* out = buffers->audio[Buffers::SEND_TRACK_0 + track]; for(unsigned int i = 0; i < nframes; i++ ) { diff --git a/src/trackoutput.cxx b/src/trackoutput.cxx index c1e64ba..549bfbd 100644 --- a/src/trackoutput.cxx +++ b/src/trackoutput.cxx @@ -108,7 +108,7 @@ void TrackOutput::process(unsigned int nframes, Buffers* buffers) if(fabs(_toMaster-_toMasterLag)>=fabs(_toMasterDiff/10.0)) _toMasterLag+=_toMasterDiff/10.0; // get & zero track buffer - float* trackBuffer = buffers->audio[Buffers::TRACK_0 + track]; + float* trackBuffer = buffers->audio[Buffers::RETURN_TRACK_0 + track]; memset( trackBuffer, 0, sizeof(float)*nframes ); // call process() up the chain From 8fd3e1e1bf81e1d793404a6693206c15a771709a Mon Sep 17 00:00:00 2001 From: Gerald Date: Tue, 4 Oct 2016 17:11:36 +0200 Subject: [PATCH 05/15] Made per track sends and returns an option --- src/buffers.hxx | 16 ---------------- src/diskreader.cxx | 11 +++++++++-- src/diskwriter.cxx | 3 ++- src/gui.cxx | 2 +- src/gui.hxx | 3 +++ src/jack.cxx | 30 +++++++++++++++++++++++------- 6 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/buffers.hxx b/src/buffers.hxx index 315af58..c5196d3 100644 --- a/src/buffers.hxx +++ b/src/buffers.hxx @@ -71,14 +71,6 @@ class Buffers SEND_TRACK_5, SEND_TRACK_6, SEND_TRACK_7, - JACK_SEND_TRACK_0, - JACK_SEND_TRACK_1, - JACK_SEND_TRACK_2, - JACK_SEND_TRACK_3, - JACK_SEND_TRACK_4, - JACK_SEND_TRACK_5, - JACK_SEND_TRACK_6, - JACK_SEND_TRACK_7, RETURN_TRACK_0, RETURN_TRACK_1, RETURN_TRACK_2, @@ -87,14 +79,6 @@ class Buffers RETURN_TRACK_5, RETURN_TRACK_6, RETURN_TRACK_7, - JACK_RETURN_TRACK_0, - JACK_RETURN_TRACK_1, - JACK_RETURN_TRACK_2, - JACK_RETURN_TRACK_3, - JACK_RETURN_TRACK_4, - JACK_RETURN_TRACK_5, - JACK_RETURN_TRACK_6, - JACK_RETURN_TRACK_7, BUFFER_COUNT, diff --git a/src/diskreader.cxx b/src/diskreader.cxx index eb4c6b8..9dbb257 100644 --- a/src/diskreader.cxx +++ b/src/diskreader.cxx @@ -101,8 +101,15 @@ int DiskReader::loadPreferences() { LUPPP_NOTE("No default controllers active."); } - - + + //Enable per track send and resturn jack ports? + cJSON* jackSendReturns=cJSON_GetObjectItem(preferencesJson,"enablePerTrackSendReturns"); + if(jackSendReturns) + { + gui->enableJackSendReturns=jackSendReturns->valueint; + if(gui->enableJackSendReturns) + LUPPP_NOTE("Enabling per track send and return ports"); + } cJSON_Delete( preferencesJson ); diff --git a/src/diskwriter.cxx b/src/diskwriter.cxx index 7193596..e17cdd9 100644 --- a/src/diskwriter.cxx +++ b/src/diskwriter.cxx @@ -520,7 +520,8 @@ void DiskWriter::writeDefaultConfigToUserHome() cJSON* defCtrls = cJSON_CreateArray(); cJSON_AddItemToObject( prfs, "defaultControllers", defCtrls ); - + // per track send and return option + cJSON_AddNumberToObject( prfs, "enablePerTrackSendReturns", 0 ); // test output on console // cout << endl << cJSON_Print( prfs ) << endl << endl; diff --git a/src/gui.cxx b/src/gui.cxx index d7fec92..dd0d0a3 100644 --- a/src/gui.cxx +++ b/src/gui.cxx @@ -363,7 +363,7 @@ static int cb_nsm_save ( char **out_msg, void *userdata ) Gui::Gui(const char* argZero) : samplerate( 0 ), window(1110,650), - + enableJackSendReturns(false), diskReader( new DiskReader() ), diskWriter( new DiskWriter() ) { diff --git a/src/gui.hxx b/src/gui.hxx index a2a011b..30b36e2 100644 --- a/src/gui.hxx +++ b/src/gui.hxx @@ -85,6 +85,9 @@ class Gui int samplerate; + ////Enable per track send and resturn jack ports + bool enableJackSendReturns; + int getWindowWidth(){return window.w();} nsm_client_t* getNsm(){return nsm;} diff --git a/src/jack.cxx b/src/jack.cxx index 252e996..456c414 100644 --- a/src/jack.cxx +++ b/src/jack.cxx @@ -198,17 +198,26 @@ Jack::Jack( std::string name ) : { /** Setup the tracks: * The TrackOutput gets a pointer to the next AudioProcessor to call: - * In this case, the track's Looper instance. + * This is either a JackSendReturn (providing send and return ports) + * or the track's Looper instance. + * This is an option in luppp.prfs **/ loopers.push_back( new Looper(i) ); + if(gui->enableJackSendReturns) + { + tracksendreturns.push_back(new JackSendReturn(i,loopers.back(),client)); + trackOutputs.push_back( new TrackOutput(i, tracksendreturns.back() ) ); + } + else + trackOutputs.push_back( new TrackOutput(i, loopers.back() ) ); - tracksendreturns.push_back(new JackSendReturn(i,loopers.back(),client)); - trackOutputs.push_back( new TrackOutput(i, tracksendreturns.back() ) ); - buffers.audio[Buffers::TRACK_0 + i] = new float[ buffers.nframes ]; buffers.audio[Buffers::SEND_TRACK_0+i]=new float[buffers.nframes]; - buffers.audio[Buffers::RETURN_TRACK_0+i]=new float[buffers.nframes]; + if(gui->enableJackSendReturns) + buffers.audio[Buffers::RETURN_TRACK_0+i]=new float[buffers.nframes]; + else + buffers.audio[Buffers::RETURN_TRACK_0+i]=buffers.audio[Buffers::SEND_TRACK_0+i]; timeManager->registerObserver( loopers.back() ); } @@ -273,7 +282,13 @@ Jack::~Jack() { delete [] buffers.audio[Buffers::TRACK_0+i]; delete [] buffers.audio[Buffers::SEND_TRACK_0+i]; - delete [] buffers.audio[Buffers::RETURN_TRACK_0+i]; + if(gui->enableJackSendReturns) + { + delete [] buffers.audio[Buffers::RETURN_TRACK_0+i]; + delete tracksendreturns[i]; + } + delete loopers[i]; + delete trackOutputs[i]; } } @@ -557,7 +572,8 @@ void Jack::clearInternalBuffers(int nframes) { memset(buffers.audio[Buffers::TRACK_0 + i],0,sizeof(float)*nframes); memset(buffers.audio[Buffers::SEND_TRACK_0 + i],0,sizeof(float)*nframes); - memset(buffers.audio[Buffers::RETURN_TRACK_0 + i],0,sizeof(float)*nframes); + if(gui->enableJackSendReturns) + memset(buffers.audio[Buffers::RETURN_TRACK_0 + i],0,sizeof(float)*nframes); } } From 10d0d48285855c930361612938b36ddd528f7344 Mon Sep 17 00:00:00 2001 From: Gerald Date: Thu, 10 Nov 2016 23:13:37 +0100 Subject: [PATCH 06/15] Added controls for send/return to gui (non-functional) --- src/gtrack.cxx | 34 +++++++++++++++++++++++++--------- src/gtrack.hxx | 6 +++++- src/gui.cxx | 4 ++-- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/gtrack.cxx b/src/gtrack.cxx index 81f2a17..002ec3c 100644 --- a/src/gtrack.cxx +++ b/src/gtrack.cxx @@ -28,6 +28,7 @@ static void gtrack_xsideDial_cb(Fl_Widget *w, void *data); static void gtrack_sendDial_cb(Fl_Widget *w, void *data); static void gtrack_send_cb(Fl_Widget *w, void *data); static void gtrack_record_cb(Fl_Widget *w, void *data); +static void gtrack_jacksendactivate_cb(Fl_Widget* w,void *data); GTrack::GTrack(int x, int y, int w, int h, const char* l ) : @@ -37,18 +38,22 @@ GTrack::GTrack(int x, int y, int w, int h, const char* l ) : radial( x+5, y+ 26, 100, 100, ""), clipSel(x + 5, y + 26 + 102, 100, 294,""), - - volBox(x+5, y+422, 100, 172, ""), - volume(x+66, y +425, 36, 166, ""), + jackSendBox(x+5, y+422, 100, 45, ""), + jackSendDial(x+21, y+422+8, 30,30, ""), + jackSendActivate(x+66, y+422+11, 36,25, "FX"), + volBox(x+5, y+422+50, 100, 172, ""), + volume(x+66, y +425+50, 36, 166, ""), + + - sendDial (x+21, y +430 + 0, 30, 30, ""), - sendActive (x+11, y +430 + 32, 50, 25, "Snd"), + sendDial (x+21, y +430 + 50, 30, 30, ""), + sendActive (x+11, y +430 + 82, 50, 25, "Snd"), - xsideDial (x+21, y +430 + 69, 30, 30, ""), - keyActive (x+11, y +430 + 101, 50, 25, "Key"), + xsideDial (x+21, y +430 + 69+50, 30, 30, ""), + keyActive (x+11, y +430 + 151, 50, 25, "Key"), - recordActive (x+11, y +430 + 132, 50, 25, "XRec") + recordActive (x+11, y +430 + 182, 50, 25, "XRec") { ID = privateID++; @@ -68,7 +73,10 @@ GTrack::GTrack(int x, int y, int w, int h, const char* l ) : recordActive.callback( gtrack_record_cb, this ); volume.callback( gtrack_vol_cb, this ); - + + jackSendActivate.setColor( 0, 0.6, 1 ); + jackSendActivate.callback(gtrack_jacksendactivate_cb,this); + jackSendDial.align(FL_ALIGN_INSIDE); //volBox.color( fl_rgb_color( 0,0,0 ) ); end(); // close the group @@ -171,3 +179,11 @@ void gtrack_record_cb(Fl_Widget *w, void *data) //printf("track %i record Arm %s\n", track->ID, b ? "off" : "on" ); } +void gtrack_jacksendactivate_cb(Fl_Widget* w,void *data) +{ + GTrack* track = (GTrack*) data; + Avtk::LightButton* d = (Avtk::LightButton*)w; + bool b=d->value(); + d->value(!b); +} + diff --git a/src/gtrack.hxx b/src/gtrack.hxx index 9741e0d..64bfdb0 100644 --- a/src/gtrack.hxx +++ b/src/gtrack.hxx @@ -78,12 +78,16 @@ class GTrack : public Fl_Group Avtk::RadialStatus radial; Avtk::ClipSelector clipSel; - + Avtk::Box volBox; Avtk::Volume volume; private: + Avtk::Box jackSendBox; + Avtk::Dial jackSendDial; + Avtk::LightButton jackSendActivate; + Avtk::Dial sendDial; Avtk::LightButton sendActive; diff --git a/src/gui.cxx b/src/gui.cxx index dd0d0a3..6f8bd2e 100644 --- a/src/gui.cxx +++ b/src/gui.cxx @@ -362,7 +362,7 @@ static int cb_nsm_save ( char **out_msg, void *userdata ) Gui::Gui(const char* argZero) : samplerate( 0 ), - window(1110,650), + window(1110,700), enableJackSendReturns(false), diskReader( new DiskReader() ), diskWriter( new DiskWriter() ) @@ -459,7 +459,7 @@ Gui::Gui(const char* argZero) : stringstream s; s << "Track " << i+1; //printf("track name %s\n", s.str().c_str() ); - tracks.push_back( new GTrack(8 + i * 118, 40, 110, 600, s.str().c_str() ) ); + tracks.push_back( new GTrack(8 + i * 118, 40, 110, 650, s.str().c_str() ) ); } master = new GMasterTrack(8 + i * 118, 40, 150, 600, "Master"); From 4023a50099ce82e1a0d2e3ea0b98f54fee98510d Mon Sep 17 00:00:00 2001 From: Gerald Date: Tue, 15 Nov 2016 18:11:28 +0100 Subject: [PATCH 07/15] implemented events for jack send return --- src/controller/controller.hxx | 3 +++ src/controller/genericmidi.cxx | 10 ++++++++++ src/controller/genericmidi.hxx | 3 +++ src/controller/guicontroller.cxx | 12 ++++++++++++ src/controller/guicontroller.hxx | 3 +++ src/controllerupdater.cxx | 14 +++++++++++++- src/controllerupdater.hxx | 3 +++ src/event.cxx | 4 ++++ src/event.hxx | 32 ++++++++++++++++++++++++++++++++ src/eventhandlerdsp.cxx | 18 ++++++++++++++++++ src/eventhandlergui.cxx | 14 ++++++++++++++ src/gtrack.cxx | 21 ++++++++++++++++++++- src/gtrack.hxx | 2 ++ src/jack.cxx | 14 ++++++++++++++ src/jack.hxx | 5 +++-- src/jacksendreturn.cxx | 23 ++++++++++++++++------- src/jacksendreturn.hxx | 7 +++++++ src/logic.cxx | 28 +++++++++++++++++++++++++++- src/logic.hxx | 4 +++- 19 files changed, 207 insertions(+), 13 deletions(-) diff --git a/src/controller/controller.hxx b/src/controller/controller.hxx index be5e993..cb6b36e 100644 --- a/src/controller/controller.hxx +++ b/src/controller/controller.hxx @@ -66,6 +66,9 @@ class Controller /// FX virtual void trackSend(int t, int send, float v){} virtual void trackSendActive(int t, int send, bool a){} + + virtual void trackJackSend(int t, float v){} + virtual void trackJackSendActivate(int t, bool a){} /// Time virtual void bpm(int bpm){} diff --git a/src/controller/genericmidi.cxx b/src/controller/genericmidi.cxx index d6ffb29..b8d71f1 100644 --- a/src/controller/genericmidi.cxx +++ b/src/controller/genericmidi.cxx @@ -209,6 +209,16 @@ void GenericMIDI::trackSendActive(int t, int send, bool a) } } +void GenericMIDI::trackJackSend(int t, float v) +{ + +} + +void GenericMIDI::trackJackSendActivate(int t, bool a) +{ + +} + /* void GenericMIDI::progress(int t, int s, float f) { diff --git a/src/controller/genericmidi.hxx b/src/controller/genericmidi.hxx index 11482bd..f5841b4 100644 --- a/src/controller/genericmidi.hxx +++ b/src/controller/genericmidi.hxx @@ -75,6 +75,9 @@ class GenericMIDI : public Controller, public MidiIO void trackSend(int t, int send, float v); void trackSendActive(int t, int send, bool a); + + virtual void trackJackSend(int t, float v); + virtual void trackJackSendActivate(int t, bool a); /// footswitch -> scene launch controls void setFootswitchToNextScene(int v); diff --git a/src/controller/guicontroller.cxx b/src/controller/guicontroller.cxx index 6ab9dc5..bc7a5c3 100644 --- a/src/controller/guicontroller.cxx +++ b/src/controller/guicontroller.cxx @@ -95,6 +95,18 @@ void LupppGUI::trackSendActive(int t, int send, bool a) writeToGuiRingbuffer( &e ); } +void LupppGUI::trackJackSend(int t, float v) +{ + EventTrackJackSend e(t,v); + writeToGuiRingbuffer(&e); +} + +void LupppGUI::trackJackSendActivate(int t, bool a) +{ + EventTrackJackSendActivate e(t,a); + writeToGuiRingbuffer(&e); +} + void LupppGUI::setSceneState(int t, int clip, GridLogic::State s) { EventGridState e( t, clip, s ); diff --git a/src/controller/guicontroller.hxx b/src/controller/guicontroller.hxx index 7dfab4c..f346b50 100644 --- a/src/controller/guicontroller.hxx +++ b/src/controller/guicontroller.hxx @@ -41,6 +41,9 @@ class LupppGUI : public Controller void trackSend(int t, int send, float r); void trackSendActive(int t, int send, bool a); + + virtual void trackJackSend(int t, float v); + virtual void trackJackSendActivate(int t, bool a); void bpm(int bpm); void tapTempo( bool b ); diff --git a/src/controllerupdater.cxx b/src/controllerupdater.cxx index d759185..546dcb5 100644 --- a/src/controllerupdater.cxx +++ b/src/controllerupdater.cxx @@ -117,7 +117,19 @@ void ControllerUpdater::setTrackSendActive(int t, int send, bool v) void ControllerUpdater::setTrackSend(int t, int send, float v) { for(unsigned int i = 0; i < c.size(); i++) - c.at(i)->trackSend(t, send, v); + c.at(i)->trackSend(t, send, v); +} + +void ControllerUpdater::setTrackJackSendActive(int t, bool v) +{ + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->trackJackSendActivate(t, v); +} + +void ControllerUpdater::setTrackJackSend(int t, float v) +{ + for(unsigned int i = 0; i < c.size(); i++) + c.at(i)->trackJackSend(t, v); } void ControllerUpdater::specialScene(int t, int scene) diff --git a/src/controllerupdater.hxx b/src/controllerupdater.hxx index aa2922d..216cb54 100644 --- a/src/controllerupdater.hxx +++ b/src/controllerupdater.hxx @@ -67,6 +67,9 @@ class ControllerUpdater void setTrackSceneProgress(int t, int s, float p); void setTrackSendActive(int t, int send, bool v); void setTrackSend(int t, int send, float v); + + void setTrackJackSendActive(int t, bool v); + void setTrackJackSend(int t, float v); void specialScene(int t, int scene); diff --git a/src/event.cxx b/src/event.cxx index e0337f8..d8e3c3c 100644 --- a/src/event.cxx +++ b/src/event.cxx @@ -28,6 +28,8 @@ const char* EventMasterInputToActive::prettyName = "master:input_to_active"; const char* EventTrackVol::prettyName = "track:volume"; const char* EventTrackSend::prettyName = "track:send"; const char* EventTrackSendActive::prettyName = "track:send_active"; +const char* EventTrackJackSend::prettyName = "track:jack_send"; +const char* EventTrackJackSendActivate::prettyName = "track:jack_send_activate"; const char* EventTrackRecordArm::prettyName = "track:record_arm"; const char* EventTimeBPM::prettyName = "tempo_bpm"; @@ -67,6 +69,8 @@ const char* Event::getPrettyName( int type ) case TRACK_VOLUME:{ return EventTrackVol::prettyName; } case TRACK_SEND:{ return EventTrackSend::prettyName; } case TRACK_SEND_ACTIVE:{ return EventTrackSendActive::prettyName; } + case TRACK_JACKSEND:{ return EventTrackJackSend::prettyName; } + case TRACK_JACKSEND_ACTIVATE:{ return EventTrackJackSendActivate::prettyName; } case TRACK_RECORD_ARM:{ return EventTrackRecordArm::prettyName; } case TIME_BPM:{ return EventTimeBPM::prettyName; } diff --git a/src/event.hxx b/src/event.hxx index 539c15a..e3efca1 100644 --- a/src/event.hxx +++ b/src/event.hxx @@ -84,6 +84,8 @@ namespace Event GRID_SELECT_NEW_CHOSEN, // a different clip is now "special" /// Track + TRACK_JACKSEND, + TRACK_JACKSEND_ACTIVATE, TRACK_SEND, TRACK_SEND_ACTIVE, TRACK_SIGNAL_LEVEL, @@ -471,6 +473,22 @@ class EventTrackSend : public EventBase EventTrackSend(int t, SEND_TYPE s, float v): track(t), send(s), value(v){} }; +class EventTrackJackSend : public EventBase +{ + public: + int type() { return int(TRACK_JACKSEND); } + uint32_t size() { return sizeof(EventTrackJackSend); } + static const char* prettyName; + const char* name(){ return prettyName; } + + int track; + + float value; + + EventTrackJackSend(){}; + EventTrackJackSend(int t, float v): track(t), value(v){} +}; + class EventTrackSendActive : public EventBase { public: @@ -487,6 +505,20 @@ class EventTrackSendActive : public EventBase EventTrackSendActive(int t, SEND_TYPE s, bool a): track(t), send(s), active(a){} }; +class EventTrackJackSendActivate : public EventBase +{ + public: + int type() { return int(TRACK_JACKSEND_ACTIVATE); } + uint32_t size() { return sizeof(EventTrackJackSendActivate); } + static const char* prettyName; + const char* name(){ return prettyName; } + + int track; + bool active; + + EventTrackJackSendActivate(){}; + EventTrackJackSendActivate(int t, bool a): track(t), active(a){} +}; class EventLooperState : public EventBase { public: diff --git a/src/eventhandlerdsp.cxx b/src/eventhandlerdsp.cxx index 7a0783d..9a165b0 100644 --- a/src/eventhandlerdsp.cxx +++ b/src/eventhandlerdsp.cxx @@ -301,6 +301,24 @@ void handleDspEvents() jack->bindingSend = ev.send; jack->bindingActive = ev.active; } break; } + + case Event::TRACK_JACKSEND_ACTIVATE: { + if ( availableRead >= sizeof(EventTrackJackSendActivate) ) { + EventTrackJackSendActivate ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSendActivate) ); + jack->getLogic()->trackJackSendActivate(ev.track,ev.active); + jack->bindingTrack = ev.track; + + jack->bindingActive = ev.active; + } break; } + + case Event::TRACK_JACKSEND: { + if ( availableRead >= sizeof(EventTrackJackSend) ) { + EventTrackJackSend ev; + jack_ringbuffer_read( rbToDsp, (char*)&ev, sizeof(EventTrackJackSend) ); + jack->getLogic()->trackJackSend(ev.track,ev.value); + jack->bindingTrack = ev.track; + } break; } case Event::TRACK_SEND: { if ( availableRead >= sizeof(EventTrackSend) ) { diff --git a/src/eventhandlergui.cxx b/src/eventhandlergui.cxx index b529b9e..467cd7b 100644 --- a/src/eventhandlergui.cxx +++ b/src/eventhandlergui.cxx @@ -253,6 +253,20 @@ void handleGuiEvents() gui->getTrack(ev.track)->setXSide( ev.value ); } } break; } + + case Event::TRACK_JACKSEND: { + if ( availableRead >= sizeof(EventTrackJackSend) ) { + EventTrackJackSend ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSend) ); + gui->getTrack(ev.track)->setJackSend(ev.value); + } break; } + + case Event::TRACK_JACKSEND_ACTIVATE: { + if ( availableRead >= sizeof(EventTrackJackSendActivate) ) { + EventTrackJackSendActivate ev; + jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackJackSendActivate) ); + gui->getTrack(ev.track)->setJackSendActivate(ev.active); + } break; } case Event::TRACK_SEND_ACTIVE: { if ( availableRead >= sizeof(EventTrackSendActive) ) { diff --git a/src/gtrack.cxx b/src/gtrack.cxx index 002ec3c..c267127 100644 --- a/src/gtrack.cxx +++ b/src/gtrack.cxx @@ -74,7 +74,7 @@ GTrack::GTrack(int x, int y, int w, int h, const char* l ) : volume.callback( gtrack_vol_cb, this ); - jackSendActivate.setColor( 0, 0.6, 1 ); + jackSendActivate.setColor( 1, 1, 0 ); jackSendActivate.callback(gtrack_jacksendactivate_cb,this); jackSendDial.align(FL_ALIGN_INSIDE); //volBox.color( fl_rgb_color( 0,0,0 ) ); @@ -97,6 +97,15 @@ void GTrack::setSendActive(bool a){ sendActive.value( a ); } void GTrack::setKeyActive(bool a){ keyActive.value( a ); } void GTrack::setRecordActive(bool a){ recordActive.value( a ); } +void GTrack::setJackSend(float s) +{ + jackSendDial.value(s); +} + +void GTrack::setJackSendActivate(bool a) +{ + jackSendActivate.value(a); +} void gtrack_sendDial_cb(Fl_Widget *w, void *data) { @@ -185,5 +194,15 @@ void gtrack_jacksendactivate_cb(Fl_Widget* w,void *data) Avtk::LightButton* d = (Avtk::LightButton*)w; bool b=d->value(); d->value(!b); + if ( b < 0.5 ) + { + EventTrackJackSendActivate e( track->ID, 1.0f ); + writeToDspRingbuffer( &e ); + } + else + { + EventTrackJackSendActivate e( track->ID, 0.0f ); + writeToDspRingbuffer( &e ); + } } diff --git a/src/gtrack.hxx b/src/gtrack.hxx index 64bfdb0..016424d 100644 --- a/src/gtrack.hxx +++ b/src/gtrack.hxx @@ -70,6 +70,8 @@ class GTrack : public Fl_Group void setKeyActive(bool a); void setRecordActive(bool a); + void setJackSend(float s); + void setJackSendActivate(bool a); int ID; diff --git a/src/jack.cxx b/src/jack.cxx index 456c414..d3463c6 100644 --- a/src/jack.cxx +++ b/src/jack.cxx @@ -326,6 +326,20 @@ TrackOutput* Jack::getTrackOutput(int t) return 0; } +JackSendReturn* Jack::getJackSendReturn(int t) +{ + if ( t >= 0 && t < NTRACKS ) + return tracksendreturns.at(t); +#ifdef DEBUG_TRACKS + else + { + printf( "Jack::getTrackOutput() returning 0x0: invalid track requested!\n" ); + } +#endif + + return 0; +} + Looper* Jack::getLooper(int t) { diff --git a/src/jack.hxx b/src/jack.hxx index bef1f2f..f0796fa 100644 --- a/src/jack.hxx +++ b/src/jack.hxx @@ -111,8 +111,9 @@ class Jack int bindingScene; int bindingSend; int bindingActive; - - private: + + JackSendReturn *getJackSendReturn(int t); +private: jack_client_t* client; Buffers buffers; diff --git a/src/jacksendreturn.cxx b/src/jacksendreturn.cxx index b66f42f..8ab7a47 100644 --- a/src/jacksendreturn.cxx +++ b/src/jacksendreturn.cxx @@ -9,6 +9,7 @@ JackSendReturn::JackSendReturn(int trackid, AudioProcessor *prev, jack_client_t m_sendport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput,0); sprintf(name, "Return_track_%d\0",trackid); m_returnport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0); + m_active=false; } void JackSendReturn::process(unsigned int nframes, Buffers *buffers) @@ -22,17 +23,25 @@ void JackSendReturn::process(unsigned int nframes, Buffers *buffers) float* ret=(float*)jack_port_get_buffer(m_returnport,(jack_nframes_t)nframes); //Copy result of previous AudioProcessor to send port - memcpy(send,buffers->audio[Buffers::SEND_TRACK_0+m_trackid],nframes*sizeof(float)); + //memcpy(send,buffers->audio[Buffers::SEND_TRACK_0+m_trackid],nframes*sizeof(float)); + for(int i=0;iaudio[Buffers::SEND_TRACK_0+m_trackid][i]; - //Get connection status - bool connected=jack_port_connected(m_returnport); - //Is return port connected? - //Yes then grab the audio data from the connected port - //No: get the audio from the previous AudioProcessor - if(connected) + + if(m_active) memcpy(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid],ret,nframes*sizeof(float)); else memcpy(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid], buffers->audio[Buffers::SEND_TRACK_0+m_trackid],nframes*sizeof(float)); } + +void JackSendReturn::activate(bool act) +{ + m_active=act; +} + +void JackSendReturn::sendVolume(float vol) +{ + m_sendvol=vol; +} diff --git a/src/jacksendreturn.hxx b/src/jacksendreturn.hxx index 3d31ca2..262db94 100644 --- a/src/jacksendreturn.hxx +++ b/src/jacksendreturn.hxx @@ -36,7 +36,14 @@ public: //The process callback virtual void process(unsigned int nframes, Buffers* buffers); + //Activate the return chain. When m_active=true then Buffers::RETURN_TRACK_0+m_trackid gets the data + //from the return port. The send port always send the incoming data + void activate(bool act); + void sendVolume(float vol); + private: + bool m_active; + float m_sendvol; jack_port_t* m_sendport; jack_port_t* m_returnport; int m_trackid; diff --git a/src/logic.cxx b/src/logic.cxx index 783267a..84fd3ba 100644 --- a/src/logic.cxx +++ b/src/logic.cxx @@ -25,7 +25,7 @@ extern Jack* jack; #include "controllerupdater.hxx" #include "trackoutput.hxx" #include "metronome.hxx" - +#include "jacksendreturn.hxx" Logic::Logic() { @@ -128,6 +128,32 @@ void Logic::trackSend(int t, int send, float v) } } +void Logic::trackJackSendActivate(int t, bool active) +{ + if ( t >= 0 && t < NTRACKS ) + { + jack->getJackSendReturn(t)->activate(active); + jack->getControllerUpdater()->setTrackJackSendActive( t, active ); + } + else + { + LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); + } +} + +void Logic::trackJackSend(int t, float vol) +{ + if ( t >= 0 && t < NTRACKS ) + { + jack->getJackSendReturn(t)->sendVolume(vol); + jack->getControllerUpdater()->setTrackJackSend( t, vol ); + } + else + { + LUPPP_WARN("invalid track number %i: check controller map has \"track\" field.", t ); + } +} + void Logic::looperClipLenght(int t, int s, int l) { if ( t >= 0 && t < NTRACKS ) diff --git a/src/logic.hxx b/src/logic.hxx index 365dbba..5f15c1f 100644 --- a/src/logic.hxx +++ b/src/logic.hxx @@ -56,7 +56,9 @@ class Logic void trackRecordArm(int track, bool armed); void trackSendActive(int track, int send, bool active); void trackSend(int track, int send, float value); - + + void trackJackSendActivate(int t, bool active); + void trackJackSend(int t, float vol); void looperUseAsTempo(int track, int scene); void looperClipLenght(int track, int scene, int lenght); }; From 1e07878b5d4f47e21dafb686ce8eefa36fc2caa8 Mon Sep 17 00:00:00 2001 From: Gerald Date: Tue, 15 Nov 2016 23:00:15 +0100 Subject: [PATCH 08/15] added callback for jacksend knob --- src/gtrack.cxx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/gtrack.cxx b/src/gtrack.cxx index c267127..f6850d2 100644 --- a/src/gtrack.cxx +++ b/src/gtrack.cxx @@ -27,6 +27,7 @@ static void gtrack_key_cb(Fl_Widget *w, void *data); static void gtrack_xsideDial_cb(Fl_Widget *w, void *data); static void gtrack_sendDial_cb(Fl_Widget *w, void *data); static void gtrack_send_cb(Fl_Widget *w, void *data); +static void gtrack_jacksend_cb(Fl_Widget *w, void *data); static void gtrack_record_cb(Fl_Widget *w, void *data); static void gtrack_jacksendactivate_cb(Fl_Widget* w,void *data); @@ -77,6 +78,7 @@ GTrack::GTrack(int x, int y, int w, int h, const char* l ) : jackSendActivate.setColor( 1, 1, 0 ); jackSendActivate.callback(gtrack_jacksendactivate_cb,this); jackSendDial.align(FL_ALIGN_INSIDE); + jackSendDial.callback(gtrack_jacksend_cb,this); //volBox.color( fl_rgb_color( 0,0,0 ) ); end(); // close the group @@ -104,7 +106,7 @@ void GTrack::setJackSend(float s) void GTrack::setJackSendActivate(bool a) { - jackSendActivate.value(a); + //jackSendActivate.value(a); } void gtrack_sendDial_cb(Fl_Widget *w, void *data) @@ -170,6 +172,16 @@ void gtrack_send_cb(Fl_Widget *w, void *data) } //printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" ); } +void gtrack_jacksend_cb(Fl_Widget *w, void *data) +{ + GTrack* track = (GTrack*) data; + Avtk::Dial* d = (Avtk::Dial*)w; + float v = d->value(); + EventTrackJackSend ev(track->ID,v); + writeToDspRingbuffer(&ev); + + //printf("track %i reverb send %s\n", track->ID, b ? "true" : "false" ); +} void gtrack_record_cb(Fl_Widget *w, void *data) { GTrack* track = (GTrack*) data; @@ -193,7 +205,7 @@ void gtrack_jacksendactivate_cb(Fl_Widget* w,void *data) GTrack* track = (GTrack*) data; Avtk::LightButton* d = (Avtk::LightButton*)w; bool b=d->value(); - d->value(!b); + // d->value(!b); if ( b < 0.5 ) { EventTrackJackSendActivate e( track->ID, 1.0f ); From 83d36b9e4744373c8e28c423990f612e6188511a Mon Sep 17 00:00:00 2001 From: Gerald Date: Wed, 16 Nov 2016 21:56:06 +0100 Subject: [PATCH 09/15] Fixed issue with FX button --- src/gtrack.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gtrack.cxx b/src/gtrack.cxx index f6850d2..ad09901 100644 --- a/src/gtrack.cxx +++ b/src/gtrack.cxx @@ -106,7 +106,7 @@ void GTrack::setJackSend(float s) void GTrack::setJackSendActivate(bool a) { - //jackSendActivate.value(a); + jackSendActivate.value(a); } void gtrack_sendDial_cb(Fl_Widget *w, void *data) From d3048154b087bcdbe96e056e8a7072b619b5c649 Mon Sep 17 00:00:00 2001 From: Gerald Date: Wed, 16 Nov 2016 22:28:53 +0100 Subject: [PATCH 10/15] fixed noise issue on send, glitch remains :( --- src/jacksendreturn.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/jacksendreturn.cxx b/src/jacksendreturn.cxx index 8ab7a47..4be5e93 100644 --- a/src/jacksendreturn.cxx +++ b/src/jacksendreturn.cxx @@ -23,9 +23,10 @@ void JackSendReturn::process(unsigned int nframes, Buffers *buffers) float* ret=(float*)jack_port_get_buffer(m_returnport,(jack_nframes_t)nframes); //Copy result of previous AudioProcessor to send port - //memcpy(send,buffers->audio[Buffers::SEND_TRACK_0+m_trackid],nframes*sizeof(float)); +// memcpy(send,buffers->audio[Buffers::SEND_TRACK_0+m_trackid],nframes*sizeof(float)); +// memset(send,0,nframes*sizeof(float)); for(int i=0;iaudio[Buffers::SEND_TRACK_0+m_trackid][i]; + send[i]=m_sendvol*buffers->audio[Buffers::SEND_TRACK_0+m_trackid][i]; if(m_active) From efa6d9054c82217cd606ff8216c9aa8c26efb37b Mon Sep 17 00:00:00 2001 From: Gerald Date: Thu, 17 Nov 2016 20:15:47 +0100 Subject: [PATCH 11/15] fixed some glitch issues, glitch on send_track_0 persists :( --- src/jack.cxx | 1 + src/jacksendreturn.cxx | 38 ++++++++++++++++++++++++++++---------- src/jacksendreturn.hxx | 1 + src/timemanager.cxx | 6 ++++-- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/jack.cxx b/src/jack.cxx index d3463c6..41318f3 100644 --- a/src/jack.cxx +++ b/src/jack.cxx @@ -393,6 +393,7 @@ int Jack::process (jack_nframes_t nframes) buffers.audio[Buffers::JACK_MASTER_OUT_R] = (float*)jack_port_get_buffer( masterOutputR , nframes ); buffers.audio[Buffers::JACK_SIDECHAIN_KEY] = (float*)jack_port_get_buffer(sidechainKeyOutput,nframes); buffers.audio[Buffers::JACK_SIDECHAIN_SIGNAL]=(float*)jack_port_get_buffer(sidechainSignalOutput,nframes); + // clear the buffers memset( buffers.audio[Buffers::JACK_MASTER_OUT_L] , 0, sizeof(float) * nframes ); diff --git a/src/jacksendreturn.cxx b/src/jacksendreturn.cxx index 4be5e93..d8feff8 100644 --- a/src/jacksendreturn.cxx +++ b/src/jacksendreturn.cxx @@ -1,5 +1,7 @@ #include "jacksendreturn.hxx" #include "jack.hxx" +#include +#include extern Jack* jack; JackSendReturn::JackSendReturn(int trackid, AudioProcessor *prev, jack_client_t *client) :m_trackid(trackid), m_previousProcessor(prev) @@ -10,30 +12,46 @@ JackSendReturn::JackSendReturn(int trackid, AudioProcessor *prev, jack_client_t sprintf(name, "Return_track_%d\0",trackid); m_returnport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0); m_active=false; + m_counter=0; } void JackSendReturn::process(unsigned int nframes, Buffers *buffers) { //Reset send buffer - memset(buffers->audio[Buffers::SEND_TRACK_0+m_trackid],0,nframes*sizeof(float)); + int offset=m_counter%(buffers->nframes); + float* sendtrack=&(buffers->audio[Buffers::SEND_TRACK_0+m_trackid][0]); + + + float* rettrack=&(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid][0]); + + memset(sendtrack,0,nframes*sizeof(float)); //Process previous AudioProcessor m_previousProcessor->process(nframes,buffers); - float* send=(float*)jack_port_get_buffer(m_sendport,(jack_nframes_t)nframes); - float* ret=(float*)jack_port_get_buffer(m_returnport,(jack_nframes_t)nframes); + float* send=(float*)jack_port_get_buffer(m_sendport,(jack_nframes_t)(buffers->nframes)); + float* ret=(float*)jack_port_get_buffer(m_returnport,(jack_nframes_t)(buffers->nframes)); + if(offset) + { + send+=offset; + ret+=offset; + } - //Copy result of previous AudioProcessor to send port -// memcpy(send,buffers->audio[Buffers::SEND_TRACK_0+m_trackid],nframes*sizeof(float)); -// memset(send,0,nframes*sizeof(float)); for(int i=0;iaudio[Buffers::SEND_TRACK_0+m_trackid][i]; + send[i]=m_sendvol*sendtrack[i]; +// if(nframes!=buffers->nframes) +// { +// cout<nframes); if(m_active) - memcpy(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid],ret,nframes*sizeof(float)); + memcpy(rettrack,ret,nframes*sizeof(float)); else - memcpy(buffers->audio[Buffers::RETURN_TRACK_0+m_trackid], - buffers->audio[Buffers::SEND_TRACK_0+m_trackid],nframes*sizeof(float)); + memcpy(rettrack, + sendtrack,nframes*sizeof(float)); + m_counter+=nframes; } diff --git a/src/jacksendreturn.hxx b/src/jacksendreturn.hxx index 262db94..813eacf 100644 --- a/src/jacksendreturn.hxx +++ b/src/jacksendreturn.hxx @@ -48,6 +48,7 @@ private: jack_port_t* m_returnport; int m_trackid; AudioProcessor* m_previousProcessor; + int m_counter; }; diff --git a/src/timemanager.cxx b/src/timemanager.cxx index db728bf..edb9786 100644 --- a/src/timemanager.cxx +++ b/src/timemanager.cxx @@ -223,7 +223,8 @@ void TimeManager::process(Buffers* buffers) } // process before beat: - jack->processFrames( before ); + if(before) + jack->processFrames( before ); // handle beat: // inform observers of new beat FIRST @@ -246,7 +247,8 @@ void TimeManager::process(Buffers* buffers) // process after // we need to clear internal buffers in order to write *after* frames to them jack->clearInternalBuffers(nframes); - jack->processFrames( after ); + if(after) + jack->processFrames( after ); // write new beat to UI (bar info currently not used) EventTimeBarBeat e( barCounter, beatCounter ); From bb91ac0e5888aea96ff2903b4f294188bc878ec8 Mon Sep 17 00:00:00 2001 From: Gerald Date: Sat, 19 Nov 2016 00:35:43 +0100 Subject: [PATCH 12/15] MAJOR change: send/returns are always there. New feature: per track output (optional, use enablePerTrackOutput in luppp.prfs) --- src/buffers.hxx | 9 +++++++ src/diskreader.cxx | 23 ++++++++++++++---- src/diskwriter.cxx | 3 +++ src/gtrack.cxx | 10 ++++++++ src/gtrack.hxx | 4 +++- src/gui.cxx | 2 +- src/gui.hxx | 2 +- src/jack.cxx | 58 +++++++++++++++++++++++++++++++-------------- src/jack.hxx | 3 ++- src/trackoutput.cxx | 6 ++++- 10 files changed, 92 insertions(+), 28 deletions(-) diff --git a/src/buffers.hxx b/src/buffers.hxx index c5196d3..0469263 100644 --- a/src/buffers.hxx +++ b/src/buffers.hxx @@ -80,6 +80,15 @@ class Buffers RETURN_TRACK_6, RETURN_TRACK_7, + JACK_TRACK_0, + JACK_TRACK_1, + JACK_TRACK_2, + JACK_TRACK_3, + JACK_TRACK_4, + JACK_TRACK_5, + JACK_TRACK_6, + JACK_TRACK_7, + BUFFER_COUNT, }; diff --git a/src/diskreader.cxx b/src/diskreader.cxx index 9dbb257..cfe9cca 100644 --- a/src/diskreader.cxx +++ b/src/diskreader.cxx @@ -103,12 +103,12 @@ int DiskReader::loadPreferences() } //Enable per track send and resturn jack ports? - cJSON* jackSendReturns=cJSON_GetObjectItem(preferencesJson,"enablePerTrackSendReturns"); - if(jackSendReturns) + cJSON* jackPerTrackOutput=cJSON_GetObjectItem(preferencesJson,"enablePerTrackOutput"); + if(jackPerTrackOutput) { - gui->enableJackSendReturns=jackSendReturns->valueint; - if(gui->enableJackSendReturns) - LUPPP_NOTE("Enabling per track send and return ports"); + gui->enablePerTrackOutput=jackPerTrackOutput->valueint; + if(gui->enablePerTrackOutput) + LUPPP_NOTE("Enabling per track output ports"); } @@ -638,6 +638,19 @@ int DiskReader::readTracks() writeToDspRingbuffer( &e2 ); writeToDspRingbuffer( &e3 ); } + + cJSON* jacksend = cJSON_GetObjectItem( track, "jacksendAmount"); + cJSON* jacksendActive = cJSON_GetObjectItem( track, "jacksendActive"); + if(jacksend) + { + EventTrackJackSend ev(t,jacksend->valuedouble); + writeToDspRingbuffer(&ev); + } + if(jacksendActive) + { + EventTrackJackSendActivate ev(t,jacksendActive->valueint); + writeToDspRingbuffer(&ev); + } } }// if track } // nTracks loop diff --git a/src/diskwriter.cxx b/src/diskwriter.cxx index e17cdd9..690dc7c 100644 --- a/src/diskwriter.cxx +++ b/src/diskwriter.cxx @@ -431,6 +431,9 @@ int DiskWriter::writeSession() cJSON_AddNumberToObject( track, "sendAmount" , gui->getTrack(t)->getSend() ); cJSON_AddNumberToObject( track, "sendActive" , gui->getTrack(t)->getSendActive() ); + + cJSON_AddNumberToObject( track, "jacksendAmount" , gui->getTrack(t)->getJackSend() ); + cJSON_AddNumberToObject( track, "jacksendActive" , gui->getTrack(t)->getJackSendActivate() ); cJSON_AddNumberToObject( track, "xsideAmount", gui->getTrack(t)->getXSide() ); cJSON_AddNumberToObject( track, "keyActive" , gui->getTrack(t)->getKeyActive() ); diff --git a/src/gtrack.cxx b/src/gtrack.cxx index ad09901..be1a809 100644 --- a/src/gtrack.cxx +++ b/src/gtrack.cxx @@ -109,6 +109,16 @@ void GTrack::setJackSendActivate(bool a) jackSendActivate.value(a); } +float GTrack::getJackSend() +{ + return jackSendDial.value(); +} + +bool GTrack::getJackSendActivate() +{ + return jackSendActivate.value(); +} + void gtrack_sendDial_cb(Fl_Widget *w, void *data) { GTrack* track = (GTrack*) data; diff --git a/src/gtrack.hxx b/src/gtrack.hxx index 016424d..a1ac8c1 100644 --- a/src/gtrack.hxx +++ b/src/gtrack.hxx @@ -85,7 +85,9 @@ class GTrack : public Fl_Group Avtk::Volume volume; - private: + float getJackSend(); + bool getJackSendActivate(); +private: Avtk::Box jackSendBox; Avtk::Dial jackSendDial; Avtk::LightButton jackSendActivate; diff --git a/src/gui.cxx b/src/gui.cxx index 6f8bd2e..6e9c89e 100644 --- a/src/gui.cxx +++ b/src/gui.cxx @@ -363,7 +363,7 @@ static int cb_nsm_save ( char **out_msg, void *userdata ) Gui::Gui(const char* argZero) : samplerate( 0 ), window(1110,700), - enableJackSendReturns(false), + enablePerTrackOutput(false), diskReader( new DiskReader() ), diskWriter( new DiskWriter() ) { diff --git a/src/gui.hxx b/src/gui.hxx index 30b36e2..9a49fd1 100644 --- a/src/gui.hxx +++ b/src/gui.hxx @@ -86,7 +86,7 @@ class Gui int samplerate; ////Enable per track send and resturn jack ports - bool enableJackSendReturns; + bool enablePerTrackOutput; int getWindowWidth(){return window.w();} diff --git a/src/jack.cxx b/src/jack.cxx index 41318f3..23a010d 100644 --- a/src/jack.cxx +++ b/src/jack.cxx @@ -204,22 +204,28 @@ Jack::Jack( std::string name ) : **/ loopers.push_back( new Looper(i) ); - if(gui->enableJackSendReturns) - { - tracksendreturns.push_back(new JackSendReturn(i,loopers.back(),client)); - trackOutputs.push_back( new TrackOutput(i, tracksendreturns.back() ) ); - } - else - trackOutputs.push_back( new TrackOutput(i, loopers.back() ) ); + tracksendreturns.push_back(new JackSendReturn(i,loopers.back(),client)); + trackOutputs.push_back( new TrackOutput(i, tracksendreturns.back() ) ); + buffers.audio[Buffers::TRACK_0 + i] = new float[ buffers.nframes ]; buffers.audio[Buffers::SEND_TRACK_0+i]=new float[buffers.nframes]; - if(gui->enableJackSendReturns) - buffers.audio[Buffers::RETURN_TRACK_0+i]=new float[buffers.nframes]; - else - buffers.audio[Buffers::RETURN_TRACK_0+i]=buffers.audio[Buffers::SEND_TRACK_0+i]; + buffers.audio[Buffers::RETURN_TRACK_0+i]=new float[buffers.nframes]; + + timeManager->registerObserver( loopers.back() ); + if(gui->enablePerTrackOutput) + { + char name[50]; + sprintf(name,"track_%d\0",i); + trackJackOutputPorts[i]=jack_port_register( client, + name, + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, + 0 ); + + } } /// setup DSP instances @@ -282,11 +288,8 @@ Jack::~Jack() { delete [] buffers.audio[Buffers::TRACK_0+i]; delete [] buffers.audio[Buffers::SEND_TRACK_0+i]; - if(gui->enableJackSendReturns) - { - delete [] buffers.audio[Buffers::RETURN_TRACK_0+i]; - delete tracksendreturns[i]; - } + delete [] buffers.audio[Buffers::RETURN_TRACK_0+i]; + delete tracksendreturns[i]; delete loopers[i]; delete trackOutputs[i]; } @@ -393,6 +396,12 @@ int Jack::process (jack_nframes_t nframes) buffers.audio[Buffers::JACK_MASTER_OUT_R] = (float*)jack_port_get_buffer( masterOutputR , nframes ); buffers.audio[Buffers::JACK_SIDECHAIN_KEY] = (float*)jack_port_get_buffer(sidechainKeyOutput,nframes); buffers.audio[Buffers::JACK_SIDECHAIN_SIGNAL]=(float*)jack_port_get_buffer(sidechainSignalOutput,nframes); + if(gui->enablePerTrackOutput) + { + for(int t=0;tenablePerTrackOutput) + { + for(int t=0;tenablePerTrackOutput) + { + for(int t=0;tenableJackSendReturns) - memset(buffers.audio[Buffers::RETURN_TRACK_0 + i],0,sizeof(float)*nframes); + + memset(buffers.audio[Buffers::RETURN_TRACK_0 + i],0,sizeof(float)*nframes); } } diff --git a/src/jack.hxx b/src/jack.hxx index f0796fa..050052e 100644 --- a/src/jack.hxx +++ b/src/jack.hxx @@ -157,6 +157,7 @@ private: jack_port_t* masterInput; jack_port_t* masterOutputL; jack_port_t* masterOutputR; + jack_port_t* masterReturnL; jack_port_t* masterReturnR; jack_port_t* headphonesPort; @@ -167,7 +168,7 @@ private: jack_port_t* masterMidiInput; - vector trackJackOutputPorts; + jack_port_t* trackJackOutputPorts[NTRACKS]; // JACK callback int process (jack_nframes_t); diff --git a/src/trackoutput.cxx b/src/trackoutput.cxx index 549bfbd..424c554 100644 --- a/src/trackoutput.cxx +++ b/src/trackoutput.cxx @@ -135,6 +135,9 @@ void TrackOutput::process(unsigned int nframes, Buffers* buffers) float* masterL = buffers->audio[Buffers::MASTER_OUT_L]; float* masterR = buffers->audio[Buffers::MASTER_OUT_R]; + + + float* jackoutput = buffers->audio[Buffers::JACK_TRACK_0+track]; for(unsigned int i = 0; i < nframes; i++) { @@ -144,7 +147,8 @@ void TrackOutput::process(unsigned int nframes, Buffers* buffers) // post-sidechain *moves* signal between "before/after" ducking, not add! masterL[i] += tmp * _toMasterLag * (1-_toPostSidechain); masterR[i] += tmp * _toMasterLag * (1-_toPostSidechain); - + if(jackoutput) + jackoutput[i] = tmp * _toMasterLag * (1-_toPostSidechain); if ( _toPostfaderActive ) reverb[i] += tmp * _toReverb * _toMasterLag; From 7ff4d83bb315e52dfe03a4fa5df6c5f812714892 Mon Sep 17 00:00:00 2001 From: Gerald Date: Mon, 21 Nov 2016 19:49:53 +0100 Subject: [PATCH 13/15] Added metronomeActiveByDefault and metronomeDefaultVolume to the preferences to allow starting luppp with active metronome --- src/diskreader.cxx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/diskreader.cxx b/src/diskreader.cxx index cfe9cca..b50d36c 100644 --- a/src/diskreader.cxx +++ b/src/diskreader.cxx @@ -110,6 +110,23 @@ int DiskReader::loadPreferences() if(gui->enablePerTrackOutput) LUPPP_NOTE("Enabling per track output ports"); } + + //Metronome on by default? + cJSON* metronomeActive=cJSON_GetObjectItem(preferencesJson,"metronomeActiveByDefault"); + if(metronomeActive) + { + EventMetronomeActive e = EventMetronomeActive( metronomeActive->valueint); + writeToDspRingbuffer( &e ); + } + + //Metronome default volume + cJSON* metronomeVol=cJSON_GetObjectItem(preferencesJson,"metronomeDefaultVolume"); + if(metronomeVol) + { + float vol=metronomeVol->valueint/100.0f; + EventMetronomeVolume e(vol); + writeToDspRingbuffer(&e); + } cJSON_Delete( preferencesJson ); From f8d5ccf34de4d1604ed2772f2beb1e79b9853b98 Mon Sep 17 00:00:00 2001 From: Harry van Haaren Date: Thu, 24 Nov 2016 23:29:37 +0000 Subject: [PATCH 14/15] Fixing master output section Looks better than before, but still not ideal. Perhaps adding a global (master) FX send to JACK could fill the space? Or else re-layout the items (labels under dials?) to fill void. --- src/gmastertrack.cxx | 19 +++++++++---------- src/gui.cxx | 14 +------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/gmastertrack.cxx b/src/gmastertrack.cxx index fb55e9d..35da00b 100644 --- a/src/gmastertrack.cxx +++ b/src/gmastertrack.cxx @@ -194,6 +194,7 @@ static void gmastertrack_button_callback(Fl_Widget *w, void *data) } } +#define OFST 33 GMasterTrack::GMasterTrack(int x, int y, int w, int h, const char* l ) : Fl_Group(x, y, w, h), title( strdup(l) ), @@ -203,14 +204,14 @@ GMasterTrack::GMasterTrack(int x, int y, int w, int h, const char* l ) : clipSel(x + 5, y + 26 + 102, 140, 294,"", true), source(x+5, y+26, 140, 100, ""), - volBox(x+5, y+422, 140, 172, ""), + volBox(x+5, y+422, 140, 232, ""), - transport ( x + w * 2/4.f - 18, y + 426 + 26 * 0, 44,24, "Stop" ), - tapTempo ( x + w * 2/4.f - 18, y + 426 + 26 * 1, 44,24, "Tap" ), - metronomeButton( x + w * 2/4.f - 18, y + 426 + 26 * 2, 44,24,"Metro"), + transport ( x + w * 2/4.f - 18, y + 436 + OFST * 0, 44,28, "Stop" ), + tapTempo ( x + w * 2/4.f - 18, y + 436 + OFST * 1, 44,28, "Tap" ), + metronomeButton( x + w * 2/4.f - 18, y + 436 + OFST * 2, 44,28,"Metro"), - tempoDial ( x + w * 2/4.f - 18, y + 426 + 41 * 2, 45, 36,"BPM"), - returnVol ( x + w * 2/4.f - 18, y + 426 + 41 * 3, 45, 36,"Return"), + tempoDial ( x + w * 2/4.f - 18, y + 436 + OFST * 3.5, 45, 38,"BPM"), + returnVol ( x + w * 2/4.f - 18, y + 436 + OFST * 5, 45, 38,"Return"), inputVolume(x + 9,y + 26 + 4, w - 18, 30,""), @@ -223,7 +224,7 @@ GMasterTrack::GMasterTrack(int x, int y, int w, int h, const char* l ) : inputToMix (x + w*0.8-20,y + 28 + 68, 40, 26,"Mix"), inputToMixVol(x + w*0.8-15,y + 28 + 36, 30, 30,""), - volume(x+106, y +425, 36, 166, "") + volume(x+106, y +425, 36, 216, "") { ID = privateID++; @@ -254,8 +255,6 @@ GMasterTrack::GMasterTrack(int x, int y, int w, int h, const char* l ) : inputToMix.callback ( gmastertrack_mixButton_callback, 0 ); inputToMixVol.callback ( gmastertrack_mixVol_callback, 0 ); - - tempoDial.align( FL_ALIGN_CENTER ); returnVol.value( 1.f ); @@ -264,7 +263,7 @@ GMasterTrack::GMasterTrack(int x, int y, int w, int h, const char* l ) : for(int i = 0; i < 4; i++) { - beatLights[i] = new Avtk::LightButton( x + 11, y + 427 + 41 * i, 38, 38, "" ); + beatLights[i] = new Avtk::LightButton( x + 10, y + 437 + 54 * i, 40, 42, "" ); } beatLights[0]->setColor( 1.0, 0.0 , 0.0 ); beatLights[1]->setColor( 1.0, 0.48, 0.0 ); diff --git a/src/gui.cxx b/src/gui.cxx index 6e9c89e..7b6a7c4 100644 --- a/src/gui.cxx +++ b/src/gui.cxx @@ -443,26 +443,14 @@ Gui::Gui(const char* argZero) : // create a new "Group" with all Luppp GUI contents, for resizing lupppGroup = new Fl_Group( 0, 0, 1110, 650, "Luppp"); { - // everything in here will have resize() called when main window is resized - - /* - Fl_Bitmap* headImg = new Fl_Bitmap( (unsigned char*)header.pixel_data, 1110, 36 ); - - Fl_Box* pic_box = new Fl_Box(0,0,1110,36); - pic_box->image( headImg ); - pic_box->redraw(); - */ - int i = 0; for (; i < NTRACKS; i++ ) { stringstream s; s << "Track " << i+1; - //printf("track name %s\n", s.str().c_str() ); tracks.push_back( new GTrack(8 + i * 118, 40, 110, 650, s.str().c_str() ) ); } - - master = new GMasterTrack(8 + i * 118, 40, 150, 600, "Master"); + master = new GMasterTrack(8 + i * 118, 40, 150, 650, "Master"); } lupppGroup->end(); From 6440e19c5794e2dcf584a03627142f07358e5e59 Mon Sep 17 00:00:00 2001 From: Harry van Haaren Date: Thu, 24 Nov 2016 23:49:05 +0000 Subject: [PATCH 15/15] Fixes #133 JackSendReturn defualt volume = 1.0f DSP and GUI level defaults for JackSend are now 1, so when you click the FX button, by default the audio will be routed to the send, returned, and audible again. This is better UX. Fixed 2 build warnings to do with string termination --- src/gtrack.cxx | 1 + src/jacksendreturn.cxx | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gtrack.cxx b/src/gtrack.cxx index be1a809..751b599 100644 --- a/src/gtrack.cxx +++ b/src/gtrack.cxx @@ -79,6 +79,7 @@ GTrack::GTrack(int x, int y, int w, int h, const char* l ) : jackSendActivate.callback(gtrack_jacksendactivate_cb,this); jackSendDial.align(FL_ALIGN_INSIDE); jackSendDial.callback(gtrack_jacksend_cb,this); + jackSendDial.value(1.0); //volBox.color( fl_rgb_color( 0,0,0 ) ); end(); // close the group diff --git a/src/jacksendreturn.cxx b/src/jacksendreturn.cxx index d8feff8..17c078d 100644 --- a/src/jacksendreturn.cxx +++ b/src/jacksendreturn.cxx @@ -4,12 +4,12 @@ #include extern Jack* jack; JackSendReturn::JackSendReturn(int trackid, AudioProcessor *prev, jack_client_t *client) - :m_trackid(trackid), m_previousProcessor(prev) + :m_trackid(trackid), m_previousProcessor(prev), m_sendvol(1.0f) { char name[50]; - sprintf(name, "Send_track_%d\0",trackid); + sprintf(name, "Send_track_%d\n",trackid); m_sendport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput,0); - sprintf(name, "Return_track_%d\0",trackid); + sprintf(name, "Return_track_%d\n",trackid); m_returnport=jack_port_register(client,name,JACK_DEFAULT_AUDIO_TYPE,JackPortIsInput,0); m_active=false; m_counter=0;