LMMS
Loading...
Searching...
No Matches
miditable.cpp
Go to the documentation of this file.
1#include <math.h>
2#include <rtosc/miditable.h>
3
4using namespace rtosc;
5
6#define RTOSC_INVALID_MIDI 255
7
9{
10 public:
11 MidiTable_Impl(unsigned len, unsigned elms)
12 :len(len), elms(elms)
13 {
14 table = new MidiAddr[elms];
15 for(unsigned i=0; i<elms; ++i) {
18 table[i].path = new char[len];
19 table[i].conversion = NULL;
20 }
21 //TODO initialize all elms
22 }
24 {
25 for(unsigned i=0; i<elms; ++i) {
26 delete [] table[i].path;
27 }
28 delete [] table;
29 }
30
31 MidiAddr *begin(void) {return table;}
32 MidiAddr *end(void) {return table + elms;}
33
34 unsigned len;
35 unsigned elms;
37};
38
39//MidiAddr::MidiAddr(void)
40// :ch(RTOSC_INVALID_MIDI),ctl(RTOSC_INVALID_MIDI)
41//{}
42
43static void black_hole3 (const char *, const char *, const char *, int, int)
44{}
45static void black_hole2(const char *a, const char *b)
46{printf("'%s' and '%s'\n", a,b);}
47static void black_hole1(const char *a)
48{printf("'%s'\n", a);}
49
50#define MAX_UNHANDLED_PATH 128
51
60
62{
63 delete impl;
64 delete [] unhandled_path;
65}
66
67bool MidiTable::has(uint8_t ch, uint8_t ctl) const
68{
69 for(auto e: *impl) {
70 if(e.ch == ch && e.ctl == ctl)
71 return true;
72 }
73 return false;
74}
75
77{
78 for(auto &e: *impl)
79 if(e.ch==ch && e.ctl == ctl)
80 return &e;
81 return NULL;
82}
83
85{
86 for(auto &e:*impl)
87 if(e.ch==ch && e.ctl == ctl)
88 return &e;
89 return NULL;
90}
91
93{
94 const char *args = strchr(port.name, ':');
95 if(!args)
96 return false;
97
98 //Consider a path to be typed based upon the argument restrictors
99 if(strchr(args, 'f')) {
100 e.type = 'f';
101 e.conversion = port.metadata;
102 } else if(strchr(args, 'i'))
103 e.type = 'i';
104 else if(strchr(args, 'T'))
105 e.type = 'T';
106 else if(strchr(args, 'c'))
107 e.type = 'c';
108 else
109 return false;
110 return true;
111}
112
113void MidiTable::addElm(uint8_t ch, uint8_t ctl, const char *path)
114{
115 const Port *port = dispatch_root.apropos(path);
116
117 if(!port || port->ports) {//missing or directory node
118 error_cb("Bad path", path);
119 return;
120 }
121
122 if(MidiAddr *e = this->get(ch,ctl)) {
123 strncpy(e->path,path,impl->len);
124 if(!mash_port(*e, *port)) {
125 e->ch = RTOSC_INVALID_MIDI;
126 e->ctl = RTOSC_INVALID_MIDI;
127 error_cb("Failed to read metadata", path);
128 }
129 modify_cb("REPLACE", path, e->conversion, (int) ch, (int) ctl);
130 return;
131 }
132
133 for(MidiAddr &e:*impl) {
134 if(e.ch == RTOSC_INVALID_MIDI) {//free spot
135 e.ch = ch;
136 e.ctl = ctl;
137 strncpy(e.path,path,impl->len);
138 if(!mash_port(e, *port)) {
140 e.ctl = RTOSC_INVALID_MIDI;
141 error_cb("Failed to read metadata", path);
142 }
143 modify_cb("ADD", path, e.conversion, (int) ch, (int) ctl);
144 return;
145 }
146 }
147}
148
157
158void MidiTable::learn(const char *s)
159{
160 if(strlen(s) > impl->len) {
161 error_cb("String too long", s);
162 return;
163 }
164 clear_entry(s);
167 check_learn();
168}
169
170void MidiTable::clear_entry(const char *s)
171{
172 for(unsigned i=0; i<impl->elms; ++i) {
173 if(!strcmp(impl->table[i].path, s)) {
174 //Invalidate
175 impl->table[i].ch = RTOSC_INVALID_MIDI;
176 impl->table[i].ctl = RTOSC_INVALID_MIDI;
177 modify_cb("DEL", s, "", -1, -1);
178 break;
179 }
180 }
181}
182
184{
185 const MidiAddr *addr = get(ch,ctl);
186 if(!addr) {
187 unhandled_ctl = ctl;
188 unhandled_ch = ch;
189 check_learn();
190 return;
191 }
192
193 char buffer[1024];
194 switch(addr->type)
195 {
196 case 'f':
197 rtosc_message(buffer, 1024, addr->path,
198 "f", translate(val,addr->conversion));
199 break;
200 case 'i':
201 rtosc_message(buffer, 1024, addr->path,
202 "i", val);
203 break;
204 case 'T':
205 rtosc_message(buffer, 1024, addr->path,
206 (val<64 ? "F" : "T"));
207 break;
208 case 'c':
209 rtosc_message(buffer, 1024, addr->path,
210 "c", val);
211 }
212
213 event_cb(buffer);
214}
215
217{
218 return Port{"learn:s", "", 0, [this](msg_t m, RtData&){
219 this->learn(rtosc_argument(m,0).s);
220 }};
221
222}
223
225{
226 return Port{"unlearn:s", "", 0, [this](msg_t m, RtData&){
227 this->clear_entry(rtosc_argument(m,0).s);
228 }};
229
230}
231
233{
234 return Port{"register:iis","", 0, [this](msg_t m,RtData&){
235 const char *pos = rtosc_argument(m,2).s;
236 while(*pos) putchar(*pos++);
238}
239
240//TODO generalize to an addScalingFunction() system
241float MidiTable::translate(uint8_t val, const char *meta_)
242{
243 //Allow for middle value to be set
244 //TODO consider the centered trait for this op
245 float x = val!=64.0 ? val/127.0 : 0.5;
246
247 Port::MetaContainer meta(meta_);
248
249 if(!meta["min"] || !meta["max"] || !meta["scale"]) {
250 fprintf(stderr, "failed to get properties\n");
251 return 0.0f;
252 }
253
254 const float min = atof(meta["min"]);
255 const float max = atof(meta["max"]);
256 const char *scale = meta["scale"];
257
258 if(!strcmp(scale,"linear"))
259 return x*(max-min)+min;
260 else if(!strcmp(scale,"logarithmic")) {
261 const float b = log(min);
262 const float a = log(max)-b;
263 return expf(a*x+b);
264 }
265
266 return 0.0f;
267}
#define NULL
Definition CarlaBridgeFormat.cpp:30
uint8_t a
Definition Spc_Cpu.h:141
Definition miditable.cpp:9
MidiAddr * begin(void)
Definition miditable.cpp:31
MidiAddr * end(void)
Definition miditable.cpp:32
MidiAddr * table
Definition miditable.cpp:36
unsigned len
Definition miditable.cpp:34
unsigned elms
Definition miditable.cpp:35
MidiTable_Impl(unsigned len, unsigned elms)
Definition miditable.cpp:11
~MidiTable_Impl()
Definition miditable.cpp:23
void process(uint8_t ch, uint8_t ctl, uint8_t val)
Definition miditable.cpp:183
short unhandled_ch
Definition miditable.h:245
void clear_entry(const char *s)
Definition miditable.cpp:170
void(* error_cb)(const char *, const char *)
Definition miditable.h:249
void addElm(uint8_t ch, uint8_t ctl, const char *path)
Definition miditable.cpp:113
class MidiTable_Impl * impl
Definition miditable.h:282
void learn(const char *s)
Definition miditable.cpp:158
static float translate(uint8_t val, const char *meta)
Definition miditable.cpp:241
void(* event_cb)(const char *)
Definition miditable.h:250
Port learnPort(void)
Definition miditable.cpp:216
bool has(uint8_t ch, uint8_t ctl) const
Definition miditable.cpp:67
short unhandled_ctl
Definition miditable.h:246
void(* modify_cb)(const char *, const char *, const char *, int, int)
Definition miditable.h:251
char * unhandled_path
Definition miditable.h:247
MidiTable(const Ports &_dispatch_root)
Definition miditable.cpp:52
~MidiTable()
Definition miditable.cpp:61
void check_learn(void)
Definition miditable.cpp:149
MidiAddr * get(uint8_t ch, uint8_t ctl)
Definition miditable.cpp:76
Port registerPort(void)
Definition miditable.cpp:232
bool mash_port(MidiAddr &e, const Port &port)
Definition miditable.cpp:92
const Ports & dispatch_root
Definition miditable.h:244
Port unlearnPort(void)
Definition miditable.cpp:224
Definition ports.h:124
* e
Definition inflate.c:1404
unsigned * m
Definition inflate.c:1559
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned x[BMAX+1]
Definition inflate.c:1586
int val
Definition jpeglib.h:956
unsigned char uint8_t
Definition mid.cpp:98
static void black_hole2(const char *a, const char *b)
Definition miditable.cpp:45
#define MAX_UNHANDLED_PATH
Definition miditable.cpp:50
static void black_hole1(const char *a)
Definition miditable.cpp:47
#define RTOSC_INVALID_MIDI
Definition miditable.cpp:6
static void black_hole3(const char *, const char *, const char *, int, int)
Definition miditable.cpp:43
Definition globals.h:37
const char * msg_t
Definition ports.h:48
#define min(x, y)
Definition os.h:74
#define max(x, y)
Definition os.h:78
size_t rtosc_message(char *buffer, size_t len, const char *address, const char *arguments,...)
Definition rtosc.c:161
rtosc_arg_t rtosc_argument(const char *msg, unsigned idx)
Definition rtosc.c:732
Definition miditable.h:223
char type
Definition miditable.h:228
const char * conversion
Definition miditable.h:232
char * path
Definition miditable.h:230
Definition ports.h:99
Definition ports.h:161
data object for the dispatch routine
Definition ports.h:55
const char * s
Definition rtosc.h:54
b
Definition crypt.c:628