00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "fluid_midi_router.h"
00025 #include "fluid_midi.h"
00026 #include "fluid_synth.h"
00027 #include "fluid_io.h"
00028
00039 fluid_midi_router_t*
00040 new_fluid_midi_router(fluid_settings_t* settings, handle_midi_event_func_t handler, void* event_handler_data)
00041 {
00042 fluid_midi_router_t* router=NULL;
00043 fluid_midi_router_rule_t* rule=NULL;
00044
00045
00046 router = FLUID_NEW(fluid_midi_router_t); if (router == NULL){
00047 FLUID_LOG(FLUID_ERR, "Out of memory");
00048 return NULL;
00049 };
00050
00051
00052
00053
00054 FLUID_MEMSET(router, 0, sizeof(fluid_midi_router_t));
00055
00056 fluid_settings_getint(settings, "synth.midi-channels", &router->nr_midi_channels);
00057
00058 fluid_mutex_init(router->ruletables_mutex);
00059
00060 router->synth = (fluid_synth_t*) event_handler_data;
00061 router->event_handler=handler;
00062 router->event_handler_data=event_handler_data;
00063
00064
00065
00066
00067
00068 if (fluid_midi_router_create_default_rules(router) != FLUID_OK) goto error_recovery;
00069
00070 return router;
00071
00072 error_recovery:
00073 FLUID_LOG(FLUID_ERR, "new_fluid_midi_router failed");
00074 fluid_midi_router_destroy_all_rules(router);
00075 FLUID_FREE(router);
00076 return NULL;
00077 }
00078
00084 int
00085 delete_fluid_midi_router(fluid_midi_router_t* router)
00086 {
00087 if (router == NULL) {
00088 return FLUID_OK;
00089 }
00090 fluid_midi_router_destroy_all_rules(router);
00091 FLUID_FREE(router);
00092 return FLUID_OK;
00093 }
00094
00095
00096
00097
00098
00099
00100 void fluid_midi_router_destroy_all_rules(fluid_midi_router_t* router){
00101 fluid_midi_router_rule_t* rules[6];
00102 fluid_midi_router_rule_t* current_rule;
00103 fluid_midi_router_rule_t* next_rule;
00104 int i;
00105
00106 rules[0]=router->note_rules;
00107 rules[1]=router->cc_rules;
00108 rules[2]=router->progchange_rules;
00109 rules[3]=router->pitchbend_rules;
00110 rules[4]=router->channel_pressure_rules;
00111 rules[5]=router->key_pressure_rules;
00112 for (i=0; i < 6; i++){
00113 current_rule=rules[i];
00114 while (current_rule){
00115 next_rule=current_rule->next;
00116 FLUID_FREE(current_rule);
00117 current_rule=next_rule;
00118 };
00119 };
00120 }
00121
00122
00123
00124
00125 fluid_midi_router_rule_t* new_fluid_midi_router_rule(void)
00126 {
00127 fluid_midi_router_rule_t* rule=FLUID_NEW(fluid_midi_router_rule_t);
00128 if (rule == NULL) {
00129 FLUID_LOG(FLUID_ERR, "Out of memory");
00130 return NULL;
00131 }
00132
00133 FLUID_MEMSET(rule, 0, sizeof(fluid_midi_router_rule_t));
00134 return rule;
00135 };
00136
00137
00138
00139
00140 int
00141 delete_fluid_midi_router_rule(fluid_midi_router_rule_t* rule)
00142 {
00143 FLUID_FREE(rule);
00144 return FLUID_OK;
00145 }
00146
00147
00148 int fluid_midi_router_create_default_rules(fluid_midi_router_t* router)
00149 {
00150 fluid_midi_router_rule_t** rules[6];
00151 int i;
00152
00153 rules[0]=&router->note_rules;
00154 rules[1]=&router->cc_rules;
00155 rules[2]=&router->progchange_rules;
00156 rules[3]=&router->pitchbend_rules;
00157 rules[4]=&router->channel_pressure_rules;
00158 rules[5]=&router->key_pressure_rules;
00159
00160 for (i=0; i < 6; i++){
00161
00162
00163
00164 if (fluid_midi_router_begin(router, rules[i]) != FLUID_OK) goto error_recovery;
00165 if (fluid_midi_router_end(router) != FLUID_OK) goto error_recovery;
00166 };
00167
00168 return FLUID_OK;
00169 error_recovery:
00170 FLUID_LOG(FLUID_ERR, "fluid_midi_router_create_default_rules failed");
00171 return FLUID_FAILED;
00172 };
00173
00174
00175
00176
00177
00178 int fluid_midi_router_begin(fluid_midi_router_t* router, fluid_midi_router_rule_t** dest)
00179 {
00180 if (!dest) goto error_recovery;
00181 router->dest=dest;
00182
00183
00184
00185
00186 router->new_rule_chan_min=0;
00187 router->new_rule_chan_max=999999;
00188 router->new_rule_chan_mul=1.;
00189 router->new_rule_chan_add=0;
00190 router->new_rule_par1_min=0;
00191 router->new_rule_par1_max=999999;
00192 router->new_rule_par1_mul=1.;
00193 router->new_rule_par1_add=0;
00194 router->new_rule_par2_min=0;
00195 router->new_rule_par2_max=999999;
00196 router->new_rule_par2_mul=1.;
00197 router->new_rule_par2_add=0;
00198
00199 return FLUID_OK;
00200 error_recovery:
00201 FLUID_LOG(FLUID_ERR, "fluid_midi_router_begin failed");
00202 return FLUID_FAILED;
00203 };
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 int fluid_midi_router_end(fluid_midi_router_t* router){
00217 fluid_midi_router_rule_t* rule=new_fluid_midi_router_rule(); if (rule == NULL) goto error_recovery;
00218
00219 rule->chan_min=router->new_rule_chan_min;
00220 rule->chan_max=router->new_rule_chan_max;
00221 rule->chan_mul=router->new_rule_chan_mul;
00222 rule->chan_add=router->new_rule_chan_add;
00223 rule->par1_min=router->new_rule_par1_min;
00224 rule->par1_max=router->new_rule_par1_max;
00225 rule->par1_mul=router->new_rule_par1_mul;
00226 rule->par1_add=router->new_rule_par1_add;
00227 rule->par2_min=router->new_rule_par2_min;
00228 rule->par2_max=router->new_rule_par2_max;
00229 rule->par2_mul=router->new_rule_par2_mul;
00230 rule->par2_add=router->new_rule_par2_add;
00231
00232
00233
00234
00235
00236
00237 fluid_mutex_lock(router->ruletables_mutex);
00238
00239 rule->next= *(router->dest);
00240 *router->dest=rule;
00241
00242 fluid_mutex_unlock(router->ruletables_mutex);
00243
00244 return FLUID_OK;
00245
00246 error_recovery:
00247 FLUID_LOG(FLUID_ERR, "fluid_midi_router_end failed");
00248 delete_fluid_midi_router_rule(rule);
00249 return FLUID_FAILED;
00250 };
00251
00275 int
00276 fluid_midi_router_handle_midi_event(void* data, fluid_midi_event_t* event)
00277 {
00278 fluid_midi_router_t* router=(fluid_midi_router_t*)data;
00279 fluid_synth_t* synth = router->synth;
00280 fluid_midi_router_rule_t* rule=NULL;
00281 fluid_midi_router_rule_t* next_rule=NULL;
00282 int event_has_par2=0;
00283 int negative_event=0;
00284 int par1_max=127;
00285 int par2_max=127;
00286 int ret_val=FLUID_OK;
00287
00288
00289
00290 if (event->type == NOTE_ON && event->param2 == 0) {
00291
00292
00293
00294
00295 event->type = NOTE_OFF;
00296 event->param2=127;
00297 };
00298
00299
00300
00301 fluid_mutex_lock(router->ruletables_mutex);
00302
00303
00304
00305
00306
00307
00308
00309 switch (event->type) {
00310 case NOTE_ON:
00311 rule=router->note_rules;
00312 event_has_par2=1;
00313 break;
00314 case NOTE_OFF:
00315 rule=router->note_rules;
00316 event_has_par2=1;
00317 break;
00318 case CONTROL_CHANGE:
00319 rule=router->cc_rules;
00320 event_has_par2=1;
00321 break;
00322 case PROGRAM_CHANGE:
00323 rule=router->progchange_rules;
00324 break;
00325 case PITCH_BEND:
00326 rule=router->pitchbend_rules;
00327 par1_max=16383;
00328 break;
00329 case CHANNEL_PRESSURE:
00330 rule=router->channel_pressure_rules;
00331 break;
00332 case KEY_PRESSURE:
00333 rule=router->key_pressure_rules;
00334 event_has_par2=1;
00335 break;
00336 case MIDI_SYSTEM_RESET:
00337 return router->event_handler(router->event_handler_data,event);
00338 default:
00339 break;
00340 }
00341
00342
00343
00344
00345
00346 while (rule){
00347 int chan;
00348 int par1;
00349 int par2=0;
00350 int event_par1=(int)event->param1;
00351 int event_par2=(int)event->param2;
00352 fluid_midi_event_t new_event;
00353
00354
00355
00356
00357 next_rule=rule->next;
00358
00359
00360
00361
00362 if (rule->state == MIDIRULE_DONE){
00363 goto do_next_rule;
00364 };
00365
00366
00367 if (rule->chan_min > rule->chan_max){
00368
00369 if (event->channel > rule->chan_max && event->channel < rule->chan_min){
00370 goto do_next_rule;
00371 }
00372 } else {
00373
00374 if (event->channel > rule->chan_max || event->channel < rule->chan_min){
00375 goto do_next_rule;
00376 }
00377 };
00378
00379
00380 if (rule->par1_min > rule->par1_max){
00381
00382 if (event_par1 > rule->par1_max && event_par1 < rule->par1_min){
00383 goto do_next_rule;
00384 }
00385 } else {
00386
00387 if (event_par1 > rule->par1_max || event_par1 < rule->par1_min){
00388 goto do_next_rule;
00389 }
00390 };
00391
00392
00393
00394
00395
00396 if (event_has_par2 && event->type != NOTE_OFF){
00397 if (rule->par2_min > rule->par2_max){
00398
00399 if (event_par2 > rule->par2_max && event_par2 < rule->par2_min){
00400 goto do_next_rule;
00401 }
00402 } else {
00403
00404 if (event_par2 > rule->par2_max || event_par2 < rule->par2_min){
00405 goto do_next_rule;
00406 };
00407 };
00408 };
00409
00410
00411
00412
00413
00414 chan=(int)((fluid_real_t)event->channel * (fluid_real_t)rule->chan_mul + (fluid_real_t)rule->chan_add + 0.5);
00415
00416
00417 par1=(int)((fluid_real_t)event_par1 * (fluid_real_t)rule->par1_mul + (fluid_real_t)rule->par1_add + 0.5);
00418
00419
00420 if (event_has_par2){
00421 par2=(int)((fluid_real_t)event_par2 * (fluid_real_t)rule->par2_mul + (fluid_real_t)rule->par2_add + 0.5);
00422 };
00423
00424
00425 if (chan < 0){
00426 chan=0;
00427
00428 };
00429
00430
00431 if (par1 < 0){
00432 par1=0;
00433 } else if (par1 > par1_max){
00434 par1=par1_max;
00435 };
00436
00437
00438 if (event_has_par2){
00439 if (par2 < 0){
00440 par2=0;
00441 } else if (par2 > par2_max){
00442 par2=par2_max;
00443 };
00444 };
00445
00446
00447
00448
00449
00450
00451
00452
00453 if (
00454 event->type == NOTE_ON
00455 || (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 >= 64)
00456 ){
00457
00458 if (rule->keys_cc[par1] == 0){
00459 rule->keys_cc[par1]=1;
00460 rule->pending_events++;
00461 };
00462 } else if (
00463 event->type == NOTE_OFF
00464 || (event->type == CONTROL_CHANGE && par1 == SUSTAIN_SWITCH && par2 < 64)
00465 ){
00466
00467 if (rule->keys_cc[par1] > 0){
00468 rule->keys_cc[par1]=0;
00469 rule->pending_events--;
00470 negative_event=1;
00471 };
00472 };
00473
00474 if (rule->state == MIDIRULE_WAITING){
00475 if (negative_event){
00476 if (rule->pending_events == 0){
00477
00478
00479
00480
00481
00482 rule->state=MIDIRULE_DONE;
00483 };
00484 } else {
00485
00486
00487
00488
00489
00490
00491 goto do_next_rule;
00492 };
00493 };
00494
00495
00496
00497
00498
00499 fluid_midi_event_set_type(&new_event, event->type);
00500 fluid_midi_event_set_channel(&new_event, chan);
00501
00502
00503 new_event.param1 = par1;
00504 new_event.param2 = par2;
00505
00506
00507
00508
00509
00510
00511
00512 if (router->event_handler(router->event_handler_data, &new_event) != FLUID_OK) {
00513 ret_val=FLUID_FAILED;
00514 }
00515
00516 do_next_rule:
00517 rule=next_rule;
00518 };
00519
00520
00521 fluid_mutex_unlock(router->ruletables_mutex);
00522
00523 return ret_val;
00524 }
00525
00526 int fluid_midi_router_handle_clear(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
00527 {
00528 fluid_midi_router_t* router=synth->midi_router;
00529
00530 if (ac != 0) {
00531 fluid_ostream_printf(out, "router_clear needs no arguments.\n");
00532 goto error_recovery;
00533 }
00534
00535
00536 fluid_midi_router_disable_all_rules(router);
00537
00538
00539 fluid_midi_router_free_unused_rules(router);
00540
00541 return 0;
00542 error_recovery:
00543 return -1;
00544 };
00545
00546 int fluid_midi_router_handle_default(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
00547 {
00548 fluid_midi_router_t* router=synth->midi_router;
00549
00550 if (ac != 0) {
00551 fluid_ostream_printf(out, "router_default needs no arguments.\n");
00552 return -1;
00553 }
00554
00555
00556 fluid_midi_router_disable_all_rules(router);
00557
00558
00559 if (fluid_midi_router_create_default_rules(router) != FLUID_OK){
00560 FLUID_LOG(FLUID_ERR, "create_default_rules failed");
00561 goto error_recovery;
00562 };
00563
00564
00565 fluid_midi_router_free_unused_rules(router);
00566
00567 return 0;
00568 error_recovery:
00569 return -1;
00570 };
00571
00572 int fluid_midi_router_handle_begin(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
00573 {
00574 fluid_midi_router_t* router=synth->midi_router;
00575 fluid_midi_router_rule_t** dest=NULL;
00576
00577 if (ac != 1) {
00578 fluid_ostream_printf(out, "router_begin needs no arguments.\n");
00579 goto error_recovery;
00580 }
00581
00582 if (FLUID_STRCMP(av[0],"note") == 0){
00583 dest=& router->note_rules;
00584 } else if (FLUID_STRCMP(av[0],"cc") == 0){
00585 dest=& router->cc_rules;
00586 } else if (FLUID_STRCMP(av[0],"prog") == 0){
00587 dest=& router->progchange_rules;
00588 } else if (FLUID_STRCMP(av[0],"pbend") == 0){
00589 dest=& router->pitchbend_rules;
00590 } else if (FLUID_STRCMP(av[0],"cpress") == 0){
00591 dest=& router->channel_pressure_rules;
00592 } else if (FLUID_STRCMP(av[0],"kpress") == 0){
00593 dest=& router->key_pressure_rules;
00594 };
00595
00596 if (dest == NULL){
00597 fluid_ostream_printf(out, "router_begin args: note, cc, prog, pbend, cpress, kpress\n");
00598 goto error_recovery;
00599 };
00600
00601 if (fluid_midi_router_begin(router, dest) != FLUID_OK){
00602 goto error_recovery;
00603 };
00604
00605
00606 fluid_midi_router_free_unused_rules(router);
00607
00608 return 0;
00609
00610 error_recovery:
00611 return -1;
00612 };
00613
00614 int fluid_midi_router_handle_end(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
00615 {
00616 fluid_midi_router_t* router=synth->midi_router;
00617
00618 if (ac != 0) {
00619 fluid_ostream_printf(out, "router_end needs no arguments.");
00620 goto error_recovery;
00621 }
00622
00623 if (fluid_midi_router_end(router) != FLUID_OK){
00624 FLUID_LOG(FLUID_ERR, "midi_router_end failed");
00625 goto error_recovery;
00626 };
00627
00628
00629 fluid_midi_router_free_unused_rules(router);
00630
00631 return 0;
00632
00633 error_recovery:
00634 return -1;
00635 };
00636
00637 int fluid_midi_router_handle_chan(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
00638 {
00639 fluid_midi_router_t* router=synth->midi_router;
00640
00641 if (ac != 4) {
00642 fluid_ostream_printf(out, "router_chan needs four args: min, max, mul, add.");
00643 goto error_recovery;
00644 }
00645
00646 router->new_rule_chan_min=atoi(av[0]);
00647 router->new_rule_chan_max=atoi(av[1]);
00648 router->new_rule_chan_mul=atoi(av[2]);
00649 router->new_rule_chan_add=atoi(av[3]);
00650
00651
00652 fluid_midi_router_free_unused_rules(router);
00653
00654 return 0;
00655
00656 error_recovery:
00657 return -1;
00658 };
00659
00660 int fluid_midi_router_handle_par1(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
00661 {
00662 fluid_midi_router_t* router=synth->midi_router;
00663
00664 if (ac != 4) {
00665 fluid_ostream_printf(out, "router_par1 needs four args: min, max, mul, add.");
00666 goto error_recovery;
00667 }
00668
00669 router->new_rule_par1_min=atoi(av[0]);
00670 router->new_rule_par1_max=atoi(av[1]);
00671 router->new_rule_par1_mul=atoi(av[2]);
00672 router->new_rule_par1_add=atoi(av[3]);
00673
00674
00675 fluid_midi_router_free_unused_rules(router);
00676
00677 return 0;
00678
00679 error_recovery:
00680 return -1;
00681 };
00682
00683 int fluid_midi_router_handle_par2(fluid_synth_t* synth, int ac, char** av, fluid_ostream_t out)
00684 {
00685 fluid_midi_router_t* router=synth->midi_router;
00686
00687 if (ac != 4) {
00688 fluid_ostream_printf(out, "router_par2 needs four args: min, max, mul, add.");
00689 goto error_recovery;
00690 }
00691
00692 router->new_rule_par2_min=atoi(av[0]);
00693 router->new_rule_par2_max=atoi(av[1]);
00694 router->new_rule_par2_mul=atoi(av[2]);
00695 router->new_rule_par2_add=atoi(av[3]);
00696
00697
00698 fluid_midi_router_free_unused_rules(router);
00699 return 0;
00700
00701 error_recovery:
00702 return -1;
00703 };
00704
00705 void fluid_midi_router_disable_all_rules(fluid_midi_router_t* router)
00706 {
00707
00708
00709
00710
00711
00712
00713 fluid_midi_router_rule_t* rules[6];
00714 fluid_midi_router_rule_t* current_rule;
00715 int i;
00716 rules[0]=router->note_rules;
00717 rules[1]=router->cc_rules;
00718 rules[2]=router->progchange_rules;
00719 rules[3]=router->pitchbend_rules;
00720 rules[4]=router->channel_pressure_rules;
00721 rules[5]=router->key_pressure_rules;
00722
00723
00724
00725
00726
00727 for (i=0; i < 6; i++){
00728 fluid_mutex_lock(router->ruletables_mutex);
00729 current_rule=rules[i];
00730 while (current_rule){
00731 if (current_rule->pending_events == 0){
00732
00733 current_rule->state=MIDIRULE_DONE;
00734 } else {
00735
00736 current_rule->state=MIDIRULE_WAITING;
00737 };
00738 current_rule=current_rule->next;
00739 };
00740 fluid_mutex_unlock(router->ruletables_mutex);
00741 };
00742 };
00743
00744 void fluid_midi_router_free_unused_rules(fluid_midi_router_t* router)
00745 {
00746 int i;
00747
00748 for (i=0; i < 6; i++){
00749 fluid_midi_router_rule_t** p=NULL;
00750
00751
00752
00753
00754 fluid_mutex_lock(router->ruletables_mutex);
00755 switch(i){
00756 case 0:
00757 p=&router->note_rules;
00758 break;
00759 case 1:
00760 p=&router->cc_rules;
00761 break;
00762 case 2:
00763 p=&router->progchange_rules;
00764 break;
00765 case 3:
00766 p=&router->pitchbend_rules;
00767 break;
00768 case 4:
00769 p=&router->channel_pressure_rules;
00770 break;
00771 case 5:
00772 p=&router->key_pressure_rules;
00773 break;
00774 default:
00775 break;
00776 };
00777
00778 while (*p){
00779 fluid_midi_router_rule_t* current_rule=*p;
00780 fluid_midi_router_rule_t* next_rule=current_rule->next;
00781
00782 if (current_rule->state == MIDIRULE_DONE){
00783
00784
00785
00786
00787
00788
00789 *p=next_rule;
00790
00791
00792 delete_fluid_midi_router_rule(current_rule);
00793
00794 } else {
00795
00796 p = ¤t_rule->next;
00797 };
00798 };
00799 fluid_mutex_unlock(router->ruletables_mutex);
00800 };
00801 };
00802
00813 int fluid_midi_dump_prerouter(void* data, fluid_midi_event_t* event)
00814 {
00815 switch (event->type) {
00816 case NOTE_ON:
00817 fprintf(stdout, "event_pre_noteon %i %i %i\n",
00818 event->channel, event->param1, event->param2);
00819 break;
00820 case NOTE_OFF:
00821 fprintf(stdout, "event_pre_noteoff %i %i %i\n",
00822 event->channel, event->param1, event->param2);
00823 break;
00824 case CONTROL_CHANGE:
00825 fprintf(stdout, "event_pre_cc %i %i %i\n",
00826 event->channel, event->param1, event->param2);
00827 break;
00828 case PROGRAM_CHANGE:
00829 fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1);
00830 break;
00831 case PITCH_BEND:
00832 fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1);
00833 break;
00834 case CHANNEL_PRESSURE:
00835 fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1);
00836 break;
00837 case KEY_PRESSURE:
00838 fprintf(stdout, "event_pre_kpress %i %i %i\n",
00839 event->channel, event->param1, event->param2);
00840 break;
00841 default:
00842 break;
00843 };
00844 return fluid_midi_router_handle_midi_event((fluid_midi_router_t*) data, event);
00845 };
00846
00857 int fluid_midi_dump_postrouter(void* data, fluid_midi_event_t* event)
00858 {
00859 switch (event->type) {
00860 case NOTE_ON:
00861 fprintf(stdout, "event_post_noteon %i %i %i\n",
00862 event->channel, event->param1, event->param2);
00863 break;
00864 case NOTE_OFF:
00865 fprintf(stdout, "event_post_noteoff %i %i %i\n",
00866 event->channel, event->param1, event->param2);
00867 break;
00868 case CONTROL_CHANGE:
00869 fprintf(stdout, "event_post_cc %i %i %i\n",
00870 event->channel, event->param1, event->param2);
00871 break;
00872 case PROGRAM_CHANGE:
00873 fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1);
00874 break;
00875 case PITCH_BEND:
00876 fprintf(stdout, "event_post_pitch %i %i\n", event->channel, event->param1);
00877 break;
00878 case CHANNEL_PRESSURE:
00879 fprintf(stdout, "event_post_cpress %i %i\n", event->channel, event->param1);
00880 break;
00881 case KEY_PRESSURE:
00882 fprintf(stdout, "event_post_kpress %i %i %i\n",
00883 event->channel, event->param1, event->param2);
00884 break;
00885 default:
00886 break;
00887 };
00888 return fluid_synth_handle_midi_event((fluid_synth_t*) data, event);
00889 };