1 /*! 2 * @file midiseq_lv2.cpp 3 * @brief Implements an LV2 plugin inheriting from MidiSeq 4 * 5 * 6 * Copyright 2009 - 2017 <qmidiarp-devel@lists.sourceforge.net> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 * MA 02110-1301, USA. 22 * 23 */ 24 25 #include <cstdio> 26 #include <cmath> 27 #include "midiseq_lv2.h" 28 29 MidiSeqLV2::MidiSeqLV2 ( 30 double sample_rate, const LV2_Feature *const *host_features ) 31 :MidiSeq() 32 { 33 MidiEventID = 0; 34 sampleRate = sample_rate; 35 curFrame = 0; 36 inEventBuffer = NULL; 37 outEventBuffer = NULL; 38 getData(&data); 39 mouseXCur = 0; 40 mouseYCur = 0; 41 mouseEvCur = 0; 42 tempo = 120.0f; 43 internalTempo = 120.0f; 44 lastMouseIndex = 0; 45 dispVertIndex = 0; 46 47 transportBpm = 120.0f; 48 transportFramesDelta = 0; 49 curTick = 0; 50 tempoChangeTick = 0; 51 hostTransport = true; 52 transportSpeed = 0; 53 transportAtomReceived = false; 54 55 transpFromGui = 0; 56 velFromGui = 256; 57 58 bufPtr = 0; 59 dataChanged = true; 60 ui_up = false; 61 62 LV2_URID_Map *urid_map; 63 64 /* Scan host features for URID map */ 65 66 for (int i = 0; host_features[i]; ++i) { 67 if (::strcmp(host_features[i]->URI, LV2_URID_URI "#map") == 0) { 68 urid_map = (LV2_URID_Map *) host_features[i]->data; 69 if (urid_map) { 70 MidiEventID = urid_map->map(urid_map->handle, LV2_MIDI_EVENT_URI); 71 break; 72 } 73 } 74 } 75 if (!urid_map) { 76 printf("Host does not support urid:map.\n"); 77 return; 78 } 79 80 lv2_atom_forge_init(&forge, urid_map); 81 82 /* Map URIS */ 83 QMidiArpURIs* const uris = &m_uris; 84 map_uris(urid_map, uris); 85 uridMap = urid_map; 86 } 87 88 89 MidiSeqLV2::~MidiSeqLV2 (void) 90 { 91 } 92 93 void MidiSeqLV2::connect_port ( uint32_t port, void *seqdata ) 94 { 95 switch(port) { 96 case 0: 97 inEventBuffer = (LV2_Atom_Sequence*)seqdata; 98 break; 99 case 1: 100 outEventBuffer = (const LV2_Atom_Sequence*)seqdata; 101 break; 102 default: 103 val[port - 2] = (float *)seqdata; 104 break; 105 } 106 } 107 108 void MidiSeqLV2::updatePosAtom(const LV2_Atom_Object* obj) 109 { 110 if (!hostTransport) return; 111 112 QMidiArpURIs* const uris = &m_uris; 113 114 uint64_t pos1 = transportFramesDelta; 115 float bpm1 = tempo; 116 int speed1 = transportSpeed; 117 118 // flag that the host sends transport information via atom port and 119 // that we will no longer process designated port events 120 transportAtomReceived = true; 121 122 LV2_Atom *bpm = NULL, *speed = NULL, *pos = NULL; 123 lv2_atom_object_get(obj, 124 uris->time_frame, &pos, 125 uris->time_beatsPerMinute, &bpm, 126 uris->time_speed, &speed, 127 NULL); 128 129 if (bpm && bpm->type == uris->atom_Float) bpm1 = ((LV2_Atom_Float*)bpm)->body; 130 if (pos && pos->type == uris->atom_Long) pos1 = ((LV2_Atom_Long*)pos)->body; 131 if (speed && speed->type == uris->atom_Float) speed1 = ((LV2_Atom_Float*)speed)->body; 132 133 updatePos(pos1, bpm1, speed1); 134 } 135 136 void MidiSeqLV2::updatePos(uint64_t pos, float bpm, int speed, bool ignore_pos) 137 { 138 if (transportBpm != bpm) { 139 /* Tempo changed */ 140 transportBpm = bpm; 141 tempo = transportBpm; 142 transportSpeed = 0; 143 } 144 145 if (!ignore_pos && (transportBpm > 0)) { 146 const float frames_per_beat = 60.0f / transportBpm * sampleRate; 147 transportFramesDelta = pos; 148 tempoChangeTick = pos * TPQN / frames_per_beat; 149 } 150 if (transportSpeed != speed) { 151 /* Speed changed, e.g. 0 (stop) to 1 (play) */ 152 transportSpeed = speed; 153 curFrame = transportFramesDelta; 154 if (transportSpeed) { 155 setNextTick(tempoChangeTick); 156 } 157 } 158 //printf("transportBpm %f, transportFramesDelta %d\n", transportBpm, transportFramesDelta); 159 } 160 161 void MidiSeqLV2::run (uint32_t nframes ) 162 { 163 const QMidiArpURIs* uris = &m_uris; 164 const uint32_t capacity = outEventBuffer->atom.size; 165 166 lv2_atom_forge_set_buffer(&forge, (uint8_t*)outEventBuffer, capacity); 167 lv2_atom_forge_sequence_head(&forge, &m_frame, 0); 168 169 sendWave(); 170 updateParams(); 171 172 if (inEventBuffer) { 173 LV2_ATOM_SEQUENCE_FOREACH(inEventBuffer, event) { 174 // Control Atom Input 175 if (event && (event->body.type == uris->atom_Object 176 || event->body.type == uris->atom_Blank)) { 177 const LV2_Atom_Object* obj = (LV2_Atom_Object*)&event->body; 178 if (obj->body.otype == uris->time_Position) { 179 /* Received position information, update */ 180 if (hostTransport) updatePosAtom(obj); 181 } 182 else if (obj->body.otype == uris->ui_up) { 183 /* UI was activated */ 184 ui_up = true; 185 dataChanged = true; 186 } 187 else if (obj->body.otype == uris->ui_down) { 188 /* UI was closed */ 189 ui_up = false; 190 } 191 } 192 // MIDI Input 193 else if (event && event->body.type == MidiEventID) { 194 uint8_t *di = (uint8_t *) LV2_ATOM_BODY(&event->body); 195 MidiEvent inEv = {0, 0, 0, 0}; 196 if ( (di[0] & 0xf0) == 0x90 ) { 197 inEv.type = EV_NOTEON; 198 inEv.value = di[2]; 199 } 200 else if ( (di[0] & 0xf0) == 0x80 ) { 201 inEv.type = EV_NOTEON; 202 inEv.value = 0; 203 } 204 else if ( (di[0] & 0xf0) == 0xb0 ) { 205 inEv.type = EV_CONTROLLER; 206 inEv.value = di[2]; 207 } 208 else inEv.type = EV_NONE; 209 210 inEv.channel = di[0] & 0x0f; 211 inEv.data=di[1]; 212 int tick = ((uint64_t)(curFrame - transportFramesDelta) * nframes 213 +(uint64_t)(&event->time.frames) % nframes) 214 *TPQN*tempo/nframes/60/sampleRate + tempoChangeTick; 215 if (handleEvent(inEv, tick - 2)) //if event is unmatched, forward it 216 forgeMidiEvent((int)((uint64_t)(&event->time.frames) % nframes), di, 3); 217 } 218 } 219 } 220 221 222 // MIDI Output 223 for (uint f = 0 ; f < nframes; f++) { 224 curTick = (uint64_t)(curFrame - transportFramesDelta) 225 *TPQN*tempo/60/sampleRate + tempoChangeTick; 226 if ((curTick >= nextTick) && (transportSpeed)) { 227 getNextFrame(curTick); 228 if (!returnNote.muted && !isMuted) { 229 unsigned char d[3]; 230 d[0] = 0x90 + channelOut; 231 d[1] = returnNote.value; 232 d[2] = vel; 233 forgeMidiEvent(f, d, 3); 234 evTickQueue[bufPtr] = curTick + notelength / 4; 235 evQueue[bufPtr] = returnNote.value; 236 bufPtr++; 237 } 238 float pos = (float)getFramePtr(); 239 *val[CURSOR_POS] = pos; 240 } 241 242 // Note Off Queue handling 243 int noteofftick = evTickQueue[0]; 244 int idx = 0; 245 for (int l1 = 0; l1 < bufPtr; l1++) { 246 int tmptick = evTickQueue[l1]; 247 if (noteofftick > tmptick) { 248 idx = l1; 249 noteofftick = tmptick; 250 } 251 } 252 if ( (bufPtr) && ((curTick >= noteofftick) 253 || (hostTransport && !transportSpeed)) ) { 254 int outval = evQueue[idx]; 255 for (int l4 = idx ; l4 < (bufPtr - 1);l4++) { 256 evQueue[l4] = evQueue[l4 + 1]; 257 evTickQueue[l4] = evTickQueue[l4 + 1]; 258 } 259 bufPtr--; 260 261 unsigned char d[3]; 262 d[0] = 0x80 + channelOut; 263 d[1] = outval; 264 d[2] = 127; 265 forgeMidiEvent(f, d, 3); 266 } 267 curFrame++; 268 } 269 } 270 271 void MidiSeqLV2::forgeMidiEvent(uint32_t f, const uint8_t* const buffer, uint32_t size) 272 { 273 QMidiArpURIs* const uris = &m_uris; 274 LV2_Atom midiatom; 275 midiatom.type = uris->midi_MidiEvent; 276 midiatom.size = size; 277 lv2_atom_forge_frame_time(&forge, f); 278 lv2_atom_forge_raw(&forge, &midiatom, sizeof(LV2_Atom)); 279 lv2_atom_forge_raw(&forge, buffer, size); 280 lv2_atom_forge_pad(&forge, sizeof(LV2_Atom) + size); 281 } 282 283 void MidiSeqLV2::updateParams() 284 { 285 bool changed = false; 286 287 if (loopMarker != (int)*val[LOOPMARKER]) { 288 changed = true; 289 setLoopMarker((int)*val[LOOPMARKER]); 290 } 291 292 if (dispVertIndex != (int)*val[DISPLAY_ZOOM]) { 293 changed = true; 294 dispVertIndex = (int)*val[DISPLAY_ZOOM]; 295 updateDispVert(dispVertIndex); 296 } 297 298 if (mouseXCur != *val[MOUSEX] || mouseYCur != *val[MOUSEY] 299 || mouseEvCur != *val[MOUSEPRESSED]) { 300 int ix = 1; 301 int evtype = 0; 302 changed = true; 303 mouseXCur = *val[MOUSEX]; 304 mouseYCur = *val[MOUSEY]; 305 if ((mouseEvCur == 2) && (*val[MOUSEPRESSED] != 2)) 306 evtype = 1; 307 else 308 evtype = *val[MOUSEPRESSED]; 309 310 mouseEvCur = *val[MOUSEPRESSED]; 311 312 if (mouseEvCur == 2) return; // mouse was released 313 ix = mouseEvent(mouseXCur, mouseYCur, *val[MOUSEBUTTON], evtype); 314 if (evtype == 1) lastMouseIndex = ix; // if we have a new press event set last point index here 315 } 316 317 if (currentRecStep != *val[CURR_RECSTEP]) { 318 changed = true; 319 *val[CURR_RECSTEP] = currentRecStep; 320 } 321 322 if (velFromGui != *val[VELOCITY]) { 323 velFromGui = *val[VELOCITY]; 324 updateVelocity(velFromGui); 325 } 326 327 if (notelength != sliderToTickLen(*val[NOTELENGTH])) { 328 updateNoteLength(sliderToTickLen(*val[NOTELENGTH])); 329 } 330 331 if (res != seqResValues[(int)*val[RESOLUTION]]) { 332 changed = true; 333 updateResolution(seqResValues[(int)*val[RESOLUTION]]); 334 } 335 336 if (size != seqSizeValues[(int)*val[SIZE]]) { 337 changed = true; 338 updateSize(seqSizeValues[(int)*val[SIZE]]); 339 } 340 341 if (transpFromGui != (int)*val[TRANSPOSE]) { 342 transpFromGui = (int)*val[TRANSPOSE]; 343 updateTranspose(transpFromGui); 344 } 345 346 if (curLoopMode != (*val[LOOPMODE])) updateLoop(*val[LOOPMODE]); 347 348 if (recordMode != ((bool)*val[RECORD])) { 349 setRecordMode((bool)*val[RECORD]); 350 } 351 352 if (deferChanges != ((bool)*val[DEFER])) deferChanges = ((bool)*val[DEFER]); 353 if (isMuted != (bool)*val[MUTE] && !parChangesPending) setMuted((bool)(*val[MUTE])); 354 355 enableNoteIn = (int)*val[ENABLE_NOTEIN]; 356 enableVelIn = (int)*val[ENABLE_VELIN]; 357 enableNoteOff = (bool)*val[ENABLE_NOTEOFF]; 358 restartByKbd = (bool)*val[ENABLE_RESTARTBYKBD]; 359 trigByKbd = (bool)*val[ENABLE_TRIGBYKBD]; 360 trigLegato = (bool)*val[ENABLE_TRIGLEGATO]; 361 362 channelOut = (int)*val[CH_OUT]; 363 chIn = (int)*val[CH_IN]; 364 indexIn[0] = (int)*val[INDEX_IN1]; 365 indexIn[1] = (int)*val[INDEX_IN2]; 366 rangeIn[0] = (int)*val[RANGE_IN1]; 367 rangeIn[1] = (int)*val[RANGE_IN2]; 368 369 if (internalTempo != *val[TEMPO]) { 370 internalTempo = *val[TEMPO]; 371 initTransport(); 372 } 373 374 if (hostTransport != (bool)(*val[TRANSPORT_MODE])) { 375 hostTransport = (bool)(*val[TRANSPORT_MODE]); 376 initTransport(); 377 } 378 379 if (hostTransport && !transportAtomReceived) { 380 updatePos( (uint64_t)*val[HOST_POSITION], 381 (float)*val[HOST_TEMPO], 382 (int)*val[HOST_SPEED], 383 false); 384 } 385 386 if (changed) { 387 getData(&data); 388 dataChanged = true; 389 } 390 } 391 392 void MidiSeqLV2::initTransport() 393 { 394 if (!hostTransport) { 395 transportFramesDelta = curFrame; 396 if (curTick > 0) tempoChangeTick = curTick; 397 transportBpm = internalTempo; 398 tempo = internalTempo; 399 transportSpeed = 1; 400 } 401 else transportSpeed = 0; 402 403 setNextTick(tempoChangeTick); 404 } 405 406 void MidiSeqLV2::sendWave() 407 { 408 if (!(dataChanged && ui_up)) return; 409 dataChanged = false; 410 411 const QMidiArpURIs* uris = &m_uris; 412 int ct = res * size + 1; // last element in wave is an end tag 413 int tempArray[ct]; 414 415 for (int l1 = 0; l1 < ct; l1++) { 416 tempArray[l1]=data[l1].value*((data[l1].muted) ? -1 : 1); 417 } 418 419 /* forge container object of type 'hex_customwave' */ 420 LV2_Atom_Forge_Frame frame; 421 lv2_atom_forge_frame_time(&forge, 0); 422 lv2_atom_forge_object(&forge, &frame, 1, uris->hex_customwave); 423 424 /* Send customWave to UI */ 425 lv2_atom_forge_property_head(&forge, uris->hex_customwave, 0); 426 lv2_atom_forge_vector(&forge, sizeof(int), uris->atom_Int, 427 ct, tempArray); 428 429 /* close-off frame */ 430 lv2_atom_forge_pop(&forge, &frame); 431 } 432 433 static LV2_State_Status MidiSeqLV2_state_restore ( LV2_Handle instance, 434 LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, 435 uint32_t flags, const LV2_Feature* const* ) 436 { 437 MidiSeqLV2 *pPlugin = static_cast<MidiSeqLV2 *> (instance); 438 439 if (pPlugin == NULL) return LV2_STATE_ERR_UNKNOWN; 440 441 QMidiArpURIs* const uris = &pPlugin->m_uris; 442 443 uint32_t type = uris->atom_String; 444 445 if (type == 0) return LV2_STATE_ERR_BAD_TYPE; 446 447 size_t size = 0; 448 int l1; 449 uint32_t key = uris->hex_mutemask; 450 if (!key) return LV2_STATE_ERR_NO_PROPERTY; 451 452 const char *value1 453 = (const char *) (*retrieve)(handle, key, &size, &type, &flags); 454 455 if (size < 2) return LV2_STATE_ERR_UNKNOWN; 456 457 pPlugin->setFramePtr(0); 458 pPlugin->maxNPoints = (size - 1 ) / 2; 459 460 for (l1 = 0; l1 < pPlugin->maxNPoints; l1++) { 461 pPlugin->muteMask[l1] = (value1[2 * l1 + 1] == '1'); 462 } 463 464 key = uris->hex_customwave; 465 if (!key) return LV2_STATE_ERR_NO_PROPERTY; 466 467 const char *value 468 = (const char *) (*retrieve)(handle, key, &size, &type, &flags); 469 470 if (size < 2) return LV2_STATE_ERR_UNKNOWN; 471 472 Sample sample; 473 int step = TPQN / pPlugin->res; 474 int lt = 0; 475 476 for (l1 = 0; l1 < pPlugin->maxNPoints; l1++) { 477 int hi = 0; 478 int lo = 0; 479 if (value[2*l1] <= '9' && value[2*l1] >= '0') hi = value[2*l1] - '0'; 480 if (value[2*l1] <= 'f' && value[2*l1] >= 'a') hi = value[2*l1] - 'a' + 10; 481 482 if (value[2*l1 + 1] <= '9' && value[2*l1 + 1] >= '0') lo = value[2*l1 + 1] - '0'; 483 if (value[2*l1 + 1] <= 'f' && value[2*l1 + 1] >= 'a') lo = value[2*l1 + 1] - 'a' + 10; 484 485 sample.value = hi * 16 + lo; 486 sample.tick = lt; 487 sample.muted = pPlugin->muteMask[l1]; 488 pPlugin->customWave[l1] = sample; 489 lt+=step; 490 } 491 492 pPlugin->getData(&pPlugin->data); 493 pPlugin->dataChanged = true; 494 return LV2_STATE_SUCCESS; 495 } 496 497 static LV2_State_Status MidiSeqLV2_state_save ( LV2_Handle instance, 498 LV2_State_Store_Function store, LV2_State_Handle handle, 499 uint32_t flags, const LV2_Feature* const* ) 500 { 501 MidiSeqLV2 *pPlugin = static_cast<MidiSeqLV2 *> (instance); 502 503 if (pPlugin == NULL) return LV2_STATE_ERR_UNKNOWN; 504 505 QMidiArpURIs* const uris = &pPlugin->m_uris; 506 507 uint32_t type = uris->atom_String; 508 509 if (type == 0) return LV2_STATE_ERR_BAD_TYPE; 510 511 flags |= (LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); 512 513 const char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7', 514 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 515 int l1; 516 char bt[pPlugin->maxNPoints * 2 + 1]; 517 518 for (l1 = 0; l1 < pPlugin->maxNPoints; l1++) { 519 bt[2*l1] = hexmap[(pPlugin->customWave[l1].value & 0xF0) >> 4]; 520 bt[2*l1 + 1] = hexmap[pPlugin->customWave[l1].value & 0x0F]; 521 } 522 bt[pPlugin->maxNPoints * 2] = '\0'; 523 524 const char *value = bt; 525 526 size_t size = strlen(value) + 1; 527 528 uint32_t key = uris->hex_customwave; 529 if (!key) return LV2_STATE_ERR_NO_PROPERTY; 530 531 store(handle, key, value, size, type, flags); 532 533 for (l1 = 0; l1 < pPlugin->maxNPoints; l1++) { 534 bt[2*l1] = '0'; 535 bt[2*l1 + 1] = hexmap[pPlugin->muteMask[l1]]; 536 } 537 538 const char *value1 = bt; 539 540 size = strlen(value1) + 1; 541 key = uris->hex_mutemask; 542 if (!key) return LV2_STATE_ERR_NO_PROPERTY; 543 544 LV2_State_Status result = (*store)(handle, key, value1, size, type, flags); 545 546 return result; 547 } 548 549 static const LV2_State_Interface MidiSeqLV2_state_interface = 550 { 551 MidiSeqLV2_state_save, 552 MidiSeqLV2_state_restore 553 }; 554 555 void MidiSeqLV2::activate (void) 556 { 557 initTransport(); 558 } 559 560 void MidiSeqLV2::deactivate (void) 561 { 562 transportSpeed = 0; 563 } 564 565 static LV2_Handle MidiSeqLV2_instantiate ( 566 const LV2_Descriptor *, double sample_rate, const char *, 567 const LV2_Feature *const *host_features ) 568 { 569 return new MidiSeqLV2(sample_rate, host_features); 570 } 571 572 static void MidiSeqLV2_connect_port ( 573 LV2_Handle instance, uint32_t port, void *data ) 574 { 575 MidiSeqLV2 *pPlugin = static_cast<MidiSeqLV2 *> (instance); 576 if (pPlugin) 577 pPlugin->connect_port(port, data); 578 } 579 580 static void MidiSeqLV2_run ( LV2_Handle instance, uint32_t nframes ) 581 { 582 MidiSeqLV2 *pPlugin = static_cast<MidiSeqLV2 *> (instance); 583 if (pPlugin) 584 pPlugin->run(nframes); 585 } 586 587 static void MidiSeqLV2_activate ( LV2_Handle instance ) 588 { 589 MidiSeqLV2 *pPlugin = static_cast<MidiSeqLV2 *> (instance); 590 if (pPlugin) 591 pPlugin->activate(); 592 } 593 594 static void MidiSeqLV2_deactivate ( LV2_Handle instance ) 595 { 596 MidiSeqLV2 *pPlugin = static_cast<MidiSeqLV2 *> (instance); 597 if (pPlugin) 598 pPlugin->deactivate(); 599 } 600 601 static void MidiSeqLV2_cleanup ( LV2_Handle instance ) 602 { 603 MidiSeqLV2 *pPlugin = static_cast<MidiSeqLV2 *> (instance); 604 if (pPlugin) 605 delete pPlugin; 606 } 607 608 static const void *MidiSeqLV2_extension_data ( const char * uri) 609 { 610 static const LV2_State_Interface state_iface = 611 { MidiSeqLV2_state_save, MidiSeqLV2_state_restore }; 612 if (!strcmp(uri, LV2_STATE__interface)) { 613 return &state_iface; 614 } 615 else return NULL; 616 } 617 618 static const LV2_Descriptor MidiSeqLV2_descriptor = 619 { 620 QMIDIARP_SEQ_LV2_URI, 621 MidiSeqLV2_instantiate, 622 MidiSeqLV2_connect_port, 623 MidiSeqLV2_activate, 624 MidiSeqLV2_run, 625 MidiSeqLV2_deactivate, 626 MidiSeqLV2_cleanup, 627 MidiSeqLV2_extension_data 628 }; 629 630 LV2_SYMBOL_EXPORT const LV2_Descriptor *lv2_descriptor ( uint32_t index ) 631 { 632 return (index == 0 ? &MidiSeqLV2_descriptor : NULL); 633 } 634 635