/* -*- mode:C++; indent-tabs-mode:t; tab-width:8; c-basic-offset: 8 -*- */ /* * * Copyright (c) 2003 by Karsten Wiese * Copyright (c) 2004-2007 by Rui Nuno Capela * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "Cus428Midi.h" char Cus428Midi::KnobParam[] = { 0x17, 0x16, 0x15, 0x14, 0x13, 0x2A, 0x29, 0x28, (char)-1, 0x10, 0x11, 0x18, 0x19, 0x1A, (char)-1, (char)-1, (char)-1, (char)-1, 0x2C, 0x2D, 0x2E, 0x2F, (char)-1, (char)-1, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0, 1, 2, 3, 4, 5, 6, 7, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, (char)-1, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, }; extern int verbose; // Parse and dispatch input MIDI events. void Cus428Midi::ProcessMidiEvents() { snd_seq_event_t *ev; unsigned char *data; do { ev = NULL; snd_seq_event_input(Seq, &ev); if (ev == NULL) break; switch (ev->type) { case SND_SEQ_EVENT_SYSEX: data = (unsigned char *) ev->data.ext.ptr; if (data[1] == 0x7f && data[3] == 0x06) { // MMC Command code is in data[4]... if (verbose > 1) fprintf(stderr, "MMC Command 0x%02x: ", data[4]); switch (data[4]) { case MMC_CMD_STOP: if (verbose > 1) fprintf(stderr, "STOP.\n"); OneState->TransportSet(T_STOP, true); break; case MMC_CMD_PLAY: case MMC_CMD_DEFERRED_PLAY: if (verbose > 1) fprintf(stderr, "PLAY.\n"); OneState->TransportSet(T_PLAY, true); break; case MMC_CMD_FAST_FORWARD: if (verbose > 1) fprintf(stderr, "FFWD.\n"); OneState->TransportSet(T_F_FWD, true); break; case MMC_CMD_REWIND: if (verbose > 1) fprintf(stderr, "REW.\n"); OneState->TransportSet(T_REW, true); break; case MMC_CMD_RECORD_STROBE: case MMC_CMD_RECORD_PAUSE: if (verbose > 1) fprintf(stderr, "RECORD ON.\n"); OneState->TransportSet(T_RECORD, true); break; case MMC_CMD_RECORD_EXIT: if (verbose > 1) fprintf(stderr, "RECORD OFF.\n"); OneState->TransportSet(T_RECORD, false); break; case MMC_CMD_LOCATE: if (verbose > 1) fprintf(stderr, "LOCATE.\n"); OneState->LocateWheel(&data[7]); break; case MMC_CMD_MASKED_WRITE: if (verbose > 1) fprintf(stderr, "MASKED WRITE.\n"); OneState->MaskedWrite(&data[6]); break; case MMC_CMD_MMC_RESET: if (verbose > 1) fprintf(stderr, "MMC RESET.\n"); OneState->MmcReset(); break; default: if (verbose > 1) fprintf(stderr, "Not implemented.\n"); break; } } // Look for Tascam US-224/US-428(?) specific LED codes. else if (data[1] == 0x4e && data[3] == 0x12) { if (verbose > 1) fprintf(stderr, "TASCAM Command 0x%02x.\n", data[4]); // Transport LEDs. switch (data[4]) { case 0x01: // Transport LEDs... switch(data[5]) { case 0x13: // REWIND. OneState->LightSet(Cus428State::eL_Rew, data[6]); OneState->LightSend(); break; case 0x14: // FFWD. OneState->LightSet(Cus428State::eL_FFwd, data[6]); OneState->LightSend(); break; case 0x16: // PLAY. OneState->LightSet(Cus428State::eL_Play, data[6]); OneState->LightSend(); break; case 0x17: // REC. OneState->LightSet(Cus428State::eL_Record, data[6]); OneState->LightSend(); break; default: break; } break; case 0x02: // Mute LEDs OneState->LightSet(Cus428State::eL_Mute0 + data[5], data[6]); OneState->LightSend(); break; case 0x03: // Select LEDs OneState->LightSet(Cus428State::eL_Select0 + data[5], data[6]); OneState->LightSend(); break; case 0x04: // Record LEDs OneState->LightSet(Cus428State::eL_Rec0 + data[5], data[6]); OneState->LightSend(); break; case 0x05: // Null LED OneState->LightSet(Cus428State::eL_Null, data[5]); OneState->LightSend(); break; case 0x06: // Solo LED OneState->LightSet(Cus428State::eL_Solo, data[5]); OneState->LightSend(); break; case 0x07: // Bank L LED OneState->LightSet(Cus428State::eL_BankL, data[5]); OneState->LightSend(); break; case 0x08: // Bank R LED OneState->LightSet(Cus428State::eL_BankR, data[5]); OneState->LightSend(); break; case 0x10: // Dump fader position. OneState->SliderSend(data[5]); break; } } break; default: break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(Seq, 0) > 0); } // Send MMC command. void Cus428Midi::SendMmcCommand(unsigned char MmcCmd, unsigned char *MmcData, unsigned char MmcLen) { unsigned char SysexSize; unsigned char SysexLen; unsigned char *SysexData; SysexSize = 6; if (MmcLen > 0) SysexSize += 1 + MmcLen; SysexData = (unsigned char *) alloca(SysexSize); SysexLen = 0; SysexData[SysexLen++] = 0xf0; // Sysex header. SysexData[SysexLen++] = 0x7f; // Realtime sysex. SysexData[SysexLen++] = 0x7f; // All-caller-id. SysexData[SysexLen++] = 0x06; // MMC command mode. SysexData[SysexLen++] = MmcCmd; // MMC command code. if (MmcData && MmcLen > 0) { SysexData[SysexLen++] = MmcLen; memcpy(&SysexData[SysexLen], MmcData, MmcLen); SysexLen += MmcLen; } SysexData[SysexLen++] = 0xf7; // Sysex trailer. snd_seq_ev_set_sysex(&Ev, SysexLen, SysexData); SubMitEvent(); }