static QString __portName( snd_seq_t * _seq, const snd_seq_addr_t * _addr ) { snd_seq_client_info_t * cinfo; snd_seq_port_info_t * pinfo; snd_seq_client_info_malloc( &cinfo ); snd_seq_port_info_malloc( &pinfo ); snd_seq_get_any_port_info( _seq, _addr->client, _addr->port, pinfo ); snd_seq_get_any_client_info( _seq, _addr->client, cinfo ); const QString name = __portName( cinfo, pinfo ); snd_seq_client_info_free( cinfo ); snd_seq_port_info_free( pinfo ); return name; }
std::string Alsa::getPortName(unsigned int portNumber_ ) { snd_seq_client_info_t *cinfo; snd_seq_port_info_t *pinfo; snd_seq_client_info_alloca( &cinfo ); snd_seq_port_info_alloca( &pinfo ); std::string stringName; if ( portInfo( _apiData->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber_ ) ) { int cnum = snd_seq_port_info_get_client(pinfo); snd_seq_get_any_client_info( _apiData->seq, cnum, cinfo ); std::ostringstream os; os << snd_seq_client_info_get_name(cinfo); os << ":"; os << snd_seq_port_info_get_port(pinfo); stringName = os.str(); return stringName; } std::cerr << "error: CxxMidi::Output::Alsa::getPortName: error looking for port name" << std::endl; return stringName; }
static port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const snd_seq_port_info_t *info) { snd_seq_client_info_t* client_info; port_t *port; char *c; int err; int jack_caps; char name[128]; port = calloc(1, sizeof(port_t)); if (!port) return NULL; port->remote = addr; snd_seq_client_info_alloca (&client_info); snd_seq_get_any_client_info (self->seq, addr.client, client_info); snprintf(port->name, sizeof(port->name), "alsa_pcm:%s/midi_%s_%d", snd_seq_client_info_get_name(client_info), port_type[type].name, addr.port+1); // replace all offending characters by - for (c = port->name; *c; ++c) if (!isalnum(*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') *c = '-'; jack_caps = port_type[type].jack_caps; /* mark anything that looks like a hardware port as physical&terminal */ if (snd_seq_port_info_get_type (info) & (SND_SEQ_PORT_TYPE_HARDWARE|SND_SEQ_PORT_TYPE_PORT|SND_SEQ_PORT_TYPE_SPECIFIC)) { jack_caps |= (JackPortIsPhysical | JackPortIsTerminal); } if (jack_caps & JackPortIsOutput) snprintf(name, sizeof(name), "system:midi_capture_%d", ++self->midi_in_cnt); else snprintf(name, sizeof(name), "system:midi_playback_%d", ++self->midi_out_cnt); port->jack_port = jack_port_register(self->jack, name, JACK_DEFAULT_MIDI_TYPE, jack_caps, 0); if (!port->jack_port) goto failed; jack_port_set_alias (port->jack_port, port->name); /* generate an alias */ snprintf(port->name, sizeof(port->name), "%s:midi/%s_%d", snd_seq_client_info_get_name (client_info), port_type[type].name, addr.port+1); // replace all offending characters by - for (c = port->name; *c; ++c) if (!isalnum(*c) && *c != '/' && *c != '_' && *c != ':' && *c != '(' && *c != ')') *c = '-'; jack_port_set_alias (port->jack_port, port->name); if (type == PORT_INPUT) err = alsa_connect_from(self, port->remote.client, port->remote.port); else err = snd_seq_connect_to(self->seq, self->port_id, port->remote.client, port->remote.port); if (err) goto failed; port->early_events = jack_ringbuffer_create(MAX_EVENT_SIZE*16); info_log("port created: %s", port->name); return port; failed: port_free(self, port); return NULL; }
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; }
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 }