From 5fa5f8210b4924a1f2ae0100dfb6c0b50c85db81 Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Sun, 9 Jan 2011 21:32:13 +0000 Subject: Completed soloing system. Other fixes - see ChangeLog. --- muse2/ChangeLog | 8 + muse2/muse/app.cpp | 332 ++++++++++++++++++++----------- muse2/muse/arranger/tlist.cpp | 8 +- muse2/muse/audiotrack.cpp | 3 +- muse2/muse/ctrl/ctrledit.cpp | 22 +++ muse2/muse/ctrl/ctrledit.h | 3 + muse2/muse/midiport.cpp | 8 +- muse2/muse/mixer/amixer.cpp | 3 +- muse2/muse/mixer/astrip.cpp | 374 ++++++++++++++++++++++------------- muse2/muse/mixer/mstrip.cpp | 5 +- muse2/muse/node.cpp | 26 ++- muse2/muse/route.cpp | 67 ++++++- muse2/muse/track.cpp | 78 +++----- muse2/muse/widgets/mtrackinfo.cpp | 15 +- muse2/muse/widgets/mtrackinfobase.ui | 18 +- 15 files changed, 641 insertions(+), 329 deletions(-) diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 5006df0b..8bcfe6f0 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,11 @@ +09.01.2011: + - These changes marked as p4.0.14: + - Applied aux send fix AudioTrack::writeProperties() by Remon. Thanks. (Tim) + * Feature!: Complete soloing system (after 4 years). Support chaining Midi Port/Audio Out -> Audio In. (Tim) + Click on audio strip iR, or midi strip oR, or midi track info oR buttons to see new additions. + Tested thoroughly, but of course this major change needs wider testing. + TODO TODO: Fix trackinfo width (a minor button placement gui issue). + - Fixed very slow midi trackinfo property adjustments with mixer shown. In AudioMixerApp::songChanged(). (Tim) 04.01.2011: - Added saving and restoring of pianoroll trackinfo h-splitter state. (Tim) - Fixed multiple velocity controllers appearing on song reload. Tested OK. (Tim) diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 1f2edc1a..2c4758a6 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -49,6 +49,7 @@ #include "transpose.h" #include "waveedit.h" #include "widgets/projectcreateimpl.h" +#include "widgets/menutitleitem.h" #ifdef DSSI_SUPPORT #include "dssihost.h" @@ -2188,7 +2189,7 @@ PopupMenu* MusE::getRoutingPopupMenu() void MusE::updateRouteMenus(Track* track, QObject* master) { - // NOTE: The puropse of this routine is to make sure the items actually reflect + // NOTE: The purpose of this routine is to make sure the items actually reflect // the routing status. And with MusE-1 QT3, it was also required to actually // check the items since QT3 didn't do it for us. // But now with MusE-2 and QT4, QT4 checks an item when it is clicked. @@ -2218,9 +2219,84 @@ void MusE::updateRouteMenus(Track* track, QObject* master) { // p3.3.50 Ignore the 'toggle' items. if(imm->second.type == Route::MIDI_PORT_ROUTE && - imm->first >= (MIDI_PORTS * MIDI_CHANNELS) && imm->first < (MIDI_PORTS * MIDI_CHANNELS + MIDI_PORTS)) + //imm->first >= (MIDI_PORTS * MIDI_CHANNELS) && imm->first < (MIDI_PORTS * MIDI_CHANNELS + MIDI_PORTS)) + imm->second.channel == (1 << MIDI_CHANNELS) - 1) // p4.0.14 See if all channels are set, rather than using ID. continue; + + // p4.0.14 TODO FIXME Couldn't quite figure out the logic yet. It should be possible (I hope). + // But not really required for now, as per above note. + if(gIsOutRoutingPopupMenu && track->isMidiTrack() && + imm->second.type == Route::TRACK_ROUTE && imm->second.track->type() == Track::AUDIO_INPUT) + return; + #if 0 + printf("imm route:\n"); // REMOVE Tim. + imm->second.dump(); + if(track->isMidiTrack()) + { + if(imm->second.type == Route::TRACK_ROUTE && imm->second.track->type() == Track::AUDIO_INPUT) + { + Route &aRoute = imm->second; + int chbit = aRoute.channel; + ///Route bRoute(track, chbit); + ///int mdidx = bRoute.midiPort; + int port = ((MidiTrack*)track)->outPort(); + if(port < 0 || port >= MIDI_PORTS) + continue; + int tchbit = 1 << ((MidiTrack*)track)->outChannel(); + + MidiPort* mp = &midiPorts[port]; + + ///Route bRoute(port, chbit); + + //int chmask = 0; + bool found = false; + RouteList* mprl = gIsOutRoutingPopupMenu ? mp->outRoutes() : mp->inRoutes(); + iRoute ir = mprl->begin(); + for(; ir != mprl->end(); ++ir) + { + printf("mp route:\n"); // REMOVE Tim. + ir->dump(); // REMOVE Tim. + ///if(aRoute.type == Route::TRACK_ROUTE) // Is the map route a track route? + { + if(ir->type == Route::TRACK_ROUTE && ir->track == aRoute.track) // Is the track route a midi port route? + //&& (ir->channel & chbit) == chbit) + //&& (ir->channel & tchbit)) // Is the exact channel mask bit(s) set? + { + printf("track matches\n"); // REMOVE Tim. + if(ir->channel & tchbit) + { + found = true; + printf("found: bit matches\n"); // REMOVE Tim. + } + break; + } + } + ///else + ///if(*ir == aRoute) + ///{ + //found = true; + /// break; + ///} + } + //pup->setItemChecked(imm->first, found); + //printf("MusE::updateRouteMenus setItemChecked\n"); + // TODO: MusE-2: Convert this, fastest way is to change the routing map, otherwise this requires a lookup. + //if(pup->isItemChecked(imm->first) != (irl != rl->end())) + // pup->setItemChecked(imm->first, irl != rl->end()); + QAction* act = pup->findActionFromData(imm->first); + //printf("set act checked to:%d\n", ir != mprl->end()); // REMOVE Tim. + //if(act && act->isChecked() != (ir != mprl->end())) + // act->setChecked(ir != mprl->end()); + printf("set act checked to:%d\n", found); // REMOVE Tim. + if(act && act->isChecked() != found) + act->setChecked(found); + + //return; + } + } + #endif + //bool found = false; iRoute irl = rl->begin(); for(; irl != rl->end(); ++irl) @@ -2278,6 +2354,69 @@ void MusE::routingPopupMenuActivated(Track* track, int n) iRouteMenuMap imm = gRoutingMenuMap.find(n); if(imm == gRoutingMenuMap.end()) return; + + // Support Midi Port to Audio Input track routes. p4.0.14 Tim. + if(imm->second.type == Route::TRACK_ROUTE) + { + //if(gIsOutRoutingPopupMenu) // Try to avoid splitting like this. + { + Route &aRoute = imm->second; + int chbit = aRoute.channel; + int port = ((MidiTrack*)track)->outPort(); + if(port < 0 || port >= MIDI_PORTS) + return; + + MidiPort* mp = &midiPorts[port]; + ///MidiDevice* md = mp->device(); + + // This is desirable, but could lead to 'hidden' routes unless we add more support + // such as removing the existing routes when user changes flags. + // So for now, just list all valid ports whether read or write. + ///if(!md) + /// return; + ///if(!(md->rwFlags() & (gIsOutRoutingPopupMenu ? 1 : 2))) + /// return; + + //int channel = ((MidiTrack*)track->outChannel(); + Route bRoute(port, chbit); + + int chmask = 0; + RouteList* mprl = gIsOutRoutingPopupMenu ? mp->outRoutes() : mp->inRoutes(); + iRoute ir = mprl->begin(); + for (; ir != mprl->end(); ++ir) + { + if(ir->type == Route::TRACK_ROUTE && ir->track == aRoute.track) // Is there already a route to this port? + { + chmask = ir->channel; // Grab the channel mask. + break; + } + } + //if (iir != rl->end()) + if ((chmask & chbit) == chbit) // Is the channel's bit(s) set? + { + // disconnect + if(gIsOutRoutingPopupMenu) + audio->msgRemoveRoute(bRoute, aRoute); + else + audio->msgRemoveRoute(aRoute, bRoute); + } + else + { + // connect + if(gIsOutRoutingPopupMenu) + audio->msgAddRoute(bRoute, aRoute); + else + audio->msgAddRoute(aRoute, bRoute); + } + + audio->msgUpdateSoloStates(); + song->update(SC_ROUTE); + + } + return; + } + + if(imm->second.type != Route::MIDI_PORT_ROUTE) return; Route &aRoute = imm->second; @@ -2580,45 +2719,71 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst) if(!track) return 0; - //QPoint ppt = QCursor::pos(); - if(track->isMidiTrack()) { + RouteList* rl = dst ? track->outRoutes() : track->inRoutes(); + //Route dst(track, -1); - //QPoint ppt = parent->rect().bottomLeft(); - - //if(dst) - //{ - // TODO + PopupMenu* pup = getRoutingPopupMenu(); + pup->disconnect(); + //connect(pup, SIGNAL(activated(int)), SLOT(routingPopupMenuActivated(int))); + //connect(pup, SIGNAL(aboutToHide()), SLOT(routingPopupMenuAboutToHide())); - //} - //else - //{ - RouteList* rl = dst ? track->outRoutes() : track->inRoutes(); - //Route dst(track, -1); + pup->clear(); + gRoutingMenuMap.clear(); - PopupMenu* pup = getRoutingPopupMenu(); - pup->disconnect(); - //connect(pup, SIGNAL(activated(int)), SLOT(routingPopupMenuActivated(int))); - //connect(pup, SIGNAL(aboutToHide()), SLOT(routingPopupMenuAboutToHide())); + int gid = 0; + QAction* act = 0; + + if(dst) + { + // Support Midi Port to Audio Input track routes. p4.0.14 Tim. + int port = ((MidiTrack*)track)->outPort(); + if(port >= 0 && port < MIDI_PORTS) + { + MidiPort* mp = &midiPorts[port]; + RouteList* mprl = mp->outRoutes(); + int chbits = 1 << ((MidiTrack*)track)->outChannel(); + //MidiDevice* md = mp->device(); + //if(!md) + // continue; - int gid = 0; - //int n; - QAction* act = 0; - - // Routes can't be re-read until the message sent from msgAddRoute1() - // has had time to be sent and actually affected the routes. - ///_redisplay: - - pup->clear(); - gRoutingMenuMap.clear(); - gid = 0; - - //MidiInPortList* tl = song->midiInPorts(); - //for(iMidiInPort i = tl->begin();i != tl->end(); ++i) + pup->addSeparator(); + pup->addAction(new MenuTitleItem(tr("Soloing chain"), pup)); + PopupMenu* subp = new PopupMenu(pup); + subp->setTitle(tr("Audio returns")); + pup->addMenu(subp); + + InputList* al = song->inputs(); + for (iAudioInput i = al->begin(); i != al->end(); ++i) + { + Track* t = *i; + QString s(t->name()); + + act = subp->addAction(s); + act->setData(gid); + act->setCheckable(true); + + Route r(t, chbits); + + gRoutingMenuMap.insert( pRouteMenuMap(gid, r) ); + + for(iRoute ir = mprl->begin(); ir != mprl->end(); ++ir) + { + if(ir->type == Route::TRACK_ROUTE && ir->track == t && (ir->channel & chbits)) + { + act->setChecked(true); + break; + } + } + ++gid; + } + } + } + else + { for(int i = 0; i < MIDI_PORTS; ++i) { - //MidiInPort* track = *i; // NOTE: Could possibly list all devices, bypassing ports, but no, let's stick with ports. MidiPort* mp = &midiPorts[i]; MidiDevice* md = mp->device(); @@ -2630,10 +2795,6 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst) //printf("MusE::prepareRoutingPopupMenu adding submenu portnum:%d\n", i); - //QMenu* m = menu->addMenu(track->name()); - //QPopupMenu* subp = new QPopupMenu(parent); - //PopupMenu* subp = new PopupMenu(this); - //PopupMenu* subp = new PopupMenu(); PopupMenu* subp = new PopupMenu(pup); subp->setTitle(md->name()); @@ -2656,101 +2817,46 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst) for(int ch = 0; ch < MIDI_CHANNELS; ++ch) { - //QAction* a = m->addAction(QString("Channel %1").arg(ch+1)); - //subp->insertItem(QT_TRANSLATE_NOOP("@default", QString("Channel %1").arg(ch+1)), i * MIDI_CHANNELS + ch); - gid = i * MIDI_CHANNELS + ch; - - //printf("MusE::prepareRoutingPopupMenu inserting gid:%d\n", gid); - act = subp->addAction(QString("Channel %1").arg(ch+1)); act->setCheckable(true); act->setData(gid); - //a->setCheckable(true); - //Route src(track, ch, RouteNode::TRACK); - //Route src(md, ch); - //Route r = Route(src, dst); - //a->setData(QVariant::fromValue(r)); - //a->setChecked(rl->indexOf(r) != -1); - //Route srcRoute(md, ch); - //Route srcRoute(i, ch); // p3.3.49 New: Midi port route. int chbit = 1 << ch; Route srcRoute(i, chbit); // p3.3.50 In accordance with new channel mask, use the bit position. gRoutingMenuMap.insert( pRouteMenuMap(gid, srcRoute) ); - //for(iRoute ir = rl->begin(); ir != rl->end(); ++ir) // p3.3.50 Removed. - //{ - //if(*ir == dst) - // if(*ir == srcRoute) - // { - // subp->setItemChecked(id, true); - // break; - // } - //} if(chanmask & chbit) // p3.3.50 Is the channel already set? Show item check mark. act->setChecked(true); + + ++gid; } - //subp->insertItem(QString("Toggle all"), 1000+i); - // p3.3.50 One route with all channel bits set. - gid = MIDI_PORTS * MIDI_CHANNELS + i; // Make sure each 'toggle' item gets a unique id. + //gid = MIDI_PORTS * MIDI_CHANNELS + i; // Make sure each 'toggle' item gets a unique id. act = subp->addAction(QString("Toggle all")); //act->setCheckable(true); act->setData(gid); Route togRoute(i, (1 << MIDI_CHANNELS) - 1); // Set all channel bits. gRoutingMenuMap.insert( pRouteMenuMap(gid, togRoute) ); - + ++gid; pup->addMenu(subp); } - - /* - QPopupMenu* pup = new QPopupMenu(iR); - pup->setCheckable(true); - //MidiTrack* t = (MidiTrack*)track; - RouteList* irl = track->inRoutes(); - - MidiTrack* t = (MidiTrack*)track; - int gid = 0; - for (int i = 0; i < channel; ++i) - { - char buffer[128]; - snprintf(buffer, 128, "%s %d", tr("Channel").toLatin1().constData(), i+1); - MenuTitleItem* titel = new MenuTitleItem(QString(buffer)); - pup->insertItem(titel); - - if (!checkAudioDevice()) return; - std::list ol = audioDevice->outputPorts(); - for (std::list::iterator ip = ol.begin(); ip != ol.end(); ++ip) { - int id = pup->insertItem(*ip, (gid * 16) + i); - Route dst(*ip, true, i); - ++gid; - for (iRoute ir = irl->begin(); ir != irl->end(); ++ir) { - if (*ir == dst) { - pup->setItemChecked(id, true); - break; - } - } - } - if (i+1 != channel) - pup->addSeparator(); - } - */ - - if(pup->actions().isEmpty()) - { - gRoutingPopupMenuMaster = 0; - //pup->clear(); - //pup->disconnect(); - gRoutingMenuMap.clear(); - //oR->setDown(false); - return 0; - } - - gIsOutRoutingPopupMenu = dst; - return pup; + } + + if(pup->actions().isEmpty()) + { + gRoutingPopupMenuMaster = 0; + //pup->clear(); + //pup->disconnect(); + gRoutingMenuMap.clear(); + //oR->setDown(false); + return 0; } - return 0; + gIsOutRoutingPopupMenu = dst; + return pup; + } + + return 0; } #if 0 @@ -3145,9 +3251,9 @@ void MusE::startPianoroll(PartList* pl, bool showDefaultCtrls) { PianoRoll* pianoroll = new PianoRoll(pl, this, 0, arranger->cursorValue()); - pianoroll->show(); if(showDefaultCtrls) // p4.0.12 pianoroll->addCtrl(); + pianoroll->show(); toplevels.push_back(Toplevel(Toplevel::PIANO_ROLL, (unsigned long)(pianoroll), pianoroll)); connect(pianoroll, SIGNAL(deleted(unsigned long)), SLOT(toplevelDeleted(unsigned long))); connect(muse, SIGNAL(configChanged()), pianoroll, SLOT(configChanged())); @@ -3215,9 +3321,9 @@ void MusE::startDrumEditor(PartList* pl, bool showDefaultCtrls) { DrumEdit* drumEditor = new DrumEdit(pl, this, 0, arranger->cursorValue()); - drumEditor->show(); if(showDefaultCtrls) // p4.0.12 drumEditor->addCtrl(); + drumEditor->show(); toplevels.push_back(Toplevel(Toplevel::DRUM, (unsigned long)(drumEditor), drumEditor)); connect(drumEditor, SIGNAL(deleted(unsigned long)), SLOT(toplevelDeleted(unsigned long))); connect(muse, SIGNAL(configChanged()), drumEditor, SLOT(configChanged())); diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index 02f742f7..e32d0010 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -1027,6 +1027,9 @@ void TList::mousePressEvent(QMouseEvent* ev) //if(button == QMouseEvent::LeftButton) // portsPopupMenu(t, x, t->y() - ypos); + audio->msgUpdateSoloStates(); // p4.0.14 + //song->update(SC_ROUTE); // + break; case COL_MUTE: // p3.3.29 @@ -1141,7 +1144,10 @@ void TList::mousePressEvent(QMouseEvent* ev) // may result in adding/removing mixer strip: //song->update(-1); //song->update(SC_CHANNELS); - song->update(SC_MIDI_TRACK_PROP); + //song->update(SC_MIDI_TRACK_PROP); + audio->msgUpdateSoloStates(); // p4.0.14 + //song->update(SC_MIDI_TRACK_PROP | SC_ROUTE); // + song->update(SC_MIDI_TRACK_PROP); // } } else diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp index 7330e79e..19bbbaf1 100644 --- a/muse2/muse/audiotrack.cpp +++ b/muse2/muse/audiotrack.cpp @@ -860,7 +860,8 @@ void AudioTrack::writeProperties(int level, Xml& xml) const if (hasAuxSend()) { int naux = song->auxs()->size(); for (int idx = 0; idx < naux; ++idx) { - QString s("%2\n"); + //QString s("%2\n"); + QString s("%2\n"); // Aux fix from Remon, thanks. xml.nput(level, s.arg(idx).arg(_auxSend[idx]).toAscii().constData()); } } diff --git a/muse2/muse/ctrl/ctrledit.cpp b/muse2/muse/ctrl/ctrledit.cpp index fe04844d..8842ba97 100644 --- a/muse2/muse/ctrl/ctrledit.cpp +++ b/muse2/muse/ctrl/ctrledit.cpp @@ -132,3 +132,25 @@ void CtrlEdit::setCanvasWidth(int w) { canvas->setFixedWidth(w); } + +void CtrlEdit::setController(int n) +{ + canvas->setController(n); +} + +void CtrlEdit::setController(const QString& name) +{ + int portno = canvas->track()->outPort(); + MidiPort* port = &midiPorts[portno]; + MidiInstrument* instr = port->instrument(); + MidiControllerList* mcl = instr->controller(); + + for (iMidiController ci = mcl->begin(); ci != mcl->end(); ++ci) + { + if (ci->second->name() == name) + { + canvas->setController(ci->second->num()); + break; + } + } +} diff --git a/muse2/muse/ctrl/ctrledit.h b/muse2/muse/ctrl/ctrledit.h index 61bf9b46..eec235b1 100644 --- a/muse2/muse/ctrl/ctrledit.h +++ b/muse2/muse/ctrl/ctrledit.h @@ -37,6 +37,8 @@ class CtrlEdit : public QWidget { void setXPos(int val) { canvas->setXPos(val); } void setXMag(int val) { canvas->setXMag(val); } void setCanvasWidth(int w); + void setController(int /*n*/); + signals: void timeChanged(unsigned); void destroyedCtrl(CtrlEdit*); @@ -48,6 +50,7 @@ class CtrlEdit : public QWidget { bool expand = false, const char* name = 0); void readStatus(Xml&); void writeStatus(int, Xml&); + void setController(const QString& name); }; #endif diff --git a/muse2/muse/midiport.cpp b/muse2/muse/midiport.cpp index 02fed8d1..16cfd429 100644 --- a/muse2/muse/midiport.cpp +++ b/muse2/muse/midiport.cpp @@ -62,7 +62,7 @@ MidiPort::MidiPort() // to make midi mixer operational // for (int i = 0; i < MIDI_CHANNELS; ++i) { - addManagedController(i, CTRL_PROGRAM); + addManagedController(i, CTRL_PROGRAM); addManagedController(i, CTRL_VOLUME); addManagedController(i, CTRL_PANPOT); _automationType[i] = AUTO_READ; @@ -1013,8 +1013,10 @@ void MidiPort::writeRouting(int level, Xml& xml) const { if(r->type == Route::TRACK_ROUTE && !r->name().isEmpty()) { - //xml.tag(level++, "Route"); - + // Ignore Midi Port to Audio Input routes. Handled by Track route writer. p4.0.14 Tim. + if(r->track && r->track->type() == Track::AUDIO_INPUT) + continue; + s = QT_TRANSLATE_NOOP("@default", "Route"); if(r->channel != -1 && r->channel != 0) s += QString(QT_TRANSLATE_NOOP("@default", " channelMask=\"%1\"")).arg(r->channel); // Use new channel mask. diff --git a/muse2/muse/mixer/amixer.cpp b/muse2/muse/mixer/amixer.cpp index 7fb406f3..e4a82ce8 100644 --- a/muse2/muse/mixer/amixer.cpp +++ b/muse2/muse/mixer/amixer.cpp @@ -538,7 +538,8 @@ void AudioMixerApp::songChanged(int flags) action = STRIP_INSERTED; else if (flags & SC_MIDI_TRACK_PROP) action = UPDATE_MIDI; - if (action != NO_UPDATE) + //if (action != NO_UPDATE) + if (action != NO_UPDATE && action != UPDATE_MIDI) // p4.0.14 Fix for very slow track prop adjusting. updateMixer(action); if (action != UPDATE_ALL) { StripList::iterator si = stripList.begin(); diff --git a/muse2/muse/mixer/astrip.cpp b/muse2/muse/mixer/astrip.cpp index 1317f63d..a680d302 100644 --- a/muse2/muse/mixer/astrip.cpp +++ b/muse2/muse/mixer/astrip.cpp @@ -68,6 +68,11 @@ QWidget* MenuTitleItem::createWidget(QWidget *parent) { QLabel* l = new QLabel(s, parent); l->setAlignment(Qt::AlignCenter); + l->setAutoFillBackground(true); + //QPalette palette; + //palette.setColor(label->backgroundRole(), c); + //l->setPalette(palette); + l->setBackgroundRole(QPalette::Dark); return l; } @@ -1541,6 +1546,181 @@ static int nonSyntiTrackAddSyntis(AudioTrack* t, PopupMenu* lb, int id, RouteMen return id; } +//--------------------------------------------------------- +// addMidiPorts +//--------------------------------------------------------- + +static int addMidiPorts(AudioTrack* t, PopupMenu* pup, int id, RouteMenuMap& mm, bool isOutput) +{ + QAction* act; + for(int i = 0; i < MIDI_PORTS; ++i) + { + MidiPort* mp = &midiPorts[i]; + MidiDevice* md = mp->device(); + + // This is desirable, but could lead to 'hidden' routes unless we add more support + // such as removing the existing routes when user changes flags. + // So for now, just list all valid ports whether read or write. + if(!md) + continue; + //if(!(md->rwFlags() & (isOutput ? 1 : 2))) + // continue; + + RouteList* rl = isOutput ? t->outRoutes() : t->inRoutes(); + + PopupMenu* subp = new PopupMenu(pup); + subp->setTitle(md->name()); + + int chanmask = 0; + // To reduce number of routes required, from one per channel to just one containing a channel mask. + // Look for the first route to this midi port. There should always be only a single route for each midi port, now. + for(iRoute ir = rl->begin(); ir != rl->end(); ++ir) + { + if(ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == i) + { + // We have a route to the midi port. Grab the channel mask. + chanmask = ir->channel; + break; + } + } + + for(int ch = 0; ch < MIDI_CHANNELS; ++ch) + { + act = subp->addAction(QString("Channel %1").arg(ch+1)); + act->setCheckable(true); + act->setData(id); + + int chbit = 1 << ch; + Route srcRoute(i, chbit); // In accordance with new channel mask, use the bit position. + + mm.insert( pRouteMenuMap(id, srcRoute) ); + + if(chanmask & chbit) // Is the channel already set? Show item check mark. + act->setChecked(true); + + ++id; + } + + //gid = MIDI_PORTS * MIDI_CHANNELS + i; // Make sure each 'toggle' item gets a unique id. + act = subp->addAction(QString("Toggle all")); + //act->setCheckable(true); + act->setData(id); + Route togRoute(i, (1 << MIDI_CHANNELS) - 1); // Set all channel bits. + mm.insert( pRouteMenuMap(id, togRoute) ); + ++id; + + pup->addMenu(subp); + } + return id; +} + +//--------------------------------------------------------- +// routingPopupMenuActivated +//--------------------------------------------------------- + +void AudioStrip::routingPopupMenuActivated(QAction* act) +{ + if(!track || gRoutingPopupMenuMaster != this || track->isMidiTrack()) + return; + + PopupMenu* pup = muse->getRoutingPopupMenu(); + + if(pup->actions().isEmpty()) + return; + + AudioTrack* t = (AudioTrack*)track; + RouteList* rl = gIsOutRoutingPopupMenu ? t->outRoutes() : t->inRoutes(); + + int n = act->data().toInt(); + if (n == -1) + return; + + iRouteMenuMap imm = gRoutingMenuMap.find(n); + if(imm == gRoutingMenuMap.end()) + return; + + if(gIsOutRoutingPopupMenu) + { + Route srcRoute(t, imm->second.channel, imm->second.channels); + srcRoute.remoteChannel = imm->second.remoteChannel; + + Route &dstRoute = imm->second; + + // check if route src->dst exists: + iRoute irl = rl->begin(); + for (; irl != rl->end(); ++irl) { + if (*irl == dstRoute) + break; + } + if (irl != rl->end()) { + // disconnect if route exists + audio->msgRemoveRoute(srcRoute, dstRoute); + } + else { + // connect if route does not exist + audio->msgAddRoute(srcRoute, dstRoute); + } + audio->msgUpdateSoloStates(); + song->update(SC_ROUTE); + } + else + { + Route &srcRoute = imm->second; + + // Support Midi Port to Audio Input routes. p4.0.14 Tim. + if(track->type() == Track::AUDIO_INPUT && srcRoute.type == Route::MIDI_PORT_ROUTE) + { + int chbit = srcRoute.channel; + Route dstRoute(t, chbit); + int mdidx = srcRoute.midiPort; + int chmask = 0; + iRoute iir = rl->begin(); + for (; iir != rl->end(); ++iir) + { + if(iir->type == Route::MIDI_PORT_ROUTE && iir->midiPort == mdidx) // Is there already a route to this port? + { + chmask = iir->channel; // Grab the channel mask. + break; + } + } + + if ((chmask & chbit) == chbit) // Is the channel's bit(s) set? + { + //printf("astrip: removing src route ch:%d dst route ch:%d\n", srcRoute.channel, dstRoute.channel); + audio->msgRemoveRoute(srcRoute, dstRoute); + } + else + { + //printf("astrip: adding src route ch:%d dst route ch:%d\n", srcRoute.channel, dstRoute.channel); + audio->msgAddRoute(srcRoute, dstRoute); + } + + audio->msgUpdateSoloStates(); + song->update(SC_ROUTE); + return; + } + + Route dstRoute(t, imm->second.channel, imm->second.channels); + dstRoute.remoteChannel = imm->second.remoteChannel; + + iRoute irl = rl->begin(); + for (; irl != rl->end(); ++irl) { + if (*irl == srcRoute) + break; + } + if (irl != rl->end()) { + // disconnect + audio->msgRemoveRoute(srcRoute, dstRoute); + } + else { + // connect + audio->msgAddRoute(srcRoute, dstRoute); + } + audio->msgUpdateSoloStates(); + song->update(SC_ROUTE); + } +} + //--------------------------------------------------------- // iRoutePressed //--------------------------------------------------------- @@ -1564,7 +1744,7 @@ void AudioStrip::iRoutePressed() QAction* act = 0; int gid = 0; - int id = 0; + //int id = 0; pup->clear(); gRoutingMenuMap.clear(); @@ -1592,13 +1772,15 @@ void AudioStrip::iRoutePressed() std::list ol = audioDevice->outputPorts(); for(std::list::iterator ip = ol.begin(); ip != ol.end(); ++ip) { - id = gid * 16 + i; + //id = gid * 16 + i; // IDs removed p4.0.14 Tim. act = pup->addAction(*ip); - act->setData(id); + //act->setData(id); + act->setData(gid); act->setCheckable(true); Route dst(*ip, true, i, Route::JACK_ROUTE); - gRoutingMenuMap.insert( pRouteMenuMap(id, dst) ); + //gRoutingMenuMap.insert( pRouteMenuMap(id, dst) ); + gRoutingMenuMap.insert( pRouteMenuMap(gid, dst) ); ++gid; for(iRoute ir = irl->begin(); ir != irl->end(); ++ir) { @@ -1612,6 +1794,29 @@ void AudioStrip::iRoutePressed() if(i+1 != channel) pup->addSeparator(); } + + // p4.0.14 + // + // Display using separate menus for midi ports and audio outputs: + // + pup->addSeparator(); + pup->addAction(new MenuTitleItem(tr("Soloing chain"), pup)); + PopupMenu* subp = new PopupMenu(pup); + subp->setTitle(tr("Audio sends")); + pup->addMenu(subp); + gid = addOutPorts(t, subp, gid, gRoutingMenuMap, -1, -1, false); + subp = new PopupMenu(pup); + subp->setTitle(tr("Midi sends")); + pup->addMenu(subp); + addMidiPorts(t, subp, gid, gRoutingMenuMap, false); + // + // Display all in the same menu: + // + //pup->addAction(new MenuTitleItem(tr("Audio sends"), pup)); + //gid = addOutPorts(t, pup, gid, gRoutingMenuMap, -1, -1, false); + //pup->addSeparator(); + //pup->addAction(new MenuTitleItem(tr("Midi sends"), pup)); + //addMidiPorts(t, pup, gid, gRoutingMenuMap, false); } break; //case Track::AUDIO_OUTPUT: @@ -1661,140 +1866,7 @@ void AudioStrip::iRoutePressed() pup->popup(ppt); iR->setDown(false); } - -//--------------------------------------------------------- -// routingPopupMenuActivated -//--------------------------------------------------------- - -void AudioStrip::routingPopupMenuActivated(QAction* act) -{ - if(!track || gRoutingPopupMenuMaster != this || track->isMidiTrack()) - return; - - PopupMenu* pup = muse->getRoutingPopupMenu(); - - if(pup->actions().isEmpty()) - return; - - AudioTrack* t = (AudioTrack*)track; - RouteList* rl = gIsOutRoutingPopupMenu ? t->outRoutes() : t->inRoutes(); - - int n = act->data().toInt(); - if (n == -1) - return; - if(gIsOutRoutingPopupMenu) - { - if(track->type() == Track::AUDIO_OUTPUT) - { - - int chan = n & 0xf; - - Route srcRoute(t, chan); - Route dstRoute(act->text(), true, -1, Route::JACK_ROUTE); - dstRoute.channel = chan; - - // check if route src->dst exists: - iRoute irl = rl->begin(); - for (; irl != rl->end(); ++irl) { - if (*irl == dstRoute) - break; - } - if (irl != rl->end()) { - // disconnect if route exists - audio->msgRemoveRoute(srcRoute, dstRoute); - } - else { - // connect if route does not exist - audio->msgAddRoute(srcRoute, dstRoute); - } - audio->msgUpdateSoloStates(); - song->update(SC_ROUTE); - return; - } - - iRouteMenuMap imm = gRoutingMenuMap.find(n); - if(imm == gRoutingMenuMap.end()) - return; - - Route srcRoute(t, imm->second.channel, imm->second.channels); - srcRoute.remoteChannel = imm->second.remoteChannel; - - Route &dstRoute = imm->second; - - // check if route src->dst exists: - iRoute irl = rl->begin(); - for (; irl != rl->end(); ++irl) { - if (*irl == dstRoute) - break; - } - if (irl != rl->end()) { - // disconnect if route exists - audio->msgRemoveRoute(srcRoute, dstRoute); - } - else { - // connect if route does not exist - audio->msgAddRoute(srcRoute, dstRoute); - } - audio->msgUpdateSoloStates(); - song->update(SC_ROUTE); - } - else - { - if(track->type() == Track::AUDIO_INPUT) - { - int chan = n & 0xf; - - Route srcRoute(act->text(), false, -1, Route::JACK_ROUTE); - Route dstRoute(t, chan); - - srcRoute.channel = chan; - - iRoute irl = rl->begin(); - for(; irl != rl->end(); ++irl) - { - if(*irl == srcRoute) - break; - } - if(irl != rl->end()) - // disconnect - audio->msgRemoveRoute(srcRoute, dstRoute); - else - // connect - audio->msgAddRoute(srcRoute, dstRoute); - - audio->msgUpdateSoloStates(); - song->update(SC_ROUTE); - return; - } - - iRouteMenuMap imm = gRoutingMenuMap.find(n); - if(imm == gRoutingMenuMap.end()) - return; - - Route &srcRoute = imm->second; - - Route dstRoute(t, imm->second.channel, imm->second.channels); - dstRoute.remoteChannel = imm->second.remoteChannel; - - iRoute irl = rl->begin(); - for (; irl != rl->end(); ++irl) { - if (*irl == srcRoute) - break; - } - if (irl != rl->end()) { - // disconnect - audio->msgRemoveRoute(srcRoute, dstRoute); - } - else { - // connect - audio->msgAddRoute(srcRoute, dstRoute); - } - audio->msgUpdateSoloStates(); - song->update(SC_ROUTE); - } -} - //--------------------------------------------------------- // oRoutePressed //--------------------------------------------------------- @@ -1817,7 +1889,7 @@ void AudioStrip::oRoutePressed() QAction* act = 0; int gid = 0; - int id = 0; + //int id = 0; pup->clear(); gRoutingMenuMap.clear(); @@ -1845,13 +1917,15 @@ void AudioStrip::oRoutePressed() std::list ol = audioDevice->inputPorts(); for(std::list::iterator ip = ol.begin(); ip != ol.end(); ++ip) { - id = gid * 16 + i; + //id = gid * 16 + i; // IDs removed p4.0.14 Tim. act = pup->addAction(*ip); - act->setData(id); + //act->setData(id); + act->setData(gid); act->setCheckable(true); Route dst(*ip, true, i, Route::JACK_ROUTE); - gRoutingMenuMap.insert( pRouteMenuMap(id, dst) ); + //gRoutingMenuMap.insert( pRouteMenuMap(id, dst) ); + gRoutingMenuMap.insert( pRouteMenuMap(gid, dst) ); ++gid; for(iRoute ir = orl->begin(); ir != orl->end(); ++ir) { @@ -1865,6 +1939,24 @@ void AudioStrip::oRoutePressed() if(i+1 != channel) pup->addSeparator(); } + + // p4.0.14 + // + // Display using separate menu for audio inputs: + // + pup->addSeparator(); + pup->addAction(new MenuTitleItem(tr("Soloing chain"), pup)); + PopupMenu* subp = new PopupMenu(pup); + subp->setTitle(tr("Audio returns")); + pup->addMenu(subp); + gid = addInPorts(t, subp, gid, gRoutingMenuMap, -1, -1, true); + // + // Display all in the same menu: + // + //pup->addSeparator(); + //MenuTitleItem* title = new MenuTitleItem(tr("Audio returns"), pup); + //pup->addAction(title); + //gid = addInPorts(t, pup, gid, gRoutingMenuMap, -1, -1, true); } break; //case Track::AUDIO_INPUT: diff --git a/muse2/muse/mixer/mstrip.cpp b/muse2/muse/mixer/mstrip.cpp index abf37a28..f6e195b0 100644 --- a/muse2/muse/mixer/mstrip.cpp +++ b/muse2/muse/mixer/mstrip.cpp @@ -394,8 +394,9 @@ MidiStrip::MidiStrip(QWidget* parent, MidiTrack* t) oR->setText(tr("oR")); oR->setCheckable(false); // TODO: Works OK, but disabled for now, until we figure out what to do about multiple out routes and display values... - oR->setEnabled(false); - oR->setToolTip(tr("output routing")); + // Enabled (for Midi Port to Audio Input routing). p4.0.14 Tim. + //oR->setEnabled(false); + //oR->setToolTip(tr("output routing")); grid->addWidget(oR, _curGridRow++, 1); connect(oR, SIGNAL(pressed()), SLOT(oRoutePressed())); diff --git a/muse2/muse/node.cpp b/muse2/muse/node.cpp index 8db0a3d3..114b03d3 100644 --- a/muse2/muse/node.cpp +++ b/muse2/muse/node.cpp @@ -208,9 +208,21 @@ void MidiTrack::updateSoloStates(bool noDec) if(outPort() >= 0) { - MidiDevice *md = midiPorts[outPort()].device(); + MidiPort* mp = &midiPorts[outPort()]; + MidiDevice *md = mp->device(); if(md && md->isSynti()) ((SynthI*)md)->updateInternalSoloStates(); + + // Support Midi Port -> Audio Input solo chains. p4.0.14 Tim. + const int chbits = 1 << outChannel(); + const RouteList* rl = mp->outRoutes(); + for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir) + { + if(ir->type == Route::TRACK_ROUTE && ir->track && ir->track->type() == Track::AUDIO_INPUT && (ir->channel & chbits) ) + { + ir->track->updateInternalSoloStates(); + } + } } } @@ -245,6 +257,18 @@ void AudioTrack::updateSoloStates(bool noDec) { if(ir->type == Route::TRACK_ROUTE) ir->track->updateInternalSoloStates(); + else + // Support Midi Port -> Audio Input solo chains. p4.0.14 Tim. + if(ir->type == Route::MIDI_PORT_ROUTE) + { + const MidiTrackList* ml = song->midis(); + for(ciMidiTrack im = ml->begin(); im != ml->end(); ++im) + { + MidiTrack* mt = *im; + if(mt->outPort() == ir->midiPort && ((1 << mt->outChannel()) & ir->channel) ) + mt->updateInternalSoloStates(); + } + } } } _tmpSoloChainDoIns = false; diff --git a/muse2/muse/route.cpp b/muse2/muse/route.cpp index 19f8d09f..92c32317 100644 --- a/muse2/muse/route.cpp +++ b/muse2/muse/route.cpp @@ -348,6 +348,59 @@ void addRoute(Route src, Route dst) fprintf(stderr, "addRoute: source is midi port:%d, but destination is not track\n", src.midiPort); return; } + + // p4.0.14 + /* + if(dst.track->type() == Track::AUDIO_INPUT) + { + if(src.channel < 1 || src.channel >= (1 << MIDI_CHANNELS)) + { + fprintf(stderr, "addRoute: source is midi port:%d, but channel mask:%d out of range\n", src.midiPort, src.channel); + return; + } + + MidiPort *mp = &midiPorts[src.midiPort]; + //src.channel = dst.channel = -1; + RouteList* outRoutes = mp->outRoutes(); + iRoute ir = outRoutes->begin(); + for ( ; ir != outRoutes->end(); ++ir) + { + //if (*i == dst) // route already there + ir->dump(); // REMOVE Tim. + if (ir->type == Route::TRACK_ROUTE && ir->track == dst.track) // Does a route to the track exist? + { + //#ifdef ROUTE_DEBUG + fprintf(stderr, "addRoute: src midi port:%d dst audio in track:%s out route already exists. ir->channel:%d |= dst.channel:%d\n", + src.midiPort, dst.track->name().toLatin1().constData(), ir->channel, dst.channel); // REMOVE Tim. + //#endif + ir->channel |= dst.channel; // Bitwise OR the desired channel bit with the existing bit mask. + break; + //return; + } + } + if(ir == outRoutes->end()) // 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(); + + ir = inRoutes->begin(); + for ( ; ir != inRoutes->end(); ++ir) + { + if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == src.midiPort) // Does a route to the midi port exist? + { + fprintf(stderr, "addRoute: src midi port:%d dst audio in track:%s in route already exists. ir->channel:%d |= src.channel:%d\n", + src.midiPort, dst.track->name().toLatin1().constData(), ir->channel, src.channel); // REMOVE Tim. + ir->channel |= src.channel; // Bitwise OR the desired channel bit with the existing bit mask. + break; + } + } + if(ir == inRoutes->end()) // Only if route not found, add the route, with the requested channel bits as mask to start with. + inRoutes->push_back(src); + + 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); @@ -752,14 +805,18 @@ void removeRoute(Route src, Route dst) 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? + if(i->type == Route::TRACK_ROUTE && i->track == dst.track) // p3.3.50 Is there a route to the track? { + //printf("i->channel:%x dst.channel:%x\n", i->channel, dst.channel); 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. + { + //printf("erasing out route from midi port:%d\n", src.midiPort); 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... + // No, must break, else crash. There should only be one route anyway... } } } @@ -777,9 +834,9 @@ void removeRoute(Route src, Route dst) 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... + // No, must break, else crash. There should only be one route anyway... } } } diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp index b4519d8d..5038820e 100644 --- a/muse2/muse/track.cpp +++ b/muse2/muse/track.cpp @@ -739,40 +739,43 @@ bool Track::readProperties(Xml& xml, const QString& tag) void Track::writeRouting(int level, Xml& xml) const { QString s; - if (type() == Track::AUDIO_INPUT) { const RouteList* rl = &_inRoutes; for (ciRoute r = rl->begin(); r != rl->end(); ++r) { + // Support Midi Port to Audio Input track routes. p4.0.14 Tim. + if(r->type == Route::MIDI_PORT_ROUTE) + { + s = QT_TRANSLATE_NOOP("@default", "Route"); + if(r->channel != -1 && r->channel != 0) + s += QString(QT_TRANSLATE_NOOP("@default", " channelMask=\"%1\"")).arg(r->channel); // Use new channel mask. + xml.tag(level++, s.toLatin1().constData()); + + xml.tag(level, "source mport=\"%d\"/", r->midiPort); + + s = QT_TRANSLATE_NOOP("@default", "dest"); + s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(Xml::xmlString(name())); + xml.tag(level, s.toLatin1().constData()); + + xml.etag(level--, "Route"); + } + else if(!r->name().isEmpty()) { s = QT_TRANSLATE_NOOP("@default", "Route"); if(r->channel != -1) s += QString(QT_TRANSLATE_NOOP("@default", " channel=\"%1\"")).arg(r->channel); - ///Route dst(name(), true, r->channel); - //xml.tag(level++, "Route"); xml.tag(level++, s.toAscii().constData()); // p3.3.38 New routing scheme. - ///xml.strTag(level, "srcNode", r->name()); - //xml.tag(level, "source type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); s = QT_TRANSLATE_NOOP("@default", "source"); if(r->type != Route::TRACK_ROUTE) s += QString(QT_TRANSLATE_NOOP("@default", " type=\"%1\"")).arg(r->type); - //s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(r->name()); s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(Xml::xmlString(r->name())); xml.tag(level, s.toAscii().constData()); - ///xml.strTag(level, "dstNode", dst.name()); - - //if(r->channel != -1) - // xml.tag(level, "dest type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::TRACK_ROUTE, r->channel, name().toLatin1().constData()); - //else - // xml.tag(level, "dest type=\"%d\" name=\"%s\"/", Route::TRACK_ROUTE, name().toLatin1().constData()); - - //xml.tag(level, "dest name=\"%s\"/", name().toLatin1().constData()); xml.tag(level, "dest name=\"%s\"/", Xml::xmlString(name()).toLatin1().constData()); xml.etag(level--, "Route"); @@ -783,16 +786,13 @@ void Track::writeRouting(int level, Xml& xml) const const RouteList* rl = &_outRoutes; for (ciRoute r = rl->begin(); r != rl->end(); ++r) { - //if(!r->name().isEmpty()) + // p4.0.14 Ignore Audio Output to Audio Input routes. + // They are taken care of by Audio Input in the section above. + if(r->type == Route::TRACK_ROUTE && r->track && r->track->type() == Track::AUDIO_INPUT) + continue; + if(r->midiPort != -1 || !r->name().isEmpty()) // p3.3.49 { - ///QString src(name()); - ///if (type() == Track::AUDIO_OUTPUT) - ///{ - ///Route s(src, false, r->channel); - ///src = s.name(); - ///} - s = QT_TRANSLATE_NOOP("@default", "Route"); if(r->type == Route::MIDI_PORT_ROUTE) // p3.3.50 { @@ -809,45 +809,11 @@ void Track::writeRouting(int level, Xml& xml) const if(r->remoteChannel != -1) s += QString(QT_TRANSLATE_NOOP("@default", " remch=\"%1\"")).arg(r->remoteChannel); - //xml.tag(level++, "Route"); xml.tag(level++, s.toAscii().constData()); - ///xml.strTag(level, "srcNode", src); - //if(r->channel != -1) - // Allow for a regular mono or stereo track to feed a multi-channel synti. - // thisChannel is the 'starting' channel of this source if feeding a regular track. - //if(r->type == Route::TRACK_ROUTE && r->track->isSynti() && r->channel != -1) - //if(isSynti() && r->thisChannel != -1) - //xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::TRACK_ROUTE, r->channel, name().toLatin1().constData()); - // xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::TRACK_ROUTE, r->thisChannel, name().toLatin1().constData()); - //else - - //if(r->channel != -1) - // xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::TRACK_ROUTE, r->channel, name().toLatin1().constData()); - //else - // xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::TRACK_ROUTE, name().toLatin1().constData()); - //xml.tag(level, "source name=\"%s\"/", name().toLatin1().constData()); xml.tag(level, "source name=\"%s\"/", Xml::xmlString(name()).toLatin1().constData()); - ///xml.strTag(level, "dstNode", r->name()); - //if(r->channel != -1) - // xml.tag(level, "dest type=\"%d\" channel=\"%d\" name=\"%s\"/", r->type, r->channel, r->name().toLatin1().constData()); - //else - // xml.tag(level, "dest type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); - - // Allow for a regular mono or stereo track to feed a multi-channel synti. - // Channel is the 'starting' channel of the destination. - //if(r->type == Route::TRACK_ROUTE && r->track->isSynti() && r->channel != -1) - - //if(r->type == Route::TRACK_ROUTE && r->track->type() == Track::AUDIO_SOFTSYNTH && r->remoteChannel != -1) - // xml.tag(level, "dest type=\"%d\" channel=\"%d\" name=\"%s\"/", r->type, r->remoteChannel, r->name().toLatin1().constData()); - //else - //if(r->type == Route::MIDI_DEVICE_ROUTE) - // xml.tag(level, "dest devtype=\"%d\" name=\"%s\"/", r->device->deviceType(), r->name().toLatin1().constData()); - //else - // xml.tag(level, "dest type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); - s = QT_TRANSLATE_NOOP("@default", "dest"); //if(r->type == Route::MIDI_DEVICE_ROUTE) // p3.3.49 Obsolete since 1.1-RC2 diff --git a/muse2/muse/widgets/mtrackinfo.cpp b/muse2/muse/widgets/mtrackinfo.cpp index f9903037..04911b02 100644 --- a/muse2/muse/widgets/mtrackinfo.cpp +++ b/muse2/muse/widgets/mtrackinfo.cpp @@ -154,9 +154,10 @@ MidiTrackInfo::MidiTrackInfo(QWidget* parent, Track* sel_track) : QWidget(parent connect(iRButton, SIGNAL(pressed()), SLOT(inRoutesPressed())); // TODO: Works OK, but disabled for now, until we figure out what to do about multiple out routes and display values... + // Enabled (for Midi Port to Audio Input routing). p4.0.14 Tim. //oRButton->setEnabled(false); //oRButton->setVisible(false); - //connect(oRButton, SIGNAL(pressed()), SLOT(outRoutesPressed())); + connect(oRButton, SIGNAL(pressed()), SLOT(outRoutesPressed())); connect(song, SIGNAL(songChanged(int)), SLOT(songChanged(int))); connect(muse, SIGNAL(configChanged()), SLOT(configChanged())); @@ -541,7 +542,10 @@ void MidiTrackInfo::iOutputChannelChanged(int channel) // may result in adding/removing mixer strip: //song->update(-1); - song->update(SC_MIDI_TRACK_PROP); + //song->update(SC_MIDI_TRACK_PROP); + audio->msgUpdateSoloStates(); // p4.0.14 + //song->update(SC_MIDI_TRACK_PROP | SC_ROUTE); // + song->update(SC_MIDI_TRACK_PROP); // } } @@ -563,7 +567,10 @@ void MidiTrackInfo::iOutputPortChanged(int index) track->setOutPortAndUpdate(index); audio->msgIdle(false); - song->update(SC_MIDI_TRACK_PROP); + //song->update(SC_MIDI_TRACK_PROP); + audio->msgUpdateSoloStates(); // p4.0.14 + //song->update(SC_MIDI_TRACK_PROP | SC_ROUTE); // + song->update(SC_MIDI_TRACK_PROP); // } //--------------------------------------------------------- @@ -652,7 +659,7 @@ void MidiTrackInfo::outRoutesPressed() connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*))); connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide())); pup->popup(QCursor::pos()); - ///oRButton->setDown(false); + oRButton->setDown(false); return; } diff --git a/muse2/muse/widgets/mtrackinfobase.ui b/muse2/muse/widgets/mtrackinfobase.ui index 1649b1d5..3437b97e 100644 --- a/muse2/muse/widgets/mtrackinfobase.ui +++ b/muse2/muse/widgets/mtrackinfobase.ui @@ -131,10 +131,26 @@ input routing - In + iR + + + + + 0 + 0 + + + + output routing + + + oR + + + -- cgit v1.2.3