foreach (Sliver *sliver, slivers) { sliver->status = Sliver::STATUS_OFFLINE; sliverHash[sliver->name] = sliver; if (relayEnabled()) { installProgram(sliver); addSliverConnection(sliver); } else { if (sliver->IPv6.isEmpty()) { qDebug() << "No ip, getting address"; getIpAddress(sliver); installProgram(sliver); } else { addSliverConnection(sliver); QTimer *timer = new QTimer(this); //if there's a specified IP address, give the connection some time before running the script setting things up. connect(timer, &QTimer::timeout, [timer, sliver, this]() { qDebug() << "Checking connection status"; if (sliver->status == sliver->STATUS_OFFLINE) { qDebug() << "Still offline, reinstalling"; installProgram(sliver); } timer->stop(); timer->deleteLater(); }); timer->start(3000); } } QTimer *timer = new QTimer(this); //Will try to connect as long as the sliver is not connected connect(timer, &QTimer::timeout, [timer, sliver, this]() { if (sliver->status != sliver->STATUS_CONNECTED) { qDebug() << "Retryign connection"; addSliverConnection(sliver); } else { timer->stop(); timer->deleteLater(); } static int time = 0; time+=3; //if (time > 35) { // shutDownNodeprogs(QList<Sliver*>() << sliver); // installProgram(sliver); // time = 0; // } }); timer->start(3000); }
void process_midi_event(void *instp, const struct bmidi_event_t *ev) { struct b_instance * inst = (struct b_instance *) instp; struct b_midicfg * m = (struct b_midicfg *) inst->midicfg; switch(ev->type) { case NOTE_ON: if(m->keyTable[ev->channel] && m->keyTable[ev->channel][ev->d.tone.note] != 255) { if (ev->d.tone.velocity > 0){ oscKeyOn (inst->synth, m->keyTable[ev->channel][ev->d.tone.note]); } else { oscKeyOff (inst->synth, m->keyTable[ev->channel][ev->d.tone.note]); } } break; case NOTE_OFF: if(m->keyTable[ev->channel] && m->keyTable[ev->channel][ev->d.tone.note] != 255) oscKeyOff (inst->synth, m->keyTable[ev->channel][ev->d.tone.note]); break; case PROGRAM_CHANGE: installProgram(inst, ev->d.control.value); break; case CONTROL_CHANGE: #ifdef DEBUG_MIDI_CC { unsigned char * ctrlUse = NULL; const char *fn=""; if (ev->channel == m->rcvChA) ctrlUse = m->ctrlUseA; else if (ev->channel == m->rcvChB) ctrlUse = m->ctrlUseB; else if (ev->channel == m->rcvChC) ctrlUse = m->ctrlUseC; if (ctrlUse) { int j; for (j=0; j < CTRL_USE_MAX; ++j) { if (ctrlUse[j] == ev->d.control.param) { fn = ccFuncNames[j]; break; } } } printf("CC: %2d %03d -> %3d (%s) %s\n", ev->channel, ev->d.control.param, ev->d.control.value, fn, (m->ctrlvec[ev->channel] && m->ctrlvec[ev->channel][ev->d.control.param].fn != emptyControlFunction) ? "*":"-" ); } #endif /* see http://www.midi.org/techspecs/midimessages.php#3 * for reserved and dedicated CCs */ /* 0x00 and 0x20 are used for BANK select */ if (ev->d.control.param == 0x00 || ev->d.control.param == 0x20) { break; } else if (ev->d.control.param == 121) { /* TODO - reset all controller */ break; } else if (ev->d.control.param == 120 || ev->d.control.param == 123) { /* Midi panic: 120: all sound off, 123: all notes off*/ int i; for (i=0; i < MAX_KEYS; ++i) { oscKeyOff (inst->synth, i); } break; } else if (ev->d.control.param >= 120) { /* params 122-127 are reserved - skip them. */ break; } else { /* auto assign function from midi-controller */ if (m->ccuimap >= 0) { unsigned char * ctrlUse; if (ev->channel == m->rcvChA) { ctrlUse = m->ctrlUseA; } else if (ev->channel == m->rcvChB) { ctrlUse = m->ctrlUseA; } else if (ev->channel == m->rcvChC) { ctrlUse = m->ctrlUseC; } else { // N/A break; } // unassign functions from this controller if (m->ctrlvec[ev->channel] && m->ctrlvec[ev->channel][ev->d.control.param].fn) { if (!remove_CC_map(m, ev->channel, ev->d.control.param)) { remember_dynamic_CC_change(instp, ev->channel, ev->d.control.param, -1); } } // assign new functions to this controller const int fnid = m->ccuimap & 0xff; ctrlUse[fnid] = ev->d.control.param; memcpy(&m->ctrlvec[ev->channel][ev->d.control.param], &m->ctrlvecF[fnid], sizeof(ctrl_function)); m->ctrlvec[ev->channel][ev->d.control.param].mm = NULL; reverse_cc_map(m, fnid, ev->channel, ev->d.control.param); m->ctrlflg[ev->channel][ev->d.control.param] = (m->ccuimap&0xff00) >> 16; remember_dynamic_CC_change(instp, ev->channel, ev->d.control.param, fnid); // send feedback to GUI.. if (m->hookfn) { m->hookfn(-1, "special.midimap", 0, NULL, m->hookarg); } m->ccuimap = -1; } else if (m->ctrlvec[ev->channel] && m->ctrlvec[ev->channel][ev->d.control.param].fn) { uint8_t val = ev->d.control.value & 0x7f; if (m->ctrlflg[ev->channel][ev->d.control.param] & MFLAG_INV) { val = 127 - val; } execControlFunction(m, &m->ctrlvec[ev->channel][ev->d.control.param], val); } }
static void run(LV2_Handle instance, uint32_t n_samples) { B3S* b3s = (B3S*)instance; float* audio[2]; audio[0] = b3s->outL; audio[1] = b3s->outR; /* prepare outgoing MIDI */ const uint32_t capacity = b3s->midiout->atom.size; static bool warning_printed = false; if (!warning_printed && capacity < 4096) { warning_printed = true; fprintf(stderr, "B3LV2: LV message buffer is only %d bytes. Expect problems.\n", capacity); fprintf(stderr, "B3LV2: if your LV2 host allows one to configure a buffersize use at least 4kBytes.\n"); } lv2_atom_forge_set_buffer(&b3s->forge, (uint8_t*)b3s->midiout, capacity); lv2_atom_forge_sequence_head(&b3s->forge, &b3s->frame, 0); uint32_t written = 0; if (b3s->queue_panic) { b3s->queue_panic = 0; midi_panic(b3s->inst); } /* Process incoming events from GUI and handle MIDI events */ if (b3s->midiin) { LV2_Atom_Event* ev = lv2_atom_sequence_begin(&(b3s->midiin)->body); while(!lv2_atom_sequence_is_end(&(b3s->midiin)->body, (b3s->midiin)->atom.size, ev)) { if (ev->body.type == b3s->uris.midi_MidiEvent) { /* process midi messages from player */ if (written + BUFFER_SIZE_SAMPLES < ev->time.frames && ev->time.frames < n_samples) { /* first syntheize sound up until the message timestamp */ written = synthSound(b3s, written, ev->time.frames, audio); } /* send midi message to synth, CC's will trigger hook -> update GUI */ parse_raw_midi_data(b3s->inst, (uint8_t*)(ev+1), ev->body.size); } else if (ev->body.type == b3s->uris.atom_Blank || ev->body.type == b3s->uris.atom_Object) { /* process messages from GUI */ const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body; if (obj->body.otype == b3s->uris.sb3_uiinit) { b3s->update_gui_now = 1; } else if (obj->body.otype == b3s->uris.sb3_uimccquery) { midi_loopCCAssignment(b3s->inst->midicfg, 7, mcc_cb, b3s); } else if (obj->body.otype == b3s->uris.sb3_uimccset) { const LV2_Atom* cmd = NULL; const LV2_Atom* flags = NULL; lv2_atom_object_get(obj, b3s->uris.sb3_cckey, &flags, b3s->uris.sb3_ccval, &cmd, 0); if (cmd && flags) { midi_uiassign_cc(b3s->inst->midicfg, (const char*)LV2_ATOM_BODY(cmd), ((LV2_Atom_Int*)flags)->body); } } else if (obj->body.otype == b3s->uris.sb3_midipgm) { const LV2_Atom* key = NULL; lv2_atom_object_get(obj, b3s->uris.sb3_cckey, &key, 0); if (key) { installProgram(b3s->inst, ((LV2_Atom_Int*)key)->body); } } else if (obj->body.otype == b3s->uris.sb3_midisavepgm) { const LV2_Atom* pgm = NULL; const LV2_Atom* name = NULL; lv2_atom_object_get(obj, b3s->uris.sb3_cckey, &pgm, b3s->uris.sb3_ccval, &name, 0); if (pgm && name) { saveProgramm(b3s->inst, (int) ((LV2_Atom_Int*)pgm)->body, (char*) LV2_ATOM_BODY(name), 0); b3s->update_pgm_now = 1; } } else if (obj->body.otype == b3s->uris.sb3_loadpgm) { iowork(b3s, obj, CMD_LOADPGM); } else if (obj->body.otype == b3s->uris.sb3_loadcfg) { iowork(b3s, obj, CMD_LOADCFG); } else if (obj->body.otype == b3s->uris.sb3_savepgm) { iowork(b3s, obj, CMD_SAVEPGM); } else if (obj->body.otype == b3s->uris.sb3_savecfg) { iowork(b3s, obj, CMD_SAVECFG); } else if (obj->body.otype == b3s->uris.sb3_cfgstr) { if (!b3s->inst_offline) { advanced_config_set(b3s, obj); } } else if (obj->body.otype == b3s->uris.sb3_control) { b3s->suspend_ui_msg = 1; const LV2_Atom_Object* obj = (LV2_Atom_Object*)&ev->body; char *k; int v; if (!get_cc_key_value(&b3s->uris, obj, &k, &v)) { #ifdef DEBUGPRINT fprintf(stderr, "B3LV2: callMIDIControlFunction(..,\"%s\", %d);\n", k, v); #endif callMIDIControlFunction(b3s->inst->midicfg, k, v); } b3s->suspend_ui_msg = 0; } } ev = lv2_atom_sequence_next(ev); } } /* synthesize [remaining] sound */ synthSound(b3s, written, n_samples, audio); /* send active keys to GUI - IFF changed */ bool keychanged = false; for (int i = 0 ; i < MAX_KEYS/32; ++i) { if (b3s->active_keys[i] != b3s->inst->synth->_activeKeys[i]) { keychanged = true; } b3s->active_keys[i] = b3s->inst->synth->_activeKeys[i]; } if (keychanged) { LV2_Atom_Forge_Frame frame; lv2_atom_forge_frame_time(&b3s->forge, 0); x_forge_object(&b3s->forge, &frame, 1, b3s->uris.sb3_activekeys); lv2_atom_forge_property_head(&b3s->forge, b3s->uris.sb3_keyarrary, 0); lv2_atom_forge_vector(&b3s->forge, sizeof(unsigned int), b3s->uris.atom_Int, MAX_KEYS/32, b3s->active_keys); lv2_atom_forge_pop(&b3s->forge, &frame); } /* check for new instances */ postrun(b3s); if (b3s->update_gui_now) { b3s->update_gui_now = 0; b3s->update_pgm_now = 1; b3s->suspend_ui_msg = 1; rc_loop_state(b3s->inst->state, rc_cb, b3s); b3s->suspend_ui_msg = 0; forge_kvconfigmessage(&b3s->forge, &b3s->uris, b3s->uris.sb3_cfgkv, "lv2.info", b3s->lv2nfo); forge_kvcontrolmessage(&b3s->forge, &b3s->uris, "special.init", (int32_t) b3s->thirtysec); } else if (b3s->update_pgm_now) { b3s->update_pgm_now = 0; loopProgammes(b3s->inst->progs, 1, pgm_cb, b3s); } }
/* * Main program. */ int main (int argc, char * argv []) { int i,c,k; int doDefaultConfig = TRUE; int doDefaultProgram = TRUE; int printCCTable = FALSE; int doDefaultCC = TRUE; char * configOverride [NOF_CFG_OVERS]; int configOverEnd = 0; int loadProgram = -1; unsigned int randomPreset[9]; unsigned int defaultPreset[9] = {8,8,8, 0,0,0,0, 0,0}; unsigned int * presetSelect = defaultPreset; char *midnam = NULL; char * alternateProgrammeFile = NULL; char * alternateConfigFile = NULL; memset(&inst, 0, sizeof(b_instance)); srand ((unsigned int) time (NULL)); for (i=0;i<AUDIO_CHANNELS; i++) jack_port[i] = NULL; jack_ports = strdup("system:playback_"); const char *optstring = "c:CdDhHl:M:p:PrU:V"; const struct option long_options[] = { { "help", no_argument, 0, 'H' }, { "program", required_argument, 0, 'p' }, { "config", required_argument, 0, 'c' }, { "noconfig", no_argument, 0, 'C' }, { "dumpcc", no_argument, 0, 'd' }, { "noCC", no_argument, 0, 'D' }, { "midnam", required_argument, 0, 'M' }, { "noprogram", no_argument, 0, 'P' }, { "randomize", no_argument, 0, 'r' }, { "upper", required_argument, 0, 'U' }, { "version", no_argument, 0, 'V' }, { 0, 0, 0, 0 } }; while ((c = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { switch (c) { case 'c': alternateConfigFile = optarg; break; case 'C': doDefaultConfig = FALSE; break; case 'd': printCCTable = TRUE; break; case 'D': doDefaultCC = FALSE; break; case 'h': Usage(0); return (0); break; case 'H': Usage(1); return (0); break; case 'l': loadProgram = atoi(optarg); break; case 'M': midnam = optarg; break; case 'r': for (k = 0; k < 9; k++) randomPreset[k] = rand () % 9; fprintf (stderr, "Random Preset: " "%d%d %d%d%d%d %d%d%d\n", randomPreset[0], randomPreset[1], randomPreset[2], randomPreset[3], randomPreset[4], randomPreset[5], randomPreset[6], randomPreset[7], randomPreset[8]); presetSelect = randomPreset; break; case 'p': alternateProgrammeFile = optarg; break; case 'P': doDefaultProgram = FALSE; break; case 'U': parse_preset(defaultPreset, optarg); break; case 'V': PrintVersion(); return(0); default: fprintf(stderr, "invalid argument.\n"); Usage(0); return(1); } } for (i = optind; i < argc; ++i) { char * av = argv[i]; if (strchr (av, '=') != NULL) { /* Remember this as a config parameter */ if (configOverEnd < NOF_CFG_OVERS) { configOverride[configOverEnd++] = av; } else { fprintf (stderr, "Too many configuration parameters (%d), please consider using a\n" "configuration file instead of the commandline.\n", NOF_CFG_OVERS); return(1); } } } /* * allocate data structures, instances. */ allocAll(); /* * evaluate configuration */ if (getenv("XDG_CONFIG_HOME")) { size_t hl = strlen(getenv("XDG_CONFIG_HOME")); defaultConfigFile=(char*) malloc(hl+32); defaultProgrammeFile=(char*) malloc(hl+32); sprintf(defaultConfigFile, "%s/setBfree/default.cfg", getenv("XDG_CONFIG_HOME")); sprintf(defaultProgrammeFile, "%s/setBfree/default.pgm", getenv("XDG_CONFIG_HOME")); } else if (getenv("HOME")) { size_t hl = strlen(getenv("HOME")); defaultConfigFile=(char*) malloc(hl+30); defaultProgrammeFile=(char*) malloc(hl+30); sprintf(defaultConfigFile, "%s/.config/setBfree/default.cfg", getenv("HOME")); sprintf(defaultProgrammeFile, "%s/.config/setBfree/default.pgm", getenv("HOME")); } /* * Here we call modules that need to execute code in order to arrange * static initializations that is not practical to achieve in source code. */ initControllerTable (inst.midicfg); if (doDefaultCC) { midiPrimeControllerMapping (inst.midicfg); } /* * Commandline arguments are parsed. If we are of a mind to try the * default configuration file we do that now. */ if (doDefaultConfig == TRUE && defaultConfigFile) { if (access (defaultConfigFile, R_OK) == 0) { fprintf(stderr, "loading cfg: %s\n", defaultConfigFile); parseConfigurationFile (&inst, defaultConfigFile); } } if (alternateConfigFile) { if (access (alternateConfigFile, R_OK) == 0) { fprintf(stderr, "loading cfg: %s\n", alternateConfigFile); parseConfigurationFile (&inst, alternateConfigFile); } } /* * Then apply any configuration parameters collected from the commandline. * These must be applied last so that they can override the parameters * read from the files (if any). */ for (i = 0; i < configOverEnd; i++) { parseConfigurationLine (&inst, "commandline argument", 0, configOverride[i]); } /* * Having configured the initialization phase we can now actually do it. */ #ifndef _WIN32 if (mlockall (MCL_CURRENT | MCL_FUTURE)) { fprintf(stderr, "Warning: Can not lock memory.\n"); } #endif initAll (); /* * We are initialized and now load the programme file. */ if (doDefaultProgram == TRUE && defaultProgrammeFile) { if (access (defaultProgrammeFile, R_OK) == 0) loadProgrammeFile (inst.progs, defaultProgrammeFile); } else { walkProgrammes(inst.progs, 1); // clear built-in default program } if (alternateProgrammeFile != NULL) loadProgrammeFile (inst.progs, alternateProgrammeFile); if (walkProgrammes(inst.progs, 0)) { listProgrammes (inst.progs, stderr); } initMidiTables(inst.midicfg); if (printCCTable) { listCCAssignments(inst.midicfg, stderr); } if (midnam) { FILE *fp = fopen(midnam, "w"); if (fp) { save_midname(&inst, fp); fclose(fp); } else { fprintf(stderr, "failed to write midnam to '%s'\n", midnam); } } /* * With the programmes eager and ready to go, we spawn off the MIDI * listener thread. The thread will initialize the MIDI device. */ #ifdef HAVE_ASEQ pthread_t t_midi; if (!use_jack_midi) { if (!aseq_open(midi_port)) { k = pthread_create(&t_midi, NULL, aseq_run, &inst); if (k != 0) { fprintf (stderr, "%d : %s\n", k, "pthread_create : MIDIInReader thread"); return (1); } } else { return (1); } } #endif setMIDINoteShift (inst.midicfg, 0); setDrawBars (&inst, 0, presetSelect); #if 0 // initial values are assigned in tonegen.c initToneGenerator() setDrawBars (&inst, 1, presetSelect); /* 838 000 000 */ setDrawBars (&inst, 2, presetSelect); /* 86 - */ #endif const int pgm_off = inst.progs->MIDIControllerPgmOffset; if (loadProgram >= 0 && loadProgram >= pgm_off) { installProgram(&inst, (loadProgram - pgm_off)); } #ifndef _WIN32 signal (SIGHUP, catchsig); signal (SIGINT, catchsig); #endif connect_jack_ports(); synth_ready = 1; fprintf(stderr,"All systems go. press CTRL-C, or send SIGINT or SIGHUP to terminate\n"); while (j_client) /* jack callback is doing this the work now */ #ifdef _WIN32 Sleep (1000); #else sleep (1); #endif /* shutdown and cleanup */ #ifdef HAVE_ASEQ if (!use_jack_midi) { aseq_stop=1; pthread_join(t_midi, NULL); aseq_close(); } #endif free(defaultConfigFile); free(defaultProgrammeFile); free(j_output_bufferptrs); free(j_output_port); free(midi_port); free(jack_ports); for (i=0;i<AUDIO_CHANNELS; i++) free(jack_port[i]); freeAll(); #ifndef _WIN32 munlockall(); #endif fprintf(stderr, "bye\n"); return 0; }