zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 7346fef91b2b73e444a90da70f6c02c4c30f2bd8
parent 3a1b2c8c80e33c865f9cf872341873e8adc580ae
Author: paulnasca <paulnasca>
Date:   Wed,  1 Nov 2006 15:58:36 +0000

*** empty log message ***

Diffstat:
MAUTHORS.txt | 2+-
MChangeLog | 1+
Msrc/Input/ALSAMidiIn.C | 11+++++++++++
Msrc/Input/ALSAMidiIn.h | 1+
Msrc/Makefile | 6++++++
Msrc/Makefile.inc | 3+++
Msrc/Misc/Makefile | 4++++
Msrc/Output/JACKaudiooutput.C | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/Output/JACKaudiooutput.h | 2++
Msrc/UI/MasterUI.fl | 40++++++++++++++++++++++++----------------
Msrc/main.C | 46+++++++++++++++++++++++++++++++++++++++++++++-
11 files changed, 162 insertions(+), 24 deletions(-)

diff --git a/AUTHORS.txt b/AUTHORS.txt @@ -3,5 +3,5 @@ Main author: Contributors: Gerald Folcher (legato, mono notes memory) - Lars Luthman (zombie fix) + Lars Luthman (zombie fix,jack midi, LASH support) diff --git a/ChangeLog b/ChangeLog @@ -811,6 +811,7 @@ - Inlocuit fl_ask cu fl_choice in fisierele .fl - In mod prestabilit nu se mai seteaza volumul la efectul 0 - Efectele sunt numerotare de la 1 si in la "send to" din partui +01 Nov 2006 - Adaugat patch-urile de Jack Midi si LASH de Lars Luthman diff --git a/src/Input/ALSAMidiIn.C b/src/Input/ALSAMidiIn.C @@ -94,3 +94,14 @@ void ALSAMidiIn::getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmd }; +int ALSAMidiIn::getalsaid() { + if (midi_handle) { + snd_seq_client_info_t* seq_info; + snd_seq_client_info_malloc(&seq_info); + snd_seq_get_client_info(midi_handle, seq_info); + int id = snd_seq_client_info_get_client(seq_info); + snd_seq_client_info_free(seq_info); + return id; + } + return -1; +} diff --git a/src/Input/ALSAMidiIn.h b/src/Input/ALSAMidiIn.h @@ -32,6 +32,7 @@ class ALSAMidiIn:public MidiIn{ ALSAMidiIn(); ~ALSAMidiIn(); void getmidicmd(MidiCmdType &cmdtype,unsigned char &cmdchan,int *cmdparams); + int getalsaid(); private: snd_seq_t *midi_handle; diff --git a/src/Makefile b/src/Makefile @@ -70,6 +70,12 @@ CXXFLAGS += `pkg-config --cflags jack` LIBS+= `pkg-config --libs jack` endif +ifeq ($(LINUX_USE_LASH),YES) +CXXFLAGS += `pkg-config --cflags lash-1.0` -DUSE_LASH +LIBS+= `pkg-config --libs lash-1.0` +endif + + objects=main.o SUBDIRS=DSP Effects Input Misc Output Params Synth Seq diff --git a/src/Makefile.inc b/src/Makefile.inc @@ -42,6 +42,9 @@ LINUX_AUDIOOUT=OSS LINUX_DSSI=NO #LINUX_DSSI=YES +#Next line sets if the LASH session handler will be used +LINUX_USE_LASH=YES +#LINUX_USE_LASH=NO # W I N D O W S C O N F I G U R A T I O N diff --git a/src/Misc/Makefile b/src/Misc/Makefile @@ -2,6 +2,10 @@ include ../Makefile.inc objects=Bank.o Master.o Microtonal.o Part.o Util.o Config.o Dump.o XMLwrapper.o +ifeq ($(LINUX_USE_LASH),YES) +objects += LASHClient.o +endif + all: $(objects) diff --git a/src/Output/JACKaudiooutput.C b/src/Output/JACKaudiooutput.C @@ -21,11 +21,13 @@ */ #include <stdlib.h> +#include <jack/midiport.h> #include "JACKaudiooutput.h" Master *jackmaster; jack_client_t *jackclient; -jack_port_t *outport_left,*outport_right; +char jackname[100]; +jack_port_t *outport_left,*outport_right,*midi_inport; int jackprocess(jack_nframes_t nframes,void *arg); int jacksrate(jack_nframes_t nframes,void *arg); @@ -34,13 +36,12 @@ void jackshutdown(void *arg); bool JACKaudiooutputinit(Master *master_){ jackmaster=master_; jackclient=0; - char tmpstr[100]; for (int i=0;i<15;i++){ - if (i!=0) snprintf(tmpstr,100,"ZynAddSubFX_%d",i); - else snprintf(tmpstr,100,"ZynAddSubFX"); - jackclient=jack_client_new(tmpstr); - if (jackclient!=0) break; + if (i!=0) snprintf(jackname,100,"ZynAddSubFX_%d",i); + else snprintf(jackname,100,"ZynAddSubFX"); + jackclient=jack_client_new(jackname); + if (jackclient!=0) break; }; if (jackclient==0) { @@ -60,6 +61,8 @@ bool JACKaudiooutputinit(Master *master_){ JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); outport_right=jack_port_register(jackclient,"out_2", JACK_DEFAULT_AUDIO_TYPE,JackPortIsOutput|JackPortIsTerminal,0); + midi_inport=jack_port_register(jackclient,"midi_input", + JACK_DEFAULT_MIDI_TYPE,JackPortIsInput|JackPortIsTerminal,0); if (jack_activate(jackclient)){ fprintf(stderr,"Cannot activate jack client\n"); @@ -78,6 +81,7 @@ int jackprocess(jack_nframes_t nframes,void *arg){ jack_default_audio_sample_t *outr=(jack_default_audio_sample_t *) jack_port_get_buffer (outport_right, nframes); if (!pthread_mutex_trylock(&jackmaster->mutex)) { + JACKhandlemidi(nframes); jackmaster->GetAudioOutSamples(nframes,jack_get_sample_rate(jackclient),outl,outr); pthread_mutex_unlock(&jackmaster->mutex); } @@ -102,4 +106,58 @@ void jackshutdown(void *arg){ }; +void JACKhandlemidi(unsigned long frames) { + + // We must have the master mutex before we run this function + + // XXX This is really nasty, not only do we lose the sample accuracy of + // JACK MIDI, but any accuracy at all below the buffer size + + void* midi_buf = jack_port_get_buffer(midi_inport, frames); + jack_midi_event_t jack_midi_event; + jack_nframes_t event_index = 0; + jack_nframes_t event_count = + jack_midi_port_get_info(midi_buf, frames)->event_count; + unsigned char* midi_data; + unsigned char type, chan; + + while (event_index < event_count) { + + jack_midi_event_get(&jack_midi_event, midi_buf, event_index, frames); + midi_data = jack_midi_event.buffer; + type = midi_data[0] & 0xF0; + chan = midi_data[0] & 0x0F; + + switch (type) { + + case 0x80: /* note-off */ + jackmaster->NoteOff(chan, midi_data[1]); + break; + + case 0x90: /* note-on */ + jackmaster->NoteOn(chan, midi_data[1], midi_data[2]); + break; + + case 0xB0: /* controller */ + jackmaster->SetController(chan, midi_data[1], midi_data[2]); + break; + + case 0xE0: /* pitch bend */ + jackmaster->SetController(chan, C_pitchwheel, + ((midi_data[2] << 7) | midi_data[1])); + break; + + /* XXX TODO: handle MSB/LSB controllers and RPNs and NRPNs */ + } + + event_index++; + } + +} + +const char* JACKgetname() { + if (jackclient != NULL) + return jackname; + return NULL; +} diff --git a/src/Output/JACKaudiooutput.h b/src/Output/JACKaudiooutput.h @@ -40,6 +40,8 @@ bool JACKaudiooutputinit(Master *master_); void JACKfinish(); +void JACKhandlemidi(unsigned long frames); +const char* JACKgetname(); #endif diff --git a/src/UI/MasterUI.fl b/src/UI/MasterUI.fl @@ -1705,10 +1705,15 @@ simplesyseffsend->value(master->Psysefxvol[nsyseff][npart]);} {} updatepanel();} {} } - Function {do_load_master()} {} { + Function {do_load_master(char* file = NULL)} {} { code {char *filename; -filename=fl_file_chooser("Open:","({*.xmz})",NULL,0); -if (filename==NULL) return; + if (file == NULL) { + filename=fl_file_chooser("Open:","({*.xmz})",NULL,0); + if (filename==NULL) return; + } + else { + filename = file; + } pthread_mutex_lock(&master->mutex); @@ -1729,20 +1734,23 @@ if (result>=0) setfilelabel(filename); if (result==-10) fl_alert("Error: Could not load the file\\nbecause it is not a zynaddsubfx parameters file."); else if (result<0) fl_alert("Error: Could not load the file.");} {} } - Function {do_save_master()} {} { + Function {do_save_master(char* file = NULL)} {} { code {char *filename; -int result=0; - -filename=fl_file_chooser("Save:","({*.xmz})",NULL,0); -if (filename==NULL) return; -filename=fl_filename_setext(filename,".xmz"); - -result=fileexists(filename); -if (result) { - result=0; - if (!fl_choice("The file exists. \\nOverwrite it?","No","Yes",NULL)) return; - -}; + int result=0; + if (file == NULL) { + filename=fl_file_chooser("Save:","({*.xmz})",NULL,0); + if (filename==NULL) return; + filename=fl_filename_setext(filename,".xmz"); + result=fileexists(filename); + if (result) { + result=0; + if (!fl_choice("The file exists. Overwrite it?","No","Yes",NULL)) return; + + } + } + else { + filename = file; + } pthread_mutex_lock(&master->mutex); diff --git a/src/main.C b/src/main.C @@ -83,6 +83,11 @@ bool usejackit=false; OSSaudiooutput *audioout; #endif +#ifdef USE_LASH +#include "Misc/LASHClient.h" +LASHClient *lash; +#endif + MidiIn *Midi; int Pexitprogram=0;//if the UI set this to 1, the program will exit @@ -180,7 +185,26 @@ void *thread2(void *arg){ void *thread3(void *arg){ #ifndef DISABLE_GUI ui->showUI(); - while (Pexitprogram==0) Fl::wait(); + while (Pexitprogram==0) { +#ifdef USE_LASH + std::string filename; + switch (lash->checkevents(filename)) { + case LASHClient::Save: + ui->do_save_master(const_cast<char*>(filename.c_str())); + lash->confirmevent(LASHClient::Save); + break; + case LASHClient::Restore: + ui->do_load_master(const_cast<char*>(filename.c_str())); + lash->confirmevent(LASHClient::Restore); + break; + case LASHClient::Quit: + Pexitprogram = 1; + default: + break; + } +#endif + Fl::wait(); + } #endif return(0); }; @@ -312,6 +336,10 @@ void exitprogram(){ delete(Midi); delete(master); +#ifdef USE_LASH + delete(lash); +#endif + // pthread_mutex_unlock(&master->mutex); delete(denormalkillbuf); delete(OscilGen::tmpsmps); @@ -345,6 +373,11 @@ void exitprogram(){ #ifndef VSTAUDIOOUT int main(int argc, char *argv[]){ + +#ifdef USE_LASH + lash = new LASHClient(&argc, &argv); +#endif + config.init(); dump.startnow(); int noui=0; @@ -492,6 +525,17 @@ int main(int argc, char *argv[]){ initprogram(); +#ifdef USE_LASH +#ifdef ALSAMIDIIN + ALSAMidiIn* alsamidi = dynamic_cast<ALSAMidiIn*>(Midi); + if (alsamidi) + lash->setalsaid(alsamidi->getalsaid()); +#endif +#ifdef JACKAUDIOOUT + lash->setjackname(JACKgetname()); +#endif +#endif + if (strlen(loadfile)>1){ int tmp=master->loadXML(loadfile); if (tmp<0) {