summaryrefslogtreecommitdiff
path: root/muse2/muse
diff options
context:
space:
mode:
Diffstat (limited to 'muse2/muse')
-rw-r--r--muse2/muse/app.cpp306
-rw-r--r--muse2/muse/app.h17
-rw-r--r--muse2/muse/arranger/alayout.cpp2
-rw-r--r--muse2/muse/arranger/arranger.cpp59
-rw-r--r--muse2/muse/arranger/arrangerview.cpp29
-rw-r--r--muse2/muse/arranger/arrangerview.h10
-rw-r--r--muse2/muse/arranger/pcanvas.cpp144
-rw-r--r--muse2/muse/arranger/pcanvas.h6
-rw-r--r--muse2/muse/arranger/tlist.cpp169
-rw-r--r--muse2/muse/audio.cpp54
-rw-r--r--muse2/muse/audio.h10
-rw-r--r--muse2/muse/audioprefetch.cpp7
-rw-r--r--muse2/muse/audiotrack.cpp36
-rw-r--r--muse2/muse/cliplist/cliplist.cpp2
-rw-r--r--muse2/muse/cobject.cpp22
-rw-r--r--muse2/muse/cobject.h18
-rw-r--r--muse2/muse/conf.cpp148
-rw-r--r--muse2/muse/confmport.cpp169
-rw-r--r--muse2/muse/ctrl/ctrlcanvas.cpp2
-rw-r--r--muse2/muse/driver/alsamidi.cpp259
-rw-r--r--muse2/muse/driver/jack.cpp164
-rw-r--r--muse2/muse/driver/jackaudio.h1
-rw-r--r--muse2/muse/dssihost.cpp294
-rw-r--r--muse2/muse/dssihost.h7
-rw-r--r--muse2/muse/gconfig.cpp11
-rw-r--r--muse2/muse/gconfig.h5
-rw-r--r--muse2/muse/globals.cpp6
-rw-r--r--muse2/muse/globals.h1
-rw-r--r--muse2/muse/helper.cpp638
-rw-r--r--muse2/muse/helper.h9
-rw-r--r--muse2/muse/instruments/editinstrument.cpp50
-rw-r--r--muse2/muse/instruments/minstrument.cpp62
-rw-r--r--muse2/muse/instruments/minstrument.h8
-rw-r--r--muse2/muse/liste/editevent.cpp7
-rw-r--r--muse2/muse/liste/listedit.cpp3
-rw-r--r--muse2/muse/main.cpp116
-rw-r--r--muse2/muse/marker/markerview.cpp5
-rw-r--r--muse2/muse/marker/markerview.h2
-rw-r--r--muse2/muse/master/lmaster.cpp2
-rw-r--r--muse2/muse/master/masteredit.cpp2
-rw-r--r--muse2/muse/midiedit/drumedit.cpp2
-rw-r--r--muse2/muse/midiedit/ecanvas.cpp91
-rw-r--r--muse2/muse/midiedit/pianoroll.cpp2
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp181
-rw-r--r--muse2/muse/midiedit/scoreedit.h74
-rw-r--r--muse2/muse/midiport.cpp12
-rw-r--r--muse2/muse/midiseq.cpp25
-rw-r--r--muse2/muse/mixer/amixer.cpp2
-rw-r--r--muse2/muse/mixer/astrip.cpp38
-rw-r--r--muse2/muse/mixer/mstrip.cpp6
-rw-r--r--muse2/muse/mixer/strip.cpp24
-rw-r--r--muse2/muse/mixer/strip.h1
-rw-r--r--muse2/muse/node.cpp769
-rw-r--r--muse2/muse/osc.cpp21
-rw-r--r--muse2/muse/osc.h6
-rw-r--r--muse2/muse/part.cpp12
-rw-r--r--muse2/muse/plugin.cpp117
-rw-r--r--muse2/muse/plugin.h115
-rw-r--r--muse2/muse/remote/pyapi.cpp4
-rw-r--r--muse2/muse/route.cpp725
-rw-r--r--muse2/muse/route.h12
-rw-r--r--muse2/muse/shortcuts.cpp2
-rw-r--r--muse2/muse/song.cpp155
-rw-r--r--muse2/muse/song.h5
-rw-r--r--muse2/muse/songfile.cpp50
-rw-r--r--muse2/muse/structure.cpp238
-rw-r--r--muse2/muse/structure.h7
-rw-r--r--muse2/muse/synth.cpp61
-rw-r--r--muse2/muse/synth.h8
-rw-r--r--muse2/muse/ticksynth.cpp1
-rw-r--r--muse2/muse/track.cpp155
-rw-r--r--muse2/muse/track.h68
-rw-r--r--muse2/muse/undo.cpp16
-rw-r--r--muse2/muse/undo.h1
-rw-r--r--muse2/muse/vst.h1
-rw-r--r--muse2/muse/wave.cpp24
-rw-r--r--muse2/muse/wave.h6
-rw-r--r--muse2/muse/waveedit/waveedit.cpp1
-rw-r--r--muse2/muse/wavetrack.cpp8
-rw-r--r--muse2/muse/widgets/citem.h2
-rw-r--r--muse2/muse/widgets/filedialog.cpp42
-rw-r--r--muse2/muse/widgets/filedialog.h1
-rw-r--r--muse2/muse/widgets/genset.cpp56
-rw-r--r--muse2/muse/widgets/genset.h4
-rw-r--r--muse2/muse/widgets/gensetbase.ui121
-rw-r--r--muse2/muse/widgets/header.cpp6
-rw-r--r--muse2/muse/widgets/knob.cpp24
-rw-r--r--muse2/muse/widgets/knob.h1
-rw-r--r--muse2/muse/widgets/meter.cpp7
-rw-r--r--muse2/muse/widgets/midisync.ui13
-rw-r--r--muse2/muse/widgets/mtrackinfo.cpp33
-rw-r--r--muse2/muse/widgets/musewidgetsplug.cpp3
-rw-r--r--muse2/muse/widgets/popupmenu.cpp23
-rw-r--r--muse2/muse/widgets/poslabel.cpp6
-rw-r--r--muse2/muse/widgets/projectcreate.ui99
-rw-r--r--muse2/muse/widgets/projectcreateimpl.cpp191
-rw-r--r--muse2/muse/widgets/projectcreateimpl.h19
-rw-r--r--muse2/muse/widgets/routepopup.cpp48
-rw-r--r--muse2/muse/widgets/synthconfigbase.ui14
-rw-r--r--muse2/muse/widgets/utils.cpp3
-rw-r--r--muse2/muse/widgets/visibletracks.cpp2
-rw-r--r--muse2/muse/widgets/visibletracks.h3
-rw-r--r--muse2/muse/xml.cpp94
103 files changed, 4275 insertions, 2448 deletions
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp
index bd6bc560..148f3072 100644
--- a/muse2/muse/app.cpp
+++ b/muse2/muse/app.cpp
@@ -4,6 +4,7 @@
// $Id: app.cpp,v 1.113.2.68 2009/12/21 14:51:51 spamatica Exp $
//
// (C) Copyright 1999-2011 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -33,6 +34,8 @@
#include <QProgressDialog>
#include <QMdiArea>
#include <QMdiSubWindow>
+#include <QSocketNotifier>
+#include <QString>
#include <iostream>
@@ -55,6 +58,7 @@
#include "filedialog.h"
#include "gconfig.h"
#include "gui.h"
+#include "helper.h"
#include "icons.h"
#include "instruments/editinstrument.h"
#include "listedit.h"
@@ -84,8 +88,11 @@ extern void exitJackAudio();
extern void exitDummyAudio();
extern void exitOSC();
extern void exitMidiAlsa();
-}
+extern void initMidiSequencer();
+extern void initAudio();
+extern void initAudioPrefetch();
+}
namespace MusEGui {
@@ -94,12 +101,12 @@ namespace MusEGui {
static pthread_t watchdogThread;
//ErrorHandler *error;
-
#define PROJECT_LIST_LEN 6
static QString* projectList[PROJECT_LIST_LEN];
#ifdef HAVE_LASH
#include <lash/lash.h>
+#include <lo/lo_osc_types.h>
lash_client_t * lash_client = 0;
extern snd_seq_t * alsaSeq;
#endif /* HAVE_LASH */
@@ -171,14 +178,7 @@ bool MusE::seqStart()
if(MusEGlobal::realTimeScheduling)
{
{
- //pfprio = MusEGlobal::realTimePriority - 5;
- // p3.3.40
pfprio = MusEGlobal::realTimePriority + 1;
-
- //midiprio = MusEGlobal::realTimePriority - 2;
- // p3.3.37
- //midiprio = MusEGlobal::realTimePriority + 1;
- // p3.3.40
midiprio = MusEGlobal::realTimePriority + 2;
}
}
@@ -198,9 +198,6 @@ bool MusE::seqStart()
MusEGlobal::audioPrefetch->msgSeek(0, true); // force
- //MusEGlobal::midiSeqRunning = !midiSeq->start(MusEGlobal::realTimeScheduling ? MusEGlobal::realTimePriority : 0);
- // Changed by Tim. p3.3.22
- //MusEGlobal::midiSeq->start(MusEGlobal::realTimeScheduling ? MusEGlobal::realTimePriority : 0);
MusEGlobal::midiSeq->start(midiprio);
int counter=0;
@@ -224,7 +221,7 @@ bool MusE::seqStart()
}
return true;
}
-
+
//---------------------------------------------------------
// stop
//---------------------------------------------------------
@@ -258,6 +255,7 @@ bool MusE::seqRestart()
}
seqStop();
}
+
if(!seqStart())
return false;
@@ -299,7 +297,7 @@ void addProject(const QString& name)
//---------------------------------------------------------
//MusE::MusE(int argc, char** argv) : QMainWindow(0, "mainwindow")
-MusE::MusE(int argc, char** argv) : QMainWindow()
+MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow()
{
// By T356. For LADSPA plugins in plugin.cpp
// QWidgetFactory::addWidgetFactory( new PluginWidgetFactory ); ddskrjo
@@ -333,6 +331,7 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
progress = 0;
activeTopWin = NULL;
currentMenuSharingTopwin = NULL;
+ waitingForTopwin = NULL;
appName = QString("MusE");
setWindowTitle(appName);
@@ -346,8 +345,6 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
MusEGlobal::heartBeatTimer = new QTimer(this);
MusEGlobal::heartBeatTimer->setObjectName("timer");
connect(MusEGlobal::heartBeatTimer, SIGNAL(timeout()), MusEGlobal::song, SLOT(beat()));
-
-
connect(this, SIGNAL(activeTopWinChanged(MusEGui::TopWin*)), SLOT(activeTopWinChangedSlot(MusEGui::TopWin*)));
#ifdef ENABLE_PYTHON
@@ -460,7 +457,7 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
MusEGlobal::panicAction->setWhatsThis(tr("send note off to all midi channels"));
connect(MusEGlobal::panicAction, SIGNAL(activated()), MusEGlobal::song, SLOT(panic()));
- MusECore::initMidiInstruments();
+ MusECore::initMidiInstruments();
MusECore::initMidiPorts();
MusECore::initMidiDevices();
@@ -706,7 +703,7 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
//rlimit lim;
//getrlimit(RLIMIT_RTPRIO, &lim);
//printf("RLIMIT_RTPRIO soft:%d hard:%d\n", lim.rlim_cur, lim.rlim_max); // Reported 80, 80 even with non-RT kernel.
-
+
if (MusEGlobal::realTimePriority < sched_get_priority_min(SCHED_FIFO))
MusEGlobal::realTimePriority = sched_get_priority_min(SCHED_FIFO);
else if (MusEGlobal::realTimePriority > sched_get_priority_max(SCHED_FIFO))
@@ -721,18 +718,19 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
MusEGlobal::midiRTPrioOverride = sched_get_priority_max(SCHED_FIFO);
}
- // Changed by Tim. p3.3.17
- //MusEGlobal::midiSeq = new MusECore::MidiSeq(MusEGlobal::realTimeScheduling ? MusEGlobal::realTimePriority : 0, "Midi");
- MusEGlobal::midiSeq = new MusECore::MidiSeq("Midi");
- MusEGlobal::audio = new MusECore::Audio();
- //MusEGlobal::audioPrefetch = new MusECore::AudioPrefetch(0, "Disc");
- MusEGlobal::audioPrefetch = new MusECore::AudioPrefetch("Prefetch");
-
+ MusECore::initMidiSequencer();
+ MusECore::initAudio();
+
+ // Moved here from Audio::Audio
+ QSocketNotifier* ss = new QSocketNotifier(MusEGlobal::audio->getFromThreadFdr(), QSocketNotifier::Read, this);
+ connect(ss, SIGNAL(activated(int)), MusEGlobal::song, SLOT(seqSignal(int)));
+
+ MusECore::initAudioPrefetch();
+
//---------------------------------------------------
// Popups
//---------------------------------------------------
-
// when adding a menu to the main window, remember adding it to
// either the leadingMenus or trailingMenus list!
// also do NOT use menuBar()->addMenu(QString&), but ALWAYS
@@ -961,6 +959,11 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
transport = new MusEGui::Transport(this, "transport");
bigtime = 0;
+ MusEGlobal::song->blockSignals(false);
+
+ // Load start song moved to main.cpp p4.0.41 REMOVE Tim.
+ /*
+
//---------------------------------------------------
// load project
// if no songname entered on command line:
@@ -975,7 +978,8 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
name = argv[0];
else if (MusEGlobal::config.startMode == 0) {
if (argc < 2)
- name = projectList[0] ? *projectList[0] : QString("untitled");
+ //name = projectList[0] ? *projectList[0] : QString("untitled");
+ name = projectList[0] ? *projectList[0] : MusEGui::getUniqueUntitledName(); // p4.0.40
else
name = argv[0];
printf("starting with selected song %s\n", MusEGlobal::config.startSong.toLatin1().constData());
@@ -989,19 +993,47 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
printf("starting with pre configured song %s\n", MusEGlobal::config.startSong.toLatin1().constData());
name = MusEGlobal::config.startSong;
}
- MusEGlobal::song->blockSignals(false);
- loadProjectFile(name, useTemplate, true);
-
+
+ // loadProjectFile(name, useTemplate, true); //commented out by flo: see below (*)
+ */
+
changeConfig(false);
QSettings settings("MusE", "MusE-qt");
restoreGeometry(settings.value("MusE/geometry").toByteArray());
//restoreState(settings.value("MusE/windowState").toByteArray());
- MusEGlobal::song->update();
-
- updateWindowMenu();
+ MusEGlobal::song->update(); // commented out by flo: will be done by the below (*)
+ updateWindowMenu(); // same here
+
+ // Load start song moved to main.cpp p4.0.41 REMOVE Tim.
+ /*
+
+ // this is (*).
+ // this is a really hackish workaround for the loading-on-startup problem.
+ // i have absolutely no idea WHY it breaks when using loadProjectFile()
+ // above, but it does on my machine (it doesn't on others!).
+ // the problem can be worked around by delaying loading the song file.
+ // i use hackishSongOpenTimer for this, which calls after 10ms a slot
+ // which then does the actual loadProjectFile() call.
+ // FIXME: please, if anyone finds the real problem, FIX it and
+ // remove that dirty, dirty workaround!
+ hackishSongOpenFilename=name;
+ hackishSongOpenUseTemplate=useTemplate;
+ hackishSongOpenTimer=new QTimer(this);
+ hackishSongOpenTimer->setInterval(10);
+ hackishSongOpenTimer->setSingleShot(true);
+ connect(hackishSongOpenTimer, SIGNAL(timeout()), this, SLOT(hackishSongOpenTimerTimeout()));
+ hackishSongOpenTimer->start();
+ */
}
+// Load start song moved to main.cpp p4.0.41 REMOVE Tim.
+//void MusE::hackishSongOpenTimerTimeout()
+//{
+ ///loadProjectFile(hackishSongOpenFilename, hackishSongOpenUseTemplate, true);
+ //loadProjectFile(hackishSongOpenFilename, hackishSongOpenUseTemplate, !hackishSongOpenUseTemplate);
+//}
+
MusE::~MusE()
{
}
@@ -1015,6 +1047,44 @@ void MusE::setHeartBeat()
MusEGlobal::heartBeatTimer->start(1000/MusEGlobal::config.guiRefresh);
}
+//---------------------------------------------------
+// loadDefaultSong
+// if no songname entered on command line:
+// startMode: 0 - load last song
+// 1 - load default template
+// 2 - load configured start song
+//---------------------------------------------------
+
+void MusE::loadDefaultSong(int argc, char** argv)
+{
+ QString name;
+ bool useTemplate = false;
+ if (argc >= 2)
+ name = argv[0];
+ else if (MusEGlobal::config.startMode == 0) {
+ if (argc < 2)
+ //name = projectList[0] ? *projectList[0] : QString("untitled");
+ name = projectList[0] ? *projectList[0] : MusEGui::getUniqueUntitledName(); // p4.0.40
+ else
+ name = argv[0];
+ printf("starting with selected song %s\n", MusEGlobal::config.startSong.toLatin1().constData());
+ }
+ else if (MusEGlobal::config.startMode == 1) {
+ printf("starting with default template\n");
+ name = MusEGlobal::museGlobalShare + QString("/templates/default.med");
+ useTemplate = true;
+ }
+ else if (MusEGlobal::config.startMode == 2) {
+ printf("starting with pre configured song %s\n", MusEGlobal::config.startSong.toLatin1().constData());
+ name = MusEGlobal::config.startSong;
+ }
+ //loadProjectFile(name, useTemplate, true);
+ loadProjectFile(name, useTemplate, !useTemplate);
+
+ //MusEGlobal::song->update();
+ //updateWindowMenu();
+}
+
//---------------------------------------------------------
// resetDevices
//---------------------------------------------------------
@@ -1156,7 +1226,8 @@ void MusE::loadProjectFile1(const QString& name, bool songTemplate, bool loadAll
QApplication::restoreOverrideCursor();
return;
}
- project.setFile("untitled");
+ //project.setFile("untitled");
+ project.setFile(MusEGui::getUniqueUntitledName()); // p4.0.40
MusEGlobal::museProject = MusEGlobal::museProjectInitPath;
}
else {
@@ -1214,7 +1285,8 @@ void MusE::loadProjectFile1(const QString& name, bool songTemplate, bool loadAll
}
if (!songTemplate) {
addProject(project.absoluteFilePath());
- setWindowTitle(QString("MusE: Song: ") + project.completeBaseName());
+ //setWindowTitle(QString("MusE: Song: ") + project.completeBaseName());
+ setWindowTitle(QString("MusE: Song: ") + MusEGui::projectTitleFromFilename(project.absoluteFilePath()));
}
MusEGlobal::song->dirty = false;
progress->setValue(30);
@@ -1236,7 +1308,7 @@ void MusE::loadProjectFile1(const QString& name, bool songTemplate, bool loadAll
// set the geometry if the mixer has already been created.
if(mixer1)
{
- //if(mixer1->geometry().size() != MusEGlobal::config.mixer1.geometry.size()) // p3.3.53 Moved below
+ //if(mixer1->geometry().size() != MusEGlobal::config.mixer1.geometry.size()) // Moved below
// mixer1->resize(MusEGlobal::config.mixer1.geometry.size());
if(mixer1->geometry().topLeft() != MusEGlobal::config.mixer1.geometry.topLeft())
@@ -1244,7 +1316,7 @@ void MusE::loadProjectFile1(const QString& name, bool songTemplate, bool loadAll
}
if(mixer2)
{
- //if(mixer2->geometry().size() != MusEGlobal::config.mixer2.geometry.size()) // p3.3.53 Moved below
+ //if(mixer2->geometry().size() != MusEGlobal::config.mixer2.geometry.size()) // Moved below
// mixer2->resize(MusEGlobal::config.mixer2.geometry.size());
if(mixer2->geometry().topLeft() != MusEGlobal::config.mixer2.geometry.topLeft())
@@ -1273,7 +1345,7 @@ void MusE::loadProjectFile1(const QString& name, bool songTemplate, bool loadAll
arrangerView->scoreNamingChanged(); // inform the score menus about the new scores and their names
progress->setValue(50);
- // p3.3.53 Try this AFTER the song update above which does a mixer update... Tested OK - mixers resize properly now.
+ // Try this AFTER the song update above which does a mixer update... Tested OK - mixers resize properly now.
if (loadAll)
{
if(mixer1)
@@ -1336,10 +1408,13 @@ void MusE::loadProjectFile1(const QString& name, bool songTemplate, bool loadAll
void MusE::setUntitledProject()
{
setConfigDefaults();
- QString name("untitled");
+ //QString name("untitled");
+ QString name(MusEGui::getUniqueUntitledName()); // p4.0.40
+
MusEGlobal::museProject = "./"; //QFileInfo(name).absolutePath();
project.setFile(name);
- setWindowTitle(tr("MusE: Song: %1").arg(project.completeBaseName()));
+ //setWindowTitle(tr("MusE: Song: %1").arg(project.completeBaseName()));
+ setWindowTitle(tr("MusE: Song: %1").arg(MusEGui::projectTitleFromFilename(name)));
}
//---------------------------------------------------------
@@ -1391,14 +1466,14 @@ void MusE::loadTemplate()
if (!fn.isEmpty()) {
// MusEGlobal::museProject = QFileInfo(fn).absolutePath();
- loadProjectFile(fn, true, true);
+ //loadProjectFile(fn, true, true);
// With templates, don't clear midi ports.
// Any named ports in the template file are useless since they likely
// would not be found on other users' machines.
// So keep whatever the user currently has set up for ports.
// Note that this will also keep the current window configurations etc.
// but actually that's also probably a good thing. p4.0.17 Tim. TESTING: Maybe some problems...
- //loadProjectFile(fn, true, false);
+ loadProjectFile(fn, true, false);
setUntitledProject();
}
@@ -1410,7 +1485,11 @@ void MusE::loadTemplate()
bool MusE::save()
{
- if (project.completeBaseName() == "untitled")
+ //if (project.completeBaseName() == "untitled") // p4.0.40 Must catch "untitled 1" "untitled 2" etc
+ //if (MusEGui::projectTitleFromFilename(project.absoluteFilePath()) == "untitled")
+ //if (MusEGui::projectTitleFromFilename(project.absoluteFilePath()) == MusEGui::getUniqueUntitledName())
+ ///if (project.absoluteFilePath() == MusEGui::getUniqueUntitledName())
+ if (MusEGlobal::museProject == MusEGlobal::museProjectInitPath )
return saveAs();
else
return save(project.filePath(), false);
@@ -1542,7 +1621,7 @@ void MusE::closeEvent(QCloseEvent* event)
MusECore::exitMetronome();
// 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
+ // Even though it is a child of MusE, it just passes MusE onto the underlying PopupMenus.
if(routingPopupMenu)
delete routingPopupMenu;
#if 0
@@ -1572,7 +1651,7 @@ void MusE::closeEvent(QCloseEvent* event)
}
#ifdef HAVE_LASH
- // Disconnect gracefully from LASH. Tim. p3.3.14
+ // Disconnect gracefully from LASH.
if(lash_client)
{
if(MusEGlobal::debugMsg)
@@ -1590,7 +1669,6 @@ void MusE::closeEvent(QCloseEvent* event)
printf("MusE: Exiting OSC\n");
MusECore::exitOSC();
- // p3.3.47
delete MusEGlobal::audioPrefetch;
delete MusEGlobal::audio;
delete MusEGlobal::midiSeq;
@@ -1619,8 +1697,8 @@ void MusE::showMarker(bool flag)
markerView = new MusEGui::MarkerView(this);
connect(markerView, SIGNAL(closed()), SLOT(markerClosed()));
- toplevels.push_back(markerView);
markerView->show();
+ toplevels.push_back(markerView);
}
markerView->setVisible(flag);
viewMarkerAction->setChecked(flag);
@@ -1642,6 +1720,20 @@ void MusE::markerClosed()
setCurrentMenuSharingTopwin(NULL);
updateWindowMenu();
+
+ // focus the last activated topwin which is not the marker view
+ QList<QMdiSubWindow*> l = mdiArea->subWindowList(QMdiArea::StackingOrder);
+ for (QList<QMdiSubWindow*>::iterator lit=l.begin(); lit!=l.end(); lit++)
+ if ((*lit)->isVisible() && (*lit)->widget() != markerView)
+ {
+ if (MusEGlobal::debugMsg)
+ printf("bringing '%s' to front instead of closed arranger window\n",(*lit)->widget()->windowTitle().toAscii().data());
+
+ bringToFront((*lit)->widget());
+
+ break;
+ }
+
}
//---------------------------------------------------------
@@ -1675,6 +1767,20 @@ void MusE::arrangerClosed()
{
viewArrangerAction->setChecked(false);
updateWindowMenu();
+
+ // focus the last activated topwin which is not the arranger view
+ QList<QMdiSubWindow*> l = mdiArea->subWindowList(QMdiArea::StackingOrder);
+ for (QList<QMdiSubWindow*>::iterator lit=l.begin(); lit!=l.end(); lit++)
+ if ((*lit)->isVisible() && (*lit)->widget() != arrangerView)
+ {
+ if (MusEGlobal::debugMsg)
+ printf("bringing '%s' to front instead of closed arranger window\n",(*lit)->widget()->windowTitle().toAscii().data());
+
+ bringToFront((*lit)->widget());
+
+ break;
+ }
+
}
//---------------------------------------------------------
@@ -1716,7 +1822,7 @@ MusEGui::RoutePopupMenu* MusE::getRoutingPopupMenu()
bool MusE::saveAs()
{
QString name;
- if (MusEGlobal::museProject == MusEGlobal::museProjectInitPath ) {
+ //if (MusEGlobal::museProject == MusEGlobal::museProjectInitPath ) // Use project dialog always now.
if (MusEGlobal::config.useProjectSaveDialog) {
MusEGui::ProjectCreateImpl pci(MusEGlobal::muse);
if (pci.exec() == QDialog::Rejected) {
@@ -1737,10 +1843,11 @@ bool MusE::saveAs()
QMessageBox::warning(this,"Path error","Can't create project path", QMessageBox::Ok);
return false;
}
- }
- else {
- name = MusEGui::getSaveFileName(QString(""), MusEGlobal::med_file_save_pattern, this, tr("MusE: Save As"));
- }
+ //}
+ //else {
+ // name = MusEGui::getSaveFileName(QString(""), MusEGlobal::med_file_save_pattern, this, tr("MusE: Save As"));
+ //}
+
bool ok = false;
if (!name.isEmpty()) {
QString tempOldProj = MusEGlobal::museProject;
@@ -1748,7 +1855,8 @@ bool MusE::saveAs()
ok = save(name, true);
if (ok) {
project.setFile(name);
- setWindowTitle(tr("MusE: Song: %1").arg(project.completeBaseName()));
+ //setWindowTitle(tr("MusE: Song: %1").arg(project.completeBaseName()));
+ setWindowTitle(tr("MusE: Song: %1").arg(MusEGui::projectTitleFromFilename(name)));
addProject(name);
}
else
@@ -1830,8 +1938,8 @@ void MusE::openInScoreEdit(MusEGui::ScoreEdit* destination, MusECore::PartList*
if (destination==NULL) // if no destination given, create a new one
{
destination = new MusEGui::ScoreEdit(this, 0, _arranger->cursorValue());
- destination->show();
toplevels.push_back(destination);
+ destination->show();
connect(destination, SIGNAL(isDeleting(MusEGui::TopWin*)), SLOT(toplevelDeleting(MusEGui::TopWin*)));
connect(destination, SIGNAL(name_changed()), arrangerView, SLOT(scoreNamingChanged()));
//connect(muse, SIGNAL(configChanged()), destination, SLOT(config_changed()));
@@ -1866,10 +1974,10 @@ void MusE::startPianoroll(MusECore::PartList* pl, bool showDefaultCtrls)
{
MusEGui::PianoRoll* pianoroll = new MusEGui::PianoRoll(pl, this, 0, _arranger->cursorValue());
- if(showDefaultCtrls) // p4.0.12
+ if(showDefaultCtrls)
pianoroll->addCtrl();
- pianoroll->show();
toplevels.push_back(pianoroll);
+ pianoroll->show();
connect(pianoroll, SIGNAL(isDeleting(MusEGui::TopWin*)), SLOT(toplevelDeleting(MusEGui::TopWin*)));
connect(MusEGlobal::muse, SIGNAL(configChanged()), pianoroll, SLOT(configChanged()));
updateWindowMenu();
@@ -1890,8 +1998,8 @@ void MusE::startListEditor()
void MusE::startListEditor(MusECore::PartList* pl)
{
MusEGui::ListEdit* listEditor = new MusEGui::ListEdit(pl);
- listEditor->show();
toplevels.push_back(listEditor);
+ listEditor->show();
connect(listEditor, SIGNAL(isDeleting(MusEGui::TopWin*)), SLOT(toplevelDeleting(MusEGui::TopWin*)));
connect(MusEGlobal::muse,SIGNAL(configChanged()), listEditor, SLOT(configChanged()));
updateWindowMenu();
@@ -1904,8 +2012,8 @@ void MusE::startListEditor(MusECore::PartList* pl)
void MusE::startMasterEditor()
{
MusEGui::MasterEdit* masterEditor = new MusEGui::MasterEdit();
- masterEditor->show();
toplevels.push_back(masterEditor);
+ masterEditor->show();
connect(masterEditor, SIGNAL(isDeleting(MusEGui::TopWin*)), SLOT(toplevelDeleting(MusEGui::TopWin*)));
updateWindowMenu();
}
@@ -1917,8 +2025,8 @@ void MusE::startMasterEditor()
void MusE::startLMasterEditor()
{
MusEGui::LMaster* lmaster = new MusEGui::LMaster();
- lmaster->show();
toplevels.push_back(lmaster);
+ lmaster->show();
connect(lmaster, SIGNAL(isDeleting(MusEGui::TopWin*)), SLOT(toplevelDeleting(MusEGui::TopWin*)));
connect(MusEGlobal::muse, SIGNAL(configChanged()), lmaster, SLOT(configChanged()));
updateWindowMenu();
@@ -1939,10 +2047,10 @@ void MusE::startDrumEditor()
void MusE::startDrumEditor(MusECore::PartList* pl, bool showDefaultCtrls)
{
MusEGui::DrumEdit* drumEditor = new MusEGui::DrumEdit(pl, this, 0, _arranger->cursorValue());
- if(showDefaultCtrls) // p4.0.12
+ if(showDefaultCtrls)
drumEditor->addCtrl();
- drumEditor->show();
toplevels.push_back(drumEditor);
+ drumEditor->show();
connect(drumEditor, SIGNAL(isDeleting(MusEGui::TopWin*)), SLOT(toplevelDeleting(MusEGui::TopWin*)));
connect(MusEGlobal::muse, SIGNAL(configChanged()), drumEditor, SLOT(configChanged()));
updateWindowMenu();
@@ -1966,8 +2074,8 @@ void MusE::startWaveEditor(MusECore::PartList* pl)
{
MusEGui::WaveEdit* waveEditor = new MusEGui::WaveEdit(pl);
waveEditor->show();
- connect(MusEGlobal::muse, SIGNAL(configChanged()), waveEditor, SLOT(configChanged()));
toplevels.push_back(waveEditor);
+ connect(MusEGlobal::muse, SIGNAL(configChanged()), waveEditor, SLOT(configChanged()));
connect(waveEditor, SIGNAL(isDeleting(MusEGui::TopWin*)), SLOT(toplevelDeleting(MusEGui::TopWin*)));
updateWindowMenu();
}
@@ -2088,6 +2196,19 @@ void MusE::toplevelDeleting(MusEGui::TopWin* tl)
{
activeTopWin=NULL;
emit activeTopWinChanged(NULL);
+
+ // focus the last activated topwin which is not the deleting one
+ QList<QMdiSubWindow*> l = mdiArea->subWindowList(QMdiArea::StackingOrder);
+ for (QList<QMdiSubWindow*>::iterator lit=l.begin(); lit!=l.end(); lit++)
+ if ((*lit)->isVisible() && (*lit)->widget() != tl)
+ {
+ if (MusEGlobal::debugMsg)
+ printf("bringing '%s' to front instead of closed window\n",(*lit)->widget()->windowTitle().toAscii().data());
+
+ bringToFront((*lit)->widget());
+
+ break;
+ }
}
if (tl == currentMenuSharingTopwin)
@@ -2168,7 +2289,7 @@ void MusE::kbAccel(int key)
MusEGlobal::song->setPlay(true);
}
- // p4.0.10 Tim. Normally each editor window handles these, to inc by the editor's raster snap value.
+ // Normally each editor window handles these, to inc by the editor's raster snap value.
// But users were asking for a global version - "they don't work when I'm in mixer or transport".
// Since no editor claimed the key event, we don't know a specific editor's snap setting,
// so adopt a policy where the arranger is the 'main' raster reference, I guess...
@@ -2649,7 +2770,8 @@ MusE::lash_idle_cb ()
int ok = save (ss.toAscii(), false);
if (ok) {
project.setFile(ss.toAscii());
- setWindowTitle(tr("MusE: Song: %1").arg(project.completeBaseName()));
+ //setWindowTitle(tr("MusE: Song: %1").arg(project.completeBaseName()));
+ setWindowTitle(tr("MusE: Song: %1").arg(MusEGui::projectTitleFromFilename(project.absoluteFilePath())));
addProject(ss.toAscii());
MusEGlobal::museProject = QFileInfo(ss.toAscii()).absolutePath();
}
@@ -3071,21 +3193,32 @@ void MusE::focusChanged(QWidget*, QWidget* now)
if (currentMenuSharingTopwin && (currentMenuSharingTopwin!=activeTopWin))
currentMenuSharingTopwin->storeInitialState();
-
+ // if the activated widget is a QMdiSubWindow containing some TopWin
+ if ( (dynamic_cast<QMdiSubWindow*>(ptr)!=0) &&
+ (dynamic_cast<MusEGui::TopWin*>( ((QMdiSubWindow*)ptr)->widget() )!=0) )
+ {
+ waitingForTopwin=(MusEGui::TopWin*) ((QMdiSubWindow*)ptr)->widget();
+ return;
+ }
while (ptr)
{
+ if (MusEGlobal::heavyDebugMsg)
+ printf("focusChanged: at widget %p with type %s\n",ptr, typeid(*ptr).name());
+
if ( (dynamic_cast<MusEGui::TopWin*>(ptr)!=0) || // *ptr is a TopWin or a derived class
(ptr==this) ) // the main window is selected
break;
ptr=dynamic_cast<QWidget*>(ptr->parent()); //in the unlikely case that ptr is a QObject, this returns NULL, which stops the loop
}
+ MusEGui::TopWin* win=dynamic_cast<MusEGui::TopWin*>(ptr);
// ptr is either NULL, this or the pointer to a TopWin
- if (ptr!=this) // if the main win is selected, don't treat that as "none", but also don't handle it
+
+ // if the main win or some deleting topwin is selected,
+ // don't treat that as "none", but also don't handle it
+ if (ptr!=this && (!win || !win->deleting()) )
{
- MusEGui::TopWin* win=dynamic_cast<MusEGui::TopWin*>(ptr);
-
// now 'win' is either NULL or the pointer to the active TopWin
if (win!=activeTopWin)
{
@@ -3233,6 +3366,26 @@ void MusE::shareMenuAndToolbarChanged(MusEGui::TopWin* win, bool val)
}
}
+void MusE::topwinMenuInited(MusEGui::TopWin* topwin)
+{
+ if (topwin==NULL)
+ return;
+
+ if (topwin == waitingForTopwin)
+ {
+ if (waitingForTopwin->deleting())
+ {
+ waitingForTopwin=NULL;
+ }
+ else
+ {
+ activeTopWin=waitingForTopwin;
+ waitingForTopwin=NULL;
+ emit activeTopWinChanged(activeTopWin);
+ }
+ }
+}
+
void MusE::updateWindowMenu()
{
bool sep;
@@ -3286,6 +3439,8 @@ void MusE::updateWindowMenu()
void MusE::bringToFront(QWidget* widget)
{
MusEGui::TopWin* win=dynamic_cast<MusEGui::TopWin*>(widget);
+ if (!win) return;
+
if (win->isMdiWin())
{
win->show();
@@ -3449,4 +3604,19 @@ void MusE::tileSubWindows()
}
}
+QString MusE::projectTitle() const
+{
+ return MusEGui::projectTitleFromFilename(project.fileName());
+}
+
+QString MusE::projectPath() const
+{
+ return MusEGui::projectPathFromFilename(project.absoluteFilePath());
+}
+
+QString MusE::projectExtension() const
+{
+ return MusEGui::projectExtensionFromFilename(project.fileName());
+}
+
} //namespace MusEGui
diff --git a/muse2/muse/app.h b/muse2/muse/app.h
index 27722e9a..184581dc 100644
--- a/muse2/muse/app.h
+++ b/muse2/muse/app.h
@@ -43,6 +43,7 @@ class QToolBar;
class QToolButton;
class QProgressDialog;
class QMdiArea;
+class QTimer;
namespace MusECore {
class AudioOutput;
@@ -91,7 +92,7 @@ class TopWin;
class Transport;
class VisibleTracks;
-#define MENU_ADD_SYNTH_ID_BASE 0x1000
+#define MENU_ADD_SYNTH_ID_BASE 0x8000
//---------------------------------------------------------
@@ -128,6 +129,7 @@ class MusE : public QMainWindow
TopWin* activeTopWin;
TopWin* currentMenuSharingTopwin;
+ TopWin* waitingForTopwin;
std::list<QToolBar*> requiredToolbars; //always displayed
std::list<QToolBar*> optionalToolbars; //only displayed when no toolbar-sharing window is active
@@ -213,6 +215,10 @@ class MusE : public QMainWindow
MidiTransformerDialog* midiTransformerDialog;
QMenu* openRecent;
+ //QTimer* hackishSongOpenTimer;
+ //QString hackishSongOpenFilename;
+ //bool hackishSongOpenUseTemplate;
+
bool readMidi(FILE*);
void read(MusECore::Xml& xml, bool skipConfig, bool isTemplate);
void processTrack(MusECore::MidiTrack* track);
@@ -327,6 +333,8 @@ class MusE : public QMainWindow
void arrangeSubWindowsColumns();
void tileSubWindows();
+ //void hackishSongOpenTimerTimeout();
+
public slots:
bool saveAs();
void bounceToFile(MusECore::AudioOutput* ao = 0);
@@ -371,12 +379,14 @@ class MusE : public QMainWindow
void addMdiSubWindow(QMdiSubWindow*);
void shareMenuAndToolbarChanged(MusEGui::TopWin*, bool);
+ void topwinMenuInited(MusEGui::TopWin*);
void updateWindowMenu();
public:
MusE(int argc, char** argv);
~MusE();
+ void loadDefaultSong(int argc, char** argv);
Arranger* arranger() const { return _arranger; }
QRect configGeometryMain;
QProgressDialog *progress;
@@ -384,10 +394,13 @@ class MusE : public QMainWindow
void kbAccel(int);
void changeConfig(bool writeFlag);
void seqStop();
- bool seqStart();
+ bool seqStart();
void setHeartBeat();
void importController(int, MusECore::MidiPort*, int);
QString projectName() { return project.fileName(); }
+ QString projectTitle() const;
+ QString projectPath() const;
+ QString projectExtension() const;
QWidget* mixer1Window();
QWidget* mixer2Window();
QWidget* transportWindow();
diff --git a/muse2/muse/arranger/alayout.cpp b/muse2/muse/arranger/alayout.cpp
index a892356c..119da498 100644
--- a/muse2/muse/arranger/alayout.cpp
+++ b/muse2/muse/arranger/alayout.cpp
@@ -117,7 +117,7 @@ void TLLayout::setGeometry(const QRect &rect)
QSize s1 = li[1]->sizeHint();
QSize s2 = li[2]->sizeHint();
- QSize s3 = li[3]->sizeHint();
+ //QSize s3 = li[3]->sizeHint();
QSize s4 = li[4]->sizeHint();
QSize s5 = li[5]->sizeHint();
diff --git a/muse2/muse/arranger/arranger.cpp b/muse2/muse/arranger/arranger.cpp
index ae753378..cb024070 100644
--- a/muse2/muse/arranger/arranger.cpp
+++ b/muse2/muse/arranger/arranger.cpp
@@ -569,27 +569,40 @@ void Arranger::songChanged(int type)
// Is it simply a midi controller value adjustment? Forget it.
if(type != SC_MIDI_CONTROLLER)
{
- unsigned endTick = MusEGlobal::song->len();
- int offset = AL::sigmap.ticksMeasure(endTick);
- hscroll->setRange(-offset, endTick + offset); //DEBUG
- canvas->setOrigin(-offset, 0);
- time->setOrigin(-offset, 0);
-
- int bar, beat;
- unsigned tick;
- AL::sigmap.tickValues(endTick, &bar, &beat, &tick);
- if (tick || beat)
- ++bar;
- lenEntry->blockSignals(true);
- lenEntry->setValue(bar);
- lenEntry->blockSignals(false);
-
- if(type & SC_SONG_TYPE) // p4.0.7 Tim.
+ // TEST p4.0.36 Try these, may need more/less.
+ if(type & ( SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED |
+ SC_PART_INSERTED | SC_PART_REMOVED | SC_PART_MODIFIED))
+ {
+ unsigned endTick = MusEGlobal::song->len();
+ int offset = AL::sigmap.ticksMeasure(endTick);
+ hscroll->setRange(-offset, endTick + offset); //DEBUG
+ canvas->setOrigin(-offset, 0);
+ time->setOrigin(-offset, 0);
+
+ int bar, beat;
+ unsigned tick;
+ AL::sigmap.tickValues(endTick, &bar, &beat, &tick);
+ if (tick || beat)
+ ++bar;
+ lenEntry->blockSignals(true);
+ lenEntry->setValue(bar);
+ lenEntry->blockSignals(false);
+ }
+
+ if(type & SC_SONG_TYPE)
setMode(MusEGlobal::song->mtype());
- trackSelectionChanged();
- canvas->partsChanged();
- typeBox->setCurrentIndex(int(MusEGlobal::song->mtype()));
+ if(type & SC_SELECTION) // TEST p4.0.36 Try this alone, may need more.
+ trackSelectionChanged();
+
+ // Keep this light, partsChanged is a heavy move! TEST p4.0.36 Try these, may need more.
+ if(type & (SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED |
+ SC_PART_INSERTED | SC_PART_REMOVED | SC_PART_MODIFIED |
+ SC_SIG | SC_TEMPO)) // Maybe sig. Requires tempo.
+ canvas->partsChanged();
+
+ //typeBox->setCurrentIndex(int(MusEGlobal::song->mtype())); // REMOVE Tim. Redundant.
+
if (type & SC_SIG)
time->redraw();
if (type & SC_TEMPO)
@@ -616,6 +629,14 @@ void Arranger::songChanged(int type)
}
}
}
+
+ // TEST p4.0.36 Try this
+ if(type & ( //SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED |
+ SC_PART_INSERTED | SC_PART_REMOVED | SC_PART_MODIFIED |
+ SC_EVENT_INSERTED | SC_EVENT_REMOVED | SC_EVENT_MODIFIED)) //|
+ //SC_SIG | SC_TEMPO)) // Maybe sig. and tempo. No, moved above.
+ canvas->redraw();
+
}
updateTrackInfo(type);
diff --git a/muse2/muse/arranger/arrangerview.cpp b/muse2/muse/arranger/arrangerview.cpp
index 3b726845..52be5194 100644
--- a/muse2/muse/arranger/arrangerview.cpp
+++ b/muse2/muse/arranger/arrangerview.cpp
@@ -37,7 +37,7 @@
#include <QMessageBox>
#include <QMimeData>
#include <QPushButton>
-#include <QResizeEvent>
+//#include <QResizeEvent>
#include <QScrollArea>
#include <QScrollBar>
#include <QSettings>
@@ -129,6 +129,7 @@ ArrangerView::ArrangerView(QWidget* parent)
connect(muse, SIGNAL(configChanged()), arranger, SLOT(configChanged()));
connect(arranger, SIGNAL(setUsedTool(int)), editTools, SLOT(set(int)));
connect(arranger, SIGNAL(selectionChanged()), SLOT(selectionChanged()));
+ connect(MusEGlobal::song, SIGNAL(songChanged(int)), visTracks, SLOT(updateVisibleTracksButtons()));
@@ -167,8 +168,8 @@ ArrangerView::ArrangerView(QWidget* parent)
scoreSubmenu = new QMenu(tr("Score"), this);
scoreSubmenu->setIcon(QIcon(*scoreIconSet));
- scoreAllInOneSubsubmenu = new QMenu(tr("all parts in one staff"), this);
- scoreOneStaffPerTrackSubsubmenu = new QMenu(tr("one staff per part"), this);
+ scoreAllInOneSubsubmenu = new QMenu(tr("all tracks in one staff"), this);
+ scoreOneStaffPerTrackSubsubmenu = new QMenu(tr("one staff per track"), this);
scoreSubmenu->addMenu(scoreAllInOneSubsubmenu);
scoreSubmenu->addMenu(scoreOneStaffPerTrackSubsubmenu);
@@ -193,6 +194,10 @@ ArrangerView::ArrangerView(QWidget* parent)
strGlobalInsertAction = new QAction(tr("Global Insert"), this);
strGlobalSplitAction = new QAction(tr("Global Split"), this);
+ strGlobalCutSelAction = new QAction(tr("Global Cut - selected tracks"), this);
+ strGlobalInsertSelAction = new QAction(tr("Global Insert - selected tracks"), this);
+ strGlobalSplitSelAction = new QAction(tr("Global Split - selected tracks"), this);
+
//-------------------------------------------------------------
@@ -246,7 +251,11 @@ ArrangerView::ArrangerView(QWidget* parent)
menuStructure->addAction(strGlobalCutAction);
menuStructure->addAction(strGlobalInsertAction);
menuStructure->addAction(strGlobalSplitAction);
-
+ menuStructure->addSeparator();
+ menuStructure->addAction(strGlobalCutSelAction);
+ menuStructure->addAction(strGlobalInsertSelAction);
+ menuStructure->addAction(strGlobalSplitSelAction);
+
QMenu* functions_menu = menuBar()->addMenu(tr("Functions"));
@@ -341,6 +350,9 @@ ArrangerView::ArrangerView(QWidget* parent)
connect(strGlobalCutAction, SIGNAL(activated()), SLOT(globalCut()));
connect(strGlobalInsertAction, SIGNAL(activated()), SLOT(globalInsert()));
connect(strGlobalSplitAction, SIGNAL(activated()), SLOT(globalSplit()));
+ connect(strGlobalCutSelAction, SIGNAL(activated()), SLOT(globalCutSel()));
+ connect(strGlobalInsertSelAction, SIGNAL(activated()), SLOT(globalInsertSel()));
+ connect(strGlobalSplitSelAction, SIGNAL(activated()), SLOT(globalSplitSel()));
@@ -351,7 +363,7 @@ ArrangerView::ArrangerView(QWidget* parent)
connect(cb, SIGNAL(dataChanged()), SLOT(clipboardChanged()));
connect(cb, SIGNAL(selectionChanged()), SLOT(clipboardChanged()));
-
+ MusEGlobal::muse->topwinMenuInited(this);
// work around for probable QT/WM interaction bug.
// for certain window managers, e.g xfce, this window is
@@ -368,7 +380,7 @@ ArrangerView::~ArrangerView()
void ArrangerView::closeEvent(QCloseEvent* e)
{
- emit deleted(static_cast<TopWin*>(this));
+ emit isDeleting(static_cast<TopWin*>(this));
emit closed();
e->accept();
}
@@ -729,4 +741,9 @@ void ArrangerView::globalCut() { MusECore::globalCut(); }
void ArrangerView::globalInsert() { MusECore::globalInsert(); }
void ArrangerView::globalSplit() { MusECore::globalSplit(); }
+// variants only applicable for selected tracks
+void ArrangerView::globalCutSel() { MusECore::globalCut(true); }
+void ArrangerView::globalInsertSel() { MusECore::globalInsert(true); }
+void ArrangerView::globalSplitSel() { MusECore::globalSplit(true); }
+
} // namespace MusEGui
diff --git a/muse2/muse/arranger/arrangerview.h b/muse2/muse/arranger/arrangerview.h
index de610bd6..c56767a6 100644
--- a/muse2/muse/arranger/arrangerview.h
+++ b/muse2/muse/arranger/arrangerview.h
@@ -89,7 +89,8 @@ class ArrangerView : public TopWin
QMenu* master;
QAction *strGlobalCutAction, *strGlobalInsertAction, *strGlobalSplitAction;
- QAction *trackMidiAction, *trackDrumAction, *trackWaveAction, *trackAOutputAction, *trackAGroupAction;
+ QAction *strGlobalCutSelAction, *strGlobalInsertSelAction, *strGlobalSplitSelAction;
+ QAction *trackMidiAction, *trackDrumAction, *trackWaveAction, *trackAOutputAction, *trackAGroupAction;
QAction *trackAInputAction, *trackAAuxAction;
QAction *editCutAction, *editCopyAction, *editCopyRangeAction;
QAction *editPasteAction, *editPasteCloneAction, *editPasteDialogAction, *editPasteCloneDialogAction;
@@ -119,11 +120,14 @@ class ArrangerView : public TopWin
void globalCut();
void globalInsert();
void globalSplit();
- void cmd(int);
+ void globalCutSel();
+ void globalInsertSel();
+ void globalSplitSel();
+ void cmd(int);
void addNewTrack(QAction* action);
signals:
- void deleted(MusEGui::TopWin*);
+ void isDeleting(MusEGui::TopWin*);
void closed();
public slots:
diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp
index d19fa082..f190de3b 100644
--- a/muse2/muse/arranger/pcanvas.cpp
+++ b/muse2/muse/arranger/pcanvas.cpp
@@ -3,7 +3,7 @@
// Linux Music Editor
// $Id: pcanvas.cpp,v 1.48.2.26 2009/11/22 11:08:33 spamatica Exp $
// (C) Copyright 1999 Werner Schweer (ws@seh.de)
-// (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -302,12 +302,9 @@ void PartCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
QPoint newpos = raster(QPoint(nx, ny));
selectItem(ci, true);
- MusECore::UndoOp operation=moveItem(ci, newpos, dtype);
- if (operation.type != MusECore::UndoOp::DoNothing)
- {
+ bool result=moveItem(operations, ci, newpos, dtype);
+ if (result)
ci->move(newpos);
- operations.push_back(operation);
- }
if(moving.size() == 1) {
itemReleased(curItem, newpos);
@@ -326,37 +323,41 @@ void PartCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
//---------------------------------------------------------
// Changed by T356.
-MusECore::UndoOp PartCanvas::moveItem(CItem* item, const QPoint& newpos, DragType t)
+bool PartCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& newpos, DragType t)
{
- MusECore::UndoOp result;
NPart* npart = (NPart*) item;
MusECore::Part* spart = npart->part();
MusECore::Track* track = npart->track();
+ MusECore::Track* dtrack=NULL;
unsigned dtick = newpos.x();
unsigned ntrack = y2pitch(item->mp().y());
MusECore::Track::TrackType type = track->type();
if (tracks->index(track) == ntrack && (dtick == spart->tick())) {
- return MusECore::UndoOp(MusECore::UndoOp::DoNothing);
+ return false;
}
if (ntrack >= tracks->size()) {
ntrack = tracks->size();
if (MusEGlobal::debugMsg)
printf("PartCanvas::moveItem - add new track\n");
- MusECore::Track* newTrack = MusEGlobal::song->addTrack(type); // Add at end of list.
+ dtrack = MusEGlobal::song->addTrack(operations, type); // Add at end of list.
+
if (type == MusECore::Track::WAVE) {
MusECore::WaveTrack* st = (MusECore::WaveTrack*) track;
- MusECore::WaveTrack* dt = (MusECore::WaveTrack*) newTrack;
+ MusECore::WaveTrack* dt = (MusECore::WaveTrack*) dtrack;
dt->setChannels(st->channels());
}
emit tracklistChanged();
}
- MusECore::Track* dtrack = tracks->index(ntrack);
- if (dtrack->type() != type) {
- QMessageBox::critical(this, QString("MusE"),
- tr("Cannot copy/move/clone to different Track-Type"));
- return MusECore::UndoOp(MusECore::UndoOp::DoNothing);
+ else
+ {
+ dtrack = tracks->index(ntrack);
+ if (dtrack->type() != type) {
+ QMessageBox::critical(this, QString("MusE"),
+ tr("Cannot copy/move/clone to different Track-Type"));
+ return false;
+ }
}
-
+
MusECore::Part* dpart;
bool clone = (t == MOVE_CLONE || (t == MOVE_COPY && spart->events()->arefCount() > 1));
@@ -397,22 +398,24 @@ MusECore::UndoOp PartCanvas::moveItem(CItem* item, const QPoint& newpos, DragTyp
if (t == MOVE_COPY || t == MOVE_CLONE) {
// These will not increment ref count, and will not chain clones...
// TODO FINDMICH: is this still correct (by flo93)? i doubt it!
- result=MusECore::UndoOp(MusECore::UndoOp::AddPart,dpart);
+ operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddPart,dpart));
}
else if (t == MOVE_MOVE) {
dpart->setSelected(spart->selected());
// These will increment ref count if not a clone, and will chain clones...
// TODO FINDMICH: is this still correct (by flo93)? i doubt it!
- result=MusECore::UndoOp(MusECore::UndoOp::ModifyPart,spart, dpart, true, false);
+ operations.push_back(MusECore::UndoOp(MusECore::UndoOp::ModifyPart,spart, dpart, true, false));
spart->setSelected(false);
}
- // else // will never happen -> result will always be defined
+ // else // will never happen -> operations will never be empty
if (MusEGlobal::song->len() < (dpart->lenTick() + dpart->tick()))
- MusEGlobal::song->setLen(dpart->lenTick() + dpart->tick());
-
- return result;
+ operations.push_back( MusECore::UndoOp(MusECore::UndoOp::ModifySongLen,
+ dpart->lenTick() + dpart->tick(),
+ MusEGlobal::song->len() ) );
+
+ return true;
}
//---------------------------------------------------------
@@ -883,8 +886,8 @@ void PartCanvas::mousePress(QMouseEvent* event)
default:
if (item)
emit trackChanged(item->part()->track());
- else
- emit trackChanged(NULL);
+ //else -- don't see the point of removing track selection, commenting out (rj)
+ // emit trackChanged(NULL);
break;
case CutTool:
if (item) splitItem(item, pt);
@@ -1193,7 +1196,7 @@ void PartCanvas::keyPress(QKeyEvent* event)
//If we're at topmost, leave
if (!track) {
- printf("no track above!\n");
+ //printf("no track above!\n");
return;
}
int middle = curItem->x() + curItem->part()->lenTick()/2;
@@ -1327,17 +1330,25 @@ void PartCanvas::keyPress(QKeyEvent* event)
curItem = newItem;
selectItem(newItem, true);
- //Check if we've hit the upper or lower boundaries of the window. If so, set a new position
+ //Check if we've hit the left, right, upper or lower boundaries of the window. If so, scroll to new position.
if (newItem->x() < mapxDev(0)) {
- int curpos = pos[0];
- setPos(0,newItem->x(),true);
- setPos(0,curpos,false); //Dummy to put the current position back once we've scrolled
+ emit horizontalScroll(rmapx(newItem->x() - xorg) - 10); // Leave some room.
+ }
+ else if (newItem->x() + newItem->width() > mapxDev(width())) {
+ int mx = rmapx(newItem->x());
+ int newx = mx + rmapx(newItem->width()) - width();
+ emit horizontalScroll( (newx > mx ? mx - 10 : newx + 10) - rmapx(xorg) );
+ }
+
+ if (newItem->y() < mapyDev(0)) {
+ int my = rmapy(newItem->y());
+ int newy = my + rmapy(newItem->height()) - height();
+ emit verticalScroll( (newy < my ? my - 10 : newy + 10) - rmapy(yorg) );
}
- else if (newItem->x() > mapxDev(width())) {
- int curpos = pos[0];
- setPos(0,newItem->x(),true);
- setPos(0,curpos,false); //Dummy to put the current position back once we've scrolled
+ else if (newItem->y() + newItem->height() > mapyDev(height())) {
+ emit verticalScroll( rmapy(newItem->y() + newItem->height() - yorg) - height() + 10);
}
+
redraw();
}
}
@@ -2299,9 +2310,9 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, MusECore::EventList* ev
//else
// color_brightness=64; // otherwise use dark color
if (brightness >= 12000 && !pt->selected())
- color_brightness=64; // 96; // too bright: use dark color
+ color_brightness=54; // 96; // too bright: use dark color
else
- color_brightness=190; //160; // too dark: use lighter color
+ color_brightness=200; //160; // too dark: use lighter color
}
else
color_brightness=80;
@@ -3207,9 +3218,13 @@ void PartCanvas::viewDropEvent(QDropEvent* event)
if (!track) { // we need to create a track for this drop
if (text.endsWith(".mpt", Qt::CaseInsensitive)) {
- track = MusEGlobal::song->addTrack(MusECore::Track::MIDI); // Add at end of list.
+ MusECore::Undo operations;
+ track = MusEGlobal::song->addTrack(operations, MusECore::Track::MIDI); // Add at end of list.
+ MusEGlobal::song->applyOperationGroup(operations);
} else {
- track = MusEGlobal::song->addTrack(MusECore::Track::WAVE); // Add at end of list.
+ MusECore::Undo operations;
+ track = MusEGlobal::song->addTrack(operations, MusECore::Track::WAVE); // Add at end of list.
+ MusEGlobal::song->applyOperationGroup(operations);
}
}
if (track->type() == MusECore::Track::WAVE &&
@@ -3634,7 +3649,8 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra
{
double y;
if (cl->valueType() == MusECore::VAL_LOG ) { // use db scale for volume
- y = dbToVal(cl->curVal()); // represent volume between 0 and 1
+ //printf("log conversion val=%f min=%f max=%f\n", cl->curVal(), min, max);
+ y = logToVal(cl->curVal(), min, max); // represent volume between 0 and 1
if (y < 0) y = 0.0;
}
else
@@ -3647,7 +3663,8 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra
{
double y = ic->second.val;
if (cl->valueType() == MusECore::VAL_LOG ) { // use db scale for volume
- y = dbToVal(y); // represent volume between 0 and 1
+ //printf("log conversion val=%f min=%f max=%f\n", cl->curVal(), min, max);
+ y = logToVal(y, min, max); // represent volume between 0 and 1
if (y < 0) y = 0.0;
}
else
@@ -3746,7 +3763,7 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo
{
double y;
if (cl->valueType() == MusECore::VAL_LOG ) { // use db scale for volume
- y = dbToVal(cl->curVal()); // represent volume between 0 and 1
+ y = logToVal(cl->curVal(), min, max); // represent volume between 0 and 1
if (y < 0) y = 0.0;
}
else
@@ -3759,7 +3776,7 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo
{
double y = ic->second.val;
if (cl->valueType() == MusECore::VAL_LOG ) { // use db scale for volume
- y = dbToVal(y); // represent volume between 0 and 1
+ y = logToVal(y, min, max); // represent volume between 0 and 1
if (y < 0) y = 0;
}
else
@@ -3951,7 +3968,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
automation.currentCtrlList->range(&min,&max);
double cvval;
if (automation.currentCtrlList->valueType() == MusECore::VAL_LOG ) { // use db scale for volume
- cvval = valToDb(yfraction);
+ printf("log conversion val=%f min=%f max=%f\n", yfraction, min, max);
+ cvval = valToLog(yfraction, min, max);
//printf("calc yfraction = %f v=%f ",yfraction,cvval);
if (cvval< min) cvval=min;
if (cvval>max) cvval=max;
@@ -3984,13 +4002,45 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
}
-double PartCanvas::dbToVal(double inDb)
+//---------------------------------------------------------
+//
+// logToVal
+// - represent logarithmic value on linear scale from 0 to 1
+//
+//---------------------------------------------------------
+double PartCanvas::logToVal(double inLog, double min, double max)
{
- return (20.0*MusECore::fast_log10(inDb)+60.0) / 70.0;
+ //printf("logToVal inLog %f :", inLog);
+ if (inLog < min) inLog = min;
+ if (inLog > max) inLog = max;
+ double linMin = 20.0*MusECore::fast_log10(min);
+ double linMax = 20.0*MusECore::fast_log10(max);
+ double linVal = 20.0*MusECore::fast_log10(inLog);
+
+ double outVal = (linVal-linMin) / (linMax - linMin);
+ // printf("inLog %f outVal %f linVal %f min %f max %f dbMin %f dbMax %f\n", inLog, outVal, linVal, min, max, linMin, linMax);
+
+ return outVal;
}
-double PartCanvas::valToDb(double inV)
+
+//---------------------------------------------------------
+//
+// valToLog
+// - represent value from 0 to 1 as logarithmic value between min and max
+//
+//---------------------------------------------------------
+double PartCanvas::valToLog(double inV, double min, double max)
{
- return exp10((inV*70.0-60.0)/20.0);
+ double linMin = 20.0*MusECore::fast_log10(min);
+ double linMax = 20.0*MusECore::fast_log10(max);
+
+ double linVal = (inV * (linMax - linMin)) + linMin;
+ double outVal = exp10((linVal)/20.0);
+
+ //printf("::valToLog inV %f outVal %f linVal %f min %f max %f\n", inV, outVal, linVal, min, max);
+ if (outVal > max) outVal = max;
+ if (outVal < min) outVal = min;
+ return outVal;
}
//---------------------------------------------------------
diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h
index 78b88a5c..34395688 100644
--- a/muse2/muse/arranger/pcanvas.h
+++ b/muse2/muse/arranger/pcanvas.h
@@ -119,7 +119,7 @@ class PartCanvas : public Canvas {
virtual void newItem(CItem*,bool);
virtual bool deleteItem(CItem*);
virtual void moveCanvasItems(CItemList&, int, int, DragType);
- virtual MusECore::UndoOp moveItem(CItem*, const QPoint&, DragType);
+ virtual bool moveItem(MusECore::Undo& operations, CItem*, const QPoint&, DragType);
virtual void updateSong(DragType, int);
virtual void startDrag(CItem*, DragType);
@@ -148,8 +148,8 @@ class PartCanvas : public Canvas {
void checkAutomation(MusECore::Track * t, const QPoint& pointer, bool addNewCtrl);
void processAutomationMovements(QPoint pos, bool addPoint);
- double dbToVal(double inDb);
- double valToDb(double inV);
+ double logToVal(double inLog, double min, double max);
+ double valToLog(double inV, double min, double max);
protected:
virtual void drawCanvas(QPainter&, const QRect&);
diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp
index 1e3ad419..620a24b7 100644
--- a/muse2/muse/arranger/tlist.cpp
+++ b/muse2/muse/arranger/tlist.cpp
@@ -62,6 +62,7 @@
#include "synth.h"
#include "config.h"
#include "popupmenu.h"
+#include "menutitleitem.h"
#ifdef DSSI_SUPPORT
#include "dssihost.h"
@@ -392,7 +393,7 @@ void TList::paint(const QRect& r)
countVisible++;
}
//int count = ((MusECore::AudioTrack*)track)->controller()->size(); //commented out by flo: gives a "unused variable" warning
- s.sprintf(" %d(%d) visible",countVisible, countAll);
+ s.sprintf(" %d(%d) %s",countVisible, countAll, tr("visible").toAscii().data());
}
@@ -584,12 +585,17 @@ void TList::portsPopupMenu(MusECore::Track* t, int x, int y)
switch(t->type()) {
case MusECore::Track::MIDI:
case MusECore::Track::DRUM:
+ // FINDMICHJETZT: this is a notice for flo's experimental
+ // branch! don't forget NEW_DRUM here!
+ // please don't remove this. i'll do it when
+ // the time is there.
case MusECore::Track::AUDIO_SOFTSYNTH:
{
MusECore::MidiTrack* track = (MusECore::MidiTrack*)t;
//QPopupMenu* p = MusECore::midiPortsPopup(0);
MusECore::MidiDevice* md = 0;
+ int potential_new_port_no=-1;
int port = -1;
if(t->type() == MusECore::Track::AUDIO_SOFTSYNTH)
{
@@ -602,25 +608,158 @@ void TList::portsPopupMenu(MusECore::Track* t, int x, int y)
port = track->outPort();
QMenu* p = MusECore::midiPortsPopup(this, port); // 0, port);
+
+ if (t->type()==MusECore::Track::MIDI || t->type()==MusECore::Track::DRUM) //FINDMICHJETZT
+ {
+ // extend that menu a bit
+
+
+ // find first free port number
+ // do not permit numbers already used in other tracks!
+ // except if it's only used in this track.
+ int no;
+ for (no=0;no<MIDI_PORTS;no++)
+ if (MusEGlobal::midiPorts[no].device()==NULL)
+ {
+ MusECore::ciTrack it;
+ for (it=MusEGlobal::song->tracks()->begin(); it!=MusEGlobal::song->tracks()->end(); it++)
+ {
+ MusECore::MidiTrack* mt=dynamic_cast<MusECore::MidiTrack*>(*it);
+ if (mt && mt!=t && mt->outPort()==no)
+ break;
+ }
+ if (it == MusEGlobal::song->tracks()->end())
+ break;
+ }
+
+ if (no==MIDI_PORTS)
+ {
+ delete p;
+ printf("THIS IS VERY UNLIKELY TO HAPPEN: no free midi ports! you have used all %i!\n",MIDI_PORTS);
+ break;
+ }
+
+
+ potential_new_port_no=no;
+ typedef std::map<std::string, int > asmap;
+ typedef std::map<std::string, int >::iterator imap;
+
+ asmap mapALSA;
+ asmap mapJACK;
+
+ int aix = 0x10000000;
+ int jix = 0x20000000;
+ for(MusECore::iMidiDevice i = MusEGlobal::midiDevices.begin(); i != MusEGlobal::midiDevices.end(); ++i)
+ {
+ if((*i)->deviceType() == MusECore::MidiDevice::ALSA_MIDI)
+ {
+ // don't add devices which are used somewhere
+ int j;
+ for (j=0;j<MIDI_PORTS;j++)
+ if (MusEGlobal::midiPorts[j].device() == *i)
+ break;
+
+ if (j==MIDI_PORTS) mapALSA.insert( std::pair<std::string, int> (std::string((*i)->name().toLatin1().constData()), aix) );
+
+ ++aix;
+ }
+ else if((*i)->deviceType() == MusECore::MidiDevice::JACK_MIDI)
+ {
+ // don't add devices which are used somewhere
+ int j;
+ for (j=0;j<MIDI_PORTS;j++)
+ if (MusEGlobal::midiPorts[j].device() == *i)
+ break;
+
+ if (j==MIDI_PORTS) mapJACK.insert( std::pair<std::string, int> (std::string((*i)->name().toLatin1().constData()), jix) );
+ ++jix;
+ }
+ }
+
+ if (!mapALSA.empty() || !mapJACK.empty())
+ {
+ QMenu* pup = p->addMenu(tr("Unused Devices"));
+ QAction* act;
+
+
+ if (!mapALSA.empty())
+ {
+ pup->addAction(new MusEGui::MenuTitleItem("ALSA:", pup));
+
+ for(imap i = mapALSA.begin(); i != mapALSA.end(); ++i)
+ {
+ int idx = i->second;
+ QString s(i->first.c_str());
+ MusECore::MidiDevice* md = MusEGlobal::midiDevices.find(s, MusECore::MidiDevice::ALSA_MIDI);
+ if(md)
+ {
+ if(md->deviceType() != MusECore::MidiDevice::ALSA_MIDI)
+ continue;
+
+ act = pup->addAction(md->name());
+ act->setData(idx);
+ }
+ }
+ }
+
+ if (!mapALSA.empty() && !mapJACK.empty())
+ pup->addSeparator();
+
+ if (!mapJACK.empty())
+ {
+ pup->addAction(new MusEGui::MenuTitleItem("JACK:", pup));
+
+ for(imap i = mapJACK.begin(); i != mapJACK.end(); ++i)
+ {
+ int idx = i->second;
+ QString s(i->first.c_str());
+ MusECore::MidiDevice* md = MusEGlobal::midiDevices.find(s, MusECore::MidiDevice::JACK_MIDI);
+ if(md)
+ {
+ if(md->deviceType() != MusECore::MidiDevice::JACK_MIDI)
+ continue;
+
+ act = pup->addAction(md->name());
+ act->setData(idx);
+ }
+ }
+ }
+ }
+ }
+
+
QAction* act = p->exec(mapToGlobal(QPoint(x, y)), 0);
if(!act)
{
delete p;
break;
}
-
+
+ QString acttext=act->text();
int n = act->data().toInt();
delete p;
if(n < 0) // Invalid item.
break;
- if(n >= MIDI_PORTS) // Show port config dialog.
+ if(n == MIDI_PORTS) // Show port config dialog.
{
MusEGlobal::muse->configMidiPorts();
break;
}
+ else if (n & 0x30000000)
+ {
+ int typ;
+ if (n & 0x10000000)
+ typ = MusECore::MidiDevice::ALSA_MIDI;
+ else
+ typ = MusECore::MidiDevice::JACK_MIDI;
+ MusECore::MidiDevice* sdev = MusEGlobal::midiDevices.find(acttext, typ);
+
+ MusEGlobal::midiSeq->msgSetMidiDevice(&MusEGlobal::midiPorts[potential_new_port_no], sdev);
+ n=potential_new_port_no;
+ }
// Changed by T356.
//track->setOutPort(n);
//MusEGlobal::audio->msgSetTrackOutPort(track, n);
@@ -1049,7 +1188,7 @@ void TList::mousePressEvent(QMouseEvent* ev)
if(act)
{
t = MusEGlobal::song->addNewTrack(act); // Add at end of list.
- if(t)
+ if(t && t->isVisible())
{
MusEGlobal::song->deselectTracks();
t->setSelected(true);
@@ -1064,13 +1203,13 @@ void TList::mousePressEvent(QMouseEvent* ev)
//delete synp;
delete p;
}
- else if (button == Qt::LeftButton) {
+ /*else if (button == Qt::LeftButton) {
if (!ctrl)
{
MusEGlobal::song->deselectTracks();
emit selectionChanged(0);
}
- }
+ }*/
return;
}
@@ -1108,7 +1247,8 @@ void TList::mousePressEvent(QMouseEvent* ev)
return;
}
- mode = START_DRAG;
+
+ mode = NORMAL;
switch (col) {
case COL_CLEF:
@@ -1137,8 +1277,8 @@ void TList::mousePressEvent(QMouseEvent* ev)
}
delete p;
}
-
break;
+
case COL_AUTOMATION:
{
if (!t->isMidiTrack()) {
@@ -1174,6 +1314,8 @@ void TList::mousePressEvent(QMouseEvent* ev)
case COL_RECORD:
{
+ mode = START_DRAG;
+
bool val = !(t->recordFlag());
if (button == Qt::LeftButton) {
if (!t->isMidiTrack()) {
@@ -1212,6 +1354,7 @@ void TList::mousePressEvent(QMouseEvent* ev)
}
break;
case COL_NONE:
+ mode = START_DRAG;
break;
case COL_CLASS:
if (t->isMidiTrack())
@@ -1232,9 +1375,10 @@ void TList::mousePressEvent(QMouseEvent* ev)
//MusEGlobal::audio->msgUpdateSoloStates(); // p4.0.14
//MusEGlobal::song->update(SC_ROUTE); //
-
break;
+
case COL_MUTE:
+ mode = START_DRAG;
// p3.3.29
if ((button == Qt::RightButton) || (((QInputEvent*)ev)->modifiers() & Qt::ShiftModifier))
t->setOff(!t->off());
@@ -1248,11 +1392,13 @@ void TList::mousePressEvent(QMouseEvent* ev)
MusEGlobal::song->update(SC_MUTE);
break;
case COL_SOLO:
+ mode = START_DRAG;
MusEGlobal::audio->msgSetSolo(t, !t->solo());
MusEGlobal::song->update(SC_SOLO);
break;
case COL_NAME:
+ mode = START_DRAG;
if (button == Qt::LeftButton) {
if (!ctrl) {
MusEGlobal::song->deselectTracks();
@@ -1327,11 +1473,13 @@ void TList::mousePressEvent(QMouseEvent* ev)
break;
case COL_TIMELOCK:
+ mode = START_DRAG;
t->setLocked(!t->locked());
break;
case COL_OCHANNEL:
{
+ mode = START_DRAG; // or not? (flo)
int delta = 0;
if (button == Qt::RightButton)
delta = 1;
@@ -1397,6 +1545,9 @@ void TList::mousePressEvent(QMouseEvent* ev)
}
}
break;
+
+ default:
+ mode = START_DRAG;
}
redraw();
}
diff --git a/muse2/muse/audio.cpp b/muse2/muse/audio.cpp
index fd90c2c2..0b1574cc 100644
--- a/muse2/muse/audio.cpp
+++ b/muse2/muse/audio.cpp
@@ -25,8 +25,6 @@
#include <cmath>
#include <errno.h>
-#include <QSocketNotifier>
-
#include "app.h"
#include "song.h"
#include "node.h"
@@ -51,10 +49,18 @@
namespace MusEGlobal {
MusECore::Audio* audio;
MusECore::AudioDevice* audioDevice; // current audio device in use
-extern unsigned int volatile midiExtSyncTicks; // p3.3.25
+extern unsigned int volatile midiExtSyncTicks;
}
namespace MusECore {
+
+
+void initAudio()
+{
+ MusEGlobal::audio = new Audio();
+}
+
+
extern double curTime();
//static const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 };
@@ -166,8 +172,11 @@ Audio::Audio()
exit(-1);
}
sigFd = filedes[1];
- QSocketNotifier* ss = new QSocketNotifier(filedes[0], QSocketNotifier::Read);
- MusEGlobal::song->connect(ss, SIGNAL(activated(int)), MusEGlobal::song, SLOT(seqSignal(int)));
+ sigFdr = filedes[0];
+
+ // Moved to MusE::MusE
+ //QSocketNotifier* ss = new QSocketNotifier(filedes[0], QSocketNotifier::Read);
+ //MusEGlobal::song->connect(ss, SIGNAL(activated(int)), MusEGlobal::song, SLOT(seqSignal(int)));
}
//---------------------------------------------------------
@@ -182,7 +191,9 @@ bool Audio::start()
//process(MusEGlobal::segmentSize); // warm up caches
state = STOP;
_loopCount = 0;
- MusEGlobal::muse->setHeartBeat();
+
+ MusEGlobal::muse->setHeartBeat();
+
if (MusEGlobal::audioDevice) {
//_running = true;
//MusEGlobal::audioDevice->start();
@@ -221,9 +232,11 @@ bool Audio::start()
// shall we really stop JACK transport and locate to
// saved position?
- MusEGlobal::audioDevice->stopTransport();
+ MusEGlobal::audioDevice->stopTransport();
+
//MusEGlobal::audioDevice->seekTransport(MusEGlobal::song->cPos().frame());
- MusEGlobal::audioDevice->seekTransport(MusEGlobal::song->cPos());
+ MusEGlobal::audioDevice->seekTransport(MusEGlobal::song->cPos());
+
return true;
}
@@ -531,6 +544,26 @@ void Audio::process1(unsigned samplePos, unsigned offset, unsigned frames)
// Pre-process the metronome.
((AudioTrack*)metronome)->preProcessAlways();
+ // Process Aux tracks first.
+ for(ciTrack it = tl->begin(); it != tl->end(); ++it)
+ {
+ if((*it)->isMidiTrack())
+ continue;
+ track = (AudioTrack*)(*it);
+ if(!track->processed() && track->type() == Track::AUDIO_AUX)
+ {
+ //printf("Audio::process1 Do aux: track:%s\n", track->name().toLatin1().constData());
+ channels = track->channels();
+ // Just a dummy buffer.
+ float* buffer[channels];
+ float data[frames * channels];
+ for (int i = 0; i < channels; ++i)
+ buffer[i] = data + i * frames;
+ //printf("Audio::process1 calling track->copyData for track:%s\n", track->name().toLatin1());
+ track->copyData(samplePos, channels, -1, -1, frames, buffer);
+ }
+ }
+
OutputList* ol = MusEGlobal::song->outputs();
for (ciAudioOutput i = ol->begin(); i != ol->end(); ++i)
(*i)->process(samplePos, offset, frames);
@@ -548,8 +581,11 @@ void Audio::process1(unsigned samplePos, unsigned offset, unsigned frames)
track = (AudioTrack*)(*it);
// Ignore unprocessed tracks which have an output route, because they will be processed by
// whatever track(s) they are routed to.
- if(!track->processed() && track->noOutRoute() && (track->type() != Track::AUDIO_OUTPUT))
+ //if(!track->processed() && track->noOutRoute() && (track->type() != Track::AUDIO_OUTPUT))
+ // No, do all.
+ if(!track->processed() && (track->type() != Track::AUDIO_OUTPUT))
{
+ //printf("Audio::process1 track:%s\n", track->name().toLatin1().constData());
channels = track->channels();
// Just a dummy buffer.
float* buffer[channels];
diff --git a/muse2/muse/audio.h b/muse2/muse/audio.h
index 8d89be78..3c4eb17d 100644
--- a/muse2/muse/audio.h
+++ b/muse2/muse/audio.h
@@ -166,7 +166,9 @@ class Audio {
int fromThreadFdw, fromThreadFdr; // message pipe
int sigFd; // pipe fd for messages to gui
-
+ //QSocketNotifier* _socketNotifier;
+ int sigFdr;
+
// record values:
Pos startRecordPos;
Pos endRecordPos;
@@ -189,8 +191,12 @@ class Audio {
public:
Audio();
- virtual ~Audio() {}
+ virtual ~Audio() { }
+ // Access to message pipe (like from gui namespace), otherwise audio would need to depend on gui.
+ int getFromThreadFdw() { return sigFd; }
+ int getFromThreadFdr() { return sigFdr; }
+
void process(unsigned frames);
bool sync(int state, unsigned frame);
void shutdown();
diff --git a/muse2/muse/audioprefetch.cpp b/muse2/muse/audioprefetch.cpp
index 9406911f..1fcb7cef 100644
--- a/muse2/muse/audioprefetch.cpp
+++ b/muse2/muse/audioprefetch.cpp
@@ -39,7 +39,11 @@ MusECore::AudioPrefetch* audioPrefetch;
namespace MusECore {
-// Added by Tim. p3.3.20
+void initAudioPrefetch()
+{
+ MusEGlobal::audioPrefetch = new AudioPrefetch("Prefetch");
+}
+
//#define AUDIOPREFETCH_DEBUG
enum { PREFETCH_TICK, PREFETCH_SEEK
@@ -140,6 +144,7 @@ void AudioPrefetch::msgTick()
{
PrefetchMsg msg;
msg.id = PREFETCH_TICK;
+ msg.pos = 0; // seems to be unused, was uninitalized.
while (sendMsg1(&msg, sizeof(msg))) {
printf("AudioPrefetch::msgTick(): send failed!\n");
}
diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp
index b674e20c..aceacc75 100644
--- a/muse2/muse/audiotrack.cpp
+++ b/muse2/muse/audiotrack.cpp
@@ -107,7 +107,7 @@ AudioTrack::AudioTrack(TrackType t)
_automationType = AUTO_OFF;
//setChannels(1);
setChannels(2);
- addController(new CtrlList(AC_VOLUME,"Volume",0.0,3.16 /* roughly 10 db */, VAL_LOG));
+ addController(new CtrlList(AC_VOLUME,"Volume",0.001,3.163 /* roughly 10 db */, VAL_LOG));
addController(new CtrlList(AC_PAN, "Pan", -1.0, 1.0, VAL_LINEAR));
addController(new CtrlList(AC_MUTE,"Mute",0.0,1.0, VAL_LINEAR, true /*dont show in arranger */));
@@ -1610,8 +1610,40 @@ void AudioAux::read(Xml& xml)
// getData
//---------------------------------------------------------
-bool AudioAux::getData(unsigned /*pos*/, int ch, unsigned /*samples*/, float** data)
+bool AudioAux::getData(unsigned pos, int ch, unsigned samples, float** data)
{
+ // Make sure all the aux-supporting tracks are processed first so aux data is gathered. p4.0.37
+ TrackList* tl = MusEGlobal::song->tracks();
+ AudioTrack* track;
+ for(ciTrack it = tl->begin(); it != tl->end(); ++it)
+ {
+ if((*it)->isMidiTrack())
+ continue;
+ track = (AudioTrack*)(*it);
+ // If there are any Aux route paths to the track, defer processing until the second main track processing pass.
+ if(!track->processed() && track->hasAuxSend() && !track->auxRefCount())
+ {
+ int chans = track->channels();
+ // Just a dummy buffer.
+ float* buff[chans];
+ float buff_data[samples * chans];
+ for (int i = 0; i < chans; ++i)
+ buff[i] = buff_data + i * samples;
+
+ //printf("AudioAux::getData name:%s\n calling copyData on:%s auxRefCount:%d\n",
+ // name().toLatin1().constData(), track->name().toLatin1().constData(), track->auxRefCount());
+
+ track->copyData(pos, chans, -1, -1, samples, buff);
+
+ /* float* buff[ch];
+ float buff_data[samples * ch];
+ for (int i = 0; i < ch; ++i)
+ buff[i] = buff_data + i * samples;
+ //printf("Audio::process1 calling track->copyData for track:%s\n", track->name().toLatin1());
+ track->copyData(pos, ch, -1, -1, samples, buff); */
+ }
+ }
+
for (int i = 0; i < ch; ++i)
data[i] = buffer[i % channels()];
return true;
diff --git a/muse2/muse/cliplist/cliplist.cpp b/muse2/muse/cliplist/cliplist.cpp
index 1055f449..60041dae 100644
--- a/muse2/muse/cliplist/cliplist.cpp
+++ b/muse2/muse/cliplist/cliplist.cpp
@@ -32,6 +32,7 @@
#include "wave.h"
#include "xml.h"
#include "ui_cliplisteditorbase.h"
+#include "app.h"
namespace MusEGui {
@@ -168,6 +169,7 @@ ClipListEdit::ClipListEdit(QWidget* parent)
connect(editor->len, SIGNAL(valueChanged(const MusECore::Pos&)), SLOT(lenChanged(const MusECore::Pos&)));
updateList();
+ MusEGlobal::muse->topwinMenuInited(this);
}
ClipListEdit::~ClipListEdit()
diff --git a/muse2/muse/cobject.cpp b/muse2/muse/cobject.cpp
index 80fc7eae..50586d45 100644
--- a/muse2/muse/cobject.cpp
+++ b/muse2/muse/cobject.cpp
@@ -50,7 +50,7 @@ bool TopWin::initInited=false;
TopWin::TopWin(ToplevelType t, QWidget* parent, const char* name, Qt::WindowFlags f)
: QMainWindow(parent, f)
{
- _isDeleting = false;
+ _isDeleting = false;
if (initInited==false)
initConfiguration();
@@ -78,7 +78,10 @@ TopWin::TopWin(ToplevelType t, QWidget* parent, const char* name, Qt::WindowFlag
mdisubwin=NULL;
_sharesToolsAndMenu=_defaultSubwin[_type] ? _sharesWhenSubwin[_type] : _sharesWhenFree[_type];
if (_defaultSubwin[_type])
+ {
setIsMdiWin(true);
+ _savedToolbarState=_toolbarNonsharedInit[_type];
+ }
if (_sharesToolsAndMenu)
menuBar()->hide();
@@ -125,7 +128,11 @@ void TopWin::readStatus(MusECore::Xml& xml)
if (!sharesToolsAndMenu())
{
if (!restoreState(QByteArray::fromHex(xml.parse1().toAscii())))
- fprintf(stderr,"ERROR: couldn't restore toolbars. however, this is not really a problem.\n");
+ {
+ fprintf(stderr,"ERROR: couldn't restore toolbars. trying default configuration...\n");
+ if (!restoreState(_toolbarNonsharedInit[_type]))
+ fprintf(stderr,"ERROR: couldn't restore default toolbars. this is not really a problem.\n");
+ }
}
else
{
@@ -565,4 +572,15 @@ void TopWin::resize(const QSize& s)
resize(s.width(), s.height());
}
+TopWin* ToplevelList::findType(TopWin::ToplevelType type) const
+{
+ for (ciToplevel i = begin(); i != end(); ++i)
+ {
+ if((*i)->type() == type)
+ return (*i);
+ }
+ return 0;
+}
+
+
} // namespace MusEGui
diff --git a/muse2/muse/cobject.h b/muse2/muse/cobject.h
index 309d8424..f6ea2ce1 100644
--- a/muse2/muse/cobject.h
+++ b/muse2/muse/cobject.h
@@ -141,9 +141,21 @@ class TopWin : public QMainWindow
};
-typedef std::list <TopWin*> ToplevelList;
-typedef ToplevelList::iterator iToplevel;
-typedef ToplevelList::const_iterator ciToplevel;
+//---------------------------------------------------------
+// ToplevelList
+//---------------------------------------------------------
+
+//typedef std::list <TopWin*> ToplevelList;
+//typedef ToplevelList::iterator iToplevel;
+//typedef ToplevelList::const_iterator ciToplevel;
+
+typedef std::list<TopWin*>::iterator iToplevel;
+typedef std::list<TopWin*>::const_iterator ciToplevel;
+
+class ToplevelList : public std::list<TopWin* > {
+ public:
+ TopWin* findType(TopWin::ToplevelType) const;
+ };
} // namespace MusEGui
diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp
index c11adf7b..ea2b33f3 100644
--- a/muse2/muse/conf.cpp
+++ b/muse2/muse/conf.cpp
@@ -220,7 +220,7 @@ static void readPortChannel(Xml& xml, int midiPort)
// readConfigMidiPort
//---------------------------------------------------------
-static void readConfigMidiPort(Xml& xml)
+static void readConfigMidiPort(Xml& xml, bool skipConfig)
{
int idx = 0;
QString device;
@@ -234,11 +234,9 @@ static void readConfigMidiPort(Xml& xml)
// FIXME: TODO: Make this user-configurable!
QString instrument("GM");
+ int rwFlags = 3;
int openFlags = 1;
- bool thruFlag = false;
- //int dic = 0;
- //int doc = 0;
- int dic = -1; // p4.0.17
+ int dic = -1;
int doc = -1;
MidiSyncInfo tmpSi;
@@ -251,6 +249,19 @@ static void readConfigMidiPort(Xml& xml)
QString tag = xml.s1();
switch (token) {
case Xml::TagStart:
+
+ // skipConfig added so it doesn't overwrite midi ports. p4.0.41 Tim.
+ // Try to keep the controller information. But, this may need to be moved below.
+ // Also may want to try to keep sync info, but that's a bit risky, so let's not for now.
+ if (tag == "channel") {
+ readPortChannel(xml, idx);
+ break;
+ }
+ else if (skipConfig){
+ xml.skip(tag);
+ break;
+ }
+
if (tag == "name")
device = xml.parse1();
else if (tag == "type")
@@ -262,6 +273,8 @@ static void readConfigMidiPort(Xml& xml)
}
else if (tag == "openFlags")
openFlags = xml.parseInt();
+ else if (tag == "rwFlags") // Jack midi devs need this. p4.0.41
+ rwFlags = xml.parseInt();
else if (tag == "defaultInChans")
dic = xml.parseInt();
else if (tag == "defaultOutChans")
@@ -270,16 +283,15 @@ static void readConfigMidiPort(Xml& xml)
tmpSi.read(xml);
else if (tag == "instrument") {
instrument = xml.parse1();
- // Moved by Tim.
- //MusEGlobal::midiPorts[idx].setInstrument(
+ //MusEGlobal::midiPorts[idx].setInstrument( // Moved below
// registerMidiInstrument(instrument)
// );
}
else if (tag == "midithru")
- thruFlag = xml.parseInt(); // obsolete
- else if (tag == "channel") {
- readPortChannel(xml, idx);
- }
+ xml.parseInt(); // obsolete
+ //else if (tag == "channel") {
+ // readPortChannel(xml, idx); // Moved above
+ // }
else
xml.unknown("MidiDevice");
break;
@@ -290,6 +302,10 @@ static void readConfigMidiPort(Xml& xml)
break;
case Xml::TagEnd:
if (tag == "midiport") {
+
+ if(skipConfig) // p4.0.41
+ return;
+
//if (idx > MIDI_PORTS) {
if (idx < 0 || idx >= MIDI_PORTS) {
fprintf(stderr, "bad midi port %d (>%d)\n",
@@ -305,9 +321,8 @@ static void readConfigMidiPort(Xml& xml)
if(!dev && type == MidiDevice::JACK_MIDI)
{
if(MusEGlobal::debugMsg)
- fprintf(stderr, "readConfigMidiPort: creating jack midi device %s\n", device.toLatin1().constData());
- //dev = MidiJackDevice::createJackMidiDevice(device, openFlags);
- dev = MidiJackDevice::createJackMidiDevice(device); // p3.3.55
+ fprintf(stderr, "readConfigMidiPort: creating jack midi device %s with rwFlags:%d\n", device.toLatin1().constData(), rwFlags);
+ dev = MidiJackDevice::createJackMidiDevice(device, rwFlags);
}
if(MusEGlobal::debugMsg && !dev)
@@ -315,7 +330,7 @@ static void readConfigMidiPort(Xml& xml)
MidiPort* mp = &MusEGlobal::midiPorts[idx];
- mp->setInstrument(registerMidiInstrument(instrument)); // By Tim.
+ mp->setInstrument(registerMidiInstrument(instrument));
if(dic != -1) // p4.0.17 Leave them alone unless set by song.
mp->setDefaultInChannels(dic);
if(doc != -1)
@@ -480,7 +495,7 @@ static void loadConfigMetronom(Xml& xml)
// readSeqConfiguration
//---------------------------------------------------------
-static void readSeqConfiguration(Xml& xml)
+static void readSeqConfiguration(Xml& xml, bool skipConfig)
{
for (;;) {
Xml::Token token = xml.parse();
@@ -492,7 +507,7 @@ static void readSeqConfiguration(Xml& xml)
if (tag == "metronom")
loadConfigMetronom(xml);
else if (tag == "midiport")
- readConfigMidiPort(xml);
+ readConfigMidiPort(xml, skipConfig);
else if (tag == "rcStop")
MusEGlobal::rcStopNote = xml.parseInt();
else if (tag == "rcEnable")
@@ -542,7 +557,7 @@ void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig
midiport configuration and VOLUME.
*/
if (tag == "sequencer") {
- readSeqConfiguration(xml);
+ readSeqConfiguration(xml, readOnlySequencer);
break;
}
else if (readOnlySequencer) {
@@ -580,8 +595,10 @@ void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig
MidiTrack::setVisible((bool)xml.parseInt());
else if (tag == "inputTracksVisible")
AudioInput::setVisible((bool)xml.parseInt());
- else if (tag == "outputTracksVisible")
+ else if (tag == "outputTracksVisible") {
+ printf("output track set from config!\n");
AudioOutput::setVisible((bool)xml.parseInt());
+ }
else if (tag == "synthTracksVisible")
SynthI::setVisible((bool)xml.parseInt());
else if (tag == "bigtimeVisible")
@@ -624,7 +641,18 @@ void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig
MusEGlobal::config.geometryTransport = readGeometry(xml, tag);
else if (tag == "geometryBigTime")
MusEGlobal::config.geometryBigTime = readGeometry(xml, tag);
-
+ else if (tag == "Mixer") {
+ if(mixers == 0)
+ MusEGlobal::config.mixer1.read(xml);
+ else
+ MusEGlobal::config.mixer2.read(xml);
+ ++mixers;
+ }
+ else if (tag == "geometryMain")
+ MusEGlobal::config.geometryMain = readGeometry(xml, tag);
+
+ // don't insert else if(...) clauses between
+ // this line and "Global config stuff begins here".
else if (!doReadGlobalConfig) {
xml.skip(tag);
break;
@@ -636,9 +664,6 @@ void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig
// ---- Global config stuff begins here ----
- else if (tag == "geometryMain")
- MusEGlobal::config.geometryMain = readGeometry(xml, tag);
-
else if (tag == "theme")
MusEGlobal::config.style = xml.parse1();
else if (tag == "styleSheetFile")
@@ -847,20 +872,6 @@ void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig
MusEGlobal::config.canvasBgPixmap = xml.parse1();
else if (tag == "canvasCustomBgList")
MusEGlobal::config.canvasCustomBgList = xml.parse1().split(";", QString::SkipEmptyParts);
-
- //else if (tag == "mixer1")
- // MusEGlobal::config.mixer1.read(xml);
- //else if (tag == "mixer2")
- // MusEGlobal::config.mixer2.read(xml);
- else if (tag == "Mixer")
- {
- if(mixers == 0)
- MusEGlobal::config.mixer1.read(xml);
- else
- MusEGlobal::config.mixer2.read(xml);
- ++mixers;
- }
-
else if (tag == "bigtimeForegroundcolor")
MusEGlobal::config.bigTimeForegroundColor = readColor(xml);
else if (tag == "bigtimeBackgroundcolor")
@@ -932,8 +943,8 @@ void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig
MusEGlobal::config.minControlProcessPeriod = xml.parseUInt();
else if (tag == "guiRefresh")
MusEGlobal::config.guiRefresh = xml.parseInt();
- else if (tag == "userInstrumentsDir")
- MusEGlobal::config.userInstrumentsDir = xml.parse1();
+ else if (tag == "userInstrumentsDir") // Obsolete
+ MusEGlobal::config.userInstrumentsDir = xml.parse1(); // Keep for compatibility
else if (tag == "startMode")
MusEGlobal::config.startMode = xml.parseInt();
else if (tag == "startSong")
@@ -950,6 +961,10 @@ void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig
MusEGlobal::config.leftMouseButtonCanDecrease = xml.parseInt();
else if (tag == "rangeMarkerWithoutMMB")
MusEGlobal::config.rangeMarkerWithoutMMB = xml.parseInt();
+ else if (tag == "addHiddenTracks")
+ MusEGlobal::config.addHiddenTracks = xml.parseInt();
+ else if (tag == "unhideTracks")
+ MusEGlobal::config.unhideTracks = xml.parseInt();
// ---- the following only skips obsolete entries ----
else if ((tag == "arranger") || (tag == "geometryPianoroll") || (tag == "geometryDrumedit"))
@@ -1173,7 +1188,6 @@ static void writeSeqConfiguration(int level, Xml& xml, bool writePortInfo)
if (dev) {
xml.strTag(level, "name", dev->name());
- // p3.3.38
//if(dynamic_cast<MidiJackDevice*>(dev))
if(dev->deviceType() != MidiDevice::ALSA_MIDI)
//xml.intTag(level, "type", MidiDevice::JACK_MIDI);
@@ -1183,6 +1197,9 @@ static void writeSeqConfiguration(int level, Xml& xml, bool writePortInfo)
// openFlags was read before, but never written here.
//xml.intTag(level, "record", dev->rwFlags() & 0x2 ? 1 : 0);
xml.intTag(level, "openFlags", dev->openFlags());
+
+ if(dev->deviceType() == MidiDevice::JACK_MIDI)
+ xml.intTag(level, "rwFlags", dev->rwFlags()); // Need this. Jack midi devs are created by app. p4.0.41
}
mport->syncInfo().write(level, xml);
// write out registered controller for all channels
@@ -1249,9 +1266,8 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const
xml.intTag(level, "dummyAudioBufSize", MusEGlobal::config.dummyAudioBufSize);
xml.intTag(level, "dummyAudioSampleRate", MusEGlobal::config.dummyAudioSampleRate);
xml.uintTag(level, "minControlProcessPeriod", MusEGlobal::config.minControlProcessPeriod);
-
xml.intTag(level, "guiRefresh", MusEGlobal::config.guiRefresh);
- xml.strTag(level, "userInstrumentsDir", MusEGlobal::config.userInstrumentsDir);
+
// Removed by Orcan. 20101220
//xml.strTag(level, "helpBrowser", config.helpBrowser);
xml.intTag(level, "extendedMidi", MusEGlobal::config.extendedMidi);
@@ -1287,6 +1303,17 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const
xml.intTag(level, "leftMouseButtonCanDecrease", MusEGlobal::config.leftMouseButtonCanDecrease);
xml.intTag(level, "rangeMarkerWithoutMMB", MusEGlobal::config.rangeMarkerWithoutMMB);
+ xml.intTag(level, "unhideTracks", MusEGlobal::config.unhideTracks);
+ xml.intTag(level, "addHiddenTracks", MusEGlobal::config.addHiddenTracks);
+
+ xml.intTag(level, "waveTracksVisible", MusECore::WaveTrack::visible());
+ xml.intTag(level, "auxTracksVisible", MusECore::AudioAux::visible());
+ xml.intTag(level, "groupTracksVisible", MusECore::AudioGroup::visible());
+ xml.intTag(level, "midiTracksVisible", MusECore::MidiTrack::visible());
+ xml.intTag(level, "inputTracksVisible", MusECore::AudioInput::visible());
+ xml.intTag(level, "outputTracksVisible", MusECore::AudioOutput::visible());
+ xml.intTag(level, "synthTracksVisible", MusECore::SynthI::visible());
+
//for (int i = 0; i < 6; ++i) {
for (int i = 0; i < NUM_FONTS; ++i) {
char buffer[32];
@@ -1339,7 +1366,6 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const
xml.colorTag(level, "auxTrackBg", MusEGlobal::config.auxTrackBg);
xml.colorTag(level, "synthTrackBg", MusEGlobal::config.synthTrackBg);
- // Removed by Tim. p3.3.6
//xml.intTag(level, "txSyncPort", txSyncPort);
//xml.intTag(level, "rxSyncPort", rxSyncPort);
xml.intTag(level, "mtctype", MusEGlobal::mtcType);
@@ -1366,11 +1392,8 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const
xml.intTag(level, "bigtimeVisible", MusEGlobal::config.bigTimeVisible);
xml.intTag(level, "transportVisible", MusEGlobal::config.transportVisible);
- //xml.intTag(level, "mixerVisible", MusEGlobal::config.mixerVisible); // Obsolete
xml.intTag(level, "mixer1Visible", MusEGlobal::config.mixer1Visible);
xml.intTag(level, "mixer2Visible", MusEGlobal::config.mixer2Visible);
- //MusEGlobal::config.mixer1.write(level, xml, "mixer1");
- //MusEGlobal::config.mixer2.write(level, xml, "mixer2");
MusEGlobal::config.mixer1.write(level, xml);
MusEGlobal::config.mixer2.write(level, xml);
@@ -1423,20 +1446,9 @@ void MusE::writeConfiguration(int level, MusECore::Xml& xml) const
xml.intTag(level, "midiFilterCtrl3", MusEGlobal::midiFilterCtrl3);
xml.intTag(level, "midiFilterCtrl4", MusEGlobal::midiFilterCtrl4);
- xml.intTag(level, "waveTracksVisible", MusECore::WaveTrack::visible());
- xml.intTag(level, "auxTracksVisible", MusECore::AudioAux::visible());
- xml.intTag(level, "groupTracksVisible", MusECore::AudioGroup::visible());
- xml.intTag(level, "midiTracksVisible", MusECore::MidiTrack::visible());
- xml.intTag(level, "inputTracksVisible", MusECore::AudioInput::visible());
- xml.intTag(level, "outputTracksVisible", MusECore::AudioOutput::visible());
- xml.intTag(level, "synthTracksVisible", MusECore::SynthI::visible());
- // Removed by Tim. p3.3.6
-
//xml.intTag(level, "txDeviceId", txDeviceId);
//xml.intTag(level, "rxDeviceId", rxDeviceId);
- // Changed by Tim. p3.3.6
-
//xml.intTag(level, "txSyncPort", txSyncPort);
/*
// To keep old muse versions happy...
@@ -1458,8 +1470,6 @@ void MusE::writeConfiguration(int level, MusECore::Xml& xml) const
}
*/
- // Added by Tim. p3.3.6
-
//xml.tag(level++, "midiSyncInfo");
//for(iMusECore::MidiDevice id = MusECore::MusEGlobal::midiDevices.begin(); id != MusECore::MusEGlobal::midiDevices.end(); ++id)
//{
@@ -1487,8 +1497,6 @@ void MusE::writeConfiguration(int level, MusECore::Xml& xml) const
xml.intTag(level, "bigtimeVisible", viewBigtimeAction->isChecked());
xml.intTag(level, "transportVisible", viewTransportAction->isChecked());
- //xml.intTag(level, "markerVisible", viewMarkerAction->isChecked()); // Obsolete (done by song's toplevel list)
- //xml.intTag(level, "mixerVisible", menuView->isItemChecked(aid1)); // Obsolete
xml.geometryTag(level, "geometryMain", this); // FINDME: maybe remove this? do we want
// the main win to jump around when loading?
@@ -1497,18 +1505,13 @@ void MusE::writeConfiguration(int level, MusECore::Xml& xml) const
if (bigtime)
xml.geometryTag(level, "geometryBigTime", bigtime);
- //if (audioMixer)
- // xml.geometryTag(level, "geometryMixer", audioMixer); // Obsolete
xml.intTag(level, "mixer1Visible", viewMixerAAction->isChecked());
xml.intTag(level, "mixer2Visible", viewMixerBAction->isChecked());
if (mixer1)
- //mixer1->write(level, xml, "mixer1");
mixer1->write(level, xml);
if (mixer2)
- //mixer2->write(level, xml, "mixer2");
mixer2->write(level, xml);
- //_arranger->writeStatus(level, xml); // Obsolete. done by song's toplevel list. arrangerview also handles arranger.
writeSeqConfiguration(level, xml, true);
MusEGui::write_function_dialog_config(level, xml);
@@ -1646,18 +1649,12 @@ namespace MusEGlobal {
// write
//---------------------------------------------------------
-//void MixerConfig::write(MusECore::Xml& xml, const char* name)
void MixerConfig::write(int level, MusECore::Xml& xml)
-//void MixerConfig::write(int level, MusECore::Xml& xml, const char* name)
{
- //xml.stag(QString(name));
- //xml.tag(level++, name.toLatin1().constData());
xml.tag(level++, "Mixer");
- //xml.tag(level++, name);
-
+
xml.strTag(level, "name", name);
- //xml.tag("geometry", geometry);
xml.qrectTag(level, "geometry", geometry);
xml.intTag(level, "showMidiTracks", showMidiTracks);
@@ -1669,19 +1666,14 @@ void MixerConfig::write(int level, MusECore::Xml& xml)
xml.intTag(level, "showAuxTracks", showAuxTracks);
xml.intTag(level, "showSyntiTracks", showSyntiTracks);
- //xml.etag(name);
- //xml.etag(level, name.toLatin1().constData());
xml.etag(level, "Mixer");
- //xml.etag(level, name);
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
-//void MixerConfig::read(QDomNode node)
void MixerConfig::read(MusECore::Xml& xml)
-//void MixerConfig::read(MusECore::Xml& xml, const QString& name)
{
for (;;) {
MusECore::Xml::Token token(xml.parse());
diff --git a/muse2/muse/confmport.cpp b/muse2/muse/confmport.cpp
index 00914b36..d45dd370 100644
--- a/muse2/muse/confmport.cpp
+++ b/muse2/muse/confmport.cpp
@@ -183,22 +183,25 @@ void MPConfig::changeDefOutputRoutes(QAction* act)
MusEGlobal::audio->msgUpdateSoloStates();
MusEGlobal::song->update(SC_ROUTE);
#else
- int ch = 0;
- for( ; ch < MIDI_CHANNELS; ++ch)
- if(defch & (1 << ch)) break;
-
- MusEGlobal::audio->msgIdle(true);
- for(MusECore::iMidiTrack it = mtl->begin(); it != mtl->end(); ++it)
- {
- // Leave drum track channel at current setting.
- if((*it)->type() == MusECore::Track::DRUM)
- (*it)->setOutPortAndUpdate(no);
- else
- (*it)->setOutPortAndChannelAndUpdate(no, ch);
- }
- MusEGlobal::audio->msgIdle(false);
- MusEGlobal::audio->msgUpdateSoloStates();
- MusEGlobal::song->update(SC_MIDI_TRACK_PROP);
+ for(int ch = 0; ch < MIDI_CHANNELS; ++ch)
+ if(defch & (1 << ch))
+ {
+ MusEGlobal::audio->msgIdle(true);
+ for(MusECore::iMidiTrack it = mtl->begin(); it != mtl->end(); ++it)
+ {
+ // Leave drum track channel at current setting.
+ if((*it)->type() == MusECore::Track::DRUM)
+ (*it)->setOutPortAndUpdate(no);
+ else
+ (*it)->setOutPortAndChannelAndUpdate(no, ch);
+ }
+ MusEGlobal::audio->msgIdle(false);
+ MusEGlobal::audio->msgUpdateSoloStates();
+ MusEGlobal::song->update(SC_MIDI_TRACK_PROP);
+
+ // Stop at the first output channel found.
+ break;
+ }
#endif
}
}
@@ -902,8 +905,105 @@ void MPConfig::rbClicked(QTableWidgetItem* item)
sdev = 0;
}
+ int allch = (1 << MIDI_CHANNELS) - 1;
+ MusECore::MidiTrackList* mtl = MusEGlobal::song->midis();
+
+ // Remove track routes to/from an existing port already using the selected device...
+ if(sdev)
+ {
+ for(int i = 0; i < MIDI_PORTS; ++i)
+ {
+ if(MusEGlobal::midiPorts[i].device() == sdev)
+ {
+ for(MusECore::iMidiTrack it = mtl->begin(); it != mtl->end(); ++it)
+ MusEGlobal::audio->msgRemoveRoute(MusECore::Route(i, allch), MusECore::Route(*it, allch));
+
+ // Turn on if and when multiple output routes are supported.
+ #if 0
+ for(MusECore::iMidiTrack it = mtl->begin(); it != mtl->end(); ++it)
+ MusEGlobal::audio->msgRemoveRoute(MusECore::Route(no, allch), MusECore::Route(*it, allch));
+
+ //MusEGlobal::audio->msgUpdateSoloStates();
+ //MusEGlobal::song->update(SC_ROUTE);
+ #endif
+
+ break;
+ }
+ }
+ }
+
+ // Remove all track routes to/from this port...
+ for(MusECore::iMidiTrack it = mtl->begin(); it != mtl->end(); ++it)
+ // Remove all routes from this port to the tracks.
+ MusEGlobal::audio->msgRemoveRoute(MusECore::Route(no, allch), MusECore::Route(*it, allch));
+ // Turn on if and when multiple output routes are supported.
+ #if 0
+ for(MusECore::iMidiTrack it = mtl->begin(); it != mtl->end(); ++it)
+ MusEGlobal::audio->msgRemoveRoute(MusECore::Route(no, allch), MusECore::Route(*it, allch));
+
+ //MusEGlobal::audio->msgUpdateSoloStates();
+ //MusEGlobal::song->update(SC_ROUTE);
+ #endif
+
MusEGlobal::midiSeq->msgSetMidiDevice(port, sdev);
MusEGlobal::muse->changeConfig(true); // save configuration file
+
+ // Add all track routes to/from this port...
+ if(sdev)
+ {
+ int chbits = MusEGlobal::midiPorts[no].defaultInChannels();
+ // Do not add input routes to synths.
+ if(!sdev->isSynti())
+ {
+ for(MusECore::iMidiTrack it = mtl->begin(); it != mtl->end(); ++it)
+ {
+ // Remove all routes from this port to the tracks first.
+ //MusEGlobal::audio->msgRemoveRoute(MusECore::Route(no, allch), MusECore::Route(*it, allch));
+ // Now connect all the specified routes.
+ if(chbits)
+ MusEGlobal::audio->msgAddRoute(MusECore::Route(no, chbits), MusECore::Route(*it, chbits));
+ }
+ }
+ chbits = MusEGlobal::midiPorts[no].defaultOutChannels();
+ // Turn on if and when multiple output routes are supported.
+ #if 0
+ for(MusECore::iMidiTrack it = mtl->begin(); it != mtl->end(); ++it)
+ {
+ // Remove all routes from this port to the tracks first.
+ //MusEGlobal::audio->msgRemoveRoute(MusECore::Route(no, allch), MusECore::Route(*it, allch));
+ // Now connect all the specified routes.
+ if(chbits)
+ MusEGlobal::audio->msgAddRoute(MusECore::Route(no, chbits), MusECore::Route(*it, chbits));
+ }
+ //MusEGlobal::audio->msgUpdateSoloStates();
+ //MusEGlobal::song->update(SC_ROUTE);
+ #else
+ for(int ch = 0; ch < MIDI_CHANNELS; ++ch)
+ if(chbits & (1 << ch))
+ {
+ MusEGlobal::audio->msgIdle(true);
+ for(MusECore::iMidiTrack it = mtl->begin(); it != mtl->end(); ++it)
+ {
+ // Leave drum track channel at current setting.
+ if((*it)->type() == MusECore::Track::DRUM)
+ (*it)->setOutPortAndUpdate(no);
+ else
+ (*it)->setOutPortAndChannelAndUpdate(no, ch);
+ }
+ MusEGlobal::audio->msgIdle(false);
+ //MusEGlobal::audio->msgUpdateSoloStates();
+ //MusEGlobal::song->update(SC_MIDI_TRACK_PROP);
+
+ // Stop at the first output channel found.
+ break;
+ }
+ #endif
+ }
+
+ //MusEGlobal::audio->msgUpdateSoloStates();
+ ////MusEGlobal::song->update(SC_ROUTE);
+
+ MusEGlobal::audio->msgUpdateSoloStates();
MusEGlobal::song->update();
}
}
@@ -1061,7 +1161,8 @@ MPConfig::MPConfig(QWidget* parent)
//popup = 0;
instrPopup = 0;
defpup = 0;
- _showAliases = -1; // 0: Show first aliases, if available. Nah, stick with -1: none at first.
+ //_showAliases = -1; // 0: Show first aliases, if available. Nah, stick with -1: none at first.
+ _showAliases = 0; // 0: Show first aliases, if available.
QStringList columnnames;
columnnames << tr("Port")
@@ -1125,8 +1226,7 @@ void MPConfig::songChanged(int flags)
// Is it simply a midi controller value adjustment? Forget it.
//if(flags == SC_MIDI_CONTROLLER)
// return;
- // No need for anything but this, yet.
- if(!(flags & SC_CONFIG))
+ if(!(flags & (SC_CONFIG | SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED)))
return;
// Get currently selected index...
@@ -1299,32 +1399,29 @@ void MPConfig::songChanged(int flags)
synthList->clear();
for (std::vector<MusECore::Synth*>::iterator i = MusEGlobal::synthis.begin();
i != MusEGlobal::synthis.end(); ++i) {
- //s = (*i)->baseName();
- //s = (*i)->name();
-
QTreeWidgetItem* item = new QTreeWidgetItem(synthList);
- //item->setText(0, s);
item->setText(0, QString((*i)->baseName()));
+ item->setText(1, MusECore::synthType2String((*i)->synthType()));
s.setNum((*i)->instances());
- item->setText(1, s);
- item->setTextAlignment(1, Qt::AlignHCenter);
- //item->setText(2, QString((*i)->baseName()));
- item->setText(2, QString((*i)->name()));
+ item->setText(2, s);
+ //item->setTextAlignment(2, Qt::AlignHCenter);
+ item->setText(3, QString((*i)->name()));
- item->setText(3, QString((*i)->version()));
- item->setText(4, QString((*i)->description()));
+ item->setText(4, QString((*i)->version()));
+ item->setText(5, QString((*i)->description()));
}
instanceList->clear();
MusECore::SynthIList* sl = MusEGlobal::song->syntis();
for (MusECore::iSynthI si = sl->begin(); si != sl->end(); ++si) {
QTreeWidgetItem* iitem = new QTreeWidgetItem(instanceList);
iitem->setText(0, (*si)->name());
+ iitem->setText(1, MusECore::synthType2String((*si)->synth()->synthType()));
if ((*si)->midiPort() == -1)
s = tr("<none>");
else
s.setNum((*si)->midiPort() + 1);
- iitem->setText(1, s);
- iitem->setTextAlignment(1, Qt::AlignHCenter);
+ iitem->setText(2, s);
+ //iitem->setTextAlignment(2, Qt::AlignHCenter);
}
synthList->resizeColumnToContents(1);
mdevView->resizeColumnsToContents();
@@ -1345,7 +1442,10 @@ void MPConfig::addInstanceClicked()
QTreeWidgetItem* item = synthList->currentItem();
if (item == 0)
return;
- MusECore::SynthI *si = MusEGlobal::song->createSynthI(item->text(0), item->text(2)); // Add at end of list.
+ // Add at end of list.
+ MusECore::SynthI *si = MusEGlobal::song->createSynthI(item->text(0),
+ item->text(3),
+ MusECore::string2SynthType(item->text(1)));
if(!si)
return;
@@ -1374,8 +1474,9 @@ void MPConfig::removeInstanceClicked()
MusECore::SynthIList* sl = MusEGlobal::song->syntis();
MusECore::iSynthI ii;
for (ii = sl->begin(); ii != sl->end(); ++ii) {
- if ((*ii)->iname() == item->text(0))
- break;
+ if( (*ii)->iname() == item->text(0) &&
+ MusECore::synthType2String((*ii)->synth()->synthType()) == item->text(1) )
+ break;
}
if (ii == sl->end()) {
printf("synthesizerConfig::removeInstanceClicked(): synthi not found\n");
diff --git a/muse2/muse/ctrl/ctrlcanvas.cpp b/muse2/muse/ctrl/ctrlcanvas.cpp
index f55eea5d..60e19ba7 100644
--- a/muse2/muse/ctrl/ctrlcanvas.cpp
+++ b/muse2/muse/ctrl/ctrlcanvas.cpp
@@ -1928,7 +1928,7 @@ void CtrlCanvas::drawOverlay(QPainter& p)
//p.setFont(MusEGlobal::config.fonts[3]);
//p.setPen(Qt::black);
//p.drawText(width()/2-100,height()/2-10, "Use shift + pencil or line tool to draw new events");
- p.drawText(2 , y * 2, "Use shift + pencil or line tool to draw new events");
+ p.drawText(2 , y * 2, "Drawing hint: Hold Ctrl to affect only existing events");
}
}
diff --git a/muse2/muse/driver/alsamidi.cpp b/muse2/muse/driver/alsamidi.cpp
index 3b6f5a20..4687f17f 100644
--- a/muse2/muse/driver/alsamidi.cpp
+++ b/muse2/muse/driver/alsamidi.cpp
@@ -48,6 +48,7 @@ static int alsaSeqFdo = -1;
snd_seq_t* alsaSeq = 0;
static snd_seq_addr_t musePort;
+static snd_seq_addr_t announce_adr;
//---------------------------------------------------------
// MidiAlsaDevice
@@ -85,42 +86,55 @@ QString MidiAlsaDevice::open()
QString estr;
int wer = 0;
int rer = 0;
+
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca(&pinfo);
+ //snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
+ snd_seq_port_info_set_addr(pinfo, &adr);
+
+ int cap = snd_seq_port_info_get_capability(pinfo);
// subscribe for writing
if (_openFlags & 1)
{
- snd_seq_port_subscribe_set_sender(subs, &musePort);
- snd_seq_port_subscribe_set_dest(subs, &adr);
- // Not already subscribed (or error)? Then try subscribing.
- if(snd_seq_get_port_subscription(alsaSeq, subs) < 0)
- {
- //int error = snd_seq_subscribe_port(alsaSeq, subs);
- wer = snd_seq_subscribe_port(alsaSeq, subs);
- //if (error < 0)
- if(wer < 0)
- //return QString("Play: ")+QString(snd_strerror(error));
- estr += (QString("Play: ") + QString(snd_strerror(wer)) + QString(" "));
- }
- if(!wer)
+ if(cap & SND_SEQ_PORT_CAP_SUBS_WRITE)
+ {
+ snd_seq_port_subscribe_set_sender(subs, &musePort);
+ snd_seq_port_subscribe_set_dest(subs, &adr);
+ // Not already subscribed (or error)? Then try subscribing.
+ if(snd_seq_get_port_subscription(alsaSeq, subs) < 0)
+ {
+ //int error = snd_seq_subscribe_port(alsaSeq, subs);
+ wer = snd_seq_subscribe_port(alsaSeq, subs);
+ //if (error < 0)
+ if(wer < 0)
+ //return QString("Play: ")+QString(snd_strerror(error));
+ estr += (QString("Play: ") + QString(snd_strerror(wer)) + QString(" "));
+ }
+ }
+ if(!wer && (cap & SND_SEQ_PORT_CAP_WRITE))
_writeEnable = true;
}
// subscribe for reading
if (_openFlags & 2)
{
- snd_seq_port_subscribe_set_dest(subs, &musePort);
- snd_seq_port_subscribe_set_sender(subs, &adr);
- // Not already subscribed (or error)? Then try subscribing.
- if(snd_seq_get_port_subscription(alsaSeq, subs) < 0)
- {
- //int error = snd_seq_subscribe_port(alsaSeq, subs);
- rer = snd_seq_subscribe_port(alsaSeq, subs);
- //if (error < 0)
- if(rer < 0)
- //return QString("Rec: ") + QString(snd_strerror(error));
- estr += (QString("Rec: ") + QString(snd_strerror(rer)));
- }
- if(!rer)
+ if(cap & SND_SEQ_PORT_CAP_SUBS_READ)
+ {
+ snd_seq_port_subscribe_set_dest(subs, &musePort);
+ snd_seq_port_subscribe_set_sender(subs, &adr);
+ // Not already subscribed (or error)? Then try subscribing.
+ if(snd_seq_get_port_subscription(alsaSeq, subs) < 0)
+ {
+ //int error = snd_seq_subscribe_port(alsaSeq, subs);
+ rer = snd_seq_subscribe_port(alsaSeq, subs);
+ //if (error < 0)
+ if(rer < 0)
+ //return QString("Rec: ") + QString(snd_strerror(error));
+ estr += (QString("Rec: ") + QString(snd_strerror(rer)));
+ }
+ }
+ if(!rer && (cap & SND_SEQ_PORT_CAP_READ))
_readEnable = true;
}
@@ -141,6 +155,16 @@ void MidiAlsaDevice::close()
// Allocated on stack, no need to call snd_seq_port_subscribe_free() later.
snd_seq_port_subscribe_alloca(&subs);
+ int wer = 0;
+ int rer = 0;
+
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca(&pinfo);
+ //snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
+ snd_seq_port_info_set_addr(pinfo, &adr);
+
+ int cap = snd_seq_port_info_get_capability(pinfo);
+
// This function appears to be called only by MidiPort::setMidiDevice(),
// which closes then opens the device.
// Because the open flags are set BEFORE setMidiDevice() is called, we must ignore the flags.
@@ -160,37 +184,49 @@ void MidiAlsaDevice::close()
//if (_openFlags & 1) {
//if (!(_openFlags & 1))
{
- snd_seq_port_subscribe_set_sender(subs, &musePort);
- snd_seq_port_subscribe_set_dest(subs, &adr);
-
- // Already subscribed? Then unsubscribe.
- if(!snd_seq_get_port_subscription(alsaSeq, subs))
- {
- if(!snd_seq_unsubscribe_port(alsaSeq, subs))
- _writeEnable = false;
- else
- printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for writing\n");
+ if(cap & SND_SEQ_PORT_CAP_SUBS_WRITE)
+ {
+ snd_seq_port_subscribe_set_sender(subs, &musePort);
+ snd_seq_port_subscribe_set_dest(subs, &adr);
+
+ // Already subscribed? Then unsubscribe.
+ if(!snd_seq_get_port_subscription(alsaSeq, subs))
+ {
+ wer = snd_seq_unsubscribe_port(alsaSeq, subs);
+ //if(!wer)
+ // _writeEnable = false;
+ //else
+ if(wer < 0)
+ printf("MidiAlsaDevice::close Error unsubscribing alsa midi port %d:%d for writing: %s\n", adr.client, adr.port, snd_strerror(wer));
+ }
+ //else
+ //_writeEnable = false;
}
- else
- _writeEnable = false;
+ _writeEnable = false;
}
//if (_openFlags & 2) {
//if (!(_openFlags & 2))
{
- snd_seq_port_subscribe_set_dest(subs, &musePort);
- snd_seq_port_subscribe_set_sender(subs, &adr);
-
- // Already subscribed? Then unsubscribe.
- if(!snd_seq_get_port_subscription(alsaSeq, subs))
- {
- if(!snd_seq_unsubscribe_port(alsaSeq, subs))
- _readEnable = false;
- else
- printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for reading\n");
- }
- else
- _readEnable = false;
+ if(cap & SND_SEQ_PORT_CAP_SUBS_READ)
+ {
+ snd_seq_port_subscribe_set_dest(subs, &musePort);
+ snd_seq_port_subscribe_set_sender(subs, &adr);
+
+ // Already subscribed? Then unsubscribe.
+ if(!snd_seq_get_port_subscription(alsaSeq, subs))
+ {
+ rer = snd_seq_unsubscribe_port(alsaSeq, subs);
+ //if(!rer)
+ // _readEnable = false;
+ //else
+ if(rer < 0)
+ printf("MidiAlsaDevice::close Error unsubscribing alsa midi port %d:%d for reading: %s\n", adr.client, adr.port, snd_strerror(rer));
+ }
+ //else
+ // _readEnable = false;
+ }
+ _readEnable = false;
}
}
@@ -698,6 +734,13 @@ bool initMidiAlsa()
snd_seq_client_info_set_client(cinfo, -1);
while (snd_seq_query_next_client(alsaSeq, cinfo) >= 0) {
+ const char* cname = snd_seq_client_info_get_name(cinfo);
+ //printf( "ALSA client name: %s\n", cname);
+
+ // Put Midi Through and user clients after others. Insert other unwanted clients here: // p4.0.41
+ if(snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT || strcmp("Midi Through", cname) == 0)
+ continue;
+
snd_seq_port_info_t *pinfo;
snd_seq_port_info_alloca(&pinfo);
snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
@@ -705,6 +748,8 @@ bool initMidiAlsa()
while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) {
unsigned int capability = snd_seq_port_info_get_capability(pinfo);
+ if (capability & SND_SEQ_PORT_CAP_NO_EXPORT) // Ignore ports like "qjackctl" or "port". p4.0.41
+ continue;
if ((capability & outCap) == 0) {
const char *name = snd_seq_port_info_get_name(pinfo);
if (strcmp("Timer", name) == 0 ||
@@ -726,29 +771,52 @@ bool initMidiAlsa()
adr.client, adr.port,
flags, capability);
MusEGlobal::midiDevices.add(dev);
-
- /*
- // Experimental... Need to list 'sensible' devices first and ignore unwanted ones...
- // Add instance last in midi device list.
- for(int i = 0; i < MIDI_PORTS; ++i)
- {
- MidiPort* mp = &MusEGlobal::midiPorts[i];
- if(mp->device() == 0)
- {
- // midiSeq might not be initialzed yet!
- //MusEGlobal::midiSeq->msgSetMidiDevice(mp, dev);
- mp->setMidiDevice(dev);
-
- //muse->changeConfig(true); // save configuration file
- //update();
- break;
- }
}
- */
-
+ }
+
+ snd_seq_client_info_set_client(cinfo, -1); // Reset
+ while (snd_seq_query_next_client(alsaSeq, cinfo) >= 0) {
+ const char* cname = snd_seq_client_info_get_name(cinfo);
+ //printf( "ALSA client name: %s\n", cname);
+
+ // Put Midi Through and user clients after others. Insert other unwanted clients here: // p4.0.41
+ if( !(snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT || strcmp("Midi Through", cname) == 0) )
+ continue;
+
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca(&pinfo);
+ snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
+ snd_seq_port_info_set_port(pinfo, -1);
+
+ while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) {
+ unsigned int capability = snd_seq_port_info_get_capability(pinfo);
+ if (capability & SND_SEQ_PORT_CAP_NO_EXPORT) // Ignore ports like "qjackctl" or "port". p4.0.41
+ continue;
+ if ((capability & outCap) == 0) {
+ const char *name = snd_seq_port_info_get_name(pinfo);
+ if (strcmp("Timer", name) == 0 ||
+ strcmp("Announce", name) == 0 ||
+ strcmp("Receiver", name) == 0)
+ continue;
+ }
+ snd_seq_addr_t adr = *snd_seq_port_info_get_addr(pinfo);
+ MidiAlsaDevice* dev = new MidiAlsaDevice(adr, QString(snd_seq_port_info_get_name(pinfo)));
+ int flags = 0;
+ if (capability & outCap)
+ flags |= 1;
+ if (capability & inCap)
+ flags |= 2;
+ dev->setrwFlags(flags);
+ if (MusEGlobal::debugMsg)
+ printf("ALSA port add: <%s>, %d:%d flags %d 0x%0x\n",
+ snd_seq_port_info_get_name(pinfo),
+ adr.client, adr.port,
+ flags, capability);
+ MusEGlobal::midiDevices.add(dev);
}
}
-
+
+
//snd_seq_set_client_name(alsaSeq, "MusE Sequencer");
snd_seq_set_client_name(alsaSeq, MusEGlobal::audioDevice->clientName());
@@ -783,14 +851,14 @@ bool initMidiAlsa()
// alsa port changes
//-----------------------------------------
- snd_seq_addr_t aadr;
- aadr.client = SND_SEQ_CLIENT_SYSTEM;
- aadr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
+ //snd_seq_addr_t aadr;
+ announce_adr.client = SND_SEQ_CLIENT_SYSTEM;
+ announce_adr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
snd_seq_port_subscribe_t* subs;
snd_seq_port_subscribe_alloca(&subs);
snd_seq_port_subscribe_set_dest(subs, &musePort);
- snd_seq_port_subscribe_set_sender(subs, &aadr);
+ snd_seq_port_subscribe_set_sender(subs, &announce_adr);
error = snd_seq_subscribe_port(alsaSeq, subs);
if (error < 0) {
printf("Alsa: Subscribe System failed: %s", snd_strerror(error));
@@ -807,12 +875,35 @@ bool initMidiAlsa()
void exitMidiAlsa()
{
if(alsaSeq)
- {
- int error = snd_seq_close(alsaSeq); // FIXME Hm, this did not get rid of a buch of valgrind leaks.
- if(error < 0)
+ {
+ int error = 0;
+ snd_seq_port_subscribe_t* subs;
+ // Allocated on stack, no need to call snd_seq_port_subscribe_free() later.
+ snd_seq_port_subscribe_alloca(&subs);
+
+ snd_seq_port_info_t *pinfo;
+ snd_seq_port_info_alloca(&pinfo);
+ //snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
+ snd_seq_port_info_set_addr(pinfo, &announce_adr);
+
+ snd_seq_port_subscribe_set_dest(subs, &musePort);
+ snd_seq_port_subscribe_set_sender(subs, &announce_adr);
+
+ // Already subscribed? Then unsubscribe.
+ if(!snd_seq_get_port_subscription(alsaSeq, subs))
{
- fprintf(stderr, "Could not close ALSA sequencer: %s\n", snd_strerror(error));
- }
+ error = snd_seq_unsubscribe_port(alsaSeq, subs);
+ if(error < 0)
+ printf("MusE: exitMidiAlsa: Error unsubscribing alsa midi Announce port %d:%d for reading: %s\n", announce_adr.client, announce_adr.port, snd_strerror(error));
+ }
+
+ error = snd_seq_delete_simple_port(alsaSeq, musePort.port);
+ if(error < 0)
+ fprintf(stderr, "MusE: Could not delete ALSA simple port: %s\n", snd_strerror(error));
+
+ error = snd_seq_close(alsaSeq);
+ if(error < 0)
+ fprintf(stderr, "MusE: Could not close ALSA sequencer: %s\n", snd_strerror(error));
}
}
@@ -852,7 +943,9 @@ void alsaScanMidiPorts()
snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
snd_seq_port_info_set_port(pinfo, -1);
while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) {
- unsigned int capability = snd_seq_port_info_get_capability(pinfo);
+ unsigned int capability = snd_seq_port_info_get_capability(pinfo);
+ if (capability & SND_SEQ_PORT_CAP_NO_EXPORT) // Ignore ports like "qjackctl" or "port". p4.0.41
+ continue;
if (((capability & outCap) == 0)
&& ((capability & inCap) == 0))
continue;
@@ -902,6 +995,8 @@ void alsaScanMidiPorts()
//
// check for devices to add
//
+ // TODO: Possibly auto-add them to available midi ports. p4.0.41
+ //
for (std::list<AlsaPort>::iterator k = portList.begin(); k != portList.end(); ++k) {
iMidiDevice i = MusEGlobal::midiDevices.begin();
// printf("ALSA port: <%s>\n", k->name);
@@ -922,6 +1017,8 @@ void alsaScanMidiPorts()
// printf("add device\n");
}
}
+
+
}
//---------------------------------------------------------
diff --git a/muse2/muse/driver/jack.cpp b/muse2/muse/driver/jack.cpp
index 733353d8..421152a7 100644
--- a/muse2/muse/driver/jack.cpp
+++ b/muse2/muse/driver/jack.cpp
@@ -735,7 +735,11 @@ void JackAudioDevice::connectJackMidiPorts()
{
RouteList* rl = md->outRoutes();
for (ciRoute r = rl->begin(); r != rl->end(); ++r)
+ {
+ if(r->type != Route::JACK_ROUTE)
+ continue;
connect(port, r->jackPort);
+ }
}
}
@@ -748,7 +752,11 @@ void JackAudioDevice::connectJackMidiPorts()
{
RouteList* rl = md->inRoutes();
for (ciRoute r = rl->begin(); r != rl->end(); ++r)
+ {
+ if(r->type != Route::JACK_ROUTE)
+ continue;
connect(r->jackPort, port);
+ }
}
}
}
@@ -939,6 +947,8 @@ void JackAudioDevice::graphChanged()
for (int i = 0;i < 20;i++) {
erased = false;
for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {
+ if(irl->type != Route::JACK_ROUTE)
+ continue;
if (irl->channel != channel)
continue;
QString name = irl->name();
@@ -977,6 +987,8 @@ void JackAudioDevice::graphChanged()
while (*pn) {
bool found = false;
for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {
+ if(irl->type != Route::JACK_ROUTE)
+ continue;
if (irl->channel != channel)
continue;
QString name = irl->name();
@@ -1027,6 +1039,8 @@ void JackAudioDevice::graphChanged()
for (int i = 0; i < 20 ; i++) {
erased = false;
for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {
+ if(irl->type != Route::JACK_ROUTE)
+ continue;
if (irl->channel != channel)
continue;
QString name = irl->name();
@@ -1064,6 +1078,8 @@ void JackAudioDevice::graphChanged()
while (*pn) {
bool found = false;
for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {
+ if(irl->type != Route::JACK_ROUTE)
+ continue;
if (irl->channel != channel)
continue;
QString name = irl->name();
@@ -1139,6 +1155,8 @@ void JackAudioDevice::graphChanged()
{
erased = false;
for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {
+ if(irl->type != Route::JACK_ROUTE)
+ continue;
//if (irl->channel != channel)
// continue;
QString name = irl->name();
@@ -1181,6 +1199,8 @@ void JackAudioDevice::graphChanged()
while (*pn) {
bool found = false;
for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {
+ if(irl->type != Route::JACK_ROUTE)
+ continue;
//if (irl->channel != channel)
// continue;
QString name = irl->name();
@@ -1239,6 +1259,8 @@ void JackAudioDevice::graphChanged()
{
erased = false;
for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {
+ if(irl->type != Route::JACK_ROUTE)
+ continue;
//if (irl->channel != channel)
// continue;
QString name = irl->name();
@@ -1280,6 +1302,8 @@ void JackAudioDevice::graphChanged()
while (*pn) {
bool found = false;
for (ciRoute irl = rl->begin(); irl != rl->end(); ++irl) {
+ if(irl->type != Route::JACK_ROUTE)
+ continue;
//if (irl->channel != channel)
// continue;
QString name = irl->name();
@@ -1482,6 +1506,8 @@ void JackAudioDevice::start(int /*priority*/)
RouteList* rl = ai->inRoutes();
void* port = ai->jackPort(ch);
for (ciRoute ir = rl->begin(); ir != rl->end(); ++ir) {
+ if(ir->type != Route::JACK_ROUTE)
+ continue;
if (ir->channel == ch)
connect(ir->jackPort, port);
}
@@ -1495,6 +1521,8 @@ void JackAudioDevice::start(int /*priority*/)
RouteList* rl = ai->outRoutes();
void* port = ai->jackPort(ch);
for (ciRoute r = rl->begin(); r != rl->end(); ++r) {
+ if(r->type != Route::JACK_ROUTE)
+ continue;
if (r->channel == ch) {
connect(port, r->jackPort);
}
@@ -1603,6 +1631,107 @@ int JackAudioDevice::frameDelay() const
#endif
//---------------------------------------------------------
+// getJackPorts
+//---------------------------------------------------------
+
+void JackAudioDevice::getJackPorts(const char** ports, std::list<QString>& name_list, bool midi, bool physical, int aliases)
+ {
+ if (JACK_DEBUG)
+ printf("JackAudioDevice::getJackPorts()\n");
+ //std::list<QString> clientList;
+ //if(!checkJackClient(_client)) return clientList;
+ //if(!checkJackClient(_client)) return;
+ QString qname;
+ //const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
+ //const char** ports = jack_get_ports(_client, 0, type, JackPortIsInput);
+ //const char** ports = jack_get_ports(_client, 0, type, jflags);
+
+ QString cname(jack_get_client_name(_client));
+
+ for (const char** p = ports; p && *p; ++p) {
+ jack_port_t* port = jack_port_by_name(_client, *p);
+ //int flags = jack_port_flags(port);
+ //if (!(flags & JackPortIsInput))
+ // continue;
+ //char buffer[128];
+
+ int port_flags = jack_port_flags(port);
+ //printf("JackAudioDevice::getJackPorts port: %s flags: %d\n", *p, port_flags);
+
+ // Ignore our own client ports.
+ if(jack_port_is_mine(_client, port))
+ {
+ if(MusEGlobal::debugMsg)
+ printf("JackAudioDevice::getJackPorts ignoring own port: %s\n", *p);
+ continue;
+ }
+
+ int nsz = jack_port_name_size();
+ char buffer[nsz];
+
+ bool mthrough = false;
+
+ if(midi)
+ {
+ strncpy(buffer, *p, nsz);
+ char a2[nsz];
+ char* al[2];
+ al[0] = buffer;
+ al[1] = a2;
+ int na = jack_port_get_aliases(port, al);
+ if(na >= 1)
+ {
+ qname = QString(al[0]);
+ //printf("Checking port name for: %s\n", (QString("alsa_pcm:") + cname + QString("/")).toLatin1().constData());
+ // Ignore our own ALSA client!
+ if(qname.startsWith(QString("alsa_pcm:") + cname + QString("/")))
+ continue;
+ // Put Midi Through after all others.
+ mthrough = qname.startsWith(QString("alsa_pcm:Midi-Through/"));
+ //if((physical && mthrough) || (!physical && !mthrough))
+ //if(physical && mthrough)
+ // continue;
+ }
+ }
+ // Put physical/terminal ports before others.
+ bool is_phys = (port_flags & (JackPortIsTerminal | JackPortIsPhysical)) && !mthrough;
+ if((physical && !is_phys) || (!physical && is_phys))
+ continue;
+
+
+ strncpy(buffer, *p, nsz);
+ if((aliases == 0) || (aliases == 1))
+ {
+ char a2[nsz];
+ char* al[2];
+ al[0] = buffer;
+ al[1] = a2;
+ int na = jack_port_get_aliases(port, al);
+ int a = aliases;
+ if(a >= na)
+ {
+ a = na;
+ if(a > 0)
+ a--;
+ }
+ qname = QString(al[a]);
+ }
+ else
+ qname = QString(buffer);
+
+ //clientList.push_back(QString(buffer));
+ name_list.push_back(qname);
+ }
+
+ // p3.3.37
+ //if(ports)
+ //free(ports);
+ // jack_free(ports); // p4.0.29
+
+ //return clientList;
+ }
+
+//---------------------------------------------------------
// outputPorts
//---------------------------------------------------------
@@ -1612,9 +1741,11 @@ std::list<QString> JackAudioDevice::outputPorts(bool midi, int aliases)
printf("JackAudioDevice::outputPorts()\n");
std::list<QString> clientList;
if(!checkJackClient(_client)) return clientList;
- QString qname;
const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
const char** ports = jack_get_ports(_client, 0, type, JackPortIsOutput);
+
+ /*
+ QString qname;
for (const char** p = ports; p && *p; ++p) {
jack_port_t* port = jack_port_by_name(_client, *p);
//int flags = jack_port_flags(port);
@@ -1666,12 +1797,15 @@ std::list<QString> JackAudioDevice::outputPorts(bool midi, int aliases)
//clientList.push_back(QString(buffer));
clientList.push_back(qname);
}
-
- // p3.3.37
- if(ports)
- //free(ports);
- jack_free(ports); // p4.0.29
+ */
+ if(ports)
+ {
+ getJackPorts(ports, clientList, midi, true, aliases); // Get physical ports first.
+ getJackPorts(ports, clientList, midi, false, aliases); // Get non-physical ports last.
+ jack_free(ports);
+ }
+
return clientList;
}
@@ -1683,11 +1817,14 @@ std::list<QString> JackAudioDevice::inputPorts(bool midi, int aliases)
{
if (JACK_DEBUG)
printf("JackAudioDevice::inputPorts()\n");
+
std::list<QString> clientList;
if(!checkJackClient(_client)) return clientList;
- QString qname;
const char* type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE;
const char** ports = jack_get_ports(_client, 0, type, JackPortIsInput);
+
+ /*
+ QString qname;
for (const char** p = ports; p && *p; ++p) {
jack_port_t* port = jack_port_by_name(_client, *p);
//int flags = jack_port_flags(port);
@@ -1739,12 +1876,15 @@ std::list<QString> JackAudioDevice::inputPorts(bool midi, int aliases)
//clientList.push_back(QString(buffer));
clientList.push_back(qname);
}
-
- // p3.3.37
- if(ports)
- //free(ports);
- jack_free(ports); // p4.0.29
+ */
+ if(ports)
+ {
+ getJackPorts(ports, clientList, midi, true, aliases); // Get physical ports first.
+ getJackPorts(ports, clientList, midi, false, aliases); // Get non-physical ports last.
+ jack_free(ports);
+ }
+
return clientList;
}
diff --git a/muse2/muse/driver/jackaudio.h b/muse2/muse/driver/jackaudio.h
index bd78d481..c4d37db9 100644
--- a/muse2/muse/driver/jackaudio.h
+++ b/muse2/muse/driver/jackaudio.h
@@ -50,6 +50,7 @@ class JackAudioDevice : public AudioDevice {
// Free-running frame counter incremented always in process.
jack_nframes_t _frameCounter;
+ void getJackPorts(const char** ports, std::list<QString>& name_list, bool midi, bool physical, int aliases);
static int processAudio(jack_nframes_t frames, void*);
public:
diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp
index 92120dbb..2e4e6d35 100644
--- a/muse2/muse/dssihost.cpp
+++ b/muse2/muse/dssihost.cpp
@@ -99,6 +99,7 @@ static void scanDSSILib(QFileInfo& fi) // ddskrjo removed const for argument
// That way we cover all bases - effect plugins and synths.
// Non-synths will show up in the ladspa effect dialog, while synths will show up here...
// There should be nothing left out...
+ // TIP: Until we add programs to plugins, comment these four checks to load dssi effects as synths, in order to have programs.
if(descr->run_synth ||
descr->run_synth_adding ||
descr->run_multiple_synths ||
@@ -498,6 +499,9 @@ bool DssiSynthIF::init(DssiSynth* s)
int inports = synth->_inports;
if(inports != 0)
{
+ posix_memalign((void**)&audioInSilenceBuf, 16, sizeof(float) * MusEGlobal::segmentSize);
+ memset(audioInSilenceBuf, 0, sizeof(float) * MusEGlobal::segmentSize);
+
audioInBuffers = new float*[inports];
for(int k = 0; k < inports; ++k)
{
@@ -723,6 +727,7 @@ DssiSynthIF::DssiSynthIF(SynthI* s)
controls = 0;
controlsOut = 0;
audioInBuffers = 0;
+ audioInSilenceBuf = 0;
audioOutBuffers = 0;
}
@@ -785,6 +790,9 @@ DssiSynthIF::~DssiSynthIF()
delete[] audioInBuffers;
}
+ if(audioInSilenceBuf)
+ free(audioInSilenceBuf);
+
if(audioOutBuffers)
{
for(unsigned long i = 0; i < synth->_outports; ++i)
@@ -1420,7 +1428,7 @@ bool DssiSynthIF::processEvent(const MusECore::MidiPlayEvent& e, snd_seq_event_t
// getData
//---------------------------------------------------------
-MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MPEventList* el, MusECore::iMPEvent i, unsigned pos, int ports, unsigned n, float** buffer)
+MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MPEventList* el, MusECore::iMPEvent start_event, unsigned pos, int ports, unsigned nframes, float** buffer)
{
//#ifdef DSSI_DEBUG
// fprintf(stderr, "DssiSynthIF::getData elsize:%d pos:%d ports:%d samples:%d processed already?:%d\n", el->size(), pos, ports, n, synti->processed());
@@ -1440,19 +1448,11 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
// All ports must be connected to something!
unsigned long nop, k;
- // First, copy the given input buffers to our local input buffers.
- //np = portsin > synth->_inports ? synth->_inports : portsin;
- //for(k = 0; k < np; ++k)
- // memcpy(audioInBuffers[k], inbuffer[k], sizeof(float) * n);
- //for(; k < portsin; ++k)
- // memset(audioInBuffers[k], 0, sizeof(float) * n);
// Watch our limits.
//willyfoobar-2011-02-13
//old code//np = ports > synth->_outports ? synth->_outports : ports;
nop = ((unsigned long) ports) > synth->_outports ? synth->_outports : ((unsigned long) ports);
- // TODO Number of inports requested?
- //nip = ((unsigned long) iports) > synth->_inports ? synth->_inports : ((unsigned long) iports);
const DSSI_Descriptor* dssi = synth->dssi;
const LADSPA_Descriptor* descr = dssi->LADSPA_Plugin;
@@ -1484,18 +1484,109 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
// Note for dssi-vst this MUST equal MusEGlobal::audio period. It doesn't like broken-up runs (it stutters),
// even with fixed sizes. Could be a Wine + Jack thing, wanting a full Jack buffer's length.
//unsigned long fixedsize = 2048;
- unsigned long fixedsize = n;
+ unsigned long fixedsize = nframes;
// For now, the fixed size is clamped to the MusEGlobal::audio buffer size.
// TODO: We could later add slower processing over several cycles -
// so that users can select a small MusEGlobal::audio period but a larger control period.
- if(fixedsize > n)
- fixedsize = n;
+ if(fixedsize > nframes)
+ fixedsize = nframes;
unsigned long min_per = MusEGlobal::config.minControlProcessPeriod;
- if(min_per > n)
- min_per = n;
+ if(min_per > nframes)
+ min_per = nframes;
+
+ //
+ // p4.0.38 Handle inputs...
+ //
+ if(!((MusECore::AudioTrack*)synti)->noInRoute())
+ {
+ RouteList* irl = ((MusECore::AudioTrack*)synti)->inRoutes();
+ iRoute i = irl->begin();
+ if(i->track->isMidiTrack())
+ {
+ //if(MusEGlobal::debugMsg)
+ //printf("DssiSynthIF::getData: Error: First route is a midi track route!\n");
+ }
+ else
+ {
+ int ch = i->channel == -1 ? 0 : i->channel;
+ int remch = i->remoteChannel == -1 ? 0 : i->remoteChannel;
+ int chs = i->channels == -1 ? 0 : i->channels;
+
+ if((unsigned)ch < synth->_inports && (unsigned)(ch + chs) <= synth->_inports)
+ {
+ //printf("DssiSynthIF::getData calling copyData on %s ch:%d remch:%d chs:%d\n", i->track->name().toLatin1().constData(), ch, remch, chs);
+
+ int h = remch + chs;
+ for(int j = remch; j < h; ++j)
+ {
+ //printf(" setting used idx:%d\n", j);
+ synth->iUsedIdx[j] = true;
+ }
+
+ ((MusECore::AudioTrack*)i->track)->copyData(pos, chs, ch, -1, nframes, &audioInBuffers[remch]);
+ }
+ }
+
+ ++i;
+ for(; i != irl->end(); ++i)
+ {
+ if(i->track->isMidiTrack())
+ {
+ //if(MusEGlobal::debugMsg)
+ // printf("DssiSynthIF::getData: Error: Route is a midi track route!\n");
+ continue;
+ }
+
+ int ch = i->channel == -1 ? 0 : i->channel;
+ int remch = i->remoteChannel == -1 ? 0 : i->remoteChannel;
+ int chs = i->channels == -1 ? 0 : i->channels;
+ if((unsigned)ch < synth->_inports && (unsigned)(ch + chs) <= synth->_inports)
+ {
+ //printf("DssiSynthIF::getData calling addData on %s ch:%d remch:%d chs:%d\n", i->track->name().toLatin1().constData(), ch, remch, chs);
+
+ bool u1 = synth->iUsedIdx[remch];
+ if(chs >= 2)
+ {
+ bool u2 = synth->iUsedIdx[remch + 1];
+ if(u1 && u2)
+ ((MusECore::AudioTrack*)i->track)->addData(pos, chs, ch, -1, nframes, &audioInBuffers[remch]);
+ else
+ if(!u1 && !u2)
+ ((MusECore::AudioTrack*)i->track)->copyData(pos, chs, ch, -1, nframes, &audioInBuffers[remch]);
+ else
+ {
+ if(u1)
+ ((MusECore::AudioTrack*)i->track)->addData(pos, 1, ch, 1, nframes, &audioInBuffers[remch]);
+ else
+ ((MusECore::AudioTrack*)i->track)->copyData(pos, 1, ch, 1, nframes, &audioInBuffers[remch]);
+
+ if(u2)
+ ((MusECore::AudioTrack*)i->track)->addData(pos, 1, ch + 1, 1, nframes, &audioInBuffers[remch + 1]);
+ else
+ ((MusECore::AudioTrack*)i->track)->copyData(pos, 1, ch + 1, 1, nframes, &audioInBuffers[remch + 1]);
+ }
+ }
+ else
+ {
+ if(u1)
+ ((MusECore::AudioTrack*)i->track)->addData(pos, 1, ch, -1, nframes, &audioInBuffers[remch]);
+ else
+ ((MusECore::AudioTrack*)i->track)->copyData(pos, 1, ch, -1, nframes, &audioInBuffers[remch]);
+ }
+
+ int h = remch + chs;
+ for(int j = remch; j < h; ++j)
+ {
+ //printf(" setting used idx:%d\n", j);
+ synth->iUsedIdx[j] = true;
+ }
+ }
+ }
+ }
+
// Process automation control values now.
// TODO: This needs to be respect frame resolution. Put this inside the sample loop below.
if(MusEGlobal::automation && synti && synti->automationType() != AUTO_OFF && id() != -1)
@@ -1507,11 +1598,11 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
}
}
- while(sample < n)
+ while(sample < nframes)
{
//unsigned long nsamp = n;
//unsigned long nsamp = n - sample;
- unsigned long nsamp = usefixedrate ? fixedsize : n - sample;
+ unsigned long nsamp = usefixedrate ? fixedsize : nframes - sample;
bool found = false;
unsigned long frame = 0;
unsigned long index = 0;
@@ -1525,7 +1616,7 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
// The events happened in the last period or even before that. Shift into this period with + n. This will sync with MusEGlobal::audio.
// If the events happened even before current frame - n, make sure they are counted immediately as zero-frame.
//evframe = (pos + frameOffset > v.frame + n) ? 0 : v.frame - pos - frameOffset + n;
- evframe = (syncFrame > v.frame + n) ? 0 : v.frame - syncFrame + n;
+ evframe = (syncFrame > v.frame + nframes) ? 0 : v.frame - syncFrame + nframes;
// Protection. Observed this condition. Why? Supposed to be linear timestamps.
if(found && evframe < frame)
{
@@ -1545,7 +1636,7 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
//if(v.frame < startPos || v.frame >= (endPos + frameOffset)
//if(evframe < sample || evframe >= n
//if(evframe < sample || evframe >= (n + frameOffset)
- if(evframe >= n
+ if(evframe >= nframes
//|| (found && v.frame != frame)
//|| (!usefixedrate && found && !v.unique && v.frame != frame)
//|| (found && !v.unique && evframe != frame)
@@ -1567,6 +1658,31 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
index = v.idx;
// Set the ladspa control port value.
controls[v.idx].val = v.value;
+
+ // Need to update the automation value, otherwise it overwrites later with the last MusEGlobal::automation value.
+ if(id() != -1)
+ {
+ // Since we are now in the audio thread context, there's no need to send a message,
+ // just modify directly.
+ //MusEGlobal::audio->msgSetPluginCtrlVal(_track, genACnum(_id, k), controls[k].val);
+ synti->setPluginCtrlVal(genACnum(id(), v.idx), v.value);
+
+ // Record automation.
+ // NO! Take care of this immediately in the OSC control handler, because we don't want
+ // any delay.
+ // OTOH Since this is the actual place and time where the control ports values
+ // are set, best to reflect what happens here to automation.
+ // However for dssi-vst it might be best to handle it that way.
+
+ //AutomationType at = _track->automationType();
+ // TODO: Taken from our native gui control handlers.
+ // This may need modification or may cause problems -
+ // we don't have the luxury of access to the dssi gui controls !
+ //if(at == AUTO_WRITE || (MusEGlobal::audio->isPlaying() && at == AUTO_TOUCH))
+ // enableController(k, false);
+ //_track->recordAutomation(id, v.value);
+ }
+
}
// Process automation control values now.
@@ -1583,8 +1699,8 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
if(found && !usefixedrate)
//nsamp = frame - sample + 1;
nsamp = frame - sample;
- if(sample + nsamp >= n) // Safety check.
- nsamp = n - sample;
+ if(sample + nsamp >= nframes) // Safety check.
+ nsamp = nframes - sample;
//printf("DssiSynthIF::getData n:%d frame:%lu sample:%lu nsamp:%lu pos:%d fOffset:%d syncFrame:%lu loopcount:%d\n",
// n, frame, sample, nsamp, pos, frameOffset, syncFrame, loopcount); // REMOVE Tim.
@@ -1596,10 +1712,10 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
nevents = 0;
// Process event list events...
- for(; i != el->end(); ++i)
+ for(; start_event != el->end(); ++start_event)
{
//if(i->time() >= (endPos + frameOffset)) // NOTE: frameOffset? Tested, examined printouts of times: Seems OK for playback.
- if(i->time() >= (pos + sample + nsamp + frameOffset)) // frameOffset? Test again...
+ if(start_event->time() >= (pos + sample + nsamp + frameOffset)) // frameOffset? Test again...
break;
#ifdef DSSI_DEBUG
@@ -1611,40 +1727,40 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
if(synti->midiPort() != -1)
{
MusECore::MidiPort* mp = &MusEGlobal::midiPorts[synti->midiPort()];
- if(i->type() == MusECore::ME_CONTROLLER)
+ if(start_event->type() == MusECore::ME_CONTROLLER)
{
- int da = i->dataA();
- int db = i->dataB();
+ int da = start_event->dataA();
+ int db = start_event->dataB();
db = mp->limitValToInstrCtlRange(da, db);
- if(!mp->setHwCtrlState(i->channel(), da, db))
+ if(!mp->setHwCtrlState(start_event->channel(), da, db))
continue;
}
else
- if(i->type() == MusECore::ME_PITCHBEND)
+ if(start_event->type() == MusECore::ME_PITCHBEND)
{
- int da = mp->limitValToInstrCtlRange(MusECore::CTRL_PITCH, i->dataA());
- if(!mp->setHwCtrlState(i->channel(), MusECore::CTRL_PITCH, da))
+ int da = mp->limitValToInstrCtlRange(MusECore::CTRL_PITCH, start_event->dataA());
+ if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_PITCH, da))
continue;
}
else
- if(i->type() == MusECore::ME_PROGRAM)
+ if(start_event->type() == MusECore::ME_PROGRAM)
{
- if(!mp->setHwCtrlState(i->channel(), MusECore::CTRL_PROGRAM, i->dataA()))
+ if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_PROGRAM, start_event->dataA()))
continue;
}
}
// Returns false if the event was not filled. It was handled, but some other way.
- if(processEvent(*i, &events[nevents]))
+ if(processEvent(*start_event, &events[nevents]))
{
// Time-stamp the event. p4.0.15 Tim.
- int ft = i->time() - frameOffset - pos;
+ int ft = start_event->time() - frameOffset - pos;
if(ft < 0)
ft = 0;
//if (ft >= (int)MusEGlobal::segmentSize)
if (ft >= int(sample + nsamp))
{
- printf("DssiSynthIF::getData: eventlist event time:%d out of range. pos:%d offset:%d ft:%d sample:%lu nsamp:%lu\n", i->time(), pos, frameOffset, ft, sample, nsamp);
+ printf("DssiSynthIF::getData: eventlist event time:%d out of range. pos:%d offset:%d ft:%d sample:%lu nsamp:%lu\n", start_event->time(), pos, frameOffset, ft, sample, nsamp);
///if (ft > (int)MusEGlobal::segmentSize)
//ft = MusEGlobal::segmentSize - 1;
ft = sample + nsamp - 1;
@@ -1696,61 +1812,6 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
}
}
- /*
- //
- // p3.3.39 Handle inputs...
- //
- //if((MusEGlobal::song->bounceTrack != this) && !noInRoute())
- if(!((MusECore::AudioTrack*)synti)->noInRoute())
- {
- RouteList* irl = ((MusECore::AudioTrack*)synti)->inRoutes();
- iRoute i = irl->begin();
- if(!i->track->isMidiTrack())
- {
- //if(MusEGlobal::debugMsg)
- printf("DssiSynthIF::getData: Error: First route is a midi track route!\n");
- }
- else
- {
- int ch = i->channel == -1 ? 0 : i->channel;
- int remch = i->remoteChannel == -1 ? 0 : i->remoteChannel;
- int chs = i->channels == -1 ? 0 : i->channels;
-
- // TODO:
- //if(ch >= synth->_inports)
- //iUsedIdx[ch] = true;
- //if(chs == 2)
- // iUsedIdx[ch + 1] = true;
-
- //((MusECore::AudioTrack*)i->track)->copyData(framePos, channels, nframe, bp);
- ((MusECore::AudioTrack*)i->track)->copyData(pos, ports,
- //(i->track->type() == Track::AUDIO_SOFTSYNTH && i->channel != -1) ? i->channel : 0,
- i->channel,
- i->channels,
- n, bp);
- }
-
- //unsigned pos, int ports, unsigned n, float** buffer
-
- ++i;
- for(; i != irl->end(); ++i)
- {
- if(i->track->isMidiTrack())
- {
- //if(MusEGlobal::debugMsg)
- printf("DssiSynthIF::getData: Error: Route is a midi track route!\n");
- continue;
- }
- //((MusECore::AudioTrack*)i->track)->addData(framePos, channels, nframe, bp);
- ((MusECore::AudioTrack*)i->track)->addData(framePos, channels,
- //(i->track->type() == Track::AUDIO_SOFTSYNTH && i->channel != -1) ? i->channel : 0,
- i->channel,
- i->channels,
- nframe, bp);
- }
- }
- */
-
k = 0;
// Connect the given buffers directly to the ports, up to a max of synth ports.
for(; k < nop; ++k)
@@ -1758,9 +1819,21 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
// Connect the remaining ports to some local buffers (not used yet).
for(; k < synth->_outports; ++k)
descr->connect_port(handle, synth->oIdx[k], audioOutBuffers[k] + sample);
- // Just connect all inputs to some local buffers (not used yet). TODO: Support inputs.
+ // Connect all inputs either to some local buffers, or a silence buffer.
for(k = 0; k < synth->_inports; ++k)
- descr->connect_port(handle, synth->iIdx[k], audioInBuffers[k] + sample);
+ {
+ //printf(" k:%d synth->iIdx[k]:%d\n", k, synth->iIdx[k]);
+ if(synth->iUsedIdx[k])
+ {
+ synth->iUsedIdx[k] = false; // Reset
+ descr->connect_port(handle, synth->iIdx[k], audioInBuffers[k] + sample);
+ }
+ else
+ {
+ //printf(" input used size:%ld idx:%ld = %d silencing...\n", synth->iUsedIdx.size(), k, synth->iUsedIdx[k]);
+ descr->connect_port(handle, synth->iIdx[k], audioInSilenceBuf + sample);
+ }
+ }
// Run the synth for a period of time. This processes events and gets/fills our local buffers...
if(synth->dssi->run_synth)
@@ -1772,10 +1845,10 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
snd_seq_event_t* ev = events;
synth->dssi->run_multiple_synths(1, &handle, nsamp, &ev, &nevents);
}
+ // TIP: Until we add programs to plugins, uncomment these four checks to load dssi effects as synths, in order to have programs.
//else
//if(synth->dssi->LADSPA_Plugin->run)
//{
- // // Just a test, worked OK.
// synth->dssi->LADSPA_Plugin->run(handle, nsamp);
//}
@@ -1783,14 +1856,13 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP
loopcount++; // REMOVE Tim.
}
- return i;
+ return start_event;
}
//---------------------------------------------------------
// putEvent
//---------------------------------------------------------
-//bool DssiSynthIF::putEvent(const MidiEvent& ev)
bool DssiSynthIF::putEvent(const MusECore::MidiPlayEvent& ev)
{
#ifdef DSSI_DEBUG
@@ -2033,16 +2105,37 @@ int DssiSynthIF::oscControl(unsigned long port, float value)
fprintf(stderr, "DssiSynthIF::oscControl: fifo overflow: in control number:%lu\n", cport);
}
- MusECore::ciMidiCtl2LadspaPort ip = synth->port2MidiCtlMap.find(cport);
- if(ip != synth->port2MidiCtlMap.end())
+ // Record automation:
+ // Take care of this immediately, because we don't want the silly delay associated with
+ // processing the fifo one-at-a-time in the apply().
+ // NOTE: With some vsts we don't receive control events until the user RELEASES a control.
+ // So the events all arrive at once when the user releases a control.
+ // That makes this pretty useless... But what the heck...
+ if(id() != -1)
{
+ //int id = genACnum(_id, cport);
+ unsigned long pid = genACnum(id(), cport);
+ AutomationType at = synti->automationType();
+
+ // TODO: Taken from our native gui control handlers.
+ // This may need modification or may cause problems -
+ // we don't have the luxury of access to the dssi gui controls !
+ if(at == AUTO_WRITE || (MusEGlobal::audio->isPlaying() && at == AUTO_TOUCH))
+ enableController(cport, false);
+
+ synti->recordAutomation(pid, value);
+ }
+
+ //MusECore::ciMidiCtl2LadspaPort ip = synth->port2MidiCtlMap.find(cport);
+ //if(ip != synth->port2MidiCtlMap.end())
+ //{
// TODO: TODO: Update midi MusE's midi controller knobs, sliders, boxes etc with a call to the midi port's setHwCtrlState() etc.
// But first we need a ladspa2MidiValue() function! ...
//
//
//float val = ladspa2MidiValue(ld, i, ?, ?);
- }
+ //}
return 0;
}
@@ -2064,8 +2157,8 @@ int DssiSynthIF::oscMidi(int a, int b, int c)
{
MusECore::MidiPlayEvent event(0, port, channel, a, b, c);
- #ifdef DSSI_DEBUG
- printf(stderr, "DssiSynthIF::oscMidi midi event chn:%d a:%d b:%d\n", event.channel(), event.dataA(), event.dataB());
+ #ifdef DSSI_DEBUG
+ printf("DssiSynthIF::oscMidi midi event chn:%d a:%d b:%d\n", event.channel(), event.dataA(), event.dataB());
#endif
MusEGlobal::midiPorts[port].sendEvent(event);
@@ -2329,7 +2422,8 @@ QString DssiSynthIF::name() const { return synti->nam
QString DssiSynthIF::lib() const { return synth ? synth->completeBaseName() : QString(); }
QString DssiSynthIF::dirPath() const { return synth ? synth->absolutePath() : QString(); }
QString DssiSynthIF::fileName() const { return synth ? synth->fileName() : QString(); }
-MusECore::AudioTrack* DssiSynthIF::track() { return (MusECore::AudioTrack*)synti; }
+QString DssiSynthIF::titlePrefix() const { return QString(); }
+MusECore::AudioTrack* DssiSynthIF::track() { return (MusECore::AudioTrack*)synti; }
void DssiSynthIF::enableController(unsigned long i, bool v) { controls[i].enCtrl = v; }
bool DssiSynthIF::controllerEnabled(unsigned long i) const { return controls[i].enCtrl; }
bool DssiSynthIF::controllerEnabled2(unsigned long i) const { return controls[i].en2Ctrl; }
diff --git a/muse2/muse/dssihost.h b/muse2/muse/dssihost.h
index 9b00b642..2836d72e 100644
--- a/muse2/muse/dssihost.h
+++ b/muse2/muse/dssihost.h
@@ -76,7 +76,8 @@ class DssiSynth : public Synth {
unsigned long _portCount, _inports, _outports, _controlInPorts, _controlOutPorts;
std::vector<unsigned long> iIdx; // Audio input index to port number.
std::vector<unsigned long> oIdx; // Audio output index to port number.
- std::vector<bool> iUsedIdx; // During process, tells whether an audio input port was used by any input routes.
+ //std::vector<bool> iUsedIdx; // During process, tells whether an audio input port was used by any input routes.
+ std::vector<int> iUsedIdx; // During process, tells whether an audio input port was used by any input routes.
std::vector<unsigned long> rpIdx; // Port number to control input index. Item is -1 if it's not a control input.
MusECore::MidiCtl2LadspaPortMap midiCtl2PortMap; // Maps midi controller numbers to DSSI port numbers.
MusECore::MidiCtl2LadspaPortMap port2MidiCtlMap; // Maps DSSI port numbers to midi controller numbers.
@@ -88,6 +89,8 @@ class DssiSynth : public Synth {
public:
DssiSynth(QFileInfo&, const DSSI_Descriptor*); // removed const for QFileInfo
virtual ~DssiSynth();
+ virtual Type synthType() const { return DSSI_SYNTH; }
+
virtual void incInstances(int);
virtual SynthIF* createSIF(SynthI*);
@@ -122,6 +125,7 @@ class DssiSynthIF : public SynthIF, public PluginIBase
float** audioInBuffers;
float** audioOutBuffers;
+ float* audioInSilenceBuf; // Just all zeros all the time, so we don't have to clear for silence.
public:
DssiSynthIF(SynthI* s);
@@ -195,6 +199,7 @@ class DssiSynthIF : public SynthIF, public PluginIBase
QString lib() const;
QString dirPath() const;
QString fileName() const;
+ QString titlePrefix() const;
MusECore::AudioTrack* track();
void enableController(unsigned long /*i*/, bool v = true);
bool controllerEnabled(unsigned long /*i*/) const;
diff --git a/muse2/muse/gconfig.cpp b/muse2/muse/gconfig.cpp
index bb9f42f4..0abbbd76 100644
--- a/muse2/muse/gconfig.cpp
+++ b/muse2/muse/gconfig.cpp
@@ -129,8 +129,8 @@ GlobalConfigValues config = {
-60.0, // double minSlider;
false, // use Jack freewheel
20, // int guiRefresh;
- QString(""), // userInstrumentsDir
- //QString(""), // helpBrowser; // Obsolete
+ QString(""), // userInstrumentsDir // Obsolete. Must keep for compatibility.
+ //QString(""), // helpBrowser; // Obsolete
true, // extendedMidi
384, // division for smf export
QString(""), // copyright string for smf export
@@ -187,7 +187,12 @@ GlobalConfigValues config = {
64, // minControlProcessPeriod
false, // popupsDefaultStayOpen
false, // leftMouseButtonCanDecrease
- false // rangeMarkerWithoutMMB
+ false, // rangeMarkerWithoutMMB
+ true, // addHiddenTracks
+ true // unhideTracks
+
};
+//GlobalConfigValues globalConfig = config;
+
} // namespace MusEGlobal
diff --git a/muse2/muse/gconfig.h b/muse2/muse/gconfig.h
index d9038ea1..95b88170 100644
--- a/muse2/muse/gconfig.h
+++ b/muse2/muse/gconfig.h
@@ -109,7 +109,7 @@ struct GlobalConfigValues {
double minSlider;
bool freewheelMode;
int guiRefresh;
- QString userInstrumentsDir;
+ QString userInstrumentsDir; // Obsolete. Must keep for compatibility.
bool extendedMidi; // extended smf format
int midiDivision; // division for smf export
@@ -164,6 +164,9 @@ struct GlobalConfigValues {
bool popupsDefaultStayOpen;
bool leftMouseButtonCanDecrease;
bool rangeMarkerWithoutMMB;
+ bool addHiddenTracks;
+ bool unhideTracks;
+
};
diff --git a/muse2/muse/globals.cpp b/muse2/muse/globals.cpp
index 05ba1011..d50ea1eb 100644
--- a/muse2/muse/globals.cpp
+++ b/muse2/muse/globals.cpp
@@ -165,6 +165,12 @@ const char* med_file_save_pattern[] = {
QT_TRANSLATE_NOOP("file_patterns", "All Files (*)"),
0
};
+const char* project_create_file_save_pattern[] = {
+ QT_TRANSLATE_NOOP("file_patterns", "Uncompressed med Files (*.med)"),
+ QT_TRANSLATE_NOOP("file_patterns", "gzip compressed med Files (*.med.gz)"),
+ QT_TRANSLATE_NOOP("file_patterns", "bzip2 compressed med Files (*.med.bz2)"),
+ 0
+ };
const char* image_file_pattern[] = {
QT_TRANSLATE_NOOP("file_patterns", "(*.jpg *.gif *.png)"),
diff --git a/muse2/muse/globals.h b/muse2/muse/globals.h
index ae624fb8..7563c171 100644
--- a/muse2/muse/globals.h
+++ b/muse2/muse/globals.h
@@ -94,6 +94,7 @@ extern const char* midi_file_pattern[];
extern const char* midi_file_save_pattern[];
extern const char* med_file_pattern[];
extern const char* med_file_save_pattern[];
+extern const char* project_create_file_save_pattern[];
extern const char* image_file_pattern[];
//extern const char* ctrl_file_pattern[];
extern const char* part_file_pattern[];
diff --git a/muse2/muse/helper.cpp b/muse2/muse/helper.cpp
index 682bfe8e..f560fbfb 100644
--- a/muse2/muse/helper.cpp
+++ b/muse2/muse/helper.cpp
@@ -20,6 +20,8 @@
//
//=========================================================
+#include <list>
+
#include "helper.h"
#include "part.h"
#include "track.h"
@@ -28,8 +30,22 @@
#include "icons.h"
#include "synth.h"
#include "functions.h"
+#include "gconfig.h"
+
+#include "driver/jackmidi.h"
+#include "route.h"
+#include "mididev.h"
+#include "globaldefs.h"
+#include "audio.h"
+#include "audiodev.h"
+#include "midiseq.h"
#include <QApplication>
+#include <QDir>
+#include <QFileInfo>
+#include <QFileDialog>
+#include <QString>
+//#include <QTemporaryFile>
#ifdef DSSI_SUPPORT
#include "dssihost.h"
@@ -118,170 +134,56 @@ QMenu* populateAddSynth(QWidget* parent)
//typedef std::multimap<std::string, int, addSynth_cmp_str >::iterator imap;
typedef std::multimap<std::string, int >::iterator imap;
- MusECore::MessSynth* synMESS = 0;
- QMenu* synpMESS = 0;
- asmap mapMESS;
-
- #ifdef DSSI_SUPPORT
- MusECore::DssiSynth* synDSSI = 0;
- QMenu* synpDSSI = 0;
- asmap mapDSSI;
- #endif
- #ifdef VST_SUPPORT
- MusECore::VstSynth* synVST = 0;
- QMenu* synpVST = 0;
- asmap mapVST;
- #endif
+ int ntypes = MusECore::Synth::SYNTH_TYPE_END;
+ asmap smaps[ntypes];
+ QMenu* mmaps[ntypes];
+ for(int itype = 0; itype < ntypes; ++itype)
+ mmaps[itype] = 0;
- // Not necessary, but what the heck.
- QMenu* synpOther = 0;
- asmap mapOther;
+ MusECore::Synth* synth;
+ MusECore::Synth::Type type;
- //const int synth_base_id = 0x1000;
int ii = 0;
for(std::vector<MusECore::Synth*>::iterator i = MusEGlobal::synthis.begin(); i != MusEGlobal::synthis.end(); ++i)
{
- synMESS = dynamic_cast<MusECore::MessSynth*>(*i);
- if(synMESS)
- {
- mapMESS.insert( std::pair<std::string, int> (std::string(synMESS->description().toLower().toLatin1().constData()), ii) );
- }
- else
- {
-
- #ifdef DSSI_SUPPORT
- synDSSI = dynamic_cast<MusECore::DssiSynth*>(*i);
- if(synDSSI)
- {
- mapDSSI.insert( std::pair<std::string, int> (std::string(synDSSI->description().toLower().toLatin1().constData()), ii) );
- }
- else
- #endif
-
- {
- #ifdef VST_SUPPORT
- synVST = dynamic_cast<MusECore::VstSynth*>(*i);
- if(synVST)
- {
- mapVST.insert( std::pair<std::string, int> (std::string(synVST->description().toLower().toLatin1().constData()), ii) );
- }
- else
- #endif
-
- {
- mapOther.insert( std::pair<std::string, int> (std::string((*i)->description().toLower().toLatin1().constData()), ii) );
- }
- }
- }
+ synth = *i;
+ type = synth->synthType();
+ if(type >= ntypes)
+ continue;
+ smaps[type].insert( std::pair<std::string, int> (std::string(synth->description().toLower().toLatin1().constData()), ii) );
++ii;
}
int sz = MusEGlobal::synthis.size();
- for(imap i = mapMESS.begin(); i != mapMESS.end(); ++i)
- {
- int idx = i->second;
- if(idx > sz) // Sanity check
- continue;
- MusECore::Synth* s = MusEGlobal::synthis[idx];
- if(s)
+ for(int itype = 0; itype < ntypes; ++itype)
+ {
+ for(imap i = smaps[itype].begin(); i != smaps[itype].end(); ++i)
{
- // No MESS sub-menu yet? Create it now.
- if(!synpMESS)
- synpMESS = new QMenu(parent);
- QAction* sM = synpMESS->addAction(s->description() + " <" + s->name() + ">");
- sM->setData(MENU_ADD_SYNTH_ID_BASE + idx);
- }
- }
-
- #ifdef DSSI_SUPPORT
- for(imap i = mapDSSI.begin(); i != mapDSSI.end(); ++i)
- {
- int idx = i->second;
- if(idx > sz)
- continue;
- MusECore::Synth* s = MusEGlobal::synthis[idx];
- if(s)
- {
- // No DSSI sub-menu yet? Create it now.
- if(!synpDSSI)
- synpDSSI = new QMenu(parent);
- //synpDSSI->insertItem(QT_TRANSLATE_NOOP("@default", s->description()) + " <" + QT_TRANSLATE_NOOP("@default", s->name()) + ">", MENU_ADD_SYNTH_ID_BASE + idx);
- QAction* sD = synpDSSI->addAction(s->description() + " <" + s->name() + ">");
- sD->setData(MENU_ADD_SYNTH_ID_BASE + idx);
- }
- }
- #endif
-
- #ifdef VST_SUPPORT
- for(imap i = mapVST.begin(); i != mapVST.end(); ++i)
- {
- int idx = i->second;
- if(idx > sz)
- continue;
- Synth* s = MusEGlobal::synthis[idx];
- if(s)
- {
- // No VST sub-menu yet? Create it now.
- if(!synpVST)
- synpVST = new QMenu(parent);
- QAction* sV = synpVST->addAction(s->description() + " <" + "@default", s->name() + ">");
- sV->setData(MENU_ADD_SYNTH_ID_BASE + idx);
- }
- }
- #endif
-
- for(imap i = mapOther.begin(); i != mapOther.end(); ++i)
- {
- int idx = i->second;
- if(idx > sz)
- continue;
- MusECore::Synth* s = MusEGlobal::synthis[idx];
- // No Other sub-menu yet? Create it now.
- if(!synpOther)
- synpOther = new QMenu(parent);
- //synpOther->insertItem(QT_TRANSLATE_NOOP("@default", s->description()) + " <" + QT_TRANSLATE_NOOP("@default", s->name()) + ">", MENU_ADD_SYNTH_ID_BASE + idx);
- QAction* sO = synpOther->addAction(s->description() + " <" + s->name() + ">");
- sO->setData(MENU_ADD_SYNTH_ID_BASE + idx);
- }
-
- if(synpMESS)
- {
- synpMESS->setIcon(*synthIcon);
- synpMESS->setTitle("MESS");
- synp->addMenu(synpMESS);
- }
-
- #ifdef DSSI_SUPPORT
- if(synpDSSI)
- {
- synpDSSI->setIcon(*synthIcon);
- synpDSSI->setTitle("DSSI");
- synp->addMenu(synpDSSI);
- }
- #endif
-
- #ifdef VST_SUPPORT
- if(synpVST)
- {
- synpVST->setIcon(*synthIcon);
- synpVST->setTitle("FST");
- synp->addMenu(synpVST);
- }
- #endif
-
- if(synpOther)
- {
- synpOther->setIcon(*synthIcon);
- synpOther->setTitle(QObject::tr("Other"));
- synp->addMenu(synpOther);
+ int idx = i->second;
+ if(idx > sz) // Sanity check
+ continue;
+ synth = MusEGlobal::synthis[idx];
+ if(synth)
+ {
+ // No sub-menu yet? Create it now.
+ if(!mmaps[itype])
+ {
+ mmaps[itype] = new QMenu(parent);
+ mmaps[itype]->setIcon(*synthIcon);
+ mmaps[itype]->setTitle(MusECore::synthType2String((MusECore::Synth::Type)itype));
+ synp->addMenu(mmaps[itype]);
+ }
+ QAction* act = mmaps[itype]->addAction(synth->description() + " <" + synth->name() + ">");
+ act->setData( MENU_ADD_SYNTH_ID_BASE * (itype + 1) + idx );
+ }
+ }
}
-
+
return synp;
}
-
//---------------------------------------------------------
// populateAddTrack
// this is also used in "mixer"
@@ -290,19 +192,27 @@ QMenu* populateAddSynth(QWidget* parent)
QActionGroup* populateAddTrack(QMenu* addTrack, bool populateAll)
{
QActionGroup* grp = new QActionGroup(addTrack);
+ if (MusEGlobal::config.addHiddenTracks)
+ populateAll=true;
- QAction* midi = addTrack->addAction(QIcon(*addtrack_addmiditrackIcon),
+ if (populateAll || MusECore::MidiTrack::visible()) {
+ QAction* midi = addTrack->addAction(QIcon(*addtrack_addmiditrackIcon),
qApp->translate("@default", QT_TRANSLATE_NOOP("@default", "Add Midi Track")));
- midi->setData(MusECore::Track::MIDI);
- grp->addAction(midi);
- QAction* drum = addTrack->addAction(QIcon(*addtrack_drumtrackIcon),
+ midi->setData(MusECore::Track::MIDI);
+ grp->addAction(midi);
+ }
+ if (populateAll || MusECore::MidiTrack::visible()) {
+ QAction* drum = addTrack->addAction(QIcon(*addtrack_drumtrackIcon),
qApp->translate("@default", QT_TRANSLATE_NOOP("@default", "Add Drum Track")));
- drum->setData(MusECore::Track::DRUM);
- grp->addAction(drum);
- QAction* wave = addTrack->addAction(QIcon(*addtrack_wavetrackIcon),
+ drum->setData(MusECore::Track::DRUM);
+ grp->addAction(drum);
+ }
+ if (populateAll || MusECore::WaveTrack::visible()) {
+ QAction* wave = addTrack->addAction(QIcon(*addtrack_wavetrackIcon),
qApp->translate("@default", QT_TRANSLATE_NOOP("@default", "Add Wave Track")));
- wave->setData(MusECore::Track::WAVE);
- grp->addAction(wave);
+ wave->setData(MusECore::Track::WAVE);
+ grp->addAction(wave);
+ }
if (populateAll || MusECore::AudioOutput::visible()) {
QAction* aoutput = addTrack->addAction(QIcon(*addtrack_audiooutputIcon),
@@ -332,20 +242,47 @@ QActionGroup* populateAddTrack(QMenu* addTrack, bool populateAll)
grp->addAction(aaux);
}
- // Create a sub-menu and fill it with found synth types. Make addTrack the owner.
- QMenu* synp = populateAddSynth(addTrack);
- synp->setIcon(*synthIcon);
- synp->setTitle(qApp->translate("@default", QT_TRANSLATE_NOOP("@default", "Add Synth")));
+ if (populateAll || MusECore::SynthI::visible()) {
+ // Create a sub-menu and fill it with found synth types. Make addTrack the owner.
+ QMenu* synp = populateAddSynth(addTrack);
+ synp->setIcon(*synthIcon);
+ synp->setTitle(qApp->translate("@default", QT_TRANSLATE_NOOP("@default", "Add Synth")));
+
+ // Add the sub-menu to the given menu.
+ addTrack->addMenu(synp);
+ }
- // Add the sub-menu to the given menu.
- addTrack->addMenu(synp);
-
//QObject::connect(addTrack, SIGNAL(triggered(QAction *)), MusEGlobal::song, SLOT(addNewTrack(QAction *)));
return grp;
}
+
+//---------------------------------------------------------
+// getFilterExtension
+//---------------------------------------------------------
-} // namespace MusEGui
+QString getFilterExtension(const QString &filter)
+{
+ //
+ // Return the first extension found. Must contain at least one * character.
+ //
+
+ int pos = filter.indexOf('*');
+ if(pos == -1)
+ return QString();
+
+ QString filt;
+ int len = filter.length();
+ ++pos;
+ for( ; pos < len; ++pos)
+ {
+ QChar c = filter[pos];
+ if((c == ')') || (c == ';') || (c == ',') || (c == ' '))
+ break;
+ filt += filter[pos];
+ }
+ return filt;
+}
QStringList localizedStringListFromCharArray(const char** array, const char* context)
{
@@ -355,3 +292,374 @@ QStringList localizedStringListFromCharArray(const char** array, const char* con
return temp;
}
+
+QString browseProjectFolder(QWidget* parent)
+{
+ QString path;
+ if(!MusEGlobal::config.projectBaseFolder.isEmpty())
+ {
+ QDir d(MusEGlobal::config.projectBaseFolder);
+ path = d.absolutePath();
+ }
+
+ QString dir = QFileDialog::getExistingDirectory(parent, qApp->tr("Select project directory"), path);
+ if(dir.isEmpty())
+ dir = MusEGlobal::config.projectBaseFolder;
+ // projDirLineEdit->setText(dir);
+ //return QFileDialog::getExistingDirectory(this, qApp.tr("Select project directory"), path);
+ return dir;
+}
+
+QString projectTitleFromFilename(QString filename)
+{
+ int idx;
+ idx = filename.lastIndexOf(".med.bz2", -1, Qt::CaseInsensitive);
+ if(idx == -1)
+ idx = filename.lastIndexOf(".med.gz", -1, Qt::CaseInsensitive);
+ if(idx == -1)
+ idx = filename.lastIndexOf(".med", -1, Qt::CaseInsensitive);
+
+ if(idx != -1)
+ filename.truncate(idx);
+
+ QFileInfo fi(filename);
+
+ //return fi.baseName();
+ return fi.fileName();
+}
+
+QString projectPathFromFilename(QString filename)
+{
+ QFileInfo fi(filename);
+ return QDir::cleanPath(fi.absolutePath());
+}
+
+QString projectExtensionFromFilename(QString filename)
+{
+ int idx;
+ idx = filename.lastIndexOf(".med.bz2", -1, Qt::CaseInsensitive);
+ if(idx == -1)
+ idx = filename.lastIndexOf(".med.gz", -1, Qt::CaseInsensitive);
+ if(idx == -1)
+ idx = filename.lastIndexOf(".med", -1, Qt::CaseInsensitive);
+ if(idx == -1)
+ idx = filename.lastIndexOf(".bz2", -1, Qt::CaseInsensitive);
+ if(idx == -1)
+ idx = filename.lastIndexOf(".gz", -1, Qt::CaseInsensitive);
+
+ return (idx == -1) ? QString() : filename.right(filename.size() - idx);
+}
+
+QString getUniqueUntitledName()
+{
+ QString filename("untitled");
+ //QTemporaryFile tf(MusEGlobal::config.projectBaseFolder +"/" + s + "XXXXXX.med");
+ //if(tf.open())
+ // s = MusEGui::projectTitleFromFilename(tf.fileName());
+
+ QString fbase(MusEGlobal::config.projectBaseFolder);
+
+ QString nfb = fbase;
+ if(MusEGlobal::config.projectStoreInFolder)
+ nfb += "/" + filename;
+ QFileInfo fi(nfb + "/" + filename + ".med"); // TODO p4.0.40 Check other extensions.
+ if(!fi.exists())
+ //return filename;
+ return fi.filePath();
+
+ // Find a new filename
+ QString nfn = filename;
+ int idx;
+ for (idx=2; idx<10000; idx++) {
+ QString num = QString::number(idx);
+ nfn = filename + "_" + num;
+ nfb = fbase;
+ if(MusEGlobal::config.projectStoreInFolder)
+ nfb += "/" + nfn;
+ QFileInfo fi(nfb + "/" + nfn + ".med");
+ if(!fi.exists())
+ //break;
+ return fi.filePath();
+ }
+
+ //if(idx >= 10000)
+ printf("MusE error: Could not make untitled project name (10000 or more untitled projects in project dir - clean up!\n");
+
+ //return nfn;
+
+ nfb = fbase;
+ if(MusEGlobal::config.projectStoreInFolder)
+ nfb += "/" + filename;
+ return nfb + "/" + filename + ".med";
+}
+
+
+#if 1
+
+// -------------------------------------------------------------------------------------------------------
+// populateMidiPorts()
+// This version creats separate devices for input and output ports.
+// It does not attempt to pair them together.
+// -------------------------------------------------------------------------------------------------------
+void populateMidiPorts()
+{
+ if(!MusEGlobal::checkAudioDevice())
+ return;
+
+ MusECore::MidiDevice* dev = 0;
+
+ int port_num = 0;
+
+ // If Jack is running, prefer Jack midi devices over ALSA.
+ if(MusEGlobal::audioDevice->deviceType() == MusECore::AudioDevice::JACK_AUDIO)
+ {
+ std::list<QString> sl;
+ sl = MusEGlobal::audioDevice->inputPorts(true, 1); // Ask for second aliases.
+ for(std::list<QString>::iterator i = sl.begin(); i != sl.end(); ++i)
+ {
+ dev = MusECore::MidiJackDevice::createJackMidiDevice(*i, 1);
+ if(dev)
+ {
+ //printf("populateMidiPorts Created jack writeable device: %s\n", dev->name().toLatin1().constData());
+ //dev->setOpenFlags(1);
+ MusEGlobal::midiSeq->msgSetMidiDevice(&MusEGlobal::midiPorts[port_num], dev);
+ MusECore::Route srcRoute(dev, -1);
+ MusECore::Route dstRoute(*i, true, -1, MusECore::Route::JACK_ROUTE);
+ MusEGlobal::audio->msgAddRoute(srcRoute, dstRoute);
+ if(++port_num == MIDI_PORTS)
+ return;
+ }
+ }
+
+ sl = MusEGlobal::audioDevice->outputPorts(true, 1); // Ask for second aliases.
+ for(std::list<QString>::iterator i = sl.begin(); i != sl.end(); ++i)
+ {
+ dev = MusECore::MidiJackDevice::createJackMidiDevice(*i, 2);
+ if(dev)
+ {
+ //printf("populateMidiPorts Created jack readable device: %s\n", dev->name().toLatin1().constData());
+ //dev->setOpenFlags(2);
+ MusEGlobal::midiSeq->msgSetMidiDevice(&MusEGlobal::midiPorts[port_num], dev);
+ MusECore::Route srcRoute(*i, false, -1, MusECore::Route::JACK_ROUTE);
+ MusECore::Route dstRoute(dev, -1);
+ MusEGlobal::audio->msgAddRoute(srcRoute, dstRoute);
+ if(++port_num == MIDI_PORTS)
+ return;
+ }
+ }
+ }
+ else
+ // If Jack is not running, use ALSA devices.
+ if(MusEGlobal::audioDevice->deviceType() == MusECore::AudioDevice::DUMMY_AUDIO)
+ {
+ for(MusECore::iMidiDevice i = MusEGlobal::midiDevices.begin(); i != MusEGlobal::midiDevices.end(); ++i)
+ {
+ if((*i)->deviceType() != MusECore::MidiDevice::ALSA_MIDI)
+ continue;
+ dev = *i;
+ // Select only sensible devices first - not thru etc.
+ //if( ... )
+ // continue;
+
+ //dev->setOpenFlags(1);
+ MusEGlobal::midiSeq->msgSetMidiDevice(&MusEGlobal::midiPorts[port_num], dev);
+
+ if(++port_num == MIDI_PORTS)
+ return;
+ }
+
+ //for(MusECore::iMidiDevice i = MusEGlobal::midiDevices.begin(); i != MusEGlobal::midiDevices.end(); ++i)
+ //{
+ // if((*i)->deviceType() != MusECore::MidiDevice::ALSA_MIDI)
+ // continue;
+ // // Select the ones ignored in the first pass.
+ // if(! ... )
+ // continue;
+ //
+ // dev->setOpenFlags(1);
+ // MusEGlobal::midiSeq->msgSetMidiDevice(port_num, dev);
+ //
+ // if(++port_num == MIDI_PORTS)
+ // return;
+ //}
+ }
+
+ //MusEGlobal::muse->changeConfig(true); // save configuration file
+ //MusEGlobal::song->update();
+
+}
+
+#else
+
+// -------------------------------------------------------------------------------------------------------
+// populateMidiPorts()
+// This version worked somewhat well with system devices.
+// But no, it is virtually impossible to tell from the names whether ports should be paired.
+// There is too much room for error - what markers to look for ("capture_"/"playback_") etc.
+// It works kind of OK with 'seq' Jack Midi ALSA devices, but not for 'raw' which have a different
+// naming structure ("in-hw-0-0-0"/"out-hw-0-0-0").
+// It also fails to combine if the ports were named by a client app, for example another instance of MusE.
+// -------------------------------------------------------------------------------------------------------
+
+void populateMidiPorts()
+{
+ if(!MusEGlobal::checkAudioDevice())
+ return;
+
+ MusECore::MidiDevice* dev = 0;
+
+ int port_num = 0;
+
+ // If Jack is running, prefer Jack midi devices over ALSA.
+ if(MusEGlobal::audioDevice->deviceType() == MusECore::AudioDevice::JACK_AUDIO)
+ {
+ std::list<QString> wsl;
+ std::list<QString> rsl;
+ //wsl = MusEGlobal::audioDevice->inputPorts(true, 1); // Ask for second aliases.
+ wsl = MusEGlobal::audioDevice->inputPorts(true, 0); // Ask for first aliases.
+ //rsl = MusEGlobal::audioDevice->outputPorts(true, 1); // Ask for second aliases.
+ rsl = MusEGlobal::audioDevice->outputPorts(true, 0); // Ask for first aliases.
+
+ for(std::list<QString>::iterator wi = wsl.begin(); wi != wsl.end(); ++wi)
+ {
+ QString ws = *wi;
+ int y = ws.lastIndexOf("_");
+ if(y >= 1)
+ {
+ int x = ws.lastIndexOf("_", y-1);
+ if(x >= 0)
+ ws.remove(x, y - x);
+ }
+
+
+ bool match_found = false;
+ for(std::list<QString>::iterator ri = rsl.begin(); ri != rsl.end(); ++ri)
+ {
+ QString rs = *ri;
+ int y = rs.lastIndexOf("_");
+ if(y >= 1)
+ {
+ int x = rs.lastIndexOf("_", y-1);
+ if(x >= 0)
+ rs.remove(x, y - x);
+ }
+
+ // Do we have a matching pair?
+ if(rs == ws)
+ {
+ // Would like to remove the client name, but no, we need it as a distinguishing identifier.
+ //int z = ws.indexOf(":");
+ //if(z >= 0)
+ // ws.remove(0, z + 1);
+
+ dev = MusECore::MidiJackDevice::createJackMidiDevice(ws, 3);
+ if(dev)
+ {
+ //printf("populateMidiPorts Created jack writeable/readable device: %s\n", dev->name().toLatin1().constData());
+ //dev->setOpenFlags(1);
+ MusEGlobal::midiSeq->msgSetMidiDevice(&MusEGlobal::midiPorts[port_num], dev);
+ MusECore::Route devRoute(dev, -1);
+ MusECore::Route wdstRoute(*wi, true, -1, MusECore::Route::JACK_ROUTE);
+ MusECore::Route rsrcRoute(*ri, false, -1, MusECore::Route::JACK_ROUTE);
+ MusEGlobal::audio->msgAddRoute(devRoute, wdstRoute);
+ MusEGlobal::audio->msgAddRoute(rsrcRoute, devRoute);
+ if(++port_num == MIDI_PORTS)
+ return;
+ }
+
+ rsl.erase(ri); // Done with this read port. Remove.
+ match_found = true;
+ break;
+ }
+ }
+
+ if(!match_found)
+ {
+ // No match was found. Create a single writeable device.
+ QString s = *wi;
+ // Would like to remove the client name, but no, we need it as a distinguishing identifier.
+ //int z = s.indexOf(":");
+ //if(z >= 0)
+ // s.remove(0, z + 1);
+ dev = MusECore::MidiJackDevice::createJackMidiDevice(s, 1);
+ if(dev)
+ {
+ //printf("populateMidiPorts Created jack writeable device: %s\n", dev->name().toLatin1().constData());
+ //dev->setOpenFlags(1);
+ MusEGlobal::midiSeq->msgSetMidiDevice(&MusEGlobal::midiPorts[port_num], dev);
+ MusECore::Route srcRoute(dev, -1);
+ MusECore::Route dstRoute(*wi, true, -1, MusECore::Route::JACK_ROUTE);
+ MusEGlobal::audio->msgAddRoute(srcRoute, dstRoute);
+ if(++port_num == MIDI_PORTS)
+ return;
+ }
+ }
+ }
+
+ // Create the remaining readable ports as single readable devices.
+ for(std::list<QString>::iterator ri = rsl.begin(); ri != rsl.end(); ++ri)
+ {
+ QString s = *ri;
+ // Would like to remove the client name, but no, we need it as a distinguishing identifier.
+ //int z = s.indexOf(":");
+ //if(z >= 0)
+ // s.remove(0, z + 1);
+ dev = MusECore::MidiJackDevice::createJackMidiDevice(s, 2);
+ if(dev)
+ {
+ //printf("populateMidiPorts Created jack readable device: %s\n", dev->name().toLatin1().constData());
+ //dev->setOpenFlags(2);
+ MusEGlobal::midiSeq->msgSetMidiDevice(&MusEGlobal::midiPorts[port_num], dev);
+ MusECore::Route srcRoute(*ri, false, -1, MusECore::Route::JACK_ROUTE);
+ MusECore::Route dstRoute(dev, -1);
+ MusEGlobal::audio->msgAddRoute(srcRoute, dstRoute);
+ if(++port_num == MIDI_PORTS)
+ return;
+ }
+ }
+ }
+ else
+ // If Jack is not running, use ALSA devices.
+ if(MusEGlobal::audioDevice->deviceType() == MusECore::AudioDevice::DUMMY_AUDIO)
+ {
+ for(MusECore::iMidiDevice i = MusEGlobal::midiDevices.begin(); i != MusEGlobal::midiDevices.end(); ++i)
+ {
+ if((*i)->deviceType() != MusECore::MidiDevice::ALSA_MIDI)
+ continue;
+ dev = *i;
+ // Select only sensible devices first - not thru etc.
+ //if( ... )
+ // continue;
+
+ //dev->setOpenFlags(1);
+ MusEGlobal::midiSeq->msgSetMidiDevice(&MusEGlobal::midiPorts[port_num], dev);
+
+ if(++port_num == MIDI_PORTS)
+ return;
+ }
+
+ //for(MusECore::iMidiDevice i = MusEGlobal::midiDevices.begin(); i != MusEGlobal::midiDevices.end(); ++i)
+ //{
+ // if((*i)->deviceType() != MusECore::MidiDevice::ALSA_MIDI)
+ // continue;
+ // // Select the ones ignored in the first pass.
+ // if(! ... )
+ // continue;
+ //
+ // dev->setOpenFlags(1);
+ // MusEGlobal::midiSeq->msgSetMidiDevice(port_num, dev);
+ //
+ // if(++port_num == MIDI_PORTS)
+ // return;
+ //}
+ }
+
+ //MusEGlobal::muse->changeConfig(true); // save configuration file
+ //MusEGlobal::song->update();
+
+}
+#endif // populateMidiPorts
+
+
+} // namespace MusEGui
+
diff --git a/muse2/muse/helper.h b/muse2/muse/helper.h
index e1bf93de..f9c9a78c 100644
--- a/muse2/muse/helper.h
+++ b/muse2/muse/helper.h
@@ -42,8 +42,15 @@ bool any_event_selected(const std::set<Part*>&, bool in_range=false);
namespace MusEGui {
QMenu* populateAddSynth(QWidget* parent);
QActionGroup* populateAddTrack(QMenu* addTrack, bool populateAll=false);
+QStringList localizedStringListFromCharArray(const char** array, const char* context);
+QString getFilterExtension(const QString &filter);
+QString browseProjectFolder(QWidget* parent = 0);
+QString projectTitleFromFilename(QString filename);
+QString projectPathFromFilename(QString filename);
+QString projectExtensionFromFilename(QString filename);
+QString getUniqueUntitledName();
+void populateMidiPorts();
}
-QStringList localizedStringListFromCharArray(const char** array, const char* context);
#endif
diff --git a/muse2/muse/instruments/editinstrument.cpp b/muse2/muse/instruments/editinstrument.cpp
index 742e0626..b90b872e 100644
--- a/muse2/muse/instruments/editinstrument.cpp
+++ b/muse2/muse/instruments/editinstrument.cpp
@@ -407,27 +407,10 @@ void EditInstrument::saveAs()
if(!QDir(MusEGlobal::museUserInstruments).exists())
{
- if(QMessageBox::question(this,
- tr("MusE:"),
- tr("The user instrument directory\n%1\ndoes not exist yet. Create it now?\n").arg(MusEGlobal::museUserInstruments) +
- tr("(You can change the user instruments directory at Settings->Global Settings->Midi)"),
- QMessageBox::Ok | QMessageBox::Default,
- QMessageBox::Cancel | QMessageBox::Escape,
- Qt::NoButton) == QMessageBox::Ok)
- {
- if(QDir().mkdir(MusEGlobal::museUserInstruments))
- printf("Created user instrument directory: %s\n", MusEGlobal::museUserInstruments.toLatin1().constData());
- else
- {
- printf("Unable to create user instrument directory: %s\n", MusEGlobal::museUserInstruments.toLatin1().constData());
- QMessageBox::critical(this, tr("MusE:"), tr("Unable to create user instrument directory '%1'").arg(MusEGlobal::museUserInstruments));
- //return;
- path = MusEGlobal::museUser;
- }
- }
- else
- // return;
- path = MusEGlobal::museUser;
+ printf("MusE Error! User instrument directory: %s does not exist. Should be created at startup!\n", MusEGlobal::museUserInstruments.toLatin1().constData());
+
+ //path = MusEGlobal::museUser;
+ //path = MusEGlobal::configPath;
}
//if (instrument->filePath().isEmpty())
@@ -699,27 +682,10 @@ void EditInstrument::fileSaveAs()
if(!QDir(MusEGlobal::museUserInstruments).exists())
{
- if(QMessageBox::question(this,
- tr("MusE:"),
- tr("The user instrument directory\n%1\ndoes not exist yet. Create it now?\n").arg(MusEGlobal::museUserInstruments) +
- tr("(You can change the user instruments directory at Settings->Global Settings->Midi)"),
- QMessageBox::Ok | QMessageBox::Default,
- QMessageBox::Cancel | QMessageBox::Escape,
- Qt::NoButton) == QMessageBox::Ok)
- {
- if(QDir().mkdir(MusEGlobal::museUserInstruments))
- printf("Created user instrument directory: %s\n", MusEGlobal::museUserInstruments.toLatin1().constData());
- else
- {
- printf("Unable to create user instrument directory: %s\n", MusEGlobal::museUserInstruments.toLatin1().constData());
- QMessageBox::critical(this, tr("MusE:"), tr("Unable to create user instrument directory '%1'").arg(MusEGlobal::museUserInstruments));
- //return;
- path = MusEGlobal::museUser;
- }
- }
- else
- // return;
- path = MusEGlobal::museUser;
+ printf("MusE Error! User instrument directory: %s does not exist. Should be created at startup!\n", MusEGlobal::museUserInstruments.toLatin1().constData());
+
+ //path = MusEGlobal::museUser;
+ //path = MusEGlobal::configPath;
}
path += QString("/%1.idf").arg(so);
diff --git a/muse2/muse/instruments/minstrument.cpp b/muse2/muse/instruments/minstrument.cpp
index 8e8bb6c3..22ed3737 100644
--- a/muse2/muse/instruments/minstrument.cpp
+++ b/muse2/muse/instruments/minstrument.cpp
@@ -936,8 +936,69 @@ QString MidiInstrument::getPatchName(int channel, int prog, MType mode, bool dru
// populatePatchPopup
//---------------------------------------------------------
+void MidiInstrument::populatePatchPopup(MusEGui::PopupMenu* menu, int chan, MType songType, bool drum)
+ {
+ menu->clear();
+ int mask = 0;
+ bool drumchan = chan == 9;
+ switch (songType) {
+ case MT_XG: mask = 4; break;
+ case MT_GS: mask = 2; break;
+ case MT_GM:
+ if(drumchan)
+ {
+ int id = (0xff << 16) + (0xff << 8) + 0x00; // First patch
+ QAction* act = menu->addAction(gmdrumname);
+ //act->setCheckable(true);
+ act->setData(id);
+ return;
+ }
+ mask = 1;
+ break;
+ case MT_UNKNOWN: mask = 7; break;
+ }
+ if (pg.size() > 1) {
+ for (ciPatchGroup i = pg.begin(); i != pg.end(); ++i) {
+ PatchGroup* pgp = *i;
+ //QMenu* pm = menu->addMenu(pgp->name);
+ MusEGui::PopupMenu* pm = new MusEGui::PopupMenu(pgp->name, menu, menu->stayOpen()); // Use the parent stayOpen here.
+ menu->addMenu(pm);
+ pm->setFont(MusEGlobal::config.fonts[0]);
+ const PatchList& pl = pgp->patches;
+ for (ciPatch ipl = pl.begin(); ipl != pl.end(); ++ipl) {
+ const Patch* mp = *ipl;
+ if ((mp->typ & mask) &&
+ ((drum && songType != MT_GM) ||
+ (mp->drum == drumchan)) )
+ {
+ int id = ((mp->hbank & 0xff) << 16)
+ + ((mp->lbank & 0xff) << 8) + (mp->prog & 0xff);
+ QAction* act = pm->addAction(mp->name);
+ //act->setCheckable(true);
+ act->setData(id);
+ }
+
+ }
+ }
+ }
+ else if (pg.size() == 1 ){
+ // no groups
+ const PatchList& pl = pg.front()->patches;
+ for (ciPatch ipl = pl.begin(); ipl != pl.end(); ++ipl) {
+ const Patch* mp = *ipl;
+ if (mp->typ & mask) {
+ int id = ((mp->hbank & 0xff) << 16)
+ + ((mp->lbank & 0xff) << 8) + (mp->prog & 0xff);
+ QAction* act = menu->addAction(mp->name);
+ //act->setCheckable(true);
+ act->setData(id);
+ }
+ }
+ }
+
} // namespace MusECore
+/*
namespace MusEGui {
void populatePatchPopup(MusECore::MidiInstrument* midiInstrument, PopupMenu* menu, int chan, MType songType, bool drum)
@@ -1000,5 +1061,6 @@ void populatePatchPopup(MusECore::MidiInstrument* midiInstrument, PopupMenu* men
}
}
}
+*/
} // namespace MusEGui
diff --git a/muse2/muse/instruments/minstrument.h b/muse2/muse/instruments/minstrument.h
index 3a645d7f..385e67b4 100644
--- a/muse2/muse/instruments/minstrument.h
+++ b/muse2/muse/instruments/minstrument.h
@@ -143,7 +143,7 @@ class MidiInstrument {
virtual void reset(int, MType);
virtual QString getPatchName(int,int,MType,bool);
//virtual void populatePatchPopup(QMenu*, int, MType, bool);
- //virtual void populatePatchPopup(MusEGui::PopupMenu*, int, MType, bool);
+ virtual void populatePatchPopup(MusEGui::PopupMenu*, int, MType, bool);
void read(Xml&);
void write(int level, Xml&);
@@ -171,8 +171,8 @@ extern void removeMidiInstrument(const MidiInstrument* instr);
} // namespace MusECore
-namespace MusEGui {
-extern void populatePatchPopup(MusECore::MidiInstrument*, PopupMenu*, int, MType, bool);
-}
+//namespace MusEGui {
+//extern void populatePatchPopup(MusECore::MidiInstrument*, PopupMenu*, int, MType, bool);
+//}
#endif
diff --git a/muse2/muse/liste/editevent.cpp b/muse2/muse/liste/editevent.cpp
index bca5729b..214f74c2 100644
--- a/muse2/muse/liste/editevent.cpp
+++ b/muse2/muse/liste/editevent.cpp
@@ -871,20 +871,17 @@ void EditCtrlDialog::instrPopup()
int port = track->outPort();
MusECore::MidiInstrument* instr = MusEGlobal::midiPorts[port].instrument();
- ///instr->populatePatchPopup(pop, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
//QMenu* pup = new QMenu(this);
MusEGui::PopupMenu* pup = new MusEGui::PopupMenu(this);
- populatePatchPopup(instr, pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
+ //populatePatchPopup(instr, pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
+ instr->populatePatchPopup(pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
- ///if(pop->actions().count() == 0)
- /// return;
if(pup->actions().count() == 0)
{
delete pup;
return;
}
- ///QAction* rv = pop->exec(patchName->mapToGlobal(QPoint(10,5)));
QAction* rv = pup->exec(patchName->mapToGlobal(QPoint(10,5)));
if (rv) {
val = rv->data().toInt();
diff --git a/muse2/muse/liste/listedit.cpp b/muse2/muse/liste/listedit.cpp
index f6a77b85..6795cedb 100644
--- a/muse2/muse/liste/listedit.cpp
+++ b/muse2/muse/liste/listedit.cpp
@@ -45,6 +45,7 @@
#include "event.h"
#include "midiport.h"
#include "midictrl.h"
+#include "app.h"
namespace MusEGui {
@@ -616,6 +617,8 @@ ListEdit::ListEdit(MusECore::PartList* pl)
initShortcuts();
setWindowTitle("MusE: List Editor");
+
+ MusEGlobal::muse->topwinMenuInited(this);
}
//---------------------------------------------------------
diff --git a/muse2/muse/main.cpp b/muse2/muse/main.cpp
index 0353d0d6..d946bf00 100644
--- a/muse2/muse/main.cpp
+++ b/muse2/muse/main.cpp
@@ -24,6 +24,8 @@
#include <QApplication>
#include <QDir>
#include <QFile>
+#include <QFileInfo>
+#include <QFileInfoList>
#include <QKeyEvent>
#include <QMessageBox>
#include <QLocale>
@@ -31,6 +33,8 @@
#include <QTimer>
#include <QTranslator>
#include <QIcon>
+#include <QString>
+#include <QStringList>
#include <sys/mman.h>
#include <alsa/asoundlib.h>
@@ -41,6 +45,7 @@
#include "audiodev.h"
#include "gconfig.h"
#include "globals.h"
+#include "helper.h"
#include "icons.h"
#include "sync.h"
#include "functions.h"
@@ -267,9 +272,38 @@ int main(int argc, char* argv[])
if (! cPath.exists())
cPath.mkpath(".");
+ // Create user templates dir if it doesn't exist
+ QDir utemplDir = QDir(MusEGlobal::configPath + QString("/templates"));
+ if(!utemplDir.exists())
+ {
+ utemplDir.mkpath(".");
+ // Support old versions: Copy existing templates over.
+ QDir old_utemplDir = QDir(QString(getenv("HOME")) + QString("/templates"));
+ // printf(" old templates dir:%s\n", (QString(getenv("HOME")) + QString("/templates")).toLatin1().constData());
+ if(old_utemplDir.exists())
+ {
+ //printf(" found old templates dir\n");
+ // We really just want these, even though it's possible other filenames were saved.
+ // Another application might have used that directory.
+ QStringList flt; flt << "*.med" << "*.med.gz" << "*.med.bz2" << "*.mid" << "*.midi" << "*.kar";
+ old_utemplDir.setNameFilters(flt);
+
+ QFileInfoList fil = old_utemplDir.entryInfoList();
+ QFileInfo fi;
+ foreach(fi, fil)
+ {
+ QString fn = fi.fileName();
+ QFile f(fi.absoluteFilePath());
+ f.copy(utemplDir.absolutePath() + "/" + fn);
+ //printf(" copy old template to:%s result:%d\n", QString(utemplPath.absolutePath() + "/" + fn).toLatin1().constData(), rv);
+ }
+ }
+ }
+
QFile cConf (MusEGlobal::configName);
QFile cConfTempl (MusEGlobal::museGlobalShare + QString("/templates/MusE.cfg"));
- if (! cConf.exists())
+ bool cConfExists = cConf.exists();
+ if (!cConfExists)
{
printf ("creating new config...\n");
if (cConfTempl.copy(MusEGlobal::configName))
@@ -303,10 +337,51 @@ int main(int argc, char* argv[])
MusEGui::init_function_dialogs(MusEGlobal::muse);
MusEGui::initShortCuts();
+
MusECore::readConfiguration();
- MusEGlobal::museUserInstruments = MusEGlobal::config.userInstrumentsDir;
+ // Need to put a sane default here because we can't use ~ in the file name string.
+ if(!cConfExists)
+ MusEGlobal::config.projectBaseFolder = MusEGlobal::museUser + QString("/MusE");
+ //MusEGlobal::museUserInstruments = MusEGlobal::config.userInstrumentsDir;
+
+ // Create user instruments dir if it doesn't exist
+ {
+ QString uinstrPath = MusEGlobal::configPath + QString("/instruments");
+ QDir uinstrDir = QDir(uinstrPath);
+ if(!uinstrDir.exists())
+ uinstrDir.mkpath(".");
+
+ if(!MusEGlobal::config.userInstrumentsDir.isEmpty() && MusEGlobal::config.userInstrumentsDir != uinstrPath) // Only if it is different.
+ {
+ // Support old versions: Copy existing instruments over.
+ QDir old_uinstrDir(MusEGlobal::config.userInstrumentsDir);
+ //printf(" old instruments dir:%s\n", MusEGlobal::config.userInstrumentsDir.toLatin1().constData());
+ if(old_uinstrDir.exists())
+ {
+ //printf(" found old instruments dir\n");
+ QStringList flt; flt << "*.idf";
+ old_uinstrDir.setNameFilters(flt);
+
+ QFileInfoList fil = old_uinstrDir.entryInfoList();
+ QFileInfo fi;
+ foreach(fi, fil)
+ {
+ QString fn = fi.fileName();
+ QFile f(fi.absoluteFilePath());
+ QFile newf(uinstrDir.absolutePath() + "/" + fn);
+ if(!newf.exists())
+ {
+ f.copy(newf.fileName());
+ //printf(" copy old instrument to:%s result:%d\n", newf.fileName().toLatin1().constData(), rv);
+ }
+ }
+ }
+ }
+ MusEGlobal::museUserInstruments = uinstrPath;
+ }
+
if (MusEGlobal::config.useDenormalBias)
printf("Denormal protection enabled.\n");
// SHOW MUSE SPLASH SCREEN
@@ -324,7 +399,7 @@ int main(int argc, char* argv[])
stimer->start(6000);
}
}
-
+
int i;
QString optstr("ahvdDmMsP:Y:l:py");
@@ -393,6 +468,7 @@ int main(int argc, char* argv[])
}
*/
+
AL::initDsp();
if (MusEGlobal::debugMsg)
@@ -438,8 +514,7 @@ int main(int argc, char* argv[])
else
MusEGlobal::realTimeScheduling = MusEGlobal::audioDevice->isRealtime();
-
- // What unreliable nonsense. With Jack2 this reports true even if it is not running realtime.
+ // ??? With Jack2 this reports true even if it is not running realtime.
// Jack says: "Cannot use real-time scheduling (RR/10)(1: Operation not permitted)". The kernel is non-RT.
// I cannot seem to find a reliable answer to the question, even with dummy audio and system calls.
//if (MusEGlobal::debugMsg)
@@ -448,11 +523,7 @@ int main(int argc, char* argv[])
MusEGlobal::useJackTransport.setValue(true);
// setup the prefetch fifo length now that the segmentSize is known
- // Changed by Tim. p3.3.17
- // Changed to 4 *, JUST FOR TEST!!!
MusEGlobal::fifoLength = 131072 / MusEGlobal::segmentSize;
- //MusEGlobal::fifoLength = (131072 / MusEGlobal::segmentSize) * 4;
-
argc -= optind;
++argc;
@@ -498,7 +569,6 @@ int main(int argc, char* argv[])
if(MusEGlobal::loadDSSI)
MusECore::initDSSI();
- // p3.3.39
MusECore::initOSC();
MusEGui::initIcons();
@@ -517,21 +587,19 @@ int main(int argc, char* argv[])
++it;
}
}
-
+
MusEGlobal::muse = new MusEGui::MusE(argc, &argv[optind]);
app.setMuse(MusEGlobal::muse);
MusEGlobal::muse->setWindowIcon(*MusEGui::museIcon);
-
- // Added by Tim. p3.3.22
if (!MusEGlobal::debugMode) {
if (mlockall(MCL_CURRENT | MCL_FUTURE))
perror("WARNING: Cannot lock memory:");
}
MusEGlobal::muse->show();
- MusEGlobal::muse->seqStart();
-
+ MusEGlobal::muse->seqStart();
+
#ifdef HAVE_LASH
{
MusEGui::lash_client = 0;
@@ -542,14 +610,28 @@ int main(int argc, char* argv[])
MusEGui::lash_client = lash_init (lash_args, muse_name, lash_flags, LASH_PROTOCOL(2,0));
lash_alsa_client_id (MusEGui::lash_client, snd_seq_client_id (MusECore::alsaSeq));
if (!noAudio) {
- // p3.3.38
- //char *jack_name = ((JackAudioDevice*)MusEGlobal::audioDevice)->getJackName();
const char *jack_name = MusEGlobal::audioDevice->clientName();
lash_jack_client_name (MusEGui::lash_client, jack_name);
}
}
}
#endif /* HAVE_LASH */
+
+ //--------------------------------------------------
+ // Auto-fill the midi ports, if appropriate. p4.0.41
+ //--------------------------------------------------
+ if(argc < 2 && MusEGlobal::config.startMode == 1)
+ {
+ MusEGui::populateMidiPorts();
+ //MusEGlobal::muse->changeConfig(true); // save configuration file
+ //MusEGlobal::song->update();
+ }
+
+ //--------------------------------------------------
+ // Load the default song.
+ //--------------------------------------------------
+ MusEGlobal::muse->loadDefaultSong(argc, &argv[optind]); // p4.0.41
+
QTimer::singleShot(100, MusEGlobal::muse, SLOT(showDidYouKnowDialog()));
int rv = app.exec();
diff --git a/muse2/muse/marker/markerview.cpp b/muse2/muse/marker/markerview.cpp
index bc9e48b9..39ce4fc0 100644
--- a/muse2/muse/marker/markerview.cpp
+++ b/muse2/muse/marker/markerview.cpp
@@ -26,6 +26,7 @@
#include "markerview.h"
#include "xml.h"
#include "globals.h"
+#include "app.h"
#include "sync.h"
#include "icons.h"
#include "song.h"
@@ -157,7 +158,7 @@ void MarkerItem::setTick(unsigned v)
void MarkerView::closeEvent(QCloseEvent* e)
{
- emit deleted(static_cast<TopWin*>(this));
+ emit isDeleting(static_cast<TopWin*>(this));
emit closed();
e->accept();
}
@@ -296,6 +297,8 @@ MarkerView::MarkerView(QWidget* parent)
updateList();
+ MusEGlobal::muse->topwinMenuInited(this);
+
// work around for probable QT/WM interaction bug.
// for certain window managers, e.g xfce, this window is
// is displayed although not specifically set to show();
diff --git a/muse2/muse/marker/markerview.h b/muse2/muse/marker/markerview.h
index b50ab7a4..06e22daf 100644
--- a/muse2/muse/marker/markerview.h
+++ b/muse2/muse/marker/markerview.h
@@ -96,7 +96,7 @@ class MarkerView : public TopWin {
void songChanged(int);
signals:
- void deleted(MusEGui::TopWin*);
+ void isDeleting(MusEGui::TopWin*);
void closed();
public:
diff --git a/muse2/muse/master/lmaster.cpp b/muse2/muse/master/lmaster.cpp
index 52b488d0..f461e1d3 100644
--- a/muse2/muse/master/lmaster.cpp
+++ b/muse2/muse/master/lmaster.cpp
@@ -27,6 +27,7 @@
#include "xml.h"
#include "song.h"
#include "globals.h"
+#include "app.h"
#include "audio.h"
//#include "posedit.h"
//#include "sigedit.h"
@@ -286,6 +287,7 @@ LMaster::LMaster()
connect(keyButton, SIGNAL(clicked()), SLOT(insertKey()));
initShortcuts();
+ MusEGlobal::muse->topwinMenuInited(this);
}
//---------------------------------------------------------
diff --git a/muse2/muse/master/masteredit.cpp b/muse2/muse/master/masteredit.cpp
index 191f82ab..f6169766 100644
--- a/muse2/muse/master/masteredit.cpp
+++ b/muse2/muse/master/masteredit.cpp
@@ -37,6 +37,7 @@
#include "doublelabel.h"
///#include "sigedit.h"
#include "globals.h"
+#include "app.h"
#include <values.h>
@@ -269,6 +270,7 @@ MasterEdit::MasterEdit()
connect(canvas, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
initTopwinState();
+ MusEGlobal::muse->topwinMenuInited(this);
}
//---------------------------------------------------------
diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp
index b07ebbbe..52e63da0 100644
--- a/muse2/muse/midiedit/drumedit.cpp
+++ b/muse2/muse/midiedit/drumedit.cpp
@@ -53,6 +53,7 @@
#include "vscale.h"
#include "swidget.h"
#include "globals.h"
+#include "app.h"
#include "icons.h"
#include "filedialog.h"
#include "drummap.h"
@@ -535,6 +536,7 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un
initTopwinState();
+ MusEGlobal::muse->topwinMenuInited(this);
}
//---------------------------------------------------------
diff --git a/muse2/muse/midiedit/ecanvas.cpp b/muse2/muse/midiedit/ecanvas.cpp
index 9189d177..80d901bb 100644
--- a/muse2/muse/midiedit/ecanvas.cpp
+++ b/muse2/muse/midiedit/ecanvas.cpp
@@ -3,6 +3,7 @@
// Linux Music Editor
// $Id: ecanvas.cpp,v 1.8.2.6 2009/05/03 04:14:00 terminator356 Exp $
// (C) Copyright 2001 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -325,54 +326,54 @@ void EventCanvas::keyPress(QKeyEvent* event)
}
// Select items by key (PianoRoll & DrumEditor)
else if (key == shortcuts[SHRT_SEL_RIGHT].key || key == shortcuts[SHRT_SEL_RIGHT_ADD].key) {
- iCItem i, iRightmost;
- CItem* rightmost = NULL;
- //Get the rightmost selected note (if any)
- for (i = items.begin(); i != items.end(); ++i) {
- if (i->second->isSelected()) {
- iRightmost = i; rightmost = i->second;
- }
- }
- if (rightmost) {
- iCItem temp = iRightmost; temp++;
- //If so, deselect current note and select the one to the right
- if (temp != items.end()) {
- if (key != shortcuts[SHRT_SEL_RIGHT_ADD].key)
- deselectAll();
-
- iRightmost++;
- iRightmost->second->setSelected(true);
- updateSelection();
- }
- }
- //if (rightmost && mapx(rightmost->event().tick()) > width()) for some reason this doesn't this doesnt move the event in view
- // emit followEvent(rightmost->x());
-
+ rciCItem i;
+ for (i = items.rbegin(); i != items.rend(); ++i)
+ if (i->second->isSelected())
+ break;
+
+ if(i == items.rend())
+ i = items.rbegin();
+
+ if(i != items.rbegin())
+ --i;
+ if(i->second)
+ {
+ if (key != shortcuts[SHRT_SEL_RIGHT_ADD].key)
+ deselectAll();
+ CItem* sel = i->second;
+ sel->setSelected(true);
+ updateSelection();
+ if (sel->x() + sel->width() > mapxDev(width()))
+ {
+ int mx = rmapx(sel->x());
+ int newx = mx + rmapx(sel->width()) - width();
+ // Leave a bit of room for the specially-drawn drum notes. But good for piano too.
+ emit horizontalScroll( (newx > mx ? mx - 10: newx + 10) - rmapx(xorg) );
+ }
+ }
}
//Select items by key: (PianoRoll & DrumEditor)
else if (key == shortcuts[SHRT_SEL_LEFT].key || key == shortcuts[SHRT_SEL_LEFT_ADD].key) {
- iCItem i, iLeftmost;
- CItem* leftmost = NULL;
- if (items.size() > 0 ) {
- for (i = items.end(), i--; i != items.begin(); i--) {
- if (i->second->isSelected()) {
- iLeftmost = i; leftmost = i->second;
- }
- }
- if (leftmost) {
- if (iLeftmost != items.begin()) {
- //Add item
- if (key != shortcuts[SHRT_SEL_LEFT_ADD].key)
- deselectAll();
-
- iLeftmost--;
- iLeftmost->second->setSelected(true);
- updateSelection();
- }
- }
- //if (leftmost && mapx(leftmost->event().tick())< 0 ) for some reason this doesn't this doesnt move the event in view
- // emit followEvent(leftmost->x());
- }
+ ciCItem i;
+ for (i = items.begin(); i != items.end(); ++i)
+ if (i->second->isSelected())
+ break;
+
+ if(i == items.end())
+ i = items.begin();
+
+ if(i != items.begin())
+ --i;
+ if(i->second)
+ {
+ if (key != shortcuts[SHRT_SEL_LEFT_ADD].key)
+ deselectAll();
+ CItem* sel = i->second;
+ sel->setSelected(true);
+ updateSelection();
+ if (sel->x() <= mapxDev(0))
+ emit horizontalScroll(rmapx(sel->x() - xorg) - 10); // Leave a bit of room.
+ }
}
else if (key == shortcuts[SHRT_INC_PITCH].key) {
modifySelected(NoteInfo::VAL_PITCH, 1);
diff --git a/muse2/muse/midiedit/pianoroll.cpp b/muse2/muse/midiedit/pianoroll.cpp
index 926f4212..8c2a7a87 100644
--- a/muse2/muse/midiedit/pianoroll.cpp
+++ b/muse2/muse/midiedit/pianoroll.cpp
@@ -56,6 +56,7 @@
#include "tb1.h"
#include "utils.h"
#include "globals.h"
+#include "app.h"
#include "gconfig.h"
#include "icons.h"
#include "audio.h"
@@ -532,6 +533,7 @@ PianoRoll::PianoRoll(MusECore::PartList* pl, QWidget* parent, const char* name,
}
initTopwinState();
+ MusEGlobal::muse->topwinMenuInited(this);
}
//---------------------------------------------------------
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index b06f2487..51e1cafc 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -166,6 +166,15 @@ QColor* mycolors; // array [NUM_MYCOLORS]
set<QString> ScoreEdit::names;
+int ScoreCanvas::_quant_power2_init=3;
+int ScoreCanvas::_pixels_per_whole_init=300;
+int ScoreCanvas::note_velo_init=64;
+int ScoreCanvas::note_velo_off_init=64;
+int ScoreCanvas::new_len_init=0;
+ScoreCanvas::coloring_mode_t ScoreCanvas::coloring_mode_init=COLOR_MODE_BLACK;
+bool ScoreCanvas::preamble_contains_timesig_init=true;
+bool ScoreCanvas::preamble_contains_keysig_init=true;
+
//---------------------------------------------------------
// ScoreEdit
@@ -293,8 +302,22 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos)
len_actions->addAction(n32_action);
len_actions->addAction(nlast_action);
- nlast_action->setChecked(true);
- menu_command(CMD_NOTELEN_LAST);
+ switch (ScoreCanvas::new_len_init)
+ {
+ case 0: nlast_action->setChecked(true); menu_command(CMD_NOTELEN_LAST); break;
+ case 1: n1_action->setChecked(true); menu_command(CMD_NOTELEN_1); break;
+ case 2: n2_action->setChecked(true); menu_command(CMD_NOTELEN_2); break;
+ case 4: n4_action->setChecked(true); menu_command(CMD_NOTELEN_4); break;
+ case 8: n8_action->setChecked(true); menu_command(CMD_NOTELEN_8); break;
+ case 16: n16_action->setChecked(true); menu_command(CMD_NOTELEN_16); break;
+ case 32: n32_action->setChecked(true); menu_command(CMD_NOTELEN_32); break;
+ default:
+ cerr << "ERROR: THIS SHOULD NEVER HAPPEN. newLen is invalid in ScoreEdit::ScoreEdit.\n" <<
+ " (newLen="<<ScoreCanvas::new_len_init<<"; the only valid values are 0,1,2,4,8,16 and 32)\n" <<
+ " however, don't worry, this is no major problem, using 0 instead" << endl;
+ nlast_action->setChecked(true);
+ menu_command(CMD_NOTELEN_LAST);
+ }
note_settings_toolbar->addSeparator();
@@ -316,7 +339,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos)
connect(velo_spinbox, SIGNAL(editingFinished()), SLOT(velo_box_changed()));
connect(this,SIGNAL(velo_changed(int)), score_canvas, SLOT(set_velo(int)));
note_settings_toolbar->addWidget(velo_spinbox);
- velo_spinbox->setValue(64);
+ velo_spinbox->setValue(ScoreCanvas::note_velo_init);
note_settings_toolbar->addWidget(new QLabel(tr("Off-Velocity:"), note_settings_toolbar));
velo_off_spinbox = new QSpinBox(this);
@@ -327,7 +350,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos)
connect(velo_off_spinbox, SIGNAL(editingFinished()), SLOT(velo_off_box_changed()));
connect(this,SIGNAL(velo_off_changed(int)), score_canvas, SLOT(set_velo_off(int)));
note_settings_toolbar->addWidget(velo_off_spinbox);
- velo_off_spinbox->setValue(64);
+ velo_off_spinbox->setValue(ScoreCanvas::note_velo_off_init);
@@ -336,13 +359,16 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos)
quant_toolbar->addWidget(new QLabel(tr("Quantisation:"), quant_toolbar));
quant_combobox = new QComboBox(this);
quant_combobox->addItem("2"); // if you add or remove items from
- quant_combobox->addItem("4"); // here, also change quant_mapper[]
- quant_combobox->addItem("8"); // in ScoreCanvas::set_quant()!
+ quant_combobox->addItem("4"); // here, also change all code regarding
+ quant_combobox->addItem("8"); // _quant_power2 and _quant_power2_init
quant_combobox->addItem("16"); // and MAX_QUANT_POWER (must be log2(largest_value))
quant_combobox->addItem("32");
+ quant_combobox->setCurrentIndex(score_canvas->quant_power2()-1);
+ // the above is intendedly executed BEFORE connecting. otherwise this would
+ // destroy pixels_per_whole_init!
connect(quant_combobox, SIGNAL(currentIndexChanged(int)), score_canvas, SLOT(set_quant(int)));
quant_toolbar->addWidget(quant_combobox);
- quant_combobox->setCurrentIndex(2);
+
quant_toolbar->addSeparator();
@@ -353,7 +379,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos)
connect(px_per_whole_spinbox, SIGNAL(valueChanged(int)), score_canvas, SLOT(set_pixels_per_whole(int)));
connect(score_canvas, SIGNAL(pixels_per_whole_changed(int)), px_per_whole_spinbox, SLOT(setValue(int)));
quant_toolbar->addWidget(px_per_whole_spinbox);
- px_per_whole_spinbox->setValue(300);
+ px_per_whole_spinbox->setValue(ScoreCanvas::_pixels_per_whole_init);
QMenu* edit_menu = menuBar()->addMenu(tr("&Edit"));
@@ -454,8 +480,18 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos)
menu_mapper->setMapping(color_velo_action, CMD_COLOR_VELO);
menu_mapper->setMapping(color_part_action, CMD_COLOR_PART);
- color_black_action->setChecked(true);
- menu_command(CMD_COLOR_BLACK);
+ switch (ScoreCanvas::coloring_mode_init)
+ {
+ case 0: color_black_action->setChecked(true); menu_command(CMD_COLOR_BLACK); break;
+ case 1: color_velo_action->setChecked(true); menu_command(CMD_COLOR_VELO); break;
+ case 2: color_part_action->setChecked(true); menu_command(CMD_COLOR_PART); break;
+ default:
+ cerr << "ERROR: THIS SHOULD NEVER HAPPEN. noteColor is invalid in ScoreEdit::ScoreEdit.\n" <<
+ " (noteColor="<<ScoreCanvas::coloring_mode_init<<"; the only valid values are 0,1 and 2)\n" <<
+ " however, don't worry, this is no major problem, using 0 instead" << endl;
+ color_black_action->setChecked(true);
+ menu_command(CMD_COLOR_BLACK);
+ }
QMenu* preamble_menu = settings_menu->addMenu(tr("Set up &preamble"));
preamble_keysig_action = preamble_menu->addAction(tr("Display &key signature"));
@@ -466,8 +502,8 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos)
preamble_keysig_action->setCheckable(true);
preamble_timesig_action->setCheckable(true);
- preamble_keysig_action->setChecked(true);
- preamble_timesig_action->setChecked(true);
+ preamble_keysig_action->setChecked(ScoreCanvas::preamble_contains_keysig_init);
+ preamble_timesig_action->setChecked(ScoreCanvas::preamble_contains_timesig_init);
QAction* set_name_action = settings_menu->addAction(tr("Set Score &name"), menu_mapper, SLOT(map()));
menu_mapper->setMapping(set_name_action, CMD_SET_NAME);
@@ -503,6 +539,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos)
apply_velo=true;
initTopwinState();
+ MusEGlobal::muse->topwinMenuInited(this);
}
void ScoreEdit::init_shortcuts()
@@ -587,7 +624,7 @@ bool ScoreEdit::set_name(QString newname, bool emit_signal, bool emergency_name)
ScoreEdit::~ScoreEdit()
{
-
+ names.erase(name);
}
void ScoreEdit::velo_box_changed()
@@ -602,9 +639,9 @@ void ScoreEdit::velo_off_box_changed()
void ScoreEdit::song_changed(int flags)
{
- if(_isDeleting) // Ignore while while deleting to prevent crash.
- return;
-
+ if(_isDeleting) // Ignore while while deleting to prevent crash.
+ return;
+
if (flags & (SC_SELECTION | SC_EVENT_MODIFIED | SC_EVENT_REMOVED))
{
map<MusECore::Event*, MusECore::Part*> selection=get_events(score_canvas->get_all_parts(),1);
@@ -673,8 +710,9 @@ void ScoreEdit::viewport_height_changed(int height)
void ScoreEdit::closeEvent(QCloseEvent* e)
{
- _isDeleting = true; // Set flag so certain signals like songChanged, which may cause crash during delete, can be ignored.
-
+ _isDeleting = true; // Set flag so certain signals like songChanged, which may cause crash during delete, can be ignored.
+ names.erase(name);
+
QSettings settings("MusE", "MusE-qt");
//settings.setValue("ScoreEdit/geometry", saveGeometry());
settings.setValue("ScoreEdit/windowState", saveState());
@@ -692,8 +730,8 @@ void ScoreEdit::menu_command(int cmd)
{
bool ok;
QString newname = QInputDialog::getText(this, tr("Enter the new score title"),
- tr("Enter the new score title"), QLineEdit::Normal,
- name, &ok);
+ tr("Enter the new score title"), QLineEdit::Normal,
+ name, &ok);
if (ok)
{
if (!set_name(newname))
@@ -1059,7 +1097,23 @@ void ScoreEdit::read_configuration(MusECore::Xml& xml)
switch (token)
{
case MusECore::Xml::TagStart:
- if (tag == "topwin")
+ if (tag=="quantPowerInit")
+ ScoreCanvas::_quant_power2_init=xml.parseInt();
+ else if (tag=="pxPerWholeInit")
+ ScoreCanvas::_pixels_per_whole_init=xml.parseInt();
+ else if (tag=="newNoteVeloInit")
+ ScoreCanvas::note_velo_init=xml.parseInt();
+ else if (tag=="newNoteVeloOffInit")
+ ScoreCanvas::note_velo_off_init=xml.parseInt();
+ else if (tag=="newLenInit")
+ ScoreCanvas::new_len_init=xml.parseInt();
+ else if (tag=="noteColorInit")
+ ScoreCanvas::coloring_mode_init=(ScoreCanvas::coloring_mode_t)xml.parseInt();
+ else if (tag=="preambleContainsKeysig")
+ ScoreCanvas::preamble_contains_keysig_init=xml.parseInt();
+ else if (tag=="preambleContainsTimesig")
+ ScoreCanvas::preamble_contains_timesig_init=xml.parseInt();
+ else if (tag == "topwin")
TopWin::readConfiguration(SCORE, xml);
else
xml.unknown("ScoreEdit");
@@ -1079,7 +1133,18 @@ void ScoreEdit::read_configuration(MusECore::Xml& xml)
void ScoreEdit::write_configuration(int level, MusECore::Xml& xml)
{
xml.tag(level++, "scoreedit");
+
+ xml.intTag(level, "quantPowerInit", ScoreCanvas::_quant_power2_init);
+ xml.intTag(level, "pxPerWholeInit", ScoreCanvas::_pixels_per_whole_init);
+ xml.intTag(level, "newNoteVeloInit", ScoreCanvas::note_velo_init);
+ xml.intTag(level, "newNoteVeloOffInit", ScoreCanvas::note_velo_off_init);
+ xml.intTag(level, "newLenInit", ScoreCanvas::new_len_init);
+ xml.intTag(level, "noteColorInit", ScoreCanvas::coloring_mode_init);
+ xml.intTag(level, "preambleContainsKeysig", ScoreCanvas::preamble_contains_keysig_init);
+ xml.intTag(level, "preambleContainsTimesig", ScoreCanvas::preamble_contains_timesig_init);
+
TopWin::writeConfiguration(SCORE, level, xml);
+
xml.etag(level, "scoreedit");
}
@@ -1216,22 +1281,20 @@ ScoreCanvas::ScoreCanvas(ScoreEdit* pr, QWidget* parent_widget) : View(parent_wi
dragged_event_part=NULL;
last_len=384;
- new_len=-1;
+ new_len=-1; // will be initalized with new_len_init by ScoreEdit::ScoreEdit();
- set_quant(2); //this is actually unneccessary, as while
- //initalizing the quant_combobox, this gets
- //called again. but for safety...
- set_pixels_per_whole(300); //same as above. but safety rocks
+ _quant_power2=_quant_power2_init; // ScoreEdit relies on this to be done!
+ _pixels_per_whole_init = _pixels_per_whole_init;
- set_velo(64);
- set_velo_off(64);
+ note_velo=note_velo_init;
+ note_velo_off_init=note_velo_off_init;
dragging_staff=false;
- coloring_mode=COLOR_MODE_BLACK;
- preamble_contains_keysig=true;
- preamble_contains_timesig=true;
+ coloring_mode=coloring_mode_init;
+ preamble_contains_keysig=preamble_contains_keysig_init;
+ preamble_contains_timesig=preamble_contains_timesig_init;
x_scroll_speed=0;
@@ -1455,7 +1518,7 @@ void ScoreCanvas::song_changed(int flags)
{
if(parent && parent->deleting()) // Ignore while while deleting to prevent crash.
return;
-
+
if (flags & (SC_PART_MODIFIED | SC_PART_REMOVED | SC_PART_INSERTED | SC_TRACK_REMOVED))
{
update_parts();
@@ -1534,7 +1597,7 @@ void color_image(QImage& img, const QColor& color)
{
uchar* ptr=img.bits();
//int bytes=img.byteCount();
- int bytes=img.bytesPerLine() * img.height(); // By Tim. For older Qt versions. Tested OK on Qt4.5.
+ int bytes=img.bytesPerLine() * img.height(); // By Tim. For older Qt versions. Tested OK on Qt4.5.
int r,g,b;
color.getRgb(&r,&g,&b);
@@ -4280,16 +4343,16 @@ void ScoreCanvas::menu_command(int cmd)
{
switch (cmd)
{
- case CMD_COLOR_BLACK: coloring_mode=COLOR_MODE_BLACK; redraw(); break;
- case CMD_COLOR_PART: coloring_mode=COLOR_MODE_PART; redraw(); break;
- case CMD_COLOR_VELO: coloring_mode=COLOR_MODE_VELO; redraw(); break;
- case CMD_NOTELEN_1: new_len=TICKS_PER_WHOLE/ 1; break;
- case CMD_NOTELEN_2: new_len=TICKS_PER_WHOLE/ 2; break;
- case CMD_NOTELEN_4: new_len=TICKS_PER_WHOLE/ 4; break;
- case CMD_NOTELEN_8: new_len=TICKS_PER_WHOLE/ 8; break;
- case CMD_NOTELEN_16: new_len=TICKS_PER_WHOLE/16; break;
- case CMD_NOTELEN_32: new_len=TICKS_PER_WHOLE/32; break;
- case CMD_NOTELEN_LAST: new_len=-1; break;
+ case CMD_COLOR_BLACK: coloring_mode_init=coloring_mode=COLOR_MODE_BLACK; redraw(); break;
+ case CMD_COLOR_PART: coloring_mode_init=coloring_mode=COLOR_MODE_PART; redraw(); break;
+ case CMD_COLOR_VELO: coloring_mode_init=coloring_mode=COLOR_MODE_VELO; redraw(); break;
+ case CMD_NOTELEN_1: new_len_init= 1; new_len=TICKS_PER_WHOLE/ 1; break;
+ case CMD_NOTELEN_2: new_len_init= 2; new_len=TICKS_PER_WHOLE/ 2; break;
+ case CMD_NOTELEN_4: new_len_init= 4; new_len=TICKS_PER_WHOLE/ 4; break;
+ case CMD_NOTELEN_8: new_len_init= 8; new_len=TICKS_PER_WHOLE/ 8; break;
+ case CMD_NOTELEN_16: new_len_init=16; new_len=TICKS_PER_WHOLE/16; break;
+ case CMD_NOTELEN_32: new_len_init=32; new_len=TICKS_PER_WHOLE/32; break;
+ case CMD_NOTELEN_LAST: new_len_init= 0; new_len=-1; break;
default:
cerr << "ERROR: ILLEGAL FUNCTION CALL: ScoreCanvas::menu_command called with unknown command ("<<cmd<<")"<<endl;
@@ -4299,23 +4362,24 @@ void ScoreCanvas::menu_command(int cmd)
void ScoreCanvas::preamble_keysig_slot(bool state)
{
preamble_contains_keysig=state;
+ preamble_contains_keysig_init=state;
redraw();
}
void ScoreCanvas::preamble_timesig_slot(bool state)
{
preamble_contains_timesig=state;
+ preamble_contains_timesig_init=state;
redraw();
}
void ScoreCanvas::set_quant(int val)
{
- int quant_mapper[]={1,2,3,4,5};
-
- if ((val>=0) && (val<signed(sizeof(quant_mapper)/sizeof(*quant_mapper))))
+ if ((val>=0) && (val<5))
{
int old_len=quant_len();
- _quant_power2=quant_mapper[val];
+ _quant_power2=val+1;
+ _quant_power2_init=_quant_power2;
set_pixels_per_whole(pixels_per_whole() * quant_len() / old_len );
@@ -4342,6 +4406,7 @@ void ScoreCanvas::set_pixels_per_whole(int val)
// zero!)
_pixels_per_whole=val;
+ _pixels_per_whole_init=val;
for (list<staff_t>::iterator it=staves.begin(); it!=staves.end(); it++)
it->calc_item_pos();
@@ -4383,6 +4448,7 @@ void ScoreCanvas::maybe_close_if_empty()
void ScoreCanvas::set_velo(int velo)
{
note_velo=velo;
+ note_velo_init=velo;
if (parent->get_apply_velo())
modify_velocity(get_all_parts(),1, 0,velo);
@@ -4391,6 +4457,7 @@ void ScoreCanvas::set_velo(int velo)
void ScoreCanvas::set_velo_off(int velo)
{
note_velo_off=velo;
+ note_velo_off_init=velo;
if (parent->get_apply_velo())
modify_off_velocity(get_all_parts(),1, 0,velo);
@@ -4586,24 +4653,23 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo
/* BUGS and potential bugs
* o tied notes don't work properly when there's a key-change in
* between, for example, when a cis is tied to a des
- * o schedule_all_same_len_parts: if there are two clones A and B,
- * and both A and B get scheduled to be expanded (because we
- * have one event from A and one event from B), this causes a bug,
- * because after A (and B) got resized, the B-resize is invalid!
- * o when changing toolbarstate when sharing and immediately after that
+ * > o when changing toolbarstate when sharing and immediately after that
* changing "share" status, the changed state isn't stored
+ * (could be solved by storing the current window when quitting/saving whatever)
* ? pasting in editors sometimes fails oO? ( ERROR: reading eventlist
* from clipboard failed. ignoring this one... ) [ not reproducible ]
- * > o non-mdi topwin states aren't restored when launching muse2 somefile.med
* ! o using super glue while a score editor displaying the glued parts
* is open lets muse segfault. this may or may not be fixed in
* the release branch :/
*
* CURRENT TODO
* > o fix valgrind problems (the two "FINDMICHJETZT" lines in scoreedit.cpp)
- * > o newly created windows have to be focussed!
+ * > o add a songposition scrollbar-toolbar (in different sizes)
+ * this might be equivalent to "redo transport menu" (below).
+ * > o add toolbar(s) for tempo- etc spinboxes from the transport window
*
* IMPORTANT TODO
+ * o support edge-scrolling when opening a lasso
* o add "dotted quarter" quantize option (for 6/8 beat)
* o ticks-to-quarter spinboxes
* o mirror most menus to an additional right-click context menu to avoid the long mouse pointer
@@ -4628,6 +4694,7 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo
* o thin out: remove unneeded ctrl messages
*
* less important stuff
+ * o allow "fixating" toolbars?
* o quantize-templates (everything is forced into a specified
* rhythm)
* o part-templates (you specify some notes and a control-chord;
@@ -4639,8 +4706,6 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo
* calc_pos_add_list must be called before calc_item_pos then,
* and calc_item_pos must respect the pos_add_list instead of
* keeping its own pos_add variable (which is only an optimisation)
- * o support edge-scrolling when opening a lasso
- * o save more configuration stuff (quant, color)
*
* really unimportant nice-to-haves
* o support in-song clef-changes
@@ -4653,10 +4718,6 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo
*
*
* stuff for the other muse developers
- * o update translations
- * o remove ambiguous translation: "offset"="zeitversatz"
- * this is ambigous in mod. note len and WRONG in mod. velo dialogs
- *
* o process accurate timesignatures from muse's list (has to be implemented first in muse)
* ( (2+2+3)/4 or (3+2+2)/4 instead of 7/4 )
*/
diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h
index baea78e3..37765dda 100644
--- a/muse2/muse/midiedit/scoreedit.h
+++ b/muse2/muse/midiedit/scoreedit.h
@@ -668,8 +668,20 @@ class ScoreCanvas : public MusEGui::View
void move_staff_below(list<staff_t>::iterator dest, list<staff_t>::iterator src);
void cleanup_staves();
void maybe_close_if_empty();
-
+
+// defaults ----------------------------------------------------------
+ public:
+ enum coloring_mode_t {COLOR_MODE_BLACK, COLOR_MODE_PART, COLOR_MODE_VELO};
+ static int _quant_power2_init;
+ static int _pixels_per_whole_init;
+ static int note_velo_init, note_velo_off_init;
+ static int new_len_init;
+ static coloring_mode_t coloring_mode_init;
+ static bool preamble_contains_timesig_init;
+ static bool preamble_contains_keysig_init;
+
// member variables ---------------------------------------------------
+ private:
int _quant_power2;
int _pixels_per_whole;
@@ -746,7 +758,7 @@ class ScoreCanvas : public MusEGui::View
bool srec;
bool held_notes[128];
- enum {COLOR_MODE_BLACK, COLOR_MODE_PART, COLOR_MODE_VELO} coloring_mode;
+ coloring_mode_t coloring_mode;
bool preamble_contains_keysig;
bool preamble_contains_timesig;
@@ -776,38 +788,38 @@ class ScoreCanvas : public MusEGui::View
void add_new_parts(const std::map< MusECore::Part*, std::set<MusECore::Part*> >&);
- public slots:
- void x_scroll_event(int);
- void y_scroll_event(int);
- void song_changed(int);
- void fully_recalculate();
- void goto_tick(int,bool);
- void pos_changed(int i, unsigned u, bool b);
- void heartbeat_timer_event();
-
- void set_tool(int);
- void set_quant(int);
- void menu_command(int);
- void preamble_keysig_slot(bool);
- void preamble_timesig_slot(bool);
- void set_pixels_per_whole(int);
+ public slots:
+ void x_scroll_event(int);
+ void y_scroll_event(int);
+ void song_changed(int);
+ void fully_recalculate();
+ void goto_tick(int,bool);
+ void pos_changed(int i, unsigned u, bool b);
+ void heartbeat_timer_event();
- void set_velo(int);
- void set_velo_off(int);
+ void set_tool(int);
+ void set_quant(int);
+ void menu_command(int);
+ void preamble_keysig_slot(bool);
+ void preamble_timesig_slot(bool);
+ void set_pixels_per_whole(int);
- void set_steprec(bool);
-
- void update_parts(); //re-populates the set<MusECore::Part*>s from the set<int>s
+ void set_velo(int);
+ void set_velo_off(int);
+
+ void set_steprec(bool);
+
+ void update_parts(); //re-populates the set<MusECore::Part*>s from the set<int>s
signals:
- void xscroll_changed(int);
- void yscroll_changed(int);
- void viewport_width_changed(int);
- void canvas_width_changed(int);
- void preamble_width_changed(int);
- void viewport_height_changed(int);
- void canvas_height_changed(int);
- void pixels_per_whole_changed(int);
- void pos_add_changed();
+ void xscroll_changed(int);
+ void yscroll_changed(int);
+ void viewport_width_changed(int);
+ void canvas_width_changed(int);
+ void preamble_width_changed(int);
+ void viewport_height_changed(int);
+ void canvas_height_changed(int);
+ void pixels_per_whole_changed(int);
+ void pos_add_changed();
protected:
virtual void draw(QPainter& p, const QRect& rect);
diff --git a/muse2/muse/midiport.cpp b/muse2/muse/midiport.cpp
index 19fef51b..b7d1d7b7 100644
--- a/muse2/muse/midiport.cpp
+++ b/muse2/muse/midiport.cpp
@@ -332,8 +332,8 @@ QMenu* midiPortsPopup(QWidget* parent, int checkPort)
{
MusECore::MidiDevice* md = MusEGlobal::midiPorts[pi].device();
//if(md && !md->isSynti() && (md->rwFlags() & 1))
- //if(md && (md->rwFlags() & 1))
- if(md && (md->rwFlags() & 1 || md->isSynti()) )
+ if(md && (md->rwFlags() & 1))
+ //if(md && (md->rwFlags() & 1 || md->isSynti()) ) // Revert. Hm, why synths? Only writeable ports. p4.0.41
break;
}
if(pi == MIDI_PORTS)
@@ -352,8 +352,12 @@ QMenu* midiPortsPopup(QWidget* parent, int checkPort)
for (int i = 0; i < MIDI_PORTS; ++i) {
MidiPort* port = &MusEGlobal::midiPorts[i];
+ MusECore::MidiDevice* md = port->device();
+ //if(md && !(md->rwFlags() & 1 || md->isSynti()) && (i != checkPort))
+ if(md && !(md->rwFlags() & 1) && (i != checkPort)) // Only writeable ports, or current one.
+ continue;
name.sprintf("%d:%s", port->portno()+1, port->portname().toLatin1().constData());
- if(port->device() || (i == checkPort))
+ if(md || (i == checkPort))
{
act = p->addAction(name);
act->setData(i);
@@ -361,7 +365,7 @@ QMenu* midiPortsPopup(QWidget* parent, int checkPort)
act->setChecked(i == checkPort);
}
- if(!port->device())
+ if(!md)
{
if(!subp) // No submenu yet? Create it now.
{
diff --git a/muse2/muse/midiseq.cpp b/muse2/muse/midiseq.cpp
index e31db7c7..1e46db11 100644
--- a/muse2/muse/midiseq.cpp
+++ b/muse2/muse/midiseq.cpp
@@ -44,6 +44,7 @@
#include "synth.h"
#include "song.h"
#include "gconfig.h"
+#include <lo/lo_osc_types.h>
namespace MusEGlobal {
MusECore::MidiSeq* midiSeq;
@@ -54,6 +55,12 @@ namespace MusECore {
int MidiSeq::ticker = 0;
+void initMidiSequencer()
+{
+ //MusEGlobal::midiSeq = new MidiSeq(MusEGlobal::realTimeScheduling ? MusEGlobal::realTimePriority : 0, "Midi");
+ MusEGlobal::midiSeq = new MidiSeq("Midi");
+}
+
//---------------------------------------------------------
// readMsg
//---------------------------------------------------------
@@ -819,16 +826,16 @@ void MidiSeq::msgMsg(int id)
void MidiSeq::msgSetMidiDevice(MidiPort* port, MidiDevice* device)
{
- MusECore::AudioMsg msg;
- msg.id = MusECore::SEQM_IDLE;
- msg.a = true;
- Thread::sendMsg(&msg);
-
- port->setMidiDevice(device);
+ MusECore::AudioMsg msg;
+ msg.id = MusECore::SEQM_IDLE;
+ msg.a = true;
+ Thread::sendMsg(&msg);
+
+ port->setMidiDevice(device);
- msg.id = MusECore::SEQM_IDLE;
- msg.a = false;
- Thread::sendMsg(&msg);
+ msg.id = MusECore::SEQM_IDLE;
+ msg.a = false;
+ Thread::sendMsg(&msg);
}
// This does not appear to be used anymore. Was called in Audio::process1, now Audio::processMidi is called directly. p4.0.15 Tim.
diff --git a/muse2/muse/mixer/amixer.cpp b/muse2/muse/mixer/amixer.cpp
index 731af9a4..439a92b9 100644
--- a/muse2/muse/mixer/amixer.cpp
+++ b/muse2/muse/mixer/amixer.cpp
@@ -169,7 +169,7 @@ AudioMixerApp::AudioMixerApp(QWidget* parent, MusEGlobal::MixerConfig* c)
setWindowIcon(*museIcon);
QMenu* menuConfig = menuBar()->addMenu(tr("&Create"));
- MusEGui::populateAddTrack(menuConfig);
+ MusEGui::populateAddTrack(menuConfig,true);
connect(menuConfig, SIGNAL(triggered(QAction *)), MusEGlobal::song, SLOT(addNewTrack(QAction *)));
QMenu* menuView = menuBar()->addMenu(tr("&View"));
diff --git a/muse2/muse/mixer/astrip.cpp b/muse2/muse/mixer/astrip.cpp
index 10f281fb..9c393a1a 100644
--- a/muse2/muse/mixer/astrip.cpp
+++ b/muse2/muse/mixer/astrip.cpp
@@ -147,6 +147,7 @@ void AudioStrip::songChanged(int val)
// Set the strip label's font.
//label->setFont(MusEGlobal::config.fonts[1]);
setLabelFont();
+ setLabelText();
// Adjust minimum volume slider and label values.
slider->setRange(MusEGlobal::config.minSlider-0.1, 10.0);
@@ -203,7 +204,17 @@ void AudioStrip::songChanged(int val)
pre->setChecked(src->prefader());
pre->blockSignals(false);
}
- }
+
+ // Are there any Aux Track routing paths to this track? Then we cannot process aux for this track!
+ // Hate to do this, but as a quick visual reminder, seems most logical to disable Aux knobs and labels.
+ int rc = track->auxRefCount();
+ int n = auxKnob.size();
+ for (int idx = 0; idx < n; ++idx)
+ {
+ auxKnob[idx]->setEnabled( rc == 0 );
+ auxLabel[idx]->setEnabled( rc == 0 );
+ }
+ }
if (val & SC_AUX) {
int n = auxKnob.size();
for (int idx = 0; idx < n; ++idx) {
@@ -333,11 +344,14 @@ void AudioStrip::updateOffState()
stereo->setEnabled(val);
label->setEnabled(val);
+ // Are there any Aux Track routing paths to this track? Then we cannot process aux for this track!
+ // Hate to do this, but as a quick visual reminder, seems most logical to disable Aux knobs and labels.
+ bool ae = track->auxRefCount() == 0 && val;
int n = auxKnob.size();
for (int i = 0; i < n; ++i)
{
- auxKnob[i]->setEnabled(val);
- auxLabel[i]->setEnabled(val);
+ auxKnob[i]->setEnabled(ae);
+ auxLabel[i]->setEnabled(ae);
}
if (pre)
@@ -348,12 +362,12 @@ void AudioStrip::updateOffState()
solo->setEnabled(val);
if (mute)
mute->setEnabled(val);
- if (autoType)
- autoType->setEnabled(val);
- if (iR)
- iR->setEnabled(val);
- if (oR)
- oR->setEnabled(val);
+ //if (autoType)
+ // autoType->setEnabled(val);
+ //if (iR)
+ // iR->setEnabled(val);
+ //if (oR)
+ // oR->setEnabled(val);
if (off) {
off->blockSignals(true);
off->setChecked(track->off());
@@ -799,6 +813,12 @@ AudioStrip::AudioStrip(QWidget* parent, MusECore::AudioTrack* at)
double val = MusECore::fast_log10(t->auxSend(idx))*20.0;
ak->setValue(val);
al->setValue(val);
+
+ // Are there any Aux Track routing paths to this track? Then we cannot process aux for this track!
+ // Hate to do this, but as a quick visual reminder, seems most logical to disable Aux knobs and labels.
+ int rc = track->auxRefCount();
+ ak->setEnabled( rc == 0 );
+ al->setEnabled( rc == 0 );
}
}
else {
diff --git a/muse2/muse/mixer/mstrip.cpp b/muse2/muse/mixer/mstrip.cpp
index 2e51feb9..dc495aa6 100644
--- a/muse2/muse/mixer/mstrip.cpp
+++ b/muse2/muse/mixer/mstrip.cpp
@@ -448,9 +448,8 @@ void MidiStrip::updateOffState()
// TODO: Disabled for now.
//if (autoType)
// autoType->setEnabled(val);
- if (iR)
- iR->setEnabled(val);
- // TODO: Disabled for now.
+ //if (iR)
+ // iR->setEnabled(val);
//if (oR)
// oR->setEnabled(val);
if (off) {
@@ -504,6 +503,7 @@ void MidiStrip::songChanged(int val)
// Set the strip label's font.
//label->setFont(MusEGlobal::config.fonts[1]);
setLabelFont();
+ setLabelText();
}
}
diff --git a/muse2/muse/mixer/strip.cpp b/muse2/muse/mixer/strip.cpp
index b87c4629..c26a9a15 100644
--- a/muse2/muse/mixer/strip.cpp
+++ b/muse2/muse/mixer/strip.cpp
@@ -29,6 +29,8 @@
#include <QColor>
#include <QVBoxLayout>
#include <QFrame>
+#include <QMouseEvent>
+#include <QMenu>
#include "globals.h"
#include "gconfig.h"
@@ -161,7 +163,8 @@ void Strip::setLabelText()
//gradient.setColorAt(0, c.darker());
//gradient.setColorAt(0, c);
//gradient.setColorAt(1, c.darker());
- gradient.setColorAt(0, c.lighter());
+ gradient.setColorAt(0, c);
+ gradient.setColorAt(0.5, c.lighter());
gradient.setColorAt(1, c);
//palette.setBrush(QPalette::Button, gradient);
//palette.setBrush(QPalette::Window, gradient);
@@ -303,6 +306,23 @@ void Strip::resizeEvent(QResizeEvent* ev)
setLabelText();
setLabelFont();
}
-
+
+void Strip::mousePressEvent(QMouseEvent* ev)
+{
+ if (ev->button() == Qt::RightButton) {
+ QMenu* menu = new QMenu;
+ menu->addAction(tr("Remove track?"));
+ QPoint pt = QCursor::pos();
+ QAction* act = menu->exec(pt, 0);
+ if (!act)
+ {
+ delete menu;
+ return;
+ }
+ MusEGlobal::song->removeTrack0(track);
+ MusEGlobal::audio->msgUpdateSoloStates();
+ }
+}
+
} // namespace MusEGui
diff --git a/muse2/muse/mixer/strip.h b/muse2/muse/mixer/strip.h
index 5b3b541b..d0cde1a6 100644
--- a/muse2/muse/mixer/strip.h
+++ b/muse2/muse/mixer/strip.h
@@ -73,6 +73,7 @@ class Strip : public QFrame {
MusEGui::ComboBox* autoType;
void setLabelText();
virtual void resizeEvent(QResizeEvent*);
+ virtual void mousePressEvent(QMouseEvent *);
private slots:
void recordToggled(bool);
diff --git a/muse2/muse/node.cpp b/muse2/muse/node.cpp
index dd41ba10..cb77f939 100644
--- a/muse2/muse/node.cpp
+++ b/muse2/muse/node.cpp
@@ -4,6 +4,7 @@
// $Id: node.cpp,v 1.36.2.25 2009/12/20 05:00:35 terminator356 Exp $
//
// (C) Copyright 2000-2004 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -25,6 +26,8 @@
#include <sndfile.h>
#include <stdlib.h>
+#include <QString>
+
#include "node.h"
#include "globals.h"
#include "gconfig.h"
@@ -44,7 +47,6 @@
//#define NODE_DEBUG
//#define FIFO_DEBUG
-// Added by Tim. p3.3.18
//#define METRONOME_DEBUG
namespace MusECore {
@@ -162,10 +164,19 @@ void Track::updateInternalSoloStates()
void MidiTrack::updateInternalSoloStates()
{
- if(this == _tmpSoloChainTrack)
- return;
-
- Track::updateInternalSoloStates();
+ if(_nodeTraversed) // Anti circular mechanism.
+ {
+ fprintf(stderr, "MidiTrack::updateInternalSoloStates %s :\n MusE Warning: Please check your routes: Circular path found!\n", name().toLatin1().constData());
+ return;
+ }
+ //if(this == _tmpSoloChainTrack)
+ // return;
+
+ _nodeTraversed = true;
+
+ Track::updateInternalSoloStates();
+
+ _nodeTraversed = false; // Reset.
}
@@ -175,40 +186,61 @@ void MidiTrack::updateInternalSoloStates()
void AudioTrack::updateInternalSoloStates()
{
- if(this == _tmpSoloChainTrack)
- return;
-
- Track::updateInternalSoloStates();
-
- if(_tmpSoloChainDoIns)
+ if(_nodeTraversed) // Anti circular mechanism.
+ {
+ fprintf(stderr, "AudioTrack::updateInternalSoloStates %s :\n MusE Warning: Please check your routes: Circular path found!\n", name().toLatin1().constData());
+ return;
+ }
+ //if(this == _tmpSoloChainTrack)
+ // return;
+
+ _nodeTraversed = true;
+
+ Track::updateInternalSoloStates();
+
+ if(_tmpSoloChainDoIns)
+ {
+ if(type() == AUDIO_SOFTSYNTH)
+ {
+ const MusECore::MidiTrackList* ml = MusEGlobal::song->midis();
+ for(MusECore::ciMidiTrack im = ml->begin(); im != ml->end(); ++im)
{
- if(type() == AUDIO_SOFTSYNTH)
- {
- const MusECore::MidiTrackList* ml = MusEGlobal::song->midis();
- for(MusECore::ciMidiTrack im = ml->begin(); im != ml->end(); ++im)
- {
- MusECore::MidiTrack* mt = *im;
- if(mt->outPort() >= 0 && mt->outPort() == ((SynthI*)this)->midiPort())
- mt->updateInternalSoloStates();
- }
- }
-
- const RouteList* rl = inRoutes();
- for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir)
- {
- if(ir->type == Route::TRACK_ROUTE)
- ir->track->updateInternalSoloStates();
- }
+ MusECore::MidiTrack* mt = *im;
+ if(mt->outPort() >= 0 && mt->outPort() == ((SynthI*)this)->midiPort())
+ mt->updateInternalSoloStates();
}
- else
- {
- const RouteList* rl = outRoutes();
- for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir)
+ }
+
+ const RouteList* rl = inRoutes();
+ for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir)
+ {
+ if(ir->type == Route::TRACK_ROUTE)
+ ir->track->updateInternalSoloStates();
+ else
+ // Support Midi Port -> Audio Input solo chains. p4.0.37 Tim.
+ if(ir->type == Route::MIDI_PORT_ROUTE)
+ {
+ const MidiTrackList* ml = MusEGlobal::song->midis();
+ for(ciMidiTrack im = ml->begin(); im != ml->end(); ++im)
{
- if(ir->type == Route::TRACK_ROUTE)
- ir->track->updateInternalSoloStates();
+ MidiTrack* mt = *im;
+ if(mt->outPort() == ir->midiPort && ((1 << mt->outChannel()) & ir->channel) )
+ mt->updateInternalSoloStates();
}
- }
+ }
+ }
+ }
+ else
+ {
+ const RouteList* rl = outRoutes();
+ for(ciRoute ir = rl->begin(); ir != rl->end(); ++ir)
+ {
+ if(ir->type == Route::TRACK_ROUTE)
+ ir->track->updateInternalSoloStates();
+ }
+ }
+
+ _nodeTraversed = false; // Reset.
}
@@ -221,6 +253,8 @@ void MidiTrack::updateSoloStates(bool noDec)
if(noDec && !_solo)
return;
+ _nodeTraversed = true; // Anti circular mechanism.
+
_tmpSoloChainTrack = this;
_tmpSoloChainDoIns = false;
_tmpSoloChainNoDec = noDec;
@@ -244,6 +278,8 @@ void MidiTrack::updateSoloStates(bool noDec)
}
}
}
+
+ _nodeTraversed = false; // Reset.
}
@@ -256,6 +292,8 @@ void AudioTrack::updateSoloStates(bool noDec)
if(noDec && !_solo)
return;
+ _nodeTraversed = true; // Anti circular mechanism.
+
_tmpSoloChainTrack = this;
_tmpSoloChainNoDec = noDec;
updateSoloState();
@@ -301,6 +339,8 @@ void AudioTrack::updateSoloStates(bool noDec)
ir->track->updateInternalSoloStates();
}
}
+
+ _nodeTraversed = false; // Reset.
}
@@ -327,7 +367,6 @@ void Track::setOff(bool val)
// copyData
//---------------------------------------------------------
-//void AudioTrack::copyData(unsigned pos, int dstChannels, unsigned nframes, float** dstBuffer)
void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int srcChannels, unsigned nframes, float** dstBuffer)
{
//Changed by T356. 12/12/09.
@@ -336,60 +375,51 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s
// Make better use of AudioTrack::outBuffers as a post-effect pre-volume cache system for multiple calls here during processing.
// Previously only WaveTrack used them. (Changed WaveTrack as well).
+ #ifdef NODE_DEBUG
+ printf("MusE: AudioTrack::copyData name:%s processed:%d\n", name().toLatin1().constData(), processed());
+ #endif
+
if(srcStartChan == -1)
srcStartChan = 0;
- int srcChans = (srcChannels == -1) ? channels() : srcChannels;
+ int trackChans = channels();
+ int srcChans = (srcChannels == -1) ? trackChans : srcChannels;
int srcTotalOutChans = totalOutChannels();
if(channels() == 1)
srcTotalOutChans = 1;
- #ifdef NODE_DEBUG
- printf("MusE: AudioTrack::copyData name:%s processed:%d\n", name().toLatin1().constData(), processed());
- #endif
-
// Special consideration for metronome: It is not part of the track list,
// and it has no in or out routes, yet multiple output tracks may call addData on it !
// We can't tell how many output tracks call it, so we can only assume there might be more than one.
// Not strictly necessary here because only addData is ever called, but just to be consistent...
- //bool usedirectbuf = (outRoutes()->size() <= 1) || (type() == AUDIO_OUTPUT);
- bool usedirectbuf = ((outRoutes()->size() <= 1) || (type() == AUDIO_OUTPUT)) && (this != metronome);
+ //bool usedirectbuf = ((outRoutes()->size() <= 1) || (type() == AUDIO_OUTPUT)) && (this != metronome);
int i;
- // p3.3.38
- //float* buffer[srcChannels];
float* buffer[srcTotalOutChans];
+ float data[nframes * srcTotalOutChans];
-
- //float data[nframes * srcChannels];
- //for(i = 0; i < srcChannels; ++i)
- // buffer[i] = data + i * nframes;
-
// precalculate stereo volume
double vol[2];
double _volume = volume();
double _pan = pan();
vol[0] = _volume * (1.0 - _pan);
vol[1] = _volume * (1.0 + _pan);
- float meter[srcChans];
+ float meter[trackChans];
// Have we been here already during this process cycle?
if(processed())
{
// If there is only one (or no) output routes, it's an error - we've been called more than once per process cycle!
+ // No, this is no longer an error, it's deliberate. Processing no longer done in 'chains', now done randomly. p4.0.37
#ifdef NODE_DEBUG
- if(usedirectbuf)
- printf("MusE: AudioTrack::copyData Error! One or no out routes, but already processed! Copying local buffers anyway...\n");
+ printf("MusE: AudioTrack::copyData name:%s already processed _haveData:%d\n", name().toLatin1().constData(), _haveData);
#endif
// Is there already some data gathered from a previous call during this process cycle?
if(_haveData)
{
// Point the input buffers at our local cached 'pre-volume' buffers. They need processing, so continue on after.
- //for(i = 0; i < srcChannels; ++i)
- // buffer[i] = outBuffers[i];
- // p3.3.38
for(i = 0; i < srcTotalOutChans; ++i)
buffer[i] = outBuffers[i];
}
@@ -413,29 +443,16 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s
{
// First time here during this process cycle.
- // Point the input buffers at a temporary stack buffer.
- //float data[nframes * srcChannels];
- //for(i = 0; i < srcChannels; ++i)
- // buffer[i] = data + i * nframes;
- // p3.3.38
- float data[nframes * srcTotalOutChans];
- for(i = 0; i < srcTotalOutChans; ++i)
- buffer[i] = data + i * nframes;
-
- // getData can use the supplied buffers, or change buffer to point to its own local buffers or Jack buffers etc.
- // For ex. if this is an audio input, Jack will set the pointers for us in AudioInput::getData!
- // p3.3.29 1/27/10 Don't do any processing at all if off. Whereas, mute needs to be ready for action at all times,
- // so still call getData before it. Off is NOT meant to be toggled rapidly, but mute is !
- //if(!getData(pos, srcChannels, nframes, buffer) || off() || (isMute() && !_prefader))
- //if(off() || !getData(pos, srcChannels, nframes, buffer) || (isMute() && !_prefader))
- // p3.3.38
- if(off() || !getData(pos, srcTotalOutChans, nframes, buffer) || (isMute() && !_prefader))
- {
+ _haveData = false; // Reset.
+ _processed = true; // Set this now.
+
+ if(off())
+ {
#ifdef NODE_DEBUG
- printf("MusE: AudioTrack::copyData name:%s dstChannels:%d zeroing buffers\n", name().toLatin1().constData(), dstChannels);
+ printf("MusE: AudioTrack::copyData name:%s dstChannels:%d Off, zeroing buffers\n", name().toLatin1().constData(), dstChannels);
#endif
- // No data was available. Zero the supplied buffers.
+ // Track is off. Zero the supplied buffers.
unsigned int q;
for(i = 0; i < dstChannels; ++i)
{
@@ -448,13 +465,12 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s
memset(dstBuffer[i], 0, sizeof(float) * nframes);
}
- for(i = 0; i < srcChans; ++i)
+ _efxPipe->apply(0, nframes, 0); // Just process controls only, not audio (do not 'run').
+
+ for(i = 0; i < trackChans; ++i)
{
- //_meter[i] = 0;
_meter[i] = 0.0;
-
- /*
- if(!usedirectbuf)
+ /*if(!usedirectbuf)
{
if(MusEGlobal::config.useDenormalBias)
{
@@ -463,22 +479,49 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s
}
else
memset(outBuffers[i], 0, sizeof(float) * nframes);
- }
- */
+ } */
}
- _haveData = false;
- _processed = true;
+ //_haveData = false;
+ //_processed = true;
+ //_isProcessing = false; // Unblock.
return;
}
+
+ // Point the input buffers at a temporary stack buffer.
+ for(i = 0; i < srcTotalOutChans; ++i)
+ buffer[i] = data + i * nframes;
+
+ // getData can use the supplied buffers, or change buffer to point to its own local buffers or Jack buffers etc.
+ // For ex. if this is an audio input, Jack will set the pointers for us in AudioInput::getData!
+ // Don't do any processing at all if off. Whereas, mute needs to be ready for action at all times,
+ // so still call getData before it. Off is NOT meant to be toggled rapidly, but mute is !
+ if(!getData(pos, srcTotalOutChans, nframes, buffer) || (isMute() && !_prefader))
+ {
+ #ifdef NODE_DEBUG
+ printf("MusE: AudioTrack::copyData name:%s srcTotalOutChans:%d zeroing buffers\n", name().toLatin1().constData(), srcTotalOutChans);
+ #endif
+
+ // No data was available. Track is not off. Zero the working buffers and continue on.
+ unsigned int q;
+ for(i = 0; i < srcTotalOutChans; ++i)
+ {
+ if(MusEGlobal::config.useDenormalBias)
+ {
+ for(q = 0; q < nframes; ++q)
+ buffer[i][q] = MusEGlobal::denormalBias;
+ }
+ else
+ memset(buffer[i], 0, sizeof(float) * nframes);
+ }
+ }
//---------------------------------------------------
// apply plugin chain
//---------------------------------------------------
- // p3.3.41
//fprintf(stderr, "AudioTrack::copyData %s efx apply srcChans:%d\n", name().toLatin1().constData(), srcChans);
- _efxPipe->apply(srcChans, nframes, buffer);
+ _efxPipe->apply(trackChans, nframes, buffer);
//---------------------------------------------------
// aux sends
@@ -525,18 +568,16 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s
if(_prefader)
{
- for(i = 0; i < srcChans; ++i)
+ for(i = 0; i < trackChans; ++i)
{
float* p = buffer[i];
meter[i] = 0.0;
for(unsigned k = 0; k < nframes; ++k)
{
- double f = fabs(*p);
+ double f = fabs(*p++);
if(f > meter[i])
meter[i] = f;
- ++p;
}
- //_meter[i] = lrint(meter[i] * 32767.0);
_meter[i] = meter[i];
if(_meter[i] > _peak[i])
_peak[i] = _meter[i];
@@ -570,20 +611,19 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s
else
memset(outBuffers[i], 0, sizeof(float) * nframes);
}
- }
- */
+ } */
+
- _haveData = false;
- _processed = true;
+ if(!_prefader)
+ for(i = 0; i < trackChans; ++i) // Must process ALL channels, even if unconnected. Only max 2 channels.
+ _meter[i] = 0.0;
+
return;
}
// If we're using local cached 'pre-volume' buffers, copy the input buffers (as they are right now: post-effect pre-volume) back to them.
- if(!usedirectbuf)
+ //if(!usedirectbuf)
{
- //for(i = 0; i < srcChannels; ++i)
- // AL::dsp->cpy(outBuffers[i], buffer[i], nframes);
- // p3.3.38
for(i = 0; i < srcTotalOutChans; ++i)
AL::dsp->cpy(outBuffers[i], buffer[i], nframes);
}
@@ -606,9 +646,9 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s
else
memset(dstBuffer[i], 0, sizeof(float) * nframes);
}
- _processed = true;
return;
}
+
// Force a source range to fit actual available total out channels.
if((srcStartChan + srcChans) > srcTotalOutChans)
srcChans = srcTotalOutChans - srcStartChan;
@@ -618,132 +658,94 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s
// postfader metering
//---------------------------------------------------
-
- if(srcChans == dstChannels)
+ #ifdef NODE_DEBUG
+ printf("MusE: AudioTrack::copyData trackChans:%d srcTotalOutChans:%d srcStartChan:%d srcChans:%d dstChannels:%d\n", trackChans, srcTotalOutChans, srcStartChan, srcChans, dstChannels);
+ #endif
+
+ if(!_prefader)
{
- if(_prefader)
+ for(int c = 0; c < trackChans; ++c)
{
- for(int c = 0; c < dstChannels; ++c)
+ meter[c] = 0.0;
+ double v = (trackChans == 1 ? _volume : vol[c]);
+ float* sp = buffer[c];
+ for(unsigned k = 0; k < nframes; ++k)
{
- // p3.3.38
- //float* sp = buffer[c];
- float* sp = buffer[c + srcStartChan];
-
- float* dp = dstBuffer[c];
- for(unsigned k = 0; k < nframes; ++k)
- *dp++ = (*sp++ * vol[c]);
+ float val = *sp++ * v; // If the track is mono pan has no effect on meters.
+ double f = fabs(val);
+ if(f > meter[c])
+ meter[c] = f;
}
- }
- else
+ _meter[c] = meter[c];
+ if(_meter[c] > _peak[c])
+ _peak[c] = _meter[c];
+ }
+ }
+
+ if(srcChans == dstChannels)
+ {
+ for(int c = 0; c < dstChannels; ++c)
{
- for(int c = 0; c < dstChannels; ++c)
- {
- meter[c] = 0.0;
-
- // p3.3.38
- //float* sp = buffer[c];
- float* sp = buffer[c + srcStartChan];
-
- float* dp = dstBuffer[c];
- //printf("2 dstBuffer[c]=%d\n",long(dstBuffer[c]));
- for(unsigned k = 0; k < nframes; ++k)
- {
- float val = *sp++ * vol[c];
- *dp++ = val;
- double f = fabs(val);
- if(f > meter[c])
- meter[c] = f;
- }
- //_meter[c] = lrint(meter[c] * 32767.0);
- _meter[c] = meter[c];
- if(_meter[c] > _peak[c])
- _peak[c] = _meter[c];
- }
+ double v;
+ if(srcStartChan > 2) // Don't apply pan or volume to extra channels above 2.
+ //v = _volume;
+ v = 1.0;
+ else
+ if(srcChans >= 2) // If 2 channels apply pan normally.
+ v = vol[c];
+ else
+ if(trackChans < 2) // If 1 channel and track is 1 channel, don't apply pan.
+ v = _volume;
+ else
+ v = vol[srcStartChan]; // Otherwise 1 channel but track is 2 channels. Apply the channel volume.
+
+ float* sp = buffer[c + srcStartChan];
+ float* dp = dstBuffer[c];
+ for(unsigned k = 0; k < nframes; ++k)
+ //*dp++ = (*sp++ * vol[c]);
+ *dp++ = (*sp++ * v);
}
}
else if(srcChans == 1 && dstChannels == 2)
{
- // p3.3.38
- //float* sp = buffer[0];
- float* sp = buffer[srcStartChan];
-
- if(_prefader)
+ for(int c = 0; c < dstChannels; ++c)
{
- for(int c = 0; c < dstChannels; ++c)
- {
- float* dp = dstBuffer[c];
- for(unsigned k = 0; k < nframes; ++k)
- *dp++ = (*sp++ * vol[c]);
- }
- }
- else
- {
- meter[0] = 0.0;
- for(unsigned k = 0; k < nframes; ++k)
- {
- float val = *sp++;
- double f = fabs(val) * _volume;
- if(f > meter[0])
- meter[0] = f;
- *(dstBuffer[0] + k) = val * vol[0];
- *(dstBuffer[1] + k) = val * vol[1];
- }
- //_meter[0] = lrint(meter[0] * 32767.0);
- _meter[0] = meter[0];
- if(_meter[0] > _peak[0])
- _peak[0] = _meter[0];
+ double v;
+ if(srcStartChan > 2) // Don't apply pan or volume to extra channels above 2.
+ //v = _volume;
+ v = 1.0;
+ else
+ if(trackChans <= 1) // If track is mono apply pan.
+ v = vol[c];
+ else
+ v = vol[srcStartChan]; // Otherwise track is stereo, apply the same channel volume to both.
+
+ float* sp = buffer[srcStartChan];
+ float* dp = dstBuffer[c];
+ for(unsigned k = 0; k < nframes; ++k)
+ //*dp++ = (*sp++ * vol[c]);
+ *dp++ = (*sp++ * v);
}
}
else if(srcChans == 2 && dstChannels == 1)
{
- // p3.3.38
- //float* sp1 = buffer[0];
- //float* sp2 = buffer[1];
+ //double v1 = (srcStartChan > 2 ? _volume : vol[srcStartChan]); // Don't apply pan to extra channels above 2.
+ //double v2 = (srcStartChan > 2 ? _volume : vol[srcStartChan + 1]); //
+ double v1 = (srcStartChan > 2 ? 1.0 : vol[srcStartChan]); // Don't apply pan or volume to extra channels above 2.
+ double v2 = (srcStartChan > 2 ? 1.0 : vol[srcStartChan + 1]); //
+ float* dp = dstBuffer[0];
float* sp1 = buffer[srcStartChan];
float* sp2 = buffer[srcStartChan + 1];
-
- if(_prefader)
- {
- float* dp = dstBuffer[0];
- for(unsigned k = 0; k < nframes; ++k)
- *dp++ = (*sp1++ * vol[0] + *sp2++ * vol[1]);
- }
- else
- {
- float* dp = dstBuffer[0];
- meter[0] = 0.0;
- meter[1] = 0.0;
- for(unsigned k = 0; k < nframes; ++k)
- {
- float val1 = *sp1++ * vol[0];
- float val2 = *sp2++ * vol[1];
- double f1 = fabs(val1);
- if(f1 > meter[0])
- meter[0] = f1;
- double f2 = fabs(val2);
- if(f2 > meter[1])
- meter[1] = f2;
- *dp++ = (val1 + val2);
- }
- //_meter[0] = lrint(meter[0] * 32767.0);
- _meter[0] = meter[0];
- if(_meter[0] > _peak[0])
- _peak[0] = _meter[0];
- //_meter[1] = lrint(meter[1] * 32767.0);
- _meter[1] = meter[1];
- if(_meter[1] > _peak[1])
- _peak[1] = _meter[1];
- }
+ for(unsigned k = 0; k < nframes; ++k)
+ //*dp++ = (*sp1++ * vol[0] + *sp2++ * vol[1]);
+ *dp++ = (*sp1++ * v1 + *sp2++ * v2);
}
-
- _processed = true;
}
//---------------------------------------------------------
// addData
//---------------------------------------------------------
-//void AudioTrack::addData(unsigned pos, int dstChannels, unsigned nframes, float** dstBuffer)
void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int srcChannels, unsigned nframes, float** dstBuffer)
{
//Changed by T356. 12/12/09.
@@ -752,21 +754,21 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr
// Make better use of AudioTrack::outBuffers as a post-effect pre-volume cache system for multiple calls here during processing.
// Previously only WaveTrack used them. (Changed WaveTrack as well).
- //Added by Tim. p3.3.16
#ifdef NODE_DEBUG
printf("MusE: AudioTrack::addData name:%s processed:%d\n", name().toLatin1().constData(), processed());
#endif
- if (off())
- {
- _processed = true;
- return;
- }
+ //if (off())
+ //{
+ // _processed = true;
+ // return;
+ //}
if(srcStartChan == -1)
srcStartChan = 0;
- int srcChans = (srcChannels == -1) ? channels() : srcChannels;
+ int trackChans = channels();
+ int srcChans = (srcChannels == -1) ? trackChans : srcChannels;
int srcTotalOutChans = totalOutChannels();
if(channels() == 1)
srcTotalOutChans = 1;
@@ -774,18 +776,12 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr
// Special consideration for metronome: It is not part of the track list,
// and it has no in or out routes, yet multiple output tracks may call addData on it !
// We can't tell how many output tracks call it, so we can only assume there might be more than one.
- //bool usedirectbuf = (outRoutes()->size() <= 1) || (type() == AUDIO_OUTPUT);
- bool usedirectbuf = ((outRoutes()->size() <= 1) || (type() == AUDIO_OUTPUT)) && (this != metronome);
+ //bool usedirectbuf = ((outRoutes()->size() <= 1) || (type() == AUDIO_OUTPUT)) && (this != metronome);
int i;
- // p3.3.38
- //float* buffer[srcChannels];
float* buffer[srcTotalOutChans];
-
- //float data[nframes * srcChannels];
- //for (i = 0; i < srcChannels; ++i)
- // buffer[i] = data + i * nframes;
+ float data[nframes * srcTotalOutChans];
// precalculate stereo volume
double vol[2];
@@ -793,105 +789,96 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr
double _pan = pan();
vol[0] = _volume * (1.0 - _pan);
vol[1] = _volume * (1.0 + _pan);
- float meter[srcChans];
+ //float meter[srcChans];
+ float meter[trackChans];
// Have we been here already during this process cycle?
if(processed())
{
// If there is only one (or no) output routes, it's an error - we've been called more than once per process cycle!
+ // No, this is no longer an error, it's deliberate. Processing no longer done in 'chains', now done randomly. p4.0.37
#ifdef NODE_DEBUG
- if(usedirectbuf)
- printf("MusE: AudioTrack::addData Error! One or no out routes, but already processed! Copying local buffers anyway...\n");
+ printf("MusE: AudioTrack::addData name:%s already processed _haveData:%d\n", name().toLatin1().constData(), _haveData);
#endif
// Is there already some data gathered from a previous call during this process cycle?
if(_haveData)
{
// Point the input buffers at our local cached 'pre-volume' buffers. They need processing, so continue on after.
- //for(i = 0; i < srcChannels; ++i)
- // buffer[i] = outBuffers[i];
- // p3.3.38
for(i = 0; i < srcTotalOutChans; ++i)
buffer[i] = outBuffers[i];
}
else
+ {
// No data was available from a previous call during this process cycle. Nothing to add, just return.
return;
+ }
}
else
{
// First time here during this process cycle.
- // Point the input buffers at a temporary stack buffer.
- //float data[nframes * srcChannels];
- //for(i = 0; i < srcChannels; ++i)
- // buffer[i] = data + i * nframes;
- // p3.3.38
- float data[nframes * srcTotalOutChans];
- for(i = 0; i < srcTotalOutChans; ++i)
- buffer[i] = data + i * nframes;
-
+ _haveData = false; // Reset.
+ _processed = true; // Set this now.
- // getData can use the supplied buffers, or change buffer to point to its own local buffers or Jack buffers etc.
- // For ex. if this is an audio input, Jack will set the pointers for us.
- //if(!getData(pos, srcChannels, nframes, buffer))
- // p3.3.38
- if(!getData(pos, srcTotalOutChans, nframes, buffer))
- {
- // No data was available. Nothing to add, but zero our local buffers and the meters.
- for(i = 0; i < srcChans; ++i)
+ if(off())
+ {
+ #ifdef NODE_DEBUG
+ printf("MusE: AudioTrack::addData name:%s dstChannels:%d Track is Off \n", name().toLatin1().constData(), dstChannels);
+ #endif
+
+ // Nothing to zero or add...
+
+ _efxPipe->apply(0, nframes, 0); // Track is off. Just process controls only, not audio (do not 'run').
+
+ for(i = 0; i < trackChans; ++i)
{
- // If we're using local buffers, we must zero them so that the next thing requiring them
- // during this process cycle will see zeros.
- /*
- if(!usedirectbuf)
+ _meter[i] = 0.0;
+ /*if(!usedirectbuf)
{
if(MusEGlobal::config.useDenormalBias)
{
- for(unsigned int q = 0; q < nframes; ++q)
+ for(q = 0; q < nframes; ++q)
outBuffers[i][q] = MusEGlobal::denormalBias;
- }
- else
+ }
+ else
memset(outBuffers[i], 0, sizeof(float) * nframes);
- }
- */
-
- //_meter[i] = 0;
- _meter[i] = 0.0;
- }
-
- _haveData = false;
- _processed = true;
+ } */
+ }
return;
}
-
- /*
- // p3.3.41 Added.
- unsigned int q;
- for(i = 0; i < srcChans; ++i)
+
+ // Point the input buffers at a temporary stack buffer.
+ for(i = 0; i < srcTotalOutChans; ++i)
+ buffer[i] = data + i * nframes;
+
+ // getData can use the supplied buffers, or change buffer to point to its own local buffers or Jack buffers etc.
+ // For ex. if this is an audio input, Jack will set the pointers for us.
+ if(!getData(pos, srcTotalOutChans, nframes, buffer))
{
- if(MusEGlobal::config.useDenormalBias)
- {
- for(q = 0; q < nframes; ++q)
+ // No data was available. Track is not off. Zero the working buffers and continue on.
+ unsigned int q;
+ for(i = 0; i < srcTotalOutChans; ++i)
+ {
+ if(MusEGlobal::config.useDenormalBias)
{
- if(q & 1)
- buffer[i][q] -= MusEGlobal::denormalBias;
- else
- buffer[i][q] += MusEGlobal::denormalBias;
- }
- }
- }
- */
-
+ for(q = 0; q < nframes; ++q)
+ buffer[i][q] = MusEGlobal::denormalBias;
+ }
+ else
+ memset(buffer[i], 0, sizeof(float) * nframes);
+ }
+ }
+
//---------------------------------------------------
// apply plugin chain
//---------------------------------------------------
- // p3.3.41
//fprintf(stderr, "AudioTrack::addData %s efx apply srcChans:%d nframes:%ld %e %e %e %e\n",
// name().toLatin1().constData(), srcChans, nframes, buffer[0][0], buffer[0][1], buffer[0][2], buffer[0][3]);
- _efxPipe->apply(srcChans, nframes, buffer);
- // p3.3.41
+
+ _efxPipe->apply(trackChans, nframes, buffer);
+
//fprintf(stderr, "AudioTrack::addData after efx: %e %e %e %e\n",
// buffer[0][0], buffer[0][1], buffer[0][2], buffer[0][3]);
@@ -940,18 +927,16 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr
if(_prefader)
{
- for(i = 0; i < srcChans; ++i)
+ for(i = 0; i < trackChans; ++i)
{
float* p = buffer[i];
meter[i] = 0.0;
for(unsigned k = 0; k < nframes; ++k)
{
- double f = fabs(*p);
+ double f = fabs(*p++);
if(f > meter[i])
meter[i] = f;
- ++p;
}
- //_meter[i] = lrint(meter[i] * 32767.0);
_meter[i] = meter[i];
if(_meter[i] > _peak[i])
_peak[i] = _meter[i];
@@ -961,8 +946,7 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr
if(isMute())
{
// If we're using local buffers, we must zero them.
- /*
- if(!usedirectbuf)
+ /* if(!usedirectbuf)
{
for(i = 0; i < srcChannels; ++i)
{
@@ -974,20 +958,19 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr
else
memset(outBuffers[i], 0, sizeof(float) * nframes);
}
- }
- */
+ } */
- _haveData = false;
- _processed = true;
+ if(!_prefader)
+ //for(i = 0; i < srcChans; ++i)
+ for(i = 0; i < trackChans; ++i)
+ _meter[i] = 0.0;
+
return;
}
// If we're using local cached 'pre-volume' buffers, copy the input buffers (as they are right now: post-effect pre-volume) back to them.
- if(!usedirectbuf)
+ //if(!usedirectbuf)
{
- //for(i = 0; i < srcChannels; ++i)
- // AL::dsp->cpy(outBuffers[i], buffer[i], nframes);
- // p3.3.38
for(i = 0; i < srcTotalOutChans; ++i)
AL::dsp->cpy(outBuffers[i], buffer[i], nframes);
}
@@ -1010,9 +993,9 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr
else
memset(dstBuffer[i], 0, sizeof(float) * nframes);
}
- _processed = true;
return;
}
+
// Force a source range to fit actual available total out channels.
if((srcStartChan + srcChans) > srcTotalOutChans)
srcChans = srcTotalOutChans - srcStartChan;
@@ -1022,123 +1005,88 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr
// postfader metering
//---------------------------------------------------
- if(srcChans == dstChannels)
+ #ifdef NODE_DEBUG
+ printf("MusE: AudioTrack::addData trackChans:%d srcTotalOutChans:%d srcChans:%d dstChannels:%d\n", trackChans, srcTotalOutChans, srcChans, dstChannels);
+ #endif
+
+ if(!_prefader)
{
- if(_prefader)
+ for(int c = 0; c < trackChans; ++c)
{
- for(int c = 0; c < dstChannels; ++c)
+ meter[c] = 0.0;
+ double v = (trackChans == 1 ? _volume : vol[c]);
+ float* sp = buffer[c];
+ for(unsigned k = 0; k < nframes; ++k)
{
- // p3.3.38
- //float* sp = buffer[c];
- float* sp = buffer[c + srcStartChan];
-
- float* dp = dstBuffer[c];
- for(unsigned k = 0; k < nframes; ++k)
- *dp++ += (*sp++ * vol[c]);
+ float val = *sp++ * v; // If the track is mono pan has no effect on meters.
+ double f = fabs(val);
+ if(f > meter[c])
+ meter[c] = f;
}
- }
- else
+ _meter[c] = meter[c];
+ if(_meter[c] > _peak[c])
+ _peak[c] = _meter[c];
+ }
+ }
+
+ if(srcChans == dstChannels)
+ {
+ for(int c = 0; c < dstChannels; ++c)
{
- for(int c = 0; c < dstChannels; ++c)
- {
- meter[c] = 0.0;
- // p3.3.38
- //float* sp = buffer[c];
- float* sp = buffer[c + srcStartChan];
-
- float* dp = dstBuffer[c];
- for(unsigned k = 0; k < nframes; ++k)
- {
- float val = *sp++ * vol[c];
- *dp++ += val;
- double f = fabs(val);
- if (f > meter[c])
- meter[c] = f;
- }
- //_meter[c] = lrint(meter[c] * 32767.0);
- _meter[c] = meter[c];
- if(_meter[c] > _peak[c])
- _peak[c] = _meter[c];
- }
+ double v;
+ if(srcStartChan > 2) // Don't apply pan or volume to extra channels above 2.
+ //v = _volume;
+ v = 1.0;
+ else
+ if(srcChans >= 2) // If 2 channels apply pan normally.
+ v = vol[c];
+ else
+ if(trackChans < 2) // If 1 channel and track is 1 channel, don't apply pan.
+ v = _volume;
+ else
+ v = vol[srcStartChan]; // Otherwise 1 channel but track is 2 channels. Apply the channel volume.
+
+ float* sp = buffer[c + srcStartChan];
+ float* dp = dstBuffer[c];
+ for(unsigned k = 0; k < nframes; ++k)
+ //*dp++ += (*sp++ * vol[c]);
+ *dp++ += (*sp++ * v);
}
}
else if(srcChans == 1 && dstChannels == 2)
{
- // p3.3.38
- float* sp = buffer[srcStartChan];
-
- if(_prefader)
+ for(int c = 0; c < dstChannels; ++c)
{
- for(int c = 0; c < dstChannels; ++c)
- {
- float* dp = dstBuffer[c];
- //float* sp = buffer[0];
- for(unsigned k = 0; k < nframes; ++k)
- *dp++ += (*sp++ * vol[c]);
- }
- }
- else
- {
- //float* sp = buffer[0];
- meter[0] = 0.0;
- for(unsigned k = 0; k < nframes; ++k)
- {
- float val = *sp++;
- double f = fabs(val) * _volume;
- if(f > meter[0])
- meter[0] = f;
- *(dstBuffer[0] + k) += val * vol[0];
- *(dstBuffer[1] + k) += val * vol[1];
- }
- //_meter[0] = lrint(meter[0] * 32767.0);
- _meter[0] = meter[0];
- if(_meter[0] > _peak[0])
- _peak[0] = _meter[0];
+ double v;
+ if(srcStartChan > 2) // Don't apply pan or volume to extra channels above 2.
+ //v = _volume;
+ v = 1.0;
+ else
+ if(trackChans <= 1) // If track is mono apply pan.
+ v = vol[c];
+ else
+ v = vol[srcStartChan]; // Otherwise track is stereo, apply the same channel volume to both.
+
+ float* sp = buffer[srcStartChan];
+ float* dp = dstBuffer[c];
+ for(unsigned k = 0; k < nframes; ++k)
+ //*dp++ += (*sp++ * vol[c]);
+ *dp++ += (*sp++ * v);
}
}
else if(srcChans == 2 && dstChannels == 1)
{
- // p3.3.38
- //float* sp1 = buffer[0];
- //float* sp2 = buffer[1];
+ //double v1 = (srcStartChan > 2 ? _volume : vol[srcStartChan]); // Don't apply pan to extra channels above 2.
+ //double v2 = (srcStartChan > 2 ? _volume : vol[srcStartChan + 1]); //
+ double v1 = (srcStartChan > 2 ? 1.0 : vol[srcStartChan]); // Don't apply pan or volume to extra channels above 2.
+ double v2 = (srcStartChan > 2 ? 1.0 : vol[srcStartChan + 1]); //
float* sp1 = buffer[srcStartChan];
float* sp2 = buffer[srcStartChan + 1];
-
- if(_prefader)
- {
- float* dp = dstBuffer[0];
- for(unsigned k = 0; k < nframes; ++k)
- *dp++ += (*sp1++ * vol[0] + *sp2++ * vol[1]);
- }
- else
- {
- float* dp = dstBuffer[0];
- meter[0] = 0.0;
- meter[1] = 0.0;
- for(unsigned k = 0; k < nframes; ++k)
- {
- float val1 = *sp1++ * vol[0];
- float val2 = *sp2++ * vol[1];
- double f1 = fabs(val1);
- if(f1 > meter[0])
- meter[0] = f1;
- double f2 = fabs(val2);
- if(f2 > meter[1])
- meter[1] = f2;
- *dp++ += (val1 + val2);
- }
- //_meter[0] = lrint(meter[0] * 32767.0);
- _meter[0] = meter[0];
- if(_meter[0] > _peak[0])
- _peak[0] = _meter[0];
- //_meter[1] = lrint(meter[1] * 32767.0);
- _meter[1] = meter[1];
- if(_meter[1] > _peak[1])
- _peak[1] = _meter[1];
- }
+ float* dp = dstBuffer[0];
+ for(unsigned k = 0; k < nframes; ++k)
+ //*dp++ += (*sp1++ * vol[0] + *sp2++ * vol[1]);
+ *dp++ += (*sp1++ * v1 + *sp2++ * v2);
}
-
- _processed = true;
}
//---------------------------------------------------------
@@ -1300,15 +1248,12 @@ bool AudioTrack::getData(unsigned pos, int channels, unsigned nframes, float** b
printf(" calling copyData on %s...\n", ir->track->name().toLatin1().constData());
#endif
- // p3.3.38
- //((AudioTrack*)ir->track)->copyData(pos, channels, nframes, buffer);
((AudioTrack*)ir->track)->copyData(pos, channels,
//(ir->track->type() == Track::AUDIO_SOFTSYNTH && ir->channel != -1) ? ir->channel : 0,
ir->channel,
ir->channels,
nframes, buffer);
- // p3.3.41
//fprintf(stderr, "AudioTrack::getData %s data: nframes:%ld %e %e %e %e\n", name().toLatin1().constData(), nframes, buffer[0][0], buffer[0][1], buffer[0][2], buffer[0][3]);
++ir;
@@ -1320,8 +1265,6 @@ bool AudioTrack::getData(unsigned pos, int channels, unsigned nframes, float** b
if(ir->track->isMidiTrack())
continue;
- // p3.3.38
- //((AudioTrack*)ir->track)->addData(pos, channels, nframes, buffer);
((AudioTrack*)ir->track)->addData(pos, channels,
//(ir->track->type() == Track::AUDIO_SOFTSYNTH && ir->channel != -1) ? ir->channel : 0,
ir->channel,
@@ -1344,12 +1287,11 @@ bool AudioInput::getData(unsigned, int channels, unsigned nframes, float** buffe
void* jackPort = jackPorts[ch];
//float* jackbuf = 0;
- //if (jackPort) {
- // p3.3.41 Do not get buffers of unconnected client ports. Causes repeating leftover data, can be loud, or DC !
+ // Do not get buffers of unconnected client ports. Causes repeating leftover data, can be loud, or DC !
if (jackPort && MusEGlobal::audioDevice->connections(jackPort))
{
//buffer[ch] = MusEGlobal::audioDevice->getBuffer(jackPort, nframes);
- // p3.3.41 If the client port buffer is also used by another channel (connected to the same jack port),
+ // If the client port buffer is also used by another channel (connected to the same jack port),
// don't directly set pointer, copy the data instead.
// Otherwise the next channel will interfere - it will overwrite the buffer !
// Verified symptoms: Can't use a splitter. Mono noise source on a stereo track sounds in mono. Etc...
@@ -1366,8 +1308,6 @@ bool AudioInput::getData(unsigned, int channels, unsigned nframes, float** buffe
{
for (unsigned int i=0; i < nframes; i++)
buffer[ch][i] += MusEGlobal::denormalBias;
-
- // p3.3.41
//fprintf(stderr, "AudioInput::getData %s Jack port %p efx apply channels:%d nframes:%ld %e %e %e %e\n",
// name().toLatin1().constData(), jackPort, channels, nframes, buffer[0][0], buffer[0][1], buffer[0][2], buffer[0][3]);
}
@@ -1384,8 +1324,6 @@ bool AudioInput::getData(unsigned, int channels, unsigned nframes, float** buffe
memset(buffer[ch], 0, nframes * sizeof(float));
}
- // p3.3.41
- //fprintf(stderr, "AudioInput::getData %s No Jack port efx apply channels:%d nframes:%ld %e %e %e %e\n",
// name().toLatin1().constData(), channels, nframes, buffer[0][0], buffer[0][1], buffer[0][2], buffer[0][3]);
}
}
@@ -1524,7 +1462,7 @@ void AudioTrack::record()
return;
}
if (_recFile) {
- // Line removed by Tim. p3.3.8 Oct 28, 2009
+ // Line removed by Tim. Oct 28, 2009
//_recFile->seek(pos, 0);
//
// Fix for recorded waves being shifted ahead by an amount
@@ -1570,7 +1508,6 @@ void AudioTrack::record()
if( (pos >= fr) && (!MusEGlobal::song->punchout() || (!MusEGlobal::song->loop() && pos < MusEGlobal::song->rPos().frame())) )
{
pos -= fr;
- // Added by Tim. p3.3.8
//int position = _recFile->seek(0, SEEK_CUR);
//printf("AudioTrack::record loopcnt:%d lframe:%d newpos:%d curpos:%d start:%d end:%d\n", MusEGlobal::audio->loopCount(), MusEGlobal::audio->loopFrame(), pos, position, MusEGlobal::audio->getStartRecordPos().frame(), MusEGlobal::audio->getEndRecordPos().frame());
@@ -1614,7 +1551,6 @@ void AudioOutput::processInit(unsigned nframes)
void AudioOutput::process(unsigned pos, unsigned offset, unsigned n)
{
- //Added by Tim. p3.3.16
#ifdef NODE_DEBUG
printf("MusE: AudioOutput::process name:%s processed:%d\n", name().toLatin1().constData(), processed());
#endif
@@ -1622,9 +1558,6 @@ void AudioOutput::process(unsigned pos, unsigned offset, unsigned n)
for (int i = 0; i < _channels; ++i) {
buffer1[i] = buffer[i] + offset;
}
-
- // p3.3.38
- //copyData(pos, _channels, n, buffer1);
copyData(pos, _channels, -1, -1, n, buffer1);
}
@@ -1666,17 +1599,13 @@ void AudioOutput::processWrite()
putFifo(_channels, _nframes, buffer);
}
}
- // Changed by Tim. p3.3.18
+ // Changed by Tim.
//if (MusEGlobal::audioClickFlag && MusEGlobal::song->click()) {
if (sendMetronome() && MusEGlobal::audioClickFlag && MusEGlobal::song->click()) {
- // Added by Tim. p3.3.18
#ifdef METRONOME_DEBUG
printf("MusE: AudioOutput::processWrite Calling metronome->addData frame:%u channels:%d frames:%lu\n", MusEGlobal::audio->pos().frame(), _channels, _nframes);
#endif
-
- // p3.3.38
- //metronome->addData(MusEGlobal::audio->pos().frame(), _channels, _nframes, buffer);
metronome->addData(MusEGlobal::audio->pos().frame(), _channels, -1, -1, _nframes, buffer);
}
}
@@ -1721,7 +1650,6 @@ Fifo::~Fifo()
{
for (int i = 0; i < nbuffer; ++i)
{
- // p3.3.45
if(buffer[i]->buffer)
{
//printf("Fifo::~Fifo freeing buffer\n");
@@ -1742,7 +1670,6 @@ Fifo::~Fifo()
bool Fifo::put(int segs, unsigned long samples, float** src, unsigned pos)
{
- // Added by Tim. p3.3.17
#ifdef FIFO_DEBUG
printf("FIFO::put segs:%d samples:%lu pos:%u\n", segs, samples, pos);
#endif
@@ -1765,7 +1692,6 @@ bool Fifo::put(int segs, unsigned long samples, float** src, unsigned pos)
// Changed by Tim. p3.3.15
//b->buffer = new float[n];
posix_memalign((void**)&(b->buffer), 16, sizeof(float) * n);
- // p3.3.45
if(!b->buffer)
{
printf("Fifo::put could not allocate buffer segs:%d samples:%lu pos:%u\n", segs, samples, pos);
@@ -1774,7 +1700,6 @@ bool Fifo::put(int segs, unsigned long samples, float** src, unsigned pos)
b->maxSize = n;
}
- // p3.3.45
if(!b->buffer)
{
printf("Fifo::put no buffer! segs:%d samples:%lu pos:%u\n", segs, samples, pos);
@@ -1798,7 +1723,6 @@ bool Fifo::put(int segs, unsigned long samples, float** src, unsigned pos)
bool Fifo::get(int segs, unsigned long samples, float** dst, unsigned* pos)
{
- // Added by Tim. p3.3.17
#ifdef FIFO_DEBUG
printf("FIFO::get segs:%d samples:%lu\n", segs, samples);
#endif
@@ -1808,7 +1732,6 @@ bool Fifo::get(int segs, unsigned long samples, float** dst, unsigned* pos)
return true;
}
FifoBuffer* b = buffer[ridx];
- // p3.3.45
if(!b->buffer)
{
printf("Fifo::get no buffer! segs:%d samples:%lu b->pos:%u\n", segs, samples, b->pos);
@@ -1844,7 +1767,6 @@ void Fifo::remove()
bool Fifo::getWriteBuffer(int segs, unsigned long samples, float** buf, unsigned pos)
{
- // Added by Tim. p3.3.17
#ifdef FIFO_DEBUG
printf("Fifo::getWriteBuffer segs:%d samples:%lu pos:%u\n", segs, samples, pos);
#endif
@@ -1866,7 +1788,6 @@ bool Fifo::getWriteBuffer(int segs, unsigned long samples, float** buf, unsigned
// Changed by Tim. p3.3.15
//b->buffer = new float[n];
posix_memalign((void**)&(b->buffer), 16, sizeof(float) * n);
- // p3.3.45
if(!b->buffer)
{
printf("Fifo::getWriteBuffer could not allocate buffer segs:%d samples:%lu pos:%u\n", segs, samples, pos);
@@ -1875,8 +1796,6 @@ bool Fifo::getWriteBuffer(int segs, unsigned long samples, float** buf, unsigned
b->maxSize = n;
}
-
- // p3.3.45
if(!b->buffer)
{
printf("Fifo::getWriteBuffer no buffer! segs:%d samples:%lu pos:%u\n", segs, samples, pos);
diff --git a/muse2/muse/osc.cpp b/muse2/muse/osc.cpp
index 6959803e..7daeb9ff 100644
--- a/muse2/muse/osc.cpp
+++ b/muse2/muse/osc.cpp
@@ -841,7 +841,8 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin
arguments << oscUrl
<< filePath
<< name
- << QString("channel-1");
+ //<< QString("channel-1");
+ << (titlePrefix() + label);
#ifdef OSC_DEBUG
fprintf(stderr, "OscIF::oscInitGui starting QProcess\n");
@@ -885,7 +886,8 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin
oscUrl.toLatin1().constData(),
filePath.toLatin1().constData(),
name.toLatin1().constData(),
- "channel 1", (void*)0);
+ //"channel 1", (void*)0);
+ label.toLatin1().constData(), (void*)0);
// Should not return after execlp. If so it's an error.
fprintf(stderr, "exec %s %s %s %s %s failed: %s\n",
@@ -941,13 +943,13 @@ void OscIF::oscShowGui(bool v)
}
//for (int i = 0; i < 5; ++i) {
- for (int i = 0; i < 10; ++i) { // Give it a wee bit more time?
+ for (int i = 0; i < 20; ++i) { // Give it a wee bit more time?
if (_uiOscPath)
break;
sleep(1);
}
if (_uiOscPath == 0) {
- printf("OscIF::oscShowGui(): no _uiOscPath. Error: Timeout - synth gui did not start within 10 seconds.\n");
+ printf("OscIF::oscShowGui(): no _uiOscPath. Error: Timeout - synth gui did not start within 20 seconds.\n");
return;
}
@@ -1091,10 +1093,14 @@ bool OscDssiIF::oscInitGui()
_oscSynthIF->dssiSynth()->name(), _oscSynthIF->dssiSynthI()->name(),
_oscSynthIF->dssiSynth()->fileName(), _oscSynthIF->dssi_ui_filename());
}
+
+QString OscDssiIF::titlePrefix() const
+{
+ return _oscSynthIF ? _oscSynthIF->titlePrefix() : QString();
+}
#endif // DSSI_SUPPORT
-
//---------------------------------------------------------
// OscEffectIF::
// oscSetPluginI
@@ -1165,6 +1171,11 @@ bool OscEffectIF::oscInitGui()
_oscPluginI->plugin()->fileName(), _oscPluginI->dssi_ui_filename());
}
+QString OscEffectIF::titlePrefix() const
+{
+ return _oscPluginI ? _oscPluginI->titlePrefix() : QString();
+}
+
#else //OSC_SUPPORT
void initOSC() {}
diff --git a/muse2/muse/osc.h b/muse2/muse/osc.h
index 30df03cb..e3f1a26d 100644
--- a/muse2/muse/osc.h
+++ b/muse2/muse/osc.h
@@ -74,6 +74,8 @@ class OscIF
virtual bool oscInitGui() { return false; }
virtual void oscShowGui(bool);
virtual bool oscGuiVisible() const;
+
+ virtual QString titlePrefix() const { return QString(); }
};
class OscEffectIF : public OscIF
@@ -95,6 +97,8 @@ class OscEffectIF : public OscIF
virtual int oscConfigure(lo_arg**);
virtual bool oscInitGui();
+
+ virtual QString titlePrefix() const;
};
#ifdef DSSI_SUPPORT
@@ -117,6 +121,8 @@ class OscDssiIF : public OscIF
virtual int oscConfigure(lo_arg**);
virtual bool oscInitGui();
+
+ virtual QString titlePrefix() const;
};
#endif // DSSI_SUPPORT
diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp
index eb5b1af6..da01a5d5 100644
--- a/muse2/muse/part.cpp
+++ b/muse2/muse/part.cpp
@@ -750,6 +750,18 @@ WavePart::WavePart(const WavePart& p) : Part(p)
Part::~Part()
{
+ if (_prevClone!=this || _nextClone!=this)
+ {
+ printf("THIS MIGHT BE A HINT FOR BUGS: Part isn't unchained in ~Part()! i'll do that now. this is\n"
+ "not an actual bug, actually that manual unchain should be unneccessary if this was coded\n"
+ "properly. but as it wasn't, and the unchain was always done manually, this might be an\n"
+ "indicator that it have been forgotten. either your computer will explode in 3..2..1..now,\n"
+ "or you can ignore this message.\n"
+ "\n");
+
+ unchainClone(this);
+ }
+
_events->incRef(-1);
if (_events->refCount() <= 0)
delete _events;
diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp
index 2bdd0317..227a9daf 100644
--- a/muse2/muse/plugin.cpp
+++ b/muse2/muse/plugin.cpp
@@ -1573,65 +1573,60 @@ bool Pipeline::nativeGuiVisible(int idx)
//---------------------------------------------------------
// apply
+// If ports is 0, just process controllers only, not audio (do not 'run').
//---------------------------------------------------------
-//void Pipeline::apply(int ports, unsigned long nframes, float** buffer1)
void Pipeline::apply(unsigned long ports, unsigned long nframes, float** buffer1)
{
// prepare a second set of buffers in case a plugin is not
// capable of inPlace processing
-
- // Removed by Tim. p3.3.15
//float* buffer2[ports];
//float data[nframes * ports];
//for (int i = 0; i < ports; ++i)
// buffer2[i] = data + i * nframes;
- // p3.3.41
- //fprintf(stderr, "Pipeline::apply data: nframes:%lu %e %e %e %e\n", nframes, buffer1[0][0], buffer1[0][1], buffer1[0][2], buffer1[0][3]);
+ //fprintf(stderr, "Pipeline::apply data: nframes:%lu %e %e %e %e\n", nframes, buffer1[0][0], buffer1[0][1], buffer1[0][2], buffer1[0][3]);
bool swap = false;
for (iPluginI ip = begin(); ip != end(); ++ip) {
PluginI* p = *ip;
- if (p && p->on()) {
- if (p->inPlaceCapable())
- {
- if (swap)
- //p->connect(ports, buffer2, buffer2);
- //p->connect(ports, buffer, buffer);
- p->apply(nframes, ports, buffer, buffer); // p4.0.21
- else
- //p->connect(ports, buffer1, buffer1);
- p->apply(nframes, ports, buffer1, buffer1); //
- }
- else
- {
- if (swap)
- //p->connect(ports, buffer2, buffer1);
- //p->connect(ports, buffer, buffer1);
- p->apply(nframes, ports, buffer, buffer1); //
- else
- //p->connect(ports, buffer1, buffer2);
- //p->connect(ports, buffer1, buffer);
- p->apply(nframes, ports, buffer1, buffer); //
- swap = !swap;
- }
- //p->apply(nframes); // Rem. p4.0.21
- }
+
+ if(p)
+ {
+ //if (p && p->on()) {
+ if (p->on())
+ {
+ //fprintf(stderr, "Pipeline::apply PluginI:%p on:%d\n", p, p->on());
+ if (p->inPlaceCapable())
+ {
+ if (swap)
+ p->apply(nframes, ports, buffer, buffer);
+ else
+ p->apply(nframes, ports, buffer1, buffer1);
+ }
+ else
+ {
+ if (swap)
+ p->apply(nframes, ports, buffer, buffer1);
+ else
+ p->apply(nframes, ports, buffer1, buffer);
+ swap = !swap;
+ }
+ }
+ else
+ {
+ p->apply(nframes, 0, 0, 0); // Do not process (run) audio, process controllers only.
+ }
}
- if (swap)
+ }
+ if (ports != 0 && swap)
{
- //for (int i = 0; i < ports; ++i)
- for (unsigned long i = 0; i < ports; ++i) // p4.0.21
+ for (unsigned long i = 0; i < ports; ++i)
//memcpy(buffer1[i], buffer2[i], sizeof(float) * nframes);
//memcpy(buffer1[i], buffer[i], sizeof(float) * nframes);
AL::dsp->cpy(buffer1[i], buffer[i], nframes);
}
-
- // p3.3.41
- //fprintf(stderr, "Pipeline::apply after data: nframes:%lu %e %e %e %e\n", nframes, buffer1[0][0], buffer1[0][1], buffer1[0][2], buffer1[0][3]);
-
}
//---------------------------------------------------------
@@ -2439,6 +2434,7 @@ void PluginI::showGui()
if (_plugin) {
if (_gui == 0)
makeGui();
+ _gui->setWindowTitle(titlePrefix() + name());
if (_gui->isVisible())
_gui->hide();
else
@@ -2558,7 +2554,17 @@ void PluginI::enable2AllControllers(bool v)
}
//---------------------------------------------------------
+// titlePrefix
+//---------------------------------------------------------
+
+QString PluginI::titlePrefix() const
+{
+ return _track->name() + QString(": ");
+}
+
+//---------------------------------------------------------
// apply
+// If ports is 0, just process controllers only, not audio (do not 'run').
//---------------------------------------------------------
/*
@@ -2653,7 +2659,6 @@ void PluginI::apply(unsigned long n)
*/
#if 1
-// p4.0.21
void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** bufOut)
{
// Process control value changes.
@@ -2769,7 +2774,6 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float**
//controls[v.idx].val = v.value;
controls[v.idx].tmpVal = v.value;
- /*
// Need to update the automation value, otherwise it overwrites later with the last MusEGlobal::automation value.
if(_track && _id != -1)
{
@@ -2795,7 +2799,6 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float**
// enableController(k, false);
//_track->recordAutomation(id, v.value);
}
- */
}
// Now update the actual values from the temporary values...
@@ -2813,20 +2816,23 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float**
nsamp = n - sample;
//printf("PluginI::apply ports:%lu n:%lu frame:%lu sample:%lu nsamp:%lu syncFrame:%lu loopcount:%d\n",
- // ports, n, frame, sample, nsamp, syncFrame, loopcount); // REMOVE Tim.
+ // ports, n, frame, sample, nsamp, syncFrame, loopcount);
// Don't allow zero-length runs. This could/should be checked in the control loop instead.
// Note this means it is still possible to get stuck in the top loop (at least for a while).
if(nsamp == 0)
continue;
- connect(ports, sample, bufIn, bufOut);
+ if(ports != 0)
+ {
+ connect(ports, sample, bufIn, bufOut);
- for(int i = 0; i < instances; ++i)
- {
- //fprintf(stderr, "PluginI::apply handle %d\n", i);
- _plugin->apply(handle[i], nsamp);
- }
+ for(int i = 0; i < instances; ++i)
+ {
+ //fprintf(stderr, "PluginI::apply handle %d\n", i);
+ _plugin->apply(handle[i], nsamp);
+ }
+ }
sample += nsamp;
loopcount++; // REMOVE Tim.
@@ -3444,7 +3450,8 @@ PluginGui::PluginGui(MusECore::PluginIBase* p)
params = 0;
paramsOut = 0;
plugin = p;
- setWindowTitle(plugin->name());
+ //setWindowTitle(plugin->name());
+ setWindowTitle(plugin->titlePrefix() + plugin->name());
QToolBar* tools = addToolBar(tr("File Buttons"));
@@ -4106,16 +4113,18 @@ void PluginGui::save()
void PluginGui::bypassToggled(bool val)
{
+ setWindowTitle(plugin->titlePrefix() + plugin->name());
plugin->setOn(val);
MusEGlobal::song->update(SC_ROUTE);
}
//---------------------------------------------------------
-// songChanged
+// setOn
//---------------------------------------------------------
void PluginGui::setOn(bool val)
{
+ setWindowTitle(plugin->titlePrefix() + plugin->name());
onOff->blockSignals(true);
onOff->setChecked(val);
onOff->blockSignals(false);
@@ -4208,11 +4217,11 @@ void PluginGui::updateControls()
}
- if(!MusEGlobal::automation)
- return;
- AutomationType at = plugin->track()->automationType();
- if(at == AUTO_OFF)
- return;
+ //if(!MusEGlobal::automation)
+ // return;
+ //AutomationType at = plugin->track()->automationType();
+ //if(at == AUTO_OFF)
+ // return;
if (params) {
//for (int i = 0; i < plugin->parameters(); ++i) {
for (unsigned long i = 0; i < plugin->parameters(); ++i) { // p4.0.21
diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h
index 717f98b6..044fd863 100644
--- a/muse2/muse/plugin.h
+++ b/muse2/muse/plugin.h
@@ -72,18 +72,6 @@ class Xml;
class MidiController;
-/*
-//---------------------------------------------------------
-// PluginBase
-//---------------------------------------------------------
-
-class PluginBase
-{
- protected:
- void range(unsigned long i, float*, float*) const;
-};
-*/
-
//---------------------------------------------------------
// Plugin
//---------------------------------------------------------
@@ -155,13 +143,11 @@ class Plugin {
if (plugin && plugin->cleanup)
plugin->cleanup(handle);
}
- //void connectPort(LADSPA_Handle handle, int port, float* value) {
- void connectPort(LADSPA_Handle handle, unsigned long port, float* value) { // p4.0.21
+ void connectPort(LADSPA_Handle handle, unsigned long port, float* value) {
if(plugin)
plugin->connect_port(handle, port, value);
}
- //void apply(LADSPA_Handle handle, int n) {
- void apply(LADSPA_Handle handle, unsigned long n) { // p4.0.21
+ void apply(LADSPA_Handle handle, unsigned long n) {
if(plugin)
plugin->run(handle, n);
}
@@ -170,12 +156,10 @@ class Plugin {
int oscConfigure(LADSPA_Handle /*handle*/, const char* /*key*/, const char* /*value*/);
#endif
- //int ports() { return plugin ? plugin->PortCount : 0; }
unsigned long ports() { return _portCount; }
LADSPA_PortDescriptor portd(unsigned long k) const {
return plugin ? plugin->PortDescriptors[k] : 0;
- //return _portDescriptors[k];
}
LADSPA_PortRangeHint range(unsigned long i) {
@@ -184,8 +168,7 @@ class Plugin {
return plugin->PortRangeHints[i];
}
- //double defaultValue(unsigned long port) const;
- float defaultValue(unsigned long port) const; // p4.0.21
+ float defaultValue(unsigned long port) const;
void range(unsigned long i, float*, float*) const;
CtrlValueType ctrlValueType(unsigned long /*i*/) const;
CtrlList::Mode ctrlMode(unsigned long /*i*/) const;
@@ -202,20 +185,6 @@ class Plugin {
unsigned long controlInPorts() const { return _controlInPorts; }
unsigned long controlOutPorts() const { return _controlOutPorts; }
bool inPlaceCapable() const { return _inPlaceCapable; }
-
- /*
- bool isLog(int k) const {
- LADSPA_PortRangeHint r = plugin->PortRangeHints[pIdx[k]];
- return LADSPA_IS_HINT_LOGARITHMIC(r.HintDescriptor);
- }
- bool isBool(int k) const {
- return LADSPA_IS_HINT_TOGGLED(plugin->PortRangeHints[pIdx[k]].HintDescriptor);
- }
- bool isInt(int k) const {
- LADSPA_PortRangeHint r = plugin->PortRangeHints[pIdx[k]];
- return LADSPA_IS_HINT_INTEGER(r.HintDescriptor);
- }
- */
};
typedef std::list<Plugin>::iterator iPlugin;
@@ -266,21 +235,18 @@ class PluginIBase
~PluginIBase();
virtual bool on() const = 0;
virtual void setOn(bool /*val*/) = 0;
- //virtual int pluginID() = 0;
- virtual unsigned long pluginID() = 0; // p4.0.21
+ virtual unsigned long pluginID() = 0;
virtual int id() = 0;
virtual QString pluginLabel() const = 0;
virtual QString name() const = 0;
virtual QString lib() const = 0;
virtual QString dirPath() const = 0;
virtual QString fileName() const = 0;
+ virtual QString titlePrefix() const = 0;
virtual AudioTrack* track() = 0;
- //virtual void enableController(int /*i*/, bool /*v*/ = true) = 0;
- //virtual bool controllerEnabled(int /*i*/) const = 0;
- //virtual bool controllerEnabled2(int /*i*/) const = 0;
- virtual void enableController(unsigned long /*i*/, bool /*v*/ = true) = 0; // p4.0.21
+ virtual void enableController(unsigned long /*i*/, bool /*v*/ = true) = 0;
virtual bool controllerEnabled(unsigned long /*i*/) const = 0;
virtual bool controllerEnabled2(unsigned long /*i*/) const = 0;
virtual void updateControllers() = 0;
@@ -288,12 +254,7 @@ class PluginIBase
virtual void writeConfiguration(int /*level*/, Xml& /*xml*/) = 0;
virtual bool readConfiguration(Xml& /*xml*/, bool /*readPreset*/=false) = 0;
- //virtual int parameters() const = 0;
- //virtual void setParam(int /*i*/, double /*val*/) = 0;
- //virtual double param(int /*i*/) const = 0;
- //virtual const char* paramName(int /*i*/) = 0;
- //virtual LADSPA_PortRangeHint range(int /*i*/) = 0;
- virtual unsigned long parameters() const = 0; // p4.0.21
+ virtual unsigned long parameters() const = 0;
virtual unsigned long parametersOut() const = 0;
virtual void setParam(unsigned long /*i*/, float /*val*/) = 0;
virtual float param(unsigned long /*i*/) const = 0;
@@ -307,8 +268,6 @@ class PluginIBase
virtual CtrlList::Mode ctrlMode(unsigned long /*i*/) const = 0;
QString dssi_ui_filename() const;
- //virtual void showGui(bool) = 0; // p4.0.20
- //virtual void showNativeGui(bool) = 0; //
MusEGui::PluginGui* gui() const { return _gui; }
void deleteGui();
};
@@ -353,7 +312,6 @@ class PluginBase
#define AUDIO_IN (LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT)
#define AUDIO_OUT (LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT)
-//class PluginI {
class PluginI : public PluginIBase {
Plugin* _plugin;
int channel;
@@ -365,10 +323,8 @@ class PluginI : public PluginIBase {
Port* controls;
Port* controlsOut;
- //int controlPorts;
- //int controlOutPorts;
- unsigned long controlPorts; // p4.0.21
- unsigned long controlOutPorts; //
+ unsigned long controlPorts;
+ unsigned long controlOutPorts;
///PluginGui* _gui;
bool _on;
@@ -400,26 +356,17 @@ class PluginI : public PluginIBase {
void setTrack(AudioTrack* t) { _track = t; }
AudioTrack* track() { return _track; }
- //int pluginID() { return _plugin->id(); }
- unsigned long pluginID() { return _plugin->id(); } // p4.0.21
+ unsigned long pluginID() { return _plugin->id(); }
void setID(int i);
int id() { return _id; }
void updateControllers();
bool initPluginInstance(Plugin*, int channels);
void setChannels(int);
- //void connect(int ports, float** src, float** dst);
- //void apply(int n);
- //void connect(unsigned ports, float** src, float** dst);
- //void apply(unsigned n);
- void connect(unsigned long ports, unsigned long offset, float** src, float** dst); // p4.0.21
- void apply(unsigned long n, unsigned long ports, float** bufIn, float** bufOut); //
-
- //void enableController(int i, bool v = true) { controls[i].enCtrl = v; }
- //bool controllerEnabled(int i) const { return controls[i].enCtrl; }
- //void enable2Controller(int i, bool v = true) { controls[i].en2Ctrl = v; }
- //bool controllerEnabled2(int i) const { return controls[i].en2Ctrl; }
- void enableController(unsigned long i, bool v = true) { controls[i].enCtrl = v; } // p4.0.21
+ void connect(unsigned long ports, unsigned long offset, float** src, float** dst);
+ void apply(unsigned long n, unsigned long ports, float** bufIn, float** bufOut);
+
+ void enableController(unsigned long i, bool v = true) { controls[i].enCtrl = v; }
bool controllerEnabled(unsigned long i) const { return controls[i].enCtrl; }
void enable2Controller(unsigned long i, bool v = true) { controls[i].en2Ctrl = v; }
bool controllerEnabled2(unsigned long i) const { return controls[i].en2Ctrl; }
@@ -434,6 +381,7 @@ class PluginI : public PluginIBase {
QString lib() const { return _plugin->lib(); }
QString dirPath() const { return _plugin->dirPath(); }
QString fileName() const { return _plugin->fileName(); }
+ QString titlePrefix() const;
#ifdef OSC_SUPPORT
OscEffectIF& oscIF() { return _oscif; }
@@ -453,8 +401,7 @@ class PluginI : public PluginIBase {
void writeConfiguration(int level, Xml& xml);
bool readConfiguration(Xml& xml, bool readPreset=false);
bool loadControl(Xml& xml);
- //bool setControl(const QString& s, double val);
- bool setControl(const QString& s, float val); // p4.0.21
+ bool setControl(const QString& s, float val);
void showGui();
void showGui(bool);
bool isDssiPlugin() const { return _plugin->isDssiPlugin(); }
@@ -464,20 +411,8 @@ class PluginI : public PluginIBase {
bool guiVisible();
bool nativeGuiVisible();
- //int parameters() const { return controlPorts; }
- //void setParam(int i, double val) { controls[i].tmpVal = val; }
- //double param(int i) const { return controls[i].val; }
- //double defaultValue(unsigned int param) const;
- //const char* paramName(int i) { return _plugin->portName(controls[i].idx); }
- //LADSPA_PortDescriptor portd(int i) const { return _plugin->portd(controls[i].idx); }
- //void range(int i, float* min, float* max) const { _plugin->range(controls[i].idx, min, max); }
- //bool isAudioIn(int k) { return (_plugin->portd(k) & AUDIO_IN) == AUDIO_IN; }
- //bool isAudioOut(int k) { return (_plugin->portd(k) & AUDIO_OUT) == AUDIO_OUT; }
- //LADSPA_PortRangeHint range(int i) { return _plugin->range(controls[i].idx); }
- // p4.0.21
unsigned long parameters() const { return controlPorts; }
unsigned long parametersOut() const { return controlOutPorts; }
- //void setParam(unsigned i, float val) { controls[i].tmpVal = val; }
void setParam(unsigned long i, float val);
float param(unsigned long i) const { return controls[i].val; }
float paramOut(unsigned long i) const { return controlsOut[i].val; }
@@ -500,8 +435,6 @@ class PluginI : public PluginIBase {
// chain of connected efx inserts
//---------------------------------------------------------
-//const int PipelineDepth = 4; // Moved to globaldefs.h
-
class Pipeline : public std::vector<PluginI*> {
float* buffer[MAX_CHANNELS];
@@ -525,8 +458,7 @@ class Pipeline : public std::vector<PluginI*> {
void deleteAllGuis();
bool guiVisible(int);
bool nativeGuiVisible(int);
- //void apply(int ports, unsigned long nframes, float** buffer);
- void apply(unsigned long ports, unsigned long nframes, float** buffer); // p4.0.21
+ void apply(unsigned long ports, unsigned long nframes, float** buffer);
void move(int idx, bool up);
bool empty(int idx) const;
void setChannels(int);
@@ -537,11 +469,6 @@ typedef Pipeline::const_iterator ciPluginI;
extern void initPlugins();
-//extern bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, int port, float* val);
-//extern void ladspaControlRange(const LADSPA_Descriptor* plugin, int i, float* min, float* max);
-//extern bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, int port, int ctlnum, int* min, int* max, int* def);
-//extern float midi2LadspaValue(const LADSPA_Descriptor* plugin, int port, int ctlnum, int val);
-// p4.0.21
extern bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, unsigned long port, float* val);
extern void ladspaControlRange(const LADSPA_Descriptor* plugin, unsigned long port, float* min, float* max);
extern bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, unsigned long port, int ctlnum, int* min, int* max, int* def);
@@ -593,8 +520,7 @@ struct GuiWidgets {
};
QWidget* widget;
int type;
- //int param;
- unsigned long param; // p4.0.21
+ unsigned long param;
};
//---------------------------------------------------------
@@ -604,13 +530,11 @@ struct GuiWidgets {
class PluginGui : public QMainWindow {
Q_OBJECT
- //PluginI* plugin; // plugin instance
MusECore::PluginIBase* plugin; // plugin instance
GuiParam* params;
GuiParam* paramsOut;
- //int nobj;
- unsigned long nobj; // number of widgets in gw // p4.0.21
+ unsigned long nobj; // number of widgets in gw
GuiWidgets* gw;
QAction* onOff;
@@ -640,7 +564,6 @@ class PluginGui : public QMainWindow {
void heartBeat();
public:
- //PluginGui(MusECore::PluginI*);
PluginGui(MusECore::PluginIBase*);
~PluginGui();
diff --git a/muse2/muse/remote/pyapi.cpp b/muse2/muse/remote/pyapi.cpp
index 645c639e..de8f15ef 100644
--- a/muse2/muse/remote/pyapi.cpp
+++ b/muse2/muse/remote/pyapi.cpp
@@ -1129,7 +1129,9 @@ bool Song::event(QEvent* _e)
break;
}
case QPybridgeEvent::SONG_ADD_TRACK:
- MusEGlobal::song->addTrack((Track::TrackType)e->getP1()); // Add at end of list.
+ MusECore::Undo operations;
+ MusEGlobal::song->addTrack(operations, (Track::TrackType)e->getP1()); // Add at end of list.
+ MusEGlobal::song->applyOperationGroup(operations);
break;
case QPybridgeEvent::SONG_CHANGE_TRACKNAME: {
Track* t = this->findTrack(e->getS1());
diff --git a/muse2/muse/route.cpp b/muse2/muse/route.cpp
index f00c6d6c..1d494fb0 100644
--- a/muse2/muse/route.cpp
+++ b/muse2/muse/route.cpp
@@ -4,6 +4,7 @@
// $Id: route.cpp,v 1.18.2.3 2008/05/21 00:28:52 terminator356 Exp $
//
// (C) Copyright 2003-2004 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -37,8 +38,6 @@
//#define ROUTE_DEBUG
-//#define ROUTE_MIDIPORT_NAME_PREFIX "MusE MidiPort "
-
namespace MusECore {
const QString ROUTE_MIDIPORT_NAME_PREFIX = "MusE MidiPort ";
@@ -57,9 +56,7 @@ Route::Route(void* t, int ch)
type = JACK_ROUTE;
}
-//Route::Route(AudioTrack* t, int ch)
Route::Route(Track* t, int ch, int chans)
-//Route::Route(Track* t, int ch)
{
track = t;
midiPort = -1;
@@ -69,7 +66,6 @@ Route::Route(Track* t, int ch, int chans)
type = TRACK_ROUTE;
}
-//Route::Route(MidiJackDevice* d)
Route::Route(MidiDevice* d, int ch)
{
device = d;
@@ -77,19 +73,10 @@ Route::Route(MidiDevice* d, int ch)
channel = ch;
channels = -1;
remoteChannel = -1;
- /*
- //if(dynamic_cast<MidiJackDevice*>(d))
- if(d->deviceType() == MidiDevice::JACK_MIDI)
- type = JACK_MIDI_ROUTE;
- else
- //if(dynamic_cast<MidiAlsaDevice*>(d))
- if(d->deviceType() == MidiDevice::ALSA_MIDI)
- type = ALSA_MIDI_ROUTE;
- */
type = MIDI_DEVICE_ROUTE;
}
-Route::Route(int port, int ch) // p3.3.49
+Route::Route(int port, int ch)
{
track = 0;
midiPort = port;
@@ -99,16 +86,12 @@ Route::Route(int port, int ch) // p3.3.49
type = MIDI_PORT_ROUTE;
}
-//Route::Route(const QString& s, bool dst, int ch)
Route::Route(const QString& s, bool dst, int ch, int rtype)
{
- //Route node(name2route(s, dst));
Route node(name2route(s, dst, rtype));
channel = node.channel;
if(channel == -1)
channel = ch;
- //if(channels == -1)
- // channels = chans;
channels = node.channels;
remoteChannel = node.remoteChannel;
type = node.type;
@@ -123,14 +106,6 @@ Route::Route(const QString& s, bool dst, int ch, int rtype)
jackPort = node.jackPort;
midiPort = -1;
}
- /*
- else
- if (type == JACK_MIDI_ROUTE)
- device = node.device;
- else
- if (type == ALSA_MIDI_ROUTE)
- device = node.device;
- */
else
if(type == MIDI_DEVICE_ROUTE)
{
@@ -138,10 +113,10 @@ Route::Route(const QString& s, bool dst, int ch, int rtype)
midiPort = -1;
}
else
- if(type == MIDI_PORT_ROUTE) // p3.3.49
+ if(type == MIDI_PORT_ROUTE)
{
track = 0;
- midiPort = node.midiPort; //
+ midiPort = node.midiPort;
}
}
@@ -179,31 +154,20 @@ void addRoute(Route src, Route dst)
// dst.type, dst.channel, dst.name().toLatin1().constData());
if (src.type == Route::JACK_ROUTE)
{
- //if (dst.type != TRACK_ROUTE)
- //{
- // fprintf(stderr, "addRoute: bad route 1\n");
- // exit(-1);
- // return;
- //}
-
if (dst.type == Route::TRACK_ROUTE)
{
if (dst.track->type() != Track::AUDIO_INPUT)
{
fprintf(stderr, "addRoute: source is jack, dest:%s is track but not audio input\n", dst.track->name().toLatin1().constData());
- //exit(-1);
return;
}
if (dst.channel < 0)
{
fprintf(stderr, "addRoute: source is jack, dest:%s is track but invalid channel:%d\n", dst.track->name().toLatin1().constData(), dst.channel);
- //exit(-1);
return;
}
- //src.channel = src.dstChannel = dst.channel;
src.channel = dst.channel;
- //src.channels = dst.channels = 1;
RouteList* inRoutes = dst.track->inRoutes();
for (ciRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
{
@@ -221,28 +185,11 @@ void addRoute(Route src, Route dst)
inRoutes->push_back(src);
}
else
- //if (dst.type == Route::JACK_MIDI_ROUTE)
if (dst.type == Route::MIDI_DEVICE_ROUTE)
- //if (dst.type == Route::MIDI_PORT_ROUTE) // p3.3.49
{
- //MidiDevice *md = MusEGlobal::midiPorts[dst.midiPort].device();
- //if(dst.device->deviceType() == MidiDevice::JACK_MIDI)
- //if(!md)
- //{
- // fprintf(stderr, "addRoute: source is Jack, but no destination port device\n");
- // return;
- //}
-
if(dst.device->deviceType() == MidiDevice::JACK_MIDI)
- //if(md->deviceType() == MidiDevice::JACK_MIDI)
{
src.channel = dst.channel;
- //src.channel = -1;
- //src.channel = 0;
- //src.channel = src.dstChannel = dst.channel;
- //src.channels = dst.channels = 1;
- //dst.channel = -1;
-
RouteList* routes = dst.device->inRoutes();
for (ciRoute i = routes->begin(); i != routes->end(); ++i)
{
@@ -262,45 +209,32 @@ void addRoute(Route src, Route dst)
else
{
fprintf(stderr, "addRoute: source is Jack, but destination is not jack midi - type:%d\n", dst.device->deviceType());
- // exit(-1);
return;
}
}
else
{
fprintf(stderr, "addRoute: source is Jack, but destination is not track or midi - type:%d \n", dst.type);
- // exit(-1);
return;
}
}
else if (dst.type == Route::JACK_ROUTE)
{
- //if (src.type != TRACK_ROUTE)
- //{
- // fprintf(stderr, "addRoute: bad route 3\n");
- // exit(-1);
- // return;
- //}
-
if (src.type == Route::TRACK_ROUTE)
{
if (src.track->type() != Track::AUDIO_OUTPUT)
{
fprintf(stderr, "addRoute: destination is jack, source is track but not audio output\n");
- // exit(-1);
return;
}
if (src.channel < 0)
{
fprintf(stderr, "addRoute: destination is jack, source:%s is track but invalid channel:%d\n", src.track->name().toLatin1().constData(), src.channel);
- // exit(-1);
return;
}
RouteList* outRoutes = src.track->outRoutes();
- //dst.channel = dst.dstChannel = src.channel;
dst.channel = src.channel;
- //dst.channels = src.channels = 1;
for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
{
@@ -318,17 +252,11 @@ void addRoute(Route src, Route dst)
outRoutes->push_back(dst);
}
else
- //if (src.type == Route::JACK_MIDI_ROUTE)
if (src.type == Route::MIDI_DEVICE_ROUTE)
{
if(src.device->deviceType() == MidiDevice::JACK_MIDI)
{
dst.channel = src.channel;
- //dst.channel = -1;
- //src.channel = -1;
- //dst.channel = dst.dstChannel = src.channel;
- //dst.channels = src.channels = 1;
-
RouteList* routes = src.device->outRoutes();
for (ciRoute i = routes->begin(); i != routes->end(); ++i)
{
@@ -348,18 +276,16 @@ void addRoute(Route src, Route dst)
else
{
fprintf(stderr, "addRoute: destination is Jack, but source is not jack midi - type:%d\n", src.device->deviceType());
- // exit(-1);
return;
}
}
else
{
fprintf(stderr, "addRoute: destination is Jack, but source is not track or midi - type:%d \n", src.type);
- // exit(-1);
return;
}
}
- else if(src.type == Route::MIDI_PORT_ROUTE) // p3.3.49
+ else if(src.type == Route::MIDI_PORT_ROUTE)
{
if(dst.type != Route::TRACK_ROUTE)
{
@@ -367,66 +293,18 @@ void addRoute(Route src, Route dst)
return;
}
- // p4.0.14
- /*
- if(dst.track->type() == Track::AUDIO_INPUT)
- {
- if(src.channel < 1 || src.channel >= (1 << MIDI_CHANNELS))
- {
- fprintf(stderr, "addRoute: source is midi port:%d, but channel mask:%d out of range\n", src.midiPort, src.channel);
- return;
- }
-
- MidiPort *mp = &MusEGlobal::midiPorts[src.midiPort];
- //src.channel = dst.channel = -1;
- RouteList* outRoutes = mp->outRoutes();
- iRoute ir = outRoutes->begin();
- for ( ; ir != outRoutes->end(); ++ir)
- {
- //if (*i == dst) // route already there
- ir->dump();
- if (ir->type == Route::TRACK_ROUTE && ir->track == dst.track) // Does a route to the track exist?
- {
- //#ifdef ROUTE_DEBUG
- fprintf(stderr, "addRoute: src midi port:%d dst audio in track:%s out route already exists. ir->channel:%d |= dst.channel:%d\n",
- src.midiPort, dst.track->name().toLatin1().constData(), ir->channel, dst.channel);
- //#endif
- ir->channel |= dst.channel; // Bitwise OR the desired channel bit with the existing bit mask.
- break;
- //return;
- }
- }
- if(ir == outRoutes->end()) // Only if route not found, add the route, with the requested channel bits as mask to start with.
- outRoutes->push_back(dst);
-
- RouteList* inRoutes = dst.track->inRoutes();
-
- ir = inRoutes->begin();
- for ( ; ir != inRoutes->end(); ++ir)
- {
- if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == src.midiPort) // Does a route to the midi port exist?
- {
- fprintf(stderr, "addRoute: src midi port:%d dst audio in track:%s in route already exists. ir->channel:%d |= src.channel:%d\n",
- src.midiPort, dst.track->name().toLatin1().constData(), ir->channel, src.channel);
- ir->channel |= src.channel; // Bitwise OR the desired channel bit with the existing bit mask.
- break;
- }
- }
- if(ir == inRoutes->end()) // Only if route not found, add the route, with the requested channel bits as mask to start with.
- inRoutes->push_back(src);
-
- return;
- }
- */
-
MidiPort *mp = &MusEGlobal::midiPorts[src.midiPort];
- // p4.0.17 Do not allow ports with synth midi devices to connect to audio ins!
- if(dst.track->type() == Track::AUDIO_INPUT && mp->device() && mp->device()->isSynti())
- {
- fprintf(stderr, "addRoute: destination is audio in, but source midi port:%d is synth device\n", src.midiPort);
+ // Do not allow ports with synth midi devices to connect to audio ins! p4.0.17
+ //if(dst.track->type() == Track::AUDIO_INPUT && mp->device() && mp->device()->isSynti())
+ //{
+ // fprintf(stderr, "addRoute: destination is audio in, but source midi port:%d is synth device\n", src.midiPort);
+ // return;
+ //}
+ // Actually, do not allow synth ports to connect to any track. It may be useful in some cases,
+ // may be desired later, but for now it's just a routing hassle. p4.0.35
+ if(mp->device() && mp->device()->isSynti())
return;
- }
if(dst.channel < 1 || dst.channel >= (1 << MIDI_CHANNELS))
{
@@ -443,46 +321,39 @@ void addRoute(Route src, Route dst)
src.channel = dst.channel;
RouteList* outRoutes = mp->outRoutes();
- //for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
- iRoute ir = outRoutes->begin(); // p3.3.50
+ iRoute ir = outRoutes->begin();
for ( ; ir != outRoutes->end(); ++ir)
{
- //if (*i == dst) // route already there
- if (ir->type == Route::TRACK_ROUTE && ir->track == dst.track) // p3.3.50 Does a route to the track exist?
+ if (ir->type == Route::TRACK_ROUTE && ir->track == dst.track) // Does a route to the track exist?
{
- //#ifdef ROUTE_DEBUG
- //fprintf(stderr, "addRoute: src midi port:%d dst track:%s route already exists.\n", src.midiPort, dst.track->name().toLatin1().constData());
- //#endif
- ir->channel |= dst.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
+ ir->channel |= dst.channel; // Bitwise OR the desired channel bit with the existing bit mask.
break;
-
- //return;
}
}
#ifdef ROUTE_DEBUG
fprintf(stderr, "addRoute: src midi port:%d dst track name:%s pushing dst and src routes\n", src.midiPort, dst.track->name().toLatin1().constData());
#endif
- if(ir == outRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
+ if(ir == outRoutes->end()) // Only if route not found, add the route, with the requested channel bits as mask to start with.
outRoutes->push_back(dst);
RouteList* inRoutes = dst.track->inRoutes();
- // p3.3.50 Make sure only one single route, with a channel mask, can ever exist.
+ // Make sure only one single route, with a channel mask, can ever exist.
ir = inRoutes->begin();
for ( ; ir != inRoutes->end(); ++ir)
{
- if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == src.midiPort) // p3.3.50 Does a route to the midi port exist?
+ if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == src.midiPort) // Does a route to the midi port exist?
{
- ir->channel |= src.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
+ ir->channel |= src.channel; // Bitwise OR the desired channel bit with the existing bit mask.
break;
}
}
- if(ir == inRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
+ if(ir == inRoutes->end()) // Only if route not found, add the route, with the requested channel bits as mask to start with.
inRoutes->push_back(src);
}
- else if(dst.type == Route::MIDI_PORT_ROUTE) // p3.3.49
+ else if(dst.type == Route::MIDI_PORT_ROUTE)
{
if(src.type != Route::TRACK_ROUTE)
{
@@ -495,7 +366,6 @@ void addRoute(Route src, Route dst)
return;
}
-
//MidiDevice *md = MusEGlobal::midiPorts[dst.midiPort].device();
//if(!md)
//{
@@ -506,24 +376,17 @@ void addRoute(Route src, Route dst)
dst.channel = src.channel;
RouteList* outRoutes = src.track->outRoutes();
- //for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
- iRoute ir = outRoutes->begin(); // p3.3.50
+ iRoute ir = outRoutes->begin();
for ( ; ir != outRoutes->end(); ++ir)
{
- //if (*i == dst) // route already there
- if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == dst.midiPort) // p3.3.50 Does a route to the midi port exist?
+ if (ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == dst.midiPort) // Does a route to the midi port exist?
{
- //#ifdef ROUTE_DEBUG
- //fprintf(stderr, "addRoute: dst midi port:%d src track:%s route already exists.\n", dst.midiPort, src.track->name().toLatin1().constData());
- //#endif
- //return;
-
- ir->channel |= dst.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
+ ir->channel |= dst.channel; // Bitwise OR the desired channel bit with the existing bit mask.
break;
}
}
- if(ir == outRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
+ if(ir == outRoutes->end()) // Only if route not found, add the route, with the requested channel bits as mask to start with.
outRoutes->push_back(dst);
MidiPort *mp = &MusEGlobal::midiPorts[dst.midiPort];
@@ -533,167 +396,97 @@ void addRoute(Route src, Route dst)
#endif
RouteList* inRoutes = mp->inRoutes();
- // p3.3.50 Make sure only one single route, with a channel mask, can ever exist.
+ // Make sure only one single route, with a channel mask, can ever exist.
ir = inRoutes->begin();
for ( ; ir != inRoutes->end(); ++ir)
{
- if (ir->type == Route::TRACK_ROUTE && ir->track == src.track) // p3.3.50 Does a route to the track exist?
+ if (ir->type == Route::TRACK_ROUTE && ir->track == src.track) // Does a route to the track exist?
{
- ir->channel |= src.channel; // p3.3.50 Bitwise OR the desired channel bit with the existing bit mask.
+ ir->channel |= src.channel; // Bitwise OR the desired channel bit with the existing bit mask.
break;
}
}
- if(ir == inRoutes->end()) // p3.3.50 Only if route not found, add the route, with the requested channel bits as mask to start with.
+ if(ir == inRoutes->end()) // Only if route not found, add the route, with the requested channel bits as mask to start with.
inRoutes->push_back(src);
- //inRoutes->insert(inRoutes->begin(), src);
}
else
{
- if(src.type != Route::TRACK_ROUTE || dst.type != Route::TRACK_ROUTE) // p3.3.49
+ if(src.type != Route::TRACK_ROUTE || dst.type != Route::TRACK_ROUTE)
{
fprintf(stderr, "addRoute: source or destination are not track routes\n");
return;
}
- // Removed p3.3.49
- /*
- //if ((src.type == Route::JACK_MIDI_ROUTE) || (src.type == Route::ALSA_MIDI_ROUTE))
- if(src.type == Route::MIDI_DEVICE_ROUTE)
- {
- //src.channel = src.dstChannel = dst.dstChannel = dst.channel;
- src.channel = dst.channel;
- //src.channels = dst.channels = 1;
- RouteList* outRoutes = src.device->outRoutes();
- #ifdef ROUTE_DEBUG
- fprintf(stderr, "addRoute: src name: %s looking for existing dest in out routes...\n", src.device->name().toLatin1().constData());
- #endif
- for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
- {
- if (*i == dst) // route already there
- {
- //#ifdef ROUTE_DEBUG
- fprintf(stderr, "addRoute: src Jack or ALSA midi route already exists.\n");
- //#endif
- return;
- }
- }
- #ifdef ROUTE_DEBUG
- fprintf(stderr, "addRoute: src midi dst name: %s pushing destination and source routes\n", dst.track->name().toLatin1().constData());
- #endif
-
- outRoutes->push_back(dst);
- RouteList* inRoutes = dst.track->inRoutes();
- inRoutes->push_back(src);
- }
- else
- */
+ RouteList* outRoutes = src.track->outRoutes();
- {
- ///if(dst.type == Route::MIDI_DEVICE_ROUTE) // Removed p3.3.49
- //{
- /// dst.channel = src.channel;
- //src.channel = src.dstChannel = dst.dstChannel = dst.channel;
- //src.channels = dst.channels = 1;
- //}
- //else
- //{
- //src.channel = src.dstChannel = dst.dstChannel = dst.channel;
- //src.channels = dst.channels = 1;
- //}
-
- RouteList* outRoutes = src.track->outRoutes();
-
- //
- // Must enforce to ensure channel and channels are valid if defaults of -1 passed.
- //
- if(src.track->type() == Track::AUDIO_SOFTSYNTH)
- {
- if(src.channel == -1)
- src.channel = 0;
- if(src.channels == -1)
- src.channels = src.track->channels();
- //if(dst.type == Route::TRACK_ROUTE) // p3.3.49 Removed
- //{
- //if(dst.channel == -1)
- // dst.channel = 0;
- //if(dst.channels == -1)
- // Yes, that's correct: dst channels = src track channels.
- // dst.channels = src.track->channels();
- dst.channel = src.channel;
- dst.channels = src.channels;
- dst.remoteChannel = src.remoteChannel;
- //}
- }
- //if(dst.type == Route::TRACK_ROUTE && dst.track->type() == Track::AUDIO_SOFTSYNTH)
- //{
- // if(dst.channel == -1)
- // dst.channel = 0;
- // if(dst.channels == -1)
- // Yes, that's correct: dst channels = src track channels.
- // dst.channels = src.track->channels();
- //}
-
- for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
- {
- if (*i == dst) // route already there
- // TODO:
- //if (i->type == dst.type && i->channel == dst.channel)
+ //
+ // Must enforce to ensure channel and channels are valid if defaults of -1 passed.
+ //
+ if(src.track->type() == Track::AUDIO_SOFTSYNTH)
+ {
+ if(src.channel == -1)
+ src.channel = 0;
+ if(src.channels == -1)
+ src.channels = src.track->channels();
+ dst.channel = src.channel;
+ dst.channels = src.channels;
+ dst.remoteChannel = src.remoteChannel;
+ }
+
+ for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
+ {
+ if (*i == dst) // route already there
+ // TODO:
+ //if (i->type == dst.type && i->channel == dst.channel)
+ {
+ //if(i->type == Route::TRACK_ROUTE)
+ {
+ //if(i->track == dst.track)
{
- //if(i->type == Route::TRACK_ROUTE)
+ //if(i->channels == dst.channels)
{
- //if(i->track == dst.track)
- {
- //if(i->channels == dst.channels)
- {
- //#ifdef ROUTE_DEBUG
- fprintf(stderr, "addRoute: src track route already exists.\n");
- //#endif
- return;
- }
- //else
- //{
-
- //}
- }
+ //#ifdef ROUTE_DEBUG
+ fprintf(stderr, "addRoute: src track route already exists.\n");
+ //#endif
+ return;
}
- }
- }
- outRoutes->push_back(dst);
- RouteList* inRoutes;
-
- // Removed p3.3.49
- /*
- //if ((dst.type == Route::JACK_MIDI_ROUTE) || (dst.type == Route::ALSA_MIDI_ROUTE))
- if(dst.type == Route::MIDI_DEVICE_ROUTE)
- {
- #ifdef ROUTE_DEBUG
- fprintf(stderr, "addRoute: src track dst midi name: %s pushing destination and source routes\n", dst.device->name().toLatin1().constData());
- #endif
- inRoutes = dst.device->inRoutes();
- }
- else
- */
-
- {
- #ifdef ROUTE_DEBUG
- //fprintf(stderr, "addRoute: src track ch:%d chs:%d dst track ch:%d chs:%d name: %s pushing destination and source routes\n", src.channel, src.channels, dst.channel, dst.channels, dst.track->name().toLatin1().constData());
- fprintf(stderr, "addRoute: src track ch:%d chs:%d remch:%d dst track ch:%d chs:%d remch:%d name: %s pushing dest and source routes\n",
- src.channel, src.channels, src.remoteChannel, dst.channel, dst.channels, dst.remoteChannel, dst.track->name().toLatin1().constData());
- //fprintf(stderr, "addRoute: src track ch:%d dst track ch:%d name: %s pushing destination and source routes\n", src.channel, dst.channel, dst.track->name().toLatin1().constData());
- #endif
- inRoutes = dst.track->inRoutes();
- }
-
-
- //
- // make sure AUDIO_AUX is processed last
- //
- if (src.track->type() == Track::AUDIO_AUX)
- inRoutes->push_back(src);
- else
- inRoutes->insert(inRoutes->begin(), src);
- }
+ //else
+ //{
+
+ //}
+ }
+ }
+ }
+ }
+ outRoutes->push_back(dst);
+ RouteList* inRoutes;
+
+ #ifdef ROUTE_DEBUG
+ //fprintf(stderr, "addRoute: src track ch:%d chs:%d dst track ch:%d chs:%d name: %s pushing destination and source routes\n", src.channel, src.channels, dst.channel, dst.channels, dst.track->name().toLatin1().constData());
+ fprintf(stderr, "addRoute: src track ch:%d chs:%d remch:%d dst track ch:%d chs:%d remch:%d name: %s pushing dest and source routes\n",
+ src.channel, src.channels, src.remoteChannel, dst.channel, dst.channels, dst.remoteChannel, dst.track->name().toLatin1().constData());
+ //fprintf(stderr, "addRoute: src track ch:%d dst track ch:%d name: %s pushing destination and source routes\n", src.channel, dst.channel, dst.track->name().toLatin1().constData());
+ #endif
+ inRoutes = dst.track->inRoutes();
+
+ //
+ // make sure AUDIO_AUX is processed last
+ //
+ if (src.track->type() == Track::AUDIO_AUX) // REMOVE Tim. This special aux code may not be useful or needed now.
+ inRoutes->push_back(src); //
+ else
+ inRoutes->insert(inRoutes->begin(), src);
+
+ // Is the source an Aux Track or else does it have Aux Tracks routed to it?
+ // Update the destination track's aux ref count, and all tracks it is routed to.
+ if(src.track->auxRefCount())
+ //dst.track->updateAuxStates( src.track->auxRefCount() );
+ src.track->updateAuxRoute( src.track->auxRefCount(), dst.track );
+ else
+ if(src.track->type() == Track::AUDIO_AUX)
+ //dst.track->updateAuxStates( 1 );
+ src.track->updateAuxRoute( 1, dst.track );
}
}
@@ -709,12 +502,6 @@ void removeRoute(Route src, Route dst)
if (src.type == Route::JACK_ROUTE)
{
- //if (dst.type != TRACK_ROUTE)
- //{
- // fprintf(stderr, "removeRoute: bad route 1\n");
- // exit(-1);
- // return;
- //}
if(!dst.isValid())
{
printf("removeRoute: source is jack, invalid destination\n");
@@ -726,7 +513,6 @@ void removeRoute(Route src, Route dst)
if (dst.track->type() != Track::AUDIO_INPUT)
{
fprintf(stderr, "removeRoute: source is jack, destination is track but not audio input\n");
- // exit(-1);
return;
}
RouteList* inRoutes = dst.track->inRoutes();
@@ -741,7 +527,6 @@ void removeRoute(Route src, Route dst)
}
}
else
- //if (dst.type == Route::JACK_MIDI_ROUTE)
if (dst.type == Route::MIDI_DEVICE_ROUTE)
{
RouteList* routes = dst.device->inRoutes();
@@ -758,18 +543,11 @@ void removeRoute(Route src, Route dst)
else
{
fprintf(stderr, "removeRoute: source is jack, destination unknown\n");
- // exit(-1);
return;
}
}
else if (dst.type == Route::JACK_ROUTE)
{
- //if (src.type != TRACK_ROUTE)
- //{
- // fprintf(stderr, "removeRoute: bad route 3\n");
- // exit(-1);
- // return;
- //}
if(!src.isValid())
{
printf("removeRoute: destination is jack, invalid source\n");
@@ -781,7 +559,6 @@ void removeRoute(Route src, Route dst)
if (src.track->type() != Track::AUDIO_OUTPUT)
{
fprintf(stderr, "removeRoute: destination is jack, source is track but not audio output\n");
- // exit(-1);
return;
}
RouteList* outRoutes = src.track->outRoutes();
@@ -795,7 +572,6 @@ void removeRoute(Route src, Route dst)
}
}
else
- //if (src.type == Route::JACK_MIDI_ROUTE)
if (src.type == Route::MIDI_DEVICE_ROUTE)
{
RouteList* routes = src.device->outRoutes();
@@ -811,11 +587,10 @@ void removeRoute(Route src, Route dst)
else
{
fprintf(stderr, "removeRoute: destination is jack, source unknown\n");
- // exit(-1);
return;
}
}
- else if(src.type == Route::MIDI_PORT_ROUTE) // p3.3.49
+ else if(src.type == Route::MIDI_PORT_ROUTE)
{
if(dst.type != Route::TRACK_ROUTE)
{
@@ -829,19 +604,18 @@ void removeRoute(Route src, Route dst)
RouteList* outRoutes = mp->outRoutes();
for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
{
- //if (*i == dst)
- if(i->type == Route::TRACK_ROUTE && i->track == dst.track) // p3.3.50 Is there a route to the track?
+ if(i->type == Route::TRACK_ROUTE && i->track == dst.track) // Is there a route to the track?
{
//printf("i->channel:%x dst.channel:%x\n", i->channel, dst.channel);
- i->channel &= ~dst.channel; // p3.3.50 Unset the desired channel bits.
+ i->channel &= ~dst.channel; // Unset the desired channel bits.
if(i->channel == 0) // Only if there are no channel bits set, erase the route.
{
//printf("erasing out route from midi port:%d\n", src.midiPort);
outRoutes->erase(i);
}
- break; // For safety, keep looking and remove any more found.
- // No, must break, else crash. There should only be one route anyway...
+ break; // For safety, keep looking and remove any more found.
+ // No, must break, else crash. There should only be one route anyway...
}
}
}
@@ -853,22 +627,21 @@ void removeRoute(Route src, Route dst)
RouteList* inRoutes = dst.track->inRoutes();
for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
{
- //if (*i == src)
- if (i->type == Route::MIDI_PORT_ROUTE && i->midiPort == src.midiPort) // p3.3.50 Is there a route to the midi port?
+ if (i->type == Route::MIDI_PORT_ROUTE && i->midiPort == src.midiPort) // Is there a route to the midi port?
{
- i->channel &= ~src.channel; // p3.3.50 Unset the desired channel bits.
+ i->channel &= ~src.channel; // Unset the desired channel bits.
if(i->channel == 0) // Only if there are no channel bits set, erase the route.
inRoutes->erase(i);
- break; // For safety, keep looking and remove any more found.
- // No, must break, else crash. There should only be one route anyway...
+ break; // For safety, keep looking and remove any more found.
+ // No, must break, else crash. There should only be one route anyway...
}
}
}
else
printf("removeRoute: source is midi port:%d but destination track invalid\n", src.midiPort);
}
- else if(dst.type == Route::MIDI_PORT_ROUTE) // p3.3.49
+ else if(dst.type == Route::MIDI_PORT_ROUTE)
{
if(src.type != Route::TRACK_ROUTE)
{
@@ -881,15 +654,14 @@ void removeRoute(Route src, Route dst)
RouteList* outRoutes = src.track->outRoutes();
for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
{
- //if (*i == dst)
- if (i->type == Route::MIDI_PORT_ROUTE && i->midiPort == dst.midiPort) // p3.3.50 Is there a route to the midi port?
+ if (i->type == Route::MIDI_PORT_ROUTE && i->midiPort == dst.midiPort) // Is there a route to the midi port?
{
- i->channel &= ~dst.channel; // p3.3.50 Unset the desired channel bits.
+ i->channel &= ~dst.channel; // Unset the desired channel bits.
if(i->channel == 0) // Only if there are no channel bits set, erase the route.
outRoutes->erase(i);
- break; // For safety, keep looking and remove any more found.
- // No, must break, else crash. There should only be one route anyway...
+ break; // For safety, keep looking and remove any more found.
+ // No, must break, else crash. There should only be one route anyway...
}
}
}
@@ -902,15 +674,14 @@ void removeRoute(Route src, Route dst)
RouteList* inRoutes = mp->inRoutes();
for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
{
- //if (*i == src)
- if (i->type == Route::TRACK_ROUTE && i->track == src.track) // p3.3.50 Is there a route to the track?
+ if (i->type == Route::TRACK_ROUTE && i->track == src.track) // Is there a route to the track?
{
- i->channel &= ~src.channel; // p3.3.50 Unset the desired channel bits.
+ i->channel &= ~src.channel; // Unset the desired channel bits.
if(i->channel == 0) // Only if there are no channel bits set, erase the route.
inRoutes->erase(i);
- break; // For safety, keep looking and remove any more found.
- // No, must break, else crash. There should only be one route anyway...
+ break; // For safety, keep looking and remove any more found.
+ // No, must break, else crash. There should only be one route anyway...
}
}
}
@@ -919,87 +690,54 @@ void removeRoute(Route src, Route dst)
}
else
{
- if(src.type != Route::TRACK_ROUTE || dst.type != Route::TRACK_ROUTE) // p3.3.49
+ if(src.type != Route::TRACK_ROUTE || dst.type != Route::TRACK_ROUTE)
{
fprintf(stderr, "removeRoute: source and destination are not tracks\n");
return;
}
- // Removed p3.3.49
- /*
- //if((src.type == Route::JACK_MIDI_ROUTE) || (src.type == Route::ALSA_MIDI_ROUTE))
- if(src.type == Route::MIDI_DEVICE_ROUTE)
+ // Is the source an Aux Track or else does it have Aux Tracks routed to it?
+ // Update the destination track's aux ref count, and all tracks it is routed to.
+ if(src.isValid() && dst.isValid())
{
- if(src.isValid())
- {
- RouteList* outRoutes = src.device->outRoutes();
- for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
- {
- if (*i == dst) {
- outRoutes->erase(i);
- break;
- }
- }
- }
+ if(src.track->auxRefCount())
+ //dst.track->updateAuxStates( -src.track->auxRefCount() );
+ src.track->updateAuxRoute( -src.track->auxRefCount(), dst.track );
else
- printf("removeRoute: source is midi but invalid\n");
-
- if(dst.isValid())
+ if(src.track->type() == Track::AUDIO_AUX)
+ //dst.track->updateAuxStates( -1 );
+ src.track->updateAuxRoute( -1, dst.track );
+ }
+
+ if(src.isValid())
+ {
+ RouteList* outRoutes = src.track->outRoutes();
+ for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
{
- RouteList* inRoutes = dst.track->inRoutes();
- for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
- {
- if (*i == src) {
- inRoutes->erase(i);
- break;
- }
- }
+ if (*i == dst) {
+ outRoutes->erase(i);
+ break;
+ }
}
- else
- printf("removeRoute: source is midi but destination invalid\n");
- }
+ }
else
- */
+ printf("removeRoute: source is track but invalid\n");
+ if(dst.isValid())
{
- if(src.isValid())
- {
- RouteList* outRoutes = src.track->outRoutes();
- for (iRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
- {
- if (*i == dst) {
- outRoutes->erase(i);
- break;
- }
- }
- }
- else
- printf("removeRoute: source is track but invalid\n");
+ RouteList* inRoutes;
- if(dst.isValid())
+ inRoutes = dst.track->inRoutes();
+ for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
{
- RouteList* inRoutes;
-
- //if ((dst.type == Route::JACK_MIDI_ROUTE) || (dst.type == Route::ALSA_MIDI_ROUTE))
- // Removed p3.3.49
- /*
- if (dst.type == Route::MIDI_DEVICE_ROUTE)
- inRoutes = dst.device->inRoutes();
- else
- */
-
- inRoutes = dst.track->inRoutes();
- for (iRoute i = inRoutes->begin(); i != inRoutes->end(); ++i)
- {
- if (*i == src) {
- inRoutes->erase(i);
- break;
- }
- }
- }
- else
- printf("removeRoute: source is track but destination invalid\n");
- }
+ if (*i == src) {
+ inRoutes->erase(i);
+ break;
+ }
+ }
+ }
+ else
+ printf("removeRoute: source is track but destination invalid\n");
}
}
@@ -1013,9 +751,19 @@ void removeRoute(Route src, Route dst)
// So far it only works with MidiDevice <-> Jack.
//---------------------------------------------------------
-// p3.3.55
void removeAllRoutes(Route src, Route dst)
{
+ // TODO: Is the source an Aux Track or else does it have Aux Tracks routed to it?
+ // Update the destination track's aux ref count, and all tracks it is routed to.
+ /* if(src.isValid() && dst.isValid())
+ {
+ if(src.track->auxRefCount())
+ dst.track->updateAuxStates( -src.track->auxRefCount() );
+ else
+ if(src.track->type() == Track::TrackType::AUDIO_AUX))
+ dst.track->updateAuxStates( -1 );
+ } */
+
if(src.isValid())
{
if(src.type == Route::MIDI_DEVICE_ROUTE)
@@ -1052,22 +800,11 @@ static QString track2name(const Track* n)
QString Route::name() const
{
- // p3.3.38 Removed
- /*
- QString s;
- if ((type == TRACK_ROUTE) && (channel != -1)) {
-// if (channel != -1) {
- QString c;
- c.setNum(channel+1);
- s = c + ":";
- }
- */
-
if(type == MIDI_DEVICE_ROUTE)
{
if(device)
{
- // p3.3.55 Removed for unified jack in/out devices, the actual port names are now different from device name.
+ // For unified jack in/out devices, the actual port names are now different from device name.
// Like this: device: "MyJackDevice1" -> inport: "MyJackDevice1_in" outport: "MyJackDevice1_out"
/*
if(device->deviceType() == MidiDevice::JACK_MIDI)
@@ -1075,8 +812,7 @@ QString Route::name() const
else
*/
- //if(device->deviceType() == MidiDevice::ALSA_MIDI)
- return device->name();
+ return device->name();
}
return QWidget::tr("None");
}
@@ -1084,16 +820,14 @@ QString Route::name() const
if(type == JACK_ROUTE)
{
if (!MusEGlobal::checkAudioDevice()) return "";
- //return s + MusEGlobal::audioDevice->portName(jackPort);
return MusEGlobal::audioDevice->portName(jackPort);
}
else
- if(type == MIDI_PORT_ROUTE) // p3.3.49
+ if(type == MIDI_PORT_ROUTE)
{
return ROUTE_MIDIPORT_NAME_PREFIX + QString().setNum(midiPort);
}
else
- //return s + track2name(track);
return track2name(track);
}
@@ -1106,7 +840,6 @@ Route name2route(const QString& rn, bool /*dst*/, int rtype)
{
// printf("name2route %s\n", rn.toLatin1().constData());
int channel = -1;
- //int channel = 0;
QString s(rn);
// Support old route style in med files. Obsolete.
if (rn[0].isNumber() && rn[1]==':')
@@ -1117,8 +850,6 @@ Route name2route(const QString& rn, bool /*dst*/, int rtype)
if(rtype == -1)
{
- //if(dst)
- //{
if(MusEGlobal::checkAudioDevice())
{
void* p = MusEGlobal::audioDevice->findPort(s.toLatin1().constData());
@@ -1149,7 +880,6 @@ Route name2route(const QString& rn, bool /*dst*/, int rtype)
return Route(*i, channel);
}
- // p3.3.49
if(s.left(ROUTE_MIDIPORT_NAME_PREFIX.length()) == ROUTE_MIDIPORT_NAME_PREFIX)
{
bool ok = false;
@@ -1160,8 +890,6 @@ Route name2route(const QString& rn, bool /*dst*/, int rtype)
}
else
{
- //if(dst)
- //{
if(rtype == Route::TRACK_ROUTE)
{
TrackList* tl = MusEGlobal::song->tracks();
@@ -1178,8 +906,6 @@ Route name2route(const QString& rn, bool /*dst*/, int rtype)
AudioTrack* track = (AudioTrack*)*i;
if(track->name() == s)
return Route(track, channel);
- //return Route(track, channel, 1);
- //return Route(track, channel, track->channels());
}
}
}
@@ -1191,7 +917,6 @@ Route name2route(const QString& rn, bool /*dst*/, int rtype)
for(iMidiDevice i = MusEGlobal::midiDevices.begin(); i != MusEGlobal::midiDevices.end(); ++i)
{
if((*i)->name() == s)
- //if (jmd->name() == rn)
return Route(*i, channel);
/*
@@ -1224,7 +949,7 @@ Route name2route(const QString& rn, bool /*dst*/, int rtype)
}
}
else
- if(rtype == Route::MIDI_PORT_ROUTE) // p3.3.49
+ if(rtype == Route::MIDI_PORT_ROUTE)
{
if(s.left(ROUTE_MIDIPORT_NAME_PREFIX.length()) == ROUTE_MIDIPORT_NAME_PREFIX)
{
@@ -1238,7 +963,6 @@ Route name2route(const QString& rn, bool /*dst*/, int rtype)
printf(" name2route: <%s> not found\n", rn.toLatin1().constData());
return Route((Track*) 0, channel);
- //return Route((Track*) 0, channel, 1);
}
//---------------------------------------------------------
@@ -1255,10 +979,6 @@ bool checkRoute(const QString& s, const QString& d)
return false;
if (src.type == Route::JACK_ROUTE)
{
- //if (dst.type != TRACK_ROUTE) {
- // return false;
- // }
-
if (dst.type == Route::TRACK_ROUTE)
{
if (dst.track->type() != Track::AUDIO_INPUT) {
@@ -1274,12 +994,9 @@ bool checkRoute(const QString& s, const QString& d)
}
}
else
- //if (dst.type == Route::JACK_MIDI_ROUTE)
if (dst.type == Route::MIDI_DEVICE_ROUTE)
{
- //src.channel = dst.channel;
src.channel = -1;
- //dst.channel = -1;
RouteList* routes = dst.device->inRoutes();
for (ciRoute i = routes->begin(); i != routes->end(); ++i)
{
@@ -1293,10 +1010,6 @@ bool checkRoute(const QString& s, const QString& d)
}
else if (dst.type == Route::JACK_ROUTE)
{
- //if (src.type != TRACK_ROUTE) {
- // return false;
- // }
-
if (src.type == Route::TRACK_ROUTE)
{
if (src.track->type() != Track::AUDIO_OUTPUT) {
@@ -1312,13 +1025,10 @@ bool checkRoute(const QString& s, const QString& d)
}
}
else
- //if (src.type == Route::JACK_MIDI_ROUTE)
if (src.type == Route::MIDI_DEVICE_ROUTE)
{
RouteList* routes = src.device->outRoutes();
- //dst.channel = src.channel;
dst.channel = -1;
- //src.channel = -1;
for (ciRoute i = routes->begin(); i != routes->end(); ++i)
{
if (*i == dst) { // route already there
@@ -1329,7 +1039,7 @@ bool checkRoute(const QString& s, const QString& d)
else
return false;
}
- else if (src.type == Route::MIDI_PORT_ROUTE) // p3.3.49
+ else if (src.type == Route::MIDI_PORT_ROUTE)
{
RouteList* outRoutes = MusEGlobal::midiPorts[src.midiPort].outRoutes();
for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
@@ -1339,13 +1049,11 @@ bool checkRoute(const QString& s, const QString& d)
}
}
}
- //else if (dst.type == Route::MIDI_PORT_ROUTE) // p3.3.49
+ //else if (dst.type == Route::MIDI_PORT_ROUTE)
//{
//}
else
{
- //RouteList* outRoutes = ((src.type == Route::JACK_MIDI_ROUTE) || (src.type == Route::ALSA_MIDI_ROUTE)) ?
- // src.device->outRoutes() : src.track->outRoutes();
RouteList* outRoutes = (src.type == Route::MIDI_DEVICE_ROUTE) ? src.device->outRoutes() : src.track->outRoutes();
for (ciRoute i = outRoutes->begin(); i != outRoutes->end(); ++i)
@@ -1366,7 +1074,7 @@ void Route::read(Xml& xml)
{
QString s;
int dtype = MidiDevice::ALSA_MIDI;
- int port = -1; // p3.3.49
+ int port = -1;
unsigned char rtype = Route::TRACK_ROUTE;
for (;;)
@@ -1397,7 +1105,7 @@ void Route::read(Xml& xml)
if(tag == "name")
s = xml.s2();
else
- if(tag == "mport") // p3.3.49
+ if(tag == "mport")
{
port = xml.s2().toInt();
rtype = Route::MIDI_PORT_ROUTE;
@@ -1409,7 +1117,7 @@ void Route::read(Xml& xml)
#ifdef ROUTE_DEBUG
printf("Route::read(): tag end type:%d channel:%d name:%s\n", rtype, channel, s.toLatin1().constData());
#endif
- if(rtype == MIDI_PORT_ROUTE) // p3.3.49
+ if(rtype == MIDI_PORT_ROUTE)
{
if(port >= 0 && port < MIDI_PORTS)
{
@@ -1462,7 +1170,6 @@ void Route::read(Xml& xml)
MidiDevice* md = *imd;
if(md->name() == s && md->deviceType() == dtype)
{
- // p3.3.45
// We found a device, but if it is not in use by the song (port is -1), ignore it.
// This prevents loading and propagation of bogus routes in the med file.
if(md->midiPort() == -1)
@@ -1509,7 +1216,7 @@ void Song::readRoute(Xml& xml)
case Xml::End:
return;
case Xml::TagStart:
- // p3.3.38 2010/02/03 Support old routes in med files. Now obsolete!
+ // 2010/02/03 Support old routes in med files. Now obsolete!
if (tag == "srcNode")
src = xml.parse1();
else if (tag == "dstNode")
@@ -1545,7 +1252,7 @@ void Song::readRoute(Xml& xml)
if(tag == "remch")
remch = xml.s2().toInt();
else
- if(tag == "channelMask") // p3.3.50 New channel mask for midi port-track routes.
+ if(tag == "channelMask") // New channel mask for midi port-track routes.
ch = xml.s2().toInt();
else
printf("Song::readRoute(): unknown attribute:%s\n", tag.toLatin1().constData());
@@ -1564,17 +1271,17 @@ void Song::readRoute(Xml& xml)
// Support new routes.
if(sroute.isValid() && droute.isValid())
{
- // p3.3.49 Support pre- 1.1-RC2 midi-device-to-track routes. Obsolete. Replaced with midi port routes.
+ // Support pre- 1.1-RC2 midi-device-to-track routes. Obsolete. Replaced with midi port routes.
if(sroute.type == Route::MIDI_DEVICE_ROUTE && droute.type == Route::TRACK_ROUTE)
{
if(sroute.device->midiPort() >= 0 && sroute.device->midiPort() < MIDI_PORTS
- && ch >= 0 && ch < MIDI_CHANNELS) // p3.3.50
+ && ch >= 0 && ch < MIDI_CHANNELS)
{
sroute.midiPort = sroute.device->midiPort();
sroute.device = 0;
sroute.type = Route::MIDI_PORT_ROUTE;
- sroute.channel = 1 << ch; // p3.3.50 Convert to new bit-wise channel mask.
+ sroute.channel = 1 << ch; // Convert to new bit-wise channel mask.
droute.channel = sroute.channel;
addRoute(sroute, droute);
@@ -1586,13 +1293,13 @@ void Song::readRoute(Xml& xml)
else if(sroute.type == Route::TRACK_ROUTE && droute.type == Route::MIDI_DEVICE_ROUTE)
{
if(droute.device->midiPort() >= 0 && droute.device->midiPort() < MIDI_PORTS
- && ch >= 0 && ch < MIDI_CHANNELS) // p3.3.50
+ && ch >= 0 && ch < MIDI_CHANNELS)
{
droute.midiPort = droute.device->midiPort();
droute.device = 0;
droute.type = Route::MIDI_PORT_ROUTE;
- droute.channel = 1 << ch; // p3.3.50 Convert to new bit-wise channel mask.
+ droute.channel = 1 << ch; // Convert to new bit-wise channel mask.
sroute.channel = droute.channel;
addRoute(sroute, droute);
@@ -1659,7 +1366,7 @@ void Route::dump() const
printf("Route dump: jack audio port <%s> channel %d\n", MusEGlobal::audioDevice->portName(jackPort).toLatin1().constData(), channel);
}
else
- if (type == MIDI_PORT_ROUTE) // p3.3.49
+ if (type == MIDI_PORT_ROUTE)
{
printf("Route dump: midi port <%d> channel mask %d\n", midiPort, channel);
}
@@ -1672,8 +1379,6 @@ void Route::dump() const
if(device->deviceType() == MidiDevice::JACK_MIDI)
{
if(MusEGlobal::checkAudioDevice())
- //printf("jack midi port device <%s> ", MusEGlobal::audioDevice->portName(device->clientPort()).toLatin1().constData());
- // p3.3.55
{
printf("jack midi device <%s> ", device->name().toLatin1().constData());
if(device->inClientPort())
@@ -1730,36 +1435,16 @@ bool Route::operator==(const Route& a) const
{
//if (!MusEGlobal::checkAudioDevice()) return false;
//return MusEGlobal::audioDevice->portName(jackPort) == MusEGlobal::audioDevice->portName(a.jackPort);
- // p3.3.55 Simplified.
- return jackPort == a.jackPort;
+ return jackPort == a.jackPort; // Simplified.
}
else
- if (type == MIDI_PORT_ROUTE) // p3.3.49
+ if (type == MIDI_PORT_ROUTE)
{
return midiPort == a.midiPort;
}
else
if (type == MIDI_DEVICE_ROUTE)
{
- // p3.3.55 Changed for unified jack in/out devices, the actual port names are now different from device name.
- // Like this: device: "MyJackDevice1" -> inport: "MyJackDevice1_in" outport: "MyJackDevice1_out"
- /*
- if(device && a.device && device->deviceType() == a.device->deviceType())
- {
- if(device->deviceType() == MidiDevice::JACK_MIDI)
- {
- if (!MusEGlobal::checkAudioDevice()) return false;
- return MusEGlobal::audioDevice->portName(device->clientPort()) == MusEGlobal::audioDevice->portName(a.device->clientPort());
- }
- else
- if(device->deviceType() == MidiDevice::ALSA_MIDI)
- // TODO: OK ??
- return device->clientPort() == a.device->clientPort() && (channel == a.channel);
- else
- if(device->deviceType() == MidiDevice::SYNTH_MIDI)
- return device->name() == a.device->name();
- }
- */
return device == a.device;
}
}
@@ -1767,4 +1452,56 @@ bool Route::operator==(const Route& a) const
return false;
}
+/*
+//---------------------------------------------------------
+// isCircularRoute
+// Recursive.
+// If dst is valid, start traversal from there, not from src.
+// Returns true if circular.
+//---------------------------------------------------------
+
+bool isCircularRoutePath(Track* src, Track* dst)
+{
+ //if(isMidiTrack() || _type == AUDIO_AUX)
+ //if(isMidiTrack())
+ // return;
+
+ bool rv = false;
+
+ if(dst)
+ {
+ src->setNodeTraversed(true);
+ rv = isCircularRoutePath(dst, NULL);
+ src->setNodeTraversed(false);
+ //if(rv)
+ // fprintf(stderr, " Circular route %s -> %s\n", src->name().toLatin1().constData(), dst->name().toLatin1().constData());
+ return rv;
+ }
+
+ if(src->nodeTraversed())
+ return true;
+
+ src->setNodeTraversed(true);
+
+ //printf("isCircularRoute %s\n", src->name().toLatin1().constData());
+
+ RouteList* orl = src->outRoutes();
+ for (iRoute i = orl->begin(); i != orl->end(); ++i)
+ {
+ if( !(*i).isValid() || (*i).type != Route::TRACK_ROUTE )
+ continue;
+ Track* t = (*i).track;
+ //if(t->isMidiTrack())
+ // continue;
+ rv = isCircularRoutePath(src, NULL);
+ if(rv)
+ break;
+ }
+
+ src->setNodeTraversed(false);
+ return rv;
+}
+*/
+
+
} // namespace MusECore
diff --git a/muse2/muse/route.h b/muse2/muse/route.h
index 36b00d47..587369bc 100644
--- a/muse2/muse/route.h
+++ b/muse2/muse/route.h
@@ -4,6 +4,7 @@
// $Id: route.h,v 1.5.2.1 2008/05/21 00:28:52 terminator356 Exp $
//
// (C) Copyright 2001 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -43,17 +44,15 @@ class Xml;
//---------------------------------------------------------
struct Route {
- enum { TRACK_ROUTE=0, JACK_ROUTE=1, MIDI_DEVICE_ROUTE=2, MIDI_PORT_ROUTE=3 }; // p3.3.49
+ enum { TRACK_ROUTE=0, JACK_ROUTE=1, MIDI_DEVICE_ROUTE=2, MIDI_PORT_ROUTE=3 };
union {
- //AudioTrack* track;
Track* track;
- //MidiJackDevice* device;
MidiDevice* device;
void* jackPort;
};
- int midiPort; // p3.3.49 Midi port number. Best not to put this in the union to avoid problems?
+ int midiPort; // Midi port number. Best not to put this in the union to avoid problems?
//snd_seq_addr_t alsaAdr;
@@ -75,7 +74,7 @@ struct Route {
Route(void* t, int ch=-1);
Route(Track* t, int ch = -1, int chans = -1);
Route(MidiDevice* d, int ch);
- Route(int port, int ch); // p3.3.49
+ Route(int port, int ch);
Route(const QString&, bool dst, int ch, int rtype = -1);
Route();
@@ -84,7 +83,7 @@ struct Route {
bool isValid() const {
return ((type == TRACK_ROUTE) && (track != 0)) || ((type == JACK_ROUTE) && (jackPort != 0)) ||
((type == MIDI_DEVICE_ROUTE) && (device != 0)) ||
- ((type == MIDI_PORT_ROUTE) && (midiPort >= 0) && (midiPort < MIDI_PORTS)); // p3.3.49
+ ((type == MIDI_PORT_ROUTE) && (midiPort >= 0) && (midiPort < MIDI_PORTS));
}
void read(Xml& xml);
void dump() const;
@@ -106,6 +105,7 @@ extern void removeRoute(Route, Route);
extern void removeAllRoutes(Route, Route); // p3.3.55
extern Route name2route(const QString&, bool dst, int rtype = -1);
extern bool checkRoute(const QString&, const QString&);
+//extern bool isCircularRoutePath(Track* src, Track* dst); // Recursive.
//---------------------------------------------------------
// RouteMenuMap
diff --git a/muse2/muse/shortcuts.cpp b/muse2/muse/shortcuts.cpp
index 132eef97..cefb198e 100644
--- a/muse2/muse/shortcuts.cpp
+++ b/muse2/muse/shortcuts.cpp
@@ -66,7 +66,7 @@ void initShortCuts()
defShrt(SHRT_COPY, Qt::CTRL + Qt::Key_C, QT_TRANSLATE_NOOP("shortcuts", "Edit: Copy"), INVIS_SHRT, "copy");
defShrt(SHRT_COPY_RANGE, Qt::CTRL + Qt::SHIFT + Qt::Key_C, QT_TRANSLATE_NOOP("shortcuts", "Edit: Copy in range"), GLOBAL_SHRT, "copy_range");
defShrt(SHRT_UNDO, Qt::CTRL + Qt::Key_Z, QT_TRANSLATE_NOOP("shortcuts", "Edit: Undo"), INVIS_SHRT, "undo");
- defShrt(SHRT_REDO, Qt::CTRL + Qt::Key_Y, QT_TRANSLATE_NOOP("shortcuts", "Edit: Redo"), INVIS_SHRT, "redo");
+ defShrt(SHRT_REDO, Qt::CTRL + Qt::SHIFT + Qt::Key_Z, QT_TRANSLATE_NOOP("shortcuts", "Edit: Redo"), INVIS_SHRT, "redo");
defShrt(SHRT_CUT, Qt::CTRL + Qt::Key_X, QT_TRANSLATE_NOOP("shortcuts", "Edit: Cut"), INVIS_SHRT, "cut");
defShrt(SHRT_PASTE, Qt::CTRL + Qt::Key_V, QT_TRANSLATE_NOOP("shortcuts", "Edit: Paste"), INVIS_SHRT, "paste");
defShrt(SHRT_PASTE_DIALOG, Qt::CTRL + Qt::SHIFT + Qt::Key_V, QT_TRANSLATE_NOOP("shortcuts", "Edit: Paste (with dialog)"), GLOBAL_SHRT, "paste_dialog");
diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp
index 70314035..36be50a0 100644
--- a/muse2/muse/song.cpp
+++ b/muse2/muse/song.cpp
@@ -156,6 +156,7 @@ void Song::setSig(const AL::TimeSignature& sig)
Track* Song::addNewTrack(QAction* action, Track* insertAt)
{
+printf("Song::addNewTrack\n");
int n = action->data().toInt();
// Ignore negative numbers since this slot could be called by a menu or list etc. passing -1.
if(n < 0)
@@ -165,13 +166,20 @@ Track* Song::addNewTrack(QAction* action, Track* insertAt)
if(n >= MENU_ADD_SYNTH_ID_BASE)
{
n -= MENU_ADD_SYNTH_ID_BASE;
+ int ntype = n / MENU_ADD_SYNTH_ID_BASE;
+ if(ntype >= Synth::SYNTH_TYPE_END)
+ return 0;
+
+ n %= MENU_ADD_SYNTH_ID_BASE;
if(n >= (int)MusEGlobal::synthis.size())
return 0;
- SynthI* si = createSynthI(MusEGlobal::synthis[n]->baseName(), MusEGlobal::synthis[n]->name(), insertAt);
+ //printf("Song::addNewTrack synth: type:%d idx:%d class:%s label:%s\n", ntype, n, MusEGlobal::synthis[n]->baseName().toLatin1().constData(), MusEGlobal::synthis[n]->name().toLatin1().constData());
+ SynthI* si = createSynthI(MusEGlobal::synthis[n]->baseName(), MusEGlobal::synthis[n]->name(), (Synth::Type)ntype, insertAt);
if(!si)
return 0;
-
+ if (MusEGlobal::config.unhideTracks) SynthI::setVisible(true);
+
// Add instance last in midi device list.
for (int i = 0; i < MIDI_PORTS; ++i)
{
@@ -181,15 +189,19 @@ Track* Song::addNewTrack(QAction* action, Track* insertAt)
{
MusEGlobal::midiSeq->msgSetMidiDevice(port, si);
MusEGlobal::muse->changeConfig(true); // save configuration file
- deselectTracks();
- si->setSelected(true);
- update();
+ if (SynthI::visible()) {
+ deselectTracks();
+ si->setSelected(true);
+ update();
+ }
return si;
}
}
- deselectTracks();
- si->setSelected(true);
- update(SC_SELECTION);
+ if (SynthI::visible()) {
+ deselectTracks();
+ si->setSelected(true);
+ update(SC_SELECTION);
+ }
return si;
}
// Normal track.
@@ -200,10 +212,14 @@ Track* Song::addNewTrack(QAction* action, Track* insertAt)
if((Track::TrackType)n >= Track::AUDIO_SOFTSYNTH)
return 0;
- Track* t = addTrack((Track::TrackType)n, insertAt);
- deselectTracks();
- t->setSelected(true);
- update(SC_SELECTION);
+ Undo operations;
+ Track* t = addTrack(operations, (Track::TrackType)n, insertAt);
+ applyOperationGroup(operations);
+ if (t->isVisible()) {
+ deselectTracks();
+ t->setSelected(true);
+ update(SC_SELECTION);
+ }
return t;
}
}
@@ -216,53 +232,63 @@ Track* Song::addNewTrack(QAction* action, Track* insertAt)
// If insertAt is valid, inserts before insertAt. Else at the end after all tracks.
//---------------------------------------------------------
-Track* Song::addTrack(Track::TrackType type, Track* insertAt)
+Track* Song::addTrack(Undo& operations, Track::TrackType type, Track* insertAt)
{
+ printf("Song::addTrack\n");
Track* track = 0;
int lastAuxIdx = _auxs.size();
switch(type) {
case Track::MIDI:
track = new MidiTrack();
track->setType(Track::MIDI);
+ if (MusEGlobal::config.unhideTracks) MidiTrack::setVisible(true);
break;
case Track::DRUM:
track = new MidiTrack();
track->setType(Track::DRUM);
((MidiTrack*)track)->setOutChannel(9);
+ if (MusEGlobal::config.unhideTracks) MidiTrack::setVisible(true);
break;
case Track::WAVE:
track = new MusECore::WaveTrack();
((AudioTrack*)track)->addAuxSend(lastAuxIdx);
+ if (MusEGlobal::config.unhideTracks) WaveTrack::setVisible(true);
break;
case Track::AUDIO_OUTPUT:
track = new AudioOutput();
+ if (MusEGlobal::config.unhideTracks) AudioOutput::setVisible(true);
break;
case Track::AUDIO_GROUP:
track = new AudioGroup();
((AudioTrack*)track)->addAuxSend(lastAuxIdx);
+ if (MusEGlobal::config.unhideTracks) AudioGroup::setVisible(true);
break;
case Track::AUDIO_AUX:
track = new AudioAux();
+ if (MusEGlobal::config.unhideTracks) AudioAux::setVisible(true);
break;
case Track::AUDIO_INPUT:
track = new AudioInput();
((AudioTrack*)track)->addAuxSend(lastAuxIdx);
+ if (MusEGlobal::config.unhideTracks) AudioInput::setVisible(true);
break;
case Track::AUDIO_SOFTSYNTH:
printf("not implemented: Song::addTrack(SOFTSYNTH)\n");
// ((AudioTrack*)track)->addAuxSend(lastAuxIdx);
break;
default:
- printf("Song::addTrack() illegal type %d\n", type);
- abort();
+ printf("THIS SHOULD NEVER HAPPEN: Song::addTrack() illegal type %d. returning NULL.\n"
+ "save your work if you can and expect soon crashes!\n", type);
+ return NULL;
}
track->setDefaultName();
int idx = insertAt ? _tracks.index(insertAt) : -1;
- insertTrack1(track, idx);
- msgInsertTrack(track, idx, true);
- insertTrack3(track, idx);
+ // insertTrack1(track, idx); // this and the below are replaced
+ // msgInsertTrack(track, idx, true); // by the UndoOp-operation
+ // insertTrack3(track, idx); // does nothing
+ operations.push_back(UndoOp(UndoOp::AddTrack, idx, track));
// Add default track <-> midiport routes.
if(track->isMidiTrack())
@@ -1928,7 +1954,7 @@ void Song::panic()
// If clear_all is false, it will not touch things like midi ports.
//---------------------------------------------------------
-void Song::clear(bool signal, bool /*clear_all*/)
+void Song::clear(bool signal, bool clear_all)
{
if(MusEGlobal::debugMsg)
printf("Song::clear\n");
@@ -1953,7 +1979,7 @@ void Song::clear(bool signal, bool /*clear_all*/)
// p3.3.50 Reset this.
MusEGlobal::midiPorts[i].setFoundInSongFile(false);
- //if(clear_all) // Allow not touching devices. p4.0.17 TESTING: Maybe some problems...
+ if(clear_all) // Allow not touching devices. p4.0.17 TESTING: Maybe some problems...
// This will also close the device.
MusEGlobal::midiPorts[i].setMidiDevice(0);
}
@@ -1972,7 +1998,7 @@ void Song::clear(bool signal, bool /*clear_all*/)
//if((*imd)->deviceType() == MidiDevice::JACK_MIDI)
if(dynamic_cast< MidiJackDevice* >(*imd))
{
- //if(clear_all) // Allow not touching devices. p4.0.17 TESTING: Maybe some problems...
+ if(clear_all) // Allow not touching devices. p4.0.17 TESTING: Maybe some problems...
{
// Remove the device from the list.
MusEGlobal::midiDevices.erase(imd);
@@ -2919,7 +2945,6 @@ void Song::insertTrack2(Track* track, int idx)
break;
default:
fprintf(stderr, "unknown track type %d\n", track->type());
- // abort();
return;
}
@@ -2936,7 +2961,7 @@ void Song::insertTrack2(Track* track, int idx)
for (iTrack i = _tracks.begin(); i != _tracks.end(); ++i) {
if ((*i)->isMidiTrack())
continue;
- MusECore::WaveTrack* wt = (MusECore::WaveTrack*)*i;
+ MusECore::AudioTrack* wt = (MusECore::AudioTrack*)*i;
if (wt->hasAuxSend()) {
wt->addAuxSend(n);
}
@@ -2957,6 +2982,13 @@ void Song::insertTrack2(Track* track, int idx)
Route src(track, r->channel, r->channels);
src.remoteChannel = r->remoteChannel;
r->track->outRoutes()->push_back(src);
+ // Is the source an Aux Track or else does it have Aux Tracks routed to it?
+ // Update the Audio Output track's aux ref count. p4.0.37
+ if(r->track->auxRefCount())
+ track->updateAuxRoute( r->track->auxRefCount(), NULL );
+ else
+ if(r->track->type() == Track::AUDIO_AUX)
+ track->updateAuxRoute( 1, NULL );
}
}
else if (track->type() == Track::AUDIO_INPUT)
@@ -2970,6 +3002,13 @@ void Song::insertTrack2(Track* track, int idx)
Route src(track, r->channel, r->channels);
src.remoteChannel = r->remoteChannel;
r->track->inRoutes()->push_back(src);
+ // Is this track an Aux Track or else does it have Aux Tracks routed to it?
+ // Update the other track's aux ref count and all tracks it is connected to. p4.0.37
+ if(track->auxRefCount())
+ r->track->updateAuxRoute( track->auxRefCount(), NULL );
+ else
+ if(track->type() == Track::AUDIO_AUX)
+ r->track->updateAuxRoute( 1, NULL );
}
}
else if (track->isMidiTrack()) // p3.3.50
@@ -3000,6 +3039,13 @@ void Song::insertTrack2(Track* track, int idx)
Route src(track, r->channel, r->channels);
src.remoteChannel = r->remoteChannel;
r->track->outRoutes()->push_back(src);
+ // Is the source an Aux Track or else does it have Aux Tracks routed to it?
+ // Update this track's aux ref count. p4.0.37
+ if(r->track->auxRefCount())
+ track->updateAuxRoute( r->track->auxRefCount(), NULL );
+ else
+ if(r->track->type() == Track::AUDIO_AUX)
+ track->updateAuxRoute( 1, NULL );
}
rl = track->outRoutes();
for (ciRoute r = rl->begin(); r != rl->end(); ++r)
@@ -3010,6 +3056,13 @@ void Song::insertTrack2(Track* track, int idx)
Route src(track, r->channel, r->channels);
src.remoteChannel = r->remoteChannel;
r->track->inRoutes()->push_back(src);
+ // Is this track an Aux Track or else does it have Aux Tracks routed to it?
+ // Update the other track's aux ref count and all tracks it is connected to. p4.0.37
+ if(track->auxRefCount())
+ r->track->updateAuxRoute( track->auxRefCount(), NULL );
+ else
+ if(track->type() == Track::AUDIO_AUX)
+ r->track->updateAuxRoute( 1, NULL );
}
}
@@ -3022,18 +3075,9 @@ void Song::insertTrack2(Track* track, int idx)
// non realtime part of insertTrack
//---------------------------------------------------------
+// empty. gets executed after the realtime part
void Song::insertTrack3(Track* /*track*/, int /*idx*/)//prevent compiler warning: unused parameter
{
- //printf("Song::insertTrack3\n");
-
- /*
- switch(track->type()) {
- case Track::AUDIO_SOFTSYNTH:
- break;
- default:
- break;
- }
- */
}
//---------------------------------------------------------
@@ -3153,6 +3197,13 @@ void Song::removeTrack2(Track* track)
Route src(track, r->channel, r->channels);
src.remoteChannel = r->remoteChannel;
r->track->outRoutes()->removeRoute(src);
+ // Is the source an Aux Track or else does it have Aux Tracks routed to it?
+ // Update the Audio Output track's aux ref count. p4.0.37
+ if(r->track->auxRefCount())
+ track->updateAuxRoute( -r->track->auxRefCount(), NULL );
+ else
+ if(r->track->type() == Track::AUDIO_AUX)
+ track->updateAuxRoute( -1, NULL );
}
}
else if (track->type() == Track::AUDIO_INPUT)
@@ -3167,6 +3218,13 @@ void Song::removeTrack2(Track* track)
Route src(track, r->channel, r->channels);
src.remoteChannel = r->remoteChannel;
r->track->inRoutes()->removeRoute(src);
+ // Is this track an Aux Track or else does it have Aux Tracks routed to it?
+ // Update the other track's aux ref count and all tracks it is connected to. p4.0.37
+ if(track->auxRefCount())
+ r->track->updateAuxRoute( -track->auxRefCount(), NULL );
+ else
+ if(track->type() == Track::AUDIO_AUX)
+ r->track->updateAuxRoute( -1, NULL );
}
}
else if (track->isMidiTrack()) // p3.3.50
@@ -3198,6 +3256,13 @@ void Song::removeTrack2(Track* track)
Route src(track, r->channel, r->channels);
src.remoteChannel = r->remoteChannel;
r->track->outRoutes()->removeRoute(src);
+ // Is the source an Aux Track or else does it have Aux Tracks routed to it?
+ // Update this track's aux ref count. p4.0.37
+ if(r->track->auxRefCount())
+ track->updateAuxRoute( -r->track->auxRefCount(), NULL );
+ else
+ if(r->track->type() == Track::AUDIO_AUX)
+ track->updateAuxRoute( -1, NULL );
}
rl = track->outRoutes();
for (ciRoute r = rl->begin(); r != rl->end(); ++r)
@@ -3209,6 +3274,13 @@ void Song::removeTrack2(Track* track)
Route src(track, r->channel, r->channels);
src.remoteChannel = r->remoteChannel;
r->track->inRoutes()->removeRoute(src);
+ // Is this track an Aux Track or else does it have Aux Tracks routed to it?
+ // Update the other track's aux ref count and all tracks it is connected to. p4.0.37
+ if(track->auxRefCount())
+ r->track->updateAuxRoute( -track->auxRefCount(), NULL );
+ else
+ if(track->type() == Track::AUDIO_AUX)
+ r->track->updateAuxRoute( -1, NULL );
}
}
@@ -3219,21 +3291,10 @@ void Song::removeTrack2(Track* track)
// non realtime part of removeTrack
//---------------------------------------------------------
+//empty. gets executed after the realtime part
void Song::removeTrack3(Track* /*track*/)//prevent of compiler warning: unused parameter
- {
- /*
- switch(track->type()) {
- case Track::AUDIO_SOFTSYNTH:
- {
- SynthI* s = (SynthI*) track;
- s->deactivate3();
- }
- break;
- default:
- break;
- }
- */
- }
+{
+}
//---------------------------------------------------------
// executeScript
diff --git a/muse2/muse/song.h b/muse2/muse/song.h
index 7bbd831d..2c07396c 100644
--- a/muse2/muse/song.h
+++ b/muse2/muse/song.h
@@ -37,6 +37,7 @@
#include "al/sig.h"
#include "undo.h"
#include "track.h"
+#include "synth.h"
class QAction;
class QFont;
@@ -362,7 +363,7 @@ class Song : public QObject {
// Configuration
//-----------------------------------------
- SynthI* createSynthI(const QString& sclass, const QString& label = QString(), Track* insertAt = 0);
+ SynthI* createSynthI(const QString& sclass, const QString& label = QString(), Synth::Type type = Synth::SYNTH_TYPE_END, Track* insertAt = 0);
void rescanAlsaPorts();
@@ -410,7 +411,7 @@ class Song : public QObject {
void setQuantize(bool val);
void panic();
void seqSignal(int fd);
- Track* addTrack(Track::TrackType type, Track* insertAt = 0);
+ Track* addTrack(Undo& operations, Track::TrackType type, Track* insertAt = 0);
Track* addNewTrack(QAction* action, Track* insertAt = 0);
QString getScriptPath(int id, bool delivered);
void populateScriptMenu(QMenu* menuPlugins, QObject* receiver);
diff --git a/muse2/muse/songfile.cpp b/muse2/muse/songfile.cpp
index 9adfd406..9a3c11f5 100644
--- a/muse2/muse/songfile.cpp
+++ b/muse2/muse/songfile.cpp
@@ -1325,13 +1325,19 @@ void MusE::readToplevels(MusECore::Xml& xml)
}
else if (tag == "marker") {
showMarker(true);
- if (toplevels.back()->type()==MusEGui::TopWin::MARKER)
- toplevels.back()->readStatus(xml);
+ TopWin* tw = toplevels.findType(TopWin::MARKER);
+ if(!tw)
+ xml.skip("marker");
+ else
+ tw->readStatus(xml);
}
else if (tag == "arrangerview") {
showArranger(true);
- if (toplevels.back()->type()==MusEGui::TopWin::ARRANGER)
- toplevels.back()->readStatus(xml);
+ TopWin* tw = toplevels.findType(TopWin::ARRANGER);
+ if(!tw)
+ xml.skip("arrangerview");
+ else
+ tw->readStatus(xml);
}
else if (tag == "waveedit") {
if(!pl->empty())
@@ -1343,8 +1349,11 @@ void MusE::readToplevels(MusECore::Xml& xml)
}
else if (tag == "cliplist") {
startClipList(true);
- if (toplevels.back()->type()==MusEGui::TopWin::CLIPLIST)
- toplevels.back()->readStatus(xml);
+ TopWin* tw = toplevels.findType(TopWin::CLIPLIST);
+ if(!tw)
+ xml.skip("cliplist");
+ else
+ tw->readStatus(xml);
}
else
xml.unknown("MusE");
@@ -1506,9 +1515,34 @@ void MusE::read(MusECore::Xml& xml, bool skipConfig, bool isTemplate)
else if (tag == "configuration")
if (skipConfig)
//xml.skip(tag);
- readConfiguration(xml,true /* only read sequencer settings */, false /* do NOT read global settings */);
+ readConfiguration(xml,true /* only read sequencer settings */, false /* do NOT read global settings, see below */);
+ // see even more below!
else
- readConfiguration(xml, false, false /* do NOT read global settings */);
+ readConfiguration(xml, false, false /* do NOT read global settings, see below */);
+ /* Explanation for why "do NOT read global settings":
+ * if you would use true here, then muse would overwrite certain global config stuff
+ * by the settings stored in the song. but you don't want this. imagine that you
+ * send a friend a .med file. your friend opens it and baaam, his configuration is
+ * garbled. why? well, because these readConfigurations here would have overwritten
+ * parts (but not all) of his global config (like MDI/SDI, toolbar states etc.)
+ * with the data stored in the song. (it IS stored there. dunny why, i find it pretty
+ * senseless.)
+ *
+ * If you've a problem which seems to be solved by replacing "false" with "true", i've
+ * a better solution for you: go into conf.cpp, in void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig)
+ * (around line 525), look for a comment like this:
+ * "Global and/or per-song config stuff ends here" (alternatively just search for
+ * "----"). Your problem is probably that some non-global setting should be loaded but
+ * is not. Fix it by either placing the else if (foo)... clause responsible for that
+ * setting to be loaded into the first part, that is, before "else if (!doReadGlobalConfig)"
+ * or (if the settings actually IS global and not per-song), ensure that the routine
+ * which writes the global (and not the song-)configuration really writes that setting.
+ * (it might happen that it formerly worked because it was written to the song instead
+ * of the global config by mistake, and now isn't loaded anymore. write it to the
+ * correct location.)
+ *
+ * -- flo93
+ */
else if (tag == "song")
{
MusEGlobal::song->read(xml, isTemplate);
diff --git a/muse2/muse/structure.cpp b/muse2/muse/structure.cpp
index 90d02908..70b19540 100644
--- a/muse2/muse/structure.cpp
+++ b/muse2/muse/structure.cpp
@@ -137,7 +137,7 @@ void adjustGlobalLists(Undo& operations, int startPos, int diff)
// - cut master track
//---------------------------------------------------------
-void globalCut()
+void globalCut(bool onlySelectedTracks)
{
int lpos = MusEGlobal::song->lpos();
int rpos = MusEGlobal::song->rpos();
@@ -146,17 +146,11 @@ void globalCut()
Undo operations;
TrackList* tracks = MusEGlobal::song->tracks();
- bool at_least_one_selected=false;
-
- for (iTrack it = tracks->begin(); it != tracks->end(); ++it)
- if ( (*it)->selected() ) {
- at_least_one_selected=true;
- break;
- }
for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
- MidiTrack* track = dynamic_cast<MidiTrack*>(*it);
- if (track == 0 || (at_least_one_selected && !track->selected()))
+ //MidiTrack* track = dynamic_cast<MidiTrack*>(*it);
+ Track* track = *it;
+ if (track == 0 || (onlySelectedTracks && !track->selected()))
continue;
PartList* pl = track->parts();
for (iPart p = pl->begin(); p != pl->end(); ++p) {
@@ -169,63 +163,61 @@ void globalCut()
operations.push_back(UndoOp(UndoOp::DeletePart,part));
}
else if ((t < lpos) && ((t+l) > lpos) && ((t+l) <= rpos)) {
- // remove part tail
- int len = lpos - t;
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
- nPart->setLenTick(len);
- //
- // cut Events in nPart
- EventList* el = nPart->events();
- for (iEvent ie = el->lower_bound(len); ie != el->end(); ++ie)
- operations.push_back(UndoOp(UndoOp::DeleteEvent,ie->second, nPart, false, false));
-
- operations.push_back(UndoOp(UndoOp::ModifyPart,part, nPart, true, true));
- }
+ // remove part tail
+ int len = lpos - t;
+ Part *nPart;
+ if (track->isMidiTrack())
+ nPart = new MidiPart(*(MidiPart*)part);
+ else
+ nPart = new WavePart(*(WavePart*)part);
+
+ nPart->setLenTick(len);
+ //
+ // cut Events in nPart
+ EventList* el = nPart->events();
+ for (iEvent ie = el->lower_bound(len); ie != el->end(); ++ie)
+ operations.push_back(UndoOp(UndoOp::DeleteEvent,ie->second, nPart, false, false));
+
+ operations.push_back(UndoOp(UndoOp::ModifyPart,part, nPart, true, true));
+ }
else if ((t < lpos) && ((t+l) > lpos) && ((t+l) > rpos)) {
//----------------------
// remove part middle
//----------------------
+ Part* p1;
+ Part* p2;
+ Part* p3;
+ track->splitPart(part, lpos, p1, p2);
+ delete p2;
+ track->splitPart(part, rpos, p2, p3);
+ delete p2;
+ p3->setTick(lpos);
+ p1->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it so we must decrement it first :/
+ p3->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it so we must decrement it first :/
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
- EventList* el = nPart->events();
- iEvent is = el->lower_bound(lpos-t);
- iEvent ie = el->lower_bound(rpos-t); //lower bound, because we do NOT want to erase the events at rpos-t
- for (iEvent i = is; i != ie; ++i)
- operations.push_back(UndoOp(UndoOp::DeleteEvent,i->second, nPart, false, false));
-
- for (iEvent i = el->lower_bound(rpos-t); i != el->end(); ++i) {
- Event event = i->second;
- Event nEvent = event.clone();
- nEvent.setTick(nEvent.tick() - (rpos-lpos));
- // Indicate no undo, and do not do port controller values and clone parts.
- operations.push_back(UndoOp(UndoOp::ModifyEvent,nEvent, event, nPart, false, false));
- }
- nPart->setLenTick(l - (rpos-lpos));
// Indicate no undo, and do port controller values and clone parts.
- operations.push_back(UndoOp(UndoOp::ModifyPart,part, nPart, true, true));
+ operations.push_back(UndoOp(UndoOp::ModifyPart,part, p1, true, true));
+ operations.push_back(UndoOp(UndoOp::AddPart,p3));
}
else if ((t >= lpos) && (t < rpos) && (t+l) > rpos) {
// remove part head
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
- EventList* el = nPart->events();
- iEvent i_end = el->lower_bound(rpos-t); //lower bound, because we do NOT want to erase the events at rpos-t
- for (iEvent it = el->begin(); it!=i_end; it++)
- operations.push_back(UndoOp(UndoOp::DeleteEvent,it->second, nPart, false, false));
-
- for (iEvent it = el->lower_bound(rpos-t); it!=el->end(); it++) {
- Event event = it->second;
- Event nEvent = event.clone();
- nEvent.setTick(nEvent.tick() - (rpos-t));
- // Indicate no undo, and do not do port controller values and clone parts.
- operations.push_back(UndoOp(UndoOp::ModifyEvent,nEvent, event, nPart, false, false));
- }
-
- nPart->setLenTick(l - (rpos-t));
- operations.push_back(UndoOp(UndoOp::ModifyPart,part, nPart, true, true));
+ Part* p1;
+ Part* p2;
+ track->splitPart(part, rpos, p1, p2);
+ delete p1;
+ p2->setTick(lpos);
+ p2->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it so we must decrement it first :/
+ operations.push_back(UndoOp(UndoOp::ModifyPart,part, p2, true, true));
}
else if (t >= rpos) {
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
+ // move part to the left
+ Part *nPart;
+ if (track->isMidiTrack())
+ nPart = new MidiPart(*(MidiPart*)part);
+ else
+ nPart = new WavePart(*(WavePart*)part);
+ //MidiPart* nPart = new MidiPart(*(MidiPart*)part);
int nt = part->tick();
nPart->setTick(nt - (rpos -lpos));
// Indicate no undo, and do port controller values but not clone parts.
@@ -246,33 +238,24 @@ void globalCut()
// - insert in master track
//---------------------------------------------------------
-void globalInsert()
- {
- Undo operations=movePartsTotheRight(MusEGlobal::song->lpos(), MusEGlobal::song->rpos()-MusEGlobal::song->lpos(), true);
+void globalInsert(bool onlySelectedTracks)
+{
+ Undo operations=movePartsTotheRight(MusEGlobal::song->lpos(), MusEGlobal::song->rpos()-MusEGlobal::song->lpos(), onlySelectedTracks);
MusEGlobal::song->applyOperationGroup(operations);
- }
-
+}
Undo movePartsTotheRight(unsigned int startTicks, int moveTicks, bool only_selected, set<Track*>* tracklist)
- {
+{
if (moveTicks<=0)
return Undo();
Undo operations;
TrackList* tracks = MusEGlobal::song->tracks();
- bool at_least_one_selected=false;
-
- for (iTrack it = tracks->begin(); it != tracks->end(); ++it)
- if ( (*it)->selected() ) {
- at_least_one_selected=true;
- break;
- }
-
for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
- MidiTrack* track = dynamic_cast<MidiTrack*>(*it);
+ Track* track = *it;
if ( (track == 0) ||
- (only_selected && at_least_one_selected && !track->selected()) ||
+ (only_selected && !track->selected()) ||
(tracklist && tracklist->find(track)==tracklist->end()) )
continue;
PartList* pl = track->parts();
@@ -283,23 +266,23 @@ Undo movePartsTotheRight(unsigned int startTicks, int moveTicks, bool only_selec
if (t + l <= startTicks)
continue;
if (startTicks > t && startTicks < (t+l)) {
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
- nPart->setLenTick(l + moveTicks);
- EventList* el = nPart->events();
-
- for (riEvent i = el->rbegin(); i!=el->rend(); ++i)
- {
- if (i->first < startTicks-t)
- break;
- Event event = i->second;
- Event nEvent = i->second.clone();
- nEvent.setTick(nEvent.tick() + moveTicks);
- operations.push_back(UndoOp(UndoOp::ModifyEvent, nEvent, event, nPart, false, false));
- }
- operations.push_back(UndoOp(UndoOp::ModifyPart, part, nPart, true, true));
+ // split part to insert new space
+ Part* p1;
+ Part* p2;
+ track->splitPart(part, startTicks, p1, p2);
+ p2->setTick(startTicks+moveTicks);
+ p2->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it so we must decrement it first :/
+ p1->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it so we must decrement it first :/
+
+ operations.push_back(UndoOp(UndoOp::ModifyPart, part, p1, true, true));
+ operations.push_back(UndoOp(UndoOp::AddPart, p2));
}
else if (t >= startTicks) {
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
+ Part *nPart;
+ if (track->isMidiTrack())
+ nPart = new MidiPart(*(MidiPart*)part);
+ else
+ nPart = new WavePart(*(WavePart*)part);
nPart->setTick(t + moveTicks);
operations.push_back(UndoOp(UndoOp::ModifyPart, part, nPart, true, false));
}
@@ -317,47 +300,50 @@ Undo movePartsTotheRight(unsigned int startTicks, int moveTicks, bool only_selec
// - split all parts at the song position pointer
//---------------------------------------------------------
-void globalSplit()
- {
- int pos = MusEGlobal::song->cpos();
- Undo operations;
- TrackList* tracks = MusEGlobal::song->tracks();
- bool at_least_one_selected=false;
-
- for (iTrack it = tracks->begin(); it != tracks->end(); ++it)
- if ( (*it)->selected() ) {
- at_least_one_selected=true;
- break;
- }
-
-
- for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
- Track* track = *it;
- if (track == 0 || (at_least_one_selected && !track->selected()))
- continue;
-
- PartList* pl = track->parts();
- for (iPart p = pl->begin(); p != pl->end(); ++p) {
- Part* part = p->second;
- int p1 = part->tick();
- int l0 = part->lenTick();
- if (pos > p1 && pos < (p1+l0)) {
- Part* p1;
- Part* p2;
- track->splitPart(part, pos, p1, p2);
+void globalSplit(bool onlySelectedTracks)
+{
+ Undo operations=partSplitter(MusEGlobal::song->cpos(), onlySelectedTracks);
+ MusEGlobal::song->applyOperationGroup(operations);
+}
- p1->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it
- p2->events()->incARef(-1); // so we must decrement it first :/
+Undo partSplitter(unsigned int pos, bool onlySelectedTracks)
+{
+ Undo operations;
+ TrackList* tracks = MusEGlobal::song->tracks();
+
+ for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
+ Track* track = *it;
+ if (track == 0 || (onlySelectedTracks && !track->selected()))
+ continue;
+
+ PartList* pl = track->parts();
+ for (iPart p = pl->begin(); p != pl->end(); ++p) {
+ Part* part = p->second;
+ unsigned int p1 = part->tick();
+ unsigned int l0 = part->lenTick();
+ if (pos > p1 && pos < (p1+l0)) {
+ Part* p1;
+ Part* p2;
+ track->splitPart(part, pos, p1, p2);
+
+ p1->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it
+ p2->events()->incARef(-1); // so we must decrement it first :/
+
+ //MusEGlobal::song->informAboutNewParts(part, p1); // is unneccessary because of ModifyPart
+ MusEGlobal::song->informAboutNewParts(part, p2);
+ operations.push_back(UndoOp(UndoOp::ModifyPart,part, p1, true, false));
+ operations.push_back(UndoOp(UndoOp::AddPart,p2));
+ if (MusEGlobal::debugMsg)
+ {
+ printf("in partSplitter: part1 %d\n",p1->events()->refCount());
+ printf("in partSplitter: part2 %d\n",p2->events()->refCount());
+ }
+ break;
+ }
+ }
+ }
+ return operations;
+}
- //MusEGlobal::song->informAboutNewParts(part, p1); // is unneccessary because of ModifyPart
- MusEGlobal::song->informAboutNewParts(part, p2);
- operations.push_back(UndoOp(UndoOp::ModifyPart,part, p1, true, false));
- operations.push_back(UndoOp(UndoOp::AddPart,p2));
- break;
- }
- }
- }
- MusEGlobal::song->applyOperationGroup(operations);
- }
} // namespace MusECore
diff --git a/muse2/muse/structure.h b/muse2/muse/structure.h
index b92c4e14..3a359dc0 100644
--- a/muse2/muse/structure.h
+++ b/muse2/muse/structure.h
@@ -28,10 +28,11 @@
namespace MusECore {
Undo movePartsTotheRight(unsigned int startTick, int moveTick, bool only_selected=false, std::set<Track*>* tracklist=NULL);
+Undo partSplitter(unsigned int tick, bool onlySelectedTracks=false);
void adjustGlobalLists(Undo& operations, int startPos, int diff);
-void globalCut();
-void globalInsert();
-void globalSplit();
+void globalCut(bool onlySelectedTracks=false);
+void globalInsert(bool onlySelectedTracks=false);
+void globalSplit(bool onlySelectedTracks=false);
}
#endif
diff --git a/muse2/muse/synth.cpp b/muse2/muse/synth.cpp
index 93067835..7ab18bda 100644
--- a/muse2/muse/synth.cpp
+++ b/muse2/muse/synth.cpp
@@ -32,6 +32,7 @@
#include <dlfcn.h>
#include <QDir>
+#include <QString>
//#include <QMenu>
#include "app.h"
@@ -62,6 +63,19 @@ namespace MusECore {
extern void connectNodes(AudioTrack*, AudioTrack*);
bool SynthI::_isVisible=false;
+const char* synthTypes[] = { "METRONOME", "MESS", "DSSI", "VST", "UNKNOWN" };
+QString synthType2String(Synth::Type type) { return QString(synthTypes[type]); }
+
+Synth::Type string2SynthType(const QString& type)
+{
+ for(int i = 0; i < Synth::SYNTH_TYPE_END; ++i)
+ {
+ if(synthType2String((Synth::Type)i) == type)
+ return (Synth::Type)i;
+ }
+ return Synth::SYNTH_TYPE_END;
+}
+
/*
//---------------------------------------------------------
// description
@@ -145,19 +159,17 @@ void MessSynthIF::setNativeGeometry(int x, int y, int w, int h)
// search for synthesizer base class
//---------------------------------------------------------
-//static Synth* findSynth(const QString& sclass)
-static Synth* findSynth(const QString& sclass, const QString& label)
+static Synth* findSynth(const QString& sclass, const QString& label, Synth::Type type = Synth::SYNTH_TYPE_END)
{
for (std::vector<Synth*>::iterator i = MusEGlobal::synthis.begin();
i != MusEGlobal::synthis.end(); ++i)
{
- //if ((*i)->baseName() == sclass)
- //if ((*i)->name() == sclass)
- if ( ((*i)->baseName() == sclass) && (label.isEmpty() || ((*i)->name() == label)) )
-
- return *i;
+ if( ((*i)->baseName() == sclass) &&
+ (label.isEmpty() || ((*i)->name() == label)) &&
+ (type == Synth::SYNTH_TYPE_END || type == (*i)->synthType()) )
+ return *i;
}
- printf("synthi class:%s label:%s not found\n", sclass.toLatin1().constData(), label.toLatin1().constData());
+ printf("synthi type:%d class:%s label:%s not found\n", type, sclass.toLatin1().constData(), label.toLatin1().constData());
return 0;
}
@@ -166,10 +178,9 @@ static Synth* findSynth(const QString& sclass, const QString& label)
// create a synthesizer instance of class "label"
//---------------------------------------------------------
-static SynthI* createSynthInstance(const QString& sclass, const QString& label)
+static SynthI* createSynthInstance(const QString& sclass, const QString& label, Synth::Type type = Synth::SYNTH_TYPE_END)
{
- //Synth* s = findSynth(sclass);
- Synth* s = findSynth(sclass, label);
+ Synth* s = findSynth(sclass, label, type);
SynthI* si = 0;
if (s) {
si = new SynthI();
@@ -652,13 +663,11 @@ void initMidiSynth()
// If insertAt is valid, inserts before insertAt. Else at the end after all tracks.
//---------------------------------------------------------
-SynthI* Song::createSynthI(const QString& sclass, const QString& label, Track* insertAt)
+SynthI* Song::createSynthI(const QString& sclass, const QString& label, Synth::Type type, Track* insertAt)
{
//printf("Song::createSynthI calling ::createSynthI class:%s\n", sclass.toLatin1().constData());
- //SynthI* si = ::createSynthI(sclass);
- //SynthI* si = ::createSynthI(sclass, label);
- SynthI* si = createSynthInstance(sclass, label);
+ SynthI* si = createSynthInstance(sclass, label, type);
if(!si)
return 0;
//printf("Song::createSynthI created SynthI. Before insertTrack1...\n");
@@ -705,6 +714,9 @@ void SynthI::write(int level, Xml& xml) const
{
xml.tag(level++, "SynthI");
AudioTrack::writeProperties(level, xml);
+ //xml.intTag(level, "synthType", synth()->synthType());
+ xml.strTag(level, "synthType", synthType2String(synth()->synthType()));
+
xml.strTag(level, "class", synth()->baseName());
// To support plugins like dssi-vst where all the baseNames are the same 'dssi-vst' and the label is the name of the dll file.
@@ -823,7 +835,8 @@ void SynthI::read(Xml& xml)
{
QString sclass;
QString label;
-
+ Synth::Type type = Synth::SYNTH_TYPE_END;
+
int port = -1;
bool startgui = false;
bool startngui = false;
@@ -837,7 +850,10 @@ void SynthI::read(Xml& xml)
case Xml::End:
return;
case Xml::TagStart:
- if (tag == "class")
+ if (tag == "synthType")
+ //type = xml.parseInt();
+ type = string2SynthType(xml.parse1());
+ else if (tag == "class")
sclass = xml.parse1();
else if (tag == "label")
label = xml.parse1();
@@ -866,8 +882,15 @@ void SynthI::read(Xml& xml)
break;
case Xml::TagEnd:
if (tag == "SynthI") {
- //Synth* s = findSynth(sclass);
- Synth* s = findSynth(sclass, label);
+
+ // NOTICE: This is a hack to quietly change songs to use the new 'fluid_synth' name instead of 'fluidsynth'.
+ // Recent linker changes required the name change in fluidsynth's cmakelists. Nov 8, 2011 By Tim.
+ if(sclass == QString("fluidsynth") &&
+ (type == Synth::SYNTH_TYPE_END || type == Synth::MESS_SYNTH) &&
+ (label.isEmpty() || label == QString("FluidSynth")) )
+ sclass = QString("fluid_synth");
+
+ Synth* s = findSynth(sclass, label, type);
if (s == 0)
return;
if (initInstance(s, name()))
diff --git a/muse2/muse/synth.h b/muse2/muse/synth.h
index c5b63424..497395c0 100644
--- a/muse2/muse/synth.h
+++ b/muse2/muse/synth.h
@@ -72,6 +72,8 @@ class Synth {
QString _version;
public:
+ enum Type { METRO_SYNTH=0, MESS_SYNTH, DSSI_SYNTH, VST_SYNTH, SYNTH_TYPE_END };
+
//Synth(const QFileInfo& fi);
//Synth(const QFileInfo& fi, QString label);
Synth(const QFileInfo& fi, QString label, QString descr, QString maker, QString ver);
@@ -80,6 +82,7 @@ class Synth {
//virtual const char* description() const { return ""; }
//virtual const char* version() const { return ""; }
+ virtual Type synthType() const = 0;
int instances() const { return _instances; }
virtual void incInstances(int val) { _instances += val; }
QString completeBaseName() /*const*/ { return info.completeBaseName(); } // ddskrjo
@@ -117,6 +120,8 @@ class MessSynth : public Synth {
//virtual const char* description() const;
//virtual const char* version() const;
+ virtual Type synthType() const { return MESS_SYNTH; }
+
//virtual void* instantiate();
virtual void* instantiate(const QString&);
@@ -363,6 +368,9 @@ class MessSynthIF : public SynthIF {
virtual int getControllerInfo(int id, const char** name, int* ctrl, int* min, int* max, int* initval);
};
+extern QString synthType2String(Synth::Type);
+extern Synth::Type string2SynthType(const QString&);
+
} // namespace MusECore
namespace MusEGlobal {
diff --git a/muse2/muse/ticksynth.cpp b/muse2/muse/ticksynth.cpp
index 1edc0b12..6d3721ea 100644
--- a/muse2/muse/ticksynth.cpp
+++ b/muse2/muse/ticksynth.cpp
@@ -49,6 +49,7 @@ class MetronomeSynth : public Synth {
//MetronomeSynth(const QFileInfo& fi) : Synth(fi, QString("Metronome")) {}
MetronomeSynth(const QFileInfo& fi) : Synth(fi, QString("Metronome"), QString("Metronome"), QString(), QString()) {}
virtual ~MetronomeSynth() {}
+ virtual Type synthType() const { return METRO_SYNTH; }
virtual void incInstances(int) {}
virtual void* instantiate();
diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp
index 2091d03e..e9aa0cf6 100644
--- a/muse2/muse/track.cpp
+++ b/muse2/muse/track.cpp
@@ -4,6 +4,7 @@
// $Id: track.cpp,v 1.34.2.11 2009/11/30 05:05:49 terminator356 Exp $
//
// (C) Copyright 2000-2004 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -36,10 +37,12 @@
namespace MusECore {
//bool Track::_isVisible=true;
-unsigned int Track::_soloRefCnt = 0;
+unsigned int Track::_soloRefCnt = 0;
Track* Track::_tmpSoloChainTrack = 0;
bool Track::_tmpSoloChainDoIns = false;
bool Track::_tmpSoloChainNoDec = false;
+//bool Track::_tmpIsAuxProcessing = false;
+//int Track::_tmpIsAuxProcRefCount = 0;
const char* Track::_cname[] = {
"Midi", "Drum", "Wave", "AudioOut", "AudioIn", "AudioGroup",
@@ -199,6 +202,8 @@ int Track::y() const
void Track::init()
{
+ _auxRouteCount = 0;
+ _nodeTraversed = false;
_activity = 0;
_lastActivity = 0;
_recordFlag = false;
@@ -233,6 +238,8 @@ Track::Track(Track::TrackType t)
//Track::Track(const Track& t)
Track::Track(const Track& t, bool cloneParts)
{
+ _auxRouteCount = t._auxRouteCount;
+ _nodeTraversed = t._nodeTraversed;
_activity = t._activity;
_lastActivity = t._lastActivity;
_recordFlag = t._recordFlag;
@@ -298,6 +305,8 @@ Track::~Track()
Track& Track::operator=(const Track& t)
{
+ _auxRouteCount = t._auxRouteCount;
+ _nodeTraversed = t._nodeTraversed;
_activity = t._activity;
_lastActivity = t._lastActivity;
_recordFlag = t._recordFlag;
@@ -414,6 +423,107 @@ void Track::dump() const
_name.toLatin1().constData(), _type, _parts.size(), _selected);
}
+//---------------------------------------------------------
+// updateAuxRoute
+// Internal use. Update all the Aux ref counts of tracks dst is connected to.
+// If dst is valid, start traversal from there, not from this track.
+//---------------------------------------------------------
+
+void Track::updateAuxRoute(int refInc, Track* dst)
+{
+ //if(isMidiTrack() || _type == AUDIO_AUX)
+ if(isMidiTrack())
+ return;
+
+ //printf("Track::updateAuxRoute %s _auxRouteCount:%d refInc:%d\n", name().toLatin1().constData(), _auxRouteCount, refInc);
+
+ if(dst)
+ {
+ _nodeTraversed = true;
+ dst->updateAuxRoute(refInc, NULL);
+ _nodeTraversed = false;
+ return;
+ }
+
+ if(_type == AUDIO_AUX)
+ return;
+
+ if(_nodeTraversed)
+ {
+ fprintf(stderr, "Track::updateAuxRoute %s _auxRouteCount:%d refInc:%d :\n", name().toLatin1().constData(), _auxRouteCount, refInc);
+ if(refInc >= 0)
+ fprintf(stderr, " MusE Warning: Please check your routes: Circular path found!\n");
+ else
+ fprintf(stderr, " MusE: Circular path removed.\n");
+ return;
+ }
+
+ _nodeTraversed = true;
+
+ _auxRouteCount += refInc;
+ if(_auxRouteCount < 0)
+ {
+ fprintf(stderr, "Track::updateAuxRoute Ref underflow! %s _auxRouteCount:%d refInc:%d\n", name().toLatin1().constData(), _auxRouteCount, refInc);
+ //_auxRouteCount = 0;
+ }
+
+ for (iRoute i = _outRoutes.begin(); i != _outRoutes.end(); ++i)
+ {
+ if( !(*i).isValid() || (*i).type != Route::TRACK_ROUTE )
+ continue;
+ Track* t = (*i).track;
+ //if(t->isMidiTrack())
+ // continue;
+ t->updateAuxRoute(refInc, NULL);
+ }
+
+ _nodeTraversed = false;
+}
+
+//---------------------------------------------------------
+// isCircularRoute
+// If dst is valid, start traversal from there, not from this track.
+// Returns true if circular.
+//---------------------------------------------------------
+
+bool Track::isCircularRoute(Track* dst)
+{
+ //if(isMidiTrack() || _type == AUDIO_AUX)
+ //if(isMidiTrack())
+ // return;
+
+ bool rv = false;
+
+ if(dst)
+ {
+ _nodeTraversed = true;
+ rv = dst->isCircularRoute(NULL);
+ _nodeTraversed = false;
+ //if(rv)
+ // fprintf(stderr, " Circular route %s -> %s\n", name().toLatin1().constData(), dst->name().toLatin1().constData());
+ return rv;
+ }
+
+ if(_nodeTraversed)
+ return true;
+
+ _nodeTraversed = true;
+
+ for (iRoute i = _outRoutes.begin(); i != _outRoutes.end(); ++i)
+ {
+ if( !(*i).isValid() || (*i).type != Route::TRACK_ROUTE )
+ continue;
+ Track* t = (*i).track;
+ //if(t->isMidiTrack())
+ // continue;
+ rv = t->isCircularRoute(NULL);
+ if(rv)
+ break;
+ }
+
+ _nodeTraversed = false;
+ return rv;
+}
//---------------------------------------------------------
// MidiTrack
@@ -462,7 +572,6 @@ void MidiTrack::init()
{
_outPort = 0;
_outChannel = 0;
- // Changed by Tim. p3.3.8
//_inPortMask = 0xffff;
///_inPortMask = 0xffffffff;
@@ -537,7 +646,7 @@ void MidiTrack::setOutPortAndChannelAndUpdate(int port, int ch)
//---------------------------------------------------------
// setInPortAndChannelMask
// For old song files with port mask (max 32 ports) and channel mask (16 channels),
-// before midi routing was added (the iR button). p3.3.48
+// before midi routing was added (the iR button).
//---------------------------------------------------------
void MidiTrack::setInPortAndChannelMask(unsigned int portmask, int chanmask)
@@ -550,7 +659,7 @@ void MidiTrack::setInPortAndChannelMask(unsigned int portmask, int chanmask)
for(int port = 0; port < 32; ++port) // 32 is the old maximum number of ports.
{
- // p3.3.50 If the port was not used in the song file to begin with, just ignore it.
+ // If the port was not used in the song file to begin with, just ignore it.
// This saves from having all of the first 32 ports' channels connected.
if(!MusEGlobal::midiPorts[port].foundInSongFile())
continue;
@@ -558,34 +667,18 @@ void MidiTrack::setInPortAndChannelMask(unsigned int portmask, int chanmask)
//if(!(portmask & (1 << port)))
// continue;
- // p3.3.50 Removed. Allow to connect to port with no device so user can change device later.
+ // Removed. Allow to connect to port with no device so user can change device later.
//MidiPort* mp = &MusEGlobal::midiPorts[port];
//MidiDevice* md = mp->device();
//if(!md)
// continue;
- //for(int ch = 0; ch < MIDI_CHANNELS; ++ch) // p3.3.50 Removed.
- //{
- //if(!(chanmask & (1 << ch)))
- // continue;
-
- //Route aRoute(md, ch);
- //Route bRoute(this, ch);
- Route aRoute(port, chanmask); // p3.3.50
+ Route aRoute(port, chanmask);
Route bRoute(this, chanmask);
- // p3.3.50 Removed.
- //iRoute iir = rl->begin();
- //for(; iir != rl->end(); ++iir)
- //{
- //if(*iir == aRoute)
- // if(iir->type == Route::MIDI_PORT_ROUTE && iir->midiPort == port) // p3.3.50
- // break;
- //}
-
// Route wanted?
//if((portmask & (1 << port)) && (chanmask & (1 << ch)))
- if(portmask & (1 << port)) // p3.3.50
+ if(portmask & (1 << port))
{
// Route already exists?
//if(iir != rl->end())
@@ -818,11 +911,11 @@ void MidiTrack::read(Xml& xml)
//setInPortMask(xml.parseInt());
///setInPortMask(xml.parseUInt());
//xml.skip(tag); // Obsolete.
- portmask = xml.parseUInt(); // p3.3.48: Support old files.
+ portmask = xml.parseUInt(); // Support old files.
else if (tag == "inchannelMap")
///setInChannelMask(xml.parseInt());
//xml.skip(tag); // Obsolete.
- chanmask = xml.parseInt(); // p3.3.48: Support old files.
+ chanmask = xml.parseInt(); // Support old files.
else if (tag == "locked")
_locked = xml.parseInt();
else if (tag == "echo")
@@ -843,7 +936,7 @@ void MidiTrack::read(Xml& xml)
case Xml::TagEnd:
if (tag == "miditrack" || tag == "drumtrack")
{
- setInPortAndChannelMask(portmask, chanmask); // p3.3.48: Support old files.
+ setInPortAndChannelMask(portmask, chanmask); // Support old files.
return;
}
default:
@@ -972,7 +1065,7 @@ void Track::writeRouting(int level, Xml& xml) const
xml.tag(level++, s.toAscii().constData());
- // p3.3.38 New routing scheme.
+ // New routing scheme.
s = "source";
if(r->type != Route::TRACK_ROUTE)
s += QString(" type=\"%1\"").arg(r->type);
@@ -994,10 +1087,10 @@ void Track::writeRouting(int level, Xml& xml) const
if(r->type == Route::TRACK_ROUTE && r->track && r->track->type() == Track::AUDIO_INPUT)
continue;
- if(r->midiPort != -1 || !r->name().isEmpty()) // p3.3.49
+ if(r->midiPort != -1 || !r->name().isEmpty())
{
s = "Route";
- if(r->type == Route::MIDI_PORT_ROUTE) // p3.3.50
+ if(r->type == Route::MIDI_PORT_ROUTE)
{
if(r->channel != -1 && r->channel != 0)
s += QString(" channelMask=\"%1\"").arg(r->channel); // Use new channel mask.
@@ -1019,14 +1112,14 @@ void Track::writeRouting(int level, Xml& xml) const
s = "dest";
- //if(r->type == Route::MIDI_DEVICE_ROUTE) // p3.3.49 Obsolete since 1.1-RC2
+ //if(r->type == Route::MIDI_DEVICE_ROUTE) // Obsolete since 1.1-RC2
// s += QString(QT_TRANSLATE_NOOP("@default", " devtype=\"%1\"")).arg(r->device->deviceType()); //
//if(r->type != Route::TRACK_ROUTE) //
if(r->type != Route::TRACK_ROUTE && r->type != Route::MIDI_PORT_ROUTE)
s += QString(" type=\"%1\"").arg(r->type);
//s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(r->name());
- if(r->type == Route::MIDI_PORT_ROUTE) // p3.3.49
+ if(r->type == Route::MIDI_PORT_ROUTE)
s += QString(" mport=\"%1\"/").arg(r->midiPort);
else
s += QString(" name=\"%1\"/").arg(Xml::xmlString(r->name()));
diff --git a/muse2/muse/track.h b/muse2/muse/track.h
index 25a846ac..04cf71c2 100644
--- a/muse2/muse/track.h
+++ b/muse2/muse/track.h
@@ -4,6 +4,7 @@
// $Id: track.h,v 1.39.2.17 2009/12/20 05:00:35 terminator356 Exp $
//
// (C) Copyright 1999-2004 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -70,9 +71,10 @@ class Track {
static bool _tmpSoloChainDoIns;
static bool _tmpSoloChainNoDec;
- // p3.3.38
RouteList _inRoutes;
RouteList _outRoutes;
+ bool _nodeTraversed; // Internal anti circular route traversal flag.
+ int _auxRouteCount; // Number of aux paths feeding this track.
QString _name;
bool _recordFlag;
@@ -89,8 +91,6 @@ class Track {
int _activity;
int _lastActivity;
- //int _meter[MAX_CHANNELS];
- //int _peak[MAX_CHANNELS];
double _meter[MAX_CHANNELS];
double _peak[MAX_CHANNELS];
@@ -147,7 +147,10 @@ class Track {
bool noInRoute() const { return _inRoutes.empty(); }
bool noOutRoute() const { return _outRoutes.empty(); }
void writeRouting(int, Xml&) const;
-
+ bool isCircularRoute(Track* dst);
+ int auxRefCount() const { return _auxRouteCount; } // Number of Aux Tracks with routing paths to this track.
+ void updateAuxRoute(int refInc, Track* dst); // Internal use.
+
PartList* parts() { return &_parts; }
const PartList* cparts() const { return &_parts; }
Part* findPart(unsigned tick);
@@ -168,20 +171,21 @@ class Track {
virtual void setMute(bool val);
virtual void setOff(bool val);
- virtual void updateSoloStates(bool noDec) = 0;
- virtual void updateInternalSoloStates();
- void updateSoloState();
void setInternalSolo(unsigned int val);
- static void clearSoloRefCounts();
virtual void setSolo(bool val) = 0;
virtual bool isMute() const = 0;
-
unsigned int internalSolo() const { return _internalSolo; }
bool soloMode() const { return _soloRefCnt; }
bool solo() const { return _solo; }
bool mute() const { return _mute; }
bool off() const { return _off; }
bool recordFlag() const { return _recordFlag; }
+ //
+ // Internal use...
+ static void clearSoloRefCounts();
+ void updateSoloState();
+ virtual void updateSoloStates(bool noDec) = 0;
+ virtual void updateInternalSoloStates();
int activity() { return _activity; }
void setActivity(int v) { _activity = v; }
@@ -190,8 +194,6 @@ class Track {
void addActivity(int v) { _activity += v; }
void resetPeaks();
static void resetAllMeter();
- //int meter(int ch) const { return _meter[ch]; }
- //int peak(int ch) const { return _peak[ch]; }
double meter(int ch) const { return _meter[ch]; }
double peak(int ch) const { return _peak[ch]; }
void resetMeter();
@@ -220,9 +222,9 @@ class MidiTrack : public Track {
int _outPort;
int _outChannel;
//int _inPortMask;
- ///unsigned int _inPortMask; // bitmask of accepted record ports
- ///int _inChannelMask; // bitmask of accepted record channels
- bool _recEcho; // For midi (and audio). Whether to echo incoming record events to output device.
+ //unsigned int _inPortMask; // bitmask of accepted record ports
+ //int _inChannelMask; // bitmask of accepted record channels
+ bool _recEcho; // For midi (and audio). Whether to echo incoming record events to output device.
EventList* _events; // tmp Events during midi import
MPEventList* _mpevents; // tmp Events druring recording
@@ -270,17 +272,17 @@ class MidiTrack : public Track {
void setOutPortAndChannelAndUpdate(int /*port*/, int /*chan*/);
//void setInPortMask(int i) { _inPortMask = i; }
- ///void setInPortMask(unsigned int i) { _inPortMask = i; } // Obsolete
- ///void setInChannelMask(int i) { _inChannelMask = i; } //
+ //void setInPortMask(unsigned int i) { _inPortMask = i; } // Obsolete
+ //void setInChannelMask(int i) { _inChannelMask = i; } //
// Backward compatibility: For reading old songs.
void setInPortAndChannelMask(unsigned int /*portmask*/, int /*chanmask*/);
void setRecEcho(bool b) { _recEcho = b; }
int outPort() const { return _outPort; }
//int inPortMask() const { return _inPortMask; }
- ///unsigned int inPortMask() const { return _inPortMask; }
+ //unsigned int inPortMask() const { return _inPortMask; }
int outChannel() const { return _outChannel; }
- ///int inChannelMask() const { return _inChannelMask; }
+ //int inChannelMask() const { return _inChannelMask; }
bool recEcho() const { return _recEcho; }
virtual bool isMute() const;
@@ -298,14 +300,10 @@ class MidiTrack : public Track {
clefTypes getClef() { return clefType; }
};
-} // namespace MusECore
-
-namespace MusECore {
-
//---------------------------------------------------------
// AudioTrack
// this track can hold audio automation data and can
-// hold tracktypes AUDIO, AUDIO_MASTER, AUDIO_GROUP,
+// hold tracktypes WAVE, AUDIO_GROUP, AUDIO_OUTPUT,
// AUDIO_INPUT, AUDIO_SOFTSYNTH, AUDIO_AUX
//---------------------------------------------------------
@@ -313,25 +311,19 @@ class AudioTrack : public Track {
//friend class MidiTrack;
//static unsigned int _soloRefCnt;
- bool _haveData;
+ bool _haveData; // Whether we have data from a previous process call during current cycle.
CtrlListList _controller;
CtrlRecList _recEvents; // recorded automation events
bool _prefader; // prefader metering
std::vector<double> _auxSend;
- Pipeline* _efxPipe;
-
- AutomationType _automationType;
-
- //RouteList _inRoutes;
- //RouteList _outRoutes;
-
- bool _sendMetronome;
-
//void readRecfile(Xml& xml);
void readAuxSend(Xml& xml);
-
+
+ bool _sendMetronome;
+ AutomationType _automationType;
+ Pipeline* _efxPipe;
protected:
float** outBuffers;
@@ -344,7 +336,7 @@ class AudioTrack : public Track {
SndFile* _recFile;
Fifo fifo; // fifo -> _recFile
bool _processed;
-
+
public:
AudioTrack(TrackType t);
//AudioTrack(TrackType t, int num_out_bufs = MAX_CHANNELS);
@@ -424,12 +416,6 @@ class AudioTrack : public Track {
void readVolume(Xml& xml);
//void writeRouting(int, Xml&) const;
- // routing
- //RouteList* inRoutes() { return &_inRoutes; }
- //RouteList* outRoutes() { return &_outRoutes; }
- //bool noInRoute() const { return _inRoutes.empty(); }
- //bool noOutRoute() const { return _outRoutes.empty(); }
-
virtual void preProcessAlways() { _processed = false; }
virtual void addData(unsigned /*samplePos*/, int /*channels*/, int /*srcStartChan*/, int /*srcChannels*/, unsigned /*frames*/, float** /*buffer*/);
virtual void copyData(unsigned /*samplePos*/, int /*channels*/, int /*srcStartChan*/, int /*srcChannels*/, unsigned /*frames*/, float** /*buffer*/);
diff --git a/muse2/muse/undo.cpp b/muse2/muse/undo.cpp
index eb554495..8587b108 100644
--- a/muse2/muse/undo.cpp
+++ b/muse2/muse/undo.cpp
@@ -50,8 +50,11 @@ const char* UndoOp::typeName()
"AddTrack", "DeleteTrack", "ModifyTrack",
"AddPart", "DeletePart", "ModifyPart",
"AddEvent", "DeleteEvent", "ModifyEvent",
- "AddTempo", "DeleteTempo", "AddSig", "DeleteSig",
- "SwapTrack", "ModifyClip"
+ "AddTempo", "DeleteTempo",
+ "AddSig", "DeleteSig",
+ "AddKey", "DeleteKey",
+ "SwapTrack", "ModifyClip", "ModifyMarker",
+ "ModifySongLen", "DoNothing"
};
return name[type];
}
@@ -95,6 +98,7 @@ void UndoOp::dump()
case ModifyMarker:
case AddKey:
case DeleteKey:
+ case ModifySongLen:
case DoNothing:
break;
}
@@ -530,6 +534,10 @@ void Song::doUndo2()
MusEGlobal::keymap.addKey(i->a, (key_enum)i->b);
updateFlags |= SC_KEY;
break;
+ case UndoOp::ModifySongLen:
+ _len=i->b;
+ updateFlags = -1; // set all flags
+ break;
case UndoOp::ModifyClip:
case UndoOp::ModifyMarker:
case UndoOp::DoNothing:
@@ -767,6 +775,10 @@ void Song::doRedo2()
MusEGlobal::keymap.delKey(i->a);
updateFlags |= SC_KEY;
break;
+ case UndoOp::ModifySongLen:
+ _len=i->a;
+ updateFlags = -1; // set all flags
+ break;
case UndoOp::ModifyClip:
case UndoOp::ModifyMarker:
case UndoOp::DoNothing:
diff --git a/muse2/muse/undo.h b/muse2/muse/undo.h
index 19c252bf..af55a307 100644
--- a/muse2/muse/undo.h
+++ b/muse2/muse/undo.h
@@ -54,6 +54,7 @@ struct UndoOp {
SwapTrack,
ModifyClip,
ModifyMarker,
+ ModifySongLen, // a = new len, b = old len
DoNothing
};
UndoType type;
diff --git a/muse2/muse/vst.h b/muse2/muse/vst.h
index b57b598d..b41e7137 100644
--- a/muse2/muse/vst.h
+++ b/muse2/muse/vst.h
@@ -50,6 +50,7 @@ class VstSynth : public Synth {
}
virtual ~VstSynth() {}
+ virtual Type synthType() const { return VST_SYNTH; }
virtual void incInstances(int val);
virtual void* instantiate();
//virtual SynthIF* createSIF() const;
diff --git a/muse2/muse/wave.cpp b/muse2/muse/wave.cpp
index 06759441..f22f6f97 100644
--- a/muse2/muse/wave.cpp
+++ b/muse2/muse/wave.cpp
@@ -105,7 +105,7 @@ SndFile::~SndFile()
bool SndFile::openRead()
{
if (openFlag) {
- printf("SndFile:: alread open\n");
+ printf("SndFile:: already open\n");
return false;
}
QString p = path();
@@ -468,7 +468,7 @@ size_t SndFile::readWithHeap(int srcChannels, float** dst, size_t n, bool overwr
{
float *buffer = new float[n * sfinfo.channels];
int rn = readInternal(srcChannels,dst,n,overwrite, buffer);
- delete buffer;
+ delete[] buffer;
return rn;
}
@@ -588,11 +588,11 @@ size_t SndFile::write(int srcChannels, float** src, size_t n)
else {
printf("SndFile:write channel mismatch %d -> %d\n",
srcChannels, dstChannels);
- delete buffer;
+ delete[] buffer;
return 0;
}
int nbr = sf_writef_float(sf, buffer, n) ;
- delete buffer;
+ delete[] buffer;
return nbr;
}
@@ -1120,6 +1120,22 @@ SndFileR::~SndFileR()
}
}
+void SndFileList::clearDelete()
+{
+ // ~SndFile searches itself on the list (and will find for
+ // sure) and deletes the entry on its own.
+ while (!empty())
+ delete *begin();
+
+ /* this is wrong, because ~SndFile deletes itself from the
+ * list, causing the iterator to be invalidated -> fail.
+ for (SndFileList::iterator i = begin(); i != end(); ++i)
+ delete *i;
+ clear();
+ */
+}
+
+
} // namespace MusECore
namespace MusEGui {
diff --git a/muse2/muse/wave.h b/muse2/muse/wave.h
index 58e0ab87..535df939 100644
--- a/muse2/muse/wave.h
+++ b/muse2/muse/wave.h
@@ -182,11 +182,7 @@ class SndFileR {
class SndFileList : public std::list<SndFile*> {
public:
SndFile* search(const QString& name);
- void clearDelete() {
- for (SndFileList::iterator i = begin(); i != end(); ++i)
- delete *i;
- clear();
- }
+ void clearDelete();
};
typedef SndFileList::iterator iSndFile;
diff --git a/muse2/muse/waveedit/waveedit.cpp b/muse2/muse/waveedit/waveedit.cpp
index 537d8529..1c1115b1 100644
--- a/muse2/muse/waveedit/waveedit.cpp
+++ b/muse2/muse/waveedit/waveedit.cpp
@@ -289,6 +289,7 @@ WaveEdit::WaveEdit(MusECore::PartList* pl)
}
initTopwinState();
+ MusEGlobal::muse->topwinMenuInited(this);
}
void WaveEdit::initShortcuts()
diff --git a/muse2/muse/wavetrack.cpp b/muse2/muse/wavetrack.cpp
index 9edeffb6..0d699cbe 100644
--- a/muse2/muse/wavetrack.cpp
+++ b/muse2/muse/wavetrack.cpp
@@ -229,8 +229,8 @@ bool WaveTrack::getData(unsigned framePos, int channels, unsigned nframe, float*
ciRoute i = irl->begin();
if(i->track->isMidiTrack())
{
- if(MusEGlobal::debugMsg)
- printf("WaveTrack::getData: Error: First route is a midi track route!\n");
+ //if(MusEGlobal::debugMsg)
+ // printf("WaveTrack::getData: Error: First route is a midi track route!\n");
return false;
}
// p3.3.38
@@ -246,8 +246,8 @@ bool WaveTrack::getData(unsigned framePos, int channels, unsigned nframe, float*
{
if(i->track->isMidiTrack())
{
- if(MusEGlobal::debugMsg)
- printf("WaveTrack::getData: Error: Route is a midi track route!\n");
+ //if(MusEGlobal::debugMsg)
+ // printf("WaveTrack::getData: Error: Route is a midi track route!\n");
//return false;
continue;
}
diff --git a/muse2/muse/widgets/citem.h b/muse2/muse/widgets/citem.h
index 1777eb23..199d18b0 100644
--- a/muse2/muse/widgets/citem.h
+++ b/muse2/muse/widgets/citem.h
@@ -90,7 +90,7 @@ class CItem {
};
typedef std::multimap<int, CItem*, std::less<int> >::iterator iCItem;
-//typedef std::multimap<int, CItem*, std::less<int> >::const_iterator ciCItem;
+typedef std::multimap<int, CItem*, std::less<int> >::const_iterator ciCItem;
typedef std::multimap<int, CItem*, std::less<int> >::const_reverse_iterator rciCItem;
//---------------------------------------------------------
diff --git a/muse2/muse/widgets/filedialog.cpp b/muse2/muse/widgets/filedialog.cpp
index 68f2718f..7f2c1681 100644
--- a/muse2/muse/widgets/filedialog.cpp
+++ b/muse2/muse/widgets/filedialog.cpp
@@ -123,11 +123,13 @@ void MFileDialog::userToggled(bool flag)
if (lastUserDir.isEmpty()) {
- lastUserDir = MusEGlobal::museUser + QString("/") + baseDir; // Initialize if first time
+ //lastUserDir = MusEGlobal::museUser + QString("/") + baseDir; // Initialize if first time
+ lastUserDir = MusEGlobal::configPath + QString("/") + baseDir; // Initialize if first time // p4.0.39
}
if (testDirCreate(this, lastUserDir))
- setDirectory(MusEGlobal::museUser);
+ //setDirectory(MusEGlobal::museUser);
+ setDirectory(MusEGlobal::configPath); // p4.0.39
else
setDirectory(lastUserDir);
@@ -270,34 +272,6 @@ void MFileDialog::directoryChanged(const QString&)
}
}
-
-//---------------------------------------------------------
-// getFilterExtension
-//---------------------------------------------------------
-
-QString getFilterExtension(const QString &filter)
-{
- //
- // Return the first extension found. Must contain at least one * character.
- //
-
- int pos = filter.indexOf('*');
- if(pos == -1)
- return QString();
-
- QString filt;
- int len = filter.length();
- ++pos;
- for( ; pos < len; ++pos)
- {
- QChar c = filter[pos];
- if((c == ')') || (c == ';') || (c == ',') || (c == ' '))
- break;
- filt += filter[pos];
- }
- return filt;
-}
-
//---------------------------------------------------------
// getOpenFileName
//---------------------------------------------------------
@@ -509,10 +483,12 @@ FILE* fileOpen(QWidget* parent, QString name, const QString& ext,
FILE* fp = 0;
if (popenFlag) {
if (strcmp(mode, "r") == 0)
- zip += QString(" -d < ");
+ //zip += QString(" -d < ");
+ zip += QString(" -d < \""); // p4.0.40
else
- zip += QString(" > ");
- zip += name;
+ zip += QString(" > \"");
+ //zip += name;
+ zip = zip + name + QString("\""); // p4.0.40
fp = popen(zip.toAscii().data(), mode);
}
else {
diff --git a/muse2/muse/widgets/filedialog.h b/muse2/muse/widgets/filedialog.h
index b731b65a..b4e21e2c 100644
--- a/muse2/muse/widgets/filedialog.h
+++ b/muse2/muse/widgets/filedialog.h
@@ -3,6 +3,7 @@
// Linux Music Editor
// $Id: filedialog.h,v 1.2.2.2 2008/01/19 13:33:46 wschweer Exp $
// (C) Copyright 2000 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
diff --git a/muse2/muse/widgets/genset.cpp b/muse2/muse/widgets/genset.cpp
index d7642b3b..ec2c8637 100644
--- a/muse2/muse/widgets/genset.cpp
+++ b/muse2/muse/widgets/genset.cpp
@@ -4,6 +4,7 @@
// $Id: genset.cpp,v 1.7.2.8 2009/12/01 03:52:40 terminator356 Exp $
//
// (C) Copyright 2001-2004 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -24,8 +25,10 @@
#include <stdio.h>
#include <QFileDialog>
+#include <QFileInfo>
#include <QRect>
#include <QShowEvent>
+#include <QString>
#include "genset.h"
#include "app.h"
@@ -33,6 +36,7 @@
#include "midiseq.h"
#include "globals.h"
#include "icons.h"
+#include "helper.h"
namespace MusEGui {
@@ -93,12 +97,6 @@ GlobalSettingsConfig::GlobalSettingsConfig(QWidget* parent)
}
}
- userInstrumentsPath->setText(MusEGlobal::config.userInstrumentsDir);
- selectInstrumentsDirButton->setIcon(*openIcon);
- defaultInstrumentsDirButton->setIcon(*undoIcon);
- connect(selectInstrumentsDirButton, SIGNAL(clicked()), SLOT(selectInstrumentsPath()));
- connect(defaultInstrumentsDirButton, SIGNAL(clicked()), SLOT(defaultInstrumentsPath()));
-
guiRefreshSelect->setValue(MusEGlobal::config.guiRefresh);
minSliderSelect->setValue(int(MusEGlobal::config.minSlider));
minMeterSelect->setValue(MusEGlobal::config.minMeter);
@@ -119,6 +117,9 @@ GlobalSettingsConfig::GlobalSettingsConfig(QWidget* parent)
Period affects midi playback resolution.
Shorter periods are desirable.</string>
</property> */
+
+ projDirEntry->setText(MusEGlobal::config.projectBaseFolder);
+ projDirOpenToolButton->setIcon(*openIcon);
startSongEntry->setText(MusEGlobal::config.startSong);
startSongGroup->button(MusEGlobal::config.startMode)->setChecked(true);
@@ -171,9 +172,14 @@ Shorter periods are desirable.</string>
popsDefStayOpenCheckBox->setChecked(MusEGlobal::config.popupsDefaultStayOpen);
lmbDecreasesCheckBox->setChecked(MusEGlobal::config.leftMouseButtonCanDecrease);
rangeMarkerWithoutMMBCheckBox->setChecked(MusEGlobal::config.rangeMarkerWithoutMMB);
-
+
+ addHiddenCheckBox->setChecked(MusEGlobal::config.addHiddenTracks);
+ unhideTracksCheckBox->setChecked(MusEGlobal::config.unhideTracks);
+
//updateSettings(); // TESTING
+ connect(projDirOpenToolButton, SIGNAL(clicked()), SLOT(browseProjDir()));
+
connect(applyButton, SIGNAL(clicked()), SLOT(apply()));
connect(okButton, SIGNAL(clicked()), SLOT(ok()));
connect(cancelButton, SIGNAL(clicked()), SLOT(cancel()));
@@ -258,6 +264,8 @@ void GlobalSettingsConfig::updateSettings()
//dummyAudioRealRate->setText(dad ? QString().setNum(sampleRate) : "---");
//dummyAudioRealRate->setText(QString().setNum(sampleRate)); // Not used any more. p4.0.20
+ projDirEntry->setText(MusEGlobal::config.projectBaseFolder);
+
startSongEntry->setText(MusEGlobal::config.startSong);
startSongGroup->button(MusEGlobal::config.startMode)->setChecked(true);
@@ -310,6 +318,9 @@ void GlobalSettingsConfig::updateSettings()
lmbDecreasesCheckBox->setChecked(MusEGlobal::config.leftMouseButtonCanDecrease);
rangeMarkerWithoutMMBCheckBox->setChecked(MusEGlobal::config.rangeMarkerWithoutMMB);
+ addHiddenCheckBox->setChecked(MusEGlobal::config.addHiddenTracks);
+ unhideTracksCheckBox->setChecked(MusEGlobal::config.unhideTracks);
+
updateMdiSettings();
}
@@ -350,7 +361,9 @@ void GlobalSettingsConfig::apply()
MusEGlobal::config.useOutputLimiter = outputLimiterCheckBox->isChecked();
MusEGlobal::config.vstInPlace = vstInPlaceCheckBox->isChecked();
MusEGlobal::config.rtcTicks = rtcResolutions[rtcticks];
- MusEGlobal::config.userInstrumentsDir = userInstrumentsPath->text();
+
+ MusEGlobal::config.projectBaseFolder = projDirEntry->text();
+
MusEGlobal::config.startSong = startSongEntry->text();
MusEGlobal::config.startMode = startSongGroup->checkedId();
int das = dummyAudioSize->currentIndex();
@@ -408,6 +421,9 @@ void GlobalSettingsConfig::apply()
MusEGlobal::config.leftMouseButtonCanDecrease = lmbDecreasesCheckBox->isChecked();
MusEGlobal::config.rangeMarkerWithoutMMB = rangeMarkerWithoutMMBCheckBox->isChecked();
+ MusEGlobal::config.addHiddenTracks = addHiddenCheckBox->isChecked();
+ MusEGlobal::config.unhideTracks = unhideTracksCheckBox->isChecked();
+
//MusEGlobal::muse->showMixer(MusEGlobal::config.mixerVisible);
MusEGlobal::muse->showMixer1(MusEGlobal::config.mixer1Visible);
MusEGlobal::muse->showMixer2(MusEGlobal::config.mixer2Visible);
@@ -442,8 +458,6 @@ void GlobalSettingsConfig::apply()
MusEGlobal::muse->resize(MusEGlobal::config.geometryMain.size());
MusEGlobal::muse->move(MusEGlobal::config.geometryMain.topLeft());
- MusEGlobal::museUserInstruments = MusEGlobal::config.userInstrumentsDir;
-
MusEGlobal::muse->setHeartBeat(); // set guiRefresh
MusEGlobal::midiSeq->msgSetRtc(); // set midi tick rate
@@ -546,21 +560,6 @@ void GlobalSettingsConfig::transportCurrent()
transportY->setValue(r.y());
}
-void GlobalSettingsConfig::selectInstrumentsPath()
- {
- QString dir = QFileDialog::getExistingDirectory(this,
- tr("Selects instruments directory"),
- MusEGlobal::config.userInstrumentsDir);
- userInstrumentsPath->setText(dir);
- }
-
-void GlobalSettingsConfig::defaultInstrumentsPath()
- {
- QString dir = MusEGlobal::configPath + "/instruments";
- userInstrumentsPath->setText(dir);
- }
-
-
void GlobalSettingsConfig::traditionalPreset()
{
for (std::list<MdiSettings*>::iterator it = mdisettings.begin(); it!=mdisettings.end(); it++)
@@ -598,5 +597,12 @@ void GlobalSettingsConfig::borlandPreset()
updateMdiSettings();
}
+void GlobalSettingsConfig::browseProjDir()
+{
+ QString dir = MusEGui::browseProjectFolder(this);
+ if(!dir.isEmpty())
+ projDirEntry->setText(dir);
+}
+
} // namespace MusEGui
diff --git a/muse2/muse/widgets/genset.h b/muse2/muse/widgets/genset.h
index 0e1697ee..b076a27f 100644
--- a/muse2/muse/widgets/genset.h
+++ b/muse2/muse/widgets/genset.h
@@ -4,6 +4,7 @@
// $Id: genset.h,v 1.3 2004/01/25 09:55:17 wschweer Exp $
//
// (C) Copyright 2001 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -53,8 +54,7 @@ class GlobalSettingsConfig : public QDialog, public Ui::GlobalSettingsDialogBase
void bigtimeCurrent();
void mainCurrent();
void transportCurrent();
- void selectInstrumentsPath();
- void defaultInstrumentsPath();
+ void browseProjDir();
void traditionalPreset();
void mdiPreset();
void borlandPreset();
diff --git a/muse2/muse/widgets/gensetbase.ui b/muse2/muse/widgets/gensetbase.ui
index ba26cf38..124ee72a 100644
--- a/muse2/muse/widgets/gensetbase.ui
+++ b/muse2/muse/widgets/gensetbase.ui
@@ -30,7 +30,36 @@
<string>Application</string>
</attribute>
<layout class="QGridLayout">
- <item row="1" column="0">
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="projDirGroupBox">
+ <property name="title">
+ <string>Project directory</string>
+ </property>
+ <layout class="QHBoxLayout" name="qhboxProjDir">
+ <item>
+ <widget class="QLabel" name="textLabel_ProjDir">
+ <property name="text">
+ <string>Projects:</string>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="projDirEntry"/>
+ </item>
+ <item>
+ <widget class="QToolButton" name="projDirOpenToolButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0">
<widget class="QGroupBox" name="groupBox4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -413,14 +442,14 @@
</layout>
</widget>
</item>
- <item row="0" column="0">
+ <item row="1" column="0">
<widget class="QGroupBox" name="groupBox3">
<property name="title">
<string>Start Muse</string>
</property>
<layout class="QGridLayout">
<item row="0" column="0">
- <layout class="QGridLayout">
+ <layout class="QGridLayout" name="gridLayout11">
<item row="1" column="0">
<spacer name="spacer7_2">
<property name="orientation">
@@ -438,7 +467,7 @@
</spacer>
</item>
<item row="2" column="0" colspan="2">
- <layout class="QHBoxLayout">
+ <layout class="QHBoxLayout" name="qhboxStartSong">
<item>
<widget class="QLabel" name="textLabel1_2">
<property name="text">
@@ -811,9 +840,9 @@ Adjusts responsiveness of audio controls and
<number>2</number>
</property>
<item row="0" column="0">
- <layout class="QGridLayout">
+ <layout class="QGridLayout" name="gridLayoutwaveEditor">
<item row="0" column="0">
- <layout class="QHBoxLayout">
+ <layout class="QHBoxLayout" name="qhboxLayoutWaveEditor">
<item>
<widget class="QLabel" name="textLabel2_2">
<property name="sizePolicy">
@@ -1179,31 +1208,7 @@ Adjusts responsiveness of audio controls and
</item>
</widget>
</item>
- <item row="3" column="0">
- <widget class="QLabel" name="TextLabel3_4">
- <property name="text">
- <string>Instruments Directory</string>
- </property>
- </widget>
- </item>
<item row="3" column="1">
- <widget class="QLineEdit" name="userInstrumentsPath"/>
- </item>
- <item row="3" column="2">
- <widget class="QPushButton" name="selectInstrumentsDirButton">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="3" column="3">
- <widget class="QPushButton" name="defaultInstrumentsDirButton">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -1223,7 +1228,7 @@ Adjusts responsiveness of audio controls and
</widget>
<widget class="QWidget" name="tab3">
<attribute name="title">
- <string>GUI</string>
+ <string>GUI Behaviour</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
@@ -1406,10 +1411,58 @@ left button behave like the middle button in such areas.</string>
</property>
</widget>
</item>
+ <item row="9" column="0">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="7" column="1">
+ <widget class="QCheckBox" name="addHiddenCheckBox">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Allow adding hidden tracks in track list menu</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Unhide tracks when adding hidden tracks</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QCheckBox" name="unhideTracksCheckBox">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
- <item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>GUI Style</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayoutTab2">
+ <item row="0" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>MDI-subwindowness and sharing menus</string>
@@ -1460,8 +1513,8 @@ left button behave like the middle button in such areas.</string>
<rect>
<x>0</x>
<y>0</y>
- <width>482</width>
- <height>143</height>
+ <width>512</width>
+ <height>378</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
diff --git a/muse2/muse/widgets/header.cpp b/muse2/muse/widgets/header.cpp
index 2c1057c3..968e7f73 100644
--- a/muse2/muse/widgets/header.cpp
+++ b/muse2/muse/widgets/header.cpp
@@ -51,7 +51,7 @@ void Header::readStatus(MusECore::Xml& xml)
for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
int logialIdx=abs((*it).toInt());
bool isHidden = (*it).toInt() < 0 ? true:false;
- int section = visualIndex(logialIdx);
+ int section = visualIndex(logialIdx - (isHidden? 1:0));
moveSection(section, index);
if (isHidden)
hideSection(logialIdx-1);
@@ -65,7 +65,7 @@ void Header::readStatus(MusECore::Xml& xml)
bool foundIt=false;
for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
int id=((*it).toInt());
- if ( id == i || i ==1-id )
+ if ( id == i || i == -1 - id )
foundIt=true;
}
if (foundIt == false) {
@@ -97,7 +97,7 @@ void Header::writeStatus(int level, MusECore::Xml& xml) const
//xml.nput(level, "<%s> ", name());
xml.nput(level, "<%s> ", MusECore::Xml::xmlString(objectName()).toLatin1().constData());
int n = count();
- for (int i = n; i >= 0; --i) {
+ for (int i = n-1; i >= 0; --i) {
if (isSectionHidden(logicalIndex(i)))
xml.nput("%d ", -logicalIndex(i)-1); // hidden is stored as negative value starting from -1
else
diff --git a/muse2/muse/widgets/knob.cpp b/muse2/muse/widgets/knob.cpp
index 920d2028..269f65cf 100644
--- a/muse2/muse/widgets/knob.cpp
+++ b/muse2/muse/widgets/knob.cpp
@@ -323,6 +323,30 @@ void Knob::rangeChange()
repaint();
}
+void Knob::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button() == Qt::MidButton || e->modifiers() & Qt::ControlModifier) {
+ int xpos = e->x() - width() /2;
+ double v = float(e->y()) / height() * 1.2;
+
+ double halfRange = (maxValue() - minValue())/2;
+ double midValue = minValue() + halfRange;
+ // apply to range
+ if (xpos < 0) { // left values
+ v = -v;
+ }
+ setValue(v * halfRange + midValue);
+ SliderBase::valueChange();
+
+ // fake a left-click to make the knob still "stick" to
+ // the mouse.
+ QMouseEvent temp(e->type(), e->pos(), Qt::LeftButton, e->buttons(), e->modifiers());
+ SliderBase::mousePressEvent(&temp);
+ return;
+ }
+ SliderBase::mousePressEvent(e);
+}
+
//---------------------------------------------------------
// resizeEvent
//---------------------------------------------------------
diff --git a/muse2/muse/widgets/knob.h b/muse2/muse/widgets/knob.h
index 483fafa6..bd8621a1 100644
--- a/muse2/muse/widgets/knob.h
+++ b/muse2/muse/widgets/knob.h
@@ -80,6 +80,7 @@ class Knob : public SliderBase, public ScaleIf
virtual void paintEvent(QPaintEvent *);
virtual void resizeEvent(QResizeEvent *e);
+ virtual void mousePressEvent(QMouseEvent *e);
double getValue(const QPoint &p);
void getScrollMode( QPoint &p, const Qt::MouseButton &button, int &scrollMode, int &direction );
void scaleChange() { repaint(); }
diff --git a/muse2/muse/widgets/meter.cpp b/muse2/muse/widgets/meter.cpp
index 5c79ffb2..d9ca8e20 100644
--- a/muse2/muse/widgets/meter.cpp
+++ b/muse2/muse/widgets/meter.cpp
@@ -229,6 +229,8 @@ void Meter::setRange(double min, double max)
void Meter::paintEvent(QPaintEvent* ev)
{
+ // For some reason upon resizing we get double calls here and in resizeEvent.
+
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
@@ -534,8 +536,11 @@ void Meter::drawVU(QPainter& p, const QRect& rect, const QPainterPath& drawPath,
void Meter::resizeEvent(QResizeEvent* ev)
{
- QFrame::resizeEvent(ev);
+ // For some reason upon resizing we get double calls here and in paintEvent.
+ //printf("Meter::resizeEvent w:%d h:%d\n", ev->size().width(), ev->size().height());
cur_yv = -1; // Force re-initialization.
+ QFrame::resizeEvent(ev);
+ update();
}
//---------------------------------------------------------
diff --git a/muse2/muse/widgets/midisync.ui b/muse2/muse/widgets/midisync.ui
index 8fc6248a..81d7451e 100644
--- a/muse2/muse/widgets/midisync.ui
+++ b/muse2/muse/widgets/midisync.ui
@@ -388,6 +388,19 @@ Enabled inputs in the list will
</column>
</widget>
</item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="toBeDoneLabel">
+ <property name="text">
+ <string>Note: Sync delay and MTC sync currently not fully implemeted</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/muse2/muse/widgets/mtrackinfo.cpp b/muse2/muse/widgets/mtrackinfo.cpp
index b5460447..19e9729a 100644
--- a/muse2/muse/widgets/mtrackinfo.cpp
+++ b/muse2/muse/widgets/mtrackinfo.cpp
@@ -574,7 +574,8 @@ void MidiTrackInfo::setLabelText()
//gradient.setColorAt(0, c.darker());
//gradient.setColorAt(0, c);
//gradient.setColorAt(1, c.darker());
- gradient.setColorAt(0, c.lighter());
+ gradient.setColorAt(0, c);
+ gradient.setColorAt(0.5, c.lighter());
gradient.setColorAt(1, c);
//palette.setBrush(QPalette::Button, gradient);
//palette.setBrush(QPalette::Window, gradient);
@@ -635,14 +636,17 @@ void MidiTrackInfo::iOutputPortChanged(int index)
{
if(!selected)
return;
+ int port_num = iOutput->itemData(index).toInt();
+ if(port_num < 0 || port_num >= MIDI_PORTS)
+ return;
MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected;
- if (index == track->outPort())
+ if (port_num == track->outPort())
return;
// Changed by T356.
- //track->setOutPort(index);
+ //track->setOutPort(port_num);
MusEGlobal::audio->msgIdle(true);
- //audio->msgSetTrackOutPort(track, index);
- track->setOutPortAndUpdate(index);
+ //audio->msgSetTrackOutPort(track, port_num);
+ track->setOutPortAndUpdate(port_num);
MusEGlobal::audio->msgIdle(false);
//MusEGlobal::song->update(SC_MIDI_TRACK_PROP);
@@ -1081,11 +1085,9 @@ void MidiTrackInfo::instrPopup()
//QMenu* pup = new QMenu;
PopupMenu* pup = new PopupMenu(true);
- //instr->populatePatchPopup(pop, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
- populatePatchPopup(instr, pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
+ instr->populatePatchPopup(pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
+ //populatePatchPopup(instr, pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM);
- //if(pop->actions().count() == 0)
- // return;
if(pup->actions().count() == 0)
{
delete pup;
@@ -1095,7 +1097,6 @@ 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 = pup->exec(iPatch->mapToGlobal(QPoint(10,5)));
if(act)
{
@@ -1346,12 +1347,20 @@ void MidiTrackInfo::updateTrackInfo(int flags)
//iInput->clear();
iOutput->clear();
+ int item_idx = 0;
for (int i = 0; i < MIDI_PORTS; ++i) {
+ MusECore::MidiDevice* md = MusEGlobal::midiPorts[i].device();
+ if(!md) // In the case of this combo box, don't bother listing empty ports. p4.0.41
+ continue;
+ //if(!(md->rwFlags() & 1 || md->isSynti()) && (i != outPort))
+ if(!(md->rwFlags() & 1) && (i != outPort)) // Only writeable ports, or current one. p4.0.41
+ continue;
QString name;
name.sprintf("%d:%s", i+1, MusEGlobal::midiPorts[i].portname().toLatin1().constData());
- iOutput->insertItem(i, name);
+ iOutput->insertItem(item_idx, name, i);
if (i == outPort)
- iOutput->setCurrentIndex(i);
+ iOutput->setCurrentIndex(item_idx);
+ item_idx++;
}
iOutput->blockSignals(false);
diff --git a/muse2/muse/widgets/musewidgetsplug.cpp b/muse2/muse/widgets/musewidgetsplug.cpp
index 4068da57..f707fb7c 100644
--- a/muse2/muse/widgets/musewidgetsplug.cpp
+++ b/muse2/muse/widgets/musewidgetsplug.cpp
@@ -157,7 +157,8 @@ MusEGlobal::GlobalConfigValues config = {
-60.0, // double minSlider;
false, // use Jack freewheel
20, // int guiRefresh;
- QString(""), // helpBrowser
+ QString(""), // userInstrumentsDir // Obsolete. Must keep for compatibility.
+ //QString(""), // helpBrowser // Obsolete
true, // extendedMidi
384, // division for smf export
QString(""), // copyright string for smf export
diff --git a/muse2/muse/widgets/popupmenu.cpp b/muse2/muse/widgets/popupmenu.cpp
index af546ec3..af870975 100644
--- a/muse2/muse/widgets/popupmenu.cpp
+++ b/muse2/muse/widgets/popupmenu.cpp
@@ -341,21 +341,38 @@ void PopupMenu::popHovered(QAction* action)
void PopupMenu::mouseReleaseEvent(QMouseEvent *e)
{
- #ifdef POPUP_MENU_DISABLE_STAY_OPEN
+ QAction* action = actionAt(e->pos());
+ if (!(action && action == activeAction() && !action->isSeparator() && action->isEnabled()))
+ action=NULL;
+
+ #ifdef POPUP_MENU_DISABLE_STAY_OPEN
+ if (action && action->menu() != NULL && action->isCheckable())
+ action->activate(QAction::Trigger);
+
QMenu::mouseReleaseEvent(e);
+
+ if (action && action->menu() != NULL && action->isCheckable())
+ close();
+
return;
#else
// Check for Ctrl to stay open.
if(!_stayOpen || (!MusEGlobal::config.popupsDefaultStayOpen && (e->modifiers() & Qt::ControlModifier) == 0))
{
+ if (action && action->menu() != NULL && action->isCheckable())
+ action->activate(QAction::Trigger);
+
QMenu::mouseReleaseEvent(e);
+
+ if (action && action->menu() != NULL && action->isCheckable())
+ close();
+
return;
}
//printf("PopupMenu::mouseReleaseEvent\n");
- QAction *action = actionAt(e->pos());
- if (action && action == activeAction() && !action->isSeparator() && action->isEnabled())
+ if (action)
action->activate(QAction::Trigger);
else
QMenu::mouseReleaseEvent(e);
diff --git a/muse2/muse/widgets/poslabel.cpp b/muse2/muse/widgets/poslabel.cpp
index 6cdcb27e..b893c58d 100644
--- a/muse2/muse/widgets/poslabel.cpp
+++ b/muse2/muse/widgets/poslabel.cpp
@@ -138,7 +138,11 @@ void PosLabel::setTickValue(unsigned val)
if (val == _tickValue)
return;
if (val >= MAX_TICK)
- abort();
+ {
+ printf("THIS SHOULD NEVER HAPPEN: val=%u > MAX_TICK=%u in PosLabel::setTickValue()!\n",val, MAX_TICK);
+ val=MAX_TICK-1;
+ }
+
_tickValue = val;
updateValue();
}
diff --git a/muse2/muse/widgets/projectcreate.ui b/muse2/muse/widgets/projectcreate.ui
index 406c83d6..d03f093c 100644
--- a/muse2/muse/widgets/projectcreate.ui
+++ b/muse2/muse/widgets/projectcreate.ui
@@ -17,28 +17,94 @@
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Project Name:</string>
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <item>
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Projects folder:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="projDirLineEdit">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="projDirToolButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Project Name:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLineEdit" name="projectNameEdit"/>
</item>
<item>
+ <widget class="QCheckBox" name="templateCheckBox">
+ <property name="text">
+ <string>Project is a Template</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>60</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Project song file type:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="projectFileTypeCB"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>75</width>
+ <width>40</width>
<height>20</height>
</size>
</property>
@@ -87,9 +153,16 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="browseDirButton">
+ <widget class="QToolButton" name="browseDirButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="restorePathButton">
<property name="text">
- <string>Browse</string>
+ <string>...</string>
</property>
</widget>
</item>
@@ -123,6 +196,18 @@
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>projectNameEdit</tabstop>
+ <tabstop>templateCheckBox</tabstop>
+ <tabstop>projectFileTypeCB</tabstop>
+ <tabstop>createFolderCheckbox</tabstop>
+ <tabstop>storageDirEdit</tabstop>
+ <tabstop>browseDirButton</tabstop>
+ <tabstop>commentEdit</tabstop>
+ <tabstop>buttonBox</tabstop>
+ <tabstop>projDirLineEdit</tabstop>
+ <tabstop>projDirToolButton</tabstop>
+ </tabstops>
<resources/>
<connections>
<connection>
diff --git a/muse2/muse/widgets/projectcreateimpl.cpp b/muse2/muse/widgets/projectcreateimpl.cpp
index 31973101..665d725e 100644
--- a/muse2/muse/widgets/projectcreateimpl.cpp
+++ b/muse2/muse/widgets/projectcreateimpl.cpp
@@ -4,6 +4,7 @@
// $Id: ./muse/widgets/projectcreateimpl.cpp $
//
// Copyright (C) 1999-2011 by Werner Schweer and others
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -21,12 +22,16 @@
//
//=========================================================
#include <stdio.h>
-#include <qfiledialog.h>
-#include <qdir.h>
+#include <QFileDialog>
+#include <QDir>
+#include <QStringList>
+
#include "projectcreateimpl.h"
#include "gconfig.h"
#include "globals.h"
#include "app.h"
+#include "helper.h"
+#include "icons.h"
namespace MusEGui {
@@ -35,10 +40,51 @@ ProjectCreateImpl::ProjectCreateImpl(QWidget *parent) :
{
setupUi(this);
- createFolderCheckbox->setChecked(MusEGlobal::config.projectStoreInFolder);
+ //bool is_new = (MusEGlobal::museProject == MusEGlobal::museProjectInitPath);
+ directoryPath = MusEGlobal::config.projectBaseFolder;
+
+ QStringList filters = localizedStringListFromCharArray(MusEGlobal::project_create_file_save_pattern, "file_patterns");
+ projectFileTypeCB->addItems(filters);
+
+ QString proj_title = MusEGlobal::muse->projectTitle();
+ QString proj_path = MusEGlobal::muse->projectPath();
+ QString proj_ext = MusEGlobal::muse->projectExtension();
+
+ projectNameEdit->setText(proj_title);
+
+ bool is_template = proj_path.startsWith(MusEGlobal::configPath + "/templates");
+
+ templateCheckBox->setChecked(is_template);
+
+ projDirPath = proj_path;
+
+ int type_idx = 0;
+ if(!proj_ext.isEmpty())
+ {
+ // FIXME Imperfect. Trying to avoid adding yet another series of character strings. p4.0.40
+ type_idx = projectFileTypeCB->findText(proj_ext, Qt::MatchContains | Qt::MatchCaseSensitive);
+ if(type_idx == -1)
+ type_idx = 0;
+ }
+ projectFileTypeCB->setCurrentIndex(type_idx);
+
+ projDirToolButton->setIcon(*openIcon);
+ browseDirButton->setIcon(*openIcon);
+ restorePathButton->setIcon(*undoIcon);
+
+ restorePathButton->setEnabled(false); // Disabled at first.
+
+ //createFolderCheckbox->setChecked(MusEGlobal::config.projectStoreInFolder && is_new); // Suggest no folder if not new.
+
+ connect(templateCheckBox,SIGNAL(clicked()), this, SLOT(templateButtonChanged()));
+ //connect(templateCheckBox,SIGNAL(clicked()), this, SLOT(updateDirectoryPath()));
+ connect(projDirToolButton,SIGNAL(clicked()), this, SLOT(browseProjDir()));
+ connect(restorePathButton,SIGNAL(clicked()), this, SLOT(restorePath()));
connect(browseDirButton,SIGNAL(clicked()), this, SLOT(selectDirectory()));
- connect(projectNameEdit,SIGNAL(textChanged(QString)), this, SLOT(updateDirectoryPath()));
- connect(createFolderCheckbox,SIGNAL(clicked()), this, SLOT(updateDirectoryPath()));
+ //connect(projectNameEdit,SIGNAL(textChanged(QString)), this, SLOT(updateDirectoryPath()));
+ connect(projectNameEdit,SIGNAL(textChanged(QString)), this, SLOT(updateProjectName()));
+ connect(createFolderCheckbox,SIGNAL(clicked()), this, SLOT(createProjFolderChanged()));
+ connect(projectFileTypeCB,SIGNAL(currentIndexChanged(int)), this, SLOT(updateDirectoryPath()));
connect(buttonBox, SIGNAL(accepted()), this, SLOT(ok()));
#if QT_VERSION >= 0x040700
projectNameEdit->setPlaceholderText("<Project Name>");
@@ -46,52 +92,155 @@ ProjectCreateImpl::ProjectCreateImpl(QWidget *parent) :
// as of Qt-4.7.1
//commentEdit->setPlaceholderText("<Add information about project here>");
#endif
- directoryPath = MusEGlobal::config.projectBaseFolder;
updateDirectoryPath();
show();
}
void ProjectCreateImpl::selectDirectory()
{
- QFileDialog qfd;
- qfd.selectFile(directoryPath);
- qfd.setFileMode(QFileDialog::DirectoryOnly);
- if (qfd.exec() == QDialog::Rejected) {
- return;
- }
- directoryPath=qfd.selectedFiles().first();
+ QString dpath = templateCheckBox->isChecked() ?
+ (overrideTemplDirPath.isEmpty() ? (MusEGlobal::configPath + QString("/templates")) : overrideTemplDirPath) :
+ (overrideDirPath.isEmpty() ? directoryPath : overrideDirPath);
+
+ QString dir = QFileDialog::getExistingDirectory(this, tr("Select directory"), dpath);
+ if(dir.isEmpty())
+ return;
+
+ (templateCheckBox->isChecked() ? overrideTemplDirPath : overrideDirPath) = dir;
+ restorePathButton->setEnabled(true);
updateDirectoryPath();
}
-void ProjectCreateImpl::updateDirectoryPath()
+void ProjectCreateImpl::updateProjectName()
{
+ QString curExt = projectFileTypeCB->currentText();
+ if(curExt.isEmpty())
+ curExt = ".med";
+ else
+ {
+ curExt = MusEGui::getFilterExtension(curExt);
+ // Do we have a valid extension?
+ if(curExt.isEmpty())
+ curExt = ".med";
+ }
+
QString name = "";
if (createFolderCheckbox->isChecked()) {
if (!projectNameEdit->text().isEmpty())
- name = projectNameEdit->text() + "/" + projectNameEdit->text() + ".med";
+ //name = projectNameEdit->text() + "/" + projectNameEdit->text() + ".med";
+ name = projectNameEdit->text() + "/" + projectNameEdit->text() + curExt;
//storageDirEdit->setText(directoryPath + name );
} else {
if (!projectNameEdit->text().isEmpty())
- name = projectNameEdit->text() + ".med";
+ //name = projectNameEdit->text() + ".med";
+ name = projectNameEdit->text() + curExt;
//storageDirEdit->setText(directoryPath +"/" + name);
}
- storageDirEdit->setText(directoryPath +"/" + name ); // Tim
+
+ bool is_new = (MusEGlobal::museProject == MusEGlobal::museProjectInitPath);
+
+ QString dpath = templateCheckBox->isChecked() ?
+ (overrideTemplDirPath.isEmpty() ? (MusEGlobal::configPath + QString("/templates")) : overrideTemplDirPath) :
+ (overrideDirPath.isEmpty() ? (is_new ? directoryPath : projDirPath) : overrideDirPath);
+
+ QDir proj_dir(dpath);
+ //if(is_project && MusEGlobal::config.projectStoreInFolder)
+ bool is_project = dpath.startsWith(MusEGlobal::config.projectBaseFolder);
+ //bool is_template = dpath.startsWith(MusEGlobal::configPath + "/templates") && templateCheckBox->isChecked();
+ //bool is_new = (MusEGlobal::museProject == MusEGlobal::museProjectInitPath) && MusEGlobal::config.projectStoreInFolder;
+ //bool is_new = (MusEGlobal::museProject == MusEGlobal::museProjectInitPath) &&
+ MusEGlobal::config.projectStoreInFolder &&
+ (templateCheckBox->isChecked() ? overrideTemplDirPath.isEmpty() : overrideDirPath.isEmpty());
+ //bool is_template = is_new && dpath.startsWith(MusEGlobal::configPath + "/templates") && templateCheckBox->isChecked();
+ if(!is_new && createFolderCheckbox->isChecked() && !templateCheckBox->isChecked() &&
+ (templateCheckBox->isChecked() ? overrideTemplDirPath.isEmpty() : overrideDirPath.isEmpty()))
+ proj_dir.cdUp();
+ dpath = proj_dir.absolutePath();
+
+ //if(!initProjPath.isEmpty())
+ //{
+ // initProjPath.clear();
+ //}
+
+ storageDirEdit->blockSignals(true);
+ storageDirEdit->setText(dpath + "/" + name );
+ storageDirEdit->blockSignals(false);
+
+ projDirLineEdit->setEnabled(!templateCheckBox->isChecked() && is_project);
+}
+
+void ProjectCreateImpl::updateDirectoryPath()
+{
+ updateProjectName();
+
+ projDirLineEdit->blockSignals(true);
+ projDirLineEdit->setText(MusEGlobal::config.projectBaseFolder);
+ projDirLineEdit->blockSignals(false);
}
-QString ProjectCreateImpl::getProjectPath()
+QString ProjectCreateImpl::getProjectPath() const
{
return storageDirEdit->text();
}
-QString ProjectCreateImpl::getSongInfo()
+
+QString ProjectCreateImpl::getSongInfo() const
{
return commentEdit->toPlainText();
}
+
void ProjectCreateImpl::ok()
{
MusEGlobal::config.projectStoreInFolder = createFolderCheckbox->isChecked();
- MusEGlobal::config.projectBaseFolder = directoryPath;
- MusEGlobal::muse->changeConfig(true);
+ //MusEGlobal::config.projectBaseFolder = directoryPath;
+ //MusEGlobal::muse->changeConfig(true);
emit accept();
}
+void ProjectCreateImpl::createProjFolderChanged()
+{
+ //MusEGlobal::config.projectStoreInFolder = createFolderCheckbox->isChecked();
+ //MusEGlobal::muse->changeConfig(true); // Save to config file.
+ updateDirectoryPath();
+}
+
+void ProjectCreateImpl::browseProjDir()
+{
+ QString dir = MusEGui::browseProjectFolder(this);
+ if(!dir.isEmpty())
+ {
+ directoryPath = dir;
+ MusEGlobal::config.projectBaseFolder = dir;
+ MusEGlobal::muse->changeConfig(true); // Save to config file.
+ updateDirectoryPath();
+ }
+}
+
+void ProjectCreateImpl::templateButtonChanged()
+{
+ restorePathButton->setEnabled(templateCheckBox->isChecked() ? !overrideTemplDirPath.isEmpty() : !overrideDirPath.isEmpty());
+ updateDirectoryPath();
+}
+
+void ProjectCreateImpl::restorePath()
+{
+ if(templateCheckBox->isChecked())
+ overrideTemplDirPath.clear();
+ else
+ overrideDirPath.clear();
+ restorePathButton->setEnabled(templateCheckBox->isChecked() ? !overrideTemplDirPath.isEmpty() : !overrideDirPath.isEmpty());
+ updateDirectoryPath();
+}
+
+/*
+bool ProjectCreateImpl::getProjectIsTemplate() const
+{
+ return templateCheckBox->isChecked();
+}
+
+QString ProjectCreateImpl::getTemplatePath() const
+{
+ return templDirPath;
+}
+*/
+
} //namespace MusEGui
diff --git a/muse2/muse/widgets/projectcreateimpl.h b/muse2/muse/widgets/projectcreateimpl.h
index 258b0921..f08cb1bc 100644
--- a/muse2/muse/widgets/projectcreateimpl.h
+++ b/muse2/muse/widgets/projectcreateimpl.h
@@ -4,6 +4,7 @@
// $Id: ./muse/widgets/projectcreateimpl.h $
//
// Copyright (C) 1999-2011 by Werner Schweer and others
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -33,18 +34,28 @@ class ProjectCreateImpl : public QDialog, Ui::ProjectCreate
Q_OBJECT
QString directoryPath;
+ QString overrideDirPath;
+ QString overrideTemplDirPath;
+ QString projDirPath;
+
public:
explicit ProjectCreateImpl(QWidget *parent = 0);
- QString getProjectPath();
- QString getSongInfo();
+ QString getProjectPath() const;
+ QString getSongInfo() const;
+ //bool getProjectIsTemplate() const;
+ //QString getTemplatePath() const;
signals:
-public slots:
+protected slots:
+ void updateProjectName();
void updateDirectoryPath();
void selectDirectory();
void ok();
-
+ void createProjFolderChanged();
+ void browseProjDir();
+ void templateButtonChanged();
+ void restorePath();
};
} // namespace MusEGui
diff --git a/muse2/muse/widgets/routepopup.cpp b/muse2/muse/widgets/routepopup.cpp
index 80ae98bd..0f1f8264 100644
--- a/muse2/muse/widgets/routepopup.cpp
+++ b/muse2/muse/widgets/routepopup.cpp
@@ -43,10 +43,10 @@ namespace MusEGui {
int RoutePopupMenu::addMenuItem(MusECore::AudioTrack* track, MusECore::Track* route_track, PopupMenu* lb, int id, int channel, int channels, bool isOutput)
{
// totalInChannels is only used by syntis.
- int toch = ((MusECore::AudioTrack*)track)->totalOutChannels();
+ //int toch = ((MusECore::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;
+ //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))
@@ -95,6 +95,13 @@ int RoutePopupMenu::addMenuItem(MusECore::AudioTrack* track, MusECore::Track* ro
}
}
}
+
+ if(!act->isChecked()) // If circular route exists, allow user to break it, otherwise forbidden.
+ {
+ if( (isOutput ? track : route_track)->isCircularRoute(isOutput ? route_track : track) )
+ act->setEnabled(false);
+ }
+
return ++id;
}
@@ -259,6 +266,13 @@ int RoutePopupMenu::addSyntiPorts(MusECore::AudioTrack* t, PopupMenu* lb, int id
}
}
}
+
+ if(!act->isChecked()) // If circular route exists, allow user to break it, otherwise forbidden.
+ {
+ if( (isOutput ? t : track)->isCircularRoute(isOutput ? track : t) )
+ act->setEnabled(false);
+ }
+
++id;
}
@@ -520,6 +534,13 @@ int RoutePopupMenu::nonSyntiTrackAddSyntis(MusECore::AudioTrack* t, PopupMenu* l
}
}
}
+
+ if(!act->isChecked()) // If circular route exists, allow user to break it, otherwise forbidden.
+ {
+ if( (isOutput ? t : track)->isCircularRoute(isOutput ? track : t) )
+ act->setEnabled(false);
+ }
+
++id;
}
@@ -573,6 +594,13 @@ int RoutePopupMenu::nonSyntiTrackAddSyntis(MusECore::AudioTrack* t, PopupMenu* l
}
}
}
+
+ if(!act->isChecked()) // If circular route exists, allow user to break it, otherwise forbidden.
+ {
+ if( (isOutput ? t : track)->isCircularRoute(isOutput ? track : t) )
+ act->setEnabled(false);
+ }
+
++id;
}
}
@@ -1062,9 +1090,8 @@ void RoutePopupMenu::prepare()
for( ; pi < MIDI_PORTS; ++pi)
{
MusECore::MidiDevice* md = MusEGlobal::midiPorts[pi].device();
- //if(md && !md->isSynti() && (md->rwFlags() & 2))
- //if(md && (md->rwFlags() & 2)) // p4.0.27
- if(md && (md->rwFlags() & 2 || md->isSynti()) ) // p4.0.27
+ if(md && !md->isSynti() && (md->rwFlags() & 2))
+ //if(md && (md->rwFlags() & 2 || md->isSynti()) ) // p4.0.27 Reverted p4.0.35
break;
}
if(pi == MIDI_PORTS)
@@ -1091,12 +1118,9 @@ void RoutePopupMenu::prepare()
// continue;
// Do not list synth devices!
- ///if(md && md->isSynti())
- /// continue;
- ///if(md && !(md->rwFlags() & 2))
- /// continue;
- // p4.0.27 Go ahead. Synths esp MESS send out stuff.
- if( md && !(md->rwFlags() & 2) && !md->isSynti() )
+ if( md && (!(md->rwFlags() & 2) || md->isSynti()) )
+ // p4.0.27 Go ahead. Synths esp MESS send out stuff. Reverted p4.0.35
+ //if( md && !(md->rwFlags() & 2) && !md->isSynti() )
continue;
//printf("MusE::prepareRoutingPopupMenu adding submenu portnum:%d\n", i);
diff --git a/muse2/muse/widgets/synthconfigbase.ui b/muse2/muse/widgets/synthconfigbase.ui
index 97f0beaa..500241a8 100644
--- a/muse2/muse/widgets/synthconfigbase.ui
+++ b/muse2/muse/widgets/synthconfigbase.ui
@@ -6,12 +6,12 @@
<rect>
<x>0</x>
<y>0</y>
- <width>630</width>
+ <width>810</width>
<height>492</height>
</rect>
</property>
<property name="windowTitle">
- <string>MusE: Synth Configuration</string>
+ <string>Midi Port and Soft Synth Configuration</string>
</property>
<layout class="QGridLayout">
<item row="1" column="1">
@@ -32,6 +32,11 @@
</column>
<column>
<property name="text">
+ <string>Type</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
<string>Midi Port</string>
</property>
</column>
@@ -137,6 +142,11 @@
</column>
<column>
<property name="text">
+ <string>Type</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
<string>Inst</string>
</property>
</column>
diff --git a/muse2/muse/widgets/utils.cpp b/muse2/muse/widgets/utils.cpp
index 708bef07..1641b267 100644
--- a/muse2/muse/widgets/utils.cpp
+++ b/muse2/muse/widgets/utils.cpp
@@ -528,7 +528,8 @@ int get_paste_len()
if (p->endTick() > end_tick)
end_tick=p->endTick();
-
+
+ unchainClone(p);
delete p;
}
}
diff --git a/muse2/muse/widgets/visibletracks.cpp b/muse2/muse/widgets/visibletracks.cpp
index f8ce06bf..4976ecf9 100644
--- a/muse2/muse/widgets/visibletracks.cpp
+++ b/muse2/muse/widgets/visibletracks.cpp
@@ -29,6 +29,7 @@
#include "action.h"
#include "track.h"
#include "synth.h"
+#include "app.h"
namespace MusEGui {
@@ -130,6 +131,7 @@ void VisibleTracks::visibilityChanged(QAction* action)
default:
break;
}
+ MusEGlobal::muse->changeConfig(true); // save settings
emit visibilityChanged();
}
diff --git a/muse2/muse/widgets/visibletracks.h b/muse2/muse/widgets/visibletracks.h
index d56c9ce7..bf49c068 100644
--- a/muse2/muse/widgets/visibletracks.h
+++ b/muse2/muse/widgets/visibletracks.h
@@ -52,13 +52,14 @@ class VisibleTracks : public QToolBar {
private slots:
void visibilityChanged(QAction* action);
+ public slots:
+ void updateVisibleTracksButtons();
signals:
void visibilityChanged();
public:
VisibleTracks(QWidget* /*parent*/, const char* name = 0); // Needs a parent !
- void updateVisibleTracksButtons();
~VisibleTracks();
};
diff --git a/muse2/muse/xml.cpp b/muse2/muse/xml.cpp
index 139437c1..45bed368 100644
--- a/muse2/muse/xml.cpp
+++ b/muse2/muse/xml.cpp
@@ -4,6 +4,7 @@
// $Id: xml.cpp,v 1.17.2.6 2009/12/07 20:48:45 spamatica Exp $
//
// (C) Copyright 2000 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -24,6 +25,7 @@
#include <stdio.h>
#include <stdarg.h>
+#include <QByteArray>
#include <QString>
#include <QColor>
#include <QWidget>
@@ -112,9 +114,12 @@ void Xml::nextc()
void Xml::token(int cc)
{
- char buffer[512];
+ //char buffer[512];
+ QByteArray buffer;
+
int i = 0;
- for (; i < 511;) {
+ //for (; i < 511;) {
+ for (; i < 9999999;) { // Stop at a reasonably large amount 10 million.
if (c == ' ' || c == '\t' || c == cc || c == '\n' || c == EOF)
break;
buffer[i++] = c;
@@ -131,12 +136,16 @@ void Xml::token(int cc)
void Xml::stoken()
{
- char buffer[1024*4];
+ //char buffer[1024*4];
+ QByteArray buffer;
+
int i = 0;
buffer[i] = c;
++i;
next();
- for (;i < 1024*4-1;) {
+
+ //for (;i < 1024*4-1;) {
+ for (;i < 10000000*4-1;) { // Stop at a reasonably large amount 10 million.
if (c == '"') {
buffer[i++] = c;
next();
@@ -207,8 +216,10 @@ QString Xml::strip(const QString& s)
Xml::Token Xml::parse()
{
- char buffer[1024*1024]; // increase buffer -rj
- char* p;
+ //char buffer[1024*1024]; // increase buffer -rj
+ //char* p;
+ QByteArray buffer;
+ int idx = 0;
again:
bool endFlag = false;
@@ -262,15 +273,23 @@ Xml::Token Xml::parse()
}
if (c == '?') {
next();
- p = buffer;
+ //p = buffer;
+ //p = buffer.data();
+ idx = 0;
for (;;) {
if (c == '?' || c == EOF || c == '>')
break;
- *p++ = c;
+
+ //*p++ = c;
+ buffer[idx++] = c;
+
// TODO: check overflow
next();
}
- *p = 0;
+
+ //*p = 0;
+ buffer[idx] = 0;
+
_s1 = QString(buffer);
if (c == EOF) {
fprintf(stderr, "XML: unexpected EOF\n");
@@ -298,15 +317,23 @@ Xml::Token Xml::parse()
}
goto again;
}
- p = buffer;
+ //p = buffer;
+ //p = buffer.data();
+ idx = 0;
for (;;) {
if (c == '/' || c == ' ' || c == '\t' || c == '>' || c == '\n' || c == EOF)
break;
// TODO: check overflow
- *p++ = c;
+
+ //*p++ = c;
+ buffer[idx++] = c;
+
next();
}
- *p = 0;
+
+ //*p = 0;
+ buffer[idx] = 0;
+
_s1 = QString(buffer);
// skip white space:
while (c == ' ' || c == '\t' || c == '\n')
@@ -355,26 +382,43 @@ Xml::Token Xml::parse()
fprintf(stderr, "XML: level = 0\n");
goto error;
}
- p = buffer;
+ //p = buffer;
+ //p = buffer.data();
+ idx = 0;
for (;;) {
if (c == EOF || c == '<')
break;
if (c == '&') {
next();
if (c == '<') { // be tolerant with old muse files
- *p++ = '&';
+
+ //*p++ = '&';
+ buffer[idx++] = '&';
+
continue;
}
- char name[32];
- char* dp = name;
- *dp++ = c;
- for (; dp-name < 31;) {
+
+ //char name[32];
+ //char* dp = name;
+ QByteArray name;
+ int name_idx = 0;
+
+ //*dp++ = c;
+ name[name_idx++] = c;
+
+ //for (; dp-name < 31;) {
+ for (; name_idx < 9999999;) { // Stop at a reasonably large amount 10 million.
next();
if (c == ';')
break;
- *dp++ = c;
+
+ //*dp++ = c;
+ name[name_idx++] = c;
}
- *dp = 0;
+
+ //*dp = 0;
+ name[name_idx] = 0;
+
if (strcmp(name, "lt") == 0)
c = '<';
else if (strcmp(name, "gt") == 0)
@@ -388,10 +432,16 @@ Xml::Token Xml::parse()
else
c = '?';
}
- *p++ = c;
+
+ //*p++ = c;
+ buffer[idx++] = c;
+
next();
}
- *p = 0;
+
+ //*p = 0;
+ buffer[idx] = 0;
+
_s1 = QString(buffer);
if (c == '<')