summaryrefslogtreecommitdiffstats
path: root/src/gui/editors/parameters
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/editors/parameters')
-rw-r--r--src/gui/editors/parameters/AudioInstrumentParameterPanel.cpp437
-rw-r--r--src/gui/editors/parameters/AudioInstrumentParameterPanel.h107
-rw-r--r--src/gui/editors/parameters/InstrumentParameterBox.cpp265
-rw-r--r--src/gui/editors/parameters/InstrumentParameterBox.h126
-rw-r--r--src/gui/editors/parameters/InstrumentParameterPanel.cpp61
-rw-r--r--src/gui/editors/parameters/InstrumentParameterPanel.h78
-rw-r--r--src/gui/editors/parameters/MIDIInstrumentParameterPanel.cpp1175
-rw-r--r--src/gui/editors/parameters/MIDIInstrumentParameterPanel.h137
-rw-r--r--src/gui/editors/parameters/RosegardenParameterArea.cpp227
-rw-r--r--src/gui/editors/parameters/RosegardenParameterArea.h108
-rw-r--r--src/gui/editors/parameters/RosegardenParameterBox.cpp89
-rw-r--r--src/gui/editors/parameters/RosegardenParameterBox.h92
-rw-r--r--src/gui/editors/parameters/SegmentParameterBox.cpp1214
-rw-r--r--src/gui/editors/parameters/SegmentParameterBox.h174
-rw-r--r--src/gui/editors/parameters/TrackParameterBox.cpp1022
-rw-r--r--src/gui/editors/parameters/TrackParameterBox.h161
16 files changed, 5473 insertions, 0 deletions
diff --git a/src/gui/editors/parameters/AudioInstrumentParameterPanel.cpp b/src/gui/editors/parameters/AudioInstrumentParameterPanel.cpp
new file mode 100644
index 0000000..44a202b
--- /dev/null
+++ b/src/gui/editors/parameters/AudioInstrumentParameterPanel.cpp
@@ -0,0 +1,437 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "AudioInstrumentParameterPanel.h"
+#include <qlayout.h>
+#include <kapplication.h>
+
+#include <klocale.h>
+#include "misc/Debug.h"
+#include "misc/Strings.h"
+#include "base/AudioPluginInstance.h"
+#include "base/Instrument.h"
+#include "base/MidiProgram.h"
+#include "document/RosegardenGUIDoc.h"
+#include "gui/studio/AudioPluginManager.h"
+#include "gui/studio/AudioPlugin.h"
+#include "gui/studio/StudioControl.h"
+#include "gui/widgets/AudioFaderBox.h"
+#include "gui/widgets/AudioVUMeter.h"
+#include "gui/widgets/Fader.h"
+#include "gui/widgets/Rotary.h"
+#include "gui/widgets/AudioRouteMenu.h"
+#include "InstrumentParameterPanel.h"
+#include "sound/MappedCommon.h"
+#include "sound/MappedStudio.h"
+#include <qcolor.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qpalette.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qstring.h>
+#include <qtooltip.h>
+#include <qwidget.h>
+#include <qsignalmapper.h>
+
+
+namespace Rosegarden
+{
+
+void
+AudioInstrumentParameterPanel::slotSelectAudioLevel(float dB)
+{
+ if (m_selectedInstrument == 0)
+ return ;
+
+ if (m_selectedInstrument->getType() == Instrument::Audio ||
+ m_selectedInstrument->getType() == Instrument::SoftSynth) {
+ m_selectedInstrument->setLevel(dB);
+
+ StudioControl::setStudioObjectProperty
+ (MappedObjectId(m_selectedInstrument->getMappedId()),
+ MappedAudioFader::FaderLevel,
+ MappedObjectValue(dB));
+ }
+
+ emit updateAllBoxes();
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+AudioInstrumentParameterPanel::slotSelectAudioRecordLevel(float dB)
+{
+ if (m_selectedInstrument == 0)
+ return ;
+
+ // std::cerr << "AudioInstrumentParameterPanel::slotSelectAudioRecordLevel("
+ // << dB << ")" << std::endl;
+
+ if (m_selectedInstrument->getType() == Instrument::Audio) {
+ m_selectedInstrument->setRecordLevel(dB);
+
+ StudioControl::setStudioObjectProperty
+ (MappedObjectId(m_selectedInstrument->getMappedId()),
+ MappedAudioFader::FaderRecordLevel,
+ MappedObjectValue(dB));
+
+ emit updateAllBoxes();
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+ }
+}
+
+void
+AudioInstrumentParameterPanel::slotPluginSelected(InstrumentId instrumentId,
+ int index, int plugin)
+{
+ if (!m_selectedInstrument ||
+ instrumentId != m_selectedInstrument->getId())
+ return ;
+
+ RG_DEBUG << "AudioInstrumentParameterPanel::slotPluginSelected - "
+ << "instrument = " << instrumentId
+ << ", index = " << index
+ << ", plugin = " << plugin << endl;
+
+ QColor pluginBackgroundColour = Qt::black;
+ bool bypassed = false;
+
+ QPushButton *button = 0;
+ QString noneText;
+
+ // updates synth gui button &c:
+ m_audioFader->slotSetInstrument(&m_doc->getStudio(), m_selectedInstrument);
+
+ if (index == (int)Instrument::SYNTH_PLUGIN_POSITION) {
+ button = m_audioFader->m_synthButton;
+ noneText = i18n("<no synth>");
+ } else {
+ button = m_audioFader->m_plugins[index];
+ noneText = i18n("<no plugin>");
+ }
+
+ if (!button)
+ return ;
+
+ if (plugin == -1) {
+
+ button->setText(noneText);
+ QToolTip::add
+ (button, noneText);
+
+ } else {
+
+ AudioPlugin *pluginClass = m_doc->getPluginManager()->getPlugin(plugin);
+
+ if (pluginClass) {
+ button->setText(pluginClass->getLabel());
+
+ QToolTip::add
+ (button, pluginClass->getLabel());
+
+ pluginBackgroundColour = pluginClass->getColour();
+ }
+ }
+
+ AudioPluginInstance *inst =
+ m_selectedInstrument->getPlugin(index);
+
+ if (inst)
+ bypassed = inst->isBypassed();
+
+ setButtonColour(index, bypassed, pluginBackgroundColour);
+
+ if (index == (int)Instrument::SYNTH_PLUGIN_POSITION) {
+ emit changeInstrumentLabel(instrumentId, button->text());
+ }
+}
+
+void
+AudioInstrumentParameterPanel::slotPluginBypassed(InstrumentId instrumentId,
+ int pluginIndex, bool bp)
+{
+ if (!m_selectedInstrument ||
+ instrumentId != m_selectedInstrument->getId())
+ return ;
+
+ AudioPluginInstance *inst =
+ m_selectedInstrument->getPlugin(pluginIndex);
+
+ QColor backgroundColour = Qt::black; // default background colour
+
+ if (inst && inst->isAssigned()) {
+ AudioPlugin *pluginClass
+ = m_doc->getPluginManager()->getPlugin(
+ m_doc->getPluginManager()->
+ getPositionByIdentifier(inst->getIdentifier().c_str()));
+
+ /// Set the colour on the button
+ //
+ if (pluginClass)
+ backgroundColour = pluginClass->getColour();
+ }
+
+ setButtonColour(pluginIndex, bp, backgroundColour);
+}
+
+void
+AudioInstrumentParameterPanel::setButtonColour(
+ int pluginIndex, bool bypassState, const QColor &colour)
+{
+ RG_DEBUG << "AudioInstrumentParameterPanel::setButtonColour "
+ << "pluginIndex = " << pluginIndex
+ << ", bypassState = " << bypassState
+ << ", rgb = " << colour.name() << endl;
+
+ QPushButton *button = 0;
+
+ if (pluginIndex == Instrument::SYNTH_PLUGIN_POSITION) {
+ button = m_audioFader->m_synthButton;
+ } else {
+ button = m_audioFader->m_plugins[pluginIndex];
+ }
+
+ if (!button)
+ return ;
+
+ // Set the bypass colour on the plugin button
+ if (bypassState) {
+ button->
+ setPaletteForegroundColor(kapp->palette().
+ color(QPalette::Active, QColorGroup::Button));
+
+ button->
+ setPaletteBackgroundColor(kapp->palette().
+ color(QPalette::Active, QColorGroup::ButtonText));
+ } else if (colour == Qt::black) {
+ button->
+ setPaletteForegroundColor(kapp->palette().
+ color(QPalette::Active, QColorGroup::ButtonText));
+
+ button->
+ setPaletteBackgroundColor(kapp->palette().
+ color(QPalette::Active, QColorGroup::Button));
+ } else {
+ button->
+ setPaletteForegroundColor(Qt::white);
+
+ button->
+ setPaletteBackgroundColor(colour);
+ }
+}
+
+AudioInstrumentParameterPanel::AudioInstrumentParameterPanel(RosegardenGUIDoc* doc, QWidget* parent)
+ : InstrumentParameterPanel(doc, parent),
+ m_audioFader(new AudioFaderBox(this))
+{
+ QGridLayout *gridLayout = new QGridLayout(this, 3, 2, 5, 5);
+
+ // Instrument label : first row, all cols
+ gridLayout->addMultiCellWidget(m_instrumentLabel, 0, 0, 0, 1, AlignCenter);
+
+ // fader and connect it
+ gridLayout->addMultiCellWidget(m_audioFader, 1, 1, 0, 1);
+
+ gridLayout->setRowStretch(2, 1);
+
+ connect(m_audioFader, SIGNAL(audioChannelsChanged(int)),
+ this, SLOT(slotAudioChannels(int)));
+
+ connect(m_audioFader->m_signalMapper, SIGNAL(mapped(int)),
+ this, SLOT(slotSelectPlugin(int)));
+
+ connect(m_audioFader->m_fader, SIGNAL(faderChanged(float)),
+ this, SLOT(slotSelectAudioLevel(float)));
+
+ connect(m_audioFader->m_recordFader, SIGNAL(faderChanged(float)),
+ this, SLOT(slotSelectAudioRecordLevel(float)));
+
+ connect(m_audioFader->m_pan, SIGNAL(valueChanged(float)),
+ this, SLOT(slotSetPan(float)));
+
+ connect(m_audioFader->m_audioOutput, SIGNAL(changed()),
+ this, SLOT(slotAudioRoutingChanged()));
+
+ connect(m_audioFader->m_audioInput, SIGNAL(changed()),
+ this, SLOT(slotAudioRoutingChanged()));
+
+ connect(m_audioFader->m_synthButton, SIGNAL(clicked()),
+ this, SLOT(slotSynthButtonClicked()));
+
+ connect(m_audioFader->m_synthGUIButton, SIGNAL(clicked()),
+ this, SLOT(slotSynthGUIButtonClicked()));
+}
+
+void
+AudioInstrumentParameterPanel::slotSynthButtonClicked()
+{
+ slotSelectPlugin(Instrument::SYNTH_PLUGIN_POSITION);
+}
+
+void
+AudioInstrumentParameterPanel::slotSynthGUIButtonClicked()
+{
+ emit showPluginGUI(m_selectedInstrument->getId(),
+ Instrument::SYNTH_PLUGIN_POSITION);
+}
+
+void
+AudioInstrumentParameterPanel::slotSetPan(float pan)
+{
+ RG_DEBUG << "AudioInstrumentParameterPanel::slotSetPan - "
+ << "pan = " << pan << endl;
+
+ StudioControl::setStudioObjectProperty
+ (MappedObjectId(m_selectedInstrument->getMappedId()),
+ MappedAudioFader::Pan,
+ MappedObjectValue(pan));
+
+ m_selectedInstrument->setPan(MidiByte(pan + 100.0));
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+AudioInstrumentParameterPanel::setAudioMeter(float dBleft, float dBright,
+ float recDBleft, float recDBright)
+{
+ // RG_DEBUG << "AudioInstrumentParameterPanel::setAudioMeter: (" << dBleft
+ // << "," << dBright << ")" << endl;
+
+ if (m_selectedInstrument) {
+ // Always set stereo, because we have to reflect what's happening
+ // with the pan setting even on mono tracks
+ m_audioFader->m_vuMeter->setLevel(dBleft, dBright);
+ m_audioFader->m_vuMeter->setRecordLevel(recDBleft, recDBright);
+ }
+}
+
+void
+AudioInstrumentParameterPanel::setupForInstrument(Instrument* instrument)
+{
+ blockSignals(true);
+
+ m_selectedInstrument = instrument;
+
+ m_instrumentLabel->setText(strtoqstr(instrument->getName()));
+
+ m_audioFader->m_recordFader->setFader(instrument->getRecordLevel());
+ m_audioFader->m_fader->setFader(instrument->getLevel());
+
+ m_audioFader->slotSetInstrument(&m_doc->getStudio(), instrument);
+
+ int start = 0;
+
+ if (instrument->getType() == Instrument::SoftSynth)
+ start = -1;
+
+ for (int i = start; i < int(m_audioFader->m_plugins.size()); i++) {
+ int index;
+ QPushButton *button;
+ QString noneText;
+
+ if (i == -1) {
+ index = Instrument::SYNTH_PLUGIN_POSITION;
+ button = m_audioFader->m_synthButton;
+ noneText = i18n("<no synth>");
+ } else {
+ index = i;
+ button = m_audioFader->m_plugins[i];
+ noneText = i18n("<no plugin>");
+ }
+
+ button->show();
+
+ AudioPluginInstance *inst = instrument->getPlugin(index);
+
+ if (inst && inst->isAssigned()) {
+ AudioPlugin *pluginClass
+ = m_doc->getPluginManager()->getPlugin(
+ m_doc->getPluginManager()->
+ getPositionByIdentifier(inst->getIdentifier().c_str()));
+
+ if (pluginClass) {
+ button->setText(pluginClass->getLabel());
+ QToolTip::add
+ (button, pluginClass->getLabel());
+ setButtonColour(index, inst->isBypassed(),
+ pluginClass->getColour());
+ }
+ } else {
+ button->setText(noneText);
+ QToolTip::add
+ (button, noneText);
+ setButtonColour(index, inst ? inst->isBypassed() : false, Qt::black);
+ }
+ }
+
+ // Set the number of channels on the fader widget
+ //
+ m_audioFader->setAudioChannels(instrument->getAudioChannels());
+
+ // Pan - adjusted backwards
+ //
+ m_audioFader->m_pan->setPosition(instrument->getPan() - 100);
+
+ // Tell fader box whether to include e.g. audio input selection
+ //
+ m_audioFader->setIsSynth(instrument->getType() == Instrument::SoftSynth);
+
+ blockSignals(false);
+}
+
+void
+AudioInstrumentParameterPanel::slotAudioChannels(int channels)
+{
+ RG_DEBUG << "AudioInstrumentParameterPanel::slotAudioChannels - "
+ << "channels = " << channels << endl;
+
+ m_selectedInstrument->setAudioChannels(channels);
+
+ StudioControl::setStudioObjectProperty
+ (MappedObjectId(m_selectedInstrument->getMappedId()),
+ MappedAudioFader::Channels,
+ MappedObjectValue(channels));
+
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+
+}
+
+void
+AudioInstrumentParameterPanel::slotAudioRoutingChanged()
+{
+ if (m_selectedInstrument)
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+AudioInstrumentParameterPanel::slotSelectPlugin(int index)
+{
+ if (m_selectedInstrument) {
+ emit selectPlugin(0, m_selectedInstrument->getId(), index);
+ }
+}
+
+}
+#include "AudioInstrumentParameterPanel.moc"
diff --git a/src/gui/editors/parameters/AudioInstrumentParameterPanel.h b/src/gui/editors/parameters/AudioInstrumentParameterPanel.h
new file mode 100644
index 0000000..932e6bc
--- /dev/null
+++ b/src/gui/editors/parameters/AudioInstrumentParameterPanel.h
@@ -0,0 +1,107 @@
+
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef _RG_AUDIOINSTRUMENTPARAMETERPANEL_H_
+#define _RG_AUDIOINSTRUMENTPARAMETERPANEL_H_
+
+#include "base/MidiProgram.h"
+#include "InstrumentParameterPanel.h"
+#include <qpixmap.h>
+#include <qstring.h>
+
+
+class QWidget;
+class QColor;
+
+
+namespace Rosegarden
+{
+
+class RosegardenGUIDoc;
+class Instrument;
+class AudioFaderBox;
+
+
+class AudioInstrumentParameterPanel : public InstrumentParameterPanel
+{
+ Q_OBJECT
+public:
+ AudioInstrumentParameterPanel(RosegardenGUIDoc* doc, QWidget* parent);
+
+ virtual void setupForInstrument(Instrument*);
+
+ // Set the audio meter to a given level for a maximum of
+ // two channels.
+ //
+ void setAudioMeter(float dBleft, float dBright,
+ float recDBleft, float recDBright);
+
+ // Set the button colour
+ //
+ void setButtonColour(int pluginIndex, bool bypassState,
+ const QColor &color);
+
+public slots:
+ // From AudioFaderBox
+ //
+ void slotSelectAudioLevel(float dB);
+ void slotSelectAudioRecordLevel(float dB);
+ void slotAudioChannels(int channels);
+ void slotAudioRoutingChanged();
+ void slotSelectPlugin(int index);
+
+ // From the parameter box clicks
+ void slotSetPan(float pan);
+
+ // From Plugin dialog
+ //
+ void slotPluginSelected(InstrumentId id, int index, int plugin);
+ void slotPluginBypassed(InstrumentId id, int pluginIndex, bool bp);
+
+ void slotSynthButtonClicked();
+ void slotSynthGUIButtonClicked();
+
+signals:
+ void selectPlugin(QWidget *, InstrumentId, int index);
+ void instrumentParametersChanged(InstrumentId);
+ void showPluginGUI(InstrumentId, int index);
+ void changeInstrumentLabel(InstrumentId id, QString label);
+
+protected:
+ //--------------- Data members ---------------------------------
+
+ AudioFaderBox *m_audioFader;
+
+private:
+
+ QPixmap m_monoPixmap;
+ QPixmap m_stereoPixmap;
+
+};
+
+
+}
+
+#endif
diff --git a/src/gui/editors/parameters/InstrumentParameterBox.cpp b/src/gui/editors/parameters/InstrumentParameterBox.cpp
new file mode 100644
index 0000000..8114e0d
--- /dev/null
+++ b/src/gui/editors/parameters/InstrumentParameterBox.cpp
@@ -0,0 +1,265 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "InstrumentParameterBox.h"
+#include <qlayout.h>
+
+#include <klocale.h>
+#include "misc/Debug.h"
+#include "AudioInstrumentParameterPanel.h"
+#include "base/Instrument.h"
+#include "base/MidiProgram.h"
+#include "document/RosegardenGUIDoc.h"
+#include "MIDIInstrumentParameterPanel.h"
+#include "RosegardenParameterArea.h"
+#include "RosegardenParameterBox.h"
+#include <ktabwidget.h>
+#include <qfont.h>
+#include <qframe.h>
+#include <qscrollview.h>
+#include <qstring.h>
+#include <qvbox.h>
+#include <qwidget.h>
+#include <qwidgetstack.h>
+
+
+namespace Rosegarden
+{
+
+InstrumentParameterBox::InstrumentParameterBox(RosegardenGUIDoc *doc,
+ QWidget *parent)
+ : RosegardenParameterBox(i18n("Instrument"),
+ i18n("Instrument Parameters"),
+ parent),
+ m_widgetStack(new QWidgetStack(this)),
+ m_noInstrumentParameters(new QVBox(this)),
+ m_midiInstrumentParameters(new MIDIInstrumentParameterPanel(doc, this)),
+ m_audioInstrumentParameters(new AudioInstrumentParameterPanel(doc, this)),
+ m_selectedInstrument(-1),
+ m_doc(doc),
+ m_lastShowAdditionalControlsArg(false)
+{
+ m_widgetStack->setFont(m_font);
+ m_noInstrumentParameters->setFont(m_font);
+ m_midiInstrumentParameters->setFont(m_font);
+ m_audioInstrumentParameters->setFont(m_font);
+
+ bool contains = false;
+
+ std::vector<InstrumentParameterBox*>::iterator it =
+ instrumentParamBoxes.begin();
+
+ for (; it != instrumentParamBoxes.end(); it++)
+ if ((*it) == this)
+ contains = true;
+
+ if (!contains)
+ instrumentParamBoxes.push_back(this);
+
+ m_widgetStack->addWidget(m_midiInstrumentParameters);
+ m_widgetStack->addWidget(m_audioInstrumentParameters);
+ m_widgetStack->addWidget(m_noInstrumentParameters);
+
+ m_midiInstrumentParameters->adjustSize();
+ m_audioInstrumentParameters->adjustSize();
+ m_noInstrumentParameters->adjustSize();
+
+ connect(m_audioInstrumentParameters, SIGNAL(updateAllBoxes()),
+ this, SLOT(slotUpdateAllBoxes()));
+
+ connect(m_audioInstrumentParameters,
+ SIGNAL(instrumentParametersChanged(InstrumentId)),
+ this,
+ SIGNAL(instrumentParametersChanged(InstrumentId)));
+
+ connect(m_audioInstrumentParameters,
+ SIGNAL(selectPlugin(QWidget *, InstrumentId, int)),
+ this,
+ SIGNAL(selectPlugin(QWidget *, InstrumentId, int)));
+
+ connect(m_audioInstrumentParameters,
+ SIGNAL(showPluginGUI(InstrumentId, int)),
+ this,
+ SIGNAL(showPluginGUI(InstrumentId, int)));
+
+ connect(m_midiInstrumentParameters, SIGNAL(updateAllBoxes()),
+ this, SLOT(slotUpdateAllBoxes()));
+
+ connect(m_midiInstrumentParameters,
+ SIGNAL(changeInstrumentLabel(InstrumentId, QString)),
+ this, SIGNAL(changeInstrumentLabel(InstrumentId, QString)));
+
+ connect(m_audioInstrumentParameters,
+ SIGNAL(changeInstrumentLabel(InstrumentId, QString)),
+ this, SIGNAL(changeInstrumentLabel(InstrumentId, QString)));
+
+ connect(m_midiInstrumentParameters,
+ SIGNAL(instrumentParametersChanged(InstrumentId)),
+ this,
+ SIGNAL(instrumentParametersChanged(InstrumentId)));
+
+ // Layout the groups left to right.
+
+ QBoxLayout* layout = new QVBoxLayout(this);
+ layout->addWidget(m_widgetStack);
+
+}
+
+InstrumentParameterBox::~InstrumentParameterBox()
+{
+ // deregister this parameter box
+ std::vector<InstrumentParameterBox*>::iterator it =
+ instrumentParamBoxes.begin();
+
+ for (; it != instrumentParamBoxes.end(); it++) {
+ if ((*it) == this) {
+ instrumentParamBoxes.erase(it);
+ break;
+ }
+ }
+}
+
+Instrument *
+InstrumentParameterBox::getSelectedInstrument()
+{
+ if (m_selectedInstrument < 0) return 0;
+ if (!m_doc) return 0;
+ return m_doc->getStudio().getInstrumentById(m_selectedInstrument);
+}
+
+QString
+InstrumentParameterBox::getPreviousBox(RosegardenParameterArea::Arrangement arrangement) const
+{
+ return i18n("Track");
+}
+
+void
+InstrumentParameterBox::setAudioMeter(float ch1, float ch2, float ch1r, float ch2r)
+{
+ m_audioInstrumentParameters->setAudioMeter(ch1, ch2, ch1r, ch2r);
+}
+
+void
+InstrumentParameterBox::setDocument(RosegardenGUIDoc* doc)
+{
+ m_doc = doc;
+ m_midiInstrumentParameters->setDocument(m_doc);
+ m_audioInstrumentParameters->setDocument(m_doc);
+}
+
+void
+InstrumentParameterBox::slotPluginSelected(InstrumentId id, int index, int plugin)
+{
+ m_audioInstrumentParameters->slotPluginSelected(id, index, plugin);
+}
+
+void
+InstrumentParameterBox::slotPluginBypassed(InstrumentId id, int index, bool bypassState)
+{
+ m_audioInstrumentParameters->slotPluginBypassed(id, index, bypassState);
+}
+
+void
+InstrumentParameterBox::useInstrument(Instrument *instrument)
+{
+ RG_DEBUG << "useInstrument() - populate Instrument\n";
+
+ if (instrument == 0) {
+ m_widgetStack->raiseWidget(m_noInstrumentParameters);
+ emit instrumentPercussionSetChanged(instrument);
+ return ;
+ }
+
+ // ok
+ if (instrument) {
+ m_selectedInstrument = instrument->getId();
+ } else {
+ m_selectedInstrument = -1;
+ }
+
+ // Hide or Show according to Instrument type
+ //
+ if (instrument->getType() == Instrument::Audio ||
+ instrument->getType() == Instrument::SoftSynth) {
+
+ m_audioInstrumentParameters->setupForInstrument(getSelectedInstrument());
+ m_widgetStack->raiseWidget(m_audioInstrumentParameters);
+
+ } else { // Midi
+
+ m_midiInstrumentParameters->setupForInstrument(getSelectedInstrument());
+ m_midiInstrumentParameters->showAdditionalControls(m_lastShowAdditionalControlsArg);
+ m_widgetStack->raiseWidget(m_midiInstrumentParameters);
+ emit instrumentPercussionSetChanged(instrument);
+
+ }
+
+}
+
+void
+InstrumentParameterBox::slotUpdateAllBoxes()
+{
+ emit instrumentPercussionSetChanged(getSelectedInstrument());
+
+ std::vector<InstrumentParameterBox*>::iterator it =
+ instrumentParamBoxes.begin();
+
+ // To update all open IPBs
+ //
+ for (; it != instrumentParamBoxes.end(); it++) {
+ if ((*it) != this && getSelectedInstrument() &&
+ (*it)->getSelectedInstrument() == getSelectedInstrument())
+ (*it)->useInstrument(getSelectedInstrument());
+ }
+}
+
+void
+InstrumentParameterBox::slotInstrumentParametersChanged(InstrumentId id)
+{
+ std::vector<InstrumentParameterBox*>::iterator it =
+ instrumentParamBoxes.begin();
+
+ blockSignals(true);
+
+ for (; it != instrumentParamBoxes.end(); it++) {
+ if ((*it)->getSelectedInstrument()) {
+ if ((*it)->getSelectedInstrument()->getId() == id) {
+ (*it)->useInstrument((*it)->getSelectedInstrument()); // refresh
+ }
+ }
+ }
+
+ blockSignals(false);
+}
+
+void
+InstrumentParameterBox::showAdditionalControls(bool showThem)
+{
+ m_midiInstrumentParameters->showAdditionalControls(showThem);
+ m_lastShowAdditionalControlsArg = showThem;
+}
+
+}
+#include "InstrumentParameterBox.moc"
diff --git a/src/gui/editors/parameters/InstrumentParameterBox.h b/src/gui/editors/parameters/InstrumentParameterBox.h
new file mode 100644
index 0000000..f406567
--- /dev/null
+++ b/src/gui/editors/parameters/InstrumentParameterBox.h
@@ -0,0 +1,126 @@
+
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef _RG_INSTRUMENTPARAMETERBOX_H_
+#define _RG_INSTRUMENTPARAMETERBOX_H_
+
+#include "base/MidiProgram.h"
+#include "RosegardenParameterArea.h"
+#include "RosegardenParameterBox.h"
+#include <qstring.h>
+#include <vector>
+
+
+class QWidgetStack;
+class QWidget;
+class QFrame;
+
+
+namespace Rosegarden
+{
+
+class RosegardenGUIDoc;
+class MIDIInstrumentParameterPanel;
+class Instrument;
+class AudioInstrumentParameterPanel;
+
+
+/**
+ * Display and allow modification of Instrument parameters
+ */
+class InstrumentParameterBox : public RosegardenParameterBox
+{
+Q_OBJECT
+
+public:
+ InstrumentParameterBox(RosegardenGUIDoc *doc,
+ QWidget *parent = 0);
+ ~InstrumentParameterBox();
+
+ void useInstrument(Instrument *instrument);
+
+ Instrument* getSelectedInstrument();
+
+ void setAudioMeter(float dBleft, float dBright,
+ float recDBleft, float recDBright);
+
+ void setDocument(RosegardenGUIDoc* doc);
+
+ virtual void showAdditionalControls(bool showThem);
+
+ virtual QString getPreviousBox(RosegardenParameterArea::Arrangement) const;
+
+public slots:
+
+ // To update all InstrumentParameterBoxen for an Instrument. Called
+ // from one of the parameter panels when something changes.
+ //
+ void slotUpdateAllBoxes();
+
+ // Update InstrumentParameterBoxes that are showing a given instrument.
+ // Called from the Outside.
+ //
+ void slotInstrumentParametersChanged(InstrumentId id);
+
+ // From Plugin dialog
+ //
+ void slotPluginSelected(InstrumentId id, int index, int plugin);
+ void slotPluginBypassed(InstrumentId id, int pluginIndex, bool bp);
+
+signals:
+
+ void changeInstrumentLabel(InstrumentId id, QString label);
+
+ void selectPlugin(QWidget*, InstrumentId id, int index);
+ void showPluginGUI(InstrumentId id, int index);
+
+ void instrumentParametersChanged(InstrumentId);
+ void instrumentPercussionSetChanged(Instrument *);
+
+protected:
+
+ //--------------- Data members ---------------------------------
+ QWidgetStack *m_widgetStack;
+ QFrame *m_noInstrumentParameters;
+ MIDIInstrumentParameterPanel *m_midiInstrumentParameters;
+ AudioInstrumentParameterPanel *m_audioInstrumentParameters;
+
+ // -1 if no instrument, InstrumentId otherwise
+ int m_selectedInstrument;
+
+ // So we can setModified()
+ //
+ RosegardenGUIDoc *m_doc;
+ bool m_lastShowAdditionalControlsArg;
+};
+
+// Global references
+//
+static std::vector<InstrumentParameterBox*> instrumentParamBoxes;
+
+
+}
+
+#endif
diff --git a/src/gui/editors/parameters/InstrumentParameterPanel.cpp b/src/gui/editors/parameters/InstrumentParameterPanel.cpp
new file mode 100644
index 0000000..9437daf
--- /dev/null
+++ b/src/gui/editors/parameters/InstrumentParameterPanel.cpp
@@ -0,0 +1,61 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "InstrumentParameterPanel.h"
+
+#include "base/Instrument.h"
+#include "document/RosegardenGUIDoc.h"
+#include <ksqueezedtextlabel.h>
+#include <qfontmetrics.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qwidget.h>
+
+
+namespace Rosegarden
+{
+
+InstrumentParameterPanel::InstrumentParameterPanel(RosegardenGUIDoc *doc,
+ QWidget* parent)
+ : QFrame(parent),
+ m_instrumentLabel(new KSqueezedTextLabel(this)),
+ m_selectedInstrument(0),
+ m_doc(doc)
+{
+ QFontMetrics metrics(m_instrumentLabel->fontMetrics());
+ int width25 = metrics.width("1234567890123456789012345");
+
+ m_instrumentLabel->setFixedWidth(width25);
+ m_instrumentLabel->setAlignment(Qt::AlignCenter);
+}
+
+void
+InstrumentParameterPanel::setDocument(RosegardenGUIDoc* doc)
+{
+ m_doc = doc;
+}
+
+}
+#include "InstrumentParameterPanel.moc"
diff --git a/src/gui/editors/parameters/InstrumentParameterPanel.h b/src/gui/editors/parameters/InstrumentParameterPanel.h
new file mode 100644
index 0000000..9a794d0
--- /dev/null
+++ b/src/gui/editors/parameters/InstrumentParameterPanel.h
@@ -0,0 +1,78 @@
+
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef _RG_INSTRUMENTPARAMETERPANEL_H_
+#define _RG_INSTRUMENTPARAMETERPANEL_H_
+
+#include <qframe.h>
+#include <vector>
+#include <utility>
+
+class QWidget;
+class QLabel;
+
+
+namespace Rosegarden
+{
+
+class RosegardenGUIDoc;
+class Instrument;
+class Rotary;
+
+typedef std::pair<Rotary *, QLabel *> RotaryPair;
+typedef std::vector<std::pair<int, RotaryPair> > RotaryMap;
+
+
+////////////////////////////////////////////////////////////////////////
+
+class InstrumentParameterPanel : public QFrame
+{
+ Q_OBJECT
+public:
+ InstrumentParameterPanel(RosegardenGUIDoc *doc, QWidget* parent);
+
+ virtual ~InstrumentParameterPanel() {};
+
+ virtual void setupForInstrument(Instrument*) = 0;
+
+ void setDocument(RosegardenGUIDoc* doc);
+
+ void showAdditionalControls(bool showThem);
+
+signals:
+ void updateAllBoxes();
+
+protected:
+ //--------------- Data members ---------------------------------
+ QLabel *m_instrumentLabel;
+ Instrument *m_selectedInstrument;
+ RosegardenGUIDoc *m_doc;
+};
+
+
+
+}
+
+#endif
diff --git a/src/gui/editors/parameters/MIDIInstrumentParameterPanel.cpp b/src/gui/editors/parameters/MIDIInstrumentParameterPanel.cpp
new file mode 100644
index 0000000..fcd4247
--- /dev/null
+++ b/src/gui/editors/parameters/MIDIInstrumentParameterPanel.cpp
@@ -0,0 +1,1175 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "MIDIInstrumentParameterPanel.h"
+#include <qlayout.h>
+
+#include "sound/Midi.h"
+#include <klocale.h>
+#include "misc/Debug.h"
+#include "misc/Strings.h"
+#include "base/Colour.h"
+#include "base/Composition.h"
+#include "base/ControlParameter.h"
+#include "base/Instrument.h"
+#include "base/MidiDevice.h"
+#include "base/MidiProgram.h"
+#include "document/RosegardenGUIDoc.h"
+#include "gui/studio/StudioControl.h"
+#include "gui/widgets/Rotary.h"
+#include "InstrumentParameterPanel.h"
+#include "sound/MappedEvent.h"
+#include "sound/MappedInstrument.h"
+#include <kcombobox.h>
+#include <ksqueezedtextlabel.h>
+#include <qcheckbox.h>
+#include <qcolor.h>
+#include <qfontmetrics.h>
+#include <qframe.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qregexp.h>
+#include <qsignalmapper.h>
+#include <qstring.h>
+#include <qwidget.h>
+#include <algorithm>
+
+
+namespace Rosegarden
+{
+
+MIDIInstrumentParameterPanel::MIDIInstrumentParameterPanel(RosegardenGUIDoc *doc, QWidget* parent):
+ InstrumentParameterPanel(doc, parent),
+ m_rotaryFrame(0),
+ m_rotaryMapper(new QSignalMapper(this))
+{
+ m_mainGrid = new QGridLayout(this, 10, 3, 2, 1);
+
+ m_connectionLabel = new KSqueezedTextLabel(this);
+ m_bankValue = new KComboBox(this);
+ m_channelValue = new KComboBox(this);
+ m_programValue = new KComboBox(this);
+ m_variationValue = new KComboBox(this);
+ m_bankCheckBox = new QCheckBox(this);
+ m_programCheckBox = new QCheckBox(this);
+ m_variationCheckBox = new QCheckBox(this);
+ m_percussionCheckBox = new QCheckBox(this);
+
+ m_bankValue->setSizeLimit(20);
+ m_programValue->setSizeLimit(20);
+ m_variationValue->setSizeLimit(20);
+
+ m_bankLabel = new QLabel(i18n("Bank"), this);
+ m_variationLabel = new QLabel(i18n("Variation"), this);
+ m_programLabel = new QLabel(i18n("Program"), this);
+ QLabel *channelLabel = new QLabel(i18n("Channel out"), this);
+ QLabel *percussionLabel = new QLabel(i18n("Percussion"), this);
+
+ // Ensure a reasonable amount of space in the program dropdowns even
+ // if no instrument initially selected
+ QFontMetrics metrics(m_programValue->font());
+ int width22 = metrics.width("1234567890123456789012");
+ int width25 = metrics.width("1234567890123456789012345");
+
+ m_bankValue->setMinimumWidth(width22);
+ m_programValue->setMinimumWidth(width22);
+ m_variationValue->setMinimumWidth(width22);
+
+ m_connectionLabel->setFixedWidth(width25);
+ m_connectionLabel->setAlignment(Qt::AlignCenter);
+
+ // Configure the empty final row to accomodate any extra vertical space.
+
+ m_mainGrid->setRowStretch(m_mainGrid->numRows() - 1, 1);
+
+
+ m_mainGrid->setColStretch(2, 1);
+
+ m_mainGrid->addMultiCellWidget(m_instrumentLabel, 0, 0, 0, 2, AlignCenter);
+ m_mainGrid->addMultiCellWidget(m_connectionLabel, 1, 1, 0, 2, AlignCenter);
+
+ m_mainGrid->addMultiCellWidget(channelLabel, 2, 2, 0, 1, AlignLeft);
+ m_mainGrid->addWidget(m_channelValue, 2, 2, AlignRight);
+
+ m_mainGrid->addMultiCellWidget(percussionLabel, 3, 3, 0, 1, AlignLeft);
+ m_mainGrid->addWidget(m_percussionCheckBox, 3, 2, AlignRight);
+
+ m_mainGrid->addWidget(m_bankLabel, 4, 0, AlignLeft);
+ m_mainGrid->addWidget(m_bankCheckBox, 4, 1, AlignRight);
+ m_mainGrid->addWidget(m_bankValue, 4, 2, AlignRight);
+
+ m_mainGrid->addWidget(m_programLabel, 5, 0, AlignLeft);
+ m_mainGrid->addWidget(m_programCheckBox, 5, 1, AlignRight);
+ m_mainGrid->addWidget(m_programValue, 5, 2, AlignRight);
+
+ m_mainGrid->addWidget(m_variationLabel, 6, 0);
+ m_mainGrid->addWidget(m_variationCheckBox, 6, 1);
+ m_mainGrid->addWidget(m_variationValue, 6, 2, AlignRight);
+
+ // Populate channel lists
+ //
+ for (int i = 0; i < 16; i++) {
+ m_channelValue->insertItem(QString("%1").arg(i + 1));
+ }
+
+ m_channelValue->setSizeLimit(16);
+
+ // Disable these by default - they are activate by their
+ // checkboxes
+ //
+ m_programValue->setDisabled(true);
+ m_bankValue->setDisabled(true);
+ m_variationValue->setDisabled(true);
+
+ // Only active if we have an Instrument selected
+ //
+ m_percussionCheckBox->setDisabled(true);
+ m_programCheckBox->setDisabled(true);
+ m_bankCheckBox->setDisabled(true);
+ m_variationCheckBox->setDisabled(true);
+
+ // Connect up the toggle boxes
+ //
+ connect(m_percussionCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(slotTogglePercussion(bool)));
+
+ connect(m_programCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(slotToggleProgramChange(bool)));
+
+ connect(m_bankCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(slotToggleBank(bool)));
+
+ connect(m_variationCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(slotToggleVariation(bool)));
+
+
+ // Connect activations
+ //
+ connect(m_bankValue, SIGNAL(activated(int)),
+ this, SLOT(slotSelectBank(int)));
+
+ connect(m_variationValue, SIGNAL(activated(int)),
+ this, SLOT(slotSelectVariation(int)));
+
+ connect(m_programValue, SIGNAL(activated(int)),
+ this, SLOT(slotSelectProgram(int)));
+
+ connect(m_channelValue, SIGNAL(activated(int)),
+ this, SLOT(slotSelectChannel(int)));
+
+ // don't select any of the options in any dropdown
+ m_programValue->setCurrentItem( -1);
+ m_bankValue->setCurrentItem( -1);
+ m_channelValue->setCurrentItem( -1);
+ m_variationValue->setCurrentItem( -1);
+
+ connect(m_rotaryMapper, SIGNAL(mapped(int)),
+ this, SLOT(slotControllerChanged(int)));
+}
+
+void
+MIDIInstrumentParameterPanel::setupForInstrument(Instrument *instrument)
+{
+ RG_DEBUG << "MIDIInstrumentParameterPanel::setupForInstrument" << endl;
+ MidiDevice *md = dynamic_cast<MidiDevice*>
+ (instrument->getDevice());
+ if (!md) {
+ RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::setupForInstrument:"
+ << " No MidiDevice for Instrument "
+ << instrument->getId() << endl;
+ return ;
+ }
+
+ m_selectedInstrument = instrument;
+
+ // Set instrument name
+ //
+ m_instrumentLabel->setText(strtoqstr(instrument->getPresentationName()));
+
+ // Set Studio Device name
+ //
+ QString connection(strtoqstr(md->getConnection()));
+ if (connection == "") {
+ m_connectionLabel->setText(i18n("[ %1 ]").arg(i18n("No connection")));
+ } else {
+
+ // remove trailing "(duplex)", "(read only)", "(write only)" etc
+ connection.replace(QRegExp("\\s*\\([^)0-9]+\\)\\s*$"), "");
+
+ QString text = i18n("[ %1 ]").arg(connection);
+ /*QString origText(text);
+
+ QFontMetrics metrics(m_connectionLabel->fontMetrics());
+ int maxwidth = metrics.width
+ ("Program: [X] Acoustic Grand Piano 123");// kind of arbitrary!
+
+ int hlen = text.length() / 2;
+ while (metrics.width(text) > maxwidth && text.length() > 10) {
+ --hlen;
+ text = origText.left(hlen) + "..." + origText.right(hlen);
+ }
+
+ if (text.length() > origText.length() - 7) text = origText;*/
+ m_connectionLabel->setText(text);
+ }
+
+ // Enable all check boxes
+ //
+ m_percussionCheckBox->setDisabled(false);
+ m_programCheckBox->setDisabled(false);
+ m_bankCheckBox->setDisabled(false);
+ m_variationCheckBox->setDisabled(false);
+
+ // Activate all checkboxes
+ //
+ m_percussionCheckBox->setChecked(instrument->isPercussion());
+ m_programCheckBox->setChecked(instrument->sendsProgramChange());
+ m_bankCheckBox->setChecked(instrument->sendsBankSelect());
+ m_variationCheckBox->setChecked(instrument->sendsBankSelect());
+
+ // Basic parameters
+ //
+ m_channelValue->setCurrentItem((int)instrument->getMidiChannel());
+
+ // Check for program change
+ //
+ populateBankList();
+ populateProgramList();
+ populateVariationList();
+
+ // Setup the ControlParameters
+ //
+ setupControllers(md);
+
+ // Set all the positions by controller number
+ //
+ for (RotaryMap::iterator it = m_rotaries.begin() ;
+ it != m_rotaries.end(); ++it) {
+ MidiByte value = 0;
+
+ // Special cases
+ //
+ if (it->first == MIDI_CONTROLLER_PAN)
+ value = int(instrument->getPan());
+ else if (it->first == MIDI_CONTROLLER_VOLUME)
+ value = int(instrument->getVolume());
+ else {
+ try {
+ value = instrument->getControllerValue(
+ MidiByte(it->first));
+ } catch (...) {
+ continue;
+ }
+ }
+
+ setRotaryToValue(it->first, int(value));
+ }
+}
+
+void
+MIDIInstrumentParameterPanel::setupControllers(MidiDevice *md)
+{
+ if (!m_rotaryFrame) {
+ m_rotaryFrame = new QFrame(this);
+ m_mainGrid->addMultiCellWidget(m_rotaryFrame, 8, 8, 0, 2, Qt::AlignHCenter);
+ m_rotaryGrid = new QGridLayout(m_rotaryFrame, 10, 3, 8, 1);
+ m_rotaryGrid->addItem(new QSpacerItem(10, 4), 0, 1);
+ }
+
+ // To cut down on flicker, we avoid destroying and recreating
+ // widgets as far as possible here. If a label already exists,
+ // we just set its text; if a rotary exists, we only replace it
+ // if we actually need a different one.
+
+ Composition &comp = m_doc->getComposition();
+ ControlList list = md->getControlParameters();
+
+ // sort by IPB position
+ //
+ std::sort(list.begin(), list.end(),
+ ControlParameter::ControlPositionCmp());
+
+ int count = 0;
+ RotaryMap::iterator rmi = m_rotaries.begin();
+
+ for (ControlList::iterator it = list.begin();
+ it != list.end(); ++it) {
+ if (it->getIPBPosition() == -1)
+ continue;
+
+ // Get the knob colour - only if the colour is non-default (>0)
+ //
+ QColor knobColour = Qt::black; // special case for Rotary
+ if (it->getColourIndex() > 0) {
+ Colour c =
+ comp.getGeneralColourMap().getColourByIndex
+ (it->getColourIndex());
+ knobColour = QColor(c.getRed(), c.getGreen(), c.getBlue());
+ }
+
+ Rotary *rotary = 0;
+
+ if (rmi != m_rotaries.end()) {
+
+ // Update the controller number that is associated with the
+ // existing rotary widget.
+
+ rmi->first = it->getControllerValue();
+
+ // Update the properties of the existing rotary widget.
+
+ rotary = rmi->second.first;
+ int redraw = 0; // 1 -> position, 2 -> all
+
+ if (rotary->getMinValue() != it->getMin()) {
+ rotary->setMinValue(it->getMin());
+ redraw = 1;
+ }
+ if (rotary->getMaxValue() != it->getMax()) {
+ rotary->setMaxValue(it->getMax());
+ redraw = 1;
+ }
+ if (rotary->getKnobColour() != knobColour) {
+ rotary->setKnobColour(knobColour);
+ redraw = 2;
+ }
+ if (redraw == 1 || rotary->getPosition() != it->getDefault()) {
+ rotary->setPosition(it->getDefault());
+ if (redraw == 1)
+ redraw = 0;
+ }
+ if (redraw == 2) {
+ rotary->repaint();
+ }
+
+ // Update the controller name that is associated with
+ // with the existing rotary widget.
+
+ QLabel *label = rmi->second.second;
+ label->setText(strtoqstr(it->getName()));
+
+ ++rmi;
+
+ } else {
+
+ QHBox *hbox = new QHBox(m_rotaryFrame);
+ hbox->setSpacing(8);
+
+ float smallStep = 1.0;
+
+ float bigStep = 5.0;
+ if (it->getMax() - it->getMin() < 10)
+ bigStep = 1.0;
+ else if (it->getMax() - it->getMin() < 20)
+ bigStep = 2.0;
+
+ rotary = new Rotary
+ (hbox,
+ it->getMin(),
+ it->getMax(),
+ smallStep,
+ bigStep,
+ it->getDefault(),
+ 20,
+ Rotary::NoTicks,
+ false,
+ it->getDefault() == 64); //!!! hacky
+
+ rotary->setKnobColour(knobColour);
+
+ // Add a label
+ QLabel *label = new KSqueezedTextLabel(strtoqstr(it->getName()), hbox);
+
+ RG_DEBUG << "Adding new widget at " << (count / 2) << "," << (count % 2) << endl;
+
+ // Add the compound widget
+ //
+ m_rotaryGrid->addWidget(hbox, count / 2, (count % 2) * 2, AlignLeft);
+ hbox->show();
+
+ // Add to list
+ //
+ m_rotaries.push_back(std::pair<int, RotaryPair>
+ (it->getControllerValue(),
+ RotaryPair(rotary, label)));
+
+ // Connect
+ //
+ connect(rotary, SIGNAL(valueChanged(float)),
+ m_rotaryMapper, SLOT(map()));
+
+ rmi = m_rotaries.end();
+ }
+
+ // Add signal mapping
+ //
+ m_rotaryMapper->setMapping(rotary,
+ int(it->getControllerValue()));
+
+ count++;
+ }
+
+ if (rmi != m_rotaries.end()) {
+ for (RotaryMap::iterator rmj = rmi; rmj != m_rotaries.end(); ++rmj) {
+ delete rmj->second.first;
+ delete rmj->second.second;
+ }
+ m_rotaries = std::vector<std::pair<int, RotaryPair> >
+ (m_rotaries.begin(), rmi);
+ }
+
+ m_rotaryFrame->show();
+}
+
+void
+MIDIInstrumentParameterPanel::setRotaryToValue(int controller, int value)
+{
+ /*
+ RG_DEBUG << "MIDIInstrumentParameterPanel::setRotaryToValue - "
+ << "controller = " << controller
+ << ", value = " << value << std::endl;
+ */
+
+ for (RotaryMap::iterator it = m_rotaries.begin() ; it != m_rotaries.end(); ++it) {
+ if (it->first == controller) {
+ it->second.first->setPosition(float(value));
+ return ;
+ }
+ }
+}
+
+void
+MIDIInstrumentParameterPanel::slotSelectChannel(int index)
+{
+ if (m_selectedInstrument == 0)
+ return ;
+
+ m_selectedInstrument->setMidiChannel(index);
+
+ // don't use the emit - use this method instead
+ StudioControl::sendMappedInstrument(
+ MappedInstrument(m_selectedInstrument));
+ emit updateAllBoxes();
+}
+
+void
+MIDIInstrumentParameterPanel::populateBankList()
+{
+ if (m_selectedInstrument == 0)
+ return ;
+
+ m_bankValue->clear();
+ m_banks.clear();
+
+ MidiDevice *md = dynamic_cast<MidiDevice*>
+ (m_selectedInstrument->getDevice());
+ if (!md) {
+ RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::populateBankList:"
+ << " No MidiDevice for Instrument "
+ << m_selectedInstrument->getId() << endl;
+ return ;
+ }
+
+ int currentBank = -1;
+ BankList banks;
+
+ /*
+ RG_DEBUG << "MIDIInstrumentParameterPanel::populateBankList: "
+ << "variation type is " << md->getVariationType() << endl;
+ */
+
+ if (md->getVariationType() == MidiDevice::NoVariations) {
+
+ banks = md->getBanks(m_selectedInstrument->isPercussion());
+
+ if (!banks.empty()) {
+ if (m_bankLabel->isHidden()) {
+ m_bankLabel->show();
+ m_bankCheckBox->show();
+ m_bankValue->show();
+ }
+ } else {
+ m_bankLabel->hide();
+ m_bankCheckBox->hide();
+ m_bankValue->hide();
+ }
+
+ for (unsigned int i = 0; i < banks.size(); ++i) {
+ if (m_selectedInstrument->getProgram().getBank() == banks[i]) {
+ currentBank = i;
+ }
+ }
+
+ } else {
+
+ MidiByteList bytes;
+ bool useMSB = (md->getVariationType() == MidiDevice::VariationFromLSB);
+
+ if (useMSB) {
+ bytes = md->getDistinctMSBs(m_selectedInstrument->isPercussion());
+ } else {
+ bytes = md->getDistinctLSBs(m_selectedInstrument->isPercussion());
+ }
+
+ if (bytes.size() < 2) {
+ if (!m_bankLabel->isHidden()) {
+ m_bankLabel->hide();
+ m_bankCheckBox->hide();
+ m_bankValue->hide();
+ }
+ } else {
+ if (m_bankLabel->isHidden()) {
+ m_bankLabel->show();
+ m_bankCheckBox->show();
+ m_bankValue->show();
+ }
+ }
+
+ if (useMSB) {
+ for (unsigned int i = 0; i < bytes.size(); ++i) {
+ BankList bl = md->getBanksByMSB
+ (m_selectedInstrument->isPercussion(), bytes[i]);
+ RG_DEBUG << "MIDIInstrumentParameterPanel::populateBankList: have " << bl.size() << " variations for msb " << bytes[i] << endl;
+
+ if (bl.size() == 0)
+ continue;
+ if (m_selectedInstrument->getMSB() == bytes[i]) {
+ currentBank = banks.size();
+ }
+ banks.push_back(bl[0]);
+ }
+ } else {
+ for (unsigned int i = 0; i < bytes.size(); ++i) {
+ BankList bl = md->getBanksByLSB
+ (m_selectedInstrument->isPercussion(), bytes[i]);
+ RG_DEBUG << "MIDIInstrumentParameterPanel::populateBankList: have " << bl.size() << " variations for lsb " << bytes[i] << endl;
+ if (bl.size() == 0)
+ continue;
+ if (m_selectedInstrument->getLSB() == bytes[i]) {
+ currentBank = banks.size();
+ }
+ banks.push_back(bl[0]);
+ }
+ }
+ }
+
+ for (BankList::const_iterator i = banks.begin();
+ i != banks.end(); ++i) {
+ m_banks.push_back(*i);
+ m_bankValue->insertItem(strtoqstr(i->getName()));
+ }
+
+ m_bankValue->setEnabled(m_selectedInstrument->sendsBankSelect());
+
+ if (currentBank < 0 && !banks.empty()) {
+ m_bankValue->setCurrentItem(0);
+ slotSelectBank(0);
+ } else {
+ m_bankValue->setCurrentItem(currentBank);
+ }
+}
+
+void
+MIDIInstrumentParameterPanel::populateProgramList()
+{
+ if (m_selectedInstrument == 0)
+ return ;
+
+ m_programValue->clear();
+ m_programs.clear();
+
+ MidiDevice *md = dynamic_cast<MidiDevice*>
+ (m_selectedInstrument->getDevice());
+ if (!md) {
+ RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::populateProgramList: No MidiDevice for Instrument "
+ << m_selectedInstrument->getId() << endl;
+ return ;
+ }
+
+ /*
+ RG_DEBUG << "MIDIInstrumentParameterPanel::populateProgramList:"
+ << " variation type is " << md->getVariationType() << endl;
+ */
+
+ MidiBank bank( m_selectedInstrument->isPercussion(),
+ m_selectedInstrument->getMSB(),
+ m_selectedInstrument->getLSB());
+
+ if (m_selectedInstrument->sendsBankSelect()) {
+ bank = m_selectedInstrument->getProgram().getBank();
+ }
+
+ int currentProgram = -1;
+
+ ProgramList programs = md->getPrograms(bank);
+
+ if (!programs.empty()) {
+ if (m_programLabel->isHidden()) {
+ m_programLabel->show();
+ m_programCheckBox->show();
+ m_programValue->show();
+ }
+ } else {
+ m_programLabel->hide();
+ m_programCheckBox->hide();
+ m_programValue->hide();
+ }
+
+ for (unsigned int i = 0; i < programs.size(); ++i) {
+ std::string programName = programs[i].getName();
+ if (programName != "") {
+ m_programValue->insertItem(QString("%1. %2")
+ .arg(programs[i].getProgram() + 1)
+ .arg(strtoqstr(programName)));
+ if (m_selectedInstrument->getProgram() == programs[i]) {
+ currentProgram = m_programs.size();
+ }
+ m_programs.push_back(programs[i]);
+ }
+ }
+
+ m_programValue->setEnabled(m_selectedInstrument->sendsProgramChange());
+
+ if (currentProgram < 0 && !m_programs.empty()) {
+ m_programValue->setCurrentItem(0);
+ slotSelectProgram(0);
+ } else {
+ m_programValue->setCurrentItem(currentProgram);
+
+ // Ensure that stored program change value is same as the one
+ // we're now showing (BUG 937371)
+ //
+ if (!m_programs.empty()) {
+ m_selectedInstrument->setProgramChange
+ ((m_programs[m_programValue->currentItem()]).getProgram());
+ }
+ }
+}
+
+void
+MIDIInstrumentParameterPanel::populateVariationList()
+{
+ if (m_selectedInstrument == 0)
+ return ;
+
+ m_variationValue->clear();
+ m_variations.clear();
+
+ MidiDevice *md = dynamic_cast<MidiDevice*>
+ (m_selectedInstrument->getDevice());
+ if (!md) {
+ RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::populateVariationList: No MidiDevice for Instrument "
+ << m_selectedInstrument->getId() << endl;
+ return ;
+ }
+
+ /*
+ RG_DEBUG << "MIDIInstrumentParameterPanel::populateVariationList:"
+ << " variation type is " << md->getVariationType() << endl;
+ */
+
+ if (md->getVariationType() == MidiDevice::NoVariations) {
+ if (!m_variationLabel->isHidden()) {
+ m_variationLabel->hide();
+ m_variationCheckBox->hide();
+ m_variationValue->hide();
+ }
+ return ;
+ }
+
+ bool useMSB = (md->getVariationType() == MidiDevice::VariationFromMSB);
+ MidiByteList variations;
+
+ if (useMSB) {
+ MidiByte lsb = m_selectedInstrument->getLSB();
+ variations = md->getDistinctMSBs(m_selectedInstrument->isPercussion(),
+ lsb);
+ RG_DEBUG << "MIDIInstrumentParameterPanel::populateVariationList: have " << variations.size() << " variations for lsb " << lsb << endl;
+
+ } else {
+ MidiByte msb = m_selectedInstrument->getMSB();
+ variations = md->getDistinctLSBs(m_selectedInstrument->isPercussion(),
+ msb);
+ RG_DEBUG << "MIDIInstrumentParameterPanel::populateVariationList: have " << variations.size() << " variations for msb " << msb << endl;
+ }
+
+ m_variationValue->setCurrentItem( -1);
+
+ MidiProgram defaultProgram;
+
+ if (useMSB) {
+ defaultProgram = MidiProgram
+ (MidiBank(m_selectedInstrument->isPercussion(),
+ 0,
+ m_selectedInstrument->getLSB()),
+ m_selectedInstrument->getProgramChange());
+ } else {
+ defaultProgram = MidiProgram
+ (MidiBank(m_selectedInstrument->isPercussion(),
+ m_selectedInstrument->getMSB(),
+ 0),
+ m_selectedInstrument->getProgramChange());
+ }
+ std::string defaultProgramName = md->getProgramName(defaultProgram);
+
+ int currentVariation = -1;
+
+ for (unsigned int i = 0; i < variations.size(); ++i) {
+
+ MidiProgram program;
+
+ if (useMSB) {
+ program = MidiProgram
+ (MidiBank(m_selectedInstrument->isPercussion(),
+ variations[i],
+ m_selectedInstrument->getLSB()),
+ m_selectedInstrument->getProgramChange());
+ } else {
+ program = MidiProgram
+ (MidiBank(m_selectedInstrument->isPercussion(),
+ m_selectedInstrument->getMSB(),
+ variations[i]),
+ m_selectedInstrument->getProgramChange());
+ }
+
+ std::string programName = md->getProgramName(program);
+
+ if (programName != "") { // yes, that is how you know whether it exists
+ /*
+ m_variationValue->insertItem(programName == defaultProgramName ?
+ i18n("(default)") :
+ strtoqstr(programName));
+ */
+ m_variationValue->insertItem(QString("%1. %2")
+ .arg(variations[i] + 1)
+ .arg(strtoqstr(programName)));
+ if (m_selectedInstrument->getProgram() == program) {
+ currentVariation = m_variations.size();
+ }
+ m_variations.push_back(variations[i]);
+ }
+ }
+
+ if (currentVariation < 0 && !m_variations.empty()) {
+ m_variationValue->setCurrentItem(0);
+ slotSelectVariation(0);
+ } else {
+ m_variationValue->setCurrentItem(currentVariation);
+ }
+
+ if (m_variations.size() < 2) {
+ if (!m_variationLabel->isHidden()) {
+ m_variationLabel->hide();
+ m_variationCheckBox->hide();
+ m_variationValue->hide();
+ }
+
+ } else {
+ //!!! seem to have problems here -- the grid layout doesn't
+ //like us adding stuff in the middle so if we go from 1
+ //visible row (say program) to 2 (program + variation) the
+ //second one overlaps the control knobs
+
+ if (m_variationLabel->isHidden()) {
+ m_variationLabel->show();
+ m_variationCheckBox->show();
+ m_variationValue->show();
+ }
+
+ if (m_programValue->width() > m_variationValue->width()) {
+ m_variationValue->setMinimumWidth(m_programValue->width());
+ } else {
+ m_programValue->setMinimumWidth(m_variationValue->width());
+ }
+ }
+
+ m_variationValue->setEnabled(m_selectedInstrument->sendsBankSelect());
+}
+
+void
+MIDIInstrumentParameterPanel::slotTogglePercussion(bool value)
+{
+ if (m_selectedInstrument == 0) {
+ m_percussionCheckBox->setChecked(false);
+ emit updateAllBoxes();
+ return ;
+ }
+
+ m_selectedInstrument->setPercussion(value);
+
+ populateBankList();
+ populateProgramList();
+ populateVariationList();
+
+ sendBankAndProgram();
+
+ emit changeInstrumentLabel(m_selectedInstrument->getId(),
+ strtoqstr(m_selectedInstrument->
+ getProgramName()));
+ emit updateAllBoxes();
+
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+MIDIInstrumentParameterPanel::slotToggleBank(bool value)
+{
+ if (m_selectedInstrument == 0) {
+ m_bankCheckBox->setChecked(false);
+ emit updateAllBoxes();
+ return ;
+ }
+
+ m_variationCheckBox->setChecked(value);
+ m_selectedInstrument->setSendBankSelect(value);
+
+ m_bankValue->setDisabled(!value);
+ populateBankList();
+ populateProgramList();
+ populateVariationList();
+
+ sendBankAndProgram();
+
+ emit changeInstrumentLabel(m_selectedInstrument->getId(),
+ strtoqstr(m_selectedInstrument->
+ getProgramName()));
+ emit updateAllBoxes();
+
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+MIDIInstrumentParameterPanel::slotToggleProgramChange(bool value)
+{
+ if (m_selectedInstrument == 0) {
+ m_programCheckBox->setChecked(false);
+ emit updateAllBoxes();
+ return ;
+ }
+
+ m_selectedInstrument->setSendProgramChange(value);
+
+ m_programValue->setDisabled(!value);
+ populateProgramList();
+ populateVariationList();
+
+ if (value)
+ sendBankAndProgram();
+
+ emit changeInstrumentLabel(m_selectedInstrument->getId(),
+ strtoqstr(m_selectedInstrument->
+ getProgramName()));
+ emit updateAllBoxes();
+
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+MIDIInstrumentParameterPanel::slotToggleVariation(bool value)
+{
+ if (m_selectedInstrument == 0) {
+ m_variationCheckBox->setChecked(false);
+ emit updateAllBoxes();
+ return ;
+ }
+
+ m_bankCheckBox->setChecked(value);
+ m_selectedInstrument->setSendBankSelect(value);
+
+ m_variationValue->setDisabled(!value);
+ populateVariationList();
+
+ sendBankAndProgram();
+
+ emit changeInstrumentLabel(m_selectedInstrument->getId(),
+ strtoqstr(m_selectedInstrument->
+ getProgramName()));
+ emit updateAllBoxes();
+
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+MIDIInstrumentParameterPanel::slotSelectBank(int index)
+{
+ if (m_selectedInstrument == 0)
+ return ;
+
+ MidiDevice *md = dynamic_cast<MidiDevice*>
+ (m_selectedInstrument->getDevice());
+ if (!md) {
+ RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::slotSelectBank: No MidiDevice for Instrument "
+ << m_selectedInstrument->getId() << endl;
+ return ;
+ }
+
+ const MidiBank *bank = &m_banks[index];
+
+ bool change = false;
+
+ if (md->getVariationType() != MidiDevice::VariationFromLSB) {
+ if (m_selectedInstrument->getLSB() != bank->getLSB()) {
+ m_selectedInstrument->setLSB(bank->getLSB());
+ change = true;
+ }
+ }
+ if (md->getVariationType() != MidiDevice::VariationFromMSB) {
+ if (m_selectedInstrument->getMSB() != bank->getMSB()) {
+ m_selectedInstrument->setMSB(bank->getMSB());
+ change = true;
+ }
+ }
+
+ populateProgramList();
+
+ if (change) {
+ sendBankAndProgram();
+ emit updateAllBoxes();
+ }
+
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+MIDIInstrumentParameterPanel::slotSelectProgram(int index)
+{
+ const MidiProgram *prg = &m_programs[index];
+ if (prg == 0) {
+ RG_DEBUG << "program change not found in bank" << endl;
+ return ;
+ }
+
+ bool change = false;
+ if (m_selectedInstrument->getProgramChange() != prg->getProgram()) {
+ m_selectedInstrument->setProgramChange(prg->getProgram());
+ change = true;
+ }
+
+ populateVariationList();
+
+ if (change) {
+ sendBankAndProgram();
+ emit changeInstrumentLabel(m_selectedInstrument->getId(),
+ strtoqstr(m_selectedInstrument->
+ getProgramName()));
+ emit updateAllBoxes();
+ }
+
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+MIDIInstrumentParameterPanel::slotSelectVariation(int index)
+{
+ MidiDevice *md = dynamic_cast<MidiDevice*>
+ (m_selectedInstrument->getDevice());
+ if (!md) {
+ RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::slotSelectVariation: No MidiDevice for Instrument "
+ << m_selectedInstrument->getId() << endl;
+ return ;
+ }
+
+ if (index < 0 || index > int(m_variations.size())) {
+ RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::slotSelectVariation: index " << index << " out of range" << endl;
+ return ;
+ }
+
+ MidiByte v = m_variations[index];
+
+ bool change = false;
+
+ if (md->getVariationType() == MidiDevice::VariationFromLSB) {
+ if (m_selectedInstrument->getLSB() != v) {
+ m_selectedInstrument->setLSB(v);
+ change = true;
+ }
+ } else if (md->getVariationType() == MidiDevice::VariationFromMSB) {
+ if (m_selectedInstrument->getMSB() != v) {
+ m_selectedInstrument->setMSB(v);
+ change = true;
+ }
+ }
+
+ if (change) {
+ sendBankAndProgram();
+ }
+
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+}
+
+void
+MIDIInstrumentParameterPanel::sendBankAndProgram()
+{
+ if (m_selectedInstrument == 0)
+ return ;
+
+ MidiDevice *md = dynamic_cast<MidiDevice*>
+ (m_selectedInstrument->getDevice());
+ if (!md) {
+ RG_DEBUG << "WARNING: MIDIInstrumentParameterPanel::sendBankAndProgram: No MidiDevice for Instrument "
+ << m_selectedInstrument->getId() << endl;
+ return ;
+ }
+
+ if (m_selectedInstrument->sendsBankSelect()) {
+
+ // Send the bank select message before any PC message
+ //
+ MappedEvent mEMSB(m_selectedInstrument->getId(),
+ MappedEvent::MidiController,
+ MIDI_CONTROLLER_BANK_MSB,
+ m_selectedInstrument->getMSB());
+
+ RG_DEBUG << "MIDIInstrumentParameterPanel::sendBankAndProgram - "
+ << "sending MSB = "
+ << int(m_selectedInstrument->getMSB())
+ << endl;
+
+ StudioControl::sendMappedEvent(mEMSB);
+
+ MappedEvent mELSB(m_selectedInstrument->getId(),
+ MappedEvent::MidiController,
+ MIDI_CONTROLLER_BANK_LSB,
+ m_selectedInstrument->getLSB());
+
+ RG_DEBUG << "MIDIInstrumentParameterPanel::sendBankAndProgram - "
+ << "sending LSB = "
+ << int(m_selectedInstrument->getLSB())
+ << endl;
+
+ StudioControl::sendMappedEvent(mELSB);
+ }
+
+ MappedEvent mE(m_selectedInstrument->getId(),
+ MappedEvent::MidiProgramChange,
+ m_selectedInstrument->getProgramChange(),
+ (MidiByte)0);
+
+ RG_DEBUG << "MIDIInstrumentParameterPanel::sendBankAndProgram - "
+ << "sending program change = "
+ << int(m_selectedInstrument->getProgramChange())
+ << endl;
+
+
+ // Send the controller change
+ //
+ StudioControl::sendMappedEvent(mE);
+}
+
+void
+MIDIInstrumentParameterPanel::slotControllerChanged(int controllerNumber)
+{
+
+ RG_DEBUG << "MIDIInstrumentParameterPanel::slotControllerChanged - "
+ << "controller = " << controllerNumber << "\n";
+
+
+ if (m_selectedInstrument == 0)
+ return ;
+
+ MidiDevice *md = dynamic_cast<MidiDevice*>
+ (m_selectedInstrument->getDevice());
+ if (!md)
+ return ;
+
+ /*
+ ControlParameter *controller =
+ md->getControlParameter(MidiByte(controllerNumber));
+ */
+
+ int value = getValueFromRotary(controllerNumber);
+
+ if (value == -1) {
+ RG_DEBUG << "MIDIInstrumentParameterPanel::slotControllerChanged - "
+ << "couldn't get value of rotary for controller "
+ << controllerNumber << endl;
+ return ;
+ }
+
+
+ // two special cases
+ if (controllerNumber == int(MIDI_CONTROLLER_PAN)) {
+ float adjValue = value;
+ if (m_selectedInstrument->getType() == Instrument::Audio ||
+ m_selectedInstrument->getType() == Instrument::SoftSynth)
+ value += 100;
+
+ m_selectedInstrument->setPan(MidiByte(adjValue));
+ } else if (controllerNumber == int(MIDI_CONTROLLER_VOLUME)) {
+ m_selectedInstrument->setVolume(MidiByte(value));
+ } else // just set the controller (this will create it on the instrument if
+ // it doesn't exist)
+ {
+ m_selectedInstrument->setControllerValue(MidiByte(controllerNumber),
+ MidiByte(value));
+
+ RG_DEBUG << "SET CONTROLLER VALUE (" << controllerNumber << ") = " << value << endl;
+ }
+ /*
+ else
+ {
+ RG_DEBUG << "MIDIInstrumentParameterPanel::slotControllerChanged - "
+ << "no controller retrieved\n";
+ return;
+ }
+ */
+
+ MappedEvent mE(m_selectedInstrument->getId(),
+ MappedEvent::MidiController,
+ (MidiByte)controllerNumber,
+ (MidiByte)value);
+ StudioControl::sendMappedEvent(mE);
+
+ emit updateAllBoxes();
+ emit instrumentParametersChanged(m_selectedInstrument->getId());
+
+}
+
+int
+MIDIInstrumentParameterPanel::getValueFromRotary(int rotary)
+{
+ for (RotaryMap::iterator it = m_rotaries.begin(); it != m_rotaries.end(); ++it) {
+ if (it->first == rotary)
+ return int(it->second.first->getPosition());
+ }
+
+ return -1;
+}
+
+void
+MIDIInstrumentParameterPanel::showAdditionalControls(bool showThem)
+{
+ m_instrumentLabel->setShown(showThem);
+ int index = 0;
+ for (RotaryMap::iterator it = m_rotaries.begin(); it != m_rotaries.end(); ++it) {
+ it->second.first->parentWidget()->setShown(showThem || (index < 8));
+ //it->second.first->setShown(showThem || (index < 8));
+ //it->second.second->setShown(showThem || (index < 8));
+ index++;
+ }
+}
+
+}
+#include "MIDIInstrumentParameterPanel.moc"
diff --git a/src/gui/editors/parameters/MIDIInstrumentParameterPanel.h b/src/gui/editors/parameters/MIDIInstrumentParameterPanel.h
new file mode 100644
index 0000000..7f1a1c5
--- /dev/null
+++ b/src/gui/editors/parameters/MIDIInstrumentParameterPanel.h
@@ -0,0 +1,137 @@
+
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef _RG_MIDIINSTRUMENTPARAMETERPANEL_H_
+#define _RG_MIDIINSTRUMENTPARAMETERPANEL_H_
+
+#include "base/MidiProgram.h"
+#include "base/MidiDevice.h"
+#include "InstrumentParameterPanel.h"
+#include <qstring.h>
+
+
+class QWidget;
+class QSignalMapper;
+class QLabel;
+class QGridLayout;
+class QFrame;
+class QCheckBox;
+class KComboBox;
+
+
+namespace Rosegarden
+{
+
+class RosegardenGUIDoc;
+class MidiDevice;
+class Instrument;
+
+
+class MIDIInstrumentParameterPanel : public InstrumentParameterPanel
+{
+ Q_OBJECT
+public:
+
+ MIDIInstrumentParameterPanel(RosegardenGUIDoc *doc, QWidget* parent);
+
+ void setupControllers(MidiDevice *); // setup ControlParameters on box
+
+ virtual void setupForInstrument(Instrument*);
+
+ void showAdditionalControls(bool showThem);
+
+signals:
+ void changeInstrumentLabel(InstrumentId id, QString label);
+ void instrumentParametersChanged(InstrumentId);
+
+public slots:
+ void slotSelectProgram(int index);
+ void slotSelectBank(int index);
+ void slotSelectVariation(int index);
+ void slotSelectChannel(int index);
+ //void slotSelectInputChannel(int index);
+
+ void slotControllerChanged(int index);
+
+ void slotTogglePercussion(bool value);
+ void slotToggleProgramChange(bool value);
+ void slotToggleBank(bool value);
+ void slotToggleVariation(bool value);
+
+protected:
+
+ // fill (or hide) bank combo based on whether the instrument is percussion
+ void populateBankList();
+
+ // fill program combo based on current bank
+ void populateProgramList();
+
+ // fill (or hide) variation combo based on current bank and program
+ void populateVariationList();
+
+ // send the bank and program events relevant to this instrument
+ void sendBankAndProgram();
+
+ // get value of a specific rotary (keyed by controller value)
+ int getValueFromRotary(int rotary);
+
+ // set rotary to value
+ void setRotaryToValue(int controller, int value);
+
+ //--------------- Data members ---------------------------------
+
+ QLabel *m_connectionLabel;
+
+ KComboBox *m_bankValue;
+ KComboBox *m_variationValue;
+ KComboBox *m_channelValue;
+ KComboBox *m_programValue;
+ //KComboBox *m_channelInValue;
+
+ QCheckBox *m_percussionCheckBox;
+ QCheckBox *m_bankCheckBox;
+ QCheckBox *m_variationCheckBox;
+ QCheckBox *m_programCheckBox;
+
+ QLabel *m_bankLabel;
+ QLabel *m_variationLabel;
+ QLabel *m_programLabel;
+
+ QGridLayout *m_mainGrid;
+ QFrame *m_rotaryFrame;
+ QGridLayout *m_rotaryGrid;
+ RotaryMap m_rotaries;
+ QSignalMapper *m_rotaryMapper;
+
+ BankList m_banks;
+ ProgramList m_programs;
+ MidiByteList m_variations;
+};
+
+
+
+}
+
+#endif
diff --git a/src/gui/editors/parameters/RosegardenParameterArea.cpp b/src/gui/editors/parameters/RosegardenParameterArea.cpp
new file mode 100644
index 0000000..968c737
--- /dev/null
+++ b/src/gui/editors/parameters/RosegardenParameterArea.cpp
@@ -0,0 +1,227 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ This file Copyright 2006 Martin Shepherd <[email protected]>.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "RosegardenParameterArea.h"
+
+#include "RosegardenParameterBox.h"
+#include <ktabwidget.h>
+#include <qfont.h>
+#include <qframe.h>
+#include <qpoint.h>
+#include <qscrollview.h>
+#include <qstring.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qvgroupbox.h>
+#include <qwidget.h>
+#include <qwidgetstack.h>
+#include <iostream>
+#include <set>
+
+
+namespace Rosegarden
+{
+
+RosegardenParameterArea::RosegardenParameterArea(QWidget *parent,
+ const char *name, WFlags f)
+ : QWidgetStack(parent, name, f),
+ m_style(RosegardenParameterArea::CLASSIC_STYLE),
+ m_scrollView(new QScrollView(this, 0, Qt::WStaticContents)),
+ m_classic(new QVBox(m_scrollView->viewport())),
+ m_tabBox(new KTabWidget(this)),
+ m_active(0),
+ m_spacing(0)
+{
+ m_scrollView->addChild(m_classic);
+ m_scrollView->setHScrollBarMode(QScrollView::AlwaysOff);
+ m_scrollView->setVScrollBarMode(QScrollView::Auto);
+ m_scrollView->setResizePolicy(QScrollView::AutoOneFit);
+
+ // Install the classic-style VBox widget in the widget-stack.
+
+ addWidget(m_scrollView, CLASSIC_STYLE);
+
+ // Install the widget that implements the tab-style to the widget-stack.
+
+ addWidget(m_tabBox, TAB_BOX_STYLE);
+
+}
+
+void RosegardenParameterArea::addRosegardenParameterBox(
+ RosegardenParameterBox *b)
+{
+ // Check that the box hasn't been added before.
+
+ for (unsigned int i = 0; i < m_parameterBoxes.size(); i++) {
+ if (m_parameterBoxes[i] == b)
+ return ;
+ }
+
+ // Append the parameter box to the list to be displayed.
+
+ m_parameterBoxes.push_back(b);
+
+ m_scrollView->setMinimumWidth(std::max(m_scrollView->minimumWidth(),
+ b->sizeHint().width()) + 8);
+
+ // Create a titled group box for the parameter box, parented by the
+ // classic layout widget, so that it can be used to provide a title
+ // and outline, in classic mode. Add this container to an array that
+ // parallels the above array of parameter boxes.
+
+ QVGroupBox *box = new QVGroupBox(b->getLongLabel(), m_classic);
+ box->layout()->setMargin( 4 ); // about half the default value
+ QFont f;
+ f.setBold( true );
+ box->setFont( f );
+ m_groupBoxes.push_back(box);
+
+ if (m_spacing)
+ delete m_spacing;
+ m_spacing = new QFrame(m_classic);
+ m_classic->setStretchFactor(m_spacing, 100);
+
+ // Add the parameter box to the current container of the displayed
+ // widgets, unless the current container has been set up yet.
+
+ if (m_active)
+ moveWidget(0, m_active, b);
+
+ // Queue a redisplay of the parameter area, to incorporate the new box.
+
+ update();
+}
+
+void RosegardenParameterArea::setArrangement(Arrangement style)
+{
+ // Lookup the container of the specified style.
+
+ QWidget *container;
+ switch (style) {
+ case CLASSIC_STYLE:
+ container = m_classic;
+ break;
+ case TAB_BOX_STYLE:
+ container = m_tabBox;
+ break;
+ default:
+ std::cerr << "setArrangement() was passed an unknown arrangement style."
+ << std::endl;
+ return ;
+ }
+
+ // Does the current container of the parameter-box widgets differ
+ // from the one that is associated with the currently configured
+ // style?
+
+ if (container != m_active) {
+
+ // Move the parameter boxes from the old container to the new one.
+
+ std::vector<RosegardenParameterBox *> sorted;
+ std::set<RosegardenParameterBox *> unsorted;
+
+ for (unsigned int i = 0; i < m_parameterBoxes.size(); i++) {
+ unsorted.insert(m_parameterBoxes[i]);
+ }
+
+ QString previous = "";
+
+ while (!unsorted.empty()) {
+ std::set<RosegardenParameterBox *>::iterator i = unsorted.begin();
+ bool have = false;
+ while (i != unsorted.end()) {
+ if ((*i)->getPreviousBox(style) == previous) {
+ sorted.push_back(*i);
+ previous = (*i)->getShortLabel();
+ unsorted.erase(i);
+ have = true;
+ break;
+ }
+ ++i;
+ }
+ if (!have) {
+ while (!unsorted.empty()) {
+ sorted.push_back(*unsorted.begin());
+ unsorted.erase(unsorted.begin());
+ }
+ break;
+ }
+ }
+
+ for (std::vector<RosegardenParameterBox *>::iterator i = sorted.begin();
+ i != sorted.end(); ++i) {
+ moveWidget(m_active, container, *i);
+ (*i)->showAdditionalControls(style == TAB_BOX_STYLE);
+ }
+
+ // Switch the widget stack to displaying the new container.
+
+ raiseWidget(style);
+ }
+
+ // Record the identity of the active container, and the associated
+ // arrangement style.
+
+ m_active = container;
+ m_style = style;
+}
+
+void RosegardenParameterArea::moveWidget(QWidget *old_container,
+ QWidget *new_container,
+ RosegardenParameterBox *box)
+{
+ // Remove any state that is associated with the parameter boxes,
+ // from the active container.
+
+ if (old_container == m_classic) {
+ ;
+ } else if (old_container == m_tabBox) {
+ m_tabBox->removePage(box);
+ }
+
+ // Reparent the parameter box, and perform any container-specific
+ // configuration.
+
+ if (new_container == m_classic) {
+ int index = 0;
+ while (index < m_parameterBoxes.size()) {
+ if (box == m_parameterBoxes[index])
+ break;
+ ++index;
+ }
+ if (index < m_parameterBoxes.size()) {
+ box->reparent(m_groupBoxes[index], 0, QPoint(0, 0), FALSE);
+ }
+ } else if (new_container == m_tabBox) {
+ box->reparent(new_container, 0, QPoint(0, 0), FALSE);
+ m_tabBox->insertTab(box, box->getShortLabel());
+ }
+}
+
+}
+#include "RosegardenParameterArea.moc"
diff --git a/src/gui/editors/parameters/RosegardenParameterArea.h b/src/gui/editors/parameters/RosegardenParameterArea.h
new file mode 100644
index 0000000..1236a43
--- /dev/null
+++ b/src/gui/editors/parameters/RosegardenParameterArea.h
@@ -0,0 +1,108 @@
+
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ This file Copyright 2006 Martin Shepherd <[email protected]>.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef _RG_ROSEGARDENPARAMETERAREA_H_
+#define _RG_ROSEGARDENPARAMETERAREA_H_
+
+#include <qwidgetstack.h>
+#include <vector>
+
+
+class QWidget;
+class QVGroupBox;
+class QVBox;
+class QScrollView;
+class KTabWidget;
+
+
+namespace Rosegarden
+{
+
+class RosegardenParameterBox;
+
+
+/**
+ * A widget that arranges a set of Rosegarden parameter-box widgets
+ * within a frame, in a dynamically configurable manner.
+ */
+class RosegardenParameterArea : public QWidgetStack
+{
+ Q_OBJECT
+public:
+
+ // Create the parameter display area.
+
+ RosegardenParameterArea(QWidget *parent=0, const char *name=0, WFlags f=0);
+
+ // Add a rosegarden parameter box to the list that are to be displayed.
+
+ void addRosegardenParameterBox(RosegardenParameterBox *b);
+
+
+ // List the supported methods of arranging the various parameter-box
+ // widgets within the parameter area.
+
+ enum Arrangement {
+ CLASSIC_STYLE, // A simple vertical tiling of parameter-box widgets.
+ TAB_BOX_STYLE // A horizontal list of tabs, displaying one box at a time.
+ };
+
+ // Redisplay the widgets with a different layout style.
+
+ void setArrangement(Arrangement style);
+
+protected:
+private:
+ Arrangement m_style; // The current layout style.
+
+ // The list of parameter box widgets that are being displayed by this
+ // widget.
+
+ std::vector<RosegardenParameterBox *> m_parameterBoxes;
+
+ // Create a parallel array of group boxes, to be used when the
+ // corresponding parameter box widget needs to be enclosed by a
+ // titled outline.
+
+ std::vector<QVGroupBox *> m_groupBoxes;
+
+ // Move a RosegardenParameterBox widget from one container to another.
+
+ void moveWidget(QWidget *old_container, QWidget *new_container,
+ RosegardenParameterBox *box);
+
+ QScrollView *m_scrollView; // Holds the m_classic container
+ QVBox *m_classic; // The container widget for m_style==CLASSIC_STYLE.
+ KTabWidget *m_tabBox; // The container widget for m_style==TAB_BOX_STYLE.
+ QWidget *m_active; // The current container widget.
+ QWidget *m_spacing;
+};
+
+
+}
+
+#endif
diff --git a/src/gui/editors/parameters/RosegardenParameterBox.cpp b/src/gui/editors/parameters/RosegardenParameterBox.cpp
new file mode 100644
index 0000000..7d9100c
--- /dev/null
+++ b/src/gui/editors/parameters/RosegardenParameterBox.cpp
@@ -0,0 +1,89 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "RosegardenParameterBox.h"
+
+#include "RosegardenParameterArea.h"
+#include <ktabwidget.h>
+#include <qfont.h>
+#include <qframe.h>
+#include <qscrollview.h>
+#include <qstring.h>
+#include <qvbox.h>
+#include <qwidget.h>
+#include <qwidgetstack.h>
+
+
+namespace Rosegarden
+{
+
+RosegardenParameterBox::RosegardenParameterBox(const QString &shortLabel,
+ const QString &longLabel,
+ QWidget *parent,
+ const char *name) :
+ QFrame(parent, name),
+ m_shortLabel(shortLabel),
+ m_longLabel(longLabel),
+ m_mode(LANDSCAPE_MODE)
+{
+ init();
+}
+
+void RosegardenParameterBox::init()
+{
+ QFont plainFont;
+ plainFont.setPointSize(plainFont.pointSize() * 95 / 100);
+ if (plainFont.pixelSize() > 14)
+ plainFont.setPixelSize(14);
+ plainFont.setBold(false);
+ m_font = plainFont;
+
+ QFont boldFont;
+ boldFont.setPointSize(int(boldFont.pointSize() * 9.5 / 10.0 + 0.5));
+ if (boldFont.pixelSize() > 14)
+ boldFont.setPixelSize(14);
+ boldFont.setBold(true);
+
+ setFont(boldFont);
+}
+
+QString RosegardenParameterBox::getShortLabel() const
+{
+ return m_shortLabel;
+}
+
+QString RosegardenParameterBox::getLongLabel() const
+{
+ return m_longLabel;
+}
+
+QString RosegardenParameterBox::getPreviousBox(RosegardenParameterArea::Arrangement) const
+{
+ // No ordering known -- depends on subclasses
+ return "";
+}
+
+}
+#include "RosegardenParameterBox.moc"
diff --git a/src/gui/editors/parameters/RosegardenParameterBox.h b/src/gui/editors/parameters/RosegardenParameterBox.h
new file mode 100644
index 0000000..6f17358
--- /dev/null
+++ b/src/gui/editors/parameters/RosegardenParameterBox.h
@@ -0,0 +1,92 @@
+
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef _RG_ROSEGARDENPARAMETERBOX_H_
+#define _RG_ROSEGARDENPARAMETERBOX_H_
+
+#include "RosegardenParameterArea.h"
+#include <qfont.h>
+#include <qframe.h>
+#include <qstring.h>
+#include <klocale.h>
+
+
+class QWidget;
+
+
+namespace Rosegarden
+{
+
+
+
+/**
+ * A flat QFrame, in which a group of parameters can be laid out.
+ * Virtual method functions are defined for for requesting a layout
+ * style, and returning the single-word to use for labelling the
+ * box.
+ */
+
+class RosegardenParameterBox : public QFrame
+{
+ Q_OBJECT
+public:
+ RosegardenParameterBox(const QString &shortLabel, // e.g. i18n("Track")
+ const QString &longLabel, // e.g. i18n("Track Parameters")
+ QWidget *parent = 0,
+ const char *name = 0);
+
+ // Ask for a one-word string that can be used to label the widget.
+ QString getShortLabel() const;
+
+ // Ask for the full label (e.g. short-label "Parameters")
+ QString getLongLabel() const;
+
+ // Get the short label of the prior parameter box (to establish an ordering)
+ virtual QString getPreviousBox(RosegardenParameterArea::Arrangement) const;
+
+ virtual void showAdditionalControls(bool) = 0;
+
+protected:
+ void init();
+
+ // List the layout styles that may be requested via a call to setStyle().
+
+ enum LayoutMode {
+ LANDSCAPE_MODE, // Optimize the layout for a tall and narrow parent.
+ PORTRAIT_MODE // Optimize the layout for a short and wide parent.
+ };
+
+ void setLayoutMode(LayoutMode mode);
+
+ QFont m_font;
+ QString m_shortLabel; // The string that containers can use for labelling and identification
+ QString m_longLabel; // The full title
+ LayoutMode m_mode; // The current layout mode.
+};
+
+
+}
+
+#endif
diff --git a/src/gui/editors/parameters/SegmentParameterBox.cpp b/src/gui/editors/parameters/SegmentParameterBox.cpp
new file mode 100644
index 0000000..c17cbe2
--- /dev/null
+++ b/src/gui/editors/parameters/SegmentParameterBox.cpp
@@ -0,0 +1,1214 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "SegmentParameterBox.h"
+#include <qlayout.h>
+#include <kapplication.h>
+
+#include <klocale.h>
+#include "misc/Debug.h"
+#include "misc/Strings.h"
+#include "document/ConfigGroups.h"
+#include "base/Colour.h"
+#include "base/ColourMap.h"
+#include "base/Composition.h"
+#include "base/MidiProgram.h"
+#include "base/NotationTypes.h"
+#include "base/BasicQuantizer.h"
+#include "base/RealTime.h"
+#include "base/Segment.h"
+#include "base/Selection.h"
+#include "commands/segment/SegmentChangeQuantizationCommand.h"
+#include "commands/segment/SegmentColourCommand.h"
+#include "commands/segment/SegmentColourMapCommand.h"
+#include "commands/segment/SegmentCommandRepeat.h"
+#include "commands/segment/SegmentLabelCommand.h"
+#include "document/MultiViewCommandHistory.h"
+#include "document/RosegardenGUIDoc.h"
+#include "gui/dialogs/PitchPickerDialog.h"
+#include "gui/editors/notation/NotationStrings.h"
+#include "gui/editors/notation/NotePixmapFactory.h"
+#include "gui/general/GUIPalette.h"
+#include "gui/widgets/ColourTable.h"
+#include "gui/widgets/TristateCheckBox.h"
+#include "RosegardenParameterArea.h"
+#include "RosegardenParameterBox.h"
+#include <kcolordialog.h>
+#include <kcombobox.h>
+#include <kcommand.h>
+#include <kconfig.h>
+#include <klineeditdlg.h>
+#include <ktabwidget.h>
+#include <qbutton.h>
+#include <qcheckbox.h>
+#include <qcolor.h>
+#include <qdialog.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qscrollview.h>
+#include <qspinbox.h>
+#include <qstring.h>
+#include <qtooltip.h>
+#include <qvbox.h>
+#include <qwidget.h>
+#include <qwidgetstack.h>
+
+
+namespace Rosegarden
+{
+
+SegmentParameterBox::SegmentParameterBox(RosegardenGUIDoc* doc,
+ QWidget *parent)
+ : RosegardenParameterBox(i18n("Segment"),
+ i18n("Segment Parameters"),
+ parent),
+ m_highestPlayable(127),
+ m_lowestPlayable(0),
+ m_standardQuantizations(BasicQuantizer::getStandardQuantizations()),
+ m_doc(doc),
+ m_transposeRange(48)
+{
+ initBox();
+
+ m_doc->getComposition().addObserver(this);
+
+ connect(getCommandHistory(), SIGNAL(commandExecuted()),
+ this, SLOT(update()));
+}
+
+SegmentParameterBox::~SegmentParameterBox()
+{
+ if (!isCompositionDeleted()) {
+ m_doc->getComposition().removeObserver(this);
+ }
+}
+
+void
+SegmentParameterBox::initBox()
+{
+ QFont font(m_font);
+
+ QFontMetrics fontMetrics(font);
+ // magic numbers: 13 is the height of the menu pixmaps, 10 is just 10
+ //int comboHeight = std::max(fontMetrics.height(), 13) + 10;
+ int width = fontMetrics.width("12345678901234567890");
+
+ // QFrame *frame = new QFrame(this);
+ QGridLayout *gridLayout = new QGridLayout(this, 8, 6, 4, 2);
+
+ QLabel *label = new QLabel(i18n("Label"), this);
+ QLabel *repeatLabel = new QLabel(i18n("Repeat"), this);
+ QLabel *quantizeLabel = new QLabel(i18n("Quantize"), this);
+ QLabel *transposeLabel = new QLabel(i18n("Transpose"), this);
+ QLabel *delayLabel = new QLabel(i18n("Delay"), this);
+ QLabel *colourLabel = new QLabel(i18n("Color"), this);
+// m_autoFadeLabel = new QLabel(i18n("Audio auto-fade"), this);
+// m_fadeInLabel = new QLabel(i18n("Fade in"), this);
+// m_fadeOutLabel = new QLabel(i18n("Fade out"), this);
+// m_rangeLabel = new QLabel(i18n("Range"), this);
+
+ // Label ..
+ m_label = new QLabel(this);
+ m_label->setFont(font);
+ m_label->setFixedWidth(width);
+ //m_label->setFixedHeight(comboHeight);
+ m_label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+
+ // .. and edit button
+ m_labelButton = new QPushButton(i18n("Edit"), this);
+ m_labelButton->setFont(font);
+ // m_labelButton->setFixedWidth(50);
+
+ connect(m_labelButton, SIGNAL(released()),
+ SLOT(slotEditSegmentLabel()));
+
+ m_repeatValue = new TristateCheckBox(this);
+ m_repeatValue->setFont(font);
+ //m_repeatValue->setFixedHeight(comboHeight);
+
+ // handle state changes
+ connect(m_repeatValue, SIGNAL(pressed()), SLOT(slotRepeatPressed()));
+
+ // non-reversing motif style read-only combo
+ m_quantizeValue = new KComboBox(this);
+ m_quantizeValue->setFont(font);
+ //m_quantizeValue->setFixedHeight(comboHeight);
+
+ // handle quantize changes from drop down
+ connect(m_quantizeValue, SIGNAL(activated(int)),
+ SLOT(slotQuantizeSelected(int)));
+
+ // reversing motif style read-write combo
+ m_transposeValue = new KComboBox(this);
+ m_transposeValue->setFont(font);
+ //m_transposeValue->setFixedHeight(comboHeight);
+
+ // handle transpose combo changes
+ connect(m_transposeValue, SIGNAL(activated(int)),
+ SLOT(slotTransposeSelected(int)));
+
+ // and text changes
+ connect(m_transposeValue, SIGNAL(textChanged(const QString&)),
+ SLOT(slotTransposeTextChanged(const QString&)));
+
+ // reversing motif style read-write combo
+ m_delayValue = new KComboBox(this);
+ m_delayValue->setFont(font);
+ //m_delayValue->setFixedHeight(comboHeight);
+
+ // handle delay combo changes
+ connect(m_delayValue, SIGNAL(activated(int)),
+ SLOT(slotDelaySelected(int)));
+
+ // Detect when the document colours are updated
+ connect(m_doc, SIGNAL(docColoursChanged()),
+ this, SLOT(slotDocColoursChanged()));
+
+ // handle text changes for delay
+ connect(m_delayValue, SIGNAL(textChanged(const QString&)),
+ SLOT(slotDelayTextChanged(const QString &)));
+
+ // set up combo box for colours
+ m_colourValue = new KComboBox(false, this);
+ m_colourValue->setFont(font);
+ //m_colourValue->setFixedHeight(comboHeight);
+ // m_colourValue->setMaximumWidth(width);
+ m_colourValue->setSizeLimit(20);
+
+ // handle colour combo changes
+ connect(m_colourValue, SIGNAL(activated(int)),
+ SLOT(slotColourSelected(int)));
+
+ // pre-set width of buttons so they don't grow later
+// width = fontMetrics.width(i18n("used internally for spacing", "High: ----"));
+
+ // highest playable note
+ //
+// m_highButton = new QPushButton(i18n("High: ---"), this);
+// QToolTip::add
+// (m_highButton, i18n("Choose the highest suggested playable note, using a staff"));
+// m_highButton->setFont(font);
+// m_highButton->setMinimumWidth(width);
+
+// connect(m_highButton, SIGNAL(released()),
+// SLOT(slotHighestPressed()));
+
+ // lowest playable note
+ //
+// m_lowButton = new QPushButton(i18n("Low: ----"), this);
+// QToolTip::add
+// (m_lowButton, i18n("Choose the lowest suggested playable note, using a staff"));
+// m_lowButton->setFont(font);
+// m_lowButton->setMinimumWidth(width);
+
+// connect(m_lowButton, SIGNAL(released()),
+// SLOT(slotLowestPressed()));
+
+ // Audio autofade enabled
+ //
+// m_autoFadeBox = new QCheckBox(this);
+// connect(m_autoFadeBox, SIGNAL(stateChanged(int)),
+// this, SLOT(slotAudioFadeChanged(int)));
+
+ // Fade in and out times
+ //
+// m_fadeInSpin = new QSpinBox(this);
+// m_fadeInSpin->setMinValue(0);
+// m_fadeInSpin->setMaxValue(5000);
+// m_fadeInSpin->setSuffix(i18n(" ms"));
+// connect(m_fadeInSpin, SIGNAL(valueChanged(int)),
+// this, SLOT(slotFadeInChanged(int)));
+
+// m_fadeOutSpin = new QSpinBox(this);
+// m_fadeOutSpin->setMinValue(0);
+// m_fadeOutSpin->setMaxValue(5000);
+// m_fadeOutSpin->setSuffix(i18n(" ms"));
+// connect(m_fadeOutSpin, SIGNAL(valueChanged(int)),
+// this, SLOT(slotFadeOutChanged(int)));
+
+ label->setFont(font);
+ repeatLabel->setFont(font);
+ quantizeLabel->setFont(font);
+ transposeLabel->setFont(font);
+ delayLabel->setFont(font);
+ colourLabel->setFont(font);
+// m_autoFadeLabel->setFont(font);
+// m_fadeInLabel->setFont(font);
+// m_fadeOutLabel->setFont(font);
+// m_rangeLabel->setFont(font);
+
+ int row = 0;
+
+// gridLayout->addRowSpacing(0, 12); // why??
+
+ gridLayout->addWidget(label, row, 0); //, AlignRight);
+ gridLayout->addMultiCellWidget(m_label, row, row, 1, 4); //, AlignLeft);
+ gridLayout->addWidget(m_labelButton, row, 5); //, AlignLeft);
+ ++row;
+
+ gridLayout->addWidget(repeatLabel, row, 0); //, AlignRight);
+ gridLayout->addWidget(m_repeatValue, row, 1); //, AlignLeft);
+
+ gridLayout->addMultiCellWidget(transposeLabel, row, row, 2, 3, AlignRight);
+ gridLayout->addMultiCellWidget(m_transposeValue, row, row, 4, 5);
+ ++row;
+
+ gridLayout->addWidget(quantizeLabel, row, 0); //, AlignRight);
+ gridLayout->addMultiCellWidget(m_quantizeValue, row, row, 1, 2); //, AlignLeft);
+
+ gridLayout->addWidget(delayLabel, row, 3, AlignRight);
+ gridLayout->addMultiCellWidget(m_delayValue, row, row, 4, 5);
+ ++row;
+
+ gridLayout->addWidget(colourLabel, row, 0); //, AlignRight);
+ gridLayout->addMultiCellWidget(m_colourValue, row, row, 1, 5);
+ ++row;
+
+// gridLayout->addWidget(m_rangeLabel, row, 0); //, AlignRight);
+// gridLayout->addMultiCellWidget(m_lowButton, row, row, 1, 2);
+// gridLayout->addMultiCellWidget(m_highButton, row, row, 3, 4);
+// ++row;
+
+// m_autoFadeLabel->hide();
+// m_autoFadeBox->hide();
+ /*
+ gridLayout->addWidget(m_fadeInLabel, 5, 0, AlignRight);
+ gridLayout->addWidget(m_fadeInSpin, 5, 1);
+
+ gridLayout->addWidget(m_fadeOutLabel, 5, 2, AlignRight);
+ gridLayout->addWidget(m_fadeOutSpin, 5, 3);
+ */
+ // Configure the empty final row to accomodate any extra vertical space.
+
+ gridLayout->setRowStretch(gridLayout->numRows() - 1, 1);
+
+ // Configure the empty final column to accomodate any extra horizontal
+ // space.
+
+// gridLayout->setColStretch(gridLayout->numCols() - 1, 1);
+
+ // populate the quantize combo
+ //
+ QPixmap noMap = NotePixmapFactory::toQPixmap(NotePixmapFactory::makeToolbarPixmap("menu-no-note"));
+
+ for (unsigned int i = 0; i < m_standardQuantizations.size(); ++i) {
+
+ timeT time = m_standardQuantizations[i];
+ timeT error = 0;
+ QString label = NotationStrings::makeNoteMenuLabel(time, true, error);
+ QPixmap pmap = NotePixmapFactory::toQPixmap(NotePixmapFactory::makeNoteMenuPixmap(time, error));
+ m_quantizeValue->insertItem(error ? noMap : pmap, label);
+ }
+ m_quantizeValue->insertItem(noMap, i18n("Off"));
+
+ // default to last item
+ m_quantizeValue->setCurrentItem(m_quantizeValue->count() - 1);
+
+ // populate the transpose combo
+ //
+ for (int i = -m_transposeRange; i < m_transposeRange + 1; i++) {
+ m_transposeValue->insertItem(noMap, QString("%1").arg(i));
+ if (i == 0)
+ m_transposeValue->setCurrentItem(m_transposeValue->count() - 1);
+ }
+
+ m_delays.clear();
+
+ for (int i = 0; i < 6; i++) {
+ timeT time = 0;
+ if (i > 0 && i < 6) {
+ time = Note(Note::Hemidemisemiquaver).getDuration() << (i - 1);
+ } else if (i > 5) {
+ time = Note(Note::Crotchet).getDuration() * (i - 4);
+ }
+
+ m_delays.push_back(time);
+
+ // check if it's a valid note duration (it will be for the
+ // time defn above, but if we were basing it on the sequencer
+ // resolution it might not be) & include a note pixmap if so
+ //
+ timeT error = 0;
+ QString label = NotationStrings::makeNoteMenuLabel(time, true, error);
+ QPixmap pmap = NotePixmapFactory::toQPixmap(NotePixmapFactory::makeNoteMenuPixmap(time, error));
+ m_delayValue->insertItem((error ? noMap : pmap), label);
+ }
+
+ for (int i = 0; i < 10; i++) {
+ int rtd = (i < 5 ? ((i + 1) * 10) : ((i - 3) * 50));
+ m_realTimeDelays.push_back(rtd);
+ m_delayValue->insertItem(i18n("%1 ms").arg(rtd));
+ }
+
+ // set delay blank initially
+ m_delayValue->setCurrentItem( -1);
+
+ // populate m_colourValue
+ slotDocColoursChanged();
+
+ //!!! disabled until after 1.3
+// m_highButton->hide();
+// m_lowButton->hide();
+// m_rangeLabel->hide();
+ //////////////////////////////
+
+}
+
+void
+SegmentParameterBox::setDocument(RosegardenGUIDoc* doc)
+{
+ if (m_doc != 0)
+ disconnect(m_doc, SIGNAL(docColoursChanged()),
+ this, SLOT(slotDocColoursChanged()));
+
+ m_doc = doc;
+
+ // Detect when the document colours are updated
+ connect (m_doc, SIGNAL(docColoursChanged()),
+ this, SLOT(slotDocColoursChanged()));
+
+ slotDocColoursChanged(); // repopulate combo
+}
+
+void
+SegmentParameterBox::useSegment(Segment *segment)
+{
+ m_segments.clear();
+ m_segments.push_back(segment);
+ populateBoxFromSegments();
+}
+
+void
+SegmentParameterBox::useSegments(const SegmentSelection &segments)
+{
+ m_segments.clear();
+
+ m_segments.resize(segments.size());
+ std::copy(segments.begin(), segments.end(), m_segments.begin());
+
+ populateBoxFromSegments();
+}
+
+void
+SegmentParameterBox::slotDocColoursChanged()
+{
+ RG_DEBUG << "SegmentParameterBox::slotDocColoursChanged()" << endl;
+
+ m_colourValue->clear();
+ m_colourList.clear();
+ // Populate it from composition.m_segmentColourMap
+ ColourMap temp = m_doc->getComposition().getSegmentColourMap();
+
+ unsigned int i = 0;
+
+ for (RCMap::const_iterator it = temp.begin(); it != temp.end(); ++it) {
+ QString qtrunc(strtoqstr(it->second.second));
+ QPixmap colour(15, 15);
+ colour.fill(GUIPalette::convertColour(it->second.first));
+ if (qtrunc == "") {
+ m_colourValue->insertItem(colour, i18n("Default"), i);
+ } else {
+ // truncate name to 15 characters to avoid the combo forcing the
+ // whole kit and kaboodle too wide
+ if (qtrunc.length() > 15)
+ qtrunc = qtrunc.left(12) + "...";
+ m_colourValue->insertItem(colour, qtrunc, i);
+ }
+ m_colourList[it->first] = i; // maps colour number to menu index
+ ++i;
+ }
+
+ m_addColourPos = i;
+ m_colourValue->insertItem(i18n("Add New Color"), m_addColourPos);
+
+ m_colourValue->setCurrentItem(0);
+}
+
+void SegmentParameterBox::update()
+{
+ RG_DEBUG << "SegmentParameterBox::update()" << endl;
+
+ populateBoxFromSegments();
+}
+
+void
+SegmentParameterBox::segmentRemoved(const Composition *composition,
+ Segment *segment)
+{
+ if (composition == &m_doc->getComposition()) {
+
+ for (std::vector<Segment*>::iterator it =
+ m_segments.begin(); it != m_segments.end(); ++it) {
+
+ if (*it == segment) {
+ m_segments.erase(it);
+ return ;
+ }
+ }
+ }
+}
+
+void
+SegmentParameterBox::populateBoxFromSegments()
+{
+ std::vector<Segment*>::iterator it;
+ Tristate repeated = NotApplicable;
+ Tristate quantized = NotApplicable;
+ Tristate transposed = NotApplicable;
+ Tristate delayed = NotApplicable;
+ Tristate diffcolours = NotApplicable;
+ Tristate highlow = NotApplicable;
+ unsigned int myCol = 0;
+ unsigned int myHigh = 127;
+ unsigned int myLow = 0;
+
+ timeT qntzLevel = 0;
+ // At the moment we have no negative delay, so we use negative
+ // values to represent real-time delay in ms
+ timeT delayLevel = 0;
+ int transposeLevel = 0;
+
+ if (m_segments.size() == 0)
+ m_label->setText("");
+ else
+ m_label->setText(strtoqstr(m_segments[0]->getLabel()));
+
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ // ok, first thing is we know we have at least one segment
+ if (repeated == NotApplicable)
+ repeated = None;
+ if (quantized == NotApplicable)
+ quantized = None;
+ if (transposed == NotApplicable)
+ transposed = None;
+ if (delayed == NotApplicable)
+ delayed = None;
+ if (diffcolours == NotApplicable)
+ diffcolours = None;
+ if (highlow == NotApplicable)
+ highlow = None;
+
+ // Set label to "*" when multiple labels don't match
+ //
+ if (strtoqstr((*it)->getLabel()) != m_label->text())
+ m_label->setText("*");
+
+ // Are all, some or none of the Segments repeating?
+ if ((*it)->isRepeating()) {
+ if (it == m_segments.begin())
+ repeated = All;
+ else {
+ if (repeated == None)
+ repeated = Some;
+ }
+ } else {
+ if (repeated == All)
+ repeated = Some;
+ }
+
+ // Quantization
+ //
+ if ((*it)->hasQuantization()) {
+ if (it == m_segments.begin()) {
+ quantized = All;
+ qntzLevel = (*it)->getQuantizer()->getUnit();
+ } else {
+ // If quantize levels don't match
+ if (quantized == None ||
+ (quantized == All &&
+ qntzLevel !=
+ (*it)->getQuantizer()->getUnit()))
+ quantized = Some;
+ }
+ } else {
+ if (quantized == All)
+ quantized = Some;
+ }
+
+ // Transpose
+ //
+ if ((*it)->getTranspose() != 0) {
+ if (it == m_segments.begin()) {
+ transposed = All;
+ transposeLevel = (*it)->getTranspose();
+ } else {
+ if (transposed == None ||
+ (transposed == All &&
+ transposeLevel != (*it)->getTranspose()))
+ transposed = Some;
+ }
+
+ } else {
+ if (transposed == All)
+ transposed = Some;
+ }
+
+ // Delay
+ //
+ timeT myDelay = (*it)->getDelay();
+ if (myDelay == 0) {
+ myDelay = -((*it)->getRealTimeDelay().sec * 1000 +
+ (*it)->getRealTimeDelay().msec());
+ }
+
+ if (myDelay != 0) {
+ if (it == m_segments.begin()) {
+ delayed = All;
+ delayLevel = myDelay;
+ } else {
+ if (delayed == None ||
+ (delayed == All &&
+ delayLevel != myDelay))
+ delayed = Some;
+ }
+ } else {
+ if (delayed == All)
+ delayed = Some;
+ }
+
+ // Colour
+
+ if (it == m_segments.begin()) {
+ myCol = (*it)->getColourIndex();
+ } else {
+ if (myCol != (*it)->getColourIndex())
+ ;
+ diffcolours = All;
+ }
+
+ // Highest/Lowest playable
+ //
+ if (it == m_segments.begin()) {
+ myHigh = (*it)->getHighestPlayable();
+ myLow = (*it)->getLowestPlayable();
+ } else {
+ if (myHigh != (*it)->getHighestPlayable() ||
+ myLow != (*it)->getLowestPlayable()) {
+ highlow = All;
+ }
+ }
+
+ }
+
+ switch (repeated) {
+ case All:
+ m_repeatValue->setChecked(true);
+ break;
+
+ case Some:
+ m_repeatValue->setNoChange();
+ break;
+
+ case None:
+ case NotApplicable:
+ default:
+ m_repeatValue->setChecked(false);
+ break;
+ }
+
+ m_repeatValue->setEnabled(repeated != NotApplicable);
+
+ switch (quantized) {
+ case All: {
+ for (unsigned int i = 0;
+ i < m_standardQuantizations.size(); ++i) {
+ if (m_standardQuantizations[i] == qntzLevel) {
+ m_quantizeValue->setCurrentItem(i);
+ break;
+ }
+ }
+ }
+ break;
+
+ case Some:
+ // Set the edit text to an unfeasible blank value meaning "Some"
+ //
+ m_quantizeValue->setCurrentItem( -1);
+ break;
+
+ // Assuming "Off" is always the last field
+ case None:
+ default:
+ m_quantizeValue->setCurrentItem(m_quantizeValue->count() - 1);
+ break;
+ }
+
+ m_quantizeValue->setEnabled(quantized != NotApplicable);
+
+ switch (transposed) {
+ // setCurrentItem works with QStrings
+ // 2nd arg of "true" means "add if necessary"
+ case All:
+ m_transposeValue->
+ setCurrentItem(QString("%1").arg(transposeLevel), true);
+ break;
+
+ case Some:
+ m_transposeValue->setCurrentItem(QString(""), true);
+ break;
+
+ case None:
+ default:
+ m_transposeValue->setCurrentItem("0");
+ break;
+ }
+
+ m_transposeValue->setEnabled(transposed != NotApplicable);
+
+ m_delayValue->blockSignals(true);
+
+ switch (delayed) {
+ case All:
+ if (delayLevel >= 0) {
+ timeT error = 0;
+ QString label = NotationStrings::makeNoteMenuLabel(delayLevel,
+ true,
+ error);
+ m_delayValue->setCurrentItem(label, true);
+
+ } else if (delayLevel < 0) {
+
+ m_delayValue->setCurrentItem(i18n("%1 ms").arg( -delayLevel),
+ true);
+ }
+
+ break;
+
+ case Some:
+ m_delayValue->setCurrentItem("", true);
+ break;
+
+ case None:
+ default:
+ m_delayValue->setCurrentItem(0);
+ break;
+ }
+
+ m_delayValue->setEnabled(delayed != NotApplicable);
+
+ m_delayValue->blockSignals(false);
+
+ switch (diffcolours) {
+ case None:
+ if (m_colourList.find(myCol) != m_colourList.end())
+ m_colourValue->setCurrentItem(m_colourList[myCol]);
+ else
+ m_colourValue->setCurrentItem(0);
+ break;
+
+
+ case All:
+ case NotApplicable:
+ default:
+ m_colourValue->setCurrentItem(0);
+ break;
+
+ }
+
+ m_colourValue->setEnabled(diffcolours != NotApplicable);
+
+ //!!! this is all borked up and useless; sort out after 1.3
+/*
+ switch (highlow) {
+ case All:
+ updateHighLow();
+ break;
+
+ case Some:
+ case None:
+ default:
+ m_highButton->setText(i18n("High: ---"));
+ m_lowButton->setText(i18n("Low: ----"));
+ highlow = NotApplicable;
+ break;
+ }
+
+ m_highButton->setEnabled(highlow != NotApplicable);
+ m_lowButton->setEnabled(highlow != NotApplicable);
+*/
+
+ // Enable or disable the fade in/out params
+/*
+ if (m_segments.size() == 1 &&
+ (*(m_segments.begin()))->getType() == Segment::Audio) {
+ m_autoFadeBox->blockSignals(true);
+ m_fadeInSpin->blockSignals(true);
+ m_fadeOutSpin->blockSignals(true);
+
+ ... !!! No, not setting up autofade widgets. The implementation's too
+ incomplete to finish for this release.
+
+ (Or for the next one after the one the previous comment referred to.)
+
+ (Or for the one after the one after that. Will we ever get those
+ working, or should Rich's final legacy simply be quietly disappeared?)
+
+ m_fadeInLabel->show();
+ m_fadeInSpin->show();
+ m_fadeOutLabel->show();
+ m_fadeOutSpin->show();
+
+ instead:
+
+ m_fadeInLabel->hide();
+ m_fadeInSpin->hide();
+ m_fadeOutLabel->hide();
+ m_fadeOutSpin->hide();
+
+ m_autoFadeLabel->setEnabled(true);
+ m_autoFadeBox->setEnabled(true);
+ m_fadeInLabel->setEnabled(true);
+ m_fadeInSpin->setEnabled(true);
+ m_fadeOutLabel->setEnabled(true);
+ m_fadeOutSpin->setEnabled(true);
+
+ Segment *seg = *(m_segments.begin());
+
+ int fadeInTime = seg->getFadeInTime().sec * 1000 +
+ seg->getFadeInTime().msec();
+ m_fadeInSpin->setValue(fadeInTime);
+
+ int fadeOutTime = seg->getFadeOutTime().sec * 1000 +
+ seg->getFadeOutTime().msec();
+ m_fadeOutSpin->setValue(fadeOutTime);
+
+ m_autoFadeBox->setChecked(seg->isAutoFading());
+
+ m_autoFadeBox->blockSignals(false);
+ m_fadeInSpin->blockSignals(false);
+ m_fadeOutSpin->blockSignals(false);
+ } else {
+ m_autoFadeLabel->setEnabled(false);
+ m_autoFadeBox->setEnabled(false);
+ m_fadeInLabel->setEnabled(false);
+ m_fadeInSpin->setEnabled(false);
+ m_fadeOutLabel->setEnabled(false);
+ m_fadeOutSpin->setEnabled(false);
+
+ m_autoFadeLabel->hide();
+ m_autoFadeBox->hide();
+ m_fadeInLabel->hide();
+ m_fadeInSpin->hide();
+ m_fadeOutLabel->hide();
+ m_fadeOutSpin->hide();
+
+ m_autoFadeBox->setChecked(false);
+ m_fadeInSpin->setValue(0);
+ m_fadeOutSpin->setValue(0);
+ }
+*/
+
+}
+
+void SegmentParameterBox::slotRepeatPressed()
+{
+ if (m_segments.size() == 0)
+ return ;
+
+ bool state = false;
+
+ switch (m_repeatValue->state()) {
+ case QButton::Off:
+ state = true;
+ break;
+
+ case QButton::NoChange:
+ case QButton::On:
+ default:
+ state = false;
+ break;
+ }
+
+ // update the check box and all current Segments
+ m_repeatValue->setChecked(state);
+
+ addCommandToHistory(new SegmentCommandRepeat(m_segments, state));
+
+ // std::vector<Segment*>::iterator it;
+
+ // for (it = m_segments.begin(); it != m_segments.end(); it++)
+ // (*it)->setRepeating(state);
+}
+
+void
+SegmentParameterBox::slotQuantizeSelected(int qLevel)
+{
+ bool off = (qLevel == m_quantizeValue->count() - 1);
+
+ SegmentChangeQuantizationCommand *command =
+ new SegmentChangeQuantizationCommand
+ (off ? 0 : m_standardQuantizations[qLevel]);
+
+ std::vector<Segment*>::iterator it;
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ command->addSegment(*it);
+ }
+
+ addCommandToHistory(command);
+}
+
+void
+SegmentParameterBox::slotTransposeTextChanged(const QString &text)
+{
+ if (text.isEmpty() || m_segments.size() == 0)
+ return ;
+
+ int transposeValue = text.toInt();
+
+ // addCommandToHistory(new SegmentCommandChangeTransposeValue(m_segments,
+ // transposeValue));
+
+ std::vector<Segment*>::iterator it;
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ (*it)->setTranspose(transposeValue);
+ }
+
+ emit documentModified();
+}
+
+void
+SegmentParameterBox::slotTransposeSelected(int value)
+{
+ slotTransposeTextChanged(m_transposeValue->text(value));
+}
+
+void
+SegmentParameterBox::slotDelayTimeChanged(timeT delayValue)
+{
+ // by convention and as a nasty hack, we use negative timeT here
+ // to represent positive RealTime in ms
+
+ if (delayValue > 0) {
+
+ std::vector<Segment*>::iterator it;
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ (*it)->setDelay(delayValue);
+ (*it)->setRealTimeDelay(RealTime::zeroTime);
+ }
+
+ } else if (delayValue < 0) {
+
+ std::vector<Segment*>::iterator it;
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ (*it)->setDelay(0);
+ int sec = ( -delayValue) / 1000;
+ int nsec = (( -delayValue) - 1000 * sec) * 1000000;
+ (*it)->setRealTimeDelay(RealTime(sec, nsec));
+ }
+ } else {
+
+ std::vector<Segment*>::iterator it;
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ (*it)->setDelay(0);
+ (*it)->setRealTimeDelay(RealTime::zeroTime);
+ }
+ }
+
+ emit documentModified();
+}
+
+void
+SegmentParameterBox::slotDelayTextChanged(const QString &text)
+{
+ if (text.isEmpty() || m_segments.size() == 0)
+ return ;
+
+ slotDelayTimeChanged( -(text.toInt()));
+}
+
+void
+SegmentParameterBox::slotDelaySelected(int value)
+{
+ if (value < int(m_delays.size())) {
+ slotDelayTimeChanged(m_delays[value]);
+ } else {
+ slotDelayTimeChanged( -(m_realTimeDelays[value - m_delays.size()]));
+ }
+}
+
+void
+SegmentParameterBox::slotColourSelected(int value)
+{
+ if (value != m_addColourPos) {
+ unsigned int temp = 0;
+
+ ColourTable::ColourList::const_iterator pos;
+ for (pos = m_colourList.begin(); pos != m_colourList.end(); ++pos) {
+ if (pos->second == value) {
+ temp = pos->first;
+ break;
+ }
+ }
+
+ SegmentSelection segments;
+ std::vector<Segment*>::iterator it;
+
+ for (it = m_segments.begin(); it != m_segments.end(); ++it) {
+ segments.insert(*it);
+ }
+
+ SegmentColourCommand *command = new SegmentColourCommand(segments, temp);
+
+ addCommandToHistory(command);
+ } else {
+ ColourMap newMap = m_doc->getComposition().getSegmentColourMap();
+ QColor newColour;
+ bool ok = false;
+ QString newName = KLineEditDlg::getText(i18n("New Color Name"), i18n("Enter new name"),
+ i18n("New"), &ok);
+ if ((ok == true) && (!newName.isEmpty())) {
+ KColorDialog box(this, "", true);
+
+ int result = box.getColor(newColour);
+
+ if (result == KColorDialog::Accepted) {
+ Colour newRColour = GUIPalette::convertColour(newColour);
+ newMap.addItem(newRColour, qstrtostr(newName));
+ SegmentColourMapCommand *command = new SegmentColourMapCommand(m_doc, newMap);
+ addCommandToHistory(command);
+ slotDocColoursChanged();
+ }
+ }
+ // Else we don't do anything as they either didn't give a name·
+ // or didn't give a colour
+ }
+
+
+}
+
+void
+SegmentParameterBox::updateHighLow()
+{
+ // Key of C major and NoAccidental means any "black key" notes will be
+ // written as sharps.
+ Accidental accidental = Accidentals::NoAccidental;
+ Rosegarden::Key key = Rosegarden::Key("C major");
+
+ Pitch highest(m_highestPlayable, accidental);
+ Pitch lowest(m_lowestPlayable, accidental);
+
+ KConfig *config = kapp->config();
+ config->setGroup(GeneralOptionsConfigGroup);
+ int base = config->readNumEntry("midipitchoctave", -2);
+ //!!! FIXME this code is broken, and needs to be fixed after the fashion of
+ //the TPB, but I'm not bothering with that at this time, because they are
+ //going to be hidden for 1.3 anyway
+// m_highButton->setText(QString("&High: %1%2").arg(highest.getNoteName(key)).arg(highest.getOctave(base)));
+// m_lowButton->setText(QString("&Low: %1%2").arg(lowest.getNoteName(key)).arg(lowest.getOctave(base)));
+}
+
+void
+SegmentParameterBox::slotHighestPressed()
+{
+ RG_DEBUG << "SegmentParameterBox::slotHighestPressed()" << endl;
+
+ PitchPickerDialog dialog(0, m_highestPlayable, i18n("Highest playable note"));
+ std::vector<Segment*>::iterator it;
+
+ if (dialog.exec() == QDialog::Accepted) {
+ m_highestPlayable = dialog.getPitch();
+ updateHighLow();
+
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ (*it)->setHighestPlayable(m_highestPlayable);
+ }
+
+ emit documentModified();
+ }
+}
+
+void
+SegmentParameterBox::slotLowestPressed()
+{
+ RG_DEBUG << "SegmentParameterBox::slotLowestPressed()" << endl;
+
+ PitchPickerDialog dialog(0, m_lowestPlayable, i18n("Lowest playable note"));
+ std::vector<Segment*>::iterator it;
+
+ if (dialog.exec() == QDialog::Accepted) {
+ m_lowestPlayable = dialog.getPitch();
+ updateHighLow();
+
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ (*it)->setLowestPlayable(m_lowestPlayable);
+ }
+
+ emit documentModified();
+ }
+}
+
+MultiViewCommandHistory*
+SegmentParameterBox::getCommandHistory()
+{
+ return m_doc->getCommandHistory();
+}
+
+void
+SegmentParameterBox::addCommandToHistory(KCommand *command)
+{
+ m_doc->getCommandHistory()->addCommand(command);
+}
+
+void
+SegmentParameterBox::slotEditSegmentLabel()
+{
+ QString editLabel;
+
+ if (m_segments.size() == 0)
+ return ;
+ else if (m_segments.size() == 1)
+ editLabel = i18n("Modify Segment label");
+ else
+ editLabel = i18n("Modify Segments label");
+
+ bool ok = false;
+
+ // Remove the asterisk if we're using it
+ //
+ QString label = m_label->text();
+ if (label == "*")
+ label = "";
+
+ QString newLabel = KLineEditDlg::getText(editLabel,
+ i18n("Enter new label"),
+ m_label->text(),
+ &ok,
+ this);
+
+ if (ok) {
+ SegmentSelection segments;
+ std::vector<Segment*>::iterator it;
+ for (it = m_segments.begin(); it != m_segments.end(); ++it)
+ segments.insert(*it);
+
+ SegmentLabelCommand *command = new
+ SegmentLabelCommand(segments, newLabel);
+
+ addCommandToHistory(command);
+
+ // fix #1776915, maybe?
+ update();
+ }
+}
+
+void
+SegmentParameterBox::slotAudioFadeChanged(int value)
+{
+ RG_DEBUG << "SegmentParameterBox::slotAudioFadeChanged - value = "
+ << value << endl;
+/*
+ if (m_segments.size() == 0)
+ return ;
+
+ bool state = false;
+ if (value == QButton::On)
+ state = true;
+
+ std::vector<Segment*>::iterator it;
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ (*it)->setAutoFade(state);
+ }
+*/
+}
+
+void
+SegmentParameterBox::slotFadeInChanged(int value)
+{
+ RG_DEBUG << "SegmentParameterBox::slotFadeInChanged - value = "
+ << value << endl;
+/*
+ if (m_segments.size() == 0)
+ return ;
+
+ if (value == 0 && m_fadeOutSpin->value() == 0)
+ slotAudioFadeChanged(QButton::Off);
+ else
+ slotAudioFadeChanged(QButton::On);
+
+ // Convert from ms
+ //
+ RealTime fadeInTime(value / 1000, (value % 1000) * 1000000);
+
+ std::vector<Segment*>::iterator it;
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ (*it)->setFadeInTime(fadeInTime);
+ }
+
+ emit documentModified();
+*/
+}
+
+void
+SegmentParameterBox::slotFadeOutChanged(int value)
+{
+ RG_DEBUG << "SegmentParameterBox::slotFadeOutChanged - value = "
+ << value << endl;
+/*
+ if (m_segments.size() == 0)
+ return ;
+
+ if (value == 0 && m_fadeInSpin->value() == 0)
+ slotAudioFadeChanged(QButton::Off);
+ else
+ slotAudioFadeChanged(QButton::On);
+
+ // Convert from ms
+ //
+ RealTime fadeOutTime(value / 1000000, (value % 1000) * 10000000);
+
+ std::vector<Segment*>::iterator it;
+ for (it = m_segments.begin(); it != m_segments.end(); it++) {
+ (*it)->setFadeOutTime(fadeOutTime);
+ }
+
+ emit documentModified();
+*/
+}
+
+void
+SegmentParameterBox::showAdditionalControls(bool showThem)
+{
+ //!!! disabled until after 1.3
+ /* m_highButton->setShown(showThem);
+ m_lowButton->setShown(showThem);
+ m_rangeLabel->setShown(showThem); */
+}
+
+QString
+SegmentParameterBox::getPreviousBox(RosegardenParameterArea::Arrangement arrangement) const
+{
+ if (arrangement == RosegardenParameterArea::CLASSIC_STYLE) {
+ return "";
+ } else {
+ return i18n("Instrument");
+ }
+}
+
+}
+#include "SegmentParameterBox.moc"
diff --git a/src/gui/editors/parameters/SegmentParameterBox.h b/src/gui/editors/parameters/SegmentParameterBox.h
new file mode 100644
index 0000000..a8b0353
--- /dev/null
+++ b/src/gui/editors/parameters/SegmentParameterBox.h
@@ -0,0 +1,174 @@
+
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef _RG_SEGMENTPARAMETERBOX_H_
+#define _RG_SEGMENTPARAMETERBOX_H_
+
+#include "base/Composition.h"
+#include "base/MidiProgram.h"
+#include "gui/widgets/ColourTable.h"
+#include "RosegardenParameterArea.h"
+#include "RosegardenParameterBox.h"
+#include <qstring.h>
+#include <vector>
+#include "base/Event.h"
+
+
+class QWidget;
+class QSpinBox;
+class QPushButton;
+class QLabel;
+class QCheckBox;
+class KCommand;
+class KComboBox;
+
+
+namespace Rosegarden
+{
+
+class TristateCheckBox;
+class SegmentSelection;
+class Segment;
+class RosegardenGUIDoc;
+class MultiViewCommandHistory;
+class Composition;
+
+
+class SegmentParameterBox : public RosegardenParameterBox,
+ public CompositionObserver
+{
+Q_OBJECT
+
+public:
+
+ typedef enum
+ {
+ None,
+ Some,
+ All,
+ NotApplicable // no applicable segments selected
+ } Tristate;
+
+ SegmentParameterBox(RosegardenGUIDoc *doc,
+ QWidget *parent=0);
+ ~SegmentParameterBox();
+
+ // Use Segments to update GUI parameters
+ //
+ void useSegment(Segment *segment);
+ void useSegments(const SegmentSelection &segments);
+
+ // Command history stuff
+ MultiViewCommandHistory* getCommandHistory();
+ void addCommandToHistory(KCommand *command);
+
+ void setDocument(RosegardenGUIDoc*);
+
+ // CompositionObserver interface
+ //
+ virtual void segmentRemoved(const Composition *,
+ Segment *);
+
+ virtual void showAdditionalControls(bool showThem);
+
+ virtual QString getPreviousBox(RosegardenParameterArea::Arrangement) const;
+
+public slots:
+ void slotRepeatPressed();
+ void slotQuantizeSelected(int);
+
+ void slotTransposeSelected(int);
+ void slotTransposeTextChanged(const QString &);
+
+ void slotDelaySelected(int);
+ void slotDelayTimeChanged(timeT delayValue);
+ void slotDelayTextChanged(const QString &);
+
+ void slotEditSegmentLabel();
+
+ void slotColourSelected(int);
+ void slotDocColoursChanged();
+
+ void slotAudioFadeChanged(int);
+ void slotFadeInChanged(int);
+ void slotFadeOutChanged(int);
+
+ void slotHighestPressed();
+ void slotLowestPressed();
+
+ virtual void update();
+
+signals:
+ void documentModified();
+ void canvasModified();
+
+protected:
+ void initBox();
+ void populateBoxFromSegments();
+ void updateHighLow();
+
+ QLabel *m_label;
+// QLabel *m_rangeLabel;
+ QPushButton *m_labelButton;
+// QPushButton *m_highButton;
+// QPushButton *m_lowButton;
+ TristateCheckBox *m_repeatValue;
+ KComboBox *m_quantizeValue;
+ KComboBox *m_transposeValue;
+ KComboBox *m_delayValue;
+ KComboBox *m_colourValue;
+
+ // Audio autofade
+ //
+// QLabel *m_autoFadeLabel;
+// QCheckBox *m_autoFadeBox;
+// QLabel *m_fadeInLabel;
+// QSpinBox *m_fadeInSpin;
+// QLabel *m_fadeOutLabel;
+// QSpinBox *m_fadeOutSpin;
+
+ int m_addColourPos;
+
+ // used to keep track of highest/lowest as there is no associated spinbox
+ // to query for its value
+ int m_highestPlayable;
+ int m_lowestPlayable;
+
+ std::vector<Segment*> m_segments;
+ std::vector<timeT> m_standardQuantizations;
+ std::vector<timeT> m_delays;
+ std::vector<int> m_realTimeDelays;
+ ColourTable::ColourList m_colourList;
+
+ RosegardenGUIDoc *m_doc;
+
+ MidiByte m_transposeRange;
+};
+
+
+
+}
+
+#endif
diff --git a/src/gui/editors/parameters/TrackParameterBox.cpp b/src/gui/editors/parameters/TrackParameterBox.cpp
new file mode 100644
index 0000000..fc85346
--- /dev/null
+++ b/src/gui/editors/parameters/TrackParameterBox.cpp
@@ -0,0 +1,1022 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ This file is Copyright 2006
+ Pedro Lopez-Cabanillas <[email protected]>
+ D. Michael McIntyre <[email protected]>
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+
+#include "TrackParameterBox.h"
+#include <qlayout.h>
+#include <kapplication.h>
+
+#include <klocale.h>
+#include "misc/Debug.h"
+#include "misc/Strings.h"
+#include "gui/general/ClefIndex.h"
+#include "document/ConfigGroups.h"
+#include "base/AudioPluginInstance.h"
+#include "base/Colour.h"
+#include "base/ColourMap.h"
+#include "base/Composition.h"
+#include "base/Device.h"
+#include "base/Exception.h"
+#include "base/Instrument.h"
+#include "base/MidiDevice.h"
+#include "base/MidiProgram.h"
+#include "base/NotationTypes.h"
+#include "base/Studio.h"
+#include "base/Track.h"
+#include "base/StaffExportTypes.h"
+#include "commands/segment/SegmentSyncCommand.h"
+#include "document/RosegardenGUIDoc.h"
+#include "gui/dialogs/PitchPickerDialog.h"
+#include "gui/general/GUIPalette.h"
+#include "gui/general/PresetHandlerDialog.h"
+#include "gui/widgets/CollapsingFrame.h"
+#include "gui/widgets/ColourTable.h"
+#include "RosegardenParameterArea.h"
+#include "RosegardenParameterBox.h"
+#include "sound/PluginIdentifier.h"
+#include <kcolordialog.h>
+#include <kcombobox.h>
+#include <kconfig.h>
+#include <klineeditdlg.h>
+#include <kmessagebox.h>
+#include <ksqueezedtextlabel.h>
+#include <ktabwidget.h>
+#include <qcolor.h>
+#include <qdialog.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qregexp.h>
+#include <qscrollview.h>
+#include <qstring.h>
+#include <qtooltip.h>
+#include <qvbox.h>
+#include <qwidget.h>
+#include <qwidgetstack.h>
+#include <qcheckbox.h>
+
+
+namespace Rosegarden
+{
+
+TrackParameterBox::TrackParameterBox( RosegardenGUIDoc *doc,
+ QWidget *parent)
+ : RosegardenParameterBox(i18n("Track"),
+ i18n("Track Parameters"),
+ parent),
+ m_doc(doc),
+ m_highestPlayable(127),
+ m_lowestPlayable(0),
+ m_selectedTrackId( -1)
+{
+ QFont font(m_font);
+ QFont title_font(m_font);
+ QFontMetrics metrics(font);
+ int width11 = metrics.width("12345678901");
+ int width20 = metrics.width("12345678901234567890");
+ int width22 = metrics.width("1234567890123456789012");
+ int width25 = metrics.width("1234567890123456789012345");
+ setFont(m_font);
+ title_font.setBold(true);
+
+ // Set up default expansions for the collapsing elements
+ KConfig *config = kapp->config();
+ QString groupTemp = config->group();
+ config->setGroup("CollapsingFrame");
+ bool expanded = config->readBoolEntry("trackparametersplayback", true);
+ config->writeEntry("trackparametersplayback", expanded);
+ expanded = config->readBoolEntry("trackparametersrecord", false);
+ config->writeEntry("trackparametersrecord", expanded);
+ expanded = config->readBoolEntry("trackparametersdefaults", false);
+ config->writeEntry("trackparametersdefaults", expanded);
+ expanded = config->readBoolEntry("trackstaffgroup", false);
+ config->writeEntry("trackstaffgroup", expanded);
+ config->setGroup(groupTemp);
+
+ QGridLayout *mainLayout = new QGridLayout(this, 5, 1, 2, 1);
+
+ int row = 0;
+
+ // track label
+ //
+ m_trackLabel = new KSqueezedTextLabel(i18n("<untitled>"), this);
+ m_trackLabel->setAlignment(Qt::AlignCenter);
+ //mainLayout->addMultiCellWidget(m_trackLabel, 0, 0, 0, 5, AlignCenter);
+ mainLayout->addWidget(m_trackLabel, 0, 0);
+
+ // playback group
+ //
+ CollapsingFrame *cframe = new CollapsingFrame(i18n("Playback parameters"),
+ this, "trackparametersplayback");
+ m_playbackGroup = new QFrame(cframe);
+ cframe->setWidget(m_playbackGroup);
+ QGridLayout *groupLayout = new QGridLayout(m_playbackGroup, 3, 3, 3, 2);
+
+ // playback group title
+ //
+ row = 0;
+
+ // playback device
+ //
+ // row++;
+ QLabel *devLabel = new QLabel(i18n("Device"), m_playbackGroup);
+ groupLayout->addWidget(devLabel, row, 0);
+ m_playDevice = new KComboBox(m_playbackGroup);
+ m_playDevice->setMinimumWidth(width25);
+ groupLayout->addMultiCellWidget(m_playDevice, row, row, 1, 2);
+
+ // playback instrument
+ //
+ row++;
+ QLabel *insLabel = new QLabel(i18n("Instrument"), m_playbackGroup);
+ groupLayout->addMultiCellWidget(insLabel, row, row, 0, 1);
+ m_instrument = new KComboBox(m_playbackGroup);
+ m_instrument->setSizeLimit( 16 );
+ m_instrument->setMinimumWidth(width22);
+ groupLayout->addWidget(m_instrument, row, 2);
+
+ groupLayout->setColStretch(groupLayout->numCols() - 1, 1);
+
+ mainLayout->addWidget(cframe, 1, 0);
+
+ // record group
+ //
+ cframe = new CollapsingFrame(i18n("Recording filters"), this,
+ "trackparametersrecord");
+ m_recordGroup = new QFrame(cframe);
+ cframe->setWidget(m_recordGroup);
+ groupLayout = new QGridLayout(m_recordGroup, 3, 3, 3, 2);
+
+ // recording group title
+ //
+ row = 0;
+
+ // recording device
+ groupLayout->addWidget(new QLabel(i18n("Device"), m_recordGroup), row, 0);
+ m_recDevice = new KComboBox(m_recordGroup);
+ m_recDevice->setMinimumWidth(width25);
+ groupLayout->addMultiCellWidget(m_recDevice, row, row, 1, 2);
+
+ // recording channel
+ //
+ row++;
+ groupLayout->addMultiCellWidget(new QLabel(i18n("Channel"), m_recordGroup), row, row, 0, 1);
+ m_recChannel = new KComboBox(m_recordGroup);
+ m_recChannel->setSizeLimit( 17 );
+ m_recChannel->setMinimumWidth(width11);
+ groupLayout->addWidget(m_recChannel, row, 2);
+
+ groupLayout->setColStretch(groupLayout->numCols() - 1, 1);
+
+ mainLayout->addWidget(cframe, 2, 0);
+
+ // staff group
+ //
+ cframe = new CollapsingFrame(i18n("Staff export options"), this,
+ "staffoptions");
+ m_staffGroup = new QFrame(cframe);
+ cframe->setWidget(m_staffGroup);
+ groupLayout = new QGridLayout(m_staffGroup, 2, 2, 2, 2);
+
+ groupLayout->setColStretch(1, 1);
+
+ row = 0;
+
+ // Notation size (export only)
+ //
+ // NOTE: This is the only way to get a \small or \tiny inserted before the
+ // first note in LilyPond export. Setting the actual staff size on a
+ // per-staff (rather than per-score) basis is something the author of the
+ // LilyPond documentation has no idea how to do, so we settle for this,
+ // which is not as nice, but actually a lot easier to implement.
+ m_staffGrpLbl = new QLabel(i18n("Notation size:"), m_staffGroup);
+ groupLayout->addWidget(m_staffGrpLbl, row, 0, AlignLeft);
+ m_staffSizeCombo = new KComboBox(m_staffGroup);
+ m_staffSizeCombo->setMinimumWidth(width11);
+ m_staffSizeCombo->insertItem(i18n("Normal"), StaffTypes::Normal);
+ m_staffSizeCombo->insertItem(i18n("Small"), StaffTypes::Small);
+ m_staffSizeCombo->insertItem(i18n("Tiny"), StaffTypes::Tiny);
+
+ groupLayout->addMultiCellWidget(m_staffSizeCombo, row, row, 1, 2);
+
+ // Staff bracketing (export only at the moment, but using this for GUI
+ // rendering would be nice in the future!) //!!!
+ row++;
+ m_grandStaffLbl = new QLabel(i18n("Bracket type:"), m_staffGroup);
+ groupLayout->addWidget(m_grandStaffLbl, row, 0, AlignLeft);
+ m_staffBracketCombo = new KComboBox(m_staffGroup);
+ m_staffBracketCombo->setMinimumWidth(width11);
+ m_staffBracketCombo->insertItem(i18n("-----"), Brackets::None);
+ m_staffBracketCombo->insertItem(i18n("[----"), Brackets::SquareOn);
+ m_staffBracketCombo->insertItem(i18n("----]"), Brackets::SquareOff);
+ m_staffBracketCombo->insertItem(i18n("[---]"), Brackets::SquareOnOff);
+ m_staffBracketCombo->insertItem(i18n("{----"), Brackets::CurlyOn);
+ m_staffBracketCombo->insertItem(i18n("----}"), Brackets::CurlyOff);
+ m_staffBracketCombo->insertItem(i18n("{[---"), Brackets::CurlySquareOn);
+ m_staffBracketCombo->insertItem(i18n("---]}"), Brackets::CurlySquareOff);
+
+ groupLayout->addMultiCellWidget(m_staffBracketCombo, row, row, 1, 2);
+
+ mainLayout->addWidget(cframe, 3, 0);
+
+
+ // default segment group
+ //
+ cframe = new CollapsingFrame(i18n("Create segments with"), this,
+ "trackparametersdefaults");
+ m_defaultsGroup = new QFrame(cframe);
+ cframe->setWidget(m_defaultsGroup);
+ groupLayout = new QGridLayout(m_defaultsGroup, 6, 6, 3, 2);
+
+ groupLayout->setColStretch(1, 1);
+
+ row = 0;
+
+ // preset picker
+ m_psetLbl = new QLabel(i18n("Preset"), m_defaultsGroup);
+ groupLayout->addWidget(m_psetLbl, row, 0, AlignLeft);
+
+ m_presetLbl = new QLabel(i18n("<none>"), m_defaultsGroup);
+ m_presetLbl->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+ m_presetLbl->setFixedWidth(width20);
+ groupLayout->addMultiCellWidget(m_presetLbl, row, row, 1, 3);
+
+ m_presetButton = new QPushButton(i18n("Load"), m_defaultsGroup);
+ groupLayout->addMultiCellWidget(m_presetButton, row, row, 4, 5);
+
+ // default clef
+ //
+ row++;
+ m_clefLbl = new QLabel(i18n("Clef"), m_defaultsGroup);
+ groupLayout->addWidget(m_clefLbl, row, 0, AlignLeft);
+ m_defClef = new KComboBox(m_defaultsGroup);
+ m_defClef->setMinimumWidth(width11);
+ m_defClef->insertItem(i18n("treble"), TrebleClef);
+ m_defClef->insertItem(i18n("bass"), BassClef);
+ m_defClef->insertItem(i18n("crotales"), CrotalesClef);
+ m_defClef->insertItem(i18n("xylophone"), XylophoneClef);
+ m_defClef->insertItem(i18n("guitar"), GuitarClef);
+ m_defClef->insertItem(i18n("contrabass"), ContrabassClef);
+ m_defClef->insertItem(i18n("celesta"), CelestaClef);
+ m_defClef->insertItem(i18n("old celesta"), OldCelestaClef);
+ m_defClef->insertItem(i18n("french"), FrenchClef);
+ m_defClef->insertItem(i18n("soprano"), SopranoClef);
+ m_defClef->insertItem(i18n("mezzosoprano"), MezzosopranoClef);
+ m_defClef->insertItem(i18n("alto"), AltoClef);
+ m_defClef->insertItem(i18n("tenor"), TenorClef);
+ m_defClef->insertItem(i18n("baritone"), BaritoneClef);
+ m_defClef->insertItem(i18n("varbaritone"), VarbaritoneClef);
+ m_defClef->insertItem(i18n("subbass"), SubbassClef);
+ /* clef types in the datbase that are not yet supported must be ignored for
+ * now:
+ m_defClef->insertItem(i18n("two bar"), TwoBarClef); */
+ groupLayout->addMultiCellWidget(m_defClef, row, row, 1, 2);
+
+ // default transpose
+ //
+ m_transpLbl = new QLabel(i18n("Transpose"), m_defaultsGroup);
+ groupLayout->addMultiCellWidget(m_transpLbl, row, row, 3, 4, AlignRight);
+ m_defTranspose = new KComboBox(m_defaultsGroup);
+
+ connect(m_defTranspose, SIGNAL(activated(int)),
+ SLOT(slotTransposeIndexChanged(int)));
+
+ int transposeRange = 48;
+ for (int i = -transposeRange; i < transposeRange + 1; i++) {
+ m_defTranspose->insertItem(QString("%1").arg(i));
+ if (i == 0)
+ m_defTranspose->setCurrentItem(m_defTranspose->count() - 1);
+ }
+
+ groupLayout->addMultiCellWidget(m_defTranspose, row, row, 5, 5);
+
+ // highest/lowest playable note
+ //
+ row++;
+ m_rangeLbl = new QLabel(i18n("Pitch"), m_defaultsGroup);
+ groupLayout->addMultiCellWidget(m_rangeLbl, row, row, 0, 0);
+
+ groupLayout->addWidget(new QLabel(i18n("Lowest"), m_defaultsGroup), row, 1, AlignRight);
+
+ m_lowButton = new QPushButton(i18n("---"), m_defaultsGroup);
+ QToolTip::add
+ (m_lowButton, i18n("Choose the lowest suggested playable note, using a staff"));
+ groupLayout->addMultiCellWidget(m_lowButton, row, row, 2, 2);
+
+ groupLayout->addWidget(new QLabel(i18n("Highest"), m_defaultsGroup), row, 3, AlignRight);
+
+ m_highButton = new QPushButton(i18n("---"), m_defaultsGroup);
+ QToolTip::add
+ (m_highButton, i18n("Choose the highest suggested playable note, using a staff"));
+ groupLayout->addMultiCellWidget(m_highButton, row, row, 4, 5);
+
+ updateHighLow();
+
+ // default color
+ //
+ row++;
+ m_colorLbl = new QLabel(i18n("Color"), m_defaultsGroup);
+ groupLayout->addWidget(m_colorLbl, row, 0, AlignLeft);
+ m_defColor = new KComboBox(false, m_defaultsGroup);
+ m_defColor->setSizeLimit(20);
+ groupLayout->addMultiCellWidget(m_defColor, row, row, 1, 5);
+
+ // populate combo from doc colors
+ slotDocColoursChanged();
+
+ mainLayout->addWidget(cframe, 4, 0);
+
+
+ // Configure the empty final row to accomodate any extra vertical space.
+ //
+// mainLayout->setColStretch(mainLayout->numCols() - 1, 1);
+ mainLayout->setRowStretch(mainLayout->numRows() - 1, 1);
+
+ // Connections
+ connect( m_playDevice, SIGNAL(activated(int)),
+ this, SLOT(slotPlaybackDeviceChanged(int)));
+
+ connect( m_instrument, SIGNAL(activated(int)),
+ this, SLOT(slotInstrumentChanged(int)));
+
+ connect( m_recDevice, SIGNAL(activated(int)),
+ this, SLOT(slotRecordingDeviceChanged(int)));
+
+ connect( m_recChannel, SIGNAL(activated(int)),
+ this, SLOT(slotRecordingChannelChanged(int)));
+
+ connect( m_defClef, SIGNAL(activated(int)),
+ this, SLOT(slotClefChanged(int)));
+
+ // Detect when the document colours are updated
+ connect(m_doc, SIGNAL(docColoursChanged()),
+ this, SLOT(slotDocColoursChanged()));
+
+ // handle colour combo changes
+ connect(m_defColor, SIGNAL(activated(int)),
+ SLOT(slotColorChanged(int)));
+
+ connect(m_highButton, SIGNAL(released()),
+ SLOT(slotHighestPressed()));
+
+ connect(m_lowButton, SIGNAL(released()),
+ SLOT(slotLowestPressed()));
+
+ connect(m_presetButton, SIGNAL(released()),
+ SLOT(slotPresetPressed()));
+
+ connect(m_staffSizeCombo, SIGNAL(activated(int)),
+ this, SLOT(slotStaffSizeChanged(int)));
+
+ connect(m_staffBracketCombo, SIGNAL(activated(int)),
+ this, SLOT(slotStaffBracketChanged(int)));
+}
+
+TrackParameterBox::~TrackParameterBox()
+{}
+
+void
+
+TrackParameterBox::setDocument( RosegardenGUIDoc *doc )
+{
+ if (m_doc != doc) {
+ RG_DEBUG << "TrackParameterBox::setDocument\n";
+ m_doc = doc;
+ populateDeviceLists();
+ }
+}
+
+void
+TrackParameterBox::populateDeviceLists()
+{
+ RG_DEBUG << "TrackParameterBox::populateDeviceLists()\n";
+ populatePlaybackDeviceList();
+ //populateRecordingDeviceList();
+ slotUpdateControls( -1);
+ m_lastInstrumentType = -1;
+}
+
+void
+TrackParameterBox::populatePlaybackDeviceList()
+{
+ RG_DEBUG << "TrackParameterBox::populatePlaybackDeviceList()\n";
+ m_playDevice->clear();
+ m_playDeviceIds.clear();
+ m_instrument->clear();
+ m_instrumentIds.clear();
+ m_instrumentNames.clear();
+
+ Studio &studio = m_doc->getStudio();
+
+ // Get the list
+ InstrumentList list = studio.getPresentationInstruments();
+ InstrumentList::iterator it;
+ int currentDevId = -1;
+
+ for (it = list.begin(); it != list.end(); it++) {
+
+ if (! (*it))
+ continue; // sanity check
+
+ //QString iname(strtoqstr((*it)->getPresentationName()));
+ QString iname(strtoqstr((*it)->getName()));
+ QString pname(strtoqstr((*it)->getProgramName()));
+ Device *device = (*it)->getDevice();
+ DeviceId devId = device->getId();
+
+ if ((*it)->getType() == Instrument::SoftSynth) {
+ iname.replace("Synth plugin ", "");
+ pname = "";
+ AudioPluginInstance *plugin = (*it)->getPlugin
+ (Instrument::SYNTH_PLUGIN_POSITION);
+ if (plugin) {
+ pname = strtoqstr(plugin->getProgram());
+ QString identifier = strtoqstr(plugin->getIdentifier());
+ if (identifier != "") {
+ QString type, soName, label;
+ PluginIdentifier::parseIdentifier
+ (identifier, type, soName, label);
+ if (pname == "") {
+ pname = strtoqstr(plugin->getDistinctiveConfigurationText());
+ }
+ if (pname != "") {
+ pname = QString("%1: %2").arg(label).arg(pname);
+ } else {
+ pname = label;
+ }
+ }
+ }
+ }
+
+ if (devId != (DeviceId)(currentDevId)) {
+ currentDevId = int(devId);
+ QString deviceName = strtoqstr(device->getName());
+ m_playDevice->insertItem(deviceName);
+ m_playDeviceIds.push_back(currentDevId);
+ }
+
+ if (pname != "")
+ iname += " (" + pname + ")";
+ m_instrumentIds[currentDevId].push_back((*it)->getId());
+ m_instrumentNames[currentDevId].append(iname);
+
+ }
+
+ m_playDevice->setCurrentItem( -1);
+ m_instrument->setCurrentItem( -1);
+}
+
+void
+TrackParameterBox::populateRecordingDeviceList()
+{
+ RG_DEBUG << "TrackParameterBox::populateRecordingDeviceList()\n";
+
+ if (m_selectedTrackId < 0)
+ return ;
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(m_selectedTrackId);
+ if (!trk)
+ return ;
+
+ Instrument *inst = m_doc->getStudio().getInstrumentById(trk->getInstrument());
+ if (!inst)
+ return ;
+
+ if (m_lastInstrumentType != (char)inst->getInstrumentType()) {
+ m_lastInstrumentType = (char)inst->getInstrumentType();
+
+ m_recDevice->clear();
+ m_recDeviceIds.clear();
+ m_recChannel->clear();
+
+ if (inst->getInstrumentType() == Instrument::Audio) {
+
+ m_recDeviceIds.push_back(Device::NO_DEVICE);
+ m_recDevice->insertItem(i18n("Audio"));
+ m_recChannel->insertItem(i18n("Audio"));
+
+ m_recDevice->setEnabled(false);
+ m_recChannel->setEnabled(false);
+
+ // hide these for audio instruments
+ m_defaultsGroup->parentWidget()->setShown(false);
+
+ } else { // InstrumentType::Midi and InstrumentType::SoftSynth
+
+ // show these if not audio instrument
+ m_defaultsGroup->parentWidget()->setShown(true);
+
+ m_recDeviceIds.push_back(Device::ALL_DEVICES);
+ m_recDevice->insertItem(i18n("All"));
+
+ DeviceList *devices = m_doc->getStudio().getDevices();
+ DeviceListConstIterator it;
+ for (it = devices->begin(); it != devices->end(); it++) {
+ MidiDevice *dev =
+ dynamic_cast<MidiDevice*>(*it);
+ if (dev) {
+ if (dev->getDirection() == MidiDevice::Record
+ && dev->isRecording()) {
+ QString connection = strtoqstr(dev->getConnection());
+ // remove trailing "(duplex)", "(read only)", "(write only)" etc
+ connection.replace(QRegExp("\\s*\\([^)0-9]+\\)\\s*$"), "");
+ m_recDevice->insertItem(connection);
+ m_recDeviceIds.push_back(dev->getId());
+ }
+ }
+ }
+
+ m_recChannel->insertItem(i18n("All"));
+ for (int i = 1; i < 17; ++i) {
+ m_recChannel->insertItem(QString::number(i));
+ }
+
+ m_recDevice->setEnabled(true);
+ m_recChannel->setEnabled(true);
+ }
+ }
+
+ if (inst->getInstrumentType() == Instrument::Audio) {
+ m_recDevice->setCurrentItem(0);
+ m_recChannel->setCurrentItem(0);
+ } else {
+ m_recDevice->setCurrentItem(0);
+ m_recChannel->setCurrentItem((int)trk->getMidiInputChannel() + 1);
+ for (unsigned int i = 0; i < m_recDeviceIds.size(); ++i) {
+ if (m_recDeviceIds[i] == trk->getMidiInputDevice()) {
+ m_recDevice->setCurrentItem(i);
+ break;
+ }
+ }
+ }
+}
+
+void
+TrackParameterBox::updateHighLow()
+{
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+ if (!trk)
+ return ;
+
+ trk->setHighestPlayable(m_highestPlayable);
+ trk->setLowestPlayable(m_lowestPlayable);
+
+ Accidental accidental = Accidentals::NoAccidental;
+
+ Pitch highest(m_highestPlayable, accidental);
+ Pitch lowest(m_lowestPlayable, accidental);
+
+ KConfig *config = kapp->config();
+ config->setGroup(GeneralOptionsConfigGroup);
+ int base = config->readNumEntry("midipitchoctave", -2);
+ bool useSharps = true;
+ bool includeOctave = true;
+
+// m_highButton->setText(i18n("High: %1").arg(highest.getAsString(useSharps, includeOctave, base)));
+// m_lowButton->setText(i18n("Low: %1").arg(lowest.getAsString(useSharps, includeOctave, base)));
+ m_highButton->setText(QString("%1").arg(highest.getAsString(useSharps, includeOctave, base)));
+ m_lowButton->setText(QString("%1").arg(lowest.getAsString(useSharps, includeOctave, base)));
+
+ m_presetLbl->setEnabled(false);
+}
+
+void
+TrackParameterBox::slotUpdateControls(int /*dummy*/)
+{
+ RG_DEBUG << "TrackParameterBox::slotUpdateControls()\n";
+ slotPlaybackDeviceChanged( -1);
+ slotInstrumentChanged( -1);
+
+ if (m_selectedTrackId < 0)
+ return ;
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(m_selectedTrackId);
+ if (!trk)
+ return ;
+
+ m_defClef->setCurrentItem(trk->getClef());
+ m_defTranspose->setCurrentItem(QString("%1").arg(trk->getTranspose()), true);
+ m_defColor->setCurrentItem(trk->getColor());
+ m_highestPlayable = trk->getHighestPlayable();
+ m_lowestPlayable = trk->getLowestPlayable();
+ updateHighLow();
+ // set this down here because updateHighLow just disabled the label
+ m_presetLbl->setText(trk->getPresetLabel());
+ m_presetLbl->setEnabled(true);
+
+ m_staffSizeCombo->setCurrentItem(trk->getStaffSize());
+ m_staffBracketCombo->setCurrentItem(trk->getStaffBracket());
+}
+
+void
+TrackParameterBox::slotSelectedTrackChanged()
+{
+ RG_DEBUG << "TrackParameterBox::slotSelectedTrackChanged()\n";
+ Composition &comp = m_doc->getComposition();
+ TrackId newTrack = comp.getSelectedTrack();
+ if ( newTrack != m_selectedTrackId ) {
+ m_presetLbl->setEnabled(true);
+ m_selectedTrackId = newTrack;
+ slotSelectedTrackNameChanged();
+ slotUpdateControls( -1);
+ }
+}
+
+void
+TrackParameterBox::slotSelectedTrackNameChanged()
+{
+ RG_DEBUG << "TrackParameterBox::sotSelectedTrackNameChanged()\n";
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(m_selectedTrackId);
+ QString m_trackName = trk->getLabel();
+ if (m_trackName.isEmpty())
+ m_trackName = i18n("<untitled>");
+ else
+ m_trackName.truncate(20);
+ int trackNum = trk->getPosition() + 1;
+ m_trackLabel->setText(i18n("[ Track %1 - %2 ]").arg(trackNum).arg(m_trackName));
+}
+
+void
+TrackParameterBox::slotPlaybackDeviceChanged(int index)
+{
+ RG_DEBUG << "TrackParameterBox::slotPlaybackDeviceChanged(" << index << ")\n";
+ DeviceId devId;
+ if (index == -1) {
+ if (m_selectedTrackId < 0)
+ return ;
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(m_selectedTrackId);
+ if (!trk)
+ return ;
+ Instrument *inst = m_doc->getStudio().getInstrumentById(trk->getInstrument());
+ if (!inst)
+ return ;
+ devId = inst->getDevice()->getId();
+ int pos = -1;
+ IdsVector::const_iterator it;
+ for ( it = m_playDeviceIds.begin(); it != m_playDeviceIds.end(); ++it) {
+ pos++;
+ if ((*it) == devId)
+ break;
+ }
+ m_playDevice->setCurrentItem(pos);
+ } else {
+ devId = m_playDeviceIds[index];
+ }
+
+ m_instrument->clear();
+ m_instrument->insertStringList(m_instrumentNames[devId]);
+
+ populateRecordingDeviceList();
+
+ if (index != -1) {
+ m_instrument->setCurrentItem(0);
+ slotInstrumentChanged(0);
+ }
+}
+
+void
+TrackParameterBox::slotInstrumentChanged(int index)
+{
+ RG_DEBUG << "TrackParameterBox::slotInstrumentChanged(" << index << ")\n";
+ DeviceId devId;
+ Instrument *inst;
+ if (index == -1) {
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+ if (!trk)
+ return ;
+ inst = m_doc->getStudio().getInstrumentById(trk->getInstrument());
+ if (!inst)
+ return ;
+ devId = inst->getDevice()->getId();
+
+ int pos = -1;
+ IdsVector::const_iterator it;
+ for ( it = m_instrumentIds[devId].begin(); it != m_instrumentIds[devId].end(); ++it ) {
+ pos++;
+ if ((*it) == trk->getInstrument())
+ break;
+ }
+ m_instrument->setCurrentItem(pos);
+ } else {
+ devId = m_playDeviceIds[m_playDevice->currentItem()];
+ // set the new selected instrument for the track
+ int item = 0;
+ std::map<DeviceId, IdsVector>::const_iterator it;
+ for ( it = m_instrumentIds.begin(); it != m_instrumentIds.end(); ++it) {
+ if ( (*it).first == devId )
+ break;
+ item += (*it).second.size();
+ }
+ item += index;
+ RG_DEBUG << "TrackParameterBox::slotInstrumentChanged() item = " << item << "\n";
+ emit instrumentSelected( m_selectedTrackId, item );
+ }
+}
+
+void
+TrackParameterBox::slotRecordingDeviceChanged(int index)
+{
+ RG_DEBUG << "TrackParameterBox::slotRecordingDeviceChanged(" << index << ")" << endl;
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+ if (!trk)
+ return ;
+ Instrument *inst = m_doc->getStudio().getInstrumentById(trk->getInstrument());
+ if (!inst)
+ return ;
+ if (inst->getInstrumentType() == Instrument::Audio) {
+ //Not implemented yet
+ } else {
+ trk->setMidiInputDevice(m_recDeviceIds[index]);
+ }
+}
+
+void
+TrackParameterBox::slotRecordingChannelChanged(int index)
+{
+ RG_DEBUG << "TrackParameterBox::slotRecordingChannelChanged(" << index << ")" << endl;
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+ if (!trk)
+ return ;
+ Instrument *inst = m_doc->getStudio().getInstrumentById(trk->getInstrument());
+ if (!inst)
+ return ;
+ if (inst->getInstrumentType() == Instrument::Audio) {
+ //Not implemented yet
+ } else {
+ trk->setMidiInputChannel(index - 1);
+ }
+}
+
+void
+TrackParameterBox::slotInstrumentLabelChanged(InstrumentId id, QString label)
+{
+ RG_DEBUG << "TrackParameterBox::slotInstrumentLabelChanged(" << id << ") = " << label << "\n";
+ populatePlaybackDeviceList();
+ slotUpdateControls( -1);
+}
+
+void
+TrackParameterBox::showAdditionalControls(bool showThem)
+{
+ // m_defaultsGroup->parentWidget()->setShown(showThem);
+}
+
+void
+TrackParameterBox::slotClefChanged(int clef)
+{
+ RG_DEBUG << "TrackParameterBox::slotClefChanged(" << clef << ")" << endl;
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+ trk->setClef(clef);
+ m_presetLbl->setEnabled(false);
+}
+
+void
+TrackParameterBox::slotTransposeChanged(int transpose)
+{
+ RG_DEBUG << "TrackParameterBox::slotTransposeChanged(" << transpose << ")" << endl;
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+ trk->setTranspose(transpose);
+ m_presetLbl->setEnabled(false);
+}
+
+void
+TrackParameterBox::slotTransposeIndexChanged(int index)
+{
+ slotTransposeTextChanged(m_defTranspose->text(index));
+}
+
+void
+TrackParameterBox::slotTransposeTextChanged(QString text)
+{
+ if (text.isEmpty())
+ return ;
+ int value = text.toInt();
+ slotTransposeChanged(value);
+}
+
+void
+TrackParameterBox::slotDocColoursChanged()
+{
+ RG_DEBUG << "TrackParameterBox::slotDocColoursChanged()" << endl;
+
+ m_defColor->clear();
+ m_colourList.clear();
+ // Populate it from composition.m_segmentColourMap
+ ColourMap temp = m_doc->getComposition().getSegmentColourMap();
+
+ unsigned int i = 0;
+
+ for (RCMap::const_iterator it = temp.begin(); it != temp.end(); ++it) {
+ QString qtrunc(strtoqstr(it->second.second));
+ QPixmap colour(15, 15);
+ colour.fill(GUIPalette::convertColour(it->second.first));
+ if (qtrunc == "") {
+ m_defColor->insertItem(colour, i18n("Default"), i);
+ } else {
+ // truncate name to 15 characters to avoid the combo forcing the
+ // whole kit and kaboodle too wide
+ if (qtrunc.length() > 15)
+ qtrunc = qtrunc.left(12) + "...";
+ m_defColor->insertItem(colour, qtrunc, i);
+ }
+ m_colourList[it->first] = i; // maps colour number to menu index
+ ++i;
+ }
+
+ m_addColourPos = i;
+ m_defColor->insertItem(i18n("Add New Color"), m_addColourPos);
+
+ m_defColor->setCurrentItem(0);
+}
+
+void
+TrackParameterBox::slotColorChanged(int index)
+{
+ RG_DEBUG << "TrackParameterBox::slotColorChanged(" << index << ")" << endl;
+
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+
+ trk->setColor(index);
+
+ if (index == m_addColourPos) {
+ ColourMap newMap = m_doc->getComposition().getSegmentColourMap();
+ QColor newColour;
+ bool ok = false;
+ QString newName = KLineEditDlg::getText(i18n("New Color Name"), i18n("Enter new name"),
+ i18n("New"), &ok);
+ if ((ok == true) && (!newName.isEmpty())) {
+ KColorDialog box(this, "", true);
+
+ int result = box.getColor(newColour);
+
+ if (result == KColorDialog::Accepted) {
+ Colour newRColour = GUIPalette::convertColour(newColour);
+ newMap.addItem(newRColour, qstrtostr(newName));
+ slotDocColoursChanged();
+ }
+ }
+ // Else we don't do anything as they either didn't give a name�
+ // or didn't give a colour
+ }
+}
+
+void
+TrackParameterBox::slotHighestPressed()
+{
+ RG_DEBUG << "TrackParameterBox::slotHighestPressed()" << endl;
+
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+ if (!trk)
+ return ;
+
+ PitchPickerDialog dialog(0, m_highestPlayable, i18n("Highest playable note"));
+
+ if (dialog.exec() == QDialog::Accepted) {
+ m_highestPlayable = dialog.getPitch();
+ updateHighLow();
+ }
+
+ m_presetLbl->setEnabled(false);
+}
+
+void
+TrackParameterBox::slotLowestPressed()
+{
+ RG_DEBUG << "TrackParameterBox::slotLowestPressed()" << endl;
+
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+ if (!trk)
+ return ;
+
+ PitchPickerDialog dialog(0, m_lowestPlayable, i18n("Lowest playable note"));
+
+ if (dialog.exec() == QDialog::Accepted) {
+ m_lowestPlayable = dialog.getPitch();
+ updateHighLow();
+ }
+
+ m_presetLbl->setEnabled(false);
+}
+
+void
+TrackParameterBox::slotPresetPressed()
+{
+ RG_DEBUG << "TrackParameterBox::slotPresetPressed()" << endl;
+
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(comp.getSelectedTrack());
+ if (!trk)
+ return ;
+
+ PresetHandlerDialog dialog(this);
+
+ try {
+ if (dialog.exec() == QDialog::Accepted) {
+ m_presetLbl->setText(dialog.getName());
+ trk->setPresetLabel(dialog.getName());
+ if (dialog.getConvertAllSegments()) {
+ SegmentSyncCommand* command = new SegmentSyncCommand(
+ comp.getSegments(), comp.getSelectedTrack(),
+ dialog.getTranspose(), dialog.getLowRange(),
+ dialog.getHighRange(),
+ clefIndexToClef(dialog.getClef()));
+ m_doc->getCommandHistory()->addCommand(command);
+ }
+ m_defClef->setCurrentItem(dialog.getClef());
+ m_defTranspose->setCurrentItem(QString("%1").arg
+ (dialog.getTranspose()), true);
+
+ m_highestPlayable = dialog.getHighRange();
+ m_lowestPlayable = dialog.getLowRange();
+ updateHighLow();
+ slotClefChanged(dialog.getClef());
+ slotTransposeChanged(dialog.getTranspose());
+
+ // the preceding slots will have set this disabled, so we
+ // re-enable it until it is subsequently re-disabled by the
+ // user overriding the preset, calling one of the above slots
+ // in the normal course
+ m_presetLbl->setEnabled(true);
+ }
+ } catch (Exception e) {
+ //!!! This should be a more verbose error to pass along the
+ // row/column of the corruption, but I can't be bothered to work
+ // that out just at the moment. Hopefully this code will never
+ // execute anyway.
+ KMessageBox::sorry(0, i18n("The instrument preset database is corrupt. Check your installation."));
+ }
+
+}
+
+void
+TrackParameterBox::slotStaffSizeChanged(int index)
+{
+ RG_DEBUG << "TrackParameterBox::sotStaffSizeChanged()" << endl;
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(m_selectedTrackId);
+
+ trk->setStaffSize(index);
+}
+
+
+void
+TrackParameterBox::slotStaffBracketChanged(int index)
+{
+ RG_DEBUG << "TrackParameterBox::sotStaffBracketChanged()" << endl;
+ Composition &comp = m_doc->getComposition();
+ Track *trk = comp.getTrackById(m_selectedTrackId);
+
+ trk->setStaffBracket(index);
+}
+
+QString
+TrackParameterBox::getPreviousBox(RosegardenParameterArea::Arrangement arrangement) const
+{
+ if (arrangement == RosegardenParameterArea::CLASSIC_STYLE) {
+ return i18n("Segment");
+ } else {
+ return "";
+ }
+}
+
+}
+#include "TrackParameterBox.moc"
diff --git a/src/gui/editors/parameters/TrackParameterBox.h b/src/gui/editors/parameters/TrackParameterBox.h
new file mode 100644
index 0000000..c5fa0f9
--- /dev/null
+++ b/src/gui/editors/parameters/TrackParameterBox.h
@@ -0,0 +1,161 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Rosegarden
+ A MIDI and audio sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ This file is Copyright 2006
+ Pedro Lopez-Cabanillas <[email protected]>
+ D. Michael McIntyre <[email protected]>
+
+ Other copyrights also apply to some parts of this work. Please
+ see the AUTHORS file and individual file headers for details.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version. See the file
+ COPYING included with this distribution for more information.
+*/
+
+#ifndef _RG_TRACKPARAMETERBOX_H_
+#define _RG_TRACKPARAMETERBOX_H_
+
+#include "base/MidiProgram.h"
+#include "base/Track.h"
+#include "gui/widgets/ColourTable.h"
+#include <map>
+#include "RosegardenParameterArea.h"
+#include "RosegardenParameterBox.h"
+#include <qstring.h>
+#include <qcheckbox.h> // #include <QCheckBox> in QT4, thinking ahead
+#include <vector>
+
+
+class QWidget;
+class QPushButton;
+class QLabel;
+class QFrame;
+class KComboBox;
+class QCheckBox;
+
+
+namespace Rosegarden
+{
+
+class RosegardenGUIDoc;
+
+
+class TrackParameterBox : public RosegardenParameterBox
+{
+Q_OBJECT
+
+public:
+ TrackParameterBox( RosegardenGUIDoc *doc,
+ QWidget *parent=0);
+ ~TrackParameterBox();
+
+ void setDocument( RosegardenGUIDoc *doc );
+ void populateDeviceLists();
+ virtual void showAdditionalControls(bool showThem);
+
+ virtual QString getPreviousBox(RosegardenParameterArea::Arrangement) const;
+
+public slots:
+ void slotSelectedTrackChanged();
+ void slotSelectedTrackNameChanged();
+ void slotPlaybackDeviceChanged(int index);
+ void slotInstrumentChanged(int index);
+ void slotRecordingDeviceChanged(int index);
+ void slotRecordingChannelChanged(int index);
+ void slotUpdateControls(int);
+ void slotInstrumentLabelChanged(InstrumentId id, QString label);
+
+ void slotClefChanged(int clef);
+ void slotTransposeChanged(int transpose);
+ void slotTransposeIndexChanged(int index);
+ void slotTransposeTextChanged(QString text);
+ void slotDocColoursChanged();
+ void slotColorChanged(int index);
+ void slotHighestPressed();
+ void slotLowestPressed();
+ void slotPresetPressed();
+
+ void slotStaffSizeChanged(int index);
+ void slotStaffBracketChanged(int index);
+
+signals:
+ void instrumentSelected(TrackId, int);
+
+protected:
+ void populatePlaybackDeviceList();
+ void populateRecordingDeviceList();
+ void updateHighLow();
+
+private:
+ RosegardenGUIDoc *m_doc;
+
+ KComboBox *m_playDevice;
+ KComboBox *m_instrument;
+ KComboBox *m_recDevice;
+ KComboBox *m_recChannel;
+
+ QPushButton *m_presetButton;
+ QPushButton *m_highButton;
+ QPushButton *m_lowButton;
+
+ KComboBox *m_defClef;
+ KComboBox *m_defColor;
+ KComboBox *m_defTranspose;
+ KComboBox *m_staffSizeCombo;
+ KComboBox *m_staffBracketCombo;
+
+
+ int m_addColourPos;
+ int m_highestPlayable;
+ int m_lowestPlayable;
+ ColourTable::ColourList m_colourList;
+
+ QLabel *m_trackLabel;
+
+ typedef std::vector<DeviceId> IdsVector;
+
+ IdsVector m_playDeviceIds;
+ IdsVector m_recDeviceIds;
+
+ std::map<DeviceId, IdsVector> m_instrumentIds;
+ std::map<DeviceId, QStringList> m_instrumentNames;
+
+ int m_selectedTrackId;
+
+ char m_lastInstrumentType;
+
+ // Additional elements that may be hidden in vertical stacked mode
+ //QFrame *m_separator2;
+ QFrame *m_playbackGroup;
+ QFrame *m_recordGroup;
+ QFrame *m_defaultsGroup;
+ QFrame *m_staffGroup;
+ QLabel *m_segHeader;
+ QLabel *m_presetLbl;
+ QLabel *m_staffGrpLbl;
+ QLabel *m_grandStaffLbl;
+ QLabel *m_clefLbl;
+ QLabel *m_transpLbl;
+ QLabel *m_colorLbl;
+ QLabel *m_rangeLbl;
+ QLabel *m_psetLbl;
+};
+
+
+}
+
+#endif