mirror of
https://github.com/libretro/gambatte-libretro.git
synced 2024-11-26 17:30:23 +00:00
- one more decimal position in refresh rate representation.
- use xrandr screen names - hide empty full mode comboboxes - windowed resolution -> window size - lots of refactoring. git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@247 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
parent
e1470f5279
commit
d21f4d5f91
@ -30,8 +30,10 @@ class Array : Uncopyable {
|
||||
public:
|
||||
Array(const std::size_t size = 0) : a(size ? new T[size] : 0), sz(size) {}
|
||||
~Array() { delete []a; }
|
||||
void reset(const std::size_t size) { delete []a; a = size ? new T[size] : 0; sz = size; }
|
||||
void reset(const std::size_t size = 0) { delete []a; a = size ? new T[size] : 0; sz = size; }
|
||||
std::size_t size() const { return sz; }
|
||||
T * get() { return a; }
|
||||
const T * get() const { return a; }
|
||||
operator T*() { return a; }
|
||||
operator const T*() const { return a; }
|
||||
};
|
||||
|
@ -46,7 +46,6 @@ public:
|
||||
|
||||
bool operator==(AudioEngineConf r) const { return ae == r.ae; }
|
||||
bool operator!=(AudioEngineConf r) const { return ae != r.ae; }
|
||||
operator ConstAudioEngineConf() { return ConstAudioEngineConf(ae); }
|
||||
operator const ConstAudioEngineConf() const { return ConstAudioEngineConf(ae); }
|
||||
};
|
||||
|
||||
|
@ -48,7 +48,6 @@ public:
|
||||
|
||||
bool operator==(BlitterConf r) const { return blitter == r.blitter; }
|
||||
bool operator!=(BlitterConf r) const { return blitter != r.blitter; }
|
||||
operator ConstBlitterConf() { return ConstBlitterConf(blitter); }
|
||||
operator const ConstBlitterConf() const { return ConstBlitterConf(blitter); }
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,8 @@ SOURCES += framework/src/blittercontainer.cpp \
|
||||
framework/src/mediaworker.cpp \
|
||||
framework/src/samplebuffer.cpp \
|
||||
framework/src/blitterwidget.cpp \
|
||||
framework/src/joysticklock.cpp
|
||||
framework/src/joysticklock.cpp \
|
||||
framework/src/persistcheckbox.cpp
|
||||
SOURCES += $$COMMONPATH/resample/src/chainresampler.cpp \
|
||||
$$COMMONPATH/resample/src/i0.cpp \
|
||||
$$COMMONPATH/resample/src/makesinckernel.cpp \
|
||||
@ -31,6 +32,7 @@ HEADERS += framework/src/blitterwidget.h \
|
||||
framework/inputdialog.h \
|
||||
framework/src/audioengine.h \
|
||||
framework/audioengineconf.h \
|
||||
framework/persistcheckbox.h \
|
||||
framework/src/addaudioengines.h \
|
||||
framework/src/addblitterwidgets.h \
|
||||
framework/src/getfullmodetoggler.h \
|
||||
|
@ -93,7 +93,7 @@ private:
|
||||
void restore();
|
||||
|
||||
public:
|
||||
InputDialog(const std::vector<Button> &buttonInfos,
|
||||
explicit InputDialog(const std::vector<Button> &buttonInfos,
|
||||
bool deleteButtonActions = true,
|
||||
QWidget *parent = 0);
|
||||
~InputDialog();
|
||||
@ -108,7 +108,7 @@ public slots:
|
||||
void reject();
|
||||
};
|
||||
|
||||
// used in implementation of InputDialog
|
||||
// used in the implementation of InputDialog, included here because it's a Q_OBJECT
|
||||
class InputBox : public QLineEdit {
|
||||
Q_OBJECT
|
||||
|
||||
@ -130,7 +130,7 @@ protected:
|
||||
|
||||
public:
|
||||
enum { NULL_VALUE = 0, KBD_VALUE = 0x7FFFFFFF };
|
||||
InputBox(QWidget *nextFocus = 0);
|
||||
explicit InputBox(QWidget *nextFocus = 0);
|
||||
void setData(const SDL_Event &data) { setData(data.id, data.value); }
|
||||
void setData(unsigned id, int value = KBD_VALUE);
|
||||
void setNextFocus(QWidget *const nextFocus) { this->nextFocus = nextFocus; }
|
||||
@ -140,7 +140,7 @@ public slots:
|
||||
void clearData() { setData(0, NULL_VALUE); }
|
||||
};
|
||||
|
||||
// used in implementation of InputDialog
|
||||
// used in the implementation of InputDialog, included here because it's a Q_OBJECT
|
||||
class InputBoxPair : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -71,7 +71,7 @@ class MainWindow : public QMainWindow {
|
||||
PixelBuffer::PixelFormat pixelFormat = PixelBuffer::RGB32*/) : width(width), height(height)/*, pixelFormat(pixelFormat)*/ {}
|
||||
};
|
||||
|
||||
class JoystickIniter {
|
||||
class JoystickIniter : Uncopyable {
|
||||
std::vector<SDL_Joystick*> joysticks;
|
||||
public:
|
||||
JoystickIniter();
|
||||
@ -97,10 +97,8 @@ class MainWindow : public QMainWindow {
|
||||
QSize windowSize;
|
||||
Rational frameTime_;
|
||||
unsigned focusPauseBit;
|
||||
// int timerId;
|
||||
int hz;
|
||||
int refreshRate;
|
||||
bool running;
|
||||
// bool threaded;
|
||||
bool refreshRateSync;
|
||||
bool cursorHidden;
|
||||
|
||||
@ -118,7 +116,7 @@ class MainWindow : public QMainWindow {
|
||||
void execPausedQueue();
|
||||
void updateMinimumSize();
|
||||
void setBlitter(BlitterWidget *blitter);
|
||||
void setVideo(unsigned w, unsigned h, /*PixelBuffer::PixelFormat pf,*/ /*const VideoFilter *vf, */BlitterWidget *blitter);
|
||||
void setVideo(unsigned w, unsigned h, BlitterWidget *blitter);
|
||||
void correctFullScreenGeometry();
|
||||
void doSetWindowSize(const QSize &sz);
|
||||
void updateSwapInterval();
|
||||
@ -127,14 +125,14 @@ class MainWindow : public QMainWindow {
|
||||
void emitAudioEngineFailure() { emit audioEngineFailure(); worker->recover(); }
|
||||
|
||||
private slots:
|
||||
void hzChange(int hz);
|
||||
void refreshRateChange(int refreshRate);
|
||||
void updateJoysticks();
|
||||
|
||||
public:
|
||||
/** Can be used to gain frame buffer access outside the MediaSource
|
||||
* methods that take the frame buffer as argument.
|
||||
* The frame buffer is the buffer that a MediaSource should write
|
||||
* its video content to. It's generally not an actual video memory frame buffer.
|
||||
* its video content to.
|
||||
*/
|
||||
class FrameBuffer {
|
||||
MainWindow *const mw;
|
||||
@ -151,7 +149,7 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
MainWindow(MediaSource *source);
|
||||
explicit MainWindow(MediaSource *source);
|
||||
|
||||
/** Sets the duration in seconds of each video frame.
|
||||
* Eg. use setFrameTime(1, 60) for 60 fps video.
|
||||
@ -230,12 +228,6 @@ public:
|
||||
setVideo(w, h,/* pf,*/ blitters[blitterNo]);
|
||||
}
|
||||
|
||||
/** Will synchronize frame rate to vertical retrace if the blitter supports a swapInterval of at least 1.
|
||||
* Picks a swapInterval closest to the current frame rate.
|
||||
* Literally speeds things up or slows things down to match the swapInterval. Audio pitch will change accordingly.
|
||||
*/
|
||||
void setSyncToRefreshRate(bool on);
|
||||
|
||||
/** speed = N, gives N times faster than normal when fastForward is enabled. */
|
||||
void setFastForwardSpeed(unsigned speed) { worker->setFastForwardSpeed(speed); }
|
||||
|
||||
@ -251,6 +243,8 @@ public:
|
||||
/** Returns the modes supported by each screen. */
|
||||
const std::vector<ResInfo>& modeVector(unsigned screen) const { return fullModeToggler->modeVector(screen); }
|
||||
|
||||
const QString screenName(unsigned screen) const { return fullModeToggler->screenName(screen); }
|
||||
|
||||
/** Returns the number of screens. */
|
||||
unsigned screens() const { return fullModeToggler->screens(); }
|
||||
|
||||
@ -309,6 +303,12 @@ public slots:
|
||||
void hideCursor();
|
||||
void setFastForward(bool enable) { worker->setFastForward(enable); }
|
||||
|
||||
/** Will synchronize frame rate to vertical retrace if the blitter supports a swapInterval of at least 1.
|
||||
* Picks a swapInterval closest to the current frame rate.
|
||||
* Literally speeds things up or slows things down to match the swapInterval. Audio pitch will change accordingly.
|
||||
*/
|
||||
void setSyncToRefreshRate(bool on);
|
||||
|
||||
signals:
|
||||
void audioEngineFailure();
|
||||
void videoBlitterFailure();
|
||||
|
41
gambatte_qt/src/framework/persistcheckbox.h
Normal file
41
gambatte_qt/src/framework/persistcheckbox.h
Normal file
@ -0,0 +1,41 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2011 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef PERSIST_CHECKBOX_H
|
||||
#define PERSIST_CHECKBOX_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
class QCheckBox;
|
||||
class QWidget;
|
||||
|
||||
class PersistCheckBox {
|
||||
QCheckBox *const checkBox_;
|
||||
const QString key_;
|
||||
bool value_;
|
||||
|
||||
public:
|
||||
PersistCheckBox(QCheckBox *checkBox, const QString &key, bool defaultValue);
|
||||
~PersistCheckBox();
|
||||
void accept();
|
||||
void reject() const;
|
||||
bool value() const { return value_; }
|
||||
QCheckBox * checkBox() const { return checkBox_; }
|
||||
};
|
||||
|
||||
#endif
|
@ -19,6 +19,6 @@
|
||||
#ifndef SCALINGMETHOD_H
|
||||
#define SCALINGMETHOD_H
|
||||
|
||||
enum ScalingMethod { UNRESTRICTED, KEEP_RATIO, INTEGER };
|
||||
enum ScalingMethod { UNRESTRICTED, KEEP_RATIO, INTEGER }; enum { NUM_SCALING_METHODS = INTEGER + 1 };
|
||||
|
||||
#endif
|
||||
|
@ -29,6 +29,7 @@ public:
|
||||
typedef typename std::vector<T*, Allocator>::size_type size_type;
|
||||
explicit auto_vector(const Allocator& a = Allocator()) : std::vector<T*, Allocator>(a) {}
|
||||
explicit auto_vector(size_type n, const Allocator& a = Allocator()) : std::vector<T*, Allocator>(n, 0, a) {}
|
||||
explicit auto_vector(const std::vector<T*, Allocator> &v) : std::vector<T*, Allocator>(v) {}
|
||||
|
||||
template<class InputIterator>
|
||||
auto_vector(InputIterator first, InputIterator last, const Allocator& a = Allocator()) : std::vector<T*, Allocator>(first, last, a) {}
|
||||
|
@ -40,7 +40,7 @@ class FtEst {
|
||||
unsigned count;
|
||||
|
||||
public:
|
||||
FtEst(long frameTime = 0) { init(frameTime); }
|
||||
explicit FtEst(long frameTime = 0) { init(frameTime); }
|
||||
void init(long frameTime);
|
||||
void update(usec_t t);
|
||||
long est() const { return (ftAvg + UP / 2) >> UPSHIFT; }
|
||||
@ -51,8 +51,6 @@ class BlitterWidget : public QWidget {
|
||||
VideoBufferLocker vbl;
|
||||
const QString nameString_;
|
||||
const unsigned maxSwapInterval_;
|
||||
|
||||
private:
|
||||
bool paused;
|
||||
|
||||
protected:
|
||||
@ -93,7 +91,10 @@ public:
|
||||
// return pf == pixbuf.pixelFormat;
|
||||
}
|
||||
|
||||
virtual void setCorrectedGeometry(int w, int h, int new_w, int new_h) { setGeometry((w - new_w) >> 1, (h - new_h) >> 1, new_w, new_h); }
|
||||
virtual void setCorrectedGeometry(int w, int h, int new_w, int new_h) {
|
||||
setGeometry((w - new_w) >> 1, (h - new_h) >> 1, new_w, new_h);
|
||||
}
|
||||
|
||||
virtual long frameTimeEst() const { return 0; }
|
||||
virtual long sync() { return 0; }
|
||||
virtual void setExclusive(bool) {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* Copyright (C) 2008 by Sindre Aam<EFBFBD>s *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -76,7 +76,7 @@ Direct3DBlitter::Direct3DBlitter(VideoBufferLocker vbl, QWidget *parent) :
|
||||
backBufferWidth(1),
|
||||
backBufferHeight(1),
|
||||
clear(0),
|
||||
hz(0),
|
||||
dhz(600),
|
||||
swapInterval(0),
|
||||
adapterIndex(0),
|
||||
exclusive(false),
|
||||
@ -329,7 +329,7 @@ void Direct3DBlitter::setSwapInterval(const unsigned newSwapInterval) {
|
||||
if (newSwapInterval != swapInterval) {
|
||||
swapInterval = newSwapInterval;
|
||||
resetDevice();
|
||||
ftEst.init(hz ? swapInterval * 1000000 / hz : 0);
|
||||
ftEst.init(swapInterval * 10000000 / dhz);
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,7 +356,7 @@ void Direct3DBlitter::present() {
|
||||
if (device) {
|
||||
if (swapInterval) {
|
||||
const unsigned long estft = ftEst.est();
|
||||
const usec_t swaplimit = getusecs() - lastblank > estft - estft / 32 ? estft * 2 - 500000 / hz : 0;
|
||||
const usec_t swaplimit = getusecs() - lastblank > estft - estft / 32 ? estft * 2 - 5000000 / dhz : 0;
|
||||
|
||||
device->Present(NULL, NULL, 0, NULL);
|
||||
|
||||
@ -590,9 +590,9 @@ void Direct3DBlitter::rejectSettings() const {
|
||||
bfBox->setChecked(bf);
|
||||
}
|
||||
|
||||
void Direct3DBlitter::rateChange(int hz) {
|
||||
this->hz = hz;
|
||||
ftEst.init(hz ? swapInterval * 1000000 / hz : 0);
|
||||
void Direct3DBlitter::rateChange(const int dhz) {
|
||||
this->dhz = dhz ? dhz : 600;
|
||||
ftEst.init(swapInterval * 10000000 / this->dhz);
|
||||
}
|
||||
|
||||
void Direct3DBlitter::resizeEvent(QResizeEvent */*e*/) {
|
||||
|
@ -50,7 +50,7 @@ class Direct3DBlitter : public BlitterWidget {
|
||||
unsigned backBufferWidth;
|
||||
unsigned backBufferHeight;
|
||||
unsigned clear;
|
||||
unsigned hz;
|
||||
unsigned dhz;
|
||||
unsigned swapInterval;
|
||||
unsigned adapterIndex;
|
||||
bool exclusive;
|
||||
@ -94,7 +94,7 @@ public:
|
||||
|
||||
QPaintEngine* paintEngine () const { return NULL; }
|
||||
void setSwapInterval(unsigned si);
|
||||
void rateChange(int hz);
|
||||
void rateChange(int dhz);
|
||||
};
|
||||
|
||||
#endif /*DIRECT3DBLITTER_H_*/
|
||||
|
@ -61,7 +61,7 @@ DirectDrawBlitter::DirectDrawBlitter(VideoBufferLocker vbl, QWidget *parent) :
|
||||
pixelFormat(PixelBuffer::RGB32),
|
||||
lastblank(0),
|
||||
clear(0),
|
||||
hz(0),
|
||||
dhz(600),
|
||||
swapInterval(0),
|
||||
deviceIndex(0),
|
||||
inWidth(1),
|
||||
@ -495,7 +495,7 @@ long DirectDrawBlitter::frameTimeEst() const {
|
||||
void DirectDrawBlitter::setSwapInterval(const unsigned newSwapInterval) {
|
||||
if (newSwapInterval != swapInterval) {
|
||||
swapInterval = newSwapInterval;
|
||||
ftEst.init(hz ? swapInterval * 1000000 / hz : 0);
|
||||
ftEst.init(swapInterval * 10000000 / dhz);
|
||||
}
|
||||
}
|
||||
|
||||
@ -550,7 +550,7 @@ long DirectDrawBlitter::sync() {
|
||||
if (exclusive & flipping) {
|
||||
if (swapInterval) {
|
||||
const unsigned long estft = ftEst.est();
|
||||
const usec_t swaplimit = getusecs() - lastblank > estft - estft / 32 ? estft * 2 - 500000 / hz : 0;
|
||||
const usec_t swaplimit = getusecs() - lastblank > estft - estft / 32 ? estft * 2 - 5000000 / dhz : 0;
|
||||
|
||||
if (!blitted)
|
||||
finalBlit(DDBLT_WAIT);
|
||||
@ -584,7 +584,7 @@ long DirectDrawBlitter::sync() {
|
||||
}
|
||||
} else {
|
||||
if (const unsigned si = swapInterval ? swapInterval : vblank) {
|
||||
const usec_t refreshPeriod = 1000000 / hz;
|
||||
const usec_t refreshPeriod = 10000000 / dhz;
|
||||
|
||||
while (getusecs() - lastblank < (si - 1) * refreshPeriod + refreshPeriod / 2)
|
||||
Sleep(1);
|
||||
@ -600,7 +600,7 @@ long DirectDrawBlitter::sync() {
|
||||
ftEst.update(lastblank);
|
||||
|
||||
blitted = false;
|
||||
|
||||
|
||||
if (ddrval != DD_OK && ddrval != DDERR_WASSTILLDRAWING)
|
||||
std::cout << "lpDDSPrimary->Flip failed" << std::endl;
|
||||
|
||||
@ -648,9 +648,9 @@ void DirectDrawBlitter::rejectSettings() const {
|
||||
deviceSelector->setCurrentIndex(deviceIndex);
|
||||
}
|
||||
|
||||
void DirectDrawBlitter::rateChange(int hz) {
|
||||
this->hz = hz;
|
||||
ftEst.init(hz ? swapInterval * 1000000 / hz : 0);
|
||||
void DirectDrawBlitter::rateChange(const int dhz) {
|
||||
this->dhz = dhz ? dhz : 600;
|
||||
ftEst.init(swapInterval * 10000000 / this->dhz);
|
||||
}
|
||||
|
||||
void DirectDrawBlitter::paintEvent(QPaintEvent */*event*/) {
|
||||
|
@ -46,7 +46,7 @@ class DirectDrawBlitter : public BlitterWidget {
|
||||
PixelBuffer::PixelFormat pixelFormat;
|
||||
usec_t lastblank;
|
||||
unsigned clear;
|
||||
unsigned hz;
|
||||
unsigned dhz;
|
||||
unsigned swapInterval;
|
||||
unsigned deviceIndex;
|
||||
unsigned inWidth;
|
||||
@ -94,7 +94,7 @@ public:
|
||||
|
||||
QPaintEngine* paintEngine () const { return NULL; }
|
||||
|
||||
void rateChange(int hz);
|
||||
void rateChange(int dhz);
|
||||
void setSwapInterval(unsigned si);
|
||||
};
|
||||
|
||||
|
@ -60,7 +60,6 @@ protected:
|
||||
|
||||
public:
|
||||
SubWidget(unsigned swapInterval, bool bf, QGLBlitter *parent);
|
||||
~SubWidget();
|
||||
|
||||
void blit();
|
||||
//void blitFront();
|
||||
@ -118,20 +117,6 @@ QGLBlitter::SubWidget::SubWidget(const unsigned swapInterval_in, const bool bf_i
|
||||
setAutoBufferSwap(false);
|
||||
setMouseTracking(true);
|
||||
// setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
||||
|
||||
// QSettings settings;
|
||||
// settings.beginGroup("qglsubwidget");
|
||||
// bf = settings.value("bf", true).toBool();
|
||||
// settings.endGroup();
|
||||
}
|
||||
|
||||
QGLBlitter::SubWidget::~SubWidget() {
|
||||
uninit();
|
||||
|
||||
// QSettings settings;
|
||||
// settings.beginGroup("qglsubwidget");
|
||||
// settings.setValue("bf", bf);
|
||||
// settings.endGroup();
|
||||
}
|
||||
|
||||
void QGLBlitter::SubWidget::blit() {
|
||||
@ -292,45 +277,24 @@ void QGLBlitter::SubWidget::updateTexture(quint32 *const buffer) {
|
||||
QGLBlitter::QGLBlitter(VideoBufferLocker vbl, QWidget *parent) :
|
||||
BlitterWidget(vbl, QString("OpenGL"), 2, parent),
|
||||
confWidget(new QWidget),
|
||||
vsyncBox(new QCheckBox(QString("Wait for vertical blank"))),
|
||||
bfBox(new QCheckBox(QString("Bilinear filtering"))),
|
||||
buffer(NULL),
|
||||
vsync_(new QCheckBox(QString("Wait for vertical blank")), "qglblitter/vsync", false),
|
||||
bf_(new QCheckBox(QString("Bilinear filtering")), "qglblitter/bf", true),
|
||||
swapInterval_(0),
|
||||
hz(60)
|
||||
// hz1(60),
|
||||
// hz2(119)
|
||||
dhz(600),
|
||||
subWidget(new SubWidget(0, bf_.value(), this))
|
||||
{
|
||||
// setLayout(new QVBoxLayout);
|
||||
// layout()->setMargin(0);
|
||||
// layout()->setSpacing(0);
|
||||
// layout()->addWidget(subWidget);
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("qglblitter");
|
||||
vsync = settings.value("vsync", false).toBool();
|
||||
bf = settings.value("bf", true).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
confWidget->setLayout(new QVBoxLayout);
|
||||
confWidget->layout()->setMargin(0);
|
||||
confWidget->layout()->addWidget(vsyncBox);
|
||||
confWidget->layout()->addWidget(bfBox);
|
||||
vsyncBox->setChecked(vsync);
|
||||
bfBox->setChecked(bf);
|
||||
|
||||
subWidget = new SubWidget(0, bf, this);
|
||||
confWidget->layout()->addWidget(vsync_.checkBox());
|
||||
confWidget->layout()->addWidget(bf_.checkBox());
|
||||
}
|
||||
|
||||
QGLBlitter::~QGLBlitter() {
|
||||
uninit();
|
||||
|
||||
// delete subWidget;
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("qglblitter");
|
||||
settings.setValue("vsync", vsync);
|
||||
settings.setValue("bf", bf);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void QGLBlitter::resizeEvent(QResizeEvent *const event) {
|
||||
@ -339,9 +303,7 @@ void QGLBlitter::resizeEvent(QResizeEvent *const event) {
|
||||
|
||||
void QGLBlitter::uninit() {
|
||||
subWidget->uninit();
|
||||
|
||||
delete []buffer;
|
||||
buffer = NULL;
|
||||
buffer.reset();
|
||||
}
|
||||
|
||||
bool QGLBlitter::isUnusable() const {
|
||||
@ -349,8 +311,7 @@ bool QGLBlitter::isUnusable() const {
|
||||
}
|
||||
|
||||
void QGLBlitter::setBufferDimensions(const unsigned int width, const unsigned int height) {
|
||||
delete []buffer;
|
||||
buffer = new quint32[width * height];
|
||||
buffer.reset(width * height);
|
||||
|
||||
subWidget->setBufferDimensions(width, height);
|
||||
setPixelBuffer(buffer, PixelBuffer::RGB32, width);
|
||||
@ -444,7 +405,7 @@ void QGLBlitter::resetSubWidget() {
|
||||
// else if (hz == hz2 || hz == hz1 * 2)
|
||||
// swapInterval = 2;
|
||||
// }
|
||||
const unsigned swapInterval = swapInterval_ ? swapInterval_ : vsync;
|
||||
const unsigned swapInterval = swapInterval_ ? swapInterval_ : vsync_.value();
|
||||
|
||||
if (swapInterval == subWidget->getSwapInterval())
|
||||
return;
|
||||
@ -455,29 +416,28 @@ void QGLBlitter::resetSubWidget() {
|
||||
const unsigned h = subWidget->getInHeight();
|
||||
|
||||
// subWidget->hide();
|
||||
delete subWidget;
|
||||
subWidget = new SubWidget(swapInterval, bf, this);
|
||||
subWidget.reset();
|
||||
subWidget.reset(new SubWidget(swapInterval, bf_.value(), this));
|
||||
subWidget->corrected_w = corrected_w;
|
||||
subWidget->corrected_h = corrected_h;
|
||||
subWidget->setGeometry(0, 0, width(), height());
|
||||
subWidget->show();
|
||||
ftEst.init(hz ? swapInterval * 1000000 / hz : 0);
|
||||
ftEst.init(swapInterval * 10000000 / dhz);
|
||||
|
||||
if (buffer)
|
||||
subWidget->setBufferDimensions(w, h);
|
||||
}
|
||||
|
||||
void QGLBlitter::acceptSettings() {
|
||||
bf = bfBox->isChecked();
|
||||
subWidget->setBilinearFiltering(bf);
|
||||
|
||||
vsync = vsyncBox->isChecked();
|
||||
bf_.accept();
|
||||
subWidget->setBilinearFiltering(bf_.value());
|
||||
vsync_.accept();
|
||||
resetSubWidget();
|
||||
}
|
||||
|
||||
void QGLBlitter::rejectSettings() const {
|
||||
vsyncBox->setChecked(vsync);
|
||||
bfBox->setChecked(bf);
|
||||
vsync_.reject();
|
||||
bf_.reject();
|
||||
}
|
||||
|
||||
void QGLBlitter::setSwapInterval(unsigned si) {
|
||||
@ -485,7 +445,7 @@ void QGLBlitter::setSwapInterval(unsigned si) {
|
||||
resetSubWidget();
|
||||
}
|
||||
|
||||
void QGLBlitter::rateChange(const int hz) {
|
||||
this->hz = hz;
|
||||
ftEst.init(hz ? subWidget->getSwapInterval() * 1000000 / hz : 0);
|
||||
void QGLBlitter::rateChange(const int dhz) {
|
||||
this->dhz = dhz ? dhz : 600;
|
||||
ftEst.init(subWidget->getSwapInterval() * 10000000 / this->dhz);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -20,23 +20,21 @@
|
||||
#define QGLBLITTER_H
|
||||
|
||||
#include "../blitterwidget.h"
|
||||
#include "../../persistcheckbox.h"
|
||||
#include "array.h"
|
||||
#include <memory>
|
||||
|
||||
class QCheckBox;
|
||||
|
||||
class QGLBlitter : public BlitterWidget {
|
||||
class SubWidget;
|
||||
|
||||
FtEst ftEst;
|
||||
SubWidget *subWidget;
|
||||
const std::auto_ptr<QWidget> confWidget;
|
||||
QCheckBox *const vsyncBox;
|
||||
QCheckBox *const bfBox;
|
||||
quint32 *buffer;
|
||||
PersistCheckBox vsync_;
|
||||
PersistCheckBox bf_;
|
||||
Array<quint32> buffer;
|
||||
unsigned swapInterval_;
|
||||
int hz;
|
||||
bool vsync;
|
||||
bool bf;
|
||||
int dhz;
|
||||
std::auto_ptr<SubWidget> subWidget;
|
||||
|
||||
void resetSubWidget();
|
||||
void privSetPaused(const bool /*paused*/) {}
|
||||
@ -46,9 +44,8 @@ protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
public:
|
||||
QGLBlitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
explicit QGLBlitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
~QGLBlitter();
|
||||
// void init();
|
||||
void uninit();
|
||||
bool isUnusable() const;
|
||||
void setCorrectedGeometry(int w, int h, int new_w, int new_h);
|
||||
@ -58,12 +55,11 @@ public:
|
||||
long sync();
|
||||
QWidget* settingsWidget() const { return confWidget.get(); }
|
||||
|
||||
// // public slots:
|
||||
void acceptSettings();
|
||||
void rejectSettings() const;
|
||||
|
||||
void setSwapInterval(unsigned);
|
||||
void rateChange(int hz);
|
||||
void rateChange(int dhz);
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -27,32 +27,18 @@
|
||||
QPainterBlitter::QPainterBlitter(VideoBufferLocker vbl, QWidget *parent) :
|
||||
BlitterWidget(vbl, "QPainter", false, parent),
|
||||
confWidget(new QWidget),
|
||||
bfBox(new QCheckBox(QString("Semi-bilinear filtering"))),
|
||||
buffer(NULL),
|
||||
inWidth(160),
|
||||
inHeight(144),
|
||||
bf(false)
|
||||
bf_(new QCheckBox(QString("Semi-bilinear filtering"), confWidget.get()), "qpainterblitter/bf", false),
|
||||
buffer(0)
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup("qpainterblitter");
|
||||
bf = settings.value("bf", false).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
confWidget->setLayout(new QVBoxLayout);
|
||||
confWidget->layout()->setMargin(0);
|
||||
confWidget->layout()->addWidget(bfBox);
|
||||
bfBox->setChecked(bf);
|
||||
confWidget->layout()->addWidget(bf_.checkBox());
|
||||
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||
}
|
||||
|
||||
QPainterBlitter::~QPainterBlitter() {
|
||||
uninit();
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("qpainterblitter");
|
||||
settings.setValue("bf", bf);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void QPainterBlitter::blit() {
|
||||
@ -60,10 +46,13 @@ void QPainterBlitter::blit() {
|
||||
backImage = backImage == image2.get() ? image.get() : image2.get();
|
||||
setPixelBuffer(backImage->bits(), PixelBuffer::RGB32, backImage->bytesPerLine() >> 2);
|
||||
} else {
|
||||
if (bf)
|
||||
semiLinearScale<quint32, 0xFF00FF, 0x00FF00, 8>(buffer, reinterpret_cast<quint32*>(image->bits()), inWidth, inHeight, image->width(), image->height(), image->bytesPerLine() >> 2);
|
||||
else
|
||||
nearestNeighborScale(buffer, reinterpret_cast<quint32*>(image->bits()), inWidth, inHeight, image->width(), image->height(), image->bytesPerLine() >> 2);
|
||||
if (bf_.value()) {
|
||||
semiLinearScale<quint32, 0xFF00FF, 0x00FF00, 8>(buffer, reinterpret_cast<quint32*>(image->bits()),
|
||||
inBuffer().width, inBuffer().height, image->width(), image->height(), image->bytesPerLine() >> 2);
|
||||
} else {
|
||||
nearestNeighborScale(buffer, reinterpret_cast<quint32*>(image->bits()),
|
||||
inBuffer().width, inBuffer().height, image->width(), image->height(), image->bytesPerLine() >> 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,15 +73,12 @@ void QPainterBlitter::paintEvent(QPaintEvent *const event) {
|
||||
void QPainterBlitter::resizeEvent(QResizeEvent */*event*/) {
|
||||
if (image.get()) {
|
||||
lockPixelBuffer();
|
||||
setBufferDimensions(inWidth, inHeight);
|
||||
setBufferDimensions(inBuffer().width, inBuffer().height);
|
||||
unlockPixelBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void QPainterBlitter::setBufferDimensions(const unsigned int w, const unsigned int h) {
|
||||
inWidth = w;
|
||||
inHeight = h;
|
||||
|
||||
uninit();
|
||||
image.reset(new QImage(width(), height(), QImage::Format_RGB32));
|
||||
|
||||
@ -119,9 +105,9 @@ void QPainterBlitter::uninit() {
|
||||
}
|
||||
|
||||
void QPainterBlitter::acceptSettings() {
|
||||
bf = bfBox->isChecked();
|
||||
bf_.accept();
|
||||
}
|
||||
|
||||
void QPainterBlitter::rejectSettings() const {
|
||||
bfBox->setChecked(bf);
|
||||
bf_.reject();
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define QPAINTERBLITTER_H
|
||||
|
||||
#include "../blitterwidget.h"
|
||||
#include "../../persistcheckbox.h"
|
||||
#include <memory>
|
||||
#include <QImage>
|
||||
|
||||
@ -30,10 +31,8 @@ class QPainterBlitter : public BlitterWidget {
|
||||
const std::auto_ptr<QWidget> confWidget;
|
||||
std::auto_ptr<QImage> image;
|
||||
std::auto_ptr<QImage> image2;
|
||||
QCheckBox *const bfBox;
|
||||
PersistCheckBox bf_;
|
||||
union { quint32 *buffer; QImage *backImage; };
|
||||
unsigned int inWidth, inHeight;
|
||||
bool bf;
|
||||
|
||||
protected:
|
||||
void privSetPaused(bool) {}
|
||||
@ -41,7 +40,7 @@ protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
public:
|
||||
QPainterBlitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
explicit QPainterBlitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
~QPainterBlitter();
|
||||
void blit();
|
||||
void draw();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -40,7 +40,7 @@ public:
|
||||
virtual ~SubBlitter() {};
|
||||
};
|
||||
|
||||
class X11Blitter::ShmBlitter : public SubBlitter {
|
||||
class X11Blitter::ShmBlitter : public SubBlitter, Uncopyable {
|
||||
XShmSegmentInfo shminfo;
|
||||
XImage *ximage;
|
||||
const bool doubleBuffer;
|
||||
@ -56,7 +56,6 @@ public:
|
||||
|
||||
X11Blitter::ShmBlitter::ShmBlitter(const unsigned width, const unsigned height, const VisInfo &visInfo, const bool db) : doubleBuffer(db) {
|
||||
shminfo.shmaddr = NULL;
|
||||
std::cout << "creating shm ximage...\n";
|
||||
ximage = XShmCreateImage(QX11Info::display(), reinterpret_cast<Visual*>(visInfo.visual), visInfo.depth, ZPixmap, NULL, &shminfo, width, height);
|
||||
|
||||
if (ximage == NULL) {
|
||||
@ -110,8 +109,8 @@ unsigned X11Blitter::ShmBlitter::pitch() const {
|
||||
return ximage ? ximage->width : 0;
|
||||
}
|
||||
|
||||
class X11Blitter::PlainBlitter : public X11Blitter::SubBlitter {
|
||||
XImage *ximage;
|
||||
class X11Blitter::PlainBlitter : public X11Blitter::SubBlitter, Uncopyable {
|
||||
XImage *const ximage;
|
||||
char *data;
|
||||
|
||||
bool doubleBuffer() const { return data; }
|
||||
@ -125,25 +124,26 @@ public:
|
||||
~PlainBlitter();
|
||||
};
|
||||
|
||||
X11Blitter::PlainBlitter::PlainBlitter(const unsigned int width, const unsigned int height, const VisInfo &visInfo, const bool db) : data(0) {
|
||||
std::cout << "creating ximage...\n";
|
||||
ximage = XCreateImage(QX11Info::display(), reinterpret_cast<Visual*>(visInfo.visual), visInfo.depth, ZPixmap, 0, NULL, width, height, visInfo.depth <= 16 ? 16 : 32, 0);
|
||||
|
||||
if (ximage == NULL) {
|
||||
std::cout << "failed to create ximage\n";
|
||||
} else {
|
||||
X11Blitter::PlainBlitter::PlainBlitter(const unsigned int width, const unsigned int height, const VisInfo &visInfo, const bool db)
|
||||
: ximage(XCreateImage(QX11Info::display(), reinterpret_cast<Visual*>(visInfo.visual),
|
||||
visInfo.depth, ZPixmap, 0, NULL, width, height, visInfo.depth <= 16 ? 16 : 32, 0)),
|
||||
data(0)
|
||||
{
|
||||
if (ximage) {
|
||||
ximage->data = new char[ximage->bytes_per_line * ximage->height << db];
|
||||
|
||||
if (db)
|
||||
data = ximage->data;
|
||||
} else {
|
||||
std::cout << "failed to create ximage\n";
|
||||
}
|
||||
}
|
||||
|
||||
X11Blitter::PlainBlitter::~PlainBlitter () {
|
||||
if (ximage) {
|
||||
if (doubleBuffer())
|
||||
if (doubleBuffer()) {
|
||||
delete[] data;
|
||||
else
|
||||
} else
|
||||
delete[] ximage->data;
|
||||
|
||||
XFree(ximage);
|
||||
@ -243,24 +243,14 @@ static XVisualInfo* getVisualPtr() {
|
||||
X11Blitter::X11Blitter(VideoBufferLocker vbl, QWidget *parent) :
|
||||
BlitterWidget(vbl, QString("X11"), false, parent),
|
||||
confWidget(new QWidget),
|
||||
bfBox(new QCheckBox(QString("Semi-bilinear filtering"))),
|
||||
buffer(NULL),
|
||||
inWidth(160),
|
||||
inHeight(144),
|
||||
bf(false)
|
||||
bf_(new QCheckBox(QString("Semi-bilinear filtering")), "x11blitter/bf", false)
|
||||
{
|
||||
visInfo.visual = NULL;
|
||||
visInfo.depth = 0;
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("x11blitter");
|
||||
bf = settings.value("bf", false).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
confWidget->setLayout(new QVBoxLayout);
|
||||
confWidget->layout()->setMargin(0);
|
||||
confWidget->layout()->addWidget(bfBox);
|
||||
bfBox->setChecked(bf);
|
||||
confWidget->layout()->addWidget(bf_.checkBox());
|
||||
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||
setAttribute(Qt::WA_PaintOnScreen, true);
|
||||
@ -272,32 +262,20 @@ bf(false)
|
||||
}
|
||||
}
|
||||
|
||||
X11Blitter::~X11Blitter() {
|
||||
}
|
||||
|
||||
bool X11Blitter::isUnusable() const {
|
||||
return visInfo.visual == NULL;
|
||||
}
|
||||
|
||||
void X11Blitter::init() {
|
||||
XSync(QX11Info::display(), 0);
|
||||
|
||||
shm = XShmQueryExtension(QX11Info::display());
|
||||
// shm = false;
|
||||
std::cout << "shm: " << shm << std::endl;
|
||||
}
|
||||
|
||||
void X11Blitter::uninit() {
|
||||
subBlitter.reset();
|
||||
|
||||
delete[] buffer;
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
X11Blitter::~X11Blitter() {
|
||||
uninit();
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("x11blitter");
|
||||
settings.setValue("bf", bf);
|
||||
settings.endGroup();
|
||||
buffer.reset();
|
||||
}
|
||||
|
||||
long X11Blitter::sync() {
|
||||
@ -331,12 +309,11 @@ void X11Blitter::paintEvent(QPaintEvent *event) {
|
||||
}
|
||||
|
||||
void X11Blitter::setBufferDimensions(const unsigned int w, const unsigned int h) {
|
||||
inWidth = w;
|
||||
inHeight = h;
|
||||
|
||||
uninit();
|
||||
|
||||
const bool scale = width() != static_cast<int>(w) || height() != static_cast<int>(h);
|
||||
bool shm = XShmQueryExtension(QX11Info::display());
|
||||
std::cout << "shm: " << shm << std::endl;
|
||||
|
||||
if (shm) {
|
||||
subBlitter.reset(new ShmBlitter(width(), height(), visInfo, !scale));
|
||||
@ -351,7 +328,7 @@ void X11Blitter::setBufferDimensions(const unsigned int w, const unsigned int h)
|
||||
subBlitter.reset(new PlainBlitter(width(), height(), visInfo, !scale));
|
||||
|
||||
if (scale) {
|
||||
buffer = new char[w * h * (visInfo.depth <= 16 ? 2 : 4)];
|
||||
buffer.reset(w * h * (visInfo.depth <= 16 ? 2 : 4));
|
||||
setPixelBuffer(buffer, visInfo.depth <= 16 ? PixelBuffer::RGB16 : PixelBuffer::RGB32, w);
|
||||
} else
|
||||
setPixelBuffer(subBlitter->pixels(), visInfo.depth <= 16 ? PixelBuffer::RGB16 : PixelBuffer::RGB32, subBlitter->pitch());
|
||||
@ -360,24 +337,24 @@ void X11Blitter::setBufferDimensions(const unsigned int w, const unsigned int h)
|
||||
void X11Blitter::blit() {
|
||||
if (buffer) {
|
||||
if (visInfo.depth <= 16) {
|
||||
if (bf) {
|
||||
semiLinearScale<quint16, 0xF81F, 0x07E0, 6>(reinterpret_cast<quint16*>(buffer),
|
||||
static_cast<quint16*>(subBlitter->pixels()),
|
||||
inWidth, inHeight, width(), height(), subBlitter->pitch());
|
||||
if (bf_.value()) {
|
||||
semiLinearScale<quint16, 0xF81F, 0x07E0, 6>(
|
||||
reinterpret_cast<quint16*>(buffer.get()), static_cast<quint16*>(subBlitter->pixels()),
|
||||
inBuffer().width, inBuffer().height, width(), height(), subBlitter->pitch());
|
||||
} else {
|
||||
nearestNeighborScale(reinterpret_cast<quint16*>(buffer),
|
||||
nearestNeighborScale(reinterpret_cast<quint16*>(buffer.get()),
|
||||
static_cast<quint16*>(subBlitter->pixels()),
|
||||
inWidth, inHeight, width(), height(), subBlitter->pitch());
|
||||
inBuffer().width, inBuffer().height, width(), height(), subBlitter->pitch());
|
||||
}
|
||||
} else {
|
||||
if (bf) {
|
||||
semiLinearScale<quint32, 0xFF00FF, 0x00FF00, 8>(reinterpret_cast<quint32*>(buffer),
|
||||
static_cast<quint32*>(subBlitter->pixels()),
|
||||
inWidth, inHeight, width(), height(), subBlitter->pitch());
|
||||
if (bf_.value()) {
|
||||
semiLinearScale<quint32, 0xFF00FF, 0x00FF00, 8>(
|
||||
reinterpret_cast<quint32*>(buffer.get()), static_cast<quint32*>(subBlitter->pixels()),
|
||||
inBuffer().width, inBuffer().height, width(), height(), subBlitter->pitch());
|
||||
} else {
|
||||
nearestNeighborScale(reinterpret_cast<quint32*>(buffer),
|
||||
nearestNeighborScale(reinterpret_cast<quint32*>(buffer.get()),
|
||||
static_cast<quint32*>(subBlitter->pixels()),
|
||||
inWidth, inHeight, width(), height(), subBlitter->pitch());
|
||||
inBuffer().width, inBuffer().height, width(), height(), subBlitter->pitch());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -389,15 +366,15 @@ void X11Blitter::blit() {
|
||||
void X11Blitter::resizeEvent(QResizeEvent */*event*/) {
|
||||
if (subBlitter.get()) {
|
||||
lockPixelBuffer();
|
||||
setBufferDimensions(inWidth, inHeight);
|
||||
setBufferDimensions(inBuffer().width, inBuffer().height);
|
||||
unlockPixelBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void X11Blitter::acceptSettings() {
|
||||
bf = bfBox->isChecked();
|
||||
bf_.accept();
|
||||
}
|
||||
|
||||
void X11Blitter::rejectSettings() const {
|
||||
bfBox->setChecked(bf);
|
||||
bf_.reject();
|
||||
}
|
||||
|
@ -20,11 +20,10 @@
|
||||
#define X11BLITTER_H
|
||||
|
||||
#include "../blitterwidget.h"
|
||||
|
||||
#include "../../persistcheckbox.h"
|
||||
#include "array.h"
|
||||
#include <memory>
|
||||
|
||||
class QCheckBox;
|
||||
|
||||
class X11Blitter : public BlitterWidget {
|
||||
class SubBlitter;
|
||||
class ShmBlitter;
|
||||
@ -37,13 +36,9 @@ class X11Blitter : public BlitterWidget {
|
||||
|
||||
const std::auto_ptr<QWidget> confWidget;
|
||||
std::auto_ptr<SubBlitter> subBlitter;
|
||||
QCheckBox *const bfBox;
|
||||
char *buffer;
|
||||
unsigned int inWidth, inHeight;
|
||||
PersistCheckBox bf_;
|
||||
Array<char> buffer;
|
||||
VisInfo visInfo;
|
||||
// unsigned int scale;
|
||||
bool shm;
|
||||
bool bf;
|
||||
|
||||
protected:
|
||||
void setBufferDimensions(const unsigned width, const unsigned height);
|
||||
@ -51,7 +46,7 @@ protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
public:
|
||||
X11Blitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
explicit X11Blitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
~X11Blitter();
|
||||
void init();
|
||||
void uninit();
|
||||
@ -62,7 +57,7 @@ public:
|
||||
void acceptSettings();
|
||||
void rejectSettings() const;
|
||||
|
||||
QPaintEngine* paintEngine() const { return NULL; }
|
||||
QPaintEngine* paintEngine() const { return 0; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -23,6 +23,7 @@
|
||||
#include <QList>
|
||||
|
||||
#include "xvblitter.h"
|
||||
#include "uncopyable.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -58,7 +59,6 @@ public:
|
||||
};
|
||||
|
||||
XvBlitter::ShmBlitter::ShmBlitter(const XvPortID xvport, const int formatid, const unsigned int width, const unsigned int height) {
|
||||
std::cout << "creating shm xvimage...\n";
|
||||
shminfo.shmaddr = NULL;
|
||||
xvimage = XvShmCreateImage(QX11Info::display(), xvport, formatid, NULL, width << (formatid != 3), height, &shminfo);
|
||||
|
||||
@ -114,7 +114,7 @@ unsigned XvBlitter::ShmBlitter::pitch() const {
|
||||
}
|
||||
|
||||
class XvBlitter::PlainBlitter : public SubBlitter {
|
||||
XvImage *xvimage;
|
||||
XvImage *const xvimage;
|
||||
char *data;
|
||||
|
||||
public:
|
||||
@ -127,15 +127,14 @@ public:
|
||||
~PlainBlitter();
|
||||
};
|
||||
|
||||
XvBlitter::PlainBlitter::PlainBlitter(const XvPortID xvport, const int formatid, const unsigned int width, const unsigned int height) : data(0) {
|
||||
std::cout << "creating xvimage...\n";
|
||||
xvimage = XvCreateImage(QX11Info::display(), xvport, formatid, NULL, width << (formatid != 3), height);
|
||||
|
||||
if (xvimage == NULL) {
|
||||
std::cout << "failed to create xvimage\n";
|
||||
} else {
|
||||
XvBlitter::PlainBlitter::PlainBlitter(const XvPortID xvport, const int formatid, const unsigned int width, const unsigned int height)
|
||||
: xvimage(XvCreateImage(QX11Info::display(), xvport, formatid, 0, width << (formatid != 3), height)),
|
||||
data(0)
|
||||
{
|
||||
if (xvimage) {
|
||||
xvimage->data = data = new char[xvimage->data_size * 2];
|
||||
}
|
||||
} else
|
||||
std::cout << "failed to create xvimage\n";
|
||||
}
|
||||
|
||||
XvBlitter::PlainBlitter::~PlainBlitter() {
|
||||
@ -173,64 +172,146 @@ unsigned XvBlitter::PlainBlitter::pitch() const {
|
||||
return xvimage ? xvimage->pitches[0] >> 2 : 0;
|
||||
}
|
||||
|
||||
static int search(const XvImageFormatValues *const formats, const int numFormats, const int id) {
|
||||
namespace {
|
||||
|
||||
class XvAdaptorInfos : Uncopyable {
|
||||
unsigned num_;
|
||||
XvAdaptorInfo *infos_;
|
||||
public:
|
||||
XvAdaptorInfos() : num_(0), infos_(0) {
|
||||
if (XvQueryAdaptors(QX11Info::display(), QX11Info::appRootWindow(), &num_, &infos_) != Success) {
|
||||
std::cout << "failed to query xv adaptors\n";
|
||||
num_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~XvAdaptorInfos() {
|
||||
if (infos_)
|
||||
XvFreeAdaptorInfo(infos_);
|
||||
}
|
||||
|
||||
unsigned len() const { return num_; }
|
||||
operator const XvAdaptorInfo*() const { return infos_; }
|
||||
};
|
||||
|
||||
class XvPortImageFormats : Uncopyable {
|
||||
int num_;
|
||||
XvImageFormatValues *const formats_;
|
||||
|
||||
public:
|
||||
explicit XvPortImageFormats(const XvPortID baseId)
|
||||
: num_(0), formats_(XvListImageFormats(QX11Info::display(), baseId, &num_))
|
||||
{
|
||||
}
|
||||
|
||||
~XvPortImageFormats() {
|
||||
if (formats_)
|
||||
XFree(formats_);
|
||||
}
|
||||
|
||||
int len() const { return num_; }
|
||||
operator const XvImageFormatValues*() const { return formats_; }
|
||||
};
|
||||
|
||||
static int findId(const XvPortImageFormats &formats, const int id) {
|
||||
int i = 0;
|
||||
|
||||
while (i < numFormats && formats[i].id != id)
|
||||
while (i < formats.len() && formats[i].id != id)
|
||||
++i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void addPorts(QComboBox *portSelector) {
|
||||
unsigned int num_adaptors;
|
||||
XvAdaptorInfo *adaptor_info;
|
||||
XvAdaptorInfos adaptors;
|
||||
|
||||
if (XvQueryAdaptors(QX11Info::display(), QX11Info::appRootWindow(), &num_adaptors, &adaptor_info) == Success) {
|
||||
for (unsigned int i = 0; i < num_adaptors; ++i) {
|
||||
if (!(adaptor_info[i].type & XvImageMask))
|
||||
continue;
|
||||
|
||||
int numFormats;
|
||||
XvImageFormatValues *const formats = XvListImageFormats(QX11Info::display(), adaptor_info[i].base_id, &numFormats);
|
||||
|
||||
int formatId = 0x3;
|
||||
int j = search(formats, numFormats, formatId);
|
||||
|
||||
if (j == numFormats) {
|
||||
formatId = 0x59565955;
|
||||
j = search(formats, numFormats, formatId);
|
||||
}
|
||||
|
||||
if (j < numFormats) {
|
||||
QList<QVariant> l;
|
||||
l.append(static_cast<uint>(adaptor_info[i].base_id));
|
||||
l.append(formats[j].id);
|
||||
portSelector->addItem(adaptor_info[i].name, l);
|
||||
}
|
||||
|
||||
XFree(formats);
|
||||
for (unsigned i = 0; i < adaptors.len(); ++i) {
|
||||
if (!(adaptors[i].type & XvImageMask))
|
||||
continue;
|
||||
|
||||
const XvPortImageFormats formats(adaptors[i].base_id);
|
||||
|
||||
int formatId = 0x3;
|
||||
int j = findId(formats, formatId);
|
||||
|
||||
if (j == formats.len()) {
|
||||
formatId = 0x59565955;
|
||||
j = findId(formats, formatId);
|
||||
}
|
||||
|
||||
XvFreeAdaptorInfo(adaptor_info);
|
||||
} else {
|
||||
std::cout << "failed to query xv adaptors\n";
|
||||
if (j < formats.len()) {
|
||||
QList<QVariant> l;
|
||||
l.append(static_cast<uint>(adaptors[i].base_id));
|
||||
l.append(formats[j].id);
|
||||
portSelector->addItem(adaptors[i].name, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
XvBlitter::ConfWidget::ConfWidget()
|
||||
: widget_(new QWidget), portSelector_(new QComboBox(widget_.get())), portIndex_(0)
|
||||
{
|
||||
addPorts(portSelector_);
|
||||
|
||||
if ((portIndex_ = QSettings().value("xvblitter/portIndex", 0).toUInt()) >= static_cast<unsigned>(portSelector_->count()))
|
||||
portIndex_ = 0;
|
||||
|
||||
restore();
|
||||
|
||||
widget_->setLayout(new QHBoxLayout);
|
||||
widget_->layout()->setMargin(0);
|
||||
widget_->layout()->addWidget(new QLabel(QString(tr("Xv Port:"))));
|
||||
widget_->layout()->addWidget(portSelector_);
|
||||
}
|
||||
|
||||
XvBlitter::ConfWidget::~ConfWidget() {
|
||||
QSettings settings;
|
||||
settings.setValue("xvblitter/portIndex", portIndex_);
|
||||
}
|
||||
|
||||
void XvBlitter::ConfWidget::store() {
|
||||
portIndex_ = portSelector_->currentIndex();
|
||||
}
|
||||
|
||||
void XvBlitter::ConfWidget::restore() const {
|
||||
portSelector_->setCurrentIndex(portIndex_);
|
||||
}
|
||||
|
||||
XvPortID XvBlitter::ConfWidget::portId() const {
|
||||
return static_cast<XvPortID>(portSelector_->itemData(portIndex_).toList().front().toUInt());
|
||||
}
|
||||
|
||||
int XvBlitter::ConfWidget::formatId() const {
|
||||
return portSelector_->itemData(portIndex_).toList().back().toInt();
|
||||
}
|
||||
|
||||
int XvBlitter::ConfWidget::numPorts() const {
|
||||
return portSelector_->count();
|
||||
}
|
||||
|
||||
XvBlitter::PortGrabber::PortGrabber() : port_(0), grabbed_(false) {}
|
||||
|
||||
XvBlitter::PortGrabber::~PortGrabber() {
|
||||
ungrab();
|
||||
}
|
||||
|
||||
bool XvBlitter::PortGrabber::grab(const XvPortID port) {
|
||||
ungrab();
|
||||
port_ = port;
|
||||
return grabbed_ = XvGrabPort(QX11Info::display(), port, CurrentTime) == Success;
|
||||
}
|
||||
|
||||
void XvBlitter::PortGrabber::ungrab() {
|
||||
if (grabbed_) {
|
||||
XvUngrabPort(QX11Info::display(), port_, CurrentTime);
|
||||
grabbed_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
XvBlitter::XvBlitter(VideoBufferLocker vbl, QWidget *parent) :
|
||||
BlitterWidget(vbl, QString("Xv"), 0, parent),
|
||||
// xvbuffer(NULL),
|
||||
// yuv_table(NULL),
|
||||
// xvimage(NULL),
|
||||
confWidget(new QWidget()),
|
||||
portSelector(new QComboBox),
|
||||
inWidth(160),
|
||||
inHeight(144),
|
||||
old_w(0),
|
||||
old_h(0),
|
||||
portGrabbed(false),
|
||||
failed(true),
|
||||
initialized(false)
|
||||
{
|
||||
|
||||
@ -248,26 +329,10 @@ XvBlitter::XvBlitter(VideoBufferLocker vbl, QWidget *parent) :
|
||||
gcValues.foreground = gcValues.background = 2110;
|
||||
gc = XCreateGC(QX11Info::display(), QX11Info::appRootWindow(), GCForeground | GCBackground, &gcValues);
|
||||
}
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(new QLabel(QString(tr("Xv Port:"))));
|
||||
addPorts(portSelector);
|
||||
layout->addWidget(portSelector);
|
||||
confWidget->setLayout(layout);
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("xvblitter");
|
||||
|
||||
if ((portIndex = settings.value("portIndex", 0).toUInt()) >= static_cast<unsigned>(portSelector->count()))
|
||||
portIndex = 0;
|
||||
|
||||
settings.endGroup();
|
||||
rejectSettings();
|
||||
}
|
||||
|
||||
bool XvBlitter::isUnusable() const {
|
||||
return portSelector->count() == 0;
|
||||
return confWidget.numPorts() == 0;
|
||||
}
|
||||
|
||||
/*static bool getBestPort(const unsigned int num_adaptors, const XvAdaptorInfo *const adaptor_info, XvPortID *const port_out) {
|
||||
@ -313,46 +378,26 @@ void XvBlitter::init() {
|
||||
|
||||
XSync(QX11Info::display(), 0);
|
||||
|
||||
shm = XShmQueryExtension(QX11Info::display());
|
||||
std::cout << "shm: " << shm << std::endl;
|
||||
|
||||
initPort();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void XvBlitter::uninit() {
|
||||
// delete []xvbuffer;
|
||||
// xvbuffer = NULL;
|
||||
// delete []yuv_table;
|
||||
// yuv_table = NULL;
|
||||
|
||||
subBlitter.reset();
|
||||
|
||||
if (portGrabbed) {
|
||||
XvUngrabPort(QX11Info::display(), xvport, CurrentTime);
|
||||
portGrabbed = false;
|
||||
}
|
||||
|
||||
failed = true;
|
||||
portGrabber.ungrab();
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
XvBlitter::~XvBlitter() {
|
||||
uninit();
|
||||
XFreeGC(QX11Info::display(), gc);
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("xvblitter");
|
||||
settings.setValue("portIndex", portIndex);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
long XvBlitter::sync() {
|
||||
if (failed || subBlitter->failed())
|
||||
if (!portGrabber.grabbed() || subBlitter->failed())
|
||||
return -1;
|
||||
|
||||
subBlitter->blit(winId(), xvport, width(), height());
|
||||
subBlitter->blit(winId(), portGrabber.port(), width(), height());
|
||||
XSync(QX11Info::display(), 0);
|
||||
|
||||
return 0;
|
||||
@ -362,21 +407,21 @@ void XvBlitter::paintEvent(QPaintEvent *event) {
|
||||
const QRect &rect = event->rect();
|
||||
XFillRectangle(QX11Info::display(), winId(), gc, rect.x(), rect.y(), rect.width(), rect.height());
|
||||
|
||||
if (isPaused() && !failed) {
|
||||
subBlitter->blit(winId(), xvport, width(), height());
|
||||
if (isPaused() && portGrabber.grabbed()) {
|
||||
subBlitter->blit(winId(), portGrabber.port(), width(), height());
|
||||
}
|
||||
}
|
||||
|
||||
void XvBlitter::setBufferDimensions(const unsigned int width, const unsigned int height) {
|
||||
inWidth = width;
|
||||
inHeight = height;
|
||||
|
||||
const int formatid = portSelector->itemData(portIndex).toList().back().toInt();
|
||||
void XvBlitter::setBufferDimensions(const unsigned width, const unsigned height) {
|
||||
const int formatid = confWidget.formatId();
|
||||
|
||||
subBlitter.reset(); // predestruct previous object to ensure resource availability.
|
||||
|
||||
bool shm = XShmQueryExtension(QX11Info::display());
|
||||
std::cout << "shm: " << shm << std::endl;
|
||||
|
||||
if (shm) {
|
||||
subBlitter.reset(new ShmBlitter(xvport, formatid, width, height));
|
||||
subBlitter.reset(new ShmBlitter(portGrabber.port(), formatid, width, height));
|
||||
|
||||
if (subBlitter->failed()) {
|
||||
shm = false;
|
||||
@ -385,77 +430,75 @@ void XvBlitter::setBufferDimensions(const unsigned int width, const unsigned int
|
||||
}
|
||||
|
||||
if (!shm)
|
||||
subBlitter.reset(new PlainBlitter(xvport, formatid, width, height));
|
||||
subBlitter.reset(new PlainBlitter(portGrabber.port(), formatid, width, height));
|
||||
|
||||
// delete []xvbuffer;
|
||||
// xvbuffer = new u_int16_t[width*height];
|
||||
|
||||
setPixelBuffer(subBlitter->pixels(), formatid == 3 ? PixelBuffer::RGB32 : PixelBuffer::UYVY, subBlitter->pitch());
|
||||
|
||||
old_w = old_h = 0;
|
||||
}
|
||||
|
||||
void XvBlitter::blit() {
|
||||
if (!failed) {
|
||||
/*{
|
||||
u_int32_t *yuv_pixel = (u_int32_t*)(subBlitter->inBuffer().pixels);
|
||||
const u_int16_t *s = xvbuffer;
|
||||
unsigned n = inWidth * inHeight;
|
||||
|
||||
while (n--) {
|
||||
*yuv_pixel++ = yuv_table[*s++];
|
||||
}
|
||||
}*/
|
||||
if (portGrabber.grabbed()) {
|
||||
subBlitter->flip();
|
||||
setPixelBuffer(subBlitter->pixels(), inBuffer().pixelFormat, subBlitter->pitch());
|
||||
}
|
||||
}
|
||||
|
||||
static void setAttrib(XvAttribute *const attribs, const int nattr, const char *const name, const int value, const XvPortID xvport) {
|
||||
Atom atom;
|
||||
namespace {
|
||||
|
||||
class XvAttributes : Uncopyable {
|
||||
const XvPortID xvport_;
|
||||
int numAttribs_;
|
||||
XvAttribute *const attribs_;
|
||||
|
||||
for (int i = 0; i < nattr; ++i) {
|
||||
if (!strcmp(attribs[i].name, name)) {
|
||||
if ((atom = XInternAtom(QX11Info::display(), name, True)) != None)
|
||||
XvSetPortAttribute(QX11Info::display(), xvport, atom, value);
|
||||
|
||||
break;
|
||||
Atom atomOf(const char *const name) const {
|
||||
for (int i = 0; i < numAttribs_; ++i) {
|
||||
if (!strcmp(attribs_[i].name, name))
|
||||
return XInternAtom(QX11Info::display(), name, True);
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit XvAttributes(const XvPortID xvport)
|
||||
: xvport_(xvport), numAttribs_(0), attribs_(XvQueryPortAttributes(QX11Info::display(), xvport, &numAttribs_))
|
||||
{
|
||||
}
|
||||
|
||||
~XvAttributes() {
|
||||
if (attribs_)
|
||||
XFree(attribs_);
|
||||
}
|
||||
|
||||
void set(const char *const name, const int value) {
|
||||
const Atom atom = atomOf(name);
|
||||
|
||||
if (atom != None)
|
||||
XvSetPortAttribute(QX11Info::display(), xvport_, atom, value);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void XvBlitter::initPort() {
|
||||
xvport = static_cast<XvPortID>(portSelector->itemData(portIndex).toList().front().toUInt());
|
||||
failed = !(portGrabbed = (XvGrabPort(QX11Info::display(), xvport, CurrentTime) == Success));
|
||||
|
||||
if (!failed) {
|
||||
int nattr = 0;
|
||||
XvAttribute *const attribs = XvQueryPortAttributes(QX11Info::display(), xvport, &nattr);
|
||||
setAttrib(attribs, nattr, "XV_AUTOPAINT_COLORKEY", 0, xvport);
|
||||
setAttrib(attribs, nattr, "XV_COLORKEY", 2110, xvport);
|
||||
XFree(attribs);
|
||||
if (portGrabber.grab(confWidget.portId())) {
|
||||
XvAttributes attribs(portGrabber.port());
|
||||
attribs.set("XV_AUTOPAINT_COLORKEY", 0);
|
||||
attribs.set("XV_COLORKEY", 2110);
|
||||
}
|
||||
}
|
||||
|
||||
void XvBlitter::acceptSettings() {
|
||||
if (static_cast<int>(portIndex) != portSelector->currentIndex()) {
|
||||
portIndex = portSelector->currentIndex();
|
||||
|
||||
if (initialized) {
|
||||
if (portGrabbed) {
|
||||
XvUngrabPort(QX11Info::display(), xvport, CurrentTime);
|
||||
portGrabbed = false;
|
||||
}
|
||||
|
||||
initPort();
|
||||
lockPixelBuffer();
|
||||
setBufferDimensions(inWidth, inHeight);
|
||||
unlockPixelBuffer();
|
||||
repaint();
|
||||
}
|
||||
confWidget.store();
|
||||
|
||||
if (initialized && confWidget.portId() != portGrabber.port()) {
|
||||
initPort();
|
||||
lockPixelBuffer();
|
||||
setBufferDimensions(inBuffer().width, inBuffer().height);
|
||||
unlockPixelBuffer();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void XvBlitter::rejectSettings() const {
|
||||
portSelector->setCurrentIndex(portIndex);
|
||||
confWidget.restore();
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "../blitterwidget.h"
|
||||
#include "uncopyable.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
@ -33,22 +34,38 @@ class XvBlitter : public BlitterWidget {
|
||||
class ShmBlitter;
|
||||
class PlainBlitter;
|
||||
|
||||
// XShmSegmentInfo shminfo;
|
||||
class ConfWidget {
|
||||
const std::auto_ptr<QWidget> widget_;
|
||||
QComboBox *const portSelector_;
|
||||
unsigned portIndex_;
|
||||
|
||||
public:
|
||||
ConfWidget();
|
||||
~ConfWidget();
|
||||
void store();
|
||||
void restore() const;
|
||||
XvPortID portId() const;
|
||||
int formatId() const;
|
||||
int numPorts() const;
|
||||
QWidget * qwidget() const { return widget_.get(); }
|
||||
};
|
||||
|
||||
class PortGrabber : Uncopyable {
|
||||
XvPortID port_;
|
||||
bool grabbed_;
|
||||
public:
|
||||
PortGrabber();
|
||||
~PortGrabber();
|
||||
bool grab(XvPortID port);
|
||||
void ungrab();
|
||||
bool grabbed() const { return grabbed_; }
|
||||
XvPortID port() const { return port_; }
|
||||
};
|
||||
|
||||
ConfWidget confWidget;
|
||||
PortGrabber portGrabber;
|
||||
std::auto_ptr<SubBlitter> subBlitter;
|
||||
XvPortID xvport;
|
||||
// u_int16_t *xvbuffer;
|
||||
// u_int32_t *yuv_table;
|
||||
// XvImage *xvimage;
|
||||
const std::auto_ptr<QWidget> confWidget;
|
||||
QComboBox *const portSelector;
|
||||
unsigned int inWidth, inHeight;
|
||||
int old_w, old_h;
|
||||
unsigned portIndex;
|
||||
GC gc;
|
||||
// bool init;
|
||||
bool shm;
|
||||
bool portGrabbed;
|
||||
bool failed;
|
||||
bool initialized;
|
||||
|
||||
void initPort();
|
||||
@ -59,7 +76,7 @@ protected:
|
||||
// void resizeEvent(QResizeEvent *event);
|
||||
|
||||
public:
|
||||
XvBlitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
explicit XvBlitter(VideoBufferLocker vbl, QWidget *parent = 0);
|
||||
~XvBlitter();
|
||||
void init();
|
||||
void uninit();
|
||||
@ -68,7 +85,7 @@ public:
|
||||
void setBufferDimensions(const unsigned int width, const unsigned int height);
|
||||
void blit();
|
||||
|
||||
QWidget* settingsWidget() const { return confWidget.get(); }
|
||||
QWidget* settingsWidget() const { return confWidget.qwidget(); }
|
||||
void acceptSettings();
|
||||
void rejectSettings() const;
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QRect>
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
|
||||
#include "../resinfo.h"
|
||||
@ -42,6 +43,7 @@ public:
|
||||
virtual void setScreen(const QWidget *widget) = 0;
|
||||
virtual unsigned screen() const = 0;
|
||||
virtual unsigned screens() const = 0;
|
||||
virtual const QString screenName(unsigned screen) const { return QString::number(screen); }
|
||||
|
||||
signals:
|
||||
void rateChange(int newHz);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -38,7 +38,7 @@ static void addMode(const DEVMODE &devmode, std::vector<ResInfo> &infoVector, un
|
||||
|
||||
info.w = devmode.dmPelsWidth;
|
||||
info.h = devmode.dmPelsHeight;
|
||||
rate = devmode.dmDisplayFrequency;
|
||||
rate = devmode.dmDisplayFrequency * 10;
|
||||
|
||||
std::vector<ResInfo>::iterator it = std::lower_bound(infoVector.begin(), infoVector.end(), info, std::greater<ResInfo>());
|
||||
|
||||
@ -170,7 +170,7 @@ void GdiToggler::setFullMode(const bool enable) {
|
||||
const ResInfo &info = infoVector[widgetScreen][fullResIndex[widgetScreen]];
|
||||
devmode.dmPelsWidth = info.w;
|
||||
devmode.dmPelsHeight = info.h;
|
||||
devmode.dmDisplayFrequency = info.rates[fullRateIndex[widgetScreen]];
|
||||
devmode.dmDisplayFrequency = info.rates[fullRateIndex[widgetScreen]] / 10;
|
||||
} else if (isFull) {
|
||||
mon->enumDisplaySettings(widgetScreen, ENUM_REGISTRY_SETTINGS, &devmode);
|
||||
}
|
||||
@ -180,7 +180,7 @@ void GdiToggler::setFullMode(const bool enable) {
|
||||
mon->changeDisplaySettings(widgetScreen, &devmode, enable ? CDS_FULLSCREEN : 0);
|
||||
|
||||
if (devmode.dmDisplayFrequency != currentRate)
|
||||
emit rateChange(devmode.dmDisplayFrequency);
|
||||
emit rateChange(devmode.dmDisplayFrequency * 10);
|
||||
}
|
||||
|
||||
isFull = enable;
|
||||
@ -191,5 +191,5 @@ void GdiToggler::emitRate() {
|
||||
devmode.dmSize = sizeof(DEVMODE);
|
||||
devmode.dmDriverExtra = 0;
|
||||
mon->enumDisplaySettings(widgetScreen, ENUM_CURRENT_SETTINGS, &devmode);
|
||||
emit rateChange(devmode.dmDisplayFrequency);
|
||||
emit rateChange(devmode.dmDisplayFrequency * 10);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -44,7 +44,7 @@ static void addMode(CFDictionaryRef mode, std::vector<ResInfo> &infoVector, unsi
|
||||
|
||||
info.w = w;
|
||||
info.h = h;
|
||||
rate = static_cast<short>(r + 0.5);
|
||||
rate = static_cast<short>(r * 10.0 + 0.5);
|
||||
}
|
||||
|
||||
std::vector<ResInfo>::iterator it = std::lower_bound(infoVector.begin(), infoVector.end(), info, std::greater<ResInfo>());
|
||||
@ -156,7 +156,7 @@ void QuartzToggler::setFullMode(const bool enable) {
|
||||
bpp,
|
||||
infoVector[widgetScreen][fullResIndex[widgetScreen]].w,
|
||||
infoVector[widgetScreen][fullResIndex[widgetScreen]].h,
|
||||
infoVector[widgetScreen][fullResIndex[widgetScreen]].rates[fullRateIndex[widgetScreen]],
|
||||
infoVector[widgetScreen][fullResIndex[widgetScreen]].rates[fullRateIndex[widgetScreen]] / 10.0,
|
||||
NULL
|
||||
);
|
||||
|
||||
@ -174,8 +174,8 @@ void QuartzToggler::setFullMode(const bool enable) {
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(currentMode, kCGDisplayRefreshRate)), kCFNumberDoubleType, &oldRate);
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(mode, kCGDisplayRefreshRate)), kCFNumberDoubleType, &newRate);
|
||||
|
||||
if (static_cast<int>(oldRate + 0.5) != static_cast<int>(newRate + 0.5))
|
||||
emit rateChange(static_cast<int>(newRate + 0.5));
|
||||
if (static_cast<int>(oldRate * 10.0 + 0.5) != static_cast<int>(newRate * 10.0 + 0.5))
|
||||
emit rateChange(static_cast<int>(newRate * 10.0 + 0.5));
|
||||
}
|
||||
|
||||
isFull = enable;
|
||||
@ -186,5 +186,5 @@ void QuartzToggler::emitRate() {
|
||||
|
||||
CFNumberGetValue(static_cast<CFNumberRef>(CFDictionaryGetValue(CGDisplayCurrentMode(activeDspys[widgetScreen]), kCGDisplayRefreshRate)), kCFNumberDoubleType, &rate);
|
||||
|
||||
emit rateChange(static_cast<int>(rate + 0.5));
|
||||
emit rateChange(static_cast<int>(rate * 10.0 + 0.5));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* Copyright (C) 2008 by Sindre Aam<EFBFBD>s *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -57,7 +57,7 @@ static inline bool operator>(const ResInfo &l, const ResInfo &r) {
|
||||
|
||||
static unsigned getRate(const unsigned dotclock, const unsigned htotal, const unsigned vtotal) {
|
||||
if (unsigned long pixels = htotal * vtotal)
|
||||
return (dotclock * 1000ul + (pixels >> 1)) / pixels;
|
||||
return (dotclock * 10000ull + (pixels >> 1)) / pixels;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aam<EFBFBD>s *
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -17,6 +17,7 @@
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include "xrandr12toggler.h"
|
||||
#include "uncopyable.h"
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <QWidget>
|
||||
@ -30,9 +31,9 @@ static inline bool operator>(const ResInfo &l, const ResInfo &r) {
|
||||
return l.w > r.w || (l.w == r.w && l.h > r.h);
|
||||
}
|
||||
|
||||
static unsigned getRate(const unsigned dotclock, const unsigned htotal, const unsigned vtotal) {
|
||||
static unsigned getRate(const unsigned long dotclock, const unsigned htotal, const unsigned vtotal) {
|
||||
if (unsigned long pixels = htotal * vtotal)
|
||||
return (dotclock + (pixels >> 1)) / pixels;
|
||||
return (dotclock * 10ull + (pixels >> 1)) / pixels;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -76,19 +77,19 @@ static XRRModeInfo* getModeInfo(const XRRScreenResources *const resources, const
|
||||
}
|
||||
|
||||
static bool isGood(const RRMode mode, const std::vector<XRROutputInfo*> &outputInfos) {
|
||||
bool good = true;
|
||||
|
||||
for (std::size_t o = 0; o < outputInfos.size() && good; ++o) {
|
||||
int mm = 0;
|
||||
|
||||
while ((good = mm < outputInfos[o]->nmode) && outputInfos[o]->modes[mm] != mode)
|
||||
++mm;
|
||||
for (std::size_t o = 0; o < outputInfos.size(); ++o) {
|
||||
RRMode *const modesEnd = outputInfos[o]->modes + outputInfos[o]->nmode;
|
||||
|
||||
if (std::find(outputInfos[o]->modes, modesEnd, mode) == modesEnd)
|
||||
return false;
|
||||
}
|
||||
|
||||
return good;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class OutputInfos {
|
||||
namespace {
|
||||
|
||||
class OutputInfos : Uncopyable {
|
||||
std::vector<XRROutputInfo*> v;
|
||||
public:
|
||||
OutputInfos(XRRScreenResources *resources, const XRRCrtcInfo *crtcInfo);
|
||||
@ -96,8 +97,10 @@ public:
|
||||
const std::vector<XRROutputInfo*>& get() { return v; }
|
||||
};
|
||||
|
||||
OutputInfos::OutputInfos(XRRScreenResources *const resources, const XRRCrtcInfo *const crtcInfo) : v(crtcInfo->noutput) {
|
||||
for (int i = 0; i < crtcInfo->noutput;) {
|
||||
OutputInfos::OutputInfos(XRRScreenResources *const resources, const XRRCrtcInfo *const crtcInfo)
|
||||
: v(crtcInfo ? crtcInfo->noutput : 0)
|
||||
{
|
||||
for (std::size_t i = 0; i < v.size();) {
|
||||
v[i] = XRRGetOutputInfo(QX11Info::display(), resources, crtcInfo->outputs[i]);
|
||||
|
||||
if (v[i])
|
||||
@ -112,11 +115,12 @@ OutputInfos::~OutputInfos() {
|
||||
XRRFreeOutputInfo(v[i]);
|
||||
}
|
||||
|
||||
class CrtcInfoPtr {
|
||||
class CrtcInfoPtr : Uncopyable {
|
||||
XRRCrtcInfo *const crtcInfo;
|
||||
|
||||
public:
|
||||
CrtcInfoPtr(XRRScreenResources *const resources, const RRCrtc crtc) : crtcInfo(XRRGetCrtcInfo(QX11Info::display(), resources, crtc)) {}
|
||||
CrtcInfoPtr(XRRScreenResources *const resources, const RRCrtc crtc)
|
||||
: crtcInfo(XRRGetCrtcInfo(QX11Info::display(), resources, crtc)) {}
|
||||
~CrtcInfoPtr() { if (crtcInfo) XRRFreeCrtcInfo(crtcInfo); }
|
||||
operator XRRCrtcInfo*() { return crtcInfo; }
|
||||
operator const XRRCrtcInfo*() const { return crtcInfo; }
|
||||
@ -148,6 +152,8 @@ static RRMode getMode(XRRScreenResources *const resources, const XRRCrtcInfo *co
|
||||
return crtcInfo->mode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool XRandR12Toggler::isUsable() {
|
||||
int unused = 0;
|
||||
int major = 1;
|
||||
@ -300,8 +306,7 @@ void XRandR12Toggler::setFullMode(const bool enable) {
|
||||
}
|
||||
|
||||
void XRandR12Toggler::emitRate() {
|
||||
CrtcInfoPtr crtcInfo(resources, resources->crtcs[widgetScreen]);
|
||||
|
||||
const CrtcInfoPtr crtcInfo(resources, resources->crtcs[widgetScreen]);
|
||||
short rate = 0;
|
||||
|
||||
if (crtcInfo) {
|
||||
@ -311,3 +316,12 @@ void XRandR12Toggler::emitRate() {
|
||||
|
||||
emit rateChange(rate);
|
||||
}
|
||||
|
||||
const QString XRandR12Toggler::screenName(const unsigned screen) const {
|
||||
OutputInfos outputInfos(resources, CrtcInfoPtr(resources, resources->crtcs[screen]));
|
||||
|
||||
if (!outputInfos.get().empty())
|
||||
return QString(outputInfos.get()[0]->name);
|
||||
|
||||
return FullModeToggler::screenName(screen);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aam<EFBFBD>s *
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -20,10 +20,11 @@
|
||||
#define XRANDR12TOGGLER_H_
|
||||
|
||||
#include "../fullmodetoggler.h"
|
||||
#include "uncopyable.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
||||
class XRandR12Toggler : public FullModeToggler {
|
||||
class XRandR12Toggler : public FullModeToggler, Uncopyable {
|
||||
Q_OBJECT
|
||||
|
||||
RRMode originalMode;
|
||||
@ -49,6 +50,7 @@ public:
|
||||
void setScreen(const QWidget *widget);
|
||||
unsigned screen() const { return widgetScreen; }
|
||||
unsigned screens() const { return infoVector.size(); }
|
||||
const QString screenName(unsigned screen) const;
|
||||
|
||||
signals:
|
||||
void rateChange(int newHz);
|
||||
|
@ -32,7 +32,7 @@ bool XRandRToggler::isUsable() {
|
||||
}
|
||||
|
||||
XRandRToggler::XRandRToggler() :
|
||||
config(0),
|
||||
config(XRRGetScreenInfo(QX11Info::display(), QX11Info::appRootWindow())),
|
||||
originalResIndex(0),
|
||||
fullResIndex(0),
|
||||
rotation(0),
|
||||
@ -40,7 +40,6 @@ fullRateIndex(0),
|
||||
originalRate(0),
|
||||
isFull(false)
|
||||
{
|
||||
config = XRRGetScreenInfo(QX11Info::display(), QX11Info::appRootWindow());
|
||||
fullResIndex = originalResIndex = XRRConfigCurrentConfiguration(config, &rotation);
|
||||
originalRate = XRRConfigCurrentRate(config);
|
||||
|
||||
@ -56,7 +55,7 @@ isFull(false)
|
||||
short *rates = XRRConfigRates(config, i, &nHz);
|
||||
|
||||
for (int j = 0; j < nHz; ++j)
|
||||
info.rates.push_back(rates[j]);
|
||||
info.rates.push_back(rates[j] * 10);
|
||||
|
||||
infoVector.push_back(info);
|
||||
}
|
||||
@ -64,11 +63,11 @@ isFull(false)
|
||||
{
|
||||
unsigned i = 0;
|
||||
|
||||
while (i < infoVector[fullResIndex].rates.size() && infoVector[fullResIndex].rates[i] != originalRate)
|
||||
while (i < infoVector[fullResIndex].rates.size() && infoVector[fullResIndex].rates[i] != originalRate * 10)
|
||||
++i;
|
||||
|
||||
if (i == infoVector[fullResIndex].rates.size())
|
||||
infoVector[fullResIndex].rates.push_back(originalRate);
|
||||
infoVector[fullResIndex].rates.push_back(originalRate * 10);
|
||||
|
||||
fullRateIndex = i;
|
||||
}
|
||||
@ -118,7 +117,7 @@ void XRandRToggler::setFullMode(const bool enable) {
|
||||
|
||||
if (enable) {
|
||||
newID = fullResIndex;
|
||||
newRate = infoVector[fullResIndex].rates[fullRateIndex];
|
||||
newRate = infoVector[fullResIndex].rates[fullRateIndex] / 10;
|
||||
|
||||
if (!isFull) {
|
||||
originalResIndex = currentID;
|
||||
@ -133,12 +132,12 @@ void XRandRToggler::setFullMode(const bool enable) {
|
||||
XRRSetScreenConfigAndRate(QX11Info::display(), config, QX11Info::appRootWindow(), newID, rotation, newRate, CurrentTime);
|
||||
|
||||
if (newRate != currentRate)
|
||||
emit rateChange(newRate);
|
||||
emit rateChange(newRate * 10);
|
||||
}
|
||||
|
||||
isFull = enable;
|
||||
}
|
||||
|
||||
void XRandRToggler::emitRate() {
|
||||
emit rateChange(XRRConfigCurrentRate(config));
|
||||
emit rateChange(XRRConfigCurrentRate(config) * 10);
|
||||
}
|
||||
|
@ -20,15 +20,16 @@
|
||||
#define XRANDRTOGGLER_H
|
||||
|
||||
#include "../fullmodetoggler.h"
|
||||
#include "uncopyable.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
||||
class XRandRToggler : public FullModeToggler {
|
||||
class XRandRToggler : public FullModeToggler, Uncopyable {
|
||||
Q_OBJECT
|
||||
|
||||
std::vector<ResInfo> infoVector;
|
||||
XRRScreenConfiguration *config;
|
||||
XRRScreenConfiguration *const config;
|
||||
unsigned originalResIndex;
|
||||
unsigned fullResIndex;
|
||||
Rotation rotation;
|
||||
|
@ -47,9 +47,7 @@ MainWindow::JoystickIniter::JoystickIniter() {
|
||||
const int numJs = SDL_NumJoysticks();
|
||||
|
||||
for (int i = 0; i < numJs; ++i) {
|
||||
SDL_Joystick *joy = SDL_JoystickOpen(i);
|
||||
|
||||
if (joy)
|
||||
if (SDL_Joystick *joy = SDL_JoystickOpen(i))
|
||||
joysticks.push_back(joy);
|
||||
}
|
||||
|
||||
@ -74,12 +72,6 @@ struct MainWindow::Pauser::DoPause {
|
||||
void operator()(MainWindow *const mw) {
|
||||
if (mw->running) {
|
||||
mw->worker->pause();
|
||||
|
||||
// if (mw->timerId) {
|
||||
// mw->killTimer(mw->timerId);
|
||||
// mw->timerId = 0;
|
||||
// }
|
||||
|
||||
mw->jsTimer->start();
|
||||
}
|
||||
|
||||
@ -92,9 +84,6 @@ struct MainWindow::Pauser::DoUnpause {
|
||||
if (mw->running) {
|
||||
mw->jsTimer->stop();
|
||||
mw->worker->unpause();
|
||||
|
||||
// if (!mw->threaded && !mw->timerId)
|
||||
// mw->timerId = mw->startTimer(0);
|
||||
}
|
||||
|
||||
mw->blitterContainer->blitter()->setPaused(false);
|
||||
@ -141,14 +130,14 @@ public:
|
||||
bool tryLockVideoBuffer() { return mw->vbmut.tryLock(); }
|
||||
void unlockVideoBuffer() { mw->vbmut.unlock(); }
|
||||
const PixelBuffer& videoBuffer() {
|
||||
return /*mw->videoChain.empty() ? */mw->blitterContainer->blitter()->inBuffer()/* : mw->videoChain.front()->inBuffer()*/;
|
||||
return mw->blitterContainer->blitter()->inBuffer();
|
||||
}
|
||||
};
|
||||
|
||||
void MainWindow::WorkerCallback::blit(const usec_t synctimebase, const usec_t synctimeinc) {
|
||||
struct BlitEvent : CustomEvent {
|
||||
WorkerCallback &cb;
|
||||
BlitEvent(WorkerCallback &cb) : cb(cb) {}
|
||||
explicit BlitEvent(WorkerCallback &cb) : cb(cb) {}
|
||||
|
||||
void exec(MainWindow *const mw) {
|
||||
if (blitRequested(cb.blitState) && mw->running) {
|
||||
@ -241,10 +230,8 @@ MainWindow::MainWindow(MediaSource *const source)
|
||||
windowSize(-1, -1),
|
||||
frameTime_(1, 60),
|
||||
focusPauseBit(0),
|
||||
// timerId(0),
|
||||
hz(60),
|
||||
refreshRate(600),
|
||||
running(false),
|
||||
// threaded(true),
|
||||
refreshRateSync(false),
|
||||
cursorHidden(false)
|
||||
{
|
||||
@ -277,7 +264,7 @@ MainWindow::MainWindow(MediaSource *const source)
|
||||
blitterContainer->setMinimumSize(QSize(imageFormat.width, imageFormat.height));
|
||||
blitterContainer->setSourceSize(QSize(imageFormat.width, imageFormat.height));
|
||||
blitterContainer->setAspectRatio(QSize(imageFormat.width, imageFormat.height));
|
||||
connect(fullModeToggler.get(), SIGNAL(rateChange(int)), this, SLOT(hzChange(int)));
|
||||
connect(fullModeToggler.get(), SIGNAL(rateChange(int)), this, SLOT(refreshRateChange(int)));
|
||||
fullModeToggler->emitRate();
|
||||
|
||||
cursorTimer->setSingleShot(true);
|
||||
@ -308,11 +295,7 @@ void MainWindow::run() {
|
||||
if (pauser.isPaused()) {
|
||||
jsTimer->start();
|
||||
worker->pause();
|
||||
}/* else if (!threaded)
|
||||
timerId = startTimer(0);*/
|
||||
|
||||
// if (!threaded)
|
||||
// worker->deactivate();
|
||||
}
|
||||
|
||||
SDL_JoystickUpdate();
|
||||
SDL_ClearEvents();
|
||||
@ -325,14 +308,8 @@ void MainWindow::stop() {
|
||||
|
||||
worker->stop();
|
||||
jsTimer->stop();
|
||||
// videoChain.clear();
|
||||
running = false;
|
||||
|
||||
// if (timerId) {
|
||||
// killTimer(timerId);
|
||||
// timerId = 0;
|
||||
// }
|
||||
|
||||
blitterContainer->blitter()->uninit();
|
||||
blitterContainer->blitter()->setVisible(false);
|
||||
|
||||
@ -342,44 +319,18 @@ void MainWindow::stop() {
|
||||
}
|
||||
|
||||
void MainWindow::rebuildVideoChain() {
|
||||
ImageFormat ifmt(imageFormat);
|
||||
/*videoChain.clear(); // and delete. can we do better than complete reinitialization?
|
||||
|
||||
if (vfilter) {
|
||||
VideoLink *const filterLink = vfilter->create(ifmt.width, ifmt.height, ifmt.pixelFormat);
|
||||
|
||||
if (filterLink->inBuffer().pixelFormat != ifmt.pixelFormat) {
|
||||
videoChain.push_back(VideoFormatConverter::create(ifmt.width,
|
||||
ifmt.height, ifmt.pixelFormat, vfilter->inBuffer().pixelFormat));
|
||||
}
|
||||
|
||||
videoChain.push_back(filterLink);
|
||||
ifmt.width = filterLink->outWidth();
|
||||
ifmt.height = filterLink->outHeight();
|
||||
ifmt.pixelFormat = filterLink->outPixelFormat();
|
||||
}*/
|
||||
|
||||
/*if (!*/blitterContainer->blitter()->setVideoFormat(ifmt.width, ifmt.height/*, ifmt.pixelFormat*/)/*) {*/;
|
||||
// videoChain.push_back(VideoFormatConverter::create(ifmt.width, ifmt.height,
|
||||
// ifmt.pixelFormat, blitterContainer->blitter()->inBuffer().pixelFormat));
|
||||
// }
|
||||
|
||||
// worker->setVideoBuffer(/*videoChain.empty() ? */blitterContainer->blitter()->inBuffer()/* : videoChain.front()->inBuffer()*/);
|
||||
}
|
||||
|
||||
static const QSize getFilteredSize(const QSize &sz/*, const VideoFiler *const filter*/) {
|
||||
return /*filter ? filter->outSize(sz) : */sz;
|
||||
blitterContainer->blitter()->setVideoFormat(imageFormat.width, imageFormat.height);
|
||||
}
|
||||
|
||||
void MainWindow::updateMinimumSize() {
|
||||
if (layout()->sizeConstraint() != QLayout::SetFixedSize)
|
||||
centralWidget()->setMinimumSize(getFilteredSize(QSize(imageFormat.width, imageFormat.height)/*, vfilter*/));
|
||||
centralWidget()->setMinimumSize(QSize(imageFormat.width, imageFormat.height));
|
||||
}
|
||||
|
||||
void MainWindow::doSetWindowSize(const QSize &sz) {
|
||||
if (!isFullScreen() && isVisible()) {
|
||||
if (sz == QSize(-1, -1)) {
|
||||
centralWidget()->setMinimumSize(getFilteredSize(QSize(imageFormat.width, imageFormat.height)/*, vfilter*/));
|
||||
centralWidget()->setMinimumSize(QSize(imageFormat.width, imageFormat.height));
|
||||
layout()->setSizeConstraint(QLayout::SetMinimumSize);
|
||||
setMinimumSize(1, 1); // needed on macx
|
||||
setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); // needed on macx. needed for metacity full screen switching, layout()->setSizeConstraint(QLayout::SetMinAndMaxSize) won't do.
|
||||
@ -414,7 +365,7 @@ void MainWindow::setBlitter(BlitterWidget *const blitter) {
|
||||
blitterContainer->setBlitter(blitter);
|
||||
blitterContainer->blitter()->setVisible(visible);
|
||||
blitterContainer->blitter()->setPaused(paused);
|
||||
blitterContainer->blitter()->rateChange(hz);
|
||||
blitterContainer->blitter()->rateChange(refreshRate);
|
||||
updateSwapInterval();
|
||||
|
||||
if (running)
|
||||
@ -422,16 +373,12 @@ void MainWindow::setBlitter(BlitterWidget *const blitter) {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setVideo(const unsigned w, const unsigned h,
|
||||
/*const PixelBuffer::PixelFormat pf,*/ /*const VideoFilter *const vf, */BlitterWidget *const blitter)
|
||||
void MainWindow::setVideo(const unsigned w, const unsigned h, BlitterWidget *const blitter)
|
||||
{
|
||||
if (imageFormat.width != w || imageFormat.height != h /*|| imageFormat.pixelFormat != pf*/ ||
|
||||
/*vfilter != vf || */blitter != blitterContainer->blitter())
|
||||
{
|
||||
if (imageFormat.width != w || imageFormat.height != h || blitter != blitterContainer->blitter()) {
|
||||
vbmut.lock();
|
||||
imageFormat = ImageFormat(w, h/*, pf*/);
|
||||
imageFormat = ImageFormat(w, h);
|
||||
setBlitter(blitter);
|
||||
// vfilter = vf;
|
||||
|
||||
if (running)
|
||||
rebuildVideoChain();
|
||||
@ -556,8 +503,10 @@ void MainWindow::setFrameTime(unsigned num, unsigned denom) {
|
||||
denom = 1;
|
||||
}
|
||||
|
||||
frameTime_ = Rational(num, denom);
|
||||
updateSwapInterval();
|
||||
if (static_cast<long>(num) != frameTime_.num || static_cast<long>(denom) != frameTime_.denom) {
|
||||
frameTime_ = Rational(num, denom);
|
||||
updateSwapInterval();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::waitUntilPaused() {
|
||||
@ -577,9 +526,9 @@ void MainWindow::setSyncToRefreshRate(bool on) {
|
||||
void MainWindow::correctFullScreenGeometry() {
|
||||
const QRect &screenRect = fullModeToggler->fullScreenRect(this);
|
||||
|
||||
if (geometry() != screenRect) {
|
||||
if (geometry() != screenRect)
|
||||
setGeometry(screenRect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::setFullScreenMode(const unsigned screenNo, const unsigned resIndex, const unsigned rateIndex) {
|
||||
@ -591,7 +540,7 @@ void MainWindow::setFullScreenMode(const unsigned screenNo, const unsigned resIn
|
||||
|
||||
if (fullModeToggler->isFullMode() && screenNo == fullModeToggler->screen()) {
|
||||
#ifdef Q_WS_WIN
|
||||
showNormal(); // is this really neccessary anymore?
|
||||
showNormal();
|
||||
showFullScreen();
|
||||
#endif
|
||||
correctFullScreenGeometry();
|
||||
@ -648,7 +597,7 @@ void MainWindow::updateSwapInterval() {
|
||||
unsigned si = 0;
|
||||
|
||||
if (refreshRateSync) {
|
||||
si = (frameTime_.num * hz + (frameTime_.denom >> 1)) / frameTime_.denom;
|
||||
si = (frameTime_.num * refreshRate + (frameTime_.denom * 10 >> 1)) / (frameTime_.denom * 10);
|
||||
|
||||
if (si < 1)
|
||||
si = 1;
|
||||
@ -659,20 +608,20 @@ void MainWindow::updateSwapInterval() {
|
||||
|
||||
blitterContainer->blitter()->setSwapInterval(si);
|
||||
|
||||
if (si)
|
||||
worker->setFrameTime(Rational(si, hz));
|
||||
else
|
||||
if (si) {
|
||||
worker->setFrameTime(Rational(si * 10, refreshRate));
|
||||
} else
|
||||
worker->setFrameTime(frameTime_);
|
||||
|
||||
worker->setFrameTimeEstimate(blitterContainer->blitter()->frameTimeEst());
|
||||
}
|
||||
|
||||
void MainWindow::hzChange(int hz) {
|
||||
if (hz < 1)
|
||||
hz = 60;
|
||||
void MainWindow::refreshRateChange(int refreshRate) {
|
||||
if (refreshRate < 1)
|
||||
refreshRate = 600;
|
||||
|
||||
this->hz = hz;
|
||||
blitterContainer->blitter()->rateChange(hz);
|
||||
this->refreshRate = refreshRate;
|
||||
blitterContainer->blitter()->rateChange(refreshRate);
|
||||
updateSwapInterval();
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "joysticklock.h"
|
||||
#include "SDL_joystick.h"
|
||||
#include "../mediasource.h"
|
||||
#include "skipsched.h"
|
||||
|
||||
#ifdef Q_WS_WIN
|
||||
#include <Objbase.h> // For CoInitialize
|
||||
@ -44,33 +45,6 @@ void MediaWorker::MeanQueue::push(const long i) {
|
||||
q.push_back(newelem);
|
||||
}
|
||||
|
||||
// void MediaWorker::FrameWaiter::frameWait(const long syncft, SyncVar &waitingForSync) {
|
||||
// const usec_t now = getusecs();
|
||||
//
|
||||
// if (now - base < syncft) {
|
||||
// {
|
||||
// SyncVar::Locked wfs(waitingForSync);
|
||||
//
|
||||
// /*while*/if (!wfs.get() && /*wfs.wait(now, syncft - (now - base)*/ wfs.wait((syncft - (now - base)) / 1000))
|
||||
// ;
|
||||
//
|
||||
// if (wfs.get())
|
||||
// wfs.set(false);
|
||||
// }
|
||||
//
|
||||
// asleep.sleepUntil(base, syncft);
|
||||
// base += syncft;
|
||||
// } else
|
||||
// base = now;
|
||||
// }
|
||||
//
|
||||
// void MediaWorker::FrameWaiter::syncedFrameWait(const long ft) {
|
||||
// if (ft) {
|
||||
// base += asleep.sleepUntil(base, ft);
|
||||
// base += ft;
|
||||
// }
|
||||
// }
|
||||
|
||||
void MediaWorker::PauseVar::unpause(const unsigned bits) {
|
||||
mut.lock();
|
||||
|
||||
@ -108,14 +82,11 @@ meanQueue(0, 0),
|
||||
frameTimeEst(0),
|
||||
doneVar(true),
|
||||
sampleBuffer(source),
|
||||
ae(NULL),
|
||||
ae(0),
|
||||
usecft(0),
|
||||
estsrate(0),
|
||||
base(0),
|
||||
/*turbo(0), */
|
||||
aelatency(0),
|
||||
aerate(0),
|
||||
audioBufLow(false) {
|
||||
aerate(0) {
|
||||
}
|
||||
|
||||
void MediaWorker::start() {
|
||||
@ -131,10 +102,8 @@ void MediaWorker::start() {
|
||||
|
||||
void MediaWorker::stop() {
|
||||
AtomicVar<bool>::Locked(doneVar).set(true);
|
||||
// SyncVar::Locked(syncVar_).set(PREPARE);
|
||||
pauseVar.unpause(~0U);
|
||||
wait();
|
||||
// SyncVar::Locked(syncVar_).set(0);
|
||||
pauseVar.rewait();
|
||||
sampleBuffer.setOutSampleRate(0);
|
||||
sndOutBuffer.reset(0);
|
||||
@ -275,26 +244,6 @@ long MediaWorker::adaptToRateEstimation(const long estft) {
|
||||
return calculateSyncft(sampleBuffer.resamplerOutRate(), estsrate, usecft);
|
||||
}
|
||||
|
||||
// we try to force the sync to begin in the GUI thread before we continue, which is why this code looks a bit funky.
|
||||
// static void signalSync(SyncVar &syncVar, MediaWorker::Callback *cb) {
|
||||
// // unsigned sync;
|
||||
//
|
||||
// {
|
||||
// SyncVar::Locked sv(syncVar);
|
||||
// sv.set(/*sync = */(sv.get() & PREPARE) ? 0 : SYNC);
|
||||
// }
|
||||
//
|
||||
// // if (sync)
|
||||
// // cb->sync();
|
||||
//
|
||||
// {
|
||||
// SyncVar::Locked sv(syncVar);
|
||||
//
|
||||
// while (sv.get() & SYNC)
|
||||
// sv.wait();
|
||||
// }
|
||||
// }
|
||||
|
||||
long MediaWorker::sourceUpdate() {
|
||||
class VidBuf {
|
||||
Callback *cb;
|
||||
@ -311,7 +260,6 @@ long MediaWorker::sourceUpdate() {
|
||||
const PixelBuffer& get() const { return pb; }
|
||||
} vidbuf(callback.get());
|
||||
|
||||
// turbo += turbo << 4;
|
||||
updateJoysticks();
|
||||
return sampleBuffer.update(vidbuf.get());
|
||||
}
|
||||
@ -342,15 +290,6 @@ static usec_t frameWait(const usec_t base, const usec_t syncft, SyncVar &waiting
|
||||
}
|
||||
|
||||
static void blitWait(MediaWorker::Callback *const cb, SyncVar &waitingForSync) {
|
||||
// unsigned notAcked;
|
||||
//
|
||||
// {
|
||||
// SyncVar::Locked sv(syncVar);
|
||||
//
|
||||
// if ((notAcked = sv.get() & PREPARE))
|
||||
// sv.set(0);
|
||||
// }
|
||||
|
||||
if (!cb->cancelBlit()) {
|
||||
SyncVar::Locked wfs(waitingForSync);
|
||||
|
||||
@ -370,10 +309,30 @@ static bool audioBufIsLow(const AudioEngine::BufferState &bstate, const int outs
|
||||
|
||||
void MediaWorker::run() {
|
||||
#ifdef Q_WS_WIN
|
||||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
const class CoInit : Uncopyable {
|
||||
public:
|
||||
CoInit() { CoInitializeEx(NULL, COINIT_MULTITHREADED); }
|
||||
~CoInit() { CoUninitialize(); }
|
||||
} coinit;
|
||||
#endif
|
||||
if (ae)
|
||||
initAudioEngine();
|
||||
|
||||
const class AeInit : Uncopyable {
|
||||
MediaWorker &w_;
|
||||
public:
|
||||
explicit AeInit(MediaWorker &w) : w_(w) {
|
||||
if (w.ae)
|
||||
w.initAudioEngine();
|
||||
}
|
||||
|
||||
~AeInit() {
|
||||
if (w_.ae)
|
||||
w_.ae->uninit();
|
||||
}
|
||||
} aeinit(*this);
|
||||
|
||||
SkipSched skipSched;
|
||||
bool audioBufLow = false;
|
||||
usec_t base = 0;
|
||||
|
||||
for (;;) {
|
||||
pauseVar.waitWhilePaused(callback.get(), ae);
|
||||
@ -387,15 +346,18 @@ void MediaWorker::run() {
|
||||
sampleBuffer.read(blitSamples >= 0 ? blitSamples : sampleBuffer.samplesBuffered(), 0);
|
||||
} else {
|
||||
const long syncft = blitSamples >= 0 ? adaptToRateEstimation(AtomicVar<long>::ConstLocked(frameTimeEst).get()) : 0;
|
||||
const bool blit = blitSamples >= 0 && !skipSched.skipNext(audioBufLow);
|
||||
const bool blit = blitSamples >= 0 && !skipSched.skipNext(audioBufLow);
|
||||
|
||||
if (blit)
|
||||
callback->blit(base, syncft);
|
||||
|
||||
{
|
||||
const long outsamples = sampleBuffer.read(blit ? blitSamples : sampleBuffer.samplesBuffered(),
|
||||
static_cast<qint16*>(sndOutBuffer));
|
||||
AudioEngine::BufferState bstate = { AudioEngine::BufferState::NOT_SUPPORTED, AudioEngine::BufferState::NOT_SUPPORTED };
|
||||
const long outsamples = sampleBuffer.read(
|
||||
blit ? blitSamples : sampleBuffer.samplesBuffered(),
|
||||
static_cast<qint16*>(sndOutBuffer));
|
||||
|
||||
AudioEngine::BufferState bstate = { AudioEngine::BufferState::NOT_SUPPORTED,
|
||||
AudioEngine::BufferState::NOT_SUPPORTED };
|
||||
|
||||
if (ae->rate() > 0 && ae->write(sndOutBuffer, outsamples, bstate, estsrate) < 0) {
|
||||
ae->pause();
|
||||
@ -412,120 +374,22 @@ void MediaWorker::run() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ae->uninit();
|
||||
|
||||
#ifdef Q_WS_WIN
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MediaWorker::frameStep() {
|
||||
const long blitSamples = sourceUpdate();
|
||||
const long outsamples = sampleBuffer.read(
|
||||
blitSamples >= 0 ? blitSamples : sampleBuffer.samplesBuffered(),
|
||||
static_cast<qint16*>(sndOutBuffer));
|
||||
|
||||
{
|
||||
const long outsamples = sampleBuffer.read(blitSamples >= 0 ? blitSamples : sampleBuffer.samplesBuffered(),
|
||||
static_cast<qint16*>(sndOutBuffer));
|
||||
|
||||
if (ae->rate() > 0) {
|
||||
if (ae->write(sndOutBuffer, outsamples) < 0) {
|
||||
ae->pause();
|
||||
pauseVar.pause(8);
|
||||
callback->audioEngineFailure();
|
||||
} else
|
||||
ae->pause();
|
||||
}
|
||||
if (ae->rate() > 0) {
|
||||
if (ae->write(sndOutBuffer, outsamples) < 0) {
|
||||
ae->pause();
|
||||
pauseVar.pause(8);
|
||||
callback->audioEngineFailure();
|
||||
} else
|
||||
ae->pause();
|
||||
}
|
||||
|
||||
return blitSamples >= 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
// returns syncft
|
||||
long MediaWorker::adaptToRateEstimation(const long estft) {
|
||||
if (estft) {
|
||||
meanQueue.push(static_cast<long>(static_cast<float>(estsrate) * estft / (usecft - (usecft >> 11)) + 0.5f));
|
||||
|
||||
const long mean = meanQueue.mean();
|
||||
const long var = std::max(meanQueue.var(), 1);
|
||||
|
||||
if (sampleBuffer.resamplerOutRate() < mean || sampleBuffer.resamplerOutRate() > mean + var * 2)
|
||||
adjustResamplerRate(mean + var);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sampleBuffer.resamplerOutRate() != ae->rate())
|
||||
adjustResamplerRate(ae->rate());
|
||||
|
||||
return calculateSyncft(ae->rate(), estsrate, usecft);
|
||||
}
|
||||
|
||||
void MediaWorker::syncedUpdate(BlitterWidget *const blitter) {
|
||||
CallQ::Locked(callq)->pop_all();
|
||||
|
||||
if (!ae || ae->rate() < 0) { // avoid stupid recursive call detection by checking here rather than on init.
|
||||
emit soundEngineFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
long outsamples = 0;
|
||||
pauseVar.unwait();
|
||||
const bool blit = sourceUpdate(&outsamples);
|
||||
pauseVar.rewait();
|
||||
const long syncft = blit ? adaptToRateEstimation(blitter->frameTimeEst()) : 0;
|
||||
|
||||
if (blit)
|
||||
blitter->prepare();
|
||||
|
||||
if (!(turbo & 0x30) && ae->write(sndOutBuffer, outsamples, bstate, estsrate) < 0) {
|
||||
ae->pause();
|
||||
emit soundEngineFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
if (blit) {
|
||||
frameWaiter.syncedFrameWait(syncft);
|
||||
|
||||
if (blitter->sync() < 0) {
|
||||
emit videoEngineFailure();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::timerEvent(QTimerEvent*) {
|
||||
worker->syncedUpdate(blitter);
|
||||
workerPaused(this);
|
||||
}
|
||||
|
||||
// NOTE: callInGuiThread
|
||||
void MainWindow::setThreaded(const bool threaded) {
|
||||
if (threaded ^ this->threaded) {
|
||||
this->threaded = threaded;
|
||||
|
||||
if (running) {
|
||||
if (threaded) {
|
||||
if (timerId)
|
||||
killTimer(timerId);
|
||||
|
||||
timerId = 0;
|
||||
worker->reactivate();
|
||||
} else {
|
||||
struct StartTimer {
|
||||
void operator()(MainWindow *const mw) {
|
||||
if (mw->running && mw->threaded)
|
||||
mw->timerId = mw->startTimer(0);
|
||||
}
|
||||
};
|
||||
|
||||
worker->deactivate();
|
||||
callWhenPaused(StartTimer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "audioengine.h"
|
||||
#include "uncopyable.h"
|
||||
#include "usec.h"
|
||||
#include "skipsched.h"
|
||||
|
||||
// enum { PREPARE = 1, SYNC = 2 };
|
||||
|
||||
@ -43,7 +42,7 @@ public:
|
||||
SyncVar &sv;
|
||||
|
||||
public:
|
||||
explicit Locked(SyncVar &sv) : sv(sv) { sv.mut.lock(); }
|
||||
Locked(SyncVar &sv) : sv(sv) { sv.mut.lock(); }
|
||||
~Locked() { sv.mut.unlock(); }
|
||||
unsigned get() const { return sv.var; }
|
||||
void set(const unsigned var) { sv.var = var; sv.cond.wakeAll(); }
|
||||
@ -95,7 +94,7 @@ public:
|
||||
class Locked : Uncopyable {
|
||||
Mutual &lc;
|
||||
public:
|
||||
explicit Locked(Mutual &lc) : lc(lc) { lc.mut.lock(); }
|
||||
Locked(Mutual &lc) : lc(lc) { lc.mut.lock(); }
|
||||
~Locked() { lc.mut.unlock(); }
|
||||
T* operator->() { return &lc.t; }
|
||||
const T* operator->() const { return &lc.t; }
|
||||
@ -106,7 +105,7 @@ public:
|
||||
class ConstLocked : Uncopyable {
|
||||
const Mutual &lc;
|
||||
public:
|
||||
explicit ConstLocked(const Mutual &lc) : lc(lc) { lc.mut.lock(); }
|
||||
ConstLocked(const Mutual &lc) : lc(lc) { lc.mut.lock(); }
|
||||
~ConstLocked() { lc.mut.unlock(); }
|
||||
const T* operator->() const { return &lc.t; }
|
||||
const T& get() const { return lc.t; }
|
||||
@ -124,7 +123,7 @@ public:
|
||||
class Locked : Uncopyable {
|
||||
AtomicVar &av;
|
||||
public:
|
||||
explicit Locked(AtomicVar &av) : av(av) { av.mut.lock(); }
|
||||
Locked(AtomicVar &av) : av(av) { av.mut.lock(); }
|
||||
~Locked() { av.mut.unlock(); }
|
||||
T get() const { return av.var; }
|
||||
void set(const T v) { av.var = v; }
|
||||
@ -133,7 +132,7 @@ public:
|
||||
class ConstLocked : Uncopyable {
|
||||
const AtomicVar &av;
|
||||
public:
|
||||
explicit ConstLocked(const AtomicVar &av) : av(av) { av.mut.lock(); }
|
||||
ConstLocked(const AtomicVar &av) : av(av) { av.mut.lock(); }
|
||||
~ConstLocked() { av.mut.unlock(); }
|
||||
T get() const { return av.var; }
|
||||
};
|
||||
@ -155,16 +154,6 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
/*class FrameWaiter {
|
||||
AdaptiveSleep asleep;
|
||||
usec_t base;
|
||||
|
||||
public:
|
||||
FrameWaiter() : base(0) {}
|
||||
void frameWait(long syncft, SyncVar &waitingForSync);
|
||||
void syncedFrameWait(long syncft);
|
||||
};*/
|
||||
|
||||
class PauseVar {
|
||||
CallQueue<> callq;
|
||||
mutable QMutex mut;
|
||||
@ -231,28 +220,20 @@ private:
|
||||
struct SetSamplesPerFrame;
|
||||
struct SetFastForward;
|
||||
|
||||
std::auto_ptr<Callback> callback;
|
||||
// SyncVar syncVar_;
|
||||
const std::auto_ptr<Callback> callback;
|
||||
SyncVar waitingForSync_;
|
||||
// FrameWaiter frameWaiter;
|
||||
MeanQueue meanQueue;
|
||||
PauseVar pauseVar;
|
||||
AtomicVar<long> frameTimeEst;
|
||||
AtomicVar<bool> doneVar;
|
||||
SkipSched skipSched;
|
||||
TurboSkip turboSkip;
|
||||
SampleBuffer sampleBuffer;
|
||||
Array<qint16> sndOutBuffer;
|
||||
AudioEngine *ae;
|
||||
long usecft;
|
||||
long estsrate;
|
||||
usec_t base;
|
||||
// unsigned turbo;
|
||||
unsigned aelatency;
|
||||
int aerate;
|
||||
// QMutex pbmut;
|
||||
// PixelBuffer pxbuf;
|
||||
bool audioBufLow;
|
||||
|
||||
long adaptToRateEstimation(long estft);
|
||||
void adjustResamplerRate(long outRate);
|
||||
@ -263,11 +244,9 @@ protected:
|
||||
void run();
|
||||
|
||||
public:
|
||||
MediaWorker(MediaSource *source, std::auto_ptr<Callback> callback, QObject *parent = NULL);
|
||||
MediaWorker(MediaSource *source, std::auto_ptr<Callback> callback, QObject *parent = 0);
|
||||
MediaSource* source() /*const */{ return sampleBuffer.source(); }
|
||||
// SyncVar& syncVar() /*const */{ return syncVar_; }
|
||||
SyncVar& waitingForSync() /*const */{ return waitingForSync_; }
|
||||
// void syncedUpdate(BlitterWidget *blitter);
|
||||
void start();
|
||||
void stop();
|
||||
void pause();
|
||||
@ -294,11 +273,6 @@ public:
|
||||
|
||||
void updateJoysticks();
|
||||
|
||||
// void lockVideoBuffer() { pbmut.lock(); }
|
||||
// void unlockVideoBuffer() { pbmut.unlock(); }
|
||||
// void setVideoBuffer(const PixelBuffer &pb) { pxbuf = pb; }
|
||||
// const PixelBuffer& videoBuffer() const { return pxbuf; }
|
||||
|
||||
template<class T> void pushCall(const T &t) { pauseVar.pushCall(t, AtomicVar<bool>::ConstLocked(doneVar).get()); }
|
||||
};
|
||||
|
||||
|
41
gambatte_qt/src/framework/src/persistcheckbox.cpp
Normal file
41
gambatte_qt/src/framework/src/persistcheckbox.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2011 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include "../persistcheckbox.h"
|
||||
#include <QCheckBox>
|
||||
#include <QSettings>
|
||||
|
||||
PersistCheckBox::PersistCheckBox(QCheckBox *const checkBox, const QString &key, const bool defaultValue)
|
||||
: checkBox_(checkBox), key_(key), value_(defaultValue)
|
||||
{
|
||||
value_ = QSettings().value(key, defaultValue).toBool();
|
||||
reject();
|
||||
}
|
||||
|
||||
PersistCheckBox::~PersistCheckBox() {
|
||||
QSettings settings;
|
||||
settings.setValue(key_, value_);
|
||||
}
|
||||
|
||||
void PersistCheckBox::accept() {
|
||||
value_ = checkBox_->isChecked();
|
||||
}
|
||||
|
||||
void PersistCheckBox::reject() const {
|
||||
checkBox_->setChecked(value_);
|
||||
}
|
@ -42,7 +42,7 @@ class SampleBuffer {
|
||||
void reset();
|
||||
|
||||
public:
|
||||
SampleBuffer(MediaSource *source) : source_(source), spf_(0), ft_(1, 0), outsrate(0), resamplerNo_(1) { reset(); }
|
||||
explicit SampleBuffer(MediaSource *source) : source_(source), spf_(0), ft_(1, 0), outsrate(0), resamplerNo_(1) { reset(); }
|
||||
long update(const PixelBuffer &pb);
|
||||
long read(long insamples, qint16 *out);
|
||||
long samplesBuffered() const { return samplesBuffered_; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -29,6 +29,7 @@
|
||||
#include <QGroupBox>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <functional>
|
||||
|
||||
static int filterValue(const int value, const int upper, const int lower = 0, const int fallback = 0) {
|
||||
if (value >= upper || value < lower)
|
||||
@ -37,385 +38,505 @@ static int filterValue(const int value, const int upper, const int lower = 0, co
|
||||
return value;
|
||||
}
|
||||
|
||||
VideoDialog::PersistInt::PersistInt(const QString &key, const int upper, const int lower, const int defaultVal)
|
||||
: key_(key), i_(filterValue(QSettings().value(key, defaultVal).toInt(), upper, lower, defaultVal))
|
||||
{
|
||||
}
|
||||
|
||||
VideoDialog::PersistInt::~PersistInt() {
|
||||
QSettings settings;
|
||||
settings.setValue(key_, i_);
|
||||
}
|
||||
|
||||
VideoDialog::EngineSelector::EngineSelector(const MainWindow *const mw)
|
||||
: comboBox_(new QComboBox), index_("video/engineIndex", mw->numBlitters())
|
||||
{
|
||||
for (std::size_t i = 0; i < mw->numBlitters(); ++i)
|
||||
comboBox_->addItem(mw->blitterConf(i).nameString());
|
||||
|
||||
restore();
|
||||
}
|
||||
|
||||
void VideoDialog::EngineSelector::addToLayout(QBoxLayout *const topLayout) {
|
||||
QHBoxLayout *const hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(new QLabel(tr("Video engine:")));
|
||||
hLayout->addWidget(comboBox_);
|
||||
topLayout->addLayout(hLayout);
|
||||
}
|
||||
|
||||
void VideoDialog::EngineSelector::store() {
|
||||
index_ = comboBox_->currentIndex();
|
||||
}
|
||||
|
||||
void VideoDialog::EngineSelector::restore() {
|
||||
comboBox_->setCurrentIndex(index_);
|
||||
}
|
||||
|
||||
VideoDialog::ScalingMethodSelector::ScalingMethodSelector()
|
||||
: unrestrictedScalingButton_(new QRadioButton(QString("None"))),
|
||||
keepRatioButton_(new QRadioButton(QString("Keep aspect ratio"))),
|
||||
integerScalingButton_(new QRadioButton(QString("Only scale by integer factors"))),
|
||||
scaling_("video/scalingType", NUM_SCALING_METHODS, 0, KEEP_RATIO)
|
||||
{
|
||||
restore();
|
||||
}
|
||||
|
||||
void VideoDialog::ScalingMethodSelector::addToLayout(QLayout *const containingLayout) {
|
||||
QGroupBox *const groupBox = new QGroupBox("Scaling restrictions");
|
||||
groupBox->setLayout(new QVBoxLayout);
|
||||
groupBox->layout()->addWidget(unrestrictedScalingButton_);
|
||||
groupBox->layout()->addWidget(keepRatioButton_);
|
||||
groupBox->layout()->addWidget(integerScalingButton_);
|
||||
containingLayout->addWidget(groupBox);
|
||||
}
|
||||
|
||||
void VideoDialog::ScalingMethodSelector::store() {
|
||||
if (integerScalingButton_->isChecked()) {
|
||||
scaling_ = INTEGER;
|
||||
} else if (keepRatioButton_->isChecked()) {
|
||||
scaling_ = KEEP_RATIO;
|
||||
} else
|
||||
scaling_ = UNRESTRICTED;
|
||||
}
|
||||
|
||||
void VideoDialog::ScalingMethodSelector::restore() {
|
||||
switch (scaling_) {
|
||||
case UNRESTRICTED: unrestrictedScalingButton_->click(); break;
|
||||
case KEEP_RATIO: keepRatioButton_->click(); break;
|
||||
case INTEGER: integerScalingButton_->click(); break;
|
||||
}
|
||||
}
|
||||
|
||||
const QAbstractButton * VideoDialog::ScalingMethodSelector::integerScalingButton() const {
|
||||
return integerScalingButton_;
|
||||
}
|
||||
|
||||
VideoDialog::SourceSelector::SourceSelector(const QString &sourcesLabel, const std::vector<VideoSourceInfo> &sourceInfos)
|
||||
: label_(new QLabel(sourcesLabel)), comboBox_(new QComboBox), index_("video/sourceIndexStore", sourceInfos.size())
|
||||
{
|
||||
setVideoSources(sourceInfos);
|
||||
restore();
|
||||
}
|
||||
|
||||
void VideoDialog::SourceSelector::addToLayout(QBoxLayout *const containingLayout) {
|
||||
QHBoxLayout *const hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(label_);
|
||||
hLayout->addWidget(comboBox_);
|
||||
containingLayout->addLayout(hLayout);
|
||||
}
|
||||
|
||||
void VideoDialog::SourceSelector::store() {
|
||||
index_ = comboBox_->currentIndex();
|
||||
}
|
||||
|
||||
void VideoDialog::SourceSelector::restore() {
|
||||
comboBox_->setCurrentIndex(index_);
|
||||
}
|
||||
|
||||
void VideoDialog::SourceSelector::setVideoSources(const std::vector<VideoSourceInfo> &sourceInfos) {
|
||||
comboBox_->clear();
|
||||
|
||||
for (std::size_t i = 0; i < sourceInfos.size(); ++i)
|
||||
comboBox_->addItem(sourceInfos[i].label, QSize(sourceInfos[i].width, sourceInfos[i].height));
|
||||
|
||||
if (comboBox_->count() < 2) {
|
||||
comboBox_->hide();
|
||||
label_->hide();
|
||||
} else if (comboBox_->parentWidget()) {
|
||||
comboBox_->show();
|
||||
label_->show();
|
||||
}
|
||||
}
|
||||
|
||||
VideoDialog::WinResSelector::WinResSelector(const QSize &aspectRatio, const QSize &sourceSize, const bool integerScaling)
|
||||
: comboBox_(new QComboBox),
|
||||
defaultRes_(QApplication::desktop()->screen()->size()),
|
||||
aspectRatio_(aspectRatio),
|
||||
index_(0)
|
||||
{
|
||||
fillComboBox(sourceSize, integerScaling);
|
||||
|
||||
index_ = filterValue(QSettings().value("video/winIndex", comboBox_->count() - 1).toInt(),
|
||||
comboBox_->count(), 0, comboBox_->count() - 1);
|
||||
restore();
|
||||
}
|
||||
|
||||
VideoDialog::WinResSelector::~WinResSelector() {
|
||||
QSettings settings;
|
||||
settings.setValue("video/winIndex", index_);
|
||||
}
|
||||
|
||||
void VideoDialog::WinResSelector::addToLayout(QBoxLayout *const containingLayout) {
|
||||
QHBoxLayout *const hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(new QLabel(QString(tr("Window size:"))));
|
||||
hLayout->addWidget(comboBox_);
|
||||
containingLayout->addLayout(hLayout);
|
||||
}
|
||||
|
||||
void VideoDialog::WinResSelector::store() {
|
||||
index_ = comboBox_->currentIndex();
|
||||
}
|
||||
|
||||
void VideoDialog::WinResSelector::restore() {
|
||||
comboBox_->setCurrentIndex(index_);
|
||||
}
|
||||
|
||||
void VideoDialog::WinResSelector::setAspectRatio(const QSize &aspectRatio, const QSize &sourceSize, const bool integerScaling) {
|
||||
aspectRatio_ = aspectRatio;
|
||||
setBaseSize(sourceSize, integerScaling);
|
||||
}
|
||||
|
||||
void VideoDialog::WinResSelector::setBaseSize(const QSize &sourceSize, const bool integerScaling) {
|
||||
const QString oldtext(comboBox_->itemText(comboBox_->currentIndex()));
|
||||
|
||||
comboBox_->clear();
|
||||
fillComboBox(sourceSize, integerScaling);
|
||||
|
||||
const int newIndex = comboBox_->findText(oldtext);
|
||||
|
||||
if (newIndex >= 0)
|
||||
comboBox_->setCurrentIndex(newIndex);
|
||||
}
|
||||
|
||||
void VideoDialog::WinResSelector::fillComboBox(const QSize &sourceSize, const bool integerScaling) {
|
||||
const QSize basesz(integerScaling ? sourceSize : aspectRatio_);
|
||||
|
||||
/*if (!integerScaling) {
|
||||
const unsigned scale = std::max(sourceSize.width() / aspectRatio_.width(), sourceSize.height() / aspectRatio_.height());
|
||||
|
||||
basesz = QSize(aspectRatio_.width() * scale, aspectRatio_.height() * scale);
|
||||
|
||||
if (basesz.width() < sourceSize.width() || basesz.height() < sourceSize.height())
|
||||
basesz += aspectRatio_;
|
||||
}*/
|
||||
|
||||
QSize sz(basesz);
|
||||
|
||||
while (sz.width() <= defaultRes_.width() && sz.height() <= defaultRes_.height()) {
|
||||
if (sz.width() >= sourceSize.width() && sz.height() >= sourceSize.height())
|
||||
comboBox_->addItem(QString::number(sz.width()) + "x" + QString::number(sz.height()), sz);
|
||||
|
||||
sz += basesz;
|
||||
}
|
||||
|
||||
comboBox_->addItem(QString(tr("Variable")), QVariant(QSize(-1, -1)));
|
||||
}
|
||||
|
||||
VideoDialog::FullResSelector::FullResSelector(
|
||||
const QString &key, const int defaultIndex,
|
||||
const QSize &sourceSize, const std::vector<ResInfo> &resVector)
|
||||
: comboBox_(new QComboBox), key_(key), index_(defaultIndex)
|
||||
{
|
||||
fillComboBox(sourceSize, resVector);
|
||||
|
||||
index_ = filterValue(comboBox_->findText(QSettings().value(key).toString()),
|
||||
comboBox_->count(), 0, index_);
|
||||
|
||||
restore();
|
||||
}
|
||||
|
||||
VideoDialog::FullResSelector::~FullResSelector() {
|
||||
QSettings settings;
|
||||
settings.setValue(key_, comboBox_->itemText(index_));
|
||||
}
|
||||
|
||||
QWidget* VideoDialog::FullResSelector::widget() {
|
||||
return comboBox_;
|
||||
}
|
||||
|
||||
void VideoDialog::FullResSelector::store() {
|
||||
index_ = comboBox_->currentIndex();
|
||||
}
|
||||
|
||||
void VideoDialog::FullResSelector::restore() {
|
||||
comboBox_->setCurrentIndex(index_);
|
||||
}
|
||||
|
||||
void VideoDialog::FullResSelector::setSourceSize(const QSize &sourceSize, const std::vector<ResInfo> &resVector) {
|
||||
const QString oldtext(comboBox_->itemText(comboBox_->currentIndex()));
|
||||
|
||||
comboBox_->clear();
|
||||
fillComboBox(sourceSize, resVector);
|
||||
|
||||
const int newIndex = comboBox_->findText(oldtext);
|
||||
|
||||
if (newIndex >= 0)
|
||||
comboBox_->setCurrentIndex(newIndex);
|
||||
}
|
||||
|
||||
void VideoDialog::FullResSelector::fillComboBox(const QSize &sourceSize, const std::vector<ResInfo> &resVector) {
|
||||
long maxArea = 0;
|
||||
std::size_t maxAreaI = 0;
|
||||
|
||||
for (std::size_t i = 0; i < resVector.size(); ++i) {
|
||||
const int hres = resVector[i].w;
|
||||
const int vres = resVector[i].h;
|
||||
|
||||
if (hres >= sourceSize.width() && vres >= sourceSize.height()) {
|
||||
comboBox_->addItem(QString::number(hres) + QString("x") + QString::number(vres), i);
|
||||
} else {
|
||||
const long area = static_cast<long>(std::min(hres, sourceSize.width())) * std::min(vres, sourceSize.height());
|
||||
|
||||
if (area > maxArea) {
|
||||
maxArea = area;
|
||||
maxAreaI = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//add resolution giving maximal area if all resolutions are too small.
|
||||
if (comboBox_->count() < 1 && maxArea)
|
||||
comboBox_->addItem(QString::number(resVector[maxAreaI].w) + "x" + QString::number(resVector[maxAreaI].h), maxAreaI);
|
||||
}
|
||||
|
||||
VideoDialog::FullHzSelector::FullHzSelector(const QString &key, const std::vector<short> &rates, const int defaultIndex)
|
||||
: comboBox_(new QComboBox), key_(key), index_(0)
|
||||
{
|
||||
setRates(rates);
|
||||
|
||||
index_ = filterValue(
|
||||
comboBox_->findText(QSettings().value(key).toString()),
|
||||
comboBox_->count(),
|
||||
0,
|
||||
defaultIndex);
|
||||
|
||||
restore();
|
||||
}
|
||||
|
||||
VideoDialog::FullHzSelector::~FullHzSelector() {
|
||||
QSettings settings;
|
||||
settings.setValue(key_, comboBox_->itemText(index_));
|
||||
}
|
||||
|
||||
QWidget* VideoDialog::FullHzSelector::widget() {
|
||||
return comboBox_;
|
||||
}
|
||||
|
||||
void VideoDialog::FullHzSelector::store() {
|
||||
index_ = comboBox_->currentIndex();
|
||||
}
|
||||
|
||||
void VideoDialog::FullHzSelector::restore() {
|
||||
comboBox_->setCurrentIndex(index_);
|
||||
}
|
||||
|
||||
void VideoDialog::FullHzSelector::setRates(const std::vector<short> &rates) {
|
||||
comboBox_->clear();
|
||||
|
||||
for (std::size_t i = 0; i < rates.size(); ++i)
|
||||
comboBox_->addItem(QString::number(rates[i] / 10.0) + QString(" Hz"), i);
|
||||
}
|
||||
|
||||
const std::vector<VideoDialog::FullResSelector*> VideoDialog::makeFullResSelectors(
|
||||
const QSize &sourceSize, const MainWindow *const mw)
|
||||
{
|
||||
std::vector<FullResSelector*> v(mw->screens(), 0);
|
||||
|
||||
for (std::size_t i = 0; i < v.size(); ++i) {
|
||||
v[i] = new FullResSelector("video/fullRes" + QString::number(i),
|
||||
mw->currentResIndex(i), sourceSize, mw->modeVector(i));
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
const std::vector<VideoDialog::FullHzSelector*> VideoDialog::makeFullHzSelectors(
|
||||
const auto_vector<FullResSelector> &fullResSelectors, const MainWindow *const mw)
|
||||
{
|
||||
std::vector<FullHzSelector*> v(fullResSelectors.size(), 0);
|
||||
|
||||
for (std::size_t i = 0; i < v.size(); ++i) {
|
||||
const int index = fullResSelectors[i]->comboBox()->currentIndex();
|
||||
|
||||
v[i] = new FullHzSelector("video/hz" + QString::number(i),
|
||||
index >= 0 ? mw->modeVector(i)[index].rates : std::vector<short>(),
|
||||
index == static_cast<int>(mw->currentResIndex(i)) ? mw->currentRateIndex(i) : 0);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
VideoDialog::VideoDialog(const MainWindow *const mw,
|
||||
const std::vector<VideoSourceInfo> &sourceInfos,
|
||||
const QString &sourcesLabel,
|
||||
const QSize &aspectRatio,
|
||||
QWidget *parent) :
|
||||
QDialog(parent),
|
||||
mw(mw),
|
||||
topLayout(new QVBoxLayout),
|
||||
engineWidget(NULL),
|
||||
engineSelector(new QComboBox),
|
||||
winResSelector(new QComboBox),
|
||||
unrestrictedScalingButton(new QRadioButton(QString("None"))),
|
||||
keepRatioButton(new QRadioButton(QString("Keep aspect ratio"))),
|
||||
integerScalingButton(new QRadioButton(QString("Only scale by integer factors"))),
|
||||
sourceSelector(new QComboBox),
|
||||
sourceSelectorLabel(new QLabel(sourcesLabel)),
|
||||
scaling(KEEP_RATIO),
|
||||
aspRatio(aspectRatio),
|
||||
defaultRes(QApplication::desktop()->screen()->size()),
|
||||
engineIndex(0),
|
||||
winIndex(0),
|
||||
sourceIndexStore(0)
|
||||
QWidget *parent)
|
||||
: QDialog(parent),
|
||||
mw(mw),
|
||||
topLayout(new QVBoxLayout),
|
||||
engineWidget(0),
|
||||
engineSelector(mw),
|
||||
sourceSelector(sourcesLabel, sourceInfos),
|
||||
winResSelector(aspectRatio,
|
||||
sourceSelector.comboBox()->itemData(sourceSelector.comboBox()->currentIndex()).toSize(),
|
||||
scalingMethodSelector.integerScalingButton()->isChecked()),
|
||||
fullResSelectors(makeFullResSelectors(sourceSelector.comboBox()->itemData(sourceSelector.comboBox()->currentIndex()).toSize(), mw)),
|
||||
fullHzSelectors(makeFullHzSelectors(fullResSelectors, mw))
|
||||
{
|
||||
fullIndex.resize(mw->screens());
|
||||
hzIndex.resize(fullIndex.size());
|
||||
fullResSelector.resize(fullIndex.size());
|
||||
hzSelector.resize(fullIndex.size());
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
setLayout(mainLayout);
|
||||
|
||||
QHBoxLayout *hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(new QLabel(tr("Video engine:")));
|
||||
hLayout->addWidget(engineSelector);
|
||||
topLayout->addLayout(hLayout);
|
||||
engineSelector.addToLayout(topLayout);
|
||||
|
||||
if ((engineWidget = mw->blitterConf(engineSelector.comboBox()->currentIndex()).settingsWidget()))
|
||||
topLayout->addWidget(engineWidget);
|
||||
|
||||
hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(new QLabel(QString(tr("Windowed resolution:"))));
|
||||
hLayout->addWidget(winResSelector);
|
||||
topLayout->addLayout(hLayout);
|
||||
winResSelector.addToLayout(topLayout);
|
||||
|
||||
for (unsigned i = 0; i < hzSelector.size(); ++i) {
|
||||
hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(new QLabel("Full screen mode (screen " + QString::number(i) + "):"));
|
||||
QHBoxLayout *hhLayout = new QHBoxLayout;
|
||||
hhLayout->addWidget((fullResSelector[i] = new QComboBox));
|
||||
hhLayout->addWidget((hzSelector[i] = new QComboBox));
|
||||
for (std::size_t i = 0; i < fullResSelectors.size(); ++i) {
|
||||
QHBoxLayout *const hLayout = new QHBoxLayout;
|
||||
QLabel *const label = new QLabel("Full screen mode (" + mw->screenName(i) + "):");
|
||||
hLayout->addWidget(label);
|
||||
|
||||
QHBoxLayout *const hhLayout = new QHBoxLayout;
|
||||
hhLayout->addWidget(fullResSelectors[i]->widget());
|
||||
hhLayout->addWidget(fullHzSelectors[i]->widget());
|
||||
hLayout->addLayout(hhLayout);
|
||||
topLayout->addLayout(hLayout);
|
||||
|
||||
if (mw->modeVector(i).empty()) {
|
||||
label->hide();
|
||||
fullResSelectors[i]->widget()->hide();
|
||||
fullHzSelectors[i]->widget()->hide();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QGroupBox *f = new QGroupBox("Scaling restrictions");
|
||||
f->setLayout(new QVBoxLayout);
|
||||
f->layout()->addWidget(unrestrictedScalingButton);
|
||||
f->layout()->addWidget(keepRatioButton);
|
||||
f->layout()->addWidget(integerScalingButton);
|
||||
topLayout->addWidget(f);
|
||||
}
|
||||
|
||||
hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(sourceSelectorLabel);
|
||||
hLayout->addWidget(sourceSelector);
|
||||
topLayout->addLayout(hLayout);
|
||||
scalingMethodSelector.addToLayout(topLayout);
|
||||
sourceSelector.addToLayout(topLayout);
|
||||
|
||||
mainLayout->addLayout(topLayout);
|
||||
mainLayout->setAlignment(topLayout, Qt::AlignTop);
|
||||
|
||||
hLayout = new QHBoxLayout;
|
||||
QPushButton *okButton = new QPushButton(tr("OK"));
|
||||
QHBoxLayout *const hLayout = new QHBoxLayout;
|
||||
QPushButton *const okButton = new QPushButton(tr("OK"));
|
||||
hLayout->addWidget(okButton);
|
||||
QPushButton *cancelButton = new QPushButton(tr("Cancel"));
|
||||
QPushButton *const cancelButton = new QPushButton(tr("Cancel"));
|
||||
hLayout->addWidget(cancelButton);
|
||||
mainLayout->addLayout(hLayout);
|
||||
mainLayout->setAlignment(hLayout, Qt::AlignBottom | Qt::AlignRight);
|
||||
okButton->setDefault(true);
|
||||
|
||||
connect(engineSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(engineChange(int)));
|
||||
connect(engineSelector.comboBox(), SIGNAL(currentIndexChanged(int)), this, SLOT(engineChange(int)));
|
||||
|
||||
for (unsigned i = 0; i < fullResSelector.size(); ++i) {
|
||||
connect(fullResSelector[i], SIGNAL(currentIndexChanged(int)), this, SLOT(fullresChange(int)));
|
||||
for (std::size_t i = 0; i < fullResSelectors.size(); ++i) {
|
||||
connect(fullResSelectors[i]->comboBox(), SIGNAL(currentIndexChanged(int)), this, SLOT(fullresChange(int)));
|
||||
}
|
||||
|
||||
connect(integerScalingButton, SIGNAL(toggled(bool)), this, SLOT(integerScalingChange(bool)));
|
||||
connect(sourceSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(sourceChange(int)));
|
||||
connect(scalingMethodSelector.integerScalingButton(), SIGNAL(toggled(bool)), this, SLOT(integerScalingChange(bool)));
|
||||
connect(sourceSelector.comboBox(), SIGNAL(currentIndexChanged(int)), this, SLOT(sourceChange(int)));
|
||||
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
|
||||
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||
|
||||
fillSourceSelector(sourceInfos);
|
||||
|
||||
for (std::size_t i = 0; i < mw->numBlitters(); ++i) {
|
||||
engineSelector->addItem(mw->blitterConf(i).nameString());
|
||||
}
|
||||
|
||||
fillWinResSelector();
|
||||
fillFullResSelector();
|
||||
keepRatioButton->click();
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("video");
|
||||
|
||||
engineIndex = filterValue(settings.value("engineIndex", 0).toInt(), engineSelector->count());
|
||||
sourceIndexStore = filterValue(settings.value("sourceIndexStore", 0).toInt(), sourceSelector->count());
|
||||
|
||||
switch (settings.value("scalingType", KEEP_RATIO).toInt()) {
|
||||
case UNRESTRICTED: scaling = UNRESTRICTED; break;
|
||||
case INTEGER: scaling = INTEGER; break;
|
||||
default: scaling = KEEP_RATIO; break;
|
||||
}
|
||||
|
||||
restore();
|
||||
|
||||
for (unsigned i = 0; i < fullIndex.size(); ++i) {
|
||||
fullIndex[i] = filterValue(fullResSelector[i]->findText(settings.value("fullRes" + QString::number(i)).toString()),
|
||||
fullResSelector[i]->count(),
|
||||
0,
|
||||
mw->currentResIndex(i));
|
||||
}
|
||||
|
||||
winIndex = filterValue(settings.value("winIndex", winResSelector->count() - 1).toInt(), winResSelector->count(), 0, winResSelector->count() - 1);
|
||||
|
||||
restore();
|
||||
|
||||
for (unsigned i = 0; i < hzIndex.size(); ++i) {
|
||||
hzIndex[i] = filterValue(hzSelector[i]->findText(settings.value("hz" + QString::number(i)).toString()),
|
||||
hzSelector[i]->count(),
|
||||
0,
|
||||
mw->currentRateIndex(i));
|
||||
}
|
||||
|
||||
restore();
|
||||
store();
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
setWindowTitle(tr("Video Settings"));
|
||||
}
|
||||
|
||||
VideoDialog::~VideoDialog() {
|
||||
// delete fullResSelectorBackup;
|
||||
void VideoDialog::fillFullResSelectors() {
|
||||
const QSize &sourceSize = sourceSelector.comboBox()->itemData(sourceSelector.comboBox()->currentIndex()).toSize();
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("video");
|
||||
|
||||
for (unsigned i = 0; i < fullIndex.size(); ++i) {
|
||||
settings.setValue("fullRes" + QString::number(i), fullResSelector[i]->itemText(fullIndex[i]));
|
||||
}
|
||||
|
||||
settings.setValue("winIndex", winIndex);
|
||||
|
||||
for (unsigned i = 0; i < hzIndex.size(); ++i) {
|
||||
settings.setValue("hz" + QString::number(i), hzSelector[i]->itemText(hzIndex[i]));
|
||||
}
|
||||
|
||||
settings.setValue("scalingType", (int)scaling);
|
||||
settings.setValue("sourceIndexStore", sourceIndexStore);
|
||||
settings.setValue("engineIndex", engineIndex);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void VideoDialog::fillWinResSelector() {
|
||||
const QString oldtext(winResSelector->itemText(winResSelector->currentIndex()));
|
||||
|
||||
winResSelector->clear();
|
||||
|
||||
const QSize &sourceSize = sourceSelector->itemData(sourceSelector->currentIndex()).toSize();
|
||||
QSize basesz(integerScalingButton->isChecked() ? sourceSize : aspRatio);
|
||||
|
||||
/*if (!integerScalingButton->isChecked()) {
|
||||
const unsigned scale = std::max(sourceSize.width() / aspRatio.width(), sourceSize.height() / aspRatio.height());
|
||||
for (std::size_t i = 0; i < fullResSelectors.size(); ++i) {
|
||||
const int oldResIndex = fullResSelectors[i]->comboBox()->currentIndex();
|
||||
|
||||
basesz = QSize(aspRatio.width() * scale, aspRatio.height() * scale);
|
||||
disconnect(fullResSelectors[i]->comboBox(), SIGNAL(currentIndexChanged(int)), this, SLOT(fullresChange(int)));
|
||||
fullResSelectors[i]->setSourceSize(sourceSize, mw->modeVector(i));
|
||||
connect(fullResSelectors[i]->comboBox(), SIGNAL(currentIndexChanged(int)), this, SLOT(fullresChange(int)));
|
||||
|
||||
if (basesz.width() < sourceSize.width() || basesz.height() < sourceSize.height())
|
||||
basesz += aspRatio;
|
||||
}*/
|
||||
|
||||
QSize sz(basesz);
|
||||
|
||||
while (sz.width() <= defaultRes.width() && sz.height() <= defaultRes.height()) {
|
||||
if (sz.width() >= sourceSize.width() && sz.height() >= sourceSize.height())
|
||||
winResSelector->addItem(QString::number(sz.width()) + "x" + QString::number(sz.height()), sz);
|
||||
const int newResIndex = fullResSelectors[i]->comboBox()->currentIndex();
|
||||
|
||||
sz += basesz;
|
||||
}
|
||||
|
||||
winResSelector->addItem(QString(tr("Variable")), QVariant(QSize(-1, -1)));
|
||||
|
||||
const int newIndex = winResSelector->findText(oldtext);
|
||||
|
||||
if (newIndex >= 0)
|
||||
winResSelector->setCurrentIndex(newIndex);
|
||||
}
|
||||
|
||||
void VideoDialog::fillFullResSelector() {
|
||||
for (unsigned j = 0; j < fullResSelector.size(); ++j) {
|
||||
const QString oldtext(fullResSelector[j]->itemText(fullResSelector[j]->currentIndex()));
|
||||
const int oldHzIndex = hzSelector[j]->currentIndex();
|
||||
|
||||
fullResSelector[j]->clear();
|
||||
|
||||
const QSize &sourceSize = sourceSelector->itemData(sourceSelector->currentIndex()).toSize();
|
||||
|
||||
unsigned maxArea = 0;
|
||||
unsigned maxAreaI = 0;
|
||||
|
||||
const std::vector<ResInfo> &resVector = mw->modeVector(j);
|
||||
|
||||
for (unsigned i = 0; i < resVector.size(); ++i) {
|
||||
const int hres = resVector[i].w;
|
||||
const int vres = resVector[i].h;
|
||||
|
||||
if (hres >= sourceSize.width() && vres >= sourceSize.height()) {
|
||||
fullResSelector[j]->addItem(QString::number(hres) + QString("x") + QString::number(vres), i);
|
||||
} else {
|
||||
const unsigned area = std::min(hres, sourceSize.width()) * std::min(vres, sourceSize.height());
|
||||
|
||||
if (area > maxArea) {
|
||||
maxArea = area;
|
||||
maxAreaI = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//add resolution giving maximal area if all resolutions are too small.
|
||||
if (fullResSelector[j]->count() < 1 && maxArea)
|
||||
fullResSelector[j]->addItem(QString::number(resVector[maxAreaI].w) + "x" + QString::number(resVector[maxAreaI].h), maxAreaI);
|
||||
|
||||
const int newIndex = fullResSelector[j]->findText(oldtext);
|
||||
|
||||
if (newIndex >= 0) {
|
||||
fullResSelector[j]->setCurrentIndex(newIndex);
|
||||
hzSelector[j]->setCurrentIndex(oldHzIndex);
|
||||
}
|
||||
if (newResIndex != oldResIndex)
|
||||
fullHzSelectors[i]->setRates(newResIndex >= 0 ? mw->modeVector(i)[newResIndex].rates : std::vector<short>());
|
||||
}
|
||||
}
|
||||
|
||||
void VideoDialog::store() {
|
||||
// for (std::size_t i = 0; i < mw->numBlitters(); ++i)
|
||||
// mw->blitterConf(i).acceptSettings();
|
||||
|
||||
engineIndex = engineSelector->currentIndex();
|
||||
|
||||
if (unrestrictedScalingButton->isChecked())
|
||||
scaling = UNRESTRICTED;
|
||||
else if (keepRatioButton->isChecked())
|
||||
scaling = KEEP_RATIO;
|
||||
else
|
||||
scaling = INTEGER;
|
||||
|
||||
sourceIndexStore = sourceSelector->currentIndex();
|
||||
winIndex = winResSelector->currentIndex();
|
||||
|
||||
for (unsigned i = 0; i < fullResSelector.size(); ++i) {
|
||||
fullIndex[i] = fullResSelector[i]->currentIndex();
|
||||
hzIndex[i] = hzSelector[i]->currentIndex();
|
||||
}
|
||||
|
||||
engineSelector.store();
|
||||
scalingMethodSelector.store();
|
||||
sourceSelector.store();
|
||||
winResSelector.store();
|
||||
std::for_each(fullResSelectors.begin(), fullResSelectors.end(), std::mem_fun(&FullResSelector::store));
|
||||
std::for_each(fullHzSelectors.begin(), fullHzSelectors.end(), std::mem_fun(&FullHzSelector::store));
|
||||
}
|
||||
|
||||
void VideoDialog::restore() {
|
||||
for (std::size_t i = 0; i < mw->numBlitters(); ++i)
|
||||
mw->blitterConf(i).rejectSettings();
|
||||
|
||||
engineSelector->setCurrentIndex(engineIndex);
|
||||
|
||||
switch (scaling) {
|
||||
case UNRESTRICTED: unrestrictedScalingButton->click(); break;
|
||||
case KEEP_RATIO: keepRatioButton->click(); break;
|
||||
case INTEGER: integerScalingButton->click(); break;
|
||||
}
|
||||
|
||||
sourceSelector->setCurrentIndex(sourceIndexStore);
|
||||
winResSelector->setCurrentIndex(winIndex);
|
||||
|
||||
for (unsigned i = 0; i < fullResSelector.size(); ++i) {
|
||||
fullResSelector[i]->setCurrentIndex(fullIndex[i]);
|
||||
hzSelector[i]->setCurrentIndex(hzIndex[i]);
|
||||
}
|
||||
engineSelector.restore();
|
||||
scalingMethodSelector.restore();
|
||||
sourceSelector.restore();
|
||||
winResSelector.restore();
|
||||
std::for_each(fullResSelectors.begin(), fullResSelectors.end(), std::mem_fun(&FullResSelector::restore));
|
||||
std::for_each(fullHzSelectors.begin(), fullHzSelectors.end(), std::mem_fun(&FullHzSelector::restore));
|
||||
}
|
||||
|
||||
void VideoDialog::engineChange(int index) {
|
||||
if (engineWidget) {
|
||||
topLayout->removeWidget(engineWidget);
|
||||
engineWidget->setParent(NULL);
|
||||
engineWidget->setParent(0);
|
||||
}
|
||||
|
||||
engineWidget = mw->blitterConf(index).settingsWidget();
|
||||
|
||||
if (engineWidget)
|
||||
if ((engineWidget = mw->blitterConf(index).settingsWidget()))
|
||||
topLayout->insertWidget(1, engineWidget);
|
||||
|
||||
/*if (mw->blitterConf(index)->integerOnlyScaler) {
|
||||
integerScalingButton->click();
|
||||
keepRatioButton->setEnabled(false);
|
||||
integerScalingButton->setEnabled(false);
|
||||
unrestrictedScalingButton->setEnabled(false);
|
||||
} else */{
|
||||
keepRatioButton->setEnabled(true);
|
||||
integerScalingButton->setEnabled(true);
|
||||
unrestrictedScalingButton->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoDialog::fullresChange(int index) {
|
||||
for (unsigned i = 0; i < fullResSelector.size(); ++i) {
|
||||
if (sender() == fullResSelector[i]) {
|
||||
hzSelector[i]->clear();
|
||||
|
||||
if (index >= 0) {
|
||||
const std::vector<short> &v = mw->modeVector(i)[index].rates;
|
||||
|
||||
for (unsigned int j = 0; j < v.size(); ++j)
|
||||
hzSelector[i]->addItem(QString::number(v[j]) + QString(" Hz"), j);
|
||||
}
|
||||
void VideoDialog::fullresChange(const int index) {
|
||||
for (std::size_t i = 0; i < fullResSelectors.size(); ++i) {
|
||||
if (sender() == fullResSelectors[i]->comboBox()) {
|
||||
fullHzSelectors[i]->setRates(index >= 0 ? mw->modeVector(i)[index].rates : std::vector<short>());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VideoDialog::sourceChange(int /*index*/) {
|
||||
fillWinResSelector();
|
||||
fillFullResSelector();
|
||||
winResSelector.setBaseSize(
|
||||
sourceSelector.comboBox()->itemData(sourceSelector.comboBox()->currentIndex()).toSize(),
|
||||
scalingMethodSelector.integerScalingButton()->isChecked());
|
||||
fillFullResSelectors();
|
||||
}
|
||||
|
||||
void VideoDialog::integerScalingChange(bool /*checked*/) {
|
||||
sourceChange(sourceSelector->currentIndex());
|
||||
void VideoDialog::integerScalingChange(const bool checked) {
|
||||
winResSelector.setBaseSize(
|
||||
sourceSelector.comboBox()->itemData(sourceSelector.comboBox()->currentIndex()).toSize(), checked);
|
||||
}
|
||||
|
||||
int VideoDialog::blitterNo() const {
|
||||
return engineIndex;
|
||||
return engineSelector.index();
|
||||
}
|
||||
|
||||
const QSize VideoDialog::windowSize() const {
|
||||
return winResSelector->itemData(winIndex).toSize();
|
||||
return winResSelector.comboBox()->itemData(winResSelector.index()).toSize();
|
||||
}
|
||||
|
||||
unsigned VideoDialog::fullResIndex(unsigned screen) const {
|
||||
//return fullResSelector->currentIndex();
|
||||
// return fullResSelectorBackup->findText(fullResSelector->itemText(fullResSelector->currentIndex()));
|
||||
return fullResSelector[screen]->itemData(fullIndex[screen]).toUInt();
|
||||
return fullResSelectors[screen]->comboBox()->itemData(fullResSelectors[screen]->index()).toUInt();
|
||||
}
|
||||
|
||||
unsigned VideoDialog::fullRateIndex(unsigned screen) const {
|
||||
return hzSelector[screen]->itemData(hzIndex[screen]).toUInt();
|
||||
return fullHzSelectors[screen]->comboBox()->itemData(fullHzSelectors[screen]->index()).toUInt();
|
||||
}
|
||||
|
||||
const QSize VideoDialog::sourceSize() const {
|
||||
return sourceSelector->itemData(sourceIndex()).toSize();
|
||||
return sourceSelector.comboBox()->itemData(sourceIndex()).toSize();
|
||||
}
|
||||
|
||||
void VideoDialog::setAspectRatio(const QSize &aspectRatio) {
|
||||
restore();
|
||||
aspRatio = aspectRatio;
|
||||
fillWinResSelector();
|
||||
winResSelector.setAspectRatio(aspectRatio,
|
||||
sourceSelector.comboBox()->itemData(sourceSelector.comboBox()->currentIndex()).toSize(),
|
||||
scalingMethodSelector.integerScalingButton()->isChecked());
|
||||
store();
|
||||
emit accepted();
|
||||
}
|
||||
|
||||
void VideoDialog::fillSourceSelector(const std::vector<VideoSourceInfo> &sourceInfos) {
|
||||
for (std::size_t i = 0; i < sourceInfos.size(); ++i)
|
||||
sourceSelector->addItem(sourceInfos[i].label, QSize(sourceInfos[i].width, sourceInfos[i].height));
|
||||
|
||||
if (sourceSelector->count() < 2) {
|
||||
sourceSelector->hide();
|
||||
sourceSelectorLabel->hide();
|
||||
} else {
|
||||
sourceSelector->show();
|
||||
sourceSelectorLabel->show();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoDialog::setVideoSources(const std::vector<VideoSourceInfo> &sourceInfos) {
|
||||
restore();
|
||||
disconnect(sourceSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(sourceChange(int)));
|
||||
sourceSelector->clear();
|
||||
|
||||
fillSourceSelector(sourceInfos);
|
||||
|
||||
connect(sourceSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(sourceChange(int)));
|
||||
sourceChange(sourceSelector->currentIndex());
|
||||
disconnect(sourceSelector.comboBox(), SIGNAL(currentIndexChanged(int)), this, SLOT(sourceChange(int)));
|
||||
sourceSelector.setVideoSources(sourceInfos);
|
||||
connect(sourceSelector.comboBox(), SIGNAL(currentIndexChanged(int)), this, SLOT(sourceChange(int)));
|
||||
sourceChange(sourceSelector.comboBox()->currentIndex());
|
||||
store();
|
||||
emit accepted();
|
||||
}
|
||||
@ -434,9 +555,10 @@ void applySettings(MainWindow *const mw, const VideoDialog *const vd) {
|
||||
{
|
||||
const BlitterConf curBlitter = mw->currentBlitterConf();
|
||||
|
||||
for (std::size_t i = 0; i < mw->numBlitters(); ++i)
|
||||
for (std::size_t i = 0; i < mw->numBlitters(); ++i) {
|
||||
if (mw->blitterConf(i) != curBlitter)
|
||||
mw->blitterConf(i).acceptSettings();
|
||||
}
|
||||
|
||||
const QSize &srcSz = vd->sourceSize();
|
||||
mw->setVideoFormatAndBlitter(srcSz.width(), srcSz.height(), vd->blitterNo());
|
||||
@ -447,6 +569,6 @@ void applySettings(MainWindow *const mw, const VideoDialog *const vd) {
|
||||
mw->setScalingMethod(vd->scalingMethod());
|
||||
mw->setWindowSize(vd->windowSize());
|
||||
|
||||
for (unsigned i = 0; i < mw->screens(); ++i)
|
||||
for (std::size_t i = 0; i < mw->screens(); ++i)
|
||||
mw->setFullScreenMode(i, vd->fullResIndex(i), vd->fullRateIndex(i));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -27,10 +27,11 @@
|
||||
class QVBoxLayout;
|
||||
class QHBoxLayout;
|
||||
class QComboBox;
|
||||
class QAbstractButton;
|
||||
class QRadioButton;
|
||||
class QLabel;
|
||||
class QBoxLayout;
|
||||
|
||||
// #include "resinfo.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
/** A utility class that can optionally be used to provide a GUI for
|
||||
@ -49,31 +50,128 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
class PersistInt {
|
||||
const QString key_;
|
||||
int i_;
|
||||
public:
|
||||
PersistInt(const QString &key, int upper, int lower = 0, int defaultVal = 0);
|
||||
~PersistInt();
|
||||
PersistInt & operator=(int i) { i_ = i; return *this; }
|
||||
operator int() const { return i_; }
|
||||
};
|
||||
|
||||
class EngineSelector {
|
||||
QComboBox *const comboBox_;
|
||||
PersistInt index_;
|
||||
|
||||
public:
|
||||
explicit EngineSelector(const MainWindow *mw);
|
||||
void addToLayout(QBoxLayout *topLayout);
|
||||
const QComboBox * comboBox() const { return comboBox_; }
|
||||
void store();
|
||||
void restore();
|
||||
int index() const { return index_; }
|
||||
};
|
||||
|
||||
class ScalingMethodSelector {
|
||||
QRadioButton *const unrestrictedScalingButton_;
|
||||
QRadioButton *const keepRatioButton_;
|
||||
QRadioButton *const integerScalingButton_;
|
||||
PersistInt scaling_;
|
||||
|
||||
public:
|
||||
ScalingMethodSelector();
|
||||
void addToLayout(QLayout *layout);
|
||||
const QAbstractButton * integerScalingButton() const;
|
||||
void store();
|
||||
void restore();
|
||||
ScalingMethod scalingMethod() const { return static_cast<ScalingMethod>(static_cast<int>(scaling_)); }
|
||||
};
|
||||
|
||||
class SourceSelector {
|
||||
QLabel *const label_;
|
||||
QComboBox *const comboBox_;
|
||||
PersistInt index_;
|
||||
|
||||
public:
|
||||
SourceSelector(const QString &sourcesLabel, const std::vector<VideoSourceInfo> &sourceInfos);
|
||||
void addToLayout(QBoxLayout *layout);
|
||||
const QComboBox * comboBox() const { return comboBox_; }
|
||||
void setVideoSources(const std::vector<VideoSourceInfo> &sourceInfos);
|
||||
void store();
|
||||
void restore();
|
||||
int index() const { return index_; }
|
||||
};
|
||||
|
||||
class WinResSelector {
|
||||
QComboBox *const comboBox_;
|
||||
const QSize defaultRes_;
|
||||
QSize aspectRatio_;
|
||||
int index_;
|
||||
|
||||
void fillComboBox(const QSize &sourceSize, bool integerScaling);
|
||||
public:
|
||||
WinResSelector(const QSize &aspectRatio, const QSize &sourceSize, bool integerScaling);
|
||||
~WinResSelector();
|
||||
void addToLayout(QBoxLayout *layout);
|
||||
const QComboBox * comboBox() const { return comboBox_; }
|
||||
void store();
|
||||
void restore();
|
||||
void setAspectRatio(const QSize &aspectRatio, const QSize &sourceSize, bool integerScaling);
|
||||
void setBaseSize(const QSize &sourceSize, bool integerScaling);
|
||||
const QSize & aspectRatio() const { return aspectRatio_; }
|
||||
int index() const { return index_; }
|
||||
};
|
||||
|
||||
class FullResSelector {
|
||||
QComboBox *const comboBox_;
|
||||
const QString key_;
|
||||
int index_;
|
||||
|
||||
void fillComboBox(const QSize &sourceSize, const std::vector<ResInfo> &resVector);
|
||||
public:
|
||||
FullResSelector(const QString &key, int defaultIndex,
|
||||
const QSize &sourceSize, const std::vector<ResInfo> &resVector);
|
||||
~FullResSelector();
|
||||
QWidget * widget();
|
||||
const QComboBox * comboBox() const { return comboBox_; }
|
||||
void store();
|
||||
void restore();
|
||||
void setSourceSize(const QSize &sourceSize, const std::vector<ResInfo> &resVector);
|
||||
int index() const { return index_; }
|
||||
};
|
||||
|
||||
class FullHzSelector {
|
||||
QComboBox *const comboBox_;
|
||||
const QString key_;
|
||||
int index_;
|
||||
|
||||
public:
|
||||
FullHzSelector(const QString &key, const std::vector<short> &rates, int defaultIndex);
|
||||
~FullHzSelector();
|
||||
QWidget * widget();
|
||||
const QComboBox * comboBox() const { return comboBox_; }
|
||||
void store();
|
||||
void restore();
|
||||
void setRates(const std::vector<short> &rates);
|
||||
int index() const { return index_; }
|
||||
};
|
||||
|
||||
const MainWindow *const mw;
|
||||
QVBoxLayout *const topLayout;
|
||||
QWidget *engineWidget;
|
||||
QComboBox *const engineSelector;
|
||||
QComboBox *const winResSelector;
|
||||
// const std::auto_ptr<QComboBox> winResSelectorBackup;
|
||||
std::vector<QComboBox*> fullResSelector;
|
||||
std::vector<QComboBox*> hzSelector;
|
||||
QRadioButton *const unrestrictedScalingButton;
|
||||
QRadioButton *const keepRatioButton;
|
||||
QRadioButton *const integerScalingButton;
|
||||
QComboBox *const sourceSelector;
|
||||
QLabel *const sourceSelectorLabel;
|
||||
ScalingMethod scaling;
|
||||
QSize aspRatio;
|
||||
const QSize defaultRes;
|
||||
std::vector<int> fullIndex;
|
||||
std::vector<int> hzIndex;
|
||||
int engineIndex;
|
||||
int winIndex;
|
||||
int sourceIndexStore;
|
||||
EngineSelector engineSelector;
|
||||
ScalingMethodSelector scalingMethodSelector;
|
||||
SourceSelector sourceSelector;
|
||||
WinResSelector winResSelector;
|
||||
const auto_vector<FullResSelector> fullResSelectors;
|
||||
const auto_vector<FullHzSelector> fullHzSelectors;
|
||||
|
||||
static const std::vector<FullResSelector*> makeFullResSelectors(const QSize &sourceSize, const MainWindow *mw);
|
||||
static const std::vector<FullHzSelector*> makeFullHzSelectors(
|
||||
const auto_vector<FullResSelector> &fullResSelectors, const MainWindow *mw);
|
||||
void fillWinResSelector();
|
||||
void fillFullResSelector();
|
||||
void fillSourceSelector(const std::vector<VideoSourceInfo> &sourceInfos);
|
||||
void fillFullResSelectors();
|
||||
void store();
|
||||
void restore();
|
||||
|
||||
@ -89,17 +187,16 @@ public:
|
||||
const QString &sourcesLabel,
|
||||
const QSize &aspectRatio,
|
||||
QWidget *parent = 0);
|
||||
~VideoDialog();
|
||||
int blitterNo() const;
|
||||
const QSize windowSize() const;
|
||||
unsigned fullResIndex(unsigned screen) const;
|
||||
unsigned fullRateIndex(unsigned screen) const;
|
||||
unsigned sourceIndex() const { return sourceIndexStore; }
|
||||
unsigned sourceIndex() const { return sourceSelector.index(); }
|
||||
const QSize sourceSize() const;
|
||||
void setVideoSources(const std::vector<VideoSourceInfo> &sourceInfos);
|
||||
void setSourceSize(const QSize &sourceSize);
|
||||
ScalingMethod scalingMethod() const { return scaling; }
|
||||
const QSize& aspectRatio() const { return aspRatio; }
|
||||
ScalingMethod scalingMethod() const { return scalingMethodSelector.scalingMethod(); }
|
||||
const QSize& aspectRatio() const { return winResSelector.aspectRatio(); }
|
||||
void setAspectRatio(const QSize &aspectRatio);
|
||||
|
||||
public slots:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aam<EFBFBD>s *
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -38,7 +38,7 @@ struct TmpPauser {
|
||||
MainWindow *const mw;
|
||||
const unsigned inc;
|
||||
|
||||
TmpPauser(MainWindow *const mw, const unsigned inc = 4) : mw(mw), inc(inc) {
|
||||
explicit TmpPauser(MainWindow *const mw, const unsigned inc = 4) : mw(mw), inc(inc) {
|
||||
mw->incPause(inc);
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ struct TmpPauser {
|
||||
};
|
||||
}
|
||||
|
||||
GambatteMenuHandler::FrameTime::FrameTime(unsigned baseNum, unsigned baseDenom) : index(STEPS) {
|
||||
FrameRateAdjuster::FrameTime::FrameTime(unsigned baseNum, unsigned baseDenom) : index(STEPS) {
|
||||
frameTimes[index] = Rational(baseNum, baseDenom);
|
||||
|
||||
for (unsigned i = index; i < STEPS * 2; ++i) {
|
||||
@ -60,15 +60,79 @@ GambatteMenuHandler::FrameTime::FrameTime(unsigned baseNum, unsigned baseDenom)
|
||||
}
|
||||
}
|
||||
|
||||
GambatteMenuHandler::GambatteMenuHandler(MainWindow *const mw, GambatteSource *const source,
|
||||
const int argc, const char *const argv[]) :
|
||||
mw(mw),
|
||||
source(source),
|
||||
soundDialog(new SoundDialog(mw, mw)),
|
||||
videoDialog(new VideoDialog(mw, source->generateVideoSourceInfos(), QString("Video filter:"), QSize(160, 144), mw)),
|
||||
miscDialog(new MiscDialog(mw)),
|
||||
frameTime(4389, 262144),
|
||||
pauseInc(4)
|
||||
FrameRateAdjuster::FrameRateAdjuster(const unsigned baseNum, const unsigned baseDenom, MainWindow *const mw, QObject *const parent)
|
||||
: QObject(parent),
|
||||
frameTime_(baseNum, baseDenom),
|
||||
decFrameRateAction_(new QAction(tr("&Decrease Frame Rate"), mw)),
|
||||
incFrameRateAction_(new QAction(tr("&Increase Frame Rate"), mw)),
|
||||
resetFrameRateAction_(new QAction(tr("&Reset Frame Rate"), mw)),
|
||||
mw_(mw),
|
||||
enabled_(true)
|
||||
{
|
||||
decFrameRateAction_->setShortcut(QString("Ctrl+D"));
|
||||
incFrameRateAction_->setShortcut(QString("Ctrl+I"));
|
||||
resetFrameRateAction_->setShortcut(QString("Ctrl+U"));
|
||||
|
||||
connect(decFrameRateAction_, SIGNAL(triggered()), this, SLOT(decFrameRate()));
|
||||
connect(incFrameRateAction_, SIGNAL(triggered()), this, SLOT(incFrameRate()));
|
||||
connect(resetFrameRateAction_, SIGNAL(triggered()), this, SLOT(resetFrameRate()));
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
const QList<QAction*> FrameRateAdjuster::actions() {
|
||||
QList<QAction*> l;
|
||||
l.append(decFrameRateAction_);
|
||||
l.append(incFrameRateAction_);
|
||||
l.append(resetFrameRateAction_);
|
||||
return l;
|
||||
}
|
||||
|
||||
void FrameRateAdjuster::setDisabled(const bool disabled) {
|
||||
enabled_ = !disabled;
|
||||
changed();
|
||||
}
|
||||
|
||||
void FrameRateAdjuster::decFrameRate() {
|
||||
if (enabled_) {
|
||||
frameTime_.inc();
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FrameRateAdjuster::incFrameRate() {
|
||||
if (enabled_) {
|
||||
frameTime_.dec();
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FrameRateAdjuster::resetFrameRate() {
|
||||
if (enabled_) {
|
||||
frameTime_.reset();
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FrameRateAdjuster::changed() {
|
||||
incFrameRateAction_->setEnabled(enabled_ && frameTime_.decPossible());
|
||||
decFrameRateAction_->setEnabled(enabled_ && frameTime_.incPossible());
|
||||
resetFrameRateAction_->setEnabled(enabled_ && frameTime_.resetPossible());
|
||||
|
||||
const FrameTime::Rational &ft = enabled_ ? frameTime_.get() : frameTime_.base();
|
||||
mw_->setFrameTime(ft.num, ft.denom);
|
||||
}
|
||||
|
||||
GambatteMenuHandler::GambatteMenuHandler(MainWindow *const mw,
|
||||
GambatteSource *const source, const int argc, const char *const argv[])
|
||||
: mw(mw),
|
||||
source(source),
|
||||
soundDialog(new SoundDialog(mw, mw)),
|
||||
videoDialog(new VideoDialog(mw, source->generateVideoSourceInfos(), QString("Video filter:"), QSize(160, 144), mw)),
|
||||
miscDialog(new MiscDialog(mw)),
|
||||
stateSlotGroup(new QActionGroup(mw)),
|
||||
frameRateAdjuster(4389, 262144, mw),
|
||||
pauseInc(4)
|
||||
{
|
||||
mw->setWindowTitle("Gambatte");
|
||||
source->inputDialog()->setParent(mw, source->inputDialog()->windowFlags());
|
||||
@ -79,7 +143,7 @@ pauseInc(4)
|
||||
savepath.truncate(iniSettings.fileName().lastIndexOf("/") + 1);
|
||||
|
||||
{
|
||||
QString palpath = savepath + "palettes";
|
||||
const QString &palpath = savepath + "palettes";
|
||||
QDir::root().mkpath(palpath);
|
||||
globalPaletteDialog = new PaletteDialog(palpath, 0, mw);
|
||||
romPaletteDialog = new PaletteDialog(palpath, globalPaletteDialog, mw);
|
||||
@ -92,6 +156,9 @@ pauseInc(4)
|
||||
source->setSavedir(savepath.toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
QActionGroup *const romLoadedActions = new QActionGroup(mw);
|
||||
romLoadedActions->setExclusive(false);
|
||||
|
||||
{
|
||||
for (int i = 0; i < MaxRecentFiles; ++i) {
|
||||
recentFileActs[i] = new QAction(mw);
|
||||
@ -102,42 +169,39 @@ pauseInc(4)
|
||||
QMenu *fileMenu = mw->menuBar()->addMenu(tr("&File"));
|
||||
fileMenu->addAction(tr("&Open..."), this, SLOT(open()), tr("Ctrl+O"));
|
||||
|
||||
{
|
||||
recentMenu = fileMenu->addMenu(tr("Open Re¢"));
|
||||
recentMenu = fileMenu->addMenu(tr("Open Re¢"));
|
||||
|
||||
for (int i = 0; i < MaxRecentFiles; ++i)
|
||||
recentMenu->addAction(recentFileActs[i]);
|
||||
}
|
||||
for (int i = 0; i < MaxRecentFiles; ++i)
|
||||
recentMenu->addAction(recentFileActs[i]);
|
||||
|
||||
fileMenu->addSeparator();
|
||||
romLoadedActions.append(fileMenu->addAction(tr("&Reset"), recentFileActs[0], SLOT(trigger()), tr("Ctrl+R")));
|
||||
romLoadedActions->addAction(fileMenu->addAction(tr("&Reset"), recentFileActs[0], SLOT(trigger()), tr("Ctrl+R")));
|
||||
fileMenu->addSeparator();
|
||||
|
||||
romLoadedActions.append(fileMenu->addAction(tr("Save State &As..."), this, SLOT(saveStateAs())));
|
||||
romLoadedActions.append(fileMenu->addAction(tr("Load State &From..."), this, SLOT(loadStateFrom())));
|
||||
romLoadedActions->addAction(fileMenu->addAction(tr("Save State &As..."), this, SLOT(saveStateAs())));
|
||||
romLoadedActions->addAction(fileMenu->addAction(tr("Load State &From..."), this, SLOT(loadStateFrom())));
|
||||
fileMenu->addSeparator();
|
||||
|
||||
romLoadedActions.append(fileMenu->addAction(tr("&Save State"), this, SLOT(saveState()), QString("Ctrl+S")));
|
||||
romLoadedActions.append(fileMenu->addAction(tr("&Load State"), this, SLOT(loadState()), QString("Ctrl+L")));
|
||||
romLoadedActions->addAction(fileMenu->addAction(tr("&Save State"), this, SLOT(saveState()), QString("Ctrl+S")));
|
||||
romLoadedActions->addAction(fileMenu->addAction(tr("&Load State"), this, SLOT(loadState()), QString("Ctrl+L")));
|
||||
|
||||
{
|
||||
stateSlotMenu = fileMenu->addMenu(tr("S&elect State Slot"));
|
||||
QMenu *const stateSlotMenu = fileMenu->addMenu(tr("S&elect State Slot"));
|
||||
stateSlotMenu->setEnabled(false);
|
||||
stateSlotMenu->addAction(tr("&Previous"), this, SLOT(prevStateSlot()), QString("Ctrl+Z"));
|
||||
stateSlotMenu->addAction(tr("&Next"), this, SLOT(nextStateSlot()), QString("Ctrl+X"));
|
||||
stateSlotMenu->addSeparator();
|
||||
|
||||
stateSlotGroup = new QActionGroup(mw);
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
const int no = i == 9 ? 0 : i + 1;
|
||||
const QString &strno = QString::number(no);
|
||||
QAction *action = stateSlotMenu->addAction("Slot &" + strno, this, SLOT(selectStateSlot()), strno);
|
||||
|
||||
QAction *const action = stateSlotMenu->addAction("Slot &" + strno, this, SLOT(selectStateSlot()), strno);
|
||||
action->setCheckable(true);
|
||||
action->setData(no);
|
||||
stateSlotGroup->addAction(action);
|
||||
}
|
||||
|
||||
connect(this, SIGNAL(romLoaded(bool)), stateSlotMenu, SLOT(setEnabled(bool)));
|
||||
}
|
||||
|
||||
fileMenu->addSeparator();
|
||||
@ -149,18 +213,20 @@ pauseInc(4)
|
||||
{
|
||||
QMenu *const playm = mw->menuBar()->addMenu(tr("&Play"));
|
||||
|
||||
romLoadedActions.append(pauseAction = playm->addAction(tr("&Pause"), this, SLOT(pauseChange()), QString("Ctrl+P")));
|
||||
romLoadedActions->addAction(pauseAction = playm->addAction(tr("&Pause"), this, SLOT(pauseChange()), QString("Ctrl+P")));
|
||||
pauseAction->setCheckable(true);
|
||||
romLoadedActions.append(playm->addAction(tr("Frame &Step"), this, SLOT(frameStep()), QString("Ctrl+.")));
|
||||
romLoadedActions->addAction(playm->addAction(tr("Frame &Step"), this, SLOT(frameStep()), QString("Ctrl+.")));
|
||||
playm->addSeparator();
|
||||
/*romLoadedActions.append(*/syncFrameRateAction = playm->addAction(tr("&Sync Frame Rate to Refresh Rate"), this, SLOT(syncFrameRate()))/*)*/;
|
||||
syncFrameRateAction = playm->addAction(tr("&Sync Frame Rate to Refresh Rate"));
|
||||
syncFrameRateAction->setCheckable(true);
|
||||
romLoadedActions.append(decFrameRateAction = playm->addAction(tr("&Decrease Frame Rate"), this, SLOT(decFrameRate()), QString("Ctrl+D")));
|
||||
romLoadedActions.append(incFrameRateAction = playm->addAction(tr("&Increase Frame Rate"), this, SLOT(incFrameRate()), QString("Ctrl+I")));
|
||||
romLoadedActions.append(resetFrameRateAction = playm->addAction(tr("&Reset Frame Rate"), this, SLOT(resetFrameRate()), QString("Ctrl+U")));
|
||||
connect(syncFrameRateAction, SIGNAL(triggered(bool)), &frameRateAdjuster, SLOT(setDisabled(bool)));
|
||||
connect(syncFrameRateAction, SIGNAL(triggered(bool)), mw , SLOT(setSyncToRefreshRate(bool)));
|
||||
|
||||
foreach (QAction *const action, frameRateAdjuster.actions())
|
||||
playm->addAction(romLoadedActions->addAction(action));
|
||||
}
|
||||
|
||||
QMenu *settingsm = mw->menuBar()->addMenu(tr("&Settings"));
|
||||
QMenu *const settingsm = mw->menuBar()->addMenu(tr("&Settings"));
|
||||
|
||||
settingsm->addAction(tr("&Input..."), this, SLOT(execInputDialog()));
|
||||
settingsm->addAction(tr("&Miscellaneous..."), this, SLOT(execMiscDialog()));
|
||||
@ -177,8 +243,9 @@ pauseInc(4)
|
||||
|
||||
palm->addAction(tr("&Global..."), this, SLOT(execGlobalPaletteDialog()));
|
||||
|
||||
romPaletteAct = palm->addAction(tr("Current &ROM..."), this, SLOT(execRomPaletteDialog()));
|
||||
QAction *const romPaletteAct = palm->addAction(tr("Current &ROM..."), this, SLOT(execRomPaletteDialog()));
|
||||
romPaletteAct->setEnabled(false);
|
||||
connect(this, SIGNAL(dmgRomLoaded(bool)), romPaletteAct, SLOT(setEnabled(bool)));
|
||||
}
|
||||
|
||||
settingsm->addSeparator();
|
||||
@ -191,15 +258,13 @@ pauseInc(4)
|
||||
fsAct->setCheckable(true);
|
||||
}
|
||||
|
||||
foreach (QAction *a, romLoadedActions) {
|
||||
a->setEnabled(false);
|
||||
}
|
||||
romLoadedActions->setEnabled(false);
|
||||
|
||||
// settingsm->addAction(hideMenuAct);
|
||||
|
||||
mw->menuBar()->addSeparator();
|
||||
|
||||
QMenu *helpMenu = mw->menuBar()->addMenu(tr("&Help"));
|
||||
QMenu *const helpMenu = mw->menuBar()->addMenu(tr("&Help"));
|
||||
helpMenu->addAction(tr("&About"), this, SLOT(about()));
|
||||
|
||||
mw->addActions(mw->menuBar()->actions());
|
||||
@ -211,14 +276,13 @@ pauseInc(4)
|
||||
mw->addAction(escAct);
|
||||
}
|
||||
|
||||
mw->setFrameTime(frameTime.get().num, frameTime.get().denom);
|
||||
mw->setSamplesPerFrame(35112);
|
||||
connect(source, SIGNAL(setTurbo(bool)), mw, SLOT(setFastForward(bool)));
|
||||
connect(source, SIGNAL(togglePause()), pauseAction, SLOT(trigger()));
|
||||
connect(source, SIGNAL(frameStep()), this, SLOT(frameStep()));
|
||||
connect(source, SIGNAL(decFrameRate()), this, SLOT(decFrameRate()));
|
||||
connect(source, SIGNAL(incFrameRate()), this, SLOT(incFrameRate()));
|
||||
connect(source, SIGNAL(resetFrameRate()), this, SLOT(resetFrameRate()));
|
||||
connect(source, SIGNAL(decFrameRate()), &frameRateAdjuster, SLOT(decFrameRate()));
|
||||
connect(source, SIGNAL(incFrameRate()), &frameRateAdjuster, SLOT(incFrameRate()));
|
||||
connect(source, SIGNAL(resetFrameRate()), &frameRateAdjuster, SLOT(resetFrameRate()));
|
||||
connect(source, SIGNAL(prevStateSlot()), this, SLOT(prevStateSlot()));
|
||||
connect(source, SIGNAL(nextStateSlot()), this, SLOT(nextStateSlot()));
|
||||
connect(source, SIGNAL(saveStateSignal()), this, SLOT(saveState()));
|
||||
@ -229,17 +293,14 @@ pauseInc(4)
|
||||
connect(mw, SIGNAL(videoBlitterFailure()), this, SLOT(videoBlitterFailure()));
|
||||
connect(mw, SIGNAL(audioEngineFailure()), this, SLOT(audioEngineFailure()));
|
||||
connect(mw, SIGNAL(closing()), this, SLOT(saveWindowSize()));
|
||||
connect(this, SIGNAL(romLoaded(bool)), romLoadedActions, SLOT(setEnabled(bool)));
|
||||
connect(this, SIGNAL(romLoaded(bool)), stateSlotGroup->actions().at(0), SLOT(setChecked(bool)));
|
||||
|
||||
videoDialogChange();
|
||||
soundDialogChange();
|
||||
miscDialogChange();
|
||||
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup("mainwindow");
|
||||
mw->resize(settings.value("size", QSize(160, 144)).toSize());
|
||||
settings.endGroup();
|
||||
}
|
||||
mw->resize(QSettings().value("mainwindow/size", QSize(160, 144)).toSize());
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (argv[i][0] != '-') {
|
||||
@ -253,10 +314,10 @@ void GambatteMenuHandler::updateRecentFileActions() {
|
||||
QSettings settings;
|
||||
QStringList files = settings.value("recentFileList").toStringList();
|
||||
|
||||
int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);
|
||||
const int numRecentFiles = qMin(files.size(), static_cast<int>(MaxRecentFiles));
|
||||
|
||||
for (int i = 0; i < numRecentFiles; ++i) {
|
||||
QString text = tr("&%1 %2").arg(i + 1).arg(strippedName(files[i]));
|
||||
const QString &text = tr("&%1 %2").arg(i + 1).arg(strippedName(files[i]));
|
||||
recentFileActs[i]->setText(text);
|
||||
recentFileActs[i]->setData(files[i]);
|
||||
recentFileActs[i]->setVisible(true);
|
||||
@ -269,12 +330,7 @@ void GambatteMenuHandler::updateRecentFileActions() {
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::setCurrentFile(const QString &fileName) {
|
||||
QString curFile = fileName;
|
||||
|
||||
if (curFile.isEmpty())
|
||||
mw->setWindowTitle(tr("Gambatte"));
|
||||
else
|
||||
mw->setWindowTitle(tr("%1 - %2").arg(strippedName(curFile)).arg(tr("Gambatte")));
|
||||
mw->setWindowTitle(fileName.isEmpty() ? tr("Gambatte") : tr("%1 - %2").arg(strippedName(fileName)).arg(tr("Gambatte")));
|
||||
|
||||
QSettings settings;
|
||||
QStringList files = settings.value("recentFileList").toStringList();
|
||||
@ -310,37 +366,28 @@ void GambatteMenuHandler::loadFile(const QString &fileName) {
|
||||
setDmgPaletteColors();
|
||||
}
|
||||
|
||||
romPaletteAct->setEnabled(!source->isCgb());
|
||||
|
||||
setCurrentFile(fileName);
|
||||
|
||||
foreach (QAction *a, romLoadedActions) {
|
||||
a->setEnabled(true);
|
||||
}
|
||||
|
||||
stateSlotMenu->setEnabled(true);
|
||||
stateSlotGroup->actions().at(0)->setChecked(true);
|
||||
resetFrameRate();
|
||||
|
||||
emit romLoaded(true);
|
||||
emit dmgRomLoaded(!source->isCgb());
|
||||
|
||||
mw->run();
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::open() {
|
||||
TmpPauser tmpPauser(mw, pauseInc);
|
||||
|
||||
const QString &fileName = QFileDialog::getOpenFileName(mw, tr("Open"), recentFileActs[0]->data().toString(),
|
||||
tr("Game Boy ROM Images (*.dmg *.gb *.gbc *.sgb *.zip);;All Files (*)"));
|
||||
tr("Game Boy ROM Images (*.dmg *.gb *.gbc *.sgb *.zip);;All Files (*)"));
|
||||
|
||||
if (!fileName.isEmpty())
|
||||
loadFile(fileName);
|
||||
|
||||
mw->setFocus(); // giving back focus after getOpenFileName seems to fail at times, which can be problematic with current exclusive mode handling.
|
||||
// giving back focus after getOpenFileName seems to fail at times, which can be problematic with current exclusive mode handling.
|
||||
mw->setFocus();
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::openRecentFile() {
|
||||
QAction *action = qobject_cast<QAction *>(sender());
|
||||
|
||||
if (action)
|
||||
if (const QAction *const action = qobject_cast<QAction *>(sender()))
|
||||
loadFile(action->data().toString());
|
||||
}
|
||||
|
||||
@ -349,10 +396,10 @@ void GambatteMenuHandler::about() {
|
||||
|
||||
QMessageBox::about(
|
||||
mw,
|
||||
tr("About Gambatte"),
|
||||
tr("<h3>Gambatte Qt SVN</h3>\
|
||||
<p><b>Author:</b> Sindre Aam<EFBFBD>s (<a href=\"mailto:aamas@stud.ntnu.no\">aamas@stud.ntnu.no</a>).<br>\
|
||||
<b>Homepage:</b> <a href=\"http://sourceforge.net/projects/gambatte\">http://sourceforge.net/projects/gambatte</a>.</p>\
|
||||
"About Gambatte",
|
||||
QString::fromUtf8("<h3>Gambatte Qt SVN</h3>\
|
||||
<p><b>Author:</b> Sindre Aamås (<a href=\"mailto:sinamas@users.sourceforge.net\">sinamas@users.sourceforge.net</a>)<br>\
|
||||
<b>Homepage:</b> <a href=\"http://sourceforge.net/projects/gambatte\">http://sourceforge.net/projects/gambatte</a></p>\
|
||||
<p>Gambatte is an accuracy-focused, open-source, cross-platform Game Boy Color emulator written in C++. It is based on hundreds of corner case hardware tests, as well as previous documentation and reverse engineering efforts.</p>")
|
||||
);
|
||||
}
|
||||
@ -370,22 +417,22 @@ void GambatteMenuHandler::romPaletteChange() {
|
||||
namespace {
|
||||
struct SetDmgPaletteColorFun {
|
||||
GambatteSource *source; unsigned palnum; unsigned colornum; unsigned rgb32;
|
||||
void operator()() { source->setDmgPaletteColor(palnum, colornum, rgb32); }
|
||||
void operator()() const { source->setDmgPaletteColor(palnum, colornum, rgb32); }
|
||||
};
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::setDmgPaletteColors() {
|
||||
for (unsigned palnum = 0; palnum < 3; ++palnum)
|
||||
for (unsigned colornum = 0; colornum < 4; ++colornum) {
|
||||
const SetDmgPaletteColorFun fun = { source, palnum, colornum, romPaletteDialog->getColor(palnum, colornum) };
|
||||
mw->callInWorkerThread(fun);
|
||||
}
|
||||
for (unsigned colornum = 0; colornum < 4; ++colornum) {
|
||||
const SetDmgPaletteColorFun fun = { source, palnum, colornum, romPaletteDialog->getColor(palnum, colornum) };
|
||||
mw->callInWorkerThread(fun);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct SetVideoSourceFun {
|
||||
GambatteSource *source; unsigned sourceIndex;
|
||||
void operator()() { source->setVideoSource(sourceIndex); }
|
||||
void operator()() const { source->setVideoSource(sourceIndex); }
|
||||
};
|
||||
}
|
||||
|
||||
@ -458,7 +505,7 @@ void GambatteMenuHandler::nextStateSlot() {
|
||||
namespace {
|
||||
struct SelectStateFun {
|
||||
GambatteSource *source; int i;
|
||||
void operator()() { source->selectState(i); }
|
||||
void operator()() const { source->selectState(i); }
|
||||
};
|
||||
}
|
||||
|
||||
@ -473,7 +520,7 @@ namespace {
|
||||
struct SaveStateFun {
|
||||
GambatteSource *source;
|
||||
MainWindow::FrameBuffer fb;
|
||||
void operator()() {
|
||||
void operator()() const {
|
||||
source->saveState(MainWindow::FrameBuffer::Locked(fb).get());
|
||||
}
|
||||
};
|
||||
@ -487,7 +534,7 @@ void GambatteMenuHandler::saveState() {
|
||||
namespace {
|
||||
struct LoadStateFun {
|
||||
GambatteSource *source;
|
||||
void operator()() { source->loadState(); }
|
||||
void operator()() const { source->loadState(); }
|
||||
};
|
||||
}
|
||||
|
||||
@ -501,7 +548,7 @@ struct SaveStateAsFun {
|
||||
GambatteSource *source;
|
||||
MainWindow::FrameBuffer fb;
|
||||
QString fileName;
|
||||
void operator()() {
|
||||
void operator()() const {
|
||||
source->saveState(MainWindow::FrameBuffer::Locked(fb).get(), fileName.toLocal8Bit().constData());
|
||||
}
|
||||
};
|
||||
@ -509,8 +556,8 @@ struct SaveStateAsFun {
|
||||
|
||||
void GambatteMenuHandler::saveStateAs() {
|
||||
TmpPauser tmpPauser(mw, pauseInc);
|
||||
|
||||
const QString &fileName = QFileDialog::getSaveFileName(mw, tr("Save State"), QString(), tr("Gambatte Quick Save Files (*.gqs);;All Files (*)"));
|
||||
const QString &fileName = QFileDialog::getSaveFileName(mw, tr("Save State"),
|
||||
QString(), tr("Gambatte Quick Save Files (*.gqs);;All Files (*)"));
|
||||
|
||||
if (!fileName.isEmpty()) {
|
||||
const SaveStateAsFun fun = { source, MainWindow::FrameBuffer(mw), fileName };
|
||||
@ -522,7 +569,7 @@ namespace {
|
||||
struct LoadStateFromFun {
|
||||
GambatteSource *source;
|
||||
QString fileName;
|
||||
void operator()() {
|
||||
void operator()() const {
|
||||
source->loadState(fileName.toLocal8Bit().constData());
|
||||
}
|
||||
};
|
||||
@ -530,7 +577,8 @@ struct LoadStateFromFun {
|
||||
|
||||
void GambatteMenuHandler::loadStateFrom() {
|
||||
TmpPauser tmpPauser(mw, pauseInc);
|
||||
const QString &fileName = QFileDialog::getOpenFileName(mw, tr("Load State"), QString(), tr("Gambatte Quick Save Files (*.gqs);;All Files (*)"));
|
||||
const QString &fileName = QFileDialog::getOpenFileName(mw, tr("Load State"),
|
||||
QString(), tr("Gambatte Quick Save Files (*.gqs);;All Files (*)"));
|
||||
|
||||
if (!fileName.isEmpty()) {
|
||||
const LoadStateFromFun fun = { source, fileName };
|
||||
@ -552,39 +600,6 @@ void GambatteMenuHandler::frameStep() {
|
||||
pauseAction->trigger();
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::frameRateChange() {
|
||||
incFrameRateAction->setEnabled(frameTime.decPossible());
|
||||
decFrameRateAction->setEnabled(frameTime.incPossible());
|
||||
resetFrameRateAction->setEnabled(frameTime.resetPossible());
|
||||
mw->setFrameTime(frameTime.get().num, frameTime.get().denom);
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::syncFrameRate() {
|
||||
const bool checked = syncFrameRateAction->isChecked();
|
||||
mw->setSyncToRefreshRate(checked);
|
||||
|
||||
if (mw->isRunning()) {
|
||||
incFrameRateAction->setEnabled(!checked & frameTime.decPossible());
|
||||
decFrameRateAction->setEnabled(!checked & frameTime.incPossible());
|
||||
resetFrameRateAction->setEnabled(!checked & frameTime.resetPossible());
|
||||
}
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::decFrameRate() {
|
||||
frameTime.inc();
|
||||
frameRateChange();
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::incFrameRate() {
|
||||
frameTime.dec();
|
||||
frameRateChange();
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::resetFrameRate() {
|
||||
frameTime.reset();
|
||||
frameRateChange();
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::escPressed() {
|
||||
#ifdef Q_WS_MAC
|
||||
if (fsAct->isChecked())
|
||||
@ -599,13 +614,15 @@ void GambatteMenuHandler::escPressed() {
|
||||
|
||||
void GambatteMenuHandler::videoBlitterFailure() {
|
||||
TmpPauser tmpPauser(mw, pauseInc);
|
||||
QMessageBox::critical(mw, tr("Video engine failure"), tr("Failed to update video output. This may be fixed by changing the video engine settings."));
|
||||
QMessageBox::critical(mw, tr("Video engine failure"),
|
||||
tr("Failed to update video output. This may be fixed by changing the video engine settings."));
|
||||
videoDialog->exec();
|
||||
}
|
||||
|
||||
void GambatteMenuHandler::audioEngineFailure() {
|
||||
TmpPauser tmpPauser(mw, pauseInc);
|
||||
QMessageBox::critical(mw, tr("Sound engine failure"), tr("Failed to output audio. This may be fixed by changing the sound settings."));
|
||||
QMessageBox::critical(mw, tr("Sound engine failure"),
|
||||
tr("Failed to output audio. This may be fixed by changing the sound settings."));
|
||||
soundDialog->exec();
|
||||
}
|
||||
|
||||
@ -618,7 +635,5 @@ void GambatteMenuHandler::toggleFullScreen() {
|
||||
|
||||
void GambatteMenuHandler::saveWindowSize() {
|
||||
QSettings settings;
|
||||
settings.beginGroup("mainwindow");
|
||||
settings.setValue("size", mw->isFullScreen() ? wsz : mw->size());
|
||||
settings.endGroup();
|
||||
settings.setValue("mainwindow/size", mw->isFullScreen() ? wsz : mw->size());
|
||||
}
|
||||
|
@ -34,17 +34,15 @@ class SoundDialog;
|
||||
class VideoDialog;
|
||||
class MiscDialog;
|
||||
|
||||
class GambatteMenuHandler : public QObject {
|
||||
class FrameRateAdjuster : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
enum { MaxRecentFiles = 9 };
|
||||
|
||||
class FrameTime {
|
||||
public:
|
||||
struct Rational {
|
||||
unsigned num;
|
||||
unsigned denom;
|
||||
Rational(unsigned num = 0, unsigned denom = 0) : num(num), denom(denom) {}
|
||||
Rational(unsigned num = 0, unsigned denom = 1) : num(num), denom(denom) {}
|
||||
};
|
||||
|
||||
private:
|
||||
@ -71,11 +69,33 @@ class GambatteMenuHandler : public QObject {
|
||||
}
|
||||
|
||||
void reset() { index = STEPS; }
|
||||
const Rational& get() const { return frameTimes[index]; }
|
||||
const Rational& base() const { return frameTimes[STEPS]; }
|
||||
} frameTime_;
|
||||
|
||||
QAction *const decFrameRateAction_;
|
||||
QAction *const incFrameRateAction_;
|
||||
QAction *const resetFrameRateAction_;
|
||||
MainWindow *const mw_;
|
||||
bool enabled_;
|
||||
|
||||
void changed();
|
||||
|
||||
public:
|
||||
FrameRateAdjuster(unsigned baseNum, unsigned baseDenom, MainWindow *mw, QObject *parent = 0);
|
||||
const QList<QAction*> actions();
|
||||
|
||||
public slots:
|
||||
void setDisabled(bool disabled);
|
||||
void decFrameRate();
|
||||
void incFrameRate();
|
||||
void resetFrameRate();
|
||||
};
|
||||
|
||||
class GambatteMenuHandler : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
const Rational& get() const {
|
||||
return frameTimes[index];
|
||||
}
|
||||
};
|
||||
enum { MaxRecentFiles = 9 };
|
||||
|
||||
MainWindow *const mw;
|
||||
GambatteSource *const source;
|
||||
@ -83,23 +103,17 @@ class GambatteMenuHandler : public QObject {
|
||||
VideoDialog *const videoDialog;
|
||||
MiscDialog *const miscDialog;
|
||||
QAction *recentFileActs[MaxRecentFiles];
|
||||
QAction *romPaletteAct;
|
||||
QAction *pauseAction;
|
||||
QAction *syncFrameRateAction;
|
||||
QAction *decFrameRateAction;
|
||||
QAction *incFrameRateAction;
|
||||
QAction *resetFrameRateAction;
|
||||
QAction *forceDmgAction;
|
||||
#ifdef Q_WS_MAC
|
||||
QAction *fsAct;
|
||||
#endif
|
||||
QMenu *recentMenu;
|
||||
QMenu *stateSlotMenu;
|
||||
PaletteDialog *globalPaletteDialog;
|
||||
PaletteDialog *romPaletteDialog;
|
||||
QActionGroup *stateSlotGroup;
|
||||
QList<QAction*> romLoadedActions;
|
||||
FrameTime frameTime;
|
||||
QActionGroup *const stateSlotGroup;
|
||||
FrameRateAdjuster frameRateAdjuster;
|
||||
QSize wsz;
|
||||
unsigned pauseInc;
|
||||
|
||||
@ -107,7 +121,10 @@ class GambatteMenuHandler : public QObject {
|
||||
void setCurrentFile(const QString &fileName);
|
||||
void setDmgPaletteColors();
|
||||
void updateRecentFileActions();
|
||||
void frameRateChange();
|
||||
|
||||
signals:
|
||||
void romLoaded(bool);
|
||||
void dmgRomLoaded(bool);
|
||||
|
||||
private slots:
|
||||
void open();
|
||||
@ -133,10 +150,6 @@ private slots:
|
||||
void loadStateFrom();
|
||||
void pauseChange();
|
||||
void frameStep();
|
||||
void syncFrameRate();
|
||||
void decFrameRate();
|
||||
void incFrameRate();
|
||||
void resetFrameRate();
|
||||
void escPressed();
|
||||
void videoBlitterFailure();
|
||||
void audioEngineFailure();
|
||||
|
@ -171,7 +171,7 @@ static void* getpbdata(const PixelBuffer &pb, const unsigned vsrci) {
|
||||
return pb.width == VfilterInfo::get(vsrci).outWidth && pb.height == VfilterInfo::get(vsrci).outHeight ? pb.data : 0;
|
||||
}
|
||||
|
||||
long GambatteSource::update(const PixelBuffer &pb, qint16 *soundBuf, long &samples) {
|
||||
long GambatteSource::update(const PixelBuffer &pb, qint16 *const soundBuf, long &samples) {
|
||||
setPixelBuffer(getpbdata(pb, vsrci), pb.pixelFormat, pb.pitch);
|
||||
samples -= overupdate;
|
||||
|
||||
@ -184,9 +184,9 @@ long GambatteSource::update(const PixelBuffer &pb, qint16 *soundBuf, long &sampl
|
||||
setGbDir(inputState[LEFT_BUT], inputState[RIGHT_BUT], dpadLeft, dpadRight, dpadLeftLast);
|
||||
inputGetter.is = packedInputState(inputState);
|
||||
|
||||
unsigned isamples = samples;
|
||||
const int retval = gb.runFor(gbpixels, gbpitch, reinterpret_cast<uint_least32_t*>(soundBuf), isamples);
|
||||
samples = isamples;
|
||||
unsigned usamples = samples;
|
||||
const long retval = gb.runFor(gbpixels, gbpitch, reinterpret_cast<uint_least32_t*>(soundBuf), usamples);
|
||||
samples = usamples;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -25,45 +25,45 @@
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
|
||||
template<class Parent, class ChildLayout>
|
||||
static ChildLayout * addLayout(Parent *const parent, ChildLayout *const child) {
|
||||
parent->addLayout(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
template<class Parent, class ChildLayout>
|
||||
static ChildLayout * addLayout(Parent *const parent, ChildLayout *const child, const Qt::Alignment alignment) {
|
||||
parent->addLayout(child);
|
||||
parent->setAlignment(child, alignment);
|
||||
return child;
|
||||
}
|
||||
|
||||
MiscDialog::MiscDialog(QWidget *const parent) :
|
||||
QDialog(parent),
|
||||
turboSpeedBox(new QSpinBox(this)),
|
||||
pauseOnDialogsBox(new QCheckBox(tr("Pause when displaying dialogs"), this)),
|
||||
pauseOnFocusOutBox(new QCheckBox(tr("Pause on focus out"), this)),
|
||||
turboSpeed_(4),
|
||||
pauseOnDialogs_(true),
|
||||
pauseOnFocusOut_(false) {
|
||||
pauseOnDialogs_(new QCheckBox(tr("Pause when displaying dialogs"), this), "misc/pauseOnDialogs", true),
|
||||
pauseOnFocusOut_(new QCheckBox(tr("Pause on focus out"), this), "misc/pauseOnFocusOut", false),
|
||||
turboSpeed_(4) {
|
||||
setWindowTitle(tr("Miscellaneous Settings"));
|
||||
QVBoxLayout *const mainLayout = new QVBoxLayout;
|
||||
QVBoxLayout *const topLayout = new QVBoxLayout;
|
||||
turboSpeedBox->setRange(2, 16);
|
||||
turboSpeedBox->setSuffix("x");
|
||||
|
||||
QVBoxLayout *const mainLayout = new QVBoxLayout(this);
|
||||
QVBoxLayout *const topLayout = addLayout(mainLayout, new QVBoxLayout);
|
||||
|
||||
{
|
||||
QHBoxLayout *const hLayout = new QHBoxLayout;
|
||||
QHBoxLayout *const hLayout = addLayout(topLayout, new QHBoxLayout);
|
||||
hLayout->addWidget(new QLabel(tr("Fast-forward speed:")));
|
||||
turboSpeedBox->setRange(2, 16);
|
||||
turboSpeedBox->setSuffix("x");
|
||||
hLayout->addWidget(turboSpeedBox);
|
||||
topLayout->addLayout(hLayout);
|
||||
}
|
||||
|
||||
{
|
||||
QHBoxLayout *const hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(pauseOnDialogsBox);
|
||||
topLayout->addLayout(hLayout);
|
||||
}
|
||||
|
||||
{
|
||||
QHBoxLayout *const hLayout = new QHBoxLayout;
|
||||
hLayout->addWidget(pauseOnFocusOutBox);
|
||||
topLayout->addLayout(hLayout);
|
||||
}
|
||||
|
||||
mainLayout->addLayout(topLayout);
|
||||
addLayout(topLayout, new QHBoxLayout)->addWidget(pauseOnDialogs_.checkBox());
|
||||
addLayout(topLayout, new QHBoxLayout)->addWidget(pauseOnFocusOut_.checkBox());
|
||||
|
||||
{
|
||||
QPushButton *const okButton = new QPushButton(tr("OK"), this);
|
||||
QPushButton *const cancelButton = new QPushButton(tr("Cancel"), this);
|
||||
QHBoxLayout *const hLayout = new QHBoxLayout;
|
||||
QHBoxLayout *const hLayout = addLayout(mainLayout, new QHBoxLayout, Qt::AlignBottom | Qt::AlignRight);
|
||||
|
||||
hLayout->addWidget(okButton);
|
||||
hLayout->addWidget(cancelButton);
|
||||
@ -72,42 +72,27 @@ pauseOnFocusOut_(false) {
|
||||
|
||||
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
|
||||
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||
|
||||
mainLayout->addLayout(hLayout);
|
||||
mainLayout->setAlignment(hLayout, Qt::AlignBottom | Qt::AlignRight);
|
||||
}
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
QSettings settings;
|
||||
settings.beginGroup("misc");
|
||||
turboSpeed_ = std::min(std::max(settings.value("turboSpeed", turboSpeed_).toInt(), 2), 16);
|
||||
pauseOnDialogs_ = settings.value("pauseOnDialogs", pauseOnDialogs_).toBool();
|
||||
pauseOnFocusOut_ = settings.value("pauseOnFocusOut", pauseOnFocusOut_).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
turboSpeed_ = std::min(std::max(QSettings().value("misc/turboSpeed", turboSpeed_).toInt(), 2), 16);
|
||||
restore();
|
||||
}
|
||||
|
||||
MiscDialog::~MiscDialog() {
|
||||
QSettings settings;
|
||||
settings.beginGroup("misc");
|
||||
settings.setValue("turboSpeed", turboSpeed_);
|
||||
settings.setValue("pauseOnDialogs", pauseOnDialogs_);
|
||||
settings.setValue("pauseOnFocusOut", pauseOnFocusOut_);
|
||||
settings.endGroup();
|
||||
settings.setValue("misc/turboSpeed", turboSpeed_);
|
||||
}
|
||||
|
||||
void MiscDialog::store() {
|
||||
turboSpeed_ = turboSpeedBox->value();
|
||||
pauseOnDialogs_ = pauseOnDialogsBox->isChecked();
|
||||
pauseOnFocusOut_ = pauseOnFocusOutBox->isChecked();
|
||||
pauseOnDialogs_.accept();
|
||||
pauseOnFocusOut_.accept();
|
||||
}
|
||||
|
||||
void MiscDialog::restore() {
|
||||
turboSpeedBox->setValue(turboSpeed_);
|
||||
pauseOnDialogsBox->setChecked(pauseOnDialogs_);
|
||||
pauseOnFocusOutBox->setChecked(pauseOnFocusOut_);
|
||||
pauseOnDialogs_.reject();
|
||||
pauseOnFocusOut_.reject();
|
||||
}
|
||||
|
||||
void MiscDialog::accept() {
|
||||
|
@ -20,26 +20,24 @@
|
||||
#define MISCDIALOG_H
|
||||
|
||||
class QSpinBox;
|
||||
class QCheckBox;
|
||||
|
||||
#include "framework/persistcheckbox.h"
|
||||
#include <QDialog>
|
||||
|
||||
class MiscDialog : public QDialog {
|
||||
QSpinBox *const turboSpeedBox;
|
||||
QCheckBox *const pauseOnDialogsBox;
|
||||
QCheckBox *const pauseOnFocusOutBox;
|
||||
PersistCheckBox pauseOnDialogs_;
|
||||
PersistCheckBox pauseOnFocusOut_;
|
||||
int turboSpeed_;
|
||||
bool pauseOnDialogs_;
|
||||
bool pauseOnFocusOut_;
|
||||
|
||||
void store();
|
||||
void restore();
|
||||
public:
|
||||
MiscDialog(QWidget *parent = 0);
|
||||
explicit MiscDialog(QWidget *parent = 0);
|
||||
~MiscDialog();
|
||||
int turboSpeed() const { return turboSpeed_; }
|
||||
bool pauseOnDialogs() const { return pauseOnDialogs_ | pauseOnFocusOut_; }
|
||||
bool pauseOnFocusOut() const { return pauseOnFocusOut_; }
|
||||
bool pauseOnDialogs() const { return pauseOnDialogs_.value() | pauseOnFocusOut_.value(); }
|
||||
bool pauseOnFocusOut() const { return pauseOnFocusOut_.value(); }
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
|
Loading…
Reference in New Issue
Block a user