diff options
author | Florian Jung <flo@windfisch.org> | 2012-05-28 14:15:52 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2012-05-28 14:15:52 +0000 |
commit | d2a88cfaad5ac385fc3c6212c09ad7fbc38e9454 (patch) | |
tree | 387da0b38255003e1a971629ea0de32273ac3d3c /muse2/muse | |
parent | 716f5a5b56a3b7ff59004ef0a1af5f98cb2a691c (diff) |
merged with release_2_0
Diffstat (limited to 'muse2/muse')
158 files changed, 3096 insertions, 2340 deletions
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index d9d5a1d9..dd94f743 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -88,19 +88,16 @@ #include "sig_tempo_toolbar.h" namespace MusECore { -extern void initMidiSynth(); extern void exitJackAudio(); extern void exitDummyAudio(); extern void exitOSC(); extern void exitMidiAlsa(); - -extern void initMidiSequencer(); -extern void initAudio(); -extern void initAudioPrefetch(); } namespace MusEGui { +extern void deleteIcons(); + //extern void cacheJackRouteNames(); static pthread_t watchdogThread; @@ -292,7 +289,7 @@ void addProject(const QString& name) // MusE //--------------------------------------------------------- -MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow() +MusE::MusE() : QMainWindow() { setIconSize(ICON_SIZE); setFocusPolicy(Qt::NoFocus); @@ -324,9 +321,10 @@ MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow() activeTopWin = NULL; currentMenuSharingTopwin = NULL; waitingForTopwin = NULL; - + appName = QString("MusE"); setWindowTitle(appName); + setWindowIcon(*MusEGui::museIcon); midiPluginSignalMapper = new QSignalMapper(this); followSignalMapper = new QSignalMapper(this); windowsMapper = new QSignalMapper(this); @@ -450,10 +448,6 @@ 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::initMidiPorts(); - MusECore::initMidiDevices(); - //----Actions //-------- File Actions @@ -537,8 +531,6 @@ MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow() autoMixerAction->setCheckable(true); autoSnapshotAction = new QAction(QIcon(*MusEGui::automation_take_snapshotIcon), tr("Take Snapshot"), this); autoClearAction = new QAction(QIcon(*MusEGui::automation_clear_dataIcon), tr("Clear Automation Data"), this); - autoClearAction->setEnabled(false); - //-------- Windows Actions windowsCascadeAction = new QAction(tr("Cascade"), this); @@ -678,12 +670,14 @@ MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow() QToolBar* tempo_tb; tempo_tb = addToolBar(tr("Tempo")); tempo_tb->setObjectName("Tempo"); - tempo_tb->addWidget(new MusEGui::TempoToolbarWidget(tempo_tb)); + MusEGui::TempoToolbarWidget* tempo_tb_widget = new MusEGui::TempoToolbarWidget(tempo_tb); + tempo_tb->addWidget(tempo_tb_widget); QToolBar* sig_tb; sig_tb = addToolBar(tr("Signature")); sig_tb->setObjectName("Signature"); - sig_tb->addWidget(new MusEGui::SigToolbarWidget(tempo_tb)); + MusEGui::SigToolbarWidget* sig_tb_widget = new MusEGui::SigToolbarWidget(tempo_tb); + sig_tb->addWidget(sig_tb_widget); tools = addToolBar(tr("File Buttons")); tools->setObjectName("File Buttons"); @@ -712,32 +706,9 @@ MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow() optionalToolbars.push_back(transportToolbar); optionalToolbars.push_back(panicToolbar); - //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. + QSocketNotifier* ss = new QSocketNotifier(MusEGlobal::audio->getFromThreadFdr(), QSocketNotifier::Read, this); + connect(ss, SIGNAL(activated(int)), MusEGlobal::song, SLOT(seqSignal(int))); - 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)) - MusEGlobal::realTimePriority = sched_get_priority_max(SCHED_FIFO); - - // If we requested to force the midi thread priority... - if(MusEGlobal::midiRTPrioOverride > 0) - { - if (MusEGlobal::midiRTPrioOverride < sched_get_priority_min(SCHED_FIFO)) - MusEGlobal::midiRTPrioOverride = sched_get_priority_min(SCHED_FIFO); - else if (MusEGlobal::midiRTPrioOverride > sched_get_priority_max(SCHED_FIFO)) - MusEGlobal::midiRTPrioOverride = sched_get_priority_max(SCHED_FIFO); - } - - 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 //--------------------------------------------------- @@ -924,6 +895,10 @@ MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow() arrangerView->hide(); _arranger=arrangerView->getArranger(); + connect(tempo_tb_widget, SIGNAL(returnPressed()), arrangerView, SLOT(focusCanvas())); + connect(tempo_tb_widget, SIGNAL(escapePressed()), arrangerView, SLOT(focusCanvas())); + connect(sig_tb_widget, SIGNAL(returnPressed()), arrangerView, SLOT(focusCanvas())); + connect(sig_tb_widget, SIGNAL(escapePressed()), arrangerView, SLOT(focusCanvas())); //--------------------------------------------------- // read list of "Recent Projects" @@ -952,8 +927,6 @@ MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow() fclose(f); } - MusECore::initMidiSynth(); - arrangerView->populateAddTrack(); arrangerView->updateShortcuts(); @@ -968,15 +941,8 @@ MusE::MusE(int /*argc*/, char** /*argv*/) : QMainWindow() MusEGlobal::song->update(); updateWindowMenu(); - - // Load start song now in main.cpp } - -MusE::~MusE() -{ -} - //--------------------------------------------------------- // setHeartBeat //--------------------------------------------------------- @@ -998,6 +964,7 @@ void MusE::loadDefaultSong(int argc, char** argv) { QString name; bool useTemplate = false; + bool loadConfig = true; if (argc >= 2) name = argv[0]; else if (MusEGlobal::config.startMode == 0) { @@ -1008,15 +975,34 @@ void MusE::loadDefaultSong(int argc, char** argv) 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"); + if(MusEGlobal::config.startSong.isEmpty()) // Sanity check to avoid some errors later + { + name = MusEGlobal::museGlobalShare + QString("/templates/default.med"); + loadConfig = false; + } + else + { + name = MusEGlobal::config.startSong; + loadConfig = MusEGlobal::config.startSongLoadConfig; + } useTemplate = true; + printf("starting with template %s\n", name.toLatin1().constData()); } else if (MusEGlobal::config.startMode == 2) { + if(MusEGlobal::config.startSong.isEmpty()) // Sanity check to avoid some errors later + { + name = MusEGlobal::museGlobalShare + QString("/templates/default.med"); + useTemplate = true; + loadConfig = false; + } + else + { + name = MusEGlobal::config.startSong; + loadConfig = MusEGlobal::config.startSongLoadConfig; + } printf("starting with pre configured song %s\n", MusEGlobal::config.startSong.toLatin1().constData()); - name = MusEGlobal::config.startSong; } - loadProjectFile(name, useTemplate, !useTemplate); + loadProjectFile(name, useTemplate, loadConfig); } //--------------------------------------------------------- @@ -1360,15 +1346,11 @@ void MusE::loadProject() void MusE::loadTemplate() { + bool doReadMidiPorts; QString fn = MusEGui::getOpenFileName(QString("templates"), MusEGlobal::med_file_pattern, this, - tr("MusE: load template"), 0, MusEGui::MFileDialog::GLOBAL_VIEW); + tr("MusE: load template"), &doReadMidiPorts, MusEGui::MFileDialog::GLOBAL_VIEW); if (!fn.isEmpty()) { - // With templates, don't clear midi ports. - // Any named ports in the template file are useless (Hm, not true...) since they likely would not be found on other users' machines. - // Keep whatever the user currently has set up for ports. This will also keep the current window configurations etc. - // but actually that's also probably a good thing. - loadProjectFile(fn, true, false); - + loadProjectFile(fn, true, doReadMidiPorts); setUntitledProject(); } } @@ -1545,6 +1527,10 @@ void MusE::closeEvent(QCloseEvent* event) delete MusEGlobal::midiSeq; delete MusEGlobal::song; + if(MusEGlobal::debugMsg) + printf("MusE: Deleting icons\n"); + deleteIcons(); + qApp->quit(); } @@ -1597,7 +1583,7 @@ void MusE::markerClosed() 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()); + printf("bringing '%s' to front instead of closed marker window\n",(*lit)->widget()->windowTitle().toAscii().data()); bringToFront((*lit)->widget()); @@ -1960,16 +1946,29 @@ void MusE::startSongInfo(bool editable) void MusE::showDidYouKnowDialog() { if ((bool)MusEGlobal::config.showDidYouKnow == true) { - MusEGui::DidYouKnowWidget dyk; - dyk.tipText->setText("To get started with MusE why don't you try some demo songs available at http://demos.muse-sequencer.org/"); - dyk.show(); - if( dyk.exec()) { - if (dyk.dontShowCheckBox->isChecked()) { - MusEGlobal::config.showDidYouKnow=false; - MusEGlobal::muse->changeConfig(true); // save settings - } - } - } + MusEGui::DidYouKnowWidget dyk; + + QFile file(MusEGlobal::museGlobalShare + "/didyouknow.txt"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + printf("could not open didyouknow.txt!\n"); + return; + } + + while (!file.atEnd()) { + dyk.tipList.append(file.readLine()); + } + + //dyk.tipList.append(tr("To get started with MusE why don't you visit the tutorials at <br><a href=\"http://muse-sequencer.org\">http://muse-sequencer.org/index.php/Support</a>")); + //dyk.tipList.append(tr("MusE can act as a realtime audio mixer if you connect it to jack!")); + + dyk.show(); + if( dyk.exec()) { + if (dyk.dontShowCheckBox->isChecked()) { + MusEGlobal::config.showDidYouKnow=false; + MusEGlobal::muse->changeConfig(true); // save settings + } + } + } } //--------------------------------------------------------- // startDefineController @@ -2297,17 +2296,16 @@ void MusE::configAppearance() void MusE::loadTheme(const QString& s) { QStringList sl = QStyleFactory::keys(); - if (sl.indexOf(s) == -1) { + if (s.isEmpty() || sl.indexOf(s) == -1) { if(MusEGlobal::debugMsg) - printf("Set style does not exist, setting default."); - QApplication::setStyle(Appearance::defaultStyle); - style()->setObjectName(Appearance::defaultStyle); - + printf("Set style does not exist, setting default.\n"); + qApp->setStyle(Appearance::defaultStyle); + qApp->style()->setObjectName(Appearance::defaultStyle); } - else if (style()->objectName() != s) + else if (qApp->style()->objectName() != s) { - QApplication::setStyle(s); - style()->setObjectName(s); // p4.0.45 + qApp->setStyle(s); + qApp->style()->setObjectName(s); } } @@ -2748,9 +2746,28 @@ void MusE::startEditInstrument() void MusE::switchMixerAutomation() { + // Could be intensive, try idling instead of a single message. + MusEGlobal::audio->msgIdle(true); + MusEGlobal::automation = ! MusEGlobal::automation; // Clear all pressed and touched and rec event lists. MusEGlobal::song->clearRecAutomation(true); + + // If going to OFF mode, need to update current 'manual' values from the automation values at this time... + if(!MusEGlobal::automation) + { + MusECore::TrackList* tracks = MusEGlobal::song->tracks(); + for (MusECore::iTrack i = tracks->begin(); i != tracks->end(); ++i) { + if ((*i)->isMidiTrack()) + continue; + MusECore::AudioTrack* track = static_cast<MusECore::AudioTrack*>(*i); + if(track->automationType() != AUTO_OFF) // && track->automationType() != AUTO_WRITE) + track->controller()->updateCurValues(MusEGlobal::audio->curFramePos()); + } + } + + MusEGlobal::audio->msgIdle(false); + autoMixerAction->setChecked(MusEGlobal::automation); } @@ -2760,7 +2777,24 @@ void MusE::switchMixerAutomation() void MusE::clearAutomation() { - printf("not implemented\n"); + QMessageBox::StandardButton b = QMessageBox::warning(this, appName, + tr("This will clear all automation data on\n all audio tracks!\nProceed?"), + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel); + + if(b != QMessageBox::Ok) + return; + + // Could be intensive, try idling instead of a single message. + MusEGlobal::audio->msgIdle(true); + + MusECore::TrackList* tracks = MusEGlobal::song->tracks(); + for (MusECore::iTrack i = tracks->begin(); i != tracks->end(); ++i) { + if ((*i)->isMidiTrack()) + continue; + static_cast<MusECore::AudioTrack*>(*i)->controller()->clearAllAutomation(); + } + + MusEGlobal::audio->msgIdle(false); } //--------------------------------------------------------- @@ -2769,18 +2803,35 @@ void MusE::clearAutomation() void MusE::takeAutomationSnapshot() { - int frame = MusEGlobal::song->cPos().frame(); + QMessageBox::StandardButton b = QMessageBox::warning(this, appName, + tr("This takes an automation snapshot of\n all controllers on all audio tracks,\n" + " at the current position.\nProceed?"), + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel); + + if(b != QMessageBox::Ok) + return; + + // Could be intensive, try idling instead of a single message. + MusEGlobal::audio->msgIdle(true); + + int frame = MusEGlobal::audio->curFramePos(); MusECore::TrackList* tracks = MusEGlobal::song->tracks(); for (MusECore::iTrack i = tracks->begin(); i != tracks->end(); ++i) { if ((*i)->isMidiTrack()) continue; - MusECore::AudioTrack* track = (MusECore::AudioTrack*)*i; - MusECore::CtrlListList* cll = track->controller(); + MusECore::AudioTrack* track = static_cast<MusECore::AudioTrack*>(*i); + MusECore::CtrlListList* cll = track->controller(); + // Need to update current 'manual' values from the automation values at this time. + if(track->automationType() != AUTO_OFF) // && track->automationType() != AUTO_WRITE) + cll->updateCurValues(frame); + for (MusECore::iCtrlList icl = cll->begin(); icl != cll->end(); ++icl) { double val = icl->second->curVal(); icl->second->add(frame, val); } } + + MusEGlobal::audio->msgIdle(false); } //--------------------------------------------------------- @@ -3008,6 +3059,14 @@ void MusE::focusChanged(QWidget* old, QWidget* now) printf(" old type: %s\n", typeid(*old).name()); if(now) printf(" now type: %s\n", typeid(*now).name()); + if (dynamic_cast<QMdiSubWindow*>(now)!=0) + { + QWidget* tmp=dynamic_cast<QMdiSubWindow*>(now)->widget(); + if (tmp) + printf(" subwin contains %p which is a %s\n", tmp, typeid(*tmp).name()); + else + printf(" subwin contains NULL\n"); + } if(qApp->activeWindow()) printf(" activeWindow type: %s\n", typeid(*qApp->activeWindow()).name()); printf("\n"); @@ -3073,8 +3132,17 @@ void MusE::focusChanged(QWidget* old, QWidget* now) if ( (dynamic_cast<QMdiSubWindow*>(ptr)!=0) && (dynamic_cast<MusEGui::TopWin*>( ((QMdiSubWindow*)ptr)->widget() )!=0) ) { - waitingForTopwin=(MusEGui::TopWin*) ((QMdiSubWindow*)ptr)->widget(); - return; + MusEGui::TopWin* tmp = (MusEGui::TopWin*) ((QMdiSubWindow*)ptr)->widget(); + if (tmp->initalizing()) + { + waitingForTopwin=tmp; + return; + } + else + { + ptr=tmp; + // go on. + } } while (ptr) @@ -3149,7 +3217,7 @@ void MusE::setCurrentMenuSharingTopwin(MusEGui::TopWin* win) for (list<QToolBar*>::iterator it = foreignToolbars.begin(); it!=foreignToolbars.end(); it++) if (*it) { - if (MusEGlobal::debugMsg) printf(" removing sharer's toolbar '%s'\n", (*it)->windowTitle().toAscii().data()); + if (MusEGlobal::heavyDebugMsg) printf(" removing sharer's toolbar '%s'\n", (*it)->windowTitle().toAscii().data()); removeToolBar(*it); // this does not delete *it, which is good (*it)->setParent(NULL); } @@ -3161,7 +3229,7 @@ void MusE::setCurrentMenuSharingTopwin(MusEGui::TopWin* win) for (list<QToolBar*>::iterator it = optionalToolbars.begin(); it!=optionalToolbars.end(); it++) if (*it) { - if (MusEGlobal::debugMsg) printf(" removing optional toolbar '%s'\n", (*it)->windowTitle().toAscii().data()); + if (MusEGlobal::heavyDebugMsg) printf(" removing optional toolbar '%s'\n", (*it)->windowTitle().toAscii().data()); removeToolBar(*it); // this does not delete *it, which is good (*it)->setParent(NULL); } @@ -3181,7 +3249,7 @@ void MusE::setCurrentMenuSharingTopwin(MusEGui::TopWin* win) const QList<QAction*>& actions=win->menuBar()->actions(); for (QList<QAction*>::const_iterator it=actions.begin(); it!=actions.end(); it++) { - if (MusEGlobal::debugMsg) printf(" menu entry '%s'\n", (*it)->text().toAscii().data()); + if (MusEGlobal::heavyDebugMsg) printf(" adding menu entry '%s'\n", (*it)->text().toAscii().data()); menuBar()->addAction(*it); } @@ -3192,7 +3260,7 @@ void MusE::setCurrentMenuSharingTopwin(MusEGui::TopWin* win) for (list<QToolBar*>::const_iterator it=toolbars.begin(); it!=toolbars.end(); it++) if (*it) { - if (MusEGlobal::debugMsg) printf(" toolbar '%s'\n", (*it)->windowTitle().toAscii().data()); + if (MusEGlobal::heavyDebugMsg) printf(" adding toolbar '%s'\n", (*it)->windowTitle().toAscii().data()); addToolBar(*it); foreignToolbars.push_back(*it); @@ -3200,7 +3268,7 @@ void MusE::setCurrentMenuSharingTopwin(MusEGui::TopWin* win) } else { - if (MusEGlobal::debugMsg) printf(" toolbar break\n"); + if (MusEGlobal::heavyDebugMsg) printf(" adding toolbar break\n"); addToolBarBreak(); foreignToolbars.push_back(NULL); @@ -3260,6 +3328,13 @@ void MusE::topwinMenuInited(MusEGui::TopWin* topwin) emit activeTopWinChanged(activeTopWin); } } + else if (topwin == currentMenuSharingTopwin) + { + printf("====== DEBUG ======: topwin's menu got inited AFTER being shared!\n"); + if (!topwin->sharesToolsAndMenu()) printf("====== ======: WTF, now it doesn't share any more?!?\n"); + setCurrentMenuSharingTopwin(NULL); + setCurrentMenuSharingTopwin(topwin); + } } void MusE::updateWindowMenu() diff --git a/muse2/muse/app.h b/muse2/muse/app.h index 2976708b..4831e61d 100644 --- a/muse2/muse/app.h +++ b/muse2/muse/app.h @@ -367,8 +367,7 @@ class MusE : public QMainWindow void updateWindowMenu(); public: - MusE(int argc, char** argv); - ~MusE(); + MusE(); void loadDefaultSong(int argc, char** argv); Arranger* arranger() const { return _arranger; } ArrangerView* getArrangerView() const { return arrangerView; } diff --git a/muse2/muse/appearance.cpp b/muse2/muse/appearance.cpp index 319a8826..0ae3bf6b 100644 --- a/muse2/muse/appearance.cpp +++ b/muse2/muse/appearance.cpp @@ -27,7 +27,6 @@ #include <QFontDialog> #include <QStyleFactory> #include <QToolTip> -#include <QByteArray> #include <QFile> #include <QFileDialog> #include <QFileInfo> @@ -543,7 +542,7 @@ void Appearance::apply() config->fonts[6].setItalic(italic6->isChecked()); config->fonts[6].setBold(bold6->isChecked()); - config->style = themeComboBox->currentText(); + config->style = themeComboBox->currentIndex() == 0 ? QString() : themeComboBox->currentText(); // setting up a new theme might change the fontsize, so re-read fontSize0->setValue(QApplication::font().pointSize()); diff --git a/muse2/muse/arranger/arranger.cpp b/muse2/muse/arranger/arranger.cpp index 55275ddc..29e69582 100644 --- a/muse2/muse/arranger/arranger.cpp +++ b/muse2/muse/arranger/arranger.cpp @@ -23,7 +23,7 @@ #include "config.h" #include <stdio.h> -#include <values.h> +#include <limits.h> #include <QComboBox> #include <QGridLayout> @@ -73,7 +73,7 @@ namespace MusEGui { std::vector<Arranger::custom_col_t> Arranger::custom_columns; //FINDMICH TODO: eliminate all usage of new_custom_columns std::vector<Arranger::custom_col_t> Arranger::new_custom_columns; //and instead let the arranger update without restarting muse! -QString Arranger::header_state; +QByteArray Arranger::header_state; void Arranger::writeCustomColumns(int level, MusECore::Xml& xml) { @@ -211,7 +211,7 @@ Arranger::Arranger(ArrangerView* parent, const char* name) selected = 0; showTrackinfoFlag = true; - cursVal = MAXINT; + cursVal = INT_MAX; parentWin=parent; @@ -372,10 +372,44 @@ Arranger::Arranger(ArrangerView* parent, const char* name) ib->setFocusPolicy(Qt::NoFocus); connect(ib, SIGNAL(toggled(bool)), SLOT(showTrackInfo(bool))); - list=NULL; - header=NULL; - tgrid=NULL; - updateTListHeader(); + // set up the header + header = new Header(tracklist, "header"); + header->setFixedHeight(30); + + QFontMetrics fm1(header->font()); + int fw = 8; + + header->setColumnLabel(tr("R"), COL_RECORD, fm1.width('R')+fw); + header->setColumnLabel(tr("M"), COL_MUTE, fm1.width('M')+fw); + header->setColumnLabel(tr("S"), COL_SOLO, fm1.width('S')+fw); + header->setColumnLabel(tr("C"), COL_CLASS, fm1.width('C')+fw); + header->setColumnLabel(tr("Track"), COL_NAME, 100); + header->setColumnLabel(tr("Port"), COL_OPORT, 60); + header->setColumnLabel(tr("Ch"), COL_OCHANNEL, 30); + header->setColumnLabel(tr("T"), COL_TIMELOCK, fm1.width('T')+fw); + header->setColumnLabel(tr("Automation"), COL_AUTOMATION, 75); + header->setColumnLabel(tr("Clef"), COL_CLEF, 75); + for (unsigned i=0;i<custom_columns.size();i++) + header->setColumnLabel(custom_columns[i].name, COL_CUSTOM_MIDICTRL_OFFSET+i, MAX(fm1.width(custom_columns[i].name)+fw, 30)); + header->setResizeMode(COL_RECORD, QHeaderView::Fixed); + header->setResizeMode(COL_MUTE, QHeaderView::Fixed); + header->setResizeMode(COL_SOLO, QHeaderView::Fixed); + header->setResizeMode(COL_CLASS, QHeaderView::Fixed); + header->setResizeMode(COL_NAME, QHeaderView::Interactive); + header->setResizeMode(COL_OPORT, QHeaderView::Interactive); + header->setResizeMode(COL_OCHANNEL, QHeaderView::Fixed); + header->setResizeMode(COL_TIMELOCK, QHeaderView::Fixed); + header->setResizeMode(COL_AUTOMATION, QHeaderView::Interactive); + header->setResizeMode(COL_CLEF, QHeaderView::Interactive); + for (unsigned i=0;i<custom_columns.size();i++) + header->setResizeMode(COL_CUSTOM_MIDICTRL_OFFSET+i, QHeaderView::Interactive); + + setHeaderToolTips(); + setHeaderWhatsThis(); + header->setMovable (true); + header->restoreState(header_state); + + list = new TList(header, tracklist, "tracklist"); // Do this now that the list is available. @@ -454,17 +488,14 @@ Arranger::Arranger(ArrangerView* parent, const char* name) connect(canvas, SIGNAL(selectTrackBelow()), list, SLOT(selectTrackBelow())); connect(canvas, SIGNAL(horizontalZoomIn()), SLOT(horizontalZoomIn())); connect(canvas, SIGNAL(horizontalZoomOut()), SLOT(horizontalZoomOut())); - if(MusEGlobal::config.smartFocus) - { - connect(lenEntry, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(lenEntry, SIGNAL(escapePressed()), SLOT(focusCanvas())); - connect(globalPitchSpinBox, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(globalPitchSpinBox, SIGNAL(escapePressed()), SLOT(focusCanvas())); - connect(globalTempoSpinBox, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(globalTempoSpinBox, SIGNAL(escapePressed()), SLOT(focusCanvas())); - connect(midiTrackInfo, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(midiTrackInfo, SIGNAL(escapePressed()), SLOT(focusCanvas())); - } + connect(lenEntry, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(lenEntry, SIGNAL(escapePressed()), SLOT(focusCanvas())); + connect(globalPitchSpinBox, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(globalPitchSpinBox, SIGNAL(escapePressed()), SLOT(focusCanvas())); + connect(globalTempoSpinBox, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(globalTempoSpinBox, SIGNAL(escapePressed()), SLOT(focusCanvas())); + connect(midiTrackInfo, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(midiTrackInfo, SIGNAL(escapePressed()), SLOT(focusCanvas())); //connect(this, SIGNAL(redirectWheelEvent(QWheelEvent*)), canvas, SLOT(redirectedWheelEvent(QWheelEvent*))); connect(list, SIGNAL(redirectWheelEvent(QWheelEvent*)), canvas, SLOT(redirectedWheelEvent(QWheelEvent*))); @@ -517,65 +548,6 @@ Arranger::Arranger(ArrangerView* parent, const char* name) } -void Arranger::updateTListHeader() // TODO FIXME FINDMICHJETZT this doesn't work properly :/ -{ - if (header) - { - header_state=header->getStatus(); - delete header; - } - - header = new Header(tracklist, "header"); - - header->setFixedHeight(30); - - QFontMetrics fm1(header->font()); - int fw = 8; - - header->setColumnLabel(tr("R"), COL_RECORD, fm1.width('R')+fw); - header->setColumnLabel(tr("M"), COL_MUTE, fm1.width('M')+fw); - header->setColumnLabel(tr("S"), COL_SOLO, fm1.width('S')+fw); - header->setColumnLabel(tr("C"), COL_CLASS, fm1.width('C')+fw); - header->setColumnLabel(tr("Track"), COL_NAME, 100); - header->setColumnLabel(tr("Port"), COL_OPORT, 60); - header->setColumnLabel(tr("Ch"), COL_OCHANNEL, 30); - header->setColumnLabel(tr("T"), COL_TIMELOCK, fm1.width('T')+fw); - header->setColumnLabel(tr("Automation"), COL_AUTOMATION, 75); - header->setColumnLabel(tr("Clef"), COL_CLEF, 75); - for (unsigned i=0;i<custom_columns.size();i++) - header->setColumnLabel(custom_columns[i].name, COL_CUSTOM_MIDICTRL_OFFSET+i, MAX(fm1.width(custom_columns[i].name)+fw, 30)); - header->setResizeMode(COL_RECORD, QHeaderView::Fixed); - header->setResizeMode(COL_MUTE, QHeaderView::Fixed); - header->setResizeMode(COL_SOLO, QHeaderView::Fixed); - header->setResizeMode(COL_CLASS, QHeaderView::Fixed); - header->setResizeMode(COL_NAME, QHeaderView::Interactive); - header->setResizeMode(COL_OPORT, QHeaderView::Interactive); - header->setResizeMode(COL_OCHANNEL, QHeaderView::Fixed); - header->setResizeMode(COL_TIMELOCK, QHeaderView::Fixed); - header->setResizeMode(COL_AUTOMATION, QHeaderView::Interactive); - header->setResizeMode(COL_CLEF, QHeaderView::Interactive); - for (unsigned i=0;i<custom_columns.size();i++) - header->setResizeMode(COL_CUSTOM_MIDICTRL_OFFSET+i, QHeaderView::Interactive); - - setHeaderToolTips(); - setHeaderWhatsThis(); - header->setMovable (true); - header->setStatus(header_state); - - if (list) - { - list->setHeader(header); - connect(header, SIGNAL(sectionResized(int,int,int)), list, SLOT(redraw())); - connect(header, SIGNAL(sectionMoved(int,int,int)), list, SLOT(redraw())); - connect(header, SIGNAL(sectionMoved(int,int,int)), this, SLOT(headerMoved())); - } - - if (tgrid) - { - tgrid->wadd(2, header); - } -} - // DELETETHIS 20 //--------------------------------------------------------- // updateHScrollRange @@ -602,7 +574,7 @@ void Arranger::updateTListHeader() // TODO FIXME FINDMICHJETZT this doesn't work void Arranger::setTime(unsigned tick) { - if (tick == MAXINT) + if (tick == INT_MAX) cursorPos->setEnabled(false); else { cursVal = tick; @@ -651,8 +623,11 @@ void Arranger::configChanged() void Arranger::focusCanvas() { - canvas->setFocus(); - canvas->activateWindow(); + if(MusEGlobal::config.smartFocus) + { + canvas->setFocus(); + canvas->activateWindow(); + } } //--------------------------------------------------------- @@ -696,7 +671,7 @@ void Arranger::songChanged(int type) if(type & SC_SONG_TYPE) setMode(MusEGlobal::song->mtype()); - if(type & SC_SELECTION) // TEST p4.0.36 Try this alone, may need more. + if(type & (SC_SELECTION | SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED)) trackSelectionChanged(); // Keep this light, partsChanged is a heavy move! TEST p4.0.36 Try these, may need more. @@ -771,8 +746,7 @@ void Arranger::modeChange(int mode) { MusEGlobal::song->setMType(MType(mode)); updateTrackInfo(-1); - if(MusEGlobal::config.smartFocus) - focusCanvas(); + focusCanvas(); } //--------------------------------------------------------- @@ -807,7 +781,7 @@ void Arranger::writeConfiguration(int level, MusECore::Xml& xml) { xml.tag(level++, "arranger"); writeCustomColumns(level, xml); - xml.strTag(level, "tlist_header", header->getStatus()); + xml.strTag(level, "tlist_header", header->saveState().toHex().constData()); xml.etag(level, "arranger"); } @@ -826,7 +800,7 @@ void Arranger::readConfiguration(MusECore::Xml& xml) return; case MusECore::Xml::TagStart: if (tag == "tlist_header") - header_state = xml.parse1(); + header_state = QByteArray::fromHex(xml.parse1().toAscii()); else if (tag == "custom_columns") readCustomColumns(xml); else @@ -894,8 +868,7 @@ void Arranger::_setRaster(int index) // Set the audio record part snapping. MusEGlobal::song->setArrangerRaster(_raster); canvas->redraw(); - if(MusEGlobal::config.smartFocus) - focusCanvas(); + focusCanvas(); } //--------------------------------------------------------- @@ -1199,8 +1172,8 @@ void Arranger::updateTrackInfo(int flags) } if (selected->isMidiTrack()) { switchInfo(1); - // If a new part was selected, and only if it's different. - if((flags & SC_SELECTION) && midiTrackInfo->track() != selected) + // If a different part was selected + if(midiTrackInfo->track() != selected) // Set a new track and do a complete update. midiTrackInfo->setTrack(selected); else diff --git a/muse2/muse/arranger/arranger.h b/muse2/muse/arranger/arranger.h index 8873e2af..e51ec068 100644 --- a/muse2/muse/arranger/arranger.h +++ b/muse2/muse/arranger/arranger.h @@ -112,7 +112,7 @@ class ScrollBar : public QScrollBar { class Arranger : public QWidget { Q_OBJECT - static QString header_state; + static QByteArray header_state; int _quant, _raster; PartCanvas* canvas; @@ -167,7 +167,6 @@ class Arranger : public QWidget { void verticalScrollSetYpos(unsigned); void horizontalZoomIn(); void horizontalZoomOut(); - void focusCanvas(); signals: void editPart(MusECore::Track*); @@ -188,7 +187,7 @@ class Arranger : public QWidget { void updateTrackInfo(int flags); void configChanged(); void controllerChanged(MusECore::Track *t); - void updateTListHeader(); + void focusCanvas(); public: enum { CMD_CUT_PART, CMD_COPY_PART, CMD_COPY_PART_IN_RANGE, CMD_PASTE_PART, CMD_PASTE_CLONE_PART, diff --git a/muse2/muse/arranger/arrangerview.cpp b/muse2/muse/arranger/arrangerview.cpp index da510c0e..57c12d15 100644 --- a/muse2/muse/arranger/arrangerview.cpp +++ b/muse2/muse/arranger/arrangerview.cpp @@ -352,7 +352,7 @@ ArrangerView::ArrangerView(QWidget* parent) connect(cb, SIGNAL(dataChanged()), SLOT(clipboardChanged())); connect(cb, SIGNAL(selectionChanged()), SLOT(clipboardChanged())); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); // work around for probable QT/WM interaction bug. // for certain window managers, e.g xfce, this window is diff --git a/muse2/muse/arranger/arrangerview.h b/muse2/muse/arranger/arrangerview.h index 98e7f01c..570dcd80 100644 --- a/muse2/muse/arranger/arrangerview.h +++ b/muse2/muse/arranger/arrangerview.h @@ -39,7 +39,7 @@ #include <QByteArray> #include <QToolButton> -#include <values.h> +#include <limits.h> #include "noteinfo.h" #include "cobject.h" #include "event.h" @@ -139,6 +139,7 @@ class ArrangerView : public TopWin void selectionChanged(); void updateShortcuts(); void updateVisibleTracksButtons(); + virtual void focusCanvas() { arranger->focusCanvas(); } public: ArrangerView(QWidget* parent = 0); diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index f3e71916..cc23b59b 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -25,7 +25,7 @@ #include <sys/stat.h> #include <sys/mman.h> #include <errno.h> -#include <values.h> +#include <limits.h> #include <uuid/uuid.h> #include <math.h> #include <map> @@ -80,6 +80,8 @@ NPart::NPart(MusECore::Part* e) : CItem(MusECore::Event(), e) leftBorderTouches = false; rightBorderTouches = false; + _serial=e->sn(); + int y = track()->y(); setPos(QPoint(e->tick(), y)); setBBox(QRect(e->tick(), y, e->lenTick(), track()->height())); @@ -155,7 +157,7 @@ int PartCanvas::pitch2y(int p) const void PartCanvas::leaveEvent(QEvent*) { - emit timeChanged(MAXINT); + emit timeChanged(INT_MAX); } //--------------------------------------------------------- @@ -215,7 +217,7 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) emit dclickPart(((NPart*)(curItem))->track()); } } - // + // double click creates new part between left and // right mark @@ -226,7 +228,7 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) int y = event->y(); for (it = tl->begin(); it != tl->end(); ++it) { int h = (*it)->height(); - if (y >= yy && y < (yy + h)) + if (y >= yy && y < (yy + h) && (*it)->isVisible()) break; yy += h; } @@ -395,7 +397,7 @@ bool PartCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& // But just in case we ever have two different lists... dpart->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it // so we must decrement it first :/ - spart->events()->incARef(1); // the later MusEGlobal::song->applyOperationGroup() will decrement it + spart->events()->incARef(1); // the later MusEGlobal::song->applyOperationGroup() will decrement it // so we must increment it first :/ dpart->setSelected(spart->selected()); // These will increment ref count if not a clone, and will chain clones... @@ -444,23 +446,24 @@ void PartCanvas::songIsClearing() void PartCanvas::partsChanged() { int sn = -1; - if (curItem) sn=curItem->part()->sn(); - curItem=NULL; + if (curItem) sn=static_cast<NPart*>(curItem)->serial(); + curItem=NULL; items.clearDelete(); for (MusECore::iTrack t = tracks->begin(); t != tracks->end(); ++t) { + if ((*t)->isVisible()) //ignore parts from hidden tracks + { MusECore::PartList* pl = (*t)->parts(); for (MusECore::iPart i = pl->begin(); i != pl->end(); ++i) { MusECore::Part* part = i->second; NPart* np = new NPart(part); items.add(np); - if (np->part()->sn() == sn) + if (np->serial() == sn) curItem=np; - if (i->second->selected()) { + if (i->second->selected()) selectItem(np, true); - } // Check for touching borders. p4.0.29 MusECore::Part* pp; @@ -476,10 +479,11 @@ void PartCanvas::partsChanged() if(pp->tick() == part->endTick()) np->rightBorderTouches = true; } - } } - redraw(); + } } + redraw(); +} //--------------------------------------------------------- // updateSelection @@ -868,10 +872,10 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt) // viewMousePressEvent //--------------------------------------------------------- -void PartCanvas::mousePress(QMouseEvent* event) +bool PartCanvas::mousePress(QMouseEvent* event) { if (event->modifiers() & Qt::ControlModifier) { - return; + return true; } QPoint pt = event->pos(); CItem* item = items.find(pt); @@ -900,10 +904,26 @@ void PartCanvas::mousePress(QMouseEvent* event) } } case AutomationTool: - if (automation.controllerState != doNothing) - automation.moveController=true; - break; + if (event->button() & Qt::RightButton) { + QMenu *automationMenu = new QMenu(this); + QAction* act; + act = automationMenu->addAction(tr("Remove selected")); + act = automationMenu->exec(event->globalPos()); + if (act && automation.currentTrack) { + foreach(int frame, automation.currentCtrlFrameList) + MusEGlobal::audio->msgEraseACEvent((MusECore::AudioTrack*)automation.currentTrack, + automation.currentCtrlList->id(), frame); + } + + } + else { + if (automation.controllerState != doNothing) + automation.moveController=true; + } + return false; + break; } + return true; } //--------------------------------------------------------- @@ -3317,11 +3337,9 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) //-------------------------------- MusECore::TrackList* tl = MusEGlobal::song->tracks(); - //int yy = 0; int yy = -rmapy(yorg) - ypos; int th; for (MusECore::iTrack it = tl->begin(); it != tl->end(); ++it) { - //if (yy > y + h) if (yy > my + mh) break; MusECore::Track* track = *it; @@ -3331,9 +3349,7 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) if (MusEGlobal::config.canvasShowGrid && (track->isMidiTrack() || track->type() == MusECore::Track::WAVE)) // Tim. { p.setPen(baseColor.dark(130)); - //p.drawLine(x, yy + th, x + w, yy + th); p.drawLine(mx, yy + th, mx + mw, yy + th); - //p.setPen(baseColor); } // The update rectangle (rect and mr etc) is clipped at x<0 and y<0 in View::pdraw(). @@ -3346,26 +3362,10 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) // does NOT depend on the update rectangle (except to check intersection). That's why this issue // does not show up there. Should probably try to make that routine more efficient, just like here. Tim. p4.0.30 QRect r(mx, yy, mw, th); - //if(r.intersects(mr)) DELETETHIS { if (!track->isMidiTrack() && (track->type() != MusECore::Track::WAVE)) { - //QRect r = rect & QRect(x, yy, w, track->height()); drawAudioTrack(p, mr, r, (MusECore::AudioTrack*)track); - //p.setPen(baseColor); - } - - // DELETETHIS 13 - // This was redundant drawing. Not required, done via drawTopItem in Canvas::draw - /* - //p.setWorldMatrixEnabled(true); - //if (!track->isMidiTrack()) { // draw automation - if (!track->isMidiTrack() && (track->type() != MusECore::Track::WAVE)) { - //QRect r = rect & QRect(x, yy, w, track->height()); - drawAutomation(p, r, (MusECore::AudioTrack*)track); - //p.setPen(baseColor); - } - //p.setWorldMatrixEnabled(false); - */ + } } yy += th; } @@ -3378,8 +3378,7 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) //--------------------------------------------------------- void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) { - //QRect mr = p.transform().mapRect(rect); // Gives inconsistent positions. Source shows wrong operation for our needs. - QRect mr = map(rect); // Use our own map instead. + QRect mr = map(rect); int mx = mr.x(); int my = mr.y(); @@ -3396,7 +3395,6 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) int yy = yoff; int th; for (MusECore::iTrack it = tl->begin(); it != tl->end(); ++it) { - //if (yy > y + h) DELETETHIS if (yy > my + mh) break; MusECore::Track* track = *it; @@ -3404,15 +3402,12 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) if (!th) continue; if (!track->isMidiTrack()) { // draw automation - //QRect r = rect & QRect(x, yy, w, track->height()); DELETETHIS QRect r(mx, yy, mw, th); if(r.intersects(mr)) { drawAutomation(p, r, (MusECore::AudioTrack*)track); - //p.setPen(baseColor); DELETETHIS } } - //yy += track->height(); DELETETHIS yy += th; } @@ -3631,13 +3626,25 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra //p.drawRect(mapx(MusEGlobal::tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5); //p.drawRect(mapx(MusEGlobal::tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3); pen2.setColor((automation.currentCtrlValid && automation.currentCtrlList == cl && - automation.currentCtrlFrame == ic->second.frame) ? + automation.currentCtrlFrameList.contains(ic->second.frame)) ? Qt::white : cl->color()); p.setPen(pen2); p.drawRect(xpixel-2, ypixel-2, 5, 5); oldX = xpixel; oldY = ypixel; + if (automation.currentCtrlValid && automation.currentCtrlList == cl && + automation.currentCtrlFrameList.contains(ic->second.frame) && + automation.currentCtrlFrameList.size() == 1) { + double val = ic->second.val; + QRect textRect = rr; + textRect.setX(xpixel + 20); + textRect.setY(ypixel); + if (cl->valueType() == MusECore::VAL_LOG) { + val = MusECore::fast_log10(ic->second.val) * 20.0; + } + p.drawText(textRect, QString("Value: %1").arg(val)); + } } } if (xpixel <= rr.right()) @@ -3648,6 +3655,42 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra } } +//--------------------------------------------------------- +// checkIfOnLine +// check if our point is on the line defined by +// by first/last X/Y +//--------------------------------------------------------- + +bool checkIfOnLine(double mouseX, double mouseY, double firstX, double lastX, double firstY, double lastY, int circumference) +{ + double proportion = (mouseX-firstX)/(lastX-firstX); + + // 10 X(15) 20 + // proportion = 0.5 + // 10 + // / + // Y(5) + // / + // 1 + double calcY = (lastY-firstY)*proportion+firstY; + if(ABS(calcY-mouseY) < circumference || (lastX == firstX && ABS(mouseX-lastX) < circumference)) + return true; + return false; +} + +//--------------------------------------------------------- +// checkIfNearPoint +//--------------------------------------------------------- + +bool checkIfNearPoint(int mouseX, int mouseY, int eventX, int eventY, int circumference) +{ + int x1 = ABS(mouseX - eventX) ; + int y1 = ABS(mouseY - eventY); + if (x1 < circumference && y1 < circumference) { + return true; + } + return false; +} //--------------------------------------------------------- // checkAutomation @@ -3660,22 +3703,22 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra // controller added. //--------------------------------------------------------- -void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, bool addNewCtrl) +void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, bool NOTaddNewCtrl) { if (t->isMidiTrack()) return; - int currY; + int mouseY; int trackY = t->y(); int trackH = t->height(); { int y = pointer.y(); if(y < trackY || y >= (trackY + trackH)) return; - currY = mapy(y); } + mouseY = mapy(y); } - int currX = mapx(pointer.x()); - int circumference = 5; + int mouseX = mapx(pointer.x()); + int circumference = 10; MusECore::CtrlListList* cll = ((MusECore::AudioTrack*) t)->controller(); for(MusECore::CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll) @@ -3686,15 +3729,15 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo } MusECore::iCtrl ic=cl->begin(); - int oldX = mapx(0); - int xpixel = oldX; - int oldY = -1; - int ypixel = oldY; + int eventOldX = mapx(0); + int eventX = eventOldX; + int eventOldY = -1; + int eventY = eventOldY; double min, max; cl->range(&min,&max); bool discrete = cl->mode() == MusECore::CtrlList::DISCRETE; - // First check that there IS automation, ic == cl->end means no automation + // First check that there IS automation for this controller, ic == cl->end means no automation if (ic == cl->end()) { double y; @@ -3704,93 +3747,65 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo } else y = (cl->curVal() - min)/(max-min); // we need to set curVal between 0 and 1 - ypixel = oldY = mapy(trackY+trackH-1 - 2 - y * trackH); + eventY = eventOldY = mapy(trackY+trackH-1 - 2 - y * trackH); } - else + else // we have automation, loop through it { for (; ic !=cl->end(); ic++) { double y = ic->second.val; if (cl->valueType() == MusECore::VAL_LOG ) { // use db scale for volume - y = logToVal(y, min, max); // represent volume between 0 and 1 + y = logToVal(y, min, max); // represent volume between 0 and 1 if (y < 0) y = 0; } else y = (y-min)/(max-min); // we need to set curVal between 0 and 1 - ypixel = mapy(trackY + trackH - 2 - y * trackH); - xpixel = mapx(MusEGlobal::tempomap.frame2tick(ic->second.frame)); + eventY = mapy(trackY + trackH - 2 - y * trackH); + eventX = mapx(MusEGlobal::tempomap.frame2tick(ic->second.frame)); - if (oldY==-1) oldY = ypixel; + if (eventOldY==-1) eventOldY = eventY; - bool foundIt=false; - if (addNewCtrl) { - double firstX=oldX; - double lastX=xpixel; - double firstY=oldY; - double lastY = discrete ? oldY : ypixel; - - double proportion = (currX-firstX)/(lastX-firstX); - - if((currX < oldX) || (currX > lastX) || (firstX==lastX) ) - { - oldX = xpixel; - oldY = ypixel; - continue; // not the right region - } - - // 10 X(15) 20 - // proportion = 0.5 - // 10 - // / - // Y(5) - // / - // 1 - double calcY = (lastY-firstY)*proportion+firstY; - if(ABS(calcY-currY) < circumference || (xpixel == oldX && ABS(currX-xpixel) < circumference)) - foundIt=true; - - } else { - int x1 = ABS(currX - xpixel) ; - int y1 = ABS(currY - ypixel); - if (x1 < circumference && y1 < circumference && pointer.x() > 0 && pointer.y() > 0) { - foundIt=true; - } - - } - oldX = xpixel; - oldY = ypixel; - - if (foundIt) { - QWidget::setCursor(Qt::CrossCursor); - if (addNewCtrl) { - //automation.currentCtrl = 0; + //if (addNewCtrl) { + bool onLine = checkIfOnLine(mouseX, mouseY, eventOldX,eventX, eventOldY, discrete? eventOldY:eventY, circumference); + bool onPoint = false; + if ( pointer.x() > 0 && pointer.y() > 0) + onPoint = checkIfNearPoint(mouseX, mouseY, eventX, eventY, circumference); + + eventOldX = eventX; + eventOldY = eventY; + + if (onLine) { + if (!onPoint) { + QWidget::setCursor(Qt::CrossCursor); automation.currentCtrlValid = false; automation.controllerState = addNewController; }else { - automation.currentCtrlFrame = ic->second.frame; + QWidget::setCursor(Qt::OpenHandCursor); + automation.currentCtrlFrameList.clear(); + automation.currentCtrlFrameList.append(ic->second.frame); automation.currentCtrlValid = true; automation.controllerState = movingController; } automation.currentCtrlList = cl; automation.currentTrack = t; + update(); return; } } } - if (addNewCtrl) { - // check if we are reasonably close to a line, we only need to check Y - // as the line is straight after the last controller - //printf("post oldX:%d oldY:%d xpixel:%d ypixel:%d currX:%d currY:%d\n", oldX, oldY, xpixel, ypixel, currX, currY); - if(currX >= xpixel && ypixel == oldY && ABS(currY-ypixel) < circumference) { - QWidget::setCursor(Qt::CrossCursor); - automation.controllerState = addNewController; - automation.currentCtrlList = cl; - automation.currentTrack = t; - automation.currentCtrlValid = false; - return; - } + // we are now after the last existing controller + // check if we are reasonably close to a line, we only need to check Y + // as the line is straight after the last controller + //printf("post oldX:%d oldY:%d xpixel:%d ypixel:%d currX:%d currY:%d\n", oldX, oldY, xpixel, ypixel, currX, currY); + if(mouseX >= eventX && eventY == eventOldY && ABS(mouseY-eventY) < circumference) { + QWidget::setCursor(Qt::CrossCursor); + automation.controllerState = addNewController; + automation.currentCtrlList = cl; + automation.currentTrack = t; + automation.currentCtrlValid = false; + return; } } // if there are no hits we default to clearing all the data @@ -3798,6 +3813,7 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo automation.currentCtrlValid = false; automation.currentCtrlList = 0; automation.currentTrack = 0; + automation.currentCtrlFrameList.clear(); setCursor(); } @@ -3820,10 +3836,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) } // automation.moveController is set, lets rock. - int prevFrame = 0; int nextFrame = -1; - int currFrame = 0; if (automation.controllerState == addNewController) { @@ -3835,7 +3849,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) for (; ic !=automation.currentCtrlList->end(); ++ic) { MusECore::CtrlVal &cv = ic->second; if (cv.frame == frame) { - automation.currentCtrlFrame = cv.frame; + automation.currentCtrlFrameList.clear(); + automation.currentCtrlFrameList.append(cv.frame); automation.currentCtrlValid = true; automation.controllerState = movingController; break; @@ -3849,9 +3864,9 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) for (; ic !=automation.currentCtrlList->end(); ++ic) { MusECore::CtrlVal &cv = ic->second; - if (cv.frame == automation.currentCtrlFrame) + if (automation.currentCtrlFrameList.contains(cv.frame)) { - currFrame = cv.frame; + //currFrame = cv.frame; break; } prevFrame = cv.frame; @@ -3885,7 +3900,7 @@ 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 - printf("log conversion val=%f min=%f max=%f\n", yfraction, min, max); + //printf("log conversion val=%f min=%f max=%f\n", yfraction, min, max); cvval = valToLog(yfraction, min, max); if (cvval< min) cvval=min; if (cvval>max) cvval=max; @@ -3900,7 +3915,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) if (cvval>max) cvval=max; } - automation.currentCtrlFrame = newFrame; + automation.currentCtrlFrameList.clear(); + automation.currentCtrlFrameList.append(newFrame); automation.currentCtrlValid = true; if(icc != automation.currentCtrlList->end()) diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h index 7882ee5c..ab227eb2 100644 --- a/muse2/muse/arranger/pcanvas.h +++ b/muse2/muse/arranger/pcanvas.h @@ -59,19 +59,24 @@ class MidiEditor; //--------------------------------------------------------- class NPart : public CItem { + protected: + int _serial; + public: NPart(MusECore::Part* e); const QString name() const { return part()->name(); } void setName(const QString& s) { part()->setName(s); } MusECore::Track* track() const { return part()->track(); } + int serial() { return _serial; } bool leftBorderTouches; // Whether the borders touch other part borders. bool rightBorderTouches; + }; enum ControllerVals { doNothing, movingController, addNewController }; struct AutomationObject { - int currentCtrlFrame; + QList<int> currentCtrlFrameList; bool currentCtrlValid; MusECore::CtrlList *currentCtrlList; MusECore::Track *currentTrack; @@ -99,7 +104,7 @@ class PartCanvas : public Canvas { AutomationObject automation; virtual void keyPress(QKeyEvent*); - virtual void mousePress(QMouseEvent*); + virtual bool mousePress(QMouseEvent*); virtual void mouseMove(QMouseEvent* event); virtual void mouseRelease(const QPoint&); virtual void viewMouseDoubleClickEvent(QMouseEvent*); diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index be997504..3d831ba9 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -34,6 +34,7 @@ #include <QWheelEvent> #include <QIcon> #include <QSpinBox> +#include <QToolTip> #include "popupmenu.h" #include "globals.h" @@ -164,6 +165,38 @@ void TList::redraw(const QRect& r) update(r); } + +//--------------------------------------------------------- +// event +//--------------------------------------------------------- + +bool TList::event(QEvent *event) +{ + if (event->type() == QEvent::ToolTip) { + QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event); + MusECore::TrackList* l = MusEGlobal::song->tracks(); + int idx = 0; + int yy = -ypos; + for (MusECore::iTrack i = l->begin(); i != l->end(); ++idx, yy += (*i)->height(), ++i) { + MusECore::Track* track = *i; + MusECore::Track::TrackType type = track->type(); + int trackHeight = track->height(); + if (trackHeight==0) // not visible + continue; + if (helpEvent->pos().y() > yy && helpEvent->pos().y() < yy + trackHeight) { + if (type == MusECore::Track::AUDIO_SOFTSYNTH) { + MusECore::SynthI *s = (MusECore::SynthI*)track; + QToolTip::showText(helpEvent->globalPos(),track->name() + " : " + s->synth()->description()); + } + else + QToolTip::showText(helpEvent->globalPos(),track->name()); + } + } + return true; + } + return QWidget::event(event); +} + //--------------------------------------------------------- // paint //--------------------------------------------------------- diff --git a/muse2/muse/arranger/tlist.h b/muse2/muse/arranger/tlist.h index ff25f16c..d3701451 100644 --- a/muse2/muse/arranger/tlist.h +++ b/muse2/muse/arranger/tlist.h @@ -115,6 +115,8 @@ class TList : public QWidget { void setHeaderToolTips(); PopupMenu* colorMenu(QColor c, int id, QWidget* parent); + protected: + bool event(QEvent *); private slots: void maybeUpdateVolatileCustomColumns(); // updates AFFECT_CPOS-columns when and only when the hwState has changed void returnPressed(); diff --git a/muse2/muse/audio.cpp b/muse2/muse/audio.cpp index 80bffafe..cbcbd922 100644 --- a/muse2/muse/audio.cpp +++ b/muse2/muse/audio.cpp @@ -59,13 +59,9 @@ void initAudio() { MusEGlobal::audio = new Audio(); } - extern double curTime(); -//static const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 }; DELETETHIS 2 -//static const unsigned char mmcStopMsg[] = { 0x7f, 0x7f, 0x06, 0x01 }; - const char* seqMsgList[] = { "SEQM_ADD_TRACK", "SEQM_REMOVE_TRACK", //"SEQM_CHANGE_TRACK", DELETETHIS "SEQM_MOVE_TRACK", @@ -82,6 +78,7 @@ const char* seqMsgList[] = { "SEQM_SET_HW_CTRL_STATES", "SEQM_SET_TRACK_OUT_PORT", "SEQM_SET_TRACK_OUT_CHAN", + "SEQM_SET_TRACK_AUTO_TYPE", "SEQM_REMAP_PORT_DRUM_CTL_EVS", "SEQM_CHANGE_ALL_PORT_DRUM_CTL_EVS", "SEQM_SCAN_ALSA_MIDI_PORTS", @@ -216,9 +213,8 @@ bool Audio::start() } } + _running = true; // Set before we start to avoid error messages in process. MusEGlobal::audioDevice->start(MusEGlobal::realTimePriority); - - _running = true; // shall we really stop JACK transport and locate to // saved position? @@ -715,6 +711,10 @@ void Audio::processMsg(AudioMsg* msg) MusEGlobal::midiSeq->sendMsg(msg); break; + case SEQM_SET_TRACK_AUTO_TYPE: + msg->track->setAutomationType(AutomationType(msg->ival)); + break; + case SEQM_IDLE: idle = msg->a; MusEGlobal::midiSeq->sendMsg(msg); @@ -976,10 +976,7 @@ void Audio::recordStop() if(ao->recordFlag()) { MusEGlobal::song->bounceOutput = 0; - SndFile* sf = ao->recFile(); - if (sf) - delete sf; // close - ao->setRecFile(0); + ao->setRecFile(NULL); // if necessary, this automatically deletes _recFile ao->setRecordFlag1(false); msgSetRecord(ao, false); } @@ -990,17 +987,44 @@ void Audio::recordStop() } //--------------------------------------------------------- +// framesSinceCycleStart +// Estimated frames since the last process cycle began +//--------------------------------------------------------- + +unsigned Audio::framesSinceCycleStart() const +{ + return lrint((curTime() - syncTime) * MusEGlobal::sampleRate); +} + +//--------------------------------------------------------- +// curFramePos() +// Current play position frame. Estimated to single-frame resolution while in play mode. +//--------------------------------------------------------- + +unsigned Audio::curFramePos() const +{ + return _pos.frame() + (isPlaying() ? framesSinceCycleStart() : 0); +} + +//--------------------------------------------------------- // curFrame -// extrapolates current play frame on syncTime/syncFrame +// Extrapolates current play frame on syncTime/syncFrame +// Estimated to single-frame resolution. +// This is an always-increasing number. Good for timestamps, and +// handling them during process when referenced to syncFrame. //--------------------------------------------------------- unsigned int Audio::curFrame() const { - return lrint((curTime() - syncTime) * MusEGlobal::sampleRate) + syncFrame; + //return lrint((curTime() - syncTime) * MusEGlobal::sampleRate) + syncFrame; + return framesSinceCycleStart() + syncFrame; } //--------------------------------------------------------- // timestamp +// Estimated to single-frame resolution. +// This is an always-increasing number in play mode, but in stop mode +// it is circular (about the cur pos, width = segment size). //--------------------------------------------------------- int Audio::timestamp() const diff --git a/muse2/muse/audio.h b/muse2/muse/audio.h index 723c378c..a9d2cc82 100644 --- a/muse2/muse/audio.h +++ b/muse2/muse/audio.h @@ -44,7 +44,6 @@ class MidiPort; class MidiTrack; class Part; class PluginI; -class SndFile; class SynthI; class Track; @@ -71,6 +70,7 @@ enum { SEQM_SET_HW_CTRL_STATES, SEQM_SET_TRACK_OUT_PORT, SEQM_SET_TRACK_OUT_CHAN, + SEQM_SET_TRACK_AUTO_TYPE, SEQM_REMAP_PORT_DRUM_CTL_EVS, SEQM_CHANGE_ALL_PORT_DRUM_CTL_EVS, SEQM_SCAN_ALSA_MIDI_PORTS, @@ -106,7 +106,7 @@ extern const char* seqMsgList[]; // for debug struct AudioMsg : public ThreadMsg { // this should be an union int serialNo; - SndFile* downmix; + //SndFile* downmix; // DELETETHIS this is unused and probably WRONG (all SndFiles have been replaced by SndFileRs) AudioTrack* snode; AudioTrack* dnode; Route sroute, droute; @@ -284,6 +284,7 @@ class Audio { void msgSetHwCtrlStates(MidiPort*, int, int, int, int); void msgSetTrackOutChannel(MidiTrack*, int); void msgSetTrackOutPort(MidiTrack*, int); + void msgSetTrackAutomationType(Track*, int); void msgRemapPortDrumCtlEvents(int, int, int, int); void msgChangeAllPortDrumCtrlEvents(bool, bool); void msgSetSendMetronome(AudioTrack*, bool); @@ -303,8 +304,10 @@ class Audio { unsigned nextTick() const { return nextTickPos; } int timestamp() const; void processMidi(); + unsigned framesSinceCycleStart() const; unsigned curFrame() const; unsigned curSyncFrame() const { return syncFrame; } + unsigned curFramePos() const; void recordStop(); bool freewheel() const { return _freewheel; } void setFreewheel(bool val); diff --git a/muse2/muse/audioprefetch.cpp b/muse2/muse/audioprefetch.cpp index 92689ddb..830019f9 100644 --- a/muse2/muse/audioprefetch.cpp +++ b/muse2/muse/audioprefetch.cpp @@ -24,7 +24,7 @@ #include <poll.h> #include <stdio.h> #include <unistd.h> -#include <values.h> +#include <limits.h> #include "audioprefetch.h" #include "globals.h" diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp index 981cdada..b0c52a54 100644 --- a/muse2/muse/audiotrack.cpp +++ b/muse2/muse/audiotrack.cpp @@ -21,7 +21,7 @@ // //========================================================= -#include <values.h> +#include <limits.h> #include <stdlib.h> #include <map> @@ -101,7 +101,7 @@ AudioTrack::AudioTrack(TrackType t) _sendMetronome = false; _prefader = false; _efxPipe = new Pipeline(); - _recFile = 0; + //_recFile = 0; //unneeded, _recFile's ctor does this _channels = 0; _automationType = AUTO_OFF; setChannels(2); @@ -118,7 +118,7 @@ AudioTrack::AudioTrack(TrackType t) // This is only set by multi-channel syntis... _totalInChannels = 0; - bufferPos = MAXINT; + bufferPos = INT_MAX; setVolume(1.0); } @@ -136,7 +136,7 @@ AudioTrack::AudioTrack(const AudioTrack& t, int flags) // This is only set by multi-channel syntis... _totalInChannels = 0; - bufferPos = MAXINT; + bufferPos = INT_MAX; _recFile = NULL; @@ -207,9 +207,6 @@ void AudioTrack::internal_assign(const Track& t, int flags) } } - // FIXME: May get "addRoute: src track route already exists" when say, - // an audio output and wave track are selected just because - // of the redundancy (wave track wants to connect to output by default). if(flags & ASSIGN_ROUTES) { for(ciRoute ir = at._inRoutes.begin(); ir != at._inRoutes.end(); ++ir) @@ -217,8 +214,8 @@ void AudioTrack::internal_assign(const Track& t, int flags) // Defer all Jack routes to Audio Input and Output copy constructors or assign ! if(ir->type == Route::JACK_ROUTE) continue; - // Amazingly, this single line seems to work. - MusEGlobal::audio->msgAddRoute(*ir, Route(this, ir->channel, ir->channels)); + // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node. + _inRoutes.push_back(*ir); } for(ciRoute ir = at._outRoutes.begin(); ir != at._outRoutes.end(); ++ir) @@ -226,8 +223,8 @@ void AudioTrack::internal_assign(const Track& t, int flags) // Defer all Jack routes to Audio Input and Output copy constructors or assign ! if(ir->type == Route::JACK_ROUTE) continue; - // Amazingly, this single line seems to work. - MusEGlobal::audio->msgAddRoute(Route(this, ir->channel, ir->channels), *ir); + // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node. + _outRoutes.push_back(*ir); } } else if(flags & ASSIGN_DEFAULT_ROUTES) @@ -241,11 +238,13 @@ void AudioTrack::internal_assign(const Track& t, int flags) switch(type()) { case Track::WAVE: case Track::AUDIO_AUX: - MusEGlobal::audio->msgAddRoute(Route(this, -1), Route(ao, -1)); + // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node. + _outRoutes.push_back(Route(ao, -1)); break; // It should actually never get here now, but just in case. case Track::AUDIO_SOFTSYNTH: - MusEGlobal::audio->msgAddRoute(Route(this, 0, channels()), Route(ao, 0, channels())); + // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node. + _outRoutes.push_back(Route(ao, 0, channels())); break; default: break; @@ -688,11 +687,11 @@ void AudioTrack::seekPrevACEvent(int id) if(cl->empty()) return; - iCtrl s = cl->lower_bound(MusEGlobal::audio->pos().frame()); // p4.0.33 + iCtrl s = cl->lower_bound(MusEGlobal::audio->pos().frame()); if(s != cl->begin()) --s; - MusEGlobal::song->setPos(Song::CPOS, Pos(s->second.frame, false), false, true, false); // p4.0.33 + MusEGlobal::song->setPos(Song::CPOS, Pos(s->second.frame, false), false, true, false); return; } @@ -710,14 +709,14 @@ void AudioTrack::seekNextACEvent(int id) if(cl->empty()) return; - iCtrl s = cl->upper_bound(MusEGlobal::audio->pos().frame()); // p4.0.33 + iCtrl s = cl->upper_bound(MusEGlobal::audio->pos().frame()); if(s == cl->end()) { --s; } - MusEGlobal::song->setPos(Song::CPOS, Pos(s->second.frame, false), false, true, false); // p4.0.33 + MusEGlobal::song->setPos(Song::CPOS, Pos(s->second.frame, false), false, true, false); return; } @@ -800,15 +799,8 @@ void AudioTrack::changeACEvent(int id, int frame, int newframe, double newval) double AudioTrack::volume() const { - ciCtrlList cl = _controller.find(AC_VOLUME); - if (cl == _controller.end()) - return 0.0; - - if (MusEGlobal::automation && - automationType() != AUTO_OFF && _volumeEnCtrl && _volumeEn2Ctrl ) - return cl->second->value(MusEGlobal::song->cPos().frame()); - else - return cl->second->curVal(); + return _controller.value(AC_VOLUME, MusEGlobal::audio->curFramePos(), + !MusEGlobal::automation || automationType() == AUTO_OFF || !_volumeEnCtrl || !_volumeEn2Ctrl); } //--------------------------------------------------------- @@ -832,15 +824,8 @@ void AudioTrack::setVolume(double val) double AudioTrack::pan() const { - ciCtrlList cl = _controller.find(AC_PAN); - if (cl == _controller.end()) - return 0.0; - - if (MusEGlobal::automation && - automationType() != AUTO_OFF && _panEnCtrl && _panEn2Ctrl ) - return cl->second->value(MusEGlobal::song->cPos().frame()); - else - return cl->second->curVal(); + return _controller.value(AC_PAN, MusEGlobal::audio->curFramePos(), + !MusEGlobal::automation || automationType() == AUTO_OFF || !_volumeEnCtrl || !_volumeEn2Ctrl); } //--------------------------------------------------------- @@ -863,14 +848,8 @@ void AudioTrack::setPan(double val) double AudioTrack::pluginCtrlVal(int ctlID) const { - ciCtrlList cl = _controller.find(ctlID); - if (cl == _controller.end()) - return 0.0; - - if (MusEGlobal::automation && (automationType() != AUTO_OFF)) - return cl->second->value(MusEGlobal::song->cPos().frame()); - else - return cl->second->curVal(); + return _controller.value(ctlID, MusEGlobal::audio->curFramePos(), + !MusEGlobal::automation || automationType() == AUTO_OFF); } //--------------------------------------------------------- @@ -891,11 +870,11 @@ void AudioTrack::recordAutomation(int n, double v) if(!MusEGlobal::automation) return; if(MusEGlobal::audio->isPlaying()) - _recEvents.push_back(CtrlRecVal(MusEGlobal::song->cPos().frame(), n, v)); + _recEvents.push_back(CtrlRecVal(MusEGlobal::audio->curFramePos(), n, v)); else { if(automationType() == AUTO_WRITE) - _recEvents.push_back(CtrlRecVal(MusEGlobal::song->cPos().frame(), n, v)); + _recEvents.push_back(CtrlRecVal(MusEGlobal::audio->curFramePos(), n, v)); else if(automationType() == AUTO_TOUCH) // In touch mode and not playing. Send directly to controller list. @@ -904,7 +883,7 @@ void AudioTrack::recordAutomation(int n, double v) if (cl == _controller.end()) return; // Add will replace if found. - cl->second->add(MusEGlobal::song->cPos().frame(), v); + cl->second->add(MusEGlobal::audio->curFramePos(), v); } } } @@ -916,25 +895,26 @@ void AudioTrack::startAutoRecord(int n, double v) if(MusEGlobal::audio->isPlaying()) { if(automationType() == AUTO_TOUCH) - _recEvents.push_back(CtrlRecVal(MusEGlobal::song->cPos().frame(), n, v, ARVT_START)); + _recEvents.push_back(CtrlRecVal(MusEGlobal::audio->curFramePos(), n, v, ARVT_START)); else if(automationType() == AUTO_WRITE) - _recEvents.push_back(CtrlRecVal(MusEGlobal::song->cPos().frame(), n, v)); + _recEvents.push_back(CtrlRecVal(MusEGlobal::audio->curFramePos(), n, v)); } else { if(automationType() == AUTO_TOUCH) // In touch mode and not playing. Send directly to controller list. { + // FIXME: Unsafe? Should sync by sending a message, but that'll really slow it down with large audio bufs. iCtrlList cl = _controller.find(n); if (cl == _controller.end()) return; // Add will replace if found. - cl->second->add(MusEGlobal::song->cPos().frame(), v); + cl->second->add(MusEGlobal::audio->curFramePos(), v); } else if(automationType() == AUTO_WRITE) - _recEvents.push_back(CtrlRecVal(MusEGlobal::song->cPos().frame(), n, v)); + _recEvents.push_back(CtrlRecVal(MusEGlobal::audio->curFramePos(), n, v)); } } @@ -946,8 +926,8 @@ void AudioTrack::stopAutoRecord(int n, double v) { if(automationType() == AUTO_TOUCH) { - MusEGlobal::audio->msgAddACEvent(this, n, MusEGlobal::song->cPos().frame(), v); - _recEvents.push_back(CtrlRecVal(MusEGlobal::song->cPos().frame(), n, v, ARVT_STOP)); + MusEGlobal::audio->msgAddACEvent(this, n, MusEGlobal::audio->curFramePos(), v); + _recEvents.push_back(CtrlRecVal(MusEGlobal::audio->curFramePos(), n, v, ARVT_STOP)); } } } @@ -1087,7 +1067,7 @@ bool AudioTrack::readProperties(Xml& xml, const QString& tag) if(p && m < p->parameters()) ctlfound = true; } - // Support a special block for dssi synth ladspa controllers. p4.0.20 + // Support a special block for dssi synth ladspa controllers. else if(n == MAX_PLUGINS && type() == AUDIO_SOFTSYNTH) { SynthI* synti = dynamic_cast < SynthI* > (this); @@ -1330,70 +1310,6 @@ void AudioTrack::mapRackPluginsToControllers() */ } -// DELETETHIS 60 -/* -//--------------------------------------------------------- -// writeRouting -//--------------------------------------------------------- - -void AudioTrack::writeRouting(int level, Xml& xml) const -{ - QString n; - if (type() == Track::AUDIO_INPUT) { - ciJackRouteNameCache circ = jackRouteNameCache.find(this); - if(circ != jackRouteNameCache.end()) - { - jackRouteNameMap rm = circ->second; - for(ciJackRouteNameMap cirm = rm.begin(); cirm != rm.end(); ++cirm) - { - n = cirm->second; - if(!n.isEmpty()) - { - Route dst(name(), true, cirm->first); - xml.tag(level++, "Route"); - xml.strTag(level, "srcNode", n); - xml.strTag(level, "dstNode", dst.name()); - xml.etag(level--, "Route"); - } - } - } - } - if(type() == Track::AUDIO_OUTPUT) - { - ciJackRouteNameCache circ = jackRouteNameCache.find(this); - if(circ != jackRouteNameCache.end()) - { - jackRouteNameMap rm = circ->second; - for(ciJackRouteNameMap cirm = rm.begin(); cirm != rm.end(); ++cirm) - { - n = cirm->second; - if(!n.isEmpty()) - { - Route src(name(), false, cirm->first); - xml.tag(level++, "Route"); - xml.strTag(level, "srcNode", src.name()); - xml.strTag(level, "dstNode", n); - xml.etag(level--, "Route"); - } - } - } - } - else - { - const RouteList* rl = &_outRoutes; - for (ciRoute r = rl->begin(); r != rl->end(); ++r) { - if(!r->name().isEmpty()) - { - xml.tag(level++, "Route"); - xml.strTag(level, "srcNode", name()); - xml.strTag(level, "dstNode", r->name()); - xml.etag(level--, "Route"); - } - } - } -} -*/ - //--------------------------------------------------------- // AudioInput //--------------------------------------------------------- @@ -1446,7 +1362,9 @@ void AudioInput::internal_assign(const Track& t, int flags) // Defer all Jack routes to these copy constructors or assign ! if(ir->type != Route::JACK_ROUTE) continue; - MusEGlobal::audio->msgAddRoute(*ir, Route(this, ir->channel, ir->channels)); + // FIXME Must use msgAddRoute instead of _inRoutes.push_back, because it connects to Jack. + // The track is still fresh has not been added to track lists yet. Will cause audio processing problems ? + MusEGlobal::audio->msgAddRoute(*ir, Route(this, ir->channel, ir->channels)); } } } @@ -1556,7 +1474,9 @@ void AudioOutput::internal_assign(const Track& t, int flags) // Defer all Jack routes to these copy constructors or assign ! if(ir->type != Route::JACK_ROUTE) continue; - MusEGlobal::audio->msgAddRoute(Route(this, ir->channel, ir->channels), *ir); + // FIXME Must use msgAddRoute instead of _outRoutes.push_back, because it connects to Jack. + // The track is still fresh has not been added to track lists yet. Will cause audio processing problems ? + MusEGlobal::audio->msgAddRoute(Route(this, ir->channel, ir->channels), *ir); } } } @@ -1744,7 +1664,7 @@ void AudioAux::read(Xml& xml) 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 + // Make sure all the aux-supporting tracks are processed first so aux data is gathered. TrackList* tl = MusEGlobal::song->tracks(); AudioTrack* track; for(ciTrack it = tl->begin(); it != tl->end(); ++it) @@ -1803,7 +1723,7 @@ bool AudioTrack::setRecordFlag1(bool f) if (f == _recordFlag) return true; if (f) { - if (_recFile == 0 && MusEGlobal::song->record()) { + if (_recFile.isNull() && MusEGlobal::song->record()) { // this rec-enables a track if the global arm already was done // the standard case would be that rec-enable be done there prepareRecording(); @@ -1819,8 +1739,7 @@ bool AudioTrack::setRecordFlag1(bool f) // recording, the _recFile pointer is made into an event, // then _recFile is made zero before this function is called. QString s = _recFile->path(); - delete _recFile; - setRecFile(0); + setRecFile(NULL); remove(s.toLatin1().constData()); if(MusEGlobal::debugMsg) @@ -1843,7 +1762,7 @@ bool AudioTrack::prepareRecording() if(MusEGlobal::debugMsg) printf("prepareRecording for track %s\n", _name.toLatin1().constData()); - if (_recFile == 0) { + if (_recFile.isNull()) { // // create soundfile for recording // diff --git a/muse2/muse/cliplist/cliplist.cpp b/muse2/muse/cliplist/cliplist.cpp index f610805e..1f54f9b4 100644 --- a/muse2/muse/cliplist/cliplist.cpp +++ b/muse2/muse/cliplist/cliplist.cpp @@ -38,7 +38,7 @@ namespace MusEGui { extern int mtcType; -enum { COL_NAME=0, COL_REFS, COL_POS, COL_LEN }; +enum { COL_NAME=0, COL_REFS, COL_SAMPLERATE, COL_LEN }; //--------------------------------------------------------- // ClipItem @@ -57,10 +57,10 @@ class ClipItem : public QTreeWidgetItem { ClipItem::ClipItem(QTreeWidget* parent, const MusECore::SndFileR& w) : QTreeWidgetItem(parent), _wf(w) { - setText(COL_NAME, _wf.name()); - setText(COL_REFS, QString().setNum(_wf.getRefCount())); - setText(COL_POS, QString().setNum(_wf.samplerate())); - setText(COL_LEN, QString().setNum(_wf.samples())); + setText(COL_NAME, _wf.name()); + setText(COL_REFS, QString().setNum(_wf.getRefCount())); + setText(COL_SAMPLERATE, QString().setNum(_wf.samplerate())); + setText(COL_LEN, QString().setNum(_wf.samples())); } //--------------------------------------------------------- @@ -140,9 +140,7 @@ ClipListEdit::ClipListEdit(QWidget* parent) QFontMetrics fm(editor->view->font()); int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth,0, this); // ddskrjo 0 int w = 2 + fm.width('9') * 9 + fm.width(':') * 3 + fw * 4; - //editor->view->setColumnAlignment(COL_POS, Qt::AlignRight); - editor->view->setColumnWidth(COL_POS, w); - //editor->view->setColumnAlignment(COL_LEN, Qt::AlignRight); + editor->view->setColumnWidth(COL_SAMPLERATE, w); editor->view->setColumnWidth(COL_LEN, w); connect(editor->view, SIGNAL(itemSelectionChanged()), SLOT(clipSelectionChanged())); @@ -153,7 +151,7 @@ ClipListEdit::ClipListEdit(QWidget* parent) connect(editor->len, SIGNAL(valueChanged(const MusECore::Pos&)), SLOT(lenChanged(const MusECore::Pos&))); updateList(); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); } ClipListEdit::~ClipListEdit() diff --git a/muse2/muse/cobject.cpp b/muse2/muse/cobject.cpp index 1407a7a0..b7f257ae 100644 --- a/muse2/muse/cobject.cpp +++ b/muse2/muse/cobject.cpp @@ -52,6 +52,8 @@ bool TopWin::initInited=false; TopWin::TopWin(ToplevelType t, QWidget* parent, const char* name, Qt::WindowFlags f) : QMainWindow(parent, f) { + _initalizing = true; + _isDeleting = false; if (initInited==false) initConfiguration(); @@ -128,13 +130,19 @@ TopWin::TopWin(ToplevelType t, QWidget* parent, const char* name, Qt::WindowFlag QToolBar* tempo_tb; tempo_tb = addToolBar(tr("Tempo")); tempo_tb->setObjectName("Tempo"); - tempo_tb->addWidget(new MusEGui::TempoToolbarWidget(tempo_tb)); + MusEGui::TempoToolbarWidget* tw = new MusEGui::TempoToolbarWidget(tempo_tb); + tempo_tb->addWidget(tw); QToolBar* sig_tb; sig_tb = addToolBar(tr("Signature")); sig_tb->setObjectName("Signature"); - sig_tb->addWidget(new MusEGui::SigToolbarWidget(tempo_tb)); - + MusEGui::SigToolbarWidget* sw = new MusEGui::SigToolbarWidget(tempo_tb); + sig_tb->addWidget(sw); + + connect(tw, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(tw, SIGNAL(escapePressed()), SLOT(focusCanvas())); + connect(sw, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(sw, SIGNAL(escapePressed()), SLOT(focusCanvas())); } @@ -565,6 +573,12 @@ void TopWin::writeConfiguration(ToplevelType t, int level, MusECore::Xml& xml) xml.etag(level, "topwin"); } +void TopWin::finalizeInit() +{ + MusEGlobal::muse->topwinMenuInited(this); + _initalizing=false; +} + void TopWin::initTopwinState() { if (sharesToolsAndMenu()) diff --git a/muse2/muse/cobject.h b/muse2/muse/cobject.h index d58bb823..751186c6 100644 --- a/muse2/muse/cobject.h +++ b/muse2/muse/cobject.h @@ -62,6 +62,7 @@ class TopWin : public QMainWindow ToplevelType type() const { return _type; } static QString typeName(ToplevelType t); + bool initalizing() const { return _initalizing; } bool deleting() const { return _isDeleting; } virtual void readStatus(MusECore::Xml&); @@ -93,6 +94,7 @@ class TopWin : public QMainWindow QMdiSubWindow* mdisubwin; bool _sharesToolsAndMenu; std::list<QToolBar*> _toolbars; + bool _initalizing; void insertToolBar(QToolBar*, QToolBar*); void insertToolBarBreak(QToolBar*); @@ -124,6 +126,7 @@ class TopWin : public QMainWindow // which may cause a crash while deleting. bool _isDeleting; + void finalizeInit(); void initTopwinState(); private slots: @@ -138,7 +141,7 @@ class TopWin : public QMainWindow void restoreMainwinState(); void storeInitialState() const; virtual void setWindowTitle (const QString&); - + virtual void focusCanvas() { } }; diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp index f35fd6b2..6c5c93db 100644 --- a/muse2/muse/conf.cpp +++ b/muse2/muse/conf.cpp @@ -876,6 +876,8 @@ void readConfiguration(Xml& xml, bool doReadMidiPortConfig, bool doReadGlobalCon MusEGlobal::config.startMode = xml.parseInt(); else if (tag == "startSong") MusEGlobal::config.startSong = xml.parse1(); + else if (tag == "startSongLoadConfig") + MusEGlobal::config.startSongLoadConfig = xml.parseInt(); else if (tag == "newDrumRecordCondition") MusEGlobal::config.newDrumRecordCondition = MusECore::newDrumRecordCondition_t(xml.parseInt()); else if (tag == "projectBaseFolder") @@ -1183,6 +1185,7 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const xml.intTag(level, "importMidiSplitParts", MusEGlobal::config.importMidiSplitParts); xml.intTag(level, "startMode", MusEGlobal::config.startMode); xml.strTag(level, "startSong", MusEGlobal::config.startSong); + xml.intTag(level, "startSongLoadConfig", MusEGlobal::config.startSongLoadConfig); xml.intTag(level, "newDrumRecordCondition", MusEGlobal::config.newDrumRecordCondition); xml.strTag(level, "projectBaseFolder", MusEGlobal::config.projectBaseFolder); xml.intTag(level, "projectStoreInFolder", MusEGlobal::config.projectStoreInFolder); diff --git a/muse2/muse/confmport.cpp b/muse2/muse/confmport.cpp index d3aef647..637e927e 100644 --- a/muse2/muse/confmport.cpp +++ b/muse2/muse/confmport.cpp @@ -734,28 +734,31 @@ void MPConfig::rbClicked(QTableWidgetItem* item) printf("MPConfig::rbClicked unknown midi device: %s\n", (*i)->name().toLatin1().constData()); } - pup->addSeparator(); - pup->addAction(new MusEGui::MenuTitleItem("ALSA:", pup)); - - for(imap i = mapALSA.begin(); i != mapALSA.end(); ++i) + if(!mapALSA.empty()) { - int idx = i->second; - //if(idx > sz) // Sanity check DELETETHIS 2 - // continue; - QString s(i->first.c_str()); - MusECore::MidiDevice* md = MusEGlobal::midiDevices.find(s, MusECore::MidiDevice::ALSA_MIDI); - if(md) + pup->addSeparator(); + pup->addAction(new MusEGui::MenuTitleItem("ALSA:", pup)); + + for(imap i = mapALSA.begin(); i != mapALSA.end(); ++i) { - //if(!dynamic_cast<MidiAlsaDevice*>(md)) DELETETHIS - if(md->deviceType() != MusECore::MidiDevice::ALSA_MIDI) - continue; - - act = pup->addAction(md->name()); - act->setData(idx); - act->setCheckable(true); - act->setChecked(md == dev); + int idx = i->second; + //if(idx > sz) // Sanity check DELETETHIS 2 + // continue; + QString s(i->first.c_str()); + MusECore::MidiDevice* md = MusEGlobal::midiDevices.find(s, MusECore::MidiDevice::ALSA_MIDI); + if(md) + { + //if(!dynamic_cast<MidiAlsaDevice*>(md)) DELETETHIS + if(md->deviceType() != MusECore::MidiDevice::ALSA_MIDI) + continue; + + act = pup->addAction(md->name()); + act->setData(idx); + act->setCheckable(true); + act->setChecked(md == dev); + } } - } + } if(!mapSYNTH.empty()) { @@ -780,24 +783,27 @@ void MPConfig::rbClicked(QTableWidgetItem* item) } } - pup->addSeparator(); - pup->addAction(new MusEGui::MenuTitleItem("JACK:", pup)); - - for(imap i = mapJACK.begin(); i != mapJACK.end(); ++i) + if(!mapJACK.empty()) { - int idx = i->second; - QString s(i->first.c_str()); - MusECore::MidiDevice* md = MusEGlobal::midiDevices.find(s, MusECore::MidiDevice::JACK_MIDI); - if(md) + pup->addSeparator(); + pup->addAction(new MusEGui::MenuTitleItem("JACK:", pup)); + + for(imap i = mapJACK.begin(); i != mapJACK.end(); ++i) { - if(md->deviceType() != MusECore::MidiDevice::JACK_MIDI) - continue; - - act = pup->addAction(md->name()); - act->setData(idx); - act->setCheckable(true); - act->setChecked(md == dev); - } + 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); + act->setCheckable(true); + act->setChecked(md == dev); + } + } } act = pup->exec(ppt); diff --git a/muse2/muse/ctrl.cpp b/muse2/muse/ctrl.cpp index 9f94e9df..8071491e 100644 --- a/muse2/muse/ctrl.cpp +++ b/muse2/muse/ctrl.cpp @@ -34,7 +34,6 @@ #include "globals.h" #include "ctrl.h" #include "xml.h" -#include "audio.h" namespace MusECore { @@ -184,7 +183,7 @@ double CtrlList::value(int frame) const //--------------------------------------------------------- // curVal -// returns the value at the current audio position +// returns the static 'manual' value //--------------------------------------------------------- double CtrlList::curVal() const { @@ -193,6 +192,7 @@ double CtrlList::curVal() const //--------------------------------------------------------- // setCurVal +// Sets the static 'manual' value //--------------------------------------------------------- void CtrlList::setCurVal(double val) { @@ -201,6 +201,7 @@ void CtrlList::setCurVal(double val) //--------------------------------------------------------- // add +// Add, or replace, an event at time frame having value val. //--------------------------------------------------------- void CtrlList::add(int frame, double val) @@ -226,6 +227,17 @@ void CtrlList::del(int frame) } //--------------------------------------------------------- +// updateCurValues +// Set the current static 'manual' value (non-automation value) +// from the automation value at the given time. +//--------------------------------------------------------- + +void CtrlList::updateCurValue(int frame) +{ + _curVal = value(frame); +} + +//--------------------------------------------------------- // read //--------------------------------------------------------- @@ -346,5 +358,38 @@ void CtrlListList::add(CtrlList* vl) { insert(std::pair<const int, CtrlList*>(vl->id(), vl)); } + +//--------------------------------------------------------- +// value +//--------------------------------------------------------- + +double CtrlListList::value(int ctrlId, int frame, bool cur_val_only) const + { + ciCtrlList cl = find(ctrlId); + if (cl == end()) + return 0.0; + + if(cur_val_only) + return cl->second->curVal(); + + return cl->second->value(frame); + } + +//--------------------------------------------------------- +// updateCurValues +// Set the current 'manual' values (non-automation values) +// from the automation values at the given time. +// This is typically called right after a track's automation type changes +// to OFF, so that the manual value becomes the last automation value. +// There are some interesting advantages to having completely independent +// 'manual' and automation values, but the jumping around when switching to OFF +// becomes disconcerting. +//--------------------------------------------------------- + +void CtrlListList::updateCurValues(int frame) +{ + for(ciCtrlList cl = begin(); cl != end(); ++cl) + cl->second->updateCurValue(frame); +} } // namespace MusECore diff --git a/muse2/muse/ctrl.h b/muse2/muse/ctrl.h index 53cdcf49..687c5610 100644 --- a/muse2/muse/ctrl.h +++ b/muse2/muse/ctrl.h @@ -122,6 +122,7 @@ class CtrlList : public std::map<int, CtrlVal, std::less<int> > { double getDefault() const { return _default; } void setDefault(double val) { _default = val; } double curVal() const; + void updateCurValue(int frame); void setCurVal(double val); int id() const { return _id; } QString name() const { return _name; } @@ -174,6 +175,13 @@ class CtrlListList : public std::map<int, CtrlList*, std::less<int> > { ciCtrlList find(int id) const { return std::map<int, CtrlList*, std::less<int> >::find(id); } + + double value(int ctrlId, int frame, bool cur_val_only = false) const; + void updateCurValues(int frame); + void clearAllAutomation() { + for(iCtrlList i = begin(); i != end(); ++i) + i->second->clear(); + } }; } // namespace MusECore diff --git a/muse2/muse/ctrl/ctrlcanvas.cpp b/muse2/muse/ctrl/ctrlcanvas.cpp index 36990595..aa6fbf38 100644 --- a/muse2/muse/ctrl/ctrlcanvas.cpp +++ b/muse2/muse/ctrl/ctrlcanvas.cpp @@ -21,7 +21,7 @@ //========================================================= #include <stdio.h> -#include <values.h> +#include <limits.h> #include <QPainter> #include <QCursor> @@ -327,7 +327,7 @@ void CtrlCanvas::setMidiController(int num) void CtrlCanvas::leaveEvent(QEvent*) { - emit xposChanged(MAXINT); + emit xposChanged(INT_MAX); emit yposChanged(-1); } @@ -464,13 +464,13 @@ void CtrlCanvas::songChanged(int type) if((type & (SC_CONFIG | SC_DRUMMAP)) || ((type & (SC_PART_MODIFIED | SC_SELECTION)) && changed)) setMidiController(_cnum); - if(!curPart) // p4.0.27 + if(!curPart) return; - if(type & (SC_CONFIG | SC_DRUMMAP | SC_PART_MODIFIED | SC_EVENT_INSERTED | SC_EVENT_REMOVED | SC_EVENT_MODIFIED)) // p4.0.18 + if(type & (SC_CONFIG | SC_DRUMMAP | SC_PART_MODIFIED | SC_EVENT_INSERTED | SC_EVENT_REMOVED | SC_EVENT_MODIFIED)) updateItems(); else if(type & SC_SELECTION) - updateSelections(); // p4.0.18 + updateSelections(); } //--------------------------------------------------------- @@ -492,7 +492,7 @@ void CtrlCanvas::partControllers(const MusECore::MidiPart* part, int num, int* d } else { - if(!part) // p4.0.27 + if(!part) { if(mcvl) *mcvl = 0; @@ -655,7 +655,7 @@ void CtrlCanvas::updateSelections() void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) { - if(!_controller || curDrumPitch==-2) // p4.0.27 + if(!_controller || curDrumPitch==-2) return; start = event->pos(); @@ -669,7 +669,7 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) switch (activeTool) { case MusEGui::PointerTool: - if(curPart) // p4.0.27 + if(curPart) { drag = DRAG_LASSO_START; bool do_redraw = false; @@ -763,7 +763,7 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event) void CtrlCanvas::viewMouseMoveEvent(QMouseEvent* event) { - if(!_controller || curDrumPitch==-2) // p4.0.27 + if(!_controller || curDrumPitch==-2) return; QPoint pos = event->pos(); @@ -832,7 +832,7 @@ void CtrlCanvas::viewMouseReleaseEvent(QMouseEvent* event) lasso.setRect(-1, -1, -1, -1); //fallthrough case DRAG_LASSO: - if(_controller) // p4.0.27 + if(_controller) { lasso = lasso.normalized(); int h = height(); @@ -865,7 +865,7 @@ void CtrlCanvas::viewMouseReleaseEvent(QMouseEvent* event) void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2) { - if(!curPart || !_controller) // p4.0.27 + if(!curPart || !_controller) return; if(x2 - x1 < 0) @@ -891,8 +891,7 @@ void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2) int raster = editor->raster(); if (raster == 1) // set reasonable raster { - //raster = MusEGlobal::config.division/4; - raster = MusEGlobal::config.division/16; // Let's use 64th notes, for a bit finer resolution. p4.0.18 Tim. + raster = MusEGlobal::config.division/16; // Let's use 64th notes, for a bit finer resolution. Tim. useRaster = true; } @@ -969,11 +968,10 @@ void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2) void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2) { - if(!curPart || !_controller) // p4.0.27 + if(!curPart || !_controller) return; int h = height(); - bool changed = false; int type = _controller->num(); MusECore::Undo operations; @@ -1011,7 +1009,6 @@ void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2) ev->setEvent(newEvent); // Do not do port controller values and clone parts. operations.push_back(MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, curPart, false, false)); - changed = true; } } else { @@ -1022,7 +1019,6 @@ void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2) ev->setEvent(newEvent); // Do port controller values and clone parts. operations.push_back(MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, curPart, true, true)); - changed = true; } } } @@ -1038,7 +1034,7 @@ void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2) void CtrlCanvas::changeVal(int x1, int x2, int y) { - if(!curPart || !_controller) // p4.0.27 + if(!curPart || !_controller) return; bool changed = false; @@ -1101,7 +1097,7 @@ void CtrlCanvas::changeVal(int x1, int x2, int y) void CtrlCanvas::newVal(int x1, int y) { - if(!curPart || !_controller) // p4.0.27 + if(!curPart || !_controller) return; int xx1 = editor->rasterVal1(x1); @@ -1286,7 +1282,7 @@ void CtrlCanvas::newVal(int x1, int y) void CtrlCanvas::newVal(int x1, int y1, int x2, int y2) { - if(!curPart || !_controller) // p4.0.27 + if(!curPart || !_controller) return; if(x2 - x1 < 0) @@ -1320,8 +1316,7 @@ void CtrlCanvas::newVal(int x1, int y1, int x2, int y2) int raster = editor->raster(); if (raster == 1) // set reasonable raster { - //raster = MusEGlobal::config.division/4; - raster = MusEGlobal::config.division/16; // Let's use 64th notes, for a bit finer resolution. p4.0.18 Tim. + raster = MusEGlobal::config.division/16; // Let's use 64th notes, for a bit finer resolution. Tim. useRaster = true; } @@ -1460,7 +1455,7 @@ void CtrlCanvas::newVal(int x1, int y1, int x2, int y2) void CtrlCanvas::deleteVal(int x1, int x2, int) { - if(!curPart) // p4.0.27 + if(!curPart) return; if(x2 - x1 < 0) @@ -1604,7 +1599,7 @@ void CtrlCanvas::pdrawItems(QPainter& p, const QRect& rect, const MusECore::Midi } else { - if(!part) // p4.0.27 + if(!part) return; MusECore::MidiTrack* mt = part->track(); @@ -1726,7 +1721,7 @@ void CtrlCanvas::pdrawItems(QPainter& p, const QRect& rect, const MusECore::Midi void CtrlCanvas::pdraw(QPainter& p, const QRect& rect) { - if(!_controller) // p4.0.27 + if(!_controller) return; int x = rect.x() - 1; // compensate for 3 pixel line width diff --git a/muse2/muse/ctrl/ctrlpanel.cpp b/muse2/muse/ctrl/ctrlpanel.cpp index 938ebd5a..0fc66b3a 100644 --- a/muse2/muse/ctrl/ctrlpanel.cpp +++ b/muse2/muse/ctrl/ctrlpanel.cpp @@ -123,7 +123,7 @@ CtrlPanel::CtrlPanel(QWidget* parent, MidiEditor* e, CtrlCanvas* c, const char* _dl = new MusEGui::DoubleLabel(-1.0, 0.0, +127.0); _dl->setPrecision(0); - _dl->setToolTip(tr("double click on/off")); + _dl->setToolTip(tr("ctrl-double-click on/off")); _dl->setSpecialText(tr("off")); _dl->setFont(MusEGlobal::config.fonts[1]); _dl->setBackgroundRole(QPalette::Mid); @@ -136,7 +136,7 @@ CtrlPanel::CtrlPanel(QWidget* parent, MidiEditor* e, CtrlCanvas* c, const char* connect(_knob, SIGNAL(sliderMoved(double,int)), SLOT(ctrlChanged(double))); connect(_knob, SIGNAL(sliderRightClicked(const QPoint&, int)), SLOT(ctrlRightClicked(const QPoint&, int))); connect(_dl, SIGNAL(valueChanged(double,int)), SLOT(ctrlChanged(double))); - connect(_dl, SIGNAL(doubleClicked(int)), SLOT(labelDoubleClicked())); + connect(_dl, SIGNAL(ctrlDoubleClicked(int)), SLOT(labelDoubleClicked())); bbox->addStretch(); bbox->addWidget(selCtrl); diff --git a/muse2/muse/dialogs.cpp b/muse2/muse/dialogs.cpp index 54a080bf..ff93b877 100644 --- a/muse2/muse/dialogs.cpp +++ b/muse2/muse/dialogs.cpp @@ -89,13 +89,6 @@ void retranslate_function_dialogs() void read_function_dialog_config(MusECore::Xml& xml) { - if (erase_dialog==NULL) - { - cout << "ERROR: THIS SHOULD NEVER HAPPEN: read_function_dialog_config() called, but\n" - " dialogs are still uninitalized (NULL)!"<<endl; - return; - } - for (;;) { MusECore::Xml::Token token = xml.parse(); diff --git a/muse2/muse/driver/alsamidi.cpp b/muse2/muse/driver/alsamidi.cpp index 08f5345f..f75b9c33 100644 --- a/muse2/muse/driver/alsamidi.cpp +++ b/muse2/muse/driver/alsamidi.cpp @@ -42,6 +42,10 @@ #include <QApplication> +// Enable debugging: +//#define ALSA_DEBUG 1 + + namespace MusECore { static int alsaSeqFdi = -1; @@ -98,7 +102,9 @@ QString MidiAlsaDevice::open() int cap = snd_seq_port_info_get_capability(pinfo); - //printf("MidiAlsaDevice::open cap:%d\n", cap); +#ifdef ALSA_DEBUG + printf("MidiAlsaDevice::open cap:%d\n", cap); +#endif // subscribe for writing if (_openFlags & 1) @@ -175,7 +181,9 @@ void MidiAlsaDevice::close() int cap = snd_seq_port_info_get_capability(pinfo); - //printf("MidiAlsaDevice::close cap:%d\n", cap); +#ifdef ALSA_DEBUG + printf("MidiAlsaDevice::close cap:%d\n", cap); +#endif // This function appears to be called only by MidiPort::setMidiDevice(), // which closes then opens the device. @@ -434,6 +442,10 @@ bool MidiAlsaDevice::putEvent(snd_seq_event_t* event) { int error; +#ifdef ALSA_DEBUG + printf("MidiAlsaDevice::putEvent\n"); +#endif + do { error = snd_seq_event_output_direct(alsaSeq, event); int len = snd_seq_event_length(event); @@ -860,9 +872,10 @@ bool initMidiAlsa() snd_strerror(error)); return true; } + const int inCap = SND_SEQ_PORT_CAP_SUBS_READ; const int outCap = SND_SEQ_PORT_CAP_SUBS_WRITE; - + snd_seq_client_info_t *cinfo; snd_seq_client_info_alloca(&cinfo); snd_seq_client_info_set_client(cinfo, -1); @@ -955,7 +968,11 @@ bool initMidiAlsa() //snd_seq_set_client_name(alsaSeq, "MusE Sequencer"); - snd_seq_set_client_name(alsaSeq, MusEGlobal::audioDevice->clientName()); + error = snd_seq_set_client_name(alsaSeq, MusEGlobal::audioDevice->clientName()); + if (error < 0) { + printf("Alsa: Set client name failed: %s", snd_strerror(error)); + return true; + } int ci = snd_seq_poll_descriptors_count(alsaSeq, POLLIN); int co = snd_seq_poll_descriptors_count(alsaSeq, POLLOUT); @@ -1045,6 +1062,24 @@ void exitMidiAlsa() } +//--------------------------------------------------------- +// setAlsaClientName +//--------------------------------------------------------- + +void setAlsaClientName(const char* name) +{ +#ifdef ALSA_DEBUG + printf("setAlsaClientName: %s seq:%p\n", name, alsaSeq); +#endif + + if(!alsaSeq) + return; + + int error = snd_seq_set_client_name(alsaSeq, name); + if (error < 0) + printf("setAlsaClientName: failed: %s", snd_strerror(error)); +} + struct AlsaPort { snd_seq_addr_t adr; char* name; @@ -1064,7 +1099,9 @@ static std::list<AlsaPort> portList; void alsaScanMidiPorts() { -// printf("alsa scan midi ports\n"); +#ifdef ALSA_DEBUG + printf("alsa scan midi ports\n"); +#endif const int inCap = SND_SEQ_PORT_CAP_SUBS_READ; const int outCap = SND_SEQ_PORT_CAP_SUBS_WRITE; diff --git a/muse2/muse/driver/alsamidi.h b/muse2/muse/driver/alsamidi.h index 7a1ac1c2..97d57f2b 100644 --- a/muse2/muse/driver/alsamidi.h +++ b/muse2/muse/driver/alsamidi.h @@ -82,6 +82,7 @@ extern int alsaSelectRfd(); extern int alsaSelectWfd(); extern void alsaProcessMidiInput(); extern void alsaScanMidiPorts(); +extern void setAlsaClientName(const char*); } // namespace MusECore diff --git a/muse2/muse/driver/alsatimer.cpp b/muse2/muse/driver/alsatimer.cpp index 20f7ab88..cf211a2f 100644 --- a/muse2/muse/driver/alsatimer.cpp +++ b/muse2/muse/driver/alsatimer.cpp @@ -1,12 +1,12 @@ - //========================================================= - // MusE - // Linux Music Editor - // $Id: alsatimer.cpp,v 1.1.2.9 2009/03/28 01:46:10 terminator356 Exp $ - // - // Plenty of code borrowed from timer.c example in - // alsalib 1.0.7 - // - // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) +//========================================================= +// MusE +// Linux Music Editor +// $Id: alsatimer.cpp,v 1.1.2.9 2009/03/28 01:46:10 terminator356 Exp $ +// +// Plenty of code borrowed from timer.c example in +// alsalib 1.0.7 +// +// (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -22,10 +22,10 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // - //========================================================= +//========================================================= - #include "alsatimer.h" - #include <climits> +#include "alsatimer.h" +#include <climits> #define TIMER_DEBUG 0 @@ -73,7 +73,7 @@ namespace MusECore { int max_ids = sizeof(test_ids) / sizeof(int); long best_res = LONG_MAX; //int best_dev = -1; // SND_TIMER_GLOBAL_SYSTEM; - int best_dev = SND_TIMER_GLOBAL_SYSTEM; // p3.3.51 + int best_dev = SND_TIMER_GLOBAL_SYSTEM; int i; if (id || info || params) { @@ -107,14 +107,13 @@ namespace MusECore { device = best_dev; } - // p3.3.51 Removed. //if(best_dev==-1) // return -1; // no working timer found sprintf(timername, "hw:CLASS=%i,SCLASS=%i,CARD=%i,DEV=%i,SUBDEV=%i", devclass, sclass, card, device, subdevice); if ((err = snd_timer_open(&handle, timername, SND_TIMER_OPEN_NONBLOCK))<0) { fprintf(stderr, "AlsaTimer::initTimer(): timer open %i (%s)\n", err, snd_strerror(err)); - return -1; // p3.3.51 + return -1; } if ((err = snd_timer_info(handle, info)) < 0) { diff --git a/muse2/muse/driver/audiodev.h b/muse2/muse/driver/audiodev.h index 14fb60b3..08d6a9f0 100644 --- a/muse2/muse/driver/audiodev.h +++ b/muse2/muse/driver/audiodev.h @@ -52,6 +52,7 @@ class AudioDevice { virtual void stop () = 0; virtual int framePos() const = 0; virtual unsigned frameTime() const = 0; + virtual double systemTime() const = 0; virtual float* getBuffer(void* port, unsigned long nframes) = 0; @@ -75,7 +76,7 @@ class AudioDevice { virtual void* findPort(const char* name) = 0; virtual QString portName(void* port) = 0; virtual int getState() = 0; - virtual unsigned getCurFrame() = 0; + virtual unsigned getCurFrame() const = 0; virtual bool isRealtime() = 0; virtual int realtimePriority() const = 0; // return zero if not realtime virtual void startTransport() = 0; diff --git a/muse2/muse/driver/dummyaudio.cpp b/muse2/muse/driver/dummyaudio.cpp index 1738027d..21bb425f 100644 --- a/muse2/muse/driver/dummyaudio.cpp +++ b/muse2/muse/driver/dummyaudio.cpp @@ -27,6 +27,8 @@ #include <stdarg.h> #include <pthread.h> #include <sys/poll.h> +#include <sys/time.h> +#include <unistd.h> #include "config.h" #include "audio.h" @@ -137,7 +139,7 @@ class DummyAudioDevice : public AudioDevice { // if(DEBUG_DUMMY) // printf("DummyAudioDevice::getState %d\n", state); return state; } - virtual unsigned getCurFrame() { + virtual unsigned getCurFrame() const { if(DEBUG_DUMMY) printf("DummyAudioDevice::getCurFrame %d\n", _framePos); @@ -145,6 +147,13 @@ class DummyAudioDevice : public AudioDevice { virtual unsigned frameTime() const { return lrint(curTime() * MusEGlobal::sampleRate); } + virtual double systemTime() const + { + struct timeval t; + gettimeofday(&t, 0); + //printf("%ld %ld\n", t.tv_sec, t.tv_usec); // Note I observed values coming out of order! Causing some problems. + return (double)((double)t.tv_sec + (t.tv_usec / 1000000.0)); + } virtual bool isRealtime() { return realtimeFlag; } //virtual int realtimePriority() const { return 40; } virtual int realtimePriority() const { return _realTimePriority; } diff --git a/muse2/muse/driver/jack.cpp b/muse2/muse/driver/jack.cpp index a52410e9..4cc8bfb8 100644 --- a/muse2/muse/driver/jack.cpp +++ b/muse2/muse/driver/jack.cpp @@ -50,7 +50,7 @@ #include "jackmidi.h" -#define JACK_DEBUG 0 +#define JACK_DEBUG 0 //#include "errorhandler.h" @@ -103,6 +103,8 @@ inline bool checkJackClient(jack_client_t* _client) static void jack_thread_init (void* ) { + if (JACK_DEBUG) + printf("jack_thread_init()\n"); MusEGlobal::doSetuid(); #ifdef VST_SUPPORT if (loadVST) @@ -240,7 +242,8 @@ static void timebase_callback(jack_transport_state_t /* state */, int /* new_pos */, void*) { - //printf("Jack timebase_callback pos->frame:%u MusEGlobal::audio->tickPos:%d MusEGlobal::song->cpos:%d\n", pos->frame, MusEGlobal::audio->tickPos(), MusEGlobal::song->cpos()); + if (JACK_DEBUG) + printf("Jack timebase_callback pos->frame:%u MusEGlobal::audio->tickPos:%d MusEGlobal::song->cpos:%d\n", pos->frame, MusEGlobal::audio->tickPos(), MusEGlobal::song->cpos()); //Pos p(pos->frame, false); Pos p(MusEGlobal::extSyncFlag.value() ? MusEGlobal::audio->tickPos() : pos->frame, MusEGlobal::extSyncFlag.value() ? true : false); @@ -320,6 +323,7 @@ static void jackError(const char *s) static void noJackError(const char* /* s */) { + //printf("noJackError()\n"); } //--------------------------------------------------------- @@ -428,26 +432,25 @@ bool initJackAudio() if (MusEGlobal::debugMsg) fprintf(stderr, "initJackAudio(): client %s opened.\n", jack_get_client_name(client)); - if (client) { - jack_set_error_function(jackError); - //jackAudio = new JackAudioDevice(client, jackIdString); - jackAudio = new JackAudioDevice(client, jack_get_client_name(client)); - if (MusEGlobal::debugMsg) - fprintf(stderr, "initJackAudio(): registering client...\n"); - jackAudio->registerClient(); - MusEGlobal::sampleRate = jack_get_sample_rate(client); - MusEGlobal::segmentSize = jack_get_buffer_size(client); - jack_set_thread_init_callback(client, (JackThreadInitCallback) jack_thread_init, 0); - //jack_set_timebase_callback(client, 0, (JackTimebaseCallback) timebase_callback, 0); - } + //jack_set_error_function(jackError); + //jackAudio = new JackAudioDevice(client, jackIdString); + jackAudio = new JackAudioDevice(client, jack_get_client_name(client)); + if (MusEGlobal::debugMsg) + fprintf(stderr, "initJackAudio(): registering client...\n"); + MusEGlobal::undoSetuid(); - if (client) { - MusEGlobal::audioDevice = jackAudio; - jackAudio->scanMidiPorts(); - return false; - } - return true; + MusEGlobal::audioDevice = jackAudio; + + // WARNING Don't do this here. Do it after any MusE ALSA client is registered, otherwise random crashes can occur. + //jackAudio->registerClient(); + + MusEGlobal::sampleRate = jack_get_sample_rate(client); + MusEGlobal::segmentSize = jack_get_buffer_size(client); + + jackAudio->scanMidiPorts(); + + return false; } static int bufsize_callback(jack_nframes_t n, void*) @@ -1017,6 +1020,9 @@ void JackAudioDevice::registerClient() if (JACK_DEBUG) printf("registerClient()\n"); if(!checkJackClient(_client)) return; + + jack_set_thread_init_callback(_client, (JackThreadInitCallback) jack_thread_init, 0); + //jack_set_timebase_callback(client, 0, (JackTimebaseCallback) timebase_callback, 0); jack_set_process_callback(_client, processAudio, 0); jack_set_sync_callback(_client, processSync, 0); //jack_set_sync_timeout(_client, 5000000); // Change default 2 to 5 second sync timeout because prefetch may be very slow esp. with resampling ! @@ -1220,10 +1226,33 @@ jack_transport_state_t JackAudioDevice::transportQuery(jack_position_t* pos) } //--------------------------------------------------------- +// systemTime +// Return system time. Depends on selected clock source. +// With Jack, may be based upon wallclock time, the +// processor cycle counter or the HPET clock etc. +//--------------------------------------------------------- + +double JackAudioDevice::systemTime() const +{ + // Client valid? According to sletz: For jack_get_time "There are some timing related + // initialization that are done once when a first client is created." + if(!checkJackClient(_client)) + { + struct timeval t; + gettimeofday(&t, 0); + //printf("%ld %ld\n", t.tv_sec, t.tv_usec); // Note I observed values coming out of order! Causing some problems. + return (double)((double)t.tv_sec + (t.tv_usec / 1000000.0)); + } + + jack_time_t t = jack_get_time(); + return double(t) / 1000000.0; +} + +//--------------------------------------------------------- // getCurFrame //--------------------------------------------------------- -unsigned int JackAudioDevice::getCurFrame() +unsigned int JackAudioDevice::getCurFrame() const { if (JACK_DEBUG) printf("JackAudioDevice::getCurFrame pos.frame:%d\n", pos.frame); @@ -1430,8 +1459,8 @@ std::list<QString> JackAudioDevice::inputPorts(bool midi, int aliases) QString JackAudioDevice::portName(void* port) { - if (JACK_DEBUG) - printf("JackAudioDevice::portName(\n"); + //if (JACK_DEBUG) + // printf("JackAudioDevice::portName\n"); if(!checkJackClient(_client)) return ""; if (!port) return ""; @@ -1683,8 +1712,8 @@ int JackAudioDevice::setMaster(bool f) void JackAudioDevice::scanMidiPorts() { - if(MusEGlobal::debugMsg) - printf("JackAudioDevice::scanMidiPorts:\n"); + //if(MusEGlobal::debugMsg) + // printf("JackAudioDevice::scanMidiPorts:\n"); /* const char* type = JACK_DEFAULT_MIDI_TYPE; @@ -1833,7 +1862,7 @@ void exitJackAudio() if (JACK_DEBUG) printf("exitJackAudio() after delete jackAudio\n"); - MusEGlobal::audioDevice = NULL; // By Tim + MusEGlobal::audioDevice = NULL; } } // namespace MusECore diff --git a/muse2/muse/driver/jackaudio.h b/muse2/muse/driver/jackaudio.h index 838a20df..9640ca81 100644 --- a/muse2/muse/driver/jackaudio.h +++ b/muse2/muse/driver/jackaudio.h @@ -71,6 +71,7 @@ class JackAudioDevice : public AudioDevice { virtual int framePos() const; virtual unsigned frameTime() const { return _frameCounter; } + virtual double systemTime() const; virtual float* getBuffer(void* port, unsigned long nframes) { return (float*)jack_port_get_buffer((jack_port_t*)port, nframes); @@ -95,7 +96,7 @@ class JackAudioDevice : public AudioDevice { virtual void* findPort(const char* name); virtual QString portName(void* port); virtual int getState(); - virtual unsigned int getCurFrame(); + virtual unsigned int getCurFrame() const; virtual bool isRealtime() { return jack_is_realtime(_client); } virtual int realtimePriority() const; virtual void startTransport(); diff --git a/muse2/muse/driver/rtctimer.cpp b/muse2/muse/driver/rtctimer.cpp index e232b995..96585f87 100644 --- a/muse2/muse/driver/rtctimer.cpp +++ b/muse2/muse/driver/rtctimer.cpp @@ -1,12 +1,12 @@ - //========================================================= - // MusE - // Linux Music Editor - // $Id: rtctimer.cpp,v 1.1.2.11 2009/03/09 02:05:18 terminator356 Exp $ - // - // Most code moved from midiseq.cpp by Werner Schweer. - // - // (C) Copyright -2004 Werner Schweer (werner@seh.de) - // (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) +//========================================================= +// MusE +// Linux Music Editor +// $Id: rtctimer.cpp,v 1.1.2.11 2009/03/09 02:05:18 terminator356 Exp $ +// +// Most code moved from midiseq.cpp by Werner Schweer. +// +// (C) Copyright -2004 Werner Schweer (werner@seh.de) +// (C) Copyright 2004 Robert Jonsson (rj@spamatica.se) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -22,7 +22,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // - //========================================================= +//========================================================= #include <linux/version.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp index 69c6259d..5000e338 100644 --- a/muse2/muse/dssihost.cpp +++ b/muse2/muse/dssihost.cpp @@ -26,6 +26,8 @@ // Turn on debugging messages //#define DSSI_DEBUG +// Turn on constant flow of process debugging messages +//#define DSSI_DEBUG_PROCESS // Support vst state saving/loading with vst chunks. //#define DSSI_VST_CHUNK_SUPPORT @@ -50,6 +52,7 @@ #include "controlfifo.h" #include "xml.h" #include "song.h" +#include "ctrl.h" #include "app.h" #include "globals.h" @@ -140,7 +143,7 @@ static void scanDSSILib(QFileInfo& fi) // ddskrjo removed const for argument if(LADSPA_IS_PORT_OUTPUT(pd) && LADSPA_IS_PORT_CONTROL(pd)) co++; } - fprintf(stderr, "MusEGlobal::audio ins:%d outs:%d control ins:%d outs:%d\n", ai, ao, ci, co); + fprintf(stderr, " audio ins:%d outs:%d control ins:%d outs:%d\n", ai, ao, ci, co); } MusEGlobal::synthis.push_back(s); @@ -412,7 +415,7 @@ bool DssiSynthIF::guiVisible() const } //--------------------------------------------------------- -// showGui +// showNativeGui //--------------------------------------------------------- void DssiSynthIF::showNativeGui(bool v) @@ -420,7 +423,7 @@ void DssiSynthIF::showNativeGui(bool v) #ifdef OSC_SUPPORT #ifdef DSSI_DEBUG - printf("DssiSynthIF::showGui(): v:%d visible:%d\n", v, guiVisible()); + printf("DssiSynthIF::showNativeGui(): v:%d visible:%d\n", v, guiVisible()); #endif _oscif.oscShowGui(v); @@ -517,8 +520,6 @@ bool DssiSynthIF::init(DssiSynth* s) synth->midiCtl2PortMap.clear(); synth->port2MidiCtlMap.clear(); - synti->_guiUpdateControls.clear(); - synti->_guiUpdateProgram = false; int cip = 0; int cop = 0; @@ -542,11 +543,8 @@ bool DssiSynthIF::init(DssiSynth* s) controls[cip].enCtrl = true; controls[cip].en2Ctrl = true; - // Set to false at first. - synti->_guiUpdateControls.push_back(false); - #ifdef DSSI_DEBUG - printf("DssiSynthIF::init control port:%d port idx:%d name:%s\n", cip, k, ld->PortNames[k]); + printf("DssiSynthIF::init control port:%d port idx:%lu name:%s\n", cip, k, ld->PortNames[k]); #endif // This code is duplicated in ::getControllerInfo() @@ -642,7 +640,7 @@ bool DssiSynthIF::init(DssiSynth* s) controlsOut[cop].en2Ctrl = false; #ifdef DSSI_DEBUG - printf("DssiSynthIF::init control output port:%d port idx:%d name:%s\n", cop, k, ld->PortNames[k]); + printf("DssiSynthIF::init control output port:%d port idx:%lu name:%s\n", cop, k, ld->PortNames[k]); #endif // Control outs are not handled but still must be connected to something. @@ -719,6 +717,10 @@ DssiSynthIF::~DssiSynthIF() #ifdef DSSI_DEBUG printf("DssiSynthIF::~DssiSynthIF\n"); #endif + + #ifdef OSC_SUPPORT + _oscif.oscSetSynthIF(NULL); + #endif if(synth) { @@ -858,11 +860,6 @@ void DssiSynthIF::setParameter(unsigned long n, float v) { fprintf(stderr, "DssiSynthIF::setParameter: fifo overflow: in control number:%lu\n", n); } - - // Notify that changes are to be sent upon heartbeat. - // TODO: No, at least not for now. So far, setParameter is only called during loading of stored params, - // and we don't want this interfering with oscUpdate which also sends the values. - //synti->_guiUpdateControls[n] = true; } //--------------------------------------------------------- @@ -1066,6 +1063,10 @@ bool DssiSynthIF::processEvent(const MusECore::MidiPlayEvent& e, snd_seq_event_t snd_seq_ev_set_noteoff(event, chn, a, 0); break; case MusECore::ME_NOTEOFF: + #ifdef DSSI_DEBUG + fprintf(stderr, "DssiSynthIF::processEvent midi event is MusECore::ME_NOTEOFF\n"); + #endif + snd_seq_ev_clear(event); event->queue = SND_SEQ_QUEUE_DIRECT; snd_seq_ev_set_noteoff(event, chn, a, 0); @@ -1083,11 +1084,8 @@ bool DssiSynthIF::processEvent(const MusECore::MidiPlayEvent& e, snd_seq_event_t synti->_curProgram = prog; if(dssi->select_program) - { dssi->select_program(handle, bank, prog); - // Notify that changes are to be sent upon heartbeat. - synti->_guiUpdateProgram = true; - } + // Event pointer not filled. Return false. return false; } @@ -1115,11 +1113,8 @@ bool DssiSynthIF::processEvent(const MusECore::MidiPlayEvent& e, snd_seq_event_t synti->_curProgram = prog; if(dssi->select_program) - { dssi->select_program(handle, bank, prog); - // Notify that changes are to be sent upon heartbeat. - synti->_guiUpdateProgram = true; - } + // Event pointer not filled. Return false. return false; } @@ -1130,7 +1125,6 @@ bool DssiSynthIF::processEvent(const MusECore::MidiPlayEvent& e, snd_seq_event_t fprintf(stderr, "DssiSynthIF::processEvent midi event is MusECore::ME_CONTROLLER, dataA is MusECore::CTRL_PITCH\n"); #endif - b &= 0x3fff; snd_seq_ev_clear(event); event->queue = SND_SEQ_QUEUE_DIRECT; snd_seq_ev_set_pitchbend(event, chn, b); @@ -1225,10 +1219,6 @@ bool DssiSynthIF::processEvent(const MusECore::MidiPlayEvent& e, snd_seq_event_t // Set the ladspa port value. controls[k].val = val; - // FIXME: Testing - Works but is this safe in a RT process callback? Try hooking into gui heartbeat timer instead... - // lo_send(uiTarget, uiOscControlPath, "if", i, val); - // Notify that changes are to be sent upon heartbeat. - synti->_guiUpdateControls[k] = true; // Since we absorbed the message as a ladspa control change, return false - the event is not filled. return false; @@ -1370,6 +1360,10 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP int frameOffset = MusEGlobal::audio->getFrameOffset(); unsigned long syncFrame = MusEGlobal::audio->curSyncFrame(); + #ifdef DSSI_DEBUG_PROCESS + fprintf(stderr, "DssiSynthIF::getData: pos:%u ports:%d nframes:%u syncFrame:%lu nevents:%lu\n", pos, ports, nframes, syncFrame, nevents); + #endif + // All ports must be connected to something! unsigned long nop, k; @@ -1398,13 +1392,11 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP // But this 'packet' method sure seems to work nicely so far, so we'll throw it in... // // Must make this detectable for dssi vst synths, just like the plugins' in-place blacklist. - //const bool usefixedrate = true; - const bool usefixedrate = synth->_isDssiVst; // Try this. + const bool usefixedrate = synth->_isDssiVst; // Try this. (was: true) // TODO Make this number a global setting. // 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 = nframes; + unsigned long fixedsize = nframes; // was: 2048 // For now, the fixed size is clamped to the MusEGlobal::audio buffer size. // TODO: We could later add slower processing over several cycles - @@ -1416,9 +1408,11 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP if(min_per > nframes) min_per = nframes; - // + #ifdef DSSI_DEBUG_PROCESS + fprintf(stderr, "DssiSynthIF::getData: Handling inputs...\n"); + #endif + // p4.0.38 Handle inputs... - // if(!((MusECore::AudioTrack*)synti)->noInRoute()) { RouteList* irl = ((MusECore::AudioTrack*)synti)->inRoutes(); @@ -1488,6 +1482,10 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP } } + #ifdef DSSI_DEBUG_PROCESS + fprintf(stderr, "DssiSynthIF::getData: Processing automation control values...\n"); + #endif + // 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) @@ -1495,7 +1493,7 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP for(unsigned long k = 0; k < synth->_controlInPorts; ++k) { if(controls[k].enCtrl && controls[k].en2Ctrl ) - controls[k].val = synti->pluginCtrlVal(genACnum(id(), k)); + controls[k].val = (static_cast<MusECore::AudioTrack*>(synti))->controller()->value(genACnum(id(), k), pos); } } @@ -1510,16 +1508,24 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP while(!_controlFifo.isEmpty()) { ControlEvent v = _controlFifo.peek(); - // The events happened in the last period or even before that. Shift into this period with + n. This will sync with MusEGlobal::audio. + // The events happened in the last period or even before that. Shift into this period with + n. This will sync with audio. // If the events happened even before current frame - n, make sure they are counted immediately as zero-frame. evframe = (syncFrame > v.frame + nframes) ? 0 : v.frame - syncFrame + nframes; + + #ifdef DSSI_DEBUG + fprintf(stderr, "DssiSynthIF::getData found:%d evframe:%lu frame:%lu event frame:%lu idx:%lu val:%f unique:%d\n", + found, evframe, frame, v.frame, v.idx, v.value, v.unique); + #endif + // Protection. Observed this condition. Why? Supposed to be linear timestamps. if(found && evframe < frame) { - printf("DssiSynthIF::getData *** Error: evframe:%lu < frame:%lu idx:%lu val:%f unique:%d\n", - evframe, v.frame, v.idx, v.value, v.unique); - // Just make it equal to the current frame so it gets processed right away. - evframe = frame; + printf("DssiSynthIF::getData *** Error: evframe:%lu < frame:%lu event: frame:%lu idx:%lu val:%f unique:%d\n", + evframe, frame, v.frame, v.idx, v.value, v.unique); + + // No choice but to ignore it. + _controlFifo.remove(); // Done with the ring buffer's item. Remove it. + continue; } if(evframe >= nframes @@ -1535,45 +1541,34 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP // 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. + // Need to update the automation value, otherwise it overwrites later with the last 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. + // We're in the audio thread context: no need to send a message, just modify directly. synti->setPluginCtrlVal(genACnum(id(), v.idx), v.value); - // DELETETHIS 15, cleanup, fix, maybe just keep it? dunno. - // 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. + /* Record automation. DELETETHIS? + * 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); + AutomationType at = _track->automationType(); + if ((at == AUTO_WRITE) || + (at == AUTO_TOUCH && MusEGlobal::audio->isPlaying())) + enableController(k, false); + _track->recordAutomation(id, v.value); + */ } - } - // DELETETHIS 10 ? - // Process automation control values now. - //if(MusEGlobal::automation && synti && synti->automationType() != AUTO_OFF && id() != -1) - //{ - // for(unsigned long k = 0; k < synth->_controlInPorts; ++k) - // { - // if(controls[k].enCtrl && controls[k].en2Ctrl ) - // controls[k].val = synti->pluginCtrlVal(genACnum(id(), k)); - // } - //} - if(found && !usefixedrate) nsamp = frame - sample; + if(sample + nsamp >= nframes) // Safety check. nsamp = nframes - sample; @@ -1586,13 +1581,13 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP // Process event list events... for(; start_event != el->end(); ++start_event) { + #ifdef DSSI_DEBUG + fprintf(stderr, "DssiSynthIF::getData eventlist event time:%d pos:%u sample:%lu nsamp:%lu frameOffset:%d\n", start_event->time(), pos, sample, nsamp, frameOffset); + #endif + if(start_event->time() >= (pos + sample + nsamp + frameOffset)) // frameOffset? Test again... break; - #ifdef DSSI_DEBUG - fprintf(stderr, "DssiSynthIF::getData eventlist event time:%d\n", i->time()); - #endif - // Update hardware state so knobs and boxes are updated. Optimize to avoid re-setting existing values. // Same code as in MidiPort::sendEvent() if(synti->midiPort() != -1) @@ -1606,15 +1601,13 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP if(!mp->setHwCtrlState(start_event->channel(), da, db)) continue; } - else - if(start_event->type() == MusECore::ME_PITCHBEND) + else if(start_event->type() == MusECore::ME_PITCHBEND) { int da = mp->limitValToInstrCtlRange(MusECore::CTRL_PITCH, start_event->dataA()); if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_PITCH, da)) continue; } - else - if(start_event->type() == MusECore::ME_PROGRAM) + else if(start_event->type() == MusECore::ME_PROGRAM) { if(!mp->setHwCtrlState(start_event->channel(), MusECore::CTRL_PROGRAM, start_event->dataA())) continue; @@ -1624,22 +1617,27 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP // Returns false if the event was not filled. It was handled, but some other way. if(processEvent(*start_event, &events[nevents])) { - // Time-stamp the event. p4.0.15 Tim. - int ft = start_event->time() - frameOffset - pos; + // Time-stamp the event. + int ft = start_event->time() - frameOffset - pos - sample; if(ft < 0) ft = 0; - if (ft >= int(sample + nsamp)) + if (ft >= int(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); - ft = sample + nsamp - 1; + ft = nsamp - 1; } + + #ifdef DSSI_DEBUG + fprintf(stderr, "DssiSynthIF::getData eventlist: ft:%d current nevents:%lu\n", ft, nevents); + #endif + // "Each event is timestamped relative to the start of the block, (mis)using the ALSA "tick time" field as a frame count. // The host is responsible for ensuring that events with differing timestamps are already ordered by time." - From dssi.h events[nevents].time.tick = ft; ++nevents; - } + } } // Now process putEvent events... @@ -1658,14 +1656,14 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP // Returns false if the event was not filled. It was handled, but some other way. if(processEvent(e, &events[nevents])) { - // Time-stamp the event. p4.0.15 Tim. - int ft = e.time() - frameOffset - pos; + // Time-stamp the event. + int ft = e.time() - frameOffset - pos - sample; if(ft < 0) ft = 0; - if (ft >= int(sample + nsamp)) + if (ft >= int(nsamp)) { printf("DssiSynthIF::getData: eventFifo event time:%d out of range. pos:%d offset:%d ft:%d sample:%lu nsamp:%lu\n", e.time(), pos, frameOffset, ft, sample, nsamp); - ft = sample + nsamp - 1; + ft = nsamp - 1; } // "Each event is timestamped relative to the start of the block, (mis)using the ALSA "tick time" field as a frame count. // The host is responsible for ensuring that events with differing timestamps are already ordered by time." - From dssi.h @@ -1675,6 +1673,10 @@ MusECore::iMPEvent DssiSynthIF::getData(MusECore::MidiPort* /*mp*/, MusECore::MP } } + #ifdef DSSI_DEBUG_PROCESS + fprintf(stderr, "DssiSynthIF::getData: Connecting and running. sample:%lu nsamp:%lu nevents:%lu\n", sample, nsamp, nevents); + #endif + k = 0; // Connect the given buffers directly to the ports, up to a max of synth ports. for(; k < nop; ++k) @@ -1781,25 +1783,13 @@ void DssiSynthIF::guiHeartBeat() { #ifdef OSC_SUPPORT // Update the gui's program if needed. - if(synti->_guiUpdateProgram) - { - _oscif.oscSendProgram(synti->_curProgram, synti->_curBankL); - synti->_guiUpdateProgram = false; - } + _oscif.oscSendProgram(synti->_curProgram, synti->_curBankL); // Update the gui's controls if needed. unsigned long ports = synth->_controlInPorts; - if(ports > synti->_guiUpdateControls.size()) - return; + for(unsigned long i = 0; i < ports; ++i) - { - if(synti->_guiUpdateControls[i]) - { - _oscif.oscSendControl(controls[i].idx, controls[i].val); - // Reset. - synti->_guiUpdateControls[i] = false; - } - } + _oscif.oscSendControl(controls[i].idx, controls[i].val); #endif } @@ -1825,13 +1815,13 @@ int DssiSynthIF::oscUpdate() } // Send current bank and program. - _oscif.oscSendProgram(synti->_curProgram, synti->_curBankL); + _oscif.oscSendProgram(synti->_curProgram, synti->_curBankL, true /*force*/); // Send current control values. unsigned long ports = synth->_controlInPorts; for(unsigned long i = 0; i < ports; ++i) { - _oscif.oscSendControl(controls[i].idx, controls[i].val); + _oscif.oscSendControl(controls[i].idx, controls[i].val, true /*force*/); // Avoid overloading the GUI if there are lots and lots of ports. if((i+1) % 50 == 0) usleep(300000); @@ -1973,8 +1963,9 @@ int DssiSynthIF::oscControl(unsigned long port, float value) // 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); + if ((at == AUTO_WRITE) || + (at == AUTO_TOUCH && MusEGlobal::audio->isPlaying())) + enableController(cport, false); //TODO maybe re-enable the ctrl soon? synti->recordAutomation(pid, value); } @@ -2151,7 +2142,7 @@ int DssiSynthIF::getControllerInfo(int id, const char** name, int* ctrl, int* mi unsigned long i = controls[id].idx; #ifdef DSSI_DEBUG - printf("DssiSynthIF::getControllerInfo control port:%d port idx:%d name:%s\n", id, i, ld->PortNames[i]); + printf("DssiSynthIF::getControllerInfo control port:%d port idx:%lu name:%s\n", id, i, ld->PortNames[i]); #endif int ctlnum = DSSI_NONE; diff --git a/muse2/muse/dssihost.h b/muse2/muse/dssihost.h index 1166886a..238b468e 100644 --- a/muse2/muse/dssihost.h +++ b/muse2/muse/dssihost.h @@ -105,6 +105,8 @@ class DssiSynth : public Synth { unsigned long outPorts() const { return _outports; } unsigned long inControls() const { return _controlInPorts; } unsigned long outControls() const { return _controlOutPorts; } + + const std::vector<unsigned long>* getRpIdx() { return &rpIdx; } }; //--------------------------------------------------------- diff --git a/muse2/muse/event.h b/muse2/muse/event.h index 7e3e498c..e31fb116 100644 --- a/muse2/muse/event.h +++ b/muse2/muse/event.h @@ -27,9 +27,9 @@ #include <map> #include <sys/types.h> -#include "wave.h" // for SndFile #include "pos.h" #include "evdata.h" +#include "wave.h" // for SndFileR class QString; diff --git a/muse2/muse/exportmidi.cpp b/muse2/muse/exportmidi.cpp index c5cb44c4..8f5af4c5 100644 --- a/muse2/muse/exportmidi.cpp +++ b/muse2/muse/exportmidi.cpp @@ -180,7 +180,7 @@ void MusE::exportMidi() for (MusECore::ciMarker m = ml->begin(); m != ml->end(); ++m) { QByteArray ba = m->second.name().toLatin1(); const char* name = ba.constData(); - int len = strlen(name); + int len = ba.length(); MusECore::MidiPlayEvent ev(m->first, port, MusECore::ME_META, (unsigned char*)name, len); ev.setA(0x6); l->add(ev); @@ -192,7 +192,7 @@ void MusE::exportMidi() QByteArray ba = MusEGlobal::config.copyright.toLatin1(); const char* copyright = ba.constData(); if (copyright && *copyright) { - int len = strlen(copyright); + int len = ba.length(); MusECore::MidiPlayEvent ev(0, port, MusECore::ME_META, (unsigned char*)copyright, len); ev.setA(0x2); l->add(ev); @@ -293,7 +293,7 @@ void MusE::exportMidi() if (!track->name().isEmpty()) { QByteArray ba = track->name().toLatin1(); const char* name = ba.constData(); - int len = strlen(name); + int len = ba.length(); MusECore::MidiPlayEvent ev(0, port, MusECore::ME_META, (unsigned char*)name, len+1); ev.setA(0x3); // Meta Sequence/Track Name l->add(ev); @@ -309,7 +309,7 @@ void MusE::exportMidi() if (!track->comment().isEmpty()) { QByteArray ba = track->comment().toLatin1(); const char* comment = ba.constData(); - int len = strlen(comment); + int len = ba.length(); MusECore::MidiPlayEvent ev(0, port, MusECore::ME_META, (unsigned char*)comment, len+1); ev.setA(0xf); // Meta Text l->add(ev); diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp index ddbd3ce5..1a6927e8 100644 --- a/muse2/muse/functions.cpp +++ b/muse2/muse/functions.cpp @@ -41,10 +41,9 @@ #include "widgets/function_dialogs/legato.h" #include "widgets/pasteeventsdialog.h" -#include <values.h> +#include <limits.h> #include <iostream> #include <errno.h> -#include <values.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/mman.h> @@ -832,7 +831,7 @@ bool legato(const set<Part*>& parts, int range, int min_len, bool dont_shorten) Event& event1=*(it1->first); Part* part1=it1->second; - unsigned len=MAXINT; + unsigned len=INT_MAX; // we may NOT optimize by letting it2 start at (it1 +1); this optimisation // is only allowed when events was sorted by time. it is, however, sorted // randomly by pointer. @@ -851,7 +850,7 @@ bool legato(const set<Part*>& parts, int range, int min_len, bool dont_shorten) len=event2.tick()-event1.tick(); } - if (len==MAXINT) len=event1.lenTick(); // if no following note was found, keep the length + if (len==INT_MAX) len=event1.lenTick(); // if no following note was found, keep the length if (event1.lenTick() != len) { @@ -955,7 +954,7 @@ void paste_notes(int max_distance, bool always_new_part, bool never_new_part, Pa // if nothing is selected/relevant, this function returns NULL QMimeData* selected_events_to_mime(const set<Part*>& parts, int range) { - unsigned start_tick = MAXINT; //will be the tick of the first event or MAXINT if no events are there + unsigned start_tick = INT_MAX; //will be the tick of the first event or INT_MAX if no events are there for (set<Part*>::iterator part=parts.begin(); part!=parts.end(); part++) for (iEvent ev=(*part)->events()->begin(); ev!=(*part)->events()->end(); ev++) @@ -963,7 +962,7 @@ QMimeData* selected_events_to_mime(const set<Part*>& parts, int range) if (ev->second.tick() < start_tick) start_tick=ev->second.tick(); - if (start_tick == MAXINT) + if (start_tick == INT_MAX) return NULL; //--------------------------------------------------- @@ -1402,7 +1401,7 @@ bool merge_parts(const set<Part*>& parts) { Track* track=*t_it; - unsigned begin=MAXINT, end=0; + unsigned begin=INT_MAX, end=0; Part* first_part=NULL; // find begin of the first and end of the last part @@ -1420,9 +1419,9 @@ bool merge_parts(const set<Part*>& parts) end=p->endTick(); } - if (begin==MAXINT || end==0) + if (begin==INT_MAX || end==0) { - printf("THIS SHOULD NEVER HAPPEN: begin==MAXINT || end==0 in merge_parts()\n"); + printf("THIS SHOULD NEVER HAPPEN: begin==INT_MAX || end==0 in merge_parts()\n"); continue; // skip the actual work, as we cannot work under errornous conditions. } diff --git a/muse2/muse/gconfig.cpp b/muse2/muse/gconfig.cpp index 6ab4df4b..1a0426a7 100644 --- a/muse2/muse/gconfig.cpp +++ b/muse2/muse/gconfig.cpp @@ -143,6 +143,7 @@ GlobalConfigValues config = { true, // importMidiNewStyleDrum 1, // startMode QString(""), // start song path + false, // startSongLoadConfig 384, // gui division QRect(0, 0, 400, 300), // GeometryMain; QRect(0, 0, 200, 100), // GeometryTransport; diff --git a/muse2/muse/gconfig.h b/muse2/muse/gconfig.h index a76b7e13..ead9f258 100644 --- a/muse2/muse/gconfig.h +++ b/muse2/muse/gconfig.h @@ -138,6 +138,7 @@ struct GlobalConfigValues { // 1 - start with default template // 2 - start with song QString startSong; // path for start song + bool startSongLoadConfig; // Whether to load configuration with the start template or song int guiDivision; // division for tick display QRect geometryMain; diff --git a/muse2/muse/globals.cpp b/muse2/muse/globals.cpp index 112b9890..d92e6abf 100644 --- a/muse2/muse/globals.cpp +++ b/muse2/muse/globals.cpp @@ -116,6 +116,7 @@ bool loadVST = true; bool loadDSSI = true; bool usePythonBridge = false; bool useLASH = true; +bool useAlsaWithJack = false; const char* midi_file_pattern[] = { QT_TRANSLATE_NOOP("file_patterns", "Midi/Kar (*.mid *.MID *.kar *.KAR *.mid.gz *.mid.bz2)"), diff --git a/muse2/muse/globals.h b/muse2/muse/globals.h index d691fad1..c64fdf89 100644 --- a/muse2/muse/globals.h +++ b/muse2/muse/globals.h @@ -86,6 +86,7 @@ extern bool loadVST; extern bool loadDSSI; extern bool usePythonBridge; extern bool useLASH; +extern bool useAlsaWithJack; extern bool realTimeScheduling; extern int realTimePriority; diff --git a/muse2/muse/helper.cpp b/muse2/muse/helper.cpp index c5f9eca1..ae2b0352 100644 --- a/muse2/muse/helper.cpp +++ b/muse2/muse/helper.cpp @@ -386,7 +386,7 @@ QMenu* populateAddSynth(QWidget* parent) typedef std::multimap<std::string, int >::iterator imap; - int ntypes = MusECore::Synth::SYNTH_TYPE_END; + const int ntypes = MusECore::Synth::SYNTH_TYPE_END; asmap smaps[ntypes]; QMenu* mmaps[ntypes]; for(int itype = 0; itype < ntypes; ++itype) diff --git a/muse2/muse/icons.cpp b/muse2/muse/icons.cpp index 569f9620..cfe30495 100644 --- a/muse2/muse/icons.cpp +++ b/muse2/muse/icons.cpp @@ -747,4 +747,241 @@ void initIcons() sawIcon = new MPIXMAP(saw_xpm, NULL); } +//--------------------------------------------------------- +// deleteIcons +//--------------------------------------------------------- + +void deleteIcons() + { + delete track_commentIcon; + delete pointerIcon; + delete pencilIcon; + delete deleteIcon; + delete punchinIcon; + delete punchoutIcon; + delete punchin1Icon; + delete punchout1Icon; + delete loopIcon; + delete loop1Icon; + delete playIcon; + + delete record1_Icon; + delete record_on_Icon; + delete record_off_Icon; + delete recordIcon; + delete stopIcon; + delete startIcon; + delete fforwardIcon; + delete frewindIcon; + delete dotIcon; + delete dothIcon; + delete dot1Icon; + delete noteIcon; + delete note1Icon; + delete stickIcon; + delete waveIcon; + delete synthIcon; + delete markIcon[0]; + delete markIcon[1]; + delete markIcon[2]; + delete cutIcon; + delete steprecIcon; + delete glueIcon; + delete drawIcon; + delete cursorIcon; + delete quantIcon; + delete saveIcon; + delete saveasIcon; + delete printIcon; + delete openIcon; + delete saveIconS; + delete saveasIconS; + delete printIconS; + delete openIconS; + delete masterIcon; + delete filenewIcon; + delete filenewIconS; + delete homeIcon; + delete backIcon; + delete forwardIcon; + delete muteIcon; + delete upIcon; + delete downIcon; + delete boldIcon; + delete italicIcon; + delete underlinedIcon; + delete gvIcon; + delete midiinIcon; + delete sysexIcon; + delete ctrlIcon; + delete metaIcon; + delete pitchIcon; + delete cafterIcon; + delete pafterIcon; + delete flagIcon; + delete flagIconS; + delete lockIcon; + delete tocIcon; + delete exitIconS; + + delete undoIcon; + delete redoIcon; + delete undoIconS; + delete redoIconS; + + delete speakerIcon; + delete buttondownIcon; + delete configureIcon; + + delete editmuteIcon; + delete editmuteSIcon; + delete panicIcon; + + delete editcutIconSet; + delete editcopyIconSet; + delete editpasteIconSet; + delete editmuteIconSet; + delete editpaste2TrackIconSet; + delete editpasteCloneIconSet; + delete editpasteClone2TrackIconSet; + + /* Not used - Orcan + delete pianoIcon; + delete editcutIcon; + delete editcopyIcon; + delete editpasteIcon; + delete editpasteCloneIcon; + delete editpaste2TrackIcon; + delete editpasteClone2TrackIcon; + */ + + delete exitIcon; + delete exit1Icon; + + // 2 lines odd code + delete newmuteIcon; + delete soloIcon; + + delete routesInIcon; + delete routesOutIcon; + delete routesMidiInIcon; + delete routesMidiOutIcon; + + delete recEchoIconOn; + delete recEchoIconOff; + delete muteIconOn; + delete muteIconOff; + delete soloIconOn; + delete soloIconOff; + delete soloblksqIconOn; + delete soloblksqIconOff; + //delete soloIconSet1 + //delete soloIconSet2 + + delete toggle_small_Icon; + delete redLedIcon; + delete darkRedLedIcon; + delete greendotIcon; + //delete darkgreendotIcon; + delete bluedotIcon; + delete graydotIcon; + delete offIcon; + delete blacksquareIcon; + delete blacksqcheckIcon; + + delete mastertrackSIcon; + delete localoffSIcon; + delete miditransformSIcon; + delete midi_plugSIcon; + delete miditransposeSIcon; + delete midiThruOnIcon; + delete midiThruOffIcon; + + delete mixerSIcon; + delete mustangSIcon; + delete resetSIcon; + delete track_addIcon; + delete track_deleteIcon; + delete listSIcon; + delete inputpluginSIcon; + delete cliplistSIcon; + delete mixerAudioSIcon; + delete initSIcon; + delete deltaOnIcon; + delete deltaOffIcon; + + delete addtrack_addmiditrackIcon; + delete addtrack_audiogroupIcon; + delete addtrack_audioinputIcon; + delete addtrack_audiooutputIcon; + delete addtrack_auxsendIcon; + delete addtrack_drumtrackIcon; + delete addtrack_wavetrackIcon; + delete edit_drummsIcon; + delete edit_listIcon; + delete edit_waveIcon; + delete edit_mastertrackIcon; + delete edit_pianorollIcon; + delete edit_scoreIcon; + delete edit_track_addIcon; + delete edit_track_delIcon; + delete mastertrack_graphicIcon; + delete mastertrack_listIcon; + delete midi_transformIcon; + delete midi_transposeIcon; + delete selectIcon; + delete select_allIcon; + delete select_all_parts_on_trackIcon; + delete select_deselect_allIcon; + delete select_inside_loopIcon; + delete select_invert_selectionIcon; + delete select_outside_loopIcon; + delete pianoIconSet; + delete scoreIconSet; + + delete audio_bounce_to_fileIcon; + delete audio_bounce_to_trackIcon; + delete audio_restartaudioIcon; + delete automation_clear_dataIcon; + delete automation_mixerIcon; + delete automation_take_snapshotIcon; + delete edit_midiIcon; + delete midi_edit_instrumentIcon; + delete midi_init_instrIcon; + delete midi_inputpluginsIcon; + delete midi_inputplugins_midi_input_filterIcon; + delete midi_inputplugins_midi_input_transformIcon; + delete midi_inputplugins_random_rhythm_generatorIcon; + delete midi_inputplugins_remote_controlIcon; + delete midi_inputplugins_transposeIcon; + delete midi_local_offIcon; + delete midi_reset_instrIcon; + delete settings_appearance_settingsIcon; + delete settings_configureshortcutsIcon; + delete settings_follow_songIcon; + delete settings_globalsettingsIcon; + delete settings_metronomeIcon; + delete settings_midifileexportIcon; + delete settings_midiport_softsynthsIcon; + delete settings_midisyncIcon; + delete view_bigtime_windowIcon; + delete view_cliplistIcon; + delete view_markerIcon; + delete view_mixerIcon; + delete view_transport_windowIcon; + + delete monoIcon; + delete stereoIcon; + + delete museIcon; + delete aboutMuseImage; + delete museLeftSideLogo; + delete globalIcon; + delete userIcon; + delete projectIcon; + + delete sineIcon; + delete sawIcon; + } + } // namespace MusEGui diff --git a/muse2/muse/importmidi.cpp b/muse2/muse/importmidi.cpp index 44b68353..4f5871d6 100644 --- a/muse2/muse/importmidi.cpp +++ b/muse2/muse/importmidi.cpp @@ -22,7 +22,7 @@ //========================================================= #include <errno.h> -#include <values.h> +#include <limits.h> #include <set> #include <utility> diff --git a/muse2/muse/instruments/minstrument.cpp b/muse2/muse/instruments/minstrument.cpp index 5d578803..9e4d4bd9 100644 --- a/muse2/muse/instruments/minstrument.cpp +++ b/muse2/muse/instruments/minstrument.cpp @@ -924,7 +924,7 @@ void MidiInstrument::read(Xml& xml) delete _initScript; QByteArray ba = xml.parse1().toLatin1(); const char* istr = ba.constData(); - int len = strlen(istr) +1; + int len = ba.length() +1; if (len > 1) { _initScript = new char[len]; memcpy(_initScript, istr, len); diff --git a/muse2/muse/liste/editevent.cpp b/muse2/muse/liste/editevent.cpp index 6781c365..a60ea229 100644 --- a/muse2/muse/liste/editevent.cpp +++ b/muse2/muse/liste/editevent.cpp @@ -379,7 +379,7 @@ void EditMetaDialog::toggled(bool flag) QString dst; if (flag) { // convert to hex - dst = string2hex((unsigned char*)src, strlen(src)); + dst = string2hex((unsigned char*)src, ba.length()); } else { // convert to string int len; @@ -422,7 +422,7 @@ void EditMetaDialog::accept() const char* src = ba.constData(); if (!hexButton->isChecked()) { meta = (unsigned char*)strdup(src); - len = strlen(src); + len = ba.length(); QDialog::accept(); return; } @@ -638,6 +638,7 @@ EditCtrlDialog::EditCtrlDialog(int tick, const MusECore::Event& event, continue; } MusECore::MidiController* c = port->midiController(num); + { isList i = sList.begin(); for (; i != sList.end(); ++i) { if (*i == c->name()) @@ -645,6 +646,7 @@ EditCtrlDialog::EditCtrlDialog(int tick, const MusECore::Event& event, } if (i == sList.end()) sList.push_back(c->name()); + } } MusECore::MidiController* mc = port->midiController(num); int idx = 0; diff --git a/muse2/muse/liste/listedit.cpp b/muse2/muse/liste/listedit.cpp index a0d82969..cdc34b45 100644 --- a/muse2/muse/liste/listedit.cpp +++ b/muse2/muse/liste/listedit.cpp @@ -46,6 +46,7 @@ #include "midiport.h" #include "midictrl.h" #include "app.h" +#include "gconfig.h" namespace MusEGui { @@ -606,7 +607,7 @@ ListEdit::ListEdit(MusECore::PartList* pl) setWindowTitle("MusE: List Editor"); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); } //--------------------------------------------------------- @@ -1009,4 +1010,17 @@ void ListEdit::keyPressEvent(QKeyEvent* event) } } +//--------------------------------------------------------- +// focusCanvas +//--------------------------------------------------------- + +void ListEdit::focusCanvas() +{ + if(MusEGlobal::config.smartFocus) + { + liste->setFocus(); + liste->activateWindow(); + } +} + } // namespace MusEGui diff --git a/muse2/muse/liste/listedit.h b/muse2/muse/liste/listedit.h index 1c0c1bd9..1dddb9a6 100644 --- a/muse2/muse/liste/listedit.h +++ b/muse2/muse/liste/listedit.h @@ -84,6 +84,7 @@ class ListEdit : public MidiEditor { public slots: void songChanged(int); + void focusCanvas(); signals: void isDeleting(MusEGui::TopWin*); diff --git a/muse2/muse/main.cpp b/muse2/muse/main.cpp index de2e2512..600ee79b 100644 --- a/muse2/muse/main.cpp +++ b/muse2/muse/main.cpp @@ -36,8 +36,11 @@ #include <QString> #include <QStringList> #include <QStyle> +#include <QStyleFactory> +#include <iostream> - +#include <unistd.h> +#include <time.h> #include <sys/mman.h> #include <alsa/asoundlib.h> @@ -49,11 +52,13 @@ #include "gconfig.h" #include "globals.h" #include "helper.h" -#include "icons.h" #include "sync.h" #include "functions.h" #include "appearance.h" #include "midiseq.h" +#include "minstrument.h" +#include "midiport.h" +#include "mididev.h" #ifdef HAVE_LASH #include <lash/lash.h> @@ -69,12 +74,19 @@ extern void initVST(); extern void initPlugins(); extern void initDSSI(); extern void readConfiguration(); + +extern void initMidiSequencer(); +extern void initAudio(); +extern void initAudioPrefetch(); +extern void initMidiSynth(); + extern snd_seq_t * alsaSeq; +extern void setAlsaClientName(const char*); } namespace MusEGui { -extern void initIcons(); -extern void initShortCuts(); +void initIcons(); +void initShortCuts(); #ifdef HAVE_LASH extern lash_client_t * lash_client; #endif @@ -210,38 +222,58 @@ static QString localeList() static void usage(const char* prog, const char* txt) { - fprintf(stderr, "%s: %s\nusage: %s flags midifile\n Flags:\n", + fprintf(stderr, "\n"); + fprintf(stderr, "%s: %s\nUsage: %s flags midifile\n Flags:\n", prog, txt, prog); - fprintf(stderr, " -h this help\n"); - fprintf(stderr, " -v print version\n"); - fprintf(stderr, " -d debug mode: no threads, no RT\n"); - fprintf(stderr, " -D debug mode: enable some debug messages\n"); - fprintf(stderr, " specify twice for lots of debug messages\n"); - fprintf(stderr, " this may slow down MusE massively!\n"); - fprintf(stderr, " -m debug mode: trace midi Input\n"); - fprintf(stderr, " -M debug mode: trace midi Output\n"); - fprintf(stderr, " -s debug mode: trace sync\n"); - fprintf(stderr, " -u ubuntu/unity workaround: don't allow sharing menus\n"); - fprintf(stderr, " and mdi-subwins.\n"); - fprintf(stderr, " -a no audio\n"); - fprintf(stderr, " -P n set audio driver real time priority to n\n"); - fprintf(stderr, " (Dummy only, default 40. Else fixed by Jack.)\n"); - fprintf(stderr, " -Y n force midi real time priority to n (default: audio driver prio +2)\n"); - fprintf(stderr, " -p don't load LADSPA plugins\n"); -#ifdef ENABLE_PYTHON - fprintf(stderr, " -y enable Python control support\n"); -#endif + fprintf(stderr, " -h This help\n"); + fprintf(stderr, " -v Print version\n"); + fprintf(stderr, " -a No audio, use dummy audio driver, plus ALSA midi\n"); + fprintf(stderr, " -A Force inclusion of ALSA midi even if using Jack\n"); + fprintf(stderr, " -P n Set audio driver real time priority to n\n"); + fprintf(stderr, " (Dummy only, default 40. Else fixed by Jack.)\n"); + fprintf(stderr, " -Y n Force midi real time priority to n (default: audio driver prio +2)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -p Don't load LADSPA plugins\n"); #ifdef VST_SUPPORT - fprintf(stderr, " -V don't load VST plugins\n"); + fprintf(stderr, " -V Don't load VST plugins\n"); #endif #ifdef DSSI_SUPPORT - fprintf(stderr, " -I don't load DSSI plugins\n"); + fprintf(stderr, " -I Don't load DSSI plugins\n"); #endif #ifdef HAVE_LASH - fprintf(stderr, " -L don't use LASH\n"); + fprintf(stderr, " -L Don't use LASH\n"); +#endif +#ifdef ENABLE_PYTHON + fprintf(stderr, " -y Enable Python control support\n"); #endif - fprintf(stderr, " -l xx force locale to the given language/country code\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -l xx Force locale to the given language/country code\n"); fprintf(stderr, " (xx = %s)\n", localeList().toLatin1().constData()); + fprintf(stderr, " -u Ubuntu/unity workaround: don't allow sharing menus\n"); + fprintf(stderr, " and mdi-subwins.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -d Debug mode: no threads, no RT\n"); + fprintf(stderr, " -D Debug mode: enable some debug messages\n"); + fprintf(stderr, " specify twice for lots of debug messages\n"); + fprintf(stderr, " this may slow down MusE massively!\n"); + fprintf(stderr, " -m Debug mode: trace midi Input\n"); + fprintf(stderr, " -M Debug mode: trace midi Output\n"); + fprintf(stderr, " -s Debug mode: trace sync\n"); + fprintf(stderr, "\n"); +#ifdef HAVE_LASH + fprintf(stderr, "LASH and "); +#endif + fprintf(stderr, "Qt options are also accepted. Some common Qt options:\n"); + fprintf(stderr, " -style [=] style Set application GUI style. Motif, Windows, Platinum etc.\n" + " -stylesheet [=] stylesheet Set application styleSheet\n" + " -session [=] session Restore application from an earlier session\n" + " -widgetcount Print debug message at end, about undestroyed/maximum widgets\n" + " -reverse Set application's layout direction to Qt::RightToLeft\n" + " -graphicssystem Set backend used for on-screen widgets/QPixmaps: raster or opengl\n" + " -qmljsdebugger = port Activate QML/JS debugger with port, formatted port:1234[,block]\n" + ); + + fprintf(stderr, "\n"); } //--------------------------------------------------------- @@ -250,50 +282,17 @@ static void usage(const char* prog, const char* txt) int main(int argc, char* argv[]) { - - MusEGlobal::ruid = getuid(); - MusEGlobal::euid = geteuid(); - MusEGlobal::undoSetuid(); - getCapabilities(); - int noAudio = false; - MusEGlobal::museUser = QString(getenv("HOME")); MusEGlobal::museGlobalLib = QString(LIBDIR); MusEGlobal::museGlobalShare = QString(SHAREDIR); MusEGlobal::museProject = MusEGlobal::museProjectInitPath; //getcwd(0, 0); MusEGlobal::museInstruments = MusEGlobal::museGlobalShare + QString("/instruments"); - // Create config dir if it doesn't exists + // Create config dir if it doesn't exist QDir cPath = QDir(MusEGlobal::configPath); 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")); - if(old_utemplDir.exists()) - { - // 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); - } - } - } - QFile cConf (MusEGlobal::configName); QFile cConfTempl (MusEGlobal::museGlobalShare + QString("/templates/MusE.cfg")); bool cConfExists = cConf.exists(); @@ -317,82 +316,38 @@ int main(int argc, char* argv[]) printf (" FAILED!\n"); } -#ifdef HAVE_LASH - lash_args_t * lash_args = 0; - if(MusEGlobal::useLASH) - lash_args = lash_extract_args (&argc, &argv); -#endif - - srand(time(0)); // initialize random number generator -// signal(SIGCHLD, catchSignal); // interferes with initVST(). see also app.cpp, function catchSignal() - MusECore::initMidiController(); - QApplication::setColorSpec(QApplication::ManyColor); - MuseApplication app(argc, argv); - MusEGui::Appearance::defaultStyle = MuseApplication::style()->objectName(); - - MusEGui::init_function_dialogs(MusEGlobal::muse); MusEGui::initShortCuts(); - MusECore::readConfiguration(); - - // Need to put a sane default here because we can't use ~ in the file name string. + + // Need to put a sane defaults here because we can't use '~' in the file name strings. if(!cConfExists) - MusEGlobal::config.projectBaseFolder = MusEGlobal::museUser + QString("/MusE"); - - // 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); - if(old_uinstrDir.exists()) - { - 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()); - } - } - } - } - MusEGlobal::museUserInstruments = uinstrPath; + MusEGlobal::config.projectBaseFolder = MusEGlobal::museUser + QString("/MusE"); + MusEGlobal::config.startSong = MusEGlobal::museGlobalShare + QString("/templates/default.med"); } - if (MusEGlobal::config.useDenormalBias) - printf("Denormal protection enabled.\n"); - // SHOW MUSE SPLASH SCREEN - if (MusEGlobal::config.showSplashScreen) { - QPixmap splsh(MusEGlobal::museGlobalShare + "/splash.png"); - - if (!splsh.isNull()) { - QSplashScreen* muse_splash = new QSplashScreen(splsh, - Qt::WindowStaysOnTopHint); - muse_splash->setAttribute(Qt::WA_DeleteOnClose); // Possibly also Qt::X11BypassWindowManagerHint - muse_splash->show(); - QTimer* stimer = new QTimer(0); - muse_splash->connect(stimer, SIGNAL(timeout()), muse_splash, SLOT(close())); - stimer->setSingleShot(true); - stimer->start(6000); - } - } - - int i; + // May need this. Tested OK. Grab the default style BEFORE calling setStyle and creating the app. + //{ int dummy_argc = 1; char** dummy_argv = &argv[0]; + // QApplication dummy_app(dummy_argc, dummy_argv); + // MusEGui::Appearance::defaultStyle = dummy_app.style()->objectName(); } + //QStringList sl = QStyleFactory::keys(); + //if (sl.indexOf(MusEGlobal::config.style) != -1) { + // QStyle* style = QApplication::setStyle(MusEGlobal::config.style); + // style->setObjectName(MusEGlobal::config.style); + //} + + // Let LASH remove its recognized arguments first (generally longer than Qt's). + // Tip: LADISH's LASH emulation (current 1.0) does not take any arguments. +#ifdef HAVE_LASH + lash_args_t * lash_args = 0; + lash_args = lash_extract_args (&argc, &argv); +#endif - QString optstr("ahvdDumMsP:Y:l:py"); + // Now create the application, and let Qt remove recognized arguments. + MuseApplication app(argc, argv); + MusEGui::Appearance::defaultStyle = app.style()->objectName(); // NOTE: May need alternate method, above. + + QString optstr("aAhvdDumMsP:Y:l:py"); #ifdef VST_SUPPORT optstr += QString("V"); #endif @@ -402,23 +357,35 @@ int main(int argc, char* argv[]) #ifdef HAVE_LASH optstr += QString("L"); #endif - + + bool noAudio = false; + int i; + + // Now read the remaining arguments as our own... while ((i = getopt(argc, argv, optstr.toLatin1().constData())) != EOF) { char c = (char)i; switch (c) { - case 'v': printVersion(argv[0]); return 0; + case 'v': printVersion(argv[0]); +#ifdef HAVE_LASH + if(lash_args) lash_args_destroy(lash_args); +#endif + return 0; + case 'a': + noAudio = true; + break; + case 'A': + MusEGlobal::useAlsaWithJack = true; + break; case 'd': MusEGlobal::debugMode = true; MusEGlobal::realTimeScheduling = false; break; - case 'a': - noAudio = true; - break; case 'D': if (!MusEGlobal::debugMsg) MusEGlobal::debugMsg=true; else MusEGlobal::heavyDebugMsg=true; + break; case 'm': MusEGlobal::midiInputTrace = true; break; case 'M': MusEGlobal::midiOutputTrace = true; break; case 's': MusEGlobal::debugSync = true; break; @@ -428,20 +395,188 @@ int main(int argc, char* argv[]) case 'p': MusEGlobal::loadPlugins = false; break; case 'V': MusEGlobal::loadVST = false; break; case 'I': MusEGlobal::loadDSSI = false; break; - case 'L': MusEGlobal::useLASH = false; break; + case 'L': MusEGlobal::useLASH = false; break; case 'y': MusEGlobal::usePythonBridge = true; break; case 'l': locale_override = QString(optarg); break; - case 'h': usage(argv[0], argv[1]); return -1; - default: usage(argv[0], "bad argument"); return -1; + case 'h': usage(argv[0], argv[1]); +#ifdef HAVE_LASH + if(lash_args) lash_args_destroy(lash_args); +#endif + return -1; + default: usage(argv[0], "bad argument"); +#ifdef HAVE_LASH + if(lash_args) lash_args_destroy(lash_args); +#endif + return -1; } } + + argc -= optind; + ++argc; + + MusEGlobal::ruid = getuid(); + MusEGlobal::euid = geteuid(); + MusEGlobal::undoSetuid(); + getCapabilities(); + if (MusEGlobal::debugMsg) + printf("Start euid: %d ruid: %d, Now euid %d\n", + MusEGlobal::euid, MusEGlobal::ruid, geteuid()); + + srand(time(0)); // initialize random number generator + //signal(SIGCHLD, catchSignal); // interferes with initVST(). see also app.cpp, function catchSignal() + static QTranslator translator(0); + QString locale(QLocale::system().name()); + if (locale_override.length() >0 ) + locale = locale_override; + if (locale != "C") { + QString loc("muse_"); + loc += locale; + if (translator.load(loc, QString(".")) == false) { + QString lp(MusEGlobal::museGlobalShare); + lp += QString("/locale"); + if (translator.load(loc, lp) == false) { + printf("no locale <%s>/<%s>\n", loc.toLatin1().constData(), lp.toLatin1().constData()); + } + } + app.installTranslator(&translator); + } + printf("LOCALE %s\n",QLocale::system().name().toLatin1().data()); + + if (QLocale::system().name() == "de" || locale_override == "de") { + printf("locale de - setting override parameter.\n"); + MusEGlobal::hIsB = false; + } + + QApplication::addLibraryPath(MusEGlobal::museGlobalLib + "/qtplugins"); + if (MusEGlobal::debugMsg) { + QStringList list = app.libraryPaths(); + QStringList::Iterator it = list.begin(); + printf("QtLibraryPath:\n"); + while(it != list.end()) { + printf(" <%s>\n", (*it).toLatin1().constData()); + ++it; + } + } + + // 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")); + if(old_utemplDir.exists()) + { + // 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); + } + } + } + + // 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); + if(old_uinstrDir.exists()) + { + 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()); + } + } + } + } + MusEGlobal::museUserInstruments = uinstrPath; + + // NOTE: May need alternate method, above. + // If setStyle is called after MusE is created, bug: I get transparent background in MDI windows, other artifacts. + // Docs say any style should be set before QApplication created, but this actually works OK up to that point! + QStringList sl = QStyleFactory::keys(); + if (sl.indexOf(MusEGlobal::config.style) != -1) + { + QStyle* style = app.setStyle(MusEGlobal::config.style); + style->setObjectName(MusEGlobal::config.style); + } AL::initDsp(); + MusECore::initAudio(); + + MusEGui::initIcons(); + + MusEGlobal::muse = new MusEGui::MusE(); + app.setMuse(MusEGlobal::muse); + + MusEGui::init_function_dialogs(MusEGlobal::muse); + MusEGui::retranslate_function_dialogs(); + + // SHOW MUSE SPLASH SCREEN + if (MusEGlobal::config.showSplashScreen) { + QPixmap splsh(MusEGlobal::museGlobalShare + "/splash.png"); + + if (!splsh.isNull()) { + QSplashScreen* muse_splash = new QSplashScreen(splsh, + Qt::WindowStaysOnTopHint); + muse_splash->setAttribute(Qt::WA_DeleteOnClose); // Possibly also Qt::X11BypassWindowManagerHint + muse_splash->show(); + QTimer* stimer = new QTimer(0); + muse_splash->connect(stimer, SIGNAL(timeout()), muse_splash, SLOT(close())); + stimer->setSingleShot(true); + stimer->start(6000); + } + } + + if (MusEGlobal::config.useDenormalBias) + printf("Denormal protection enabled.\n"); + if (MusEGlobal::debugMsg) { + printf("global lib: <%s>\n", MusEGlobal::museGlobalLib.toLatin1().constData()); + printf("global share: <%s>\n", MusEGlobal::museGlobalShare.toLatin1().constData()); + printf("muse home: <%s>\n", MusEGlobal::museUser.toLatin1().constData()); + printf("project dir: <%s>\n", MusEGlobal::museProject.toLatin1().constData()); + printf("user instruments: <%s>\n", MusEGlobal::museUserInstruments.toLatin1().constData()); + } + + //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)) + MusEGlobal::realTimePriority = sched_get_priority_max(SCHED_FIFO); + // If we requested to force the midi thread priority... + if(MusEGlobal::midiRTPrioOverride > 0) + { + if (MusEGlobal::midiRTPrioOverride < sched_get_priority_min(SCHED_FIFO)) + MusEGlobal::midiRTPrioOverride = sched_get_priority_min(SCHED_FIFO); + else if (MusEGlobal::midiRTPrioOverride > sched_get_priority_max(SCHED_FIFO)) + MusEGlobal::midiRTPrioOverride = sched_get_priority_max(SCHED_FIFO); + } - if (MusEGlobal::debugMsg) - printf("Start euid: %d ruid: %d, Now euid %d\n", - MusEGlobal::euid, MusEGlobal::ruid, geteuid()); if (MusEGlobal::debugMode) { MusECore::initDummyAudio(); MusEGlobal::realTimeScheduling = false; @@ -483,45 +618,26 @@ int main(int argc, char* argv[]) // I cannot seem to find a reliable answer to the question, even with dummy audio and system calls. MusEGlobal::useJackTransport.setValue(true); - + // setup the prefetch fifo length now that the segmentSize is known MusEGlobal::fifoLength = 131072 / MusEGlobal::segmentSize; + MusECore::initAudioPrefetch(); + + // WARNING Must do it this way. Call registerClient long AFTER Jack client is created and MusE ALSA client is + // created (in initMidiDevices), otherwise random crashes can occur within Jack <= 1.9.8. Fixed in Jack 1.9.9. Tim. + MusECore::initMidiDevices(); + // Wait until things have settled. One second seems OK so far. + for(int t = 0; t < 100; ++t) + usleep(10000); + // Now it is safe to call registerClient. + MusEGlobal::audioDevice->registerClient(); - argc -= optind; - ++argc; - - if (MusEGlobal::debugMsg) { - printf("global lib: <%s>\n", MusEGlobal::museGlobalLib.toLatin1().constData()); - printf("global share: <%s>\n", MusEGlobal::museGlobalShare.toLatin1().constData()); - printf("muse home: <%s>\n", MusEGlobal::museUser.toLatin1().constData()); - printf("project dir: <%s>\n", MusEGlobal::museProject.toLatin1().constData()); - printf("user instruments: <%s>\n", MusEGlobal::museUserInstruments.toLatin1().constData()); - } - - static QTranslator translator(0); - QString locale(QApplication::keyboardInputLocale().name()); - if (locale_override.length()) - locale = locale_override; - if (locale != "C") { - QString loc("muse_"); - loc += locale; - if (translator.load(loc, QString(".")) == false) { - QString lp(MusEGlobal::museGlobalShare); - lp += QString("/locale"); - if (translator.load(loc, lp) == false) { - printf("no locale <%s>/<%s>\n", loc.toLatin1().constData(), lp.toLatin1().constData()); - } - } - app.installTranslator(&translator); - } + MusECore::initMidiController(); + MusECore::initMidiInstruments(); + MusECore::initMidiPorts(); + MusECore::initMidiSequencer(); + MusEGlobal::midiSeq->checkAndReportTimingResolution(); - if (locale == "de") { - printf("locale de\n"); - MusEGlobal::hIsB = false; - } - - MusEGui::retranslate_function_dialogs(); - if (MusEGlobal::loadPlugins) MusECore::initPlugins(); @@ -533,32 +649,9 @@ int main(int argc, char* argv[]) MusECore::initOSC(); - MusEGui::initIcons(); - MusECore::initMetronome(); - QApplication::addLibraryPath(MusEGlobal::museGlobalLib + "/qtplugins"); - if (MusEGlobal::debugMsg) { - QStringList list = app.libraryPaths(); - QStringList::Iterator it = list.begin(); - printf("QtLibraryPath:\n"); - while(it != list.end()) { - printf(" <%s>\n", (*it).toLatin1().constData()); - ++it; - } - } - - MusEGlobal::muse = new MusEGui::MusE(argc, &argv[optind]); - app.setMuse(MusEGlobal::muse); - MusEGlobal::muse->setWindowIcon(*MusEGui::museIcon); - - if (!MusEGlobal::debugMode) { - if (mlockall(MCL_CURRENT | MCL_FUTURE)) - perror("WARNING: Cannot lock memory:"); - } - - MusEGlobal::muse->show(); - MusEGlobal::muse->seqStart(); + MusECore::initMidiSynth(); #ifdef HAVE_LASH { @@ -568,19 +661,30 @@ int main(int argc, char* argv[]) int lash_flags = LASH_Config_File; const char *muse_name = PACKAGE_NAME; 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(MusECore::alsaSeq) + lash_alsa_client_id (MusEGui::lash_client, snd_seq_client_id (MusECore::alsaSeq)); if (!noAudio) { const char *jack_name = MusEGlobal::audioDevice->clientName(); lash_jack_client_name (MusEGui::lash_client, jack_name); } } + if(lash_args) + lash_args_destroy(lash_args); } #endif /* HAVE_LASH */ + if (!MusEGlobal::debugMode) { + if (mlockall(MCL_CURRENT | MCL_FUTURE)) + perror("WARNING: Cannot lock memory:"); + } + + MusEGlobal::muse->show(); + MusEGlobal::muse->seqStart(); + //-------------------------------------------------- - // Auto-fill the midi ports, if appropriate. p4.0.41 + // Auto-fill the midi ports, if appropriate. //-------------------------------------------------- - if(argc < 2 && MusEGlobal::config.startMode == 1) + if(argc < 2 && (MusEGlobal::config.startMode == 1 || MusEGlobal::config.startMode == 2) && !MusEGlobal::config.startSongLoadConfig) { MusEGui::populateMidiPorts(); //MusEGlobal::muse->changeConfig(true); // save configuration file @@ -590,11 +694,8 @@ int main(int argc, char* argv[]) //-------------------------------------------------- // Load the default song. //-------------------------------------------------- - MusEGlobal::muse->loadDefaultSong(argc, &argv[optind]); // p4.0.41 + MusEGlobal::muse->loadDefaultSong(argc, &argv[optind]); - MusEGlobal::midiSeq->checkAndReportTimingResolution(); - - 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 5e84295e..062f4385 100644 --- a/muse2/muse/marker/markerview.cpp +++ b/muse2/muse/marker/markerview.cpp @@ -275,7 +275,7 @@ MarkerView::MarkerView(QWidget* parent) updateList(); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); // work around for probable QT/WM interaction bug. // for certain window managers, e.g xfce, this window is diff --git a/muse2/muse/master/lmaster.cpp b/muse2/muse/master/lmaster.cpp index 1553e17f..154b5e1f 100644 --- a/muse2/muse/master/lmaster.cpp +++ b/muse2/muse/master/lmaster.cpp @@ -31,6 +31,7 @@ #include "audio.h" #include "shortcuts.h" #include "debug.h" +#include "gconfig.h" #include <QCloseEvent> #include <QGridLayout> @@ -273,7 +274,7 @@ LMaster::LMaster() connect(keyButton, SIGNAL(clicked()), SLOT(insertKey())); initShortcuts(); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); } //--------------------------------------------------------- @@ -285,6 +286,19 @@ LMaster::~LMaster() } //--------------------------------------------------------- +// focusCanvas +//--------------------------------------------------------- + +void LMaster::focusCanvas() +{ + if(MusEGlobal::config.smartFocus) + { + view->setFocus(); + view->activateWindow(); + } +} + +//--------------------------------------------------------- // insertSig //--------------------------------------------------------- diff --git a/muse2/muse/master/lmaster.h b/muse2/muse/master/lmaster.h index 367eff77..d3278333 100644 --- a/muse2/muse/master/lmaster.h +++ b/muse2/muse/master/lmaster.h @@ -167,6 +167,7 @@ class LMaster : public MidiEditor { public slots: void songChanged(int); void configChanged(); + void focusCanvas(); signals: void isDeleting(MusEGui::TopWin*); diff --git a/muse2/muse/master/master.cpp b/muse2/muse/master/master.cpp index 239467ee..5d6e6e63 100644 --- a/muse2/muse/master/master.cpp +++ b/muse2/muse/master/master.cpp @@ -21,7 +21,7 @@ //========================================================= #include <stdio.h> -#include <values.h> +#include <limits.h> #include <QCursor> #include <QEvent> @@ -138,7 +138,7 @@ void Master::setPos(int idx, unsigned val, bool adjustScrollbar) void Master::leaveEvent(QEvent*) { emit tempoChanged(-1); - emit timeChanged(MAXINT); + emit timeChanged(INT_MAX); } //--------------------------------------------------------- diff --git a/muse2/muse/master/masteredit.cpp b/muse2/muse/master/masteredit.cpp index 82ac697b..53ebf953 100644 --- a/muse2/muse/master/masteredit.cpp +++ b/muse2/muse/master/masteredit.cpp @@ -40,7 +40,7 @@ #include "gconfig.h" #include "audio.h" -#include <values.h> +#include <limits.h> #include <QActionGroup> #include <QCloseEvent> @@ -252,16 +252,13 @@ MasterEdit::MasterEdit() connect(canvas, SIGNAL(followEvent(int)), hscroll, SLOT(setOffset(int))); connect(canvas, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned))); - if(MusEGlobal::config.smartFocus) - { - connect(curSig, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(curSig, SIGNAL(escapePressed()), SLOT(focusCanvas())); - connect(curTempo, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(curTempo, SIGNAL(escapePressed()), SLOT(focusCanvas())); - } + connect(curSig, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(curSig, SIGNAL(escapePressed()), SLOT(focusCanvas())); + connect(curTempo, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(curTempo, SIGNAL(escapePressed()), SLOT(focusCanvas())); initTopwinState(); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); } //--------------------------------------------------------- @@ -381,8 +378,11 @@ void MasterEdit::writeConfiguration(int level, MusECore::Xml& xml) void MasterEdit::focusCanvas() { - canvas->setFocus(); - canvas->activateWindow(); + if(MusEGlobal::config.smartFocus) + { + canvas->setFocus(); + canvas->activateWindow(); + } } //--------------------------------------------------------- @@ -396,8 +396,7 @@ void MasterEdit::_setRaster(int index) }; _raster = rasterTable[index]; _rasterInit = _raster; - if(MusEGlobal::config.smartFocus) - focusCanvas(); + focusCanvas(); } //--------------------------------------------------------- @@ -427,7 +426,7 @@ void MasterEdit::posChanged(int idx, unsigned val, bool) void MasterEdit::setTime(unsigned tick) { - if (tick == MAXINT) + if (tick == INT_MAX) cursorPos->setEnabled(false); else { cursorPos->setEnabled(true); diff --git a/muse2/muse/master/masteredit.h b/muse2/muse/master/masteredit.h index faff69e2..15b5a649 100644 --- a/muse2/muse/master/masteredit.h +++ b/muse2/muse/master/masteredit.h @@ -87,10 +87,10 @@ class MasterEdit : public MidiEditor { void setTempo(int); void sigChange(const AL::TimeSignature&); void tempoChange(double); - void focusCanvas(); public slots: void songChanged(int); + void focusCanvas(); signals: void isDeleting(MusEGui::TopWin*); diff --git a/muse2/muse/midi.cpp b/muse2/muse/midi.cpp index 2c3c3d8c..ae348b5f 100644 --- a/muse2/muse/midi.cpp +++ b/muse2/muse/midi.cpp @@ -24,7 +24,6 @@ #include <cmath> #include <errno.h> -#include <values.h> #include "song.h" #include "midi.h" diff --git a/muse2/muse/mididev.cpp b/muse2/muse/mididev.cpp index 31a8f6fe..becab6f7 100644 --- a/muse2/muse/mididev.cpp +++ b/muse2/muse/mididev.cpp @@ -38,6 +38,7 @@ #include "gconfig.h" #include "globals.h" #include "audio.h" +#include "audiodev.h" #include "midiseq.h" #include "sync.h" #include "midiitransform.h" @@ -68,13 +69,16 @@ void initMidiDevices() #ifdef MIDI_DRIVER_MIDI_SERIAL initMidiSerial(); #endif - if(initMidiAlsa()) + if(MusEGlobal::useAlsaWithJack || MusEGlobal::audioDevice->deviceType() != AudioDevice::JACK_AUDIO) + { + if(initMidiAlsa()) { QMessageBox::critical(NULL, "MusE fatal error.", "MusE failed to initialize the\n" "Alsa midi subsystem, check\n" "your configuration."); exit(-1); } + } if(initMidiJack()) { diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index 6c3f865f..42eda0fd 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -35,7 +35,7 @@ #include <QPair> #include <stdio.h> -#include <values.h> +#include <limits.h> #include <errno.h> #include "dcanvas.h" diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp index 34a5bce5..9c559fcd 100644 --- a/muse2/muse/midiedit/drumedit.cpp +++ b/muse2/muse/midiedit/drumedit.cpp @@ -595,11 +595,8 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un connect(toolbar, SIGNAL(soloChanged(bool)), SLOT(soloChanged(bool))); connect(info, SIGNAL(valueChanged(MusEGui::NoteInfo::ValType, int)), SLOT(noteinfoChanged(MusEGui::NoteInfo::ValType, int))); connect(info, SIGNAL(deltaModeChanged(bool)), SLOT(deltaModeChanged(bool))); - if(MusEGlobal::config.smartFocus) - { - connect(info, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(info, SIGNAL(escapePressed()), SLOT(focusCanvas())); - } + connect(info, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(info, SIGNAL(escapePressed()), SLOT(focusCanvas())); connect(ctrl, SIGNAL(clicked()), SLOT(addCtrl())); @@ -616,10 +613,10 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un //canvas->selectFirst(); unsigned pos=0; - if(initPos >= MAXINT) + if(initPos >= INT_MAX) pos = MusEGlobal::song->cpos(); - if(pos > MAXINT) - pos = MAXINT; + if(pos > INT_MAX) + pos = INT_MAX; if (pos) hscroll->setOffset((int)pos); @@ -628,7 +625,7 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un initTopwinState(); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); } //--------------------------------------------------------- @@ -793,8 +790,11 @@ void DrumEdit::setSelection(int tick, MusECore::Event& e, MusECore::Part*, bool void DrumEdit::focusCanvas() { - canvas->setFocus(); - canvas->activateWindow(); + if(MusEGlobal::config.smartFocus) + { + canvas->setFocus(); + canvas->activateWindow(); + } } //--------------------------------------------------------- @@ -840,8 +840,7 @@ void DrumEdit::setRaster(int val) _rasterInit = val; MidiEditor::setRaster(val); canvas->redrawGrid(); - if(MusEGlobal::config.smartFocus) - focusCanvas(); // give back focus after kb input + focusCanvas(); // give back focus after kb input } //--------------------------------------------------------- @@ -1552,8 +1551,7 @@ void DrumEdit::execUserScript(int id) void DrumEdit::setStep(QString v) { ((DrumCanvas*)canvas)->setStep(v.toInt()); - if(MusEGlobal::config.smartFocus) - focusCanvas(); + focusCanvas(); } void DrumEdit::ourDrumMapChanged(bool instrMapChanged) diff --git a/muse2/muse/midiedit/drumedit.h b/muse2/muse/midiedit/drumedit.h index 7f2d26ce..7704b283 100644 --- a/muse2/muse/midiedit/drumedit.h +++ b/muse2/muse/midiedit/drumedit.h @@ -25,7 +25,7 @@ #include <QByteArray> -#include <values.h> +#include <limits.h> #include "midieditor.h" #include "noteinfo.h" #include "cobject.h" @@ -146,6 +146,7 @@ class DrumEdit : public MidiEditor { void configChanged(); void songChanged1(int); void setStep(QString); + void updateGroupingActions(); void set_ignore_hide(bool); void showAllInstruments(); @@ -154,14 +155,15 @@ class DrumEdit : public MidiEditor { void hideEmptyInstruments(); void display_old_new_conflict_message(); - void focusCanvas(); + void deltaModeChanged(bool); public slots: - void setSelection(int /*tick*/, MusECore::Event&, MusECore::Part*, bool /*update*/); + void setSelection(int tick, MusECore::Event&, MusECore::Part*, bool update); void soloChanged(bool); // called by Solo button void execDeliveredScript(int); void execUserScript(int); + void focusCanvas(); CtrlEdit* addCtrl(); void ourDrumMapChanged(bool); virtual void updateHScrollRange(); @@ -170,7 +172,7 @@ class DrumEdit : public MidiEditor { void isDeleting(MusEGui::TopWin*); public: - DrumEdit(MusECore::PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = MAXINT); + DrumEdit(MusECore::PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = INT_MAX); virtual ~DrumEdit(); virtual void readStatus(MusECore::Xml&); virtual void writeStatus(int, MusECore::Xml&) const; diff --git a/muse2/muse/midiedit/ecanvas.cpp b/muse2/muse/midiedit/ecanvas.cpp index 75757bf9..88cf3318 100644 --- a/muse2/muse/midiedit/ecanvas.cpp +++ b/muse2/muse/midiedit/ecanvas.cpp @@ -23,7 +23,7 @@ #include <stdio.h> #include <errno.h> -#include <values.h> +#include <limits.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/mman.h> @@ -92,7 +92,7 @@ QString EventCanvas::getCaption() const void EventCanvas::leaveEvent(QEvent*) { emit pitchChanged(-1); - emit timeChanged(MAXINT); + emit timeChanged(INT_MAX); } //--------------------------------------------------------- @@ -150,7 +150,8 @@ void EventCanvas::songChanged(int flags) return; if (flags & ~SC_SELECTION) { - //items.clear(); DELETETHIS + // TODO FIXME: don't we actually only want SC_PART_*, and maybe SC_TRACK_DELETED? + // (same in waveview.cpp) bool curItemNeedsRestore=false; MusECore::Event storedEvent; int partSn; @@ -163,7 +164,7 @@ void EventCanvas::songChanged(int flags) curItem=NULL; items.clearDelete(); - start_tick = MAXINT; + start_tick = INT_MAX; end_tick = 0; curPart = 0; for (MusECore::iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p) { @@ -331,6 +332,9 @@ 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) { rciCItem i; + + if (items.empty()) + return; for (i = items.rbegin(); i != items.rend(); ++i) if (i->second->isSelected()) break; @@ -359,7 +363,9 @@ void EventCanvas::keyPress(QKeyEvent* event) //Select items by key: (PianoRoll & DrumEditor) else if (key == shortcuts[SHRT_SEL_LEFT].key || key == shortcuts[SHRT_SEL_LEFT_ADD].key) { ciCItem i; - for (i = items.begin(); i != items.end(); ++i) + if (items.empty()) + return; + for (i = items.begin(); i != items.end(); ++i) if (i->second->isSelected()) break; diff --git a/muse2/muse/midiedit/pianoroll.cpp b/muse2/muse/midiedit/pianoroll.cpp index d8608c70..951fcbf2 100644 --- a/muse2/muse/midiedit/pianoroll.cpp +++ b/muse2/muse/midiedit/pianoroll.cpp @@ -431,13 +431,10 @@ PianoRoll::PianoRoll(MusECore::PartList* pl, QWidget* parent, const char* name, connect(speaker, SIGNAL(toggled(bool)), SLOT(setSpeaker(bool))); connect(canvas, SIGNAL(followEvent(int)), SLOT(follow(int))); - if(MusEGlobal::config.smartFocus) - { - connect(info, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(info, SIGNAL(escapePressed()), SLOT(focusCanvas())); - connect(midiTrackInfo, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(midiTrackInfo, SIGNAL(escapePressed()), SLOT(focusCanvas())); - } + connect(info, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(info, SIGNAL(escapePressed()), SLOT(focusCanvas())); + connect(midiTrackInfo, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(midiTrackInfo, SIGNAL(escapePressed()), SLOT(focusCanvas())); connect(hscroll, SIGNAL(scaleChanged(int)), SLOT(updateHScrollRange())); piano->setYPos(KH * 30); @@ -474,10 +471,10 @@ PianoRoll::PianoRoll(MusECore::PartList* pl, QWidget* parent, const char* name, canvas->selectAtTick(cpos.tick()); unsigned pos=0; - if(initPos >= MAXINT) + if(initPos >= INT_MAX) pos = MusEGlobal::song->cpos(); - if(pos > MAXINT) - pos = MAXINT; + if(pos > INT_MAX) + pos = INT_MAX; if (pos) hscroll->setOffset((int)pos); @@ -488,7 +485,7 @@ PianoRoll::PianoRoll(MusECore::PartList* pl, QWidget* parent, const char* name, } initTopwinState(); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); } //--------------------------------------------------------- @@ -706,8 +703,11 @@ void PianoRoll::setSelection(int tick, MusECore::Event& e, MusECore::Part* /*par void PianoRoll::focusCanvas() { - canvas->setFocus(); - canvas->activateWindow(); + if(MusEGlobal::config.smartFocus) + { + canvas->setFocus(); + canvas->activateWindow(); + } } //--------------------------------------------------------- @@ -911,8 +911,7 @@ void PianoRoll::setRaster(int val) _rasterInit = val; MidiEditor::setRaster(val); canvas->redrawGrid(); - if(MusEGlobal::config.smartFocus) - focusCanvas(); // give back focus after kb input + focusCanvas(); // give back focus after kb input } //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/pianoroll.h b/muse2/muse/midiedit/pianoroll.h index ad77b973..8040dc7b 100644 --- a/muse2/muse/midiedit/pianoroll.h +++ b/muse2/muse/midiedit/pianoroll.h @@ -28,7 +28,7 @@ #include <QLabel> #include <QKeyEvent> -#include <values.h> +#include <limits.h> #include "noteinfo.h" #include "cobject.h" #include "midieditor.h" @@ -169,7 +169,6 @@ class PianoRoll : public MidiEditor { void newCanvasWidth(int); void toggleTrackInfo(); void updateTrackInfo(); - void focusCanvas(); void deltaModeChanged(bool); signals: @@ -179,10 +178,11 @@ class PianoRoll : public MidiEditor { virtual void updateHScrollRange(); void execDeliveredScript(int id); void execUserScript(int id); + void focusCanvas(); CtrlEdit* addCtrl(); public: - PianoRoll(MusECore::PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = MAXINT); + PianoRoll(MusECore::PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = INT_MAX); ~PianoRoll(); virtual void readStatus(MusECore::Xml&); virtual void writeStatus(int, MusECore::Xml&) const; diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp index 0ccabbe0..2bf94269 100644 --- a/muse2/muse/midiedit/prcanvas.cpp +++ b/muse2/muse/midiedit/prcanvas.cpp @@ -34,7 +34,7 @@ #include <set> -#include <values.h> +#include <limits.h> #include <stdio.h> #include <math.h> #include <errno.h> diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index 44629eef..9630fc7c 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -323,11 +323,8 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) //many many undos when using the spin buttons. connect(velo_spinbox, SIGNAL(editingFinished()), SLOT(velo_box_changed())); connect(this,SIGNAL(velo_changed(int)), score_canvas, SLOT(set_velo(int))); - if(MusEGlobal::config.smartFocus) - { - connect(velo_spinbox, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(velo_spinbox, SIGNAL(escapePressed()), SLOT(focusCanvas())); - } + connect(velo_spinbox, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(velo_spinbox, SIGNAL(escapePressed()), SLOT(focusCanvas())); note_settings_toolbar->addWidget(velo_spinbox); velo_spinbox->setValue(ScoreCanvas::note_velo_init); @@ -339,11 +336,8 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) //many many undos when using the spin buttons. 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))); - if(MusEGlobal::config.smartFocus) - { - connect(velo_off_spinbox, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(velo_off_spinbox, SIGNAL(escapePressed()), SLOT(focusCanvas())); - } + connect(velo_off_spinbox, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(velo_off_spinbox, SIGNAL(escapePressed()), SLOT(focusCanvas())); note_settings_toolbar->addWidget(velo_off_spinbox); velo_off_spinbox->setValue(ScoreCanvas::note_velo_off_init); @@ -376,11 +370,8 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) px_per_whole_spinbox->setSingleStep(50); 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))); - if(MusEGlobal::config.smartFocus) - { - connect(px_per_whole_spinbox, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(px_per_whole_spinbox, SIGNAL(escapePressed()), SLOT(focusCanvas())); - } + connect(px_per_whole_spinbox, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(px_per_whole_spinbox, SIGNAL(escapePressed()), SLOT(focusCanvas())); quant_toolbar->addWidget(px_per_whole_spinbox); px_per_whole_spinbox->setValue(ScoreCanvas::_pixels_per_whole_init); @@ -542,7 +533,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) apply_velo=true; initTopwinState(); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); } void ScoreEdit::init_shortcuts() @@ -632,8 +623,11 @@ ScoreEdit::~ScoreEdit() void ScoreEdit::focusCanvas() { - score_canvas->setFocus(); - score_canvas->activateWindow(); + if(MusEGlobal::config.smartFocus) + { + score_canvas->setFocus(); + score_canvas->activateWindow(); + } } void ScoreEdit::velo_box_changed() @@ -649,8 +643,7 @@ void ScoreEdit::velo_off_box_changed() void ScoreEdit::quant_combobox_changed(int idx) { score_canvas->set_quant(idx); - if(MusEGlobal::config.smartFocus) - focusCanvas(); + focusCanvas(); } void ScoreEdit::song_changed(int flags) @@ -4036,7 +4029,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) } old_pitch=-1; - old_dest_tick=MAXINT; + old_dest_tick=INT_MAX; old_len=-1; } } @@ -4705,7 +4698,6 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo * o velo-controller doesn't work in new-style drum tracks * * CURRENT TODO - * o column's widths aren't stored into configuration. fix that. * o storing <no_toplevels /> into a template file seems to ignore * the arranger's "MDI-ness", sets is at subwin all the time! * diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h index 584c5f78..09720505 100644 --- a/muse2/muse/midiedit/scoreedit.h +++ b/muse2/muse/midiedit/scoreedit.h @@ -39,7 +39,7 @@ #include <QByteArray> #include <QToolButton> -#include <values.h> +#include <limits.h> #include "noteinfo.h" #include "cobject.h" #include "event.h" @@ -184,7 +184,6 @@ class ScoreEdit : public TopWin void init_shortcuts(); void selection_changed(); void clipboard_changed(); - void focusCanvas(); signals: void isDeleting(MusEGui::TopWin*); @@ -198,9 +197,10 @@ class ScoreEdit : public TopWin void canvas_height_changed(int); void viewport_height_changed(int); void song_changed(int); + void focusCanvas(); public: - ScoreEdit(QWidget* parent = 0, const char* name = 0, unsigned initPos = MAXINT); + ScoreEdit(QWidget* parent = 0, const char* name = 0, unsigned initPos = INT_MAX); ~ScoreEdit(); void writeStatus(int level, MusECore::Xml& xml) const; diff --git a/muse2/muse/midieditor.cpp b/muse2/muse/midieditor.cpp index 6f6ca713..4418813f 100644 --- a/muse2/muse/midieditor.cpp +++ b/muse2/muse/midieditor.cpp @@ -200,7 +200,8 @@ void MidiEditor::songChanged(int type) if (type & (SC_PART_REMOVED | SC_PART_MODIFIED | SC_PART_INSERTED | SC_TRACK_REMOVED)) { - updateHScrollRange(); + updateHScrollRange(); + if (canvas) setWindowTitle(canvas->getCaption()); else if (wview) diff --git a/muse2/muse/midifile.cpp b/muse2/muse/midifile.cpp index 5e45f261..bc546729 100644 --- a/muse2/muse/midifile.cpp +++ b/muse2/muse/midifile.cpp @@ -22,7 +22,6 @@ //========================================================= #include <errno.h> -#include <values.h> #include "song.h" #include "midi.h" diff --git a/muse2/muse/midiseq.cpp b/muse2/muse/midiseq.cpp index 1000cc46..300382e9 100644 --- a/muse2/muse/midiseq.cpp +++ b/muse2/muse/midiseq.cpp @@ -24,6 +24,7 @@ //========================================================= #include <QMessageBox> +#include <QApplication> #include <stdio.h> #include <fcntl.h> @@ -498,10 +499,13 @@ void MidiSeq::checkAndReportTimingResolution() { int freq = timer->getTimerFreq(); if (freq < 500) { - QMessageBox::warning( MusEGlobal::muse, QString("Bad timing"), QString("Timing source frequency is %1hz, which is below the recommended minimum: 500hz!\n" \ - "This could lead to audible timing problems for MIDI.\n" \ - "Please see the FAQ on http://muse-sequencer.org for remedies.\n" \ - "Also please check console output for any further error messages\n ").arg(freq)); + QMessageBox::warning( MusEGlobal::muse, + qApp->translate("@default", QT_TRANSLATE_NOOP("@default", "Bad timing")), + qApp->translate("@default", QT_TRANSLATE_NOOP("@default", + "Timing source frequency is %1hz, which is below the recommended minimum: 500hz!\n" \ + "This could lead to audible timing problems for MIDI.\n" \ + "Please see the FAQ on http://muse-sequencer.org for remedies.\n" \ + "Also please check console output for any further error messages\n ")).arg(freq) ); } } diff --git a/muse2/muse/mixer/astrip.cpp b/muse2/muse/mixer/astrip.cpp index 6b8043b9..7699af41 100644 --- a/muse2/muse/mixer/astrip.cpp +++ b/muse2/muse/mixer/astrip.cpp @@ -121,7 +121,7 @@ void AudioStrip::heartBeat() void AudioStrip::configChanged() { - // Set the whole strip's font, except for the label. + // Set the whole strip's font, except for the label. if(font() != MusEGlobal::config.fonts[1]) setFont(MusEGlobal::config.fonts[1]); @@ -150,6 +150,22 @@ void AudioStrip::configChanged() meter[c]->setRange(MusEGlobal::config.minMeter, 10.0); } +void AudioStrip::updateRouteButtons() +{ + if (iR) + { + if (track->noInRoute()) + iR->setStyleSheet("background-color:darkgray;"); + else + iR->setStyleSheet(""); + } + + if (track->noOutRoute()) + oR->setStyleSheet("background-color:red;"); + else + oR->setStyleSheet(""); +} + //--------------------------------------------------------- // songChanged //--------------------------------------------------------- @@ -159,6 +175,8 @@ void AudioStrip::songChanged(int val) // Is it simply a midi controller value adjustment? Forget it. if (val == SC_MIDI_CONTROLLER) return; + + updateRouteButtons(); MusECore::AudioTrack* src = (MusECore::AudioTrack*)track; @@ -1055,6 +1073,9 @@ AudioStrip::AudioStrip(QWidget* parent, MusECore::AudioTrack* at) off->blockSignals(false); } connect(MusEGlobal::heartBeatTimer, SIGNAL(timeout()), SLOT(heartBeat())); + + updateRouteButtons(); + } //--------------------------------------------------------- @@ -1067,7 +1088,7 @@ void AudioStrip::iRoutePressed() RoutePopupMenu* pup = new RoutePopupMenu(); pup->exec(QCursor::pos(), track, false); delete pup; - iR->setDown(false); + iR->setDown(false); } //--------------------------------------------------------- diff --git a/muse2/muse/mixer/astrip.h b/muse2/muse/mixer/astrip.h index 1ee40d97..f5406652 100644 --- a/muse2/muse/mixer/astrip.h +++ b/muse2/muse/mixer/astrip.h @@ -85,6 +85,7 @@ class AudioStrip : public Strip { void updateVolume(); void updatePan(); void updateChannels(); + void updateRouteButtons(); private slots: void stereoToggled(bool); diff --git a/muse2/muse/mixer/mstrip.cpp b/muse2/muse/mixer/mstrip.cpp index 61bd9ba5..6f98ffb8 100644 --- a/muse2/muse/mixer/mstrip.cpp +++ b/muse2/muse/mixer/mstrip.cpp @@ -108,7 +108,7 @@ void MidiStrip::addKnob(int idx, const QString& tt, const QString& label, MusEGui::DoubleLabel* dl = new MusEGui::DoubleLabel(0.0, double(mn), double(mx), this); dl->setId(idx); dl->setSpecialText(tr("off")); - dl->setToolTip(tr("double click on/off")); + dl->setToolTip(tr("ctrl-double-click on/off")); controller[idx].dl = dl; ///dl->setFont(MusEGlobal::config.fonts[1]); dl->setBackgroundRole(QPalette::Mid); @@ -166,7 +166,7 @@ void MidiStrip::addKnob(int idx, const QString& tt, const QString& label, connect(knob, SIGNAL(sliderMoved(double,int)), slot); connect(knob, SIGNAL(sliderRightClicked(const QPoint &, int)), SLOT(controlRightClicked(const QPoint &, int))); connect(dl, SIGNAL(valueChanged(double, int)), slot); - connect(dl, SIGNAL(doubleClicked(int)), SLOT(labelDoubleClicked(int))); + connect(dl, SIGNAL(ctrlDoubleClicked(int)), SLOT(labelDoubleClicked(int))); } //--------------------------------------------------------- @@ -233,7 +233,7 @@ MidiStrip::MidiStrip(QWidget* parent, MusECore::MidiTrack* t) sl->setBackgroundRole(QPalette::Mid); sl->setSpecialText(tr("off")); sl->setSuffix(tr("dB")); - sl->setToolTip(tr("double click on/off")); + sl->setToolTip(tr("ctrl-double-click on/off")); sl->setFrame(true); sl->setPrecision(0); sl->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum)); @@ -278,7 +278,7 @@ MidiStrip::MidiStrip(QWidget* parent, MusECore::MidiTrack* t) connect(slider, SIGNAL(sliderMoved(double,int)), SLOT(setVolume(double))); connect(slider, SIGNAL(sliderRightClicked(const QPoint &, int)), SLOT(controlRightClicked(const QPoint &, int))); connect(sl, SIGNAL(valueChanged(double, int)), SLOT(volLabelChanged(double))); - connect(sl, SIGNAL(doubleClicked(int)), SLOT(labelDoubleClicked(int))); + connect(sl, SIGNAL(ctrlDoubleClicked(int)), SLOT(labelDoubleClicked(int))); grid->addWidget(sl, _curGridRow++, 0, 1, 2, Qt::AlignCenter); diff --git a/muse2/muse/mixer/rack.cpp b/muse2/muse/mixer/rack.cpp index 3df46dd5..744d15b0 100644 --- a/muse2/muse/mixer/rack.cpp +++ b/muse2/muse/mixer/rack.cpp @@ -411,8 +411,17 @@ void EffectRack::doubleClicked(QListWidgetItem* it) return; } if (pipe) { - bool flag = !pipe->guiVisible(idx); - pipe->showGui(idx, flag); + bool flag; + if (pipe->has_dssi_ui(idx)) + { + flag = !pipe->nativeGuiVisible(idx); + pipe->showNativeGui(idx, flag); + + } + else { + flag = !pipe->guiVisible(idx); + pipe->showGui(idx, flag); + } } } @@ -508,6 +517,8 @@ void EffectRack::startDrag(int idx) QString xmlconf; xml.dump(xmlconf); + printf("[%s]\n", xmlconf.toLatin1().constData()); + QByteArray data(xmlconf.toLatin1().constData()); //printf("sending %d [%s]\n", data.length(), xmlconf.toLatin1().constData()); diff --git a/muse2/muse/mixer/strip.cpp b/muse2/muse/mixer/strip.cpp index 54cd2e8c..f34d5320 100644 --- a/muse2/muse/mixer/strip.cpp +++ b/muse2/muse/mixer/strip.cpp @@ -297,10 +297,23 @@ Strip::~Strip() //--------------------------------------------------------- void Strip::setAutomationType(int t) - { - track->setAutomationType(AutomationType(t)); - MusEGlobal::song->update(SC_AUTOMATION); - } +{ + // If going to OFF mode, need to update current 'manual' values from the automation values at this time... + if(t == AUTO_OFF && track->automationType() != AUTO_OFF) // && track->automationType() != AUTO_WRITE) + { + // May have a lot to do in updateCurValues, so try using idle. + MusEGlobal::audio->msgIdle(true); + track->setAutomationType(AutomationType(t)); + if(!track->isMidiTrack()) + (static_cast<MusECore::AudioTrack*>(track))->controller()->updateCurValues(MusEGlobal::audio->curFramePos()); + MusEGlobal::audio->msgIdle(false); + } + else + // Try it within one message. + MusEGlobal::audio->msgSetTrackAutomationType(track, t); + + MusEGlobal::song->update(SC_AUTOMATION); +} void Strip::resizeEvent(QResizeEvent* ev) { diff --git a/muse2/muse/node.cpp b/muse2/muse/node.cpp index be72367f..e56949aa 100644 --- a/muse2/muse/node.cpp +++ b/muse2/muse/node.cpp @@ -42,11 +42,12 @@ #include "ticksynth.h" // metronome #include "al/dsp.h" -// Uncomment this (and make sure to set Jack buffer size high like 2048) -// to see process flow messages. -//#define NODE_DEBUG -//#define FIFO_DEBUG +// Turn on debugging messages +//#define NODE_DEBUG +// Turn on constant flow of process debugging messages +//#define NODE_DEBUG_PROCESS +//#define FIFO_DEBUG //#define METRONOME_DEBUG namespace MusECore { @@ -375,7 +376,7 @@ 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 + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioTrack::copyData name:%s processed:%d\n", name().toLatin1().constData(), processed()); #endif @@ -400,8 +401,11 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s // precalculate stereo volume double vol[2]; - double _volume = volume(); - double _pan = pan(); + //double _volume = volume(); + //double _pan = pan(); + double _volume = controller()->value(AC_VOLUME, pos); + double _pan = controller()->value(AC_PAN, pos); + vol[0] = _volume * (1.0 - _pan); vol[1] = _volume * (1.0 + _pan); float meter[trackChans]; @@ -411,7 +415,7 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s { // 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 + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioTrack::copyData name:%s already processed _haveData:%d\n", name().toLatin1().constData(), _haveData); #endif @@ -447,7 +451,7 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s if(off()) { - #ifdef NODE_DEBUG + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioTrack::copyData name:%s dstChannels:%d Off, zeroing buffers\n", name().toLatin1().constData(), dstChannels); #endif @@ -482,7 +486,7 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s // 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 + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioTrack::copyData name:%s srcTotalOutChans:%d zeroing buffers\n", name().toLatin1().constData(), srcTotalOutChans); #endif @@ -622,7 +626,7 @@ void AudioTrack::copyData(unsigned pos, int dstChannels, int srcStartChan, int s // postfader metering //--------------------------------------------------- - #ifdef NODE_DEBUG + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioTrack::copyData trackChans:%d srcTotalOutChans:%d srcStartChan:%d srcChans:%d dstChannels:%d\n", trackChans, srcTotalOutChans, srcStartChan, srcChans, dstChannels); #endif @@ -711,7 +715,7 @@ 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). - #ifdef NODE_DEBUG + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioTrack::addData name:%s processed:%d\n", name().toLatin1().constData(), processed()); #endif @@ -735,8 +739,11 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr // precalculate stereo volume double vol[2]; - double _volume = volume(); - double _pan = pan(); + //double _volume = volume(); + //double _pan = pan(); + double _volume = controller()->value(AC_VOLUME, pos); + double _pan = controller()->value(AC_PAN, pos); + vol[0] = _volume * (1.0 - _pan); vol[1] = _volume * (1.0 + _pan); float meter[trackChans]; @@ -746,7 +753,7 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr { // 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 + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioTrack::addData name:%s already processed _haveData:%d\n", name().toLatin1().constData(), _haveData); #endif @@ -772,7 +779,7 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr if(off()) { - #ifdef NODE_DEBUG + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioTrack::addData name:%s dstChannels:%d Track is Off \n", name().toLatin1().constData(), dstChannels); #endif @@ -917,7 +924,7 @@ void AudioTrack::addData(unsigned pos, int dstChannels, int srcStartChan, int sr // postfader metering //--------------------------------------------------- - #ifdef NODE_DEBUG + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioTrack::addData trackChans:%d srcTotalOutChans:%d srcChans:%d dstChannels:%d\n", trackChans, srcTotalOutChans, srcChans, dstChannels); #endif @@ -1030,6 +1037,10 @@ void AudioTrack::readVolume(Xml& xml) // Removed by T356 // "recfile" tag not saved anymore /* + +THIS CODE IS OBSOLETE! _recFile has been changed from SndFile* to SndFileR. +this code has NOT been adapted! + //--------------------------------------------------------- // readRecfile //--------------------------------------------------------- @@ -1136,8 +1147,8 @@ bool AudioTrack::getData(unsigned pos, int channels, unsigned nframes, float** b RouteList* rl = inRoutes(); - #ifdef NODE_DEBUG - printf("AudioTrack::getData name:%s inRoutes:%d\n", name().toLatin1().constData(), rl->size()); + #ifdef NODE_DEBUG_PROCESS + printf("AudioTrack::getData name:%s inRoutes:%lu\n", name().toLatin1().constData(), rl->size()); #endif ciRoute ir = rl->begin(); @@ -1147,7 +1158,7 @@ bool AudioTrack::getData(unsigned pos, int channels, unsigned nframes, float** b if(ir->track->isMidiTrack()) return false; - #ifdef NODE_DEBUG + #ifdef NODE_DEBUG_PROCESS printf(" calling copyData on %s...\n", ir->track->name().toLatin1().constData()); #endif @@ -1159,7 +1170,7 @@ bool AudioTrack::getData(unsigned pos, int channels, unsigned nframes, float** b ++ir; for (; ir != rl->end(); ++ir) { - #ifdef NODE_DEBUG + #ifdef NODE_DEBUG_PROCESS printf(" calling addData on %s...\n", ir->track->name().toLatin1().constData()); #endif @@ -1439,7 +1450,7 @@ void AudioOutput::processInit(unsigned nframes) void AudioOutput::process(unsigned pos, unsigned offset, unsigned n) { - #ifdef NODE_DEBUG + #ifdef NODE_DEBUG_PROCESS printf("MusE: AudioOutput::process name:%s processed:%d\n", name().toLatin1().constData(), processed()); #endif diff --git a/muse2/muse/node.h b/muse2/muse/node.h index 50f20546..47fae6d1 100644 --- a/muse2/muse/node.h +++ b/muse2/muse/node.h @@ -98,7 +98,6 @@ static inline void muse_atomic_destroy(muse_atomic_t*) {} class Xml; class Pipeline; -class SndFile; //--------------------------------------------------------- diff --git a/muse2/muse/osc.cpp b/muse2/muse/osc.cpp index f78e7a61..0d4a1750 100644 --- a/muse2/muse/osc.cpp +++ b/muse2/muse/osc.cpp @@ -34,6 +34,7 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <math.h> #include <QFileInfo> #include <QString> @@ -178,9 +179,7 @@ int oscMessageHandler(const char* path, const char* types, lo_arg** argv, if(!instance) break; - QByteArray ba2 = synti->name().toLatin1(); - p = sub + strlen(ba2.constData()); - + p = sub + ba.length(); if (*p != '/' || *(p + 1) == 0) { fprintf(stderr, "oscMessageHandler error: synth: end of path or no /\n"); @@ -241,9 +240,7 @@ int oscMessageHandler(const char* path, const char* types, lo_arg** argv, if(!plugin) break; - QByteArray ba3 = instance->label().toLatin1(); - p = sub + strlen(ba3.constData()); - + p = sub + ba.length(); if (*p != '/' || *(p + 1) == 0) { fprintf(stderr, "oscMessageHandler: error: effect: end of path or no /\n"); @@ -387,6 +384,11 @@ OscIF::OscIF() _guiPid = -1; #endif _oscGuiVisible = false; + + old_prog=old_bank=0xDEADBEEF; + old_control=NULL; + control_port_mapper=NULL; + maxDssiPort=0; } OscIF::~OscIF() @@ -429,6 +431,9 @@ OscIF::~OscIF() free(_uiOscProgramPath); if(_uiOscPath) free(_uiOscPath); + + if (old_control) + delete [] old_control; } //--------------------------------------------------------- @@ -728,20 +733,29 @@ int OscIF::oscExiting(lo_arg**) // oscSendProgram //--------------------------------------------------------- -void OscIF::oscSendProgram(unsigned long prog, unsigned long bank) +void OscIF::oscSendProgram(unsigned long prog, unsigned long bank, bool force) { - if(_uiOscTarget && _uiOscProgramPath) + if(_uiOscTarget && _uiOscProgramPath && + (bank!=old_bank || prog!=old_prog || force) ) + { lo_send(_uiOscTarget, _uiOscProgramPath, "ii", bank, prog); + old_bank=bank; + old_prog=prog; + } } //--------------------------------------------------------- // oscSendControl //--------------------------------------------------------- -void OscIF::oscSendControl(unsigned long dssiPort, float v) +void OscIF::oscSendControl(unsigned long dssiPort, float v, bool force) { - if(_uiOscTarget && _uiOscControlPath) + if(_uiOscTarget && _uiOscControlPath && + ((dssiPort<maxDssiPort && old_control[control_port_mapper->at(dssiPort)]!=v) || force) ) + { lo_send(_uiOscTarget, _uiOscControlPath, "if", dssiPort, v); + old_control[control_port_mapper->at(dssiPort)]=v; + } } //--------------------------------------------------------- @@ -759,8 +773,45 @@ void OscIF::oscSendConfigure(const char *key, const char *val) //--------------------------------------------------------- bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QString& name, - const QString& label, const QString& filePath, const QString& guiPath) + const QString& label, const QString& filePath, const QString& guiPath, + const std::vector<unsigned long>* control_port_mapper_) { + if (old_control==NULL) + { + control_port_mapper=control_port_mapper_; + + unsigned long nDssiPorts=0; + for (unsigned i=0;i<control_port_mapper->size();i++) + if (control_port_mapper->at(i)!=(unsigned long)-1 && control_port_mapper->at(i)+1 > nDssiPorts) + nDssiPorts=control_port_mapper->at(i)+1; + + old_control=new float[nDssiPorts]; + for (unsigned long i=0;i<nDssiPorts;i++) // init them all with "not a number" + old_control[i]=NAN; + + maxDssiPort=nDssiPorts; + } + else + { + control_port_mapper=control_port_mapper_; + + unsigned long nDssiPorts=0; + for (unsigned i=0;i<control_port_mapper->size();i++) + if (control_port_mapper->at(i)!=(unsigned long)-1 && control_port_mapper->at(i)+1 > nDssiPorts) + nDssiPorts=control_port_mapper->at(i)+1; + + if (maxDssiPort!=nDssiPorts) + { + // this should never happen, right? + printf("STRANGE: nDssiPorts has changed (old=%lu, now=%lu)!\n", maxDssiPort, nDssiPorts); + delete [] old_control; + old_control=new float[nDssiPorts]; + for (unsigned long i=0;i<nDssiPorts;i++) // init them all with "not a number" + old_control[i]=NAN; + maxDssiPort=nDssiPorts; + } + } + // Are we already running? We don't want to allow another process do we... #ifdef _USE_QPROCESS_FOR_GUI_ if((_oscGuiQProc != 0) && (_oscGuiQProc->state())) @@ -902,8 +953,7 @@ void OscIF::oscShowGui(bool v) } } - //for (int i = 0; i < 5; ++i) { - for (int i = 0; i < 20; ++i) { // Give it a wee bit more time? + for (int i = 0; i < 20; ++i) { if (_uiOscPath) break; sleep(1); @@ -1020,7 +1070,11 @@ int OscDssiIF::oscMidi(lo_arg** argv) int OscDssiIF::oscProgram(lo_arg** argv) { if(_oscSynthIF) + { _oscSynthIF->oscProgram(argv[1]->i, argv[0]->i); + old_prog=argv[1]->i; + old_bank=argv[0]->i; + } return 0; } @@ -1036,7 +1090,11 @@ int OscDssiIF::oscControl(lo_arg** argv) return 0; if(_oscSynthIF) + { _oscSynthIF->oscControl(argv[0]->i, argv[1]->f); + if (port<maxDssiPort) + old_control[control_port_mapper->at(port)]=argv[1]->f; + } return 0; } @@ -1048,10 +1106,11 @@ bool OscDssiIF::oscInitGui() { if(!_oscSynthIF) return false; - + return OscIF::oscInitGui("dssi_synth", _oscSynthIF->dssiSynth()->baseName(), _oscSynthIF->dssiSynth()->name(), _oscSynthIF->dssiSynthI()->name(), - _oscSynthIF->dssiSynth()->fileName(), _oscSynthIF->dssi_ui_filename()); + _oscSynthIF->dssiSynth()->fileName(), _oscSynthIF->dssi_ui_filename(), + _oscSynthIF->dssiSynth()->getRpIdx()); } QString OscDssiIF::titlePrefix() const @@ -1109,7 +1168,11 @@ int OscEffectIF::oscControl(lo_arg** argv) return 0; if(_oscPluginI) + { _oscPluginI->oscControl(argv[0]->i, argv[1]->f); + if (port<maxDssiPort) + old_control[control_port_mapper->at(port)]=argv[1]->f; + } return 0; } @@ -1124,7 +1187,8 @@ bool OscEffectIF::oscInitGui() return OscIF::oscInitGui("ladspa_efx", _oscPluginI->plugin()->lib(false), _oscPluginI->plugin()->label(), _oscPluginI->label(), - _oscPluginI->plugin()->fileName(), _oscPluginI->dssi_ui_filename()); + _oscPluginI->plugin()->fileName(), _oscPluginI->dssi_ui_filename(), + _oscPluginI->plugin()->getRpIdx()); } QString OscEffectIF::titlePrefix() const diff --git a/muse2/muse/osc.h b/muse2/muse/osc.h index f75b5168..df811f16 100644 --- a/muse2/muse/osc.h +++ b/muse2/muse/osc.h @@ -57,9 +57,16 @@ class OscIF char* _uiOscControlPath; char* _uiOscShowPath; bool _oscGuiVisible; - + + unsigned long old_prog; + unsigned long old_bank; + float* old_control; + unsigned long maxDssiPort; + const std::vector<unsigned long>* control_port_mapper; + virtual bool oscInitGui(const QString& typ, const QString& baseName, const QString& name, - const QString& label, const QString& filePath, const QString& guiPath); + const QString& label, const QString& filePath, const QString& guiPath, + const std::vector<unsigned long>* control_port_mapper_); public: OscIF(); @@ -72,8 +79,8 @@ class OscIF virtual int oscMidi(lo_arg**) { return 0; } virtual int oscConfigure(lo_arg**) { return 0; } - virtual void oscSendProgram(unsigned long prog, unsigned long bank); - virtual void oscSendControl(unsigned long dssiPort, float val); + virtual void oscSendProgram(unsigned long prog, unsigned long bank, bool force=false); + virtual void oscSendControl(unsigned long dssiPort, float val, bool force=false); virtual void oscSendConfigure(const char *key, const char *val); virtual bool oscInitGui() { return false; } @@ -91,7 +98,7 @@ class OscEffectIF : public OscIF public: OscEffectIF() {} - void oscSetPluginI(PluginI*); + void oscSetPluginI(PluginI*); // this MUST be called with NULL-argument from PluginI's destructor! virtual int oscUpdate(lo_arg**); virtual int oscControl(lo_arg**); @@ -111,7 +118,7 @@ class OscDssiIF : public OscIF public: OscDssiIF() {} - void oscSetSynthIF(DssiSynthIF*); + void oscSetSynthIF(DssiSynthIF*); // this MUST be called with NULL-argument from DssiSynthIF's destructor! virtual int oscUpdate(lo_arg**); virtual int oscProgram(lo_arg**); diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp index 8363ff68..a632bc9c 100644 --- a/muse2/muse/part.cpp +++ b/muse2/muse/part.cpp @@ -167,6 +167,7 @@ void chainClone(Part* p) // replaceClone //--------------------------------------------------------- +// this replaces p1 by p2. p1 is isolated, and p2 takes its place instead. void replaceClone(Part* p1, Part* p2) { chainCheckErr(p1); @@ -181,7 +182,7 @@ void replaceClone(Part* p1, Part* p2) if(p1->cevents() != p2->cevents()) { bool ret = false; - // If the part to be replaced is a single uncloned part, DELETETHIS 4 this seems outdated=wrong to me + // If the part to be replaced is a single uncloned part, [DELETETHIS 4 this seems outdated=wrong to me] // and the replacement part is not, then this operation // MUST be an undo of a de-cloning of a cloned part. //if(p1->cevents()->refCount() <= 1 && p2->cevents()->refCount() > 1) @@ -647,6 +648,22 @@ Part* PartList::find(int idx) // Part //--------------------------------------------------------- +Part::Part(const Part& p) : PosLen(p) +{ + _sn=p._sn; + _name=p._name; + _selected=p._selected; + _mute=p._mute; + _colorIndex=p._colorIndex; + _hiddenEvents=p._hiddenEvents; + _track=p._track; + _events=p._events; + _prevClone=p._prevClone; + _nextClone=p._nextClone; + + _events->incRef(1); +} + Part::Part(Track* t) { _hiddenEvents = NoEventsHidden; @@ -662,10 +679,6 @@ Part::Part(Track* t) _events->incARef(1); } -//--------------------------------------------------------- -// Part -//--------------------------------------------------------- - Part::Part(Track* t, EventList* ev) { _hiddenEvents = NoEventsHidden; diff --git a/muse2/muse/part.h b/muse2/muse/part.h index e47b9843..f2bc342b 100644 --- a/muse2/muse/part.h +++ b/muse2/muse/part.h @@ -61,6 +61,12 @@ class Part : public PosLen { public: enum HiddenEventsType { NoEventsHidden = 0, LeftEventsHidden, RightEventsHidden }; + // @@@@@@@@@@@ IMPORTANT @@@@@@@@@@@@ + // @@ when adding member variables @@ + // @@ here, don't forget to update @@ + // @@ the copy-constructor! @@ + // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + private: static int snGen; int _sn; @@ -81,6 +87,7 @@ class Part : public PosLen { public: Part(Track*); Part(Track*, EventList*); + Part(const Part& p); virtual ~Part(); int sn() { return _sn; } void setSn(int n) { _sn = n; } diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp index 9b3879b9..8bf35143 100644 --- a/muse2/muse/plugin.cpp +++ b/muse2/muse/plugin.cpp @@ -85,8 +85,6 @@ MusECore::PluginList plugins; namespace MusEGui { int PluginDialog::selectedPlugType = 0; QStringList PluginDialog::sortItems = QStringList(); -///int PluginDialog::sortColumn = 0; -///Qt::SortOrder PluginDialog::sortOrder = Qt::AscendingOrder; QRect PluginDialog::geometrySave = QRect(); QByteArray PluginDialog::listSave = QByteArray(); } @@ -482,16 +480,22 @@ bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, unsigned long port, flo LADSPA_PortRangeHint range = plugin->PortRangeHints[port]; LADSPA_PortRangeHintDescriptor rh = range.HintDescriptor; float m = (rh & LADSPA_HINT_SAMPLE_RATE) ? float(MusEGlobal::sampleRate) : 1.0f; + if (LADSPA_IS_HINT_DEFAULT_MINIMUM(rh)) { - *val = range.LowerBound * m; - return true; + *val = range.LowerBound * m; + return true; + } + else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(rh)) + { + *val = range.UpperBound*m; + return true; } else if (LADSPA_IS_HINT_DEFAULT_LOW(rh)) { if (LADSPA_IS_HINT_LOGARITHMIC(rh)) { - *val = expf(fast_log10(range.LowerBound * m) * .75 + // Why fast_log10? + *val = expf(logf(range.LowerBound * m) * .75 + logf(range.UpperBound * m) * .25); return true; } @@ -506,7 +510,7 @@ bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, unsigned long port, flo if (LADSPA_IS_HINT_LOGARITHMIC(rh)) { *val = expf(logf(range.LowerBound * m) * .5 + - log10f(range.UpperBound * m) * .5); // Why log10? + logf(range.UpperBound * m) * .5); return true; } else @@ -529,11 +533,6 @@ bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, unsigned long port, flo return true; } } - else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(rh)) - { - *val = range.UpperBound*m; - return true; - } else if (LADSPA_IS_HINT_DEFAULT_0(rh)) { *val = 0.0; @@ -554,10 +553,42 @@ bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, unsigned long port, flo *val = 440.0; return true; } + + // No default found. Make one up... + else if (LADSPA_IS_HINT_BOUNDED_BELOW(rh) && LADSPA_IS_HINT_BOUNDED_ABOVE(rh)) + { + if (LADSPA_IS_HINT_LOGARITHMIC(rh)) + { + *val = expf(logf(range.LowerBound * m) * .5 + + logf(range.UpperBound * m) * .5); + return true; + } + else + { + *val = range.LowerBound*.5*m + range.UpperBound*.5*m; + return true; + } + } + else if (LADSPA_IS_HINT_BOUNDED_BELOW(rh)) + { + *val = range.LowerBound; + return true; + } + else if (LADSPA_IS_HINT_BOUNDED_ABOVE(rh)) + { + // Hm. What to do here... Just try 0.0 or the upper bound if less than zero. + //if(range.UpperBound > 0.0) + // *val = 0.0; + //else + // *val = range.UpperBound * m; + // Instead try this: Adopt an 'attenuator-like' policy, where upper is the default. + *val = range.UpperBound * m; + return true; + } } - // No default found. Set return value to 1.0, but return false. - *val = 1.0; + // No default found. Set return value to 0.0, but return false. + *val = 0.0; return false; } @@ -626,9 +657,10 @@ void PluginBase::range(unsigned long i, float* min, float* max) const // Plugin //--------------------------------------------------------- -Plugin::Plugin(QFileInfo* f, const LADSPA_Descriptor* d, bool isDssi) +Plugin::Plugin(QFileInfo* f, const LADSPA_Descriptor* d, bool isDssi, bool isDssiSynth) { _isDssi = isDssi; + _isDssiSynth = isDssiSynth; #ifdef DSSI_SUPPORT dssi_descr = NULL; #endif @@ -768,13 +800,7 @@ int Plugin::incReferences(int val) break; QString label(descr->LADSPA_Plugin->Label); - // Listing effect plugins only while excluding synths: - // Do exactly what dssi-vst.cpp does for listing ladspa plugins. - if(label == _label && - !descr->run_synth && - !descr->run_synth_adding && - !descr->run_multiple_synths && - !descr->run_multiple_synths_adding) + if(label == _label) { _isDssi = true; ladspa = NULL; @@ -993,26 +1019,24 @@ static void loadPluginLib(QFileInfo* fi) if (descr == 0) break; - // Listing effect plugins only while excluding synths: - // Do exactly what dssi-vst.cpp does for listing ladspa plugins. - if(!descr->run_synth && - !descr->run_synth_adding && - !descr->run_multiple_synths && - !descr->run_multiple_synths_adding) - { - // Make sure it doesn't already exist. - if(MusEGlobal::plugins.find(fi->completeBaseName(), QString(descr->LADSPA_Plugin->Label)) != 0) - continue; + // Make sure it doesn't already exist. + if(MusEGlobal::plugins.find(fi->completeBaseName(), QString(descr->LADSPA_Plugin->Label)) != 0) + continue; - #ifdef PLUGIN_DEBUGIN - fprintf(stderr, "loadPluginLib: dssi effect name:%s inPlaceBroken:%d\n", descr->LADSPA_Plugin->Name, LADSPA_IS_INPLACE_BROKEN(descr->LADSPA_Plugin->Properties)); - #endif - - if(MusEGlobal::debugMsg) - fprintf(stderr, "loadPluginLib: adding dssi effect plugin:%s name:%s label:%s\n", fi->filePath().toLatin1().constData(), descr->LADSPA_Plugin->Name, descr->LADSPA_Plugin->Label); - - MusEGlobal::plugins.add(fi, descr->LADSPA_Plugin, true); - } + #ifdef PLUGIN_DEBUGIN + fprintf(stderr, "loadPluginLib: dssi effect name:%s inPlaceBroken:%d\n", descr->LADSPA_Plugin->Name, LADSPA_IS_INPLACE_BROKEN(descr->LADSPA_Plugin->Properties)); + #endif + + bool is_synth = descr->run_synth || descr->run_synth_adding + || descr->run_multiple_synths || descr->run_multiple_synths_adding; + if(MusEGlobal::debugMsg) + fprintf(stderr, "loadPluginLib: adding dssi effect plugin:%s name:%s label:%s synth:%d\n", + fi->filePath().toLatin1().constData(), + descr->LADSPA_Plugin->Name, descr->LADSPA_Plugin->Label, + is_synth + ); + + MusEGlobal::plugins.add(fi, descr->LADSPA_Plugin, true, is_synth); } } else @@ -1598,6 +1622,10 @@ PluginI::PluginI() PluginI::~PluginI() { + #ifdef OSC_SUPPORT + _oscif.oscSetPluginI(NULL); + #endif + if (_plugin) { deactivate(); _plugin->incReferences(-1); @@ -1726,11 +1754,6 @@ void PluginI::setParam(unsigned long i, float val) { fprintf(stderr, "PluginI::setParameter: fifo overflow: in control number:%lu\n", i); } - - // Notify that changes are to be sent upon heartbeat. DELETETHIS 4 - // TODO: No, at least not for now. So far, setParameter is only called during loading of stored params, - // and we don't want this interfering with oscUpdate which also sends the values. - //synti->_guiUpdateControls[n] = true; } //--------------------------------------------------------- @@ -2093,7 +2116,7 @@ bool PluginI::readConfiguration(Xml& xml, bool readPreset) else if (tag == "gui") { bool flag = xml.parseInt(); if (_plugin) - showGui(flag); + showGui(flag); } else if (tag == "nativegui") { // We can't tell OSC to show the native plugin gui @@ -2305,129 +2328,19 @@ QString PluginI::titlePrefix() const // If ports is 0, just process controllers only, not audio (do not 'run'). //--------------------------------------------------------- -//DELETETHIS 90 - -/* -//void PluginI::apply(int n) -void PluginI::apply(unsigned long n) -{ - // Process control value changes. - //if(MusEGlobal::automation && _track && _track->automationType() != AUTO_OFF && _id != -1) - //{ - // for(int i = 0; i < controlPorts; ++i) - // { - // if( controls[i].enCtrl && controls[i].en2Ctrl ) - // controls[i].tmpVal = _track->pluginCtrlVal(genACnum(_id, i)); - // } - //} - - unsigned long ctls = controlPorts; - for(unsigned long k = 0; k < ctls; ++k) - { - // First, update the temporary value if needed... - - #ifdef OSC_SUPPORT - // Process OSC gui input control fifo events. - // It is probably more important that these are processed so that they take precedence over all other - // events because OSC + DSSI/DSSI-VST are fussy about receiving feedback via these control ports, from GUI changes. - - OscControlFifo* cfifo = _oscif.oscFifo(k); - //if(!cfifo) - // continue; - - // If there are 'events' in the fifo, get exactly one 'event' per control per process cycle... - //if(!cfifo->isEmpty()) - if(cfifo && !cfifo->isEmpty()) - { - OscControlValue v = cfifo->get(); - - #ifdef PLUGIN_DEBUGIN - fprintf(stderr, "PluginI::apply OscControlFifo event input control number:%lu value:%f\n", k, v.value); - #endif - - // Set the ladspa control port value. - controls[k].tmpVal = v.value; - - // Need to update the automation value, otherwise it overwrites later with the last automation value. - if(_track && _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(this, genACnum(_id, k), controls[k].val); - // p3.3.43 - //MusEGlobal::audio->msgSetPluginCtrlVal(_track, genACnum(_id, k), controls[k].val); - _track->setPluginCtrlVal(genACnum(_id, k), v.value); - - // Record automation. - // NO! Take care of this immediately in the OSC control handler, because we don't want - // the silly delay associated with processing the fifo one-at-a-time here. - - //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); - } - } - else - #endif // OSC_SUPPORT - { - // Process automation control value. - if(MusEGlobal::automation && _track && _track->automationType() != AUTO_OFF && _id != -1) - { - if(controls[k].enCtrl && controls[k].en2Ctrl ) - controls[k].tmpVal = _track->pluginCtrlVal(genACnum(_id, k)); - } - } - - // Now update the actual value from the temporary value... - controls[k].val = controls[k].tmpVal; - } - - //for (int i = 0; i < controlPorts; ++i) - // controls[i].val = controls[i].tmpVal; - - for (int i = 0; i < instances; ++i) - { - // p3.3.41 - //fprintf(stderr, "PluginI::apply handle %d\n", i); - _plugin->apply(handle[i], n); - } - } -*/ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** bufOut) { - // Process control value changes. DELETETHIS 10 - //if(MusEGlobal::automation && _track && _track->automationType() != AUTO_OFF && _id != -1) - //{ - // for(int i = 0; i < controlPorts; ++i) - // { - // if( controls[i].enCtrl && controls[i].en2Ctrl ) - // controls[i].tmpVal = _track->pluginCtrlVal(genACnum(_id, i)); - // } - //} - - // Grab the control ring buffer size now. - //const int cbsz = _controlFifo.getSize(); DELETETHIS 4 - - //unsigned endPos = pos + n; - //unsigned long frameOffset = MusEGlobal::audio->getFrameOffset(); unsigned long syncFrame = MusEGlobal::audio->curSyncFrame(); - unsigned long sample = 0; - int loopcount = 0; // REMOVE Tim. // Must make this detectable for dssi vst effects. - //const bool usefixedrate = true; - const bool usefixedrate = _plugin->_isDssiVst; // Try this. + const bool usefixedrate = _plugin->_isDssiVst; // Try this. (was: = true; ) + // TODO Make this number a global setting. // Note for dssi-vst this MUST equal 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 fixedsize = 2048; - unsigned long fixedsize = n; + unsigned long fixedsize = n; // was: 2048 // For now, the fixed size is clamped to the audio buffer size. // TODO: We could later add slower processing over several cycles - @@ -2446,111 +2359,79 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** for(unsigned long k = 0; k < controlPorts; ++k) { if(controls[k].enCtrl && controls[k].en2Ctrl ) - controls[k].tmpVal = _track->pluginCtrlVal(genACnum(_id, k)); + controls[k].tmpVal = _track->controller()->value(genACnum(_id, k), MusEGlobal::audio->pos().frame()); } } while(sample < n) { - //unsigned long nsamp = n; DELETETHIS 2 - //unsigned long nsamp = n - sample; + // nsamp is the number of samples the plugin->process() call will be supposed to do unsigned long nsamp = usefixedrate ? fixedsize : n - sample; + bool found = false; unsigned long frame = 0; unsigned long index = 0; unsigned long evframe; + // Get all control ring buffer items valid for this time period... - //for(int m = 0; m < cbsz; ++m) // Doesn't like this. Why? DELETETHIS while(!_controlFifo.isEmpty()) { - //ControlValue v = _controlFifo.get(); DELETETHIS ControlEvent v = _controlFifo.peek(); // The events happened in the last period or even before that. Shift into this period with + n. This will sync with 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; DELETETHIS evframe = (syncFrame > v.frame + n) ? 0 : v.frame - syncFrame + n; // Process only items in this time period. Make sure to process all // subsequent items which have the same frame. - //printf("PluginI::apply control idx:%lu frame:%lu val:%f unique:%d evframe:%lu\n", DELETETHIS - // v.idx, v.frame, v.value, v.unique, evframe); // REMOVE Tim. + // Protection. Observed this condition. Why? Supposed to be linear timestamps. if(found && evframe < frame) { printf("PluginI::apply *** Error: evframe:%lu < frame:%lu idx:%lu val:%f unique:%d\n", evframe, v.frame, v.idx, v.value, v.unique); - // Just make it equal to the current frame so it gets processed right away. - evframe = frame; - } - //if(v.frame >= (endPos + frameOffset) || (found && v.frame != frame)) DELETETHIS 5 - //if(v.frame < sample || v.frame >= (sample + nsamp) || (found && v.frame != frame)) - //if(v.frame < sample || v.frame >= (endPos + frameOffset) || (found && v.frame != frame)) - //if(v.frame < sample || v.frame >= (endPos + frameOffset) - //if(v.frame < sample || v.frame >= frameOffset + + // No choice but to ignore it. + _controlFifo.remove(); // Done with the ring buffer's item. Remove it. + continue; + } + + // process control events up to the end of our processing cycle. + // but stop after a control event was found (then process(), + // then loop here again), but ensure that process() must process + // at least min_per frames. if(evframe >= n - //|| (found && v.frame != frame) DELETETHIS 3 - //|| (!usefixedrate && found && !v.unique && v.frame != frame) - //|| (found && !v.unique && evframe != frame) - // Not enough requested samples to satisfy minimum setting? Keep going. - || (found && !v.unique && (evframe - sample >= min_per)) - // Protection. Observed this condition (dummy audio so far). Why? Supposed to be linear timestamps. - //|| (found && evframe < frame) DELETETHIS - // dssi-vst needs them serialized and accounted for, no matter what. This works with fixed rate - // because nsamp is constant. But with packets, we need to guarantee at least one-frame spacing. - // Although we likely won't be using packets with dssi-vst, so it's OK for now. - //|| (found && v.idx == index)) DELETETHIS - //|| (usefixedrate && found && v.idx == index)) // Try this. - || (usefixedrate && found && v.unique && v.idx == index)) // + || (found && !v.unique && (evframe - sample >= min_per)) + || (usefixedrate && found && v.unique && v.idx == index)) break; _controlFifo.remove(); // Done with the ring buffer's item. Remove it. - //if(v.idx >= controlPorts) // Sanity check. DELETETHIS - if(v.idx >= _plugin->_controlInPorts) + + if(v.idx >= _plugin->_controlInPorts) // Sanity check break; + found = true; - //frame = v.frame; DELETETHIS frame = evframe; index = v.idx; - // Set the ladspa control port value. - //controls[v.idx].val = v.value; DELETETHIS + controls[v.idx].tmpVal = v.value; - // Need to update the automation value, otherwise it overwrites later with the last MusEGlobal::automation value. + // Need to update the automation value, otherwise it overwrites later with the last automation value. if(_track && _id != -1) { - // Since we are now in the audio thread context, there's no need to send a message, DELETETHIS 5 - // just modify directly. - //MusEGlobal::audio->msgSetPluginCtrlVal(this, genACnum(_id, k), controls[k].val); - // p3.3.43 - //MusEGlobal::audio->msgSetPluginCtrlVal(_track, genACnum(_id, k), controls[k].val); + // We're in the audio thread context: no need to send a message, just modify directly. _track->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)) DELETETHIS 3 - // enableController(k, false); - //_track->recordAutomation(id, v.value); + /* Recording automation is done immediately in the * + * OSC control handler, because we don't want any delay. * + * we might want to handle dssi-vst synthes here, however! */ } } // Now update the actual values from the temporary values... for(unsigned long k = 0; k < controlPorts; ++k) - { - // printf("PluginI::apply updating port:%lu val:%f\n", k, controls[k].tmpVal); DELETETHIS controls[k].val = controls[k].tmpVal; - } - //if(found) if(found && !usefixedrate) - //nsamp = frame - sample + 1; DELETETHIS nsamp = frame - sample; + if(sample + nsamp >= n) // Safety check. nsamp = n - sample; @@ -2568,7 +2449,6 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float** } sample += nsamp; - loopcount++; // REMOVE Tim. DELETETHIS then } } @@ -2675,7 +2555,7 @@ int PluginI::oscUpdate() // Send current bank and program. unsigned long bank, prog; synti->currentProg(&prog, &bank, 0); - _oscIF.oscSendProgram(prog, bank); + _oscIF.oscSendProgram(prog, bank, true); // "true" means "force" */ // FIXME: TESTING FLAM: I have to put a delay because flammer hasn't opened yet. @@ -2688,9 +2568,9 @@ int PluginI::oscUpdate() for(unsigned long i = 0; i < controlPorts; ++i) { //unsigned long k = synth->pIdx(i); DELETETHIS 2 - //_oscIF.oscSendControl(k, controls[i]); + //_oscIF.oscSendControl(k, controls[i], true /*force*/); //printf("PluginI::oscUpdate() sending control:%lu val:%f\n", i, controls[i].val); - _oscif.oscSendControl(controls[i].idx, controls[i].val); + _oscif.oscSendControl(controls[i].idx, controls[i].val, true /*force*/); // Avoid overloading the GUI if there are lots and lots of ports. if((i+1) % 50 == 0) usleep(300000); @@ -2790,8 +2670,9 @@ int PluginI::oscControl(unsigned long port, float value) // 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); + if ((at == AUTO_WRITE) || + (at == AUTO_TOUCH && MusEGlobal::audio->isPlaying())) + enableController(cport, false); //TODO maybe re-enable the ctrl soon? _track->recordAutomation(id, value); } @@ -2858,12 +2739,12 @@ PluginDialog::PluginDialog(QWidget* parent) QVBoxLayout* layout = new QVBoxLayout(this); pList = new QTreeWidget(this); - pList->setColumnCount(11); + pList->setColumnCount(12); // "Note: In order to avoid performance issues, it is recommended that sorting // is enabled after inserting the items into the tree. Alternatively, you could // also insert the items into a list before inserting the items into the tree. " - //pList->setSortingEnabled(true); DELETETHIS QStringList headerLabels; + headerLabels << tr("Type"); headerLabels << tr("Lib"); headerLabels << tr("Label"); headerLabels << tr("Name"); @@ -2878,15 +2759,19 @@ PluginDialog::PluginDialog(QWidget* parent) pList->setHeaderLabels(headerLabels); + pList->headerItem()->setToolTip(4, tr("Audio inputs")); + pList->headerItem()->setToolTip(5, tr("Audio outputs")); + pList->headerItem()->setToolTip(6, tr("Control inputs")); + pList->headerItem()->setToolTip(7, tr("Control outputs")); + pList->headerItem()->setToolTip(8, tr("In-place capable")); + pList->headerItem()->setToolTip(9, tr("ID number")); + + pList->setRootIsDecorated(false); pList->setSelectionBehavior(QAbstractItemView::SelectRows); pList->setSelectionMode(QAbstractItemView::SingleSelection); pList->setAlternatingRowColors(true); pList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - //fillPlugs(selectedPlugType); DELETETHIS 3 - //pList->setSortingEnabled(true); - //pList->sortByColumn(sortColumn, sortOrder); - layout->addWidget(pList); //--------------------------------------------------- @@ -2946,8 +2831,8 @@ PluginDialog::PluginDialog(QWidget* parent) } plugSelGroup->setToolTip(tr("Select which types of plugins should be visible in the list.<br>" - "Note that using mono plugins on stereo tracks is not a problem, two will be used in parallell.<br>" - "Also beware that the 'all' alternative includes plugins that probably not are usable by MusE.")); + "Note that using mono plugins on stereo tracks is not a problem, two will be used in parallel.<br>" + "Also beware that the 'all' alternative includes plugins that may not be useful in an effect rack.")); w5->addSpacing(8); w5->addWidget(plugSelGroup); @@ -2969,7 +2854,6 @@ PluginDialog::PluginDialog(QWidget* parent) sortBox->setMinimumSize(100, 10); srch_lo->addWidget(sortBox); - //srch_lo->addStretch(); DELETETHIS 4 // FIXME: Adding this makes the whole bottom hlayout expand. Would like some space between lineedit and bottom. // Same thing if spacers added to group box or Ok Cancel box. //srch_lo->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Maximum)); @@ -2980,13 +2864,13 @@ PluginDialog::PluginDialog(QWidget* parent) if(listSave.isEmpty()) { - int sizes[] = { 110, 110, 110, 30, 30, 30, 30, 30, 50, 110, 110 }; - for (int i = 0; i < 11; ++i) { + int sizes[] = { 80, 110, 110, 110, 30, 30, 30, 30, 30, 50, 110, 110 }; + for (int i = 0; i < 12; ++i) { if (sizes[i] <= 50) // hack alert! pList->header()->setResizeMode(i, QHeaderView::Fixed); pList->header()->resizeSection(i, sizes[i]); } - pList->sortByColumn(0, Qt::AscendingOrder); + pList->sortByColumn(3, Qt::AscendingOrder); } else pList->header()->restoreState(listSave); @@ -3017,7 +2901,7 @@ MusECore::Plugin* PluginDialog::value() { QTreeWidgetItem* item = pList->currentItem(); if (item) - return MusEGlobal::plugins.find(item->text(0), item->text(1)); + return MusEGlobal::plugins.find(item->text(1), item->text(2)); printf("plugin not found\n"); return 0; } @@ -3085,6 +2969,7 @@ void PluginDialog::fillPlugs(QAbstractButton* ab) void PluginDialog::fillPlugs() { + QString type_name; pList->clear(); for (MusECore::iPlugin i = MusEGlobal::plugins.begin(); i != MusEGlobal::plugins.end(); ++i) { unsigned long ai = i->inports(); // p4.0.21 @@ -3119,17 +3004,24 @@ void PluginDialog::fillPlugs() } if (found && addFlag) { QTreeWidgetItem* item = new QTreeWidgetItem; - item->setText(0, i->lib()); - item->setText(1, i->label()); - item->setText(2, i->name()); - item->setText(3, QString().setNum(ai)); - item->setText(4, QString().setNum(ao)); - item->setText(5, QString().setNum(ci)); - item->setText(6, QString().setNum(co)); - item->setText(7, QString().setNum(i->inPlaceCapable())); - item->setText(8, QString().setNum(i->id())); - item->setText(9, i->maker()); - item->setText(10, i->copyright()); + if(i->isDssiSynth()) + type_name = tr("dssi synth"); + else if(i->isDssiPlugin()) + type_name = tr("dssi effect"); + else + type_name = tr("ladspa"); + item->setText(0, type_name); + item->setText(1, i->lib()); + item->setText(2, i->label()); + item->setText(3, i->name()); + item->setText(4, QString().setNum(ai)); + item->setText(5, QString().setNum(ao)); + item->setText(6, QString().setNum(ci)); + item->setText(7, QString().setNum(co)); + item->setText(8, QString().setNum(i->inPlaceCapable())); + item->setText(9, QString().setNum(i->id())); + item->setText(10, i->maker()); + item->setText(11, i->copyright()); pList->addTopLevelItem(item); } } @@ -3252,7 +3144,7 @@ PluginGui::PluginGui(MusECore::PluginIBase* p) continue; unsigned long parameter; // p4.0.21 int rv = sscanf(name, "P%lu", ¶meter); - if(rv != 1) + if(rv != 1) continue; mapper->setMapping(obj, nobj); @@ -3427,10 +3319,10 @@ PluginGui::PluginGui(MusECore::PluginIBase* p) paramsOut[i].label->setPrecision(2); paramsOut[i].label->setId(i); - Meter::MeterType mType=Meter::LinMeter; + Meter::MeterType mType=Meter::LinMeter; if(LADSPA_IS_HINT_INTEGER(range.HintDescriptor)) mType=Meter::DBMeter; - VerticalMeter* m = new VerticalMeter(this, mType); + VerticalMeter* m = new VerticalMeter(this, mType); m->setRange(dlower, dupper); m->setVal(dval); @@ -3497,7 +3389,10 @@ void PluginGui::getPluginConvertedValues(LADSPA_PortRangeHint range, void PluginGui::heartBeat() { - updateControls(); + updateControls(); // FINDMICHJETZT TODO: this is not good. we have concurrent + // access from the audio thread (possibly writing control values) + // while reading them from some GUI thread. this will lead + // to problems if writing floats is non-atomic } //--------------------------------------------------------- @@ -3511,7 +3406,7 @@ void PluginGui::ctrlPressed(int param) if(track) at = track->automationType(); - if(at != AUTO_OFF) + if (at == AUTO_READ || at == AUTO_TOUCH || at == AUTO_WRITE) plugin->enableController(param, false); int id = plugin->id(); @@ -3537,8 +3432,8 @@ void PluginGui::ctrlPressed(int param) MusEGlobal::song->controllerChange(track); track->startAutoRecord(id, val); - } - } + } + } else if(params[param].type == GuiParam::GUI_SWITCH) { float val = (float)((CheckBox*)params[param].actuator)->isChecked(); // p4.0.21 @@ -3550,8 +3445,8 @@ void PluginGui::ctrlPressed(int param) MusEGlobal::song->controllerChange(track); track->startAutoRecord(id, val); - } - } + } + } } //--------------------------------------------------------- @@ -3566,9 +3461,10 @@ void PluginGui::ctrlReleased(int param) at = track->automationType(); // Special for switch - don't enable controller until transport stopped. - if(at != AUTO_WRITE && ((params[param].type != GuiParam::GUI_SWITCH - || !MusEGlobal::audio->isPlaying() - || at != AUTO_TOUCH) || (!MusEGlobal::audio->isPlaying() && at == AUTO_TOUCH)) ) + if ((at == AUTO_OFF) || + (at == AUTO_READ) || + (at == AUTO_TOUCH && (params[param].type != GuiParam::GUI_SWITCH || + !MusEGlobal::audio->isPlaying()) ) ) plugin->enableController(param, true); int id = plugin->id(); @@ -3584,7 +3480,7 @@ void PluginGui::ctrlReleased(int param) else if (LADSPA_IS_HINT_INTEGER(params[param].hint)) val = rint(val); track->stopAutoRecord(id, val); - } + } } //--------------------------------------------------------- @@ -3609,13 +3505,11 @@ void PluginGui::sliderChanged(double val, int param) if(track) at = track->automationType(); - if(at == AUTO_WRITE || (MusEGlobal::audio->isPlaying() && at == AUTO_TOUCH)) - plugin->enableController(param, false); - if (LADSPA_IS_HINT_LOGARITHMIC(params[param].hint)) val = pow(10.0, val/20.0); else if (LADSPA_IS_HINT_INTEGER(params[param].hint)) val = rint(val); + if (plugin->param(param) != val) { plugin->setParam(param, val); ((DoubleLabel*)params[param].label)->setValue(val); @@ -3646,9 +3540,6 @@ void PluginGui::labelChanged(double val, int param) if(track) at = track->automationType(); - if(at == AUTO_WRITE || (MusEGlobal::audio->isPlaying() && at == AUTO_TOUCH)) - plugin->enableController(param, false); - double dval = val; if (LADSPA_IS_HINT_LOGARITHMIC(params[param].hint)) dval = MusECore::fast_log10(val) * 20.0; @@ -3990,9 +3881,6 @@ void PluginGui::guiParamChanged(int idx) if(track) at = track->automationType(); - if(at == AUTO_WRITE || (MusEGlobal::audio->isPlaying() && at == AUTO_TOUCH)) - plugin->enableController(param, false); - double val = 0.0; switch(type) { case GuiWidgets::SLIDER: @@ -4065,7 +3953,7 @@ void PluginGui::guiParamPressed(int idx) if(track) at = track->automationType(); - if(at != AUTO_OFF) + if (at == AUTO_READ || at == AUTO_TOUCH || at == AUTO_WRITE) plugin->enableController(param, false); int id = plugin->id(); @@ -4107,9 +3995,10 @@ void PluginGui::guiParamReleased(int idx) at = track->automationType(); // Special for switch - don't enable controller until transport stopped. - if(at != AUTO_WRITE && (type != GuiWidgets::QCHECKBOX - || !MusEGlobal::audio->isPlaying() - || at != AUTO_TOUCH)) + if ((at == AUTO_OFF) || + (at == AUTO_READ) || + (at == AUTO_TOUCH && (type != GuiWidgets::QCHECKBOX || + !MusEGlobal::audio->isPlaying()) ) ) plugin->enableController(param, true); int id = plugin->id(); @@ -4153,7 +4042,7 @@ void PluginGui::guiSliderPressed(int idx) int id = plugin->id(); - if(at == AUTO_WRITE || (at == AUTO_READ || at == AUTO_TOUCH)) + if (at == AUTO_READ || at == AUTO_TOUCH || at == AUTO_WRITE) plugin->enableController(param, false); if(!track || id == -1) @@ -4206,7 +4095,12 @@ void PluginGui::guiSliderReleased(int idx) if(track) at = track->automationType(); - if(at != AUTO_WRITE || (!MusEGlobal::audio->isPlaying() && at == AUTO_TOUCH)) + /* equivalent to + if ((at == AUTO_OFF) || + (at == AUTO_READ) || + (at == AUTO_TOUCH && (type != GuiWidgets::QCHECKBOX || <--- this type is SLIDER != CHECKBOX -> true + !MusEGlobal::audio->isPlaying()) ) ) <--- above==true -> this doesn't matter */ + if (at == AUTO_OFF || at == AUTO_READ || at == AUTO_TOUCH) plugin->enableController(param, true); int id = plugin->id(); diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h index 81c41396..9c671097 100644 --- a/muse2/muse/plugin.h +++ b/muse2/muse/plugin.h @@ -92,6 +92,7 @@ class Plugin { QString _maker; QString _copyright; + bool _isDssiSynth; bool _isDssi; // Hack: Special flag required. bool _isDssiVst; @@ -110,7 +111,7 @@ class Plugin { bool _inPlaceCapable; public: - Plugin(QFileInfo* f, const LADSPA_Descriptor* d, bool isDssi = false); + Plugin(QFileInfo* f, const LADSPA_Descriptor* d, bool isDssi = false, bool isDssiSynth = false); ~Plugin(); QString label() const { return _label; } @@ -127,6 +128,7 @@ class Plugin { int instNo() { return _instNo++; } bool isDssiPlugin() const { return _isDssi; } + bool isDssiSynth() const { return _isDssiSynth; } LADSPA_Handle instantiate(); void activate(LADSPA_Handle handle) { @@ -180,6 +182,8 @@ class Plugin { unsigned long controlInPorts() const { return _controlInPorts; } unsigned long controlOutPorts() const { return _controlOutPorts; } bool inPlaceCapable() const { return _inPlaceCapable; } + + const std::vector<unsigned long>* getRpIdx() { return &rpIdx; } }; typedef std::list<Plugin>::iterator iPlugin; @@ -190,9 +194,9 @@ typedef std::list<Plugin>::iterator iPlugin; class PluginList : public std::list<Plugin> { public: - void add(QFileInfo* fi, const LADSPA_Descriptor* d, bool isDssi = false) + void add(QFileInfo* fi, const LADSPA_Descriptor* d, bool isDssi = false, bool isDssiSynth = false) { - push_back(Plugin(fi, d, isDssi)); + push_back(Plugin(fi, d, isDssi, isDssiSynth)); } Plugin* find(const QString&, const QString&); @@ -266,38 +270,6 @@ class PluginIBase void deleteGui(); }; -/* DELETETHIS 30 -class PluginBase -{ - public: - bool on() const { return _on; } - void setOn(bool val) { _on = val; } - int pluginID() { return plugin()->id(); } - int id() { return _id; } - QString pluginLabel() const { return _plugin->label(); } - QString name() const { return _name; } - - AudioTrack* track() { return _track; } - - void enableController(int i, bool v = true) { controls[i].enCtrl = v; } - bool controllerEnabled(int i) const { return controls[i].enCtrl; } - bool controllerEnabled2(int i) const { return controls[i].en2Ctrl; } - void updateControllers(); - - void writeConfiguration(int level, Xml& xml); - bool readConfiguration(Xml& xml, bool readPreset=false); - - int parameters() const { return controlPorts; } - void setParam(int i, double val) { controls[i].tmpVal = val; } - double param(int i) const { return controls[i].val; } - const char* paramName(int i) { return _plugin->portName(controls[i].idx); } - LADSPA_PortRangeHint range(int i) - { - return _plugin->range(controls[i].idx); - } -}; -*/ - //--------------------------------------------------------- // PluginI // plugin instance diff --git a/muse2/muse/seqmsg.cpp b/muse2/muse/seqmsg.cpp index a3ea4ddc..d5257f80 100644 --- a/muse2/muse/seqmsg.cpp +++ b/muse2/muse/seqmsg.cpp @@ -244,21 +244,12 @@ void Audio::msgAddRoute(Route src, Route dst) if (!MusEGlobal::checkAudioDevice()) return; if (isRunning()) { - //if(dst.type == Route::JACK_MIDI_ROUTE) DELETETHIS if(dst.type == Route::MIDI_DEVICE_ROUTE) { - //MidiJackDevice* jmd = dynamic_cast<MidiJackDevice*>(dst.device); DELETETHIS - //if(jmd) if(dst.device) { if(dst.device->deviceType() == MidiDevice::JACK_MIDI) - MusEGlobal::audioDevice->connect(src.jackPort, dst.device->inClientPort()); // p3.3.55 - //else - //{ - // TODO... or DELETETHIS - //MidiAlsaDevice* amd = dynamic_cast<MidiAlsaDevice*>(dst.device); - //if(amd) - //} + MusEGlobal::audioDevice->connect(src.jackPort, dst.device->inClientPort()); } } else @@ -270,22 +261,12 @@ void Audio::msgAddRoute(Route src, Route dst) if (!MusEGlobal::checkAudioDevice()) return; if (MusEGlobal::audio->isRunning()) { - //if(src.type == Route::JACK_MIDI_ROUTE) DELETETHIS if(src.type == Route::MIDI_DEVICE_ROUTE) { - //MidiJackDevice* jmd = dynamic_cast<MidiJackDevice*>(src.device); DELETETHIS - //if(jmd) if(src.device) { if(src.device->deviceType() == MidiDevice::JACK_MIDI) - //MusEGlobal::audioDevice->connect(src.device->clientPort(), dst.jackPort); DELETETHIS - MusEGlobal::audioDevice->connect(src.device->outClientPort(), dst.jackPort); // p3.3.55 - //else - //{ - // TODO... or DELETETHIS - //MidiAlsaDevice* amd = dynamic_cast<MidiAlsaDevice*>(src.device); - //if(amd) - //} + MusEGlobal::audioDevice->connect(src.device->outClientPort(), dst.jackPort); } } else @@ -1262,6 +1243,19 @@ void Audio::msgSetTrackOutPort(MidiTrack* track, int port) } //--------------------------------------------------------- +// msgSetTrackAutomationType +//--------------------------------------------------------- + +void Audio::msgSetTrackAutomationType(Track* track, int type) +{ + AudioMsg msg; + msg.id = SEQM_SET_TRACK_AUTO_TYPE; + msg.track = track; + msg.ival = type; + sendMessage(&msg, false); +} + +//--------------------------------------------------------- // msgRemapPortDrumCtlEvents //--------------------------------------------------------- diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index 1b7354f2..0c7a0c73 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -84,8 +84,8 @@ Song::Song(const char* name) noteFifoSize = 0; noteFifoWindex = 0; noteFifoRindex = 0; - undoList = new UndoList; - redoList = new UndoList; + undoList = new UndoList(true); // "true" means "this is an undoList", + redoList = new UndoList(false); // "false" means "redoList" _markerList = new MarkerList; _globalPitchShift = 0; bounceTrack = NULL; @@ -570,24 +570,6 @@ void Song::deselectTracks() (*t)->setSelected(false); } -/* DELETETHIS 17 -//--------------------------------------------------------- -// changeTrack -// oldTrack - copy of the original track befor modification -// newTrack - modified original track -//--------------------------------------------------------- - -void Song::changeTrack(Track* oldTrack, Track* newTrack) - { - oldTrack->setSelected(false); //?? - int idx = _tracks.index(newTrack); - - //addUndo(UndoOp(UndoOp::ModifyTrack, oldTrack, newTrack)); - addUndo(UndoOp(UndoOp::ModifyTrack, idx, oldTrack, newTrack)); - updateFlags |= SC_TRACK_MODIFIED; - } -*/ - //--------------------------------------------------------- // addEvent // return true if event was added @@ -2100,13 +2082,11 @@ void Song::clear(bool signal, bool clear_all) MusEGlobal::keymap.clear(); undoList->clearDelete(); - // DELETETHIS - //redoList->clear(); // Check this - Should we do a clearDelete? IIRC it was OK this way - no clearDelete in case of same items in both lists. - redoList->clearDelete(); // p4.0.46 Tim + redoList->clearDelete(); if(MusEGlobal::undoAction) - MusEGlobal::undoAction->setEnabled(false); // + MusEGlobal::undoAction->setEnabled(false); if(MusEGlobal::redoAction) - MusEGlobal::redoAction->setEnabled(false); // + MusEGlobal::redoAction->setEnabled(false); _markerList->clear(); pos[0].setTick(0); @@ -2195,11 +2175,9 @@ void Song::cleanupForQuit() MusEGlobal::keymap.clear(); if(MusEGlobal::debugMsg) - printf("deleting undoList, clearing redoList\n"); + printf("deleting undoList and redoList\n"); undoList->clearDelete(); - //DELETETHIS - //redoList->clear(); // Check this - Should we do a clearDelete? IIRC it was OK this way - no clearDelete in case of same items in both lists. - redoList->clearDelete(); // p4.0.46 Tim + redoList->clearDelete(); _markerList->clear(); @@ -2262,10 +2240,6 @@ void Song::cleanupForQuit() // are handled by ~AudioTrack. if(MusEGlobal::debugMsg) - printf("Muse: Deleting sound files\n"); - SndFile::sndFiles.clearDelete(); - - if(MusEGlobal::debugMsg) printf("...finished cleaning up.\n"); } @@ -2765,16 +2739,24 @@ void Song::clearRecAutomation(bool clearList) void Song::processAutomationEvents() { + MusEGlobal::audio->msgIdle(true); // gain access to all data structures + // Just clear all pressed and touched flags, not rec event lists. clearRecAutomation(false); if (!MusEGlobal::automation) + { + MusEGlobal::audio->msgIdle(false); return; + } + for(iTrack i = _tracks.begin(); i != _tracks.end(); ++i) { if(!(*i)->isMidiTrack()) // Process (and clear) rec events. ((AudioTrack*)(*i))->processAutomationEvents(); } + + MusEGlobal::audio->msgIdle(false); } //--------------------------------------------------------- @@ -2794,7 +2776,10 @@ void Song::abortRolling() void Song::stopRolling() { - abortRolling(); + if (record()) + MusEGlobal::audio->recordStop(); + setStopPlay(false); + processAutomationEvents(); } diff --git a/muse2/muse/song.h b/muse2/muse/song.h index 7f0aae70..82b8cf18 100644 --- a/muse2/muse/song.h +++ b/muse2/muse/song.h @@ -428,7 +428,7 @@ class Song : public QObject { void markerChanged(int); void midiPortsChanged(); void midiNote(int pitch, int velo); - void controllerChanged(MusECore::Track* t); + void controllerChanged(MusECore::Track* t); // maybe DELETETHIS: this only triggers a redraw in pcanvas.cpp; what is this for? void newPartsCreated(const std::map< MusECore::Part*, std::set<MusECore::Part*> >&); }; diff --git a/muse2/muse/synth.cpp b/muse2/muse/synth.cpp index cf065bbb..332ff90f 100644 --- a/muse2/muse/synth.cpp +++ b/muse2/muse/synth.cpp @@ -143,7 +143,7 @@ static Synth* findSynth(const QString& sclass, const QString& label, Synth::Type i != MusEGlobal::synthis.end(); ++i) { if( ((*i)->baseName() == sclass) && - (label.isEmpty() || ((*i)->name() == label)) && + (label.isEmpty() || ((*i)->name() == label)) && (type == Synth::SYNTH_TYPE_END || type == (*i)->synthType()) ) return *i; } @@ -165,7 +165,6 @@ static SynthI* createSynthInstance(const QString& sclass, const QString& label, QString n; n.setNum(s->instances()); QString instance_name = s->name() + "-" + n; - if (si->initInstance(s, instance_name)) { delete si; return 0; diff --git a/muse2/muse/synth.h b/muse2/muse/synth.h index 8e19d5e8..efa76f5f 100644 --- a/muse2/muse/synth.h +++ b/muse2/muse/synth.h @@ -136,15 +136,9 @@ class SynthIF { virtual bool guiVisible() const = 0; virtual void showGui(bool v) = 0; virtual bool hasGui() const = 0; - //virtual bool guiVisible() const { return false; } DELETETHIS 3 - //virtual void showGui(bool v) { }; - //virtual bool hasGui() const { return false; } virtual bool nativeGuiVisible() const = 0; virtual void showNativeGui(bool v) = 0; virtual bool hasNativeGui() const = 0; - //virtual bool nativeGuiVisible() const { return false; } DELETETHIS 3 - //virtual void showNativeGui(bool v) { }; - //virtual bool hasNativeGui() const { return false; } virtual void getGeometry(int*, int*, int*, int*) const = 0; virtual void setGeometry(int, int, int, int) = 0; virtual void getNativeGeometry(int*, int*, int*, int*) const = 0; @@ -190,12 +184,6 @@ class SynthI : public AudioTrack, public MidiDevice, // Used once upon song reload, then discarded. std::vector<float> initParams; - // List of gui controls to update upon heartbeat. - std::vector<bool> _guiUpdateControls; - - // Update gui program upon heartbeat. - bool _guiUpdateProgram; - // Initial, and running, string parameters for synths which use them, like dssi. StringParamMap _stringParamMap; diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp index 842afbb3..905f9030 100644 --- a/muse2/muse/track.cpp +++ b/muse2/muse/track.cpp @@ -290,7 +290,6 @@ void Track::internal_assign(const Track& t, int flags) // Do not call setName here. Audio Input and Output override it and try to set // Jack ports, which have not been initialized yet here. Must wait until // .Audio Input and Output copy constructors or assign are called. - //setName(s); _name = s; break; } @@ -540,18 +539,15 @@ void MidiTrack::internal_assign(const Track& t, int flags) clefType = mt.clefType; } - // FIXME: May get "addRoute: src track route already exists" when say, - // an audio output and wave track are selected just because - // of the redundancy (wave track wants to connect to output by default). if(flags & ASSIGN_ROUTES) { for(ciRoute ir = mt._inRoutes.begin(); ir != mt._inRoutes.end(); ++ir) - // Amazingly, this single line seems to work. - MusEGlobal::audio->msgAddRoute(*ir, Route(this, ir->channel)); + // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node. + _inRoutes.push_back(*ir); for(ciRoute ir = mt._outRoutes.begin(); ir != mt._outRoutes.end(); ++ir) - // Amazingly, this single line seems to work. - MusEGlobal::audio->msgAddRoute(Route(this, ir->channel), *ir); + // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node. + _outRoutes.push_back(*ir); for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin(); it!=MusEGlobal::global_drum_ordering.end(); it++) if (it->first == &mt) @@ -574,7 +570,8 @@ void MidiTrack::internal_assign(const Track& t, int flags) { c = mp->defaultInChannels(); if(c) - MusEGlobal::audio->msgAddRoute(Route(i, c), Route(this, c)); + // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node. + _inRoutes.push_back(Route(i, c)); } if(!defOutFound) @@ -585,7 +582,8 @@ void MidiTrack::internal_assign(const Track& t, int flags) /// TODO: Switch if and when multiple output routes supported. #if 0 - MusEGlobal::audio->msgAddRoute(Route(this, c), Route(i, c)); + // Don't call msgAddRoute. Caller later calls msgAddTrack which 'mirrors' this routing node. + _outRoutes.push_back(Route(i, c)); #else for(ch = 0; ch < MIDI_CHANNELS; ++ch) { @@ -1308,7 +1306,7 @@ int MidiTrack::getFirstControllerValue(int ctrl, int def) return val; } -int MidiTrack::getControllerChangeAtTick(int tick, int ctrl, int def) +int MidiTrack::getControllerChangeAtTick(unsigned tick, int ctrl, int def) { for (iPart pit=parts()->begin(); pit!=parts()->end(); pit++) { @@ -1331,8 +1329,8 @@ int MidiTrack::getControllerChangeAtTick(int tick, int ctrl, int def) } // returns the tick where this CC gets overriden by a new one -// returns -1 for "never" -unsigned MidiTrack::getControllerValueLifetime(int tick, int ctrl) +// returns UINT_MAX for "never" +unsigned MidiTrack::getControllerValueLifetime(unsigned tick, int ctrl) { unsigned result=UINT_MAX; diff --git a/muse2/muse/track.h b/muse2/muse/track.h index 5e3319a2..93f2f673 100644 --- a/muse2/muse/track.h +++ b/muse2/muse/track.h @@ -30,6 +30,7 @@ #include <vector> #include <algorithm> +#include "wave.h" // for SndFileR #include "part.h" #include "key.h" #include "node.h" @@ -42,7 +43,6 @@ namespace MusECore { class MPEventList; class Pipeline; class PluginI; -class SndFile; class SynthI; class Xml; class DrumMap; @@ -304,9 +304,9 @@ class MidiTrack : public Track { static bool visible() { return _isVisible; } int getFirstControllerValue(int ctrl, int def=-1); - int getControllerChangeAtTick(int tick, int ctrl, int def=-1); - unsigned getControllerValueLifetime(int tick, int ctrl); // returns the tick where this CC gets overriden by a new one - // returns UINT_MAX for "never" + int getControllerChangeAtTick(unsigned tick, int ctrl, int def=-1); + unsigned getControllerValueLifetime(unsigned tick, int ctrl); // returns the tick where this CC gets overriden by a new one + // returns UINT_MAX for "never" void setClef(clefTypes i) { clefType = i; } clefTypes getClef() { return clefType; } @@ -359,7 +359,7 @@ class AudioTrack : public Track { unsigned bufferPos; virtual bool getData(unsigned, int, unsigned, float**); - SndFile* _recFile; + SndFileR _recFile; Fifo fifo; // fifo -> _recFile bool _processed; @@ -390,8 +390,8 @@ class AudioTrack : public Track { void mapRackPluginsToControllers(); void showPendingPluginNativeGuis(); - SndFile* recFile() const { return _recFile; } - void setRecFile(SndFile* sf) { _recFile = sf; } + SndFileR recFile() const { return _recFile; } + void setRecFile(SndFileR sf) { _recFile = sf; } CtrlListList* controller() { return &_controller; } diff --git a/muse2/muse/undo.cpp b/muse2/muse/undo.cpp index e12fcedc..b81de33d 100644 --- a/muse2/muse/undo.cpp +++ b/muse2/muse/undo.cpp @@ -49,7 +49,7 @@ std::list<QString> temporaryWavFiles; const char* UndoOp::typeName() { static const char* name[] = { - "AddTrack", "DeleteTrack", "ModifyTrack", + "AddTrack", "DeleteTrack", "AddPart", "DeletePart", "ModifyPart", "AddEvent", "DeleteEvent", "ModifyEvent", "AddTempo", "DeleteTempo", @@ -73,10 +73,7 @@ void UndoOp::dump() switch(type) { case AddTrack: case DeleteTrack: - printf("%d %s\n", trackno, oTrack->name().toLatin1().constData()); - break; - case ModifyTrack: - printf("%d <%s>-<%s>\n", trackno, oTrack->name().toLatin1().constData(), nTrack->name().toLatin1().constData()); + printf("%d %s\n", trackno, track->name().toLatin1().constData()); break; case AddPart: case DeletePart: @@ -124,99 +121,85 @@ void UndoList::clearDelete() { if(!empty()) { - for(iUndo iu = begin(); iu != end(); ++iu) + if (this->isUndo) { - Undo& u = *iu; - for(riUndoOp i = u.rbegin(); i != u.rend(); ++i) + for(iUndo iu = begin(); iu != end(); ++iu) { - switch(i->type) + Undo& u = *iu; + for(iUndoOp i = u.begin(); i != u.end(); ++i) { - case UndoOp::DeleteTrack: - if(i->oTrack) - { - delete i->oTrack; - iUndo iu2 = iu; - ++iu2; - for(; iu2 != end(); ++iu2) - { - Undo& u2 = *iu2; - for(riUndoOp i2 = u2.rbegin(); i2 != u2.rend(); ++i2) - { - if(i2->type == UndoOp::DeleteTrack) - { - if(i2->oTrack == i->oTrack) - i2->oTrack = 0; - } - } - } - } - break; - /* case UndoOp::ModifyTrack: DELETETHIS 50 - if(i->oTrack) - { - // Prevent delete i->oTrack from crashing. - switch(i->oTrack->type()) - { - case Track::AUDIO_OUTPUT: - { - AudioOutput* ao = (AudioOutput*)i->oTrack; - for(int ch = 0; ch < ao->channels(); ++ch) - ao->setJackPort(ch, 0); - } - break; - case Track::AUDIO_INPUT: - { - AudioInput* ai = (AudioInput*)i->oTrack; - for(int ch = 0; ch < ai->channels(); ++ch) - ai->setJackPort(ch, 0); - } - break; - default: - break; - } - if(!i->oTrack->isMidiTrack()) - ((AudioTrack*)i->oTrack)->clearEfxList(); - delete i->oTrack; - - iUndo iu2 = iu; - ++iu2; - for(; iu2 != end(); ++iu2) - { - Undo& u2 = *iu2; - for(riUndoOp i2 = u2.rbegin(); i2 != u2.rend(); ++i2) - { - if(i2->type == UndoOp::ModifyTrack) - { - if(i2->oTrack == i->oTrack) - i2->oTrack = 0; - } - } - } - } - break; */ - - //case UndoOp::DeletePart: - //delete i->oPart; - // break; - //case UndoOp::DeleteTempo: - // break; - //case UndoOp::DeleteSig: - // break; + switch(i->type) + { + case UndoOp::DeleteTrack: + if(i->track) + delete i->track; + break; + + case UndoOp::DeletePart: + delete i->oPart; + break; + + case UndoOp::ModifyPart: + delete i->oPart; + break; + case UndoOp::ModifyMarker: - if (i->copyMarker) - delete i->copyMarker; - break; - case UndoOp::ModifyTrackName: - if (i->_oldName) - delete i->_oldName; - if (i->_newName) - delete i->_newName; - break; - default: - break; + if (i->copyMarker) + delete i->copyMarker; + break; + + case UndoOp::ModifyTrackName: + if (i->_oldName) + delete [] i->_oldName; + if (i->_newName) + delete [] i->_newName; + break; + + default: + break; + } } + u.clear(); + } + } + else + { + for(riUndo iu = rbegin(); iu != rend(); ++iu) + { + Undo& u = *iu; + for(riUndoOp i = u.rbegin(); i != u.rend(); ++i) + { + switch(i->type) + { + case UndoOp::AddTrack: + delete i->track; + break; + + case UndoOp::AddPart: + delete i->oPart; + break; + + case UndoOp::ModifyPart: + delete i->nPart; + break; + case UndoOp::ModifyMarker: + if (i->realMarker) + delete i->realMarker; + break; + + case UndoOp::ModifyTrackName: + if (i->_oldName) + delete [] i->_oldName; + if (i->_newName) + delete [] i->_newName; + break; + + default: + break; + } + } + u.clear(); } - u.clear(); } } @@ -261,12 +244,12 @@ void cleanOperationGroup(Undo& group) iUndoOp op_=op; op_++; - if ((op->type==UndoOp::ModifyTrack) || (op->type==UndoOp::DeleteTrack)) + if (op->type==UndoOp::DeleteTrack) { - if (processed_tracks.find(op->oTrack)!=processed_tracks.end()) + if (processed_tracks.find(op->track)!=processed_tracks.end()) group.erase(op); else - processed_tracks.insert(op->oTrack); + processed_tracks.insert(op->track); } else if ((op->type==UndoOp::ModifyPart) || (op->type==UndoOp::DeletePart)) { @@ -320,149 +303,15 @@ void Song::doUndo2() for (riUndoOp i = u.rbegin(); i != u.rend(); ++i) { switch(i->type) { case UndoOp::AddTrack: - removeTrack2(i->oTrack); + removeTrack2(i->track); updateFlags |= SC_TRACK_REMOVED; break; case UndoOp::DeleteTrack: - insertTrack2(i->oTrack, i->trackno); - chainTrackParts(i->oTrack, true); + insertTrack2(i->track, i->trackno); + chainTrackParts(i->track, true); updateFlags |= SC_TRACK_INSERTED; break; -/* DELETETHIS 130 - case UndoOp::ModifyTrack: - { - //printf("Song::doUndo2 ModifyTrack #1 oTrack %p %s nTrack %p %s\n", i->oTrack, i->oTrack->name().toLatin1().constData(), i->nTrack, i->nTrack->name().toLatin1().constData()); - - // Unchain the track parts, but don't touch the ref counts. - unchainTrackParts(i->nTrack, false); - - //Track* track = i->nTrack->clone(); - Track* track = i->nTrack->clone(false); - - // A Track custom assignment operator was added by Tim. - *(i->nTrack) = *(i->oTrack); - - //printf("Song::doUndo2 ModifyTrack #2 oTrack %p %s nTrack %p %s\n", i->oTrack, i->oTrack->name().toLatin1().constData(), i->nTrack, i->nTrack->name().toLatin1().constData()); - - // Prevent delete i->oTrack from crashing. - switch(i->oTrack->type()) - { - case Track::AUDIO_OUTPUT: - { - AudioOutput* ao = (AudioOutput*)i->oTrack; - for(int ch = 0; ch < ao->channels(); ++ch) - ao->setJackPort(ch, 0); - } - break; - case Track::AUDIO_INPUT: - { - AudioInput* ai = (AudioInput*)i->oTrack; - for(int ch = 0; ch < ai->channels(); ++ch) - ai->setJackPort(ch, 0); - } - break; - default: - break; - } - if(!i->oTrack->isMidiTrack()) - ((AudioTrack*)i->oTrack)->clearEfxList(); - - delete i->oTrack; - i->oTrack = track; - - // Chain the track parts, but don't touch the ref counts. - chainTrackParts(i->nTrack, false); - - //printf("Song::doUndo2 ModifyTrack #3 oTrack %p %s nTrack %p %s\n", i->oTrack, i->oTrack->name().toLatin1().constData(), i->nTrack, i->nTrack->name().toLatin1().constData()); - - // Connect and register ports. - switch(i->nTrack->type()) - { - case Track::AUDIO_OUTPUT: - { - AudioOutput* ao = (AudioOutput*)i->nTrack; - ao->setName(ao->name()); - } - break; - case Track::AUDIO_INPUT: - { - AudioInput* ai = (AudioInput*)i->nTrack; - ai->setName(ai->name()); - } - break; - default: - break; - } - - // Update solo states, since the user may have changed soloing on other tracks. - updateSoloStates(); - - updateFlags |= SC_TRACK_MODIFIED; - } - break; -*/ - - /* - switch(i->nTrack->type()) - { - case Track::AUDIO_OUTPUT: - { - AudioOutput* ao = (AudioOutput*)i->nTrack; - for(int ch = 0; ch < ao->channels(); ++ch) - ao->setJackPort(ch, 0); - } - break; - case Track::AUDIO_INPUT: - { - AudioInput* ai = (AudioInput*)i->nTrack; - for(int ch = 0; ch < ai->channels(); ++ch) - ai->setJackPort(ch, 0); - } - break; - default: - break; - } - if(!i->nTrack->isMidiTrack()) - ((AudioTrack*)i->nTrack)->clearEfxList(); - - //delete i->oTrack; - //i->oTrack = track; - - // Remove the track. removeTrack2 takes care of unchaining the new track. - removeTrack2(i->nTrack); - - // Connect and register ports. - switch(i->oTrack->type()) - { - case Track::AUDIO_OUTPUT: - { - AudioOutput* ao = (AudioOutput*)i->oTrack; - ao->setName(ao->name()); - } - break; - case Track::AUDIO_INPUT: - { - AudioInput* ai = (AudioInput*)i->oTrack; - ai->setName(ai->name()); - } - break; - default: - break; - } - - // Insert the old track. - insertTrack2(i->oTrack, i->trackno); - // Chain the old track parts. (removeTrack2, above, takes care of unchaining the new track). - chainTrackParts(i->oTrack, true); - - // Update solo states, since the user may have changed soloing on other tracks. - updateSoloStates(); - - updateFlags |= SC_TRACK_MODIFIED; - } - break; - */ case UndoOp::SwapTrack: { @@ -479,7 +328,6 @@ void Song::doUndo2() removePart(part); updateFlags |= SC_PART_REMOVED; i->oPart->events()->incARef(-1); - //i->oPart->unchainClone(); DELETETHIS unchainClone(i->oPart); } break; @@ -487,19 +335,17 @@ void Song::doUndo2() addPart(i->oPart); updateFlags |= SC_PART_INSERTED; i->oPart->events()->incARef(1); - //i->oPart->chainClone(); DELETETHIS chainClone(i->oPart); break; case UndoOp::ModifyPart: if(i->doCtrls) - removePortCtrlEvents(i->oPart, i->doClones); - changePart(i->oPart, i->nPart); - i->oPart->events()->incARef(-1); - i->nPart->events()->incARef(1); - //i->oPart->replaceClone(i->nPart); DELETETHIS - replaceClone(i->oPart, i->nPart); + removePortCtrlEvents(i->nPart, i->doClones); + changePart(i->nPart, i->oPart); + i->nPart->events()->incARef(-1); + i->oPart->events()->incARef(1); + replaceClone(i->nPart, i->oPart); if(i->doCtrls) - addPortCtrlEvents(i->nPart, i->doClones); + addPortCtrlEvents(i->oPart, i->doClones); updateFlags |= SC_PART_MODIFIED; break; case UndoOp::AddEvent: @@ -572,145 +418,17 @@ void Song::doRedo2() for (iUndoOp i = u.begin(); i != u.end(); ++i) { switch(i->type) { case UndoOp::AddTrack: - insertTrack2(i->oTrack, i->trackno); - chainTrackParts(i->oTrack, true); + insertTrack2(i->track, i->trackno); + chainTrackParts(i->track, true); updateFlags |= SC_TRACK_INSERTED; break; case UndoOp::DeleteTrack: - removeTrack2(i->oTrack); + removeTrack2(i->track); updateFlags |= SC_TRACK_REMOVED; break; -/* DELETETHIS 130 - case UndoOp::ModifyTrack: - { - // Unchain the track parts, but don't touch the ref counts. - unchainTrackParts(i->nTrack, false); - - //Track* track = i->nTrack->clone(); - Track* track = i->nTrack->clone(false); - - *(i->nTrack) = *(i->oTrack); - - // Prevent delete i->oTrack from crashing. - switch(i->oTrack->type()) - { - case Track::AUDIO_OUTPUT: - { - AudioOutput* ao = (AudioOutput*)i->oTrack; - for(int ch = 0; ch < ao->channels(); ++ch) - ao->setJackPort(ch, 0); - } - break; - case Track::AUDIO_INPUT: - { - AudioInput* ai = (AudioInput*)i->oTrack; - for(int ch = 0; ch < ai->channels(); ++ch) - ai->setJackPort(ch, 0); - } - break; - default: - break; - } - if(!i->oTrack->isMidiTrack()) - ((AudioTrack*)i->oTrack)->clearEfxList(); - - delete i->oTrack; - i->oTrack = track; - - // Chain the track parts, but don't touch the ref counts. - chainTrackParts(i->nTrack, false); - - // Connect and register ports. - switch(i->nTrack->type()) - { - case Track::AUDIO_OUTPUT: - { - AudioOutput* ao = (AudioOutput*)i->nTrack; - ao->setName(ao->name()); - } - break; - case Track::AUDIO_INPUT: - { - AudioInput* ai = (AudioInput*)i->nTrack; - ai->setName(ai->name()); - } - break; - default: - break; - } - - // Update solo states, since the user may have changed soloing on other tracks. - updateSoloStates(); - - updateFlags |= SC_TRACK_MODIFIED; - } - break; -*/ - - /* - // Prevent delete i->oTrack from crashing. - switch(i->oTrack->type()) - { - case Track::AUDIO_OUTPUT: - { - AudioOutput* ao = (AudioOutput*)i->oTrack; - for(int ch = 0; ch < ao->channels(); ++ch) - ao->setJackPort(ch, 0); - } - break; - case Track::AUDIO_INPUT: - { - AudioInput* ai = (AudioInput*)i->oTrack; - for(int ch = 0; ch < ai->channels(); ++ch) - ai->setJackPort(ch, 0); - } - break; - default: - break; - } - if(!i->oTrack->isMidiTrack()) - ((AudioTrack*)i->oTrack)->clearEfxList(); - - //delete i->oTrack; - //i->oTrack = track; - - // Remove the track. removeTrack2 takes care of unchaining the old track. - removeTrack2(i->oTrack); - // Connect and register ports. - switch(i->nTrack->type()) - { - case Track::AUDIO_OUTPUT: - { - AudioOutput* ao = (AudioOutput*)i->nTrack; - ao->setName(ao->name()); - } - break; - case Track::AUDIO_INPUT: - { - AudioInput* ai = (AudioInput*)i->nTrack; - ai->setName(ai->name()); - } - break; - default: - break; - } - - // Insert the new track. - insertTrack2(i->nTrack, i->trackno); - // Chain the new track parts. (removeTrack2, above, takes care of unchaining the old track). - chainTrackParts(i->nTrack, true); - - // Update solo states, since the user may have changed soloing on other tracks. - updateSoloStates(); - - updateFlags |= SC_TRACK_MODIFIED; - } - break; - */ - case UndoOp::SwapTrack: { Track* track = _tracks[i->a]; @@ -723,26 +441,23 @@ void Song::doRedo2() addPart(i->oPart); updateFlags |= SC_PART_INSERTED; i->oPart->events()->incARef(1); - //i->oPart->chainClone(); DELETETHIS chainClone(i->oPart); break; case UndoOp::DeletePart: removePart(i->oPart); updateFlags |= SC_PART_REMOVED; i->oPart->events()->incARef(-1); - //i->oPart->unchainClone(); DELETETHIS unchainClone(i->oPart); break; case UndoOp::ModifyPart: if(i->doCtrls) - removePortCtrlEvents(i->nPart, i->doClones); - changePart(i->nPart, i->oPart); - i->oPart->events()->incARef(1); - i->nPart->events()->incARef(-1); - //i->nPart->replaceClone(i->oPart); DELETETHIS - replaceClone(i->nPart, i->oPart); + removePortCtrlEvents(i->oPart, i->doClones); + changePart(i->oPart, i->nPart); + i->nPart->events()->incARef(1); + i->oPart->events()->incARef(-1); + replaceClone(i->oPart, i->nPart); if(i->doCtrls) - addPortCtrlEvents(i->oPart, i->doClones); + addPortCtrlEvents(i->nPart, i->doClones); updateFlags |= SC_PART_MODIFIED; break; case UndoOp::AddEvent: @@ -821,19 +536,12 @@ UndoOp::UndoOp(UndoType type_, int a_, int b_, int c_) c = c_; } -UndoOp::UndoOp(UndoType type_, int n, Track* oldTrack, Track* newTrack) - { - type = type_; - trackno = n; - oTrack = oldTrack; - nTrack = newTrack; - } -UndoOp::UndoOp(UndoType type_, int n, Track* track) +UndoOp::UndoOp(UndoType type_, int n, Track* track_) { type = type_; trackno = n; - oTrack = track; + track = track_; } UndoOp::UndoOp(UndoType type_, Part* part) @@ -864,8 +572,8 @@ UndoOp::UndoOp(UndoType type_, Event& nev, Part* part_, bool doCtrls_, bool doCl UndoOp::UndoOp(UndoType type_, Part* oPart_, Part* nPart_, bool doCtrls_, bool doClones_) { type = type_; - oPart = nPart_; - nPart = oPart_; + oPart = oPart_; + nPart = nPart_; doCtrls = doCtrls_; doClones = doClones_; } @@ -879,12 +587,6 @@ UndoOp::UndoOp(UndoType type_, int c, int ctrl_, int ov, int nv) nVal = nv; } -UndoOp::UndoOp(UndoType type_, SigEvent* oevent, SigEvent* nevent) - { - type = type_; - oSignature = oevent; - nSignature = nevent; - } UndoOp::UndoOp(UndoType type_, Marker* copyMarker_, Marker* realMarker_) { type = type_; @@ -901,20 +603,20 @@ UndoOp::UndoOp(UndoType type_, const char* changedFile, const char* changeData, endframe = endframe_; } -UndoOp::UndoOp(UndoOp::UndoType type_, Track* track, const char* old_name, const char* new_name) +UndoOp::UndoOp(UndoOp::UndoType type_, Track* track_, const char* old_name, const char* new_name) { type = type_; - _renamedTrack = track; + _renamedTrack = track_; _oldName = new char[strlen(old_name) + 1]; _newName = new char[strlen(new_name) + 1]; strcpy(_oldName, old_name); strcpy(_newName, new_name); } -UndoOp::UndoOp(UndoOp::UndoType type_, Track* track, int old_chan, int new_chan) +UndoOp::UndoOp(UndoOp::UndoType type_, Track* track_, int old_chan, int new_chan) { type = type_; - _propertyTrack = track; + _propertyTrack = track_; _oldPropValue = old_chan; _newPropValue = new_chan; } @@ -953,24 +655,24 @@ bool Song::doUndo1() for (riUndoOp i = u.rbegin(); i != u.rend(); ++i) { switch(i->type) { case UndoOp::AddTrack: - removeTrack1(i->oTrack); + removeTrack1(i->track); break; case UndoOp::DeleteTrack: - insertTrack1(i->oTrack, i->trackno); + insertTrack1(i->track, i->trackno); // FIXME: Would like to put this part in Undo2, but indications // elsewhere are that (dis)connecting jack routes must not be // done in the realtime thread. The result is that we get a few // "PANIC Process init: No buffer from audio device" messages // before the routes are (dis)connected. So far seems to do no harm though... - switch(i->oTrack->type()) + switch(i->track->type()) { case Track::AUDIO_OUTPUT: case Track::AUDIO_INPUT: - connectJackRoutes((AudioTrack*)i->oTrack, false); + connectJackRoutes((AudioTrack*)i->track, false); break; //case Track::AUDIO_SOFTSYNTH: DELETETHIS 4 - //SynthI* si = (SynthI*)i->oTrack; + //SynthI* si = (SynthI*)i->track; //si->synth()->init( // break; default: @@ -1039,15 +741,11 @@ void Song::doUndo3() for (riUndoOp i = u.rbegin(); i != u.rend(); ++i) { switch(i->type) { case UndoOp::AddTrack: - removeTrack3(i->oTrack); + removeTrack3(i->track); break; case UndoOp::DeleteTrack: - insertTrack3(i->oTrack, i->trackno); + insertTrack3(i->track, i->trackno); break; - case UndoOp::ModifyTrack: - // Not much choice but to do this - Tim. DELETETHIS 2 - //clearClipboardAndCloneList(); - break; case UndoOp::ModifyMarker: { if (i->realMarker) { @@ -1085,17 +783,17 @@ bool Song::doRedo1() for (iUndoOp i = u.begin(); i != u.end(); ++i) { switch(i->type) { case UndoOp::AddTrack: - insertTrack1(i->oTrack, i->trackno); + insertTrack1(i->track, i->trackno); // FIXME: See comments in Undo1. - switch(i->oTrack->type()) + switch(i->track->type()) { case Track::AUDIO_OUTPUT: case Track::AUDIO_INPUT: - connectJackRoutes((AudioTrack*)i->oTrack, false); + connectJackRoutes((AudioTrack*)i->track, false); break; //case Track::AUDIO_SOFTSYNTH: DELETETHIS 4 - //SynthI* si = (SynthI*)i->oTrack; + //SynthI* si = (SynthI*)i->track; //si->synth()->init( // break; default: @@ -1104,7 +802,7 @@ bool Song::doRedo1() break; case UndoOp::DeleteTrack: - removeTrack1(i->oTrack); + removeTrack1(i->track); break; case UndoOp::ModifyTrackName: i->_renamedTrack->setName(i->_newName); @@ -1167,15 +865,11 @@ void Song::doRedo3() for (iUndoOp i = u.begin(); i != u.end(); ++i) { switch(i->type) { case UndoOp::AddTrack: - insertTrack3(i->oTrack, i->trackno); + insertTrack3(i->track, i->trackno); break; case UndoOp::DeleteTrack: - removeTrack3(i->oTrack); + removeTrack3(i->track); break; - case UndoOp::ModifyTrack: - // Not much choice but to do this - Tim. DELETETHIS 2 - //clearClipboardAndCloneList(); - break; case UndoOp::ModifyMarker: { if (i->copyMarker) { diff --git a/muse2/muse/undo.h b/muse2/muse/undo.h index 3487da47..b88a9457 100644 --- a/muse2/muse/undo.h +++ b/muse2/muse/undo.h @@ -45,7 +45,7 @@ extern std::list<QString> temporaryWavFiles; //!< Used for storing all tmp-files struct UndoOp { enum UndoType { - AddTrack, DeleteTrack, ModifyTrack, + AddTrack, DeleteTrack, AddPart, DeletePart, ModifyPart, AddEvent, DeleteEvent, ModifyEvent, AddTempo, DeleteTempo, @@ -67,8 +67,7 @@ struct UndoOp { int c; }; struct { - Track* oTrack; - Track* nTrack; + Track* track; int trackno; }; struct { @@ -76,11 +75,7 @@ struct UndoOp { Part* nPart; }; struct { - Part* part; - }; - struct { - SigEvent* nSignature; - SigEvent* oSignature; + Part* part; // this part is only relevant for EVENT operations, NOT for part ops! }; struct { int channel; @@ -119,14 +114,12 @@ struct UndoOp { UndoOp(); UndoOp(UndoType type, int a, int b, int c=0); - UndoOp(UndoType type, int n, Track* oldTrack, Track* newTrack); UndoOp(UndoType type, int n, Track* track); UndoOp(UndoType type, Part* part); UndoOp(UndoType type, Event& oev, Event& nev, Part* part, bool doCtrls, bool doClones); UndoOp(UndoType type, Event& nev, Part* part, bool doCtrls, bool doClones); UndoOp(UndoType type, Part* oPart, Part* nPart, bool doCtrls, bool doClones); UndoOp(UndoType type, int c, int ctrl, int ov, int nv); - UndoOp(UndoType type, SigEvent* oevent, SigEvent* nevent); UndoOp(UndoType type, const char* changedFile, const char* changeData, int startframe, int endframe); UndoOp(UndoType type, Marker* copyMarker, Marker* realMarker); UndoOp(UndoType type, Track* track, const char* old_name, const char* new_name); @@ -143,11 +136,15 @@ typedef Undo::iterator iUndoOp; typedef Undo::reverse_iterator riUndoOp; class UndoList : public std::list<Undo> { + protected: + bool isUndo; public: void clearDelete(); + UndoList(bool _isUndo) : std::list<Undo>() { isUndo=_isUndo; } }; typedef UndoList::iterator iUndo; +typedef UndoList::reverse_iterator riUndo; } // namespace MusECore diff --git a/muse2/muse/wave.cpp b/muse2/muse/wave.cpp index 536320d5..5e19648d 100644 --- a/muse2/muse/wave.cpp +++ b/muse2/muse/wave.cpp @@ -611,14 +611,14 @@ SndFile* SndFileList::search(const QString& name) if ((*i)->path() == name) return *i; } - return 0; + return NULL; } //--------------------------------------------------------- -// getSnd +// getWave //--------------------------------------------------------- -SndFile* getWave(const QString& inName, bool readOnlyFlag) +SndFileR getWave(const QString& inName, bool readOnlyFlag) { QString name = inName; @@ -639,7 +639,7 @@ SndFile* getWave(const QString& inName, bool readOnlyFlag) if (!QFile::exists(name)) { fprintf(stderr, "wave file <%s> not found\n", name.toLatin1().constData()); - return 0; + return NULL; } f = new SndFile(name); bool error; @@ -878,7 +878,7 @@ void ClipBase::write(int level, Xml& xml) const ClipBase* readClip(Xml& xml) { - SndFile* f = 0; + SndFileR f = 0; QString name; unsigned spos = 0; int len = 0; @@ -969,8 +969,8 @@ void Song::cmdAddRecordedWave(MusECore::WaveTrack* track, MusECore::Pos s, MusEC if (MusEGlobal::debugMsg) printf("cmdAddRecordedWave - loopCount = %d, punchin = %d", MusEGlobal::audio->loopCount(), punchin()); - MusECore::SndFile* f = track->recFile(); - if (f == 0) { + MusECore::SndFileR f = track->recFile(); + if (f.isNull()) { printf("cmdAddRecordedWave: no snd file for track <%s>\n", track->name().toLatin1().constData()); return; @@ -987,9 +987,9 @@ void Song::cmdAddRecordedWave(MusECore::WaveTrack* track, MusECore::Pos s, MusEC if(s.tick() >= e.tick()) { QString st = f->path(); - delete f; // The function which calls this function already does this immediately after. But do it here anyway. - track->setRecFile(0); + track->setRecFile(NULL); // upon "return", f is removed from the stack, the WaveTrack::_recFile's + // counter has dropped by 2 and _recFile will probably deleted then remove(st.toLatin1().constData()); if(MusEGlobal::debugMsg) printf("Song::cmdAddRecordedWave: remove file %s - start=%d end=%d\n", st.toLatin1().constData(), s.tick(), e.tick()); @@ -1009,8 +1009,7 @@ void Song::cmdAddRecordedWave(MusECore::WaveTrack* track, MusECore::Pos s, MusEC // create Event MusECore::Event event(MusECore::Wave); - MusECore::SndFileR sf(f); - event.setSndFile(sf); + event.setSndFile(f); // We are done with the _recFile member. Set to zero. The function which // calls this function already does this immediately after. But do it here anyway. track->setRecFile(0); @@ -1067,17 +1066,22 @@ SndFileR::SndFileR(const SndFileR& ed) // operator= //--------------------------------------------------------- -SndFileR& SndFileR::operator=(const SndFileR& ed) - { - if (sf == ed.sf) +SndFileR& SndFileR::operator=(SndFile* ptr) +{ + if (sf == ptr) return *this; if (sf && --(sf->refCount) == 0) { delete sf; } - sf = ed.sf; + sf = ptr; if (sf) (sf->refCount)++; return *this; +} + +SndFileR& SndFileR::operator=(const SndFileR& ed) + { + return operator=(ed.sf); } //--------------------------------------------------------- @@ -1086,20 +1090,9 @@ SndFileR& SndFileR::operator=(const SndFileR& ed) SndFileR::~SndFileR() { - if (sf) - if (--(sf->refCount) == 0) { - delete sf; - sf=NULL; - } + *this=NULL; // decrease the refcounter, maybe delete } -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(); -} } // namespace MusECore @@ -1136,14 +1129,14 @@ bool MusE::importWaveToTrack(QString& name, unsigned tick, MusECore::Track* trac if (track==NULL) track = (MusECore::WaveTrack*)(_arranger->curTrack()); - MusECore::SndFile* f = MusECore::getWave(name, true); + MusECore::SndFileR f = MusECore::getWave(name, true); - if (f == 0) { + if (f.isNull()) { printf("import audio file failed\n"); return true; } int samples = f->samples(); - if ((unsigned)MusEGlobal::sampleRate !=f->samplerate()) { + if ((unsigned)MusEGlobal::sampleRate != f->samplerate()) { if(QMessageBox::question(this, tr("Import Wavefile"), tr("This wave file has a samplerate of %1,\n" "as opposed to current setting %2.\n" @@ -1151,9 +1144,7 @@ bool MusE::importWaveToTrack(QString& name, unsigned tick, MusECore::Track* trac tr("&Yes"), tr("&No"), QString::null, 0, 1 )) { - if (f->getRefCount() == 0) - delete f; - return true; + return true; // this removed f from the stack, dropping refcount maybe to zero and maybe deleting the thing } } track->setChannels(f->channels()); diff --git a/muse2/muse/wave.h b/muse2/muse/wave.h index 133c0dfd..c9c7061d 100644 --- a/muse2/muse/wave.h +++ b/muse2/muse/wave.h @@ -124,9 +124,13 @@ class SndFileR { SndFileR() { sf = 0; } SndFileR(SndFile* _sf); SndFileR(const SndFileR& ed); + SndFileR& operator=(SndFile* ptr); SndFileR& operator=(const SndFileR& ed); bool operator==(const SndFileR& c) const { return sf == c.sf; } bool operator==(SndFile* c) const { return sf == c; } + SndFile* operator->() { return sf; } + const SndFile* operator->() const { return sf; } + operator bool() { return sf!=NULL; } ~SndFileR(); int getRefCount() const { return sf->refCount; } bool isNull() const { return sf == 0; } @@ -181,7 +185,8 @@ class SndFileR { class SndFileList : public std::list<SndFile*> { public: SndFile* search(const QString& name); - void clearDelete(); + // void clearDelete(); // clearDelete MUST NOT exist! deleting is handled by the refcounting SndFileRs! + // this SndFileList is just for information, consider it as "weak pointers" }; typedef SndFileList::iterator iSndFile; @@ -278,7 +283,7 @@ typedef ClipList::const_iterator ciClip; extern ClipBase* readClip(Xml& xml); #endif -extern SndFile* getWave(const QString& name, bool readOnlyFlag); +extern SndFileR getWave(const QString& name, bool readOnlyFlag); } // namespace MusECore diff --git a/muse2/muse/waveedit/waveedit.cpp b/muse2/muse/waveedit/waveedit.cpp index 6cad9871..dd7c4524 100644 --- a/muse2/muse/waveedit/waveedit.cpp +++ b/muse2/muse/waveedit/waveedit.cpp @@ -281,7 +281,7 @@ WaveEdit::WaveEdit(MusECore::PartList* pl) } initTopwinState(); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); } void WaveEdit::initShortcuts() @@ -532,4 +532,17 @@ void WaveEdit::horizontalZoomOut() } +//--------------------------------------------------------- +// focusCanvas +//--------------------------------------------------------- + +void WaveEdit::focusCanvas() +{ + if(MusEGlobal::config.smartFocus) + { + view->setFocus(); + view->activateWindow(); + } +} + } // namespace MusEGui diff --git a/muse2/muse/waveedit/waveedit.h b/muse2/muse/waveedit/waveedit.h index d0ec7a26..b2617f49 100644 --- a/muse2/muse/waveedit/waveedit.h +++ b/muse2/muse/waveedit/waveedit.h @@ -86,11 +86,10 @@ class WaveEdit : public MidiEditor { public slots: void configChanged(); - virtual void updateHScrollRange(); void horizontalZoomIn(); void horizontalZoomOut(); - + void focusCanvas(); signals: void isDeleting(MusEGui::TopWin*); diff --git a/muse2/muse/waveedit/waveview.cpp b/muse2/muse/waveedit/waveview.cpp index 04751428..c585ba4b 100644 --- a/muse2/muse/waveedit/waveview.cpp +++ b/muse2/muse/waveedit/waveview.cpp @@ -21,7 +21,7 @@ //========================================================= #include <stdio.h> -#include <values.h> +#include <limits.h> #include <sys/wait.h> #include <QPainter> @@ -221,8 +221,6 @@ void WaveView::draw(QPainter& p, const QRect& r) if (pos[2] >= x && pos[2] < x2) p.drawLine(pos[2], y, pos[2], y2); - // Changed by T356. Support multiple (or none) selected parts. - //int n = curPart->track()->channels(); int n = 1; if(curPart) n = curPart->track()->channels(); @@ -245,9 +243,6 @@ void WaveView::draw(QPainter& p, const QRect& r) QString WaveView::getCaption() const { - - // Changed by T356. Support multiple (or none) selected parts. - //return QString("Part ") + curPart->name(); if(curPart) return QString("Part ") + curPart->name(); else @@ -265,8 +260,10 @@ void WaveView::songChanged(int flags) if(flags == SC_MIDI_CONTROLLER) return; - if (flags & SC_SELECTION) { - startSample = MAXINT; + if (flags & ~SC_SELECTION) { + // TODO FIXME: don't we actually only want SC_PART_*, and maybe SC_TRACK_DELETED? + // (same in ecanvas.cpp) + startSample = INT_MAX; endSample = 0; curPart = 0; for (MusECore::iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p) { diff --git a/muse2/muse/waveevent.cpp b/muse2/muse/waveevent.cpp index 2cbf7cad..ac984a02 100644 --- a/muse2/muse/waveevent.cpp +++ b/muse2/muse/waveevent.cpp @@ -110,10 +110,8 @@ void WaveEventBase::read(Xml& xml) else if (tag == "frame") _spos = xml.parseInt(); else if (tag == "file") { - SndFile* wf = getWave(xml.parse1(), true); - if (wf) { - f = SndFileR(wf); - } + SndFileR wf = getWave(xml.parse1(), true); + if (wf) f = wf; } else xml.unknown("Event"); diff --git a/muse2/muse/wavetrack.cpp b/muse2/muse/wavetrack.cpp index cc788d2d..dd890b42 100644 --- a/muse2/muse/wavetrack.cpp +++ b/muse2/muse/wavetrack.cpp @@ -315,7 +315,7 @@ bool WaveTrack::getData(unsigned framePos, int channels, unsigned nframe, float* void WaveTrack::setChannels(int n) { AudioTrack::setChannels(n); - SndFile* sf = recFile(); + SndFileR sf = recFile(); if (sf) { if (sf->samples() == 0) { sf->remove(); diff --git a/muse2/muse/widgets/appearancebase.ui b/muse2/muse/widgets/appearancebase.ui index a3a80a96..887f3834 100644 --- a/muse2/muse/widgets/appearancebase.ui +++ b/muse2/muse/widgets/appearancebase.ui @@ -1149,6 +1149,13 @@ </widget> </item> <item> + <widget class="QLabel" name="theme_label"> + <property name="text"> + <string>May require restarting MusE for best results</string> + </property> + </widget> + </item> + <item> <spacer name="Spacer2"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -1158,7 +1165,7 @@ </property> <property name="sizeHint" stdset="0"> <size> - <width>190</width> + <width>90</width> <height>20</height> </size> </property> diff --git a/muse2/muse/widgets/arrangercolumnsbase.ui b/muse2/muse/widgets/arrangercolumnsbase.ui index bfa07e49..eda9e923 100644 --- a/muse2/muse/widgets/arrangercolumnsbase.ui +++ b/muse2/muse/widgets/arrangercolumnsbase.ui @@ -175,18 +175,10 @@ </sizepolicy> </property> <property name="toolTip"> - <string>Midi controller number low byte (* means drum controller)</string> + <string>Midi controller number low byte</string> </property> <property name="whatsThis"> - <string>Midi controller number low byte. -If low byte is * then the controller is a - 'drum controller'. For drum tracks and - GS/XG type songs and instruments. -Allows controllers for each instrument in - Muse's drum map. The low byte will be - replaced by the 'ANote' in the drum map. -Examples: The GS and XG instruments' - Drum controllers.</string> + <string>Midi controller number low byte</string> </property> <property name="specialValueText"> <string comment="wild card">*</string> diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp index 9a1935a3..a4617d53 100644 --- a/muse2/muse/widgets/canvas.cpp +++ b/muse2/muse/widgets/canvas.cpp @@ -635,6 +635,9 @@ void Canvas::viewKeyPressEvent(QKeyEvent* event) void Canvas::viewMousePressEvent(QMouseEvent* event) { + if (!mousePress(event)) + return; + ///keyState = event->state(); keyState = ((QInputEvent*)event)->modifiers(); button = event->button(); @@ -803,7 +806,6 @@ void Canvas::viewMousePressEvent(QMouseEvent* event) break; } } - mousePress(event); } void Canvas::scrollTimerDone() diff --git a/muse2/muse/widgets/canvas.h b/muse2/muse/widgets/canvas.h index 2ab4820c..fe26c25a 100644 --- a/muse2/muse/widgets/canvas.h +++ b/muse2/muse/widgets/canvas.h @@ -105,7 +105,7 @@ class Canvas : public View { virtual void draw(QPainter&, const QRect&); virtual void wheelEvent(QWheelEvent* e); - virtual void mousePress(QMouseEvent*) {} + virtual bool mousePress(QMouseEvent*) { return true; } virtual void keyPress(QKeyEvent*); virtual void mouseMove(QMouseEvent* event) = 0; virtual void mouseRelease(const QPoint&) {} diff --git a/muse2/muse/widgets/cliplisteditorbase.ui b/muse2/muse/widgets/cliplisteditorbase.ui index c07e722f..e619e2a9 100644 --- a/muse2/muse/widgets/cliplisteditorbase.ui +++ b/muse2/muse/widgets/cliplisteditorbase.ui @@ -55,7 +55,7 @@ </column> <column> <property name="text"> - <string>Start</string> + <string>Samplerate</string> </property> <property name="clickable"> <bool>true</bool> diff --git a/muse2/muse/widgets/dentry.cpp b/muse2/muse/widgets/dentry.cpp index ddaa5ffd..d2aadca8 100644 --- a/muse2/muse/widgets/dentry.cpp +++ b/muse2/muse/widgets/dentry.cpp @@ -235,6 +235,8 @@ void Dentry::mouseDoubleClickEvent(QMouseEvent* event) QLineEdit::setFrame(true); update(); emit doubleClicked(_id); + if(event->modifiers() & Qt::ControlModifier) + emit ctrlDoubleClicked(_id); } //--------------------------------------------------------- diff --git a/muse2/muse/widgets/dentry.h b/muse2/muse/widgets/dentry.h index 7ad62866..9ab61960 100644 --- a/muse2/muse/widgets/dentry.h +++ b/muse2/muse/widgets/dentry.h @@ -73,6 +73,7 @@ class Dentry : public QLineEdit { signals: void valueChanged(double, int); void doubleClicked(int); + void ctrlDoubleClicked(int); public slots: virtual void setValue(double); diff --git a/muse2/muse/widgets/didyouknow.h b/muse2/muse/widgets/didyouknow.h index b117b121..7f12dbda 100644 --- a/muse2/muse/widgets/didyouknow.h +++ b/muse2/muse/widgets/didyouknow.h @@ -34,8 +34,35 @@ class DidYouKnowWidget : public QDialog, public Ui::DidYouKnow { Q_OBJECT + int currTip; public: - DidYouKnowWidget(QDialog *parent = 0) : QDialog(parent) { setupUi(this); } + QStringList tipList; + + DidYouKnowWidget(QDialog *parent = 0) : QDialog(parent) + { + setupUi(this); + tipText->setBackgroundRole(QPalette::Text); + tipText->setForegroundRole(QPalette::Foreground); + tipText->setOpenExternalLinks(true); + currTip=0; + connect(nextButton,SIGNAL(clicked()),SLOT(nextTip())); + } + + public slots: + void nextTip() + { + if (currTip > tipList.size()-1){ + currTip=0; + } + tipText->setText(tipList[currTip]); + currTip++; + } + void show() + { + nextTip(); + QDialog::show(); + } + }; } // namespace MusEGui diff --git a/muse2/muse/widgets/didyouknow.ui b/muse2/muse/widgets/didyouknow.ui index 5051ad3c..3e7292ff 100644 --- a/muse2/muse/widgets/didyouknow.ui +++ b/muse2/muse/widgets/didyouknow.ui @@ -6,63 +6,480 @@ <rect> <x>0</x> <y>0</y> - <width>494</width> - <height>249</height> + <width>386</width> + <height>194</height> </rect> </property> <property name="windowTitle"> <string>Did you know?</string> </property> - <layout class="QVBoxLayout"> - <item> - <layout class="QVBoxLayout"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="tipText"> + <property name="palette"> + <palette> + <active> + <colorrole role="WindowText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>127</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>170</red> + <green>170</green> + <blue>170</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ToolTipBase"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="ToolTipText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="WindowText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>127</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>170</red> + <green>170</green> + <blue>170</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ToolTipBase"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="ToolTipText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="WindowText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>127</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Button"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Light"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Midlight"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Dark"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>127</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Mid"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>170</red> + <green>170</green> + <blue>170</blue> + </color> + </brush> + </colorrole> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>127</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="BrightText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ButtonText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>127</red> + <green>127</green> + <blue>127</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Window"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="Shadow"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="AlternateBase"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>255</blue> + </color> + </brush> + </colorrole> + <colorrole role="ToolTipBase"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>255</red> + <green>255</green> + <blue>220</blue> + </color> + </brush> + </colorrole> + <colorrole role="ToolTipText"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="frameShape"> + <enum>QFrame::Panel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="1" column="0"> + <layout class="QHBoxLayout"> + <item> + <widget class="QCheckBox" name="dontShowCheckBox"> + <property name="text"> + <string>Don't show on startup</string> + </property> + </widget> + </item> + <item> + <spacer name="spacer7"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>121</width> + <height>31</height> + </size> + </property> + </spacer> + </item> <item> - <widget class="QTextEdit" name="tipText"> - <property name="readOnly"> - <bool>true</bool> + <widget class="QPushButton" name="nextButton"> + <property name="text"> + <string>Next tip</string> </property> </widget> </item> <item> - <layout class="QHBoxLayout"> - <item> - <widget class="QCheckBox" name="dontShowCheckBox"> - <property name="text"> - <string>Don't show on startup</string> - </property> - </widget> - </item> - <item> - <spacer name="spacer7"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>121</width> - <height>31</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="nextButton"> - <property name="text"> - <string>Next tip</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="closeButton"> - <property name="text"> - <string>Close</string> - </property> - </widget> - </item> - </layout> + <widget class="QPushButton" name="closeButton"> + <property name="text"> + <string>Close</string> + </property> + </widget> </item> </layout> </item> diff --git a/muse2/muse/widgets/doublelabel.h b/muse2/muse/widgets/doublelabel.h index bfec39c1..d8f38ec8 100644 --- a/muse2/muse/widgets/doublelabel.h +++ b/muse2/muse/widgets/doublelabel.h @@ -36,6 +36,7 @@ class DoubleLabel : public Dentry { Q_PROPERTY( double minValue READ minValue WRITE setMinValue ) Q_PROPERTY( double maxValue READ maxValue WRITE setMaxValue ) + Q_PROPERTY( double offValue READ off WRITE setOff ) Q_PROPERTY( QString specialText READ specialText WRITE setSpecialText ) Q_PROPERTY( QString suffix READ suffix WRITE setSuffix ) Q_PROPERTY( int precision READ precision WRITE setPrecision ) diff --git a/muse2/muse/widgets/doublespinbox.cpp b/muse2/muse/widgets/doublespinbox.cpp index 71ca4149..65c3a412 100644 --- a/muse2/muse/widgets/doublespinbox.cpp +++ b/muse2/muse/widgets/doublespinbox.cpp @@ -26,22 +26,22 @@ namespace MusEGui { -//void DoubleSpinBoxLineEdit::mouseDoubleClickEvent(QMouseEvent* e) -//{ -// QLineEdit::mouseDoubleClickEvent(e); -// emit doubleClicked(); -// if((e->buttons() & Qt::LeftButton) && (e->modifiers() & Qt::ControlModifier)) -// emit ctrlDoubleClicked(); -//} - -void DoubleSpinBoxLineEdit::mousePressEvent(QMouseEvent* e) +void DoubleSpinBoxLineEdit::mouseDoubleClickEvent(QMouseEvent* e) { - QLineEdit::mousePressEvent(e); - //selectAll(); + QLineEdit::mouseDoubleClickEvent(e); + emit doubleClicked(); if((e->buttons() & Qt::LeftButton) && (e->modifiers() & Qt::ControlModifier)) - emit ctrlClicked(); + emit ctrlDoubleClicked(); } +//void DoubleSpinBoxLineEdit::mousePressEvent(QMouseEvent* e) +//{ +// QLineEdit::mousePressEvent(e); + //selectAll(); +// if((e->buttons() & Qt::LeftButton) && (e->modifiers() & Qt::ControlModifier)) +// emit ctrlClicked(); +//} + //--------------------------------------------------------- // DoubleSpinBox //--------------------------------------------------------- @@ -53,9 +53,9 @@ DoubleSpinBox::DoubleSpinBox(QWidget* parent) setLineEdit(le); setKeyboardTracking(false); - //connect(le, SIGNAL(doubleClicked()), this, SIGNAL(doubleClicked())); - //connect(le, SIGNAL(ctrlDoubleClicked()), this, SIGNAL(ctrlDoubleClicked())); - connect(le, SIGNAL(ctrlClicked()), this, SIGNAL(ctrlClicked())); + connect(le, SIGNAL(doubleClicked()), this, SIGNAL(doubleClicked())); + connect(le, SIGNAL(ctrlDoubleClicked()), this, SIGNAL(ctrlDoubleClicked())); + //connect(le, SIGNAL(ctrlClicked()), this, SIGNAL(ctrlClicked())); } DoubleSpinBox::DoubleSpinBox(double minValue, double maxValue, double step, QWidget* parent) @@ -67,9 +67,9 @@ DoubleSpinBox::DoubleSpinBox(double minValue, double maxValue, double step, QWid setSingleStep(step); setKeyboardTracking(false); - //connect(le, SIGNAL(doubleClicked()), this, SIGNAL(doubleClicked())); - //connect(le, SIGNAL(ctrlDoubleClicked()), this, SIGNAL(ctrlDoubleClicked())); - connect(le, SIGNAL(ctrlClicked()), this, SIGNAL(ctrlClicked())); + connect(le, SIGNAL(doubleClicked()), this, SIGNAL(doubleClicked())); + connect(le, SIGNAL(ctrlDoubleClicked()), this, SIGNAL(ctrlDoubleClicked())); + //connect(le, SIGNAL(ctrlClicked()), this, SIGNAL(ctrlClicked())); } void DoubleSpinBox::keyPressEvent(QKeyEvent* ev) diff --git a/muse2/muse/widgets/doublespinbox.h b/muse2/muse/widgets/doublespinbox.h index f3dfcdb0..426b9d00 100644 --- a/muse2/muse/widgets/doublespinbox.h +++ b/muse2/muse/widgets/doublespinbox.h @@ -32,13 +32,13 @@ class DoubleSpinBoxLineEdit : public QLineEdit Q_OBJECT protected: - //virtual void mouseDoubleClickEvent(QMouseEvent* e); - virtual void mousePressEvent(QMouseEvent* e); + virtual void mouseDoubleClickEvent(QMouseEvent* e); + //virtual void mousePressEvent(QMouseEvent* e); signals: - //void doubleClicked(); - //void ctrlDoubleClicked(); - void ctrlClicked(); + void doubleClicked(); + void ctrlDoubleClicked(); + //void ctrlClicked(); public: DoubleSpinBoxLineEdit(QWidget* parent = 0) : QLineEdit(parent) {}; @@ -56,9 +56,9 @@ class DoubleSpinBox : public QDoubleSpinBox { virtual void wheelEvent(QWheelEvent*); signals: - //void doubleClicked(); - //void ctrlDoubleClicked(); - void ctrlClicked(); + void doubleClicked(); + void ctrlDoubleClicked(); + //void ctrlClicked(); void returnPressed(); void escapePressed(); diff --git a/muse2/muse/widgets/filedialog.cpp b/muse2/muse/widgets/filedialog.cpp index b41f807e..6e7d6882 100644 --- a/muse2/muse/widgets/filedialog.cpp +++ b/muse2/muse/widgets/filedialog.cpp @@ -101,12 +101,10 @@ static bool testDirCreate(QWidget* parent, const QString& path) void MFileDialog::globalToggled(bool flag) { if (flag) { - buttons.userButton->setChecked(!flag); - buttons.projectButton->setChecked(!flag); + buttons.readMidiPortsButton->setChecked(false); if (lastGlobalDir.isEmpty()) lastGlobalDir = MusEGlobal::museGlobalShare + QString("/") + baseDir; // Initialize if first time - QString dir = lastGlobalDir; - setDirectory(dir); + setDirectory(lastGlobalDir); lastViewUsed = GLOBAL_VIEW; } } @@ -118,10 +116,7 @@ void MFileDialog::globalToggled(bool flag) void MFileDialog::userToggled(bool flag) { if (flag) { - buttons.globalButton->setChecked(!flag); - buttons.projectButton->setChecked(!flag); - - + buttons.readMidiPortsButton->setChecked(true); if (lastUserDir.isEmpty()) { //lastUserDir = MusEGlobal::museUser + QString("/") + baseDir; // Initialize if first time lastUserDir = MusEGlobal::configPath + QString("/") + baseDir; // Initialize if first time // p4.0.39 @@ -144,9 +139,7 @@ void MFileDialog::userToggled(bool flag) void MFileDialog::projectToggled(bool flag) { if (flag) { - buttons.globalButton->setChecked(!flag); - buttons.userButton->setChecked(!flag); - + buttons.readMidiPortsButton->setChecked(true); QString s; if (MusEGlobal::museProject == MusEGlobal::museProjectInitPath ) { // if project path is uninitialized, meaning it is still set to museProjectInitPath. @@ -204,7 +197,11 @@ MFileDialog::MFileDialog(const QString& dir, buttons.projectButton->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon)); #endif - connect(buttons.globalButton, SIGNAL(toggled(bool)), this, SLOT(globalToggled(bool))); + buttons.globalButton->setAutoExclusive(true); + buttons.userButton->setAutoExclusive(true); + buttons.projectButton->setAutoExclusive(true); + + connect(buttons.globalButton, SIGNAL(toggled(bool)), this, SLOT(globalToggled(bool))); connect(buttons.userButton, SIGNAL(toggled(bool)), this, SLOT(userToggled(bool))); connect(buttons.projectButton, SIGNAL(toggled(bool)), this, SLOT(projectToggled(bool))); connect(this, SIGNAL(directoryEntered(const QString&)), SLOT(directoryChanged(const QString&))); @@ -215,26 +212,26 @@ MFileDialog::MFileDialog(const QString& dir, switch (lastViewUsed) { case GLOBAL_VIEW: case PROJECT_VIEW: - buttons.projectButton->setChecked(true); + buttons.globalButton->setChecked(true); // Let toggled be called. Don't block these... break; case USER_VIEW: - buttons.userButton->setChecked(true); + buttons.userButton->setChecked(true); break; } } else { switch (lastViewUsed) { case GLOBAL_VIEW: - buttons.globalButton->setChecked(true); + buttons.globalButton->setChecked(true); break; case PROJECT_VIEW: - buttons.projectButton->setChecked(true); + buttons.projectButton->setChecked(true); break; case USER_VIEW: - buttons.userButton->setChecked(true); + buttons.userButton->setChecked(true); break; } @@ -281,21 +278,19 @@ QString getOpenFileName(const QString &startWith, const char** filters_chararray { QStringList filters = localizedStringListFromCharArray(filters_chararray, "file_patterns"); - QString initialSelection; // FIXME Tim. MFileDialog *dlg = new MFileDialog(startWith, QString::null, parent, false); dlg->setNameFilters(filters); dlg->setWindowTitle(name); + if (doReadMidiPorts) + dlg->buttons.readMidiPortsGroup->setVisible(true); + // Allow overrides. FIXME - some redundancy in MFileDialog ctor. Make this better. if (viewType == MFileDialog::GLOBAL_VIEW) - dlg->globalToggled(true); + dlg->buttons.globalButton->setChecked(true); // Let toggled be called. Don't block these... else if (viewType == MFileDialog::PROJECT_VIEW) - dlg->projectToggled(true); + dlg->buttons.projectButton->setChecked(true); else if (viewType == MFileDialog::USER_VIEW) - dlg->userToggled(true); - if (doReadMidiPorts) - dlg->buttons.readMidiPortsGroup->setVisible(true); + dlg->buttons.userButton->setChecked(true); - if (!initialSelection.isEmpty()) - dlg->selectFile(initialSelection); dlg->setFileMode(QFileDialog::ExistingFile); QStringList files; QString result; @@ -496,10 +491,10 @@ FILE* fileOpen(QWidget* parent, QString name, const QString& ext, zip += QString(" > \""); //zip += name; zip = zip + name + QString("\""); // p4.0.40 - fp = popen(zip.toAscii().data(), mode); + fp = popen(zip.toLocal8Bit().data(), mode); } else { - fp = fopen(name.toAscii().data(), mode); + fp = fopen(name.toLocal8Bit().data(), mode); } if (fp == 0 && !noError) { QString s(QWidget::tr("Open File\n%1\nfailed: %2").arg(name).arg(strerror(errno))); diff --git a/muse2/muse/widgets/function_dialogs/crescendo.cpp b/muse2/muse/widgets/function_dialogs/crescendo.cpp index fa94f58e..62aedd21 100644 --- a/muse2/muse/widgets/function_dialogs/crescendo.cpp +++ b/muse2/muse/widgets/function_dialogs/crescendo.cpp @@ -26,6 +26,11 @@ namespace MusEGui { +int Crescendo::range = 3; +int Crescendo::start_val = 80; +int Crescendo::end_val = 130; +bool Crescendo::absolute = 0; + Crescendo::Crescendo(QWidget* parent) : QDialog(parent) { @@ -35,8 +40,6 @@ Crescendo::Crescendo(QWidget* parent) range_group->addButton(selected_looped_button,3); connect(absolute_button, SIGNAL(toggled(bool)), SLOT(absolute_changed(bool))); - - pull_values(); } void Crescendo::pull_values() diff --git a/muse2/muse/widgets/function_dialogs/crescendo.h b/muse2/muse/widgets/function_dialogs/crescendo.h index ccd3030e..987ebd34 100644 --- a/muse2/muse/widgets/function_dialogs/crescendo.h +++ b/muse2/muse/widgets/function_dialogs/crescendo.h @@ -47,12 +47,12 @@ class Crescendo : public QDialog, public Ui::CrescendoBase public: Crescendo(QWidget* parent = 0); - int range; - int start_val; - int end_val; - bool absolute; + static int range; + static int start_val; + static int end_val; + static bool absolute; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/function_dialogs/deloverlaps.cpp b/muse2/muse/widgets/function_dialogs/deloverlaps.cpp index b6a0bf3f..16bbe88e 100644 --- a/muse2/muse/widgets/function_dialogs/deloverlaps.cpp +++ b/muse2/muse/widgets/function_dialogs/deloverlaps.cpp @@ -26,6 +26,8 @@ namespace MusEGui { +int DelOverlaps::range = 1; + DelOverlaps::DelOverlaps(QWidget* parent) : QDialog(parent) { @@ -35,8 +37,6 @@ DelOverlaps::DelOverlaps(QWidget* parent) range_group->addButton(selected_events_button,1); range_group->addButton(looped_events_button,2); range_group->addButton(selected_looped_button,3); - - pull_values(); } void DelOverlaps::pull_values() diff --git a/muse2/muse/widgets/function_dialogs/deloverlaps.h b/muse2/muse/widgets/function_dialogs/deloverlaps.h index 0036a2d4..d14b87c7 100644 --- a/muse2/muse/widgets/function_dialogs/deloverlaps.h +++ b/muse2/muse/widgets/function_dialogs/deloverlaps.h @@ -47,9 +47,9 @@ class DelOverlaps : public QDialog, public Ui::DelOverlapsBase public: DelOverlaps(QWidget* parent = 0); - int range; + static int range; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); public slots: diff --git a/muse2/muse/widgets/function_dialogs/gatetime.cpp b/muse2/muse/widgets/function_dialogs/gatetime.cpp index 987e53a5..e66f72a5 100644 --- a/muse2/muse/widgets/function_dialogs/gatetime.cpp +++ b/muse2/muse/widgets/function_dialogs/gatetime.cpp @@ -30,6 +30,10 @@ namespace MusEGui { +int GateTime::range = 1; +int GateTime::rateVal = 100; +int GateTime::offsetVal = 0; + //--------------------------------------------------------- // GateTime //--------------------------------------------------------- @@ -44,8 +48,6 @@ GateTime::GateTime(QWidget* parent) rangeGroup->addButton(loopButton, 2); rangeGroup->addButton(sloopButton, 3); rangeGroup->setExclusive(true); - - pullValues(); } //--------------------------------------------------------- diff --git a/muse2/muse/widgets/function_dialogs/gatetime.h b/muse2/muse/widgets/function_dialogs/gatetime.h index b0c3987b..d0f5d2d7 100644 --- a/muse2/muse/widgets/function_dialogs/gatetime.h +++ b/muse2/muse/widgets/function_dialogs/gatetime.h @@ -50,11 +50,11 @@ class GateTime : public QDialog, public Ui::GateTimeBase { public: GateTime(QWidget* parent=0); - int range; - int rateVal; - int offsetVal; + static int range; + static int rateVal; + static int offsetVal; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/function_dialogs/legato.cpp b/muse2/muse/widgets/function_dialogs/legato.cpp index 0d31017c..395cadc6 100644 --- a/muse2/muse/widgets/function_dialogs/legato.cpp +++ b/muse2/muse/widgets/function_dialogs/legato.cpp @@ -26,6 +26,10 @@ namespace MusEGui { +int Legato::range = 1; +int Legato::min_len = 0; +bool Legato::allow_shortening = 0; + Legato::Legato(QWidget* parent) : QDialog(parent) { @@ -35,8 +39,6 @@ Legato::Legato(QWidget* parent) range_group->addButton(selected_events_button,1); range_group->addButton(looped_events_button,2); range_group->addButton(selected_looped_button,3); - - pull_values(); } void Legato::pull_values() diff --git a/muse2/muse/widgets/function_dialogs/legato.h b/muse2/muse/widgets/function_dialogs/legato.h index 1c25fef1..b5e69ce0 100644 --- a/muse2/muse/widgets/function_dialogs/legato.h +++ b/muse2/muse/widgets/function_dialogs/legato.h @@ -47,11 +47,11 @@ class Legato : public QDialog, public Ui::LegatoBase public: Legato(QWidget* parent = 0); - int range; - int min_len; - bool allow_shortening; + static int range; + static int min_len; + static bool allow_shortening; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/function_dialogs/move.cpp b/muse2/muse/widgets/function_dialogs/move.cpp index e0a1fddf..17d1c1de 100644 --- a/muse2/muse/widgets/function_dialogs/move.cpp +++ b/muse2/muse/widgets/function_dialogs/move.cpp @@ -26,6 +26,9 @@ namespace MusEGui { +int Move::range = 1; +int Move::amount = 0; + Move::Move(QWidget* parent) : QDialog(parent) { @@ -35,8 +38,6 @@ Move::Move(QWidget* parent) range_group->addButton(selected_events_button,1); range_group->addButton(looped_events_button,2); range_group->addButton(selected_looped_button,3); - - pull_values(); } void Move::pull_values() diff --git a/muse2/muse/widgets/function_dialogs/move.h b/muse2/muse/widgets/function_dialogs/move.h index c3c8b83c..ead08728 100644 --- a/muse2/muse/widgets/function_dialogs/move.h +++ b/muse2/muse/widgets/function_dialogs/move.h @@ -47,10 +47,10 @@ class Move : public QDialog, public Ui::MoveBase public: Move(QWidget* parent = 0); - int range; - int amount; + static int range; + static int amount; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/function_dialogs/quantize.cpp b/muse2/muse/widgets/function_dialogs/quantize.cpp index 7233c2b8..a962c355 100644 --- a/muse2/muse/widgets/function_dialogs/quantize.cpp +++ b/muse2/muse/widgets/function_dialogs/quantize.cpp @@ -26,6 +26,14 @@ namespace MusEGui { +int Quantize::range = 1; +int Quantize::strength = 90; +int Quantize::threshold = 0; +int Quantize::raster_index = 3; +int Quantize::swing = 0; +bool Quantize::quant_len = 1; + + int rasterVals[] = { 1, // Whole note divisor 2, // Half note divisor @@ -49,8 +57,6 @@ Quantize::Quantize(QWidget* parent) range_group->addButton(selected_events_button,1); range_group->addButton(looped_events_button,2); range_group->addButton(selected_looped_button,3); - - pull_values(); } void Quantize::pull_values() @@ -58,7 +64,7 @@ void Quantize::pull_values() range = range_group->checkedId(); strength = strength_spinbox->value(); threshold = threshold_spinbox->value(); - raster_index = raster_combobox->currentIndex(); + raster_index = raster_combobox->currentIndex(); quant_len = len_checkbox->isChecked(); swing = swing_spinbox->value(); } @@ -102,7 +108,7 @@ void Quantize::read_configuration(MusECore::Xml& xml) else if (tag == "threshold") threshold=xml.parseInt(); else if (tag == "raster") - raster_index=xml.parseInt(); + raster_index=xml.parseInt(); else if (tag == "swing") swing=xml.parseInt(); else if (tag == "quant_len") diff --git a/muse2/muse/widgets/function_dialogs/quantize.h b/muse2/muse/widgets/function_dialogs/quantize.h index b5229f9e..c5f769cf 100644 --- a/muse2/muse/widgets/function_dialogs/quantize.h +++ b/muse2/muse/widgets/function_dialogs/quantize.h @@ -48,14 +48,14 @@ class Quantize : public QDialog, public Ui::QuantBase public: Quantize(QWidget* parent = 0); - int range; - int strength; - int threshold; - int raster_index; - int swing; - bool quant_len; + static int range; + static int strength; + static int threshold; + static int raster_index; + static int swing; + static bool quant_len; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); public slots: diff --git a/muse2/muse/widgets/function_dialogs/remove.cpp b/muse2/muse/widgets/function_dialogs/remove.cpp index c0b31ec4..496356f5 100644 --- a/muse2/muse/widgets/function_dialogs/remove.cpp +++ b/muse2/muse/widgets/function_dialogs/remove.cpp @@ -26,6 +26,13 @@ namespace MusEGui { +int Remove::range = 1; +int Remove::velo_threshold = 16; +bool Remove::velo_thres_used = 0; +int Remove::len_threshold = 12; +bool Remove::len_thres_used = 0; + + Remove::Remove(QWidget* parent) : QDialog(parent) { @@ -35,8 +42,6 @@ Remove::Remove(QWidget* parent) range_group->addButton(selected_events_button,1); range_group->addButton(looped_events_button,2); range_group->addButton(selected_looped_button,3); - - pull_values(); } void Remove::pull_values() diff --git a/muse2/muse/widgets/function_dialogs/remove.h b/muse2/muse/widgets/function_dialogs/remove.h index a572be62..ddce4b93 100644 --- a/muse2/muse/widgets/function_dialogs/remove.h +++ b/muse2/muse/widgets/function_dialogs/remove.h @@ -47,13 +47,13 @@ class Remove : public QDialog, public Ui::RemoveBase public: Remove(QWidget* parent = 0); - int range; - int velo_threshold; - bool velo_thres_used; - int len_threshold; - bool len_thres_used; + static int range; + static int velo_threshold; + static bool velo_thres_used; + static int len_threshold; + static bool len_thres_used; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/function_dialogs/setlen.cpp b/muse2/muse/widgets/function_dialogs/setlen.cpp index 4154f8e5..3afce35a 100644 --- a/muse2/muse/widgets/function_dialogs/setlen.cpp +++ b/muse2/muse/widgets/function_dialogs/setlen.cpp @@ -26,6 +26,9 @@ namespace MusEGui { +int Setlen::range = 1; +int Setlen::len = 384; + Setlen::Setlen(QWidget* parent) : QDialog(parent) { @@ -35,8 +38,6 @@ Setlen::Setlen(QWidget* parent) range_group->addButton(selected_events_button,1); range_group->addButton(looped_events_button,2); range_group->addButton(selected_looped_button,3); - - pull_values(); } void Setlen::pull_values() diff --git a/muse2/muse/widgets/function_dialogs/setlen.h b/muse2/muse/widgets/function_dialogs/setlen.h index dc577e6b..7a015b3b 100644 --- a/muse2/muse/widgets/function_dialogs/setlen.h +++ b/muse2/muse/widgets/function_dialogs/setlen.h @@ -47,10 +47,10 @@ class Setlen : public QDialog, public Ui::SetlenBase public: Setlen(QWidget* parent = 0); - int range; - int len; + static int range; + static int len; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/function_dialogs/transpose.cpp b/muse2/muse/widgets/function_dialogs/transpose.cpp index c4088d99..d57883f2 100644 --- a/muse2/muse/widgets/function_dialogs/transpose.cpp +++ b/muse2/muse/widgets/function_dialogs/transpose.cpp @@ -26,6 +26,9 @@ namespace MusEGui { +int Transpose::range = 1; +int Transpose::amount = 0; + Transpose::Transpose(QWidget* parent) : QDialog(parent) { @@ -35,8 +38,6 @@ Transpose::Transpose(QWidget* parent) range_group->addButton(selected_events_button,1); range_group->addButton(looped_events_button,2); range_group->addButton(selected_looped_button,3); - - pull_values(); } void Transpose::pull_values() diff --git a/muse2/muse/widgets/function_dialogs/transpose.h b/muse2/muse/widgets/function_dialogs/transpose.h index 5e0bd82f..bed29e1f 100644 --- a/muse2/muse/widgets/function_dialogs/transpose.h +++ b/muse2/muse/widgets/function_dialogs/transpose.h @@ -45,10 +45,10 @@ class Transpose : public QDialog, public Ui::TransposeBase public: Transpose(QWidget* parent = 0); - int range; - int amount; + static int range; + static int amount; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/function_dialogs/velocity.cpp b/muse2/muse/widgets/function_dialogs/velocity.cpp index 2db17b6d..0285f055 100644 --- a/muse2/muse/widgets/function_dialogs/velocity.cpp +++ b/muse2/muse/widgets/function_dialogs/velocity.cpp @@ -26,6 +26,10 @@ namespace MusEGui { +int Velocity::range = 1; +int Velocity::rateVal = 100; +int Velocity::offsetVal = 0; + //--------------------------------------------------------- // Velocity //--------------------------------------------------------- @@ -39,8 +43,6 @@ Velocity::Velocity(QWidget* parent) rangeGroup->addButton(selectedEvents,1); rangeGroup->addButton(loopedEvents,2); rangeGroup->addButton(selectedLooped,3); - - pullValues(); } //--------------------------------------------------------- diff --git a/muse2/muse/widgets/function_dialogs/velocity.h b/muse2/muse/widgets/function_dialogs/velocity.h index e73b8207..d452da49 100644 --- a/muse2/muse/widgets/function_dialogs/velocity.h +++ b/muse2/muse/widgets/function_dialogs/velocity.h @@ -50,11 +50,11 @@ class Velocity : public QDialog, public Ui::VelocityBase { public: Velocity(QWidget* parent = 0); - int range; - int rateVal; - int offsetVal; + static int range; + static int rateVal; + static int offsetVal; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/genset.cpp b/muse2/muse/widgets/genset.cpp index 60127a0a..5d94a41d 100644 --- a/muse2/muse/widgets/genset.cpp +++ b/muse2/muse/widgets/genset.cpp @@ -37,6 +37,7 @@ #include "globals.h" #include "icons.h" #include "helper.h" +#include "filedialog.h" namespace MusEGui { @@ -76,7 +77,11 @@ GlobalSettingsConfig::GlobalSettingsConfig(QWidget* parent) projDirOpenToolButton->setIcon(*openIcon); connect(projDirOpenToolButton, SIGNAL(clicked()), SLOT(browseProjDir())); - + startSongFileOpenToolButton->setIcon(*openIcon); + connect(startSongFileOpenToolButton, SIGNAL(clicked()), SLOT(browseStartSongFile())); + startSongResetToolButton->setIcon(*undoIcon); + connect(startSongResetToolButton, SIGNAL(clicked()), SLOT(startSongReset())); + connect(applyButton, SIGNAL(clicked()), SLOT(apply())); connect(okButton, SIGNAL(clicked()), SLOT(ok())); connect(cancelButton, SIGNAL(clicked()), SLOT(cancel())); @@ -165,7 +170,8 @@ void GlobalSettingsConfig::updateSettings() startSongEntry->setText(MusEGlobal::config.startSong); startSongGroup->button(MusEGlobal::config.startMode)->setChecked(true); - + readMidiConfigFromSongCheckBox->setChecked(MusEGlobal::config.startSongLoadConfig); + recDrumGroup->button(MusEGlobal::config.newDrumRecordCondition)->setChecked(true); showTransport->setChecked(MusEGlobal::config.transportVisible); @@ -268,8 +274,11 @@ void GlobalSettingsConfig::apply() MusEGlobal::config.startSong = startSongEntry->text(); MusEGlobal::config.startMode = startSongGroup->checkedId(); + MusEGlobal::config.startSongLoadConfig = readMidiConfigFromSongCheckBox->isChecked(); + MusEGlobal::config.newDrumRecordCondition = MusECore::newDrumRecordCondition_t(recDrumGroup->checkedId()); + int das = dummyAudioSize->currentIndex(); MusEGlobal::config.dummyAudioBufSize = dummyAudioBufSizes[das]; MusEGlobal::config.dummyAudioSampleRate = dummyAudioRate->value(); @@ -508,5 +517,24 @@ void GlobalSettingsConfig::browseProjDir() projDirEntry->setText(dir); } +void GlobalSettingsConfig::browseStartSongFile() +{ + bool doReadMidiPorts; + QString sstr = startSongGroup->button(1)->isChecked() ? QString("templates") : QString(""); + + QString fn = MusEGui::getOpenFileName(sstr, MusEGlobal::med_file_pattern, this, + tr("MusE: Choose start template or song"), &doReadMidiPorts, MusEGui::MFileDialog::GLOBAL_VIEW); + if (!fn.isEmpty()) { + startSongEntry->setText(fn); + readMidiConfigFromSongCheckBox->setChecked(doReadMidiPorts); + } +} + +void GlobalSettingsConfig::startSongReset() +{ + startSongEntry->setText(MusEGlobal::museGlobalShare + QString("/templates/default.med")); + readMidiConfigFromSongCheckBox->setChecked(false); +} + } // namespace MusEGui diff --git a/muse2/muse/widgets/genset.h b/muse2/muse/widgets/genset.h index 53f5c2c1..e149bbb2 100644 --- a/muse2/muse/widgets/genset.h +++ b/muse2/muse/widgets/genset.h @@ -55,6 +55,8 @@ class GlobalSettingsConfig : public QDialog, public Ui::GlobalSettingsDialogBase void mainCurrent(); void transportCurrent(); void browseProjDir(); + void browseStartSongFile(); + void startSongReset(); void traditionalPreset(); void mdiPreset(); void borlandPreset(); diff --git a/muse2/muse/widgets/gensetbase.ui b/muse2/muse/widgets/gensetbase.ui index 2803c198..f1dc405b 100644 --- a/muse2/muse/widgets/gensetbase.ui +++ b/muse2/muse/widgets/gensetbase.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>556</width> - <height>552</height> + <width>525</width> + <height>549</height> </rect> </property> <property name="windowTitle"> @@ -36,6 +36,9 @@ <string>Project directory</string> </property> <layout class="QHBoxLayout" name="qhboxProjDir"> + <property name="spacing"> + <number>-1</number> + </property> <item> <widget class="QLabel" name="textLabel_ProjDir"> <property name="text"> @@ -450,45 +453,39 @@ <layout class="QGridLayout"> <item row="0" column="0"> <layout class="QGridLayout" name="gridLayout11"> - <item row="1" column="0"> - <spacer name="spacer7_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>51</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="0" colspan="2"> + <item row="3" column="0" colspan="2"> <layout class="QHBoxLayout" name="qhboxStartSong"> <item> - <widget class="QLabel" name="textLabel1_2"> - <property name="text"> - <string>start song:</string> + <widget class="QLineEdit" name="startSongEntry"/> + </item> + <item> + <widget class="QToolButton" name="startSongFileOpenToolButton"> + <property name="toolTip"> + <string>Choose start song or template</string> </property> - <property name="wordWrap"> - <bool>false</bool> + <property name="text"> + <string>...</string> </property> </widget> </item> <item> - <widget class="QLineEdit" name="startSongEntry"/> + <widget class="QToolButton" name="startSongResetToolButton"> + <property name="toolTip"> + <string>Reset to default</string> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> </item> </layout> </item> - <item row="0" column="0"> + <item row="1" column="0" colspan="2"> <widget class="QGroupBox" name="startSongBox"> <property name="title"> <string>Start song</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QHBoxLayout" name="hLayout_1"> <item> <widget class="QRadioButton" name="startLastButton"> <property name="text"> @@ -508,7 +505,7 @@ </sizepolicy> </property> <property name="text"> - <string>start with template: default.med</string> + <string>start with template</string> </property> <property name="checked"> <bool>false</bool> @@ -525,12 +522,12 @@ </layout> </widget> </item> - <item row="0" column="1"> + <item row="0" column="0" colspan="2"> <widget class="QGroupBox" name="startUpBox"> <property name="title"> <string>On Launch</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> + <layout class="QHBoxLayout" name="hLayout_2"> <item> <widget class="QCheckBox" name="showSplash"> <property name="text"> @@ -548,18 +545,26 @@ </layout> </widget> </item> - <item row="1" column="1"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> + <item row="2" column="0"> + <widget class="QLabel" name="textLabel1_2"> + <property name="text"> + <string>Start template or song:</string> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QCheckBox" name="readMidiConfigFromSongCheckBox"> + <property name="toolTip"> + <string>Read MIDI Ports configuration from file, + or else automatically configure</string> </property> - </spacer> + <property name="text"> + <string>Read MIDI Ports configuration</string> + </property> + </widget> </item> </layout> </item> @@ -1473,7 +1478,7 @@ left button behave like the middle button in such areas.</string> <item row="9" column="0"> <widget class="QLabel" name="label5"> <property name="text"> - <string>Smart focus (restart required)</string> + <string>Smart focus</string> </property> <property name="wordWrap"> <bool>false</bool> @@ -1488,9 +1493,6 @@ left button behave like the middle button in such areas.</string> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="text"> - <string/> - </property> <property name="toolTip"> <string>Smart focus</string> </property> @@ -1498,6 +1500,9 @@ left button behave like the middle button in such areas.</string> <string>After editing, controls will return focus to their respective canvas</string> </property> + <property name="text"> + <string/> + </property> </widget> </item> <item row="10" column="0"> @@ -1624,8 +1629,8 @@ left button behave like the middle button in such areas.</string> <rect> <x>0</x> <y>0</y> - <width>486</width> - <height>375</height> + <width>481</width> + <height>386</height> </rect> </property> <layout class="QHBoxLayout" name="horizontalLayout_3"> @@ -1644,6 +1649,22 @@ left button behave like the middle button in such areas.</string> </widget> </item> <item> + <spacer name="spacer7_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>51</height> + </size> + </property> + </spacer> + </item> + <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <spacer name="Spacer1"> diff --git a/muse2/muse/widgets/header.cpp b/muse2/muse/widgets/header.cpp index a8e98ab5..3a9044b6 100644 --- a/muse2/muse/widgets/header.cpp +++ b/muse2/muse/widgets/header.cpp @@ -44,7 +44,7 @@ void Header::readStatus(MusECore::Xml& xml) case MusECore::Xml::End: return; case MusECore::Xml::Text: - setStatus(tag); + restoreState(QByteArray::fromHex(tag.toAscii())); break; case MusECore::Xml::TagStart: xml.unknown("Header"); @@ -58,38 +58,6 @@ void Header::readStatus(MusECore::Xml& xml) } } -void Header::setStatus(QString status) -{ - QStringList l = status.split(QString(" "), QString::SkipEmptyParts); - int index = count() -1; - for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) { - int logialIdx=abs((*it).toInt()); - bool isHidden = ((*it).toInt() < 0); - int section = visualIndex(logialIdx - (isHidden? 1:0)); - moveSection(section, index); - if (isHidden) - hideSection(logialIdx-1); - else - showSection(logialIdx); - --index; - } - - // loop again looking for missing indexes - for (int i =0; i < count(); i++) { - bool foundIt=false; - for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) { - int id=((*it).toInt()); - if ( id == i || i == -1 - id ) - foundIt=true; - } - if (foundIt == false) { - int section = visualIndex(i); - moveSection(section, i); - //printf("Adding missing i %d index %d section %d!\n", i, index, section); - } - } -} - //--------------------------------------------------------- // writeStatus //--------------------------------------------------------- @@ -97,26 +65,10 @@ void Header::setStatus(QString status) void Header::writeStatus(int level, MusECore::Xml& xml) const { xml.nput(level, "<%s> ", MusECore::Xml::xmlString(objectName()).toLatin1().constData()); - xml.nput("%s", getStatus().toLatin1().constData()); + xml.nput("%s", saveState().toHex().constData()); xml.put("</%s>", MusECore::Xml::xmlString(objectName()).toLatin1().constData()); } -QString Header::getStatus() const -{ - QString temp=""; - - int n = count(); - for (int i = n-1; i >= 0; --i) - { - if (isSectionHidden(logicalIndex(i))) - temp+=QString::number(-logicalIndex(i)-1)+" "; // hidden is stored as negative value starting from -1 - else - temp+=QString::number(logicalIndex(i))+" "; - } - - return temp; -} - //--------------------------------------------------------- // Header //--------------------------------------------------------- diff --git a/muse2/muse/widgets/header.h b/muse2/muse/widgets/header.h index 047f4f28..9cb08903 100644 --- a/muse2/muse/widgets/header.h +++ b/muse2/muse/widgets/header.h @@ -43,9 +43,7 @@ class Header : public QHeaderView { public: Header(QWidget* parent=0, const char* name=0); void writeStatus(int level, MusECore::Xml&) const; - QString getStatus() const; void readStatus(MusECore::Xml&); - void setStatus(QString status); void setColumnLabel( const QString & s, int col, int width = -1 ); void setToolTip(int col, const QString &text); void setWhatsThis(int col, const QString &text); diff --git a/muse2/muse/widgets/mtrackinfo.cpp b/muse2/muse/widgets/mtrackinfo.cpp index 06bf10d2..427ac41d 100644 --- a/muse2/muse/widgets/mtrackinfo.cpp +++ b/muse2/muse/widgets/mtrackinfo.cpp @@ -124,8 +124,9 @@ MidiTrackInfo::MidiTrackInfo(QWidget* parent, MusECore::Track* sel_track) : QWid progRecButton->setFocusPolicy(Qt::NoFocus); volRecButton->setFocusPolicy(Qt::NoFocus); panRecButton->setFocusPolicy(Qt::NoFocus); + iPatch->setFocusPolicy(Qt::NoFocus); - iOutput->setFocusPolicy(Qt::StrongFocus); + iOutput->setFocusPolicy(Qt::NoFocus); iOutputChannel->setFocusPolicy(Qt::StrongFocus); iHBank->setFocusPolicy(Qt::StrongFocus); iLBank->setFocusPolicy(Qt::StrongFocus); @@ -205,18 +206,18 @@ MidiTrackInfo::MidiTrackInfo(QWidget* parent, MusECore::Track* sel_track) : QWid connect(iHBank, SIGNAL(valueChanged(int)), SLOT(iProgHBankChanged())); connect(iLBank, SIGNAL(valueChanged(int)), SLOT(iProgLBankChanged())); connect(iProgram, SIGNAL(valueChanged(int)), SLOT(iProgramChanged())); - connect(iHBank, SIGNAL(ctrlClicked()), SLOT(iProgramDoubleClicked())); - connect(iLBank, SIGNAL(ctrlClicked()), SLOT(iProgramDoubleClicked())); - connect(iProgram, SIGNAL(ctrlClicked()), SLOT(iProgramDoubleClicked())); + connect(iHBank, SIGNAL(ctrlDoubleClicked()), SLOT(iProgramDoubleClicked())); + connect(iLBank, SIGNAL(ctrlDoubleClicked()), SLOT(iProgramDoubleClicked())); + connect(iProgram, SIGNAL(ctrlDoubleClicked()), SLOT(iProgramDoubleClicked())); connect(iLautst, SIGNAL(valueChanged(int)), SLOT(iLautstChanged(int))); - connect(iLautst, SIGNAL(ctrlClicked()), SLOT(iLautstDoubleClicked())); + connect(iLautst, SIGNAL(ctrlDoubleClicked()), SLOT(iLautstDoubleClicked())); connect(iTransp, SIGNAL(valueChanged(int)), SLOT(iTranspChanged(int))); connect(iAnschl, SIGNAL(valueChanged(int)), SLOT(iAnschlChanged(int))); connect(iVerz, SIGNAL(valueChanged(int)), SLOT(iVerzChanged(int))); connect(iLen, SIGNAL(valueChanged(int)), SLOT(iLenChanged(int))); connect(iKompr, SIGNAL(valueChanged(int)), SLOT(iKomprChanged(int))); connect(iPan, SIGNAL(valueChanged(int)), SLOT(iPanChanged(int))); - connect(iPan, SIGNAL(ctrlClicked()), SLOT(iPanDoubleClicked())); + connect(iPan, SIGNAL(ctrlDoubleClicked()), SLOT(iPanDoubleClicked())); connect(iOutput, SIGNAL(activated(int)), SLOT(iOutputPortChanged(int))); ///connect(iInput, SIGNAL(textChanged(const QString&)), SLOT(iInputPortChanged(const QString&))); connect(recordButton, SIGNAL(clicked()), SLOT(recordClicked())); diff --git a/muse2/muse/widgets/mtrackinfobase.ui b/muse2/muse/widgets/mtrackinfobase.ui index c9298a5f..93c2f2c9 100644 --- a/muse2/muse/widgets/mtrackinfobase.ui +++ b/muse2/muse/widgets/mtrackinfobase.ui @@ -588,7 +588,7 @@ </sizepolicy> </property> <property name="toolTip"> - <string>Bank Select MSB. Ctrl-click on/off.</string> + <string>Bank Select MSB. Ctrl-double-click on/off.</string> </property> <property name="autoFillBackground"> <bool>false</bool> @@ -641,7 +641,7 @@ </sizepolicy> </property> <property name="toolTip"> - <string>Bank Select LSB. Ctrl-click on/off.</string> + <string>Bank Select LSB. Ctrl-double-click on/off.</string> </property> <property name="autoFillBackground"> <bool>false</bool> @@ -694,7 +694,7 @@ </sizepolicy> </property> <property name="toolTip"> - <string>Program. Ctrl-click on/off.</string> + <string>Program. Ctrl-double-click on/off.</string> </property> <property name="autoFillBackground"> <bool>false</bool> @@ -761,7 +761,7 @@ </sizepolicy> </property> <property name="toolTip"> - <string>Volume. Ctrl-click on/off.</string> + <string>Volume. Ctrl-double-click on/off.</string> </property> <property name="autoFillBackground"> <bool>false</bool> @@ -828,10 +828,10 @@ </sizepolicy> </property> <property name="toolTip"> - <string>Change stereo position. Ctrl-click on/off.</string> + <string>Change stereo position. Ctrl-double-click on/off.</string> </property> <property name="whatsThis"> - <string>Change stereo position. Ctrl-click on/off.</string> + <string>Change stereo position. Ctrl-double-click on/off.</string> </property> <property name="autoFillBackground"> <bool>false</bool> diff --git a/muse2/muse/widgets/mtscale.cpp b/muse2/muse/widgets/mtscale.cpp index a316416d..76822bdd 100644 --- a/muse2/muse/widgets/mtscale.cpp +++ b/muse2/muse/widgets/mtscale.cpp @@ -20,7 +20,7 @@ // //========================================================= -#include <values.h> +#include <limits.h> #include <QMouseEvent> #include <QPainter> @@ -54,7 +54,7 @@ MTScale::MTScale(int* r, QWidget* parent, int xs, bool _mode) pos[1] = MusEGlobal::song->lpos(); pos[2] = MusEGlobal::song->rpos(); } - pos[3] = MAXINT; // do not show + pos[3] = INT_MAX; // do not show button = Qt::NoButton; setMouseTracking(true); connect(MusEGlobal::song, SIGNAL(posChanged(int, unsigned, bool)), SLOT(setPos(int, unsigned, bool))); @@ -87,9 +87,9 @@ void MTScale::songChanged(int type) void MTScale::setPos(int idx, unsigned val, bool) { - if (val == MAXINT) { + if (val == INT_MAX) { if (idx == 3) { - pos[3] = MAXINT; + pos[3] = INT_MAX; redraw(QRect(0, 0, width(), height())); } return; @@ -98,8 +98,8 @@ void MTScale::setPos(int idx, unsigned val, bool) val = MusEGlobal::tempomap.tick2frame(val); if (val == pos[idx]) return; - //unsigned opos = mapx(pos[idx] == MAXINT ? val : pos[idx]); - int opos = mapx(pos[idx] == MAXINT ? val : pos[idx]); + //unsigned opos = mapx(pos[idx] == INT_MAX ? val : pos[idx]); + int opos = mapx(pos[idx] == INT_MAX ? val : pos[idx]); pos[idx] = val; if (!isVisible()) return; @@ -211,7 +211,7 @@ void MTScale::viewMouseMoveEvent(QMouseEvent* event) void MTScale::leaveEvent(QEvent*) { - emit timeChanged(MAXINT); + emit timeChanged(INT_MAX); } //--------------------------------------------------------- @@ -344,7 +344,7 @@ void MTScale::pdraw(QPainter& p, const QRect& r) } } p.setPen(Qt::black); - if (pos[3] != MAXINT) { + if (pos[3] != INT_MAX) { int xp = mapx(pos[3]); if (xp >= x && xp < x+w) p.drawLine(xp, 0, xp, height()); diff --git a/muse2/muse/widgets/mtscale_flo.cpp b/muse2/muse/widgets/mtscale_flo.cpp index 5cf070f6..d0d10e8c 100644 --- a/muse2/muse/widgets/mtscale_flo.cpp +++ b/muse2/muse/widgets/mtscale_flo.cpp @@ -20,7 +20,7 @@ // //========================================================= -#include <values.h> +#include <limits.h> #include <QMouseEvent> #include <QPainter> @@ -76,10 +76,10 @@ void MTScaleFlo::songChanged(int type) void MTScaleFlo::setPos(int idx, unsigned val, bool) { - if ((val == MAXINT) || (val == pos[idx])) + if ((val == INT_MAX) || (val == pos[idx])) return; - int opos = parent->tick_to_x(pos[idx] == MAXINT ? val : pos[idx]) + xoffset - xpos; + int opos = parent->tick_to_x(pos[idx] == INT_MAX ? val : pos[idx]) + xoffset - xpos; pos[idx] = val; diff --git a/muse2/muse/widgets/musewidgetsplug.cpp b/muse2/muse/widgets/musewidgetsplug.cpp index 436970ad..bee05d51 100644 --- a/muse2/muse/widgets/musewidgetsplug.cpp +++ b/muse2/muse/widgets/musewidgetsplug.cpp @@ -171,6 +171,7 @@ MusEGlobal::GlobalConfigValues config = { true, // importMidiNewStyleDrum 1, // startMode QString(""), // start song path + false, // startSongLoadConfig 384, // gui division QRect(0, 0, 400, 300), // GeometryMain; QRect(0, 0, 200, 100), // GeometryTransport; diff --git a/muse2/muse/widgets/pastedialog.cpp b/muse2/muse/widgets/pastedialog.cpp index 5b582f30..0f20df22 100644 --- a/muse2/muse/widgets/pastedialog.cpp +++ b/muse2/muse/widgets/pastedialog.cpp @@ -29,6 +29,12 @@ using MusEGlobal::config; namespace MusEGui { +int PasteDialog::insert_method = 0; +int PasteDialog::number = 1; +int PasteDialog::raster = 384; +bool PasteDialog::all_in_one_track = 0; +bool PasteDialog::clone = 0; + PasteDialog::PasteDialog(QWidget* parent) : QDialog(parent) { @@ -42,8 +48,6 @@ PasteDialog::PasteDialog(QWidget* parent) connect(raster_spinbox, SIGNAL(valueChanged(int)), this, SLOT(raster_changed(int))); connect(n_spinbox, SIGNAL(valueChanged(int)), this, SLOT(number_changed(int))); - - pull_values(); } void PasteDialog::pull_values() diff --git a/muse2/muse/widgets/pastedialog.h b/muse2/muse/widgets/pastedialog.h index af28d3b1..d3381c80 100644 --- a/muse2/muse/widgets/pastedialog.h +++ b/muse2/muse/widgets/pastedialog.h @@ -49,13 +49,13 @@ class PasteDialog : public QDialog, public Ui::PasteDialogBase public: PasteDialog(QWidget* parent = 0); - int insert_method; - int number; - int raster; - bool all_in_one_track; - bool clone; + static int insert_method; + static int number; + static int raster; + static bool all_in_one_track; + static bool clone; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/pasteeventsdialog.cpp b/muse2/muse/widgets/pasteeventsdialog.cpp index 48782e25..4dbbed99 100644 --- a/muse2/muse/widgets/pasteeventsdialog.cpp +++ b/muse2/muse/widgets/pasteeventsdialog.cpp @@ -29,6 +29,13 @@ using MusEGlobal::config; namespace MusEGui { +int PasteEventsDialog::number = 1; +int PasteEventsDialog::raster = 384; +bool PasteEventsDialog::always_new_part = 0; +bool PasteEventsDialog::never_new_part = 0; +unsigned PasteEventsDialog::max_distance = 3072; +bool PasteEventsDialog::into_single_part = 0; + PasteEventsDialog::PasteEventsDialog(QWidget* parent) : QDialog(parent) { @@ -41,8 +48,6 @@ PasteEventsDialog::PasteEventsDialog(QWidget* parent) connect(max_distance_spinbox, SIGNAL(valueChanged(int)), this, SLOT(max_distance_changed(int))); into_single_part_allowed=true; - - pull_values(); } void PasteEventsDialog::pull_values() diff --git a/muse2/muse/widgets/pasteeventsdialog.h b/muse2/muse/widgets/pasteeventsdialog.h index e22a3693..d02c0fef 100644 --- a/muse2/muse/widgets/pasteeventsdialog.h +++ b/muse2/muse/widgets/pasteeventsdialog.h @@ -49,15 +49,15 @@ class PasteEventsDialog : public QDialog, public Ui::PasteEventsDialogBase public: PasteEventsDialog(QWidget* parent = 0); - int number; - int raster; - bool always_new_part; - bool never_new_part; - unsigned max_distance; - bool into_single_part; + static int number; + static int raster; + static bool always_new_part; + static bool never_new_part; + static unsigned max_distance; + static bool into_single_part; bool into_single_part_allowed; - void read_configuration(MusECore::Xml& xml); + static void read_configuration(MusECore::Xml& xml); void write_configuration(int level, MusECore::Xml& xml); diff --git a/muse2/muse/widgets/pixmap_button.cpp b/muse2/muse/widgets/pixmap_button.cpp index 6b706474..3bc8d16c 100644 --- a/muse2/muse/widgets/pixmap_button.cpp +++ b/muse2/muse/widgets/pixmap_button.cpp @@ -147,8 +147,6 @@ void PixmapButton::paintEvent(QPaintEvent* e) void PixmapButton::mousePressEvent(QMouseEvent* e) { - //if(e->button() != Qt::LeftButton) - // return; if(_checkable) _checked = !_checked; update(); @@ -158,17 +156,20 @@ void PixmapButton::mousePressEvent(QMouseEvent* e) emit toggled(_checked); //e->setAccepted(true); // This makes menu not close when mouse is released. May be desireable with many small buttons... - QWidget::mousePressEvent(e); + QWidget::mousePressEvent(e); // Hm, need this so menus can close. } void PixmapButton::mouseReleaseEvent(QMouseEvent* e) { - //if(e->button() != Qt::LeftButton) - // return; emit clicked(_checked); //e->setAccepted(true); // This makes menu not close when mouse is released. May be desireable with many small buttons... - QWidget::mouseReleaseEvent(e); + QWidget::mouseReleaseEvent(e); // Hm, need this so menus can close. +} + +void PixmapButton::contextMenuEvent(QContextMenuEvent * e) +{ + e->accept(); } } // MusEGui
\ No newline at end of file diff --git a/muse2/muse/widgets/pixmap_button.h b/muse2/muse/widgets/pixmap_button.h index 448b17cb..778bbc57 100644 --- a/muse2/muse/widgets/pixmap_button.h +++ b/muse2/muse/widgets/pixmap_button.h @@ -58,6 +58,7 @@ class PixmapButton : public QWidget virtual void paintEvent(QPaintEvent* ); virtual void mousePressEvent(QMouseEvent* ); virtual void mouseReleaseEvent(QMouseEvent* ); + void contextMenuEvent(QContextMenuEvent*); signals: void clicked(bool checked = false); diff --git a/muse2/muse/widgets/sig_tempo_toolbar.cpp b/muse2/muse/widgets/sig_tempo_toolbar.cpp index 4e767cd1..4ccf2092 100644 --- a/muse2/muse/widgets/sig_tempo_toolbar.cpp +++ b/muse2/muse/widgets/sig_tempo_toolbar.cpp @@ -36,6 +36,7 @@ namespace MusEGui { tempo_edit=new MusEGui::TempoEdit(this); tempo_edit->setToolTip(tr("tempo at current position")); + tempo_edit->setFocusPolicy(Qt::StrongFocus); label=new QLabel(tr("Tempo: "),this); @@ -49,7 +50,9 @@ namespace MusEGui connect(MusEGlobal::song, SIGNAL(posChanged(int, unsigned, bool)), this, SLOT(pos_changed(int,unsigned,bool))); connect(tempo_edit, SIGNAL(tempoChanged(double)), MusEGlobal::song, SLOT(setTempo(double))); - + connect(tempo_edit, SIGNAL(returnPressed()), SIGNAL(returnPressed())); + connect(tempo_edit, SIGNAL(escapePressed()), SIGNAL(escapePressed())); + song_changed(-1); } @@ -57,7 +60,7 @@ namespace MusEGui { song_changed(SC_TEMPO); } - + void TempoToolbarWidget::song_changed(int type) { if (type & SC_TEMPO) @@ -77,6 +80,7 @@ namespace MusEGui SigToolbarWidget::SigToolbarWidget(QWidget* p) : QWidget(p) { sig_edit=new Awl::SigEdit(this); + sig_edit->setFocusPolicy(Qt::StrongFocus); sig_edit->setValue(AL::TimeSignature(4, 4)); sig_edit->setToolTip(tr("time signature at current position")); @@ -92,7 +96,9 @@ namespace MusEGui connect(MusEGlobal::song, SIGNAL(posChanged(int, unsigned, bool)), this, SLOT(pos_changed(int,unsigned,bool))); connect(sig_edit, SIGNAL(valueChanged(const AL::TimeSignature&)), MusEGlobal::song, SLOT(setSig(const AL::TimeSignature&))); - + connect(sig_edit, SIGNAL(returnPressed()), SIGNAL(returnPressed())); + connect(sig_edit, SIGNAL(escapePressed()), SIGNAL(escapePressed())); + song_changed(-1); } @@ -117,5 +123,4 @@ namespace MusEGui label->setEnabled(MusEGlobal::song->masterFlag()); } } - } diff --git a/muse2/muse/widgets/sig_tempo_toolbar.h b/muse2/muse/widgets/sig_tempo_toolbar.h index 0519193d..b3fd2088 100644 --- a/muse2/muse/widgets/sig_tempo_toolbar.h +++ b/muse2/muse/widgets/sig_tempo_toolbar.h @@ -45,14 +45,18 @@ namespace MusEGui QHBoxLayout* layout; QLabel* label; Awl::SigEdit* sig_edit; - + public: SigToolbarWidget(QWidget* parent); + signals: + void returnPressed(); + void escapePressed(); + private slots: void pos_changed(int,unsigned,bool); void song_changed(int); - }; + }; class TempoToolbarWidget : public QWidget { @@ -62,14 +66,18 @@ namespace MusEGui QHBoxLayout* layout; QLabel* label; MusEGui::TempoEdit* tempo_edit; - + public: TempoToolbarWidget(QWidget* parent); + signals: + void returnPressed(); + void escapePressed(); + private slots: void pos_changed(int,unsigned,bool); void song_changed(int); - }; + }; } #endif diff --git a/muse2/muse/widgets/sigscale.cpp b/muse2/muse/widgets/sigscale.cpp index e1fdf345..74fc484a 100644 --- a/muse2/muse/widgets/sigscale.cpp +++ b/muse2/muse/widgets/sigscale.cpp @@ -20,7 +20,7 @@ // //========================================================= -#include <values.h> +#include <limits.h> #include <QMouseEvent> #include <QPainter> @@ -120,7 +120,7 @@ void SigScale::viewMouseMoveEvent(QMouseEvent* event) void SigScale::leaveEvent(QEvent*) { -// emit timeChanged(MAXINT); +// emit timeChanged(INT_MAX); } //--------------------------------------------------------- diff --git a/muse2/muse/widgets/songpos_toolbar.cpp b/muse2/muse/widgets/songpos_toolbar.cpp index 4f4f519d..1ffd0242 100644 --- a/muse2/muse/widgets/songpos_toolbar.cpp +++ b/muse2/muse/widgets/songpos_toolbar.cpp @@ -23,6 +23,8 @@ #include "songpos_toolbar.h" #include "song.h" +#include <QPainter> +#include <QPaintEvent> namespace MusEGui { @@ -51,4 +53,17 @@ namespace MusEGui song_changed(0); MTScale::resizeEvent(ev); } + void SongPosToolbarWidget::paintEvent(QPaintEvent* ev) + { + View::paintEvent(ev); + QPainter p; + p.begin(this); + p.setPen(Qt::darkGray); + p.drawRect(0, 0, width()-1, height()-1); + p.setPen(Qt::lightGray); + p.drawRect(1, 1, width()-1, height()-1); + p.end(); + } + + } diff --git a/muse2/muse/widgets/songpos_toolbar.h b/muse2/muse/widgets/songpos_toolbar.h index 2b69e2f2..063b2ffd 100644 --- a/muse2/muse/widgets/songpos_toolbar.h +++ b/muse2/muse/widgets/songpos_toolbar.h @@ -33,7 +33,9 @@ namespace MusEGui private: int _raster; - + protected: + virtual void paintEvent(QPaintEvent* ev); + public: SongPosToolbarWidget(QWidget* parent); diff --git a/muse2/muse/widgets/spinbox.cpp b/muse2/muse/widgets/spinbox.cpp index bb6aaacc..a0f35478 100644 --- a/muse2/muse/widgets/spinbox.cpp +++ b/muse2/muse/widgets/spinbox.cpp @@ -28,22 +28,22 @@ namespace MusEGui { -//void SpinBoxLineEdit::mouseDoubleClickEvent(QMouseEvent* e) -//{ -// QLineEdit::mouseDoubleClickEvent(e); -// emit doubleClicked(); -// if((e->buttons() & Qt::LeftButton) && (e->modifiers() & Qt::ControlModifier)) -// emit ctrlDoubleClicked(); -//} - -void SpinBoxLineEdit::mousePressEvent(QMouseEvent* e) +void SpinBoxLineEdit::mouseDoubleClickEvent(QMouseEvent* e) { - QLineEdit::mousePressEvent(e); - //selectAll(); + QLineEdit::mouseDoubleClickEvent(e); + emit doubleClicked(); if((e->buttons() & Qt::LeftButton) && (e->modifiers() & Qt::ControlModifier)) - emit ctrlClicked(); + emit ctrlDoubleClicked(); } +//void SpinBoxLineEdit::mousePressEvent(QMouseEvent* e) +//{ +// QLineEdit::mousePressEvent(e); + //selectAll(); +// if((e->buttons() & Qt::LeftButton) && (e->modifiers() & Qt::ControlModifier)) +// emit ctrlClicked(); +//} + //--------------------------------------------------------- // SpinBox //--------------------------------------------------------- @@ -56,9 +56,9 @@ SpinBox::SpinBox(QWidget* parent) setLineEdit(le); setKeyboardTracking(false); - //connect(le, SIGNAL(doubleClicked()), this, SIGNAL(doubleClicked())); - //connect(le, SIGNAL(ctrlDoubleClicked()), this, SIGNAL(ctrlDoubleClicked())); - connect(le, SIGNAL(ctrlClicked()), this, SIGNAL(ctrlClicked())); + connect(le, SIGNAL(doubleClicked()), this, SIGNAL(doubleClicked())); + connect(le, SIGNAL(ctrlDoubleClicked()), this, SIGNAL(ctrlDoubleClicked())); + //connect(le, SIGNAL(ctrlClicked()), this, SIGNAL(ctrlClicked())); } SpinBox::SpinBox(int minValue, int maxValue, int step, QWidget* parent) @@ -71,9 +71,9 @@ SpinBox::SpinBox(int minValue, int maxValue, int step, QWidget* parent) setSingleStep(step); setKeyboardTracking(false); - //connect(le, SIGNAL(doubleClicked()), this, SIGNAL(doubleClicked())); - //connect(le, SIGNAL(ctrlDoubleClicked()), this, SIGNAL(ctrlDoubleClicked())); - connect(le, SIGNAL(ctrlClicked()), this, SIGNAL(ctrlClicked())); + connect(le, SIGNAL(doubleClicked()), this, SIGNAL(doubleClicked())); + connect(le, SIGNAL(ctrlDoubleClicked()), this, SIGNAL(ctrlDoubleClicked())); + //connect(le, SIGNAL(ctrlClicked()), this, SIGNAL(ctrlClicked())); } void SpinBox::keyPressEvent(QKeyEvent* ev) diff --git a/muse2/muse/widgets/spinbox.h b/muse2/muse/widgets/spinbox.h index 7b57ec77..1aa6147d 100644 --- a/muse2/muse/widgets/spinbox.h +++ b/muse2/muse/widgets/spinbox.h @@ -49,13 +49,13 @@ class SpinBoxLineEdit : public QLineEdit Q_OBJECT protected: - //virtual void mouseDoubleClickEvent(QMouseEvent* e); - virtual void mousePressEvent(QMouseEvent* e); + virtual void mouseDoubleClickEvent(QMouseEvent* e); + //virtual void mousePressEvent(QMouseEvent* e); signals: - //void doubleClicked(); - //void ctrlDoubleClicked(); - void ctrlClicked(); + void doubleClicked(); + void ctrlDoubleClicked(); + //void ctrlClicked(); public: SpinBoxLineEdit(QWidget* parent = 0) : QLineEdit(parent) {}; @@ -75,9 +75,9 @@ class SpinBox : public QSpinBox { virtual void wheelEvent(QWheelEvent*); signals: - //void doubleClicked(); - //void ctrlDoubleClicked(); - void ctrlClicked(); + void doubleClicked(); + void ctrlDoubleClicked(); + //void ctrlClicked(); void returnPressed(); void escapePressed(); diff --git a/muse2/muse/widgets/tb1.cpp b/muse2/muse/widgets/tb1.cpp index 32643bb0..106de6f6 100644 --- a/muse2/muse/widgets/tb1.cpp +++ b/muse2/muse/widgets/tb1.cpp @@ -21,7 +21,7 @@ //========================================================= #include <stdio.h> -#include <values.h> +#include <limits.h> #include <QHeaderView> #include <QTableWidget> @@ -167,7 +167,7 @@ void Toolbar1::setTime(unsigned val) //printf("NOT visible\n"); return; } - if (val == MAXINT) + if (val == INT_MAX) pos->setEnabled(false); else { pos->setEnabled(true); diff --git a/muse2/muse/widgets/tracks_duplicate_base.ui b/muse2/muse/widgets/tracks_duplicate_base.ui index a8ec5766..601c9f25 100644 --- a/muse2/muse/widgets/tracks_duplicate_base.ui +++ b/muse2/muse/widgets/tracks_duplicate_base.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>269</width> - <height>319</height> + <width>238</width> + <height>261</height> </rect> </property> <property name="windowTitle"> @@ -119,6 +119,9 @@ </item> <item> <widget class="QCheckBox" name="pluginsCheckBox"> + <property name="enabled"> + <bool>false</bool> + </property> <property name="text"> <string>Copy effects rack plugins</string> </property> diff --git a/muse2/muse/widgets/utils.cpp b/muse2/muse/widgets/utils.cpp index 1641b267..e9fbc9e3 100644 --- a/muse2/muse/widgets/utils.cpp +++ b/muse2/muse/widgets/utils.cpp @@ -37,6 +37,8 @@ #include <QPainter> #include <QPointF> +#include "audio.h" +#include "audiodev.h" #include "part.h" #include "utils.h" #include "xml.h" @@ -49,12 +51,22 @@ namespace MusECore { double curTime() { - struct timeval t; - gettimeofday(&t, 0); - //printf("%ld %ld\n", t.tv_sec, t.tv_usec); // Note I observed values coming out of order! Causing some problems. - return (double)((double)t.tv_sec + (t.tv_usec / 1000000.0)); + // No audio device yet? Just get wall clock time. + if(!MusEGlobal::audioDevice) + { + struct timeval t; + gettimeofday(&t, 0); + //printf("%ld %ld\n", t.tv_sec, t.tv_usec); // Note I observed values coming out of order! Causing some problems. + return (double)((double)t.tv_sec + (t.tv_usec / 1000000.0)); + } + + // Ask the driver for the system time. + // May depend on selected clock source. + // With Jack, may be based upon wallclock time, the + // processor cycle counter or the HPET clock etc. + return MusEGlobal::audioDevice->systemTime(); + /* - // Changed by Tim. p4.0.23 struct timespec t; //clock_gettime(CLOCK_MONOTONIC, &t); //clock_gettime(CLOCK_MONOTONIC_RAW, &t); |