fluid_midi_router.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:32k
源码类别:

midi

开发平台:

C/C++

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