示例#1
0
void MidiPort::setMidiDevice(MidiDevice* dev)
{
    // close old device
    if (_device)
    {
        _device->setPort(-1);
        _device->close();
    }
    // set-up new device
    if (dev)
    {
        for (int i = 0; i < kMaxMidiPorts; ++i)
        {
            MidiPort* mp = &midiPorts[i];
            if (mp->device() == dev)
            {
                // move device
                _state = mp->state();
                mp->clearDevice();
                break;
            }
        }
        _device = dev;
        _state = _device->open();
        _device->setPort(portno());
    }
    else
        // dev is null, clear this device
        clearDevice();
}
示例#2
0
文件: pyapi.cpp 项目: OpenGanesh/oom
PyObject* getMidiControllerValue(PyObject*, PyObject* args)
{
	const char* trackname;
	int ctrltype;

	if (!PyArg_ParseTuple(args, "si", &trackname, &ctrltype))
	{
		return NULL;
	}

	Track* t = song->findTrack(QString(trackname));
	if (t == NULL)
		return NULL;

	if (t->isMidiTrack() == false)
	{
		Py_INCREF(Py_None);
		return Py_None;
	}

	MidiTrack* track = (MidiTrack*) t;
	int channel = track->outChannel();
	int outport = track->outPort();
	MidiPort* mp = &midiPorts[outport];
	if (mp == NULL)
		return Py_BuildValue("i", -1);

	int value = mp->hwCtrlState(channel, ctrltype);
	return Py_BuildValue("i", value);
}
示例#3
0
文件: part.cpp 项目: ViktorNova/los
void addPortCtrlEvents(Event& event, Part* part, bool doClones)/*{{{*/
{
    // Traverse and process the clone chain ring until we arrive at the same part again.
    // The loop is a safety net.
    // Update: Due to the varying calls, and order of, incARefcount, (msg)ChangePart, replaceClone, and remove/addPortCtrlEvents,
    //  we can not rely on the reference count as a safety net in these routines. We will just have to trust the clone chain.
    Part* p = part;
    //int j = doClones ? p->cevents()->arefCount() : 1;
    //if(j > 0)
    {
        //for(int i = 0; i < j; ++i)
        while (1)
        {
            // Added by Tim. p3.3.6
            //printf("addPortCtrlEvents i:%d %s %p events %p refs:%d arefs:%d\n", i, p->name().toLatin1().constData(), p, part->cevents(), part->cevents()->refCount(), j);

            Track* t = p->track();
            if (t)
            {
                MidiTrack* mt = (MidiTrack*) t;
                int port = mt->outPort();
                //const EventList* el = p->cevents();
                unsigned len = p->lenTick();
                //for(ciEvent ie = el->begin(); ie != el->end(); ++ie)
                //{
                //const Event& ev = ie->second;
                // Added by Tim. p3.3.6
                //printf("addPortCtrlEvents %s len:%d end:%d etick:%d\n", p->name().toLatin1().constData(), p->lenTick(), p->endTick(), event.tick());

                // Do not add events which are past the end of the part.
                if (event.tick() >= len)
                    break;

                if (event.type() == Controller)
                {
                    int ch = mt->outChannel();
                    int tck = event.tick() + p->tick();
                    int cntrl = event.dataA();
                    int val = event.dataB();
                    MidiPort* mp = &midiPorts[port];

                    mp->setControllerVal(ch, tck, cntrl, val, p);
                }
                //}
            }

            if (!doClones)
                break;
            // Get the next clone in the chain ring.
            p = p->nextClone();
            // Same as original part? Finished.
            if (p == part)
                break;
        }
    }
}/*}}}*/
示例#4
0
void initMidiPorts()
{
    //TODO: Remove the need for this code
    //We should populate the losMidiPort hash with ports as we create them
    for (int i = 0; i < kMaxMidiPorts; ++i)
    {
        MidiPort* port = &midiPorts[i];
        ///port->setInstrument(genericMidiInstrument);
        port->setInstrument(registerMidiInstrument("GM")); // Changed by Tim.
    }
}
示例#5
0
void initMidiPorts()
{
	//TODO: Remove the need for this code
	//We should populate the oomMidiPort hash with ports as we create them
	for (int i = 0; i < MIDI_PORTS; ++i)
	{
		MidiPort* port = &midiPorts[i];
		///port->setInstrument(genericMidiInstrument);
		port->setInstrument(registerMidiInstrument("GM")); // Changed by Tim.
		port->syncInfo().setPort(i);
	}
}
示例#6
0
文件: part.cpp 项目: ViktorNova/los
void removePortCtrlEvents(Part* part, bool doClones)/*{{{*/
{
    // Traverse and process the clone chain ring until we arrive at the same part again.
    // The loop is a safety net.
    // Update: Due to the varying calls, and order of, incARefcount, (msg)ChangePart, replaceClone, and remove/addPortCtrlEvents,
    //  we can not rely on the reference count as a safety net in these routines. We will just have to trust the clone chain.
    Part* p = part;
    //int j = doClones ? p->cevents()->arefCount() : 1;
    //if(j > 0)
    {
        //for(int i = 0; i < j; ++i)
        while (1)
        {
            MidiTrack* t = p->track();
            if (t)
            {
                MidiTrack* mt = (MidiTrack*) t;
                int port = mt->outPort();
                const EventList* el = p->cevents();
                //unsigned len = p->lenTick();
                for (ciEvent ie = el->begin(); ie != el->end(); ++ie)
                {
                    const Event& ev = ie->second;
                    // Added by T356. Do not remove events which are past the end of the part.
                    // No, actually, do remove ALL of them belonging to the part.
                    // Just in case there are stray values left after the part end.
                    //if(ev.tick() >= len)
                    //  break;

                    if (ev.type() == Controller)
                    {
                        int ch = mt->outChannel();
                        int tck = ev.tick() + p->tick();
                        int cntrl = ev.dataA();
                        MidiPort* mp = &midiPorts[port];

                        mp->deleteController(ch, tck, cntrl, p);
                    }
                }
            }

            if (!doClones)
                break;
            // Get the next clone in the chain ring.
            p = p->nextClone();
            // Same as original part? Finished.
            if (p == part)
                break;
        }
    }
}/*}}}*/
示例#7
0
文件: conf.cpp 项目: Adamiko/los
static void readSeqConfiguration(Xml& xml)
{
    //bool updatePorts = false;
    for (;;)
    {
        Xml::Token token = xml.parse();
        if (token == Xml::Error || token == Xml::End)
            break;
        const QString& tag = xml.s1();
        switch (token)
        {
            case Xml::TagStart:
                if (tag == "midiport")
                {
                    //updatePorts = true;
                    readConfigMidiPort(xml);
                }
                else if (tag == "rcStop")
                    rcStopNote = xml.parseInt();
                else if (tag == "rcEnable")
                    rcEnable = xml.parseInt();
                else if (tag == "rcRecord")
                    rcRecordNote = xml.parseInt();
                else if (tag == "rcGotoLeft")
                    rcGotoLeftMarkNote = xml.parseInt();
                else if (tag == "rcPlay")
                    rcPlayNote = xml.parseInt();
                else
                    xml.skip(tag);
                break;
            case Xml::TagEnd:
                if (tag == "sequencer")
                {
                    //All Midiports have been read so put all the unconfigured ports in the id list
                    //if(updatePorts)
                    //{
                        for(int i = 0; i < MIDI_PORTS; ++i)
                        {
                            MidiPort *mp = &midiPorts[i];
                            if(!losMidiPorts.contains(mp->id()))
                                losMidiPorts.insert(mp->id(), mp);
                        }
                    //}
                    return;
                }
            default:
                break;
        }
    }
}
示例#8
0
void MidiPortMenu::updateMenu()
{
	MidiPort * mp = castModel<MidiPort>();
	const MidiPort::Map & map = ( m_mode == MidiPort::Input ) ?
				mp->readablePorts() : mp->writablePorts();
	clear();
	for( MidiPort::Map::ConstIterator it = map.begin();
							it != map.end(); ++it )
	{
		QAction * a = addAction( it.key() );
		a->setCheckable( true );
		a->setChecked( it.value() );
	}
}
示例#9
0
文件: utils.cpp 项目: 87maxi/oom
int getFreeMidiPort()/*{{{*/
{
	int rv = -1;
	for (int i = 0; i < MIDI_PORTS; ++i)
	{
		MidiPort* mp = &midiPorts[i];
		//Use the first unconfigured port
		if (!mp->device())
		{
			rv = i;
			break;
		}
	}
	return rv;
}/*}}}*/
示例#10
0
文件: route.cpp 项目: 87maxi/oom
//Midi Port Route
Route::Route(int port, int ch)
{
	track = 0;
	midiPort = port;
	channel = ch;
	channels = -1;
	remoteChannel = -1;
	type = MIDI_PORT_ROUTE;
	trackId = -1;
	if(midiPort >= 0 && midiPort < MIDI_PORTS)
	{
		MidiPort* mp = &midiPorts[midiPort];
		midiPortId = mp->id();
	}
}
示例#11
0
QMenu* midiPortsPopup(QWidget* parent, int checkPort)
{
	QMenu* p = new QMenu(parent);
	for (int i = 0; i < MIDI_PORTS; ++i)
	{
		MidiPort* port = &midiPorts[i];
		QString name;
		name.sprintf("%d:%s", port->portno() + 1, port->portname().toLatin1().constData());
		QAction *act = p->addAction(name);
		act->setData(i);

		if (i == checkPort)
			act->setChecked(true);
	}
	return p;
}
示例#12
0
文件: midi.cpp 项目: faesong/oom
void Audio::panic()
{
	for (int i = 0; i < MIDI_PORTS; ++i)
	{
		MidiPort* port = &midiPorts[i];
		if (port == 0) // ??
			continue;
		for (int chan = 0; chan < MIDI_CHANNELS; ++chan)
		{
			if (debugMsg)
				 printf("send all sound of to midi port %d channel %d\n", i, chan);
			port->sendEvent(MidiPlayEvent(0, i, chan, ME_CONTROLLER, CTRL_ALL_SOUNDS_OFF, 0), true);
			port->sendEvent(MidiPlayEvent(0, i, chan, ME_CONTROLLER, CTRL_RESET_ALL_CTRL, 0), true);
		}
	}
}
示例#13
0
void MidiInstrument::reset(int portNo, MidiType)
{
    MidiPort* port = &midiPorts[portNo];
    MidiPlayEvent ev;
    ev.setType(0x90);
    ev.setPort(portNo);
    ev.setTime(0);
    for (int chan = 0; chan < kMaxMidiChannels; ++chan)
    {
        ev.setChannel(chan);
        for (int pitch = 0; pitch < 128; ++pitch)
        {
            ev.setA(pitch);
            ev.setB(0);
            port->sendEvent(ev);
        }
    }
}
示例#14
0
void MidiInstrument::reset(int portNo, MType)
{
    MidiPlayEvent ev;
    ev.setType(0x90);
    MidiPort* port = &midiPorts[portNo];
    if (port == 0)
        return;
    ev.setPort(portNo);
    for (int chan = 0; chan < MIDI_CHANNELS; ++chan)
    {
        ev.setChannel(chan);
        for (int pitch = 0; pitch < 128; ++pitch)
        {
            ev.setA(pitch);
            ev.setB(0);
            port->sendEvent(ev);
        }
    }
}
示例#15
0
void MidiPort::setMidiDevice(MidiDevice* dev)
{
    // close old device
	if (_device)
	{
        if (_device->isSynthPlugin())
		{
			_instrument = genericMidiInstrument;
		}
		_device->setPort(-1);
		_device->close();
	}
    // set-up new device
	if (dev)
	{
		for (int i = 0; i < MIDI_PORTS; ++i)
		{
			MidiPort* mp = &midiPorts[i];
			if (mp->device() == dev)
			{
                if (dev->isSynthPlugin())
					mp->setInstrument(genericMidiInstrument);
				// move device
				_state = mp->state();
				mp->clearDevice();
				break;
			}
		}
		_device = dev;
        if (_device->isSynthPlugin())
		{
            SynthPluginDevice* s = (SynthPluginDevice*) _device;
			_instrument = s;
            //_instrument = genericMidiInstrument;
		}
		_state = _device->open();
		_device->setPort(portno());
	}
	else
        // dev is null, clear this device
		clearDevice();
}
示例#16
0
文件: route.cpp 项目: 87maxi/oom
//Route From settings
//Used mostly for restoring routes from the xml file
Route::Route(const QString& s, bool dst, int ch, int rtype)
{
	trackId = -1;
	midiPort = -1;
	midiPortId = -1;
	Route node(name2route(s, dst, rtype));
	channel = node.channel;
	if (channel == -1)
		channel = ch;
	channels = node.channels;
	remoteChannel = node.remoteChannel;
	type = node.type;
	if (type == TRACK_ROUTE)
	{
		track = node.track;
		if(track)
			trackId = track->id();
	}
	else if (type == JACK_ROUTE)
	{
		jackPort = node.jackPort;
	}
	else if (type == MIDI_DEVICE_ROUTE)
	{
		device = node.device;
	}
	else if (type == MIDI_PORT_ROUTE)
	{
		track = 0;
		midiPort = node.midiPort;
		if(midiPort >= 0 && midiPort < MIDI_PORTS)
		{
			MidiPort* mp = &midiPorts[midiPort];
			midiPortId = mp->id();
		}
	}
}
示例#17
0
文件: conf.cpp 项目: Adamiko/los
static void readController(Xml& xml, int midiPort, int channel)
{
    int id = 0;
    int val = CTRL_VAL_UNKNOWN;

    for (;;)
    {
        Xml::Token token = xml.parse();
        QString tag = xml.s1();
        switch (token)
        {
            case Xml::TagStart:
                if (tag == "val")
                    val = xml.parseInt();
                else
                    xml.skip(tag);
                break;
            case Xml::Attribut:
                if (tag == "id")
                    id = xml.s2().toInt();
                break;
            case Xml::TagEnd:
                if (tag == "controller")
                {
                    MidiPort* port = &midiPorts[midiPort];
                    //port->addManagedController(channel, id);
                    val = port->limitValToInstrCtlRange(id, val);
                    // The value here will actually be sent to the device LATER, in MidiPort::setMidiDevice()
                    port->setHwCtrlState(channel, id, val);
                    return;
                }
            default:
                return;
        }
    }
}
示例#18
0
bool LOS::importMidi(const QString name, bool merge)/*{{{*/
{
    bool popenFlag;
    FILE* fp = fileOpen(this, name, QString(".mid"), "r", popenFlag);
    if (fp == 0)
        return true;
    MidiFile mf(fp);
    bool rv = mf.read();
    popenFlag ? pclose(fp) : fclose(fp);
    if (rv)
    {
        QString s(tr("reading midifile\n  "));
        s += name;
        s += tr("\nfailed: ");
        s += mf.error();
        QMessageBox::critical(this, QString("LOS"), s);
        return rv;
    }
    //
    //  evaluate song Type (GM, XG, GS, unknown)
    //
    MidiType t = song->midiType();
    if (!merge)
    {
        t = mf.midiType();
        song->setMidiType(t);
    }
    MidiInstrument* instr = 0;
    for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
    {
        MidiInstrument* mi = *i;
        if ((mi->iname() == "GM" && ((t == MIDI_TYPE_NULL) || (t == MIDI_TYPE_GM))) ||
            (mi->iname() == "GS" &&   t == MIDI_TYPE_GS) ||
            (mi->iname() == "XG" &&   t == MIDI_TYPE_XG))
        {
            instr = mi;
            break;
        }
    }
    if (instr == 0)
    {
        // the standard instrument files (GM, GS, XG) must be present
        printf("no instrument, type %d\n", t);
        return true;
        //abort();
    }

    MidiFileTrackList* etl = mf.trackList();
    int division = mf.division();

    //
    // create MidiTrack and copy events to ->events()
    //    - combine note on/off events
    //    - calculate tick value for internal resolution
    //
    int mPort = getFreeMidiPort();
    for (iMidiFileTrack t = etl->begin(); t != etl->end(); ++t)
    {
        MPEventList* el = &((*t)->events);
        if (el->empty())
            continue;
        //
        // if we split the track, SYSEX and META events go into
        // the first target track

        bool first = true;
        QList<QPair<int, int> > portChannelList;
        iMPEvent i;
        for(i = el->begin(); i != el->end(); i++)
        {
            if (i->type() != ME_SYSEX && i->type() != ME_META)
            {
                int chan = i->channel();
                int port = i->port();
                if(portChannelList.isEmpty() || !portChannelList.contains(qMakePair(chan, port)))
                {
                    portChannelList.append(qMakePair(chan, port));

                    MidiTrack* track = new MidiTrack();
                    track->setDefaultName();
                    track->setMasterFlag(true);

                    if(config.partColorNames[lastTrackPartColorIndex].contains("menu:", Qt::CaseSensitive))
                        lastTrackPartColorIndex ++;

                    track->setDefaultPartColor(lastTrackPartColorIndex);
                    lastTrackPartColorIndex ++;

                    if(lastTrackPartColorIndex == NUM_PARTCOLORS)
                        lastTrackPartColorIndex = 1;

                    //Set track channel so buildMidiEventList can match the event to a channel
                    track->setOutChannel(chan);
                    track->setOutPort(mPort);

                    MidiPort* mport = &midiPorts[track->outPort()];
                    // this overwrites any instrument set for this port:
                    mport->setInstrument(instr);

                    EventList* mel = track->events();
                    buildMidiEventList(mel, el, track, division, first, false, false);

                    first = false;

                    processTrack(track);

                    //Update track to channel 1
                    //99% of all midi we import will be alien to our setup anyway,
                    //so I'm making it easy for the user to just set the Instrument and go
                    track->setOutChannel(0);

                    song->insertTrack(track, -1);
                    mPort++;
                    //FIXME: Provice a non-iterative way to do this using the new losMidiPorts hash
                    //Or maintain a list of configured or inuse ports
                    while((&midiPorts[mPort])->device() && mPort < kMaxMidiPorts)
                        mPort++;//Just incase we have a configured port after an empty one
                }
            }
        }
        if (first)
        {
            //
            // track does only contain non-channel messages
            // (SYSEX or META)
            //
            MidiTrack* track = new MidiTrack();
            track->setDefaultName();
            track->setMasterFlag(true);
            track->setOutChannel(0);
            track->setOutPort(mPort);

            if(config.partColorNames[lastTrackPartColorIndex].contains("menu:", Qt::CaseSensitive))
                lastTrackPartColorIndex ++;

            track->setDefaultPartColor(lastTrackPartColorIndex);
            lastTrackPartColorIndex ++;

            if(lastTrackPartColorIndex == NUM_PARTCOLORS)
                lastTrackPartColorIndex = 1;

            EventList* mel = track->events();
            // Do SysexMeta. Don't do loops.
            // TODO: Properly support sysex dumps
            buildMidiEventList(mel, el, track, division, true, false, false);
            processTrack(track);
            song->insertTrack(track, -1);
            mPort++;
            while((&midiPorts[mPort])->device() && mPort < kMaxMidiPorts)
                mPort++;
        }
    }

    if (!merge)
    {
        MidiTrackList* tl = song->tracks();
        if (!tl->empty())
        {
            MidiTrack* track = tl->front();
            track->setSelected(true);
        }
        song->initLen();

        int z, n;
        sigmap.timesig(0, z, n);

        int tempo = tempomap.tempo(0);
        transport->setTimesig(z, n);
        transport->setTempo(tempo);

        bool masterF = !tempomap.empty();
        song->setMasterFlag(masterF);
        transport->setMasterFlag(masterF);

        song->updatePos();

        composer->reset();
    }
    else
    {
        song->initLen();
    }

    return false;
}/*}}}*/
示例#19
0
void MPConfig::rbClicked(QTableWidgetItem* item)
{
    if (item == 0)
        return;
    QString id = item->tableWidget()->item(item->row(), DEVCOL_NO)->text();
    int no = atoi(id.toLatin1().constData()) - 1;
    if (no < 0 || no >= kMaxMidiPorts)
        return;

    int n;
    MidiPort* port = &midiPorts[no];
    MidiDevice* dev = port->device();
    int rwFlags = dev ? dev->rwFlags() : 0;
    int openFlags = dev ? dev->openFlags() : 0;
    QTableWidget* listView = item->tableWidget();
    QPoint ppt = listView->visualItemRect(item).bottomLeft();
    QPoint mousepos = QCursor::pos();

    int col = item->column();
    ppt += QPoint(0, listView->horizontalHeader()->height());

    ppt = listView->mapToGlobal(ppt);

    switch (col)
    {
        case DEVCOL_GUI:
            if (dev == 0)
                //break;
                return;
            // falkTX, we don't want this in the connections manager
            //if (port->hasGui())
            //{
            //	port->instrument()->showGui(!port->guiVisible());
            //	item->setIcon(port->guiVisible() ? QIcon(*dotIcon) : QIcon(*dothIcon));
            //}
            //break;
            return;

        case DEVCOL_CACHE_NRPN:
            if (!dev)
                return;
            dev->setCacheNRPN(!dev->cacheNRPN());
            item->setIcon(dev->cacheNRPN() ? QIcon(*dotIcon) : QIcon(*dothIcon));

            return;

        case DEVCOL_REC:
            if (dev == 0 || !(rwFlags & 2))
                return;
            openFlags ^= 0x2;
            dev->setOpenFlags(openFlags);
            midiSeq->msgSetMidiDevice(port, dev); // reopen device
            item->setIcon(openFlags & 2 ? QIcon(*dotIcon) : QIcon(*dothIcon));

            if (dev->deviceType() == MidiDevice::JACK_MIDI)
            {
                if (dev->openFlags() & 2)
                {
                    item->tableWidget()->item(item->row(), DEVCOL_INROUTES)->setText(tr("in"));
                }
                else
                {
                    item->tableWidget()->item(item->row(), DEVCOL_INROUTES)->setText("");
                }
            }

            return;

        case DEVCOL_PLAY:
            if (dev == 0 || !(rwFlags & 1))
                return;
            openFlags ^= 0x1;
            dev->setOpenFlags(openFlags);
            midiSeq->msgSetMidiDevice(port, dev); // reopen device
            item->setIcon(openFlags & 1 ? QIcon(*dotIcon) : QIcon(*dothIcon));

            if (dev->deviceType() == MidiDevice::JACK_MIDI)
            {
                if (dev->openFlags() & 1)
                {
                    item->tableWidget()->item(item->row(), DEVCOL_OUTROUTES)->setText(tr("out"));
                }
                else
                {
                    item->tableWidget()->item(item->row(), DEVCOL_OUTROUTES)->setText("");
                }
            }

            return;

        case DEVCOL_INROUTES:
        case DEVCOL_OUTROUTES:
        {
            if (!checkAudioDevice())
                return;

            if (audioDevice->deviceType() != AudioDevice::JACK_AUDIO) //Only if Jack is running.
                return;

            if (!dev)
                return;

            // Only Jack midi devices.
            if (dev->deviceType() != MidiDevice::JACK_MIDI)
                return;

            if (!(dev->openFlags() & ((col == DEVCOL_OUTROUTES) ? 1 : 2)))
                return;

            RouteList* rl = (col == DEVCOL_OUTROUTES) ? dev->outRoutes() : dev->inRoutes(); // p3.3.55
            QMenu* pup = 0;
            int gid = 0;
            std::list<QString> sl;
            pup = new QMenu(this);
            //A temporary Route to us for matching later
            QString currentRoute("");
            bool routeSelected = false;

_redisplay:
            pup->clear();
            gid = 0;

            // Jack input ports if device is writable, and jack output ports if device is readable.
            sl = (col == DEVCOL_OUTROUTES) ? audioDevice->inputPorts(true, _showAliases) : audioDevice->outputPorts(true, _showAliases);

            QAction* act;

            act = pup->addAction(tr("Show first aliases"));
            act->setData(gid);
            act->setCheckable(true);
            act->setChecked(_showAliases == 0);
            ++gid;

            act = pup->addAction(tr("Show second aliases"));
            act->setData(gid);
            act->setCheckable(true);
            act->setChecked(_showAliases == 1);
            ++gid;

            pup->addSeparator();
            for (std::list<QString>::iterator ip = sl.begin(); ip != sl.end(); ++ip)
            {
                act = pup->addAction(*ip);
                act->setData(gid);
                act->setCheckable(true);

                Route rt(*ip, (col == DEVCOL_OUTROUTES), -1, Route::JACK_ROUTE);
                for (iRoute ir = rl->begin(); ir != rl->end(); ++ir)
                {
                    if (*ir == rt)
                    {
                        currentRoute = (*ir).name();
                        act->setChecked(true);
                        routeSelected = true;
                        break;
                    }
                }
                ++gid;
            }

            act = pup->exec(ppt);
            if (act)
            {
                n = act->data().toInt();
                if (n == 0) // Show first aliases
                {
                    if (_showAliases == 0)
                        _showAliases = -1;
                    else
                        _showAliases = 0;
                    goto _redisplay; // Go back
                }
                else if (n == 1) // Show second aliases
                {
                    if (_showAliases == 1)
                        _showAliases = -1;
                    else
                        _showAliases = 1;
                    goto _redisplay; // Go back
                }

                QString s(act->text());

                if (col == DEVCOL_OUTROUTES) // Writable
                {
                    Route srcRoute(dev, -1);
                    Route dstRoute(s, true, -1, Route::JACK_ROUTE);
                    if(routeSelected && currentRoute == s)
                    {
                        //it will alread be handled by an unchecked operation
                        routeSelected = false;
                    }

                    iRoute iir = rl->begin();
                    for (; iir != rl->end(); ++iir)
                    {
                        if (*iir == dstRoute)
                            break;
                    }

                    if (iir != rl->end())
                    {
                        // disconnect
                        audio->msgRemoveRoute(srcRoute, dstRoute);
                    }
                    else
                    {
                        // connect
                        audio->msgAddRoute(srcRoute, dstRoute);
                    }
                    if(routeSelected)
                    {
                        iRoute selr = rl->begin();
                        for (; selr != rl->end(); ++selr)
                        {
                            //clean up the routing list as something was selected that was not the current so delete the old route
                            if((*selr).name() == currentRoute)
                            {
                                audio->msgRemoveRoute(srcRoute, (*selr));
                                break;
                            }
                        }
                    }

                }
                else
                {
                    Route srcRoute(s, false, -1, Route::JACK_ROUTE);
                    Route dstRoute(dev, -1);

                    iRoute iir = rl->begin();
                    for (; iir != rl->end(); ++iir)
                    {
                        if (*iir == srcRoute)
                            break;
                    }
                    if (iir != rl->end())
                        // disconnect
                        audio->msgRemoveRoute(srcRoute, dstRoute);
                    else
                        // connect
                        audio->msgAddRoute(srcRoute, dstRoute);
                }

                audio->msgUpdateSoloStates();
                song->update(SC_ROUTE);
            }

            delete pup;
        }
            return;

        case DEVCOL_DEF_IN_CHANS:
        case DEVCOL_DEF_OUT_CHANS:
        {
        }
            //break;
            return;

        case DEVCOL_NAME:
        {
            //printf("MPConfig::rbClicked DEVCOL_NAME\n");

            // Did we click in the text area?
            // NOTE: this needs the +15 pixels to make up for padding in the stylesheet.
            if ((mousepos.x() - (ppt.x() + 15)) > buttondownIcon->width())
            {
                // Start the renaming of the cell...
                QModelIndex current = item->tableWidget()->currentIndex();
                if (item->flags() & Qt::ItemIsEditable)
                    item->tableWidget()->edit(current.sibling(current.row(), DEVCOL_NAME));

                return;
            }
            else
            {// We clicked the 'down' button.
                QMenu* pup = new QMenu(this);

                QAction* act;

                act = pup->addAction(tr("Create") + QT_TRANSLATE_NOOP("@default", " Jack") + tr(" device"));
                act->setData(0);

                typedef std::map<std::string, int > asmap;
                typedef std::map<std::string, int >::iterator imap;

                asmap mapALSA;
                asmap mapJACK;

                int aix = 0x10000000;
                int jix = 0x20000000;
                for (iMidiDevice i = midiDevices.begin(); i != midiDevices.end(); ++i)
                {
                    if ((*i)->deviceType() == MidiDevice::ALSA_MIDI)
                    {
                        mapALSA.insert(std::pair<std::string, int> (std::string((*i)->name().toLatin1().constData()), aix));
                        ++aix;
                    }
                    else if ((*i)->deviceType() == MidiDevice::JACK_MIDI)
                    {
                        mapJACK.insert(std::pair<std::string, int> (std::string((*i)->name().toLatin1().constData()), jix));
                        ++jix;
                    }
                    else
                        printf("MPConfig::rbClicked unknown midi device: %s\n", (*i)->name().toLatin1().constData());
                }

                pup->addSeparator();
                pup->addAction(new MenuTitleItem(QT_TRANSLATE_NOOP("@default", "ALSA:"), pup));

                for (imap i = mapALSA.begin(); i != mapALSA.end(); ++i)
                {
                    int idx = i->second;
                    QString s(i->first.c_str());
                    MidiDevice* md = midiDevices.find(s, MidiDevice::ALSA_MIDI);
                    if (md)
                    {
                        if (md->deviceType() != MidiDevice::ALSA_MIDI)
                            continue;

                        act = pup->addAction(QT_TRANSLATE_NOOP("@default", md->name()));
                        act->setData(idx);
                        act->setCheckable(true);
                        act->setChecked(md == dev);
                    }
                }

                pup->addSeparator();
                pup->addAction(new MenuTitleItem(QT_TRANSLATE_NOOP("@default", "JACK:"), pup));

                for (imap i = mapJACK.begin(); i != mapJACK.end(); ++i)
                {
                    int idx = i->second;
                    QString s(i->first.c_str());
                    MidiDevice* md = midiDevices.find(s, MidiDevice::JACK_MIDI);
                    if (md)
                    {
                        if (md->deviceType() != MidiDevice::JACK_MIDI)
                            continue;

                        act = pup->addAction(QT_TRANSLATE_NOOP("@default", md->name()));
                        act->setData(idx);
                        act->setCheckable(true);
                        act->setChecked(md == dev);
                    }
                }

                act = pup->exec(ppt);
                if (!act)
                {
                    delete pup;
                    return;
                }

                n = act->data().toInt();
                //printf("MPConfig::rbClicked n:%d\n", n);

                MidiDevice* sdev = 0;
                if (n < 0x10000000)
                {
                    delete pup;
                    if (n <= 2)
                    {
                        sdev = MidiJackDevice::createJackMidiDevice();

                        if (sdev)
                        {
                            int of = 3;
                            switch (n)
                            {
                                case 0: of = 0; //3; Set the open flags of the midiDevice this should be off by default
                                    break;
                                case 1: of = 2;
                                    break;
                                case 2: of = 1;
                                    break;
                            }
                            sdev->setOpenFlags(of);
                        }
                    }
                }
                else
                {
                    int typ;
                    if (n < 0x20000000)
                        typ = MidiDevice::ALSA_MIDI;
                    else if (n < 0x30000000)
                        typ = MidiDevice::JACK_MIDI;
                    else
                        typ = MidiDevice::UNKNOWN_MIDI;

                    sdev = midiDevices.find(act->text(), typ);
                    delete pup;

                    // Is it the current device? Reset it to <none>.
                    // falkTX, handle synths properly here
                    if (sdev == dev)
                    {
                        sdev = 0;
                    }
                    else
                    {
                    }
                }

                midiSeq->msgSetMidiDevice(port, sdev);
                los->changeConfig(true); // save configuration file
                song->update();
            }
        }
            //break;
            return;

        case DEVCOL_INSTR:
        {
            if (instrPopup == 0)
                instrPopup = new QMenu(this);
            instrPopup->clear();
            for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
            {
                instrPopup->addAction((*i)->iname());
            }

            QAction* act = instrPopup->exec(ppt, 0);
            if (!act)
                return;
            QString s = act->text();
            item->tableWidget()->item(item->row(), DEVCOL_INSTR)->setText(s);
            for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
            {
                if ((*i)->iname() == s)
                {
                    port->setInstrument(*i);
                    break;
                }
            }
            song->update();
        }
            return;
    }
}
示例#20
0
void MPConfig::songChanged(int flags)
{
    // Is it simply a midi controller value adjustment? Forget it.
    if (flags == SC_MIDI_CONTROLLER)
        return;

    // Get currently selected index...
    int no = -1;
    QTableWidgetItem* sitem = mdevView->currentItem();
    if (sitem)
    {
        QString id = sitem->tableWidget()->item(sitem->row(), DEVCOL_NO)->text();
        no = atoi(id.toLatin1().constData()) - 1;
        if (no < 0 || no >= kMaxMidiPorts)
            no = -1;
    }

    sitem = 0;
    for (int i = kMaxMidiPorts - 1; i >= 0; --i)
    {
        mdevView->blockSignals(true); // otherwise itemChanged() is triggered and bad things happen.
        MidiPort* port = &midiPorts[i];
        MidiDevice* dev = port->device();
        QString s;
        s.setNum(i + 1);
        QTableWidgetItem* itemno = mdevView->item(i, DEVCOL_NO);
        QTableWidgetItem* itemstate = mdevView->item(i, DEVCOL_STATE);
        itemstate->setText(port->state());
        QTableWidgetItem* iteminstr = mdevView->item(i, DEVCOL_INSTR);
        QString instrumentName = port->instrument() ? port->instrument()->iname() : tr("<unknown>");
        iteminstr->setText(instrumentName);
        iteminstr->setToolTip(instrumentName);
        QTableWidgetItem* itemname = mdevView->item(i, DEVCOL_NAME);
        QTableWidgetItem* itemgui = mdevView->item(i, DEVCOL_GUI);
        QTableWidgetItem* itemfb = mdevView->item(i, DEVCOL_CACHE_NRPN);
        QTableWidgetItem* itemrec = mdevView->item(i, DEVCOL_REC);
        QTableWidgetItem* itemplay = mdevView->item(i, DEVCOL_PLAY);
        QTableWidgetItem* itemout = mdevView->item(i, DEVCOL_OUTROUTES);
        QTableWidgetItem* itemin = mdevView->item(i, DEVCOL_INROUTES);
        QTableWidgetItem* itemdefin = mdevView->item(i, DEVCOL_DEF_IN_CHANS);
        itemdefin->setText(bitmap2String(port->defaultInChannels()));
        QTableWidgetItem* itemdefout = mdevView->item(i, DEVCOL_DEF_OUT_CHANS);
        itemdefout->setText(bitmap2String(port->defaultOutChannels()));
        mdevView->blockSignals(false);


        if (dev)
        {
            itemname->setText(dev->name());
            itemname->setToolTip(dev->name());

            // Is it a Jack midi device? Allow renaming.
            //if(dynamic_cast<MidiJackDevice*>(dev))
            if (dev->deviceType() == MidiDevice::JACK_MIDI)
                itemname->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled);

            if (dev->rwFlags() & 0x2)
            {
                itemrec->setIcon(dev->openFlags() & 2 ? QIcon(*dotIcon) : QIcon(*dothIcon));
            }
            else
            {
                itemrec->setIcon(QIcon(QPixmap()));
            }

            if (dev->rwFlags() & 0x1)
            {
                itemplay->setIcon(dev->openFlags() & 1 ? QIcon(*dotIcon) : QIcon(*dothIcon));
            }
            else
                itemplay->setIcon(QIcon(QPixmap()));
            itemfb->setIcon(dev->cacheNRPN() ? QIcon(*dotIcon) : QIcon(*dothIcon));
        }
        else
        {
            itemname->setText(tr("<none>"));
            itemname->setToolTip("");
            itemgui->setIcon(QIcon(*dothIcon));
            itemrec->setIcon(QIcon(QPixmap()));
            itemplay->setIcon(QIcon(QPixmap()));
            itemfb->setIcon(QIcon(QPixmap()));
        }
        // falkTX, we don't want this in the connections manager
        //if (port->hasGui())
        //{
        //	itemgui->setIcon(port->guiVisible() ? QIcon(*dotIcon) : QIcon(*dothIcon));
        //}
        //else
        //{
            itemgui->setIcon(QIcon(QPixmap()));
        //}
        iteminstr->setIcon(QIcon(*buttondownIcon));
        itemname->setIcon(QIcon(*buttondownIcon));

        //if(dev && dynamic_cast<MidiJackDevice*>(dev))
        if (dev && dev->deviceType() == MidiDevice::JACK_MIDI)
        {
            //item->setPixmap(DEVCOL_ROUTES, *buttondownIcon);
            //item->setText(DEVCOL_ROUTES, tr("routes"));

            // p3.3.55
            if (dev->rwFlags() & 1)
                //if(dev->openFlags() & 1)
            {
                itemout->setIcon(QIcon(*buttondownIcon));
                if (port->device() && !port->device()->outRoutes()->empty())
                {
                    RouteList* list = port->device()->outRoutes();
                    if (!list->empty())
                    {
                        iRoute r = list->begin();
                        itemout->setText(r->name());
                    }
                }
                else
                {
                    itemout->setText(tr("out"));
                }

                //if (dev->openFlags() & 1)
                //	itemout->setText(tr("out"));
            }
            if (dev->rwFlags() & 2)
                //if(dev->openFlags() & 2)
            {
                itemin->setIcon(QIcon(*buttondownIcon));
                if (dev->openFlags() & 2)
                    itemin->setText(tr("in"));
            }
        }

        if (i == no) sitem = itemno;
    }

    if (sitem)
    {
        mdevView->setCurrentItem(sitem);
    }
}
示例#21
0
文件: route.cpp 项目: 87maxi/oom
void Route::read(Xml& xml)/*{{{*/
{
	QString s;
	int dtype = MidiDevice::ALSA_MIDI;
	int port = -1;
	unsigned char rtype = Route::TRACK_ROUTE;

	for (;;)
	{
		const QString& tag = xml.s1();
		Xml::Token token = xml.parse();
		switch (token)
		{
			case Xml::Error:
			case Xml::End:
				return;
			case Xml::Attribut:
#ifdef ROUTE_DEBUG
				printf("Route::read(): attribute:%s\n", tag.toLatin1().constData());
#endif
				if (tag == "type")
					rtype = xml.s2().toInt();
				else if (tag == "devtype")
				{
					dtype = xml.s2().toInt();
					rtype = Route::MIDI_DEVICE_ROUTE;
				}
				else if (tag == "name")
					s = xml.s2();
				else if(tag == "trackId")
				{
					trackId = xml.s2().toLongLong();
					rtype = Route::TRACK_ROUTE;
				}
				else if (tag == "mport") // p3.3.49
				{
					port = xml.s2().toInt();
					rtype = Route::MIDI_PORT_ROUTE;
				}
				else if(tag == "mportId")
				{
					midiPortId  = xml.s2().toLongLong();
					rtype = Route::MIDI_PORT_ROUTE;
				}
				else
					printf("Route::read(): unknown attribute:%s\n", tag.toLatin1().constData());
				break;
			case Xml::TagEnd:
#ifdef ROUTE_DEBUG
				printf("Route::read(): tag end type:%d channel:%d name:%s\n", rtype, channel, s.toLatin1().constData());
#endif
				if (rtype == MIDI_PORT_ROUTE)
				{
					if(midiPortId > 0)
					{
						//qDebug("Route::read(): MIDI_PORT_ROUTE Finding midiport from id");
						type = rtype;
						MidiPort *mp = oomMidiPorts.value(midiPortId);
						if(mp)
						{
							midiPort = mp->portno();
							//qDebug("Route::read(): Found midiport from id: %d", midiPort);
						}
					}
					else if (port >= 0 && port < MIDI_PORTS)
					{
						type = rtype;
						midiPort = port;
						MidiPort *mp = &midiPorts[midiPort];
						midiPortId = mp->id();
					}
					else
						printf("Route::read(): midi port <%d> out of range\n", port);
				}
				else if (!s.isEmpty())
				{
					if (rtype == TRACK_ROUTE)
					{
						if(trackId > 0)
						{
							track = song->findTrackById(trackId);
							type = rtype;
						}
						else
						{
							TrackList* tl = song->tracks();
							iTrack i = tl->begin();
							for (; i != tl->end(); ++i)
							{
								Track* t = *i;
								if (t->name() == s)
								{
									track = t;
									type = rtype;
									trackId = t->id();
									break;
								}
							}
							if (i == tl->end())
								printf("Route::read(): track <%s> not found\n", s.toLatin1().constData());
						}
					}
					else if (rtype == JACK_ROUTE)
					{
						void* jport = 0;
						if (audioDevice) //Fix from Robert at muse
							jport = audioDevice->findPort(s.toLatin1().constData());

						if (jport == 0)
							printf("Route::read(): jack port <%s> not found audioDevice(%p)\n", s.toLatin1().constData(), audioDevice);
						else
						{
							jackPort = jport;
							type = rtype;
						}
					}
					else if (rtype == MIDI_DEVICE_ROUTE)
					{
						iMidiDevice imd = midiDevices.begin();
						for (; imd != midiDevices.end(); ++imd)
						{
							MidiDevice* md = *imd;
							if (md->name() == s && md->deviceType() == dtype)
							{
								// We found a device, but if it is not in use by the song (port is -1), ignore it.
								// This prevents loading and propagation of bogus routes in the oom file.
								if (md->midiPort() == -1)
									break;

								device = md;
								type = rtype;
								break;
							}
						}
						if (imd == midiDevices.end())
							printf("Route::read(): midi device <%s> not found\n", s.toLatin1().constData());
					}
				}
				return;
			default:
				break;
		}
	}
}/*}}}*/
示例#22
0
void MidiDevice::handleStop()
{
  // If the device is not in use by a port, don't bother it.
  if(_port == -1)
    return;
    
  MidiPort* mp = &MusEGlobal::midiPorts[_port];
  
  //---------------------------------------------------
  //    send midi stop
  //---------------------------------------------------
  
  // Don't send if external sync is on. The master, and our sync routing system will take care of that.   
  if(!MusEGlobal::extSyncFlag.value())
  {
    // Shall we check open flags? DELETETHIS 4?
    //if(!(dev->rwFlags() & 0x1) || !(dev->openFlags() & 1))
    //if(!(dev->openFlags() & 1))
    //  return;
          
    MidiSyncInfo& si = mp->syncInfo();
    if(si.MMCOut())
      mp->sendMMCStop();
    
    if(si.MRTOut()) 
    {
      mp->sendStop();
      //DELETETHIS 5?
      // Added check of option send continue not start. Hmm, is this required? Seems to make other devices unhappy.
      // (Could try now that this is in MidiDevice.)
      //if(!si.sendContNotStart())
      //  mp->sendSongpos(MusEGlobal::audio->tickPos() * 4 / MusEGlobal::config.division);
    }
  }  

  //---------------------------------------------------
  //    Clear all notes and flush out any stuck notes
  //     which were put directly to the device
  //---------------------------------------------------

  setStopFlag(true);
  for(iMPEvent i = _stuckNotes.begin(); i != _stuckNotes.end(); ++i) 
  {
    MidiPlayEvent ev(*i);
    ev.setTime(0);  // Immediate processing. TODO Use curFrame?
    //ev.setTime(MusEGlobal::audio->midiQueueTimeStamp(ev.time()));
        putEvent(ev, MidiDevice::NotLate);
  }
  _stuckNotes.clear();
  
  //------------------------------------------------------------
  //    Flush out any track-related playback stuck notes (NOT 'live' notes)
  //     which were not put directly to the device
  //------------------------------------------------------------
  
  for(ciMidiTrack imt = MusEGlobal::song->midis()->begin(); imt != MusEGlobal::song->midis()->end(); ++imt)
  {
    MPEventList& mel = (*imt)->stuckNotes;
    for(iMPEvent i = mel.begin(), i_next = i; i != mel.end(); i = i_next) 
    {
      ++i_next;

      if((*i).port() != _port)
        continue;
      MidiPlayEvent ev(*i);
      ev.setTime(0);  // Immediate processing. TODO Use curFrame?
      //ev.setTime(MusEGlobal::audio->midiQueueTimeStamp(ev.time()));
      putEvent(ev, MidiDevice::NotLate);
            
      mel.erase(i);
    }
  }
  
  //---------------------------------------------------
  //    reset sustain
  //---------------------------------------------------
  
  for(int ch = 0; ch < MusECore::MUSE_MIDI_CHANNELS; ++ch) 
  {
    if(mp->hwCtrlState(ch, CTRL_SUSTAIN) == 127) 
    {
      MidiPlayEvent ev(0, _port, ch, ME_CONTROLLER, CTRL_SUSTAIN, 0); // Immediate processing. TODO Use curFrame?
      //ev.setTime(MusEGlobal::audio->midiQueueTimeStamp(ev.time()));
      putEvent(ev, MidiDevice::NotLate);
    }
  }
}
示例#23
0
文件: route.cpp 项目: 87maxi/oom
void removeRoute(Route src, Route dst)/*{{{*/
{
//TODO: Add hooks to update the patchcanvas on success
//This should be conditionally checked so we dont update if the canvas is what made the connection
	if (src.type == Route::JACK_ROUTE)
	{
		if (!dst.isValid())
		{
			printf("removeRoute: source is jack, invalid destination\n");
			return;
		}

		if (dst.type == Route::TRACK_ROUTE)
		{
			if (dst.track->type() != Track::AUDIO_INPUT)
			{
				fprintf(stderr, "removeRoute: source is jack, destination is track but not audio input\n");
				// exit(-1);
				return;
			}
			RouteList* inRoutes = dst.track->inRoutes();
			iRoute i;
			for (i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if (*i == src)
				{
					inRoutes->erase(i);
					break;
				}
			}
		}
		else if (dst.type == Route::MIDI_DEVICE_ROUTE)
		{
			RouteList* routes = dst.device->inRoutes();
			iRoute i;
			for (i = routes->begin(); i != routes->end(); ++i)
			{
				if (*i == src)
				{
					routes->erase(i);
					break;
				}
			}
		}
		else
		{
			fprintf(stderr, "removeRoute: source is jack, destination unknown\n");
			return;
		}
	}
	else if (dst.type == Route::JACK_ROUTE)
	{
		if (!src.isValid())
		{
			printf("removeRoute: destination is jack, invalid source\n");
			return;
		}

		if (src.type == Route::TRACK_ROUTE)
		{
			if (src.track->type() != Track::AUDIO_OUTPUT)
			{
				fprintf(stderr, "removeRoute: destination is jack, source is track but not audio output\n");
				return;
			}
			RouteList* outRoutes = src.track->outRoutes();
			iRoute i;
			for (i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if (*i == dst)
				{
					outRoutes->erase(i);
					break;
				}
			}
		}
		else if (src.type == Route::MIDI_DEVICE_ROUTE)
		{
			RouteList* routes = src.device->outRoutes();
			iRoute i;
			for (i = routes->begin(); i != routes->end(); ++i)
			{
				if (*i == dst)
				{
					routes->erase(i);
					break;
				}
			}
		}
		else
		{
			fprintf(stderr, "removeRoute: destination is jack, source unknown\n");
			// exit(-1);
			return;
		}
	}
	else if (src.type == Route::MIDI_PORT_ROUTE) // p3.3.49
	{
		if (dst.type != Route::TRACK_ROUTE)
		{
			fprintf(stderr, "removeRoute: source is midi port:%d, but destination is not track\n", src.midiPort);
			return;
		}

		if (src.isValid())
		{
			MidiPort *mp = &midiPorts[src.midiPort];
			RouteList* outRoutes = mp->outRoutes();
			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				//if (*i == dst)
				if (i->type == Route::TRACK_ROUTE && i->track == dst.track) // p3.3.50 Is there a route to the track?
				{
					i->channel &= ~dst.channel; // p3.3.50 Unset the desired channel bits.
					if (i->channel == 0) // Only if there are no channel bits set, erase the route.
						outRoutes->erase(i);

					break; // For safety, keep looking and remove any more found.
					// No, must break, else crash. There should only be one route anyway...
				}
			}
		}
		else
			printf("removeRoute: source is midi port:%d but invalid\n", src.midiPort);

		if (dst.isValid())
		{
			RouteList* inRoutes = dst.track->inRoutes();
			for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if (i->type == Route::MIDI_PORT_ROUTE && i->midiPort == src.midiPort) // p3.3.50 Is there a route to the midi port?
				{
					i->channel &= ~src.channel; // p3.3.50 Unset the desired channel bits.
					if (i->channel == 0) // Only if there are no channel bits set, erase the route.
						inRoutes->erase(i);

					break; // For safety, keep looking and remove any more found.
					// No, must break, else crash. There should only be one route anyway...
				}
			}
		}
		else
			printf("removeRoute: source is midi port:%d but destination track invalid\n", src.midiPort);
	}
	else if (dst.type == Route::MIDI_PORT_ROUTE) // p3.3.49
	{
		if (src.type != Route::TRACK_ROUTE)
		{
			fprintf(stderr, "removeRoute: destination is midi port:%d, but source is not track\n", dst.midiPort);
			return;
		}

		if (src.isValid())
		{
			RouteList* outRoutes = src.track->outRoutes();
			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if (i->type == Route::MIDI_PORT_ROUTE && i->midiPort == dst.midiPort) // p3.3.50 Is there a route to the midi port?
				{
					i->channel &= ~dst.channel; // p3.3.50 Unset the desired channel bits.
					if (i->channel == 0) // Only if there are no channel bits set, erase the route.
						outRoutes->erase(i);

					break; // For safety, keep looking and remove any more found.
					// No, must break, else crash. There should only be one route anyway...
				}
			}
		}
		else
			printf("removeRoute: destination is midi port:%d but source track is invalid\n", dst.midiPort);

		if (dst.isValid())
		{
			MidiPort *mp = &midiPorts[src.midiPort];
			RouteList* inRoutes = mp->inRoutes();
			for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if (i->type == Route::TRACK_ROUTE && i->track == src.track) // p3.3.50 Is there a route to the track?
				{
					i->channel &= ~src.channel; // p3.3.50 Unset the desired channel bits.
					if (i->channel == 0) // Only if there are no channel bits set, erase the route.
						inRoutes->erase(i);

					break; // For safety, keep looking and remove any more found.
					// No, must break, else crash. There should only be one route anyway...
				}
			}
		}
		else
			printf("removeRoute: destination is midi port:%d but invalid\n", dst.midiPort);
	}
	else
	{
		if (src.type != Route::TRACK_ROUTE || dst.type != Route::TRACK_ROUTE) // p3.3.49
		{
			fprintf(stderr, "removeRoute: source and destination are not tracks\n");
			return;
		}

		if (src.isValid())
		{
			RouteList* outRoutes = src.track->outRoutes();
			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if ((*i).name() == dst.name())
				{
					outRoutes->erase(i);
					break;
				}
			}
		}
		else
			printf("removeRoute: source is track but invalid\n");

		if (dst.isValid())
		{
			RouteList* inRoutes = dst.track->inRoutes();
			for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if ((*i).name() == src.name())
				{
					inRoutes->erase(i);
					break;
				}
			}
		}
		else
			printf("removeRoute: source is track but destination invalid\n");
	}
}/*}}}*/
示例#24
0
void MPConfig::mdevViewItemRenamed(QTableWidgetItem* item)
{
    int col = item->column();
    QString s = item->text();
    //printf("MPConfig::mdevViewItemRenamed col:%d txt:%s\n", col, s.toLatin1().constData());
    if (item == 0)
        return;
    switch (col)
    {
        case DEVCOL_DEF_IN_CHANS:
        {
            QString id = item->tableWidget()->item(item->row(), DEVCOL_NO)->text();
            int no = atoi(id.toLatin1().constData()) - 1;
            if (no < 0 || no >= kMaxMidiPorts)
                return;
            midiPorts[no].setDefaultInChannels(((1 << kMaxMidiChannels) - 1) & string2bitmap(s));
            song->update();
        }
            break;
        case DEVCOL_DEF_OUT_CHANS:
        {
            QString id = item->tableWidget()->item(item->row(), DEVCOL_NO)->text();
            int no = atoi(id.toLatin1().constData()) - 1;
            if (no < 0 || no >= kMaxMidiPorts)
                return;
            midiPorts[no].setDefaultOutChannels(((1 << kMaxMidiChannels) - 1) & string2bitmap(s));
            song->update();
        }
            break;
        case DEVCOL_NAME:
        {
            QString id = item->tableWidget()->item(item->row(), DEVCOL_NO)->text();
            int no = atoi(id.toLatin1().constData()) - 1;
            if (no < 0 || no >= kMaxMidiPorts)
                return;

            MidiPort* port = &midiPorts[no];
            MidiDevice* dev = port->device();
            // Only Jack midi devices.
            if (!dev || dev->deviceType() != MidiDevice::JACK_MIDI)
                return;
            if (dev->name() == s)
                return;

            if (midiDevices.find(s))
            {
                QMessageBox::critical(this,
                        tr("LOS: bad device name"),
                        tr("please choose a unique device name"),
                        QMessageBox::Ok,
                        Qt::NoButton,
                        Qt::NoButton);
                songChanged(-1);
                return;
            }
            dev->setName(s);
            song->update();
        }
            break;
        default:
            //printf("MPConfig::mdevViewItemRenamed unknown column clicked col:%d txt:%s\n", col, s.toLatin1().constData());
            break;
    }
}
示例#25
0
void MidiAlsaSeq::run()
{
	// watch the pipe and sequencer input events
	int pollfd_count = snd_seq_poll_descriptors_count( m_seqHandle,
								POLLIN );
	struct pollfd * pollfd_set = new struct pollfd[pollfd_count + 1];
	snd_seq_poll_descriptors( m_seqHandle, pollfd_set + 1, pollfd_count,
								POLLIN );
	pollfd_set[0].fd = m_pipe[0];
	pollfd_set[0].events = POLLIN;
	++pollfd_count;

	while( m_quit == false )
	{
		int pollRet = poll( pollfd_set, pollfd_count, EventPollTimeOut );
		if( pollRet == 0 )
		{
			continue;
		}
		else if( pollRet == -1 )
		{
			// gdb may interrupt the poll
			if( errno == EINTR )
			{
				continue;
			}
			qCritical( "error while polling ALSA sequencer handle" );
			break;
		}
		// shutdown?
		if( m_quit )
		{
			break;
		}

		m_seqMutex.lock();

		// while event queue is not empty
		while( snd_seq_event_input_pending( m_seqHandle, true ) > 0 )
		{
			snd_seq_event_t * ev;
			if( snd_seq_event_input( m_seqHandle, &ev ) < 0 )
			{
				m_seqMutex.unlock();

				qCritical( "error while fetching MIDI event from sequencer" );
				break;
			}
			m_seqMutex.unlock();

			snd_seq_addr_t * source = NULL;
			MidiPort * dest = NULL;
			for( int i = 0; i < m_portIDs.size(); ++i )
			{
				if( m_portIDs.values()[i][0] == ev->dest.port )
				{
					dest = m_portIDs.keys()[i];
				}
				if( ( m_portIDs.values()[i][1] != -1 &&
						m_portIDs.values()[i][1] == ev->source.port ) ||
							m_portIDs.values()[i][0] == ev->source.port )
				{
					source = &ev->source;
				}
			}

			if( dest == NULL )
			{
				continue;
			}

			switch( ev->type )
			{
				case SND_SEQ_EVENT_NOTEON:
					dest->processInEvent( MidiEvent( MidiNoteOn,
								ev->data.note.channel,
								ev->data.note.note -
								KeysPerOctave,
								ev->data.note.velocity,
								source
								),
							MidiTime( ev->time.tick ) );
					break;

				case SND_SEQ_EVENT_NOTEOFF:
					dest->processInEvent( MidiEvent( MidiNoteOff,
								ev->data.note.channel,
								ev->data.note.note -
								KeysPerOctave,
								ev->data.note.velocity,
								source
								),
							MidiTime( ev->time.tick) );
					break;

				case SND_SEQ_EVENT_KEYPRESS:
					dest->processInEvent( MidiEvent(
									MidiKeyPressure,
								ev->data.note.channel,
								ev->data.note.note -
								KeysPerOctave,
								ev->data.note.velocity,
								source
								), MidiTime() );
					break;

				case SND_SEQ_EVENT_CONTROLLER:
					dest->processInEvent( MidiEvent(
								MidiControlChange,
							ev->data.control.channel,
							ev->data.control.param,
							ev->data.control.value, source ),
									MidiTime() );
					break;

				case SND_SEQ_EVENT_PGMCHANGE:
					dest->processInEvent( MidiEvent(
								MidiProgramChange,
							ev->data.control.channel,
							ev->data.control.param,
							ev->data.control.value, source ),
									MidiTime() );
					break;

				case SND_SEQ_EVENT_CHANPRESS:
					dest->processInEvent( MidiEvent(
								MidiChannelPressure,
							ev->data.control.channel,
							ev->data.control.param,
							ev->data.control.value, source ),
									MidiTime() );
					break;

				case SND_SEQ_EVENT_PITCHBEND:
					dest->processInEvent( MidiEvent( MidiPitchBend,
							ev->data.control.channel,
							ev->data.control.value + 8192, 0, source ),
									MidiTime() );
					break;

				case SND_SEQ_EVENT_SENSING:
				case SND_SEQ_EVENT_CLOCK:
					break;

				default:
					fprintf( stderr,
						"ALSA-sequencer: unhandled input "
							"event %d\n", ev->type );
					break;
			}	// end switch

			m_seqMutex.lock();

		}	// end while

		m_seqMutex.unlock();

	}

	delete[] pollfd_set;
}
示例#26
0
bool LOS::importMidi(const QString name, bool merge)/*{{{*/
{
    bool popenFlag;
    FILE* fp = fileOpen(this, name, QString(".mid"), "r", popenFlag);
    if (fp == 0)
        return true;
    MidiFile mf(fp);
    bool rv = mf.read();
    popenFlag ? pclose(fp) : fclose(fp);
    if (rv)
    {
        QString s(tr("reading midifile\n  "));
        s += name;
        s += tr("\nfailed: ");
        s += mf.error();
        QMessageBox::critical(this, QString("LOS"), s);
        return rv;
    }
    //
    //  evaluate song Type (GM, XG, GS, unknown)
    //
    MType t = song->midiType();
    if (!merge)
    {
        t = mf.mtype();
        song->setMType(t);
    }
    MidiInstrument* instr = 0;
    for (iMidiInstrument i = midiInstruments.begin(); i != midiInstruments.end(); ++i)
    {
        MidiInstrument* mi = *i;
        if ((mi->iname() == "GM" && ((t == MT_UNKNOWN) || (t == MIDI_TYPE_GM)))
                || ((mi->iname() == "GS") && (t == MT_GS))
                || ((mi->iname() == "XG") && (t == MT_XG)))
        {
            instr = mi;
            break;
        }
    }
    if (instr == 0)
    {
        // the standard instrument files (GM, GS, XG) must be present
        printf("no instrument, type %d\n", t);
        return true;
        //abort();
    }

    MidiFileTrackList* etl = mf.trackList();
    int division = mf.division();

    //
    // create MidiTrack and copy events to ->events()
    //    - combine note on/off events
    //    - calculate tick value for internal resolution
    //
    for (iMidiFileTrack t = etl->begin(); t != etl->end(); ++t)
    {
        MPEventList* el = &((*t)->events);
        if (el->empty())
            continue;
        //
        // if we split the track, SYSEX and META events go into
        // the first target track

        bool first = true;
        // somewhat silly and slooow:
        for (int port = 0; port < kMaxMidiPorts; ++port)
        {
            for (int channel = 0; channel < kMaxMidiChannels; ++channel)
            {
                //
                // check if there are any events for port/channel in track:
                //
                iMPEvent i;
                for (i = el->begin(); i != el->end(); ++i)
                {
                    MidiPlayEvent ev = *i;
                    if (ev.type() != ME_SYSEX && ev.type() != ME_META
                            && ev.channel() == channel && ev.port() == port)
                        break;
                }
                if (i == el->end())
                    continue;
                MidiTrack* track = new MidiTrack();
                if ((*t)->isDrumTrack)
                {
                    track->setType(Track::DRUM);
                }

                track->setOutChannel(channel);
                track->setOutPort(port);

                MidiPort* mport = &midiPorts[track->outPort()];
                // this overwrites any instrument set for this port:
                mport->setInstrument(instr);

                EventList* mel = track->events();
                //buildMidiEventList(mel, el, track, division, first);
                // Don't do loops.
                buildMidiEventList(mel, el, track, division, first, false);
                first = false;

                // Hmm. buildMidiEventList already takes care of this.
                // But it seems to work. How? Must test.
                if (channel == 9 && song->midiType() != MT_UNKNOWN)
                {
                    track->setType(Track::DRUM);
                    //
                    // remap drum pitch with drumInmap
                    //
                    EventList* tevents = track->events();
                    for (iEvent i = tevents->begin(); i != tevents->end(); ++i)
                    {
                        Event ev = i->second;
                        if (ev.isNote())
                        {
                            int pitch = drumInmap[ev.pitch()];
                            ev.setPitch(pitch);
                        }
                        else
                            if (ev.type() == Controller)
                        {
                            int ctl = ev.dataA();
                            MidiController *mc = mport->drumController(ctl);
                            if (mc)
                                ev.setA((ctl & ~0xff) | drumInmap[ctl & 0x7f]);
                        }
                    }
                }

                processTrack(track);

                song->insertTrack(track, -1);
            }
        }
        if (first)
        {
            //
            // track does only contain non-channel messages
            // (SYSEX or META)
            //
            MidiTrack* track = new MidiTrack();
            track->setOutChannel(0);
            track->setOutPort(0);
            EventList* mel = track->events();
            //buildMidiEventList(mel, el, track, division, true);
            // Do SysexMeta. Don't do loops.
            buildMidiEventList(mel, el, track, division, true, false);
            processTrack(track);
            song->insertTrack(track, -1);
        }
    }

    if (!merge)
    {
        TrackList* tl = song->tracks();
        if (!tl->empty())
        {
            Track* track = tl->front();
            track->setSelected(true);
        }
        song->initLen();

        int z, n;
        ///sigmap.timesig(0, z, n);
        sigmap.timesig(0, z, n);

        int tempo = tempomap.tempo(0);
        transport->setTimesig(z, n);
        transport->setTempo(tempo);

        bool masterF = !tempomap.empty();
        song->setMasterFlag(masterF);
        transport->setMasterFlag(masterF);

        song->updatePos();

        composer->reset();
        ///composer->setMode(int(song->midiType())); // p4.0.7 Tim
    }
    else
    {
        song->initLen();
    }

    return false;
}/*}}}*/
示例#27
0
文件: conf.cpp 项目: Adamiko/los
static void readConfigMidiPort(Xml& xml)/*{{{*/
{
    int idx = 0;
    qint64 id = -1;
    QString device;
    bool isGlobal = false;

    QString instrument("GM");

    QList<PatchSequence*> patchSequences;
    QList<QPair<int, QString> > presets;

    int openFlags = 1;
    int dic = 0;
    int doc = 0;
    int type = MidiDevice::ALSA_MIDI;
    bool cachenrpn = false;

    MidiDevice* dev = 0;

    for (;;)
    {
        Xml::Token token = xml.parse();
        if (token == Xml::Error || token == Xml::End)
            break;
        QString tag = xml.s1();
        switch (token)
        {
            case Xml::TagStart:
                if (tag == "name")
                {
                    device = xml.parse1();
                    if (!dev)//Look for it as an alsa or already created device
                        dev = midiDevices.find(device);
                }
                else if (tag == "type")
                {
                    type = xml.parseInt();
                }
                else if (tag == "record")
                {   // old
                    bool f = xml.parseInt();
                    if (f)
                        openFlags |= 2;
                }
                else if (tag == "openFlags")
                    openFlags = xml.parseInt();
                else if (tag == "defaultInChans")
                    dic = xml.parseInt();
                else if (tag == "defaultOutChans")
                    doc = xml.parseInt();
                else if (tag == "instrument")
                {
                    instrument = xml.parse1();
                }
                else if (tag == "channel")
                {
                    readPortChannel(xml, idx);
                }
                else if (tag == "preset" || tag == "patchSequence")
                {
                    PatchSequence* p = readMidiPortPatchSequences(xml);
                    if (p)
                        patchSequences.append(p);
                }
                else if(tag == "midiPreset")
                {
                    presets.append(readMidiPortPreset(xml));
                }
                else if(tag == "cacheNRPN")
                {
                    cachenrpn = xml.parseInt();
                }
                else
                    xml.skip(tag);
                break;
            case Xml::Attribut:
                if (tag == "idx")
                {//Check to see if this port is already used, and bump if so
                    idx = xml.s2().toInt();
                    int freePort = getFreeMidiPort();
                    if(freePort != idx)
                    {//Set a flag here so we know when loading tracks later that we are dealing with an old file or global inputs changed
                        idx = freePort;
                    }
                }
                else if(tag == "portId")
                {//New style
                    id = xml.s2().toLongLong();
                    idx = getFreeMidiPort();
                }
                else if(tag == "isGlobalInput")
                {//Find the matching input if posible and set our index to it
                    isGlobal = xml.s2().toInt();
                }
                break;
            case Xml::TagEnd:
                if (tag == "midiport")
                {
                    if(isGlobal)
                    {//Find the global input that matches
                        //
                        if(gInputListPorts.size())
                        {
                            int myport = -1;
                            for(int i = 0; i < gInputListPorts.size(); ++i)
                            {
                                myport =  gInputListPorts.at(i);

                                MidiPort* inport = &midiPorts[i];
                                if(inport && inport->device() && inport->device()->name() == device)
                                {
                                    idx = myport;
                                    break;
                                }
                            }
                        }
                    }

                    if (idx < 0 || idx >= MIDI_PORTS)
                    {
                        fprintf(stderr, "bad midi port %d (>%d)\n",
                                idx, MIDI_PORTS);
                        idx = 0;
                    }

                    if (!dev)
                    {
                        if (type == MidiDevice::JACK_MIDI)
                        {
                            dev = MidiJackDevice::createJackMidiDevice(device); // p3.3.55

                            if (debugMsg)
                                fprintf(stderr, "readConfigMidiPort: creating jack midi device %s\n", device.toLatin1().constData());
                        }
                        else
                            dev = midiDevices.find(device);
                    }

                    if (debugMsg && !dev)
                        fprintf(stderr, "readConfigMidiPort: device not found %s\n", device.toLatin1().constData());

                    MidiPort* mp = &midiPorts[idx];
                    if(id)
                        mp->setPortId(id);

                    mp->setInstrument(registerMidiInstrument(instrument));
                    mp->setDefaultInChannels(dic);
                    mp->setDefaultOutChannels(doc);

                    //Indicate the port was found in the song file, even if no device is assigned to it.
                    mp->setFoundInSongFile(true);

                    if (!patchSequences.isEmpty())
                    {
                        for (int i = 0; i < patchSequences.size(); ++i)
                        {
                            mp->appendPatchSequence(patchSequences.at(i));
                        }
                    }
                    if(!presets.isEmpty())
                    {
                        for(int i = 0; i < presets.size(); ++i)
                        {
                            QPair<int, QString> pair = presets.at(i);
                            mp->addPreset(pair.first, pair.second);
                        }
                    }

                    if (dev)
                    {
                        dev->setOpenFlags(openFlags);
                        midiSeq->msgSetMidiDevice(mp, dev);
                        dev->setCacheNRPN(cachenrpn);
                    }
                    losMidiPorts.insert(mp->id(), mp);
                    return;
                }
            default:
                break;
        }
    }
}/*}}}*/
示例#28
0
文件: route.cpp 项目: 87maxi/oom
void addRoute(Route src, Route dst)/*{{{*/
{
//TODO: Add hooks to update the patchcanvas on success
//This should be conditionally checked so we dont update if the canvas is what made the connection

#ifdef ROUTE_DEBUG
	fprintf(stderr, "addRoute:\n");
#endif

	if (!src.isValid() || !dst.isValid())
	{
		if (!src.isValid())
			fprintf(stderr, "addRoute: invalid src\n");
		if (!dst.isValid())
			fprintf(stderr, "addRoute: invalid dst\n");
		return;
	}

	if (src.type == Route::JACK_ROUTE)
	{
		if (dst.type == Route::TRACK_ROUTE)
		{
			if (dst.track->type() != Track::AUDIO_INPUT)
			{
				fprintf(stderr, "addRoute: source is jack, dest:%s is track but not audio input\n", dst.track->name().toLatin1().constData());
				return;
			}
			if (dst.channel < 0)
			{
				fprintf(stderr, "addRoute: source is jack, dest:%s is track but invalid channel:%d\n", dst.track->name().toLatin1().constData(), dst.channel);
				return;
			}

			src.channel = dst.channel;
			RouteList* inRoutes = dst.track->inRoutes();
			for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
			{
				if (*i == src) // route already there
				{
					fprintf(stderr, "addRoute: src track route already exists.\n");
					return;
				}
			}
#ifdef ROUTE_DEBUG
			fprintf(stderr, "addRoute: src Jack dst track name: %s pushing source route\n", dst.track->name().toLatin1().constData());
#endif
			inRoutes->push_back(src);
		}
		else if (dst.type == Route::MIDI_DEVICE_ROUTE)
		{
			if (dst.device->deviceType() == MidiDevice::JACK_MIDI)
			{
				src.channel = dst.channel;

				RouteList* routes = dst.device->inRoutes();
				for (iRoute i = routes->begin(); i != routes->end(); ++i)
				{
					if (*i == src) // route already there
					{
						fprintf(stderr, "addRoute: src Jack midi route already exists.\n");
						return;
					}
				}
#ifdef ROUTE_DEBUG
				fprintf(stderr, "addRoute: src Jack dst Jack midi name: %s pushing source route\n", dst.device->name().toLatin1().constData());
#endif
				routes->push_back(src);
			}
			else
			{
				fprintf(stderr, "addRoute: source is Jack, but destination is not jack midi - type:%d\n", dst.device->deviceType());
				return;
			}
		}
		else
		{
			fprintf(stderr, "addRoute: source is Jack, but destination is not track or midi - type:%d \n", dst.type);
			return;
		}
	}
	else if (dst.type == Route::JACK_ROUTE)
	{
		if (src.type == Route::TRACK_ROUTE)
		{
			if (src.track->type() != Track::AUDIO_OUTPUT)
			{
				fprintf(stderr, "addRoute: destination is jack, source is track but not audio output\n");
				return;
			}
			if (src.channel < 0)
			{
				fprintf(stderr, "addRoute: destination is jack, source:%s is track but invalid channel:%d\n", src.track->name().toLatin1().constData(), src.channel);
				return;
			}

			RouteList* outRoutes = src.track->outRoutes();
			dst.channel = src.channel;

			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if (*i == dst) // route already there
				{
#ifdef ROUTE_DEBUG
					fprintf(stderr, "addRoute: dst track route already exists.\n");
#endif
					return;
				}
			}
#ifdef ROUTE_DEBUG
			fprintf(stderr, "addRoute: dst Jack src track name: %s pushing destination route\n", src.track->name().toLatin1().constData());
#endif
			outRoutes->push_back(dst);
		}
		else if (src.type == Route::MIDI_DEVICE_ROUTE)
		{
			if (src.device->deviceType() == MidiDevice::JACK_MIDI)
			{
				dst.channel = src.channel;

				RouteList* routes = src.device->outRoutes();
				for (iRoute i = routes->begin(); i != routes->end(); ++i)
				{
					if (*i == dst) // route already there
					{
						fprintf(stderr, "addRoute: dst Jack midi route already exists.\n");
						return;
					}
				}
#ifdef ROUTE_DEBUG
				fprintf(stderr, "addRoute: dst Jack src Jack midi name: %s pushing destination route\n", src.device->name().toLatin1().constData());
#endif
				routes->push_back(dst);
			}
			else
			{
				fprintf(stderr, "addRoute: destination is Jack, but source is not jack midi - type:%d\n", src.device->deviceType());
				return;
			}
		}
		else
		{
			fprintf(stderr, "addRoute: destination is Jack, but source is not track or midi - type:%d \n", src.type);
			return;
		}
	}
	else if (src.type == Route::MIDI_PORT_ROUTE) // p3.3.49
	{
		if (dst.type != Route::TRACK_ROUTE)
		{
			fprintf(stderr, "addRoute: source is midi port:%d, but destination is not track\n", src.midiPort);
			return;
		}
		if (dst.channel < 1 || dst.channel >= (1 << MIDI_CHANNELS))
		{
			fprintf(stderr, "addRoute: source is midi port:%d, but destination channel mask:%d out of range\n", src.midiPort, dst.channel);
			return;
		}

		MidiPort *mp = &midiPorts[src.midiPort];

		src.channel = dst.channel;
		RouteList* outRoutes = mp->outRoutes();
		iRoute ir = outRoutes->begin(); // p3.3.50
		for (; ir != outRoutes->end(); ++ir)
		{
			if (ir->type == Route::TRACK_ROUTE && ir->track == dst.track) // p3.3.50 Does a route to the track exist?
			{
				ir->channel |= dst.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
				break;
			}
		}
#ifdef ROUTE_DEBUG
		fprintf(stderr, "addRoute: src midi port:%d dst track name:%s pushing dst and src routes\n", src.midiPort, dst.track->name().toLatin1().constData());
#endif

		if (ir == outRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
			outRoutes->push_back(dst);

		RouteList* inRoutes = dst.track->inRoutes();

		// p3.3.50 Make sure only one single route, with a channel mask, can ever exist.
		ir = inRoutes->begin();
		for (; ir != inRoutes->end(); ++ir)
		{
			if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == src.midiPort) // p3.3.50 Does a route to the midi port exist?
			{
				ir->channel |= src.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
				break;
			}
		}

		if (ir == inRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
			inRoutes->push_back(src);
	}
	else if (dst.type == Route::MIDI_PORT_ROUTE) // p3.3.49
	{
		if (src.type != Route::TRACK_ROUTE)
		{
			fprintf(stderr, "addRoute: destination is midi port:%d, but source is not track\n", dst.midiPort);
			return;
		}
		if (src.channel < 1 || src.channel >= (1 << MIDI_CHANNELS))
		{
			fprintf(stderr, "addRoute: destination is midi port:%d, but source channel mask:%d out of range\n", dst.midiPort, src.channel);
			return;
		}

		dst.channel = src.channel;
		RouteList* outRoutes = src.track->outRoutes();

		iRoute ir = outRoutes->begin(); // p3.3.50
		for (; ir != outRoutes->end(); ++ir)
		{
			if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == dst.midiPort) // p3.3.50 Does a route to the midi port exist?
			{
				ir->channel |= dst.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
				break;
			}
		}

		if (ir == outRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
			outRoutes->push_back(dst);

		MidiPort *mp = &midiPorts[dst.midiPort];

#ifdef ROUTE_DEBUG
		fprintf(stderr, "addRoute: src track:%s dst midi port:%d pushing dst and src routes\n", src.track->name().toLatin1().constData(), dst.midiPort);
#endif
		RouteList* inRoutes = mp->inRoutes();

		// p3.3.50 Make sure only one single route, with a channel mask, can ever exist.
		ir = inRoutes->begin();
		for (; ir != inRoutes->end(); ++ir)
		{
			if (ir->type == Route::TRACK_ROUTE && ir->track == src.track) // p3.3.50 Does a route to the track exist?
			{
				ir->channel |= src.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
				break;
			}
		}

		if (ir == inRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
			inRoutes->push_back(src);
	}
	else
	{
		if (src.type != Route::TRACK_ROUTE || dst.type != Route::TRACK_ROUTE) // p3.3.49
		{
			fprintf(stderr, "addRoute: source or destination are not track routes\n");
			return;
		}

		{
			RouteList* outRoutes = src.track->outRoutes();

			//
			// Must enforce to ensure channel and channels are valid if defaults of -1 passed.
			//
			if (src.track->type() == Track::AUDIO_SOFTSYNTH)
			{
				if (src.channel == -1)
					src.channel = 0;
				if (src.channels == -1)
					src.channels = src.track->channels();
				dst.channel = src.channel;
				dst.channels = src.channels;
				dst.remoteChannel = src.remoteChannel;
			}

			for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
			{
				if (*i == dst) // route already there
				{
					//#ifdef ROUTE_DEBUG
					fprintf(stderr, "addRoute: src track route already exists.\n");
					//#endif
					return;
				}
			}
			outRoutes->push_back(dst);
			RouteList* inRoutes;

			{
#ifdef ROUTE_DEBUG
				fprintf(stderr, "addRoute: src track ch:%d chs:%d remch:%d  dst track ch:%d chs:%d remch:%d name: %s pushing dest and source routes\n",
						src.channel, src.channels, src.remoteChannel, dst.channel, dst.channels, dst.remoteChannel, dst.track->name().toLatin1().constData());
#endif
				inRoutes = dst.track->inRoutes();
			}


			//
			// make sure AUDIO_AUX is processed last
			//
			if (src.track->type() == Track::AUDIO_AUX)
				inRoutes->push_back(src);
			else
				inRoutes->insert(inRoutes->begin(), src);
		}
	}
}/*}}}*/
示例#29
0
文件: conf.cpp 项目: Adamiko/los
static void writeSeqConfiguration(int level, Xml& xml, bool writePortInfo)/*{{{*/
{
    xml.tag(level++, "sequencer");

    if (writePortInfo)
    {
        //
        // write information about all midi ports, their assigned
        // instruments and all managed midi controllers
        //
        for (int i = 0; i < MIDI_PORTS; ++i)
        {
            bool used = false;
            MidiPort* mport = &midiPorts[i];

            // Route check by Tim. Port can now be used for routing even if no device.
            // Also, check for other non-defaults and save port, to preserve settings even if no device.
            // Dont write the config for the global inputs list they will be auto created with each startup
            if (mport->defaultInChannels() || mport->defaultOutChannels() ||
                    (mport->instrument() && !mport->instrument()->iname().isEmpty() && mport->instrument()->iname() != "GM") /*|| !mport->syncInfo().isDefault()*/ )
            {
                used = true;
            }
            else
            {//Put the ID of this track into a list
                MidiTrackList* tl = song->midis();
                for (iMidiTrack it = tl->begin(); it != tl->end(); ++it)
                {
                    MidiTrack* t = *it;
                    if (t->outPort() == i)
                    {
                        used = true;
                        break;
                    }
                }
            }

            MidiDevice* dev = mport->device();
            if (!used && !dev)
                continue;
            bool isGlobal = gInputListPorts.contains(mport->portno());
            xml.tag(level++, "midiport portId=\"%lld\" isGlobalInput=\"%d\"", mport->id(), isGlobal);

            if (mport->defaultInChannels())
                xml.intTag(level, "defaultInChans", mport->defaultInChannels());
            if (mport->defaultOutChannels())
                xml.intTag(level, "defaultOutChans", mport->defaultOutChannels());

            if (mport->instrument() && !mport->instrument()->iname().isEmpty() &&
                    (mport->instrument()->iname() != "GM")) // FIXME: TODO: Make this user configurable.
            {
                xml.strTag(level, "instrument", mport->instrument()->iname());
            }

            if (dev)
            {
                xml.strTag(level, "name", dev->name());
                xml.intTag(level, "cacheNRPN", (int)dev->cacheNRPN());

                if (dev->deviceType() != MidiDevice::ALSA_MIDI)
                    xml.intTag(level, "type", dev->deviceType());

                xml.intTag(level, "openFlags", dev->openFlags());
            }
            // write out registered controller for all channels
            MidiCtrlValListList* vll = mport->controller();
            for (int k = 0; k < MIDI_CHANNELS; ++k)
            {
                int min = k << 24;
                int max = min + 0x100000;
                xml.tag(level++, "channel idx=\"%d\"", k);
                iMidiCtrlValList s = vll->lower_bound(min);
                iMidiCtrlValList e = vll->lower_bound(max);
                if (s != e)
                {
                    for (iMidiCtrlValList i = s; i != e; ++i)
                    {
                        if(i->second->num() != 262145)
                        {
                            xml.tag(level++, "controller id=\"%d\"", i->second->num());
                            if (i->second->hwVal() != CTRL_VAL_UNKNOWN)
                                xml.intTag(level, "val", i->second->hwVal());
                            xml.etag(--level, "controller");
                        }
                    }
                }
                xml.etag(--level, "channel");
            }
            QList<PatchSequence*> *patchSequences = mport->patchSequences();
            if (patchSequences && !patchSequences->isEmpty())
            {
                for (int p = 0; p < patchSequences->size(); ++p)
                {
                    PatchSequence* ps = patchSequences->at(p);
                    QString pm = ps->name.replace('\n', " ");
                    xml.put(level, "<patchSequence id=\"%d\" name=\"%s\" checked=\"%d\" />", ps->id, pm.toLatin1().constData(), ps->selected);
                }
            }
            if(!mport->presets()->isEmpty())
            {
                QHashIterator<int, QString> iter(*mport->presets());
                while(iter.hasNext())
                {
                    iter.next();
                    xml.put(level, "<midiPreset id=\"%d\" sysex=\"%s\"/>", iter.key(), iter.value().toLatin1().constData());
                }
            }
            xml.etag(--level, "midiport");
        }
    }
    xml.tag(--level, "/sequencer");
}/*}}}*/
示例#30
0
文件: mididev.cpp 项目: UIKit0/muse
void MidiDevice::handleSeek()
{
  // If the device is not in use by a port, don't bother it.
  if(_port == -1)
    return;
  
  MidiPort* mp = &MusEGlobal::midiPorts[_port];
  MidiInstrument* instr = mp->instrument();
  MidiCtrlValListList* cll = mp->controller();
  unsigned pos = MusEGlobal::audio->tickPos();
  
  //---------------------------------------------------
  //    Send STOP 
  //---------------------------------------------------
    
  // Don't send if external sync is on. The master, and our sync routing system will take care of that.  
  if(!MusEGlobal::extSyncFlag.value())
  {
    if(mp->syncInfo().MRTOut())
    {
      // Shall we check for device write open flag to see if it's ok to send?...
      //if(!(rwFlags() & 0x1) || !(openFlags() & 1))
      //if(!(openFlags() & 1))
      //  continue;
      mp->sendStop();
    }    
  }

  //---------------------------------------------------
  //    If playing, clear all notes and flush out any
  //     stuck notes which were put directly to the device
  //---------------------------------------------------
  
  if(MusEGlobal::audio->isPlaying()) 
  {
    _playEvents.clear();
    for(iMPEvent i = _stuckNotes.begin(); i != _stuckNotes.end(); ++i) 
    {
      MidiPlayEvent ev(*i);
      ev.setTime(0);
      putEvent(ev);  // For immediate playback try putEvent, putMidiEvent, or sendEvent (for the optimizations).
    }
    _stuckNotes.clear();
  }
  
  //---------------------------------------------------
  //    Send new controller values
  //---------------------------------------------------
    
  // Find channels on this port used in the song...
  bool usedChans[MIDI_CHANNELS];
  int usedChanCount = 0;
  for(int i = 0; i < MIDI_CHANNELS; ++i)
    usedChans[i] = false;
  if(MusEGlobal::song->click() && MusEGlobal::clickPort == _port)
  {
    usedChans[MusEGlobal::clickChan] = true;
    ++usedChanCount;
  }
  bool drum_found = false;
  for(ciMidiTrack imt = MusEGlobal::song->midis()->begin(); imt != MusEGlobal::song->midis()->end(); ++imt)
  {
    //------------------------------------------------------------
    //    While we are at it, flush out any track-related playback stuck notes
    //     (NOT 'live' notes) which were not put directly to the device
    //------------------------------------------------------------
    MPEventList& mel = (*imt)->stuckNotes;
    for(iMPEvent i = mel.begin(), i_next = i; i != mel.end(); i = i_next)
    {
      ++i_next;

      if((*i).port() != _port)
        continue;
      MidiPlayEvent ev(*i);
      ev.setTime(0);
      putEvent(ev); // For immediate playback try putEvent, putMidiEvent, or sendEvent (for the optimizations).
      mel.erase(i);
    }
    
    if((*imt)->type() == MusECore::Track::DRUM)
    {
      if(!drum_found)
      {
        drum_found = true; 
        for(int i = 0; i < DRUM_MAPSIZE; ++i)
        {
          // Default to track port if -1 and track channel if -1.
          int mport = MusEGlobal::drumMap[i].port;
          if(mport == -1)
            mport = (*imt)->outPort();
          int mchan = MusEGlobal::drumMap[i].channel;
          if(mchan == -1)
            mchan = (*imt)->outChannel();
          if(mport != _port || usedChans[mchan])
            continue;
          usedChans[mchan] = true;
          ++usedChanCount;
          if(usedChanCount >= MIDI_CHANNELS)
            break;  // All are used, done searching.
        }
      }
    }
    else
    {
      if((*imt)->outPort() != _port || usedChans[(*imt)->outChannel()])
        continue;
      usedChans[(*imt)->outChannel()] = true;
      ++usedChanCount;
    }

    if(usedChanCount >= MIDI_CHANNELS)
      break;    // All are used. Done searching.
  }   
  
  for(iMidiCtrlValList ivl = cll->begin(); ivl != cll->end(); ++ivl) 
  {
    MidiCtrlValList* vl = ivl->second;
    int chan = ivl->first >> 24;
    if(!usedChans[chan])  // Channel not used in song?
      continue;
    int ctlnum = vl->num();

    // Find the first non-muted value at the given tick...
    bool values_found = false;
    bool found_value = false;
    
    iMidiCtrlVal imcv = vl->lower_bound(pos);
    if(imcv != vl->end() && imcv->first == (int)pos)
    {
      for( ; imcv != vl->end() && imcv->first == (int)pos; ++imcv)
      {
        const Part* p = imcv->second.part;
        if(!p)
          continue;
        // Ignore values that are outside of the part.
        if(pos < p->tick() || pos >= (p->tick() + p->lenTick()))
          continue;
        values_found = true;
        // Ignore if part or track is muted or off.
        if(p->mute())
          continue;
        const Track* track = p->track();
        if(track && (track->isMute() || track->off()))
          continue;
        found_value = true;
        break;
      }
    }
    else
    {
      while(imcv != vl->begin())
      {
        --imcv;
        const Part* p = imcv->second.part;
        if(!p)
          continue;
        // Ignore values that are outside of the part.
        unsigned t = imcv->first;
        if(t < p->tick() || t >= (p->tick() + p->lenTick()))
          continue;
        values_found = true;
        // Ignore if part or track is muted or off.
        if(p->mute())
          continue;
        const Track* track = p->track();
        if(track && (track->isMute() || track->off()))
          continue;
        found_value = true;
        break;
      }
    }

    if(found_value)
    {
      // Don't bother sending any sustain values if not playing. Just set the hw state.
      if(ctlnum == CTRL_SUSTAIN && !MusEGlobal::audio->isPlaying())
        mp->setHwCtrlState(chan, CTRL_SUSTAIN, imcv->second.val);
      else
        // Use sendEvent to get the optimizations and limiting. But force if there's a value at this exact position.
        // NOTE: Why again was this forced? There was a reason. Think it was RJ in response to bug rep, then I modded.
        // A reason not to force: If a straight line is drawn on graph, multiple identical events are stored
        //  (which must be allowed). So seeking through them here sends them all redundantly, not good. // REMOVE Tim.
        mp->sendEvent(MidiPlayEvent(0, _port, chan, ME_CONTROLLER, ctlnum, imcv->second.val), false); //, imcv->first == pos);
        //mp->sendEvent(MidiPlayEvent(0, _port, chan, ME_CONTROLLER, ctlnum, imcv->second.val), pos == 0 || imcv->first == pos);
    }

    // Either no value was found, or they were outside parts, or pos is in the unknown area before the first value.
    // Send instrument default initial values.  NOT for syntis. Use midiState and/or initParams for that. 
    //if((imcv == vl->end() || !done) && !MusEGlobal::song->record() && instr && !isSynti()) 
    // Hmm, without refinement we can only do this at position 0, due to possible 'skipped' values outside parts, above.
    if(!values_found && MusEGlobal::config.midiSendCtlDefaults && !MusEGlobal::song->record() && pos == 0 && instr && !isSynti())
    {
      MidiControllerList* mcl = instr->controller();
      ciMidiController imc = mcl->find(vl->num());
      if(imc != mcl->end())
      {
        MidiController* mc = imc->second;
        if(mc->initVal() != CTRL_VAL_UNKNOWN)
          // Use sendEvent to get the optimizations and limiting. No force sending. Note the addition of bias.
          mp->sendEvent(MidiPlayEvent(0, _port, chan, ME_CONTROLLER, ctlnum, mc->initVal() + mc->bias()), false);
      }
    }
  }
  
  //---------------------------------------------------
  //    reset sustain
  //---------------------------------------------------
  
  for(int ch = 0; ch < MIDI_CHANNELS; ++ch) 
  {
    if(mp->hwCtrlState(ch, CTRL_SUSTAIN) == 127) 
    {
      const MidiPlayEvent ev(0, _port, ch, ME_CONTROLLER, CTRL_SUSTAIN, 0);
      putEvent(ev);
    }
  }
  
  //---------------------------------------------------
  //    Send STOP and "set song position pointer"
  //---------------------------------------------------
    
  // Don't send if external sync is on. The master, and our sync routing system will take care of that.  
  if(!MusEGlobal::extSyncFlag.value())
  {
    if(mp->syncInfo().MRTOut())
    {
      //mp->sendStop();   // Moved above
      int beat = (pos * 4) / MusEGlobal::config.division;
      mp->sendSongpos(beat);
    }    
  }
}