/* 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; }
/** * 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; }