コード例 #1
0
ファイル: alsamidi.cpp プロジェクト: Adamiko/los
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");
}
コード例 #2
0
ファイル: port.c プロジェクト: Llefjord/jack1
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;
}
コード例 #3
0
ファイル: midibus.cpp プロジェクト: EQ4/sequencer24
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;
}
コード例 #4
0
ファイル: midiout-unix.cpp プロジェクト: speakman/qlc
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);
}
コード例 #5
0
ファイル: seqmid.c プロジェクト: NieHao/R7000
/**
 * \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);
}
コード例 #6
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);
}
コード例 #7
0
/* 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;
}
コード例 #8
0
ファイル: alsa.hpp プロジェクト: 5tan/cxxmidi
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;
}
コード例 #9
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;
}
コード例 #10
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();
}
コード例 #11
0
/* 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);
}
コード例 #12
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);
    }
コード例 #13
0
ファイル: alsa_seqmidi.c プロジェクト: Andux/jack2
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;
}
コード例 #14
0
// 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
}
コード例 #15
0
ファイル: seq-decoder.c プロジェクト: tiwai/alsa-lib
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);
	}
}
コード例 #16
0
ファイル: qxgeditMidiDevice.cpp プロジェクト: rncbc/qxgedit
// 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);
}
コード例 #17
0
ファイル: midi_alsa.c プロジェクト: damajor/play-dune
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;
}
コード例 #18
0
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() */
コード例 #19
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;
}