/* * remove all (exported) connections */ static void remove_connection(snd_seq_t *seq, snd_seq_client_info_t *cinfo, snd_seq_port_info_t *pinfo, int count) { snd_seq_query_subscribe_t *query; snd_seq_port_info_t *port; snd_seq_port_subscribe_t *subs; snd_seq_query_subscribe_alloca(&query); snd_seq_query_subscribe_set_root(query, snd_seq_port_info_get_addr(pinfo)); snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_READ); snd_seq_query_subscribe_set_index(query, 0); snd_seq_port_info_alloca(&port); snd_seq_port_subscribe_alloca(&subs); while (snd_seq_query_port_subscribers(seq, query) >= 0) { const snd_seq_addr_t *sender = snd_seq_query_subscribe_get_root(query); const snd_seq_addr_t *dest = snd_seq_query_subscribe_get_addr(query); if (snd_seq_get_any_port_info(seq, dest->client, dest->port, port) < 0 || !(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_WRITE) || (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT)) { snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1); continue; } snd_seq_port_subscribe_set_queue(subs, snd_seq_query_subscribe_get_queue(query)); snd_seq_port_subscribe_set_sender(subs, sender); snd_seq_port_subscribe_set_dest(subs, dest); if (snd_seq_unsubscribe_port(seq, subs) < 0) { snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1); } } }
/** call-seq: addr() -> [client, port] Returns the address as a tuple of two integers */ static VALUE wrap_snd_seq_port_info_get_addr(VALUE v_port_info) { snd_seq_port_info_t *port_info; Data_Get_Struct(v_port_info, snd_seq_port_info_t, port_info); const snd_seq_addr_t * const adr = snd_seq_port_info_get_addr(port_info); return rb_ary_new3(2, INT2NUM(adr->client), INT2NUM(adr->port)); }
void MidiAlsaSeq::subscribeWritablePort( MidiPort * _port, const QString & _dest, bool _subscribe ) { if( !m_portIDs.contains( _port ) ) { return; } const int pid = m_portIDs[_port][1] < 0 ? m_portIDs[_port][0] : m_portIDs[_port][1]; if( pid < 0 ) { return; } m_seqMutex.lock(); snd_seq_addr_t dest; if( snd_seq_parse_address( m_seqHandle, &dest, _dest.section( ' ', 0, 0 ).toLatin1().constData() ) ) { fprintf( stderr, "error parsing dest-address!\n" ); m_seqMutex.unlock(); return; } snd_seq_port_info_t * port_info; snd_seq_port_info_malloc( &port_info ); snd_seq_get_port_info( m_seqHandle, pid, port_info ); const snd_seq_addr_t * sender = snd_seq_port_info_get_addr( port_info ); snd_seq_port_subscribe_t * subs; snd_seq_port_subscribe_malloc( &subs ); snd_seq_port_subscribe_set_sender( subs, sender ); snd_seq_port_subscribe_set_dest( subs, &dest ); if( _subscribe ) { snd_seq_subscribe_port( m_seqHandle, subs ); } else { snd_seq_unsubscribe_port( m_seqHandle, subs ); } snd_seq_port_subscribe_free( subs ); snd_seq_port_info_free( port_info ); m_seqMutex.unlock(); }
void MIDIOut::rescanDevices() { snd_seq_client_info_t* clientInfo = NULL; snd_seq_port_info_t* portInfo = NULL; /* Don't do anything if the ALSA sequencer interface is not open */ if (m_alsa == NULL) return; /* Copy all device pointers to a destroy list */ QList <MIDIDevice*> destroyList(m_devices); /* Allocate these from stack */ snd_seq_client_info_alloca(&clientInfo); snd_seq_port_info_alloca(&portInfo); /* Find out what kinds of clients and ports there are */ snd_seq_client_info_set_client(clientInfo, 0); // TODO: -1 ????? while (snd_seq_query_next_client(m_alsa, clientInfo) == 0) { int client; /* Get the client ID */ client = snd_seq_client_info_get_client(clientInfo); /* Ignore our own client */ if (m_address->client == client) continue; /* Go thru all available ports in the client */ snd_seq_port_info_set_client(portInfo, client); snd_seq_port_info_set_port(portInfo, -1); while (snd_seq_query_next_port(m_alsa, portInfo) == 0) { const snd_seq_addr_t* address; MIDIDevice* dev; address = snd_seq_port_info_get_addr(portInfo); if (address == NULL) continue; dev = device(address); if (dev == NULL) { /* New address. Create a new device for it. */ dev = new MIDIDevice(this, address); Q_ASSERT(dev != NULL); /* Don't show QLC's internal ALSA ports */ if (dev->name().contains("__QLC__") == false) addDevice(dev); else delete dev; } else { /* This device is still alive. Do not destroy it at the end of this function. */ destroyList.removeAll(dev); } } } /* All devices that were not found during rescan are clearly no longer in our presence and must be destroyed. */ while (destroyList.isEmpty() == false) removeDevice(destroyList.takeFirst()); }
static void print_port_and_subs(snd_seq_t *seq, snd_seq_client_info_t *cinfo, snd_seq_port_info_t *pinfo, int count) { print_port(seq, cinfo, pinfo, count); list_subscribers(seq, snd_seq_port_info_get_addr(pinfo)); }
/************************************************************************** * ALSA_AddMidiPort [internal] * * Helper for ALSA_MidiInit */ static void ALSA_AddMidiPort(snd_seq_client_info_t* cinfo, snd_seq_port_info_t* pinfo, int cap, int type) { if (cap & SND_SEQ_PORT_CAP_WRITE) { TRACE("OUT (%d:%s:%s:%d:%s:%x)\n",snd_seq_client_info_get_client(cinfo), snd_seq_client_info_get_name(cinfo), snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT ? "user" : "kernel", snd_seq_port_info_get_port(pinfo), snd_seq_port_info_get_name(pinfo), type); if (MODM_NumDevs >= MAX_MIDIOUTDRV) return; if (!type) return; memcpy(&MidiOutDev[MODM_NumDevs].addr, snd_seq_port_info_get_addr(pinfo), sizeof(snd_seq_addr_t)); /* Manufac ID. We do not have access to this with soundcard.h * Does not seem to be a problem, because in mmsystem.h only * Microsoft's ID is listed. */ MidiOutDev[MODM_NumDevs].caps.wMid = 0x00FF; MidiOutDev[MODM_NumDevs].caps.wPid = 0x0001; /* FIXME Product ID */ /* Product Version. We simply say "1" */ MidiOutDev[MODM_NumDevs].caps.vDriverVersion = 0x001; MidiOutDev[MODM_NumDevs].caps.wChannelMask = 0xFFFF; /* FIXME Do we have this information? * Assuming the soundcards can handle * MIDICAPS_VOLUME and MIDICAPS_LRVOLUME but * not MIDICAPS_CACHE. */ MidiOutDev[MODM_NumDevs].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME; MultiByteToWideChar(CP_ACP, 0, snd_seq_client_info_get_name(cinfo), -1, MidiOutDev[MODM_NumDevs].caps.szPname, sizeof(MidiOutDev[MODM_NumDevs].caps.szPname) / sizeof(WCHAR)); MidiOutDev[MODM_NumDevs].caps.wTechnology = MIDI_AlsaToWindowsDeviceType(type); MidiOutDev[MODM_NumDevs].caps.wVoices = 16; /* FIXME Is it possible to know the maximum * number of simultaneous notes of a soundcard ? * I believe we don't have this information, but * it's probably equal or more than wVoices */ MidiOutDev[MODM_NumDevs].caps.wNotes = 16; MidiOutDev[MODM_NumDevs].bEnabled = TRUE; TRACE("MidiOut[%d]\tname='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%ld\n" "\tALSA info: midi dev-type=%lx, capa=%lx\n", MODM_NumDevs, wine_dbgstr_w(MidiOutDev[MODM_NumDevs].caps.szPname), MidiOutDev[MODM_NumDevs].caps.wTechnology, MidiOutDev[MODM_NumDevs].caps.wVoices, MidiOutDev[MODM_NumDevs].caps.wNotes, MidiOutDev[MODM_NumDevs].caps.wChannelMask, MidiOutDev[MODM_NumDevs].caps.dwSupport, (long)type, (long)0); MODM_NumDevs++; } if (cap & SND_SEQ_PORT_CAP_READ) { TRACE("IN (%d:%s:%s:%d:%s:%x)\n",snd_seq_client_info_get_client(cinfo), snd_seq_client_info_get_name(cinfo), snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT ? "user" : "kernel", snd_seq_port_info_get_port(pinfo), snd_seq_port_info_get_name(pinfo), type); if (MIDM_NumDevs >= MAX_MIDIINDRV) return; if (!type) return; memcpy(&MidiInDev[MIDM_NumDevs].addr, snd_seq_port_info_get_addr(pinfo), sizeof(snd_seq_addr_t)); /* Manufac ID. We do not have access to this with soundcard.h * Does not seem to be a problem, because in mmsystem.h only * Microsoft's ID is listed. */ MidiInDev[MIDM_NumDevs].caps.wMid = 0x00FF; MidiInDev[MIDM_NumDevs].caps.wPid = 0x0001; /* FIXME Product ID */ /* Product Version. We simply say "1" */ MidiInDev[MIDM_NumDevs].caps.vDriverVersion = 0x001; /* FIXME Do we have this information? * Assuming the soundcards can handle * MIDICAPS_VOLUME and MIDICAPS_LRVOLUME but * not MIDICAPS_CACHE. */ MidiInDev[MIDM_NumDevs].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME; MultiByteToWideChar(CP_ACP, 0, snd_seq_client_info_get_name(cinfo), -1, MidiInDev[MIDM_NumDevs].caps.szPname, sizeof(MidiInDev[MIDM_NumDevs].caps.szPname) / sizeof(WCHAR)); MidiInDev[MIDM_NumDevs].state = 0; TRACE("MidiIn [%d]\tname='%s' support=%ld\n" "\tALSA info: midi dev-type=%lx, capa=%lx\n", MIDM_NumDevs, wine_dbgstr_w(MidiInDev[MIDM_NumDevs].caps.szPname), MidiInDev[MIDM_NumDevs].caps.dwSupport, (long)type, (long)0); MIDM_NumDevs++; } }
void MidiEnumeratorPrivate::rescan() { qDebug() << Q_FUNC_INFO; if (m_alsa == NULL) return; bool changed = false; QList <MidiOutputDevice*> destroyOutputs(m_outputDevices); QList <MidiInputDevice*> destroyInputs(m_inputDevices); snd_seq_client_info_t* clientInfo = NULL; snd_seq_client_info_alloca(&clientInfo); snd_seq_port_info_t* portInfo = NULL; snd_seq_port_info_alloca(&portInfo); snd_seq_client_info_set_client(clientInfo, 0); while (snd_seq_query_next_client(m_alsa, clientInfo) == 0) { /* Get the client ID */ int client = snd_seq_client_info_get_client(clientInfo); /* Ignore our own client */ if (m_address->client == client) continue; /* Go thru all available ports in the client */ snd_seq_port_info_set_client(portInfo, client); snd_seq_port_info_set_port(portInfo, -1); while (snd_seq_query_next_port(m_alsa, portInfo) == 0) { const snd_seq_addr_t* address = snd_seq_port_info_get_addr(portInfo); if (address == NULL) continue; uint caps = snd_seq_port_info_get_capability(portInfo); if (caps & SND_SEQ_PORT_CAP_READ) { // Don't expose own ports QString name = AlsaMidiUtil::extractName(m_alsa, address); if (name.contains("__QLC__") == true) continue; QVariant uid = AlsaMidiUtil::addressToVariant(address); MidiInputDevice* dev = inputDevice(uid); if (dev == NULL) { AlsaMidiInputDevice* dev = new AlsaMidiInputDevice( uid, name, address, m_alsa, m_inputThread, this); m_inputDevices << dev; changed = true; } else { destroyInputs.removeAll(dev); } } if (caps & SND_SEQ_PORT_CAP_WRITE) { // Don't expose own ports QString name = AlsaMidiUtil::extractName(m_alsa, address); if (name.contains("__QLC__") == true) continue; QVariant uid = AlsaMidiUtil::addressToVariant(address); MidiOutputDevice* dev = outputDevice(uid); if (dev == NULL) { AlsaMidiOutputDevice* dev = new AlsaMidiOutputDevice( uid, name, address, m_alsa, m_address, this); m_outputDevices << dev; changed = true; } else { destroyOutputs.removeAll(dev); } } } } foreach (MidiOutputDevice* dev, destroyOutputs) { m_outputDevices.removeAll(dev); delete dev; changed = true; }