1 /* FluidSynth - A Software Synthesizer
2  *
3  * Copyright (C) 2003  Peter Hanappe and others.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public License
7  * as published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  * 02110-1301, USA
19  */
20 
21 /* Original author: Markus Nentwig, nentwig@users.sourceforge.net
22  *
23  * Josh Green made it general purpose with a complete usable public API and
24  * cleaned it up a bit.
25  */
26 
27 #include "fluid_midi_router.h"
28 #include "fluid_midi.h"
29 #include "fluid_synth.h"
30 
31 /*
32  * fluid_midi_router
33  */
34 struct _fluid_midi_router_t {
35   fluid_synth_t* synth;
36 
37   fluid_mutex_t rules_mutex;
38   fluid_midi_router_rule_t *rules[FLUID_MIDI_ROUTER_RULE_COUNT];        /* List of rules for each rule type */
39   fluid_midi_router_rule_t *free_rules;      /* List of rules to free (was waiting for final events which were received) */
40 
41   handle_midi_event_func_t event_handler;    /* Callback function for generated events */
42   void* event_handler_data;                  /* One arg for the callback */
43 
44   int nr_midi_channels;                      /* For clipping the midi channel */
45 
46   /* FIXME - If there are multiple command handlers, they will conflict! */
47   fluid_midi_router_rule_t *cmd_rule;        /* Rule currently being processed by shell command handler */
48   int cmd_rule_type;                         /* Type of the rule (fluid_midi_router_rule_type) */
49 };
50 
51 struct _fluid_midi_router_rule_t {
52     int chan_min;                            /* Channel window, for which this rule is valid */
53     int chan_max;
54     fluid_real_t chan_mul;                   /* Channel multiplier (usually 0 or 1) */
55     int chan_add;                            /* Channel offset */
56 
57     int par1_min;                            /* Parameter 1 window, for which this rule is valid */
58     int par1_max;
59     fluid_real_t par1_mul;
60     int par1_add;
61 
62     int par2_min;                            /* Parameter 2 window, for which this rule is valid */
63     int par2_max;
64     fluid_real_t par2_mul;
65     int par2_add;
66 
67     int pending_events;                      /* In case of noteon: How many keys are still down? */
68     char keys_cc[128];                       /* Flags, whether a key is down / controller is set (sustain) */
69     fluid_midi_router_rule_t* next;          /* next entry */
70     int waiting;                             /* Set to TRUE when rule has been deactivated but there are still pending_events */
71 };
72 
73 
74 /**
75  * Create a new midi router.  The default rules will pass all events unmodified.
76  * @param settings Settings used to configure MIDI router
77  * @param handler MIDI event callback.
78  * @param event_handler_data Caller defined data pointer which gets passed to 'handler'
79  * @return New MIDI router instance or NULL on error
80  *
81  * The MIDI handler callback should process the possibly filtered/modified MIDI
82  * events from the MIDI router and forward them on to a synthesizer for example.
83  * The function fluid_synth_handle_midi_event() can be used for \a handle and
84  * a #fluid_synth_t passed as the \a event_handler_data parameter for this purpose.
85  */
86 fluid_midi_router_t *
new_fluid_midi_router(fluid_settings_t * settings,handle_midi_event_func_t handler,void * event_handler_data)87 new_fluid_midi_router(fluid_settings_t *settings, handle_midi_event_func_t handler,
88                       void *event_handler_data)
89 {
90   fluid_midi_router_t *router = NULL;
91   int i;
92 
93   router = FLUID_NEW (fluid_midi_router_t);
94 
95   if (router == NULL)
96   {
97     FLUID_LOG(FLUID_ERR, "Out of memory");
98     return NULL;
99   }
100 
101   FLUID_MEMSET (router, 0, sizeof (fluid_midi_router_t));
102 
103   /* Retrieve the number of MIDI channels for range limiting */
104   fluid_settings_getint(settings, "synth.midi-channels", &router->nr_midi_channels);
105 
106   fluid_mutex_init (router->rules_mutex);
107 
108   router->synth = (fluid_synth_t *)event_handler_data;
109   router->event_handler = handler;
110   router->event_handler_data = event_handler_data;
111 
112   /* Create default routing rules which pass all events unmodified */
113   for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
114   {
115     router->rules[i] = new_fluid_midi_router_rule ();
116     if (!router->rules[i]) goto error_recovery;
117   }
118 
119   return router;
120 
121  error_recovery:
122   delete_fluid_midi_router (router);
123   return NULL;
124 }
125 
126 /**
127  * Delete a MIDI router instance.
128  * @param router MIDI router to delete
129  * @return Returns #FLUID_OK on success, #FLUID_FAILED otherwise (only if NULL
130  *   \a router passed really)
131  */
132 int
delete_fluid_midi_router(fluid_midi_router_t * router)133 delete_fluid_midi_router (fluid_midi_router_t *router)
134 {
135   fluid_midi_router_rule_t *rule;
136   fluid_midi_router_rule_t *next_rule;
137   int i;
138 
139   fluid_return_val_if_fail (router != NULL, FLUID_FAILED);
140 
141   for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
142   {
143     for (rule = router->rules[i]; rule; rule = next_rule)
144     {
145       next_rule = rule->next;
146       FLUID_FREE (rule);
147     }
148   }
149 
150   fluid_mutex_destroy (router->rules_mutex);
151   FLUID_FREE (router);
152 
153   return FLUID_OK;
154 }
155 
156 /**
157  * Set a MIDI router to use default "unity" rules. Such a router will pass all
158  * events unmodified.
159  * @param router Router to set to default rules.
160  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
161  * @since 1.1.0
162  */
163 int
fluid_midi_router_set_default_rules(fluid_midi_router_t * router)164 fluid_midi_router_set_default_rules (fluid_midi_router_t *router)
165 {
166   fluid_midi_router_rule_t *new_rules[FLUID_MIDI_ROUTER_RULE_COUNT];
167   fluid_midi_router_rule_t *del_rules[FLUID_MIDI_ROUTER_RULE_COUNT];
168   fluid_midi_router_rule_t *rule, *next_rule, *prev_rule;
169   int i, i2;
170 
171   fluid_return_val_if_fail (router != NULL, FLUID_FAILED);
172 
173   /* Allocate new default rules outside of lock */
174 
175   for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
176   {
177     new_rules[i] = new_fluid_midi_router_rule ();
178 
179     if (!new_rules[i])
180     { /* Free already allocated rules */
181       for (i2 = 0; i2 < i; i2++)
182         delete_fluid_midi_router_rule (new_rules[i]);
183 
184       return FLUID_FAILED;
185     }
186   }
187 
188 
189   fluid_mutex_lock (router->rules_mutex);       /* ++ lock */
190 
191   for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
192   {
193     del_rules[i] = NULL;
194     prev_rule = NULL;
195 
196     /* Process existing rules */
197     for (rule = router->rules[i]; rule; rule = next_rule)
198     {
199       next_rule = rule->next;
200 
201       if (rule->pending_events == 0)    /* Rule has no pending events? */
202       { /* Remove rule from rule list */
203         if (prev_rule) prev_rule->next = next_rule;
204         else if (rule == router->rules[i]) router->rules[i] = next_rule;
205 
206         /* Prepend to delete list */
207         rule->next = del_rules[i];
208         del_rules[i] = rule;
209       }
210       else
211       {
212         rule->waiting = TRUE;          /* Pending events, mark as waiting */
213         prev_rule = rule;
214       }
215     }
216 
217     /* Prepend new default rule */
218     new_rules[i]->next = router->rules[i];
219     router->rules[i] = new_rules[i];
220   }
221 
222   fluid_mutex_unlock (router->rules_mutex);     /* -- unlock */
223 
224 
225   /* Free old rules outside of lock */
226 
227   for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
228   {
229     for (rule = del_rules[i]; rule; rule = next_rule)
230     {
231       next_rule = rule->next;
232       FLUID_FREE (rule);
233     }
234   }
235 
236   return FLUID_OK;
237 }
238 
239 /**
240  * Clear all rules in a MIDI router. Such a router will drop all events until
241  * rules are added.
242  * @param router Router to clear all rules from
243  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
244  * @since 1.1.0
245  */
246 int
fluid_midi_router_clear_rules(fluid_midi_router_t * router)247 fluid_midi_router_clear_rules (fluid_midi_router_t *router)
248 {
249   fluid_midi_router_rule_t *del_rules[FLUID_MIDI_ROUTER_RULE_COUNT];
250   fluid_midi_router_rule_t *rule, *next_rule, *prev_rule;
251   int i;
252 
253   fluid_return_val_if_fail (router != NULL, FLUID_FAILED);
254 
255   fluid_mutex_lock (router->rules_mutex);       /* ++ lock */
256 
257   for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
258   {
259     del_rules[i] = NULL;
260     prev_rule = NULL;
261 
262     /* Process existing rules */
263     for (rule = router->rules[i]; rule; rule = next_rule)
264     {
265       next_rule = rule->next;
266 
267       if (rule->pending_events == 0)    /* Rule has no pending events? */
268       { /* Remove rule from rule list */
269         if (prev_rule) prev_rule->next = next_rule;
270         else if (rule == router->rules[i]) router->rules[i] = next_rule;
271 
272         /* Prepend to delete list */
273         rule->next = del_rules[i];
274         del_rules[i] = rule;
275       }
276       else
277       {
278         rule->waiting = TRUE;           /* Pending events, mark as waiting */
279         prev_rule = rule;
280       }
281     }
282   }
283 
284   fluid_mutex_unlock (router->rules_mutex);     /* -- unlock */
285 
286 
287   /* Free old rules outside of lock */
288 
289   for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
290   {
291     for (rule = del_rules[i]; rule; rule = next_rule)
292     {
293       next_rule = rule->next;
294       FLUID_FREE (rule);
295     }
296   }
297 
298   return FLUID_OK;
299 }
300 
301 /**
302  * Add a rule to a MIDI router.
303  * @param router MIDI router
304  * @param rule Rule to add (used directly and should not be accessed again following a
305  *   successful call to this function).
306  * @param type The type of rule to add (#fluid_midi_router_rule_type)
307  * @return #FLUID_OK on success, #FLUID_FAILED otherwise (invalid rule for example)
308  * @since 1.1.0
309  */
310 int
fluid_midi_router_add_rule(fluid_midi_router_t * router,fluid_midi_router_rule_t * rule,int type)311 fluid_midi_router_add_rule (fluid_midi_router_t *router, fluid_midi_router_rule_t *rule,
312                             int type)
313 {
314   fluid_midi_router_rule_t *free_rules, *next_rule;
315 
316   fluid_return_val_if_fail (router != NULL, FLUID_FAILED);
317   fluid_return_val_if_fail (rule != NULL, FLUID_FAILED);
318   fluid_return_val_if_fail (type >= 0 && type <= FLUID_MIDI_ROUTER_RULE_COUNT, FLUID_FAILED);
319 
320 
321   fluid_mutex_lock (router->rules_mutex);       /* ++ lock */
322 
323   /* Take over free rules list, if any (to free outside of lock) */
324   free_rules = router->free_rules;
325   router->free_rules = NULL;
326 
327   rule->next = router->rules[type];
328   router->rules[type] = rule;
329 
330   fluid_mutex_unlock (router->rules_mutex);     /* -- unlock */
331 
332 
333   /* Free any deactivated rules which were waiting for events and are now done */
334 
335   for (; free_rules; free_rules = next_rule)
336   {
337     next_rule = free_rules->next;
338     FLUID_FREE (free_rules);
339   }
340 
341   return FLUID_OK;
342 }
343 
344 /**
345  * Create a new MIDI router rule.
346  * @return Newly allocated router rule or NULL if out of memory.
347  * @since 1.1.0
348  *
349  * The new rule is a "unity" rule which will accept any values and wont modify
350  * them.
351  */
352 fluid_midi_router_rule_t *
new_fluid_midi_router_rule(void)353 new_fluid_midi_router_rule (void)
354 {
355   fluid_midi_router_rule_t *rule;
356 
357   rule = FLUID_NEW (fluid_midi_router_rule_t);
358 
359   if (rule == NULL) {
360     FLUID_LOG(FLUID_ERR, "Out of memory");
361     return NULL;
362   }
363 
364   FLUID_MEMSET (rule, 0, sizeof (fluid_midi_router_rule_t));
365 
366   rule->chan_min = 0;
367   rule->chan_max = 999999;
368   rule->chan_mul = 1.0;
369   rule->chan_add = 0;
370   rule->par1_min = 0;
371   rule->par1_max = 999999;
372   rule->par1_mul = 1.0;
373   rule->par1_add = 0;
374   rule->par2_min = 0;
375   rule->par2_max = 999999;
376   rule->par2_mul = 1.0;
377   rule->par2_add = 0;
378 
379   return rule;
380 };
381 
382 /**
383  * Free a MIDI router rule.
384  * @param rule Router rule to free
385  * @since 1.1.0
386  *
387  * Note that rules which have been added to a router are managed by the router,
388  * so this function should seldom be needed.
389  */
390 void
delete_fluid_midi_router_rule(fluid_midi_router_rule_t * rule)391 delete_fluid_midi_router_rule (fluid_midi_router_rule_t *rule)
392 {
393   fluid_return_if_fail (rule != NULL);
394   FLUID_FREE (rule);
395 }
396 
397 /**
398  * Set the channel portion of a rule.
399  * @param rule MIDI router rule
400  * @param min Minimum value for rule match
401  * @param max Maximum value for rule match
402  * @param mul Value which is multiplied by matching event's channel value (1.0 to not modify)
403  * @param add Value which is added to matching event's channel value (0 to not modify)
404  * @since 1.1.0
405  *
406  * The \a min and \a max parameters define a channel range window to match
407  * incoming events to.  If \a min is less than or equal to \a max then an event
408  * is matched if its channel is within the defined range (including \a min
409  * and \a max). If \a min is greater than \a max then rule is inverted and matches
410  * everything except in *between* the defined range (so \a min and \a max would match).
411  *
412  * The \a mul and \a add values are used to modify event channel values prior to
413  * sending the event, if the rule matches.
414  */
415 void
fluid_midi_router_rule_set_chan(fluid_midi_router_rule_t * rule,int min,int max,float mul,int add)416 fluid_midi_router_rule_set_chan (fluid_midi_router_rule_t *rule, int min, int max,
417                                  float mul, int add)
418 {
419   fluid_return_if_fail (rule != NULL);
420   rule->chan_min = min;
421   rule->chan_max = max;
422   rule->chan_mul = mul;
423   rule->chan_add = add;
424 }
425 
426 /**
427  * Set the first parameter portion of a rule.
428  * @param rule MIDI router rule
429  * @param min Minimum value for rule match
430  * @param max Maximum value for rule match
431  * @param mul Value which is multiplied by matching event's 1st parameter value (1.0 to not modify)
432  * @param add Value which is added to matching event's 1st parameter value (0 to not modify)
433  * @since 1.1.0
434  *
435  * The 1st parameter of an event depends on the type of event.  For note events
436  * its the MIDI note #, for CC events its the MIDI control number, for program
437  * change events its the MIDI program #, for pitch bend events its the bend value,
438  * for channel pressure its the channel pressure value and for key pressure
439  * its the MIDI note number.
440  *
441  * Pitch bend values have a maximum value of 16383 (8192 is pitch bend center) and all
442  * other events have a max of 127.  All events have a minimum value of 0.
443  *
444  * The \a min and \a max parameters define a parameter range window to match
445  * incoming events to.  If \a min is less than or equal to \a max then an event
446  * is matched if its 1st parameter is within the defined range (including \a min
447  * and \a max). If \a min is greater than \a max then rule is inverted and matches
448  * everything except in *between* the defined range (so \a min and \a max would match).
449  *
450  * The \a mul and \a add values are used to modify event 1st parameter values prior to
451  * sending the event, if the rule matches.
452  */
453 void
fluid_midi_router_rule_set_param1(fluid_midi_router_rule_t * rule,int min,int max,float mul,int add)454 fluid_midi_router_rule_set_param1 (fluid_midi_router_rule_t *rule, int min, int max,
455                                    float mul, int add)
456 {
457   fluid_return_if_fail (rule != NULL);
458   rule->par1_min = min;
459   rule->par1_max = max;
460   rule->par1_mul = mul;
461   rule->par1_add = add;
462 }
463 
464 /**
465  * Set the second parameter portion of a rule.
466  * @param rule MIDI router rule
467  * @param min Minimum value for rule match
468  * @param max Maximum value for rule match
469  * @param mul Value which is multiplied by matching event's 2nd parameter value (1.0 to not modify)
470  * @param add Value which is added to matching event's 2nd parameter value (0 to not modify)
471  * @since 1.1.0
472  *
473  * The 2nd parameter of an event depends on the type of event.  For note events
474  * its the MIDI velocity, for CC events its the control value and for key pressure
475  * events its the key pressure value.  All other types lack a 2nd parameter.
476  *
477  * All applicable 2nd parameters have the range 0-127.
478  *
479  * The \a min and \a max parameters define a parameter range window to match
480  * incoming events to.  If \a min is less than or equal to \a max then an event
481  * is matched if its 2nd parameter is within the defined range (including \a min
482  * and \a max). If \a min is greater than \a max then rule is inverted and matches
483  * everything except in *between* the defined range (so \a min and \a max would match).
484  *
485  * The \a mul and \a add values are used to modify event 2nd parameter values prior to
486  * sending the event, if the rule matches.
487  */
488 void
fluid_midi_router_rule_set_param2(fluid_midi_router_rule_t * rule,int min,int max,float mul,int add)489 fluid_midi_router_rule_set_param2 (fluid_midi_router_rule_t *rule, int min, int max,
490                                    float mul, int add)
491 {
492   fluid_return_if_fail (rule != NULL);
493   rule->par2_min = min;
494   rule->par2_max = max;
495   rule->par2_mul = mul;
496   rule->par2_add = add;
497 }
498 
499 /**
500  * Handle a MIDI event through a MIDI router instance.
501  * @param data MIDI router instance #fluid_midi_router_t, its a void * so that
502  *   this function can be used as a callback for other subsystems
503  *   (new_fluid_midi_driver() for example).
504  * @param event MIDI event to handle
505  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
506  *
507  * Purpose: The midi router is called for each event, that is received
508  * via the 'physical' midi input. Each event can trigger an arbitrary number
509  * of generated events (one for each rule that matches).
510  *
511  * In default mode, a noteon event is just forwarded to the synth's 'noteon' function,
512  * a 'CC' event to the synth's 'CC' function and so on.
513  *
514  * The router can be used to:
515  * - filter messages (for example: Pass sustain pedal CCs only to selected channels)
516  * - split the keyboard (noteon with notenr < x: to ch 1, >x to ch 2)
517  * - layer sounds (for each noteon received on ch 1, create a noteon on ch1, ch2, ch3,...)
518  * - velocity scaling (for each noteon event, scale the velocity by 1.27 to give DX7 users
519  *   a chance)
520  * - velocity switching ("v <=100: Angel Choir; V > 100: Hell's Bells")
521  * - get rid of aftertouch
522  * - ...
523  */
524 int
fluid_midi_router_handle_midi_event(void * data,fluid_midi_event_t * event)525 fluid_midi_router_handle_midi_event (void* data, fluid_midi_event_t* event)
526 {
527   fluid_midi_router_t* router = (fluid_midi_router_t *)data;
528   fluid_midi_router_rule_t **rulep, *rule, *next_rule, *prev_rule = NULL;
529   int event_has_par2 = 0; /* Flag, indicates that current event needs two parameters */
530   int par1_max = 127;     /* Range limit for par1 */
531   int par2_max = 127;     /* Range limit for par2 */
532   int ret_val = FLUID_OK;
533 
534   int chan; /* Channel of the generated event */
535   int par1; /* par1 of the generated event */
536   int par2;
537   int event_par1;
538   int event_par2;
539   fluid_midi_event_t new_event;
540 
541   /* Some keyboards report noteoff through a noteon event with vel=0.
542    * Convert those to noteoff to ease processing. */
543   if (event->type == NOTE_ON && event->param2 == 0)
544   {
545     event->type = NOTE_OFF;
546     event->param2 = 127;        /* Release velocity */
547   }
548 
549   fluid_mutex_lock (router->rules_mutex);   /* ++ lock rules */
550 
551   /* Depending on the event type, choose the correct list of rules. */
552   switch (event->type)
553   {
554       case NOTE_ON:
555 	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE];
556 	event_has_par2 = 1;
557 	break;
558       case NOTE_OFF:
559 	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE];
560 	event_has_par2 = 1;
561 	break;
562       case CONTROL_CHANGE:
563 	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CC];
564 	event_has_par2 = 1;
565 	break;
566       case PROGRAM_CHANGE:
567 	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PROG_CHANGE];
568 	break;
569       case PITCH_BEND:
570 	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PITCH_BEND];
571 	par1_max = 16383;
572 	break;
573       case CHANNEL_PRESSURE:
574 	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE];
575 	break;
576       case KEY_PRESSURE:
577 	rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE];
578 	event_has_par2 = 1;
579 	break;
580       case MIDI_SYSTEM_RESET:
581       case MIDI_SYSEX:
582         ret_val = router->event_handler (router->event_handler_data,event);
583         fluid_mutex_unlock (router->rules_mutex);  /* -- unlock rules */
584         return ret_val;
585       default:
586         rulep = NULL;    /* Event will not be passed on */
587 	break;
588   }
589 
590   /* Loop over rules in the list, looking for matches for this event. */
591   for (rule = rulep ? *rulep : NULL; rule; prev_rule = rule, rule = next_rule)
592   {
593     event_par1 = (int)event->param1;
594     event_par2 = (int)event->param2;
595     next_rule = rule->next;     /* Rule may get removed from list, so get next here */
596 
597     /* Channel window */
598     if (rule->chan_min > rule->chan_max)
599     { /* Inverted rule: Exclude everything between max and min (but not min/max) */
600       if (event->channel > rule->chan_max && event->channel < rule->chan_min)
601 	continue;
602     }
603     else        /* Normal rule: Exclude everything < max or > min (but not min/max) */
604     {
605       if (event->channel > rule->chan_max || event->channel < rule->chan_min)
606 	continue;
607     }
608 
609     /* Par 1 window */
610     if (rule->par1_min > rule->par1_max)
611     { /* Inverted rule: Exclude everything between max and min (but not min/max) */
612       if (event_par1 > rule->par1_max && event_par1 < rule->par1_min)
613 	continue;
614     }
615     else        /* Normal rule: Exclude everything < max or > min (but not min/max)*/
616     {
617       if (event_par1 > rule->par1_max || event_par1 < rule->par1_min)
618 	continue;
619     }
620 
621     /* Par 2 window (only applies to event types, which have 2 pars)
622      * For noteoff events, velocity switching doesn't make any sense.
623      * Velocity scaling might be useful, though.
624      */
625     if (event_has_par2 && event->type != NOTE_OFF)
626     {
627       if (rule->par2_min > rule->par2_max)
628       { /* Inverted rule: Exclude everything between max and min (but not min/max) */
629 	if (event_par2 > rule->par2_max && event_par2 < rule->par2_min)
630 	  continue;
631       }
632       else      /* Normal rule: Exclude everything < max or > min (but not min/max)*/
633       {
634 	if (event_par2 > rule->par2_max || event_par2 < rule->par2_min)
635 	  continue;
636       }
637     }
638 
639     /* Channel scaling / offset
640      * Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all
641      * input channels is mapped to the same synth channel.
642      */
643     chan = (int)((fluid_real_t)event->channel * (fluid_real_t)rule->chan_mul
644                  + (fluid_real_t)rule->chan_add + 0.5);
645 
646     /* Par 1 scaling / offset */
647     par1 = (int)((fluid_real_t)event_par1 * (fluid_real_t)rule->par1_mul
648                  + (fluid_real_t)rule->par1_add + 0.5);
649 
650     /* Par 2 scaling / offset, if applicable */
651     if (event_has_par2)
652       par2 = (int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul
653                    + (fluid_real_t)rule->par2_add + 0.5);
654     else par2 = 0;
655 
656     /* Channel range limiting */
657     if (chan < 0)
658       chan = 0;
659     else if (chan >= router->nr_midi_channels)
660       chan = router->nr_midi_channels - 1;
661 
662     /* Par1 range limiting */
663     if (par1 < 0)
664       par1 = 0;
665     else if (par1 > par1_max)
666       par1 = par1_max;
667 
668     /* Par2 range limiting */
669     if (event_has_par2)
670     {
671       if (par2 < 0)
672         par2 = 0;
673       else if (par2 > par2_max)
674         par2 = par2_max;
675     }
676 
677     /* At this point we have to create an event of event->type on 'chan' with par1 (maybe par2).
678      * We keep track on the state of noteon and sustain pedal events. If the application tries
679      * to delete a rule, it will only be fully removed, if pending noteoff / pedal off events have
680      * arrived. In the meantime while waiting, it will only let through 'negative' events
681      * (noteoff or pedal up).
682      */
683     if (event->type == NOTE_ON || (event->type == CONTROL_CHANGE
684                                    && par1 == SUSTAIN_SWITCH && par2 >= 64))
685     {
686       /* Noteon or sustain pedal down event generated */
687       if (rule->keys_cc[par1] == 0)
688       {
689 	rule->keys_cc[par1] = 1;
690 	rule->pending_events++;
691       }
692     }
693     else if (event->type == NOTE_OFF || (event->type == CONTROL_CHANGE
694                                          && par1 == SUSTAIN_SWITCH && par2 < 64))
695     { /* Noteoff or sustain pedal up event generated */
696       if (rule->keys_cc[par1] > 0)
697       {
698 	rule->keys_cc[par1] = 0;
699 	rule->pending_events--;
700 
701         /* Rule is waiting for negative event to be destroyed? */
702         if (rule->waiting)
703         {
704 	  if (rule->pending_events == 0)
705           { /* Remove rule from rule list */
706             if (prev_rule) prev_rule->next = next_rule;
707             else *rulep = next_rule;
708 
709             /* Add to free list */
710             rule->next = router->free_rules;
711             router->free_rules = rule;
712 
713             rule = prev_rule;   /* Set rule to previous rule, which gets assigned to the next prev_rule value (in for() statement) */
714           }
715 
716           goto send_event;      /* Pass the event to complete the cycle */
717         }
718       }
719     }
720 
721     /* Rule is still waiting for negative event? (note off or pedal up) */
722     if (rule->waiting)
723       continue;         /* Skip (rule is inactive except for matching negative event) */
724 
725 send_event:
726 
727     /* At this point it is decided, what is sent to the synth.
728      * Create a new event and make the appropriate call */
729 
730     fluid_midi_event_set_type (&new_event, event->type);
731     fluid_midi_event_set_channel (&new_event, chan);
732     new_event.param1 = par1;
733     new_event.param2 = par2;
734 
735     /* FIXME - What should be done on failure?  For now continue to process events, but return failure to caller. */
736     if (router->event_handler (router->event_handler_data, &new_event) != FLUID_OK)
737       ret_val = FLUID_FAILED;
738   }
739 
740   fluid_mutex_unlock (router->rules_mutex);         /* -- unlock rules */
741 
742   return ret_val;
743 }
744 
745 #define CHECK_VALID_ROUTER(_router, _out)                                                \
746   if (router == NULL) {                                                                  \
747     fluid_ostream_printf(out, "cannot execute router command without a midi router.\n"); \
748     return FLUID_FAILED;                                                                 \
749   }
750 
751 /* Command handler for "router_clear" command */
752 int
fluid_midi_router_handle_clear(fluid_synth_t * synth,int ac,char ** av,fluid_ostream_t out)753 fluid_midi_router_handle_clear (fluid_synth_t* synth, int ac, char** av,
754                                 fluid_ostream_t out)
755 {
756   fluid_midi_router_t *router = synth->midi_router;
757 
758   if (ac != 0) {
759     fluid_ostream_printf (out, "router_clear needs no arguments.\n");
760     return FLUID_FAILED;
761   }
762 
763   CHECK_VALID_ROUTER (router, out);
764 
765   fluid_midi_router_clear_rules (router);
766 
767   return FLUID_OK;
768 }
769 
770 /* Command handler for "router_default" command */
771 int
fluid_midi_router_handle_default(fluid_synth_t * synth,int ac,char ** av,fluid_ostream_t out)772 fluid_midi_router_handle_default(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
773 {
774   fluid_midi_router_t *router = synth->midi_router;
775 
776   if (ac != 0) {
777     fluid_ostream_printf(out, "router_default needs no arguments.\n");
778     return FLUID_FAILED;
779   }
780 
781   CHECK_VALID_ROUTER (router, out);
782 
783   fluid_midi_router_set_default_rules (router);
784 
785   return FLUID_OK;
786 }
787 
788 /* Command handler for "router_begin" command */
789 int
fluid_midi_router_handle_begin(fluid_synth_t * synth,int ac,char ** av,fluid_ostream_t out)790 fluid_midi_router_handle_begin (fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
791 {
792   fluid_midi_router_t* router = synth->midi_router;
793 
794   if (ac != 1) {
795     fluid_ostream_printf (out, "router_begin requires [note|cc|prog|pbend|cpress|kpress]\n");
796     return FLUID_FAILED;
797   }
798 
799   CHECK_VALID_ROUTER (router, out);
800 
801   if (FLUID_STRCMP (av[0], "note") == 0)
802     router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_NOTE;
803   else if (FLUID_STRCMP (av[0], "cc") == 0)
804     router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_CC;
805   else if (FLUID_STRCMP (av[0], "prog") == 0)
806     router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_PROG_CHANGE;
807   else if (FLUID_STRCMP (av[0], "pbend") == 0)
808     router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_PITCH_BEND;
809   else if (FLUID_STRCMP (av[0], "cpress") == 0)
810     router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE;
811   else if (FLUID_STRCMP (av[0], "kpress") == 0)
812     router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE;
813   else
814   {
815     fluid_ostream_printf (out, "router_begin requires [note|cc|prog|pbend|cpress|kpress]\n");
816     return FLUID_FAILED;
817   }
818 
819   if (router->cmd_rule)
820     delete_fluid_midi_router_rule (router->cmd_rule);
821 
822   router->cmd_rule = new_fluid_midi_router_rule ();
823 
824   if (!router->cmd_rule)
825     return FLUID_FAILED;
826 
827   return FLUID_OK;
828 }
829 
830 /* Command handler for "router_end" command */
831 int
fluid_midi_router_handle_end(fluid_synth_t * synth,int ac,char ** av,fluid_ostream_t out)832 fluid_midi_router_handle_end (fluid_synth_t* synth, int ac, char** av,
833                               fluid_ostream_t out)
834 {
835   fluid_midi_router_t* router = synth->midi_router;
836 
837   if (ac != 0) {
838     fluid_ostream_printf (out, "router_end needs no arguments.\n");
839     return FLUID_FAILED;
840   }
841 
842   CHECK_VALID_ROUTER (router, out);
843 
844   if (!router->cmd_rule)
845   {
846     fluid_ostream_printf (out, "No active router_begin command.\n");
847     return FLUID_FAILED;
848   }
849 
850   /* Add the rule */
851   if (fluid_midi_router_add_rule (router, router->cmd_rule, router->cmd_rule_type) != FLUID_OK)
852     delete_fluid_midi_router_rule (router->cmd_rule);   /* Free on failure */
853 
854   router->cmd_rule = NULL;
855 
856   return FLUID_OK;
857 }
858 
859 /* Command handler for "router_chan" command */
860 int
fluid_midi_router_handle_chan(fluid_synth_t * synth,int ac,char ** av,fluid_ostream_t out)861 fluid_midi_router_handle_chan (fluid_synth_t* synth, int ac, char** av,
862                                fluid_ostream_t out)
863 {
864   fluid_midi_router_t* router = synth->midi_router;
865 
866   if (ac != 4) {
867     fluid_ostream_printf(out, "router_chan needs four args: min, max, mul, add.");
868     return FLUID_FAILED;
869   }
870 
871   CHECK_VALID_ROUTER (router, out);
872 
873   if (!router->cmd_rule)
874   {
875     fluid_ostream_printf (out, "No active router_begin command.\n");
876     return FLUID_FAILED;
877   }
878 
879   fluid_midi_router_rule_set_chan (router->cmd_rule, atoi (av[0]), atoi (av[1]),
880                                    atof (av[2]), atoi (av[3]));
881   return FLUID_OK;
882 }
883 
884 /* Command handler for "router_par1" command */
885 int
fluid_midi_router_handle_par1(fluid_synth_t * synth,int ac,char ** av,fluid_ostream_t out)886 fluid_midi_router_handle_par1 (fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
887 {
888   fluid_midi_router_t* router = synth->midi_router;
889 
890   if (ac != 4) {
891     fluid_ostream_printf(out, "router_par1 needs four args: min, max, mul, add.");
892     return FLUID_FAILED;
893   }
894 
895   CHECK_VALID_ROUTER (router, out);
896 
897   if (!router->cmd_rule)
898   {
899     fluid_ostream_printf (out, "No active router_begin command.\n");
900     return FLUID_FAILED;
901   }
902 
903   fluid_midi_router_rule_set_param1 (router->cmd_rule, atoi (av[0]), atoi (av[1]),
904                                      atof (av[2]), atoi (av[3]));
905   return FLUID_OK;
906 }
907 
908 /* Command handler for "router_par2" command */
909 int
fluid_midi_router_handle_par2(fluid_synth_t * synth,int ac,char ** av,fluid_ostream_t out)910 fluid_midi_router_handle_par2 (fluid_synth_t* synth, int ac, char** av,
911                                fluid_ostream_t out)
912 {
913   fluid_midi_router_t* router = synth->midi_router;
914 
915   if (ac != 4) {
916     fluid_ostream_printf(out, "router_par2 needs four args: min, max, mul, add.");
917     return FLUID_FAILED;
918   }
919 
920   CHECK_VALID_ROUTER (router, out);
921 
922   if (!router->cmd_rule)
923   {
924     fluid_ostream_printf (out, "No active router_begin command.\n");
925     return FLUID_FAILED;
926   }
927 
928   fluid_midi_router_rule_set_param2 (router->cmd_rule, atoi (av[0]), atoi (av[1]),
929                                      atof (av[2]), atoi (av[3]));
930   return FLUID_OK;
931 }
932 
933 /**
934  * MIDI event callback function to display event information to stdout
935  * @param data MIDI router instance
936  * @param event MIDI event data
937  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
938  *
939  * An implementation of the #handle_midi_event_func_t function type, used for
940  * displaying MIDI event information between the MIDI driver and router to
941  * stdout.  Useful for adding into a MIDI router chain for debugging MIDI events.
942  */
fluid_midi_dump_prerouter(void * data,fluid_midi_event_t * event)943 int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
944 {
945   switch (event->type) {
946       case NOTE_ON:
947 	fprintf(stdout, "event_pre_noteon %i %i %i\n",
948 		event->channel, event->param1, event->param2);
949 	break;
950       case NOTE_OFF:
951 	fprintf(stdout, "event_pre_noteoff %i %i %i\n",
952 		event->channel, event->param1, event->param2);
953 	break;
954       case CONTROL_CHANGE:
955 	fprintf(stdout, "event_pre_cc %i %i %i\n",
956 		event->channel, event->param1, event->param2);
957 	break;
958       case PROGRAM_CHANGE:
959 	fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1);
960 	break;
961       case PITCH_BEND:
962         fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1);
963 	break;
964       case CHANNEL_PRESSURE:
965 	fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1);
966 	break;
967       case KEY_PRESSURE:
968 	fprintf(stdout, "event_pre_kpress %i %i %i\n",
969 		event->channel, event->param1, event->param2);
970 	break;
971       default:
972 	break;
973   }
974   return fluid_midi_router_handle_midi_event((fluid_midi_router_t*) data, event);
975 }
976 
977 /**
978  * MIDI event callback function to display event information to stdout
979  * @param data MIDI router instance
980  * @param event MIDI event data
981  * @return #FLUID_OK on success, #FLUID_FAILED otherwise
982  *
983  * An implementation of the #handle_midi_event_func_t function type, used for
984  * displaying MIDI event information between the MIDI driver and router to
985  * stdout.  Useful for adding into a MIDI router chain for debugging MIDI events.
986  */
fluid_midi_dump_postrouter(void * data,fluid_midi_event_t * event)987 int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event)
988 {
989   switch (event->type) {
990       case NOTE_ON:
991 	fprintf(stdout, "event_post_noteon %i %i %i\n",
992 		event->channel, event->param1, event->param2);
993 	break;
994       case NOTE_OFF:
995 	fprintf(stdout, "event_post_noteoff %i %i %i\n",
996 		event->channel, event->param1, event->param2);
997 	break;
998       case CONTROL_CHANGE:
999 	fprintf(stdout, "event_post_cc %i %i %i\n",
1000 		event->channel, event->param1, event->param2);
1001 	break;
1002       case PROGRAM_CHANGE:
1003 	fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1);
1004 	break;
1005       case PITCH_BEND:
1006 	fprintf(stdout, "event_post_pitch %i %i\n", event->channel, event->param1);
1007 	break;
1008       case CHANNEL_PRESSURE:
1009 	fprintf(stdout, "event_post_cpress %i %i\n", event->channel, event->param1);
1010 	break;
1011       case KEY_PRESSURE:
1012 	fprintf(stdout, "event_post_kpress %i %i %i\n",
1013 		event->channel, event->param1, event->param2);
1014 	break;
1015       default:
1016 	break;
1017   }
1018   return fluid_synth_handle_midi_event((fluid_synth_t*) data, event);
1019 }
1020