jm2cv/jm2cv.cpp

164 lines
4.3 KiB
C++
Raw Permalink Normal View History

2010-01-24 20:46:33 +00:00
#include <iostream>
#include <cstring>
#include <csignal>
2010-03-24 18:14:48 +00:00
#include <cstdio>
2013-02-13 23:13:53 +00:00
#include <unistd.h>
2010-01-24 20:46:33 +00:00
#include "cvout.h"
#include "cvin.h"
static CVOut cvout;
static CVIn cvin;
bool read_config(const char *filename)
{
FILE *f = fopen(filename, "r");
if (f == NULL) {
std::cerr << "Unable to open '" << filename << "' for reading" << std::endl;
return false;
}
2010-01-25 21:18:23 +00:00
int line = 0;
bool good = true;
2010-01-25 21:18:23 +00:00
2010-01-24 20:46:33 +00:00
while (!feof(f)) {
2010-01-25 21:18:23 +00:00
line++;
2010-01-26 09:24:54 +00:00
char buf[80], name[80];
2010-01-24 20:46:33 +00:00
fgets(buf, sizeof buf, f);
/* Ignore comments */
if (buf[0] == '#') continue;
2010-01-26 09:24:54 +00:00
/* Try parsing port name entries */
if (sscanf(buf, "cvin_name %s", name) == 1) {
cvin.set_name(name);
continue;
} else if (sscanf(buf, "cvout_name %s", name) == 1) {
cvout.set_name(name);
continue;
}
char dir[80], type[80];
2010-01-24 20:46:33 +00:00
int channel, ccmsb, cclsb, mrl, mru;
float crl, cru;
float latency;
if (sscanf(buf, "%s %s %d %s %d %d %d %d %f %f %f", dir, name, &channel, type, &ccmsb, &cclsb, &mrl, &mru, &crl, &cru, &latency) == 11) {
ControllerType itype;
bool has_lsb = true;
if (!strcmp(type, "pb")) itype = TYPE_PB;
else if (!strcmp(type, "cc")) itype = TYPE_CC;
else if (!strcmp(type, "nrpn")) itype = TYPE_NRPN;
else if (!strcmp(type, "nrpn7")) { itype = TYPE_NRPN; has_lsb = false; }
else if (!strcmp(type, "rpn")) itype = TYPE_RPN;
else if (!strcmp(type, "rpn7")) { itype = TYPE_RPN; has_lsb = false; }
2010-01-25 21:18:23 +00:00
else {
std::clog << line << ": Unknown type '" << type << "'." << std::endl;
good = false;
itype = TYPE_CC;
2010-01-25 21:18:23 +00:00
}
if (itype == TYPE_CC && cclsb == -1) has_lsb = false;
if (itype == TYPE_PB) {
if (ccmsb != -1) continue;
if (cclsb != -1) continue;
if (mrl < 0 || mrl > 16383) continue;
if (mru < 0 || mru > 16383) continue;
has_lsb = false;
} else {
2010-01-25 21:18:23 +00:00
if (ccmsb < 0 || ccmsb > 127) {
std::clog << line << ": CC MSB " << ccmsb << " must be between 0 and 127." << std::endl;
good = false;
2010-01-25 21:18:23 +00:00
}
if (cclsb < -1 || cclsb > 127) {
std::clog << line << ": CC LSB " << cclsb << " must be between -1 and 127." << std::endl;
good = false;
2010-01-25 21:18:23 +00:00
}
if (mrl < 0 || mrl > (has_lsb ? 16383 : 127)) {
std::clog << line << ": MIDI range lower bound " << mrl << " must be between 0 and " << (has_lsb ? 16383 : 127) << "." << std::endl;
good = false;
2010-01-25 21:18:23 +00:00
}
if (mru < 0 || mru > (has_lsb ? 16383 : 127)) {
std::clog << line << ": MIDI range upper bound " << mru << " must be between 0 and " << (has_lsb ? 16383 : 127) << "." << std::endl;
good = false;
2010-01-25 21:18:23 +00:00
}
}
if (mrl > mru) {
std::clog << line << ": MIDI range lower bound must be below upper bound." << std::endl;
good = false;
}
2010-01-24 20:46:33 +00:00
// if (crl < -1.0f || crl > 1.0f) continue;
// if (cru < -1.0f || cru > 1.0f) continue;
2010-01-25 21:18:23 +00:00
// if (crl > cru) continue;
if (latency < 0.0f) {
std::clog << line << ": Latency " << latency << " must be greater than zero." << std::endl;
good = false;
2010-01-25 21:18:23 +00:00
}
2010-01-24 20:46:33 +00:00
if (!strcmp(dir, "cvout")) {
2010-01-25 21:18:23 +00:00
if (channel < -1 || channel > 15) {
std::clog << line << ": MIDI channel " << channel << " must be between -1 and 15." << std::endl;
good = false;
2010-01-25 21:18:23 +00:00
}
2010-01-25 21:32:59 +00:00
if (cvout.find(name)) {
std::clog << line << ": Name '" << name << "' already defined." << std::endl;
good = false;
2010-01-25 21:32:59 +00:00
}
cvout.add_mapping(Mapping(name, channel, itype, ccmsb, cclsb, mrl, mru, crl, cru, latency, has_lsb));
} else if (!strcmp(dir, "cvin")) {
2010-01-25 21:18:23 +00:00
if (channel < 0 || channel > 15) {
std::clog << line << ": MIDI channel " << channel << " must be between 0 and 15." << std::endl;
good = false;
2010-01-25 21:18:23 +00:00
}
2010-01-25 21:32:59 +00:00
if (cvin.find(name)) {
std::clog << line << ": Name '" << name << "' already defined." << std::endl;
good = false;
2010-01-25 21:32:59 +00:00
}
cvin.add_mapping(Mapping(name, channel, itype, ccmsb, cclsb, mrl, mru, crl, cru, latency, has_lsb));
2010-01-24 20:46:33 +00:00
}
}
}
2010-01-26 19:04:06 +00:00
fclose(f);
if (!good) {
std::cerr << "Error(s) in configuration file, stopping." << std::endl;
}
return good;
2010-01-24 20:46:33 +00:00
}
static int _running = false;
static void sigint_handler(int)
{
_running = false;
}
int main(int argc, char **argv)
{
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <config>" << std::endl;
return 0;
}
if (!read_config(argv[1])) return 0;
cvout.start();
cvin.start();
_running = true;
signal(SIGINT, &sigint_handler);
signal(SIGTERM, &sigint_handler);
while (_running) {
sleep(1);
}
cvin.stop();
cvout.stop();
}