Update to v094r28 release.

byuu says:

This WIP substantially restructures the ruby API for the first time
since that project started.

It is my hope that with this restructuring, destruction of the ruby
objects should now be deterministic, which should fix the crashing on
closing the emulator on Linux. We'll see I guess ... either way, it
removed two layers of wrappers from ruby, so it's a pretty nice code
cleanup.

It won't compile on Windows due to a few issues I didn't see until
uploading the WIP, too lazy to upload another. But I fixed all the
compilation issues locally, so it'll work on Windows again with the next
WIP (unless I break something else.)

(Kind of annoying that Linux defines glActiveTexture but Windows
doesn't.)
This commit is contained in:
Tim Allen 2015-06-20 15:44:05 +10:00
parent 20cc6148cb
commit e0815b55b9
58 changed files with 485 additions and 890 deletions

View File

@ -8,7 +8,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "094.27";
static const string Version = "094.28";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -406,6 +406,8 @@ struct mObject {
mObject(const mObject&) = delete;
mObject& operator=(const mObject&) = delete;
explicit operator bool() const;
auto abstract() const -> bool;
auto adjustOffset(signed displacement) -> type&;
auto enabled(bool recursive = false) const -> bool;

View File

@ -26,6 +26,11 @@ auto mObject::destruct() -> void {
//
//used to test if returned items "exist" from eg Window::layout(), ListView::selected(), etc.
mObject::operator bool() const {
return parent() || !abstract();
}
//this is used to control dynamic allocation of pObject delegates
//an mObject is abstract only if it has no top-level object (eg a Button not attached to any Window)
//if the mObject is not abstract, the pObject delegate is allocated immediately

View File

@ -6,15 +6,14 @@
}) { \
(*this)->bind(*this); \
} \
Name(std::nullptr_t) {} \
Name(const s##Name& source) : s##Name(source) {} \
explicit operator bool() const { return !empty(); } \
Name(const s##Name& source) : s##Name(source) { assert(source); } \
explicit operator bool() const { return self().operator bool(); } \
auto self() const -> m##Name& { return (m##Name&)operator*(); } \
#define DeclareSharedObject(Name) \
DeclareShared(Name) \
template<typename T, typename... P> Name(T* parent, P&&... p) : Name() { \
if(parent && *parent) (*parent)->append(*this, std::forward<P>(p)...); \
if(parent) (*parent)->append(*this, std::forward<P>(p)...); \
} \
auto enabled(bool recursive = false) const { return self().enabled(recursive); } \
auto focused() const { return self().focused(); } \

View File

@ -57,7 +57,7 @@ auto mComboButton::selected() const -> ComboButtonItem {
for(auto& item : state.items) {
if(item->selected()) return item;
}
return {nullptr};
return {};
}
auto mComboButton::setParent(mObject* parent, signed offset) -> type& {

View File

@ -182,7 +182,7 @@ auto mListView::selected() const -> ListViewItem {
for(auto& item : state.items) {
if(item->selected()) return item;
}
return {nullptr};
return {};
}
auto mListView::selectedItems() const -> vector<ListViewItem> {

View File

@ -78,7 +78,7 @@ auto mTabFrame::selected() const -> TabFrameItem {
for(auto& item : state.items) {
if(item->selected()) return item;
}
return {nullptr};
return {};
}
auto mTabFrame::setEdge(Edge edge) -> type& {

View File

@ -18,6 +18,8 @@
#define LIBCO_C
#include "libco.h"
#define _BSD_SOURCE
#include <stdlib.h>
#include <ucontext.h>

View File

@ -15,18 +15,20 @@ ifeq ($(platform),)
else ifneq ($(findstring Windows,$(uname)),)
platform := windows
delete = del $(subst /,\,$1)
else ifneq ($(findstring CYGWIN,$(uname)),)
else ifneq ($(findstring _NT,$(uname)),)
platform := windows
delete = del $(subst /,\,$1)
else ifneq ($(findstring Darwin,$(uname)),)
platform := macosx
delete = rm -f $1
else ifneq ($(findstring Linux,$(uname)),)
platform := linux
delete = rm -f $1
else ifneq ($(findstring BSD,$(uname)),)
platform := bsd
delete = rm -f $1
else
platform := linux
delete = rm -f $1
$(error unknown platform, please specify manually.)
endif
endif
@ -44,6 +46,8 @@ ifeq ($(compiler),)
cppflags := -x c++ -std=gnu++14
else ifeq ($(platform),macosx)
compiler := clang++
else ifeq ($(platform),linux)
compiler := g++-4.9
else ifeq ($(platform),bsd)
compiler := g++49
else

View File

@ -1,19 +0,0 @@
struct Audio {
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 ~Audio() = default;
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 auto sample(uint16_t left, uint16_t right) -> void {}
virtual auto clear() -> void {}
virtual auto init() -> bool { return true; }
virtual auto term() -> void {}
};

View File

@ -1,8 +1,8 @@
#include <alsa/asoundlib.h>
namespace ruby {
struct AudioALSA : Audio {
~AudioALSA() { term(); }
struct pAudioALSA {
struct {
snd_pcm_t* handle = nullptr;
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
@ -23,10 +23,6 @@ struct pAudioALSA {
unsigned latency = 60;
} settings;
~pAudioALSA() {
term();
}
auto cap(const string& name) -> bool {
if(name == Audio::Synchronize) return true;
if(name == Audio::Frequency) return true;
@ -127,8 +123,6 @@ struct pAudioALSA {
}
auto init() -> bool {
term();
if(snd_pcm_open(&device.handle, device.name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) {
term();
return false;
@ -216,7 +210,3 @@ struct pAudioALSA {
}
}
};
DeclareAudio(ALSA)
};

View File

@ -1,8 +1,8 @@
#include <ao/ao.h>
namespace ruby {
struct AudioAO : Audio {
~AudioAO() { term(); }
struct pAudioAO {
int driver_id;
ao_sample_format driver_format;
ao_device* audio_device = nullptr;
@ -11,15 +11,6 @@ struct pAudioAO {
unsigned frequency = 22050;
} settings;
pAudioAO() {
ao_initialize();
}
~pAudioAO() {
term();
//ao_shutdown(); //FIXME: this is causing a segfault for some reason when called ...
}
auto cap(const string& name) -> bool {
if(name == Audio::Frequency) return true;
return false;
@ -49,7 +40,7 @@ struct pAudioAO {
}
auto init() -> bool {
term();
ao_initialize();
driver_id = ao_default_driver_id(); //ao_driver_id((const char*)driver)
if(driver_id < 0) return false;
@ -77,9 +68,6 @@ struct pAudioAO {
ao_close(audio_device);
audio_device = nullptr;
}
ao_shutdown();
}
};
DeclareAudio(AO)
};

View File

@ -1,8 +1,8 @@
#include <dsound.h>
namespace ruby {
struct AudioDS : Audio {
~AudioDS() { term(); }
struct pAudioDS {
LPDIRECTSOUND ds = nullptr;
LPDIRECTSOUNDBUFFER dsb_p = nullptr;
LPDIRECTSOUNDBUFFER dsb_b = nullptr;
@ -28,14 +28,6 @@ struct pAudioDS {
unsigned latency = 120;
} settings;
pAudioDS() {
settings.handle = GetDesktopWindow();
}
~pAudioDS() {
term();
}
auto cap(const string& name) -> bool {
if(name == Audio::Handle) return true;
if(name == Audio::Synchronize) return true;
@ -138,7 +130,7 @@ struct pAudioDS {
}
auto init() -> bool {
term();
settings.handle = GetDesktopWindow();
device.rings = 8;
device.latency = settings.frequency * settings.latency / device.rings / 1000.0 + 0.5;
@ -189,7 +181,3 @@ struct pAudioDS {
if(ds) { ds->Release(); ds = 0; }
}
};
DeclareAudio(DS)
};

View File

@ -6,9 +6,9 @@
#include <AL/alc.h>
#endif
namespace ruby {
struct AudioOpenAL : Audio {
~AudioOpenAL() { term(); }
struct pAudioOpenAL {
struct {
ALCdevice* handle = nullptr;
ALCcontext* context = nullptr;
@ -30,10 +30,6 @@ struct pAudioOpenAL {
unsigned latency = 40;
} settings;
~pAudioOpenAL() {
term();
}
auto cap(const string& name) -> bool {
if(name == Audio::Synchronize) return true;
if(name == Audio::Frequency) return true;
@ -196,7 +192,3 @@ private:
buffer.data = new uint32_t[buffer.size]();
}
};
DeclareAudio(OpenAL)
};

View File

@ -18,9 +18,9 @@
#define SNDCTL_DSP_POLICY _IOW('P', 45, signed)
#endif
namespace ruby {
struct AudioOSS : Audio {
~AudioOSS() { term(); }
struct pAudioOSS {
struct {
signed fd = -1;
signed format = AFMT_S16_LE;
@ -33,10 +33,6 @@ struct pAudioOSS {
unsigned frequency = 22050;
} settings;
~pAudioOSS() {
term();
}
auto cap(const string& name) -> bool {
if(name == Audio::Device) return true;
if(name == Audio::Synchronize) return true;
@ -82,8 +78,6 @@ struct pAudioOSS {
}
auto init() -> bool {
term();
device.fd = open(settings.device, O_WRONLY, O_NONBLOCK);
if(device.fd < 0) return false;
@ -119,7 +113,3 @@ private:
fcntl(device.fd, F_SETFL, flags);
}
};
DeclareAudio(OSS)
};

View File

@ -1,8 +1,8 @@
#include <pulse/pulseaudio.h>
namespace ruby {
struct AudioPulseAudio : Audio {
~AudioPulseAudio() { term(); }
struct pAudioPulseAudio {
struct {
pa_mainloop* mainloop = nullptr;
pa_context* context = nullptr;
@ -24,10 +24,6 @@ struct pAudioPulseAudio {
unsigned latency = 60;
} settings;
~pAudioPulseAudio() {
term();
}
auto cap(const string& name) -> bool {
if(name == Audio::Synchronize) return true;
if(name == Audio::Frequency) return true;
@ -161,7 +157,3 @@ struct pAudioPulseAudio {
}
}
};
DeclareAudio(PulseAudio)
}

View File

@ -1,9 +1,9 @@
#include <pulse/simple.h>
#include <pulse/error.h>
namespace ruby {
struct AudioPulseAudioSimple : Audio {
~AudioPulseAudioSimple() { term(); }
struct pAudioPulseAudioSimple {
struct {
pa_simple* handle = nullptr;
pa_sample_spec spec;
@ -18,10 +18,6 @@ struct pAudioPulseAudioSimple {
unsigned frequency = 22050;
} settings;
~pAudioPulseAudioSimple() {
term();
}
auto cap(const string& name) -> bool {
if(name == Audio::Frequency) return true;
return false;
@ -57,8 +53,6 @@ struct pAudioPulseAudioSimple {
}
auto init() -> bool {
term();
device.spec.format = PA_SAMPLE_S16LE;
device.spec.channels = 2;
device.spec.rate = settings.frequency;
@ -99,7 +93,3 @@ struct pAudioPulseAudioSimple {
}
}
};
DeclareAudio(PulseAudioSimple)
};

View File

@ -1,9 +1,9 @@
#include "xaudio2.hpp"
#include <windows.h>
namespace ruby {
struct AudioXAudio2 : Audio, public IXAudio2VoiceCallback {
AudioXAudio2() { term(); }
struct pAudioXAudio2 : public IXAudio2VoiceCallback {
IXAudio2* pXAudio2 = nullptr;
IXAudio2MasteringVoice* pMasterVoice = nullptr;
IXAudio2SourceVoice* pSourceVoice = nullptr;
@ -33,10 +33,6 @@ struct pAudioXAudio2 : public IXAudio2VoiceCallback {
unsigned latency = 120;
} settings;
~pAudioXAudio2() {
term();
}
auto cap(const string& name) -> bool {
if(name == Audio::Synchronize) return true;
if(name == Audio::Frequency) return true;
@ -117,8 +113,6 @@ struct pAudioXAudio2 : public IXAudio2VoiceCallback {
}
auto init() -> bool {
term();
device.buffers = 8;
device.latency = settings.frequency * settings.latency / device.buffers / 1000.0 + 0.5;
device.buffer = new uint32_t[device.latency * device.buffers];
@ -187,7 +181,3 @@ struct pAudioXAudio2 : public IXAudio2VoiceCallback {
InterlockedDecrement(&device.submitbuffers);
}
};
DeclareAudio(XAudio2)
};

View File

@ -1,172 +0,0 @@
/* Global Headers */
#if defined(PLATFORM_XORG)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#elif defined(PLATFORM_MACOSX)
#define decimal CocoaDecimal
#include <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h>
#undef decimal
#elif defined(PLATFORM_WINDOWS)
#include <windows.h>
#endif
using namespace nall;
/* Video */
#define DeclareVideo(Name) \
struct Video##Name : Video { \
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; \
};
#ifdef VIDEO_CGL
#include <ruby/video/cgl.cpp>
#endif
#ifdef VIDEO_DIRECT3D
#include <ruby/video/direct3d.cpp>
#endif
#ifdef VIDEO_DIRECTDRAW
#include <ruby/video/directdraw.cpp>
#endif
#ifdef VIDEO_GDI
#include <ruby/video/gdi.cpp>
#endif
#ifdef VIDEO_GLX
#include <ruby/video/glx.cpp>
#endif
#ifdef VIDEO_SDL
#include <ruby/video/sdl.cpp>
#endif
#ifdef VIDEO_WGL
#include <ruby/video/wgl.cpp>
#endif
#ifdef VIDEO_XSHM
#include <ruby/video/xshm.cpp>
#endif
#ifdef VIDEO_XV
#include <ruby/video/xv.cpp>
#endif
/* Audio */
#define DeclareAudio(Name) \
struct Audio##Name : Audio { \
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; \
};
#ifdef AUDIO_ALSA
#include <ruby/audio/alsa.cpp>
#endif
#ifdef AUDIO_AO
#include <ruby/audio/ao.cpp>
#endif
#ifdef AUDIO_DIRECTSOUND
#include <ruby/audio/directsound.cpp>
#endif
#ifdef AUDIO_OPENAL
#include <ruby/audio/openal.cpp>
#endif
#ifdef AUDIO_OSS
#include <ruby/audio/oss.cpp>
#endif
#ifdef AUDIO_PULSEAUDIO
#include <ruby/audio/pulseaudio.cpp>
#endif
#ifdef AUDIO_PULSEAUDIOSIMPLE
#include <ruby/audio/pulseaudiosimple.cpp>
#endif
#ifdef AUDIO_XAUDIO2
#include <ruby/audio/xaudio2.cpp>
#endif
/* Input */
#define DeclareInput(Name) \
struct Input##Name : Input { \
Input##Name() : p(*new pInput##Name) {} \
~Input##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 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(); } \
\
private: \
pInput##Name& p; \
};
#ifdef INPUT_CARBON
#include <ruby/input/carbon.cpp>
#endif
#ifdef INPUT_SDL
#include <ruby/input/sdl.cpp>
#endif
#ifdef INPUT_UDEV
#include <ruby/input/udev.cpp>
#endif
#ifdef INPUT_WINDOWS
#include <ruby/input/windows.cpp>
#endif
#ifdef INPUT_XLIB
#include <ruby/input/xlib.cpp>
#endif

View File

@ -1,22 +0,0 @@
struct Input {
static const nall::string Handle;
static const nall::string KeyboardSupport;
static const nall::string MouseSupport;
static const nall::string JoypadSupport;
static const nall::string JoypadRumbleSupport;
virtual ~Input() = default;
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 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 {}
};

View File

@ -1,6 +1,6 @@
namespace ruby {
struct InputCarbon : Input {
~InputCarbon() { term(); }
struct pInputCarbon {
struct Key {
uint8_t id;
string name;
@ -25,7 +25,7 @@ struct pInputCarbon {
}
auto acquire() -> bool { return false; }
auto unacquire() -> bool { return false; }
auto release() -> bool { return false; }
auto acquired() -> bool { return false; }
auto assign(shared_pointer<HID::Device> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
@ -179,7 +179,3 @@ struct pInputCarbon {
auto term() -> void {
}
};
DeclareInput(Carbon)
};

View File

@ -1,13 +1,14 @@
#ifndef RUBY_INPUT_JOYPAD_DIRECTINPUT
#define RUBY_INPUT_JOYPAD_DIRECTINPUT
namespace ruby {
auto CALLBACK DirectInput_EnumJoypadsCallback(const DIDEVICEINSTANCE* instance, void* p) -> BOOL;
auto CALLBACK DirectInput_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) -> BOOL;
auto CALLBACK DirectInput_EnumJoypadEffectsCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) -> BOOL;
struct InputJoypadDirectInput {
Input& input;
InputJoypadDirectInput(Input& input) : input(input) {}
struct Joypad {
shared_pointer<HID::Joypad> hid{new HID::Joypad};
@ -30,7 +31,7 @@ struct InputJoypadDirectInput {
auto assign(shared_pointer<HID::Joypad> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
if(input.onChange) input.onChange(hid, groupID, inputID, group.input(inputID).value(), value);
input.doChange(hid, groupID, inputID, group.input(inputID).value(), value);
group.input(inputID).setValue(value);
}
@ -213,6 +214,4 @@ auto CALLBACK DirectInput_EnumJoypadEffectsCallback(const DIDEVICEOBJECTINSTANCE
return ((InputJoypadDirectInput*)p)->initEffect(instance);
}
}
#endif

View File

@ -1,9 +1,10 @@
#ifndef RUBY_INPUT_JOYPAD_SDL
#define RUBY_INPUT_JOYPAD_SDL
namespace ruby {
struct InputJoypadSDL {
Input& input;
InputJoypadSDL(Input& input) : input(input) {}
struct Joypad {
shared_pointer<HID::Joypad> hid{new HID::Joypad};
@ -15,7 +16,7 @@ struct InputJoypadSDL {
auto assign(shared_pointer<HID::Joypad> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
if(input.onChange) input.onChange(hid, groupID, inputID, group.input(inputID).value(), value);
input.doChange(hid, groupID, inputID, group.input(inputID).value(), value);
group.input(inputID).setValue(value);
}
@ -75,6 +76,4 @@ struct InputJoypadSDL {
}
};
}
#endif

View File

@ -1,9 +1,10 @@
#ifndef RUBY_INPUT_JOYPAD_UDEV
#define RUBY_INPUT_JOYPAD_UDEV
namespace ruby {
struct InputJoypadUdev {
Input& input;
InputJoypadUdev(Input& input) : input(input) {}
udev* context = nullptr;
udev_monitor* monitor = nullptr;
udev_enumerate* enumerator = nullptr;
@ -55,7 +56,7 @@ struct InputJoypadUdev {
auto assign(shared_pointer<HID::Joypad> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
if(input.onChange) input.onChange(hid, groupID, inputID, group.input(inputID).value(), value);
input.doChange(hid, groupID, inputID, group.input(inputID).value(), value);
group.input(inputID).setValue(value);
}
@ -275,6 +276,4 @@ private:
}
};
}
#endif

View File

@ -19,9 +19,10 @@ typedef DWORD WINAPI (*pXInputPowerOffController)(DWORD dwUserIndex);
#define XINPUT_GAMEPAD_GUIDE 0x0400
namespace ruby {
struct InputJoypadXInput {
Input& input;
InputJoypadXInput(Input& input) : input(input) {}
HMODULE libxinput = nullptr;
pXInputGetStateEx XInputGetStateEx = nullptr;
pXInputSetState XInputSetState = nullptr;
@ -35,7 +36,7 @@ struct InputJoypadXInput {
auto assign(shared_pointer<HID::Joypad> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
if(input.onChange) input.onChange(hid, groupID, inputID, group.input(inputID).value(), value);
input.doChange(hid, groupID, inputID, group.input(inputID).value(), value);
group.input(inputID).setValue(value);
}
@ -158,6 +159,4 @@ struct InputJoypadXInput {
}
};
}
#endif

View File

@ -1,9 +1,10 @@
#ifndef RUBY_INPUT_KEYBOARD_RAWINPUT
#define RUBY_INPUT_KEYBOARD_RAWINPUT
namespace ruby {
struct InputKeyboardRawInput {
Input& input;
InputKeyboardRawInput(Input& input) : input(input) {}
struct Key {
uint16_t code;
uint16_t flag;
@ -29,7 +30,7 @@ struct InputKeyboardRawInput {
auto assign(unsigned inputID, bool value) -> void {
auto& group = kb.hid->buttons();
if(group.input(inputID).value() == value) return;
if(input.onChange) input.onChange(kb.hid, HID::Keyboard::GroupID::Button, inputID, group.input(inputID).value(), value);
input.doChange(kb.hid, HID::Keyboard::GroupID::Button, inputID, group.input(inputID).value(), value);
group.input(inputID).setValue(value);
}
@ -173,6 +174,4 @@ struct InputKeyboardRawInput {
}
};
}
#endif

View File

@ -1,9 +1,10 @@
#ifndef RUBY_INPUT_KEYBOARD_XLIB
#define RUBY_INPUT_KEYBOARD_XLIB
namespace ruby {
struct InputKeyboardXlib {
Input& input;
InputKeyboardXlib(Input& input) : input(input) {}
shared_pointer<HID::Keyboard> hid{new HID::Keyboard};
Display* display = nullptr;
@ -18,7 +19,7 @@ struct InputKeyboardXlib {
auto assign(unsigned inputID, bool value) -> void {
auto& group = hid->buttons();
if(group.input(inputID).value() == value) return;
if(input.onChange) input.onChange(hid, HID::Keyboard::GroupID::Button, inputID, group.input(inputID).value(), value);
input.doChange(hid, HID::Keyboard::GroupID::Button, inputID, group.input(inputID).value(), value);
group.input(inputID).setValue(value);
}
@ -169,6 +170,4 @@ struct InputKeyboardXlib {
}
};
}
#endif

View File

@ -1,9 +1,10 @@
#ifndef RUBY_INPUT_MOUSE_RAWINPUT
#define RUBY_INPUT_MOUSE_RAWINPUT
namespace ruby {
struct InputMouseRawInput {
Input& input;
InputMouseRawInput(Input& input) : input(input) {}
uintptr_t handle = 0;
bool mouseAcquired = false;
@ -24,7 +25,7 @@ struct InputMouseRawInput {
return true;
}
auto unacquire() -> bool {
auto release() -> bool {
if(mouseAcquired == true) {
mouseAcquired = false;
ReleaseCapture();
@ -70,7 +71,7 @@ struct InputMouseRawInput {
auto assign(unsigned groupID, unsigned inputID, int16_t value) -> void {
auto& group = ms.hid->group(groupID);
if(group.input(inputID).value() == value) return;
if(input.onChange) input.onChange(ms.hid, groupID, inputID, group.input(inputID).value(), value);
input.doChange(ms.hid, groupID, inputID, group.input(inputID).value(), value);
group.input(inputID).setValue(value);
}
@ -114,10 +115,8 @@ struct InputMouseRawInput {
}
auto term() -> void {
unacquire();
release();
}
};
}
#endif

View File

@ -1,9 +1,10 @@
#ifndef RUBY_INPUT_MOUSE_XLIB
#define RUBY_INPUT_MOUSE_XLIB
namespace ruby {
struct InputMouseXlib {
Input& input;
InputMouseXlib(Input& input) : input(input) {}
shared_pointer<HID::Mouse> hid{new HID::Mouse};
uintptr_t handle = 0;
@ -42,7 +43,7 @@ struct InputMouseXlib {
}
}
auto unacquire() -> bool {
auto release() -> bool {
if(acquired()) {
//restore cursor acceleration and release cursor
XChangePointerControl(display, True, True, ms.numerator, ms.denominator, ms.threshold);
@ -59,7 +60,7 @@ struct InputMouseXlib {
auto assign(unsigned groupID, unsigned inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
if(input.onChange) input.onChange(hid, groupID, inputID, group.input(inputID).value(), value);
input.doChange(hid, groupID, inputID, group.input(inputID).value(), value);
group.input(inputID).setValue(value);
}
@ -143,12 +144,10 @@ struct InputMouseXlib {
}
auto term() -> void {
unacquire();
release();
XFreeCursor(display, invisibleCursor);
XCloseDisplay(display);
}
};
}
#endif

View File

@ -6,12 +6,12 @@
#include "mouse/xlib.cpp"
#include "joypad/sdl.cpp"
namespace ruby {
struct pInputSDL {
struct InputSDL : Input {
InputKeyboardXlib xlibKeyboard;
InputMouseXlib xlibMouse;
InputJoypadSDL sdl;
InputSDL() : xlibKeyboard(*this), xlibMouse(*this), sdl(*this) {}
~InputSDL() { term(); }
struct Settings {
uintptr_t handle = 0;
@ -43,8 +43,8 @@ struct pInputSDL {
return xlibMouse.acquire();
}
auto unacquire() -> bool {
return xlibMouse.unacquire();
auto release() -> bool {
return xlibMouse.release();
}
auto acquired() -> bool {
@ -76,7 +76,3 @@ struct pInputSDL {
sdl.term();
}
};
DeclareInput(SDL)
}

View File

@ -1,11 +1,12 @@
#ifndef RUBY_INPUT_SHARED_RAWINPUT
#define RUBY_INPUT_SHARED_RAWINPUT
namespace ruby {
auto CALLBACK RawInputWindowProc(HWND, UINT, WPARAM, LPARAM) -> LRESULT;
struct RawInput {
Input& input;
RawInput(Input& input) : input(input) {}
HANDLE mutex = nullptr;
HWND hwnd = nullptr;
bool ready = false;
@ -157,6 +158,4 @@ auto CALLBACK RawInputWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
return rawinput.windowProc(hwnd, msg, wparam, lparam);
}
}
#endif

View File

@ -12,12 +12,12 @@
#include "mouse/xlib.cpp"
#include "joypad/udev.cpp"
namespace ruby {
struct pInputUdev {
struct InputUdev : input {
InputKeyboardXlib xlibKeyboard;
InputMouseXlib xlibMouse;
InputJoypadUdev udev;
Input() : xlibKeyboard(*this), xlibMouse(*this), udev(*this) {}
~Input() { term(); }
struct Settings {
uintptr_t handle = 0;
@ -49,8 +49,8 @@ struct pInputUdev {
return xlibMouse.acquire();
}
auto unacquire() -> bool {
return xlibMouse.unacquire();
auto release() -> bool {
return xlibMouse.release();
}
auto acquired() -> bool {
@ -82,7 +82,3 @@ struct pInputUdev {
udev.term();
}
};
DeclareInput(Udev)
}

View File

@ -8,13 +8,13 @@
#include "joypad/xinput.cpp"
#include "joypad/directinput.cpp"
namespace ruby {
struct pInputWindows {
struct InputWindows : Input {
InputKeyboardRawInput rawinputKeyboard;
InputMouseRawInput rawinputMouse;
InputJoypadXInput xinput;
InputJoypadDirectInput directinput;
InputWindows() : rawinputKeyboard(*this), rawinputMouse(*this), xinput(*this), directinput(*this) {}
~InputWindows() { term(); }
LPDIRECTINPUT8 directinputContext = nullptr;
@ -22,10 +22,6 @@ struct pInputWindows {
uintptr_t handle = 0;
} settings;
~pInputWindows() {
term();
}
auto cap(const string& name) -> bool {
if(name == Input::Handle) return true;
if(name == Input::KeyboardSupport) return true;
@ -52,8 +48,8 @@ struct pInputWindows {
return rawinputMouse.acquire();
}
auto unacquire() -> bool {
return rawinputMouse.unacquire();
auto release() -> bool {
return rawinputMouse.release();
}
auto acquired() -> bool {

View File

@ -7,11 +7,11 @@
#include "keyboard/xlib.cpp"
#include "mouse/xlib.cpp"
namespace ruby {
struct pInputXlib {
struct InputXlib : Input {
InputKeyboardXlib xlibKeyboard;
InputMouseXlib xlibMouse;
InputXlib() : xlibKeyboard(*this), xlibMouse(*this) {}
~InputXlib() { term(); }
struct Settings {
uintptr_t handle = 0;
@ -41,8 +41,8 @@ struct pInputXlib {
return xlibMouse.acquire();
}
auto unacquire() -> bool {
return xlibMouse.unacquire();
auto release() -> bool {
return xlibMouse.release();
}
auto acquired() -> bool {
@ -71,7 +71,3 @@ struct pInputXlib {
xlibMouse.term();
}
};
DeclareInput(Xlib)
}

View File

@ -1,18 +1,66 @@
#include <ruby/ruby.hpp>
using namespace nall;
using namespace ruby;
/* Shared */
#undef deprecated
#undef mkdir
#undef usleep
#include <ruby/implementation.cpp>
#if defined(PLATFORM_XORG)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#elif defined(PLATFORM_MACOSX)
#define decimal CocoaDecimal
#include <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h>
#undef decimal
#elif defined(PLATFORM_WINDOWS)
#include <windows.h>
#endif
/* Video */
#if defined(VIDEO_CGL)
#include <ruby/video/cgl.cpp>
#endif
#if defined(VIDEO_DIRECT3D)
#include <ruby/video/direct3d.cpp>
#endif
#if defined(VIDEO_DIRECTDRAW)
#include <ruby/video/directdraw.cpp>
#endif
#if defined(VIDEO_GDI)
#include <ruby/video/gdi.cpp>
#endif
#if defined(VIDEO_GLX)
#include <ruby/video/glx.cpp>
#endif
#if defined(VIDEO_SDL)
#include <ruby/video/sdl.cpp>
#endif
#if defined(VIDEO_WGL)
#include <ruby/video/wgl.cpp>
#endif
#if defined(VIDEO_XSHM)
#include <ruby/video/xshm.cpp>
#endif
#if defined(VIDEO_XV)
#include <ruby/video/xv.cpp>
#endif
namespace ruby {
VideoInterface video;
AudioInterface audio;
InputInterface input;
/* VideoInterface */
const string Video::Handle = "Handle";
const string Video::Synchronize = "Synchronize";
const string Video::Depth = "Depth";
@ -22,61 +70,49 @@ const string Video::Shader = "Shader";
const unsigned Video::FilterNearest = 0;
const unsigned Video::FilterLinear = 1;
auto VideoInterface::driver(string driver) -> void {
if(p) term();
auto Video::create(const string& driver) -> Video* {
if(!driver) return create(optimalDriver());
if(!driver) driver = optimalDriver();
if(0);
#ifdef VIDEO_CGL
else if(driver == "OpenGL") p = new VideoCGL();
#if defined(VIDEO_CGL)
if(driver == "OpenGL") return new VideoCGL;
#endif
#ifdef VIDEO_DIRECT3D
else if(driver == "Direct3D") p = new VideoD3D();
#if defined(VIDEO_DIRECT3D)
if(driver == "Direct3D") return new VideoD3D;
#endif
#ifdef VIDEO_DIRECTDRAW
else if(driver == "DirectDraw") p = new VideoDD();
#if defined(VIDEO_DIRECTDRAW)
if(driver == "DirectDraw") return new VideoDD;
#endif
#ifdef VIDEO_GDI
else if(driver == "GDI") p = new VideoGDI();
#if defined(VIDEO_GDI)
if(driver == "GDI") return new VideoGDI;
#endif
#ifdef VIDEO_GLX
else if(driver == "OpenGL") p = new VideoGLX();
#if defined(VIDEO_GLX)
if(driver == "OpenGL") return new VideoGLX;
#endif
#ifdef VIDEO_QTOPENGL
else if(driver == "Qt-OpenGL") p = new VideoQtOpenGL();
#if defined(VIDEO_SDL)
if(driver == "SDL") return new VideoSDL;
#endif
#ifdef VIDEO_QTRASTER
else if(driver == "Qt-Raster") p = new VideoQtRaster();
#if defined(VIDEO_WGL)
if(driver == "OpenGL") return new VideoWGL;
#endif
#ifdef VIDEO_SDL
else if(driver == "SDL") p = new VideoSDL();
#if defined(VIDEO_XSHM)
if(driver == "XShm") return new VideoXShm;
#endif
#ifdef VIDEO_WGL
else if(driver == "OpenGL") p = new VideoWGL();
#if defined(VIDEO_XV)
if(driver == "X-Video") return new VideoXv;
#endif
#ifdef VIDEO_XSHM
else if(driver == "XShm") p = new VideoXShm();
#endif
#ifdef VIDEO_XV
else if(driver == "X-Video") p = new VideoXv();
#endif
else p = new Video();
return new Video;
}
auto VideoInterface::optimalDriver() -> string {
auto Video::optimalDriver() -> string {
#if defined(VIDEO_WGL)
return "OpenGL";
#elif defined(VIDEO_DIRECT3D)
@ -85,10 +121,8 @@ auto VideoInterface::optimalDriver() -> string {
return "DirectDraw";
#elif defined(VIDEO_GDI)
return "GDI";
#elif defined(VIDEO_CGL)
return "OpenGL";
#elif defined(VIDEO_GLX)
return "OpenGL";
#elif defined(VIDEO_XV)
@ -97,13 +131,12 @@ auto VideoInterface::optimalDriver() -> string {
return "XShm";
#elif defined(VIDEO_SDL)
return "SDL";
#else
return "None";
#endif
}
auto VideoInterface::safestDriver() -> string {
auto Video::safestDriver() -> string {
#if defined(VIDEO_DIRECT3D)
return "Direct3D";
#elif defined(VIDEO_WGL)
@ -112,10 +145,8 @@ auto VideoInterface::safestDriver() -> string {
return "DirectDraw";
#elif defined(VIDEO_GDI)
return "GDI";
#elif defined(VIDEO_CGL)
return "OpenGL";
#elif defined(VIDEO_XSHM)
return "XShm";
#elif defined(VIDEO_SDL)
@ -124,83 +155,90 @@ auto VideoInterface::safestDriver() -> string {
return "X-Video";
#elif defined(VIDEO_GLX)
return "OpenGL";
#else
return "None";
#endif
}
auto VideoInterface::availableDrivers() -> string {
return
//Windows
auto Video::availableDrivers() -> lstring {
return {
#if defined(VIDEO_WGL)
"OpenGL;"
"OpenGL",
#endif
#if defined(VIDEO_DIRECT3D)
"Direct3D;"
"Direct3D",
#endif
#if defined(VIDEO_DIRECTDRAW)
"DirectDraw;"
"DirectDraw",
#endif
#if defined(VIDEO_GDI)
"GDI;"
"GDI",
#endif
//OS X
#if defined(VIDEO_CGL)
"OpenGL;"
"OpenGL",
#endif
//Linux
#if defined(VIDEO_GLX)
"OpenGL;"
"OpenGL",
#endif
#if defined(VIDEO_XV)
"X-Video;"
"X-Video",
#endif
#if defined(VIDEO_XSHM)
"XShm;"
"XShm",
#endif
#if defined(VIDEO_SDL)
"SDL;"
"SDL",
#endif
"None";
"None"};
}
auto VideoInterface::init() -> bool {
if(!p) driver();
return p->init();
}
auto VideoInterface::term() -> void {
if(p) {
p->term();
delete p;
p = nullptr;
}
}
/* Audio */
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(); }
#if defined(AUDIO_ALSA)
#include <ruby/audio/alsa.cpp>
#endif
/* AudioInterface */
#if defined(AUDIO_AO)
#include <ruby/audio/ao.cpp>
#endif
#if defined(AUDIO_DIRECTSOUND)
#include <ruby/audio/directsound.cpp>
#endif
#if defined(AUDIO_OPENAL)
#include <ruby/audio/openal.cpp>
#endif
#if defined(AUDIO_OSS)
#include <ruby/audio/oss.cpp>
#endif
#if defined(AUDIO_PULSEAUDIO)
#include <ruby/audio/pulseaudio.cpp>
#endif
#if defined(AUDIO_PULSEAUDIOSIMPLE)
#include <ruby/audio/pulseaudiosimple.cpp>
#endif
#if defined(AUDIO_XAUDIO2)
#include <ruby/audio/xaudio2.cpp>
#endif
namespace ruby {
const string Audio::Device = "Device";
const string Audio::Handle = "Handle";
@ -208,80 +246,75 @@ const string Audio::Synchronize = "Synchronize";
const string Audio::Frequency = "Frequency";
const string Audio::Latency = "Latency";
auto AudioInterface::driver(string driver) -> void {
if(p) term();
auto Audio::create(const string& driver) -> Audio* {
if(!driver) return create(optimalDriver());
if(!driver) driver = optimalDriver();
if(0);
#ifdef AUDIO_ALSA
else if(driver == "ALSA") p = new AudioALSA();
#if defined(AUDIO_ALSA)
if(driver == "ALSA") return new AudioALSA;
#endif
#ifdef AUDIO_AO
else if(driver == "libao") p = new AudioAO();
#if defined(AUDIO_AO)
if(driver == "libao") return new AudioAO;
#endif
#ifdef AUDIO_DIRECTSOUND
else if(driver == "DirectSound") p = new AudioDS();
#if defined(AUDIO_DIRECTSOUND)
if(driver == "DirectSound") return new AudioDS;
#endif
#ifdef AUDIO_OPENAL
else if(driver == "OpenAL") p = new AudioOpenAL();
#if defined(AUDIO_OPENAL)
if(driver == "OpenAL") return new AudioOpenAL;
#endif
#ifdef AUDIO_OSS
else if(driver == "OSS") p = new AudioOSS();
#if defined(AUDIO_OSS)
if(driver == "OSS") return new AudioOSS;
#endif
#ifdef AUDIO_PULSEAUDIO
else if(driver == "PulseAudio") p = new AudioPulseAudio();
#if defined(AUDIO_PULSEAUDIO)
if(driver == "PulseAudio") return new AudioPulseAudio;
#endif
#ifdef AUDIO_PULSEAUDIOSIMPLE
else if(driver == "PulseAudioSimple") p = new AudioPulseAudioSimple();
#if defined(AUDIO_PULSEAUDIOSIMPLE)
if(driver == "PulseAudioSimple") return new AudioPulseAudioSimple;
#endif
#ifdef AUDIO_XAUDIO2
else if(driver == "XAudio2") p = new AudioXAudio2();
#if defined(AUDIO_XAUDIO2)
if(driver == "XAudio2") return new AudioXAudio2;
#endif
else p = new Audio();
return new Audio;
}
auto AudioInterface::optimalDriver() -> string {
auto Audio::optimalDriver() -> string {
#if defined(AUDIO_XAUDIO2)
return "XAudio2";
#elif defined(AUDIO_DIRECTSOUND)
return "DirectSound";
#elif defined(AUDIO_ALSA)
return "ALSA";
#elif defined(AUDIO_OPENAL)
return "OpenAL";
#elif defined(AUDIO_OSS)
return "OSS";
#elif defined(AUDIO_OPENAL)
return "OpenAL";
#elif defined(AUDIO_PULSEAUDIO)
return "PulseAudio";
#elif defined(AUDIO_PULSEAUDIOSIMPLE)
return "PulseAudioSimple";
#elif defined(AUDIO_AO)
return "libao";
#else
return "None";
#endif
}
auto AudioInterface::safestDriver() -> string {
auto Audio::safestDriver() -> string {
#if defined(AUDIO_DIRECTSOUND)
return "DirectSound";
#elif defined(AUDIO_XAUDIO2)
return "XAudio2";
#elif defined(AUDIO_ALSA)
return "ALSA";
#elif defined(AUDIO_OSS)
return "OSS";
#elif defined(AUDIO_OPENAL)
return "OpenAL";
#elif defined(AUDIO_PULSEAUDIO)
@ -290,77 +323,74 @@ auto AudioInterface::safestDriver() -> string {
return "PulseAudioSimple";
#elif defined(AUDIO_AO)
return "libao";
#elif defined(AUDIO_OSS)
return "OSS";
#else
return "None";
#endif
}
auto AudioInterface::availableDrivers() -> string {
return
//Windows
auto Audio::availableDrivers() -> lstring {
return {
#if defined(AUDIO_XAUDIO2)
"XAudio2;"
"XAudio2",
#endif
#if defined(AUDIO_DIRECTSOUND)
"DirectSound;"
"DirectSound",
#endif
//Linux
#if defined(AUDIO_ALSA)
"ALSA;"
#endif
#if defined(AUDIO_OPENAL)
"OpenAL;"
"ALSA",
#endif
#if defined(AUDIO_OSS)
"OSS;"
"OSS",
#endif
#if defined(AUDIO_OPENAL)
"OpenAL",
#endif
#if defined(AUDIO_PULSEAUDIO)
"PulseAudio;"
"PulseAudio",
#endif
#if defined(AUDIO_PULSEAUDIOSIMPLE)
"PulseAudioSimple;"
"PulseAudioSimple",
#endif
#if defined(AUDIO_AO)
"libao;"
"libao",
#endif
"None";
"None"};
}
auto AudioInterface::init() -> bool {
if(!p) driver();
return p->init();
}
auto AudioInterface::term() -> void {
if(p) {
p->term();
delete p;
p = nullptr;
}
}
/* Input */
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(); }
#if defined(INPUT_CARBON)
#include <ruby/input/carbon.cpp>
#endif
/* InputInterface */
#if defined(INPUT_SDL)
#include <ruby/input/sdl.cpp>
#endif
#if defined(INPUT_UDEV)
#include <ruby/input/udev.cpp>
#endif
#if defined(INPUT_WINDOWS)
#include <ruby/input/windows.cpp>
#endif
#if defined(INPUT_XLIB)
#include <ruby/input/xlib.cpp>
#endif
namespace ruby {
const string Input::Handle = "Handle";
const string Input::KeyboardSupport = "KeyboardSupport";
@ -368,127 +398,88 @@ const string Input::MouseSupport = "MouseSupport";
const string Input::JoypadSupport = "JoypadSupport";
const string Input::JoypadRumbleSupport = "JoypadRumbleSupport";
auto InputInterface::driver(string driver) -> void {
if(p) term();
auto Input::create(const string& driver) -> Input* {
if(!driver) return create(optimalDriver());
if(!driver) driver = optimalDriver();
if(0);
#ifdef INPUT_WINDOWS
else if(driver == "Windows") p = new InputWindows();
#if defined(INPUT_WINDOWS)
if(driver == "Windows") return new InputWindows;
#endif
#ifdef INPUT_CARBON
else if(driver == "Carbon") p = new InputCarbon();
#if defined(INPUT_CARBON)
if(driver == "Carbon") return new InputCarbon;
#endif
#ifdef INPUT_UDEV
else if(driver == "udev") p = new InputUdev();
#if defined(INPUT_UDEV)
if(driver == "udev") return new InputUdev;
#endif
#ifdef INPUT_SDL
else if(driver == "SDL") p = new InputSDL();
#if defined(INPUT_SDL)
if(driver == "SDL") return new InputSDL;
#endif
#ifdef INPUT_XLIB
else if(driver == "Xlib") p = new InputXlib();
#if defined(INPUT_XLIB)
if(driver == "Xlib") return new InputXlib;
#endif
else p = new Input();
return new Input;
}
auto InputInterface::optimalDriver() -> string {
auto Input::optimalDriver() -> string {
#if defined(INPUT_WINDOWS)
return "Windows";
#elif defined(INPUT_CARBON)
return "Carbon";
#elif defined(INPUT_UDEV)
return "udev";
#elif defined(INPUT_SDL)
return "SDL";
#elif defined(INPUT_XLIB)
return "Xlib";
#else
return "None";
#endif
}
auto InputInterface::safestDriver() -> string {
auto Input::safestDriver() -> string {
#if defined(INPUT_WINDOWS)
return "Windows";
#elif defined(INPUT_CARBON)
return "Carbon";
#elif defined(INPUT_UDEV)
return "udev";
#elif defined(INPUT_SDL)
return "SDL";
#elif defined(INPUT_XLIB)
return "Xlib";
#else
return "none";
#endif
}
auto InputInterface::availableDrivers() -> string {
return
//Windows
auto Input::availableDrivers() -> lstring {
return {
#if defined(INPUT_WINDOWS)
"Windows;"
"Windows",
#endif
//OS X
#if defined(INPUT_CARBON)
"Carbon;"
"Carbon",
#endif
//Linux
#if defined(INPUT_UDEV)
"udev;"
"udev",
#endif
#if defined(INPUT_SDL)
"SDL;"
"SDL",
#endif
#if defined(INPUT_XLIB)
"Xlib;"
"Xlib",
#endif
"None";
"None"};
}
auto InputInterface::init() -> bool {
if(!p) driver();
return p->init();
}
auto InputInterface::term() -> void {
if(p) {
p->term();
delete p;
p = nullptr;
}
}
InputInterface::~InputInterface() { term(); }
auto InputInterface::cap(const string& name) -> bool { return p ? p->cap(name) : false; }
auto InputInterface::get(const string& name) -> any { return p ? p->get(name) : false; }
auto InputInterface::set(const string& name, const any& value) -> bool { return p ? p->set(name, value) : false; }
auto InputInterface::acquire() -> bool { return p ? p->acquire() : false; }
auto InputInterface::unacquire() -> bool { return p ? p->unacquire() : false; }
auto InputInterface::acquired() -> bool { return p ? p->acquired() : false; }
auto InputInterface::poll() -> vector<shared_pointer<HID::Device>> { return p ? p->poll() : vector<shared_pointer<HID::Device>>(); }
auto InputInterface::rumble(uint64_t id, bool enable) -> bool { return p ? p->rumble(id, enable) : false; }
};

View File

@ -1,7 +1,7 @@
/* ruby
* author: byuu
* license: ISC
* version: 0.12 (2015-05-24)
* version: 0.13 (2015-06-18)
*
* ruby is a cross-platform hardware abstraction layer
* it provides a common interface to video, audio and input devices
@ -14,84 +14,97 @@
namespace ruby {
#include <ruby/video.hpp>
#include <ruby/audio.hpp>
#include <ruby/input.hpp>
struct Video {
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;
struct VideoInterface {
~VideoInterface();
static const unsigned FilterNearest;
static const unsigned FilterLinear;
auto driver(nall::string driver = "") -> void;
auto optimalDriver() -> nall::string;
auto safestDriver() -> nall::string;
auto availableDrivers() -> nall::string;
auto init() -> bool;
auto term() -> void;
static auto create(const nall::string& driver = "") -> Video*;
static auto optimalDriver() -> nall::string;
static auto safestDriver() -> nall::string;
static auto availableDrivers() -> nall::lstring;
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;
virtual ~Video() = default;
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool;
auto unlock() -> void;
auto clear() -> void;
auto refresh() -> void;
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 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 {}
virtual auto init() -> bool { return true; }
virtual auto term() -> void {}
};
struct Audio {
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;
static auto create(const nall::string& driver = "") -> Audio*;
static auto optimalDriver() -> nall::string;
static auto safestDriver() -> nall::string;
static auto availableDrivers() -> nall::lstring;
virtual ~Audio() = default;
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 auto sample(uint16_t left, uint16_t right) -> void {}
virtual auto clear() -> void {}
virtual auto init() -> bool { return true; }
virtual auto term() -> void {}
};
struct Input {
static const nall::string Handle;
static const nall::string KeyboardSupport;
static const nall::string MouseSupport;
static const nall::string JoypadSupport;
static const nall::string JoypadRumbleSupport;
static auto create(const nall::string& driver = "") -> Input*;
static auto optimalDriver() -> nall::string;
static auto safestDriver() -> nall::string;
static auto availableDrivers() -> nall::lstring;
virtual ~Input() = default;
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 auto acquire() -> bool { return false; }
virtual auto release() -> 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 {}
auto onChange(const nall::function<void (nall::shared_pointer<nall::HID::Device>, unsigned, unsigned, int16_t, int16_t)>& callback) { _onChange = callback; }
auto doChange(nall::shared_pointer<nall::HID::Device> device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue) -> void {
if(_onChange) _onChange(device, group, input, oldValue, newValue);
}
private:
Video* p = nullptr;
nall::function<void (nall::shared_pointer<nall::HID::Device> device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue)> _onChange;
};
struct 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;
};
struct InputInterface {
nall::function<void (nall::shared_pointer<nall::HID::Device> device, unsigned group, unsigned input, int16_t oldValue, int16_t newValue)> onChange;
~InputInterface();
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 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;
private:
Input* p = nullptr;
};
extern VideoInterface video;
extern AudioInterface audio;
extern InputInterface input;
};
}
#endif

View File

@ -1,24 +0,0 @@
struct Video {
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 ~Video() = default;
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 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 {}
virtual auto init() -> bool { return true; }
virtual auto term() -> void {}
};

View File

@ -1,20 +1,18 @@
#include "opengl/opengl.hpp"
namespace ruby {
struct pVideoCGL;
}
struct VideoCGL;
@interface RubyVideoCGL : NSOpenGLView {
@public
ruby::pVideoCGL* video;
ruby::VideoCGL* video;
}
-(id) initWith:(ruby::pVideoCGL*)video pixelFormat:(NSOpenGLPixelFormat*)pixelFormat;
-(id) initWith:(ruby::VideoCGL*)video pixelFormat:(NSOpenGLPixelFormat*)pixelFormat;
-(void) reshape;
@end
namespace ruby {
struct VideoCGL : Video, OpenGL {
~VideoCGL() { term(); }
struct pVideoCGL : OpenGL {
RubyVideoCGL* view = nullptr;
struct {
@ -24,10 +22,6 @@ struct pVideoCGL : OpenGL {
string shader;
} settings;
~pVideoCGL() {
term();
}
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true;
@ -113,8 +107,6 @@ struct pVideoCGL : OpenGL {
}
auto init() -> bool {
term();
@autoreleasepool {
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
@ -161,13 +153,9 @@ struct pVideoCGL : OpenGL {
}
};
DeclareVideo(CGL)
}
@implementation RubyVideoCGL : NSOpenGLView
-(id) initWith:(ruby::pVideoCGL*)videoPointer pixelFormat:(NSOpenGLPixelFormat*)pixelFormat {
-(id) initWith:(ruby::VideoCGL*)videoPointer pixelFormat:(NSOpenGLPixelFormat*)pixelFormat {
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0) pixelFormat:pixelFormat]) {
video = videoPointer;
}

View File

@ -9,9 +9,9 @@
typedef HRESULT (__stdcall* EffectProc)(LPDIRECT3DDEVICE9, LPCVOID, UINT, D3DXMACRO const*, LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL, LPD3DXEFFECT*, LPD3DXBUFFER*);
typedef HRESULT (__stdcall* TextureProc)(LPDIRECT3DDEVICE9, LPCTSTR, LPDIRECT3DTEXTURE9*);
namespace ruby {
struct VideoD3D : Video {
~VideoD3D() { term(); }
struct pVideoD3D {
LPDIRECT3D9 lpd3d = nullptr;
LPDIRECT3DDEVICE9 device = nullptr;
LPDIRECT3DVERTEXBUFFER9 vertex_buffer = nullptr;
@ -61,10 +61,6 @@ struct pVideoD3D {
unsigned height;
} state;
~pVideoD3D() {
term();
}
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true;
@ -378,8 +374,6 @@ struct pVideoD3D {
}
auto init() -> bool {
term();
RECT rd;
GetClientRect(settings.handle, &rd);
state.width = rd.right;
@ -446,8 +440,4 @@ struct pVideoD3D {
}
};
DeclareVideo(D3D)
};
#undef D3DVERTEX

View File

@ -1,8 +1,8 @@
#include <ddraw.h>
namespace ruby {
struct VideoDD : Video {
~VideoDD() { term(); }
struct pVideoDD {
LPDIRECTDRAW lpdd = nullptr;
LPDIRECTDRAW7 lpdd7 = nullptr;
LPDIRECTDRAWSURFACE7 screen = nullptr;
@ -21,10 +21,6 @@ struct pVideoDD {
unsigned height;
} settings;
~pVideoDD() {
term();
}
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true;
@ -140,8 +136,6 @@ struct pVideoDD {
}
auto init() -> bool {
term();
DirectDrawCreate(0, &lpdd, 0);
lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7);
if(lpdd) { lpdd->Release(); lpdd = 0; }
@ -175,7 +169,3 @@ struct pVideoDD {
if(lpdd) { lpdd->Release(); lpdd = 0; }
}
};
DeclareVideo(DD)
};

View File

@ -1,8 +1,8 @@
#include <assert.h>
namespace ruby {
struct VideoGDI : Video {
~VideoGDI() { term(); }
struct pVideoGDI {
uint32_t* buffer = nullptr;
HBITMAP bitmap = nullptr;
HDC bitmapdc = nullptr;
@ -11,19 +11,10 @@ struct pVideoGDI {
struct {
HWND handle = nullptr;
unsigned width;
unsigned height;
unsigned width = 0;
unsigned height = 0;
} settings;
pVideoGDI() {
buffer = (uint32_t*)memory::allocate(1024 * 1024 * sizeof(uint32_t));
}
~pVideoGDI() {
if(buffer) memory::free(buffer);
term();
}
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
return false;
@ -66,6 +57,8 @@ struct pVideoGDI {
}
auto init() -> bool {
buffer = (uint32_t*)memory::allocate(1024 * 1024 * sizeof(uint32_t));
HDC hdc = GetDC(settings.handle);
bitmapdc = CreateCompatibleDC(hdc);
assert(bitmapdc);
@ -91,9 +84,6 @@ struct pVideoGDI {
auto term() -> void {
DeleteObject(bitmap);
DeleteDC(bitmapdc);
if(buffer) { memory::free(buffer); buffer = nullptr; }
}
};
DeclareVideo(GDI)
};

View File

@ -3,9 +3,9 @@
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
namespace ruby {
struct VideoGLX : Video, OpenGL {
~VideoGLX() { term(); }
struct pVideoGLX : OpenGL {
auto (*glXCreateContextAttribs)(Display*, GLXFBConfig, GLXContext, signed, const signed*) -> GLXContext = nullptr;
auto (*glXSwapInterval)(signed) -> signed = nullptr;
@ -31,10 +31,6 @@ struct pVideoGLX : OpenGL {
string shader;
} settings;
~pVideoGLX() {
term();
}
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true;
@ -128,8 +124,6 @@ struct pVideoGLX : OpenGL {
}
auto init() -> bool {
term();
display = XOpenDisplay(0);
screen = DefaultScreen(display);
@ -239,7 +233,3 @@ struct pVideoGLX : OpenGL {
}
}
};
DeclareVideo(GLX)
};

View File

@ -43,7 +43,6 @@ PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = nullptr;
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = nullptr;
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr;
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = nullptr;
PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
static bool OpenGLBind() {
#define bind(prototype, function) \
@ -90,7 +89,6 @@ static bool OpenGLBind() {
bind(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers);
bind(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer);
bind(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D);
bind(PFNGLACTIVETEXTUREPROC, glActiveTexture);
#undef bind

View File

@ -13,8 +13,6 @@
#error "ruby::OpenGL: unsupported platform"
#endif
namespace ruby {
#include "bind.hpp"
#include "shaders.hpp"
#include "utility.hpp"
@ -94,5 +92,3 @@ struct OpenGL : OpenGLProgram {
#include "surface.hpp"
#include "program.hpp"
#include "main.hpp"
}

View File

@ -5,9 +5,9 @@
#include <X11/extensions/XShm.h>
#include <SDL/SDL.h>
namespace ruby {
struct VideoSDL : Video {
~VideoSDL() { term(); }
struct pVideoSDL {
Display* display = nullptr;
SDL_Surface* screen = nullptr;
SDL_Surface* buffer = nullptr;
@ -21,10 +21,6 @@ struct pVideoSDL {
unsigned height = 0;
} settings;
~pVideoSDL() {
term();
}
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
return false;
@ -137,7 +133,3 @@ struct pVideoSDL {
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
};
DeclareVideo(SDL)
};

View File

@ -3,9 +3,9 @@
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
namespace ruby {
struct VideoWGL : Video, OpenGL {
~VideoWGL() { term(); }
struct pVideoWGL : OpenGL {
HGLRC (APIENTRY* wglCreateContextAttribs)(HDC, HGLRC, const int*) = nullptr;
BOOL (APIENTRY* wglSwapInterval)(int) = nullptr;
@ -21,10 +21,6 @@ struct pVideoWGL : OpenGL {
string shader;
} settings;
~pVideoWGL() {
term();
}
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true;
@ -95,8 +91,6 @@ struct pVideoWGL : OpenGL {
}
auto init() -> bool {
term();
GLuint pixel_format;
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
@ -146,7 +140,3 @@ struct pVideoWGL : OpenGL {
}
}
};
DeclareVideo(WGL)
};

View File

@ -8,9 +8,9 @@
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
namespace ruby {
struct VideoXShm : Video {
~VideoXShm() { term(); }
struct pVideoXShm {
struct Device {
Display* display = nullptr;
signed screen = 0;
@ -34,10 +34,6 @@ struct pVideoXShm {
unsigned height = 0;
} settings;
~pVideoXShm() {
term();
}
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
if(name == Video::Filter) return true;
@ -207,7 +203,3 @@ private:
return cr << 16 | cg << 8 | cb << 0;
}
};
DeclareVideo(XShm)
}

View File

@ -6,9 +6,9 @@
extern "C" auto XvShmCreateImage(Display*, XvPortID, signed, char*, signed, signed, XShmSegmentInfo*) -> XvImage*;
namespace ruby {
struct VideoXv : Video {
~VideoXv() { term(); }
struct pVideoXv {
uint32_t* buffer = nullptr;
uint8_t* ytable = nullptr;
uint8_t* utable = nullptr;
@ -51,10 +51,6 @@ struct pVideoXv {
unsigned height = 0;
} settings;
~pVideoXv() {
term();
}
auto cap(const string& name) -> bool {
if(name == Video::Handle) return true;
if(name == Video::Synchronize) {
@ -481,7 +477,3 @@ private:
}
}
};
DeclareVideo(Xv)
};

View File

@ -44,9 +44,9 @@ ConfigurationManager::ConfigurationManager() {
load({configpath(), "tomoko/settings.bml"});
if(!library.location) library.location = {userpath(), "Emulation/"};
if(!video.driver) video.driver = ruby::video.safestDriver();
if(!audio.driver) audio.driver = ruby::audio.safestDriver();
if(!input.driver) input.driver = ruby::input.safestDriver();
if(!video.driver) video.driver = ruby::Video::safestDriver();
if(!audio.driver) audio.driver = ruby::Audio::safestDriver();
if(!input.driver) input.driver = ruby::Input::safestDriver();
save({configpath(), "tomoko/settings.bml"});
}

View File

@ -10,7 +10,7 @@ auto InputManager::appendHotkeys() -> void {
{ auto hotkey = new InputHotkey;
hotkey->name = "Toggle Mouse Capture";
hotkey->action = [] {
input.acquired() ? input.unacquire() : input.acquire();
input->acquired() ? input->release() : input->acquire();
};
hotkeys.append(hotkey);
}

View File

@ -131,7 +131,6 @@ auto InputMapping::deviceName() -> string {
InputManager::InputManager() {
inputManager = this;
input.onChange = {&InputManager::onChange, this};
for(auto& emulator : program->emulators) {
Configuration::Node nodeEmulator;
@ -175,7 +174,6 @@ InputManager::InputManager() {
appendHotkeys();
config.load({configpath(), "tomoko/input.bml"});
config.save({configpath(), "tomoko/input.bml"});
poll(); //will call bind();
}
auto InputManager::bind() -> void {
@ -195,7 +193,7 @@ auto InputManager::bind() -> void {
}
auto InputManager::poll() -> void {
auto devices = input.poll();
auto devices = input->poll();
bool changed = devices.size() != this->devices.size();
if(changed == false) {
for(auto n : range(devices)) {

View File

@ -64,11 +64,11 @@ Presentation::Presentation() {
});
synchronizeVideo.setText("Synchronize Video").setChecked(config->video.synchronize).onToggle([&] {
config->video.synchronize = synchronizeVideo.checked();
video.set(Video::Synchronize, config->video.synchronize);
video->set(Video::Synchronize, config->video.synchronize);
});
synchronizeAudio.setText("Synchronize Audio").setChecked(config->audio.synchronize).onToggle([&] {
config->audio.synchronize = synchronizeAudio.checked();
audio.set(Audio::Synchronize, config->audio.synchronize);
audio->set(Audio::Synchronize, config->audio.synchronize);
});
muteAudio.setText("Mute Audio").setChecked(config->audio.mute).onToggle([&] {
config->audio.mute = muteAudio.checked();
@ -194,9 +194,9 @@ auto Presentation::toggleFullScreen() -> void {
statusBar.setVisible(false);
setResizable(true);
setFullScreen(true);
if(!input.acquired()) input.acquire();
if(!input->acquired()) input->acquire();
} else {
if(input.acquired()) input.unacquire();
if(input->acquired()) input->release();
setFullScreen(false);
setResizable(false);
menuBar.setVisible(true);
@ -208,14 +208,15 @@ auto Presentation::toggleFullScreen() -> void {
}
auto Presentation::drawSplashScreen() -> void {
if(!video) return;
uint32* output;
unsigned length;
if(video.lock(output, length, 256, 240)) {
if(video->lock(output, length, 256, 240)) {
for(auto y : range(240)) {
uint32* dp = output + y * (length >> 2);
for(auto x : range(256)) *dp++ = 0xff000000;
}
video.unlock();
video.refresh();
video->unlock();
video->refresh();
}
}

View File

@ -63,7 +63,7 @@ auto Program::videoRefresh(const uint32* palette, const uint32* data, unsigned p
uint32* output;
unsigned length;
if(video.lock(output, length, width, height)) {
if(video->lock(output, length, width, height)) {
pitch >>= 2, length >>= 2;
for(auto y : range(height)) {
@ -89,8 +89,8 @@ auto Program::videoRefresh(const uint32* palette, const uint32* data, unsigned p
}
}
video.unlock();
video.refresh();
video->unlock();
video->refresh();
}
static unsigned frameCounter = 0;
@ -110,7 +110,7 @@ auto Program::audioSample(int16 lsample, int16 rsample) -> void {
dsp.sample(samples);
while(dsp.pending()) {
dsp.read(samples);
audio.sample(samples[0], samples[1]);
audio->sample(samples[0], samples[1]);
}
}

View File

@ -13,6 +13,7 @@ Program::Program() {
program = this;
directory::create({configpath(), "tomoko/"});
Application::onMain({&Program::main, this});
Application::Windows::onModalChange([](bool modal) { if(modal && audio) audio->clear(); });
emulators.append(new Famicom::Interface);
emulators.append(new SuperFamicom::Interface);
@ -29,22 +30,32 @@ Program::Program() {
presentation->setVisible();
video.driver(config->video.driver);
video.set(Video::Handle, presentation->viewport.handle());
video.set(Video::Synchronize, config->video.synchronize);
if(!video.init()) { video.driver("None"); video.init(); }
video = Video::create(config->video.driver);
video->set(Video::Handle, presentation->viewport.handle());
video->set(Video::Synchronize, config->video.synchronize);
if(!video->init()) {
delete video;
video = Video::create("None");
}
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);
audio.set(Audio::Latency, 80u);
if(!audio.init()) { audio.driver("None"); audio.init(); }
audio = Audio::create(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);
audio->set(Audio::Latency, 80u);
if(!audio->init()) {
delete audio;
audio = Audio::create("None");
}
input.driver(config->input.driver);
input.set(Input::Handle, presentation->viewport.handle());
if(!input.init()) { input.driver("None"); input.init(); }
input = Input::create(config->input.driver);
input->set(Input::Handle, presentation->viewport.handle());
input->onChange({&InputManager::onChange, inputManager});
if(!input->init()) {
delete input;
input = Input::create("None");
}
dsp.setPrecision(16);
dsp.setBalance(0.0);
@ -63,7 +74,7 @@ auto Program::main() -> void {
inputManager->poll();
if(!emulator || !emulator->loaded() || pause) {
audio.clear();
audio->clear();
usleep(20 * 1000);
return;
}
@ -75,8 +86,8 @@ auto Program::quit() -> void {
unloadMedia();
config->quit();
inputManager->quit();
video.term();
audio.term();
input.term();
delete video;
delete audio;
delete input;
Application::quit();
}

View File

@ -36,8 +36,8 @@ auto Program::updateStatusText() -> void {
}
auto Program::updateVideoFilter() -> void {
if(config->video.filter == "None") video.set(Video::Filter, Video::FilterNearest);
if(config->video.filter == "Blur") video.set(Video::Filter, Video::FilterLinear);
if(config->video.filter == "None") video->set(Video::Filter, Video::FilterNearest);
if(config->video.filter == "Blur") video->set(Video::Filter, Video::FilterLinear);
}
auto Program::updateVideoPalette() -> void {
@ -49,8 +49,9 @@ auto Program::updateVideoPalette() -> void {
}
auto Program::updateAudio() -> void {
audio.set(Audio::Frequency, config->audio.frequency);
audio.set(Audio::Latency, config->audio.latency);
if(!audio) return;
audio->set(Audio::Frequency, config->audio.frequency);
audio->set(Audio::Latency, config->audio.latency);
if(auto resampler = config->audio.resampler) {
if(resampler == "Linear" ) dsp.setResampler(DSP::ResampleEngine::Linear);
if(resampler == "Hermite") dsp.setResampler(DSP::ResampleEngine::Hermite);

View File

@ -7,7 +7,7 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
driverLabel.setText("Driver Selection").setFont(Font::sans(8, "Bold"));
videoLabel.setText("Video:");
videoDriver.onChange([&] { config->video.driver = videoDriver.selected()->text(); });
for(auto& driver : string{video.availableDrivers()}.split(";")) {
for(auto& driver : Video::availableDrivers()) {
ComboButtonItem item;
item.setText(driver);
videoDriver.append(item);
@ -15,7 +15,7 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
}
audioLabel.setText("Audio:");
audioDriver.onChange([&] { config->audio.driver = audioDriver.selected()->text(); });
for(auto& driver : string{audio.availableDrivers()}.split(";")) {
for(auto& driver : Audio::availableDrivers()) {
ComboButtonItem item;
item.setText(driver);
audioDriver.append(item);
@ -23,7 +23,7 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
}
inputLabel.setText("Input:");
inputDriver.onChange([&] { config->input.driver = inputDriver.selected()->text(); });
for(auto& driver : string{input.availableDrivers()}.split(";")) {
for(auto& driver : Input::availableDrivers()) {
ComboButtonItem item;
item.setText(driver);
inputDriver.append(item);

View File

@ -1,4 +1,7 @@
#include "tomoko.hpp"
Video* video = nullptr;
Audio* audio = nullptr;
Input* input = nullptr;
Emulator::Interface* emulator = nullptr;
#include <nall/main.hpp>

View File

@ -1,12 +1,15 @@
#include <emulator/emulator.hpp>
extern Emulator::Interface* emulator;
#include <nall/nall.hpp>
#include <ruby/ruby.hpp>
#include <hiro/hiro.hpp>
using namespace nall;
using namespace ruby;
using namespace hiro;
extern Video* video;
extern Audio* audio;
extern Input* input;
#include <emulator/emulator.hpp>
extern Emulator::Interface* emulator;
#include "program/program.hpp"
#include "configuration/configuration.hpp"