diff options
| author | Tim E. Real <termtech@rogers.com> | 2011-05-26 00:18:47 +0000 | 
|---|---|---|
| committer | Tim E. Real <termtech@rogers.com> | 2011-05-26 00:18:47 +0000 | 
| commit | e8612708161b71b43d56ef47eede6cc58b035967 (patch) | |
| tree | 18580394352c090068325ded37a8f53d6807c4a0 /muse2/muse | |
| parent | a1db21404d203bec7353099a9947778735271bfd (diff) | |
Moved all routing popup menu stuff from app, astrip, mstrip, mtrackinfo into new class RoutePopupMenu, 
 *massively* cleaning up those 4 files. Used new Route QVariant type as action data instead of integers. 
Moved MenuTitleItem definitions from astrip.cpp into it's own menutitleitem.cpp 
Added to settings: "Make popup menus stay open. Otherwise hold Ctrl." 
Diffstat (limited to 'muse2/muse')
31 files changed, 1709 insertions, 2139 deletions
| diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 62871b18..72cdad6a 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -43,7 +43,7 @@  #include "mixdowndialog.h"  #include "pianoroll.h"  #include "scoreedit.h" -#include "popupmenu.h" +#include "routepopup.h"  #include "shortcutconfig.h"  #include "songinfo.h"  #include "ticksynth.h" @@ -93,7 +93,6 @@ static QString* projectList[PROJECT_LIST_LEN];  extern void initMidiSynth();  extern void exitJackAudio();  extern void exitDummyAudio(); -// p3.3.39  extern void exitOSC();  #ifdef HAVE_LASH @@ -809,7 +808,6 @@ MusE::MusE(int argc, char** argv) : QMainWindow()        editInstrument        = 0;        routingPopupMenu      = 0;        progress              = 0; -      //routingPopupView      = 0;        appName               = QString("MusE");        setWindowTitle(appName); @@ -1658,7 +1656,6 @@ void MusE::initMidiDevices()        audio->msgInitMidiDevices(); -      // Added by T356        //audio->msgIdle(false);        } @@ -2080,7 +2077,7 @@ bool MusE::save(const QString& name, bool overwriteWarn)        if (ferror(f)) {              QString s = "Write File\n" + name + "\nfailed: "                 //+ strerror(errno); -               + QString(strerror(errno));                 // p4.0.0 +               + QString(strerror(errno));                               QMessageBox::critical(this,                 tr("MusE: Write File failed"), s);              popenFlag? pclose(f) : fclose(f); @@ -2172,10 +2169,10 @@ void MusE::closeEvent(QCloseEvent* event)          printf("MusE: Exiting Metronome\n");        exitMetronome(); -      // p3.3.47 -      // Make sure to clear the menu, which deletes any sub menus. +      // Make sure to delete the menu. ~routingPopupMenu() will NOT be called automatically. +      // Even though it is a child of MusE, it just passes MusE onto the underlying PopupMenus. p4.0.26        if(routingPopupMenu) -        routingPopupMenu->clear(); +        delete routingPopupMenu;             #if 0        if(routingPopupView)        { @@ -2201,10 +2198,8 @@ void MusE::closeEvent(QCloseEvent* event)              d.remove(f.completeBaseName() + ".wca");              } -      // Added by Tim. p3.3.14 -        #ifdef HAVE_LASH -      // Disconnect gracefully from LASH. +      // Disconnect gracefully from LASH. Tim. p3.3.14        if(lash_client)        {          if(debugMsg) @@ -2292,789 +2287,18 @@ void MusE::showTransport(bool flag)  //---------------------------------------------------------  //   getRoutingPopupMenu +//   Get the special common routing popup menu. Used (so far)  +//    by audio strip, midi strip, and midi trackinfo.  //--------------------------------------------------------- -PopupMenu* MusE::getRoutingPopupMenu() +RoutePopupMenu* MusE::getRoutingPopupMenu()  {    if(!routingPopupMenu) -    routingPopupMenu = new PopupMenu(this, true); +    routingPopupMenu = new RoutePopupMenu(this);    return routingPopupMenu;  }  //--------------------------------------------------------- -//   updateRouteMenus -//--------------------------------------------------------- - -void MusE::updateRouteMenus(Track* track, QObject* master)     -{ -      // NOTE: The purpose of this routine is to make sure the items actually reflect -      //  the routing status.  -      // In case for some reason a route could not be added (or removed).  -      // Then the item will be properly un-checked (or checked) here. -       -      //if(!track || track != gRoutingPopupMenuMaster || track->type() == Track::AUDIO_AUX) -      //if(!track || track->type() == Track::AUDIO_AUX) -      if(!track || gRoutingPopupMenuMaster != master)  // p3.3.50 -        return; -         -      PopupMenu* pup = getRoutingPopupMenu(); -       -      if(pup->actions().isEmpty()) -        return; -         -      if(!pup->isVisible()) -        return; -         -      //AudioTrack* t = (AudioTrack*)track; -      RouteList* rl = gIsOutRoutingPopupMenu ? track->outRoutes() : track->inRoutes(); - -      iRouteMenuMap imm = gRoutingMenuMap.begin(); -      for(; imm != gRoutingMenuMap.end(); ++imm)  -      { -        // 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->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");   -        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");   -              ir->dump();  -              ///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");   -                  if(ir->channel & tchbit) -                  { -                    found = true; -                    printf("found: bit matches\n");   -                  }   -                  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());   -            //if(act && act->isChecked() != (ir != mprl->end())) -            //  act->setChecked(ir != mprl->end()); -            printf("set act checked to:%d\n", found);   -            if(act && act->isChecked() != found) -              act->setChecked(found); -             -            //return; -          } -        } -        #endif -         -        //bool found = false; -        iRoute irl = rl->begin(); -        for(; irl != rl->end(); ++irl)  -        { -          if(imm->second.type == Route::MIDI_PORT_ROUTE)                                     // p3.3.50 Is the map route a midi port route? -          { -            if(irl->type == Route::MIDI_PORT_ROUTE && irl->midiPort == imm->second.midiPort  // Is the track route a midi port route? -               && (irl->channel & imm->second.channel) == imm->second.channel)               // Is the exact channel mask bit(s) set? -            { -              //found = true; -              break; -            } -          } -          else -          if(*irl == imm->second) -          { -            //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);   -        if(act && act->isChecked() != (irl != rl->end())) -          act->setChecked(irl != rl->end()); -      } -}       -       -//--------------------------------------------------------- -//   routingPopupMenuActivated -//--------------------------------------------------------- - -void MusE::routingPopupMenuActivated(Track* track, int n) -{ -      //if(!track || (track != gRoutingPopupMenuMaster)) -      if(!track) -        return; -         -      if(track->isMidiTrack()) -      { -        PopupMenu* pup = getRoutingPopupMenu(); -         -        if(pup->actions().isEmpty()) -          return; -           -        //MidiTrack* t = (MidiTrack*)track; -        RouteList* rl = gIsOutRoutingPopupMenu ? track->outRoutes() : track->inRoutes(); -         -        if(n == -1)  -          return; -         -        if(!gIsOutRoutingPopupMenu && n == 0)      // p4.0.17 -        { -          muse->configMidiPorts(); -          return; -        } -         -        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; -        int chbit = aRoute.channel; -        Route bRoute(track, chbit); -        int mdidx = aRoute.midiPort; - -        MidiPort* mp = &midiPorts[mdidx]; -        MidiDevice* md = mp->device(); -        //if(!md)    // Removed p4.0.17 Allow connections to ports with no device. -        //  return; -         -        //if(!(md->rwFlags() & 2)) -        //if(!(md->rwFlags() & (gIsOutRoutingPopupMenu ? 1 : 2))) -        if(md && !(md->rwFlags() & (gIsOutRoutingPopupMenu ? 1 : 2)))   // p4.0.17 -          return; -         -        int chmask = 0;                    -        iRoute iir = rl->begin(); -        for (; iir != rl->end(); ++iir)  -        { -          //if(*iir == (dst ? bRoute : aRoute)) -          //if(*iir == aRoute) -          if(iir->type == Route::MIDI_PORT_ROUTE && iir->midiPort == mdidx)    // p3.3.50 Is there already a route to this port? -          { -                chmask = iir->channel;  // p3.3.50 Grab the channel mask. -                break; -          }       -        } -        //if (iir != rl->end())  -        if ((chmask & chbit) == chbit)             // p3.3.50 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); -      } -      else -      { -        // TODO: Try to move code from AudioStrip::routingPopupMenuActivated into here. -         -        /* -        PopupMenu* pup = getRoutingPopupMenu(); -         -        printf("MusE::routingPopupMenuActivated audio n:%d count:%d\n", n, pup->count()); -         -        if(pup->count() == 0) -          return; -           -        AudioTrack* t = (AudioTrack*)track; -        RouteList* rl = gIsOutRoutingPopupMenu ? t->outRoutes() : t->inRoutes(); -         -        //QPoint ppt = QCursor::pos(); -         -        if(n == -1)  -        { -          //printf("MusE::routingPopupMenuActivated audio n = -1 deleting popup...\n"); -          printf("MusE::routingPopupMenuActivated audio n = -1\n"); -          ///delete pup; -          ///pup = 0; -          return; -        } -        else -        //if(n == 0) -        //{ -          //printf("MusE::routingPopupMenuActivated audio n = 0 = tearOffHandle\n"); -          //oR->setDown(false);      -        //  return; -        //} -        //else -        { -            if(gIsOutRoutingPopupMenu) -            {   -              QString s(pup->text(n)); -               -              //printf("AudioStrip::routingPopupMenuActivated audio text:%s\n", s.toLatin1().constData()); -               -              if(track->type() == Track::AUDIO_OUTPUT) -              { -                ///delete orpup; -                 -                int chan = n & 0xf; -                 -                //Route srcRoute(t, -1); -                //Route srcRoute(t, chan, chans); -                //Route srcRoute(t, chan, 1); -                Route srcRoute(t, chan); -                 -                //Route dstRoute(s, true, -1); -                Route dstRoute(s, true, -1, Route::JACK_ROUTE); -                //Route dstRoute(s, true, 0, Route::JACK_ROUTE); -     -                //srcRoute.channel = dstRoute.channel = chan; -                dstRoute.channel = chan; -                //dstRoute.channels = 1; -     -                // 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); -                 -                // p3.3.47 -                //pup->popup(ppt, 0); -                 -                //oR->setDown(false);    -                return; -                 -                // p3.3.46 -                ///goto _redisplay; -              } -               -              iRouteMenuMap imm = gRoutingMenuMap.find(n); -              if(imm == gRoutingMenuMap.end()) -              {   -                ///delete orpup; -                //oR->setDown(false);     // orpup->exec() catches mouse release event -                return; -              }   -               -              //int chan = n >> 16; -              //int chans = (chan >> 15) + 1; // Bit 31 MSB: Mono or stereo. -              //chan &= 0xffff; -              //int chan = imm->second.channel; -              //int chans = imm->second.channels;  -               -              //Route srcRoute(t, -1); -              //srcRoute.remoteChannel = chan; -              //Route srcRoute(t, chan, chans); -              Route srcRoute(t, imm->second.channel, imm->second.channels); -              //Route srcRoute(t, imm->second.channel); -              srcRoute.remoteChannel = imm->second.remoteChannel; -               -              //Route dstRoute(s, true, -1); -              //Route dstRoute(s, true, -1, Route::TRACK_ROUTE); -              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); -                 -              // p3.3.46 -              //oR->setDown(false);      -              ///goto _redisplay; -               -              // p3.3.47 -              //pup->popup(ppt, 0); -            }   -            else -            { -              QString s(pup->text(n)); -               -              if(track->type() == Track::AUDIO_INPUT) -              { -                ///delete pup; -                int chan = n & 0xf; -                 -                Route srcRoute(s, 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); -                //iR->setDown(false);     // pup->exec() catches mouse release event -                return; -                 -                // p3.3.46 -                ///goto _redisplay; -              } -               -              iRouteMenuMap imm = gRoutingMenuMap.find(n); -              if(imm == gRoutingMenuMap.end()) -              {   -                //delete pup; -                //iR->setDown(false);     // pup->exec() catches mouse release event -                return; -              }   -               -              //int chan = n >> 16; -              //int chans = (chan >> 15) + 1; // Bit 31 MSB: Mono or stereo. -              //chan &= 0xffff; -              //int chan = imm->second.channel; -              //int chans = imm->second.channels;  -               -              //Route srcRoute(s, false, -1); -              //Route srcRoute(s, false, -1, Route::TRACK_ROUTE); -              Route &srcRoute = imm->second; -               -              //Route dstRoute(t, -1); -              //Route dstRoute(t, chan, chans); -              Route dstRoute(t, imm->second.channel, imm->second.channels); -              //Route dstRoute(t, imm->second.channel); -              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); -               -              // p3.3.46 -              //iR->setDown(false);      -              ///goto _redisplay; -               -               -               -               -            } -                 -        } -       */ -        -      } -      //else -      //{ -      //} -} - -//--------------------------------------------------------- -//   routingPopupMenuAboutToHide -//--------------------------------------------------------- - -void MusE::routingPopupMenuAboutToHide() -{ -      // Hmm, can't do this? Sub-menus stay open with this. Re-arranged, testing... Nope. -      //PopupMenu* pup = muse->getRoutingPopupMenu(); -      //pup->disconnect(); -      //pup->clear(); -       -      gRoutingMenuMap.clear(); -      gRoutingPopupMenuMaster = 0; -} - -//--------------------------------------------------------- -//   prepareRoutingPopupMenu -//--------------------------------------------------------- - -PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst) -{ -  if(!track) -    return 0; -     -  if(track->isMidiTrack()) -  { -    RouteList* rl = dst ? track->outRoutes() : track->inRoutes(); -    //Route dst(track, -1); -   -    PopupMenu* pup = getRoutingPopupMenu(); -    pup->disconnect(); -    //connect(pup, SIGNAL(activated(int)), SLOT(routingPopupMenuActivated(int))); -    //connect(pup, SIGNAL(aboutToHide()), SLOT(routingPopupMenuAboutToHide())); -       -    pup->clear(); -    gRoutingMenuMap.clear(); -     -    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]; -         -        // p4.0.17 Do not list synth devices! Requiring valid device 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(mp->device() && !mp->device()->isSynti())   -        { -          RouteList* mprl = mp->outRoutes(); -          int chbits = 1 << ((MidiTrack*)track)->outChannel(); -          //MidiDevice* md = mp->device(); -          //if(!md) -          //  continue; -           -          pup->addSeparator(); -          pup->addAction(new MenuTitleItem(tr("Soloing chain"), pup));  -          PopupMenu* subp = new PopupMenu(pup, true); -          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 -    { -      // Warn if no devices available. Add an item to open midi config. p4.0.17  -      int pi = 0; -      for( ; pi < MIDI_PORTS; ++pi) -      { -        MidiDevice* md = midiPorts[pi].device(); -        if(md && !md->isSynti() && (md->rwFlags() & 2)) -          break; -      } -      if(pi == MIDI_PORTS) -      { -        act = pup->addAction(tr("Warning: No midi input devices!")); -        act->setCheckable(false); -        act->setData(-1); -        pup->addSeparator(); -      } -      act = pup->addAction(QIcon(*settings_midiport_softsynthsIcon), tr("Open midi config...")); -      act->setCheckable(false); -      act->setData(gid); -      pup->addSeparator(); -      ++gid; -       -      pup->addAction(new MenuTitleItem("Midi input ports", pup));  -       -      for(int i = 0; i < MIDI_PORTS; ++i) -      { -        // NOTE: Could possibly list all devices, bypassing ports, but no, let's stick with ports. -        MidiPort* mp = &midiPorts[i]; -        MidiDevice* md = mp->device(); -        //if(!md) -        //  continue; -         -        // p4.0.17 Do not list synth devices! -        if(md && md->isSynti()) -          continue; -           -        if(md && !(md->rwFlags() & 2)) -          continue; -           -        //printf("MusE::prepareRoutingPopupMenu adding submenu portnum:%d\n", i); -         -        // MusE-2: Check this - needed with QMenu? Help says no. No - verified, it actually causes double triggers! -        //connect(subp, SIGNAL(triggered(QAction*)), pup, SIGNAL(triggered(QAction*))); -        //connect(subp, SIGNAL(aboutToHide()), pup, SIGNAL(aboutToHide())); -         -        int chanmask = 0; -        // p3.3.50 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. -        iRoute ir = rl->begin(); -        for( ; 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; -          } -        } -        // p4.0.17 List ports with no device, but with routes to this track, in the main popup. -        if(!md && ir == rl->end()) -          continue; -         -        PopupMenu* subp = new PopupMenu(pup, true); -        subp->setTitle(QString("%1:").arg(i+1) + (md ? md->name() : tr("<none>")));  -         -        for(int ch = 0; ch < MIDI_CHANNELS; ++ch)  -        { -          act = subp->addAction(QString("Channel %1").arg(ch+1)); -          act->setCheckable(true); -          act->setData(gid); -           -          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) ); -           -          if(chanmask & chbit)                  // p3.3.50 Is the channel already set? Show item check mark. -            act->setChecked(true); -           -          ++gid;   -        } -        //gid = MIDI_PORTS * MIDI_CHANNELS + i;           // Make sure each 'toggle' item gets a unique id. -        act = subp->addAction(tr("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); -      } -       -      #if 0 -      // p4.0.17 List ports with no device and no in routes, in a separate popup. -      PopupMenu* morep = new PopupMenu(pup, true); -      morep->setTitle(tr("More..."));  -      for(int i = 0; i < MIDI_PORTS; ++i) -      { -        MidiPort* mp = &midiPorts[i]; -        if(mp->device()) -          continue; -         -        PopupMenu* subp = new PopupMenu(morep, true); -        subp->setTitle(QString("%1:").arg(i) + tr("<none>"));  -         -        // MusE-2: Check this - needed with QMenu? Help says no. No - verified, it actually causes double triggers! -        //connect(subp, SIGNAL(triggered(QAction*)), pup, SIGNAL(triggered(QAction*))); -        //connect(subp, SIGNAL(aboutToHide()), pup, SIGNAL(aboutToHide())); -         -        iRoute ir = rl->begin(); -        for( ; ir != rl->end(); ++ir)    -        { -          if(ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == i)  -            break; -        } -        if(ir != rl->end()) -          continue; -         -        for(int ch = 0; ch < MIDI_CHANNELS; ++ch)  -        { -          act = subp->addAction(QString("Channel %1").arg(ch+1)); -          act->setCheckable(true); -          act->setData(gid); -           -          int chbit = 1 << ch; -          Route srcRoute(i, chbit);    // In accordance with new channel mask, use the bit position. -           -          gRoutingMenuMap.insert( pRouteMenuMap(gid, srcRoute) ); -           -          //if(chanmask & chbit)                  // Is the channel already set? Show item check mark. -          //  act->setChecked(true); -           -          ++gid;   -        } -        //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; -        morep->addMenu(subp); -      }       -      pup->addMenu(morep); -      #endif -       -    } -         -    if(pup->actions().isEmpty()) -    { -      gRoutingPopupMenuMaster = 0; -      //pup->clear(); -      //pup->disconnect(); -      gRoutingMenuMap.clear(); -      //oR->setDown(false);      -      return 0; -    } -     -    gIsOutRoutingPopupMenu = dst; -    return pup; -  } -   -  return 0; -} - -//---------------------------------------------------------  //   saveAs  //--------------------------------------------------------- diff --git a/muse2/muse/app.h b/muse2/muse/app.h index c194b603..256154e2 100644 --- a/muse2/muse/app.h +++ b/muse2/muse/app.h @@ -36,8 +36,7 @@ class Transport;  class BigTime;  class Arranger;  class Instrument; -class PopupMenu; -class PopupView; +class RoutePopupMenu;  class Track;  class PrinterConfig;  class MidiSyncConfig; @@ -69,8 +68,6 @@ class ScoreEdit;  #define MENU_ADD_SYNTH_ID_BASE 0x1000 - -  //---------------------------------------------------------  //   MusE  //--------------------------------------------------------- @@ -164,10 +161,8 @@ class MusE : public QMainWindow        QMenu* menu_functions, *menuScriptPlugins;        QMenu* select, *master, *midiEdit, *addTrack; -      // Special 'stay-open' menu for routes. -      PopupMenu* routingPopupMenu;  -      //PopupView* routingPopupView;  - +      // Special common menu for routes. Used (so far) by audio and midi strip, and midi trackinfo. +      RoutePopupMenu* routingPopupMenu;         QMenu* follow;        QMenu* midiInputPlugins; @@ -337,7 +332,6 @@ class MusE : public QMainWindow     private:        void adjustGlobalLists(int startPos, int diff); -          public slots:        bool saveAs();        void bounceToFile(AudioOutput* ao = 0); @@ -358,8 +352,6 @@ class MusE : public QMainWindow        void setUsedTool(int);        void showDidYouKnowDialog();        void startEditInstrument(); -       -      void routingPopupMenuAboutToHide();        void configMidiPorts();     public: @@ -371,7 +363,6 @@ class MusE : public QMainWindow        bool importMidi(const QString name, bool merge);        void kbAccel(int);        void changeConfig(bool writeFlag); -        void seqStop();        bool seqStart();        void setHeartBeat(); @@ -384,18 +375,8 @@ class MusE : public QMainWindow        QWidget* bigtimeWindow();        bool importWaveToTrack(QString& name, unsigned tick=0, Track* track=NULL);        void importPartToTrack(QString& filename, unsigned tick, Track* track); -        void showTransport(bool flag); - -      // Special 'stay-open' menu for routes. -      PopupMenu* getRoutingPopupMenu(); -      PopupMenu* prepareRoutingPopupMenu(Track* /*track*/, bool /*dst*/); -      void routingPopupMenuActivated(Track* /*track*/, int /*id*/); -      void updateRouteMenus(Track* /*track*/, QObject* /*master*/); -      // Testing... -      //PopupView* getRoutingPopupView(); -      //PopupView* prepareRoutingPopupView(Track* /*track*/, bool /*dst*/); -      //void routingPopupViewActivated(Track* /*track*/, int /*id*/); +      RoutePopupMenu* getRoutingPopupMenu();  #ifdef HAVE_LASH        void lash_idle_cb (); diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp index c427a55c..b004638f 100644 --- a/muse2/muse/audiotrack.cpp +++ b/muse2/muse/audiotrack.cpp @@ -34,6 +34,7 @@ bool WaveTrack::_isVisible=true;  // Jack often shuts down during file save, causing the routes to be lost in the file.  // cacheJackRouteNames() is ONLY called from MusE::save() in app.cpp  // Update: Not required any more because the real problem was Jack RT priority, which has been fixed. +// Keep this around for now. It may come in handy if we want to preserve route names with dummy audio driver!  /*  typedef std::multimap <const int, QString> jackRouteNameMap;  std::map <const AudioTrack*, jackRouteNameMap > jackRouteNameCache; diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp index 56cbc321..89cdd04d 100644 --- a/muse2/muse/conf.cpp +++ b/muse2/muse/conf.cpp @@ -948,6 +948,9 @@ void readConfiguration(Xml& xml, bool readOnlySequencer)                                config.projectStoreInFolder = xml.parseInt();                          else if (tag == "useProjectSaveDialog")                                config.useProjectSaveDialog = xml.parseInt(); +                        else if (tag == "popupsDefaultStayOpen") +                              config.popupsDefaultStayOpen = xml.parseInt(); +                          else                                xml.unknown("configuration");                          break; @@ -1217,7 +1220,6 @@ void MusE::writeGlobalConfiguration(int level, Xml& xml) const        xml.intTag(level, "midiFilterCtrl2", midiFilterCtrl2);        xml.intTag(level, "midiFilterCtrl3", midiFilterCtrl3);        xml.intTag(level, "midiFilterCtrl4", midiFilterCtrl4); -      // Removed by Tim. p3.3.6        //xml.intTag(level, "txDeviceId", txDeviceId);        //xml.intTag(level, "rxDeviceId", rxDeviceId); @@ -1226,7 +1228,8 @@ void MusE::writeGlobalConfiguration(int level, Xml& xml) const        xml.strTag(level, "externalWavEditor", config.externalWavEditor);        xml.intTag(level, "useOldStyleStopShortCut", config.useOldStyleStopShortCut);        xml.intTag(level, "moveArmedCheckBox", config.moveArmedCheckBox); - +      xml.intTag(level, "popupsDefaultStayOpen", config.popupsDefaultStayOpen); +              //for (int i = 0; i < 6; ++i) {        for (int i = 0; i < NUM_FONTS; ++i) {              char buffer[32]; @@ -1279,39 +1282,8 @@ void MusE::writeGlobalConfiguration(int level, Xml& xml) const        xml.colorTag(level, "auxTrackBg",    config.auxTrackBg);        xml.colorTag(level, "synthTrackBg",  config.synthTrackBg); -      // Changed by Tim. p3.3.6 -       +      // Removed by Tim. p3.3.6        //xml.intTag(level, "txSyncPort", txSyncPort); -      /* -      // To keep old muse versions happy... -      bool mcsync = mmc = mtc = false; -      for(int sp = 0; sp < MIDI_PORTS; ++sp) -      { -        MidiSyncTxPort* txPort = &midiSyncTxPorts[sp]; -        if(txPort->doMCSync() || txPort->doMMC() || txPort->doMTC()) -        { -          if(txPort->doMCSync()) -            mcsync = true; -          if(txPort->doMMC()) -            mmc = true; -          if(txPort->doMTC()) -            mtc = true; -          xml.intTag(level, "txSyncPort", sp); -          break; -        }   -      } -      */ -       -      // Added by Tim. p3.3.6 -       -      //xml.tag(level++, "midiSyncInfo"); -      //for(iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id)  -      //{ -      //  MidiDevice* md = *id; -      //  (*id)->syncInfo().write(level, xml, md); -      //}       -      //xml.etag(level, "midiSyncInfo"); -        //xml.intTag(level, "rxSyncPort", rxSyncPort);        xml.intTag(level, "mtctype", mtcType);        xml.nput(level, "<mtcoffset>%02d:%02d:%02d:%02d:%02d</mtcoffset>\n", diff --git a/muse2/muse/confmport.cpp b/muse2/muse/confmport.cpp index fc005923..8b323fc1 100644 --- a/muse2/muse/confmport.cpp +++ b/muse2/muse/confmport.cpp @@ -507,7 +507,7 @@ void MPConfig::rbClicked(QTableWidgetItem* item)                          //Route dst(*ip, true, i);                          //Route rt(*ip, (dev->rwFlags() & 1), -1, Route::JACK_ROUTE);                          Route rt(*ip, (col == DEVCOL_OUTROUTES), -1, Route::JACK_ROUTE);    -                        for(iRoute ir = rl->begin(); ir != rl->end(); ++ir)  +                        for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir)                           {                            if (*ir == rt)                             { @@ -553,7 +553,7 @@ void MPConfig::rbClicked(QTableWidgetItem* item)                          Route srcRoute(dev, -1);                          Route dstRoute(s, true, -1, Route::JACK_ROUTE); -                        iRoute iir = rl->begin(); +                        ciRoute iir = rl->begin();                          for(; iir != rl->end(); ++iir)                           {                            if(*iir == dstRoute) @@ -573,7 +573,7 @@ void MPConfig::rbClicked(QTableWidgetItem* item)                          Route srcRoute(s, false, -1, Route::JACK_ROUTE);                          Route dstRoute(dev, -1); -                        iRoute iir = rl->begin(); +                        ciRoute iir = rl->begin();                          for(; iir != rl->end(); ++iir)                           {                            if(*iir == srcRoute) diff --git a/muse2/muse/driver/jack.cpp b/muse2/muse/driver/jack.cpp index f70cf3d3..c4d7a8ca 100644 --- a/muse2/muse/driver/jack.cpp +++ b/muse2/muse/driver/jack.cpp @@ -711,7 +711,7 @@ void JackAudioDevice::connectJackMidiPorts()        if(port)                          //         {          RouteList* rl = md->outRoutes(); -        for (iRoute r = rl->begin(); r != rl->end(); ++r)  +        for (ciRoute r = rl->begin(); r != rl->end(); ++r)             connect(port, r->jackPort);        }          } @@ -724,7 +724,7 @@ void JackAudioDevice::connectJackMidiPorts()        if(port)                          //        {          RouteList* rl = md->inRoutes(); -        for (iRoute r = rl->begin(); r != rl->end(); ++r)  +        for (ciRoute r = rl->begin(); r != rl->end(); ++r)             connect(r->jackPort, port);        }          }     @@ -915,7 +915,7 @@ void JackAudioDevice::graphChanged()                    // the "right" amount                    for (int i = 0;i < 20;i++) {                          erased = false; -                        for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { +                        for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {                                if (irl->channel != channel)                                      continue;                                QString name = irl->name(); @@ -953,7 +953,7 @@ void JackAudioDevice::graphChanged()                          const char** pn = ports;                          while (*pn) {                                bool found = false; -                              for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { +                              for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {                                      if (irl->channel != channel)                                            continue;                                      QString name = irl->name(); @@ -1002,7 +1002,7 @@ void JackAudioDevice::graphChanged()                    // the "right" amount                    for (int i = 0; i < 20 ; i++) {                          erased = false; -                        for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { +                        for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {                                if (irl->channel != channel)                                      continue;                                QString name = irl->name(); @@ -1039,7 +1039,7 @@ void JackAudioDevice::graphChanged()                          const char** pn = ports;                          while (*pn) {                                bool found = false; -                              for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { +                              for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {                                      if (irl->channel != channel)                                            continue;                                      QString name = irl->name(); @@ -1113,7 +1113,7 @@ void JackAudioDevice::graphChanged()                        for (int i = 0; i < 20 ; i++)                         {                              erased = false; -                            for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { +                            for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {                                    //if (irl->channel != channel)                                    //      continue;                                    QString name = irl->name(); @@ -1155,7 +1155,7 @@ void JackAudioDevice::graphChanged()                              const char** pn = ports;                              while (*pn) {                                    bool found = false; -                                  for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { +                                  for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {                                          //if (irl->channel != channel)                                          //      continue;                                          QString name = irl->name(); @@ -1212,7 +1212,7 @@ void JackAudioDevice::graphChanged()                        for (int i = 0; i < 20 ; i++)                         {                              erased = false; -                            for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { +                            for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {                                    //if (irl->channel != channel)                                    //      continue;                                    QString name = irl->name(); @@ -1253,7 +1253,7 @@ void JackAudioDevice::graphChanged()                              const char** pn = ports;                              while (*pn) {                                    bool found = false; -                                  for (iRoute irl = rl->begin(); irl != rl->end(); ++irl) { +                                  for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {                                          //if (irl->channel != channel)                                          //      continue;                                          QString name = irl->name(); @@ -1473,7 +1473,7 @@ void JackAudioDevice::start(int /*priority*/)              for (int ch = 0; ch < channel; ++ch) {                    RouteList* rl = ai->inRoutes();                    void* port = ai->jackPort(ch); -                  for (iRoute ir = rl->begin(); ir != rl->end(); ++ir) { +                  for (ciRoute ir = rl->begin(); ir != rl->end(); ++ir) {                          if (ir->channel == ch)                                connect(ir->jackPort, port);                          } @@ -1486,7 +1486,7 @@ void JackAudioDevice::start(int /*priority*/)              for (int ch = 0; ch < channel; ++ch) {                    RouteList* rl = ai->outRoutes();                    void* port = ai->jackPort(ch); -                  for (iRoute r = rl->begin(); r != rl->end(); ++r) { +                  for (ciRoute r = rl->begin(); r != rl->end(); ++r) {                          if (r->channel == ch) {                                connect(port, r->jackPort);                                } diff --git a/muse2/muse/gconfig.cpp b/muse2/muse/gconfig.cpp index 4d22ad4c..49a6d572 100644 --- a/muse2/muse/gconfig.cpp +++ b/muse2/muse/gconfig.cpp @@ -168,6 +168,7 @@ GlobalConfigValues config = {        QString("./"),                // projectBaseFolder        true,                         // projectStoreInFolder        true,                         // useProjectSaveDialog -      64                            // minControlProcessPeriod +      64,                           // minControlProcessPeriod +      false                         // popupsDefaultStayOpen      }; diff --git a/muse2/muse/gconfig.h b/muse2/muse/gconfig.h index cd236b36..acf39782 100644 --- a/muse2/muse/gconfig.h +++ b/muse2/muse/gconfig.h @@ -143,6 +143,7 @@ struct GlobalConfigValues {        bool projectStoreInFolder;        bool useProjectSaveDialog;        unsigned long minControlProcessPeriod; +      bool popupsDefaultStayOpen;        };  extern GlobalConfigValues config; diff --git a/muse2/muse/globals.cpp b/muse2/muse/globals.cpp index 00c0f0a9..7f346f87 100644 --- a/muse2/muse/globals.cpp +++ b/muse2/muse/globals.cpp @@ -350,10 +350,6 @@ unsigned char rcPlayNote = 29;  unsigned char rcSteprecNote = 36;  bool automation = true; -QObject* gRoutingPopupMenuMaster = 0; -RouteMenuMap gRoutingMenuMap; -bool gIsOutRoutingPopupMenu = false; -  uid_t euid, ruid;  // effective user id, real user id  bool midiSeqRunning = false; diff --git a/muse2/muse/globals.h b/muse2/muse/globals.h index 984571e2..cee5e815 100644 --- a/muse2/muse/globals.h +++ b/muse2/muse/globals.h @@ -13,7 +13,6 @@  #include "value.h"  #include "mtc.h" -#include "route.h"  #include <unistd.h> @@ -172,15 +171,6 @@ extern unsigned char rcSteprecNote;  extern bool midiSeqRunning;  extern bool automation; -class QObject; -// Which audio strip, midi strip, or midi track info strip -//  was responsible for popping up the routing menu. -extern QObject* gRoutingPopupMenuMaster; -// Map of routing popup menu item IDs to Routes. -extern RouteMenuMap gRoutingMenuMap; -// Whether the routes popup was shown by clicking the output routes button, or input routes button. -extern bool gIsOutRoutingPopupMenu; -  // p3.3.55  #define JACK_MIDI_OUT_PORT_SUFFIX "_out"  #define JACK_MIDI_IN_PORT_SUFFIX  "_in" diff --git a/muse2/muse/mixer/astrip.cpp b/muse2/muse/mixer/astrip.cpp index c1e92e59..5644e6eb 100644 --- a/muse2/muse/mixer/astrip.cpp +++ b/muse2/muse/mixer/astrip.cpp @@ -48,33 +48,8 @@  #include "gconfig.h"  #include "ttoolbutton.h"  #include "menutitleitem.h" -#include "popupmenu.h" - -//--------------------------------------------------------- -//   MenuTitleItem -//--------------------------------------------------------- - -MenuTitleItem::MenuTitleItem(const QString& ss, QWidget* parent) -  : QWidgetAction(parent) -      { -        s = ss; -        // Don't allow to click on it. -        setEnabled(false); -        // Just to be safe, set to -1 instead of default 0. -        setData(-1); -      } - -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; -} +//#include "popupmenu.h" +#include "routepopup.h"  /*  //--------------------------------------------------------- @@ -145,14 +120,6 @@ void AudioStrip::songChanged(int val)        if (val & SC_CHANNELS)          updateChannels(); -      // p3.3.47 -      // Update the routing popup menu if anything relevant changed. -      if (val & (SC_ROUTE | SC_CHANNELS | SC_CONFIG)) -      {  -        //updateRouteMenus(); -        muse->updateRouteMenus(track, this);      // p3.3.50 Use this handy shared routine. -      } -              // Catch when label font, or configuration min slider and meter values change.        if (val & SC_CONFIG)        { @@ -215,7 +182,6 @@ void AudioStrip::songChanged(int val)        if (val & SC_TRACK_MODIFIED)        {              setLabelText(); -            // Added by Tim. p3.3.9              setLabelFont();        }       @@ -1007,898 +973,14 @@ AudioStrip::AudioStrip(QWidget* parent, AudioTrack* at)        }  //--------------------------------------------------------- -//   addMenuItem -//--------------------------------------------------------- - -static int addMenuItem(AudioTrack* track, Track* route_track, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) -{ -  // totalInChannels is only used by syntis. -  int toch = ((AudioTrack*)track)->totalOutChannels(); -  // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. -  if(track->channels() == 1) -    toch = 1; -   -  // Don't add the last stray mono route if the track is stereo. -  //if(route_track->channels() > 1 && (channel+1 == chans)) -  //  return id; -     -  RouteList* rl = isOutput ? track->outRoutes() : track->inRoutes(); -   -  QAction* act; -   -  QString s(route_track->name()); -   -  act = lb->addAction(s); -  act->setData(id); -  act->setCheckable(true); -   -  int ach = channel; -  int bch = -1; -   -  Route r(route_track, isOutput ? ach : bch, channels); -   -  r.remoteChannel = isOutput ? bch : ach; -   -  mm.insert( pRouteMenuMap(id, r) ); -   -  for(iRoute ir = rl->begin(); ir != rl->end(); ++ir)  -  { -    if(ir->type == Route::TRACK_ROUTE && ir->track == route_track && ir->remoteChannel == r.remoteChannel) -    { -      int tcompch = r.channel; -      if(tcompch == -1) -        tcompch = 0; -      int tcompchs = r.channels; -      if(tcompchs == -1) -        tcompchs = isOutput ? track->channels() : route_track->channels(); -       -      int compch = ir->channel; -      if(compch == -1) -        compch = 0; -      int compchs = ir->channels; -      if(compchs == -1) -        compchs = isOutput ? track->channels() : ir->track->channels(); -       -      if(compch == tcompch && compchs == tcompchs)  -      { -        act->setChecked(true); -        break; -      } -    }   -  } -  return ++id;       -} - -//--------------------------------------------------------- -//   addAuxPorts -//--------------------------------------------------------- - -static int addAuxPorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) -      { -      AuxList* al = song->auxs(); -      for (iAudioAux i = al->begin(); i != al->end(); ++i) { -            Track* track = *i; -            if (t == track) -                  continue; -            id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); -            } -      return id;       -      } - -//--------------------------------------------------------- -//   addInPorts -//--------------------------------------------------------- - -static int addInPorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) -      { -      InputList* al = song->inputs(); -      for (iAudioInput i = al->begin(); i != al->end(); ++i) { -            Track* track = *i; -            if (t == track) -                  continue; -            id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); -            } -      return id;       -      } - -//--------------------------------------------------------- -//   addOutPorts -//--------------------------------------------------------- - -static int addOutPorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) -      { -      OutputList* al = song->outputs(); -      for (iAudioOutput i = al->begin(); i != al->end(); ++i) { -            Track* track = *i; -            if (t == track) -                  continue; -            id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); -            } -      return id;       -      } - -//--------------------------------------------------------- -//   addGroupPorts -//--------------------------------------------------------- - -static int addGroupPorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) -      { -      GroupList* al = song->groups(); -      for (iAudioGroup i = al->begin(); i != al->end(); ++i) { -            Track* track = *i; -            if (t == track) -                  continue; -            id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); -            } -      return id;       -      } - -//--------------------------------------------------------- -//   addWavePorts -//--------------------------------------------------------- - -static int addWavePorts(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, int channel, int channels, bool isOutput) -      { -      WaveTrackList* al = song->waves(); -      for (iWaveTrack i = al->begin(); i != al->end(); ++i) { -            Track* track = *i; -            if (t == track) -                  continue; -            id = addMenuItem(t, track, lb, id, mm, channel, channels, isOutput); -            } -      return id;       -      } - -//--------------------------------------------------------- -//   addSyntiPorts -//--------------------------------------------------------- - -static int addSyntiPorts(AudioTrack* t, PopupMenu* lb, int id,  -                         RouteMenuMap& mm, int channel, int channels, bool isOutput) -{ -      RouteList* rl = isOutput ? t->outRoutes() : t->inRoutes(); -       -      QAction* act; -       -      SynthIList* al = song->syntis(); -      for (iSynthI i = al->begin(); i != al->end(); ++i)  -      { -            Track* track = *i; -            if (t == track) -                  continue; -            int toch = ((AudioTrack*)track)->totalOutChannels(); -            // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. -            if(track->channels() == 1) -              toch = 1; -             -            // totalInChannels is only used by syntis. -            int chans = (!isOutput || track->type() != Track::AUDIO_SOFTSYNTH) ? toch : ((AudioTrack*)track)->totalInChannels(); -             -            int tchans = (channels != -1) ? channels: t->channels(); -            if(tchans == 2) -            { -              // Ignore odd numbered left-over mono channel. -              //chans = chans & ~1; -              //if(chans != 0) -                chans -= 1; -            } -             -            if(chans > 0) -            { -              PopupMenu* chpup = new PopupMenu(lb, true); -              chpup->setTitle(track->name()); -              for(int ch = 0; ch < chans; ++ch) -              { -                char buffer[128]; -                if(tchans == 2) -                  snprintf(buffer, 128, "%s %d,%d", chpup->tr("Channel").toLatin1().constData(), ch+1, ch+2); -                else   -                  snprintf(buffer, 128, "%s %d", chpup->tr("Channel").toLatin1().constData(), ch+1); -                act = chpup->addAction(QString(buffer)); -                act->setData(id); -                act->setCheckable(true); -                 -                int ach = (channel == -1) ? ch : channel; -                int bch = (channel == -1) ? -1 : ch; -                 -                Route rt(track, (t->type() != Track::AUDIO_SOFTSYNTH || isOutput) ? ach : bch, tchans); -                //Route rt(track, ch); -                //rt.remoteChannel = -1; -                rt.remoteChannel = (t->type() != Track::AUDIO_SOFTSYNTH || isOutput) ? bch : ach; -                 -                mm.insert( pRouteMenuMap(id, rt) ); -                 -                for(iRoute ir = rl->begin(); ir != rl->end(); ++ir)  -                { -                  if(ir->type == Route::TRACK_ROUTE && ir->track == track && ir->remoteChannel == rt.remoteChannel) -                  { -                    int tcompch = rt.channel; -                    if(tcompch == -1) -                      tcompch = 0; -                    int tcompchs = rt.channels; -                    if(tcompchs == -1) -                      tcompchs = isOutput ? t->channels() : track->channels(); -                     -                    int compch = ir->channel; -                    if(compch == -1) -                      compch = 0; -                    int compchs = ir->channels; -                    if(compchs == -1) -                      compchs = isOutput ? t->channels() : ir->track->channels(); -                     -                    if(compch == tcompch && compchs == tcompchs)  -                    { -                      act->setChecked(true); -                      break; -                    } -                  } -                }   -                ++id; -              } -             -              lb->addMenu(chpup); -            } -      } -      return id;       -} - -//--------------------------------------------------------- -//   addMultiChannelOutPorts -//--------------------------------------------------------- - -static int addMultiChannelPorts(AudioTrack* t, PopupMenu* pup, int id, RouteMenuMap& mm, bool isOutput) -{ -  int toch = t->totalOutChannels(); -  // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. -  if(t->channels() == 1) -    toch = 1; -   -  // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less.  -  // totalInChannels is only used by syntis. -  int chans = (isOutput || t->type() != Track::AUDIO_SOFTSYNTH) ? toch : t->totalInChannels(); - -  if(chans > 1) -    pup->addAction(new MenuTitleItem("<Mono>", pup));  -   -  // -  // If it's more than one channel, create a sub-menu. If it's just one channel, don't bother with a sub-menu... -  // - -  PopupMenu* chpup = pup; -   -  for(int ch = 0; ch < chans; ++ch) -  { -    // If more than one channel, create the sub-menu. -    if(chans > 1) -      chpup = new PopupMenu(pup, true); -     -    if(isOutput) -    { -      switch(t->type())  -      { -         -        case Track::AUDIO_INPUT: -              //id = addWavePorts(t, chpup, id, mm, ch, 1, isOutput);  // Rem p4.0.20 -        case Track::WAVE: -        case Track::AUDIO_GROUP: -        case Track::AUDIO_SOFTSYNTH: -        case Track::AUDIO_AUX:        // p4.0.20 -              id = addWavePorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addOutPorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addGroupPorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addSyntiPorts(t, chpup, id, mm, ch, 1, isOutput); -              //break;                                                // Rem p4.0.20 -        //case Track::AUDIO_AUX:                                      // -              //id = addOutPorts(t, chpup, id, mm, ch, 1, isOutput);  // -              break; -        default: -              break; -      } -    } -    else -    { -      switch(t->type())  -      { -         -        case Track::AUDIO_OUTPUT: -              id = addWavePorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addInPorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addGroupPorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addAuxPorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addSyntiPorts(t, chpup, id, mm, ch, 1, isOutput); -              break; -        case Track::WAVE: -              //id = addInPorts(t, chpup, id, mm, ch, 1, isOutput);    // Rem p4.0.20 -              //break; -        case Track::AUDIO_SOFTSYNTH: -        case Track::AUDIO_GROUP: -              id = addWavePorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addInPorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addGroupPorts(t, chpup, id, mm, ch, 1, isOutput); -              id = addAuxPorts(t, chpup, id, mm, ch, 1, isOutput);     // p4.0.20 -              id = addSyntiPorts(t, chpup, id, mm, ch, 1, isOutput); -              break; -        default: -              break; -      } -    } -       -    // If more than one channel, add the created sub-menu. -    if(chans > 1) -    { -      char buffer[128]; -      snprintf(buffer, 128, "%s %d", pup->tr("Channel").toLatin1().constData(), ch+1); -      chpup->setTitle(QString(buffer)); -      pup->addMenu(chpup); -    }   -  }  -        -  // For stereo listing, ignore odd numbered left-over channels. -  chans -= 1; -  if(chans > 0) -  { -    // Ignore odd numbered left-over channels. -    //int schans = (chans & ~1) - 1; -     -    pup->addSeparator(); -    pup->addAction(new MenuTitleItem("<Stereo>", pup)); -   -    // -    // If it's more than two channels, create a sub-menu. If it's just two channels, don't bother with a sub-menu... -    // -     -    chpup = pup; -    if(chans <= 2) -      // Just do one iteration. -      chans = 1; -     -    for(int ch = 0; ch < chans; ++ch) -    { -      // If more than two channels, create the sub-menu. -      if(chans > 2) -        chpup = new PopupMenu(pup, true); -       -      if(isOutput) -      { -        switch(t->type())  -        { -          case Track::AUDIO_INPUT: -                //id = addWavePorts(t, chpup, id, mm, ch, 2, isOutput);   // Rem p4.0.20 -          case Track::WAVE: -          case Track::AUDIO_GROUP: -          case Track::AUDIO_SOFTSYNTH: -          case Track::AUDIO_AUX:                                          // p4.0.20 -                id = addWavePorts(t, chpup, id, mm, ch, 2, isOutput);     // p4.0.20 -                id = addOutPorts(t, chpup, id, mm, ch, 2, isOutput); -                id = addGroupPorts(t, chpup, id, mm, ch, 2, isOutput); -                id = addSyntiPorts(t, chpup, id, mm, ch, 2, isOutput); -                break; -          //case Track::AUDIO_AUX:                                         // Rem p4.0.20 -          //      id = addOutPorts(t, chpup, id, mm, ch, 2, isOutput); -          //      break; -          default: -                break; -        } -      }     -      else -      { -        switch(t->type())  -        { -          case Track::AUDIO_OUTPUT: -                id = addWavePorts(t, chpup, id, mm, ch, 2, isOutput); -                id = addInPorts(t, chpup, id, mm, ch, 2, isOutput); -                id = addGroupPorts(t, chpup, id, mm, ch, 2, isOutput); -                id = addAuxPorts(t, chpup, id, mm, ch, 2, isOutput); -                id = addSyntiPorts(t, chpup, id, mm, ch, 2, isOutput); -                break; -          case Track::WAVE: -                //id = addInPorts(t, chpup, id, mm, ch, 2, isOutput);   // Rem p4.0.20 -                //break; -          case Track::AUDIO_SOFTSYNTH: -          case Track::AUDIO_GROUP: -                id = addWavePorts(t, chpup, id, mm, ch, 2, isOutput); -                id = addInPorts(t, chpup, id, mm, ch, 2, isOutput); -                id = addGroupPorts(t, chpup, id, mm, ch, 2, isOutput); -                id = addAuxPorts(t, chpup, id, mm, ch, 2, isOutput);     // p4.0.20 -                id = addSyntiPorts(t, chpup, id, mm, ch, 2, isOutput); -                break; -          default: -                break; -        } -      } -       -      // If more than two channels, add the created sub-menu. -      if(chans > 2) -      { -        char buffer[128]; -        snprintf(buffer, 128, "%s %d,%d", pup->tr("Channel").toLatin1().constData(), ch+1, ch+2); -        chpup->setTitle(QString(buffer)); -        pup->addMenu(chpup); -      }   -    }  -  } -   -  return id; -} - -//--------------------------------------------------------- -//   nonSyntiTrackAddSyntis -//--------------------------------------------------------- - -static int nonSyntiTrackAddSyntis(AudioTrack* t, PopupMenu* lb, int id, RouteMenuMap& mm, bool isOutput) -{ -      RouteList* rl = isOutput ? t->outRoutes() : t->inRoutes(); -       -      QAction* act; -      SynthIList* al = song->syntis(); -      for (iSynthI i = al->begin(); i != al->end(); ++i)  -      { -            Track* track = *i; -            if (t == track) -                  continue; -             -            int toch = ((AudioTrack*)track)->totalOutChannels(); -            // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. -            if(track->channels() == 1) -              toch = 1; -             -            // totalInChannels is only used by syntis. -            int chans = (!isOutput || track->type() != Track::AUDIO_SOFTSYNTH) ? toch : ((AudioTrack*)track)->totalInChannels(); -             -            //int schans = synti->channels(); -            //if(schans < chans) -            //  chans = schans; -//            int tchans = (channels != -1) ? channels: t->channels(); -//            if(tchans == 2) -//            { -              // Ignore odd numbered left-over mono channel. -              //chans = chans & ~1; -              //if(chans != 0) -//                chans -= 1; -//            } -            //int tchans = (channels != -1) ? channels: t->channels(); -             -            if(chans > 0) -            { -              PopupMenu* chpup = new PopupMenu(lb, true); -              chpup->setTitle(track->name()); -              if(chans > 1) -                chpup->addAction(new MenuTitleItem("<Mono>", chpup)); -               -              for(int ch = 0; ch < chans; ++ch) -              { -                char buffer[128]; -                snprintf(buffer, 128, "%s %d", chpup->tr("Channel").toLatin1().constData(), ch+1); -                act = chpup->addAction(QString(buffer)); -                act->setData(id); -                act->setCheckable(true); -                 -                int ach = ch; -                int bch = -1; -                 -                Route rt(track, isOutput ? bch : ach, 1); -                 -                rt.remoteChannel = isOutput ? ach : bch; -                 -                mm.insert( pRouteMenuMap(id, rt) ); -                 -                for(iRoute ir = rl->begin(); ir != rl->end(); ++ir)  -                { -                  if(ir->type == Route::TRACK_ROUTE && ir->track == track && ir->remoteChannel == rt.remoteChannel) -                  { -                    int tcompch = rt.channel; -                    if(tcompch == -1) -                      tcompch = 0; -                    int tcompchs = rt.channels; -                    if(tcompchs == -1) -                      tcompchs = isOutput ? t->channels() : track->channels(); -                     -                    int compch = ir->channel; -                    if(compch == -1) -                      compch = 0; -                    int compchs = ir->channels; -                    if(compchs == -1) -                      compchs = isOutput ? t->channels() : ir->track->channels(); -                     -                    if(compch == tcompch && compchs == tcompchs)  -                    { -                      act->setChecked(true); -                      break; -                    } -                  } -                } -                ++id; -              } -             -              chans -= 1; -              if(chans > 0) -              { -                // Ignore odd numbered left-over channels. -                //int schans = (chans & ~1) - 1; -                 -                chpup->addSeparator(); -                chpup->addAction(new MenuTitleItem("<Stereo>", chpup));  -               -                for(int ch = 0; ch < chans; ++ch) -                { -                  char buffer[128]; -                  snprintf(buffer, 128, "%s %d,%d", chpup->tr("Channel").toLatin1().constData(), ch+1, ch+2); -                  act = chpup->addAction(QString(buffer)); -                  act->setData(id); -                  act->setCheckable(true); -                   -                  int ach = ch; -                  int bch = -1; -                   -                  Route rt(track, isOutput ? bch : ach, 2); -                   -                  rt.remoteChannel = isOutput ? ach : bch; -                   -                  mm.insert( pRouteMenuMap(id, rt) ); -                   -                  for(iRoute ir = rl->begin(); ir != rl->end(); ++ir)  -                  { -                    if(ir->type == Route::TRACK_ROUTE && ir->track == track && ir->remoteChannel == rt.remoteChannel) -                    { -                      int tcompch = rt.channel; -                      if(tcompch == -1) -                        tcompch = 0; -                      int tcompchs = rt.channels; -                      if(tcompchs == -1) -                        tcompchs = isOutput ? t->channels() : track->channels(); -                       -                      int compch = ir->channel; -                      if(compch == -1) -                        compch = 0; -                      int compchs = ir->channels; -                      if(compchs == -1) -                        compchs = isOutput ? t->channels() : ir->track->channels(); -                       -                      if(compch == tcompch && compchs == tcompchs)  -                      { -                        act->setChecked(true); -                        break; -                      } -                    }   -                  } -                  ++id; -                } -              } -               -              lb->addMenu(chpup); -            } -      } -      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; -           -    // p4.0.17 Do not list synth devices! -    if(md->isSynti()) -      continue; -           -   RouteList* rl = isOutput ? t->outRoutes() : t->inRoutes(); -     -    PopupMenu* subp = new PopupMenu(pup, true); -    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  //---------------------------------------------------------  void AudioStrip::iRoutePressed()        { -      //if(track->isMidiTrack() || (track->type() == Track::AUDIO_AUX) || (track->type() == Track::AUDIO_SOFTSYNTH)) -      if(!track || track->isMidiTrack() || track->type() == Track::AUDIO_AUX) -      { -        gRoutingPopupMenuMaster = 0; -        return; -      } -         -      QPoint ppt = QCursor::pos(); -       -      PopupMenu* pup = muse->getRoutingPopupMenu(); -      pup->disconnect(); -       -      AudioTrack* t = (AudioTrack*)track; -      RouteList* irl = t->inRoutes(); - -      QAction* act = 0; -      int gid = 0; -      //int id = 0; -       -      pup->clear(); -      gRoutingMenuMap.clear(); -      gid = 0; -       -      switch(track->type())  -      { -        case Track::AUDIO_INPUT: -        { -          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); -            pup->addAction(titel);  -   -            if(!checkAudioDevice()) -            {  -              gRoutingPopupMenuMaster = 0; -              pup->clear(); -              gRoutingMenuMap.clear(); -              iR->setDown(false);      -              return; -            } -            std::list<QString> ol = audioDevice->outputPorts(); -            for(std::list<QString>::iterator ip = ol.begin(); ip != ol.end(); ++ip)  -            { -              //id = gid * 16 + i;        // IDs removed p4.0.14 Tim. -              act = pup->addAction(*ip); -              //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(gid, dst) ); -              ++gid; -              for(iRoute ir = irl->begin(); ir != irl->end(); ++ir)  -              { -                if(*ir == dst)  -                { -                  act->setChecked(true); -                  break; -                } -              } -            } -            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, true); -          subp->setTitle(tr("Audio sends"));  -          pup->addMenu(subp); -          gid = addOutPorts(t, subp, gid, gRoutingMenuMap, -1, -1, false);   -          subp = new PopupMenu(pup, true); -          subp->setTitle(tr("Midi port 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: -        //case Track::WAVE: -        //case Track::AUDIO_GROUP: -         -        case Track::AUDIO_OUTPUT: -              gid = addWavePorts( t, pup, gid, gRoutingMenuMap, -1, -1, false); -              gid = addInPorts(   t, pup, gid, gRoutingMenuMap, -1, -1, false); -              gid = addGroupPorts(t, pup, gid, gRoutingMenuMap, -1, -1, false); -              gid = addAuxPorts(  t, pup, gid, gRoutingMenuMap, -1, -1, false); -              gid = nonSyntiTrackAddSyntis(t, pup, gid, gRoutingMenuMap, false); -              break; -        case Track::WAVE: -              gid = addWavePorts( t, pup, gid, gRoutingMenuMap, -1, -1, false);  // p4.0.20 -              gid = addInPorts(   t, pup, gid, gRoutingMenuMap, -1, -1, false); -              gid = addGroupPorts(t, pup, gid, gRoutingMenuMap, -1, -1, false);  // -              gid = addAuxPorts(  t, pup, gid, gRoutingMenuMap, -1, -1, false);  // -              gid = nonSyntiTrackAddSyntis(t, pup, gid, gRoutingMenuMap, false); // -              break; -        case Track::AUDIO_GROUP: -              gid = addWavePorts( t, pup, gid, gRoutingMenuMap, -1, -1, false); -              gid = addInPorts(   t, pup, gid, gRoutingMenuMap, -1, -1, false); -              gid = addGroupPorts(t, pup, gid, gRoutingMenuMap, -1, -1, false); -              gid = addAuxPorts(  t, pup, gid, gRoutingMenuMap, -1, -1, false);  // p4.0.20 -              gid = nonSyntiTrackAddSyntis(t, pup, gid, gRoutingMenuMap, false); -              break; -         -        case Track::AUDIO_SOFTSYNTH: -              gid = addMultiChannelPorts(t, pup, gid, gRoutingMenuMap, false); -              break; -        default: -              gRoutingPopupMenuMaster = 0; -              pup->clear(); -              gRoutingMenuMap.clear(); -              iR->setDown(false);      -              return; -      }   -       -      if(pup->actions().isEmpty()) -      { -        gRoutingPopupMenuMaster = 0; -        gRoutingMenuMap.clear(); -        iR->setDown(false);      -        return; -      } -       -      gIsOutRoutingPopupMenu = false; -      gRoutingPopupMenuMaster = this; -      connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*))); -      connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide())); -      pup->popup(ppt); +      RoutePopupMenu* pup = muse->getRoutingPopupMenu();        iR->setDown(false);      +      pup->exec(QCursor::pos(), track, false);        }  //--------------------------------------------------------- @@ -1907,136 +989,8 @@ void AudioStrip::iRoutePressed()  void AudioStrip::oRoutePressed()  { -      if(!track || track->isMidiTrack()) -      { -        gRoutingPopupMenuMaster = 0; -        return; -      } -         -      QPoint ppt = QCursor::pos(); -       -      PopupMenu* pup = muse->getRoutingPopupMenu(); -      pup->disconnect(); -       -      AudioTrack* t = (AudioTrack*)track; -      RouteList* orl = t->outRoutes(); - -      QAction* act = 0; -      int gid = 0; -      //int id = 0; -       -      pup->clear(); -      gRoutingMenuMap.clear(); -      gid = 0; -       -      switch(track->type())  -      { -        case Track::AUDIO_OUTPUT: -        { -          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); -            pup->addAction(titel);  -   -            if(!checkAudioDevice()) -            {  -              gRoutingPopupMenuMaster = 0; -              pup->clear(); -              gRoutingMenuMap.clear(); -              oR->setDown(false);      -              return; -            } -            std::list<QString> ol = audioDevice->inputPorts(); -            for(std::list<QString>::iterator ip = ol.begin(); ip != ol.end(); ++ip)  -            { -              //id = gid * 16 + i;        // IDs removed p4.0.14 Tim. -              act = pup->addAction(*ip); -              //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(gid, dst) ); -              ++gid; -              for(iRoute ir = orl->begin(); ir != orl->end(); ++ir)  -              { -                if(*ir == dst)  -                { -                  act->setChecked(true); -                  break; -                } -              } -            } -            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, true); -          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: -        //case Track::WAVE: -        //case Track::AUDIO_GROUP: - -        case Track::AUDIO_SOFTSYNTH: -              gid = addMultiChannelPorts(t, pup, gid, gRoutingMenuMap, true); -        break; -         -        case Track::AUDIO_INPUT: -              //gid = addWavePorts(        t, pup, gid, gRoutingMenuMap, -1, -1, true);  // Rem p4.0.20 -        case Track::WAVE: -        case Track::AUDIO_GROUP: -        case Track::AUDIO_AUX: -        //case Track::AUDIO_SOFTSYNTH: -              gid = addWavePorts(        t, pup, gid, gRoutingMenuMap, -1, -1, true);  // p4.0.20 -              gid = addOutPorts(         t, pup, gid, gRoutingMenuMap, -1, -1, true); -              gid = addGroupPorts(       t, pup, gid, gRoutingMenuMap, -1, -1, true); -              gid = nonSyntiTrackAddSyntis(t, pup, gid, gRoutingMenuMap, true); -        break; -        //case Track::AUDIO_AUX: -        //      gid = addOutPorts(         t, pup, gid, gRoutingMenuMap, -1, -1, true); -        //break; -         -        default: -              gRoutingPopupMenuMaster = 0; -              pup->clear(); -              gRoutingMenuMap.clear(); -              oR->setDown(false);      -              return; -      } -       -      if(pup->actions().isEmpty()) -      { -        gRoutingPopupMenuMaster = 0; -        gRoutingMenuMap.clear(); -        oR->setDown(false);      -        return; -      } -       -      gIsOutRoutingPopupMenu = true; -      gRoutingPopupMenuMaster = this; -      connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*))); -      connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide())); -      pup->popup(ppt); +      RoutePopupMenu* pup = muse->getRoutingPopupMenu();        oR->setDown(false);      +      pup->exec(QCursor::pos(), track, true);  } diff --git a/muse2/muse/mixer/astrip.h b/muse2/muse/mixer/astrip.h index 10d75305..92867033 100644 --- a/muse2/muse/mixer/astrip.h +++ b/muse2/muse/mixer/astrip.h @@ -12,7 +12,7 @@  #include <vector>  #include "strip.h" -#include "route.h" +//#include "route.h"  class Slider;  class Knob; @@ -20,7 +20,7 @@ class Knob;  class QToolButton;  //class QAction;  //class QPopupMenu; -class PopupMenu; +//class PopupMenu;  class QButton;  class TransparentToolButton;  class AudioTrack; @@ -61,7 +61,6 @@ class AudioStrip : public Strip {        void updateVolume();        void updatePan();        void updateChannels(); -      //void updateRouteMenus();     private slots:        void stereoToggled(bool); @@ -69,7 +68,6 @@ class AudioStrip : public Strip {        void offToggled(bool);        void iRoutePressed();        void oRoutePressed(); -      void routingPopupMenuActivated(QAction*);        void auxChanged(double, int);        void volumeChanged(double);        void volumePressed(); diff --git a/muse2/muse/mixer/mstrip.cpp b/muse2/muse/mixer/mstrip.cpp index 427f9ed6..d773708a 100644 --- a/muse2/muse/mixer/mstrip.cpp +++ b/muse2/muse/mixer/mstrip.cpp @@ -43,7 +43,8 @@  #include "gconfig.h"  #include "ttoolbutton.h"  //#include "utils.h" -#include "popupmenu.h" +//#include "popupmenu.h" +#include "routepopup.h"  enum { KNOB_PAN, KNOB_VAR_SEND, KNOB_REV_SEND, KNOB_CHO_SEND }; @@ -503,26 +504,17 @@ void MidiStrip::songChanged(int val)        if (val & SC_TRACK_MODIFIED)        {              setLabelText(); -            // Added by Tim. p3.3.9              setLabelFont();        }       -      // Added by Tim. p3.3.9 -      // Catch when label font changes. +      // Catch when label font changes. Tim. p3.3.9        if (val & SC_CONFIG)        {          // Set the strip label's font.          //label->setFont(config.fonts[1]);          setLabelFont();        }   -       -      // p3.3.47 Update the routing popup menu if anything relevant changes. -      //if(gRoutingPopupMenuMaster == this && track && (val & (SC_ROUTE | SC_CHANNELS | SC_CONFIG)))  -      if(val & (SC_ROUTE | SC_CHANNELS | SC_CONFIG))      // p3.3.50 -        // Use this handy shared routine. -        //muse->updateRouteMenus(track); -        muse->updateRouteMenus(track, this);              // p3.3.50      }  //--------------------------------------------------------- @@ -1007,35 +999,14 @@ void MidiStrip::setReverbSend(double val)        }  //--------------------------------------------------------- -//   routingPopupMenuActivated -//--------------------------------------------------------- - -void MidiStrip::routingPopupMenuActivated(QAction* act) -{ -  if(gRoutingPopupMenuMaster != this || !track || !track->isMidiTrack()) -    return; -   -  muse->routingPopupMenuActivated(track, act->data().toInt()); -} - -//---------------------------------------------------------  //   iRoutePressed  //---------------------------------------------------------  void MidiStrip::iRoutePressed()  { -  if(!track || !track->isMidiTrack()) -    return; -   -  PopupMenu* pup = muse->prepareRoutingPopupMenu(track, false); -  if(!pup) -    return; -   -  gRoutingPopupMenuMaster = this; -  connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*))); -  connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide())); -  pup->popup(QCursor::pos()); +  RoutePopupMenu* pup = muse->getRoutingPopupMenu();    iR->setDown(false);      +  pup->exec(QCursor::pos(), track, false);  }  //--------------------------------------------------------- @@ -1044,18 +1015,9 @@ void MidiStrip::iRoutePressed()  void MidiStrip::oRoutePressed()  { -  if(!track || !track->isMidiTrack()) -    return; -   -  PopupMenu* pup = muse->prepareRoutingPopupMenu(track, true); -  if(!pup) -    return; -   -  gRoutingPopupMenuMaster = this; -  connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*))); -  connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide())); -  pup->popup(QCursor::pos()); +  RoutePopupMenu* pup = muse->getRoutingPopupMenu();    oR->setDown(false);      +  pup->exec(QCursor::pos(), track, true);  } diff --git a/muse2/muse/mixer/mstrip.h b/muse2/muse/mixer/mstrip.h index 920cca99..39b55d21 100644 --- a/muse2/muse/mixer/mstrip.h +++ b/muse2/muse/mixer/mstrip.h @@ -32,9 +32,6 @@ class MidiStrip : public Strip {        Slider* slider;        DoubleLabel* sl;        TransparentToolButton* off; -      //QToolButton* route; -      //QToolButton* iR; -      //QToolButton* oR;        struct KNOB {              Knob* knob; @@ -55,11 +52,9 @@ class MidiStrip : public Strip {        void updateOffState();     private slots: -      //void routeClicked();        void offToggled(bool);        void iRoutePressed();        void oRoutePressed(); -      void routingPopupMenuActivated(QAction*);        void setVolume(double);        void setPan(double);        void setChorusSend(double); diff --git a/muse2/muse/node.cpp b/muse2/muse/node.cpp index 114b03d3..06dbbc8d 100644 --- a/muse2/muse/node.cpp +++ b/muse2/muse/node.cpp @@ -1264,7 +1264,7 @@ bool AudioTrack::getData(unsigned pos, int channels, unsigned nframes, float** b        printf("AudioTrack::getData name:%s inRoutes:%d\n", name().toLatin1().constData(), rl->size());        #endif -      iRoute ir = rl->begin(); +      ciRoute ir = rl->begin();        if (ir == rl->end())              return false; diff --git a/muse2/muse/route.cpp b/muse2/muse/route.cpp index 6f42c1f2..9425f056 100644 --- a/muse2/muse/route.cpp +++ b/muse2/muse/route.cpp @@ -187,7 +187,7 @@ void addRoute(Route src, Route dst)                src.channel = dst.channel;                //src.channels = dst.channels = 1;                RouteList* inRoutes = dst.track->inRoutes(); -              for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)  +              for (ciRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)                 {                  if (*i == src)    // route already there                  { @@ -226,7 +226,7 @@ void addRoute(Route src, Route dst)                  //dst.channel = -1;                  RouteList* routes = dst.device->inRoutes(); -                for (iRoute i = routes->begin(); i != routes->end(); ++i)  +                for (ciRoute i = routes->begin(); i != routes->end(); ++i)                   {                    if (*i == src)    // route already there                    { @@ -284,7 +284,7 @@ void addRoute(Route src, Route dst)                dst.channel = src.channel;                //dst.channels = src.channels = 1; -              for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)  +              for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)                 {                      if (*i == dst)    // route already there                      { @@ -312,7 +312,7 @@ void addRoute(Route src, Route dst)                  //dst.channels = src.channels = 1;                  RouteList* routes = src.device->outRoutes(); -                for (iRoute i = routes->begin(); i != routes->end(); ++i)  +                for (ciRoute i = routes->begin(); i != routes->end(); ++i)                   {                    if (*i == dst)    // route already there                    { @@ -616,7 +616,7 @@ void addRoute(Route src, Route dst)              //    dst.channels = src.track->channels();                //} -            for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)  +            for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)               {                    if (*i == dst)    // route already there                    // TODO: @@ -1248,7 +1248,7 @@ bool checkRoute(const QString& s, const QString& d)                      }                src.channel = dst.channel;                RouteList* inRoutes = dst.track->inRoutes(); -              for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)  +              for (ciRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)                 {                      if (*i == src) {   // route already there                            return false; @@ -1263,7 +1263,7 @@ bool checkRoute(const QString& s, const QString& d)                src.channel = -1;                //dst.channel = -1;                RouteList* routes = dst.device->inRoutes(); -              for (iRoute i = routes->begin(); i != routes->end(); ++i)  +              for (ciRoute i = routes->begin(); i != routes->end(); ++i)                 {                      if (*i == src) {   // route already there                            return false; @@ -1286,7 +1286,7 @@ bool checkRoute(const QString& s, const QString& d)                      }                RouteList* outRoutes = src.track->outRoutes();                dst.channel = src.channel; -              for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)  +              for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)                 {                      if (*i == dst) {   // route already there                            return false; @@ -1301,7 +1301,7 @@ bool checkRoute(const QString& s, const QString& d)                //dst.channel = src.channel;                dst.channel = -1;                //src.channel = -1; -              for (iRoute i = routes->begin(); i != routes->end(); ++i)  +              for (ciRoute i = routes->begin(); i != routes->end(); ++i)                 {                      if (*i == dst) {   // route already there                            return false; @@ -1314,7 +1314,7 @@ bool checkRoute(const QString& s, const QString& d)        else if (src.type == Route::MIDI_PORT_ROUTE) // p3.3.49        {              RouteList* outRoutes = midiPorts[src.midiPort].outRoutes(); -            for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)  +            for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)               {                    if (*i == dst) {   // route already there                          return false; @@ -1330,7 +1330,7 @@ bool checkRoute(const QString& s, const QString& d)              //                       src.device->outRoutes() : src.track->outRoutes();              RouteList* outRoutes = (src.type == Route::MIDI_DEVICE_ROUTE) ? src.device->outRoutes() : src.track->outRoutes(); -            for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)  +            for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)               {                    if (*i == dst) {   // route already there                          return false; diff --git a/muse2/muse/route.h b/muse2/muse/route.h index 2f29bcf8..9809352c 100644 --- a/muse2/muse/route.h +++ b/muse2/muse/route.h @@ -9,9 +9,10 @@  #ifndef __ROUTE_H__  #define __ROUTE_H__ +#include <QMetaType> +  #include <vector>  #include <map> -  #include "globaldefs.h"  class QString; @@ -71,6 +72,8 @@ struct Route {        void dump() const;        }; +// Allow Routes to be a QVariant +Q_DECLARE_METATYPE(Route) ;  //---------------------------------------------------------  //   RouteList @@ -93,11 +96,11 @@ extern bool checkRoute(const QString&, const QString&);  //   RouteMenuMap  //--------------------------------------------------------- -typedef std::map<int, Route, std::less<int> >::iterator iRouteMenuMap; -typedef std::map<int, Route, std::less<int> >::const_iterator ciRouteMenuMap; -typedef std::map<int, Route, std::less<int> > RouteMenuMap; -typedef std::pair<int, Route> pRouteMenuMap; -typedef std::pair<iRouteMenuMap, bool > rpRouteMenuMap; +//typedef std::map<int, Route, std::less<int> >::iterator iRouteMenuMap; +//typedef std::map<int, Route, std::less<int> >::const_iterator ciRouteMenuMap; +//typedef std::map<int, Route, std::less<int> > RouteMenuMap; +//typedef std::pair<int, Route> pRouteMenuMap; +//typedef std::pair<iRouteMenuMap, bool > rpRouteMenuMap;  #endif diff --git a/muse2/muse/seqmsg.cpp b/muse2/muse/seqmsg.cpp index 950015b2..b4d65148 100644 --- a/muse2/muse/seqmsg.cpp +++ b/muse2/muse/seqmsg.cpp @@ -396,7 +396,7 @@ void Audio::msgSetChannels(AudioTrack* node, int n)                  else if ((i >= n) && ai->jackPort(i))                   {                    RouteList* ir = node->inRoutes(); -                  for (iRoute ii = ir->begin(); ii != ir->end(); ++ii)  +                  for (ciRoute ii = ir->begin(); ii != ir->end(); ++ii)                     {                      Route r = *ii;                      if ((r.type == Route::JACK_ROUTE) && (r.channel == i))  @@ -427,7 +427,7 @@ void Audio::msgSetChannels(AudioTrack* node, int n)                          else if (i >= n && jp)                           {                                RouteList* ir = node->outRoutes(); -                              for (iRoute ii = ir->begin(); ii != ir->end(); ++ii)  +                              for (ciRoute ii = ir->begin(); ii != ir->end(); ++ii)                                 {                                      Route r = *ii;                                      if ((r.type == Route::JACK_ROUTE) && (r.channel == i))  diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index 28ea1210..6750203a 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -2926,7 +2926,7 @@ void Song::connectJackRoutes(AudioTrack* track, bool disconnect)                      for(int ch = 0; ch < ao->channels(); ++ch)                      {                          RouteList* ir = ao->outRoutes(); -                        for (iRoute ii = ir->begin(); ii != ir->end(); ++ii) +                        for (ciRoute ii = ir->begin(); ii != ir->end(); ++ii)                          {                              Route r = *ii;                              if ((r.type == Route::JACK_ROUTE) && (r.channel == ch)) @@ -2959,7 +2959,7 @@ void Song::connectJackRoutes(AudioTrack* track, bool disconnect)                          for(int ch = 0; ch < ai->channels(); ++ch)                          {                              RouteList* ir = ai->inRoutes(); -                            for (iRoute ii = ir->begin(); ii != ir->end(); ++ii) +                            for (ciRoute ii = ir->begin(); ii != ir->end(); ++ii)                              {                                  Route r = *ii;                                  if ((r.type == Route::JACK_ROUTE) && (r.channel == ch)) diff --git a/muse2/muse/wavetrack.cpp b/muse2/muse/wavetrack.cpp index fdebc8b8..ad02084c 100644 --- a/muse2/muse/wavetrack.cpp +++ b/muse2/muse/wavetrack.cpp @@ -209,7 +209,7 @@ bool WaveTrack::getData(unsigned framePos, int channels, unsigned nframe, float*        if ((song->bounceTrack != this) && !noInRoute()) {              RouteList* irl = inRoutes(); -            iRoute i = irl->begin(); +            ciRoute i = irl->begin();              if(i->track->isMidiTrack())              {                if(debugMsg) diff --git a/muse2/muse/widgets/CMakeLists.txt b/muse2/muse/widgets/CMakeLists.txt index 7589ddf0..a4da398f 100644 --- a/muse2/muse/widgets/CMakeLists.txt +++ b/muse2/muse/widgets/CMakeLists.txt @@ -47,6 +47,7 @@ QT4_WRAP_CPP (widget_mocs        intlabel.h          knob.h          lcombo.h   +      menutitleitem.h        meter.h        metronome.h          midisyncimpl.h   @@ -63,6 +64,7 @@ QT4_WRAP_CPP (widget_mocs        # posedit.h          poslabel.h          projectcreateimpl.h +      routepopup.h          scrollscale.h          shortcutcapturedialog.h          shortcutconfig.h   @@ -142,6 +144,7 @@ file (GLOB widgets_source_files        intlabel.cpp         knob.cpp         lcombo.cpp  +      menutitleitem.cpp        meter.cpp        metronome.cpp         midisyncimpl.cpp  @@ -159,6 +162,7 @@ file (GLOB widgets_source_files        # posedit.cpp         poslabel.cpp        projectcreateimpl.cpp  +      routepopup.cpp         scldiv.cpp        scldraw.cpp        sclif.cpp diff --git a/muse2/muse/widgets/genset.cpp b/muse2/muse/widgets/genset.cpp index edf3cfda..d8c76874 100644 --- a/muse2/muse/widgets/genset.cpp +++ b/muse2/muse/widgets/genset.cpp @@ -151,6 +151,7 @@ Shorter periods are desirable.</string>        oldStyleStopCheckBox->setChecked(config.useOldStyleStopShortCut);        moveArmedCheckBox->setChecked(config.moveArmedCheckBox);        projectSaveCheckBox->setChecked(config.useProjectSaveDialog); +      popsDefStayOpenCheckBox->setChecked(config.popupsDefaultStayOpen);        //updateSettings();    // TESTING @@ -263,6 +264,7 @@ void GlobalSettingsConfig::updateSettings()        oldStyleStopCheckBox->setChecked(config.useOldStyleStopShortCut);        moveArmedCheckBox->setChecked(config.moveArmedCheckBox);        projectSaveCheckBox->setChecked(config.useProjectSaveDialog); +      popsDefStayOpenCheckBox->setChecked(config.popupsDefaultStayOpen);  }  //--------------------------------------------------------- @@ -344,6 +346,7 @@ void GlobalSettingsConfig::apply()        config.useOldStyleStopShortCut = oldStyleStopCheckBox->isChecked();        config.moveArmedCheckBox = moveArmedCheckBox->isChecked();        config.useProjectSaveDialog = projectSaveCheckBox->isChecked(); +      config.popupsDefaultStayOpen = popsDefStayOpenCheckBox->isChecked();        //muse->showMixer(config.mixerVisible);        muse->showMixer1(config.mixer1Visible); diff --git a/muse2/muse/widgets/gensetbase.ui b/muse2/muse/widgets/gensetbase.ui index ca4b97f8..68f3ebb5 100644 --- a/muse2/muse/widgets/gensetbase.ui +++ b/muse2/muse/widgets/gensetbase.ui @@ -1333,7 +1333,7 @@ Adjusts responsiveness of audio controls and              </property>             </widget>            </item> -          <item row="4" column="0"> +          <item row="5" column="0">             <spacer name="verticalSpacer_2">              <property name="orientation">               <enum>Qt::Vertical</enum> @@ -1346,6 +1346,27 @@ Adjusts responsiveness of audio controls and              </property>             </spacer>            </item> +          <item row="4" column="0"> +           <widget class="QLabel" name="TextLabel1_3"> +            <property name="toolTip"> +             <string/> +            </property> +            <property name="text"> +             <string>Some popup menus stay open (else hold Ctrl)</string> +            </property> +           </widget> +          </item> +          <item row="4" column="1"> +           <widget class="QCheckBox" name="popsDefStayOpenCheckBox"> +            <property name="toolTip"> +             <string>Allows some popup menus to stay open. +Otherwise, hold Ctrl to keep them open.</string> +            </property> +            <property name="text"> +             <string/> +            </property> +           </widget> +          </item>           </layout>          </widget>         </item> diff --git a/muse2/muse/widgets/menutitleitem.cpp b/muse2/muse/widgets/menutitleitem.cpp new file mode 100644 index 00000000..8769eb02 --- /dev/null +++ b/muse2/muse/widgets/menutitleitem.cpp @@ -0,0 +1,48 @@ +//============================================================================= +//  MusE +//  Linux Music Editor +//  (C) Copyright 1999-2001 Werner Schweer (ws@seh.de) +// +//  This program is free software; you can redistribute it and/or modify +//  it under the terms of the GNU General Public License version 2. +// +//  This program is distributed in the hope that it will be useful, +//  but WITHOUT ANY WARRANTY; without even the implied warranty of +//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +//  GNU General Public License for more details. +// +//  You should have received a copy of the GNU General Public License +//  along with this program; if not, write to the Free Software +//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#include <QLabel> + +#include "menutitleitem.h" + +//--------------------------------------------------------- +//   MenuTitleItem +//--------------------------------------------------------- + +MenuTitleItem::MenuTitleItem(const QString& ss, QWidget* parent) +  : QWidgetAction(parent) +      { +        s = ss; +        // Don't allow to click on it. +        setEnabled(false); +        // Just to be safe, set to -1 instead of default 0. +        setData(-1); +      } + +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; +} + diff --git a/muse2/muse/widgets/mtrackinfo.cpp b/muse2/muse/widgets/mtrackinfo.cpp index 465b7130..6dd02931 100644 --- a/muse2/muse/widgets/mtrackinfo.cpp +++ b/muse2/muse/widgets/mtrackinfo.cpp @@ -26,6 +26,7 @@  #include "app.h"  #include "route.h"  #include "popupmenu.h" +#include "routepopup.h"  //---------------------------------------------------------  //   setTrack @@ -577,33 +578,6 @@ void MidiTrackInfo::iOutputPortChanged(int index)        }  //--------------------------------------------------------- -//   routingPopupMenuActivated -//--------------------------------------------------------- - -//void MidiTrackInfo::routingPopupMenuActivated(int n) -void MidiTrackInfo::routingPopupMenuActivated(QAction* act) -{ -  ///if(!midiTrackInfo || gRoutingPopupMenuMaster != midiTrackInfo || !selected || !selected->isMidiTrack()) -  if((gRoutingPopupMenuMaster != this) || !selected || !selected->isMidiTrack()) -    return; -  muse->routingPopupMenuActivated(selected, act->data().toInt()); -} - -#if 0 -//--------------------------------------------------------- -//   routingPopupViewActivated -//--------------------------------------------------------- - -void MidiTrackInfo::routingPopupViewActivated(const QModelIndex& mdi) -{ -  ///if(!midiTrackInfo || gRoutingPopupMenuMaster != midiTrackInfo || !selected || !selected->isMidiTrack()) -  if(gRoutingPopupMenuMaster != this || !selected || !selected->isMidiTrack()) -    return; -  muse->routingPopupMenuActivated(selected, mdi.data().toInt()); -} -#endif - -//---------------------------------------------------------  //   inRoutesPressed  //--------------------------------------------------------- @@ -614,44 +588,9 @@ void MidiTrackInfo::inRoutesPressed()    if(!selected->isMidiTrack())      return; -  PopupMenu* pup = muse->prepareRoutingPopupMenu(selected, false); -  //PopupView* pup = muse->prepareRoutingPopupView(selected, false); - -  /* -  QPoint ppt = QCursor::pos(); -   -  int i = 0; -  for( ; i < MIDI_PORTS; ++i) -  { -    if(midiPorts[i].device() && !midiPorts[pi].device()->isSynti()) -      break; -  } -  if(!pup || i == MIDI_PORTS) -  { -    int ret = QMessageBox::warning(this, tr("No devices"), -                                   tr("There are no midi port devices defined.\n" -                                      "Do you want to open the midi configuration dialog?"), -                                   QMessageBox::Ok | QMessageBox::Cancel, -                                   QMessageBox::Ok); -    if (ret == QMessageBox::Ok) { -        //printf("open config midi ports\n"); -        muse->configMidiPorts(); -    } -    if(!pup) -      return; -  } -  */ -   -  ///gRoutingPopupMenuMaster = midiTrackInfo; -  gRoutingPopupMenuMaster = this; -  connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*))); -  //connect(pup, SIGNAL(activated(const QModelIndex&)), SLOT(routingPopupViewActivated(const QModelIndex&))); -  connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide())); -  //connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupViewAboutToHide())); -  pup->popup(QCursor::pos()); -  //pup->setVisible(true); +  RoutePopupMenu* pup = muse->getRoutingPopupMenu();    iRButton->setDown(false);      -  return; +  pup->exec(QCursor::pos(), selected, false);  }  //--------------------------------------------------------- @@ -665,17 +604,9 @@ void MidiTrackInfo::outRoutesPressed()    if(!selected->isMidiTrack())      return; -  PopupMenu* pup = muse->prepareRoutingPopupMenu(selected, true); -  if(!pup) -    return; -   -  ///gRoutingPopupMenuMaster = midiTrackInfo; -  gRoutingPopupMenuMaster = this; -  connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*))); -  connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide())); -  pup->popup(QCursor::pos()); +  RoutePopupMenu* pup = muse->getRoutingPopupMenu();    oRButton->setDown(false);      -  return; +  pup->exec(QCursor::pos(), selected, true);  }  //--------------------------------------------------------- @@ -1044,7 +975,7 @@ void MidiTrackInfo::iPanChanged(int val)  void MidiTrackInfo::instrPopupActivated(QAction* act)  { -  //printf("MidiTrackInfo::instrPopupActivated\n"); // REMOVE Tim +  //printf("MidiTrackInfo::instrPopupActivated\n");     if(act && selected)     { @@ -1076,11 +1007,11 @@ void MidiTrackInfo::instrPopup()        //QMenu* pup = new QMenu;        PopupMenu* pup = new PopupMenu(true); -      ///instr->populatePatchPopup(pop, channel, song->mtype(), track->type() == Track::DRUM); +      //instr->populatePatchPopup(pop, channel, song->mtype(), track->type() == Track::DRUM);        instr->populatePatchPopup(pup, channel, song->mtype(), track->type() == Track::DRUM); -      ///if(pop->actions().count() == 0) -      ///  return; +      //if(pop->actions().count() == 0) +      //  return;        if(pup->actions().count() == 0)        {          delete pup; @@ -1090,7 +1021,7 @@ void MidiTrackInfo::instrPopup()        connect(pup, SIGNAL(triggered(QAction*)), SLOT(instrPopupActivated(QAction*)));        //connect(pup, SIGNAL(hovered(QAction*)), SLOT(instrPopupActivated(QAction*))); -      ///QAction *act = pop->exec(iPatch->mapToGlobal(QPoint(10,5))); +      //QAction *act = pop->exec(iPatch->mapToGlobal(QPoint(10,5)));        QAction *act = pup->exec(iPatch->mapToGlobal(QPoint(10,5)));        if(act)         { @@ -1310,15 +1241,6 @@ void MidiTrackInfo::updateTrackInfo(int flags)          return;        MidiTrack* track = (MidiTrack*)selected; -      // p3.3.47 Update the routing popup menu if anything relevant changes. -      //if(gRoutingPopupMenuMaster == midiTrackInfo && selected && (flags & (SC_ROUTE | SC_CHANNELS | SC_CONFIG)))  -      if(flags & (SC_ROUTE | SC_CHANNELS | SC_CONFIG))     // p3.3.50 -        // Use this handy shared routine. -        //muse->updateRouteMenus(selected); -        ///muse->updateRouteMenus(selected, midiTrackInfo);   // p3.3.50 -        muse->updateRouteMenus(selected, this);  -       -      // Added by Tim. p3.3.9        setLabelText();        setLabelFont(); diff --git a/muse2/muse/widgets/mtrackinfo.h b/muse2/muse/widgets/mtrackinfo.h index 0e559f33..ed229ad6 100644 --- a/muse2/muse/widgets/mtrackinfo.h +++ b/muse2/muse/widgets/mtrackinfo.h @@ -46,8 +46,6 @@ class MidiTrackInfo : public QWidget, public Ui::MidiTrackInfoBase        void recEchoToggled(bool);        void inRoutesPressed();        void outRoutesPressed(); -      void routingPopupMenuActivated(QAction*); -      //void routingPopupViewActivated(const QModelIndex&);        void instrPopupActivated(QAction*);     protected slots: diff --git a/muse2/muse/widgets/musewidgetsplug.cpp b/muse2/muse/widgets/musewidgetsplug.cpp index 8cb0b57e..993b0fb8 100644 --- a/muse2/muse/widgets/musewidgetsplug.cpp +++ b/muse2/muse/widgets/musewidgetsplug.cpp @@ -190,13 +190,14 @@ GlobalConfigValues config = {        true,                         // useDenormalBias        false,                        // useOutputLimiter        true,                         // showDidYouKnow -      false,                         // vstInPlace  Enable VST in-place processing +      false,                        // vstInPlace  Enable VST in-place processing        44100,                        // Dummy audio preferred sample rate        512                           // Dummy audio buffer size        QString("./"),                // projectBaseFolder        true,                         // projectStoreInFolder        true,                         // useProjectSaveDialog -      64                            // minControlProcessPeriod +      64,                           // minControlProcessPeriod +      false                         // popupsDefaultStayOpen        };  //--------------------------------------------------------- diff --git a/muse2/muse/widgets/popupmenu.cpp b/muse2/muse/widgets/popupmenu.cpp index 263c8475..adbe7dd6 100644 --- a/muse2/muse/widgets/popupmenu.cpp +++ b/muse2/muse/widgets/popupmenu.cpp @@ -22,6 +22,8 @@  //#include <QStandardItemModel>  #include "popupmenu.h" +#include "gconfig.h" +#include "route.h"  //====================== @@ -82,7 +84,7 @@ void PopupMenu::clear()      QMenu* menu = act->menu();      if(menu)      { -      menu->clear(); +      menu->clear();    // Recursive.        act->setMenu(0);  // CHECK: Is this OK?        delete menu;      } @@ -97,7 +99,25 @@ void PopupMenu::clear()    #endif    // POPUP_MENU_DISABLE_AUTO_SCROLL  } -QAction* PopupMenu::findActionFromData(QVariant v) const +void PopupMenu::clearAllChecks() const +{ +  QList<QAction*> list = actions(); +  for(int i = 0; i < list.size(); ++i) +  { +    QAction* act = list[i]; +    PopupMenu* menu = static_cast <PopupMenu*>(act->menu()); +    if(menu) +      menu->clearAllChecks();     // Recursive. +    if(act->isCheckable()) +    { +      act->blockSignals(true); +      act->setChecked(false); +      act->blockSignals(false); +    }   +  } +} + +QAction* PopupMenu::findActionFromData(const QVariant& v) const  {    QList<QAction*> list = actions();    for(int i = 0; i < list.size(); ++i) @@ -106,9 +126,21 @@ QAction* PopupMenu::findActionFromData(QVariant v) const      PopupMenu* menu = (PopupMenu*)act->menu();      if(menu)      { -      if(QAction* actm = menu->findActionFromData(v)) +      if(QAction* actm = menu->findActionFromData(v))      // Recursive.          return actm;      } +     +    // "Operator == Compares this QVariant with v and returns true if they are equal,  +    //   otherwise returns false. In the case of custom types, their equalness operators  +    //   are not called. Instead the values' addresses are compared." +    // +    // Take care of struct Route first. Insert other future custom structures here too ! +    if(act->data().canConvert<Route>() && v.canConvert<Route>()) +    { +      if(act->data().value<Route>() == v.value<Route>()) +        return act;     +    } +    else      if(act->data() == v)        return act;    } @@ -117,7 +149,7 @@ QAction* PopupMenu::findActionFromData(QVariant v) const  bool PopupMenu::event(QEvent* event)  { -  //printf("PopupMenu::event type:%d\n", event->type());   // REMOVE Tim. +  //printf("PopupMenu::event type:%d\n", event->type());       switch(event->type())    { @@ -125,6 +157,7 @@ bool PopupMenu::event(QEvent* event)      case QEvent::MouseButtonDblClick:      {          if(_stayOpen) +      //if(_stayOpen && config.popupsDefaultStayOpen)        {          QMouseEvent* e = static_cast<QMouseEvent*>(event);          if(e->modifiers() == Qt::NoModifier) @@ -143,6 +176,7 @@ bool PopupMenu::event(QEvent* event)      case QEvent::KeyPress:      {        if(_stayOpen) +      //if(_stayOpen && config.popupsDefaultStayOpen)        {          QKeyEvent* e = static_cast<QKeyEvent*>(event);          if(e->modifiers() == Qt::NoModifier && e->key() == Qt::Key_Space) @@ -169,7 +203,7 @@ bool PopupMenu::event(QEvent* event)        int dw = QApplication::desktop()->width();  // We want the whole thing if multiple monitors.        //printf("PopupMenu::event MouseMove: pos x:%d y:%d  globPos x:%d y:%d\n",  -      //      pos.x(), pos.y(), globPos.x(), globPos.y());  // REMOVE Tim. +      //      pos.x(), pos.y(), globPos.x(), globPos.y());          /*        //QAction* action = actionAt(globPos); @@ -178,7 +212,7 @@ bool PopupMenu::event(QEvent* event)        {           QRect r = actionGeometry(action);          //printf(" act x:%d y:%d w:%d h:%d  popup px:%d py:%d pw:%d ph:%d\n",  -        //      r.x(), r.y(), r.width(), r.height(), x(), y(), width(), height());  // REMOVE Tim. +        //      r.x(), r.y(), r.width(), r.height(), x(), y(), width(), height());            //action->hover();              } @@ -224,7 +258,7 @@ bool PopupMenu::event(QEvent* event)  #ifndef POPUP_MENU_DISABLE_AUTO_SCROLL    void PopupMenu::timerHandler()  { -  // printf("PopupMenu::timerHandler\n");   // REMOVE Tim. +  // printf("PopupMenu::timerHandler\n");       //if(!isVisible() || !hasFocus())    if(!isVisible()) @@ -261,9 +295,9 @@ void PopupMenu::popHovered(QAction* action)      QRect r = actionGeometry(action);      //printf("PopupMenu::popHovered x:%d y:%d w:%d h:%d px:%d py:%d pw:%d ph:%d\n",  -    //       r.x(), r.y(), r.width(), r.height(), x(), y(), width(), height());  // REMOVE Tim. +    //       r.x(), r.y(), r.width(), r.height(), x(), y(), width(), height());        //printf("PopupMenu::popHovered x:%d y:%d w:%d h:%d px:%d py:%d pw:%d ph:%d dtw:%d\n",  -    //      r.x(), r.y(), r.width(), r.height(), x(), y(), width(), height(), dw);  // REMOVE Tim. +    //      r.x(), r.y(), r.width(), r.height(), x(), y(), width(), height(), dw);        //int x = r.x() + ctrlSubPop->x();      if(x() + r.x() < 0)        //setGeometry(0, y(), width(), height());       @@ -295,49 +329,20 @@ void PopupMenu::mouseReleaseEvent(QMouseEvent *e)      return;      #else -    if(!_stayOpen) +    // Check for Ctrl to stay open. +    if(!_stayOpen || (!config.popupsDefaultStayOpen && (e->modifiers() & Qt::ControlModifier) == 0))        {        QMenu::mouseReleaseEvent(e);        return;      }   -    //printf("PopupMenu::mouseReleaseEvent\n");  // REMOVE Tim. -     -    //Q_D(QMenu); -    //if (d->mouseEventTaken(e)) -    //    return; - -    //d->mouseDown = false; -    //QAction *action = d->actionAt(e->pos()); +    //printf("PopupMenu::mouseReleaseEvent\n");        QAction *action = actionAt(e->pos()); -     -    //for(QWidget *caused = this; caused;) { -    //    if (QMenu *m = qobject_cast<QMenu*>(caused)) { -    //        QAction *currentAction = d->currentAction; -    //        if(currentAction && (!currentAction->isEnabled() || currentAction->menu() || currentAction->isSeparator())) -    //            currentAction = 0; -    //        caused = m->d_func()->causedPopup.widget; -    //        if (m->d_func()->eventLoop) -    //            m->d_func()->syncAction = currentAction; // synchronous operation -    //    } else { -    //        break; -    //    } -    //} -     -    //if (action && action == d->currentAction) {      if (action && action == activeAction() && !action->isSeparator() && action->isEnabled())  -    { -        //if (action->menu()) -        //    action->menu()->d_func()->setFirstActionActive(); -        //else -            //d->activateAction(action, QAction::Trigger); -            action->activate(QAction::Trigger); -    } +      action->activate(QAction::Trigger);      else  -    //if (d->motions > 6) { -    //    d->hideUpToMenuBar(); -    //  }        QMenu::mouseReleaseEvent(e); +            #endif   // POPUP_MENU_DISABLE_STAY_OPEN   } diff --git a/muse2/muse/widgets/popupmenu.h b/muse2/muse/widgets/popupmenu.h index 47be57ae..e0e7d26f 100644 --- a/muse2/muse/widgets/popupmenu.h +++ b/muse2/muse/widgets/popupmenu.h @@ -60,8 +60,9 @@ class PopupMenu : public QMenu      PopupMenu(const QString& title, QWidget* parent = 0, bool stayOpen = false);      ~PopupMenu();      void clear(); -    QAction* findActionFromData(QVariant) const; +    QAction* findActionFromData(const QVariant&) const;      bool stayOpen() const { return _stayOpen; } +    void clearAllChecks() const;  }; diff --git a/muse2/muse/widgets/routepopup.cpp b/muse2/muse/widgets/routepopup.cpp new file mode 100644 index 00000000..910d693d --- /dev/null +++ b/muse2/muse/widgets/routepopup.cpp @@ -0,0 +1,1416 @@ +//========================================================= +//  MusE +//  Linux Music Editor +// +//  RoutePopupMenu.cpp  +//  (C) Copyright 2011 Tim E. Real (terminator356 A T sourceforge D O T net) +// +//  This program is free software; you can redistribute it and/or modify +//  it under the terms of the GNU General Public License version 2. +// +//  This program is distributed in the hope that it will be useful, +//  but WITHOUT ANY WARRANTY; without even the implied warranty of +//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +//  GNU General Public License for more details. +// +//  You should have received a copy of the GNU General Public License +//  along with this program; if not, write to the Free Software +//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#include "app.h" +#include "routepopup.h" +#include "midiport.h" +#include "mididev.h" +#include "audio.h" +#include "driver/audiodev.h" +#include "song.h" +#include "track.h" +#include "synth.h" +#include "route.h" +#include "icons.h" +#include "menutitleitem.h" +#include "popupmenu.h" + +//--------------------------------------------------------- +//   addMenuItem +//--------------------------------------------------------- + +int RoutePopupMenu::addMenuItem(AudioTrack* track, Track* route_track, PopupMenu* lb, int id, int channel, int channels, bool isOutput) +{ +  // totalInChannels is only used by syntis. +  int toch = ((AudioTrack*)track)->totalOutChannels(); +  // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. +  if(track->channels() == 1) +    toch = 1; +   +  // Don't add the last stray mono route if the track is stereo. +  //if(route_track->channels() > 1 && (channel+1 == chans)) +  //  return id; +     +  RouteList* rl = isOutput ? track->outRoutes() : track->inRoutes(); +   +  QAction* act; +   +  QString s(route_track->name()); +   +  act = lb->addAction(s); +  act->setCheckable(true); +   +  int ach = channel; +  int bch = -1; +   +  Route r(route_track, isOutput ? ach : bch, channels); +   +  r.remoteChannel = isOutput ? bch : ach; +   +  act->setData(qVariantFromValue(r));    +   +  for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir)  +  { +    if(ir->type == Route::TRACK_ROUTE && ir->track == route_track && ir->remoteChannel == r.remoteChannel) +    { +      int tcompch = r.channel; +      if(tcompch == -1) +        tcompch = 0; +      int tcompchs = r.channels; +      if(tcompchs == -1) +        tcompchs = isOutput ? track->channels() : route_track->channels(); +       +      int compch = ir->channel; +      if(compch == -1) +        compch = 0; +      int compchs = ir->channels; +      if(compchs == -1) +        compchs = isOutput ? track->channels() : ir->track->channels(); +       +      if(compch == tcompch && compchs == tcompchs)  +      { +        act->setChecked(true); +        break; +      } +    }   +  } +  return ++id;       +} + +//--------------------------------------------------------- +//   addAuxPorts +//--------------------------------------------------------- + +int RoutePopupMenu::addAuxPorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput) +      { +      AuxList* al = song->auxs(); +      for (iAudioAux i = al->begin(); i != al->end(); ++i) { +            Track* track = *i; +            if (t == track) +                  continue; +            id = addMenuItem(t, track, lb, id, channel, channels, isOutput); +            } +      return id;       +      } + +//--------------------------------------------------------- +//   addInPorts +//--------------------------------------------------------- + +int RoutePopupMenu::addInPorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput) +      { +      InputList* al = song->inputs(); +      for (iAudioInput i = al->begin(); i != al->end(); ++i) { +            Track* track = *i; +            if (t == track) +                  continue; +            id = addMenuItem(t, track, lb, id, channel, channels, isOutput); +            } +      return id;       +      } + +//--------------------------------------------------------- +//   addOutPorts +//--------------------------------------------------------- + +int RoutePopupMenu::addOutPorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput) +      { +      OutputList* al = song->outputs(); +      for (iAudioOutput i = al->begin(); i != al->end(); ++i) { +            Track* track = *i; +            if (t == track) +                  continue; +            id = addMenuItem(t, track, lb, id, channel, channels, isOutput); +            } +      return id;       +      } + +//--------------------------------------------------------- +//   addGroupPorts +//--------------------------------------------------------- + +int RoutePopupMenu::addGroupPorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput) +      { +      GroupList* al = song->groups(); +      for (iAudioGroup i = al->begin(); i != al->end(); ++i) { +            Track* track = *i; +            if (t == track) +                  continue; +            id = addMenuItem(t, track, lb, id, channel, channels, isOutput); +            } +      return id;       +      } + +//--------------------------------------------------------- +//   addWavePorts +//--------------------------------------------------------- + +int RoutePopupMenu::addWavePorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput) +      { +      WaveTrackList* al = song->waves(); +      for (iWaveTrack i = al->begin(); i != al->end(); ++i) { +            Track* track = *i; +            if (t == track) +                  continue; +            id = addMenuItem(t, track, lb, id, channel, channels, isOutput); +            } +      return id;       +      } + +//--------------------------------------------------------- +//   addSyntiPorts +//--------------------------------------------------------- + +int RoutePopupMenu::addSyntiPorts(AudioTrack* t, PopupMenu* lb, int id,  +                         int channel, int channels, bool isOutput) +{ +      RouteList* rl = isOutput ? t->outRoutes() : t->inRoutes(); +       +      QAction* act; +       +      SynthIList* al = song->syntis(); +      for (iSynthI i = al->begin(); i != al->end(); ++i)  +      { +            Track* track = *i; +            if (t == track) +                  continue; +            int toch = ((AudioTrack*)track)->totalOutChannels(); +            // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. +            if(track->channels() == 1) +              toch = 1; +             +            // totalInChannels is only used by syntis. +            int chans = (!isOutput || track->type() != Track::AUDIO_SOFTSYNTH) ? toch : ((AudioTrack*)track)->totalInChannels(); +             +            int tchans = (channels != -1) ? channels: t->channels(); +            if(tchans == 2) +            { +              // Ignore odd numbered left-over mono channel. +              //chans = chans & ~1; +              //if(chans != 0) +                chans -= 1; +            } +             +            if(chans > 0) +            { +              PopupMenu* chpup = new PopupMenu(lb, true); +              chpup->setTitle(track->name()); +              for(int ch = 0; ch < chans; ++ch) +              { +                char buffer[128]; +                if(tchans == 2) +                  snprintf(buffer, 128, "%s %d,%d", chpup->tr("Channel").toLatin1().constData(), ch+1, ch+2); +                else   +                  snprintf(buffer, 128, "%s %d", chpup->tr("Channel").toLatin1().constData(), ch+1); +                act = chpup->addAction(QString(buffer)); +                act->setCheckable(true); +                 +                int ach = (channel == -1) ? ch : channel; +                int bch = (channel == -1) ? -1 : ch; +                 +                Route rt(track, (t->type() != Track::AUDIO_SOFTSYNTH || isOutput) ? ach : bch, tchans); +                rt.remoteChannel = (t->type() != Track::AUDIO_SOFTSYNTH || isOutput) ? bch : ach; +                 +                act->setData(qVariantFromValue(rt));    +                 +                for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir)  +                { +                  if(ir->type == Route::TRACK_ROUTE && ir->track == track && ir->remoteChannel == rt.remoteChannel) +                  { +                    int tcompch = rt.channel; +                    if(tcompch == -1) +                      tcompch = 0; +                    int tcompchs = rt.channels; +                    if(tcompchs == -1) +                      tcompchs = isOutput ? t->channels() : track->channels(); +                     +                    int compch = ir->channel; +                    if(compch == -1) +                      compch = 0; +                    int compchs = ir->channels; +                    if(compchs == -1) +                      compchs = isOutput ? t->channels() : ir->track->channels(); +                     +                    if(compch == tcompch && compchs == tcompchs)  +                    { +                      act->setChecked(true); +                      break; +                    } +                  } +                }   +                ++id; +              } +             +              lb->addMenu(chpup); +            } +      } +      return id;       +} + +//--------------------------------------------------------- +//   addMultiChannelOutPorts +//--------------------------------------------------------- + +int RoutePopupMenu::addMultiChannelPorts(AudioTrack* t, PopupMenu* pup, int id, bool isOutput) +{ +  int toch = t->totalOutChannels(); +  // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. +  if(t->channels() == 1) +    toch = 1; +   +  // Number of allocated buffers is always MAX_CHANNELS or more, even if _totalOutChannels is less.  +  // totalInChannels is only used by syntis. +  int chans = (isOutput || t->type() != Track::AUDIO_SOFTSYNTH) ? toch : t->totalInChannels(); + +  if(chans > 1) +    pup->addAction(new MenuTitleItem("<Mono>", pup));  +   +  // +  // If it's more than one channel, create a sub-menu. If it's just one channel, don't bother with a sub-menu... +  // + +  PopupMenu* chpup = pup; +   +  for(int ch = 0; ch < chans; ++ch) +  { +    // If more than one channel, create the sub-menu. +    if(chans > 1) +      chpup = new PopupMenu(pup, true); +     +    if(isOutput) +    { +      switch(t->type())  +      { +         +        case Track::AUDIO_INPUT: +        case Track::WAVE: +        case Track::AUDIO_GROUP: +        case Track::AUDIO_SOFTSYNTH: +        case Track::AUDIO_AUX:         +              id = addWavePorts(t, chpup, id, ch, 1, isOutput); +              id = addOutPorts(t, chpup, id, ch, 1, isOutput); +              id = addGroupPorts(t, chpup, id, ch, 1, isOutput); +              id = addSyntiPorts(t, chpup, id, ch, 1, isOutput); +              break; +        default: +              break; +      } +    } +    else +    { +      switch(t->type())  +      { +         +        case Track::AUDIO_OUTPUT: +              id = addWavePorts(t, chpup, id, ch, 1, isOutput); +              id = addInPorts(t, chpup, id, ch, 1, isOutput); +              id = addGroupPorts(t, chpup, id, ch, 1, isOutput); +              id = addAuxPorts(t, chpup, id, ch, 1, isOutput); +              id = addSyntiPorts(t, chpup, id, ch, 1, isOutput); +              break; +        case Track::WAVE: +        case Track::AUDIO_SOFTSYNTH: +        case Track::AUDIO_GROUP: +              id = addWavePorts(t, chpup, id, ch, 1, isOutput); +              id = addInPorts(t, chpup, id, ch, 1, isOutput); +              id = addGroupPorts(t, chpup, id, ch, 1, isOutput); +              id = addAuxPorts(t, chpup, id, ch, 1, isOutput);      +              id = addSyntiPorts(t, chpup, id, ch, 1, isOutput); +              break; +        default: +              break; +      } +    } +       +    // If more than one channel, add the created sub-menu. +    if(chans > 1) +    { +      char buffer[128]; +      snprintf(buffer, 128, "%s %d", pup->tr("Channel").toLatin1().constData(), ch+1); +      chpup->setTitle(QString(buffer)); +      pup->addMenu(chpup); +    }   +  }  +        +  // For stereo listing, ignore odd numbered left-over channels. +  chans -= 1; +  if(chans > 0) +  { +    // Ignore odd numbered left-over channels. +    //int schans = (chans & ~1) - 1; +     +    pup->addSeparator(); +    pup->addAction(new MenuTitleItem("<Stereo>", pup)); +   +    // +    // If it's more than two channels, create a sub-menu. If it's just two channels, don't bother with a sub-menu... +    // +     +    chpup = pup; +    if(chans <= 2) +      // Just do one iteration. +      chans = 1; +     +    for(int ch = 0; ch < chans; ++ch) +    { +      // If more than two channels, create the sub-menu. +      if(chans > 2) +        chpup = new PopupMenu(pup, true); +       +      if(isOutput) +      { +        switch(t->type())  +        { +          case Track::AUDIO_INPUT: +          case Track::WAVE: +          case Track::AUDIO_GROUP: +          case Track::AUDIO_SOFTSYNTH: +          case Track::AUDIO_AUX:                                           +                id = addWavePorts(t, chpup, id, ch, 2, isOutput);      +                id = addOutPorts(t, chpup, id, ch, 2, isOutput); +                id = addGroupPorts(t, chpup, id, ch, 2, isOutput); +                id = addSyntiPorts(t, chpup, id, ch, 2, isOutput); +                break; +          default: +                break; +        } +      }     +      else +      { +        switch(t->type())  +        { +          case Track::AUDIO_OUTPUT: +                id = addWavePorts(t, chpup, id, ch, 2, isOutput); +                id = addInPorts(t, chpup, id, ch, 2, isOutput); +                id = addGroupPorts(t, chpup, id, ch, 2, isOutput); +                id = addAuxPorts(t, chpup, id, ch, 2, isOutput); +                id = addSyntiPorts(t, chpup, id, ch, 2, isOutput); +                break; +          case Track::WAVE: +          case Track::AUDIO_SOFTSYNTH: +          case Track::AUDIO_GROUP: +                id = addWavePorts(t, chpup, id, ch, 2, isOutput); +                id = addInPorts(t, chpup, id, ch, 2, isOutput); +                id = addGroupPorts(t, chpup, id, ch, 2, isOutput); +                id = addAuxPorts(t, chpup, id, ch, 2, isOutput);      +                id = addSyntiPorts(t, chpup, id, ch, 2, isOutput); +                break; +          default: +                break; +        } +      } +       +      // If more than two channels, add the created sub-menu. +      if(chans > 2) +      { +        char buffer[128]; +        snprintf(buffer, 128, "%s %d,%d", pup->tr("Channel").toLatin1().constData(), ch+1, ch+2); +        chpup->setTitle(QString(buffer)); +        pup->addMenu(chpup); +      }   +    }  +  } +   +  return id; +} + +//--------------------------------------------------------- +//   nonSyntiTrackAddSyntis +//--------------------------------------------------------- + +int RoutePopupMenu::nonSyntiTrackAddSyntis(AudioTrack* t, PopupMenu* lb, int id, bool isOutput) +{ +      RouteList* rl = isOutput ? t->outRoutes() : t->inRoutes(); +       +      QAction* act; +      SynthIList* al = song->syntis(); +      for (iSynthI i = al->begin(); i != al->end(); ++i)  +      { +            Track* track = *i; +            if (t == track) +                  continue; +             +            int toch = ((AudioTrack*)track)->totalOutChannels(); +            // If track channels = 1, it must be a mono synth. And synti channels cannot be changed by user. +            if(track->channels() == 1) +              toch = 1; +             +            // totalInChannels is only used by syntis. +            int chans = (!isOutput || track->type() != Track::AUDIO_SOFTSYNTH) ? toch : ((AudioTrack*)track)->totalInChannels(); +             +            //int schans = synti->channels(); +            //if(schans < chans) +            //  chans = schans; +//            int tchans = (channels != -1) ? channels: t->channels(); +//            if(tchans == 2) +//            { +              // Ignore odd numbered left-over mono channel. +              //chans = chans & ~1; +              //if(chans != 0) +//                chans -= 1; +//            } +            //int tchans = (channels != -1) ? channels: t->channels(); +             +            if(chans > 0) +            { +              PopupMenu* chpup = new PopupMenu(lb, true); +              chpup->setTitle(track->name()); +              if(chans > 1) +                chpup->addAction(new MenuTitleItem("<Mono>", chpup)); +               +              for(int ch = 0; ch < chans; ++ch) +              { +                char buffer[128]; +                snprintf(buffer, 128, "%s %d", chpup->tr("Channel").toLatin1().constData(), ch+1); +                act = chpup->addAction(QString(buffer)); +                act->setCheckable(true); +                 +                int ach = ch; +                int bch = -1; +                 +                Route rt(track, isOutput ? bch : ach, 1); +                 +                rt.remoteChannel = isOutput ? ach : bch; +                 +                act->setData(qVariantFromValue(rt));    +                 +                for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir)  +                { +                  if(ir->type == Route::TRACK_ROUTE && ir->track == track && ir->remoteChannel == rt.remoteChannel) +                  { +                    int tcompch = rt.channel; +                    if(tcompch == -1) +                      tcompch = 0; +                    int tcompchs = rt.channels; +                    if(tcompchs == -1) +                      tcompchs = isOutput ? t->channels() : track->channels(); +                     +                    int compch = ir->channel; +                    if(compch == -1) +                      compch = 0; +                    int compchs = ir->channels; +                    if(compchs == -1) +                      compchs = isOutput ? t->channels() : ir->track->channels(); +                     +                    if(compch == tcompch && compchs == tcompchs)  +                    { +                      act->setChecked(true); +                      break; +                    } +                  } +                } +                ++id; +              } +             +              chans -= 1; +              if(chans > 0) +              { +                // Ignore odd numbered left-over channels. +                //int schans = (chans & ~1) - 1; +                 +                chpup->addSeparator(); +                chpup->addAction(new MenuTitleItem("<Stereo>", chpup));  +               +                for(int ch = 0; ch < chans; ++ch) +                { +                  char buffer[128]; +                  snprintf(buffer, 128, "%s %d,%d", chpup->tr("Channel").toLatin1().constData(), ch+1, ch+2); +                  act = chpup->addAction(QString(buffer)); +                  act->setCheckable(true); +                   +                  int ach = ch; +                  int bch = -1; +                   +                  Route rt(track, isOutput ? bch : ach, 2); +                   +                  rt.remoteChannel = isOutput ? ach : bch; +                   +                  act->setData(qVariantFromValue(rt));    +                   +                  for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir)  +                  { +                    if(ir->type == Route::TRACK_ROUTE && ir->track == track && ir->remoteChannel == rt.remoteChannel) +                    { +                      int tcompch = rt.channel; +                      if(tcompch == -1) +                        tcompch = 0; +                      int tcompchs = rt.channels; +                      if(tcompchs == -1) +                        tcompchs = isOutput ? t->channels() : track->channels(); +                       +                      int compch = ir->channel; +                      if(compch == -1) +                        compch = 0; +                      int compchs = ir->channels; +                      if(compchs == -1) +                        compchs = isOutput ? t->channels() : ir->track->channels(); +                       +                      if(compch == tcompch && compchs == tcompchs)  +                      { +                        act->setChecked(true); +                        break; +                      } +                    }   +                  } +                  ++id; +                } +              } +               +              lb->addMenu(chpup); +            } +      } +      return id;       +} + +//--------------------------------------------------------- +//   addMidiPorts +//--------------------------------------------------------- + +int RoutePopupMenu::addMidiPorts(AudioTrack* t, PopupMenu* pup, int id, 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; +           +    // Do not list synth devices! +    if(md->isSynti()) +      continue; +           +   RouteList* rl = isOutput ? t->outRoutes() : t->inRoutes(); +     +    PopupMenu* subp = new PopupMenu(pup, true); +    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(ciRoute 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); +       +      int chbit = 1 << ch; +      Route srcRoute(i, chbit);    // In accordance with channel mask, use the bit position. +       +      act->setData(qVariantFromValue(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); +    Route togRoute(i, (1 << MIDI_CHANNELS) - 1);    // Set all channel bits. +    act->setData(qVariantFromValue(togRoute));    +    ++id; +     +    pup->addMenu(subp); +  }     +  return id;       +} + + +//====================== +// RoutePopupMenu +//====================== + +RoutePopupMenu::RoutePopupMenu(QWidget* parent, Track* track, bool isOutput)  +               : _track(track), _isOutMenu(isOutput) +{ +  _pup = new PopupMenu(parent, true); +  init(); +} + +RoutePopupMenu::RoutePopupMenu(const QString& title, QWidget* parent, Track* track, bool isOutput) +               : _track(track), _isOutMenu(isOutput) +{ +  _pup = new PopupMenu(title, parent, true); +  init();         +} + +RoutePopupMenu::~RoutePopupMenu() +{ +  //printf("RoutePopupMenu::~RoutePopupMenu\n");   +  // Make sure to clear which clears and deletes any sub popups. +  _pup->clear(); +  delete _pup; +} + +void RoutePopupMenu::init() +{ +  connect(song, SIGNAL(songChanged(int)), SLOT(songChanged(int))); +} + +void RoutePopupMenu::songChanged(int val) +{ +  if(val & (SC_ROUTE | SC_CHANNELS | SC_CONFIG))      +    updateRouteMenus();              +} + +void RoutePopupMenu::updateRouteMenus()     +{ +  // NOTE: The purpose of this routine is to make sure the items actually reflect +  //  the routing status.  +  // In case for some reason a route could not be added (or removed).  +  // Then the item will be properly un-checked (or checked) here. +   +  //printf("RoutePopupMenu::updateRouteMenus\n");   +   +  if(!_track || !_pup || _pup->actions().isEmpty() || !_pup->isVisible())   +    return; +     +  RouteList* rl = _isOutMenu ? _track->outRoutes() : _track->inRoutes(); + +  // Clear all the action check marks. +  _pup->clearAllChecks();     +     +  // Take care of Midi Port to Audio Input routes first...   +  if(_isOutMenu && _track->isMidiTrack()) +  { +    int port = ((MidiTrack*)_track)->outPort(); +    if(port >= 0 && port < MIDI_PORTS) +    { +      MidiPort* mp = &midiPorts[port]; +      RouteList* mprl = mp->outRoutes(); +      for (ciRoute ir = mprl->begin(); ir != mprl->end(); ++ir)  +      { +        if(ir->type == Route::TRACK_ROUTE && ir->track && ir->track->type() == Track::AUDIO_INPUT) +        { +          for(int ch = 0; ch < MIDI_CHANNELS; ++ch) +          { +            int chbits = 1 << ch; +            if(ir->channel & chbits) +            { +              Route r(ir->track, chbits); +              //printf("RoutePopupMenu::updateRouteMenus MidiPort to AudioInput chbits:%d\n", chbits);   +              QAction* act = _pup->findActionFromData(qVariantFromValue(r));   +              if(act) +                act->setChecked(true); +            }   +          }   +        }   +      }   +    } +  } + +  // Now check the ones that are found in the route list. +  for(ciRoute irl = rl->begin(); irl != rl->end(); ++irl)  +  { +    // Do MidiTrack to MidiPort routes... +    if(irl->type == Route::MIDI_PORT_ROUTE) +    { +      //printf("RoutePopupMenu::updateRouteMenus MIDI_PORT_ROUTE\n");   +      for(int ch = 0; ch < MIDI_CHANNELS; ++ch) +      { +        int chbits = 1 << ch; +        if(irl->channel & chbits) +        { +          Route r(irl->midiPort, chbits); +          QAction* act = _pup->findActionFromData(qVariantFromValue(r));   +          if(act) +            act->setChecked(true); +        }     +      }     +    } +    else +    // Do all other routes... +    { +      //printf("RoutePopupMenu::updateRouteMenus other irl type:%d\n", irl->type);   +      QAction* act = _pup->findActionFromData(qVariantFromValue(*irl));   +      if(act) +        act->setChecked(true); +    } +  } +}       + +void RoutePopupMenu::popupActivated(QAction* action) +{ +      if(!action || !_track || !_pup || _pup->actions().isEmpty()) +        return; +         +      if(_track->isMidiTrack()) +      { +        RouteList* rl = _isOutMenu ? _track->outRoutes() : _track->inRoutes(); +         +        // Take care of Route data items first... +        if(qVariantCanConvert<Route>(action->data()))     +        { +          Route aRoute = action->data().value<Route>(); +           +          // Support Midi Port to Audio Input track routes.  +          if(aRoute.type == Route::TRACK_ROUTE && aRoute.track && aRoute.track->type() == Track::AUDIO_INPUT) +          { +            //if(gIsOutRoutingPopupMenu)    // Try to avoid splitting like this.  +            { +              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; +               +              Route bRoute(port, chbit); +               +              int chmask = 0;                    +              RouteList* mprl = _isOutMenu ? mp->outRoutes() : mp->inRoutes(); +              ciRoute 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 ((chmask & chbit) == chbit)             // Is the channel's bit(s) set? +              { +                // disconnect +                if(_isOutMenu) +                  audio->msgRemoveRoute(bRoute, aRoute); +                else +                  audio->msgRemoveRoute(aRoute, bRoute); +              } +              else  +              { +                // connect +                if(_isOutMenu) +                  audio->msgAddRoute(bRoute, aRoute); +                else +                  audio->msgAddRoute(aRoute, bRoute); +              } +               +              audio->msgUpdateSoloStates(); +              song->update(SC_ROUTE); +               +            } +            return; +          } +          else if(aRoute.type == Route::MIDI_PORT_ROUTE) +          { +            int chbit = aRoute.channel; +            Route bRoute(_track, chbit); +            int mdidx = aRoute.midiPort; +     +            MidiPort* mp = &midiPorts[mdidx]; +            MidiDevice* md = mp->device(); +            //if(!md)    // Rem. Allow connections to ports with no device. +            //  return; +             +            //if(!(md->rwFlags() & 2)) +            //if(!(md->rwFlags() & (gIsOutRoutingPopupMenu ? 1 : 2))) +            if(md && !(md->rwFlags() & (_isOutMenu ? 1 : 2)))    +              return; +             +            int chmask = 0;                    +            ciRoute 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? +            { +              // disconnect +              if(_isOutMenu) +                audio->msgRemoveRoute(bRoute, aRoute); +              else +                audio->msgRemoveRoute(aRoute, bRoute); +            } +            else  +            { +              // connect +              if(_isOutMenu) +                audio->msgAddRoute(bRoute, aRoute); +              else +                audio->msgAddRoute(aRoute, bRoute); +            } +             +            audio->msgUpdateSoloStates(); +            song->update(SC_ROUTE); +          }   +        }   +        else +        // ... now take care of integer data items. +        if(qVariantCanConvert<int>(action->data()))     +        { +          int n = action->data().value<int>(); +          if(!_isOutMenu && n == 0) +            muse->configMidiPorts(); +          return;   +        } +      } +      else +      { +        AudioTrack* t = (AudioTrack*)_track; +        RouteList* rl = _isOutMenu ? t->outRoutes() : t->inRoutes(); +         +        if(!qVariantCanConvert<Route>(action->data()))     +          return;   +           +        if(_isOutMenu) +        {   +          Route dstRoute = action->data().value<Route>();              +          Route srcRoute(t, dstRoute.channel, dstRoute.channels);     +          srcRoute.remoteChannel = dstRoute.remoteChannel; +   +          // check if route src->dst exists: +          ciRoute 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 = action->data().value<Route>();              +           +          // Support Midi Port to Audio Input routes.  +          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;                    +            ciRoute 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("routingPopupMenuActivated: removing src route ch:%d dst route ch:%d\n", srcRoute.channel, dstRoute.channel);  +              audio->msgRemoveRoute(srcRoute, dstRoute); +            } +            else  +            { +              //printf("routingPopupMenuActivated: 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, srcRoute.channel, srcRoute.channels);      +          dstRoute.remoteChannel = srcRoute.remoteChannel; +   +          ciRoute 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); +        } +         +        +      } +      //else +      //{ +      //} +} + +void RoutePopupMenu::prepare() +{ +  _pup->disconnect(); +  _pup->clear(); +    +  if(!_track) +    return; +    +  connect(_pup, SIGNAL(triggered(QAction*)), SLOT(popupActivated(QAction*))); +   +  if(_track->isMidiTrack()) +  { +    RouteList* rl = _isOutMenu ? _track->outRoutes() : _track->inRoutes(); +     +    int gid = 0; +    QAction* act = 0; +     +    if(_isOutMenu)    +    { +      // Support Midi Port to Audio Input track routes.  +      int port = ((MidiTrack*)_track)->outPort(); +      if(port >= 0 && port < MIDI_PORTS) +      { +        MidiPort* mp = &midiPorts[port]; +         +        // Do not list synth devices! Requiring valid device 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(mp->device() && !mp->device()->isSynti())   +        { +          RouteList* mprl = mp->outRoutes(); +          int chbits = 1 << ((MidiTrack*)_track)->outChannel(); +          //MidiDevice* md = mp->device(); +          //if(!md) +          //  continue; +           +          _pup->addSeparator(); +          _pup->addAction(new MenuTitleItem(tr("Soloing chain"), _pup));  +          PopupMenu* subp = new PopupMenu(_pup, true); +          subp->setTitle(tr("Audio returns"));  +          _pup->addMenu(subp); +           +          InputList* al = song->inputs(); +          for (ciAudioInput i = al->begin(); i != al->end(); ++i)  +          { +            Track* t = *i; +            QString s(t->name()); +            act = subp->addAction(s); +            act->setCheckable(true); +            Route r(t, chbits); +            act->setData(qVariantFromValue(r));    +            for(ciRoute 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 +    { +      // Warn if no devices available. Add an item to open midi config.  +      int pi = 0; +      for( ; pi < MIDI_PORTS; ++pi) +      { +        MidiDevice* md = midiPorts[pi].device(); +        if(md && !md->isSynti() && (md->rwFlags() & 2)) +          break; +      } +      if(pi == MIDI_PORTS) +      { +        act = _pup->addAction(tr("Warning: No midi input devices!")); +        act->setCheckable(false); +        act->setData(-1); +        _pup->addSeparator(); +      } +      act = _pup->addAction(QIcon(*settings_midiport_softsynthsIcon), tr("Open midi config...")); +      act->setCheckable(false); +      act->setData(gid); +      _pup->addSeparator(); +      ++gid; +       +      _pup->addAction(new MenuTitleItem("Midi input ports", _pup));  +       +      for(int i = 0; i < MIDI_PORTS; ++i) +      { +        // NOTE: Could possibly list all devices, bypassing ports, but no, let's stick with ports. +        MidiPort* mp = &midiPorts[i]; +        MidiDevice* md = mp->device(); +        //if(!md) +        //  continue; +         +        // Do not list synth devices! +        if(md && md->isSynti()) +          continue; +           +        if(md && !(md->rwFlags() & 2)) +          continue; +           +        //printf("MusE::prepareRoutingPopupMenu adding submenu portnum:%d\n", i); +         +        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. +        ciRoute ir = rl->begin(); +        for( ; 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; +          } +        } +        // List ports with no device, but with routes to this track, in the main popup. +        if(!md && ir == rl->end()) +          continue; +         +        PopupMenu* subp = new PopupMenu(_pup, true); +        subp->setTitle(QString("%1:").arg(i+1) + (md ? md->name() : tr("<none>")));  +         +        for(int ch = 0; ch < MIDI_CHANNELS; ++ch)  +        { +          act = subp->addAction(QString("Channel %1").arg(ch+1)); +          act->setCheckable(true); +          int chbit = 1 << ch; +          Route srcRoute(i, chbit);    // In accordance with channel mask, use the bit position. +          act->setData(qVariantFromValue(srcRoute));    +          if(chanmask & chbit)                  // Is the channel already set? Show item check mark. +            act->setChecked(true); +          ++gid;   +        } +        //gid = MIDI_PORTS * MIDI_CHANNELS + i;           // Make sure each 'toggle' item gets a unique id. +        act = subp->addAction(tr("Toggle all")); +        //act->setCheckable(true); +        Route togRoute(i, (1 << MIDI_CHANNELS) - 1);    // Set all channel bits. +        act->setData(qVariantFromValue(togRoute));    +        ++gid; +        _pup->addMenu(subp); +      } +       +      #if 0 +      // p4.0.17 List ports with no device and no in routes, in a separate popup. +      PopupMenu* morep = new PopupMenu(pup, true); +      morep->setTitle(tr("More..."));  +      for(int i = 0; i < MIDI_PORTS; ++i) +      { +        MidiPort* mp = &midiPorts[i]; +        if(mp->device()) +          continue; +         +        PopupMenu* subp = new PopupMenu(morep, true); +        subp->setTitle(QString("%1:").arg(i) + tr("<none>"));  +         +        // MusE-2: Check this - needed with QMenu? Help says no. No - verified, it actually causes double triggers! +        //connect(subp, SIGNAL(triggered(QAction*)), pup, SIGNAL(triggered(QAction*))); +        //connect(subp, SIGNAL(aboutToHide()), pup, SIGNAL(aboutToHide())); +         +        iRoute ir = rl->begin(); +        for( ; ir != rl->end(); ++ir)    +        { +          if(ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == i)  +            break; +        } +        if(ir != rl->end()) +          continue; +         +        for(int ch = 0; ch < MIDI_CHANNELS; ++ch)  +        { +          act = subp->addAction(QString("Channel %1").arg(ch+1)); +          act->setCheckable(true); +          act->setData(gid); +           +          int chbit = 1 << ch; +          Route srcRoute(i, chbit);    // In accordance with new channel mask, use the bit position. +           +          gRoutingMenuMap.insert( pRouteMenuMap(gid, srcRoute) ); +           +          //if(chanmask & chbit)                  // Is the channel already set? Show item check mark. +          //  act->setChecked(true); +           +          ++gid;   +        } +        //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; +        morep->addMenu(subp); +      }       +      pup->addMenu(morep); +      #endif +       +    } +    return; +  } +  else +  { +    AudioTrack* t = (AudioTrack*)_track; +    int channel = t->channels(); +    if(_isOutMenu)    +    { +      RouteList* orl = t->outRoutes(); + +      QAction* act = 0; +      int gid = 0; +      gid = 0; +       +      switch(_track->type())  +      { +        case Track::AUDIO_OUTPUT: +        { +          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); +            _pup->addAction(titel);  +   +            if(!checkAudioDevice()) +            {  +              _pup->clear(); +              return; +            } +            std::list<QString> ol = audioDevice->inputPorts(); +            for(std::list<QString>::iterator ip = ol.begin(); ip != ol.end(); ++ip)  +            { +              act = _pup->addAction(*ip); +              act->setCheckable(true); +               +              Route dst(*ip, true, i, Route::JACK_ROUTE); +              act->setData(qVariantFromValue(dst));    +              ++gid; +              for(ciRoute ir = orl->begin(); ir != orl->end(); ++ir)  +              { +                if(*ir == dst)  +                { +                  act->setChecked(true); +                  break; +                } +              } +            } +            if(i+1 != channel) +              _pup->addSeparator(); +          }       +           +          // +          // Display using separate menu for audio inputs: +          // +          _pup->addSeparator(); +          _pup->addAction(new MenuTitleItem(tr("Soloing chain"), _pup));  +          PopupMenu* subp = new PopupMenu(_pup, true); +          subp->setTitle(tr("Audio returns"));  +          _pup->addMenu(subp); +          gid = addInPorts(t, subp, gid, -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, -1, -1, true);   +        } +        break; +        case Track::AUDIO_SOFTSYNTH: +              gid = addMultiChannelPorts(t, _pup, gid, true); +        break; +         +        case Track::AUDIO_INPUT: +        case Track::WAVE: +        case Track::AUDIO_GROUP: +        case Track::AUDIO_AUX: +              gid = addWavePorts(        t, _pup, gid, -1, -1, true);   +              gid = addOutPorts(         t, _pup, gid, -1, -1, true); +              gid = addGroupPorts(       t, _pup, gid, -1, -1, true); +              gid = nonSyntiTrackAddSyntis(t, _pup, gid, true); +        break; +        default: +              _pup->clear(); +              return; +      } +    } +    else +    { +      if(_track->type() == Track::AUDIO_AUX) +        return; +         +      RouteList* irl = t->inRoutes(); +   +      QAction* act = 0; +      int gid = 0; +      gid = 0; +       +      switch(_track->type())  +      { +        case Track::AUDIO_INPUT: +        { +          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); +            _pup->addAction(titel);  +   +            if(!checkAudioDevice()) +            {  +              _pup->clear(); +              return; +            } +            std::list<QString> ol = audioDevice->outputPorts(); +            for(std::list<QString>::iterator ip = ol.begin(); ip != ol.end(); ++ip)  +            { +              act = _pup->addAction(*ip); +              act->setCheckable(true); +               +              Route dst(*ip, true, i, Route::JACK_ROUTE); +              act->setData(qVariantFromValue(dst));    +              ++gid; +              for(ciRoute ir = irl->begin(); ir != irl->end(); ++ir)  +              { +                if(*ir == dst)  +                { +                  act->setChecked(true); +                  break; +                } +              } +            } +            if(i+1 != channel) +              _pup->addSeparator(); +          } +           +          // +          // 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, true); +          subp->setTitle(tr("Audio sends"));  +          _pup->addMenu(subp); +          gid = addOutPorts(t, subp, gid, -1, -1, false);   +          subp = new PopupMenu(_pup, true); +          subp->setTitle(tr("Midi port sends"));  +          _pup->addMenu(subp); +          addMidiPorts(t, subp, gid, false); +          // +          // Display all in the same menu: +          // +          //_pup->addAction(new MenuTitleItem(tr("Audio sends"), _pup));  +          //gid = addOutPorts(t, _pup, gid, -1, -1, false);   +          //_pup->addSeparator(); +          //_pup->addAction(new MenuTitleItem(tr("Midi sends"), _pup));  +          //addMidiPorts(t, _pup, gid, false); +        } +        break; +        case Track::AUDIO_OUTPUT: +              gid = addWavePorts( t, _pup, gid, -1, -1, false); +              gid = addInPorts(   t, _pup, gid, -1, -1, false); +              gid = addGroupPorts(t, _pup, gid, -1, -1, false); +              gid = addAuxPorts(  t, _pup, gid, -1, -1, false); +              gid = nonSyntiTrackAddSyntis(t, _pup, gid, false); +              break; +        case Track::WAVE: +              gid = addWavePorts( t, _pup, gid, -1, -1, false);   +              gid = addInPorts(   t, _pup, gid, -1, -1, false); +              gid = addGroupPorts(t, _pup, gid, -1, -1, false);   +              gid = addAuxPorts(  t, _pup, gid, -1, -1, false);   +              gid = nonSyntiTrackAddSyntis(t, _pup, gid, false);  +              break; +        case Track::AUDIO_GROUP: +              gid = addWavePorts( t, _pup, gid, -1, -1, false); +              gid = addInPorts(   t, _pup, gid, -1, -1, false); +              gid = addGroupPorts(t, _pup, gid, -1, -1, false); +              gid = addAuxPorts(  t, _pup, gid, -1, -1, false);   +              gid = nonSyntiTrackAddSyntis(t, _pup, gid, false); +              break; +         +        case Track::AUDIO_SOFTSYNTH: +              gid = addMultiChannelPorts(t, _pup, gid, false); +              break; +        default: +              _pup->clear(); +              return; +      }   +    }   +  } +} + +void RoutePopupMenu::exec(Track* track, bool isOutput) +{ +  if(track) +  { +    _track = track; +    _isOutMenu = isOutput; +  }   +  prepare(); +  _pup->exec(); +} + +void RoutePopupMenu::exec(const QPoint& p, Track* track, bool isOutput) +{ +  if(track) +  { +    _track = track; +    _isOutMenu = isOutput; +  }   +  prepare(); +  _pup->exec(p); +} + +void RoutePopupMenu::popup(const QPoint& p, Track* track, bool isOutput) +{ +  if(track) +  { +    _track = track; +    _isOutMenu = isOutput; +  }   +  prepare(); +  _pup->popup(p); +} + diff --git a/muse2/muse/widgets/routepopup.h b/muse2/muse/widgets/routepopup.h new file mode 100644 index 00000000..6772e8ca --- /dev/null +++ b/muse2/muse/widgets/routepopup.h @@ -0,0 +1,73 @@ +//========================================================= +//  MusE +//  Linux Music Editor +// +//  RoutePopupMenu.h  +//  (C) Copyright 2011 Tim E. Real (terminator356 A T sourceforge D O T net) +// +//  This program is free software; you can redistribute it and/or modify +//  it under the terms of the GNU General Public License version 2. +// +//  This program is distributed in the hope that it will be useful, +//  but WITHOUT ANY WARRANTY; without even the implied warranty of +//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +//  GNU General Public License for more details. +// +//  You should have received a copy of the GNU General Public License +//  along with this program; if not, write to the Free Software +//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#ifndef __ROUTEPOPUPMENU_H__ +#define __ROUTEPOPUPMENU_H__ + +#include <QObject> + +class Track; +class AudioTrack; +class PopupMenu; +class QWidget; +class QString; +class QAction; +class QPoint; + +class RoutePopupMenu : public QObject +{ +  Q_OBJECT +   +    PopupMenu* _pup; +    Track* _track; +    // Whether the route popup was shown by clicking the output routes button, or input routes button. +    bool _isOutMenu; +     +    void init(); +    void prepare(); +     +    int addMenuItem(AudioTrack* track, Track* route_track, PopupMenu* lb, int id, int channel,  +                    int channels, bool isOutput); +    int addAuxPorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput); +    int addInPorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput); +    int addOutPorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput); +    int addGroupPorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput); +    int addWavePorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput); +    int addSyntiPorts(AudioTrack* t, PopupMenu* lb, int id, int channel, int channels, bool isOutput); +    int addMultiChannelPorts(AudioTrack* t, PopupMenu* pup, int id, bool isOutput); +    int nonSyntiTrackAddSyntis(AudioTrack* t, PopupMenu* lb, int id, bool isOutput); +    int addMidiPorts(AudioTrack* t, PopupMenu* pup, int id, bool isOutput); +     +  private slots: +    void popupActivated(QAction*); +    void songChanged(int); +   +  public: +    RoutePopupMenu(QWidget* parent = 0, Track* track = 0, bool isOutput = false); +    RoutePopupMenu(const QString& title, QWidget* parent = 0, Track* track = 0, bool isOutput = false); +    ~RoutePopupMenu(); +     +    void updateRouteMenus(); +    void exec(Track* track = 0, bool isOutput = false); +    void exec(const QPoint& p, Track* track = 0, bool isOutput = false); +    void popup(const QPoint& p, Track* track = 0, bool isOutput = false); +}; + +#endif | 
