mirror of https://github.com/bsnes-emu/bsnes.git
Update to v094r22 release.
byuu says: I fixed the hiro layout enable bug, so when you go to assign joypad input, the window disables itself so your input doesn't mess with the controls. I added "reset" to the hotkeys, in case you feel like clearing all of them at once. I added device selection support and the ability to disable audio synchronization (run > 60fps) to the ruby/OSS driver. This is exposed in tomoko's configuration file. I added checks to stringify so that assigning null char* strings to nall::string won't cause crashes anymore (technically the crash was in strlen(), which doesn't check for null strings, but whatever ... I'll do the check myself.) I hooked up BrowserDialog::folderSelect() to loading slotted media for now. Tested it by loading a Game Boy game successfully through the Super Game Boy. Definitely want to write a custom window for this though, that looks more like the library dialog. Remaining issues: - finish slotted cart loader (SGB, BSX, ST) - add DIP switch selection window (NSS) [I may end up punting this one to v096] - add more configuration panels (video, audio, timing)
This commit is contained in:
parent
99b2b4b57c
commit
7bf4cff946
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace Emulator {
|
||||
static const char Name[] = "higan";
|
||||
static const char Version[] = "094.21";
|
||||
static const char Version[] = "094.22";
|
||||
static const char Author[] = "byuu";
|
||||
static const char License[] = "GPLv3";
|
||||
static const char Website[] = "http://byuu.org/";
|
||||
|
|
|
@ -31,7 +31,7 @@ auto mFixedLayout::reset() -> type& {
|
|||
auto mFixedLayout::setEnabled(bool enabled) -> type& {
|
||||
mLayout::setEnabled(enabled);
|
||||
for(auto n : range(sizables())) {
|
||||
sizable(n)->setEnabled(sizable(n)->enabled(true));
|
||||
sizable(n)->setEnabled(sizable(n)->enabled());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ auto mFixedLayout::setEnabled(bool enabled) -> type& {
|
|||
auto mFixedLayout::setFont(const string& font) -> type& {
|
||||
mLayout::setFont(font);
|
||||
for(auto n : range(sizables())) {
|
||||
sizable(n)->setFont(sizable(n)->font(true));
|
||||
sizable(n)->setFont(sizable(n)->font());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ auto mFixedLayout::setFont(const string& font) -> type& {
|
|||
auto mFixedLayout::setVisible(bool visible) -> type& {
|
||||
mLayout::setVisible(visible);
|
||||
for(auto n : range(sizables())) {
|
||||
sizable(n)->setVisible(sizable(n)->visible(true));
|
||||
sizable(n)->setVisible(sizable(n)->visible());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ auto mHorizontalLayout::setAlignment(double alignment) -> type& {
|
|||
auto mHorizontalLayout::setEnabled(bool enabled) -> type& {
|
||||
mLayout::setEnabled(enabled);
|
||||
for(auto n : range(sizables())) {
|
||||
sizable(n)->setEnabled(sizable(n)->enabled(true));
|
||||
sizable(n)->setEnabled(sizable(n)->enabled());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ auto mHorizontalLayout::setEnabled(bool enabled) -> type& {
|
|||
auto mHorizontalLayout::setFont(const string& font) -> type& {
|
||||
mLayout::setFont(font);
|
||||
for(auto n : range(sizables())) {
|
||||
sizable(n)->setFont(sizable(n)->font(true));
|
||||
sizable(n)->setFont(sizable(n)->font());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ auto mHorizontalLayout::setSpacing(signed spacing) -> type& {
|
|||
auto mHorizontalLayout::setVisible(bool visible) -> type& {
|
||||
mLayout::setVisible(visible);
|
||||
for(auto n : range(sizables())) {
|
||||
sizable(n)->setVisible(sizable(n)->visible(true));
|
||||
sizable(n)->setVisible(sizable(n)->visible());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ auto mVerticalLayout::setAlignment(double alignment) -> type& {
|
|||
auto mVerticalLayout::setEnabled(bool enabled) -> type& {
|
||||
mLayout::setEnabled(enabled);
|
||||
for(auto n : range(sizables())) {
|
||||
sizable(n)->setEnabled(sizable(n)->enabled(true));
|
||||
sizable(n)->setEnabled(sizable(n)->enabled());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ auto mVerticalLayout::setEnabled(bool enabled) -> type& {
|
|||
auto mVerticalLayout::setFont(const string& font) -> type& {
|
||||
mLayout::setFont(font);
|
||||
for(auto n : range(sizables())) {
|
||||
sizable(n)->setFont(sizable(n)->font(true));
|
||||
sizable(n)->setFont(sizable(n)->font());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ auto mVerticalLayout::setSpacing(signed spacing) -> type& {
|
|||
auto mVerticalLayout::setVisible(bool visible) -> type& {
|
||||
mLayout::setVisible(visible);
|
||||
for(auto n : range(sizables())) {
|
||||
sizable(n)->setVisible(sizable(n)->visible(true));
|
||||
sizable(n)->setVisible(sizable(n)->visible());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -11,21 +11,12 @@ auto pLayout::destruct() -> void {
|
|||
}
|
||||
|
||||
auto pLayout::setEnabled(bool enabled) -> void {
|
||||
for(auto& sizable : state().sizables) {
|
||||
if(sizable->self()) sizable->self()->setEnabled(sizable->enabled(true));
|
||||
}
|
||||
}
|
||||
|
||||
auto pLayout::setFont(const string& font) -> void {
|
||||
for(auto& sizable : state().sizables) {
|
||||
if(sizable->self()) sizable->self()->setFont(sizable->font(true));
|
||||
}
|
||||
}
|
||||
|
||||
auto pLayout::setVisible(bool visible) -> void {
|
||||
for(auto& sizable : state().sizables) {
|
||||
if(sizable->self()) sizable->self()->setVisible(sizable->visible(true));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -160,14 +160,14 @@ template<> struct stringify<char*> {
|
|||
const char* _data;
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
stringify(char* source) : _data(source) {}
|
||||
stringify(char* source) : _data(source ? source : "") {}
|
||||
};
|
||||
|
||||
template<> struct stringify<const char*> {
|
||||
const char* _data;
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
stringify(const char* source) : _data(source) {}
|
||||
stringify(const char* source) : _data(source ? source : "") {}
|
||||
};
|
||||
|
||||
//strings
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
struct Audio {
|
||||
static const char* Handle;
|
||||
static const char* Synchronize;
|
||||
static const char* Frequency;
|
||||
static const char* Latency;
|
||||
static const nall::string Device;
|
||||
static const nall::string Handle;
|
||||
static const nall::string Synchronize;
|
||||
static const nall::string Frequency;
|
||||
static const nall::string Latency;
|
||||
|
||||
virtual bool cap(const nall::string& name) { return false; }
|
||||
virtual nall::any get(const nall::string& name) { return false; }
|
||||
virtual bool set(const nall::string& name, const nall::any& value) { return false; }
|
||||
virtual ~Audio() = default;
|
||||
|
||||
virtual void sample(uint16_t left, uint16_t right) {}
|
||||
virtual void clear() {}
|
||||
virtual bool init() { return true; }
|
||||
virtual void term() {}
|
||||
virtual auto cap(const nall::string& name) -> bool { return false; }
|
||||
virtual auto get(const nall::string& name) -> nall::any { return false; }
|
||||
virtual auto set(const nall::string& name, const nall::any& value) -> bool { return false; }
|
||||
|
||||
Audio() {}
|
||||
virtual ~Audio() {}
|
||||
virtual auto sample(uint16_t left, uint16_t right) -> void {}
|
||||
virtual auto clear() -> void {}
|
||||
|
||||
virtual auto init() -> bool { return true; }
|
||||
virtual auto term() -> void {}
|
||||
};
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
/*
|
||||
audio.openal (2007-12-26)
|
||||
author: Nach
|
||||
contributors: byuu, wertigon, _willow_
|
||||
*/
|
||||
|
||||
#if defined(PLATFORM_MACOSX)
|
||||
#include <OpenAL/al.h>
|
||||
#include <OpenAL/alc.h>
|
||||
|
@ -14,15 +8,14 @@
|
|||
|
||||
namespace ruby {
|
||||
|
||||
class pAudioOpenAL {
|
||||
public:
|
||||
struct pAudioOpenAL {
|
||||
struct {
|
||||
ALCdevice* handle;
|
||||
ALCcontext* context;
|
||||
ALuint source;
|
||||
ALenum format;
|
||||
unsigned latency;
|
||||
unsigned queue_length;
|
||||
unsigned queueLength;
|
||||
} device;
|
||||
|
||||
struct {
|
||||
|
@ -37,21 +30,21 @@ public:
|
|||
unsigned latency;
|
||||
} settings;
|
||||
|
||||
bool cap(const string& name) {
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Audio::Synchronize) return true;
|
||||
if(name == Audio::Frequency) return true;
|
||||
if(name == Audio::Latency) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
any get(const string& name) {
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Audio::Synchronize) return settings.synchronize;
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
if(name == Audio::Latency) return settings.latency;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set(const string& name, const any& value) {
|
||||
auto set(const string& name, const any& value) -> bool {
|
||||
if(name == Audio::Synchronize) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
return true;
|
||||
|
@ -65,7 +58,7 @@ public:
|
|||
if(name == Audio::Latency) {
|
||||
if(settings.latency != any_cast<unsigned>(value)) {
|
||||
settings.latency = any_cast<unsigned>(value);
|
||||
update_latency();
|
||||
updateLatency();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -73,7 +66,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
void sample(uint16_t sl, uint16_t sr) {
|
||||
auto sample(uint16_t sl, uint16_t sr) -> void {
|
||||
buffer.data[buffer.length++] = sl + (sr << 16);
|
||||
if(buffer.length < buffer.size) return;
|
||||
|
||||
|
@ -84,17 +77,17 @@ public:
|
|||
while(processed--) {
|
||||
alSourceUnqueueBuffers(device.source, 1, &albuffer);
|
||||
alDeleteBuffers(1, &albuffer);
|
||||
device.queue_length--;
|
||||
device.queueLength--;
|
||||
}
|
||||
//wait for buffer playback to catch up to sample generation if not synchronizing
|
||||
if(settings.synchronize == false || device.queue_length < 3) break;
|
||||
if(settings.synchronize == false || device.queueLength < 3) break;
|
||||
}
|
||||
|
||||
if(device.queue_length < 3) {
|
||||
if(device.queueLength < 3) {
|
||||
alGenBuffers(1, &albuffer);
|
||||
alBufferData(albuffer, device.format, buffer.data, buffer.size * 4, settings.frequency);
|
||||
alSourceQueueBuffers(device.source, 1, &albuffer);
|
||||
device.queue_length++;
|
||||
device.queueLength++;
|
||||
}
|
||||
|
||||
ALint playing;
|
||||
|
@ -103,22 +96,16 @@ public:
|
|||
buffer.length = 0;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
auto clear() -> void {
|
||||
}
|
||||
|
||||
void update_latency() {
|
||||
if(buffer.data) delete[] buffer.data;
|
||||
buffer.size = settings.frequency * settings.latency / 1000.0 + 0.5;
|
||||
buffer.data = new uint32_t[buffer.size];
|
||||
}
|
||||
|
||||
bool init() {
|
||||
update_latency();
|
||||
device.queue_length = 0;
|
||||
auto init() -> bool {
|
||||
updateLatency();
|
||||
device.queueLength = 0;
|
||||
|
||||
bool success = false;
|
||||
if(device.handle = alcOpenDevice(NULL)) {
|
||||
if(device.context = alcCreateContext(device.handle, NULL)) {
|
||||
if(device.handle = alcOpenDevice(nullptr)) {
|
||||
if(device.context = alcCreateContext(device.handle, nullptr)) {
|
||||
alcMakeContextCurrent(device.context);
|
||||
alGenSources(1, &device.source);
|
||||
|
||||
|
@ -147,7 +134,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
if(alIsSource(device.source) == AL_TRUE) {
|
||||
int playing = 0;
|
||||
alGetSourcei(device.source, AL_SOURCE_STATE, &playing);
|
||||
|
@ -159,7 +146,7 @@ public:
|
|||
ALuint albuffer = 0;
|
||||
alSourceUnqueueBuffers(device.source, 1, &albuffer);
|
||||
alDeleteBuffers(1, &albuffer);
|
||||
device.queue_length--;
|
||||
device.queueLength--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +155,7 @@ public:
|
|||
}
|
||||
|
||||
if(device.context) {
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcMakeContextCurrent(nullptr);
|
||||
alcDestroyContext(device.context);
|
||||
device.context = 0;
|
||||
}
|
||||
|
@ -189,7 +176,7 @@ public:
|
|||
device.handle = 0;
|
||||
device.context = 0;
|
||||
device.format = AL_FORMAT_STEREO16;
|
||||
device.queue_length = 0;
|
||||
device.queueLength = 0;
|
||||
|
||||
buffer.data = 0;
|
||||
buffer.length = 0;
|
||||
|
@ -203,6 +190,27 @@ public:
|
|||
~pAudioOpenAL() {
|
||||
term();
|
||||
}
|
||||
|
||||
private:
|
||||
auto queryDevices() -> lstring {
|
||||
lstring result;
|
||||
|
||||
const char* buffer = alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
|
||||
if(!buffer) return result;
|
||||
|
||||
while(buffer[0] || buffer[1]) {
|
||||
result.append(buffer);
|
||||
while(buffer[0]) buffer++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto updateLatency() -> void {
|
||||
if(buffer.data) delete[] buffer.data;
|
||||
buffer.size = settings.frequency * settings.latency / 1000.0 + 0.5;
|
||||
buffer.data = new uint32_t[buffer.size]();
|
||||
}
|
||||
};
|
||||
|
||||
DeclareAudio(OpenAL)
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
/*
|
||||
audio.oss (2007-12-26)
|
||||
author: Nach
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
@ -16,95 +11,112 @@
|
|||
//Failing that, one can disable OSS4 ioctl calls inside init() and remove the below defines
|
||||
|
||||
#ifndef SNDCTL_DSP_COOKEDMODE
|
||||
#define SNDCTL_DSP_COOKEDMODE _IOW('P', 30, int)
|
||||
#define SNDCTL_DSP_COOKEDMODE _IOW('P', 30, signed)
|
||||
#endif
|
||||
|
||||
#ifndef SNDCTL_DSP_POLICY
|
||||
#define SNDCTL_DSP_POLICY _IOW('P', 45, int)
|
||||
#define SNDCTL_DSP_POLICY _IOW('P', 45, signed)
|
||||
#endif
|
||||
|
||||
namespace ruby {
|
||||
|
||||
class pAudioOSS {
|
||||
public:
|
||||
struct pAudioOSS {
|
||||
struct {
|
||||
int fd;
|
||||
int format;
|
||||
int channels;
|
||||
const char* name;
|
||||
signed fd = -1;
|
||||
signed format = AFMT_S16_LE;
|
||||
signed channels = 2;
|
||||
} device;
|
||||
|
||||
struct {
|
||||
unsigned frequency;
|
||||
string device = "/dev/dsp";
|
||||
bool synchronize = true;
|
||||
unsigned frequency = 22050;
|
||||
} settings;
|
||||
|
||||
bool cap(const string& name) {
|
||||
~pAudioOSS() {
|
||||
term();
|
||||
}
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Audio::Device) return true;
|
||||
if(name == Audio::Synchronize) return true;
|
||||
if(name == Audio::Frequency) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
any get(const string& name) {
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Audio::Device) return settings.device;
|
||||
if(name == Audio::Synchronize) return settings.synchronize;
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool set(const string& name, const any& value) {
|
||||
auto set(const string& name, const any& value) -> bool {
|
||||
if(name == Audio::Device) {
|
||||
settings.device = any_cast<string>(value);
|
||||
if(!settings.device) settings.device = "/dev/dsp";
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Audio::Synchronize) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
updateSynchronization();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Audio::Frequency) {
|
||||
settings.frequency = any_cast<unsigned>(value);
|
||||
if(device.fd > 0) init();
|
||||
if(device.fd >= 0) init();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void sample(uint16_t sl, uint16_t sr) {
|
||||
uint32_t sample = sl + (sr << 16);
|
||||
unsigned unused = write(device.fd, &sample, 4);
|
||||
auto sample(uint16_t left, uint16_t right) -> void {
|
||||
uint32_t sample = left << 0 | right << 16;
|
||||
auto unused = write(device.fd, &sample, 4);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
auto clear() -> void {
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
term();
|
||||
|
||||
device.fd = open(device.name, O_WRONLY, O_NONBLOCK);
|
||||
device.fd = open(settings.device, O_WRONLY, O_NONBLOCK);
|
||||
if(device.fd < 0) return false;
|
||||
|
||||
#if 1 //SOUND_VERSION >= 0x040000
|
||||
//attempt to enable OSS4-specific features regardless of version
|
||||
//OSS3 ioctl calls will silently fail, but sound will still work
|
||||
int cooked = 1, policy = 4; //policy should be 0 - 10, lower = less latency, more CPU usage
|
||||
signed cooked = 1, policy = 4; //policy should be 0 - 10, lower = less latency, more CPU usage
|
||||
ioctl(device.fd, SNDCTL_DSP_COOKEDMODE, &cooked);
|
||||
ioctl(device.fd, SNDCTL_DSP_POLICY, &policy);
|
||||
#endif
|
||||
int freq = settings.frequency;
|
||||
signed freq = settings.frequency;
|
||||
ioctl(device.fd, SNDCTL_DSP_CHANNELS, &device.channels);
|
||||
ioctl(device.fd, SNDCTL_DSP_SETFMT, &device.format);
|
||||
ioctl(device.fd, SNDCTL_DSP_SPEED, &freq);
|
||||
|
||||
updateSynchronization();
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
if(device.fd > 0) {
|
||||
auto term() -> void {
|
||||
if(device.fd >= 0) {
|
||||
close(device.fd);
|
||||
device.fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
pAudioOSS() {
|
||||
device.fd = -1;
|
||||
device.format = AFMT_S16_LE;
|
||||
device.channels = 2;
|
||||
device.name = "/dev/dsp";
|
||||
|
||||
settings.frequency = 22050;
|
||||
}
|
||||
|
||||
~pAudioOSS() {
|
||||
term();
|
||||
private:
|
||||
auto updateSynchronization() -> void {
|
||||
if(device.fd < 0) return;
|
||||
auto flags = fcntl(device.fd, F_GETFL);
|
||||
if(flags < 0) return;
|
||||
settings.synchronize ? flags &=~ O_NONBLOCK : flags |= O_NONBLOCK;
|
||||
fcntl(device.fd, F_SETFL, flags);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,21 +19,21 @@ using namespace nall;
|
|||
|
||||
#define DeclareVideo(Name) \
|
||||
struct Video##Name : Video { \
|
||||
bool cap(const string& name) { return p.cap(name); } \
|
||||
any get(const string& name) { return p.get(name); } \
|
||||
bool set(const string& name, const any& value) { return p.set(name, value); } \
|
||||
\
|
||||
bool lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) { return p.lock(data, pitch, width, height); } \
|
||||
void unlock() { p.unlock(); } \
|
||||
\
|
||||
void clear() { p.clear(); } \
|
||||
void refresh() { p.refresh(); } \
|
||||
bool init() { return p.init(); } \
|
||||
void term() { p.term(); } \
|
||||
\
|
||||
Video##Name() : p(*new pVideo##Name) {} \
|
||||
~Video##Name() { delete &p; } \
|
||||
\
|
||||
auto cap(const string& name) -> bool { return p.cap(name); } \
|
||||
auto get(const string& name) -> any { return p.get(name); } \
|
||||
auto set(const string& name, const any& value) -> bool { return p.set(name, value); } \
|
||||
\
|
||||
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool { return p.lock(data, pitch, width, height); } \
|
||||
auto unlock() -> void { p.unlock(); } \
|
||||
auto clear() -> void { p.clear(); } \
|
||||
auto refresh() -> void { p.refresh(); } \
|
||||
\
|
||||
auto init() -> bool { return p.init(); } \
|
||||
auto term() -> void { p.term(); } \
|
||||
\
|
||||
private: \
|
||||
pVideo##Name& p; \
|
||||
};
|
||||
|
@ -78,18 +78,19 @@ using namespace nall;
|
|||
|
||||
#define DeclareAudio(Name) \
|
||||
struct Audio##Name : Audio { \
|
||||
bool cap(const string& name) { return p.cap(name); } \
|
||||
any get(const string& name) { return p.get(name); } \
|
||||
bool set(const string& name, const any& value) { return p.set(name, value); } \
|
||||
\
|
||||
void sample(uint16_t left, uint16_t right) { p.sample(left, right); } \
|
||||
void clear() { p.clear(); } \
|
||||
bool init() { return p.init(); } \
|
||||
void term() { p.term(); } \
|
||||
\
|
||||
Audio##Name() : p(*new pAudio##Name) {} \
|
||||
~Audio##Name() { delete &p; } \
|
||||
\
|
||||
auto cap(const string& name) -> bool { return p.cap(name); } \
|
||||
auto get(const string& name) -> any { return p.get(name); } \
|
||||
auto set(const string& name, const any& value) -> bool { return p.set(name, value); } \
|
||||
\
|
||||
auto sample(uint16_t left, uint16_t right) -> void { p.sample(left, right); } \
|
||||
auto clear() -> void { p.clear(); } \
|
||||
\
|
||||
auto init() -> bool { return p.init(); } \
|
||||
auto term() -> void { p.term(); } \
|
||||
\
|
||||
private: \
|
||||
pAudio##Name& p; \
|
||||
};
|
||||
|
@ -140,9 +141,9 @@ using namespace nall;
|
|||
auto acquire() -> bool { return p.acquire(); } \
|
||||
auto unacquire() -> bool { return p.unacquire(); } \
|
||||
auto acquired() -> bool { return p.acquired(); } \
|
||||
\
|
||||
auto poll() -> vector<shared_pointer<HID::Device>> { return p.poll(); } \
|
||||
auto rumble(uint64_t id, bool enable) -> bool { return p.rumble(id, enable); } \
|
||||
\
|
||||
auto init() -> bool { return p.init(); } \
|
||||
auto term() -> void { p.term(); } \
|
||||
\
|
||||
|
|
|
@ -5,7 +5,6 @@ struct Input {
|
|||
static const nall::string JoypadSupport;
|
||||
static const nall::string JoypadRumbleSupport;
|
||||
|
||||
Input() = default;
|
||||
virtual ~Input() = default;
|
||||
|
||||
virtual auto cap(const nall::string& name) -> bool { return false; }
|
||||
|
@ -15,9 +14,9 @@ struct Input {
|
|||
virtual auto acquire() -> bool { return false; }
|
||||
virtual auto unacquire() -> bool { return false; }
|
||||
virtual auto acquired() -> bool { return false; }
|
||||
|
||||
virtual auto poll() -> nall::vector<nall::shared_pointer<nall::HID::Device>> { return {}; }
|
||||
virtual auto rumble(uint64_t id, bool enable) -> bool { return false; }
|
||||
|
||||
virtual auto init() -> bool { return true; }
|
||||
virtual auto term() -> void {}
|
||||
};
|
||||
|
|
111
ruby/ruby.cpp
111
ruby/ruby.cpp
|
@ -13,70 +13,70 @@ InputInterface input;
|
|||
|
||||
/* VideoInterface */
|
||||
|
||||
const char* Video::Handle = "Handle";
|
||||
const char* Video::Synchronize = "Synchronize";
|
||||
const char* Video::Depth = "Depth";
|
||||
const char* Video::Filter = "Filter";
|
||||
const char* Video::Shader = "Shader";
|
||||
const string Video::Handle = "Handle";
|
||||
const string Video::Synchronize = "Synchronize";
|
||||
const string Video::Depth = "Depth";
|
||||
const string Video::Filter = "Filter";
|
||||
const string Video::Shader = "Shader";
|
||||
|
||||
const unsigned Video::FilterNearest = 0;
|
||||
const unsigned Video::FilterLinear = 1;
|
||||
|
||||
void VideoInterface::driver(const char* driver) {
|
||||
auto VideoInterface::driver(string driver) -> void {
|
||||
if(p) term();
|
||||
|
||||
if(!driver || !*driver) driver = optimalDriver();
|
||||
if(!driver) driver = optimalDriver();
|
||||
|
||||
if(0);
|
||||
|
||||
#ifdef VIDEO_CGL
|
||||
else if(!strcmp(driver, "OpenGL")) p = new VideoCGL();
|
||||
else if(driver == "OpenGL") p = new VideoCGL();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_DIRECT3D
|
||||
else if(!strcmp(driver, "Direct3D")) p = new VideoD3D();
|
||||
else if(driver == "Direct3D") p = new VideoD3D();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_DIRECTDRAW
|
||||
else if(!strcmp(driver, "DirectDraw")) p = new VideoDD();
|
||||
else if(driver == "DirectDraw") p = new VideoDD();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_GDI
|
||||
else if(!strcmp(driver, "GDI")) p = new VideoGDI();
|
||||
else if(driver == "GDI") p = new VideoGDI();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_GLX
|
||||
else if(!strcmp(driver, "OpenGL")) p = new VideoGLX();
|
||||
else if(driver == "OpenGL") p = new VideoGLX();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_QTOPENGL
|
||||
else if(!strcmp(driver, "Qt-OpenGL")) p = new VideoQtOpenGL();
|
||||
else if(driver == "Qt-OpenGL") p = new VideoQtOpenGL();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_QTRASTER
|
||||
else if(!strcmp(driver, "Qt-Raster")) p = new VideoQtRaster();
|
||||
else if(driver == "Qt-Raster") p = new VideoQtRaster();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_SDL
|
||||
else if(!strcmp(driver, "SDL")) p = new VideoSDL();
|
||||
else if(driver == "SDL") p = new VideoSDL();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_WGL
|
||||
else if(!strcmp(driver, "OpenGL")) p = new VideoWGL();
|
||||
else if(driver == "OpenGL") p = new VideoWGL();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_XSHM
|
||||
else if(!strcmp(driver, "XShm")) p = new VideoXShm();
|
||||
else if(driver == "XShm") p = new VideoXShm();
|
||||
#endif
|
||||
|
||||
#ifdef VIDEO_XV
|
||||
else if(!strcmp(driver, "X-Video")) p = new VideoXv();
|
||||
else if(driver == "X-Video") p = new VideoXv();
|
||||
#endif
|
||||
|
||||
else p = new Video();
|
||||
}
|
||||
|
||||
const char* VideoInterface::optimalDriver() {
|
||||
auto VideoInterface::optimalDriver() -> string {
|
||||
#if defined(VIDEO_WGL)
|
||||
return "OpenGL";
|
||||
#elif defined(VIDEO_DIRECT3D)
|
||||
|
@ -103,7 +103,7 @@ const char* VideoInterface::optimalDriver() {
|
|||
#endif
|
||||
}
|
||||
|
||||
const char* VideoInterface::safestDriver() {
|
||||
auto VideoInterface::safestDriver() -> string {
|
||||
#if defined(VIDEO_DIRECT3D)
|
||||
return "Direct3D";
|
||||
#elif defined(VIDEO_WGL)
|
||||
|
@ -130,7 +130,7 @@ const char* VideoInterface::safestDriver() {
|
|||
#endif
|
||||
}
|
||||
|
||||
const char* VideoInterface::availableDrivers() {
|
||||
auto VideoInterface::availableDrivers() -> string {
|
||||
return
|
||||
|
||||
//Windows
|
||||
|
@ -178,12 +178,12 @@ const char* VideoInterface::availableDrivers() {
|
|||
"None";
|
||||
}
|
||||
|
||||
bool VideoInterface::init() {
|
||||
auto VideoInterface::init() -> bool {
|
||||
if(!p) driver();
|
||||
return p->init();
|
||||
}
|
||||
|
||||
void VideoInterface::term() {
|
||||
auto VideoInterface::term() -> void {
|
||||
if(p) {
|
||||
p->term();
|
||||
delete p;
|
||||
|
@ -191,66 +191,66 @@ void VideoInterface::term() {
|
|||
}
|
||||
}
|
||||
|
||||
bool VideoInterface::cap(const string& name) { return p ? p->cap(name) : false; }
|
||||
any VideoInterface::get(const string& name) { return p ? p->get(name) : false; }
|
||||
bool VideoInterface::set(const string& name, const any& value) { return p ? p->set(name, value) : false; }
|
||||
bool VideoInterface::lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) { return p ? p->lock(data, pitch, width, height) : false; }
|
||||
void VideoInterface::unlock() { if(p) p->unlock(); }
|
||||
void VideoInterface::clear() { if(p) p->clear(); }
|
||||
void VideoInterface::refresh() { if(p) p->refresh(); }
|
||||
VideoInterface::VideoInterface() : p(nullptr) {}
|
||||
VideoInterface::~VideoInterface() { term(); }
|
||||
auto VideoInterface::cap(const string& name) -> bool { return p ? p->cap(name) : false; }
|
||||
auto VideoInterface::get(const string& name) -> any { return p ? p->get(name) : false; }
|
||||
auto VideoInterface::set(const string& name, const any& value) -> bool { return p ? p->set(name, value) : false; }
|
||||
auto VideoInterface::lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool { return p ? p->lock(data, pitch, width, height) : false; }
|
||||
auto VideoInterface::unlock() -> void { if(p) p->unlock(); }
|
||||
auto VideoInterface::clear() -> void { if(p) p->clear(); }
|
||||
auto VideoInterface::refresh() -> void { if(p) p->refresh(); }
|
||||
|
||||
/* AudioInterface */
|
||||
|
||||
const char* Audio::Handle = "Handle";
|
||||
const char* Audio::Synchronize = "Synchronize";
|
||||
const char* Audio::Frequency = "Frequency";
|
||||
const char* Audio::Latency = "Latency";
|
||||
const string Audio::Device = "Device";
|
||||
const string Audio::Handle = "Handle";
|
||||
const string Audio::Synchronize = "Synchronize";
|
||||
const string Audio::Frequency = "Frequency";
|
||||
const string Audio::Latency = "Latency";
|
||||
|
||||
void AudioInterface::driver(const char* driver) {
|
||||
auto AudioInterface::driver(string driver) -> void {
|
||||
if(p) term();
|
||||
|
||||
if(!driver || !*driver) driver = optimalDriver();
|
||||
if(!driver) driver = optimalDriver();
|
||||
|
||||
if(0);
|
||||
|
||||
#ifdef AUDIO_ALSA
|
||||
else if(!strcmp(driver, "ALSA")) p = new AudioALSA();
|
||||
else if(driver == "ALSA") p = new AudioALSA();
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_AO
|
||||
else if(!strcmp(driver, "libao")) p = new AudioAO();
|
||||
else if(driver == "libao") p = new AudioAO();
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_DIRECTSOUND
|
||||
else if(!strcmp(driver, "DirectSound")) p = new AudioDS();
|
||||
else if(driver == "DirectSound") p = new AudioDS();
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_OPENAL
|
||||
else if(!strcmp(driver, "OpenAL")) p = new AudioOpenAL();
|
||||
else if(driver == "OpenAL") p = new AudioOpenAL();
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_OSS
|
||||
else if(!strcmp(driver, "OSS")) p = new AudioOSS();
|
||||
else if(driver == "OSS") p = new AudioOSS();
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_PULSEAUDIO
|
||||
else if(!strcmp(driver, "PulseAudio")) p = new AudioPulseAudio();
|
||||
else if(driver == "PulseAudio") p = new AudioPulseAudio();
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_PULSEAUDIOSIMPLE
|
||||
else if(!strcmp(driver, "PulseAudioSimple")) p = new AudioPulseAudioSimple();
|
||||
else if(driver == "PulseAudioSimple") p = new AudioPulseAudioSimple();
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_XAUDIO2
|
||||
else if(!strcmp(driver, "XAudio2")) p = new AudioXAudio2();
|
||||
else if(driver == "XAudio2") p = new AudioXAudio2();
|
||||
#endif
|
||||
|
||||
else p = new Audio();
|
||||
}
|
||||
|
||||
const char* AudioInterface::optimalDriver() {
|
||||
auto AudioInterface::optimalDriver() -> string {
|
||||
#if defined(AUDIO_XAUDIO2)
|
||||
return "XAudio2";
|
||||
#elif defined(AUDIO_DIRECTSOUND)
|
||||
|
@ -274,7 +274,7 @@ const char* AudioInterface::optimalDriver() {
|
|||
#endif
|
||||
}
|
||||
|
||||
const char* AudioInterface::safestDriver() {
|
||||
auto AudioInterface::safestDriver() -> string {
|
||||
#if defined(AUDIO_DIRECTSOUND)
|
||||
return "DirectSound";
|
||||
#elif defined(AUDIO_XAUDIO2)
|
||||
|
@ -298,7 +298,7 @@ const char* AudioInterface::safestDriver() {
|
|||
#endif
|
||||
}
|
||||
|
||||
const char* AudioInterface::availableDrivers() {
|
||||
auto AudioInterface::availableDrivers() -> string {
|
||||
return
|
||||
|
||||
//Windows
|
||||
|
@ -340,12 +340,12 @@ const char* AudioInterface::availableDrivers() {
|
|||
"None";
|
||||
}
|
||||
|
||||
bool AudioInterface::init() {
|
||||
auto AudioInterface::init() -> bool {
|
||||
if(!p) driver();
|
||||
return p->init();
|
||||
}
|
||||
|
||||
void AudioInterface::term() {
|
||||
auto AudioInterface::term() -> void {
|
||||
if(p) {
|
||||
p->term();
|
||||
delete p;
|
||||
|
@ -353,13 +353,12 @@ void AudioInterface::term() {
|
|||
}
|
||||
}
|
||||
|
||||
bool AudioInterface::cap(const string& name) { return p ? p->cap(name) : false; }
|
||||
any AudioInterface::get(const string& name) { return p ? p->get(name) : false; }
|
||||
bool AudioInterface::set(const string& name, const any& value) { return p ? p->set(name, value) : false; }
|
||||
void AudioInterface::sample(uint16_t left, uint16_t right) { if(p) p->sample(left, right); }
|
||||
void AudioInterface::clear() { if(p) p->clear(); }
|
||||
AudioInterface::AudioInterface() : p(nullptr) {}
|
||||
AudioInterface::~AudioInterface() { term(); }
|
||||
auto AudioInterface::cap(const string& name) -> bool { return p ? p->cap(name) : false; }
|
||||
auto AudioInterface::get(const string& name) -> any { return p ? p->get(name) : false; }
|
||||
auto AudioInterface::set(const string& name, const any& value) -> bool { return p ? p->set(name, value) : false; }
|
||||
auto AudioInterface::sample(uint16_t left, uint16_t right) -> void { if(p) p->sample(left, right); }
|
||||
auto AudioInterface::clear() -> void { if(p) p->clear(); }
|
||||
|
||||
/* InputInterface */
|
||||
|
||||
|
|
|
@ -19,47 +19,45 @@ namespace ruby {
|
|||
#include <ruby/input.hpp>
|
||||
|
||||
struct VideoInterface {
|
||||
void driver(const char* driver = "");
|
||||
const char* optimalDriver();
|
||||
const char* safestDriver();
|
||||
const char* availableDrivers();
|
||||
bool init();
|
||||
void term();
|
||||
|
||||
bool cap(const nall::string& name);
|
||||
nall::any get(const nall::string& name);
|
||||
bool set(const nall::string& name, const nall::any& value);
|
||||
|
||||
bool lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height);
|
||||
void unlock();
|
||||
void clear();
|
||||
void refresh();
|
||||
|
||||
VideoInterface();
|
||||
~VideoInterface();
|
||||
|
||||
auto driver(nall::string driver = "") -> void;
|
||||
auto optimalDriver() -> nall::string;
|
||||
auto safestDriver() -> nall::string;
|
||||
auto availableDrivers() -> nall::string;
|
||||
auto init() -> bool;
|
||||
auto term() -> void;
|
||||
|
||||
auto cap(const nall::string& name) -> bool;
|
||||
auto get(const nall::string& name) -> nall::any;
|
||||
auto set(const nall::string& name, const nall::any& value) -> bool;
|
||||
|
||||
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool;
|
||||
auto unlock() -> void;
|
||||
auto clear() -> void;
|
||||
auto refresh() -> void;
|
||||
|
||||
private:
|
||||
Video* p = nullptr;
|
||||
};
|
||||
|
||||
struct AudioInterface {
|
||||
void driver(const char* driver = "");
|
||||
const char* optimalDriver();
|
||||
const char* safestDriver();
|
||||
const char* availableDrivers();
|
||||
bool init();
|
||||
void term();
|
||||
|
||||
bool cap(const nall::string& name);
|
||||
nall::any get(const nall::string& name);
|
||||
bool set(const nall::string& name, const nall::any& value);
|
||||
|
||||
void sample(uint16_t left, uint16_t right);
|
||||
void clear();
|
||||
|
||||
AudioInterface();
|
||||
~AudioInterface();
|
||||
|
||||
auto driver(nall::string driver = "") -> void;
|
||||
auto optimalDriver() -> nall::string;
|
||||
auto safestDriver() -> nall::string;
|
||||
auto availableDrivers() -> nall::string;
|
||||
auto init() -> bool;
|
||||
auto term() -> void;
|
||||
|
||||
auto cap(const nall::string& name) -> bool;
|
||||
auto get(const nall::string& name) -> nall::any;
|
||||
auto set(const nall::string& name, const nall::any& value) -> bool;
|
||||
|
||||
auto sample(uint16_t left, uint16_t right) -> void;
|
||||
auto clear() -> void;
|
||||
|
||||
private:
|
||||
Audio* p = nullptr;
|
||||
};
|
||||
|
@ -83,7 +81,6 @@ struct InputInterface {
|
|||
auto acquire() -> bool;
|
||||
auto unacquire() -> bool;
|
||||
auto acquired() -> bool;
|
||||
|
||||
auto poll() -> nall::vector<nall::shared_pointer<nall::HID::Device>>;
|
||||
auto rumble(uint64_t id, bool enable) -> bool;
|
||||
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
struct Video {
|
||||
static const char* Handle;
|
||||
static const char* Synchronize;
|
||||
static const char* Depth;
|
||||
static const char* Filter;
|
||||
static const char* Shader;
|
||||
static const nall::string Handle;
|
||||
static const nall::string Synchronize;
|
||||
static const nall::string Depth;
|
||||
static const nall::string Filter;
|
||||
static const nall::string Shader;
|
||||
|
||||
static const unsigned FilterNearest;
|
||||
static const unsigned FilterLinear;
|
||||
|
||||
virtual bool cap(const nall::string& name) { return false; }
|
||||
virtual nall::any get(const nall::string& name) { return false; }
|
||||
virtual bool set(const nall::string& name, const nall::any& value) { return false; }
|
||||
virtual ~Video() = default;
|
||||
|
||||
virtual bool lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) { return false; }
|
||||
virtual void unlock() {}
|
||||
virtual auto cap(const nall::string& name) -> bool { return false; }
|
||||
virtual auto get(const nall::string& name) -> nall::any { return false; }
|
||||
virtual auto set(const nall::string& name, const nall::any& value) -> bool { return false; }
|
||||
|
||||
virtual void clear() {}
|
||||
virtual void refresh() {}
|
||||
virtual bool init() { return true; }
|
||||
virtual void term() {}
|
||||
virtual auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool { return false; }
|
||||
virtual auto unlock() -> void {}
|
||||
virtual auto clear() -> void {}
|
||||
virtual auto refresh() -> void {}
|
||||
|
||||
Video() {}
|
||||
virtual ~Video() {}
|
||||
virtual auto init() -> bool { return true; }
|
||||
virtual auto term() -> void {}
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@ ConfigurationManager::ConfigurationManager() {
|
|||
append(video, "Video");
|
||||
|
||||
audio.append(audio.driver, "Driver");
|
||||
audio.append(audio.device, "Device");
|
||||
audio.append(audio.synchronize, "Synchronize");
|
||||
audio.append(audio.mute, "Mute");
|
||||
append(audio, "Audio");
|
||||
|
|
|
@ -27,6 +27,7 @@ struct ConfigurationManager : Configuration::Document {
|
|||
|
||||
struct Audio : Configuration::Node {
|
||||
string driver;
|
||||
string device;
|
||||
bool synchronize = true;
|
||||
bool mute = false;
|
||||
} audio;
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
//request from emulation core to load non-volatile media folder
|
||||
auto Program::loadRequest(unsigned id, string name, string type) -> void {
|
||||
string location = BrowserDialog()
|
||||
.setParent(*presentation)
|
||||
.setTitle({"Load ", name})
|
||||
.setPath({config().library.location, name})
|
||||
.setFilters({string{name, "|*.", type}})
|
||||
.selectFolder();
|
||||
if(!directory::exists(location)) return;
|
||||
|
||||
mediaPaths(id) = location;
|
||||
folderPaths.append(location);
|
||||
emulator->load(id);
|
||||
}
|
||||
|
||||
//request from emulation core to load non-volatile media file
|
||||
|
|
|
@ -36,6 +36,7 @@ Program::Program() {
|
|||
if(!video.init()) { video.driver("None"); video.init(); }
|
||||
|
||||
audio.driver(config().audio.driver);
|
||||
audio.set(Audio::Device, config().audio.device);
|
||||
audio.set(Audio::Handle, presentation->viewport.handle());
|
||||
audio.set(Audio::Synchronize, config().audio.synchronize);
|
||||
audio.set(Audio::Frequency, 96000u);
|
||||
|
|
|
@ -8,6 +8,12 @@ HotkeySettings::HotkeySettings(TabFrame* parent) : TabFrameItem(parent) {
|
|||
mappingList.onChange([&] {
|
||||
eraseButton.setEnabled((bool)mappingList.selected());
|
||||
});
|
||||
resetButton.setText("Reset").onActivate([&] {
|
||||
if(MessageDialog("Are you sure you want to erase all hotkey mappings?").setParent(*settingsManager).question() == 0) {
|
||||
for(auto& mapping : inputManager->hotkeys) mapping->unbind();
|
||||
refreshMappings();
|
||||
}
|
||||
});
|
||||
eraseButton.setText("Erase").onActivate([&] {
|
||||
if(auto item = mappingList.selected()) {
|
||||
inputManager->hotkeys[item->offset()]->unbind();
|
||||
|
@ -43,6 +49,7 @@ auto HotkeySettings::assignMapping() -> void {
|
|||
|
||||
if(auto item = mappingList.selected()) {
|
||||
activeMapping = inputManager->hotkeys[item->offset()];
|
||||
settingsManager->layout.setEnabled(false);
|
||||
settingsManager->statusBar.setText({"Press a key or button to map [", activeMapping->name, "] ..."});
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +61,7 @@ auto HotkeySettings::inputEvent(shared_pointer<HID::Device> device, unsigned gro
|
|||
if(activeMapping->bind(device, group, input, oldValue, newValue)) {
|
||||
activeMapping = nullptr;
|
||||
settingsManager->statusBar.setText("");
|
||||
settingsManager->layout.setEnabled(true);
|
||||
refreshMappings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,12 +102,12 @@ auto InputSettings::refreshMappings() -> void {
|
|||
auto InputSettings::assignMapping() -> void {
|
||||
inputManager->poll(); //clear any pending events first
|
||||
|
||||
auto mapping = mappingList.selected();
|
||||
if(auto mapping = mappingList.selected()) {
|
||||
activeMapping = activeDevice().mappings[mapping->offset()];
|
||||
|
||||
//settingsManager->layout.setEnabled(false);
|
||||
settingsManager->layout.setEnabled(false);
|
||||
settingsManager->statusBar.setText({"Press a key or button to map [", activeMapping->name, "] ..."});
|
||||
}
|
||||
}
|
||||
|
||||
auto InputSettings::assignMouseInput(unsigned id) -> void {
|
||||
if(auto mouse = inputManager->findMouse()) {
|
||||
|
@ -130,7 +130,7 @@ auto InputSettings::inputEvent(shared_pointer<HID::Device> device, unsigned grou
|
|||
if(activeMapping->bind(device, group, input, oldValue, newValue)) {
|
||||
activeMapping = nullptr;
|
||||
settingsManager->statusBar.setText("");
|
||||
//settingsManager->layout.setEnabled(true); //todo: this isn't enabling child widgets properly (bug in hiro)
|
||||
settingsManager->layout.setEnabled(true);
|
||||
refreshMappings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ struct HotkeySettings : TabFrameItem {
|
|||
ListView mappingList{&layout, Size{~0, ~0}};
|
||||
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
|
||||
Widget spacer{&controlLayout, Size{~0, 0}};
|
||||
Button resetButton{&controlLayout, Size{80, 0}};
|
||||
Button eraseButton{&controlLayout, Size{80, 0}};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue