void SeqDriver::procEvents() { int l1; snd_seq_event_t *evIn, evOut; bool outOfRange = false; bool unmatched = false; MidiMap* mm; do { snd_seq_event_input(seq_handle, &evIn); emit midiEvent(evIn); unmatched = true; for(l1 = 0; l1 < midiMapList->count(); l1++) { mm = midiMapList->at(l1); if (mm->isMap(evIn)) { unmatched = false; mm->doMap(evIn, &evOut, &outOfRange); if (!outOfRange) { snd_seq_ev_set_subs(&evOut); snd_seq_ev_set_direct(&evOut); snd_seq_ev_set_source(&evOut, portid_out[mm->portOut]); snd_seq_event_output_direct(seq_handle, &evOut); } } } if (!discardUnmatched && unmatched) { snd_seq_ev_set_subs(evIn); snd_seq_ev_set_direct(evIn); snd_seq_ev_set_source(evIn, portid_out[portUnmatched]); snd_seq_event_output_direct(seq_handle, evIn); } } while (snd_seq_event_input_pending(seq_handle, 0) > 0); }
// This splits the Midi events from one channel to another two channels void Spliter::midievents(){ snd_seq_event_t *midievent; midievent=NULL; snd_seq_event_input(midi_in,&midievent); if (midievent==NULL) return; if ((midievent->type==SND_SEQ_EVENT_NOTEON)||(midievent->type==SND_SEQ_EVENT_NOTEOFF)){ int cmdchan=midievent->data.note.channel; if (cmdchan==Pchin){ snd_seq_ev_set_subs(midievent); snd_seq_ev_set_direct(midievent); if (midievent->data.note.note<Psplitpoint) { midievent->data.note.channel=Pchout1; int tmp=midievent->data.note.note; tmp+=Poct1*12;if (tmp>127) tmp=127;if (tmp<0) tmp=0; midievent->data.note.note=tmp; } else { midievent->data.note.channel=Pchout2; int tmp=midievent->data.note.note; tmp+=Poct2*12;if (tmp>127) tmp=127;if (tmp<0) tmp=0; midievent->data.note.note=tmp; }; snd_seq_event_output_direct(midi_out,midievent); } else { snd_seq_ev_set_subs(midievent); snd_seq_ev_set_direct(midievent); snd_seq_event_output_direct(midi_out,midievent); }; }; snd_seq_free_event(midievent); };
void qxgeditMidiDevice::sendSysex ( unsigned char *pSysex, unsigned short iSysex ) const { #ifdef CONFIG_DEBUG fprintf(stderr, "qxgeditMidiDevice::sendSysex(%p, %u)", pSysex, iSysex); fprintf(stderr, " sysex {"); for (unsigned short i = 0; i < iSysex; ++i) fprintf(stderr, " %02x", pSysex[i]); fprintf(stderr, " }\n"); #endif // Don't do anything else if engine // has not been activated... if (m_pAlsaSeq == NULL) return; // Initialize sequencer event... snd_seq_event_t ev; snd_seq_ev_clear(&ev); // Addressing... snd_seq_ev_set_source(&ev, m_iAlsaPort); snd_seq_ev_set_subs(&ev); // The event will be direct... snd_seq_ev_set_direct(&ev); // Just set SYSEX stuff and send it out.. ev.type = SND_SEQ_EVENT_SYSEX; snd_seq_ev_set_sysex(&ev, iSysex, pSysex); snd_seq_event_output_direct(m_pAlsaSeq, &ev); }
void aubio_midi_direct_output(aubio_midi_driver_t * d, aubio_midi_event_t * event) { aubio_alsa_seq_driver_t* dev = (aubio_alsa_seq_driver_t*) d; switch(event->type) { case NOTE_ON: ev.type = SND_SEQ_EVENT_NOTEON; ev.data.note.channel = event->channel; ev.data.note.note = event->param1; ev.data.note.velocity = event->param2; //AUBIO_ERR( "NOTE_ON %d\n", event->param1); break; case NOTE_OFF: ev.type = SND_SEQ_EVENT_NOTEOFF; ev.data.note.channel = event->channel; ev.data.note.note = event->param1; ev.data.note.velocity = event->param2; //AUBIO_ERR( "NOTE_OFF %d\n", event->param1); break; default: break; } if (ev.type == SND_SEQ_EVENT_NOTEOFF || ev.type == SND_SEQ_EVENT_NOTEON ) { snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); snd_seq_ev_set_source(&ev, dev->seq_port); snd_seq_event_output_direct(dev->seq_handle, &ev); } }
void rimshot_alsa_output_play_note (rimshot_alsa_output_t *output, int channel, int note, unsigned int velocity) { snd_seq_event_t ev; snd_seq_ev_clear (&ev); snd_seq_ev_set_source (&ev, output->port); snd_seq_ev_set_subs (&ev); snd_seq_ev_set_direct (&ev); snd_seq_ev_set_noteon (&ev, channel, note, velocity); snd_seq_event_output_direct (output->seq, &ev); }
void MidiQueue::enqueueMidiMessage(const snd_seq_event_type messageType, const int sourcePort, const snd_seq_tick_time_t& tick) { snd_seq_event_t event = {}; event.type = messageType; snd_seq_ev_schedule_tick(&event, _id, 1, tick); snd_seq_ev_set_source(&event, sourcePort); snd_seq_ev_set_subs(&event); int result = snd_seq_event_output_direct(_sequencer, &event); if (result < 0) { std::cerr << "MidiQueue::enqueueMidiMessage error:" << snd_strerror(result) << std::endl; } }
void synth_noteStop(synth_t * st,int num, int status) { snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_direct(&ev); snd_seq_ev_set_source(&ev, port_out_id); snd_seq_ev_set_subs(&ev); //usleep(100000); printf("synth_noteStop %d\n", st->runningNote[num]); snd_seq_ev_set_noteoff(&ev, st->channel, st->runningNote[num], st->velocity); snd_seq_event_output_direct(seq, &ev); snd_seq_drain_output(seq); }
static gboolean put_click (const DrumClick *click) { snd_seq_event_t ev; snd_seq_ev_clear (&ev); snd_seq_ev_set_source (&ev, out_port_id); snd_seq_ev_set_subs (&ev); snd_seq_ev_schedule_tick (&ev, queue_id, 0, click->tick); snd_seq_ev_set_note (&ev, 10, 24, click->velocity, 48); int err = snd_seq_event_output_direct (seq, &ev); return err >= 0; }
void synth_noteStart(synth_t * st,int num, int status) { snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_direct(&ev); snd_seq_ev_set_source(&ev, port_out_id); snd_seq_ev_set_subs(&ev); printf("synth_noteStart %d\n", st->btn2note[num]); int note = st->btn2note[num]+st->sharp+12*st->octaveUp-12*st->octaveDown; st->runningNote[num]=note; snd_seq_ev_set_noteon(&ev, st->channel, note, st->velocity); snd_seq_event_output_direct(seq, &ev); snd_seq_drain_output(seq); }
void sys_alsa_putmidimess(int portno, int a, int b, int c) { int channel; snd_seq_event_t ev; snd_seq_ev_clear(&ev); if (portno >= 0 && portno < alsa_nmidiout) { if (a >= 224) // pitchbend { channel = a-224; snd_seq_ev_set_pitchbend(&ev, channel, (((c<<7)|b)-8192)); /* b and c are already correct but alsa needs to recalculate them */ } else if (a >= 208) // touch { channel = a-208; snd_seq_ev_set_chanpress(&ev,channel,b); } else if (a >= 192) // program { channel = a-192; snd_seq_ev_set_pgmchange(&ev,channel,b); } else if (a >= 176) // controller { channel = a-176; snd_seq_ev_set_controller(&ev,channel,b,c); } else if (a >= 160) // polytouch { channel = a-160; snd_seq_ev_set_keypress(&ev,channel,b,c); } else if (a >= 144) // note { channel = a-144; if (c) snd_seq_ev_set_noteon(&ev,channel,b,c); else snd_seq_ev_set_noteoff(&ev,channel,b,c); } snd_seq_ev_set_direct(&ev); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_source(&ev,alsa_midioutfd[portno]); snd_seq_event_output_direct(midi_handle,&ev); } //post("%d %d %d\n",a,b,c); }
static PyObject * alsaseq_output(PyObject *self, PyObject *args) { snd_seq_event_t ev; static PyObject * data; if (!PyArg_ParseTuple(args, "(bbbb(ii)(bb)(bb)O)", &ev.type, &ev.flags, &ev.tag, &ev.queue, &ev.time.time.tv_sec, &ev.time.time.tv_nsec, &ev.source.client, &ev.source.port, &ev.dest.client, &ev.dest.port, &data )) return NULL; if (!seq_handle) { PyErr_SetString(PyExc_RuntimeError, "Must initialize module with alsaseq.client() before using it"); return NULL; } /* printf ( "event.type: %d\n", ev.type ); */ switch( ev.type ) { case SND_SEQ_EVENT_NOTE: case SND_SEQ_EVENT_NOTEON: case SND_SEQ_EVENT_NOTEOFF: case SND_SEQ_EVENT_KEYPRESS: if (!PyArg_ParseTuple( data, "bbbbi;data parameter should have 5 values", &ev.data.note.channel, &ev.data.note.note, &ev.data.note.velocity, &ev.data.note.off_velocity, &ev.data.note.duration)) return NULL; break; case SND_SEQ_EVENT_CONTROLLER: case SND_SEQ_EVENT_PGMCHANGE: case SND_SEQ_EVENT_CHANPRESS: case SND_SEQ_EVENT_PITCHBEND: if (!PyArg_ParseTuple( data, "bbbbii;data parameter should have 6 values", &ev.data.control.channel, &ev.data.control.unused[0], &ev.data.control.unused[1], &ev.data.control.unused[2], &ev.data.control.param, &ev.data.control.value )) return NULL; break; } /* If not a direct event, use the queue */ if ( ev.queue != SND_SEQ_QUEUE_DIRECT ) ev.queue = queue_id; /* Modify source port if out of bounds */ if ( ev.source.port < firstoutputport ) snd_seq_ev_set_source(&ev, firstoutputport ); else if ( ev.source.port > lastoutputport ) snd_seq_ev_set_source(&ev, lastoutputport ); /* Use subscribed ports, except if ECHO event */ if ( ev.type != SND_SEQ_EVENT_ECHO ) snd_seq_ev_set_subs(&ev); snd_seq_event_output_direct( seq_handle, &ev ); Py_INCREF(Py_None); return Py_None; }
// FUNCTIONS void JVlibForm::send_data(char * buf,int data_size) { snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_direct(&ev); ev.queue = SND_SEQ_QUEUE_DIRECT; ev.type = SND_SEQ_EVENT_CONTROLLER; ev.dest = ports[0]; ev.data.control.channel = buf[0]; if (data_size>1) ev.data.control.param = buf[1]; if (data_size==3) ev.data.control.value = buf[2]; snd_seq_ev_set_fixed(&ev); snd_seq_ev_set_direct(&ev); snd_seq_event_output_direct(seq, &ev); snd_seq_drain_output(seq); } // end send_data
bool sendMessageNow (const MidiMessage& message) { if (message.getRawDataSize() > maxEventSize) { maxEventSize = message.getRawDataSize(); snd_midi_event_free (midiParser); snd_midi_event_new ((size_t) maxEventSize, &midiParser); } snd_seq_event_t event; snd_seq_ev_clear (&event); long numBytes = (long) message.getRawDataSize(); const uint8* data = message.getRawData(); snd_seq_t* seqHandle = port.client->get(); bool success = true; while (numBytes > 0) { const long numSent = snd_midi_event_encode (midiParser, data, numBytes, &event); if (numSent <= 0) { success = numSent == 0; break; } numBytes -= numSent; data += numSent; snd_seq_ev_set_source (&event, 0); snd_seq_ev_set_subs (&event); snd_seq_ev_set_direct (&event); if (snd_seq_event_output_direct (seqHandle, &event) < 0) { success = false; break; } } snd_midi_event_reset_encode (midiParser); return success; }
/* Send sysex buffer (buffer must contain complete sysex msg w/ SYSEX & EOX) */ int midi_send_sysex(int port, void *buf, int buflen) { int err; snd_seq_event_t sendev; if (port >= MAX_PORTS) return -1; snd_seq_ev_clear(&sendev); snd_seq_ev_set_source(&sendev, ports[port]); snd_seq_ev_set_subs(&sendev); snd_seq_ev_set_sysex(&sendev, buflen, buf); snd_seq_ev_set_direct(&sendev); err = snd_seq_event_output_direct(seq, &sendev); if (err < 0) eprintf("Couldn't send MIDI sysex: %s\n", snd_strerror(err)); return err; }
/* takes an native event, encodes to alsa event, puts it in the queue */ void midibus::sysex( event *a_e24 ) { lock(); snd_seq_event_t ev; /* clear event */ snd_seq_ev_clear( &ev ); snd_seq_ev_set_priority( &ev, 1 ); /* set source */ snd_seq_ev_set_source(&ev, m_local_addr_port ); snd_seq_ev_set_subs(&ev); // its immediate snd_seq_ev_set_direct( &ev ); unsigned char *data = a_e24->get_sysex(); long data_size = a_e24->get_size(); for( long offset = 0; offset < data_size; offset += c_midibus_sysex_chunk ){ long data_left = data_size - offset; snd_seq_ev_set_sysex( &ev, min( data_left, c_midibus_sysex_chunk), &data[offset] ); /* pump it into the queue */ snd_seq_event_output_direct(m_seq, &ev); usleep(80000); flush(); } unlock(); }
void send_midi_rencoder(unsigned int i) { if (i>=max_midi_rencoders) return; struct midi_rencoder *midi_rencoder = midi_rencoders + i; if (midi_rencoder->enabled==0) return; if (rencoder_seq_handle!=NULL && midi_rencoder->midi_ctrl>0) { snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_direct(&ev); //snd_seq_ev_set_dest(&ev, 64, 0); /* send to 64:0 */ snd_seq_ev_set_subs(&ev); /* send to subscribers of source port */ snd_seq_ev_set_controller(&ev, midi_rencoder->midi_chan, midi_rencoder->midi_ctrl, midi_rencoder->value); snd_seq_event_output_direct(rencoder_seq_handle, &ev); //snd_seq_drain_output(rencoder_seq_handle); //printf("SEND MIDI CHAN %d, CTRL %d = %d\n",midi_rencoder->midi_chan,midi_rencoder->midi_ctrl,midi_rencoder->value); } else if (rencoder_lo_addr!=NULL && midi_rencoder->osc_path[0]) { lo_send(rencoder_lo_addr,midi_rencoder->osc_path, "i", midi_rencoder->value); //printf("SEND OSC %s => %d\n",midi_rencoder->osc_path,midi_rencoder->value); } }
void midibus::sysex (event * e24) { #ifdef SEQ64_HAVE_LIBASOUND automutex locker(m_mutex); snd_seq_event_t ev; snd_seq_ev_clear(&ev); /* clear event */ snd_seq_ev_set_priority(&ev, 1); snd_seq_ev_set_source(&ev, m_local_addr_port); /* set source */ snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); /* it's immediate */ /* * Replaced by a vector of midibytes: * * midibyte * data = e24->get_sysex(); * * This is a bit tricky, and relies on the standard property of * std::vector where all n elements of the vector are guaranteed to be * stored contiguously (in order to be accessible via random-access * iterators). */ event::SysexContainer & data = e24->get_sysex(); int data_size = e24->get_sysex_size(); for (int offset = 0; offset < data_size; offset += c_midibus_sysex_chunk) { int data_left = data_size - offset; snd_seq_ev_set_sysex ( &ev, min(data_left, c_midibus_sysex_chunk), &data[offset] ); snd_seq_event_output_direct(m_seq, &ev); /* pump into queue */ usleep(SEQ64_USLEEP_US); flush(); } #endif // SEQ64_HAVE_LIBASOUND }
void sys_alsa_putmidibyte(int portno, int byte) { static snd_midi_event_t *dev = NULL; int res; snd_seq_event_t ev; if (!dev) { snd_midi_event_new(ALSA_MAX_EVENT_SIZE, &dev); //assert(dev); snd_midi_event_init(dev); } snd_seq_ev_clear(&ev); res = snd_midi_event_encode_byte(dev, byte, &ev); if (res > 0 && ev.type != SND_SEQ_EVENT_NONE) { // got a complete event, output it snd_seq_ev_set_direct(&ev); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_source(&ev, alsa_midioutfd[portno]); snd_seq_event_output_direct(midi_handle, &ev); } if (res != 0) // reinitialize the parser snd_midi_event_init(dev); }
/************************************************************************** * modData [internal] */ static DWORD modData(WORD wDevID, DWORD dwParam) { BYTE evt = LOBYTE(LOWORD(dwParam)); BYTE d1 = HIBYTE(LOWORD(dwParam)); BYTE d2 = LOBYTE(HIWORD(dwParam)); TRACE("(%04X, %08lX);\n", wDevID, dwParam); if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID; if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE; if (midiSeq == NULL) { WARN("can't play !\n"); return MIDIERR_NODEVICE; } switch (MidiOutDev[wDevID].caps.wTechnology) { case MOD_SYNTH: case MOD_MIDIPORT: { int handled = 1; /* Assume event is handled */ snd_seq_event_t event; snd_seq_ev_clear(&event); snd_seq_ev_set_direct(&event); snd_seq_ev_set_source(&event, port_out); snd_seq_ev_set_dest(&event, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port); switch (evt & 0xF0) { case MIDI_CMD_NOTE_OFF: snd_seq_ev_set_noteoff(&event, evt&0x0F, d1, d2); break; case MIDI_CMD_NOTE_ON: snd_seq_ev_set_noteon(&event, evt&0x0F, d1, d2); break; case MIDI_CMD_NOTE_PRESSURE: snd_seq_ev_set_keypress(&event, evt&0x0F, d1, d2); break; case MIDI_CMD_CONTROL: snd_seq_ev_set_controller(&event, evt&0x0F, d1, d2); break; case MIDI_CMD_BENDER: snd_seq_ev_set_pitchbend(&event, evt&0x0F, ((WORD)d2 << 7 | (WORD)d1) - 0x2000); break; case MIDI_CMD_PGM_CHANGE: snd_seq_ev_set_pgmchange(&event, evt&0x0F, d1); break; case MIDI_CMD_CHANNEL_PRESSURE: snd_seq_ev_set_chanpress(&event, evt&0x0F, d1); break; case MIDI_CMD_COMMON_SYSEX: switch (evt & 0x0F) { case 0x00: /* System Exclusive, don't do it on modData, * should require modLongData*/ case 0x01: /* Undefined */ case 0x04: /* Undefined. */ case 0x05: /* Undefined. */ case 0x07: /* End of Exclusive. */ case 0x09: /* Undefined. */ case 0x0D: /* Undefined. */ handled = 0; break; case 0x06: /* Tune Request */ case 0x08: /* Timing Clock. */ case 0x0A: /* Start. */ case 0x0B: /* Continue */ case 0x0C: /* Stop */ case 0x0E: /* Active Sensing. */ /* FIXME: Is this function suitable for these purposes (and also Song Select and Song Position Pointer) */ snd_seq_ev_set_sysex(&event, 1, &evt); break; case 0x0F: /* Reset */ /* snd_seq_ev_set_sysex(&event, 1, &evt); this other way may be better */ { BYTE reset_sysex_seq[] = {MIDI_CMD_COMMON_SYSEX, 0x7e, 0x7f, 0x09, 0x01, 0xf7}; snd_seq_ev_set_sysex(&event, sizeof(reset_sysex_seq), reset_sysex_seq); } break; case 0x03: /* Song Select. */ { BYTE buf[2]; buf[0] = evt; buf[1] = d1; snd_seq_ev_set_sysex(&event, sizeof(buf), buf); } break; case 0x02: /* Song Position Pointer. */ { BYTE buf[3]; buf[0] = evt; buf[1] = d1; buf[2] = d2; snd_seq_ev_set_sysex(&event, sizeof(buf), buf); } break; } break; } if (handled) snd_seq_event_output_direct(midiSeq, &event); } break; default: WARN("Technology not supported (yet) %d !\n", MidiOutDev[wDevID].caps.wTechnology); return MMSYSERR_NOTENABLED; } return MMSYSERR_NOERROR; }
/************************************************************************** * modLongData [internal] */ static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize) { int len_add = 0; LPBYTE lpData, lpNewData = NULL; snd_seq_event_t event; TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize); /* Note: MS doc does not say much about the dwBytesRecorded member of the MIDIHDR structure * but it seems to be used only for midi input. * Taking a look at the WAVEHDR structure (which is quite similar) confirms this assumption. */ if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID; if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE; if (midiSeq == NULL) { WARN("can't play !\n"); return MIDIERR_NODEVICE; } lpData = (LPBYTE) lpMidiHdr->lpData; if (lpData == NULL) return MIDIERR_UNPREPARED; if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) return MIDIERR_UNPREPARED; if (lpMidiHdr->dwFlags & MHDR_INQUEUE) return MIDIERR_STILLPLAYING; lpMidiHdr->dwFlags &= ~MHDR_DONE; lpMidiHdr->dwFlags |= MHDR_INQUEUE; /* FIXME: MS doc is not 100% clear. Will lpData only contain system exclusive * data, or can it also contain raw MIDI data, to be split up and sent to * modShortData() ? * If the latest is true, then the following WARNing will fire up */ if (lpData[0] != 0xF0 || lpData[lpMidiHdr->dwBufferLength - 1] != 0xF7) { WARN("Alleged system exclusive buffer is not correct\n\tPlease report with MIDI file\n"); lpNewData = HeapAlloc(GetProcessHeap(), 0, lpMidiHdr->dwBufferLength + 2); } TRACE("dwBufferLength=%lu !\n", lpMidiHdr->dwBufferLength); TRACE(" %02X %02X %02X ... %02X %02X %02X\n", lpData[0], lpData[1], lpData[2], lpData[lpMidiHdr->dwBufferLength-3], lpData[lpMidiHdr->dwBufferLength-2], lpData[lpMidiHdr->dwBufferLength-1]); switch (MidiOutDev[wDevID].caps.wTechnology) { case MOD_FMSYNTH: /* FIXME: I don't think there is much to do here */ break; case MOD_MIDIPORT: if (lpData[0] != 0xF0) { /* Send start of System Exclusive */ len_add = 1; lpData[0] = 0xF0; memcpy(lpNewData, lpData, lpMidiHdr->dwBufferLength); WARN("Adding missing 0xF0 marker at the beginning of " "system exclusive byte stream\n"); } if (lpData[lpMidiHdr->dwBufferLength-1] != 0xF7) { /* Send end of System Exclusive */ memcpy(lpData + len_add, lpData, lpMidiHdr->dwBufferLength); lpNewData[lpMidiHdr->dwBufferLength + len_add - 1] = 0xF0; len_add++; WARN("Adding missing 0xF7 marker at the end of " "system exclusive byte stream\n"); } snd_seq_ev_clear(&event); snd_seq_ev_set_direct(&event); snd_seq_ev_set_source(&event, port_out); snd_seq_ev_set_dest(&event, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port); TRACE("client = %d port = %d\n", MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port); snd_seq_ev_set_sysex(&event, lpMidiHdr->dwBufferLength + len_add, lpNewData ? lpNewData : lpData); snd_seq_event_output_direct(midiSeq, &event); if (lpNewData) HeapFree(GetProcessHeap(), 0, lpData); break; default: WARN("Technology not supported (yet) %d !\n", MidiOutDev[wDevID].caps.wTechnology); return MMSYSERR_NOTENABLED; } lpMidiHdr->dwFlags &= ~MHDR_INQUEUE; lpMidiHdr->dwFlags |= MHDR_DONE; if (MIDI_NotifyClient(wDevID, MOM_DONE, (DWORD)lpMidiHdr, 0L) != MMSYSERR_NOERROR) { WARN("can't notify client !\n"); return MMSYSERR_INVALPARAM; } return MMSYSERR_NOERROR; }
int main(int argc, char **argv) { int i; int listen_port = -1; char *client_name = "net2alsamidi"; char *connect_client = NULL; int connect_port = -1; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--port") == 0) { if (++i == argc) usage(argv[0]); listen_port = atoi(argv[i]); } else if (strcmp(argv[i], "--name") == 0) { if (++i == argc) usage(argv[0]); client_name = argv[i]; } else if (strcmp(argv[i], "--connect") == 0) { if (++i == argc) usage(argv[0]); connect_client = argv[i]; if (++i == argc) usage(argv[0]); connect_port = atoi(argv[i]); } else { usage(argv[0]); } } if (listen_port > 0) { snd_seq_t *seq; int port; if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0) < 0) { fprintf(stderr, "Cannot open the ALSA sequencer.\n"); exit(1); } snd_seq_set_client_name(seq, client_name); port = snd_seq_create_simple_port(seq, "from NetMIDI client", SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); if ((connect_client != NULL) && (connect_port >= 0)) { int connect_client_id = -1; { snd_seq_client_info_t *client_info; snd_seq_client_info_malloc(&client_info); while (snd_seq_query_next_client(seq, client_info) == 0) { if (strcmp(snd_seq_client_info_get_name(client_info), connect_client) == 0) { connect_client_id = snd_seq_client_info_get_client(client_info); break; } } snd_seq_client_info_free(client_info); } if (connect_client_id < 0) connect_client_id = atoi(connect_client); snd_seq_connect_to(seq, port, connect_client_id, connect_port); } { int server_socket; struct sockaddr_in server_address; if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "Cannot start a NetMIDI server on port %d.\n", listen_port); exit(1); } server_address.sin_family = AF_INET; server_address.sin_port = htons(listen_port); server_address.sin_addr.s_addr = INADDR_ANY; if (bind(server_socket, (struct sockaddr *)(&server_address), sizeof(server_address)) < 0) { fprintf(stderr, "Cannot start a NetMIDI server on port %d.\n", listen_port); exit(1); } if (listen(server_socket, 1) < 0) { fprintf(stderr, "Cannot start a NetMIDI server on port %d.\n", listen_port); exit(1); } while (1) { int socket_to_client; if ((socket_to_client = accept(server_socket, NULL, NULL)) >= 0) { snd_midi_event_t *midi_event_parser; snd_seq_event_t *event; unsigned char buffer[BUFFER_SIZE]; int bytes_read; { char one = 1; setsockopt(socket_to_client, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); } snd_midi_event_new(BUFFER_SIZE, &midi_event_parser); while ((bytes_read = recv(socket_to_client, buffer, BUFFER_SIZE, 0)) > 0) { for (i = 0; i < bytes_read; i++) { if (snd_midi_event_encode_byte(midi_event_parser, buffer[i], event) == 1) { snd_seq_event_output_direct(seq, event); } } } snd_midi_event_free(midi_event_parser); close(socket_to_client); } } close(server_socket); } snd_seq_delete_simple_port(seq, port); snd_seq_close(seq); } else { usage(argv[0]); } return 0; }
void Udp2MidiThread::run() { QUdpSocket *udpSocket = new QUdpSocket(); bool bres = udpSocket->bind(PC_PORT); if( bres == false ) { printf("Could not bind to port %d!\n", PC_PORT); return; } forever { if (abort) { delete udpSocket; return; } if( udpSocket->waitForReadyRead(250) == true ) { // Receive from UDP QHostAddress from_address; int len = udpSocket->readDatagram((char*)midimsg, MAX_MIDI_MESSAGE_LENGTH, &from_address); if( len == -1 ) { printf("udp2midi: Error receiving data!\n"); } if( (len == 3) && (midimsg[0] == 0) && (midimsg[1] == 0) && (midimsg[2] == 0) ) { string from_ip = from_address.toString().toStdString(); printf("Keepalive from: %s\n", from_ip.c_str()); midi2udp->add_ip(from_ip); } else { // Send to MIDI printf("udp2midi: Sending event: "); for(int i=0; i<len; ++i) { printf("0x%x ", midimsg[i]); } printf("\n"); long res = snd_midi_event_encode(eventparser, midimsg, len, midi_event); if( res < 0) { printf("Error encoding midi event!\n"); } snd_midi_event_reset_encode(eventparser); if(midi_event->type == SND_SEQ_EVENT_NOTEON) { printf("udp2midi: Note on: %d, channel %d\n", midi_event->data.note.note, midi_event->data.control.channel); } else if(midi_event->type == SND_SEQ_EVENT_NOTEOFF){ printf("udp2midi: Note off: %d, channel %d\n", midi_event->data.note.note, midi_event->data.control.channel); } snd_seq_ev_set_subs(midi_event); snd_seq_ev_set_direct(midi_event); snd_seq_ev_set_source(midi_event, midi_out_port); snd_seq_event_output_direct(seq_handle, midi_event); snd_seq_free_event(midi_event); } } } }
void sys_alsa_putmidimess(int portno, int a, int b, int c) { if (portno >= 0 && portno < alsa_nmidiout) { snd_seq_event_t ev; snd_seq_ev_clear(&ev); int status = a & 0xf0; int channel = a & 0x0f; status = (status >= MIDI_SYSEX) ? status : (status & 0xf0); switch (status) { case MIDI_NOTEON: snd_seq_ev_set_noteon(&ev, channel, b, c); break; case MIDI_NOTEOFF: snd_seq_ev_set_noteoff(&ev, channel, b, c); break; case MIDI_POLYAFTERTOUCH: snd_seq_ev_set_chanpress(&ev, channel, b); break; case MIDI_CONTROLCHANGE: snd_seq_ev_set_controller(&ev, channel, b, c); break; case MIDI_PROGRAMCHANGE: snd_seq_ev_set_pgmchange(&ev, channel, b); break; case MIDI_AFTERTOUCH: snd_seq_ev_set_chanpress(&ev, channel, b); break; case MIDI_PITCHBEND: /* b and c are already correct but alsa needs to recalculate them */ snd_seq_ev_set_pitchbend(&ev, channel, (((c<<7)|b)-8192)); break; case MIDI_TIMECODE: ev.type = SND_SEQ_EVENT_QFRAME; snd_seq_ev_set_fixed(&ev); ev.data.raw8.d[0] = a & 0xff; /* status */ ev.data.raw8.d[1] = b & 0x7f; /* data */ break; case MIDI_SONGPOS: ev.type = SND_SEQ_EVENT_SONGPOS; snd_seq_ev_set_fixed(&ev); ev.data.raw8.d[0] = a & 0xff; /* status */ ev.data.raw8.d[1] = b & 0x7f; /* data */ ev.data.raw8.d[2] = c & 0x7f; /* data */ break; case MIDI_SONGSELECT: ev.type = SND_SEQ_EVENT_SONGSEL; snd_seq_ev_set_fixed(&ev); ev.data.raw8.d[0] = a & 0xff; /* status */ ev.data.raw8.d[1] = b & 0x7f; /* data */ break; default: bug("couldn't put alsa midi message"); break; } snd_seq_ev_set_direct(&ev); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_source(&ev, alsa_midioutfd[portno]); snd_seq_event_output_direct(midi_handle, &ev); } //post("%d %d %d\n", a, b, c); }
int main(int argc, char *argv[]) { int getopt_return; int option_index; int valid; snd_seq_t *seq_handle; int out_port; snd_seq_addr_t seq_addr; snd_seq_event_t ev; valid = 0; while (((getopt_return = getopt_long(argc, argv, "ha:p:c:b:n:o:", options, &option_index)) >= 0) && (valid < 2)) { switch(getopt_return) { case 'a': valid++; if (snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, "Error opening ALSA sequencer.\n"); exit(1); } snd_seq_set_client_name(seq_handle, "MidiSend"); if ((out_port = snd_seq_create_simple_port(seq_handle, "MidiSend", SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "Error creating sequencer port.\n"); exit(1); } snd_seq_parse_address(seq_handle, &seq_addr, optarg); snd_seq_connect_to(seq_handle, out_port, seq_addr.client, seq_addr.port); snd_seq_ev_clear(&ev); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); snd_seq_ev_set_source(&ev, out_port); break; case 'p': if (valid) { valid++; if (argc < 6) { fprintf(stderr, "\nMissing parameter(s): midisend --program <ch> <prg>\n\n"); } else { ev.data.control.channel = atoi(optarg); ev.type = SND_SEQ_EVENT_PGMCHANGE; ev.data.control.value = atoi(argv[optind]); } } break; case 'c': if (valid) { valid++; if (argc < 7) { fprintf(stderr, "\nMissing parameter(s): midisend --control <ch> <ctrl> <val>\n\n"); } else { ev.data.control.channel = atoi(optarg); ev.type = SND_SEQ_EVENT_CONTROLLER; ev.data.control.param = atoi(argv[optind]); ev.data.control.value = atoi(argv[optind + 1]); } } break; case 'b': if (valid) { valid++; if (argc < 6) { fprintf(stderr, "\nMissing parameter(s): midisend --bend <ch> <val>\n\n"); } else { ev.data.control.channel = atoi(optarg); ev.type = SND_SEQ_EVENT_PITCHBEND; ev.data.control.value = atoi(argv[optind]) - 8192; } } break; case 'n': if (valid) { valid++; if (argc < 8) { fprintf(stderr, "\nMissing parameter(s): midisend --note <ch> <on> <num> <vel>\n\n"); } else { ev.data.control.channel = atoi(optarg); ev.type = (atoi(argv[optind])) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF; ev.data.note.note = atoi(argv[optind + 1]); ev.data.note.velocity = atoi(argv[optind + 2]); } } break; case 'o': if (valid) { valid++; if (argc < 5) { fprintf(stderr, "\nMissing parameter(s): midisend --off <ch>\n\n"); } else { ev.data.control.channel = atoi(optarg); ev.type = SND_SEQ_EVENT_CONTROLLER; ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF; ev.data.control.value = 0; } } break; case 'h': valid = 3; printf("\nMidiSend 0.0.1\nWritten by Matthias Nagorni\n"); printf("(c)2004 SUSE Linux AG Nuremberg\n"); printf("Licensed under GNU General Public License\n\n"); printf("--alsa <port> ALSA Sequencer Port (e.g. 64:0)\n"); printf("--program <ch> <prg> Program Change\n"); printf("--control <ch> <ctrl> <val> Control Change\n"); printf("--bend <ch> <val> Pitch Bend (0..16383, center = 8192)\n"); printf("--note <ch> <on> <num> <vel> Note On (on=1) Note Off (on=0)\n"); printf("--off <ch> All Notes Off\n\n"); exit(EXIT_SUCCESS); } } if (valid < 2) { fprintf(stderr, "\nUsage: midisend PORT COMMAND PARAMETERS\n\n"); fprintf(stderr, "Type \'midisend -h\' for a list of valid commands.\n\n"); } else if (valid == 2) { snd_seq_event_output_direct(seq_handle, &ev); } }
void SendMidiCommand(int nIdPortOut, char *buf) { /* MIDI COMMANDS ------------------------------------------------------------------- name status param 1 param 2 ------------------------------------------------------------------- note off 0x80+C key # velocity note on 0x90+C key # velocity poly key pressure 0xA0+C key # pressure value control change 0xB0+C control # control value program change 0xC0+C program # -- mono key pressure 0xD0+C pressure value -- pitch bend 0xE0+C range (LSB) range (MSB) system 0xF0+C manufacturer model ------------------------------------------------------------------- C is the channel number, from 0 to 15; ------------------------------------------------------------------- source: http://ftp.ec.vanderbilt.edu/computermusic/musc216site/MIDI.Commands.html In this program the pitch bend range will be transmitter as one single 8-bit number. So the end result is that MIDI commands will be transmitted as 3 bytes, starting with the operation byte: buf[0] --> operation/channel buf[1] --> param1 buf[2] --> param2 (param2 not transmitted on program change or key press) snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_source(&ev, nIdPortOut); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); snd_seq_ev_set_noteoff(&ev, 0, note, 60); snd_seq_event_output(t_seq, &ev); */ snd_seq_event_t t_event; snd_seq_ev_clear(&t_event); // printf("Serial port: %u\n", nIdPortOut); snd_seq_ev_set_source(&t_event, nIdPortOutA); snd_seq_ev_set_subs(&t_event); snd_seq_ev_set_direct(&t_event); int operation, channel, param1, param2; operation = buf[0] & 0xF0; channel = buf[0] & 0x0F; param1 = buf[1]; param2 = buf[2]; switch (operation) { case 0x80: printf("OUT ==> 0x%x Note off 0x%x 0x%x 0x%x\n", operation, channel, param1, param2); snd_seq_ev_set_noteoff(&t_event, channel, param1, param2); break; case 0x90: printf("OUT ==> 0x%x Note on 0x%x 0x%x 0x%x\n", operation, channel, param1, param2); snd_seq_ev_set_noteon(&t_event, channel, param1, param2); break; case 0xA0: printf("OUT ==> 0x%x Pressure change 0x%x 0x%x 0x%x\n", operation, channel, param1, param2); snd_seq_ev_set_keypress(&t_event, channel, param1, param2); break; case 0xB0: printf("OUT ==> 0x%x Controller change 0x%x 0x%x 0x%x\n", operation, channel, param1, param2); snd_seq_ev_set_controller(&t_event, channel, param1, param2); break; case 0xC0: printf("OUT ==> 0x%x Program change 0x%x 0x%x 0x%x\n", operation, channel, param1); snd_seq_ev_set_pgmchange(&t_event, channel, param1); break; case 0xD0: printf("OUT ==> 0x%x Channel change 0x%x 0x%x 0x%x\n", operation, channel, param1); snd_seq_ev_set_chanpress(&t_event, channel, param1); break; case 0xE0: param1 = (param1 & 0x7F) + ((param2 & 0x7F) << 7); printf("OUT ==> 0x%x Pitch bend %03u %05i\n", operation, channel, param1); snd_seq_ev_set_pitchbend(&t_event, channel, param1 - 8192); // in alsa MIDI we want signed int break; /* Not implementing system commands (0xF0) */ default: printf("OUT 0x%x Unknown MIDI cmd %03u %03u %03u\n", operation, channel, param1, param2); break; } snd_seq_event_output_direct(t_seq, &t_event); //snd_seq_drain_output(t_seq); //snd_seq_event_output(t_seq, &t_event); }