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