summaryrefslogtreecommitdiffstats
path: root/src/gui/editors/segment/TrackButtons.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/editors/segment/TrackButtons.cpp')
-rw-r--r--src/gui/editors/segment/TrackButtons.cpp1149
1 files changed, 1149 insertions, 0 deletions
diff --git a/src/gui/editors/segment/TrackButtons.cpp b/src/gui/editors/segment/TrackButtons.cpp
new file mode 100644
index 0000000..5cf9908
--- /dev/null
+++ b/src/gui/editors/segment/TrackButtons.cpp
@@ -0,0 +1,1149 @@
+/* -*- 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 <glaurent@telegraph-road.org>,
+ Chris Cannam <cannam@all-day-breakfast.com>,
+ Richard Bown <richard.bown@ferventsoftware.com>
+
+ 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 "TrackButtons.h"
+#include <qlayout.h>
+
+#include <klocale.h>
+#include <kstddirs.h>
+#include "misc/Debug.h"
+#include "misc/Strings.h"
+#include "base/AudioPluginInstance.h"
+#include "base/Composition.h"
+#include "base/Device.h"
+#include "base/Instrument.h"
+#include "base/MidiProgram.h"
+#include "base/Studio.h"
+#include "base/Track.h"
+#include "commands/segment/RenameTrackCommand.h"
+#include "document/RosegardenGUIDoc.h"
+#include "document/MultiViewCommandHistory.h"
+#include "gui/application/RosegardenGUIApp.h"
+#include "gui/general/GUIPalette.h"
+#include "gui/kdeext/KLedButton.h"
+#include "sound/AudioFileManager.h"
+#include "sound/PluginIdentifier.h"
+#include "TrackLabel.h"
+#include "TrackVUMeter.h"
+#include <kglobal.h>
+#include <kled.h>
+#include <kmessagebox.h>
+#include <qcursor.h>
+#include <qframe.h>
+#include <qiconset.h>
+#include <qlabel.h>
+#include <qobject.h>
+#include <qpixmap.h>
+#include <qpopupmenu.h>
+#include <qsignalmapper.h>
+#include <qstring.h>
+#include <qtimer.h>
+#include <qwidget.h>
+#include <qwidgetstack.h>
+#include <qtooltip.h>
+
+namespace Rosegarden
+{
+
+TrackButtons::TrackButtons(RosegardenGUIDoc* doc,
+ unsigned int trackCellHeight,
+ unsigned int trackLabelWidth,
+ bool showTrackLabels,
+ int overallHeight,
+ QWidget* parent,
+ const char* name,
+ WFlags f)
+ : QFrame(parent, name, f),
+ m_doc(doc),
+ m_layout(new QVBoxLayout(this)),
+ m_recordSigMapper(new QSignalMapper(this)),
+ m_muteSigMapper(new QSignalMapper(this)),
+ m_clickedSigMapper(new QSignalMapper(this)),
+ m_instListSigMapper(new QSignalMapper(this)),
+ m_tracks(doc->getComposition().getNbTracks()),
+ m_offset(4),
+ m_cellSize(trackCellHeight),
+ m_borderGap(1),
+ m_trackLabelWidth(trackLabelWidth),
+ m_popupItem(0),
+ m_lastSelected( -1)
+{
+ setFrameStyle(Plain);
+
+ // when we create the widget, what are we looking at?
+ if (showTrackLabels)
+ m_trackInstrumentLabels = TrackLabel::ShowTrack;
+ else
+ m_trackInstrumentLabels = TrackLabel::ShowInstrument;
+
+ // Set the spacing between vertical elements
+ //
+ m_layout->setSpacing(m_borderGap);
+
+ // Now draw the buttons and labels and meters
+ //
+ makeButtons();
+
+ m_layout->addStretch(20);
+
+ connect(m_recordSigMapper, SIGNAL(mapped(int)),
+ this, SLOT(slotToggleRecordTrack(int)));
+
+ connect(m_muteSigMapper, SIGNAL(mapped(int)),
+ this, SLOT(slotToggleMutedTrack(int)));
+
+ // connect signal mappers
+ connect(m_instListSigMapper, SIGNAL(mapped(int)),
+ this, SLOT(slotInstrumentSelection(int)));
+
+ connect(m_clickedSigMapper, SIGNAL(mapped(int)),
+ this, SIGNAL(trackSelected(int)));
+
+ // // Populate instrument popup menu just once at start-up
+ // //
+ // populateInstrumentPopup();
+
+ // We have to force the height for the moment
+ //
+ setMinimumHeight(overallHeight);
+
+}
+
+TrackButtons::~TrackButtons()
+{}
+
+void
+TrackButtons::makeButtons()
+{
+ if (!m_doc)
+ return ;
+
+ // Create a horizontal box for each track
+ // plus the two buttons
+ //
+ unsigned int nbTracks = m_doc->getComposition().getNbTracks();
+
+ for (unsigned int i = 0; i < nbTracks; ++i) {
+ Track *track = m_doc->getComposition().getTrackByPosition(i);
+
+ if (track) {
+ QFrame *trackHBox = makeButton(track->getId());
+
+ if (trackHBox) {
+ m_layout->addWidget(trackHBox);
+ m_trackHBoxes.push_back(trackHBox);
+ }
+ }
+ }
+
+ populateButtons();
+}
+
+void TrackButtons::setButtonMapping(QObject* obj, TrackId trackId)
+{
+ m_clickedSigMapper->setMapping(obj, trackId);
+ m_instListSigMapper->setMapping(obj, trackId);
+}
+
+void
+TrackButtons::populateButtons()
+{
+ Instrument *ins = 0;
+ Track *track;
+
+ for (unsigned int i = 0; i < m_trackLabels.size(); ++i) {
+ track = m_doc->getComposition().getTrackByPosition(i);
+
+ if (track) {
+ ins = m_doc->getStudio().getInstrumentById(track->getInstrument());
+
+ // Set mute button from track
+ //
+ if (track->isMuted())
+ m_muteLeds[i]->off();
+ else
+ m_muteLeds[i]->on();
+
+ // Set record button from track
+ //
+ bool recording =
+ m_doc->getComposition().isTrackRecording(track->getId());
+ setRecordTrack(track->getPosition(), recording);
+
+ // reset track tokens
+ m_trackLabels[i]->setId(track->getId());
+ setButtonMapping(m_trackLabels[i], track->getId());
+ m_trackLabels[i]->setPosition(i);
+ }
+
+ if (ins) {
+ m_trackLabels[i]->getInstrumentLabel()->setText
+ (strtoqstr(ins->getPresentationName()));
+ if (ins->sendsProgramChange()) {
+ m_trackLabels[i]->setAlternativeLabel(strtoqstr(ins->getProgramName()));
+ }
+
+ } else {
+ m_trackLabels[i]->getInstrumentLabel()->setText(i18n("<no instrument>"));
+ }
+
+ m_trackLabels[i]->update();
+ }
+
+}
+
+std::vector<int>
+TrackButtons::mutedTracks()
+{
+ std::vector<int> mutedTracks;
+
+ for (TrackId i = 0; i < m_tracks; i++) {
+ if (m_muteLeds[i]->state() == KLed::Off)
+ mutedTracks.push_back(i);
+ }
+
+ return mutedTracks;
+}
+
+void
+TrackButtons::slotToggleMutedTrack(int mutedTrackPos)
+{
+ RG_DEBUG << "TrackButtons::slotToggleMutedTrack(" << mutedTrackPos << ")\n";
+
+ if (mutedTrackPos < 0 || mutedTrackPos > (int)m_tracks )
+ return ;
+
+ Track *track =
+ m_doc->getComposition().getTrackByPosition(mutedTrackPos);
+
+ emit muteButton(track->getId(), !track->isMuted()); // will set the value
+}
+
+void
+TrackButtons::removeButtons(unsigned int position)
+{
+ RG_DEBUG << "TrackButtons::removeButtons - "
+ << "deleting track button at position "
+ << position << endl;
+
+ if (position >= m_trackHBoxes.size()) {
+ RG_DEBUG << "%%%%%%%%% BIG PROBLEM : TrackButtons::removeButtons() was passed a non-existing index\n";
+ return ;
+ }
+
+ std::vector<TrackLabel*>::iterator tit = m_trackLabels.begin();
+ tit += position;
+ m_trackLabels.erase(tit);
+
+ std::vector<TrackVUMeter*>::iterator vit = m_trackMeters.begin();
+ vit += position;
+ m_trackMeters.erase(vit);
+
+ std::vector<KLedButton*>::iterator mit = m_muteLeds.begin();
+ mit += position;
+ m_muteLeds.erase(mit);
+
+ mit = m_recordLeds.begin();
+ mit += position;
+ m_recordLeds.erase(mit);
+
+ delete m_trackHBoxes[position]; // deletes all child widgets (button, led, label...)
+
+ std::vector<QFrame*>::iterator it = m_trackHBoxes.begin();
+ it += position;
+ m_trackHBoxes.erase(it);
+
+}
+
+void
+TrackButtons::slotUpdateTracks()
+{
+ Composition &comp = m_doc->getComposition();
+ unsigned int newNbTracks = comp.getNbTracks();
+ Track *track = 0;
+
+ std::cerr << "TrackButtons::slotUpdateTracks" << std::endl;
+
+ if (newNbTracks < m_tracks) {
+ for (unsigned int i = m_tracks; i > newNbTracks; --i)
+ removeButtons(i - 1);
+ } else if (newNbTracks > m_tracks) {
+ for (unsigned int i = m_tracks; i < newNbTracks; ++i) {
+ track = m_doc->getComposition().getTrackByPosition(i);
+ if (track) {
+ QFrame *trackHBox = makeButton(track->getId());
+
+ if (trackHBox) {
+ trackHBox->show();
+ m_layout->insertWidget(i, trackHBox);
+ m_trackHBoxes.push_back(trackHBox);
+ }
+ } else
+ RG_DEBUG << "TrackButtons::slotUpdateTracks - can't find TrackId for position " << i << endl;
+ }
+ }
+
+ // Set height
+ //
+ for (unsigned int i = 0; i < m_trackHBoxes.size(); ++i) {
+
+ track = comp.getTrackByPosition(i);
+
+ if (track) {
+
+ int multiple = m_doc->getComposition()
+ .getMaxContemporaneousSegmentsOnTrack(track->getId());
+ if (multiple == 0) multiple = 1;
+
+ // nasty dupe from makeButton
+
+ int buttonGap = 8;
+ int vuWidth = 20;
+ int vuSpacing = 2;
+
+ int labelWidth = m_trackLabelWidth -
+ ((m_cellSize - buttonGap) * 2 +
+ vuSpacing * 2 + vuWidth);
+
+ m_trackHBoxes[i]->setMinimumSize
+ (labelWidth, m_cellSize * multiple - m_borderGap);
+
+ m_trackHBoxes[i]->setFixedHeight
+ (m_cellSize * multiple - m_borderGap);
+ }
+ }
+
+ // Renumber all the labels
+ //
+ for (unsigned int i = 0; i < m_trackLabels.size(); ++i) {
+ track = comp.getTrackByPosition(i);
+
+ if (track) {
+ m_trackLabels[i]->setId(track->getId());
+
+ QLabel *trackLabel = m_trackLabels[i]->getTrackLabel();
+
+ if (track->getLabel() == std::string("")) {
+ Instrument *ins =
+ m_doc->getStudio().getInstrumentById(track->getInstrument());
+ if (ins && ins->getType() == Instrument::Audio) {
+ trackLabel->setText(i18n("<untitled audio>"));
+ } else {
+ trackLabel->setText(i18n("<untitled>"));
+ }
+ } else {
+ trackLabel->setText(strtoqstr(track->getLabel()));
+ }
+
+ // RG_DEBUG << "TrackButtons::slotUpdateTracks - set button mapping at pos "
+ // << i << " to track id " << track->getId() << endl;
+ setButtonMapping(m_trackLabels[i], track->getId());
+ }
+ }
+ m_tracks = newNbTracks;
+
+ // Set record status and colour
+
+ for (unsigned int i = 0; i < m_trackLabels.size(); ++i) {
+
+ track = comp.getTrackByPosition(i);
+
+ if (track) {
+
+ setRecordTrack(i, comp.isTrackRecording(track->getId()));
+
+ Instrument *ins =
+ m_doc->getStudio().getInstrumentById(track->getInstrument());
+
+ if (ins &&
+ ins->getType() == Instrument::Audio) {
+ m_recordLeds[i]->setColor
+ (GUIPalette::getColour
+ (GUIPalette::RecordAudioTrackLED));
+ } else {
+ m_recordLeds[i]->setColor
+ (GUIPalette::getColour
+ (GUIPalette::RecordMIDITrackLED));
+ }
+ }
+ }
+
+ // repopulate the buttons
+ populateButtons();
+}
+
+void
+TrackButtons::slotToggleRecordTrack(int position)
+{
+ Composition &comp = m_doc->getComposition();
+ Track *track = comp.getTrackByPosition(position);
+
+ bool state = !comp.isTrackRecording(track->getId());
+
+ Instrument *instrument = m_doc->getStudio().getInstrumentById
+ (track->getInstrument());
+
+ bool audio = (instrument &&
+ instrument->getType() == Instrument::Audio);
+
+ if (audio && state) {
+ try {
+ m_doc->getAudioFileManager().testAudioPath();
+ } catch (AudioFileManager::BadAudioPathException e) {
+ if (KMessageBox::warningContinueCancel
+ (this,
+ i18n("The audio file path does not exist or is not writable.\nPlease set the audio file path to a valid directory in Document Properties before recording audio.\nWould you like to set it now?"),
+ i18n("Warning"),
+ i18n("Set audio file path")) == KMessageBox::Continue) {
+ RosegardenGUIApp::self()->slotOpenAudioPathSettings();
+ }
+ }
+ }
+
+ // can have any number of audio instruments armed, but only one
+ // track armed per instrument.
+
+ // Need to copy this container, as we're implicitly modifying it
+ // through calls to comp.setTrackRecording
+
+ Composition::recordtrackcontainer oldRecordTracks =
+ comp.getRecordTracks();
+
+ for (Composition::recordtrackcontainer::const_iterator i =
+ oldRecordTracks.begin();
+ i != oldRecordTracks.end(); ++i) {
+
+ if (!comp.isTrackRecording(*i)) {
+ // We've already reset this one
+ continue;
+ }
+
+ Track *otherTrack = comp.getTrackById(*i);
+
+ if (otherTrack &&
+ otherTrack != track) {
+
+ /* Obsolete code: audio, MIDI and plugin tracks behave the same now.
+ plcl, 06/2006 - Multitrack MIDI recording
+
+ bool unselect;
+
+ if (audio) {
+ unselect = (otherTrack->getInstrument() == track->getInstrument());
+ } else {
+ // our track is not an audio track, check that the
+ // other isn't either
+ Instrument *otherInstrument =
+ m_doc->getStudio().getInstrumentById(otherTrack->getInstrument());
+ bool otherAudio = (otherInstrument &&
+ otherInstrument->getType() ==
+ Instrument::Audio);
+
+ unselect = !otherAudio;
+ }
+
+ if (unselect) { */
+
+ if (otherTrack->getInstrument() == track->getInstrument()) {
+ // found another record track of the same type (and
+ // with the same instrument, if audio): unselect that
+
+ //!!! should we tell the user, particularly for the
+ //audio case? might seem odd otherwise
+
+ int otherPos = otherTrack->getPosition();
+ setRecordTrack(otherPos, false);
+ }
+ }
+ }
+
+ setRecordTrack(position, state);
+
+ emit recordButton(track->getId(), state);
+}
+
+void
+TrackButtons::setRecordTrack(int position, bool state)
+{
+ setRecordButton(position, state);
+ m_doc->getComposition().setTrackRecording
+ (m_trackLabels[position]->getId(), state);
+}
+
+void
+TrackButtons::setRecordButton(int position, bool state)
+{
+ if (position < 0 || position >= (int)m_tracks)
+ return ;
+
+ KLedButton* led = m_recordLeds[position];
+
+ led->setState(state ? KLed::On : KLed::Off);
+}
+
+void
+TrackButtons::selectLabel(int position)
+{
+ if (m_lastSelected >= 0 && m_lastSelected < (int)m_trackLabels.size()) {
+ m_trackLabels[m_lastSelected]->setSelected(false);
+ }
+
+ if (position >= 0 && position < (int)m_trackLabels.size()) {
+ m_trackLabels[position]->setSelected(true);
+ m_lastSelected = position;
+ }
+}
+
+std::vector<int>
+TrackButtons::getHighlightedTracks()
+{
+ std::vector<int> retList;
+
+ for (unsigned int i = 0; i < m_trackLabels.size(); ++i) {
+ if (m_trackLabels[i]->isSelected())
+ retList.push_back(i);
+ }
+
+ return retList;
+}
+
+void
+TrackButtons::slotRenameTrack(QString newName, TrackId trackId)
+{
+ m_doc->getCommandHistory()->addCommand
+ (new RenameTrackCommand(&m_doc->getComposition(),
+ trackId,
+ qstrtostr(newName)));
+
+ changeTrackLabel(trackId, newName);
+}
+
+void
+TrackButtons::slotSetTrackMeter(float value, int position)
+{
+ //Composition &comp = m_doc->getComposition();
+ //Studio &studio = m_doc->getStudio();
+ //Track *track;
+
+ for (unsigned int i = 0; i < m_trackMeters.size(); ++i) {
+ if (i == ((unsigned int)position)) {
+ m_trackMeters[i]->setLevel(value);
+ return ;
+ }
+ }
+}
+
+void
+TrackButtons::slotSetMetersByInstrument(float value,
+ InstrumentId id)
+{
+ Composition &comp = m_doc->getComposition();
+ //Studio &studio = m_doc->getStudio();
+ Track *track;
+
+ for (unsigned int i = 0; i < m_trackMeters.size(); ++i) {
+ track = comp.getTrackByPosition(i);
+
+ if (track != 0 && track->getInstrument() == id) {
+ m_trackMeters[i]->setLevel(value);
+ }
+ }
+}
+
+void
+TrackButtons::slotInstrumentSelection(int trackId)
+{
+ RG_DEBUG << "TrackButtons::slotInstrumentSelection(" << trackId << ")\n";
+
+ Composition &comp = m_doc->getComposition();
+ Studio &studio = m_doc->getStudio();
+
+ int position = comp.getTrackById(trackId)->getPosition();
+
+ QString instrumentName = i18n("<no instrument>");
+ Track *track = comp.getTrackByPosition(position);
+
+ Instrument *instrument = 0;
+ if (track != 0) {
+ instrument = studio.getInstrumentById(track->getInstrument());
+ if (instrument)
+ instrumentName = strtoqstr(instrument->getPresentationName());
+ }
+
+ //
+ // populate this instrument widget
+ m_trackLabels[position]->getInstrumentLabel()->setText(instrumentName);
+
+ // Ensure the instrument name is shown
+ m_trackLabels[position]->showLabel(TrackLabel::ShowInstrument);
+
+ // Yes, well as we might've changed the Device name in the
+ // Device/Bank dialog then we reload the whole menu here.
+ //
+
+ QPopupMenu instrumentPopup(this);
+
+ populateInstrumentPopup(instrument, &instrumentPopup);
+
+ // Store the popup item position
+ //
+ m_popupItem = position;
+
+ instrumentPopup.exec(QCursor::pos());
+
+ // Restore the label back to what it was showing
+ m_trackLabels[position]->showLabel(m_trackInstrumentLabels);
+
+ // Do this here as well as in slotInstrumentPopupActivated, so as
+ // to restore the correct alternative label even if no other
+ // program was selected from the menu
+ if (track != 0) {
+ instrument = studio.getInstrumentById(track->getInstrument());
+ if (instrument) {
+ m_trackLabels[position]->getInstrumentLabel()->
+ setText(strtoqstr(instrument->getPresentationName()));
+ m_trackLabels[position]->clearAlternativeLabel();
+ if (instrument->sendsProgramChange()) {
+ m_trackLabels[position]->setAlternativeLabel
+ (strtoqstr(instrument->getProgramName()));
+ }
+ }
+ }
+}
+
+void
+TrackButtons::populateInstrumentPopup(Instrument *thisTrackInstr, QPopupMenu* instrumentPopup)
+{
+ static QPixmap connectedPixmap, unconnectedPixmap,
+ connectedUsedPixmap, unconnectedUsedPixmap,
+ connectedSelectedPixmap, unconnectedSelectedPixmap;
+ static bool havePixmaps = false;
+
+ if (!havePixmaps) {
+
+ QString pixmapDir =
+ KGlobal::dirs()->findResource("appdata", "pixmaps/");
+
+ connectedPixmap.load
+ (QString("%1/misc/connected.xpm").arg(pixmapDir));
+ connectedUsedPixmap.load
+ (QString("%1/misc/connected-used.xpm").arg(pixmapDir));
+ connectedSelectedPixmap.load
+ (QString("%1/misc/connected-selected.xpm").arg(pixmapDir));
+ unconnectedPixmap.load
+ (QString("%1/misc/unconnected.xpm").arg(pixmapDir));
+ unconnectedUsedPixmap.load
+ (QString("%1/misc/unconnected-used.xpm").arg(pixmapDir));
+ unconnectedSelectedPixmap.load
+ (QString("%1/misc/unconnected-selected.xpm").arg(pixmapDir));
+
+ havePixmaps = true;
+ }
+
+ Composition &comp = m_doc->getComposition();
+ Studio &studio = m_doc->getStudio();
+
+ // clear the popup
+ instrumentPopup->clear();
+
+ std::vector<QPopupMenu*> instrumentSubMenus;
+
+ // position index
+ int i = 0;
+
+ // Get the list
+ InstrumentList list = studio.getPresentationInstruments();
+ InstrumentList::iterator it;
+ int currentDevId = -1;
+ bool deviceUsedByAnyone = false;
+
+ for (it = list.begin(); it != list.end(); it++) {
+
+ if (! (*it))
+ continue; // sanity check
+
+ QString iname(strtoqstr((*it)->getPresentationName()));
+ QString pname(strtoqstr((*it)->getProgramName()));
+ Device *device = (*it)->getDevice();
+ DeviceId devId = device->getId();
+ bool connected = false;
+
+ if ((*it)->getType() == Instrument::SoftSynth) {
+ pname = "";
+ AudioPluginInstance *plugin = (*it)->getPlugin
+ (Instrument::SYNTH_PLUGIN_POSITION);
+ if (plugin) {
+ pname = strtoqstr(plugin->getProgram());
+ QString identifier = strtoqstr(plugin->getIdentifier());
+ if (identifier != "") {
+ connected = true;
+ 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;
+ }
+ } else {
+ connected = false;
+ }
+ }
+ } else if ((*it)->getType() == Instrument::Audio) {
+ connected = true;
+ } else {
+ connected = (device->getConnection() != "");
+ }
+
+ bool instrUsedByMe = false;
+ bool instrUsedByAnyone = false;
+
+ if (thisTrackInstr && thisTrackInstr->getId() == (*it)->getId()) {
+ instrUsedByMe = true;
+ instrUsedByAnyone = true;
+ }
+
+ if (devId != (DeviceId)(currentDevId)) {
+
+ deviceUsedByAnyone = false;
+
+ if (instrUsedByMe)
+ deviceUsedByAnyone = true;
+ else {
+ for (Composition::trackcontainer::iterator tit =
+ comp.getTracks().begin();
+ tit != comp.getTracks().end(); ++tit) {
+
+ if (tit->second->getInstrument() == (*it)->getId()) {
+ instrUsedByAnyone = true;
+ deviceUsedByAnyone = true;
+ break;
+ }
+
+ Instrument *instr =
+ studio.getInstrumentById(tit->second->getInstrument());
+ if (instr && (instr->getDevice()->getId() == devId)) {
+ deviceUsedByAnyone = true;
+ }
+ }
+ }
+
+ QIconSet iconSet
+ (connected ?
+ (deviceUsedByAnyone ?
+ connectedUsedPixmap : connectedPixmap) :
+ (deviceUsedByAnyone ?
+ unconnectedUsedPixmap : unconnectedPixmap));
+
+ currentDevId = int(devId);
+
+ QPopupMenu *subMenu = new QPopupMenu(instrumentPopup);
+ QString deviceName = strtoqstr(device->getName());
+ instrumentPopup->insertItem(iconSet, deviceName, subMenu);
+ instrumentSubMenus.push_back(subMenu);
+
+ // Connect up the submenu
+ //
+ connect(subMenu, SIGNAL(activated(int)),
+ SLOT(slotInstrumentPopupActivated(int)));
+
+ } else if (!instrUsedByMe) {
+
+ for (Composition::trackcontainer::iterator tit =
+ comp.getTracks().begin();
+ tit != comp.getTracks().end(); ++tit) {
+
+ if (tit->second->getInstrument() == (*it)->getId()) {
+ instrUsedByAnyone = true;
+ break;
+ }
+ }
+ }
+
+ QIconSet iconSet
+ (connected ?
+ (instrUsedByAnyone ?
+ instrUsedByMe ?
+ connectedSelectedPixmap :
+ connectedUsedPixmap : connectedPixmap) :
+ (instrUsedByAnyone ?
+ instrUsedByMe ?
+ unconnectedSelectedPixmap :
+ unconnectedUsedPixmap : unconnectedPixmap));
+
+ if (pname != "")
+ iname += " (" + pname + ")";
+
+ instrumentSubMenus[instrumentSubMenus.size() - 1]->insertItem(iconSet, iname, i++);
+ }
+
+}
+
+void
+TrackButtons::slotInstrumentPopupActivated(int item)
+{
+ RG_DEBUG << "TrackButtons::slotInstrumentPopupActivated " << item << endl;
+
+ Composition &comp = m_doc->getComposition();
+ Studio &studio = m_doc->getStudio();
+
+ Instrument *inst = studio.getInstrumentFromList(item);
+
+ RG_DEBUG << "TrackButtons::slotInstrumentPopupActivated: instrument " << inst << endl;
+
+ if (inst != 0) {
+ Track *track = comp.getTrackByPosition(m_popupItem);
+
+ if (track != 0) {
+ track->setInstrument(inst->getId());
+
+ // select instrument
+ emit instrumentSelected((int)inst->getId());
+
+ m_trackLabels[m_popupItem]->getInstrumentLabel()->
+ setText(strtoqstr(inst->getPresentationName()));
+
+ // reset the alternative label
+ m_trackLabels[m_popupItem]->clearAlternativeLabel();
+
+ // Now see if the program is being shown for this instrument
+ // and if so reset the label
+ //
+ if (inst->sendsProgramChange())
+ m_trackLabels[m_popupItem]->setAlternativeLabel(strtoqstr(inst->getProgramName()));
+
+ if (inst->getType() == Instrument::Audio) {
+ m_recordLeds[m_popupItem]->setColor
+ (GUIPalette::getColour
+ (GUIPalette::RecordAudioTrackLED));
+ } else {
+ m_recordLeds[m_popupItem]->setColor
+ (GUIPalette::getColour
+ (GUIPalette::RecordMIDITrackLED));
+ }
+ } else
+ RG_DEBUG << "slotInstrumentPopupActivated() - can't find item!\n";
+ } else
+ RG_DEBUG << "slotInstrumentPopupActivated() - can't find item!\n";
+
+}
+
+void
+TrackButtons::changeTrackInstrumentLabels(TrackLabel::InstrumentTrackLabels label)
+{
+ // Set new label
+ m_trackInstrumentLabels = label;
+
+ // update and reconnect with new value
+ for (int i = 0; i < (int)m_tracks; i++) {
+ m_trackLabels[i]->showLabel(label);
+ }
+}
+
+void
+TrackButtons::changeInstrumentLabel(InstrumentId id, QString label)
+{
+ Composition &comp = m_doc->getComposition();
+ Track *track;
+
+ for (int i = 0; i < (int)m_tracks; i++) {
+ track = comp.getTrackByPosition(i);
+
+ if (track && track->getInstrument() == id) {
+
+ m_trackLabels[i]->setAlternativeLabel(label);
+
+ Instrument *ins = m_doc->getStudio().
+ getInstrumentById(track->getInstrument());
+
+ if (ins && ins->getType() == Instrument::Audio) {
+ m_recordLeds[i]->setColor
+ (GUIPalette::getColour
+ (GUIPalette::RecordAudioTrackLED));
+ } else {
+ m_recordLeds[i]->setColor
+ (GUIPalette::getColour
+ (GUIPalette::RecordMIDITrackLED));
+ }
+ }
+ }
+}
+
+void
+TrackButtons::changeTrackLabel(TrackId id, QString label)
+{
+ Composition &comp = m_doc->getComposition();
+ Track *track;
+
+ for (int i = 0; i < (int)m_tracks; i++) {
+ track = comp.getTrackByPosition(i);
+ if (track && track->getId() == id) {
+ if (m_trackLabels[i]->getTrackLabel()->text() != label) {
+ m_trackLabels[i]->getTrackLabel()->setText(label);
+ emit widthChanged();
+ emit nameChanged();
+ }
+ return ;
+ }
+ }
+}
+
+void
+TrackButtons::slotSynchroniseWithComposition()
+{
+ Composition &comp = m_doc->getComposition();
+ Studio &studio = m_doc->getStudio();
+ Track *track;
+
+ for (int i = 0; i < (int)m_tracks; i++) {
+ track = comp.getTrackByPosition(i);
+
+ if (track) {
+ if (track->isMuted())
+ m_muteLeds[i]->off();
+ else
+ m_muteLeds[i]->on();
+
+ Instrument *ins = studio.
+ getInstrumentById(track->getInstrument());
+
+ QString instrumentName(i18n("<no instrument>"));
+ if (ins)
+ instrumentName = strtoqstr(ins->getPresentationName());
+
+ m_trackLabels[i]->getInstrumentLabel()->setText(instrumentName);
+
+ setRecordButton(i, comp.isTrackRecording(track->getId()));
+
+ if (ins && ins->getType() == Instrument::Audio) {
+ m_recordLeds[i]->setColor
+ (GUIPalette::getColour
+ (GUIPalette::RecordAudioTrackLED));
+ } else {
+ m_recordLeds[i]->setColor
+ (GUIPalette::getColour
+ (GUIPalette::RecordMIDITrackLED));
+ }
+ }
+ }
+}
+
+void
+TrackButtons::slotLabelSelected(int position)
+{
+ Track *track =
+ m_doc->getComposition().getTrackByPosition(position);
+
+ if (track) {
+ emit trackSelected(track->getId());
+ }
+}
+
+void
+TrackButtons::setMuteButton(TrackId track, bool value)
+{
+ Track *trackObj = m_doc->getComposition().getTrackById(track);
+ if (trackObj == 0)
+ return ;
+
+ int pos = trackObj->getPosition();
+
+ RG_DEBUG << "TrackButtons::setMuteButton() trackId = "
+ << track << ", pos = " << pos << endl;
+
+ m_muteLeds[pos]->setState(value ? KLed::Off : KLed::On);
+}
+
+void
+TrackButtons::slotTrackInstrumentSelection(TrackId trackId, int item)
+{
+ RG_DEBUG << "TrackButtons::slotTrackInstrumentSelection(" << trackId << ")\n";
+
+ Composition &comp = m_doc->getComposition();
+ int position = comp.getTrackById(trackId)->getPosition();
+ m_popupItem = position;
+ slotInstrumentPopupActivated( item );
+}
+
+QFrame* TrackButtons::makeButton(Rosegarden::TrackId trackId)
+{
+ // The buttonGap sets up the sizes of the buttons
+ //
+ static const int buttonGap = 8;
+
+ QFrame *trackHBox = 0;
+
+ KLedButton *mute = 0;
+ KLedButton *record = 0;
+
+ TrackVUMeter *vuMeter = 0;
+ TrackLabel *trackLabel = 0;
+
+ int vuWidth = 20;
+ int vuSpacing = 2;
+ int multiple = m_doc->getComposition()
+ .getMaxContemporaneousSegmentsOnTrack(trackId);
+ if (multiple == 0) multiple = 1;
+ int labelWidth = m_trackLabelWidth - ( (m_cellSize - buttonGap) * 2 +
+ vuSpacing * 2 + vuWidth );
+
+ // Set the label from the Track object on the Composition
+ //
+ Rosegarden::Track *track = m_doc->getComposition().getTrackById(trackId);
+
+ if (track == 0) return 0;
+
+ // Create a horizontal box for each track
+ //
+ trackHBox = new QFrame(this);
+ QHBoxLayout *hblayout = new QHBoxLayout(trackHBox);
+
+ trackHBox->setMinimumSize(labelWidth, m_cellSize * multiple - m_borderGap);
+ trackHBox->setFixedHeight(m_cellSize * multiple - m_borderGap);
+
+ // Try a style for the box
+ //
+ trackHBox->setFrameStyle(StyledPanel);
+ trackHBox->setFrameShape(StyledPanel);
+ trackHBox->setFrameShadow(Raised);
+
+ // Insert a little gap
+ hblayout->addSpacing(vuSpacing);
+
+ // Create a VU meter
+ vuMeter = new TrackVUMeter(trackHBox,
+ VUMeter::PeakHold,
+ vuWidth,
+ buttonGap,
+ track->getPosition());
+
+ m_trackMeters.push_back(vuMeter);
+
+ hblayout->addWidget(vuMeter);
+
+ // Create another little gap
+ hblayout->addSpacing(vuSpacing);
+
+ //
+ // 'mute' and 'record' leds
+ //
+
+ mute = new KLedButton(Rosegarden::GUIPalette::getColour
+ (Rosegarden::GUIPalette::MuteTrackLED), trackHBox);
+ QToolTip::add(mute, i18n("Mute track"));
+ hblayout->addWidget(mute);
+
+ record = new KLedButton(Rosegarden::GUIPalette::getColour
+ (Rosegarden::GUIPalette::RecordMIDITrackLED), trackHBox);
+ QToolTip::add(record, i18n("Record on this track"));
+ hblayout->addWidget(record);
+
+ record->setLook(KLed::Sunken);
+ mute->setLook(KLed::Sunken);
+ record->off();
+
+ // Connect them to their sigmappers
+ connect(record, SIGNAL(stateChanged(bool)),
+ m_recordSigMapper, SLOT(map()));
+ connect(mute, SIGNAL(stateChanged(bool)),
+ m_muteSigMapper, SLOT(map()));
+ m_recordSigMapper->setMapping(record, track->getPosition());
+ m_muteSigMapper->setMapping(mute, track->getPosition());
+
+ // Store the KLedButton
+ //
+ m_muteLeds.push_back(mute);
+ m_recordLeds.push_back(record);
+
+ //
+ // Track label
+ //
+ trackLabel = new TrackLabel(trackId, track->getPosition(), trackHBox);
+ hblayout->addWidget(trackLabel);
+ hblayout->addSpacing(vuSpacing);
+
+ if (track->getLabel() == std::string("")) {
+ Rosegarden::Instrument *ins =
+ m_doc->getStudio().getInstrumentById(track->getInstrument());
+ if (ins && ins->getType() == Rosegarden::Instrument::Audio) {
+ trackLabel->getTrackLabel()->setText(i18n("<untitled audio>"));
+ } else {
+ trackLabel->getTrackLabel()->setText(i18n("<untitled>"));
+ }
+ }
+ else
+ trackLabel->getTrackLabel()->setText(strtoqstr(track->getLabel()));
+
+ trackLabel->setFixedSize(labelWidth, m_cellSize - buttonGap);
+ trackLabel->setFixedHeight(m_cellSize - buttonGap);
+ trackLabel->setIndent(7);
+
+ connect(trackLabel, SIGNAL(renameTrack(QString, TrackId)),
+ SLOT(slotRenameTrack(QString, TrackId)));
+
+ // Store the TrackLabel pointer
+ //
+ m_trackLabels.push_back(trackLabel);
+
+ // Connect it
+ setButtonMapping(trackLabel, trackId);
+
+ connect(trackLabel, SIGNAL(changeToInstrumentList()),
+ m_instListSigMapper, SLOT(map()));
+ connect(trackLabel, SIGNAL(clicked()),
+ m_clickedSigMapper, SLOT(map()));
+
+ //
+ // instrument label
+ //
+ Rosegarden::Instrument *ins =
+ m_doc->getStudio().getInstrumentById(track->getInstrument());
+
+ QString instrumentName(i18n("<no instrument>"));
+ if (ins) instrumentName = strtoqstr(ins->getPresentationName());
+
+ // Set label to program change if it's being sent
+ //
+ if (ins != 0 && ins->sendsProgramChange())
+ trackLabel->setAlternativeLabel(strtoqstr(ins->getProgramName()));
+
+ trackLabel->showLabel(m_trackInstrumentLabels);
+
+ mute->setFixedSize(m_cellSize - buttonGap, m_cellSize - buttonGap);
+ record->setFixedSize(m_cellSize - buttonGap, m_cellSize - buttonGap);
+
+ // set the mute button
+ //
+ if (track->isMuted())
+ mute->off();
+
+ return trackHBox;
+}
+
+}
+#include "TrackButtons.moc"