예제 #1
0
int
midi_open(void)
{
    if (snd_seq_open(&alsaClient, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
        ghss_debug(GDB_ERROR, ": failed to open ALSA sequencer interface");
	return 0;
    }

    snd_seq_set_client_name(alsaClient, host_name);

    alsa_client_id = snd_seq_client_id(alsaClient);

    if ((alsa_port_id = snd_seq_create_simple_port
	 (alsaClient, "input",
	  SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
        ghss_debug(GDB_ERROR, ": failed to create ALSA sequencer port");
	return 0;
    }

    alsaClient_npfd = snd_seq_poll_descriptors_count(alsaClient, POLLIN);
    alsaClient_pfd = (struct pollfd *)calloc(1, alsaClient_npfd * sizeof(struct pollfd));
    snd_seq_poll_descriptors(alsaClient, alsaClient_pfd, alsaClient_npfd, POLLIN);

    ghss_debug(GDB_ALWAYS, ": listening using ALSA MIDI");

    return 1;
}
예제 #2
0
void DeviceManager::loop()
{
    struct pollfd *pfds;
    int npfds;
    int c, err;
    npfds = snd_seq_poll_descriptors_count(handle, POLLIN);
    D("npfds: %d", npfds);
    pfds = (struct pollfd *)alloca(sizeof(*pfds) * npfds);
    for (;;) {
        snd_seq_poll_descriptors(handle, pfds, npfds, POLLIN);
        if (poll(pfds, npfds, -1) < 0)
            break;
        do {
            snd_seq_event_t *event;
            err = snd_seq_event_input(handle, &event);
            if (err < 0)
                break;
            if (event){
                list[0]->processEvent(event);
            }
        } while (err > 0);
        fflush(stdout);
//        if (stop)
//            break;
    }

    snd_seq_close(handle);
}
예제 #3
0
void AlsaMidiInputThread::run()
{
    qDebug() << Q_FUNC_INFO << "begin";

    struct pollfd* pfd = 0;
    int npfd = 0;

    m_mutex.lock();
    m_running = true;
    while (m_running == true)
    {
        if (m_changed == true)
        {
            // Poll descriptors must be re-evaluated
            npfd = snd_seq_poll_descriptors_count(m_alsa, POLLIN);
            pfd = (struct pollfd*) alloca(npfd * sizeof(struct pollfd));
            snd_seq_poll_descriptors(m_alsa, pfd, npfd, POLLIN);
            m_changed = false;
        }

        m_mutex.unlock();

        // Poll for MIDI events from the polled descriptors outside of mutex lock
        if (poll(pfd, npfd, POLL_TIMEOUT_MS) > 0)
            readEvent();

        m_mutex.lock();
    }
    m_mutex.unlock();

    qDebug() << Q_FUNC_INFO << "end";
}
예제 #4
0
    void run()
    {
        snd_seq_t *seq = m_sampl->alsa_seq();
        if (seq == NULL)
            return;

        m_running = true;

        int nfds;
        struct pollfd *pfds;

        nfds = snd_seq_poll_descriptors_count(seq, POLLIN);
        pfds = (struct pollfd *) alloca(nfds * sizeof(struct pollfd));
        snd_seq_poll_descriptors(seq, pfds, nfds, POLLIN);

        int poll_rc = 0;

        while (m_running && poll_rc >= 0) {
            poll_rc = ::poll(pfds, nfds, 200);
            while (poll_rc > 0) {
                snd_seq_event_t *ev = NULL;
                snd_seq_event_input(seq, &ev);
                m_sampl->alsa_capture(ev);
                //	snd_seq_free_event(ev);
                poll_rc = snd_seq_event_input_pending(seq, 0);
            }
        }

        m_running = false;
    }
    int MidiInputDeviceAlsa::Main() {
        int npfd;
        struct pollfd* pfd;
        snd_seq_event_t* ev;

        npfd = snd_seq_poll_descriptors_count(hAlsaSeq, POLLIN);
        pfd = (struct pollfd*) alloca(npfd * sizeof(struct pollfd));
        snd_seq_poll_descriptors(hAlsaSeq, pfd, npfd, POLLIN);
        while (true) {
            if (poll(pfd, npfd, 100000) > 0) {
                do {
                    snd_seq_event_input(hAlsaSeq, &ev);
                    int port = (int) ev->dest.port;
                    MidiInputPort* pMidiInputPort = Ports[port];

                    switch (ev->type) {
                        case SND_SEQ_EVENT_CONTROLLER:
                            if (ev->data.control.param == 0)
                                pMidiInputPort->DispatchBankSelectMsb(ev->data.control.value, ev->data.control.channel);
                            else if (ev->data.control.param == 32)
                                pMidiInputPort->DispatchBankSelectLsb(ev->data.control.value, ev->data.control.channel);
                            pMidiInputPort->DispatchControlChange(ev->data.control.param, ev->data.control.value, ev->data.control.channel);
                            break;

                        case SND_SEQ_EVENT_CHANPRESS:
                            pMidiInputPort->DispatchControlChange(128, ev->data.control.value, ev->data.control.channel);
                            break;

                        case SND_SEQ_EVENT_PITCHBEND:
                            pMidiInputPort->DispatchPitchbend(ev->data.control.value, ev->data.control.channel);
                            break;

                        case SND_SEQ_EVENT_NOTEON:
                            if (ev->data.note.velocity != 0) {
                                pMidiInputPort->DispatchNoteOn(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);
                            }
                            else {
                                pMidiInputPort->DispatchNoteOff(ev->data.note.note, 0, ev->data.control.channel);
                            }
                            break;

                        case SND_SEQ_EVENT_NOTEOFF:
                            pMidiInputPort->DispatchNoteOff(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);
                            break;

                        case SND_SEQ_EVENT_SYSEX:
                            pMidiInputPort->DispatchSysex(ev->data.ext.ptr, ev->data.ext.len);
                            break;

                        case SND_SEQ_EVENT_PGMCHANGE:
                            pMidiInputPort->DispatchProgramChange(ev->data.control.value, ev->data.control.channel);
                            break;
                    }
                    snd_seq_free_event(ev);
                } while (snd_seq_event_input_pending(hAlsaSeq, 0) > 0);
            }
        }
        // just to avoid a compiler warning
        return EXIT_FAILURE;
    }
예제 #6
0
/* Returned structure pointer is allocated using malloc. */
struct polls *
midi_init_alsa(void)
{
  struct polls *polls;
  int npfd;
  int synth_port, ctrlr_port;
  int i;

  if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
    dprintf("Couldn't open ALSA sequencer: %s\n", snd_strerror(errno));
    return NULL;
  }
  snd_seq_set_client_name(seq, "Xtor");

  client = snd_seq_client_id(seq);
  if (client < 0) {
    dprintf("Can't get client_id: %d\n", client);
    return NULL;
  }
  dprintf("Client address %d\n", client);

  synth_port = snd_seq_create_simple_port(seq, "Xtor synth port",
                                          SND_SEQ_PORT_CAP_READ |
                                          SND_SEQ_PORT_CAP_WRITE |
                                          SND_SEQ_PORT_CAP_SUBS_READ |
                                          SND_SEQ_PORT_CAP_SUBS_WRITE,
                                          SND_SEQ_PORT_TYPE_APPLICATION);
  if (synth_port < 0) {
    dprintf("Couldn't create synth port: %s\n", snd_strerror(errno));
    return NULL;
  }
  ports[SYNTH_PORT] = synth_port;

  ctrlr_port = snd_seq_create_simple_port(seq, "Xtor controller port",
                                          SND_SEQ_PORT_CAP_READ |
                                          SND_SEQ_PORT_CAP_WRITE |
                                          SND_SEQ_PORT_CAP_SUBS_READ |
                                          SND_SEQ_PORT_CAP_SUBS_WRITE,
                                          SND_SEQ_PORT_TYPE_APPLICATION);
  if (ctrlr_port < 0) {
    dprintf("Couldn't create controller port: %s\n", snd_strerror(errno));
    return NULL;
  }
  ports[CTRLR_PORT] = ctrlr_port;

  /* Fetch poll descriptor(s) for MIDI input (normally only one) */
  npfd = snd_seq_poll_descriptors_count(seq, POLLIN);
  polls = (struct polls *) malloc(sizeof(struct polls) +
				  npfd * sizeof(struct pollfd));
  polls->npfd = npfd;
  snd_seq_poll_descriptors(seq, polls->pollfds, npfd, POLLIN);

  snd_seq_nonblock(seq, SND_SEQ_NONBLOCK);

  return polls;
}
예제 #7
0
void SeqDriver::initSeqNotifier()
{
    int alsaEventFd = 0;

    struct pollfd pfd[1];
    snd_seq_poll_descriptors(seq_handle, pfd, 1, POLLIN);
    alsaEventFd = pfd[0].fd;
    seqNotifier = new QSocketNotifier(alsaEventFd, QSocketNotifier::Read);
    connect(seqNotifier, SIGNAL(activated(int)),
            this, SLOT(procEvents()));
}
예제 #8
0
void* alsa_input_thread(void * arg)
{
	struct a2j * self = arg;
	int npfd;
	struct pollfd * pfd;
	snd_seq_addr_t addr;
	snd_seq_client_info_t * client_info;
	snd_seq_port_info_t * port_info;
	bool initial;
	snd_seq_event_t * event;
	int ret;

	npfd = snd_seq_poll_descriptors_count(self->seq, POLLIN);
	pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
	snd_seq_poll_descriptors(self->seq, pfd, npfd, POLLIN);

	initial = true;
	while (g_keep_alsa_walking) {
		if ((ret = poll(pfd, npfd, 1000)) > 0) {

			while (snd_seq_event_input (self->seq, &event) > 0) {
				if (initial) {
					snd_seq_client_info_alloca(&client_info);
					snd_seq_port_info_alloca(&port_info);
					snd_seq_client_info_set_client(client_info, -1);
					while (snd_seq_query_next_client(self->seq, client_info) >= 0) {
						addr.client = snd_seq_client_info_get_client(client_info);
						if (addr.client == SND_SEQ_CLIENT_SYSTEM || addr.client == self->client_id) {
							continue;
						}
						snd_seq_port_info_set_client(port_info, addr.client);
						snd_seq_port_info_set_port(port_info, -1);
						while (snd_seq_query_next_port(self->seq, port_info) >= 0) {
							addr.port = snd_seq_port_info_get_port(port_info);
							a2j_update_port(self, addr, port_info);
						}
					}

					initial = false;
				}

				if (event->source.client == SND_SEQ_CLIENT_SYSTEM) {
					a2j_port_event(self, event);
				} else {
					a2j_input_event(self, event);
				}

				snd_seq_free_event (event);
			}
		}
	}

	return (void*) 0;
}
예제 #9
0
/*
 * Allocate and initiate a new MIDI event poller.
 */
struct pollfd *sequencer_poller_new(snd_seq_t *seq_handle,
					   int *npfd_ptr) {
  struct pollfd *pfd;
  /*
   * Prepeare event polling on the MIDI input.
   */
  *npfd_ptr = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
  pfd = (struct pollfd *)malloc(*npfd_ptr * sizeof(struct pollfd));
  snd_seq_poll_descriptors(seq_handle, pfd, *npfd_ptr, POLLIN);

  return  pfd;
}
    void run()
    {
        const int maxEventSize = 16 * 1024;
        snd_midi_event_t* midiParser;

        if (snd_midi_event_new (maxEventSize, &midiParser) >= 0)
        {
            HeapBlock <uint8> buffer (maxEventSize);

            const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN);
            struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd));

            snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN);

            while (! threadShouldExit())
            {
                if (poll (pfd, numPfds, 500) > 0)
                {
                    snd_seq_event_t* inputEvent = nullptr;

                    snd_seq_nonblock (seqHandle, 1);

                    do
                    {
                        if (snd_seq_event_input (seqHandle, &inputEvent) >= 0)
                        {
                            // xxx what about SYSEXes that are too big for the buffer?
                            const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent);

                            snd_midi_event_reset_decode (midiParser);

                            if (numBytes > 0)
                            {
                                const MidiMessage message ((const uint8*) buffer,
                                                           numBytes,
                                                           Time::getMillisecondCounter() * 0.001);


                                callback->handleIncomingMidiMessage (midiInput, message);
                            }

                            snd_seq_free_event (inputEvent);
                        }
                    }
                    while (snd_seq_event_input_pending (seqHandle, 0) > 0);

                    snd_seq_free_event (inputEvent);
                }
            }

            snd_midi_event_free (midiParser);
        }
    };
int main (int argc, char *argv[]) {

    int nfds, seq_nfds, l1;
    struct pollfd *pfds;

    if (argc < 6) {
        fprintf(stderr, "LinzerSchnitteMIDI <hw:0,0,1> <attack> <decay> <sustain> <release>\n"); 
        exit(1);
    }

    attack = atof(argv[2]);
    decay = atof(argv[3]);
    sustain = atof(argv[4]);
    release = atof(argv[5]);
/*    polyphony = atoi(argv[6]);
    buffersize = atoi(argv[7]);
    outputvolume = atoi(argv[8]);
    firstnotefreq = atoi(argv[9]);
    freqchannelwidth = atoi(argv[10]);
*/
    buf = (short *) malloc (2 * sizeof (short) * BUFSIZE);
    playback_handle = open_pcm(argv[1]);
    seq_handle = open_seq();
    seq_nfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
    nfds = snd_pcm_poll_descriptors_count (playback_handle);
    pfds = (struct pollfd *)alloca(sizeof(struct pollfd) * (seq_nfds + nfds));
    snd_seq_poll_descriptors(seq_handle, pfds, seq_nfds, POLLIN);
    snd_pcm_poll_descriptors (playback_handle, pfds+seq_nfds, nfds);
    connect2MidiThroughPort(seq_handle);
    for (l1 = 0; l1 < POLY; note_active[l1++] = 0);
    while (1) {
        if (poll (pfds, seq_nfds + nfds, 1000) > 0) {
            for (l1 = 0; l1 < seq_nfds; l1++) {
               if (pfds[l1].revents > 0) midi_callback();
            }
            for (l1 = seq_nfds; l1 < seq_nfds + nfds; l1++) {
                if (pfds[l1].revents > 0) {
                    if (playback_callback(BUFSIZE) < BUFSIZE) {
                        fprintf (stderr, "xrun ! increase buffer \n");
                        snd_pcm_prepare(playback_handle);
                    }
                }
            }
        }
    }
    snd_pcm_close (playback_handle);
    snd_seq_close (seq_handle);
    free(buf);
    return (0);
}
예제 #12
0
파일: alsaseq.c 프로젝트: bgribble/mfp
static PyObject *
alsaseq_fd(PyObject *self, PyObject *args)
{
  int npfd;
  struct pollfd *pfd;
        
	if (!PyArg_ParseTuple(args, "" ))
		return NULL;
  npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
  pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
  snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);

        return PyInt_FromLong( pfd->fd );
}
예제 #13
0
파일: mux_midi.c 프로젝트: eriser/ayemux
void midi_thread(void *data){
	snd_seq_t *seq_handle;
	int npfd;
	struct pollfd *pfd;

	seq_handle = open_seq();
	npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
	pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
	snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);
	while (1) {
		if (poll(pfd, npfd, 100000) > 0) {
			midi_action(seq_handle);
		}  
	}
}
예제 #14
0
void* ReadMidi(void* seq) 
{
	int nPfd;
	struct pollfd* t_pfd;

	nPfd = snd_seq_poll_descriptors_count(t_seq, POLLIN);
	t_pfd = (struct pollfd*) alloca(nPfd * sizeof(struct pollfd));
	snd_seq_poll_descriptors(t_seq, t_pfd, nPfd, POLLIN);	

	while (zRun) 
		if (poll(t_pfd, nPfd, 100) > 0) 
			PrintMidiIn();

	printf("\n[IN  ALSA]->process communication shutdown ...\n");
}
예제 #15
0
int main (int argc, char *argv[]) {

    int nfds, seq_nfds, l1;
    struct pollfd *pfds;
    
    if (argc < 10) {
        fprintf(stderr, "miniFMsynth <device> <FM> <harmonic> <subharmonic> <transpose> <a> <d> <s> <r>\n"); 
        exit(1);
    }
    modulation = atof(argv[2]);
    harmonic = atoi(argv[3]);
    subharmonic = atoi(argv[4]);
    transpose = atoi(argv[5]);
    attack = atof(argv[6]);
    decay = atof(argv[7]);
    sustain = atof(argv[8]);
    release = atof(argv[9]);
    pitch = 0;
    buf = (short *) malloc (2 * sizeof (short) * BUFSIZE);
    playback_handle = open_pcm(argv[1]);
    seq_handle = open_seq();
    seq_nfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
    nfds = snd_pcm_poll_descriptors_count (playback_handle);
    pfds = (struct pollfd *)alloca(sizeof(struct pollfd) * (seq_nfds + nfds));
    snd_seq_poll_descriptors(seq_handle, pfds, seq_nfds, POLLIN);
    snd_pcm_poll_descriptors (playback_handle, pfds+seq_nfds, nfds);
    for (l1 = 0; l1 < POLY; note_active[l1++] = 0);
    while (1) {
        if (poll (pfds, seq_nfds + nfds, 1000) > 0) {
            for (l1 = 0; l1 < seq_nfds; l1++) {
               if (pfds[l1].revents > 0) midi_callback();
            }
            for (l1 = seq_nfds; l1 < seq_nfds + nfds; l1++) {    
                if (pfds[l1].revents > 0) { 
                    if (playback_callback(BUFSIZE) < BUFSIZE) {
                        fprintf (stderr, "xrun !\n");
                        snd_pcm_prepare(playback_handle);
                    }
                }
            }        
        }
    }
    snd_pcm_close (playback_handle);
    snd_seq_close (seq_handle);
    free(buf);
    return (0);
}
예제 #16
0
파일: midi-rx.c 프로젝트: Harvie/Programs
int main(int argc, char *argv[]) {

  snd_seq_t *seq_handle;
  int npfd;
  struct pollfd *pfd;

  seq_handle = open_seq();
  npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
  pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
  snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);

	fprintf(stderr, "COMMAND:CHANNEL:NOTE\nCommands are described on http://www.ec.vanderbilt.edu/computermusic/musc216site/MIDI.Commands.html\n\n");
  while (1) {
    if (poll(pfd, npfd, 100000) > 0) {
      midi_action(seq_handle);
    }
  }
}
예제 #17
0
	// The main thread executive.
	void run()
	{
		snd_seq_t *pAlsaSeq = m_pMidiDevice->alsaSeq();
		if (pAlsaSeq == NULL)
			return;

		int nfds;
		struct pollfd *pfds;

		nfds = snd_seq_poll_descriptors_count(pAlsaSeq, POLLIN);
		pfds = (struct pollfd *) alloca(nfds * sizeof(struct pollfd));
		snd_seq_poll_descriptors(pAlsaSeq, pfds, nfds, POLLIN);

		qxgeditMidiInputRpn xrpn;

		m_bRunState = true;

		int iPoll = 0;
		while (m_bRunState && iPoll >= 0) {
			// Wait for events...
			iPoll = poll(pfds, nfds, 200);
			// Timeout?
			if (iPoll == 0)
				xrpn.flush();
			while (iPoll > 0) {
				snd_seq_event_t *pEv = NULL;
				snd_seq_event_input(pAlsaSeq, &pEv);
				// Process input event - ...
				// - enqueue to input track mapping;
				if (!xrpn.process(pEv))
					m_pMidiDevice->capture(pEv);
			//	snd_seq_free_event(pEv);
				iPoll = snd_seq_event_input_pending(pAlsaSeq, 0);
			}
			// Process pending events...
			while (xrpn.isPending()) {
				snd_seq_event_t ev;
				if (xrpn.dequeue(&ev))
					m_pMidiDevice->capture(&ev);
			}
		}
	}
예제 #18
0
파일: alsaseq.c 프로젝트: ppaez/alsaseq
static PyObject *
alsaseq_fd(PyObject *self, PyObject *args)
{
  int npfd;
  struct pollfd *pfd;
        
	if (!PyArg_ParseTuple(args, "" ))
		return NULL;

        if (!seq_handle) {
                PyErr_SetString(PyExc_RuntimeError, "Must initialize module with alsaseq.client() before using it");
                return NULL;
        }

  npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
  pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd));
  snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);

        return PyInt_FromLong( pfd->fd );
}
예제 #19
0
bool Midi2UdpThread::go()
{
	// Initialize midi port
	bool res = initSeq();
	if(res == false) {
		return false;
	}
	
	// start expecing MIDI events
	npfd = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
	pfd = (struct pollfd *)malloc(npfd * sizeof(struct pollfd));
	snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN);
	
	// run thread
	if(!isRunning()) {
		start(LowPriority);
	}
	
	return true;
}
예제 #20
0
void	*vj_midi_new(void *mw)
{
	vmidi_t *v = (vmidi_t*) vj_calloc(sizeof(vmidi_t));
	int portid = 0;

	if( snd_seq_open( &(v->sequencer), "hw", SND_SEQ_OPEN_DUPLEX | SND_SEQ_NONBLOCK, 0 ) < 0 )
	{
		veejay_msg(0, "Error opening ALSA sequencer");
		return v;
	}

	snd_seq_set_client_name( v->sequencer, "Veejay" );

	if( (portid = snd_seq_create_simple_port( v->sequencer, "Reloaded",
			SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE ,
			SND_SEQ_PORT_TYPE_APPLICATION )) < 0 )
	{
		veejay_msg(0, "Error creating sequencer port");
		return v;
	}

	v->npfd = snd_seq_poll_descriptors_count( v->sequencer, POLLIN );
	if( v->npfd <= 0 )
	{
		veejay_msg(0,"Unable to poll in from sequencer");
		return v;
	}
	v->pfd     = (struct pollfd *) vj_calloc( v->npfd * sizeof( struct pollfd ));
	v->mw      = mw;
	v->learn   = 0;
	v->vims    = vpn(VEVO_ANONYMOUS_PORT);	
	v->active = 1;
	snd_seq_poll_descriptors( v->sequencer, v->pfd, v->npfd, POLLIN );

	veejay_msg(VEEJAY_MSG_INFO, "MIDI listener active! Type 'aconnect -o' to see where to connect to.");
	veejay_msg(VEEJAY_MSG_INFO, "For example: $ aconnect 128 129");

	return (void*) v;
}
예제 #21
0
int snd_rawmidi_virtual_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
			     const char *name, snd_seq_t *seq_handle, int port,
			     int merge, int mode)
{
	int err;
	snd_rawmidi_t *rmidi;
	snd_rawmidi_virtual_t *virt = NULL;
	struct pollfd pfd;

	if (inputp)
		*inputp = 0;
	if (outputp)
		*outputp = 0;

	virt = calloc(1, sizeof(*virt));
	if (virt == NULL) {
		err = -ENOMEM;
		goto _err;
	}
	virt->handle = seq_handle;
	virt->port = port;
	err = snd_midi_event_new(256, &virt->midi_event);
	if (err < 0)
		goto _err;
	snd_midi_event_init(virt->midi_event);
	snd_midi_event_no_status(virt->midi_event, !merge);

	if (inputp) {
		rmidi = calloc(1, sizeof(*rmidi));
		if (rmidi == NULL) {
			err = -ENOMEM;
			goto _err;
		}
		if (name)
			rmidi->name = strdup(name);
		rmidi->type = SND_RAWMIDI_TYPE_VIRTUAL;
		rmidi->stream = SND_RAWMIDI_STREAM_INPUT;
		rmidi->mode = mode;
		err = snd_seq_poll_descriptors(seq_handle, &pfd, 1, POLLIN);
		if (err < 0)
			goto _err;
		rmidi->poll_fd = pfd.fd;
		rmidi->ops = &snd_rawmidi_virtual_ops;
		rmidi->private_data = virt;
		virt->open++;
		*inputp = rmidi;
	}
	if (outputp) {
		rmidi = calloc(1, sizeof(*rmidi));
		if (rmidi == NULL) {
			err = -ENOMEM;
			goto _err;
		}
		if (name)
			rmidi->name = strdup(name);
		rmidi->type = SND_RAWMIDI_TYPE_VIRTUAL;
		rmidi->stream = SND_RAWMIDI_STREAM_OUTPUT;
		rmidi->mode = mode;
		err = snd_seq_poll_descriptors(seq_handle, &pfd, 1, POLLOUT);
		if (err < 0)
			goto _err;
		rmidi->poll_fd = pfd.fd;
		rmidi->ops = &snd_rawmidi_virtual_ops;
		rmidi->private_data = virt;
		virt->open++;
		*outputp = rmidi;
	}

	return 0;

 _err:
	if (seq_handle)
		snd_seq_close(seq_handle);
	if (virt) {
		if (virt->midi_event)
			snd_midi_event_free(virt->midi_event);
		free(virt);
	}
	if (inputp)
		free(*inputp);
	if (outputp)
		free(*outputp);
	return err;
}
예제 #22
0
void event_decoder(snd_seq_t *handle, int argc, char *argv[])
{
	snd_seq_event_t *ev;
	snd_seq_port_info_t *pinfo;
	snd_seq_port_subscribe_t *sub;
	snd_seq_addr_t addr;
	int client, port, queue, max, err, v1, v2;
	char *ptr;
	struct pollfd *pfds;

	if ((client = snd_seq_client_id(handle))<0) {
		fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client));
		return;
	}
	printf("Client ID = %i\n", client);
	if ((queue = snd_seq_alloc_queue(handle))<0) {
		fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue));
		return;
	}
	printf("Queue ID = %i\n", queue);
	if ((err = snd_seq_nonblock(handle, 1))<0)
		fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
	snd_seq_port_info_alloca(&pinfo);
	snd_seq_port_info_set_name(pinfo, "Input");
	snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
	snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE);

	/* Enable timestamping for events sent by external subscribers. */
	snd_seq_port_info_set_timestamping(pinfo, 1);
	snd_seq_port_info_set_timestamp_real(pinfo, 1);
	snd_seq_port_info_set_timestamp_queue(pinfo, queue);

	if ((err = snd_seq_create_port(handle, pinfo)) < 0) {
		fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err));
		return;
	}
	port = snd_seq_port_info_get_port(pinfo);
	event_decoder_start_timer(handle, queue, client, port);

	snd_seq_port_subscribe_alloca(&sub);
	addr.client = SND_SEQ_CLIENT_SYSTEM;
	addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
	snd_seq_port_subscribe_set_sender(sub, &addr);
	addr.client = client;
	addr.port = port;
	snd_seq_port_subscribe_set_dest(sub, &addr);
	snd_seq_port_subscribe_set_queue(sub, queue);
	snd_seq_port_subscribe_set_time_update(sub, 1);
	snd_seq_port_subscribe_set_time_real(sub, 1);
	if ((err = snd_seq_subscribe_port(handle, sub))<0) {
		fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err));
		return;
	}

	addr.client = SND_SEQ_CLIENT_SYSTEM;
	addr.port = SND_SEQ_PORT_SYSTEM_TIMER;
	snd_seq_port_subscribe_set_sender(sub, &addr);
	if ((err = snd_seq_subscribe_port(handle, sub))<0) {
		fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err));
		return;
	}

	for (max = 0; max < argc; max++) {
		ptr = argv[max];
		if (!ptr)
			continue;
		snd_seq_port_subscribe_set_time_real(sub, 0);
		if (tolower(*ptr) == 'r') {
			snd_seq_port_subscribe_set_time_real(sub, 1);
			ptr++;
		}
		if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) {
			fprintf(stderr, "Wrong argument '%s'...\n", argv[max]);
			return;
		}
		addr.client = v1;
		addr.port = v2;
		snd_seq_port_subscribe_set_sender(sub, &addr);
		if ((err = snd_seq_subscribe_port(handle, sub))<0) {
			fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err));
			return;
		}
	}
	
	max = snd_seq_poll_descriptors_count(handle, POLLIN);
	pfds = alloca(sizeof(*pfds) * max);
	while (1) {
		snd_seq_poll_descriptors(handle, pfds, max, POLLIN);
		if (poll(pfds, max, -1) < 0)
			break;
		do {
			if ((err = snd_seq_event_input(handle, &ev))<0)
				break;
			if (!ev)
				continue;
			decode_event(ev);
			snd_seq_free_event(ev);
		} while (err > 0);
	}
}
예제 #23
0
파일: main.c 프로젝트: 50m30n3/SO-KL5
int main( int argc, char *argv[] )
{
	jack_client_t *jackClient;

	snd_seq_t *seqport;
	struct pollfd *pfd;
	int npfd;
	snd_seq_event_t *midievent;
	int channel, midiport;
	
	int note, length, i, j, minpos;
	double freq, avg, vol, scale, min;
	double *tempstring;

	puts( "SO-KL5 v.1.2 by 50m30n3 2009-2011" );

	if( argc > 1 )
		channel = atoi( argv[1] );
	else
		channel = 0;

	signal( SIGINT, sig_exit );
	signal( SIGTERM, sig_exit );


	puts( "Connecting to Jack Audio Server" );
	
	jackClient = jack_client_open( "SO-KL5", JackNoStartServer, NULL );
	if( jackClient == NULL )
	{
		fputs( "Cannot connect to Jack Server\n", stderr );
		return 1;
	}

	jack_on_shutdown( jackClient, jack_shutdown, 0 );

	outport = jack_port_register( jackClient, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 );

	jack_set_process_callback( jackClient, process, 0 );

	samplerate = jack_get_sample_rate( jackClient );


	puts( "Initializing synth parameters" );

	sustain = 0;
	cutoff = 64;
	resonance = 100;
	attack = 64;
	volume = 100;

	fcutoff = (cutoff+5.0)/400.0;
	sattack = (attack+5.0)/800.0;
	freso = (resonance/160.0)*(1.0-fcutoff);
	ssustain = 0.6+pow( sustain/127.0, 0.4)*0.4;

	for( note=0; note<NUMNOTES; note++ )
	{
		freq = 440.0*pow( 2.0, (note+BASENOTE-69) / 12.0 );
		stringcutoff[note] = 0.5 + pow( (double)note / (double)NUMNOTES, 0.5 ) * 0.45;
		length = round( (double)samplerate / freq );
		stringlength[note] = length;
		strings[note] = malloc( length * sizeof( double ) );
		if( strings[note] == NULL )
		{
			fputs( "Error allocating memory\n", stderr );
			return 1;
		}
		
		for( i=0; i<length; i++ )
		{
			strings[note][i] = 0.0;
		}
		stringpos[note] = 0;
		status[note] = 0;
	}

	freq = 440.0*pow( 2.0, (BASENOTE-69) / 12.0 );
	length = (double)samplerate / freq;
	tempstring = malloc( length * sizeof( double ) );
	if( tempstring == NULL )
	{
		fputs( "Error allocating memory\n", stderr );
		return 1;
	}

	lpval = lplast = 0.0;

	jack_activate( jackClient );


	printf( "Listening on MIDI channel %i\n", channel );

	if( snd_seq_open( &seqport, "default", SND_SEQ_OPEN_INPUT, 0 ) < 0 )
	{
		fputs( "Cannot connect to ALSA sequencer\n", stderr );
		return 1;
	}

	snd_seq_set_client_name( seqport, "SO-KL5" );

	midiport = snd_seq_create_simple_port( seqport, "input",
		SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
		SND_SEQ_PORT_TYPE_APPLICATION );

	if( midiport < 0 )
	{
		fputs( "Cannot create ALSA sequencer port\n", stderr );
		return 1;
	}

	npfd = snd_seq_poll_descriptors_count( seqport, POLLIN );
	pfd = (struct pollfd *)malloc( npfd * sizeof( struct pollfd ) );
	snd_seq_poll_descriptors( seqport, pfd, npfd, POLLIN );


	done = 0;

	while( ! done )
	{
		if( poll( pfd, npfd, 100000 ) > 0 )
		{
			do
			{
				snd_seq_event_input( seqport, &midievent );
				
				if( ( midievent->type == SND_SEQ_EVENT_NOTEON ) && ( midievent->data.note.channel == channel ) )
				{
					note = midievent->data.note.note;
					if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) )
					{
						note -= BASENOTE;

						status[note] = 1;

						for( i=0; i<stringlength[note]; i++ )
						{
							tempstring[i] = ((double)rand()/(double)RAND_MAX)*2.0-1.0;
						}

						freq = stringcutoff[note] * 0.25 + midievent->data.note.velocity/127.0 * 0.2 + sattack + 0.1;

						for( j=0; j<30; j++ )
						{
							tempstring[0] = tempstring[0]*freq + tempstring[stringlength[note]-1]*(1.0-freq);
							for( i=1; i<stringlength[note]; i++ )
							{
								tempstring[i] = tempstring[i]*freq + tempstring[(i-1)%stringlength[note]]*(1.0-freq);
							}
						}

						avg = 0.0;

						for( i=0; i<stringlength[note]; i++ )
						{
							avg += tempstring[i];
						}

						avg /= stringlength[note];

						scale = 0.0;

						for( i=0; i<stringlength[note]; i++ )
						{
							tempstring[i] -= avg;
							if( fabs( tempstring[i] ) > scale )
								scale = fabs( tempstring[i] );
						}

						min = 10.0;
						minpos = 0;

						for( i=0; i<stringlength[note]; i++ )
						{
							tempstring[i] /= scale;
							if( fabs( tempstring[i] ) + fabs( tempstring[i] - tempstring[i-1] ) * 5.0 < min )
							{
								min = fabs( tempstring[i] ) + fabs( tempstring[i] - tempstring[i-1] ) * 5.0;
								minpos = i;
							}
						}

						vol = midievent->data.note.velocity/256.0;

						for( i=0; i<stringlength[note]; i++ )
						{
							strings[note][(stringpos[note]+i)%stringlength[note]] += tempstring[(i+minpos)%stringlength[note]]*vol;
						}
					}
				}
				else if( ( midievent->type == SND_SEQ_EVENT_NOTEOFF ) && ( midievent->data.note.channel == channel ) )
				{
					note = midievent->data.note.note;
					if( ( note >= BASENOTE ) && ( note < BASENOTE+NUMNOTES ) )
					{
						note -= BASENOTE;
						status[note] = 0;
					}
				}
				else if( ( midievent->type == SND_SEQ_EVENT_CONTROLLER ) && ( midievent->data.control.channel == channel ) )
				{
					if( midievent->data.control.param == 74 )
					{
						cutoff = midievent->data.control.value;
						fcutoff = (cutoff+5.0)/400.0;
						printf( "Cutoff: %i     \r", cutoff );
						fflush( stdout );
					}
					else if( midievent->data.control.param == 71 )
					{
						resonance = midievent->data.control.value;
						freso = (resonance/140.0)*(1.0-fcutoff);
						printf( "Resonance: %i     \r", resonance );
						fflush( stdout );
					}
					else if( midievent->data.control.param == 73 )
					{
						attack = midievent->data.control.value;
						sattack = (attack+5.0)/800.0;
						printf( "Attack: %i     \r", attack );
						fflush( stdout );
					}
					else if( midievent->data.control.param == 7 )
					{
						volume = midievent->data.control.value;
						printf( "Volume: %i     \r", volume );
						fflush( stdout );
					}
					else if( ( midievent->data.control.param == 64 ) || ( midievent->data.control.param == 1 ) )
					{
						sustain = midievent->data.control.value;
						ssustain = 0.6+pow( sustain/127.0, 0.4)*0.4;
						printf( "Sustain: %i    \r", sustain );
						fflush( stdout );
					}
				}
				
				snd_seq_free_event( midievent );
			}
			while( snd_seq_event_input_pending( seqport, 0 ) > 0 );
		}
	}

	free( pfd );
	snd_seq_delete_port( seqport, midiport );
	snd_seq_close( seqport );
	
	jack_deactivate( jackClient );

	puts( "Freeing data" );
	for( note=0; note<NUMNOTES; note++ )
	{
		free( strings[note] );
	}
	free( tempstring );

	jack_port_unregister( jackClient, outport );
	jack_client_close( jackClient );

	return 0;
}
int main (int argc, char *argv[]) {

    int nfds, seq_nfds, l1;
    //int key;
    //key=0;
    char *hwdevice;
    struct pollfd *pfds;
/*
    if (argc < 2) {
        fprintf(stderr, "LinzerSchnitteMIDI <hw:0,0,1> <attack> <decay> <sustain> <release>\n"); 
        exit(1);
    }
*/
    initscr();				  /* start the curses setup */
    atexit(do_endwin);
    keypad(stdscr, TRUE);
    noecho();
    scrollok(stdscr, TRUE);
    printw("Welcome to LinzerSchnitte\n");
    refresh();
    start_color();	
    init_pair(1, COLOR_RED, COLOR_BLACK); /* end the curses setup */

/* Set default */    
    hwdevice = "hw:0,0,1";
    attack = 0.001;
    decay = 0.001;
    sustain = 1;
    release = 0.001;	
    
    if (argc > 1) {
    	hwdevice = argv[1];
    }

/*    attack = atof(argv[2]);
    decay = atof(argv[3]);
    sustain = atof(argv[4]);
    release = atof(argv[5]);
*/  
    buf = (short *) malloc (2 * sizeof (short) * BUFSIZE);
    playback_handle = open_pcm(hwdevice);
    seq_handle = open_seq();
    seq_nfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
    nfds = snd_pcm_poll_descriptors_count (playback_handle);
    pfds = (struct pollfd *)alloca(sizeof(struct pollfd) * (seq_nfds + nfds));
    snd_seq_poll_descriptors(seq_handle, pfds, seq_nfds, POLLIN);
    snd_pcm_poll_descriptors (playback_handle, pfds+seq_nfds, nfds);
    connect2MidiThroughPort(seq_handle);
    for (l1 = 0; l1 < POLY; note_active[l1++] = 0);
    while (1) {
	if (poll (pfds, seq_nfds + nfds, 1000) > 0) {
            for (l1 = 0; l1 < seq_nfds; l1++) {
               if (pfds[l1].revents > 0) midi_callback();
            }
            for (l1 = seq_nfds; l1 < seq_nfds + nfds; l1++) {
                if (pfds[l1].revents > 0) {
                    if (playback_callback(BUFSIZE) < BUFSIZE) {
                        fprintf (stderr, "xrun ! increase buffer \n");
                        snd_pcm_prepare(playback_handle);
                    }
                }
            }
        }
    }
    snd_pcm_close (playback_handle);
    snd_seq_close (seq_handle);
    free(buf);
    return (0);
}
예제 #25
0
void
mastermidibus::init (int ppqn)
{
#ifdef SEQ64_HAVE_LIBASOUND
    snd_seq_client_info_t * cinfo;          /* client info */
    snd_seq_port_info_t * pinfo;            /* port info   */
    snd_seq_client_info_alloca(&cinfo);
    snd_seq_client_info_set_client(cinfo, -1);
    if (rc().manual_alsa_ports())
    {
        /*
         * Output busses
         */

        int num_buses = SEQ64_ALSA_OUTPUT_BUSS_MAX;
        for (int i = 0; i < num_buses; ++i)
        {
            if (not_nullptr(m_buses_out[i]))
            {
                delete m_buses_out[i];
                errprintf("mmbus::init() manual: m_buses_out[%d] not null\n", i);
            }
            m_buses_out[i] = new midibus
            (
                snd_seq_client_id(m_alsa_seq), m_alsa_seq, i+1, m_queue
            );
            m_buses_out[i]->init_out_sub();
            m_buses_out_active[i] = m_buses_out_init[i] = true;
        }
        m_num_out_buses = num_buses;
        if (not_nullptr(m_buses_in[0]))
        {
            delete m_buses_in[0];
            errprint("mmbus::init() manual: m_buses_[0] not null");
        }

        /*
         * Input buss.  Only the first element is set up.  The rest are used
         * only for non-manual ALSA ports in the else-class below.
         */

        m_num_in_buses = 1;
        m_buses_in[0] = new midibus
        (
            snd_seq_client_id(m_alsa_seq), m_alsa_seq, m_num_in_buses, m_queue
        );
        m_buses_in[0]->init_in_sub();
        m_buses_in_active[0] = m_buses_in_init[0] = true;
    }
    else
    {
        /*
         * While the next client for the sequencer is available, get the client
         * from cinfo.  Fill pinfo.
         */

        while (snd_seq_query_next_client(m_alsa_seq, cinfo) >= 0)
        {
            int client = snd_seq_client_info_get_client(cinfo);
            snd_seq_port_info_alloca(&pinfo);           /* will fill pinfo */
            snd_seq_port_info_set_client(pinfo, client);
            snd_seq_port_info_set_port(pinfo, -1);
            while (snd_seq_query_next_port(m_alsa_seq, pinfo) >= 0)
            {
                /*
                 * While the next port is available, get its capability.
                 */

                int cap = snd_seq_port_info_get_capability(pinfo);
                if
                (
                    ALSA_CLIENT_CHECK(pinfo) &&
                    snd_seq_port_info_get_client(pinfo) != SND_SEQ_CLIENT_SYSTEM
                )
                {
                    /*
                     * Output busses:
                     *
                     * Why are we doing the ALSA client check again here?
                     * Because it could be altered in the if-clause above.
                     */

                    if (CAP_WRITE(cap) && ALSA_CLIENT_CHECK(pinfo))
                    {
                        if (not_nullptr(m_buses_out[m_num_out_buses]))
                        {
                            delete m_buses_out[m_num_out_buses];
                            errprintf
                            (
                                "mmbus::init(): m_buses_out[%d] not null\n",
                                m_num_out_buses
                            );
                        }
                        m_buses_out[m_num_out_buses] = new midibus
                        (
                            snd_seq_client_id(m_alsa_seq),
                            snd_seq_port_info_get_client(pinfo),
                            snd_seq_port_info_get_port(pinfo), m_alsa_seq,
                            snd_seq_client_info_get_name(cinfo),
                            snd_seq_port_info_get_name(pinfo),
                            m_num_out_buses, m_queue
                        );
                        if (m_buses_out[m_num_out_buses]->init_out())
                        {
                            m_buses_out_active[m_num_out_buses] = true;
                            m_buses_out_init[m_num_out_buses] = true;
                        }
                        else
                            m_buses_out_init[m_num_out_buses] = true;

                        ++m_num_out_buses;
                    }

                    /*
                     * Input busses
                     */

                    if (CAP_READ(cap) && ALSA_CLIENT_CHECK(pinfo)) /* inputs */
                    {
                        if (not_nullptr(m_buses_in[m_num_in_buses]))
                        {
                            delete m_buses_in[m_num_in_buses];
                            errprintf
                            (
                                "mmbus::init(): m_buses_in[%d] not null\n",
                                m_num_in_buses
                            );
                        }
                        m_buses_in[m_num_in_buses] = new midibus
                        (
                            snd_seq_client_id(m_alsa_seq),
                            snd_seq_port_info_get_client(pinfo),
                            snd_seq_port_info_get_port(pinfo), m_alsa_seq,
                            snd_seq_client_info_get_name(cinfo),
                            snd_seq_port_info_get_name(pinfo),
                            m_num_in_buses, m_queue
                        );
                        m_buses_in_active[m_num_in_buses] =
                            m_buses_in_init[m_num_in_buses] = true;

                        ++m_num_in_buses;
                    }
                }
            }
        }                                       /* end loop for clients */
    }
    set_beats_per_minute(m_beats_per_minute);
    set_ppqn(ppqn);

    /*
     * Get the number of MIDI input poll file descriptors.  Allocate the
     * poll-descriptors array.  Then get the input poll-descriptors into the
     * array
     */

    m_num_poll_descriptors = snd_seq_poll_descriptors_count(m_alsa_seq, POLLIN);
    m_poll_descriptors = new pollfd[m_num_poll_descriptors];
    snd_seq_poll_descriptors
    (
        m_alsa_seq, m_poll_descriptors, m_num_poll_descriptors, POLLIN
    );
    set_sequence_input(false, nullptr);

    /* Set the input and output buffer sizes */

    snd_seq_set_output_buffer_size(m_alsa_seq, c_midibus_output_size);
    snd_seq_set_input_buffer_size(m_alsa_seq, c_midibus_input_size);
    m_bus_announce = new midibus
    (
        snd_seq_client_id(m_alsa_seq),
        SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE,
        m_alsa_seq, "system", "announce",   // was "annouce" ca 2016-04-03
        0, m_queue
    );
    m_bus_announce->set_input(true);
    for (int i = 0; i < m_num_out_buses; ++i)
        set_clock(i, m_init_clock[i]);

    for (int i = 0; i < m_num_in_buses; ++i)
        set_input(i, m_init_input[i]);

#endif  // SEQ64_HAVE_LIBASOUND
}
예제 #26
0
파일: midibus.cpp 프로젝트: vext01/seq24
void
mastermidibus::init( )
{
    
    /* client info */
    snd_seq_client_info_t *cinfo;
    /* port info */
    snd_seq_port_info_t *pinfo;

    int client;

    snd_seq_client_info_alloca(&cinfo);
    snd_seq_client_info_set_client(cinfo, -1);

    //printf( "global_ports %d\n", global_manual_alsa_ports );
    
    if ( global_manual_alsa_ports )
    {

        int num_buses = 16;
        
        for( int i=0; i<num_buses; ++i )
        {

            m_buses_out[i] = 
                new midibus( snd_seq_client_id( m_alsa_seq ), m_alsa_seq, i+1, m_queue );

            m_buses_out[i]->init_out_sub();
            m_buses_out_active[i] = true;		
            m_buses_out_init[i] = true;
        }

        m_num_out_buses = num_buses;

        /* only one in */
        m_buses_in[0] = 
            new midibus( snd_seq_client_id( m_alsa_seq ),
                    m_alsa_seq,
                    m_num_in_buses, m_queue);

        m_buses_in[0]->init_in_sub();
        m_buses_in_active[0] = true;	
        m_buses_in_init[0] = true;
        m_num_in_buses = 1;


    }
    else 
    {
        /* while the next client one the sequencer is avaiable */
        while (snd_seq_query_next_client(m_alsa_seq, cinfo) >= 0){

            /* get client from cinfo */
            client = snd_seq_client_info_get_client(cinfo);

            /* fill pinfo */
            snd_seq_port_info_alloca(&pinfo);
            snd_seq_port_info_set_client(pinfo, client);
            snd_seq_port_info_set_port(pinfo, -1);

            /* while the next port is avail */
            while (snd_seq_query_next_port(m_alsa_seq, pinfo) >= 0 ){

                /* get its capability */
                int cap =  snd_seq_port_info_get_capability(pinfo);

                if ( snd_seq_client_id( m_alsa_seq ) != snd_seq_port_info_get_client(pinfo) &&
                        snd_seq_port_info_get_client(pinfo) != SND_SEQ_CLIENT_SYSTEM){

                    /* the outs */
                    if ( (cap & SND_SEQ_PORT_CAP_SUBS_WRITE) != 0 &&
                            snd_seq_client_id( m_alsa_seq ) != snd_seq_port_info_get_client(pinfo)){

                        m_buses_out[m_num_out_buses] = 
                            new midibus( snd_seq_client_id( m_alsa_seq ),
                                    snd_seq_port_info_get_client(pinfo),
                                    snd_seq_port_info_get_port(pinfo),
                                    m_alsa_seq,
                                    snd_seq_client_info_get_name(cinfo),
                                    snd_seq_port_info_get_name(pinfo),
                                    m_num_out_buses, m_queue );

                        if ( m_buses_out[m_num_out_buses]->init_out() ){
                            m_buses_out_active[m_num_out_buses] = true;		
                            m_buses_out_init[m_num_out_buses] = true;
                        } else {
                            m_buses_out_init[m_num_out_buses] = true;	
                        }

                        m_num_out_buses++;
                    }	

                    /* the ins */
                    if ( (cap & SND_SEQ_PORT_CAP_SUBS_READ) != 0 &&
                            snd_seq_client_id( m_alsa_seq ) != snd_seq_port_info_get_client(pinfo)){

                        m_buses_in[m_num_in_buses] = 
                            new midibus( snd_seq_client_id( m_alsa_seq ),
                                    snd_seq_port_info_get_client(pinfo),
                                    snd_seq_port_info_get_port(pinfo),
                                    m_alsa_seq,
                                    snd_seq_client_info_get_name(cinfo),
                                    snd_seq_port_info_get_name(pinfo),
                                    m_num_in_buses, m_queue);

                        //if ( m_buses_in[m_num_in_buses]->init_in() ){
                        m_buses_in_active[m_num_in_buses] = true;	
                        m_buses_in_init[m_num_in_buses] = true;
                        //} else {
                        //m_buses_in_init[m_num_in_buses] = true;	
                        //}
                        m_num_in_buses++;
                    }	
                }
            }

        } /* end loop for clients */
    }

    set_bpm( c_bpm );
    set_ppqn( c_ppqn );

    /* midi input */
    /* poll descriptors */

    /* get number of file descriptors */
    m_num_poll_descriptors = snd_seq_poll_descriptors_count(m_alsa_seq, POLLIN);

    /* allocate into */
    m_poll_descriptors = new pollfd[m_num_poll_descriptors];

    /* get descriptors */
    snd_seq_poll_descriptors(m_alsa_seq,  
            m_poll_descriptors, 
            m_num_poll_descriptors, 
            POLLIN);

    set_sequence_input( false, NULL );

    /* sizes */
    snd_seq_set_output_buffer_size(m_alsa_seq, c_midibus_output_size ); 
    snd_seq_set_input_buffer_size(m_alsa_seq, c_midibus_input_size ); 


    m_bus_announce = 
        new midibus( snd_seq_client_id( m_alsa_seq ),
                SND_SEQ_CLIENT_SYSTEM,
                SND_SEQ_PORT_SYSTEM_ANNOUNCE,
                m_alsa_seq,
                "system","annouce",
                0, m_queue);

    m_bus_announce->set_input(true);   


    for ( int i=0; i<m_num_out_buses; i++ )
        set_clock(i,m_init_clock[i]);

    for ( int i=0; i<m_num_in_buses; i++ )
        set_input(i,m_init_input[i]);

    
}
예제 #27
0
파일: midibus.cpp 프로젝트: vext01/seq24
void 
mastermidibus::port_start( int a_client, int a_port )
{
    lock();
    
 
    
    /* client info */
    snd_seq_client_info_t *cinfo;
    snd_seq_client_info_alloca(&cinfo);
    snd_seq_get_any_client_info( m_alsa_seq, a_client, cinfo );  
    
    /* port info */
    snd_seq_port_info_t *pinfo;
    
    /* fill pinfo */
    snd_seq_port_info_alloca(&pinfo);
    snd_seq_get_any_port_info( m_alsa_seq, a_client, a_port, pinfo );  
    
    
    /* get its capability */
    int cap =  snd_seq_port_info_get_capability(pinfo);
    
    if ( snd_seq_client_id( m_alsa_seq ) != snd_seq_port_info_get_client(pinfo)){
        
        /* the outs */
        if ( (cap & (SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_WRITE ))
             == (SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_WRITE )
             && snd_seq_client_id( m_alsa_seq ) != snd_seq_port_info_get_client(pinfo)){


            bool replacement = false;
            int bus_slot = m_num_out_buses;
            
            for( int i=0; i< m_num_out_buses; i++ ){
                
                if( m_buses_out[i]->get_client() == a_client  &&
                    m_buses_out[i]->get_port() == a_port &&
                    m_buses_out_active[i] == false ){
                    
                    replacement = true;
                    bus_slot = i;
                }
            }
            
            m_buses_out[bus_slot] = 
                new midibus( snd_seq_client_id( m_alsa_seq ),
                             snd_seq_port_info_get_client(pinfo),
                             snd_seq_port_info_get_port(pinfo),
                             m_alsa_seq,
                             snd_seq_client_info_get_name(cinfo),
                             snd_seq_port_info_get_name(pinfo),
                             m_num_out_buses, m_queue );
            
            m_buses_out[bus_slot]->init_out();
            m_buses_out_active[bus_slot] = true;
            m_buses_out_init[bus_slot] = true;
            
            if ( !replacement ){
                m_num_out_buses++;
            }
        }	
        
        /* the ins */
        if ( (cap & (SND_SEQ_PORT_CAP_SUBS_READ | SND_SEQ_PORT_CAP_READ ))
             == (SND_SEQ_PORT_CAP_SUBS_READ | SND_SEQ_PORT_CAP_READ )
             && snd_seq_client_id( m_alsa_seq ) != snd_seq_port_info_get_client(pinfo)){
            
            bool replacement = false;
            int bus_slot = m_num_in_buses;

          
            
            for( int i=0; i< m_num_in_buses; i++ ){
                
                if( m_buses_in[i]->get_client() == a_client  &&
                    m_buses_in[i]->get_port() == a_port &&
                    m_buses_in_active[i] == false ){
                    
                    replacement = true;
                    bus_slot = i;
                }
            }

            //printf( "in [%d] [%d]\n", replacement, bus_slot );
            
            m_buses_in[bus_slot] = 
                new midibus( snd_seq_client_id( m_alsa_seq ),
                             snd_seq_port_info_get_client(pinfo),
                             snd_seq_port_info_get_port(pinfo),
                             m_alsa_seq,
                             snd_seq_client_info_get_name(cinfo),
                             snd_seq_port_info_get_name(pinfo),
                             m_num_in_buses, m_queue);
            
            //m_buses_in[bus_slot]->init_in();
            m_buses_in_active[bus_slot] = true;
            m_buses_in_init[bus_slot] = true;

            if ( !replacement ){            
                m_num_in_buses++;
            }
        }	
    }
    
    /* end loop for clients */
    
    
    /* midi input */
    /* poll descriptors */

    /* get number of file descriptors */
    m_num_poll_descriptors = snd_seq_poll_descriptors_count(m_alsa_seq, POLLIN);

    /* allocate into */
    m_poll_descriptors = new pollfd[m_num_poll_descriptors];
    
    /* get descriptors */
    snd_seq_poll_descriptors(m_alsa_seq,  
			     m_poll_descriptors, 
			     m_num_poll_descriptors, 
			     POLLIN);
    
    unlock();
}
예제 #28
0
/** new_aubio_alsa_seq_driver */
aubio_midi_driver_t*  new_aubio_alsa_seq_driver(//aubio_settings_t* settings, 
        handle_midi_event_func_t handler, void* data)
{
    int i, err;                     
    aubio_alsa_seq_driver_t* dev;   /**< object to return */
    pthread_attr_t attr;            /**< sequencer thread */
    int sched = SCHED_FIFO;         /**< default scheduling policy */
    struct sched_param priority;    /**< scheduling priority settings */
    int count;                      /**< number of MIDI file descriptors */
    struct pollfd *pfd = NULL;      /**< poll file descriptor array (copied in dev->pfd) */
    char* device = NULL;            /**< the device name */
    char* id = NULL;
    char full_id[64];
    char full_name[64];

    /* not much use doing anything */
    if (handler == NULL) {
        AUBIO_ERR( "Invalid argument");
        return NULL;
    }

    /* allocate the device */
    dev = AUBIO_NEW(aubio_alsa_seq_driver_t);
    if (dev == NULL) {
        AUBIO_ERR( "Out of memory");
        return NULL;
    }
    AUBIO_MEMSET(dev, 0, sizeof(aubio_alsa_seq_driver_t));
    dev->seq_port = -1;
    dev->driver.data = data;
    dev->driver.handler = handler;

    /* get the device name. if none is specified, use the default device. */
    //aubio_settings_getstr(settings, "midi.alsa_seq.device", &device);
    if (device == NULL) {
        device = "default";
    }

    /* open the sequencer INPUT only, non-blocking */
    //if ((err = snd_seq_open(&dev->seq_handle, device, SND_SEQ_OPEN_INPUT,
    if ((err = snd_seq_open(&dev->seq_handle, device, SND_SEQ_OPEN_DUPLEX,
                    SND_SEQ_NONBLOCK)) < 0) {
        AUBIO_ERR( "Error opening ALSA sequencer");
        goto error_recovery;
    }

    /* get # of MIDI file descriptors */
    count = snd_seq_poll_descriptors_count(dev->seq_handle, POLLIN);
    if (count > 0) {        /* make sure there are some */
        pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count);
        dev->pfd = AUBIO_MALLOC(sizeof (struct pollfd) * count);
        /* grab file descriptor POLL info structures */
        count = snd_seq_poll_descriptors(dev->seq_handle, pfd, count, POLLIN);
    }

    for (i = 0; i < count; i++) {        /* loop over file descriptors */
        /* copy the input FDs */
        if (pfd[i].events & POLLIN) { /* use only the input FDs */
            dev->pfd[dev->npfd].fd = pfd[i].fd;
            dev->pfd[dev->npfd].events = POLLIN; 
            dev->pfd[dev->npfd].revents = 0; 
            dev->npfd++;
        }
    }
    AUBIO_FREE(pfd);

    //aubio_settings_getstr(settings, "midi.alsa_seq.id", &id);

    if (id != NULL) {
        if (AUBIO_STRCMP(id, "pid") == 0) {
            snprintf(full_id, 64, "aubio (%d)", getpid());
            snprintf(full_name, 64, "aubio_port (%d)", getpid());
        } else {
            snprintf(full_id, 64, "aubio (%s)", id);
            snprintf(full_name, 64, "aubio_port (%s)", id);
        }
    } else {
        snprintf(full_id, 64, "aubio");
        snprintf(full_name, 64, "aubio_port");
    }

    /* set the client name */
    snd_seq_set_client_name (dev->seq_handle, full_id);

    if ((dev->seq_port = snd_seq_create_simple_port (dev->seq_handle,
                    full_name,
                    SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE |
                    SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ | 
                    SND_SEQ_PORT_CAP_DUPLEX,
                    SND_SEQ_PORT_TYPE_APPLICATION)) < 0)
    {
        AUBIO_ERR( "Error creating ALSA sequencer port");
        goto error_recovery;
    }

    dev->status = AUBIO_MIDI_READY;

    /* create the midi thread */
    if (pthread_attr_init(&attr)) {
        AUBIO_ERR( "Couldn't initialize midi thread attributes");
        goto error_recovery;
    }

    /* use fifo scheduling. if it fails, use default scheduling. */
    while (1) {
        err = pthread_attr_setschedpolicy(&attr, sched);
        if (err) {
            AUBIO_MSG( "Couldn't set high priority scheduling for the MIDI input");
            if (sched == SCHED_FIFO) {
                sched = SCHED_OTHER;
                continue;
            } else {
                AUBIO_ERR( "Couldn't set scheduling policy.");
                goto error_recovery;
            }
        }

        /* SCHED_FIFO will not be active without setting the priority */
        priority.sched_priority = (sched == SCHED_FIFO) ? ALSA_SEQ_SCHED_PRIORITY : 0;
        pthread_attr_setschedparam (&attr, &priority);

        err = pthread_create(&dev->thread, &attr, aubio_alsa_seq_run, (void*) dev);
        if (err) {
            AUBIO_ERR( "Couldn't set high priority scheduling for the MIDI input");
            if (sched == SCHED_FIFO) {
                sched = SCHED_OTHER;
                continue;
            } else {
                //AUBIO_LOG(AUBIO_PANIC, "Couldn't create the midi thread.");
                AUBIO_ERR( "Couldn't create the midi thread.");
                goto error_recovery;
            }
        }
        break;
    }
    return (aubio_midi_driver_t*) dev;


error_recovery:
    del_aubio_alsa_seq_driver((aubio_midi_driver_t*) dev);
    return NULL;
}
예제 #29
0
void MidiAlsaSeq::run()
{
	// watch the pipe and sequencer input events
	int pollfd_count = snd_seq_poll_descriptors_count( m_seqHandle,
								POLLIN );
	struct pollfd * pollfd_set = new struct pollfd[pollfd_count + 1];
	snd_seq_poll_descriptors( m_seqHandle, pollfd_set + 1, pollfd_count,
								POLLIN );
	pollfd_set[0].fd = m_pipe[0];
	pollfd_set[0].events = POLLIN;
	++pollfd_count;

	while( m_quit == false )
	{
		int pollRet = poll( pollfd_set, pollfd_count, EventPollTimeOut );
		if( pollRet == 0 )
		{
			continue;
		}
		else if( pollRet == -1 )
		{
			// gdb may interrupt the poll
			if( errno == EINTR )
			{
				continue;
			}
			qCritical( "error while polling ALSA sequencer handle" );
			break;
		}
		// shutdown?
		if( m_quit )
		{
			break;
		}

		m_seqMutex.lock();

		// while event queue is not empty
		while( snd_seq_event_input_pending( m_seqHandle, true ) > 0 )
		{
			snd_seq_event_t * ev;
			if( snd_seq_event_input( m_seqHandle, &ev ) < 0 )
			{
				m_seqMutex.unlock();

				qCritical( "error while fetching MIDI event from sequencer" );
				break;
			}
			m_seqMutex.unlock();

			snd_seq_addr_t * source = NULL;
			MidiPort * dest = NULL;
			for( int i = 0; i < m_portIDs.size(); ++i )
			{
				if( m_portIDs.values()[i][0] == ev->dest.port )
				{
					dest = m_portIDs.keys()[i];
				}
				if( ( m_portIDs.values()[i][1] != -1 &&
						m_portIDs.values()[i][1] == ev->source.port ) ||
							m_portIDs.values()[i][0] == ev->source.port )
				{
					source = &ev->source;
				}
			}

			if( dest == NULL )
			{
				continue;
			}

			switch( ev->type )
			{
				case SND_SEQ_EVENT_NOTEON:
					dest->processInEvent( MidiEvent( MidiNoteOn,
								ev->data.note.channel,
								ev->data.note.note -
								KeysPerOctave,
								ev->data.note.velocity,
								source
								),
							MidiTime( ev->time.tick ) );
					break;

				case SND_SEQ_EVENT_NOTEOFF:
					dest->processInEvent( MidiEvent( MidiNoteOff,
								ev->data.note.channel,
								ev->data.note.note -
								KeysPerOctave,
								ev->data.note.velocity,
								source
								),
							MidiTime( ev->time.tick) );
					break;

				case SND_SEQ_EVENT_KEYPRESS:
					dest->processInEvent( MidiEvent(
									MidiKeyPressure,
								ev->data.note.channel,
								ev->data.note.note -
								KeysPerOctave,
								ev->data.note.velocity,
								source
								), MidiTime() );
					break;

				case SND_SEQ_EVENT_CONTROLLER:
					dest->processInEvent( MidiEvent(
								MidiControlChange,
							ev->data.control.channel,
							ev->data.control.param,
							ev->data.control.value, source ),
									MidiTime() );
					break;

				case SND_SEQ_EVENT_PGMCHANGE:
					dest->processInEvent( MidiEvent(
								MidiProgramChange,
							ev->data.control.channel,
							ev->data.control.param,
							ev->data.control.value, source ),
									MidiTime() );
					break;

				case SND_SEQ_EVENT_CHANPRESS:
					dest->processInEvent( MidiEvent(
								MidiChannelPressure,
							ev->data.control.channel,
							ev->data.control.param,
							ev->data.control.value, source ),
									MidiTime() );
					break;

				case SND_SEQ_EVENT_PITCHBEND:
					dest->processInEvent( MidiEvent( MidiPitchBend,
							ev->data.control.channel,
							ev->data.control.value + 8192, 0, source ),
									MidiTime() );
					break;

				case SND_SEQ_EVENT_SENSING:
				case SND_SEQ_EVENT_CLOCK:
					break;

				default:
					fprintf( stderr,
						"ALSA-sequencer: unhandled input "
							"event %d\n", ev->type );
					break;
			}	// end switch

			m_seqMutex.lock();

		}	// end while

		m_seqMutex.unlock();

	}

	delete[] pollfd_set;
}
예제 #30
0
파일: midi.c 프로젝트: howard5888/wineT
static DWORD WINAPI midRecThread(LPVOID arg)
{
    int npfd;
    struct pollfd *pfd;

    TRACE("Thread startup\n");

    while(!end_thread) {
	TRACE("Thread loop\n");
	npfd = snd_seq_poll_descriptors_count(midiSeq, POLLIN);
	pfd = HeapAlloc(GetProcessHeap(), 0, npfd * sizeof(struct pollfd));
	snd_seq_poll_descriptors(midiSeq, pfd, npfd, POLLIN);

	/* Check if an event is present */
	if (poll(pfd, npfd, 250) < 0) {
	    HeapFree(GetProcessHeap(), 0, pfd);
	    continue;
	}

	/* Note: This definitely does not work.  
	 * while(snd_seq_event_input_pending(midiSeq, 0) > 0) {
	       snd_seq_event_t* ev;
	       snd_seq_event_input(midiSeq, &ev);
	       ....................
	       snd_seq_free_event(ev);
	   }*/

	do {
	    WORD wDevID;
	    snd_seq_event_t* ev;
	    snd_seq_event_input(midiSeq, &ev);
	    /* Find the target device */
	    for (wDevID = 0; wDevID < MIDM_NumDevs; wDevID++)
		if ( (ev->source.client == MidiInDev[wDevID].addr.client) && (ev->source.port == MidiInDev[wDevID].addr.port) )
		    break;
	    if ((wDevID == MIDM_NumDevs) || (MidiInDev[wDevID].state != 1))
		FIXME("Unexpected event received, type = %x from %d:%d\n", ev->type, ev->source.client, ev->source.port);
	    else {
		DWORD dwTime, toSend = 0;
		/* FIXME: Should use ev->time instead for better accuracy */
		dwTime = GetTickCount() - MidiInDev[wDevID].startTime;
		TRACE("Event received, type = %x, device = %d\n", ev->type, wDevID);
		switch(ev->type)
		{
		case SND_SEQ_EVENT_NOTEOFF:
		    toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_OFF | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_NOTEON:
		    toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_ON | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_KEYPRESS:
		    toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_PRESSURE | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_CONTROLLER: 
		    toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CONTROL | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_PITCHBEND:
		    toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_BENDER | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_PGMCHANGE:
		    toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_PGM_CHANGE | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_CHANPRESS:
		    toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CHANNEL_PRESSURE | ev->data.control.channel;
		    break;
		case SND_SEQ_EVENT_SYSEX:
		    {
			int len = ev->data.ext.len;
			LPBYTE ptr = (BYTE*) ev->data.ext.ptr;
			LPMIDIHDR lpMidiHdr;

			/* FIXME: Should handle sysex greater that a single buffer */
			EnterCriticalSection(&crit_sect);
			if ((lpMidiHdr = MidiInDev[wDevID].lpQueueHdr) != NULL) {
			    if (len <= lpMidiHdr->dwBufferLength) {
				lpMidiHdr->dwBytesRecorded = len;
				memcpy(lpMidiHdr->lpData, ptr, len);
				lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
				lpMidiHdr->dwFlags |= MHDR_DONE;
				MidiInDev[wDevID].lpQueueHdr = (LPMIDIHDR)lpMidiHdr->lpNext;
				if (MIDI_NotifyClient(wDevID, MIM_LONGDATA, (DWORD)lpMidiHdr, dwTime) != MMSYSERR_NOERROR)
				    WARN("Couldn't notify client\n");
			    } else
				FIXME("No enough space in the buffer to store sysex!\n");
			} else
			    FIXME("Sysex received but no buffer to store it!\n");
			LeaveCriticalSection(&crit_sect);
		    }
		    break;
		case SND_SEQ_EVENT_SENSING:
		    /* Noting to do */
		    break;
		default:
		    FIXME("Unhandled event received, type = %x\n", ev->type);
		    break;
		}
		if (toSend != 0) {
		    TRACE("Sending event %08lx (from %d %d)\n", toSend, ev->source.client, ev->source.port);
		    if (MIDI_NotifyClient(wDevID, MIM_DATA, toSend, dwTime) != MMSYSERR_NOERROR) {
			WARN("Couldn't notify client\n");
		    }
		}
	    }
	    snd_seq_free_event(ev);
	} while(snd_seq_event_input_pending(midiSeq, 0) > 0);
	
	HeapFree(GetProcessHeap(), 0, pfd);
    }
    return 0;
}