[LAU] MIDI fan-out box -- DONE

Ken Restivo ken at restivo.org
Sat Oct 13 05:05:53 EDT 2007


Well, I did it, and it turned out to be dead easy-- about 100 lines of C code.

Attached, in case anyone now or in the future has any use for it.

-ken
-------------- next part --------------
/*********************
a simple virtual fan-out box for midi

$Id: fanout.c,v 1.14 2007-10-13 09:05:04 ken Exp $

fans out one incoming midi stream
onto virtual ALSA ports, by channel

i.e. any data received on channel 0 goes to port 0, 
any data on channel 16 goes to port 16
i force it to channel 0 upon output

build with:  gcc -Wall -o fanout fanout.c  -lasound

 Copyright (C) 2007  ken restivo <ken at restivo.org>

most of the working code, is lifted from qmidiroute, midirgui, and alsaseq2jackmidi

Program Author: Matthais Nagorni <mn at matthias-nagorni.de>
Copyright: 2002-2004 SuSE AG Nuremberg

Copyright (c)2005 Sean Bolton.
 

   This package is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This package is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this package; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301, USA.

***********************/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <alsa/asoundlib.h>


#define FANOUT_CLIENT_NAME "Fan Out Box"
#define FANOUT_PORT_NAME "fanout"
#define MAXBYTESLINE 16

#undef FANOUT_DEBUG


int portid_in;
snd_seq_t *seq_handle;
int portCount = 16;
int clientid;
int default_chan = 0;



int
main(int argc, char ** argv)
{


    if (snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
        fprintf(stderr, "Error opening ALSA sequencer.\n");
        exit(1);
    }

    snd_seq_set_client_name(seq_handle, FANOUT_CLIENT_NAME);

    clientid = snd_seq_client_id(seq_handle);


    if ((portid_in = snd_seq_create_simple_port(seq_handle, FANOUT_PORT_NAME,
                                                SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
                                                SND_SEQ_PORT_TYPE_APPLICATION)) < 0) 
    {
        fprintf(stderr, "Error creating sequencer port.\n");
        exit(1);
    }                                     


    int l1;
    int portid_out[portCount];
    char * portname;
    for (l1 = 0; l1 < portCount; l1++) {
        //XXX yeah, it's a memory leak. so what.
        asprintf(&portname,  "%s output %d", FANOUT_PORT_NAME, l1); 

        if ((portid_out[l1] = snd_seq_create_simple_port(seq_handle,  portname,
                                                         SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
                                                         SND_SEQ_PORT_TYPE_APPLICATION)) < 0) 
        {
            fprintf(stderr, "Error creating sequencer port.\n");
            exit(1);
        }
    }                                    



    //set up listener

 

    snd_seq_event_t *ev;
	unsigned int cmdchan = 0;

    // te loop!
            
    // now go get!
    while( snd_seq_event_input(seq_handle, &ev)){
        if(ev == NULL) {
            fprintf(stderr, "fanout: shooting blanks??\n");
            continue;
        }

        
        if ((ev->type == SND_SEQ_EVENT_NOTEON)
            || (ev->type == SND_SEQ_EVENT_NOTEOFF))
        {
            
			cmdchan = ev->data.note.channel;
			//force
			ev->data.note.channel = default_chan;
			
		} else  if ((ev->type == SND_SEQ_EVENT_CHANPRESS)
					|| (ev->type == SND_SEQ_EVENT_PITCHBEND)
					|| (ev->type == SND_SEQ_EVENT_CONTROLLER) 
					|| (ev->type == SND_SEQ_EVENT_PGMCHANGE))
		{
            
			cmdchan = ev->data.control.channel;
			//force
			ev->data.control.channel = default_chan;
			
		} else {
			//WTF?
	        fprintf(stderr, "fanout: event type %d isn't handled. sysex?\n", ev->type);
    		continue;
			
		}			
		
		
		snd_seq_ev_set_subs (ev);
		snd_seq_ev_set_direct (ev);
		

		if(cmdchan > portCount - 1){
	        fprintf(stderr, "fanout: channel %d doesn't have a port. you got trouble\n", cmdchan);
    		continue;
		}
		
		snd_seq_ev_set_source(ev, portid_out[cmdchan]);
		snd_seq_event_output_direct(seq_handle, ev);
		
		
		
		snd_seq_free_event(ev);
    }  // END LOOP
    
        
    
    return(0);
    
}


// TO DO: cleanup, signals


-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.linuxaudio.org/pipermail/linux-audio-user/attachments/20071013/36e9a733/attachment.pgp 


More information about the Linux-audio-user mailing list