SDL: Add ability to suspend screensaver

This commit is contained in:
Jeffrey Pfau 2015-05-05 22:43:44 -07:00
parent 1b74517e8b
commit b079c3bd56
12 changed files with 430 additions and 319 deletions

View File

@ -14,6 +14,7 @@ Features:
- Remappable controls for tilt and gyroscope sensors
- Status messages for actions taken while a game is running (e.g. save/load state)
- Memory inspector
- Screensaver can now be suspended while a game is running
Bugfixes:
- GBA: Fix timers not updating timing when writing to only the reload register
- All: Fix sanitize-deb script not cleaning up after itself

View File

@ -204,6 +204,9 @@ void GBAConfigMap(const struct GBAConfig* config, struct GBAOptions* opts) {
if (_lookupIntValue(config, "resampleVideo", &fakeBool)) {
opts->resampleVideo = fakeBool;
}
if (_lookupIntValue(config, "suspendScreensaver", &fakeBool)) {
opts->suspendScreensaver = fakeBool;
}
if (_lookupIntValue(config, "mute", &fakeBool)) {
opts->mute = fakeBool;
}
@ -251,6 +254,7 @@ void GBAConfigLoadDefaults(struct GBAConfig* config, const struct GBAOptions* op
ConfigurationSetIntValue(&config->defaultsTable, 0, "mute", opts->mute);
ConfigurationSetIntValue(&config->defaultsTable, 0, "lockAspectRatio", opts->lockAspectRatio);
ConfigurationSetIntValue(&config->defaultsTable, 0, "resampleVideo", opts->resampleVideo);
ConfigurationSetIntValue(&config->defaultsTable, 0, "suspendScreensaver", opts->suspendScreensaver);
switch (opts->idleOptimization) {
case IDLE_LOOP_IGNORE:

View File

@ -35,6 +35,7 @@ struct GBAOptions {
int height;
bool lockAspectRatio;
bool resampleVideo;
bool suspendScreensaver;
int volume;
bool mute;

View File

@ -114,6 +114,7 @@ ConfigController::ConfigController(QObject* parent)
m_opts.rewindBufferInterval = 0;
m_opts.rewindBufferCapacity = 0;
m_opts.useBios = true;
m_opts.suspendScreensaver = true;
GBAConfigLoadDefaults(&m_config, &m_opts);
GBAConfigLoad(&m_config);
GBAConfigMap(&m_config, &m_opts);

View File

@ -469,3 +469,17 @@ void InputController::clearPendingEvent(GBAKey key) {
bool InputController::hasPendingEvent(GBAKey key) const {
return m_pendingEvents.contains(key);
}
#if defined(BUILD_SDL) && SDL_VERSION_ATLEAST(2, 0, 0)
void InputController::suspendScreensaver() {
GBASDLSuspendScreensaver(&s_sdlEvents);
}
void InputController::resumeScreensaver() {
GBASDLResumeScreensaver(&s_sdlEvents);
}
void InputController::setScreensaverSuspendable(bool suspendable) {
GBASDLSetScreensaverSuspendable(&s_sdlEvents, suspendable);
}
#endif

View File

@ -80,6 +80,13 @@ public:
public slots:
void testGamepad(int type);
#if defined(BUILD_SDL) && SDL_VERSION_ATLEAST(2, 0, 0)
// TODO: Move these to somewhere that makes sense
void suspendScreensaver();
void resumeScreensaver();
void setScreensaverSuspendable(bool);
#endif
private:
void postPendingEvent(GBAKey);
void clearPendingEvent(GBAKey);

View File

@ -34,6 +34,7 @@ SettingsView::SettingsView(ConfigController* controller, QWidget* parent)
loadSetting("rewindBufferCapacity", m_ui.rewindCapacity);
loadSetting("resampleVideo", m_ui.resampleVideo);
loadSetting("allowOpposingDirections", m_ui.allowOpposingDirections);
loadSetting("suspendScreensaver", m_ui.suspendScreensaver);
QString idleOptimization = loadSetting("idleOptimization");
if (idleOptimization == "ignore") {
@ -87,6 +88,7 @@ void SettingsView::updateConfig() {
saveSetting("rewindBufferCapacity", m_ui.rewindCapacity);
saveSetting("resampleVideo", m_ui.resampleVideo);
saveSetting("allowOpposingDirections", m_ui.allowOpposingDirections);
saveSetting("suspendScreensaver", m_ui.suspendScreensaver);
switch (m_ui.idleOptimization->currentIndex() + IDLE_LOOP_IGNORE) {
case IDLE_LOOP_IGNORE:

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>374</width>
<height>608</height>
<width>656</width>
<height>366</height>
</rect>
</property>
<property name="sizePolicy">
@ -20,11 +20,245 @@
<string>Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Audio driver:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="audioDriver">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="audioBufferSizeLabel">
<property name="text">
<string>Audio buffer:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QComboBox" name="audioBufferSize">
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string>2048</string>
</property>
<property name="currentIndex">
<number>2</number>
</property>
<item>
<property name="text">
<string>512</string>
</property>
</item>
<item>
<property name="text">
<string>1024</string>
</property>
</item>
<item>
<property name="text">
<string>2048</string>
</property>
</item>
<item>
<property name="text">
<string>4096</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="label_16">
<property name="text">
<string>samples</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Volume:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QSlider" name="volume">
<property name="maximum">
<number>256</number>
</property>
<property name="pageStep">
<number>16</number>
</property>
<property name="value">
<number>256</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mute">
<property name="text">
<string>Mute</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Sync:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QCheckBox" name="videoSync">
<property name="text">
<string>Video</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="audioSync">
<property name="text">
<string>Audio</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Frameskip:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>Skip every</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="frameskip"/>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>frames</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>FPS target:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSpinBox" name="fpsTarget">
<property name="maximum">
<number>240</number>
</property>
<property name="value">
<number>60</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>frames per second</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="7" column="0" colspan="2">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QCheckBox" name="lockAspectRatio">
<property name="text">
<string>Lock aspect ratio</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QCheckBox" name="resampleVideo">
<property name="text">
<string>Resample video</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QCheckBox" name="suspendScreensaver">
<property name="text">
<string>Suspend screensaver</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
@ -71,238 +305,27 @@
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Audio driver:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="audioDriver">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="audioBufferSizeLabel">
<property name="text">
<string>Audio buffer:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QComboBox" name="audioBufferSize">
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string>2048</string>
</property>
<property name="currentIndex">
<number>2</number>
</property>
<item>
<property name="text">
<string>512</string>
</property>
</item>
<item>
<property name="text">
<string>1024</string>
</property>
</item>
<item>
<property name="text">
<string>2048</string>
</property>
</item>
<item>
<property name="text">
<string>4096</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>samples</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Volume:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QSlider" name="volume">
<property name="maximum">
<number>256</number>
</property>
<property name="pageStep">
<number>16</number>
</property>
<property name="value">
<number>256</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mute">
<property name="text">
<string>Mute</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="7" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Sync:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QCheckBox" name="videoSync">
<property name="text">
<string>Video</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="audioSync">
<property name="text">
<string>Audio</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Frameskip:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>Skip every</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="frameskip"/>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>frames</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>FPS target:</string>
</property>
</widget>
</item>
<item row="10" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSpinBox" name="fpsTarget">
<property name="maximum">
<number>240</number>
</property>
<property name="value">
<number>60</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>frames per second</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="11" column="1">
<widget class="QCheckBox" name="lockAspectRatio">
<property name="text">
<string>Lock aspect ratio</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QCheckBox" name="resampleVideo">
<property name="text">
<string>Resample video</string>
</property>
</widget>
</item>
<item row="13" column="0" colspan="2">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="14" column="1">
<item row="4" column="1">
<widget class="QCheckBox" name="rewind">
<property name="text">
<string>Enable rewind</string>
</property>
</widget>
</item>
<item row="15" column="0">
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Rewind interval:</string>
</property>
</widget>
</item>
<item row="15" column="1">
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLabel" name="label_5">
@ -323,14 +346,14 @@
</item>
</layout>
</item>
<item row="16" column="0">
<item row="6" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Rewind length:</string>
</property>
</widget>
</item>
<item row="16" column="1">
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QSpinBox" name="rewindCapacity"/>
@ -344,28 +367,28 @@
</item>
</layout>
</item>
<item row="17" column="1">
<item row="7" column="0" colspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QCheckBox" name="allowOpposingDirections">
<property name="text">
<string>Allow opposing input directions</string>
</property>
</widget>
</item>
<item row="18" column="0" colspan="2">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="19" column="0">
<item row="9" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Idle loops</string>
</property>
</widget>
</item>
<item row="19" column="1">
<item row="9" column="1">
<widget class="QComboBox" name="idleOptimization">
<item>
<property name="text">
@ -386,6 +409,8 @@
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">

View File

@ -89,8 +89,10 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
}
connect(m_controller, SIGNAL(gameStarted(GBAThread*)), this, SLOT(gameStarted(GBAThread*)));
connect(m_controller, SIGNAL(gameStarted(GBAThread*)), &m_inputController, SLOT(suspendScreensaver()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_display, SLOT(stopDrawing()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(gameStopped()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), &m_inputController, SLOT(resumeScreensaver()));
connect(m_controller, SIGNAL(stateLoaded(GBAThread*)), m_display, SLOT(forceDraw()));
connect(m_controller, SIGNAL(rewound(GBAThread*)), m_display, SLOT(forceDraw()));
connect(m_controller, SIGNAL(gamePaused(GBAThread*)), m_display, SLOT(pauseDrawing()));
@ -102,7 +104,9 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
}
});
#endif
connect(m_controller, SIGNAL(gamePaused(GBAThread*)), &m_inputController, SLOT(resumeScreensaver()));
connect(m_controller, SIGNAL(gameUnpaused(GBAThread*)), m_display, SLOT(unpauseDrawing()));
connect(m_controller, SIGNAL(gameUnpaused(GBAThread*)), &m_inputController, SLOT(suspendScreensaver()));
connect(m_controller, SIGNAL(postLog(int, const QString&)), m_logView, SLOT(postLog(int, const QString&)));
connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(recordFrame()));
connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), m_display, SLOT(framePosted(const uint32_t*)));
@ -192,6 +196,8 @@ void Window::loadConfig() {
enterFullScreen();
}
m_inputController.setScreensaverSuspendable(opts->suspendScreensaver);
m_mruFiles = m_config->getMRU();
updateMRU();

View File

@ -117,6 +117,11 @@ int main(int argc, char** argv) {
GBASDLPlayerLoadConfig(&renderer.player, GBAConfigGetInput(&config));
context.overrides = GBAConfigGetOverrides(&config);
#if SDL_VERSION_ATLEAST(2, 0, 0)
GBASDLSetScreensaverSuspendable(&renderer.events, opts.suspendScreensaver);
GBASDLSuspendScreensaver(&renderer.events);
#endif
int didFail = 0;
if (GBAThreadStart(&context)) {
renderer.runloop(&context, &renderer);
@ -126,6 +131,11 @@ int main(int argc, char** argv) {
printf("Could not run game. Are you sure the file exists and is a Game Boy Advance game?\n");
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
GBASDLResumeScreensaver(&renderer.events);
GBASDLSetScreensaverSuspendable(&renderer.events, false);
#endif
if (GBAThreadHasCrashed(&context)) {
didFail = 1;
printf("The game crashed!\n");

View File

@ -32,7 +32,7 @@ static void _GBASDLRotationSample(struct GBARotationSource* source);
bool GBASDLInitEvents(struct GBASDLEvents* context) {
int subsystem = SDL_INIT_JOYSTICK;
#if SDL_VERSION_ATLEAST(2, 0, 0)
subsystem |= SDL_INIT_HAPTIC;
subsystem |= SDL_INIT_HAPTIC | SDL_INIT_VIDEO;
#endif
if (SDL_InitSubSystem(subsystem) < 0) {
return false;
@ -68,6 +68,8 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) {
#if !SDL_VERSION_ATLEAST(2, 0, 0)
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
#else
context->screensaverSuspendDepth = 0;
#endif
return true;
}
@ -582,3 +584,33 @@ static void _GBASDLRotationSample(struct GBARotationSource* source) {
CircleBufferWrite32(&rotation->zHistory, theta.i);
rotation->zDelta += theta.f - oldZ;
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
void GBASDLSuspendScreensaver(struct GBASDLEvents* events) {
if (events->screensaverSuspendDepth == 0 && events->screensaverSuspendable) {
SDL_DisableScreenSaver();
}
++events->screensaverSuspendDepth;
}
void GBASDLResumeScreensaver(struct GBASDLEvents* events) {
--events->screensaverSuspendDepth;
if (events->screensaverSuspendDepth == 0 && events->screensaverSuspendable) {
SDL_EnableScreenSaver();
}
}
void GBASDLSetScreensaverSuspendable(struct GBASDLEvents* events, bool suspendable) {
bool wasSuspendable = events->screensaverSuspendable;
events->screensaverSuspendable = suspendable;
if (events->screensaverSuspendDepth > 0) {
if (suspendable && !wasSuspendable) {
SDL_DisableScreenSaver();
} else if (!suspendable && wasSuspendable) {
SDL_EnableScreenSaver();
}
} else {
SDL_EnableScreenSaver();
}
}
#endif

View File

@ -29,6 +29,8 @@ struct GBASDLEvents {
size_t joysticksClaimed[MAX_PLAYERS];
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Haptic** haptic;
int screensaverSuspendDepth;
bool screensaverSuspendable;
#endif
};
@ -82,4 +84,10 @@ void GBASDLPlayerSaveConfig(const struct GBASDLPlayer*, struct Configuration*);
void GBASDLHandleEvent(struct GBAThread* context, struct GBASDLPlayer* sdlContext, const union SDL_Event* event);
#if SDL_VERSION_ATLEAST(2, 0, 0)
void GBASDLSuspendScreensaver(struct GBASDLEvents*);
void GBASDLResumeScreensaver(struct GBASDLEvents*);
void GBASDLSetScreensaverSuspendable(struct GBASDLEvents*, bool suspendable);
#endif
#endif