Exemplo n.º 1
0
void MidiAlsaDevice::close()
{
    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);

    // Changed by T356. This function appears to be called only by MidiPort::setMidiDevice(),
    //  which closes then opens the device.
    // Because the open flags are set BEFORE setMidiDevice() is called, we must ignore the flags.
    //
    // NOTE: Tested: The read unsubscribe works ok but not the write.
    //               As viewed in say, qjackctl, the connection is clearly lost,
    //                but strangely the events are still accepted, ie, playback notes
    //                are still heard etc. Tried an alsa midi device AND external fluidsynth inst.
    //
    //               Also, jack running and with jack midi disabled, we get messages like
    //                MidiAlsaDevice::0x84512c0 putEvent(): midi write error: No such device
    //                 dst 16:0
    //                only sometimes (not when playing notes), but with jack midi turned on,
    //                we don't get the messages. With jack stopped we get the messages
    //                no matter if jack midi is turned on or not.

    //if (_openFlags & 1) {
    //if (!(_openFlags & 1))
    {
        snd_seq_port_subscribe_set_sender(subs, &losPort);
        snd_seq_port_subscribe_set_dest(subs, &adr);

        // Already subscribed? Then unsubscribe.
        if (!snd_seq_get_port_subscription(alsaSeq, subs))
        {
            if (!snd_seq_unsubscribe_port(alsaSeq, subs))
                _writeEnable = false;
            else
                printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for writing\n");
        }
        else
            _writeEnable = false;
    }

    //if (_openFlags & 2) {
    //if (!(_openFlags & 2))
    {
        snd_seq_port_subscribe_set_dest(subs, &losPort);
        snd_seq_port_subscribe_set_sender(subs, &adr);

        // Already subscribed? Then unsubscribe.
        if (!snd_seq_get_port_subscription(alsaSeq, subs))
        {
            if (!snd_seq_unsubscribe_port(alsaSeq, subs))
                _readEnable = false;
            else
                printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for reading\n");
        }
        else
            _readEnable = false;
    }
}
/*
 * 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_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);
	for (; snd_seq_query_port_subscribers(seq, query) >= 0;
	     snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1)) {
		snd_seq_port_info_t *port;
		snd_seq_port_subscribe_t *subs;
		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);
		snd_seq_port_info_alloca(&port);
		if (snd_seq_get_any_port_info(seq, dest->client, dest->port, port) < 0)
			continue;
		if (!(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_WRITE))
			continue;
		if (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT)
			continue;
		snd_seq_port_subscribe_alloca(&subs);
		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);
		snd_seq_unsubscribe_port(seq, subs);
	}

	snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_WRITE);
	snd_seq_query_subscribe_set_index(query, 0);
	for (; snd_seq_query_port_subscribers(seq, query) >= 0;
	     snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1)) {
		snd_seq_port_info_t *port;
		snd_seq_port_subscribe_t *subs;
		const snd_seq_addr_t *dest = snd_seq_query_subscribe_get_root(query);
		const snd_seq_addr_t *sender = snd_seq_query_subscribe_get_addr(query);
		snd_seq_port_info_alloca(&port);
		if (snd_seq_get_any_port_info(seq, sender->client, sender->port, port) < 0)
			continue;
		if (!(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_READ))
			continue;
		if (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT)
			continue;
		snd_seq_port_subscribe_alloca(&subs);
		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);
		snd_seq_unsubscribe_port(seq, subs);
	}
}
Exemplo n.º 3
0
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");
}
Exemplo n.º 4
0
/* Remote device name is saved after first call (or rather the pointer to it,
 * so the actual string must not be deallocated); subsequent calls may use
 * NULL as the remote_device. */
int
midi_connect(int port, const char *remote_device)
{
  snd_seq_port_subscribe_t *sub;
  snd_seq_addr_t my_addr;
  snd_seq_addr_t remote_addr;
  static const char *saved_remote_device[MAX_PORTS] = { 0 };

  if (port >= MAX_PORTS) return -1;

  if (remote_device)
    saved_remote_device[port] = remote_device;
  else if (!saved_remote_device[port])
    /* Set to "" if first call does not intitialize it to remote_device */
    saved_remote_device[port] = "";

  dprintf("Client address %d:%d\n", client, port);

  snd_seq_port_subscribe_alloca(&sub);

  /* My address */
  my_addr.client = client;
  my_addr.port = ports[port];

  /* Other devices address */
  if (snd_seq_parse_address(seq, &remote_addr, saved_remote_device[port]) < 0) {
    dprintf("Can't locate destination device %s\n", saved_remote_device[port]);
    return -1;
  }

  /* We always attempt to set up subscription in both directions, regardless
   * of which error occurs when setting up the first direction. */

  /* Set up sender and destination in subscription. */
  snd_seq_port_subscribe_set_sender(sub, &my_addr);
  snd_seq_port_subscribe_set_dest(sub, &remote_addr);

  int res = subscribe(sub);

  /* And now, connection in other direction. */
  snd_seq_port_subscribe_set_sender(sub, &remote_addr);
  snd_seq_port_subscribe_set_dest(sub, &my_addr);

  int res2 = subscribe(sub);
  if (res == 0) res = res2; /* if first subscribe() had no error */

  return res;
}
Exemplo n.º 5
0
bool midibus::deinit_in( )
{

    /* temp return */
    int ret;
    
    snd_seq_port_subscribe_t *subs;
    snd_seq_port_subscribe_alloca(&subs);
    snd_seq_addr_t sender, dest;

    /* the destinatino 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 */
    ret = snd_seq_unsubscribe_port(m_seq, subs);

    if ( ret < 0 ){
        printf( "snd_seq_unsubscribe_port(%d:%d) error\n", m_dest_addr_client, m_dest_addr_port);
        return false;
    }

    return true;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
bool
midibus::deinit_in  ()
{
#ifdef SEQ64_HAVE_LIBASOUND
    snd_seq_port_subscribe_t * subs;
    snd_seq_port_subscribe_alloca(&subs);

    snd_seq_addr_t sender;                                  /* output       */
    sender.client = m_dest_addr_client;
    sender.port = m_dest_addr_port;
    snd_seq_port_subscribe_set_sender(subs, &sender);

    snd_seq_addr_t dest;                                    /* input        */
    dest.client = m_local_addr_client;
    dest.port = m_local_addr_port;
    snd_seq_port_subscribe_set_dest(subs, &dest);

    snd_seq_port_subscribe_set_queue(subs, m_queue);        /* master queue */
    snd_seq_port_subscribe_set_time_update(subs, 1);        /* get ticks    */

    int result = snd_seq_unsubscribe_port(m_seq, subs);     /* subscribe    */
    if (result < 0)
    {
        fprintf
        (
            stderr, "snd_seq_unsubscribe_port(%d:%d) error\n",
            m_dest_addr_client, m_dest_addr_port
        );
        return false;
    }
#endif  // SEQ64_HAVE_LIBASOUND
    return true;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
void MIDIOut::unsubscribeDevice(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_unsubscribe_port(m_alsa, sub);
}
Exemplo n.º 10
0
void AlsaMidiInputThread::unsubscribeDevice(AlsaMidiInputDevice* device)
{
    qDebug() << Q_FUNC_INFO;

    Q_ASSERT(device != NULL);

    /* Unsubscribe events from the device */
    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_unsubscribe_port(m_alsa, sub);
}
Exemplo n.º 11
0
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);
}
Exemplo n.º 12
0
void AlsaMidiOutputDevice::close()
{
    qDebug() << Q_FUNC_INFO;
    m_open = false;

    Q_ASSERT(m_sender_address != NULL);
    Q_ASSERT(m_receiver_address != NULL);

    /* Unsubscribe 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_unsubscribe_port(m_alsa, sub);
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
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);
}
Exemplo n.º 17
0
    /**
     * 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);
    }
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
0
// Disconnection primitive.
bool qjackctlAlsaConnect::disconnectPorts (
	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_unsubscribe_port(pAlsaSeq, pAlsaSubs) >= 0);

#else

	return false;

#endif	// CONFIG_ALSA_SEQ
}
Exemplo n.º 20
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;
}
Exemplo n.º 21
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);
}
Exemplo n.º 22
0
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);
	}
}
Exemplo n.º 23
0
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;
}