/* Command handler for "router_begin" command */
int
fluid_midi_router_handle_begin (fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
{
  fluid_midi_router_t* router = synth->midi_router;

  if (ac != 1) {
    fluid_ostream_printf (out, "router_begin requires [note|cc|prog|pbend|cpress|kpress]\n");
    return FLUID_FAILED;
  }

  CHECK_VALID_ROUTER (router, out);

  if (FLUID_STRCMP (av[0], "note") == 0)
    router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_NOTE;
  else if (FLUID_STRCMP (av[0], "cc") == 0)
    router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_CC;
  else if (FLUID_STRCMP (av[0], "prog") == 0)
    router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_PROG_CHANGE;
  else if (FLUID_STRCMP (av[0], "pbend") == 0)
    router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_PITCH_BEND;
  else if (FLUID_STRCMP (av[0], "cpress") == 0)
    router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE;
  else if (FLUID_STRCMP (av[0], "kpress") == 0)
    router->cmd_rule_type = FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE;
  else
  {
    fluid_ostream_printf (out, "router_begin requires [note|cc|prog|pbend|cpress|kpress]\n");
    return FLUID_FAILED;
  }

  if (router->cmd_rule)
    delete_fluid_midi_router_rule (router->cmd_rule);

  router->cmd_rule = new_fluid_midi_router_rule ();

  if (!router->cmd_rule)
    return FLUID_FAILED;

  return FLUID_OK;
}
/**
 * Create a new midi router.  The default rules will pass all events unmodified.
 * @param settings Settings used to configure MIDI router
 * @param handler MIDI event callback.
 * @param event_handler_data Caller defined data pointer which gets passed to 'handler'
 * @return New MIDI router instance or NULL on error
 *
 * The MIDI handler callback should process the possibly filtered/modified MIDI
 * events from the MIDI router and forward them on to a synthesizer for example.
 * The function fluid_synth_handle_midi_event() can be used for \a handle and
 * a #fluid_synth_t passed as the \a event_handler_data parameter for this purpose.
 */
fluid_midi_router_t *
new_fluid_midi_router(fluid_settings_t *settings, handle_midi_event_func_t handler,
                      void *event_handler_data)
{
  fluid_midi_router_t *router = NULL;
  int i;

  router = FLUID_NEW (fluid_midi_router_t);

  if (router == NULL)
  {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    return NULL;
  }

  FLUID_MEMSET (router, 0, sizeof (fluid_midi_router_t));

  /* Retrieve the number of MIDI channels for range limiting */
  fluid_settings_getint(settings, "synth.midi-channels", &router->nr_midi_channels);

  fluid_mutex_init (router->rules_mutex);

  router->synth = (fluid_synth_t *)event_handler_data;
  router->event_handler = handler;
  router->event_handler_data = event_handler_data;

  /* Create default routing rules which pass all events unmodified */
  for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
  {
    router->rules[i] = new_fluid_midi_router_rule ();
    if (!router->rules[i]) goto error_recovery;
  }

  return router;

 error_recovery:
  delete_fluid_midi_router (router);
  return NULL;
}
Exemple #3
0
/**
 * Set a MIDI router to use default "unity" rules. Such a router will pass all
 * events unmodified.
 * @param router Router to set to default rules.
 * @return #FLUID_OK on success, #FLUID_FAILED otherwise
 * @since 1.1.0
 */
int
fluid_midi_router_set_default_rules (fluid_midi_router_t *router)
{
  fluid_midi_router_rule_t *new_rules[FLUID_MIDI_ROUTER_RULE_COUNT];
  fluid_midi_router_rule_t *del_rules[FLUID_MIDI_ROUTER_RULE_COUNT];
  fluid_midi_router_rule_t *rule, *next_rule, *prev_rule;
  int i, i2;

  fluid_return_val_if_fail (router != NULL, FLUID_FAILED);

  /* Allocate new default rules outside of lock */

  for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
  {
    new_rules[i] = new_fluid_midi_router_rule ();

    if (!new_rules[i])
    { /* Free already allocated rules */
      for (i2 = 0; i2 < i; i2++)
        delete_fluid_midi_router_rule (new_rules[i2]);

      return FLUID_FAILED;
    }
  }


  fluid_mutex_lock (router->rules_mutex);       /* ++ lock */

  for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
  {
    del_rules[i] = NULL;
    prev_rule = NULL;

    /* Process existing rules */
    for (rule = router->rules[i]; rule; rule = next_rule)
    {
      next_rule = rule->next;

      if (rule->pending_events == 0)    /* Rule has no pending events? */
      { /* Remove rule from rule list */
        if (prev_rule) prev_rule->next = next_rule;
        else if (rule == router->rules[i]) router->rules[i] = next_rule;

        /* Prepend to delete list */
        rule->next = del_rules[i];
        del_rules[i] = rule;
      }
      else
      {
        rule->waiting = TRUE;          /* Pending events, mark as waiting */
        prev_rule = rule;
      }
    }

    /* Prepend new default rule */
    new_rules[i]->next = router->rules[i];
    router->rules[i] = new_rules[i];
  }

  fluid_mutex_unlock (router->rules_mutex);     /* -- unlock */


  /* Free old rules outside of lock */

  for (i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
  {
    for (rule = del_rules[i]; rule; rule = next_rule)
    {
      next_rule = rule->next;
      FLUID_FREE (rule);
    }
  }

  return FLUID_OK;
}