/* -*- 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 , Chris Cannam , Richard Bown 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 #include #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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Rosegarden { TransportDialog::TransportDialog(TQWidget *parent, const char *name, WFlags flags): TQWidget(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(TQt::black); // set all the pixmap backgrounds to black to avoid // flickering when we update // m_transport->TenThousandthsPixmap->setBackgroundColor(TQt::black); m_transport->ThousandthsPixmap->setBackgroundColor(TQt::black); m_transport->HundredthsPixmap->setBackgroundColor(TQt::black); m_transport->TenthsPixmap->setBackgroundColor(TQt::black); m_transport->UnitSecondsPixmap->setBackgroundColor(TQt::black); m_transport->TenSecondsPixmap->setBackgroundColor(TQt::black); m_transport->UnitMinutesPixmap->setBackgroundColor(TQt::black); m_transport->TenMinutesPixmap->setBackgroundColor(TQt::black); m_transport->UnitHoursPixmap->setBackgroundColor(TQt::black); m_transport->TenHoursPixmap->setBackgroundColor(TQt::black); m_transport->NegativePixmap->setBackgroundColor(TQt::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 TQTimer(this); m_midiOutTimer = new TQTimer(this); m_clearMetronomeTimer = new TQTimer(this); connect(m_midiInTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotClearMidiInLabel())); connect(m_midiOutTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotClearMidiOutLabel())); connect(m_clearMetronomeTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotResetBackground())); m_transport->TimeDisplayLabel->hide(); m_transport->ToEndLabel->hide(); connect(m_transport->TimeDisplayButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotChangeTimeDisplay())); connect(m_transport->ToEndButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotChangeToEnd())); connect(m_transport->LoopButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotLoopButtonClicked())); connect(m_transport->PanelOpenButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotPanelOpenButtonClicked())); connect(m_transport->PanelCloseButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotPanelCloseButtonClicked())); connect(m_transport->PanicButton, TQT_SIGNAL(clicked()), TQT_SIGNAL(panic())); m_panelOpen = *m_transport->PanelOpenButton->pixmap(); m_panelClosed = *m_transport->PanelCloseButton->pixmap(); connect(m_transport->SetStartLPButton, TQT_SIGNAL(clicked()), TQT_SLOT(slotSetStartLoopingPointAtMarkerPos())); connect(m_transport->SetStopLPButton, TQT_SIGNAL(clicked()), TQT_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. // TQPalette pal; pal.setColor(TQColorGroup::Foreground, TQColor(192, 216, 255)); m_transport->TempoDisplay->setPalette(pal); m_transport->TempoDisplay->tqsetAlignment(int(TQLabel::AlignVCenter | TQLabel::AlignRight)); m_transport->TimeSigDisplay->setPalette(pal); m_transport->TimeSigDisplay->tqsetAlignment(int(TQLabel::AlignVCenter | TQLabel::AlignRight)); TQFont 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, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTempo())); connect(m_transport->TempoDisplay, TQT_SIGNAL(scrollWheel(int)), this, TQT_SIGNAL(scrollTempo(int))); connect(m_transport->TimeSigDisplay, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTimeSignature())); // toil through the individual pixmaps connect(m_transport->NegativePixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->TenHoursPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->UnitHoursPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->HourColonPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->TenMinutesPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->UnitMinutesPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->MinuteColonPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->TenSecondsPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->UnitSecondsPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->SecondColonPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->TenthsPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->HundredthsPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->HundredthColonPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->TenThousandthsPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); connect(m_transport->ThousandthsPixmap, TQT_SIGNAL(doubleClicked()), this, TQT_SLOT(slotEditTime())); // accelerator object // m_accelerators = new TQAccel(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::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 = TQApplication::desktop()->availableGeometry(TQPoint(x, y)).width(); int dh = TQApplication::desktop()->availableGeometry(TQPoint(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; TQWidget::show(); // std::cerr << "TransportDialog::show(): now at " << this->x() << "," << this->y() << std::endl; } else { TQWidget::show(); } } void TransportDialog::hide() { if (isVisible()) { KConfig* config = rgapp->config(); config->setGroup(GeneralOptionsConfigGroup); config->writeEntry("transportx", x()); config->writeEntry("transporty", y()); } TQWidget::hide(); } void TransportDialog::loadPixmaps() { m_lcdList.clear(); TQString fileName; TQString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/"); for (int i = 0; i < 10; i++) { fileName = TQString("%1/transport/led-%2.xpm").tqarg(pixmapDir).tqarg(i); if (!m_lcdList[i].load(fileName)) { std::cerr << "TransportDialog - failed to load pixmap \"" << fileName << "\"" << std::endl; } } // Load the "negative" sign pixmap // fileName = TQString("%1/transport/led--.xpm").tqarg(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(TQWidget *w) { TQFont 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) { TQCString replyType; TQByteArray replyData; m_sampleRate = 0; if (rgapp->sequencerCall("getSampleRate()", replyType, replyData)) { TQDataStream 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(TQString("%1").tqarg(m_sampleRate)); m_transport->TimeDisplayLabel->show(); break; } } void TransportDialog::setNewMode(const std::string& newModeAsString) { TimeDisplayMode newMode = RealMode; // default value if not found std::map::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(TQt::red); } else { slotSetBackground(TQt::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); TQString 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; TQString 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.getTQString() + TQString(" %1").tqarg(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(TQString("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.getTQString() + TQString(" %1").tqarg(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(TQString("NO EVENTS"))); } void TransportDialog::closeEvent (TQCloseEvent * /*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(TQColor 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 TQObjectList *tqchildren = m_transport->LCDBoxFrame->tqchildren(); TQObjectListIt it(*tqchildren); TQObject *obj; while ((obj = it.current()) != 0) { TQWidget *w = dynamic_cast(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"