void DeviceManager::scanDevices() { snd_seq_client_info_t *cinfo; snd_seq_port_info_t *pinfo; snd_seq_client_info_alloca(&cinfo); snd_seq_port_info_alloca(&pinfo); snd_seq_client_info_set_client(cinfo, -1); while (snd_seq_query_next_client(handle, cinfo) >= 0) { int client = snd_seq_client_info_get_client(cinfo); snd_seq_port_info_set_client(pinfo, client); snd_seq_port_info_set_port(pinfo, -1); while (snd_seq_query_next_port(handle, pinfo) >= 0) { Device *d = new Device(cinfo, pinfo); if(d->isValid()){ snd_seq_connect_from(handle, 0, d->clientId, d->portId); list.push_back(d); }else{ delete d; } } } D("Device list contain %d elements.", (int) list.size()); }
static int alsa_seqmidi_start(alsa_midi_t *m) { alsa_seqmidi_t *self = (alsa_seqmidi_t*) m; int err; debug_log("midi: start"); if (!self->seq) return -EBADF; if (self->keep_walking) return -EALREADY; snd_seq_connect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); snd_seq_drop_input(self->seq); add_existing_ports(self); update_ports(self); add_ports(&self->stream[PORT_INPUT]); add_ports(&self->stream[PORT_OUTPUT]); self->keep_walking = 1; if ((err = pthread_create(&self->port_thread, NULL, port_thread, self))) { self->keep_walking = 0; return -errno; } return 0; }
static void connect_ports(void) { int i, err; for (i = 0; i < port_count; ++i) { err = snd_seq_connect_from(seq, 0, ports[i].client, ports[i].port); if (err < 0) fatal("Cannot connect from port %d:%d - %s", ports[i].client, ports[i].port, snd_strerror(err)); } }
static PyObject * alsaseq_connectfrom(PyObject *self, PyObject *args) { int myport, dest_client, dest_port; if (!PyArg_ParseTuple(args, "iii", &myport, &dest_client, &dest_port )) return NULL; snd_seq_connect_from( seq_handle, myport, dest_client, dest_port); Py_INCREF(Py_None); return Py_None; }
void midi_open(void) { snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, 0); snd_seq_set_client_name(seq_handle, "LightOrgan8"); in_port = snd_seq_create_simple_port(seq_handle, "listen:in", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION); if( snd_seq_connect_from(seq_handle, in_port, THRUPORTCLIENT, THRUPORTPORT) == -1) { perror("Can't connect to thru port"); exit(-1); } }
int open_midi_device(struct GenesisMidiDevice *device) { if (device->open) return GenesisErrorInvalidState; if (snd_seq_connect_from(device->midi_hardware->seq, 0, device->client_id, device->port_id) < 0) return GenesisErrorOpeningMidiHardware; device->open = true; int set_index = device->midi_hardware->open_devices.length(); if (device->midi_hardware->open_devices.append(device)) { close_midi_device(device); return GenesisErrorNoMem; } genesis_midi_device_ref(device); device->set_index = set_index; return 0; }
static PyObject * alsaseq_connectfrom(PyObject *self, PyObject *args) { int myport, dest_client, dest_port; if (!PyArg_ParseTuple(args, "iii", &myport, &dest_client, &dest_port )) return NULL; if (!seq_handle) { PyErr_SetString(PyExc_RuntimeError, "Must initialize module with alsaseq.client() before using it"); return NULL; } snd_seq_connect_from( seq_handle, myport, dest_client, dest_port); Py_INCREF(Py_None); return Py_None; }
static PyObject *setup(PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "i", &dest_client_id)) return NULL; // open client err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); if (err < 0) RAISE("couldnt open sequencer connection\n"); // get client id my_client_id = snd_seq_client_id(seq); // create readable port for sending events readable_port = snd_seq_create_simple_port( seq, "my readable port", SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC); // create writable port for receiving events writable_port = snd_seq_create_simple_port( seq, "my writable port", SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC); // make subscription for sending events to device if (snd_seq_connect_to(seq, readable_port, dest_client_id, 0) < 0) RAISE("Unable to subscribe to MIDI port for writing.\n"); // make subscription for capturing events from midi device if (snd_seq_connect_from(seq, writable_port, dest_client_id, 0) < 0) RAISE("Unable to subscribe to MIDI port for reading.\n"); Py_INCREF(Py_None); return Py_None; }
int connect_to_alsa (struct a2j* self) { int error; void * thread_status; self->port_add = jack_ringbuffer_create(2 * MAX_PORTS * sizeof(snd_seq_addr_t)); if (self->port_add == NULL) { goto free_self; } self->port_del = jack_ringbuffer_create(2 * MAX_PORTS * sizeof(struct a2j_port *)); if (self->port_del == NULL) { goto free_ringbuffer_add; } if (!a2j_stream_init(self)) { goto free_ringbuffer_outbound; } if ((error = snd_seq_open(&self->seq, "hw", SND_SEQ_OPEN_DUPLEX, 0)) < 0) { a2j_error("failed to open alsa seq"); goto close_stream; } if ((error = snd_seq_set_client_name(self->seq, "midi_in")) < 0) { a2j_error("snd_seq_set_client_name() failed"); goto close_seq_client; } if ((self->port_id = snd_seq_create_simple_port( self->seq, "port", SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_WRITE #ifndef DEBUG |SND_SEQ_PORT_CAP_NO_EXPORT #endif ,SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { a2j_error("snd_seq_create_simple_port() failed"); goto close_seq_client; } if ((self->client_id = snd_seq_client_id(self->seq)) < 0) { a2j_error("snd_seq_client_id() failed"); goto close_seq_client; } if ((self->queue = snd_seq_alloc_queue(self->seq)) < 0) { a2j_error("snd_seq_alloc_queue() failed"); goto close_seq_client; } snd_seq_start_queue (self->seq, self->queue, 0); a2j_stream_attach (&self->stream); if ((error = snd_seq_nonblock(self->seq, 1)) < 0) { a2j_error("snd_seq_nonblock() failed"); goto close_seq_client; } snd_seq_drop_input (self->seq); a2j_add_ports(&self->stream); if (sem_init(&self->io_semaphore, 0, 0) < 0) { a2j_error("can't create IO semaphore"); goto close_jack_client; } g_keep_alsa_walking = true; if (pthread_create(&self->alsa_io_thread, NULL, alsa_input_thread, self) < 0) { a2j_error("cannot start ALSA input thread"); goto sem_destroy; } /* wake the poll loop in the alsa input thread so initial ports are fetched */ if ((error = snd_seq_connect_from (self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE)) < 0) { a2j_error("snd_seq_connect_from() failed"); goto join_io_thread; } return 0; g_keep_alsa_walking = false; /* tell alsa threads to stop */ snd_seq_disconnect_from(self->seq, self->port_id, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); join_io_thread: pthread_join(self->alsa_io_thread, &thread_status); sem_destroy: sem_destroy(&self->io_semaphore); close_jack_client: if ((error = jack_client_close(self->jack_client)) < 0) { a2j_error("Cannot close jack client"); } close_seq_client: snd_seq_close(self->seq); close_stream: a2j_stream_close(self); free_ringbuffer_outbound: jack_ringbuffer_free(self->outbound_events); jack_ringbuffer_free(self->port_del); free_ringbuffer_add: jack_ringbuffer_free(self->port_add); free_self: free(self); return -1; }
int create_midi_hardware(GenesisContext *context, const char *client_name, void (*events_signal)(struct MidiHardware *), void (*on_devices_change)(struct MidiHardware *), void *userdata, struct MidiHardware **out_midi_hardware) { *out_midi_hardware = nullptr; struct MidiHardware *midi_hardware = create_zero<MidiHardware>(); if (!midi_hardware) { destroy_midi_hardware(midi_hardware); return GenesisErrorNoMem; } midi_hardware->context = context; midi_hardware->on_buffer_overrun = default_on_buffer_overrun; midi_hardware->events_signal = events_signal; midi_hardware->on_devices_change = on_devices_change; midi_hardware->userdata = userdata; if (!(midi_hardware->mutex = os_mutex_create())) { destroy_midi_hardware(midi_hardware); return GenesisErrorNoMem; } if (snd_seq_open(&midi_hardware->seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) { destroy_midi_hardware(midi_hardware); return GenesisErrorOpeningMidiHardware; } if (snd_seq_set_client_name(midi_hardware->seq, client_name) < 0) { destroy_midi_hardware(midi_hardware); return GenesisErrorOpeningMidiHardware; } snd_seq_client_info_malloc(&midi_hardware->client_info); snd_seq_port_info_malloc(&midi_hardware->port_info); if (!midi_hardware->client_info || !midi_hardware->port_info) { destroy_midi_hardware(midi_hardware); return GenesisErrorNoMem; } if (snd_seq_create_simple_port(midi_hardware->seq, "genesis", SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION) < 0) { destroy_midi_hardware(midi_hardware); return GenesisErrorOpeningMidiHardware; } int err = midi_hardware_refresh(midi_hardware); if (err) { destroy_midi_hardware(midi_hardware); return err; } if (!midi_hardware->system_announce_device) { destroy_midi_hardware(midi_hardware); return GenesisErrorOpeningMidiHardware; } if (snd_seq_connect_from(midi_hardware->seq, 0, midi_hardware->system_announce_device->client_id, midi_hardware->system_announce_device->port_id) < 0) { destroy_midi_hardware(midi_hardware); return GenesisErrorOpeningMidiHardware; } if (snd_seq_get_client_info(midi_hardware->seq, midi_hardware->client_info) < 0) { destroy_midi_hardware(midi_hardware); return GenesisErrorOpeningMidiHardware; } midi_hardware->client_id = snd_seq_client_info_get_client(midi_hardware->client_info); if (snd_seq_connect_from(midi_hardware->seq, 0, midi_hardware->client_id, 0) < 0) { destroy_midi_hardware(midi_hardware); return GenesisErrorOpeningMidiHardware; } if ((err = os_thread_create(midi_thread, midi_hardware, false, &midi_hardware->thread))) { destroy_midi_hardware(midi_hardware); return err; } *out_midi_hardware = midi_hardware; return 0; }
/************************************************************************** * midOpen [internal] */ static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags) { TRACE("(%04X, %p, %08lX);\n", wDevID, lpDesc, dwFlags); if (lpDesc == NULL) { WARN("Invalid Parameter !\n"); return MMSYSERR_INVALPARAM; } /* FIXME : * how to check that content of lpDesc is correct ? */ if (wDevID >= MIDM_NumDevs) { WARN("wDevID too large (%u) !\n", wDevID); return MMSYSERR_BADDEVICEID; } if (MidiInDev[wDevID].state == -1) { WARN("device disabled\n"); return MIDIERR_NODEVICE; } if (MidiInDev[wDevID].midiDesc.hMidi != 0) { WARN("device already open !\n"); return MMSYSERR_ALLOCATED; } if ((dwFlags & MIDI_IO_STATUS) != 0) { WARN("No support for MIDI_IO_STATUS in dwFlags yet, ignoring it\n"); dwFlags &= ~MIDI_IO_STATUS; } if ((dwFlags & ~CALLBACK_TYPEMASK) != 0) { FIXME("Bad dwFlags\n"); return MMSYSERR_INVALFLAG; } if (midiOpenSeq(1) < 0) { return MMSYSERR_ERROR; } /* Connect our app port to the device port */ if (snd_seq_connect_from(midiSeq, port_in, MidiInDev[wDevID].addr.client, MidiInDev[wDevID].addr.port) < 0) return MMSYSERR_NOTENABLED; TRACE("input port connected %d %d %d\n",port_in,MidiInDev[wDevID].addr.client,MidiInDev[wDevID].addr.port); if (numStartedMidiIn++ == 0) { end_thread = 0; hThread = CreateThread(NULL, 0, midRecThread, NULL, 0, NULL); if (!hThread) { numStartedMidiIn = 0; WARN("Couldn't create thread for midi-in\n"); midiCloseSeq(); return MMSYSERR_ERROR; } SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); TRACE("Created thread for midi-in\n"); } MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK); MidiInDev[wDevID].lpQueueHdr = NULL; MidiInDev[wDevID].dwTotalPlayed = 0; MidiInDev[wDevID].bufsize = 0x3FFF; MidiInDev[wDevID].midiDesc = *lpDesc; MidiInDev[wDevID].state = 0; MidiInDev[wDevID].incLen = 0; MidiInDev[wDevID].startTime = 0; if (MIDI_NotifyClient(wDevID, MIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) { WARN("can't notify client !\n"); return MMSYSERR_INVALPARAM; } return MMSYSERR_NOERROR; }
//============================================================================== static snd_seq_t* iterateDevices (const bool forInput, StringArray& deviceNamesFound, const int deviceIndexToOpen) { snd_seq_t* returnedHandle = 0; snd_seq_t* seqHandle; if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT : SND_SEQ_OPEN_OUTPUT, 0) == 0) { snd_seq_system_info_t* systemInfo; snd_seq_client_info_t* clientInfo; if (snd_seq_system_info_malloc (&systemInfo) == 0) { if (snd_seq_system_info (seqHandle, systemInfo) == 0 && snd_seq_client_info_malloc (&clientInfo) == 0) { int numClients = snd_seq_system_info_get_cur_clients (systemInfo); while (--numClients >= 0 && returnedHandle == 0) { if (snd_seq_query_next_client (seqHandle, clientInfo) == 0) { snd_seq_port_info_t* portInfo; if (snd_seq_port_info_malloc (&portInfo) == 0) { int numPorts = snd_seq_client_info_get_num_ports (clientInfo); const int client = snd_seq_client_info_get_client (clientInfo); snd_seq_port_info_set_client (portInfo, client); snd_seq_port_info_set_port (portInfo, -1); while (--numPorts >= 0) { if (snd_seq_query_next_port (seqHandle, portInfo) == 0 && (snd_seq_port_info_get_capability (portInfo) & (forInput ? SND_SEQ_PORT_CAP_READ : SND_SEQ_PORT_CAP_WRITE)) != 0) { deviceNamesFound.add (snd_seq_client_info_get_name (clientInfo)); if (deviceNamesFound.size() == deviceIndexToOpen + 1) { const int sourcePort = snd_seq_port_info_get_port (portInfo); const int sourceClient = snd_seq_client_info_get_client (clientInfo); if (sourcePort != -1) { snd_seq_set_client_name (seqHandle, forInput ? "Juce Midi Input" : "Juce Midi Output"); const int portId = snd_seq_create_simple_port (seqHandle, forInput ? "Juce Midi In Port" : "Juce Midi Out Port", forInput ? (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_TYPE_MIDI_GENERIC); snd_seq_connect_from (seqHandle, portId, sourceClient, sourcePort); returnedHandle = seqHandle; } } } } snd_seq_port_info_free (portInfo); } } } snd_seq_client_info_free (clientInfo); } snd_seq_system_info_free (systemInfo); } if (returnedHandle == 0) snd_seq_close (seqHandle); } deviceNamesFound.appendNumbersToDuplicates (true, true); return returnedHandle; }
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 = malloc(npfd * sizeof(*pfd)); snd_seq_poll_descriptors(seq_handle, pfd, npfd, POLLIN); if (argc >= 2) { snd_seq_addr_t addr; if (snd_seq_parse_address(seq_handle, &addr, argv[1]) == 0) { if (snd_seq_connect_from(seq_handle, portid, addr.client, addr.port) == 0) { printf("Connected to %s\n", argv[1]); } } } int i; for (i=2; i<argc; i++) channels |= 1<<(atoi(argv[i])-1); OLRenderParams params; memset(¶ms, 0, sizeof params); params.rate = 48000; params.on_speed = 2.0/50.0; params.off_speed = 2.0/35.0; params.start_wait = 6; params.start_dwell = 1; params.curve_dwell = 0; params.corner_dwell = 0; params.curve_angle = cosf(30.0*(M_PI/180.0)); // 30 deg params.end_dwell = 0; params.end_wait = 7; params.flatness = 0.00001; params.snap = 1/100000.0; params.render_flags = RENDER_GRAYSCALE; if(olInit(3, 30000) < 0) return 1; olSetRenderParams(¶ms); float time = 0; float ftime; int frames = 0; float nps = 0; avgnotes = 5; while(1) { olLoadIdentity(); int drawn = draw(); if (drawn < 2) draw(); ftime = olRenderFrame(100); float t = powf(0.3, ftime); avgnotes = avgnotes * t + (nps+2) * (1.0f-t); animate(ftime); int notes = 0; if (poll(pfd, npfd, 0) > 0) notes = midi_action(seq_handle); int pnotes = (notes+2)/3; nps = pnotes / ftime * 1.2; frames++; time += ftime; printf("Frame time: %f, Avg FPS:%f, Cur FPS:%f, %d, nps:%3d, avgnotes:%f\n", ftime, frames/time, 1/ftime, notes, (int)nps, avgnotes); } olShutdown(); exit (0); }
int main(int argc, char **argv) { int i; char *connect_client = NULL; int connect_port = -1; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--prefix") == 0) { if (++i == argc) usage(argv[0]); prefix = argv[i]; } else if (strcmp(argv[i], "--timeout") == 0) { if (++i == argc) usage(argv[0]); timeout = atoi(argv[i]); } else if (strcmp(argv[i], "--confirmation") == 0) { if (++i == argc) usage(argv[0]); confirmation_command_pattern = 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]); } } { snd_seq_t *seq; int port; if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_INPUT, 0) < 0) { fprintf(stderr, "Cannot open the ALSA sequencer.\n"); exit(1); } snd_seq_set_client_name(seq, "Brainstorm"); port = snd_seq_create_simple_port(seq, "Brainstorm recording port", SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, 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_from(seq, port, connect_client_id, connect_port); } signal(SIGALRM, alarm_handler); { snd_seq_event_t *event; while (snd_seq_event_input(seq, &event) >= 0) { switch (event->type) { case SND_SEQ_EVENT_NOTEOFF: { alarm(timeout); create_midi_file_for_first_event(); MidiFileTrack_createNoteOffEvent(track, get_tick(), event->data.note.channel, event->data.note.note, event->data.note.velocity); break; } case SND_SEQ_EVENT_NOTEON: { alarm(timeout); create_midi_file_for_first_event(); MidiFileTrack_createNoteOnEvent(track, get_tick(), event->data.note.channel, event->data.note.note, event->data.note.velocity); break; } case SND_SEQ_EVENT_KEYPRESS: { alarm(timeout); create_midi_file_for_first_event(); MidiFileTrack_createKeyPressureEvent(track, get_tick(), event->data.note.channel, event->data.note.note, event->data.note.velocity); break; } case SND_SEQ_EVENT_CONTROLLER: { alarm(timeout); create_midi_file_for_first_event(); MidiFileTrack_createControlChangeEvent(track, get_tick(), event->data.control.channel, event->data.control.param, event->data.control.value); break; } case SND_SEQ_EVENT_PGMCHANGE: { alarm(timeout); create_midi_file_for_first_event(); MidiFileTrack_createProgramChangeEvent(track, get_tick(), event->data.control.channel, event->data.control.value); break; } case SND_SEQ_EVENT_CHANPRESS: { alarm(timeout); create_midi_file_for_first_event(); MidiFileTrack_createChannelPressureEvent(track, get_tick(), event->data.control.channel, event->data.control.value); break; } case SND_SEQ_EVENT_PITCHBEND: { alarm(timeout); create_midi_file_for_first_event(); MidiFileTrack_createPitchWheelEvent(track, get_tick(), event->data.control.channel, event->data.control.value); break; } default: { /* I'm ignoring the pseudoevents which ALSA provides as convenience features (SND_SEQ_EVENT_NOTE, SND_SEQ_EVENT_CONTROL14, SND_SEQ_EVENT_NONREGPARAM, and SND_SEQ_EVENT_REGPARAM). Hopefully I can find some way to convince ALSA to normalize them into true MIDI events. */ break; } } } } } return 0; }