QString MidiAlsaDevice::open() { _openFlags &= _rwFlags; // restrict to available bits snd_seq_port_subscribe_t* subs; // Allocated on stack, no need to call snd_seq_port_subscribe_free() later. snd_seq_port_subscribe_alloca(&subs); QString estr; int wer = 0; int rer = 0; // subscribe for writing if (_openFlags & 1) { snd_seq_port_subscribe_set_sender(subs, &losPort); snd_seq_port_subscribe_set_dest(subs, &adr); // Not already subscribed (or error)? Then try subscribing. if (snd_seq_get_port_subscription(alsaSeq, subs) < 0) { wer = snd_seq_subscribe_port(alsaSeq, subs); if (wer < 0) estr += (QString("Play: ") + QString(snd_strerror(wer)) + QString(" ")); } if (!wer) _writeEnable = true; } // subscribe for reading if (_openFlags & 2) { snd_seq_port_subscribe_set_dest(subs, &losPort); snd_seq_port_subscribe_set_sender(subs, &adr); // Not already subscribed (or error)? Then try subscribing. if (snd_seq_get_port_subscription(alsaSeq, subs) < 0) { //int error = snd_seq_subscribe_port(alsaSeq, subs); rer = snd_seq_subscribe_port(alsaSeq, subs); if (rer < 0) estr += (QString("Rec: ") + QString(snd_strerror(rer))); } if (!rer) _readEnable = true; } if (wer < 0 || rer < 0) return estr; return QString("OK"); }
static int a2j_alsa_connect_from (alsa_midi_driver_t * driver, int client, int port) { snd_seq_port_subscribe_t* sub; snd_seq_addr_t seq_addr; int err; snd_seq_port_subscribe_alloca (&sub); seq_addr.client = client; seq_addr.port = port; snd_seq_port_subscribe_set_sender (sub, &seq_addr); seq_addr.client = driver->client_id; seq_addr.port = driver->port_id; snd_seq_port_subscribe_set_dest (sub, &seq_addr); snd_seq_port_subscribe_set_time_update (sub, 1); snd_seq_port_subscribe_set_queue (sub, driver->queue); snd_seq_port_subscribe_set_time_real (sub, 1); if ((err = snd_seq_subscribe_port (driver->seq, sub))) { a2j_error ("can't subscribe to %d:%d - %s", client, port, snd_strerror(err)); } return err; }
bool midibus::init_in () { #ifdef HAVE_LIBASOUND int result = snd_seq_create_simple_port /* create ports */ ( m_seq, "seq24 in", SND_SEQ_PORT_CAP_NO_EXPORT | SND_SEQ_PORT_CAP_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION ); m_local_addr_port = result; if (result < 0) { errprint("snd_seq_create_simple_port(read) error"); return false; } snd_seq_port_subscribe_t * subs; snd_seq_port_subscribe_alloca(&subs); snd_seq_addr_t sender; snd_seq_addr_t dest; /* the destination port is actually our local port */ sender.client = m_dest_addr_client; sender.port = m_dest_addr_port; dest.client = m_local_addr_client; dest.port = m_local_addr_port; /* set in and out ports */ snd_seq_port_subscribe_set_sender(subs, &sender); snd_seq_port_subscribe_set_dest(subs, &dest); /* use the master queue, and get ticks */ snd_seq_port_subscribe_set_queue(subs, m_queue); snd_seq_port_subscribe_set_time_update(subs, 1); /* subscribe */ result = snd_seq_subscribe_port(m_seq, subs); if (result < 0) { fprintf ( stderr, "snd_seq_connect_from(%d:%d) error\n", m_dest_addr_client, m_dest_addr_port ); return false; } #endif // HAVE_LIBASOUND return true; }
void MIDIOut::subscribeDevice(MIDIDevice* device) { snd_seq_port_subscribe_t* sub = NULL; Q_ASSERT(device != NULL); Q_ASSERT(m_address != NULL); snd_seq_port_subscribe_alloca(&sub); snd_seq_port_subscribe_set_sender(sub, m_address); snd_seq_port_subscribe_set_dest(sub, device->address()); snd_seq_subscribe_port(m_alsa, sub); }
/** * \brief simple subscription (w/o exclusive & time conversion) * \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 * * Connect from the given receiver port in the current client * to the given destination client:port. * * \sa snd_seq_subscribe_port(), snd_seq_disconnect_to() */ int snd_seq_connect_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_subscribe_port(seq, &subs); }
void AlsaMidiInputThread::subscribeDevice(AlsaMidiInputDevice* device) { qDebug() << Q_FUNC_INFO; Q_ASSERT(device != NULL); /* Subscribe events coming from the the device's MIDI port to get patched to the plugin's own MIDI port */ snd_seq_port_subscribe_t* sub = NULL; snd_seq_port_subscribe_alloca(&sub); snd_seq_port_subscribe_set_sender(sub, device->address()); snd_seq_port_subscribe_set_dest(sub, m_destinationAddress); snd_seq_subscribe_port(m_alsa, sub); }
/* Set up ALSA MIDI subscription according to supplied parameter. */ static int subscribe(snd_seq_port_subscribe_t *sub) { if (snd_seq_get_port_subscription(seq, sub) == 0) { dprintf("Connection between editor and device already established\n"); return 0; } if (snd_seq_subscribe_port(seq, sub) < 0) { dprintf("Couldn't estabilsh connection between editor and device\n"); return -1; } return 0; }
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; }
bool AlsaMidiOutputDevice::open() { qDebug() << Q_FUNC_INFO; m_open = true; Q_ASSERT(m_sender_address != NULL); Q_ASSERT(m_receiver_address != NULL); /* Subscribe QLC+ ALSA client to the MIDI device */ snd_seq_port_subscribe_t* sub = NULL; snd_seq_port_subscribe_alloca(&sub); snd_seq_port_subscribe_set_sender(sub, m_sender_address); snd_seq_port_subscribe_set_dest(sub, m_receiver_address); snd_seq_subscribe_port(m_alsa, sub); return true; }
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(); }
/* 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); }
/** * Connects this Alsa midi input device with an Alsa MIDI source. * * @param Client - Alsa sequencer client and port ID of a MIDI source * (e.g. "64:0") * @throws MidiInputException if connection cannot be established */ void MidiInputDeviceAlsa::MidiInputPortAlsa::ConnectToAlsaMidiSource(const char* MidiSource) { snd_seq_addr_t sender, dest; snd_seq_port_subscribe_t* subs; int hExtClient, hExtPort; sscanf(MidiSource, "%d:%d", &hExtClient, &hExtPort); sender.client = (char) hExtClient; sender.port = (char) hExtPort; dest.client = (char) pDevice->hAlsaSeqClient; dest.port = (char) portNumber; snd_seq_port_subscribe_malloc(&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); if (snd_seq_subscribe_port(pDevice->hAlsaSeq, subs) < 0) { snd_seq_port_subscribe_free(subs); throw MidiInputException(String("Unable to connect to Alsa seq client \'") + MidiSource + "\' (" + snd_strerror(errno) + ")"); } subscriptions.push_back(subs); }
static int alsa_connect_from(alsa_seqmidi_t *self, int client, int port) { snd_seq_port_subscribe_t* sub; snd_seq_addr_t seq_addr; int err; snd_seq_port_subscribe_alloca(&sub); seq_addr.client = client; seq_addr.port = port; snd_seq_port_subscribe_set_sender(sub, &seq_addr); seq_addr.client = self->client_id; seq_addr.port = self->port_id; snd_seq_port_subscribe_set_dest(sub, &seq_addr); snd_seq_port_subscribe_set_time_update(sub, 1); snd_seq_port_subscribe_set_queue(sub, self->queue); snd_seq_port_subscribe_set_time_real(sub, 1); if ((err=snd_seq_subscribe_port(self->seq, sub))) error_log("can't subscribe to %d:%d - %s", client, port, snd_strerror(err)); return err; }
// Connection primitive. bool qjackctlAlsaConnect::connectPorts ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { #ifdef CONFIG_ALSA_SEQ qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == NULL) return false; snd_seq_t *pAlsaSeq = pMainForm->alsaSeq(); if (pAlsaSeq == NULL) return false; qjackctlAlsaPort *pOAlsa = static_cast<qjackctlAlsaPort *> (pOPort); qjackctlAlsaPort *pIAlsa = static_cast<qjackctlAlsaPort *> (pIPort); snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = pOAlsa->alsaClient(); seq_addr.port = pOAlsa->alsaPort(); snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = pIAlsa->alsaClient(); seq_addr.port = pIAlsa->alsaPort(); snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); return (snd_seq_subscribe_port(pAlsaSeq, pAlsaSubs) >= 0); #else return false; #endif // CONFIG_ALSA_SEQ }
void event_decoder(snd_seq_t *handle, int argc, char *argv[]) { snd_seq_event_t *ev; snd_seq_port_info_t *pinfo; snd_seq_port_subscribe_t *sub; snd_seq_addr_t addr; int client, port, queue, max, err, v1, v2; char *ptr; struct pollfd *pfds; if ((client = snd_seq_client_id(handle))<0) { fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client)); return; } printf("Client ID = %i\n", client); if ((queue = snd_seq_alloc_queue(handle))<0) { fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue)); return; } printf("Queue ID = %i\n", queue); if ((err = snd_seq_nonblock(handle, 1))<0) fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err)); snd_seq_port_info_alloca(&pinfo); snd_seq_port_info_set_name(pinfo, "Input"); snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC); snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE); /* Enable timestamping for events sent by external subscribers. */ snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_real(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, queue); if ((err = snd_seq_create_port(handle, pinfo)) < 0) { fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err)); return; } port = snd_seq_port_info_get_port(pinfo); event_decoder_start_timer(handle, queue, client, port); snd_seq_port_subscribe_alloca(&sub); addr.client = SND_SEQ_CLIENT_SYSTEM; addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; snd_seq_port_subscribe_set_sender(sub, &addr); addr.client = client; addr.port = port; snd_seq_port_subscribe_set_dest(sub, &addr); snd_seq_port_subscribe_set_queue(sub, queue); snd_seq_port_subscribe_set_time_update(sub, 1); snd_seq_port_subscribe_set_time_real(sub, 1); if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err)); return; } addr.client = SND_SEQ_CLIENT_SYSTEM; addr.port = SND_SEQ_PORT_SYSTEM_TIMER; snd_seq_port_subscribe_set_sender(sub, &addr); if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err)); return; } for (max = 0; max < argc; max++) { ptr = argv[max]; if (!ptr) continue; snd_seq_port_subscribe_set_time_real(sub, 0); if (tolower(*ptr) == 'r') { snd_seq_port_subscribe_set_time_real(sub, 1); ptr++; } if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) { fprintf(stderr, "Wrong argument '%s'...\n", argv[max]); return; } addr.client = v1; addr.port = v2; snd_seq_port_subscribe_set_sender(sub, &addr); if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err)); return; } } max = snd_seq_poll_descriptors_count(handle, POLLIN); pfds = alloca(sizeof(*pfds) * max); while (1) { snd_seq_poll_descriptors(handle, pfds, max, POLLIN); if (poll(pfds, max, -1) < 0) break; do { if ((err = snd_seq_event_input(handle, &ev))<0) break; if (!ev) continue; decode_event(ev); snd_seq_free_event(ev); } while (err > 0); } }
// MIDI Input(readable) / Output(writable) device connects. bool qxgeditMidiDevice::connectDeviceList ( bool bReadable, const QStringList& list ) const { if (m_pAlsaSeq == NULL) return false; if (list.isEmpty()) return false; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_t *pPortSubs; snd_seq_port_subscribe_alloca(&pPortSubs); snd_seq_client_info_t *pClientInfo; snd_seq_port_info_t *pPortInfo; snd_seq_client_info_alloca(&pClientInfo); snd_seq_port_info_alloca(&pPortInfo); unsigned int uiPortFlags; if (bReadable) uiPortFlags = SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; else uiPortFlags = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; int iConnects = 0; while (snd_seq_query_next_client(m_pAlsaSeq, pClientInfo) >= 0) { int iAlsaClient = snd_seq_client_info_get_client(pClientInfo); if (iAlsaClient > 0 && iAlsaClient != m_iAlsaClient) { QString sClientName = snd_seq_client_info_get_name(pClientInfo); snd_seq_port_info_set_client(pPortInfo, iAlsaClient); snd_seq_port_info_set_port(pPortInfo, -1); while (snd_seq_query_next_port(m_pAlsaSeq, pPortInfo) >= 0) { unsigned int uiPortCapability = snd_seq_port_info_get_capability(pPortInfo); if (((uiPortCapability & uiPortFlags) == uiPortFlags) && ((uiPortCapability & SND_SEQ_PORT_CAP_NO_EXPORT) == 0)) { int iAlsaPort = snd_seq_port_info_get_port(pPortInfo); QString sPortName = snd_seq_port_info_get_name(pPortInfo); QStringListIterator iter(list); while (iter.hasNext()) { const QString& sItem = iter.next(); const QString& sClientItem = sItem.section(c_pszItemSep, 0, 0); const QString& sPortItem = sItem.section(c_pszItemSep, 1, 1); if (sClientName != sClientItem.section(':', 1, 1)) continue; if (sPortName != sPortItem .section(':', 1, 1)) continue; if (bReadable) { seq_addr.client = iAlsaClient; seq_addr.port = iAlsaPort; snd_seq_port_subscribe_set_sender(pPortSubs, &seq_addr); seq_addr.client = m_iAlsaClient; seq_addr.port = m_iAlsaPort; snd_seq_port_subscribe_set_dest(pPortSubs, &seq_addr); } else { seq_addr.client = m_iAlsaClient; seq_addr.port = m_iAlsaPort; snd_seq_port_subscribe_set_sender(pPortSubs, &seq_addr); seq_addr.client = iAlsaClient; seq_addr.port = iAlsaPort; snd_seq_port_subscribe_set_dest(pPortSubs, &seq_addr); } if (snd_seq_subscribe_port(m_pAlsaSeq, pPortSubs) == 0) iConnects++; } } } } } return (iConnects > 0); }
bool midi_init() { snd_seq_addr_t sender, receiver; snd_seq_port_info_t *pinfo; snd_seq_client_info_t *cinfo; bool found = false; if (snd_seq_open(&s_midi, "default", SND_SEQ_OPEN_OUTPUT, 0) < 0) { Error("Failed to initialize MIDI\n"); s_midi = NULL; return false; } snd_seq_set_client_name(s_midi, s_midiCaption); /* Create a port to work on */ s_midiPort = snd_seq_create_simple_port(s_midi, s_midiCaption, SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC); if (s_midiPort < 0) { Error("Failed to initialize MIDI\n"); snd_seq_close(s_midi); s_midi = NULL; return false; } /* Try to find a MIDI out */ snd_seq_port_info_alloca(&pinfo); snd_seq_client_info_alloca(&cinfo); snd_seq_client_info_set_client(cinfo, -1); /* Walk all clients and ports, and see if one matches our demands */ while (snd_seq_query_next_client(s_midi, cinfo) >= 0 && !found) { int client; client = snd_seq_client_info_get_client(cinfo); if (client == 0) continue; snd_seq_port_info_set_client(pinfo, client); snd_seq_port_info_set_port(pinfo, -1); while (snd_seq_query_next_port(s_midi, pinfo) >= 0) { if ((snd_seq_port_info_get_capability(pinfo) & (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) != (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) continue; /* Most linux installations come with a Midi Through Port. * This is 'hardware' support that mostly ends up on your serial, which * you most likely do not have connected. So we skip it by default. */ if (strncmp("Midi Through Port", snd_seq_port_info_get_name(pinfo), 17) == 0) continue; found = true; break; } } if (!found) { Error("No valid MIDI output ports.\n Please install and start Timidity++ like: timidity -iA\n"); snd_seq_delete_port(s_midi, s_midiPort); snd_seq_close(s_midi); s_midi = NULL; return false; } /* Subscribe ourself to the port */ receiver.client = snd_seq_port_info_get_client(pinfo); receiver.port = snd_seq_port_info_get_port(pinfo); sender.client = snd_seq_client_id(s_midi); sender.port = s_midiPort; snd_seq_port_subscribe_malloc(&s_midiSubscription); snd_seq_port_subscribe_set_sender(s_midiSubscription, &sender); snd_seq_port_subscribe_set_dest(s_midiSubscription, &receiver); snd_seq_port_subscribe_set_time_update(s_midiSubscription, 1); snd_seq_port_subscribe_set_time_real(s_midiSubscription, 1); if (snd_seq_subscribe_port(s_midi, s_midiSubscription) < 0) { Error("Failed to subscript to MIDI output\n"); snd_seq_delete_port(s_midi, s_midiPort); snd_seq_close(s_midi); s_midi = NULL; return false; } /* Start the MIDI decoder */ if (snd_midi_event_new(4, &s_midiCoder) < 0) { Error("Failed to initialize MIDI decoder\n"); snd_seq_delete_port(s_midi, s_midiPort); snd_seq_close(s_midi); s_midi = NULL; return false; } snd_midi_event_init(s_midiCoder); return true; }
void midi_init() { int rc; snd_seq_port_info_t port; snd_seq_port_subscribe_t sub; int client; if (midi_handle != NULL ) { if (IS_MIDI_DEBUG_ON) { g_print( "Reinitializing MIDI input\n"); } if (midi_file_tag >= 0) { gdk_input_remove( midi_file_tag); midi_file_tag = -1; } close_handle( midi_handle); midi_handle = NULL; } /* Open the sequencer device, in non-block mode. Don't use O_NONBLOCK here, it crashes the application as for ALSA 0.5.5. (LT 15-mar-2000) */ rc = snd_seq_open( &midi_handle, SND_SEQ_OPEN_IN); if (rc < 0) { g_warning( "error opening ALSA MIDI input stream (%s)\n", snd_strerror(rc)); return; } /* Set nonblock mode i.e. enable==0. */ rc = snd_seq_block_mode( midi_handle, 0); if (rc < 0) { close_handle( midi_handle); midi_handle = NULL; g_warning( "error disabling sequencer block mode (%s)\n", snd_strerror(rc)); return; } /* Get client id. Needed to subscribe to the kernel-level client. */ client = snd_seq_client_id( midi_handle); if (client < 0) { close_handle( midi_handle); midi_handle = NULL; g_warning( "error naming sequencer client (%s)\n", snd_strerror(client)); return; } /* Set client name. Visible with 'cat /proc/asound/seq/clients'. */ rc = set_seq_name( midi_handle); if (rc < 0) { close_handle( midi_handle); midi_handle = NULL; g_warning( "error naming sequencer client (%s)\n",snd_strerror(rc)); return; } /* Create a port for our user-level client. */ memset( &port, 0, sizeof(port)); strcpy( port.name, "tracker"); port.capability = SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_WRITE; port.capability |= SND_SEQ_PORT_CAP_SUBS_WRITE; /* necessary??? */ port.type = SND_SEQ_PORT_TYPE_APPLICATION; rc = snd_seq_create_port( midi_handle, &port); if (rc < 0) { close_handle( midi_handle); midi_handle = NULL; g_warning( "error creating sequencer port (%s)\n", snd_strerror(rc)); return; } /* Subscribe to the kernel client. */ memset( &sub, 0, sizeof(sub)); sub.sender.client = midi_settings.input.client; sub.sender.port = midi_settings.input.port; sub.dest.client = client; sub.dest.port = port.port; rc = snd_seq_subscribe_port( midi_handle, &sub); if (rc < 0) { close_handle( midi_handle); midi_handle = NULL; g_warning( "error subscribing to client %d port %d (%s)\n", sub.sender.client, sub.sender.port, snd_strerror(rc)); return; } /* Install callback to process MIDI input. */ midi_file_tag = gdk_input_add( snd_seq_file_descriptor( midi_handle), GDK_INPUT_READ, (GdkInputFunction)midi_in_cb, midi_handle); if (midi_file_tag < 0) { close_handle( midi_handle); midi_handle = NULL; g_warning( "error installing MIDI input callback (%s)\n", g_strerror(midi_file_tag)); return; } if (IS_MIDI_DEBUG_ON) { g_print( "MIDI input initialized\n"); } return; } /* midi_init() */
int main(int argc, char **argv) { int c; snd_seq_t *seq; int queue = 0, convert_time = 0, convert_real = 0, exclusive = 0; int command = SUBSCRIBE; int list_perm = 0; int client; int list_subs = 0; snd_seq_port_subscribe_t *subs; snd_seq_addr_t sender, dest; #ifdef ENABLE_NLS setlocale(LC_ALL, ""); textdomain(PACKAGE); #endif while ((c = getopt_long(argc, argv, "dior:t:elx", long_option, NULL)) != -1) { switch (c) { case 'd': command = UNSUBSCRIBE; break; case 'i': command = LIST; list_perm |= LIST_INPUT; break; case 'o': command = LIST; list_perm |= LIST_OUTPUT; break; case 'e': exclusive = 1; break; case 'r': queue = atoi(optarg); convert_time = 1; convert_real = 1; break; case 't': queue = atoi(optarg); convert_time = 1; convert_real = 0; break; case 'l': list_subs = 1; break; case 'x': command = REMOVE_ALL; break; default: usage(); exit(1); } } if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, _("can't open sequencer\n")); return 1; } snd_lib_error_set_handler(error_handler); switch (command) { case LIST: do_search_port(seq, list_perm, list_subs ? print_port_and_subs : print_port); snd_seq_close(seq); return 0; case REMOVE_ALL: remove_all_connections(seq); snd_seq_close(seq); return 0; } /* connection or disconnection */ if (optind + 2 > argc) { snd_seq_close(seq); usage(); exit(1); } if ((client = snd_seq_client_id(seq)) < 0) { snd_seq_close(seq); fprintf(stderr, _("can't get client id\n")); return 1; } /* set client info */ if (snd_seq_set_client_name(seq, "ALSA Connector") < 0) { snd_seq_close(seq); fprintf(stderr, _("can't set client info\n")); return 1; } /* set subscription */ if (snd_seq_parse_address(seq, &sender, argv[optind]) < 0) { snd_seq_close(seq); fprintf(stderr, _("invalid sender address %s\n"), argv[optind]); return 1; } if (snd_seq_parse_address(seq, &dest, argv[optind + 1]) < 0) { snd_seq_close(seq); fprintf(stderr, _("invalid destination address %s\n"), argv[optind + 1]); return 1; } 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, queue); snd_seq_port_subscribe_set_exclusive(subs, exclusive); snd_seq_port_subscribe_set_time_update(subs, convert_time); snd_seq_port_subscribe_set_time_real(subs, convert_real); if (command == UNSUBSCRIBE) { if (snd_seq_get_port_subscription(seq, subs) < 0) { snd_seq_close(seq); fprintf(stderr, _("No subscription is found\n")); return 1; } if (snd_seq_unsubscribe_port(seq, subs) < 0) { snd_seq_close(seq); fprintf(stderr, _("Disconnection failed (%s)\n"), snd_strerror(errno)); return 1; } } else { if (snd_seq_get_port_subscription(seq, subs) == 0) { snd_seq_close(seq); fprintf(stderr, _("Connection is already subscribed\n")); return 1; } if (snd_seq_subscribe_port(seq, subs) < 0) { snd_seq_close(seq); fprintf(stderr, _("Connection failed (%s)\n"), snd_strerror(errno)); return 1; } } snd_seq_close(seq); return 0; }