Пример #1
0
static void clone_cb_mcc(int fnid, const char *key, const char *kv, unsigned char val, void *arg) {
  if (fnid >= 0) {
    callMIDIControlFunction(((struct b_instance *) arg)->midicfg, key, val);
  }
}
Пример #2
0
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);
  }
}
Пример #3
0
static LV2_State_Status
restore(LV2_Handle                  instance,
        LV2_State_Retrieve_Function retrieve,
        LV2_State_Handle            handle,
        uint32_t                    flags,
        const LV2_Feature* const*   features)
{
  B3S* b3s = (B3S*)instance;
  size_t   size;
  uint32_t type;
  uint32_t valflags;
  const void* value = retrieve(handle, b3s->uris.sb3_state, &size, &type, &valflags);

  if (!value) {
    return LV2_STATE_ERR_UNKNOWN;
  }

  if (b3s->inst_offline) {
    fprintf(stderr, "B3LV2: restore ignored. re-init in progress\n");
    return LV2_STATE_ERR_UNKNOWN;
  }

  b3s->inst_offline = (b_instance*) calloc(1, sizeof(struct b_instance));
  allocSynth(b3s->inst_offline);

  const char* cfg = (const char*)value;
  const char *te, *ts = cfg;

  LOCALEGUARD_START;

  /* pass1 - evaulate CFG -- before initializing synth */
  while (ts && *ts && (te=strchr(ts, '\n'))) {
    char *val;
    char kv[1024];
    memcpy(kv, ts, te-ts);
    kv[te-ts]=0;
#ifdef DEBUGPRINT
    fprintf(stderr, "B3LV2 CFG Pass1: %s\n", kv);
#endif
    if(kv[0]=='C' && (val=strchr(kv,'='))) {
      *val=0;
#ifdef DEBUGPRINT
      fprintf(stderr, "B3LV2: evaluateConfigKeyValue(..,\"%s\", \"%s\");\n", kv+2, val+1);
#endif
      evaluateConfigKeyValue((void*)b3s->inst_offline, kv+2, val+1);
    }
    else if(kv[0]=='P') {
#ifdef DEBUGPRINT
      printf("PGM '%s'\n", kv+2);
#endif
      loadProgrammeString(b3s->inst_offline->progs, kv+2);
    }
    ts=te+1;
  }

  initSynth(b3s->inst_offline, SampleRateD);

  /* pass2 - replay CC's after initializing synth */
  ts = cfg;
  while (ts && *ts && (te=strchr(ts, '\n'))) {
    char *val;
    char kv[1024];
    memcpy(kv, ts, te-ts);
    kv[te-ts]=0;
#ifdef DEBUGPRINT
    fprintf(stderr, "B3LV2 CFG Pass2: %s\n", kv);
#endif
    if(kv[0]=='M' && (val=strchr(kv,'='))) {
      *val=0;
#ifdef DEBUGPRINT
      fprintf(stderr, "B3LV2: callMIDIControlFunction(..,\"%s\", %d);\n", kv+2, atoi(val+1));
#endif
      callMIDIControlFunction(b3s->inst_offline->midicfg, kv+2, atoi(val+1));
    }
    ts=te+1;
  }

  LOCALEGUARD_END;

  b3s->swap_instances = 1;
  return LV2_STATE_SUCCESS;
}
Пример #4
0
/**
 * This is the routine called by the MIDI parser when it detects
 * a Program Change message.
 */
void installProgram (void *instance, unsigned char uc) {
  int p = (int) uc;
  b_instance * inst = (b_instance*) instance;

  p += inst->progs->MIDIControllerPgmOffset;

  if ((0 < p) && (p < MAXPROGS)) {

    Programme * PGM = &(inst->progs->programmes[p]);
    unsigned int flags0 = PGM->flags[0];
#ifdef DEBUG_MIDI_PROGRAM_CHANGES
    char display[128];
#endif

    if (flags0 & FL_INUSE) {

#ifdef DEBUG_MIDI_PROGRAM_CHANGES
      strcpy (display, PGM->name);
#endif

      if (flags0 & FL_DRWRND) {
	char buf [32];

	if (flags0 & FL_DRAWBR) {
	  randomizeDrawbars (PGM->drawbars, buf);
#ifdef DEBUG_MIDI_PROGRAM_CHANGES
	  strcat (display, "UPR:");
	  strcat (display, buf);
#endif
	}

	if (flags0 & FL_LOWDRW) {
	  randomizeDrawbars (PGM->lowerDrawbars, buf);
#ifdef DEBUG_MIDI_PROGRAM_CHANGES
	  strcat (display, "LOW:");
	  strcat (display, buf);
#endif
	}

	if (flags0 & FL_PDLDRW) {
	  randomizeDrawbars (PGM->pedalDrawbars, buf);
#ifdef DEBUG_MIDI_PROGRAM_CHANGES
	  strcat (display, "PDL:");
	  strcat (display, buf);
#endif
	}
      }

#ifdef DEBUG_MIDI_PROGRAM_CHANGES
      /* this is not RT safe */
      //fprintf (stdout, "\rPGM: %s           \r", display); fflush (stdout);
      fprintf (stdout, "PGM: %s\n", display);
#endif

      if (flags0 & FL_DRAWBR) {
	setDrawBars (inst, 0, PGM->drawbars);
      }

      if (flags0 & FL_LOWDRW) {
	setDrawBars (inst, 1, PGM->lowerDrawbars);
      }

      if (flags0 & FL_PDLDRW) {
	setDrawBars (inst, 2, PGM->pedalDrawbars);
      }

      if (flags0 & FL_SCANNR) {
	//setVibrato (inst->synth, PGM->scanner & 0x00FF);
	assert((PGM->scanner & 0xff) > 0);
	int knob = ((PGM->scanner & 0xf) << 1) - ((PGM->scanner & CHO_) ? 1 : 2);
	callMIDIControlFunction(inst->midicfg, "vibrato.knob", knob * 23);
      }

      if (flags0 & FL_VCRUPR) {
	//setVibratoUpper (inst->synth, PGM->scanner & 0x200);
	int rt = getVibratoRouting(inst->synth) & ~0x2;
	rt |= (PGM->scanner & 0x200) ? 2 : 0;
	callMIDIControlFunction(inst->midicfg, "vibrato.routing", rt << 5);
      }

      if (flags0 & FL_VCRLWR) {
	//setVibratoLower (inst->synth, PGM->scanner & 0x100);
	int rt = getVibratoRouting(inst->synth) & ~0x1;
	rt |= (PGM->scanner & 0x100) ? 1 : 0;
	callMIDIControlFunction(inst->midicfg, "vibrato.routing", rt << 5);
      }

      if (flags0 & FL_PRCENA) {
	setPercussionEnabled (inst->synth, PGM->percussionEnabled);
	callMIDIControlFunction(inst->midicfg, "percussion.enable", PGM->percussionEnabled ? 127 : 0);
      }

      if (flags0 & FL_PRCVOL) {
	//setPercussionVolume (inst->synth, PGM->percussionVolume);
	callMIDIControlFunction(inst->midicfg, "percussion.volume", PGM->percussionVolume ? 127 : 0);
      }

      if (flags0 & FL_PRCSPD) {
	//setPercussionFast (inst->synth, PGM->percussionSpeed);
	callMIDIControlFunction(inst->midicfg, "percussion.decay", PGM->percussionSpeed ? 127 : 0);
      }

      if (flags0 & FL_PRCHRM) {
	//setPercussionFirst (inst->synth, PGM->percussionHarmonic);
	callMIDIControlFunction(inst->midicfg, "percussion.harmonic", PGM->percussionHarmonic ? 127 : 0);
      }

      if (flags0 & FL_OVRSEL) {
	//setClean (inst->preamp, PGM->overdriveSelect);
	callMIDIControlFunction(inst->midicfg, "overdrive.enable", PGM->overdriveSelect ? 0 : 127);
      }

      if (flags0 & FL_ROTENA) {
	/* Rotary enabled */
      }

      if (flags0 & FL_ROTSPS) {
	// setRevSelect (inst->whirl, (int) (PGM->rotarySpeedSelect));
	callMIDIControlFunction(inst->midicfg, "rotary.speed-preset", PGM->rotarySpeedSelect * 32);
      }

      if (flags0 & FL_RVBMIX) {
	//setReverbMix (inst->reverb, PGM->reverbMix);
	callMIDIControlFunction(inst->midicfg, "reverb.mix-preset", (PGM->reverbMix * 127.0));
      }

      /* TODO --  keyboard split & transpose are not yet saved */
      if (flags0 & (FL_KSPLTL|FL_KSPLTP|FL_TRA_PD|FL_TRA_LM|FL_TRA_UM)) {
	int b;
	b  = (flags0 & FL_KSPLTP) ?  1 : 0;
	b |= (flags0 & FL_KSPLTL) ?  2 : 0;
	b |= (flags0 & FL_TRA_PD) ?  4 : 0;
	b |= (flags0 & FL_TRA_LM) ?  8 : 0;
	b |= (flags0 & FL_TRA_UM) ? 16 : 0;
	setKeyboardSplitMulti (inst->midicfg, b,
			       PGM->keyboardSplitPedals,
			       PGM->keyboardSplitLower,
			       PGM->transpose[TR_CHA_PD],
			       PGM->transpose[TR_CHA_LM],
			       PGM->transpose[TR_CHA_UM]);
      }

      if (flags0 & FL_TRANSP) {
	setKeyboardTranspose (inst->midicfg, PGM->transpose[TR_TRANSP]);
      }

      if (flags0 & FL_TRCH_A) {
	setKeyboardTransposeA (inst->midicfg, PGM->transpose[TR_CHNL_A]);
      }

      if (flags0 & FL_TRCH_B) {
	setKeyboardTransposeB (inst->midicfg, PGM->transpose[TR_CHNL_B]);
      }

      if (flags0 & FL_TRCH_C) {
	setKeyboardTransposeC (inst->midicfg, PGM->transpose[TR_CHNL_C]);
      }

    }
  }
}