Blob Blame Raw


#include "linetestpane.h"
#ifdef LINETEST
#include "xsheetdragtool.h"
#include "toutputproperties.h"
#include "tapp.h"
#include "toutputproperties.h"
#include "toonz/tcolumnhandle.h"
#include "toonz/txshlevelhandle.h"
#include "toonz/toonzscene.h"
#include "toonz/sceneproperties.h"

#include <QThread>
#include <QStackedWidget>

using namespace DVGui;

//=============================================================================
// MixAudioThread
//-----------------------------------------------------------------------------

MixAudioThread::MixAudioThread(QObject *parent)
    : QThread(parent), m_abort(false), m_restart(false) {}

//-----------------------------------------------------------------------------

MixAudioThread::~MixAudioThread() {
  m_mutex.lock();
  m_abort = true;
  m_condition.wakeOne();
  m_mutex.unlock();
  wait();
}

//-----------------------------------------------------------------------------

void MixAudioThread::run() {
  forever {
    m_mutex.lock();
    int from = this->m_from;
    int to   = this->m_to;
    m_mutex.unlock();

    if (m_abort) return;

    TXsheet::SoundProperties *prop = new TXsheet::SoundProperties();
    prop->m_fromFrame              = from;
    prop->m_toFrame                = to;
    m_computedBuffer =
        TApp::instance()->getCurrentXsheet()->getXsheet()->makeSound(prop);
    m_buffer                       = TSoundTrackP();
    if (m_computedBuffer) m_buffer = m_computedBuffer->clone();

    if (!m_restart && m_buffer) emit computedBuffer();

    m_mutex.lock();
    if (!m_restart) m_condition.wait(&m_mutex);
    m_restart = false;
    m_mutex.unlock();
  }
}

//-----------------------------------------------------------------------------

void MixAudioThread::computeBuffer(int fromFrame, int toFrame) {
  QMutexLocker locker(&m_mutex);

  this->m_from = fromFrame;
  this->m_to   = toFrame;

  if (!isRunning()) {
    start(QThread::NormalPriority);
  } else {
    m_restart = true;
    m_condition.wakeOne();
  }
}

//=============================================================================
// LineTestPane
//-----------------------------------------------------------------------------

LineTestPane::LineTestPane(QWidget *parent, Qt::WFlags flags)
    : TPanel(parent)
    , m_flipConsole(0)
    , m_keyFrameButton(0)
    , m_mainTrack(0)
    , m_startTrack(0)
    , m_player(0)
    , m_trackStartFrame(0)
    , m_startPlayRange(-1)
    , m_endPlayRange(0)
    , m_bufferSize(0)
    , m_nextBufferSize(0) {
  bool ret     = true;
  QFrame *hbox = new QFrame(this);
  hbox->setFrameStyle(QFrame::StyledPanel);
  hbox->setObjectName("OnePixelMarginFrame");

  QVBoxLayout *mainLayout = new QVBoxLayout(hbox);
  mainLayout->setMargin(0);
  mainLayout->setSpacing(0);

  // Viewer
  m_stackedWidget = new QStackedWidget(this);
  m_sceneViewer   = new SceneViewer(this);
  m_stackedWidget->addWidget(m_sceneViewer);
  m_lineTestViewer = new LineTestViewer(this);
  m_stackedWidget->addWidget(m_lineTestViewer);

  mainLayout->addWidget(m_stackedWidget, Qt::AlignCenter);

  TApp *app        = TApp::instance();
  m_keyFrameButton = new ViewerKeyframeNavigator(0, app->getCurrentFrame());
  m_keyFrameButton->setObjectHandle(app->getCurrentObject());
  m_keyFrameButton->setXsheetHandle(app->getCurrentXsheet());

  int buttons = FlipConsole::cFullConsole;

  buttons &= (~FlipConsole::eSound);
  buttons &= (~FlipConsole::eCheckBg);
  buttons &= (~FlipConsole::eWhiteBg);
  buttons &= (~FlipConsole::eBlackBg);
  buttons &= (~FlipConsole::eSave);
  buttons &= (~FlipConsole::eCompare);
  buttons &= (~FlipConsole::eSaveImg);
  buttons &= (~FlipConsole::eHisto);
  buttons &= (~FlipConsole::eCustomize);
  buttons &= (~FlipConsole::eMatte);
  buttons &= (~FlipConsole::eGRed);
  buttons &= (~FlipConsole::eGGreen);
  buttons &= (~FlipConsole::eGBlue);
  buttons &= (~FlipConsole::eRed);
  buttons &= (~FlipConsole::eGreen);
  buttons &= (~FlipConsole::eBlue);
  buttons &= (~FlipConsole::eDefineSubCamera);
  buttons &= (~FlipConsole::eDefineLoadBox);
  buttons &= (~FlipConsole::eUseLoadBox);

  m_flipConsole = new FlipConsole(mainLayout, buttons, false, m_keyFrameButton,
                                  "SceneViewerConsole");

  ret = ret && connect(m_sceneViewer, SIGNAL(onZoomChanged()),
                       SLOT(changeWindowTitle()));
  ret = ret && connect(m_lineTestViewer, SIGNAL(onZoomChanged()),
                       SLOT(changeWindowTitle()));

  ret = connect(m_flipConsole,
                SIGNAL(drawFrame(int, const ImagePainter::VisualSettings &)),
                this,
                SLOT(onDrawFrame(int, const ImagePainter::VisualSettings &)));
  ret = ret && connect(m_flipConsole, SIGNAL(playStateChanged(bool)), this,
                       SLOT(onPlayStateChanged(bool)));
  ret = ret &&
        connect(m_flipConsole, SIGNAL(buttonPressed(FlipConsole::EGadget)),
                m_lineTestViewer, SLOT(onButtonPressed(FlipConsole::EGadget)));
  ret = ret &&
        connect(m_flipConsole, SIGNAL(buttonPressed(FlipConsole::EGadget)),
                m_sceneViewer, SLOT(onButtonPressed(FlipConsole::EGadget)));
  ret = ret && connect(m_flipConsole, SIGNAL(sliderReleased()), this,
                       SLOT(onFlipSliderReleased()));

  m_flipConsole->setFrameRate(app->getCurrentScene()
                                  ->getScene()
                                  ->getProperties()
                                  ->getOutputProperties()
                                  ->getFrameRate());

  hbox->setLayout(mainLayout);

  setWidget(hbox);

  initializeTitleBar(getTitleBar());

  ret = ret && connect(&m_mixAudioThread, SIGNAL(computedBuffer()), this,
                       SLOT(onComputedBuffer()), Qt::DirectConnection);

  ret = ret && connect(app->getCurrentScene(), SIGNAL(sceneSwitched()), this,
                       SLOT(onSceneSwitched()));

  assert(ret);
  setCurrentViewType(0);
}

//-----------------------------------------------------------------------------

LineTestPane::~LineTestPane() {}

//-----------------------------------------------------------------------------

void LineTestPane::showEvent(QShowEvent *) {
  TApp *app                    = TApp::instance();
  TFrameHandle *frameHandle    = app->getCurrentFrame();
  TSceneHandle *sceneHandle    = app->getCurrentScene();
  TXshLevelHandle *levelHandle = app->getCurrentLevel();
  TObjectHandle *objectHandle  = app->getCurrentObject();
  TXsheetHandle *xshHandle     = app->getCurrentXsheet();

  updateFrameRange();

  bool ret = true;

  ret = ret && connect(xshHandle, SIGNAL(xsheetChanged()), this,
                       SLOT(onSceneChanged()));

  ret = ret && connect(sceneHandle, SIGNAL(sceneChanged()), this,
                       SLOT(onSceneChanged()));
  ret = ret && connect(sceneHandle, SIGNAL(nameSceneChanged()), this,
                       SLOT(changeWindowTitle()));

  ret = ret && connect(levelHandle, SIGNAL(xshLevelSwitched(TXshLevel *)), this,
                       SLOT(onXshLevelSwitched(TXshLevel *)));
  ret = ret && connect(levelHandle, SIGNAL(xshLevelChanged()), this,
                       SLOT(changeWindowTitle()));
  ret = ret && connect(levelHandle, SIGNAL(xshLevelTitleChanged()), this,
                       SLOT(changeWindowTitle()));
  ret = ret && connect(levelHandle, SIGNAL(xshLevelChanged()), this,
                       SLOT(updateFrameRange()));

  ret = ret && connect(frameHandle, SIGNAL(frameSwitched()), this,
                       SLOT(changeWindowTitle()));
  ret = ret && connect(frameHandle, SIGNAL(frameSwitched()), this,
                       SLOT(onFrameSwitched()));
  ret = ret && connect(frameHandle, SIGNAL(frameTypeChanged()), this,
                       SLOT(onFrameTypeChanged()));

  assert(ret);

  // Aggiorno FPS al valore definito nel viewer corrente.
  m_flipConsole->setActive(true);
}

//-----------------------------------------------------------------------------

void LineTestPane::hideEvent(QHideEvent *) {
  TApp *app                    = TApp::instance();
  TFrameHandle *frameHandle    = app->getCurrentFrame();
  TSceneHandle *sceneHandle    = app->getCurrentScene();
  TXshLevelHandle *levelHandle = app->getCurrentLevel();
  TObjectHandle *objectHandle  = app->getCurrentObject();
  TXsheetHandle *xshHandle     = app->getCurrentXsheet();

  disconnect(xshHandle, SIGNAL(xsheetChanged()), this, SLOT(onSceneChanged()));

  disconnect(sceneHandle, SIGNAL(sceneChanged()), this, SLOT(onSceneChanged()));
  disconnect(sceneHandle, SIGNAL(nameSceneChanged()), this,
             SLOT(changeWindowTitle()));

  disconnect(levelHandle, SIGNAL(xshLevelSwitched(TXshLevel *)), this,
             SLOT(onXshLevelSwitched(TXshLevel *)));
  disconnect(levelHandle, SIGNAL(xshLevelChanged()), this,
             SLOT(changeWindowTitle()));
  disconnect(levelHandle, SIGNAL(xshLevelTitleChanged()), this,
             SLOT(changeWindowTitle()));
  disconnect(levelHandle, SIGNAL(xshLevelChanged()), this,
             SLOT(updateFrameRange()));

  disconnect(frameHandle, SIGNAL(frameSwitched()), this,
             SLOT(changeWindowTitle()));
  disconnect(frameHandle, SIGNAL(frameSwitched()), this,
             SLOT(onFrameSwitched()));
  disconnect(frameHandle, SIGNAL(frameTypeChanged()), this,
             SLOT(onFrameTypeChanged()));

  m_flipConsole->setActive(false);
}

//-----------------------------------------------------------------------------

int LineTestPane::computeBufferSize(int frame) {
  int bufferSize    = 0;
  double time       = 2.0;
  ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
  TOutputProperties *outputSettings =
      scene->getProperties()->getOutputProperties();
  int frameRate = outputSettings->getFrameRate();
  if (m_endPlayRange > m_startPlayRange) {
    int range                        = m_endPlayRange - m_startPlayRange;
    time                             = double(range) / double(frameRate);
    int minuts                       = tround(time / 60.0);
    if (minuts == 0) minuts          = 1;
    while (time > 2.0 * minuts) time = time * 0.5;
  }
  bufferSize = tfloor(frameRate * time) + 1;
  // qDebug("BUFFER SIZE: %d", bufferSize);

  if (frame + bufferSize > m_endPlayRange) {
    bufferSize = m_endPlayRange - frame + 1;
    // qDebug("\n BUFFER SIZE: %d \n", bufferSize);
  }

  return bufferSize;
}

//-----------------------------------------------------------------------------

void LineTestPane::computeBuffer(int frame) {
  int startFrame = m_trackStartFrame + m_bufferSize;
  if (startFrame >= m_endPlayRange) {
    // qDebug("\n OPS \n");
    return;
  }
  // qDebug("COMPUTE BUFFER SIZE AT FRAME: %d", startFrame);
  m_nextBufferSize = computeBufferSize(startFrame);
  // qDebug("start frame: %d, start next buffer size: %d", startFrame,
  // m_nextBufferSize);
  m_mixAudioThread.computeBuffer(startFrame, startFrame + m_nextBufferSize);
}

//-----------------------------------------------------------------------------

void LineTestPane::initSound() {
  m_mainTrack               = 0;
  m_startTrack              = 0;
  TXsheet *xsh              = TApp::instance()->getCurrentXsheet()->getXsheet();
  TFrameHandle *frameHandle = TApp::instance()->getCurrentFrame();
  m_trackStartFrame         = frameHandle->getFrame();

  m_startPlayRange = 0;
  m_endPlayRange   = frameHandle->getMaxFrameIndex();
  int fromMarker, toMarker, step;
  if (XsheetGUI::getPlayRange(fromMarker, toMarker, step)) {
    m_startPlayRange = fromMarker;
    m_endPlayRange   = toMarker;
  }

  m_bufferSize = computeBufferSize(m_trackStartFrame);
  // qDebug("initSound()");
  // qDebug("m_startPlayRange: %d", m_startPlayRange);
  // qDebug("m_endPlayRange: %d", m_endPlayRange);
  // qDebug("start frame: %d, start bufferSize: %d", m_trackStartFrame,
  // m_bufferSize);

  if (xsh) {
    if (!m_player) m_player = new TSoundOutputDevice();
    // Compute the first seconds and then launch the thread to compute the next
    // buffer
    TXsheet::SoundProperties *prop = new TXsheet::SoundProperties();
    prop->m_fromFrame              = m_trackStartFrame;
    prop->m_toFrame                = m_trackStartFrame + m_bufferSize;
    m_mainTrack                    = xsh->makeSound(prop);
    if (m_trackStartFrame == m_startPlayRange) {
      // qDebug("set start track");
      m_startTrack      = m_mainTrack;
      m_startBufferSize = m_bufferSize;
    } else  // compute start track (it's necessary to avoid async in loop)
    {
      m_startBufferSize              = computeBufferSize(m_startPlayRange);
      TXsheet::SoundProperties *prop = new TXsheet::SoundProperties();
      prop->m_fromFrame              = m_startPlayRange;
      prop->m_toFrame                = m_startPlayRange + m_startBufferSize;
      m_startTrack                   = xsh->makeSound(prop);
    }
    computeBuffer(m_trackStartFrame);
  } else {
    m_mainTrack  = 0;
    m_startTrack = 0;
  }
}

//-----------------------------------------------------------------------------

void LineTestPane::playSound() {
  if (m_player && m_mainTrack) {
    try {
      int currentFrame = TApp::instance()->getCurrentFrame()->getFrame();
      double t0        = (double)(currentFrame - m_trackStartFrame) /
                  (double)(m_mainTrack->getSampleRate());
      // Pay attention at don't call play everytime (there is a big leak
      // otherwise !)
      double trackDuration = m_mainTrack->getDuration();
      // qDebug("trackDuration: %f", trackDuration);
      if (m_mainTrack && trackDuration != 0)
        if (trackDuration > t0) m_player->play(m_mainTrack, t0, trackDuration);
    } catch (TSoundDeviceException &e) {
    }
  }
}

//-----------------------------------------------------------------------------

void LineTestPane::initializeTitleBar(TPanelTitleBar *titleBar) {
  bool ret = true;

  TPanelTitleBarButtonSet *viewModeButtonSet;
  viewModeButtonSet = new TPanelTitleBarButtonSet();
  int x             = -100;
  int iconWidth     = 17;
  TPanelTitleBarButton *button;

  m_cameraStandButton = new TPanelTitleBarButton(
      titleBar, ":Resources/standard.png", ":Resources/standard_over.png",
      ":Resources/standard_on.png");
  m_cameraStandButton->setToolTip("Camera Stand View");
  x += 18 + iconWidth;
  titleBar->add(QPoint(x, 2), m_cameraStandButton);
  m_cameraStandButton->setButtonSet(viewModeButtonSet, 0);
  m_cameraStandButton->setPressed(true);

  m_previewButton = new TPanelTitleBarButton(
      titleBar, ":Resources/viewpreview.png", ":Resources/viewpreview_over.png",
      ":Resources/viewpreview_on.png");
  m_previewButton->setToolTip(tr("Preview"));
  x += 5 + iconWidth;
  titleBar->add(QPoint(x, 2), m_previewButton);
  m_previewButton->setButtonSet(viewModeButtonSet, 1);

  ret = ret && connect(viewModeButtonSet, SIGNAL(selected(int)), this,
                       SLOT(setCurrentViewType(int)));
  assert(ret);
}

//-----------------------------------------------------------------------------

void LineTestPane::onXshLevelSwitched(TXshLevel *) { changeWindowTitle(); }

//-----------------------------------------------------------------------------

void LineTestPane::changeWindowTitle() {
  TApp *app         = TApp::instance();
  ToonzScene *scene = app->getCurrentScene()->getScene();
  if (!scene) return;
  int frame = app->getCurrentFrame()->getFrame();
  QString name;
  if (app->getCurrentFrame()->isEditingScene()) {
    QString sceneName = QString::fromStdWString(scene->getSceneName());
    if (sceneName.isEmpty()) sceneName = tr("Untitled");
    if (app->getCurrentScene()->getDirtyFlag()) sceneName += QString("*");
    name = tr("Scene: ") + sceneName;
    if (frame >= 0)
      name  = name + tr("   ::   Frame: ") + tr(toString(frame + 1).c_str());
    int col = app->getCurrentColumn()->getColumnIndex();
    if (col < 0) {
      setWindowTitle(name);
      return;
    }
    TXsheet *xsh  = app->getCurrentXsheet()->getXsheet();
    TXshCell cell = xsh->getCell(frame, col);
    if (cell.isEmpty()) {
      setWindowTitle(name);
      return;
    }
    assert(cell.m_level.getPointer());
    TFilePath fp(cell.m_level->getName());
    QString imageName =
        QString::fromStdWString(fp.withFrame(cell.m_frameId).getWideString());
    name = name + tr("   ::   Level: ") + imageName;
  } else {
    TXshLevel *level = app->getCurrentLevel()->getLevel();
    if (level) {
      TFilePath fp(level->getName());
      QString imageName = QString::fromStdWString(
          fp.withFrame(app->getCurrentFrame()->getFid()).getWideString());
      name = name + tr("Level: ") + imageName;
    }
  }
  if (m_stackedWidget->currentIndex() == 0) {
    TAffine aff = m_sceneViewer->getViewMatrix() *
                  m_sceneViewer->getNormalZoomScale().inv();
    name = name + "  ::  Zoom : " +
           QString::number(tround(100.0 * sqrt(aff.det()))) + "%";
  } else {
    TAffine aff = m_lineTestViewer->getViewMatrix() *
                  m_lineTestViewer->getNormalZoomScale().inv();
    name = name + "  ::  Zoom : " +
           QString::number(tround(100.0 * sqrt(aff.det()))) + "%";
  }

  setWindowTitle(name);
}

//-----------------------------------------------------------------------------

void LineTestPane::updateFrameRange() {
  TApp *app         = TApp::instance();
  TFrameHandle *fh  = app->getCurrentFrame();
  int frameIndex    = fh->getFrameIndex();
  int maxFrameIndex = fh->getMaxFrameIndex();
  m_flipConsole->setFrameRange(1, maxFrameIndex + 1, 1, frameIndex + 1);
}

//-----------------------------------------------------------------------------

void LineTestPane::updateFrameMarkers() {
  int fromIndex, toIndex, dummy;
  XsheetGUI::getPlayRange(fromIndex, toIndex, dummy);
  TFrameHandle *fh = TApp::instance()->getCurrentFrame();
  if (fh->isEditingLevel()) {
    fromIndex = 0;
    toIndex   = -1;
  }
  m_flipConsole->setMarkers(fromIndex, toIndex);
}

//-----------------------------------------------------------------------------

void LineTestPane::setCurrentViewType(int index) {
  TFrameHandle *frameHandle = TApp::instance()->getCurrentFrame();
  if (index == 1 && frameHandle->getFrameType() == TFrameHandle::LevelFrame)
    frameHandle->setFrame(frameHandle->getFrameIndex());
  m_stackedWidget->setCurrentIndex(index);
  if (index == 0) {
    CommandManager::instance()->enable("MI_ViewTable", true);
    CommandManager::instance()->enable("MI_FieldGuide", true);
    CommandManager::instance()->enable("MI_SafeArea", true);
    CommandManager::instance()->enable("MI_RasterizePli", true);
    CommandManager::instance()->enable("MI_ViewColorcard", true);
    CommandManager::instance()->enable("MI_ViewCamera", true);
    m_flipConsole->enableButton(FlipConsole::eFilledRaster, false, false);
  } else {
    CommandManager::instance()->enable("MI_ViewTable", false);
    CommandManager::instance()->enable("MI_FieldGuide", false);
    CommandManager::instance()->enable("MI_SafeArea", false);
    CommandManager::instance()->enable("MI_RasterizePli", false);
    CommandManager::instance()->enable("MI_ViewColorcard", false);
    CommandManager::instance()->enable("MI_ViewCamera", false);
    if (m_flipConsole)
      m_flipConsole->enableButton(FlipConsole::eFilledRaster, true, false);
  }
  changeWindowTitle();
}

//-----------------------------------------------------------------------------

void LineTestPane::onDrawFrame(int frame,
                               const ImagePainter::VisualSettings &settings) {
  TApp *app                 = TApp::instance();
  TFrameHandle *frameHandle = app->getCurrentFrame();

  assert(frame >= 0);
  if (frame != frameHandle->getFrameIndex() + 1) {
    int oldFrame = frameHandle->getFrame();
    frameHandle->setCurrentFrame(frame);
    if (!m_mainTrack && !frameHandle->isPlaying() &&
        !frameHandle->isEditingLevel() && oldFrame != frameHandle->getFrame())
      frameHandle->scrubXsheet(
          frame - 1, frame - 1,
          TApp::instance()->getCurrentXsheet()->getXsheet());

    // qDebug("frame: %d",frame);
    if (m_mainTrack && frameHandle->isPlaying() &&
        !frameHandle->isEditingLevel()) {
      if (frame == m_startPlayRange + 1) {
        if (m_startTrack) {
          m_mainTrack       = m_startTrack;
          m_trackStartFrame = frame;
          // qDebug("1. play at m_trackStartFrame: %d", m_trackStartFrame);
          playSound();

          m_bufferSize = m_startBufferSize;
          computeBuffer(frame);
        } else {
          // qDebug("2. play at m_trackStartFrame: %d", m_trackStartFrame);
          assert(0);
          initSound();
        }
      }
      int frameElapsed = frame - m_trackStartFrame - 1;
      if (frameElapsed >= (m_bufferSize)) {
        if (m_buffer) m_mainTrack = m_buffer->clone();

        m_trackStartFrame = frame;
        // qDebug("PLAY SOUND AT FRAME: %d", frame);
        playSound();

        // qDebug("3. play at m_trackStartFrame: %d", m_trackStartFrame);
        m_bufferSize = m_nextBufferSize;
        computeBuffer(frame);
      }
    }
  }
}

//-----------------------------------------------------------------------------

void LineTestPane::onComputedBuffer() {
  m_buffer = TSoundTrackP();
  m_buffer = m_mixAudioThread.getBuffer();
}

//-----------------------------------------------------------------------------

void LineTestPane::onPlayStateChanged(bool value) {
  TFrameHandle *frameHandle = TApp::instance()->getCurrentFrame();
  bool wasPlaying           = frameHandle->isPlaying();
  frameHandle->setPlaying(value);
  if (value && !frameHandle->isEditingLevel()) {
    if (m_player && wasPlaying) {
      m_player->close();
      if (m_mainTrack) m_mainTrack   = TSoundTrackP();
      if (m_startTrack) m_startTrack = TSoundTrackP();
      if (m_buffer) m_buffer         = TSoundTrackP();
    }
    initSound();
    playSound();
  } else if (m_player) {
    m_player->close();
    if (m_mainTrack) m_mainTrack   = TSoundTrackP();
    if (m_startTrack) m_startTrack = TSoundTrackP();
    if (m_buffer) m_buffer         = TSoundTrackP();
  }
}

//-----------------------------------------------------------------------------

void LineTestPane::onSceneChanged() {
  TApp *app         = TApp::instance();
  ToonzScene *scene = app->getCurrentScene()->getScene();
  assert(scene);
  m_flipConsole->updateCurrentFPS(
      scene->getProperties()->getOutputProperties()->getFrameRate());

  updateFrameRange();
  updateFrameMarkers();
  changeWindowTitle();

  int frameIndex = app->getCurrentFrame()->getFrameIndex();
  if (m_keyFrameButton->getCurrentFrame() != frameIndex)
    m_keyFrameButton->setCurrentFrame(frameIndex);
}

//-----------------------------------------------------------------------------

void LineTestPane::onSceneSwitched() {
  if (!isHidden()) onSceneChanged();
  m_flipConsole->setFrameRate(TApp::instance()
                                  ->getCurrentScene()
                                  ->getScene()
                                  ->getProperties()
                                  ->getOutputProperties()
                                  ->getFrameRate());
}

//-----------------------------------------------------------------------------

void LineTestPane::onFrameSwitched() {
  int frameIndex = TApp::instance()->getCurrentFrame()->getFrameIndex();
  m_flipConsole->setCurrentFrame(frameIndex + 1);
  if (m_keyFrameButton->getCurrentFrame() != frameIndex)
    m_keyFrameButton->setCurrentFrame(frameIndex);
}

//-----------------------------------------------------------------------------

void LineTestPane::onFrameTypeChanged() {
  if (TApp::instance()->getCurrentFrame()->getFrameType() ==
      TFrameHandle::LevelFrame) {
    if (m_stackedWidget->currentIndex() != 0) {
      m_cameraStandButton->setPressed(true);
      m_previewButton->setPressed(false);
      setCurrentViewType(0);
    }
  }

  updateFrameRange();
  updateFrameMarkers();
}

//-----------------------------------------------------------------------------

void LineTestPane::onFlipSliderReleased() {
  TApp::instance()->getCurrentXsheet()->getXsheet()->stopScrub();
}

#endif