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; }
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); }
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"; }
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; }
/* 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; }
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())); }
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; }
/* * 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); }
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 ); }
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); } } }
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"); }
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); }
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); } } }
// 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); } } }
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 ); }
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; }
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; }
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; }
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); } }
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); }
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 }
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]); }
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(); }
/** 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; }
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; }
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; }