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; }
SeqDriver::SeqDriver(QList<MidiMap *> *p_midiMapList, QWidget *parent) : QWidget(parent), modified(false) { int err; midiMapList = p_midiMapList; portCount = 0; discardUnmatched = true; portUnmatched = 0; clientid = -1; err = snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_DUPLEX, 0); if (err < 0) { qWarning("Error opening ALSA sequencer (%s).", snd_strerror(err)); exit(1); } snd_seq_set_client_name(seq_handle, PACKAGE); clientid = snd_seq_client_id(seq_handle); portid_in = snd_seq_create_simple_port(seq_handle, "in", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION); if (portid_in < 0) { qWarning("Error creating sequencer port (%s).", snd_strerror(portid_in)); exit(1); } }
static int alsa_seqmidi_attach(alsa_midi_t *m) { alsa_seqmidi_t *self = (alsa_seqmidi_t*) m; int err; debug_log("midi: attach"); if (self->seq) return -EALREADY; if ((err = snd_seq_open(&self->seq, "hw", SND_SEQ_OPEN_DUPLEX, 0)) < 0) { error_log("failed to open alsa seq"); return err; } snd_seq_set_client_name(self->seq, self->alsa_name); self->port_id = snd_seq_create_simple_port(self->seq, "port", SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_WRITE #ifndef JACK_MIDI_DEBUG |SND_SEQ_PORT_CAP_NO_EXPORT #endif ,SND_SEQ_PORT_TYPE_APPLICATION); self->client_id = snd_seq_client_id(self->seq); self->queue = snd_seq_alloc_queue(self->seq); snd_seq_start_queue(self->seq, self->queue, 0); stream_attach(self, PORT_INPUT); stream_attach(self, PORT_OUTPUT); snd_seq_nonblock(self->seq, 1); return 0; }
// Constructor. qxgeditMidiDevice::qxgeditMidiDevice ( const QString& sClientName ) : QObject(NULL) { // Set pseudo-singleton reference. g_pMidiDevice = this; m_pAlsaSeq = NULL; m_iAlsaClient = -1; m_iAlsaPort = -1; m_pInputThread = NULL; // Open new ALSA sequencer client... if (snd_seq_open(&m_pAlsaSeq, "hw", SND_SEQ_OPEN_DUPLEX, 0) >= 0) { // Set client identification... QString sName = sClientName; snd_seq_set_client_name(m_pAlsaSeq, sName.toLatin1().constData()); m_iAlsaClient = snd_seq_client_id(m_pAlsaSeq); // Create duplex port sName += " MIDI 1"; m_iAlsaPort = snd_seq_create_simple_port(m_pAlsaSeq, sName.toLatin1().constData(), 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_PORT_TYPE_APPLICATION); // Create and start our own MIDI input queue thread... m_pInputThread = new qxgeditMidiInputThread(this); m_pInputThread->start(QThread::TimeCriticalPriority); } }
void stop_midireceiver (JackVST *jvst) { int err; snd_seq_event_t event; snd_seq_t *seq2 = create_sequencer ("jfstquit", true); jvst->midiquit = 1; snd_seq_connect_to (seq2, 0, snd_seq_client_id (jvst->seq),0); snd_seq_ev_clear (&event); snd_seq_ev_set_direct (&event); snd_seq_ev_set_subs (&event); snd_seq_ev_set_source (&event, 0); snd_seq_ev_set_controller (&event,1,0x80,50); if ((err = snd_seq_event_output (seq2, &event)) < 0) { fst_error ("cannot send stop event to midi thread: %s\n", snd_strerror (err)); } snd_seq_drain_output (seq2); snd_seq_close (seq2); pthread_join (jvst->midi_thread,NULL); snd_seq_close (jvst->seq); }
int seq_open() { unsigned int caps; if (!seq_opened) { /* sequencer opening */ if (snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_OUTPUT, 0)) { fprintf(stderr, "Error opening ALSA sequencer.\n"); return(-1); } /* our client id */ my_client = snd_seq_client_id(seq_handle); /* set client info */ snd_seq_set_client_name(seq_handle, DEFAULT_NAME); /* create port */ caps = SND_SEQ_PORT_CAP_READ; if (seq_client == SND_SEQ_ADDRESS_SUBSCRIBERS) caps |= SND_SEQ_PORT_CAP_SUBS_READ; my_port = snd_seq_create_simple_port(seq_handle, DEFAULT_NAME, caps,SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); if (my_port < 0) { fprintf(stderr, "can't create port\n"); snd_seq_close(seq_handle); return 0; } /* subscribe to MIDI port */ if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) { if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) { fprintf(stderr, "can't subscribe to MIDI port (%d:%d)\n", seq_client, seq_port); snd_seq_close(seq_handle); return 0; } } } seq_opened = 1; return 1; }
void JVlibForm::init_seq() { if (seq) return; int err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0); check_snd("open sequencer", err); err = snd_seq_set_client_name(seq, "midi_player"); check_snd("set client name", err); int client = snd_seq_client_id(seq); // client # is 128 by default check_snd("get client id", client); }
/* 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; }
int ALSAMidiDriver::open() { std::string arg; unsigned int caps; if (isOpen) return -1; arg = getConfigSetting("alsa_port", ALSA_PORT); if (parse_addr(arg, &seq_client, &seq_port) < 0) { perr << "ALSAMidiDriver: Invalid port: " << arg << std::endl; return -1; } if (my_snd_seq_open(&seq_handle)) { perr << "ALSAMidiDriver: Can't open sequencer" << std::endl; return -1; } isOpen = true; my_client = snd_seq_client_id(seq_handle); snd_seq_set_client_name(seq_handle, "PENTAGRAM"); snd_seq_set_client_group(seq_handle, "input"); caps = SND_SEQ_PORT_CAP_READ; if (seq_client == SND_SEQ_ADDRESS_SUBSCRIBERS) caps = ~SND_SEQ_PORT_CAP_SUBS_READ; my_port = snd_seq_create_simple_port(seq_handle, "PENTAGRAM", caps, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); if (my_port < 0) { snd_seq_close(seq_handle); isOpen = false; perr << "ALSAMidiDriver: Can't create port" << std::endl; return -1; } if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) { /* subscribe to MIDI port */ if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) { snd_seq_close(seq_handle); isOpen = false; perr << "ALSAMidiDriver: " << "Can't subscribe to MIDI port (" << seq_client << ":" << seq_port << ")" << std::endl; return -1; } } pout << "ALSA client initialised [" << seq_client << ":" << seq_port << "]" << std::endl; return 0; }
mastermidibus::mastermidibus () : m_alsa_seq (nullptr), // one pointer m_num_out_buses (0), // or c_max_busses, or what? m_num_in_buses (0), // or c_max_busses, or 1, or what? m_buses_out (), // array of c_max_busses midibus pointers m_buses_in (), // array of c_max_busses midibus pointers m_bus_announce (nullptr), // one pointer m_buses_out_active (), // array of c_max_busses booleans m_buses_in_active (), // array of c_max_busses booleans m_buses_out_init (), // array of c_max_busses booleans m_buses_in_init (), // array of c_max_busses booleans m_init_clock (), // array of c_max_busses clock_e values m_init_input (), // array of c_max_busses booleans m_queue (0), m_ppqn (0), m_bpm (0), m_num_poll_descriptors (0), m_poll_descriptors (nullptr), m_dumping_input (false), m_seq (nullptr), m_mutex () { for (int i = 0; i < c_max_busses; ++i) // why the global? { m_buses_in_active[i] = false; m_buses_out_active[i] = false; m_buses_in_init[i] = false; m_buses_out_init[i] = false; m_init_clock[i] = e_clock_off; m_init_input[i] = false; } #ifdef HAVE_LIBASOUND /* open the sequencer client */ int result = snd_seq_open(&m_alsa_seq, "default", SND_SEQ_OPEN_DUPLEX, 0); if (result < 0) { errprint("snd_seq_open() error"); exit(1); } snd_seq_set_client_name(m_alsa_seq, "seq24"); /* client's name */ m_queue = snd_seq_alloc_queue(m_alsa_seq); /* client's queue */ #endif #ifdef LASH_SUPPORT /* * Notify LASH of our client ID so that it can restore connections. */ if (not_nullptr(global_lash_driver)) global_lash_driver->set_alsa_client_id(snd_seq_client_id(m_alsa_seq)); #endif }
static PyObject * alsaseq_id(PyObject *self, PyObject *args) { int res = 0; if (!PyArg_ParseTuple(args, "" )) return NULL; res = snd_seq_client_id( seq_handle ); return PyInt_FromLong( res ); }
MidiInputDeviceAlsa::MidiInputDeviceAlsa(std::map<String,DeviceCreationParameter*> Parameters, void* pSampler) : MidiInputDevice(Parameters, pSampler), Thread(true, true, 1, -1) { if (snd_seq_open(&hAlsaSeq, "default", SND_SEQ_OPEN_INPUT, 0) < 0) { throw MidiInputException("Error opening ALSA sequencer"); } this->hAlsaSeqClient = snd_seq_client_id(hAlsaSeq); snd_seq_set_client_name(hAlsaSeq, "LinuxSampler"); AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt()); if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) { Listen(); } }
/** * \brief simple disconnection * \param seq sequencer handle * \param myport the port id as sender * \param dest_client destination client id * \param dest_port destination port id * \return 0 on success or negative error code * * Remove connection from the given sender client:port * to the given destination port in the current client. * * \sa snd_seq_unsubscribe_port(), snd_seq_connect_to() */ int snd_seq_disconnect_to(snd_seq_t *seq, int myport, int dest_client, int dest_port) { snd_seq_port_subscribe_t subs; memset(&subs, 0, sizeof(subs)); /*subs.sender.client = seq->client;*/ subs.sender.client = snd_seq_client_id(seq); subs.sender.port = myport; subs.dest.client = dest_client; subs.dest.port = dest_port; return snd_seq_unsubscribe_port(seq, &subs); }
int lash_clinit(int argc, char** argv, jack_client_t *jack_client, snd_seq_t *alsa_handle) { lash_jackname = jack_get_client_name(jack_client); lash_client = lash_init(lash_extract_args(&argc, &argv), lash_jackname, LASH_Config_File, LASH_PROTOCOL(2, 0)); if (lash_enabled(lash_client)) { lash_jack_client_name(lash_client, lash_jackname); lash_event_t *event = lash_event_new_with_type(LASH_Client_Name); lash_event_set_string(event, lash_jackname); lash_send_event(lash_client, event); lash_alsaid = alsa_handle; lash_alsa_client_id(lash_client, (unsigned char)snd_seq_client_id(alsa_handle)); return 0; } return -1; }
void Alsa::openPort(unsigned int portNumber_) { if ( _connected ) { this->closePort(); } unsigned int nSrc = this->getPortCount(); if (nSrc < 1) { std::cerr << "error: CxxMidi::Output::Alsa::openPort: no MIDI output sources found" << std::endl; } snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); std::ostringstream ost; if ( portInfo( _apiData->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber_ ) == 0 ) { std::cerr << "error: CxxMidi::Output::Alsa::openPort: port " << portNumber_ << " is invalid" << std::endl; } snd_seq_addr_t sender, receiver; receiver.client = snd_seq_port_info_get_client( pinfo ); receiver.port = snd_seq_port_info_get_port( pinfo ); sender.client = snd_seq_client_id( _apiData->seq ); if ( _apiData->vport < 0 ) { _apiData->vport = snd_seq_create_simple_port( _apiData->seq, "CxxMidi (RtMidi) output", SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); if ( _apiData->vport < 0 ) { std::cerr << "error: CxxMidi::Output::Alsa::openPort: error creating output port" << std::endl; } } sender.port = _apiData->vport; // Make subscription snd_seq_port_subscribe_malloc( &_apiData->subscription ); snd_seq_port_subscribe_set_sender(_apiData->subscription, &sender); snd_seq_port_subscribe_set_dest(_apiData->subscription, &receiver); snd_seq_port_subscribe_set_time_update(_apiData->subscription, 1); snd_seq_port_subscribe_set_time_real(_apiData->subscription, 1); if ( snd_seq_subscribe_port(_apiData->seq, _apiData->subscription) ) { std::cerr << "error: CxxMidi::Output::Alsa::openPort: error making port connection" << std::endl; } _connected = true; }
static PyObject * alsaseq_id(PyObject *self, PyObject *args) { int res = 0; if (!PyArg_ParseTuple(args, "" )) return NULL; if (!seq_handle) { PyErr_SetString(PyExc_RuntimeError, "Must initialize module with alsaseq.client() before using it"); return NULL; } res = snd_seq_client_id( seq_handle ); return PyInt_FromLong( res ); }
/* TODO Make sample rate, buffer, gain and polyphony set from CL interface*/ void connect2MidiThroughPort(snd_seq_t *seq_handle) { snd_seq_addr_t sender, dest; snd_seq_port_subscribe_t *subs; int myID; myID=snd_seq_client_id(seq_handle); fprintf(stderr,"MyID=%d",myID); sender.client = 14; sender.port = 0; dest.client = myID; dest.port = 0; snd_seq_port_subscribe_alloca(&subs); snd_seq_port_subscribe_set_sender(subs, &sender); snd_seq_port_subscribe_set_dest(subs, &dest); snd_seq_port_subscribe_set_queue(subs, 1); snd_seq_port_subscribe_set_time_update(subs, 1); snd_seq_port_subscribe_set_time_real(subs, 1); snd_seq_subscribe_port(seq_handle, subs); }
static int set_seq_name(snd_seq_t *handle) { int err; snd_seq_client_info_t info; memset(&info, 0, sizeof(info)); info.client = snd_seq_client_id(handle); info.type = USER_CLIENT; snprintf(info.name, sizeof(info.name), "SoundTracker(%i)", getpid()); err = snd_seq_set_client_info(handle, &info); if (err < 0) { fprintf(stderr, "Set client info error: %s\n", snd_strerror(err)); return -1; } return 0; } /* set_seq_name() */
int send_note(int port, int on, int ch, int note, int vel) { snd_seq_event_t ev; snd_seq_ev_clear(&ev); ev.dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS; ev.source.client = snd_seq_client_id(handle); ev.source.port = port; snd_seq_ev_set_direct(&ev); ev.type = on ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF; snd_seq_ev_set_fixed(&ev); ev.data.note.channel = ch; ev.data.note.note = note; ev.data.note.velocity = vel; snd_seq_event_output(handle, &ev); snd_seq_drain_output(handle); return 1; }
SeqContext::SeqContext() { /* * Create the sequencer context. Connected = 3 if all goes well */ connected = verbose = 0; handle = (snd_seq_t *)0; if (snd_seq_open(&handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, "Could not open sequencer: %s", snd_strerror(errno)); return; } connected++; if( (queue = snd_seq_alloc_queue(handle)) == 0 ) { fprintf(stderr, "Failure to allocate queue\n"); return; } if( (client = snd_seq_client_id(handle)) == 0 ) { fprintf(stderr, "Failure to get client address"); return; } connected++; destlist = new AddressList; source.client = client; source.port = 0; if( seq_new_port('e') < 0 ) { fprintf(stderr, "Could not open sequencer port: %s", snd_strerror(errno)); return; } if( verbose ) { fprintf(stderr, "Opened alsa sequencer for client %d and created queue\n", client ); } connected++; }
int init_alsa(ALSA_SEQ* seq, unsigned char verbose) { if ( verbose) printf("Setting up alsa\n"); seq->g_seq = open_client(); if (seq->g_seq == NULL) { if ( verbose >= 0) printf("Error: open_client failed.\n"); return 0; } int my_client_id = snd_seq_client_id(seq->g_seq); seq->g_port = my_new_port(seq->g_seq); if ( verbose) printf("client:port = %i:%i\n", my_client_id, seq->g_port); program_change(seq->g_seq, seq->g_port, 9, 0); int ret = 1; notedown_alsa((void*)seq, 9, 57, 55); if ( verbose) printf("Returning %i\n", ret); return ret; }
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; }
/* fills the array with our buses */ mastermidibus::mastermidibus() { /* temp return */ int ret; /* set initial number buses */ m_num_out_buses = 0; m_num_in_buses = 0; for( int i=0; i<c_maxBuses; ++i ){ m_buses_in_active[i] = false; m_buses_out_active[i] = false; m_buses_in_init[i] = false; m_buses_out_init[i] = false; m_init_clock[i] = e_clock_off; m_init_input[i] = false; } /* open the sequencer client */ ret = snd_seq_open(&m_alsa_seq, "default", SND_SEQ_OPEN_DUPLEX, 0); if ( ret < 0 ){ printf( "snd_seq_open() error\n"); exit(1); } /* set our clients name */ snd_seq_set_client_name(m_alsa_seq, "seq24"); /* set up our clients queue */ m_queue = snd_seq_alloc_queue( m_alsa_seq ); /* notify lash of our client ID so it can restore connections */ lash_driver->set_alsa_client_id(snd_seq_client_id(m_alsa_seq)); }
static void stop_midireceiver(struct Data *data){ int err; snd_seq_event_t event; snd_seq_t *seq2=create_alsa_seq("alsagakkquit",true); data->toquit=true; snd_seq_connect_to(seq2,0,snd_seq_client_id(data->seq),0); snd_seq_ev_clear (&event); snd_seq_ev_set_direct (&event); snd_seq_ev_set_subs (&event); snd_seq_ev_set_source (&event, 0); snd_seq_ev_set_controller (&event,1,0x80,50); err = snd_seq_event_output (seq2, &event); if (err < 0){ fprintf (stderr, "jackvst: %s: error sending midi event: %s\n", __FUNCTION__, snd_strerror (err)); } snd_seq_drain_output (seq2); snd_seq_close(seq2); pthread_join(data->midithread,NULL); snd_seq_close(data->seq); }
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; }
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(); }
int MidiDriver_ALSA::open() { if (_isOpen) return MERR_ALREADY_OPEN; _isOpen = true; if (my_snd_seq_open(&seq_handle) < 0) { error("Can't open sequencer"); return -1; } my_client = snd_seq_client_id(seq_handle); if (snd_seq_set_client_name(seq_handle, "RESIDUALVM") < 0) { error("Can't set sequencer client name"); } snd_seq_set_client_group(seq_handle, "input"); // According to http://www.alsa-project.org/~tiwai/alsa-subs.html // you can set read or write capabilities to allow other clients to // read or write the port. I don't think we need that, unless maybe // to be able to record the sound, but I can't get that to work even // with those capabilities. my_port = snd_seq_create_simple_port(seq_handle, "RESIDUALVM port 0", 0, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); if (my_port < 0) { snd_seq_close(seq_handle); error("Can't create port"); return -1; } if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) { // Subscribe to MIDI port. Prefer one that doesn't already have // any connections, unless we've forced a port number already. if (seq_port == -1) { 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_get_any_client_info(seq_handle, seq_client, cinfo); int first_port = -1; int found_port = -1; snd_seq_port_info_set_client(pinfo, seq_client); snd_seq_port_info_set_port(pinfo, -1); while (found_port == -1 && snd_seq_query_next_port(seq_handle, pinfo) >= 0) { if (check_permission(pinfo)) { if (first_port == -1) first_port = snd_seq_port_info_get_port(pinfo); if (found_port == -1 && snd_seq_port_info_get_write_use(pinfo) == 0) found_port = snd_seq_port_info_get_port(pinfo); } } if (found_port == -1) { // Should we abort here? For now, use the first // available port. seq_port = first_port; warning("MidiDriver_ALSA: All ports on client %d (%s) are already in use", seq_client, snd_seq_client_info_get_name(cinfo)); } else { seq_port = found_port; } } if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) { error("Can't subscribe to MIDI port (%d:%d) see README for help", seq_client, seq_port); } } printf("Connected to Alsa sequencer client [%d:%d]\n", seq_client, seq_port); printf("ALSA client initialized [%d:0]\n", my_client); return 0; }
mastermidibus::mastermidibus (int ppqn, int bpm) : m_alsa_seq (nullptr), // one pointer m_max_busses (c_max_busses), m_num_out_buses (0), // or c_max_busses, or what? m_num_in_buses (0), // or c_max_busses, or 1, or what? m_buses_out (), // array of c_max_busses midibus pointers m_buses_in (), // array of c_max_busses midibus pointers m_bus_announce (nullptr), // one pointer m_buses_out_active (), // array of c_max_busses booleans m_buses_in_active (), // array of c_max_busses booleans m_buses_out_init (), // array of c_max_busses booleans m_buses_in_init (), // array of c_max_busses booleans m_init_clock (), // array of c_max_busses clock_e values m_init_input (), // array of c_max_busses booleans m_queue (0), m_ppqn (0), m_beats_per_minute (bpm), // beats per minute m_num_poll_descriptors (0), m_poll_descriptors (nullptr), m_dumping_input (false), m_vector_sequence (), m_filter_by_channel (false), // set below based on configuration m_seq (nullptr), m_mutex () { m_ppqn = choose_ppqn(ppqn); for (int i = 0; i < m_max_busses; ++i) { m_buses_in_active[i] = m_buses_out_active[i] = m_buses_in_init[i] = m_buses_out_init[i] = m_init_input[i] = false; m_init_clock[i] = e_clock_off; } #ifdef SEQ64_HAVE_LIBASOUND /* * Open the sequencer client. This line of code results in a loss of * 4 bytes somewhere in snd_seq_open(), as discovered via valgrind. */ int result = snd_seq_open(&m_alsa_seq, "default", SND_SEQ_OPEN_DUPLEX, 0); if (result < 0) { errprint("snd_seq_open() error"); exit(1); } else { /* * Tried to reduce apparent memory leaks from libasound, but this call * changed nothing. * * (void) snd_config_update_free_global(); */ } /* * Set the client's name for ALSA. It used to be "seq24". Then set up our * ALSA client's queue. */ snd_seq_set_client_name(m_alsa_seq, "sequencer64"); m_queue = snd_seq_alloc_queue(m_alsa_seq); #endif // SEQ64_HAVE_LIBASOUND #ifdef SEQ64_LASH_SUPPORT /* * Notify LASH of our client ID so that it can restore connections. */ if (not_nullptr(lash_driver())) lash_driver()->set_alsa_client_id(snd_seq_client_id(m_alsa_seq)); #endif }
void mastermidibus::port_start (int client, int port) { #ifdef SEQ64_HAVE_LIBASOUND automutex locker(m_mutex); snd_seq_client_info_t * cinfo; /* client info */ snd_seq_client_info_alloca(&cinfo); snd_seq_get_any_client_info(m_alsa_seq, client, cinfo); snd_seq_port_info_t * pinfo; /* port info */ snd_seq_port_info_alloca(&pinfo); snd_seq_get_any_port_info(m_alsa_seq, client, port, pinfo); int cap = snd_seq_port_info_get_capability(pinfo); /* get its capability */ if (ALSA_CLIENT_CHECK(pinfo)) { if (CAP_FULL_WRITE(cap) && ALSA_CLIENT_CHECK(pinfo)) /* outputs */ { 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() == client && m_buses_out[i]->get_port() == port && ! m_buses_out_active[i] ) { replacement = true; bus_slot = i; } } if (not_nullptr(m_buses_out[bus_slot])) { delete m_buses_out[bus_slot]; errprintf ( "mastermidibus::port_start(): m_buses_out[%d] not null\n", bus_slot ); } 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; } if (CAP_FULL_READ(cap) && ALSA_CLIENT_CHECK(pinfo)) /* inputs */ { 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() == client && m_buses_in[i]->get_port() == port && ! m_buses_in_active[i] ) { replacement = true; bus_slot = i; } } if (not_nullptr(m_buses_in[bus_slot])) { delete m_buses_in[bus_slot]; errprintf ( "mmbus::port_start(): m_buses_in[%d] not null\n", 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_active[bus_slot] = true; m_buses_in_init[bus_slot] = true; if (! replacement) m_num_in_buses++; } } /* end loop for clients */ /* * Get the number of MIDI input poll file descriptors. */ m_num_poll_descriptors = snd_seq_poll_descriptors_count(m_alsa_seq, POLLIN); m_poll_descriptors = new pollfd[m_num_poll_descriptors]; /* allocate info */ snd_seq_poll_descriptors /* get input descriptors */ ( m_alsa_seq, m_poll_descriptors, m_num_poll_descriptors, POLLIN ); #endif // SEQ64_HAVE_LIBASOUND }