summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse2/ChangeLog9
-rw-r--r--muse2/muse/arranger/trackinfo.cpp11
-rw-r--r--muse2/muse/conf.cpp69
-rw-r--r--muse2/muse/confmport.cpp53
-rw-r--r--muse2/muse/midiport.cpp5
-rw-r--r--muse2/muse/midiport.h7
-rw-r--r--muse2/muse/song.cpp61
-rw-r--r--muse2/muse/sync.cpp16
-rw-r--r--muse2/muse/sync.h1
-rw-r--r--muse2/muse/widgets/mtrackinfobase.ui12
10 files changed, 208 insertions, 36 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index c51dd3b1..8a7579d8 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -1,3 +1,12 @@
+11.12.2010:
+ * Feature: Added default midi track in/out channels to midi ports list. (Tim)
+ - For now, the boxes use the old text channel strings ("1 3 5", "1-5", "all, "none" etc.)
+ * Changed: Experimental: Mid ports now default to 'GM' instrument. (Tim)
+ - Was stopping new users from seeing instrument patches etc.
+ - TODO: Overhaul instrument type, instrument sysexes, and song type.
+ * Changed: Audio groups and inputs no longer default connect to first audio out. (Tim)
+ - Find it tedious, once a song grows with groups and inputs, to keep disconnecting them from output.
+ - TODO: Add a better audio default routing system.
10.12.2010:
- More compiler and build warnings fixes. (Orcan)
- Restored the scripts menu and fixed scripts handling. Tested OK. (Orcan)
diff --git a/muse2/muse/arranger/trackinfo.cpp b/muse2/muse/arranger/trackinfo.cpp
index 13197f50..20673b25 100644
--- a/muse2/muse/arranger/trackinfo.cpp
+++ b/muse2/muse/arranger/trackinfo.cpp
@@ -1192,10 +1192,12 @@ void Arranger::genMidiTrackInfo()
//midiTrackInfo->iChanDetectLabel->setPixmap(*darkgreendotIcon);
midiTrackInfo->iChanDetectLabel->setPixmap(*darkRedLedIcon);
- QIcon recEchoIconSet;
- recEchoIconSet.addPixmap(*recEchoIconOn, QIcon::Normal, QIcon::On);
- recEchoIconSet.addPixmap(*recEchoIconOff, QIcon::Normal, QIcon::Off);
- midiTrackInfo->recEchoButton->setIcon(recEchoIconSet);
+ //QIcon recEchoIconSet;
+ //recEchoIconSet.addPixmap(*recEchoIconOn, QIcon::Normal, QIcon::On);
+ //recEchoIconSet.addPixmap(*recEchoIconOff, QIcon::Normal, QIcon::Off);
+ //midiTrackInfo->recEchoButton->setIcon(recEchoIconSet);
+ midiTrackInfo->recEchoButton->setIcon(QIcon(*edit_midiIcon));
+ midiTrackInfo->recEchoButton->setIconSize(edit_midiIcon->size());
// MusE-2: AlignCenter and WordBreak are set in the ui(3) file, but not supported by QLabel. Turn them on here.
@@ -1258,6 +1260,7 @@ void Arranger::genMidiTrackInfo()
// TODO: Works OK, but disabled for now, until we figure out what to do about multiple out routes and display values...
midiTrackInfo->oRButton->setEnabled(false);
+ midiTrackInfo->oRButton->setVisible(false);
connect(midiTrackInfo->oRButton, SIGNAL(pressed()), SLOT(outRoutesPressed()));
connect(heartBeatTimer, SIGNAL(timeout()), SLOT(midiTrackInfoHeartBeat()));
diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp
index 9ab9e594..315ce9cd 100644
--- a/muse2/muse/conf.cpp
+++ b/muse2/muse/conf.cpp
@@ -200,9 +200,20 @@ static void readConfigMidiPort(Xml& xml)
{
int idx = 0;
QString device;
- QString instrument;
+
+ //QString instrument;
+ // Changed by Tim.
+ //QString instrument("generic midi");
+ // Let's be bold. New users have been confused by generic midi not enabling any patches and controllers.
+ // I had said this may cause HW problems by sending out GM sysEx when really the HW might not be GM.
+ // But this really needs to be done, one way or another.
+ // FIXME: TODO: Make this user-configurable!
+ QString instrument("GM");
+
int openFlags = 1;
bool thruFlag = false;
+ int dic = 0;
+ int doc = 0;
MidiSyncInfo tmpSi;
int type = MidiDevice::ALSA_MIDI;
@@ -224,13 +235,18 @@ static void readConfigMidiPort(Xml& xml)
}
else if (tag == "openFlags")
openFlags = xml.parseInt();
+ else if (tag == "defaultInChans")
+ dic = xml.parseInt();
+ else if (tag == "defaultOutChans")
+ doc = xml.parseInt();
else if (tag == "midiSyncInfo")
tmpSi.read(xml);
else if (tag == "instrument") {
instrument = xml.parse1();
- midiPorts[idx].setInstrument(
- registerMidiInstrument(instrument)
- );
+ // Moved by Tim.
+ //midiPorts[idx].setInstrument(
+ // registerMidiInstrument(instrument)
+ // );
}
else if (tag == "midithru")
thruFlag = xml.parseInt(); // obsolete
@@ -271,6 +287,11 @@ static void readConfigMidiPort(Xml& xml)
fprintf(stderr, "readConfigMidiPort: device not found %s\n", device.toLatin1().constData());
MidiPort* mp = &midiPorts[idx];
+
+ mp->setInstrument(registerMidiInstrument(instrument)); // By Tim.
+ mp->setDefaultInChannels(dic);
+ mp->setDefaultOutChannels(doc);
+
mp->syncInfo().copyParams(tmpSi);
// p3.3.50 Indicate the port was found in the song file, even if no device is assigned to it.
mp->setFoundInSongFile(true);
@@ -946,20 +967,42 @@ static void writeSeqConfiguration(int level, Xml& xml, bool writePortInfo)
//
for (int i = 0; i < MIDI_PORTS; ++i) {
bool used = false;
- MidiTrackList* tl = song->midis();
- for (iMidiTrack it = tl->begin(); it != tl->end(); ++it) {
- MidiTrack* t = *it;
- if (t->outPort() == i) {
- used = true;
- break;
- }
- }
MidiPort* mport = &midiPorts[i];
+ // Route check by Tim. Port can now be used for routing even if no device.
+ // Also, check for other non-defaults and save port, to preserve settings even if no device.
+ if(!mport->noInRoute() || !mport->noOutRoute() ||
+ mport->defaultInChannels() || mport->defaultOutChannels() ||
+ (!mport->instrument()->iname().isEmpty() && mport->instrument()->iname() != "GM") ||
+ !mport->syncInfo().isDefault())
+ used = true;
+ else
+ {
+ MidiTrackList* tl = song->midis();
+ for (iMidiTrack it = tl->begin(); it != tl->end(); ++it)
+ {
+ MidiTrack* t = *it;
+ if (t->outPort() == i)
+ {
+ used = true;
+ break;
+ }
+ }
+ }
+
MidiDevice* dev = mport->device();
if (!used && !dev)
continue;
xml.tag(level++, "midiport idx=\"%d\"", i);
- xml.strTag(level, "instrument", mport->instrument()->iname());
+
+ if(mport->defaultInChannels())
+ xml.intTag(level, "defaultInChans", mport->defaultInChannels());
+ if(mport->defaultOutChannels())
+ xml.intTag(level, "defaultOutChans", mport->defaultOutChannels());
+
+ if(!mport->instrument()->iname().isEmpty() && // Tim.
+ (mport->instrument()->iname() != "GM")) // FIXME: TODO: Make this user configurable.
+ xml.strTag(level, "instrument", mport->instrument()->iname());
+
if (dev) {
xml.strTag(level, "name", dev->name());
diff --git a/muse2/muse/confmport.cpp b/muse2/muse/confmport.cpp
index 203e0a63..30318f03 100644
--- a/muse2/muse/confmport.cpp
+++ b/muse2/muse/confmport.cpp
@@ -36,13 +36,15 @@
#include "driver/jackmidi.h"
#include "audiodev.h"
#include "menutitleitem.h"
+#include "utils.h"
extern std::vector<Synth*> synthis;
enum { DEVCOL_NO = 0, DEVCOL_GUI, DEVCOL_REC, DEVCOL_PLAY, DEVCOL_INSTR, DEVCOL_NAME,
//DEVCOL_STATE };
//DEVCOL_ROUTES, DEVCOL_STATE };
- DEVCOL_INROUTES, DEVCOL_OUTROUTES, DEVCOL_STATE }; // p3.3.55
+ //DEVCOL_INROUTES, DEVCOL_OUTROUTES, DEVCOL_STATE }; // p3.3.55
+ DEVCOL_INROUTES, DEVCOL_OUTROUTES, DEVCOL_DEF_IN_CHANS, DEVCOL_DEF_OUT_CHANS, DEVCOL_STATE };
//---------------------------------------------------------
// mdevViewItemRenamed
@@ -57,6 +59,26 @@ void MPConfig::mdevViewItemRenamed(QTableWidgetItem* item)
return;
switch(col)
{
+ case DEVCOL_DEF_IN_CHANS:
+ {
+ QString id = item->tableWidget()->item(item->row(), DEVCOL_NO)->text();
+ int no = atoi(id.toLatin1().constData()) - 1;
+ if(no < 0 || no >= MIDI_PORTS)
+ return;
+ midiPorts[no].setDefaultInChannels(string2bitmap(s));
+ song->update();
+ }
+ break;
+ case DEVCOL_DEF_OUT_CHANS:
+ {
+ QString id = item->tableWidget()->item(item->row(), DEVCOL_NO)->text();
+ int no = atoi(id.toLatin1().constData()) - 1;
+ if(no < 0 || no >= MIDI_PORTS)
+ return;
+ midiPorts[no].setDefaultOutChannels(string2bitmap(s));
+ song->update();
+ }
+ break;
case DEVCOL_NAME:
{
QString id = item->tableWidget()->item(item->row(), DEVCOL_NO)->text();
@@ -358,6 +380,13 @@ void MPConfig::rbClicked(QTableWidgetItem* item)
//break;
return;
+ case DEVCOL_DEF_IN_CHANS:
+ case DEVCOL_DEF_OUT_CHANS:
+ {
+ }
+ //break;
+ return;
+
case DEVCOL_NAME:
{
//printf("MPConfig::rbClicked DEVCOL_NAME\n");
@@ -623,6 +652,8 @@ void MPConfig::setToolTip(QTableWidgetItem *item, int col)
//case DEVCOL_ROUTES: item->setToolTip(tr("Jack midi ports")); break;
case DEVCOL_INROUTES: item->setToolTip(tr("Connections from Jack Midi outputs")); break;
case DEVCOL_OUTROUTES: item->setToolTip(tr("Connections to Jack Midi inputs")); break;
+ case DEVCOL_DEF_IN_CHANS: item->setToolTip(tr("Connect these to new midi tracks")); break;
+ case DEVCOL_DEF_OUT_CHANS: item->setToolTip(tr("Connect new midi tracks to this (first listed only)")); break;
case DEVCOL_STATE: item->setToolTip(tr("Device state")); break;
default: return;
}
@@ -654,6 +685,18 @@ void MPConfig::setWhatsThis(QTableWidgetItem *item, int col)
item->setWhatsThis(tr("Connections from Jack Midi output ports")); break;
case DEVCOL_OUTROUTES:
item->setWhatsThis(tr("Connections to Jack Midi input ports")); break;
+ case DEVCOL_DEF_IN_CHANS:
+ item->setWhatsThis(tr("Connect these channels, on this port, to new midi tracks.\n"
+ "Example:\n"
+ " 1 2 3 channel 1 2 and 3\n"
+ " 1-3 same\n"
+ " 1-3 5 channel 1 2 3 and 5\n"
+ " all all channels\n"
+ " none no channels")); break;
+ case DEVCOL_DEF_OUT_CHANS:
+ item->setWhatsThis(tr("Connect new midi tracks to these channels, on this port.\n"
+ "See default in channels.\n"
+ "NOTE: Currently only one output port and channel supported (first found)")); break;
case DEVCOL_STATE:
item->setWhatsThis(tr("State: result of opening the device")); break;
default:
@@ -700,6 +743,8 @@ MPConfig::MPConfig(QWidget* parent)
<< tr("Device Name")
<< tr("In routes")
<< tr("Out routes")
+ << tr("Def in ch")
+ << tr("Def out ch")
<< tr("State");
mdevView->setColumnCount(columnnames.size());
@@ -804,6 +849,12 @@ void MPConfig::songChanged(int flags)
QTableWidgetItem* itemin = new QTableWidgetItem;
addItem(i, DEVCOL_INROUTES, itemin, mdevView);
itemin->setFlags(Qt::ItemIsEnabled);
+ QTableWidgetItem* itemdefin = new QTableWidgetItem(bitmap2String(port->defaultInChannels()));
+ addItem(i, DEVCOL_DEF_IN_CHANS, itemdefin, mdevView);
+ itemdefin->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled);
+ QTableWidgetItem* itemdefout = new QTableWidgetItem(bitmap2String(port->defaultOutChannels()));
+ addItem(i, DEVCOL_DEF_OUT_CHANS, itemdefout, mdevView);
+ itemdefout->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled);
mdevView->blockSignals(false);
diff --git a/muse2/muse/midiport.cpp b/muse2/muse/midiport.cpp
index c6601591..0df08a59 100644
--- a/muse2/muse/midiport.cpp
+++ b/muse2/muse/midiport.cpp
@@ -37,7 +37,8 @@ void initMidiPorts()
{
for (int i = 0; i < MIDI_PORTS; ++i) {
MidiPort* port = &midiPorts[i];
- port->setInstrument(genericMidiInstrument);
+ ///port->setInstrument(genericMidiInstrument);
+ port->setInstrument(registerMidiInstrument("GM")); // Changed by Tim.
port->syncInfo().setPort(i);
}
}
@@ -49,6 +50,8 @@ void initMidiPorts()
MidiPort::MidiPort()
: _state("not configured")
{
+ _defaultInChannels = 0;
+ _defaultOutChannels = 0;
_device = 0;
_instrument = 0;
_controller = new MidiCtrlValListList();
diff --git a/muse2/muse/midiport.h b/muse2/muse/midiport.h
index 5ba08d67..7ee83cc9 100644
--- a/muse2/muse/midiport.h
+++ b/muse2/muse/midiport.h
@@ -36,6 +36,9 @@ class MidiPort {
MidiSyncInfo _syncInfo;
// p3.3.50 Just a flag to say the port was found in the song file, even if it has no device right now.
bool _foundInSongFile;
+ // When creating a new midi track, add these global default channel routes to/from this port. Ignored if 0.
+ int _defaultInChannels; // These are bit-wise channel masks.
+ int _defaultOutChannels; //
RouteList _inRoutes, _outRoutes;
@@ -84,6 +87,10 @@ class MidiPort {
int nullSendValue();
void setNullSendValue(int v);
+ int defaultInChannels() const { return _defaultInChannels; }
+ int defaultOutChannels() const { return _defaultOutChannels; }
+ void setDefaultInChannels(int c) { _defaultInChannels = c; }
+ void setDefaultOutChannels(int c) { _defaultOutChannels = c; }
RouteList* inRoutes() { return &_inRoutes; }
RouteList* outRoutes() { return &_outRoutes; }
bool noInRoute() const { return _inRoutes.empty(); }
diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp
index 64287e14..407b8dce 100644
--- a/muse2/muse/song.cpp
+++ b/muse2/muse/song.cpp
@@ -254,6 +254,52 @@ Track* Song::addTrack(int t)
msgInsertTrack(track, -1, true);
insertTrack3(track, -1);
+ // Add default track <-> midiport routes.
+ if(track->isMidiTrack())
+ {
+ MidiTrack* mt = (MidiTrack*)track;
+ int c, cbi, ch;
+ bool defOutFound = false; /// TODO: Remove this when multiple out routes supported.
+ for(int i = 0; i < MIDI_PORTS; ++i)
+ {
+ MidiPort* mp = &midiPorts[i];
+
+ c = mp->defaultInChannels();
+ if(c)
+ {
+ audio->msgAddRoute(Route(i, c), Route(track, c));
+ updateFlags |= SC_ROUTE;
+ }
+
+ if(!defOutFound) ///
+ {
+ c = mp->defaultOutChannels();
+ if(c)
+ {
+
+ /// TODO: Switch when multiple out routes supported.
+ #if 0
+ audio->msgAddRoute(Route(track, c), Route(i, c));
+ updateFlags |= SC_ROUTE;
+ #else
+ for(ch = 0; ch < MIDI_CHANNELS; ++ch)
+ {
+ cbi = 1 << ch;
+ if(c & cbi)
+ {
+ defOutFound = true;
+ mt->setOutPort(i);
+ mt->setOutChannel(ch);
+ updateFlags |= SC_ROUTE;
+ break;
+ }
+ }
+ #endif
+ }
+ }
+ }
+ }
+
//
// add default route to master
//
@@ -261,14 +307,15 @@ Track* Song::addTrack(int t)
if (!ol->empty()) {
AudioOutput* ao = ol->front();
switch(type) {
- case Track::MIDI:
- case Track::DRUM:
- case Track::AUDIO_OUTPUT:
- break;
+ //case Track::MIDI:
+ //case Track::DRUM:
+ //case Track::AUDIO_OUTPUT:
+ // break;
+
case Track::WAVE:
- case Track::AUDIO_GROUP:
+ //case Track::AUDIO_GROUP: // Removed by Tim.
case Track::AUDIO_AUX:
- case Track::AUDIO_INPUT:
+ //case Track::AUDIO_INPUT: // Removed by Tim.
// p3.3.38
//case Track::AUDIO_SOFTSYNTH:
audio->msgAddRoute(Route((AudioTrack*)track, -1), Route(ao, -1));
@@ -279,6 +326,8 @@ Track* Song::addTrack(int t)
audio->msgAddRoute(Route((AudioTrack*)track, 0, ((AudioTrack*)track)->channels()), Route(ao, 0, ((AudioTrack*)track)->channels()));
updateFlags |= SC_ROUTE;
break;
+ default:
+ break;
}
}
audio->msgUpdateSoloStates();
diff --git a/muse2/muse/sync.cpp b/muse2/muse/sync.cpp
index c1056e82..9fe5f4d3 100644
--- a/muse2/muse/sync.cpp
+++ b/muse2/muse/sync.cpp
@@ -402,6 +402,16 @@ void MidiSyncInfo::trigActDetect(const int ch)
}
//---------------------------------------------------------
+// isDefault
+//---------------------------------------------------------
+
+bool MidiSyncInfo::isDefault() const
+{
+ return(_idOut == 127 && _idIn == 127 && !_sendMC && !_sendMRT && !_sendMMC && !_sendMTC &&
+ /* !_sendContNotStart && */ !_recMC && !_recMRT && !_recMMC && !_recMTC && _recRewOnStart);
+}
+
+//---------------------------------------------------------
// read
//---------------------------------------------------------
@@ -462,8 +472,10 @@ void MidiSyncInfo::write(int level, Xml& xml)
// return;
// All defaults? Nothing to write.
- if(_idOut == 127 && _idIn == 127 && !_sendMC && !_sendMRT && !_sendMMC && !_sendMTC &&
- /* !_sendContNotStart && */ !_recMC && !_recMRT && !_recMMC && !_recMTC && _recRewOnStart)
+ //if(_idOut == 127 && _idIn == 127 && !_sendMC && !_sendMRT && !_sendMMC && !_sendMTC &&
+ // /* !_sendContNotStart && */ !_recMC && !_recMRT && !_recMMC && !_recMTC && _recRewOnStart)
+ // return;
+ if(isDefault())
return;
xml.tag(level++, "midiSyncInfo");
diff --git a/muse2/muse/sync.h b/muse2/muse/sync.h
index d6a08f0d..47acece8 100644
--- a/muse2/muse/sync.h
+++ b/muse2/muse/sync.h
@@ -120,6 +120,7 @@ class MidiSyncInfo
bool actDetect(const int ch) const;
void trigActDetect(const int ch);
+ bool isDefault() const;
void read(Xml& xml);
//void write(int level, Xml& xml, MidiDevice* md);
void write(int level, Xml& xml);
diff --git a/muse2/muse/widgets/mtrackinfobase.ui b/muse2/muse/widgets/mtrackinfobase.ui
index 30b111c2..43cf6927 100644
--- a/muse2/muse/widgets/mtrackinfobase.ui
+++ b/muse2/muse/widgets/mtrackinfobase.ui
@@ -330,7 +330,7 @@
<string>input routing</string>
</property>
<property name="text">
- <string>iR</string>
+ <string>Inputs</string>
</property>
</widget>
</item>
@@ -389,17 +389,11 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="maximumSize">
- <size>
- <width>14</width>
- <height>32767</height>
- </size>
- </property>
<property name="toolTip">
- <string>Echo</string>
+ <string>Midi thru</string>
</property>
<property name="whatsThis">
- <string>Echo recording events to output.</string>
+ <string>Pass input events through ('thru') to output.</string>
</property>
<property name="checkable">
<bool>true</bool>