/* -*- mode:C++; indent-tabs-mode:t; tab-width:8; c-basic-offset: 8 -*- */
/*
*
* Copyright (c) 2003 by Karsten Wiese <annabellesgarden@yahoo.de>
* Copyright (c) 2004-2007 by Rui Nuno Capela <rncbc@rncbc.org>
*
* 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 <alsa/asoundlib.h>
#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();
}