summaryrefslogtreecommitdiffstats
path: root/src/gui/dialogs/TransportDialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/dialogs/TransportDialog.cpp')
-rw-r--r--src/gui/dialogs/TransportDialog.cpp1164
1 files changed, 1164 insertions, 0 deletions
diff --git a/src/gui/dialogs/TransportDialog.cpp b/src/gui/dialogs/TransportDialog.cpp
new file mode 100644
index 0000000..115a528
--- /dev/null
+++ b/src/gui/dialogs/TransportDialog.cpp
@@ -0,0 +1,1164 @@
+/* -*- 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 "TransportDialog.h"
+
+#include <klocale.h>
+#include <kstddirs.h>
+#include "base/Composition.h"
+#include "base/NotationTypes.h"
+#include "base/RealTime.h"
+#include "misc/Debug.h"
+#include "gui/application/RosegardenApplication.h"
+#include "gui/general/MidiPitchLabel.h"
+#include "gui/studio/StudioControl.h"
+#include "gui/widgets/Label.h"
+#include "sound/MappedEvent.h"
+#include "document/ConfigGroups.h"
+#include <kconfig.h>
+#include <kglobal.h>
+#include <qaccel.h>
+#include <qcolor.h>
+#include <qcstring.h>
+#include <qdatastream.h>
+#include <qfont.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qpalette.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qstring.h>
+#include <qtimer.h>
+#include <qwidget.h>
+
+
+namespace Rosegarden
+{
+
+TransportDialog::TransportDialog(QWidget *parent,
+ const char *name,
+ WFlags flags):
+ QWidget(parent, name, WType_TopLevel | WStyle_DialogBorder | WStyle_Minimize | WStyle_SysMenu | WDestructiveClose),
+ m_transport(0),
+ m_lastTenHours(0),
+ m_lastUnitHours(0),
+ m_lastTenMinutes(0),
+ m_lastUnitMinutes(0),
+ m_lastTenSeconds(0),
+ m_lastUnitSeconds(0),
+ m_lastTenths(0),
+ m_lastHundreths(0),
+ m_lastThousandths(0),
+ m_lastTenThousandths(0),
+ m_lastNegative(false),
+ m_lastMode(RealMode),
+ m_currentMode(RealMode),
+ m_tempo(0),
+ m_numerator(0),
+ m_denominator(0),
+ m_framesPerSecond(24),
+ m_bitsPerFrame(80),
+ m_isExpanded(true),
+ m_haveOriginalBackground(false),
+ m_isBackgroundSet(false),
+ m_sampleRate(0)
+{
+ m_transport = new RosegardenTransport(this);
+
+ setCaption(i18n("Rosegarden Transport"));
+
+ resetFonts();
+
+ initModeMap();
+
+ // set the LCD frame background to black
+ //
+ m_transport->LCDBoxFrame->setBackgroundColor(Qt::black);
+
+ // set all the pixmap backgrounds to black to avoid
+ // flickering when we update
+ //
+ m_transport->TenThousandthsPixmap->setBackgroundColor(Qt::black);
+ m_transport->ThousandthsPixmap->setBackgroundColor(Qt::black);
+ m_transport->HundredthsPixmap->setBackgroundColor(Qt::black);
+ m_transport->TenthsPixmap->setBackgroundColor(Qt::black);
+ m_transport->UnitSecondsPixmap->setBackgroundColor(Qt::black);
+ m_transport->TenSecondsPixmap->setBackgroundColor(Qt::black);
+ m_transport->UnitMinutesPixmap->setBackgroundColor(Qt::black);
+ m_transport->TenMinutesPixmap->setBackgroundColor(Qt::black);
+ m_transport->UnitHoursPixmap->setBackgroundColor(Qt::black);
+ m_transport->TenHoursPixmap->setBackgroundColor(Qt::black);
+ m_transport->NegativePixmap->setBackgroundColor(Qt::black);
+
+ // unset the negative sign to begin with
+ m_transport->NegativePixmap->clear();
+
+ // Set our toggle buttons
+ //
+ m_transport->PlayButton->setToggleButton(true);
+ m_transport->RecordButton->setToggleButton(true);
+
+// Disable the loop button if JACK transport enabled, because this
+// causes a nasty race condition, and it just seems our loops are not JACK compatible
+// #1240039 - DMM
+// KConfig* config = rgapp->config();
+// config->setGroup(SequencerOptionsConfigGroup);
+// if (config->readBoolEntry("jacktransport", false))
+// {
+// m_transport->LoopButton->setEnabled(false);
+// }
+
+ // fix and hold the size of the dialog
+ //
+ setMinimumSize(m_transport->width(), m_transport->height());
+ setMaximumSize(m_transport->width(), m_transport->height());
+
+ loadPixmaps();
+
+ // Create Midi label timers
+ m_midiInTimer = new QTimer(this);
+ m_midiOutTimer = new QTimer(this);
+ m_clearMetronomeTimer = new QTimer(this);
+
+ connect(m_midiInTimer, SIGNAL(timeout()),
+ SLOT(slotClearMidiInLabel()));
+
+ connect(m_midiOutTimer, SIGNAL(timeout()),
+ SLOT(slotClearMidiOutLabel()));
+
+ connect(m_clearMetronomeTimer, SIGNAL(timeout()),
+ SLOT(slotResetBackground()));
+
+ m_transport->TimeDisplayLabel->hide();
+ m_transport->ToEndLabel->hide();
+
+ connect(m_transport->TimeDisplayButton, SIGNAL(clicked()),
+ SLOT(slotChangeTimeDisplay()));
+
+ connect(m_transport->ToEndButton, SIGNAL(clicked()),
+ SLOT(slotChangeToEnd()));
+
+ connect(m_transport->LoopButton, SIGNAL(clicked()),
+ SLOT(slotLoopButtonClicked()));
+
+ connect(m_transport->PanelOpenButton, SIGNAL(clicked()),
+ SLOT(slotPanelOpenButtonClicked()));
+
+ connect(m_transport->PanelCloseButton, SIGNAL(clicked()),
+ SLOT(slotPanelCloseButtonClicked()));
+
+ connect(m_transport->PanicButton, SIGNAL(clicked()), SIGNAL(panic()));
+
+ m_panelOpen = *m_transport->PanelOpenButton->pixmap();
+ m_panelClosed = *m_transport->PanelCloseButton->pixmap();
+
+
+ connect(m_transport->SetStartLPButton, SIGNAL(clicked()), SLOT(slotSetStartLoopingPointAtMarkerPos()));
+ connect(m_transport->SetStopLPButton, SIGNAL(clicked()), SLOT(slotSetStopLoopingPointAtMarkerPos()));
+
+ // clear labels
+ //
+ slotClearMidiInLabel();
+ slotClearMidiOutLabel();
+
+ // and by default we close the lower panel
+ //
+ int rfh = m_transport->RecordingFrame->height();
+ m_transport->RecordingFrame->hide();
+ setFixedSize(width(), height() - rfh);
+ m_transport->PanelOpenButton->setPixmap(m_panelClosed);
+
+ // and since by default we show real time (not SMPTE), by default
+ // we hide the small colon pixmaps
+ //
+ m_transport->SecondColonPixmap->hide();
+ m_transport->HundredthColonPixmap->hide();
+
+ // We have to specify these settings in this class (copied
+ // from rosegardentransport.cpp) as we're using a specialised
+ // widgets for TempoDisplay. Ugly but works - does mean that
+ // if the rest of the Transport ever changes then this code
+ // will have to as well.
+ //
+ QPalette pal;
+ pal.setColor(QColorGroup::Foreground, QColor(192, 216, 255));
+
+ m_transport->TempoDisplay->setPalette(pal);
+ m_transport->TempoDisplay->setAlignment(int(QLabel::AlignVCenter | QLabel::AlignRight));
+
+ m_transport->TimeSigDisplay->setPalette(pal);
+ m_transport->TimeSigDisplay->setAlignment(int(QLabel::AlignVCenter | QLabel::AlignRight));
+
+ QFont localFont(m_transport->OutDisplay->font() );
+ localFont.setFamily( "lucida" );
+ localFont.setBold( TRUE );
+
+ m_transport->TempoDisplay->setFont( localFont );
+ m_transport->TimeSigDisplay->setFont( localFont );
+
+ connect(m_transport->TempoDisplay, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTempo()));
+
+ connect(m_transport->TempoDisplay, SIGNAL(scrollWheel(int)),
+ this, SIGNAL(scrollTempo(int)));
+
+ connect(m_transport->TimeSigDisplay, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTimeSignature()));
+
+ // toil through the individual pixmaps
+ connect(m_transport->NegativePixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->TenHoursPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->UnitHoursPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->HourColonPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->TenMinutesPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->UnitMinutesPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->MinuteColonPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->TenSecondsPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->UnitSecondsPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->SecondColonPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->TenthsPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->HundredthsPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->HundredthColonPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->TenThousandthsPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+ connect(m_transport->ThousandthsPixmap, SIGNAL(doubleClicked()),
+ this, SLOT(slotEditTime()));
+
+ // accelerator object
+ //
+ m_accelerators = new QAccel(this);
+}
+
+TransportDialog::~TransportDialog()
+{
+ if (isVisible()) {
+ KConfig* config = rgapp->config();
+ config->setGroup(GeneralOptionsConfigGroup);
+ config->writeEntry("transportx", x());
+ config->writeEntry("transporty", y());
+ }
+}
+
+std::string
+TransportDialog::getCurrentModeAsString()
+{
+ bool found = false;
+ for (std::map<std::string, TimeDisplayMode>::iterator iter = m_modeMap.begin();
+ iter != m_modeMap.end() && !found;
+ iter++)
+ {
+ if (iter->second == m_currentMode) {
+ return iter->first;
+ }
+ }
+
+ // we shouldn't get here unless the map is not well-configured
+ RG_DEBUG << "TransportDialog::getCurrentModeAsString: could not map current mode "
+ << m_currentMode << " to string." << endl;
+ throw Exception("could not map current mode to string.");
+}
+
+void
+TransportDialog::initModeMap()
+{
+ m_modeMap["RealMode"] = RealMode;
+ m_modeMap["SMPTEMode"] = SMPTEMode;
+ m_modeMap["BarMode"] = BarMode;
+ m_modeMap["BarMetronomeMode"] = BarMetronomeMode;
+ m_modeMap["FrameMode"] = FrameMode;
+}
+
+void
+TransportDialog::show()
+{
+ KConfig* config = rgapp->config();
+ config->setGroup(GeneralOptionsConfigGroup);
+ int x = config->readNumEntry("transportx", -1);
+ int y = config->readNumEntry("transporty", -1);
+ if (x >= 0 && y >= 0) {
+ int dw = QApplication::desktop()->availableGeometry(QPoint(x, y)).width();
+ int dh = QApplication::desktop()->availableGeometry(QPoint(x, y)).height();
+ if (x + m_transport->width() > dw) x = dw - m_transport->width();
+ if (y + m_transport->height() > dh) y = dh - m_transport->height();
+ move(x, y);
+// std::cerr << "TransportDialog::show(): moved to " << x << "," << y << std::endl;
+ QWidget::show();
+// std::cerr << "TransportDialog::show(): now at " << this->x() << "," << this->y() << std::endl;
+ } else {
+ QWidget::show();
+ }
+}
+
+void
+TransportDialog::hide()
+{
+ if (isVisible()) {
+ KConfig* config = rgapp->config();
+ config->setGroup(GeneralOptionsConfigGroup);
+ config->writeEntry("transportx", x());
+ config->writeEntry("transporty", y());
+ }
+ QWidget::hide();
+}
+
+void
+TransportDialog::loadPixmaps()
+{
+ m_lcdList.clear();
+ QString fileName;
+ QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/");
+
+ for (int i = 0; i < 10; i++) {
+ fileName = QString("%1/transport/led-%2.xpm").arg(pixmapDir).arg(i);
+ if (!m_lcdList[i].load(fileName)) {
+ std::cerr << "TransportDialog - failed to load pixmap \""
+ << fileName << "\"" << std::endl;
+ }
+ }
+
+ // Load the "negative" sign pixmap
+ //
+ fileName = QString("%1/transport/led--.xpm").arg(pixmapDir);
+ m_lcdNegative.load(fileName);
+
+}
+
+void
+TransportDialog::resetFonts()
+{
+ resetFont(m_transport->TimeSigLabel);
+ resetFont(m_transport->TimeSigDisplay);
+ resetFont(m_transport->TempoLabel);
+ resetFont(m_transport->TempoDisplay);
+ resetFont(m_transport->DivisionLabel);
+ resetFont(m_transport->DivisionDisplay);
+ resetFont(m_transport->InLabel);
+ resetFont(m_transport->InDisplay);
+ resetFont(m_transport->OutLabel);
+ resetFont(m_transport->OutDisplay);
+ resetFont(m_transport->ToEndLabel);
+ resetFont(m_transport->TimeDisplayLabel);
+}
+
+void
+TransportDialog::resetFont(QWidget *w)
+{
+ QFont font = w->font();
+ font.setPixelSize(10);
+ w->setFont(font);
+}
+
+void
+TransportDialog::setSMPTEResolution(int framesPerSecond,
+ int bitsPerFrame)
+{
+ m_framesPerSecond = framesPerSecond;
+ m_bitsPerFrame = bitsPerFrame;
+}
+
+void
+TransportDialog::getSMPTEResolution(int &framesPerSecond,
+ int &bitsPerFrame)
+{
+ framesPerSecond = m_framesPerSecond;
+ bitsPerFrame = m_bitsPerFrame;
+}
+
+void
+TransportDialog::computeSampleRate()
+{
+ if (m_sampleRate == 0) {
+
+ QCString replyType;
+ QByteArray replyData;
+ m_sampleRate = 0;
+
+ if (rgapp->sequencerCall("getSampleRate()", replyType, replyData)) {
+ QDataStream streamIn(replyData, IO_ReadOnly);
+ unsigned int result;
+ streamIn >> result;
+ m_sampleRate = result;
+ } else {
+ m_sampleRate = -1;
+ }
+ }
+
+}
+
+void
+TransportDialog::cycleThroughModes()
+{
+ switch (m_currentMode) {
+
+ case RealMode:
+ if (m_sampleRate > 0)
+ m_currentMode = FrameMode;
+ else
+ m_currentMode = BarMode;
+ break;
+
+ case FrameMode:
+ m_currentMode = BarMode;
+ break;
+
+ case SMPTEMode:
+ m_currentMode = BarMode;
+ break;
+
+ case BarMode:
+ m_currentMode = BarMetronomeMode;
+ break;
+
+ case BarMetronomeMode:
+ m_currentMode = RealMode;
+ break;
+ }
+}
+
+void
+TransportDialog::displayTime()
+{
+ switch (m_currentMode) {
+ case RealMode:
+ m_clearMetronomeTimer->stop();
+ m_transport->TimeDisplayLabel->hide();
+ break;
+
+ case SMPTEMode:
+ m_clearMetronomeTimer->stop();
+ m_transport->TimeDisplayLabel->setText("SMPTE"); // DO NOT i18n
+ m_transport->TimeDisplayLabel->show();
+ break;
+
+ case BarMode:
+ m_clearMetronomeTimer->stop();
+ m_transport->TimeDisplayLabel->setText("BAR"); // DO NOT i18n
+ m_transport->TimeDisplayLabel->show();
+ break;
+
+ case BarMetronomeMode:
+ m_clearMetronomeTimer->start(1700, FALSE);
+ m_transport->TimeDisplayLabel->setText("MET"); // DO NOT i18n
+ m_transport->TimeDisplayLabel->show();
+ break;
+
+ case FrameMode:
+ m_clearMetronomeTimer->stop();
+ m_transport->TimeDisplayLabel->setText(QString("%1").arg(m_sampleRate));
+ m_transport->TimeDisplayLabel->show();
+ break;
+ }
+}
+
+void
+TransportDialog::setNewMode(const std::string& newModeAsString)
+{
+ TimeDisplayMode newMode = RealMode; // default value if not found
+
+ std::map<std::string, TimeDisplayMode>::iterator iter =
+ m_modeMap.find(newModeAsString);
+
+ if (iter != m_modeMap.end()) {
+ // value found
+ newMode = iter->second;
+ } else {
+ // don't fail: use default value set at declaration
+ }
+
+ setNewMode(newMode);
+}
+
+void
+TransportDialog::setNewMode(const TimeDisplayMode& newMode)
+{
+ computeSampleRate();
+
+ m_currentMode = newMode;
+
+ displayTime();
+}
+
+
+void
+TransportDialog::slotChangeTimeDisplay()
+{
+ computeSampleRate();
+
+ cycleThroughModes();
+
+ displayTime();
+}
+
+void
+TransportDialog::slotChangeToEnd()
+{
+ if (m_transport->ToEndButton->isOn()) {
+ m_transport->ToEndLabel->show();
+ } else {
+ m_transport->ToEndLabel->hide();
+ }
+}
+
+bool
+TransportDialog::isShowingTimeToEnd()
+{
+ return m_transport->ToEndButton->isOn();
+}
+
+void
+TransportDialog::displayRealTime(const RealTime &rt)
+{
+ RealTime st = rt;
+
+ slotResetBackground();
+
+ if (m_lastMode != RealMode) {
+ m_transport->HourColonPixmap->show();
+ m_transport->MinuteColonPixmap->show();
+ m_transport->SecondColonPixmap->hide();
+ m_transport->HundredthColonPixmap->hide();
+ m_lastMode = RealMode;
+ }
+
+ // If time is negative then reverse the time and set the minus flag
+ //
+ if (st < RealTime::zeroTime) {
+ st = RealTime::zeroTime - st;
+ if (!m_lastNegative) {
+ m_transport->NegativePixmap->setPixmap(m_lcdNegative);
+ m_lastNegative = true;
+ }
+ } else // don't show the flag
+ {
+ if (m_lastNegative) {
+ m_transport->NegativePixmap->clear();
+ m_lastNegative = false;
+ }
+ }
+
+ m_tenThousandths = ( st.usec() / 100 ) % 10;
+ m_thousandths = ( st.usec() / 1000 ) % 10;
+ m_hundreths = ( st.usec() / 10000 ) % 10;
+ m_tenths = ( st.usec() / 100000 ) % 10;
+
+ m_unitSeconds = ( st.sec ) % 10;
+ m_tenSeconds = ( st.sec / 10 ) % 6;
+
+ m_unitMinutes = ( st.sec / 60 ) % 10;
+ m_tenMinutes = ( st.sec / 600 ) % 6;
+
+ m_unitHours = ( st.sec / 3600 ) % 10;
+ m_tenHours = (st.sec / 36000 ) % 10;
+
+ updateTimeDisplay();
+}
+
+void
+TransportDialog::displayFrameTime(const RealTime &rt)
+{
+ RealTime st = rt;
+
+ slotResetBackground();
+
+ if (m_lastMode != FrameMode) {
+ m_transport->HourColonPixmap->hide();
+ m_transport->MinuteColonPixmap->hide();
+ m_transport->SecondColonPixmap->hide();
+ m_transport->HundredthColonPixmap->hide();
+ m_lastMode = FrameMode;
+ }
+
+ // If time is negative then reverse the time and set the minus flag
+ //
+ if (st < RealTime::zeroTime) {
+ st = RealTime::zeroTime - st;
+ if (!m_lastNegative) {
+ m_transport->NegativePixmap->setPixmap(m_lcdNegative);
+ m_lastNegative = true;
+ }
+ } else // don't show the flag
+ {
+ if (m_lastNegative) {
+ m_transport->NegativePixmap->clear();
+ m_lastNegative = false;
+ }
+ }
+
+ long frame = RealTime::realTime2Frame(st, m_sampleRate);
+
+ m_tenThousandths = frame % 10;
+ frame /= 10;
+ m_thousandths = frame % 10;
+ frame /= 10;
+ m_hundreths = frame % 10;
+ frame /= 10;
+ m_tenths = frame % 10;
+ frame /= 10;
+ m_unitSeconds = frame % 10;
+ frame /= 10;
+ m_tenSeconds = frame % 10;
+ frame /= 10;
+ m_unitMinutes = frame % 10;
+ frame /= 10;
+ m_tenMinutes = frame % 10;
+ frame /= 10;
+ m_unitHours = frame % 10;
+ frame /= 10;
+ m_tenHours = frame % 10;
+ frame /= 10;
+
+ updateTimeDisplay();
+}
+
+void
+TransportDialog::displaySMPTETime(const RealTime &rt)
+{
+ RealTime st = rt;
+
+ slotResetBackground();
+
+ if (m_lastMode != SMPTEMode) {
+ m_transport->HourColonPixmap->show();
+ m_transport->MinuteColonPixmap->show();
+ m_transport->SecondColonPixmap->show();
+ m_transport->HundredthColonPixmap->show();
+ m_lastMode = SMPTEMode;
+ }
+
+ // If time is negative then reverse the time and set the minus flag
+ //
+ if (st < RealTime::zeroTime) {
+ st = RealTime::zeroTime - st;
+ if (!m_lastNegative) {
+ m_transport->NegativePixmap->setPixmap(m_lcdNegative);
+ m_lastNegative = true;
+ }
+ } else // don't show the flag
+ {
+ if (m_lastNegative) {
+ m_transport->NegativePixmap->clear();
+ m_lastNegative = false;
+ }
+ }
+
+ m_tenThousandths =
+ (( st.usec() * m_framesPerSecond * m_bitsPerFrame) / 1000000 ) % 10;
+ m_thousandths =
+ (( st.usec() * m_framesPerSecond * m_bitsPerFrame) / 10000000 ) %
+ (m_bitsPerFrame / 10);
+ m_hundreths =
+ (( st.usec() * m_framesPerSecond) / 1000000 ) % 10;
+ m_tenths =
+ (( st.usec() * m_framesPerSecond) / 10000000 ) % 10;
+
+ m_unitSeconds = ( st.sec ) % 10;
+ m_tenSeconds = ( st.sec / 10 ) % 6;
+
+ m_unitMinutes = ( st.sec / 60 ) % 10;
+ m_tenMinutes = ( st.sec / 600 ) % 6;
+
+ m_unitHours = ( st.sec / 3600 ) % 10;
+ m_tenHours = ( st.sec / 36000 ) % 10;
+
+ updateTimeDisplay();
+}
+
+void
+TransportDialog::displayBarTime(int bar, int beat, int unit)
+{
+ if (m_lastMode != BarMode) {
+ m_transport->HourColonPixmap->hide();
+ m_transport->MinuteColonPixmap->show();
+ m_transport->SecondColonPixmap->hide();
+ m_transport->HundredthColonPixmap->hide();
+ m_lastMode = BarMode;
+ }
+
+ // If time is negative then reverse the time and set the minus flag
+ //
+ if (bar < 0) {
+ bar = -bar;
+ if (!m_lastNegative) {
+ m_transport->NegativePixmap->setPixmap(m_lcdNegative);
+ m_lastNegative = true;
+ }
+ } else // don't show the flag
+ {
+ if (m_lastNegative) {
+ m_transport->NegativePixmap->clear();
+ m_lastNegative = false;
+ }
+ }
+
+ if (m_currentMode == BarMetronomeMode && unit < 2) {
+ if (beat == 1) {
+ slotSetBackground(Qt::red);
+ } else {
+ slotSetBackground(Qt::cyan);
+ }
+ } else {
+ slotResetBackground();
+ }
+
+ m_tenThousandths = ( unit ) % 10;
+ m_thousandths = ( unit / 10 ) % 10;
+ m_hundreths = ( unit / 100 ) % 10;
+ m_tenths = ( unit / 1000 ) % 10;
+
+ if (m_tenths == 0) {
+ m_tenths = -1;
+ if (m_hundreths == 0) {
+ m_hundreths = -1;
+ if (m_thousandths == 0) {
+ m_thousandths = -1;
+ }
+ }
+ }
+
+ m_unitSeconds = ( beat ) % 10;
+ m_tenSeconds = ( beat / 10 ) % 6;
+
+ if (m_tenSeconds == 0) {
+ m_tenSeconds = -1;
+ }
+
+ m_unitMinutes = ( bar ) % 10;
+ m_tenMinutes = ( bar / 10 ) % 10;
+
+ m_unitHours = ( bar / 100 ) % 10;
+ m_tenHours = ( bar / 1000 ) % 10;
+
+ if (m_tenHours == 0) {
+ m_tenHours = -1;
+ if (m_unitHours == 0) {
+ m_unitHours = -1;
+ if (m_tenMinutes == 0) {
+ m_tenMinutes = -1;
+ }
+ }
+ }
+
+ updateTimeDisplay();
+}
+
+void
+TransportDialog::updateTimeDisplay()
+{
+ if (m_tenThousandths != m_lastTenThousandths) {
+ if (m_tenThousandths < 0)
+ m_transport->TenThousandthsPixmap->clear();
+ else
+ m_transport->TenThousandthsPixmap->setPixmap(m_lcdList[m_tenThousandths]);
+ m_lastTenThousandths = m_tenThousandths;
+ }
+
+ if (m_thousandths != m_lastThousandths) {
+ if (m_thousandths < 0)
+ m_transport->ThousandthsPixmap->clear();
+ else
+ m_transport->ThousandthsPixmap->setPixmap(m_lcdList[m_thousandths]);
+ m_lastThousandths = m_thousandths;
+ }
+
+ if (m_hundreths != m_lastHundreths) {
+ if (m_hundreths < 0)
+ m_transport->HundredthsPixmap->clear();
+ else
+ m_transport->HundredthsPixmap->setPixmap(m_lcdList[m_hundreths]);
+ m_lastHundreths = m_hundreths;
+ }
+
+ if (m_tenths != m_lastTenths) {
+ if (m_tenths < 0)
+ m_transport->TenthsPixmap->clear();
+ else
+ m_transport->TenthsPixmap->setPixmap(m_lcdList[m_tenths]);
+ m_lastTenths = m_tenths;
+ }
+
+ if (m_unitSeconds != m_lastUnitSeconds) {
+ if (m_unitSeconds < 0)
+ m_transport->UnitSecondsPixmap->clear();
+ else
+ m_transport->UnitSecondsPixmap->setPixmap(m_lcdList[m_unitSeconds]);
+ m_lastUnitSeconds = m_unitSeconds;
+ }
+
+ if (m_tenSeconds != m_lastTenSeconds) {
+ if (m_tenSeconds < 0)
+ m_transport->TenSecondsPixmap->clear();
+ else
+ m_transport->TenSecondsPixmap->setPixmap(m_lcdList[m_tenSeconds]);
+ m_lastTenSeconds = m_tenSeconds;
+ }
+
+ if (m_unitMinutes != m_lastUnitMinutes) {
+ if (m_unitMinutes < 0)
+ m_transport->UnitMinutesPixmap->clear();
+ else
+ m_transport->UnitMinutesPixmap->setPixmap(m_lcdList[m_unitMinutes]);
+ m_lastUnitMinutes = m_unitMinutes;
+ }
+
+ if (m_tenMinutes != m_lastTenMinutes) {
+ if (m_tenMinutes < 0)
+ m_transport->TenMinutesPixmap->clear();
+ else
+ m_transport->TenMinutesPixmap->setPixmap(m_lcdList[m_tenMinutes]);
+ m_lastTenMinutes = m_tenMinutes;
+ }
+
+ if (m_unitHours != m_lastUnitHours) {
+ if (m_unitHours < 0)
+ m_transport->UnitHoursPixmap->clear();
+ else
+ m_transport->UnitHoursPixmap->setPixmap(m_lcdList[m_unitHours]);
+ m_lastUnitHours = m_unitHours;
+ }
+
+ if (m_tenHours != m_lastTenHours) {
+ if (m_tenHours < 0)
+ m_transport->TenHoursPixmap->clear();
+ else
+ m_transport->TenHoursPixmap->setPixmap(m_lcdList[m_tenHours]);
+ m_lastTenHours = m_tenHours;
+ }
+}
+
+void
+TransportDialog::setTempo(const tempoT &tempo)
+{
+ if (m_tempo == tempo)
+ return ;
+ m_tempo = tempo;
+
+ // Send the quarter note length to the sequencer - shouldn't
+ // really hang this off here but at least it's a single point
+ // where the tempo should always be consistent. Quarter Note
+ // Length is sent (MIDI CLOCK) at 24ppqn.
+ //
+ double qnD = 60.0 / Composition::getTempoQpm(tempo);
+ RealTime qnTime =
+ RealTime(long(qnD),
+ long((qnD - double(long(qnD))) * 1000000000.0));
+
+ StudioControl::sendQuarterNoteLength(qnTime);
+
+ QString tempoString;
+ tempoString.sprintf("%4.3f", Composition::getTempoQpm(tempo));
+
+ m_transport->TempoDisplay->setText(tempoString);
+}
+
+void
+TransportDialog::setTimeSignature(const TimeSignature &timeSig)
+{
+ int numerator = timeSig.getNumerator();
+ int denominator = timeSig.getDenominator();
+ if (m_numerator == numerator && m_denominator == denominator)
+ return ;
+ m_numerator = numerator;
+ m_denominator = denominator;
+
+ QString timeSigString;
+ timeSigString.sprintf("%d/%d", numerator, denominator);
+ m_transport->TimeSigDisplay->setText(timeSigString);
+}
+
+void
+TransportDialog::setMidiInLabel(const MappedEvent *mE)
+{
+ assert(mE > 0);
+
+ switch (mE->getType()) {
+ case MappedEvent::MidiNote:
+ case MappedEvent::MidiNoteOneShot:
+ {
+ // don't do anything if we've got an effective NOTE OFF
+ //
+ if (mE->getVelocity() == 0)
+ return ;
+
+ MidiPitchLabel mPL(mE->getPitch());
+ m_transport->InDisplay->setText
+ (mPL.getQString() +
+ QString(" %1").arg(mE->getVelocity()));
+ }
+ break;
+
+ case MappedEvent::MidiPitchBend:
+ m_transport->InDisplay->setText(i18n("PITCH WHEEL"));
+ break;
+
+ case MappedEvent::MidiController:
+ m_transport->InDisplay->setText(i18n("CONTROLLER"));
+ break;
+
+ case MappedEvent::MidiProgramChange:
+ m_transport->InDisplay->setText(i18n("PROG CHNGE"));
+ break;
+
+ case MappedEvent::MidiKeyPressure:
+ case MappedEvent::MidiChannelPressure:
+ m_transport->InDisplay->setText(i18n("PRESSURE"));
+ break;
+
+ case MappedEvent::MidiSystemMessage:
+ m_transport->InDisplay->setText(i18n("SYS MESSAGE"));
+ break;
+
+ default: // do nothing
+ return ;
+ }
+
+ // Reset the timer if it's already running
+ //
+ if (m_midiInTimer->isActive())
+ m_midiInTimer->stop();
+
+ // 1.5 second timeout for MIDI event
+ //
+ m_midiInTimer->start(1500, true);
+}
+
+void
+TransportDialog::slotClearMidiInLabel()
+{
+ m_transport->InDisplay->setText(i18n(QString("NO EVENTS")));
+
+ // also, just to be sure:
+ slotResetBackground();
+}
+
+void
+TransportDialog::setMidiOutLabel(const MappedEvent *mE)
+{
+ assert(mE > 0);
+
+ switch (mE->getType()) {
+ case MappedEvent::MidiNote:
+ case MappedEvent::MidiNoteOneShot:
+ {
+ MidiPitchLabel mPL(mE->getPitch());
+ m_transport->OutDisplay->setText
+ (mPL.getQString() +
+ QString(" %1").arg(mE->getVelocity()));
+ }
+ break;
+
+ case MappedEvent::MidiPitchBend:
+ m_transport->OutDisplay->setText(i18n("PITCH WHEEL"));
+ break;
+
+ case MappedEvent::MidiController:
+ m_transport->OutDisplay->setText(i18n("CONTROLLER"));
+ break;
+
+ case MappedEvent::MidiProgramChange:
+ m_transport->OutDisplay->setText(i18n("PROG CHNGE"));
+ break;
+
+ case MappedEvent::MidiKeyPressure:
+ case MappedEvent::MidiChannelPressure:
+ m_transport->OutDisplay->setText(i18n("PRESSURE"));
+ break;
+
+ case MappedEvent::MidiSystemMessage:
+ m_transport->OutDisplay->setText(i18n("SYS MESSAGE"));
+ break;
+
+ default: // do nothing
+ return ;
+ }
+
+ // Reset the timer if it's already running
+ //
+ if (m_midiOutTimer->isActive())
+ m_midiOutTimer->stop();
+
+ // 200 millisecond timeout
+ //
+ m_midiOutTimer->start(200, true);
+}
+
+void
+TransportDialog::slotClearMidiOutLabel()
+{
+ m_transport->OutDisplay->setText(i18n(QString("NO EVENTS")));
+}
+
+void
+TransportDialog::closeEvent (QCloseEvent * /*e*/)
+{
+ //e->accept(); // accept the close event here
+ emit closed();
+}
+
+void
+TransportDialog::slotLoopButtonClicked()
+{
+ // disable if JACK transport has been set #1240039 - DMM
+ // KConfig* config = rgapp->config();
+ // config->setGroup(SequencerOptionsConfigGroup);
+ // if (config->readBoolEntry("jacktransport", false))
+ // {
+ // //!!! - this will fail silently
+ // m_transport->LoopButton->setEnabled(false);
+ // m_transport->LoopButton->setOn(false);
+ // return;
+ // }
+
+ if (m_transport->LoopButton->isOn()) {
+ emit setLoop();
+ } else {
+ emit unsetLoop();
+ }
+}
+
+void
+TransportDialog::slotSetStartLoopingPointAtMarkerPos()
+{
+ emit setLoopStartTime();
+}
+
+void
+TransportDialog::slotSetStopLoopingPointAtMarkerPos()
+{
+ emit setLoopStopTime();
+}
+
+void
+TransportDialog::slotPanelOpenButtonClicked()
+{
+ int rfh = m_transport->RecordingFrame->height();
+
+ if (m_transport->RecordingFrame->isVisible()) {
+ m_transport->RecordingFrame->hide();
+ setFixedSize(width(), height() - rfh);
+ m_transport->PanelOpenButton->setPixmap(m_panelClosed);
+ m_isExpanded = false;
+ } else {
+ setFixedSize(width(), height() + rfh);
+ m_transport->RecordingFrame->show();
+ m_transport->PanelOpenButton->setPixmap(m_panelOpen);
+ m_isExpanded = true;
+ }
+}
+
+void
+TransportDialog::slotPanelCloseButtonClicked()
+{
+ int rfh = m_transport->RecordingFrame->height();
+
+ if (m_transport->RecordingFrame->isVisible()) {
+ m_transport->RecordingFrame->hide();
+ setFixedSize(width(), height() - rfh);
+ m_transport->PanelOpenButton->setPixmap(m_panelClosed);
+ m_isExpanded = false;
+ }
+}
+
+bool
+TransportDialog::isExpanded()
+{
+ return m_isExpanded;
+}
+
+void
+TransportDialog::slotEditTempo()
+{
+ emit editTempo(this);
+}
+
+void
+TransportDialog::slotEditTimeSignature()
+{
+ emit editTimeSignature(this);
+}
+
+void
+TransportDialog::slotEditTime()
+{
+ emit editTransportTime(this);
+}
+
+void
+TransportDialog::slotSetBackground(QColor c)
+{
+ if (!m_haveOriginalBackground) {
+ m_originalBackground = m_transport->LCDBoxFrame->paletteBackgroundColor();
+ m_haveOriginalBackground = true;
+ }
+
+ m_transport->LCDBoxFrame->setPaletteBackgroundColor(c);
+ m_transport->NegativePixmap->setPaletteBackgroundColor(c);
+ m_transport->TenHoursPixmap->setPaletteBackgroundColor(c);
+ m_transport->UnitHoursPixmap->setPaletteBackgroundColor(c);
+ m_transport->TimeDisplayLabel->setPaletteBackgroundColor(c);
+
+ /* this is a bit more thorough, but too slow and flickery:
+
+ const QObjectList *children = m_transport->LCDBoxFrame->children();
+ QObjectListIt it(*children);
+ QObject *obj;
+
+ while ((obj = it.current()) != 0) {
+
+ QWidget *w = dynamic_cast<QWidget *>(obj);
+ if (w) {
+ w->setPaletteBackgroundColor(c);
+ }
+ ++it;
+ }
+
+ */
+
+ m_isBackgroundSet = true;
+}
+
+void
+TransportDialog::slotResetBackground()
+{
+ if (m_isBackgroundSet) {
+ slotSetBackground(m_originalBackground);
+ }
+ m_isBackgroundSet = false;
+}
+
+}
+#include "TransportDialog.moc"