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 { namespace Emulator {
static const string Name = "higan"; 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 Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "http://byuu.org/"; static const string Website = "http://byuu.org/";

View File

@ -406,6 +406,8 @@ struct mObject {
mObject(const mObject&) = delete; mObject(const mObject&) = delete;
mObject& operator=(const mObject&) = delete; mObject& operator=(const mObject&) = delete;
explicit operator bool() const;
auto abstract() const -> bool; auto abstract() const -> bool;
auto adjustOffset(signed displacement) -> type&; auto adjustOffset(signed displacement) -> type&;
auto enabled(bool recursive = false) const -> bool; 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 //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) //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 //if the mObject is not abstract, the pObject delegate is allocated immediately

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,18 +15,20 @@ ifeq ($(platform),)
else ifneq ($(findstring Windows,$(uname)),) else ifneq ($(findstring Windows,$(uname)),)
platform := windows platform := windows
delete = del $(subst /,\,$1) delete = del $(subst /,\,$1)
else ifneq ($(findstring CYGWIN,$(uname)),) else ifneq ($(findstring _NT,$(uname)),)
platform := windows platform := windows
delete = del $(subst /,\,$1) delete = del $(subst /,\,$1)
else ifneq ($(findstring Darwin,$(uname)),) else ifneq ($(findstring Darwin,$(uname)),)
platform := macosx platform := macosx
delete = rm -f $1 delete = rm -f $1
else ifneq ($(findstring Linux,$(uname)),)
platform := linux
delete = rm -f $1
else ifneq ($(findstring BSD,$(uname)),) else ifneq ($(findstring BSD,$(uname)),)
platform := bsd platform := bsd
delete = rm -f $1 delete = rm -f $1
else else
platform := linux $(error unknown platform, please specify manually.)
delete = rm -f $1
endif endif
endif endif
@ -44,6 +46,8 @@ ifeq ($(compiler),)
cppflags := -x c++ -std=gnu++14 cppflags := -x c++ -std=gnu++14
else ifeq ($(platform),macosx) else ifeq ($(platform),macosx)
compiler := clang++ compiler := clang++
else ifeq ($(platform),linux)
compiler := g++-4.9
else ifeq ($(platform),bsd) else ifeq ($(platform),bsd)
compiler := g++49 compiler := g++49
else 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> #include <alsa/asoundlib.h>
namespace ruby { struct AudioALSA : Audio {
~AudioALSA() { term(); }
struct pAudioALSA {
struct { struct {
snd_pcm_t* handle = nullptr; snd_pcm_t* handle = nullptr;
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
@ -23,10 +23,6 @@ struct pAudioALSA {
unsigned latency = 60; unsigned latency = 60;
} settings; } settings;
~pAudioALSA() {
term();
}
auto cap(const string& name) -> bool { auto cap(const string& name) -> bool {
if(name == Audio::Synchronize) return true; if(name == Audio::Synchronize) return true;
if(name == Audio::Frequency) return true; if(name == Audio::Frequency) return true;
@ -127,8 +123,6 @@ struct pAudioALSA {
} }
auto init() -> bool { auto init() -> bool {
term();
if(snd_pcm_open(&device.handle, device.name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) { if(snd_pcm_open(&device.handle, device.name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) {
term(); term();
return false; return false;
@ -216,7 +210,3 @@ struct pAudioALSA {
} }
} }
}; };
DeclareAudio(ALSA)
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
#include "xaudio2.hpp" #include "xaudio2.hpp"
#include <windows.h> #include <windows.h>
namespace ruby { struct AudioXAudio2 : Audio, public IXAudio2VoiceCallback {
AudioXAudio2() { term(); }
struct pAudioXAudio2 : public IXAudio2VoiceCallback {
IXAudio2* pXAudio2 = nullptr; IXAudio2* pXAudio2 = nullptr;
IXAudio2MasteringVoice* pMasterVoice = nullptr; IXAudio2MasteringVoice* pMasterVoice = nullptr;
IXAudio2SourceVoice* pSourceVoice = nullptr; IXAudio2SourceVoice* pSourceVoice = nullptr;
@ -33,10 +33,6 @@ struct pAudioXAudio2 : public IXAudio2VoiceCallback {
unsigned latency = 120; unsigned latency = 120;
} settings; } settings;
~pAudioXAudio2() {
term();
}
auto cap(const string& name) -> bool { auto cap(const string& name) -> bool {
if(name == Audio::Synchronize) return true; if(name == Audio::Synchronize) return true;
if(name == Audio::Frequency) return true; if(name == Audio::Frequency) return true;
@ -117,8 +113,6 @@ struct pAudioXAudio2 : public IXAudio2VoiceCallback {
} }
auto init() -> bool { auto init() -> bool {
term();
device.buffers = 8; device.buffers = 8;
device.latency = settings.frequency * settings.latency / device.buffers / 1000.0 + 0.5; device.latency = settings.frequency * settings.latency / device.buffers / 1000.0 + 0.5;
device.buffer = new uint32_t[device.latency * device.buffers]; device.buffer = new uint32_t[device.latency * device.buffers];
@ -187,7 +181,3 @@ struct pAudioXAudio2 : public IXAudio2VoiceCallback {
InterlockedDecrement(&device.submitbuffers); 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 { struct Key {
uint8_t id; uint8_t id;
string name; string name;
@ -25,7 +25,7 @@ struct pInputCarbon {
} }
auto acquire() -> bool { return false; } auto acquire() -> bool { return false; }
auto unacquire() -> bool { return false; } auto release() -> bool { return false; }
auto acquired() -> bool { return false; } auto acquired() -> bool { return false; }
auto assign(shared_pointer<HID::Device> hid, unsigned groupID, unsigned inputID, int16_t value) -> void { auto assign(shared_pointer<HID::Device> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
@ -179,7 +179,3 @@ struct pInputCarbon {
auto term() -> void { auto term() -> void {
} }
}; };
DeclareInput(Carbon)
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,18 +1,66 @@
#include <ruby/ruby.hpp> #include <ruby/ruby.hpp>
using namespace nall;
using namespace ruby;
/* Shared */
#undef deprecated #undef deprecated
#undef mkdir #undef mkdir
#undef usleep #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 { namespace ruby {
VideoInterface video;
AudioInterface audio;
InputInterface input;
/* VideoInterface */
const string Video::Handle = "Handle"; const string Video::Handle = "Handle";
const string Video::Synchronize = "Synchronize"; const string Video::Synchronize = "Synchronize";
const string Video::Depth = "Depth"; const string Video::Depth = "Depth";
@ -22,61 +70,49 @@ const string Video::Shader = "Shader";
const unsigned Video::FilterNearest = 0; const unsigned Video::FilterNearest = 0;
const unsigned Video::FilterLinear = 1; const unsigned Video::FilterLinear = 1;
auto VideoInterface::driver(string driver) -> void { auto Video::create(const string& driver) -> Video* {
if(p) term(); if(!driver) return create(optimalDriver());
if(!driver) driver = optimalDriver(); #if defined(VIDEO_CGL)
if(driver == "OpenGL") return new VideoCGL;
if(0);
#ifdef VIDEO_CGL
else if(driver == "OpenGL") p = new VideoCGL();
#endif #endif
#ifdef VIDEO_DIRECT3D #if defined(VIDEO_DIRECT3D)
else if(driver == "Direct3D") p = new VideoD3D(); if(driver == "Direct3D") return new VideoD3D;
#endif #endif
#ifdef VIDEO_DIRECTDRAW #if defined(VIDEO_DIRECTDRAW)
else if(driver == "DirectDraw") p = new VideoDD(); if(driver == "DirectDraw") return new VideoDD;
#endif #endif
#ifdef VIDEO_GDI #if defined(VIDEO_GDI)
else if(driver == "GDI") p = new VideoGDI(); if(driver == "GDI") return new VideoGDI;
#endif #endif
#ifdef VIDEO_GLX #if defined(VIDEO_GLX)
else if(driver == "OpenGL") p = new VideoGLX(); if(driver == "OpenGL") return new VideoGLX;
#endif #endif
#ifdef VIDEO_QTOPENGL #if defined(VIDEO_SDL)
else if(driver == "Qt-OpenGL") p = new VideoQtOpenGL(); if(driver == "SDL") return new VideoSDL;
#endif #endif
#ifdef VIDEO_QTRASTER #if defined(VIDEO_WGL)
else if(driver == "Qt-Raster") p = new VideoQtRaster(); if(driver == "OpenGL") return new VideoWGL;
#endif #endif
#ifdef VIDEO_SDL #if defined(VIDEO_XSHM)
else if(driver == "SDL") p = new VideoSDL(); if(driver == "XShm") return new VideoXShm;
#endif #endif
#ifdef VIDEO_WGL #if defined(VIDEO_XV)
else if(driver == "OpenGL") p = new VideoWGL(); if(driver == "X-Video") return new VideoXv;
#endif #endif
#ifdef VIDEO_XSHM return new Video;
else if(driver == "XShm") p = new VideoXShm();
#endif
#ifdef VIDEO_XV
else if(driver == "X-Video") p = new VideoXv();
#endif
else p = new Video();
} }
auto VideoInterface::optimalDriver() -> string { auto Video::optimalDriver() -> string {
#if defined(VIDEO_WGL) #if defined(VIDEO_WGL)
return "OpenGL"; return "OpenGL";
#elif defined(VIDEO_DIRECT3D) #elif defined(VIDEO_DIRECT3D)
@ -85,10 +121,8 @@ auto VideoInterface::optimalDriver() -> string {
return "DirectDraw"; return "DirectDraw";
#elif defined(VIDEO_GDI) #elif defined(VIDEO_GDI)
return "GDI"; return "GDI";
#elif defined(VIDEO_CGL) #elif defined(VIDEO_CGL)
return "OpenGL"; return "OpenGL";
#elif defined(VIDEO_GLX) #elif defined(VIDEO_GLX)
return "OpenGL"; return "OpenGL";
#elif defined(VIDEO_XV) #elif defined(VIDEO_XV)
@ -97,13 +131,12 @@ auto VideoInterface::optimalDriver() -> string {
return "XShm"; return "XShm";
#elif defined(VIDEO_SDL) #elif defined(VIDEO_SDL)
return "SDL"; return "SDL";
#else #else
return "None"; return "None";
#endif #endif
} }
auto VideoInterface::safestDriver() -> string { auto Video::safestDriver() -> string {
#if defined(VIDEO_DIRECT3D) #if defined(VIDEO_DIRECT3D)
return "Direct3D"; return "Direct3D";
#elif defined(VIDEO_WGL) #elif defined(VIDEO_WGL)
@ -112,10 +145,8 @@ auto VideoInterface::safestDriver() -> string {
return "DirectDraw"; return "DirectDraw";
#elif defined(VIDEO_GDI) #elif defined(VIDEO_GDI)
return "GDI"; return "GDI";
#elif defined(VIDEO_CGL) #elif defined(VIDEO_CGL)
return "OpenGL"; return "OpenGL";
#elif defined(VIDEO_XSHM) #elif defined(VIDEO_XSHM)
return "XShm"; return "XShm";
#elif defined(VIDEO_SDL) #elif defined(VIDEO_SDL)
@ -124,83 +155,90 @@ auto VideoInterface::safestDriver() -> string {
return "X-Video"; return "X-Video";
#elif defined(VIDEO_GLX) #elif defined(VIDEO_GLX)
return "OpenGL"; return "OpenGL";
#else #else
return "None"; return "None";
#endif #endif
} }
auto VideoInterface::availableDrivers() -> string { auto Video::availableDrivers() -> lstring {
return return {
//Windows
#if defined(VIDEO_WGL) #if defined(VIDEO_WGL)
"OpenGL;" "OpenGL",
#endif #endif
#if defined(VIDEO_DIRECT3D) #if defined(VIDEO_DIRECT3D)
"Direct3D;" "Direct3D",
#endif #endif
#if defined(VIDEO_DIRECTDRAW) #if defined(VIDEO_DIRECTDRAW)
"DirectDraw;" "DirectDraw",
#endif #endif
#if defined(VIDEO_GDI) #if defined(VIDEO_GDI)
"GDI;" "GDI",
#endif #endif
//OS X
#if defined(VIDEO_CGL) #if defined(VIDEO_CGL)
"OpenGL;" "OpenGL",
#endif #endif
//Linux
#if defined(VIDEO_GLX) #if defined(VIDEO_GLX)
"OpenGL;" "OpenGL",
#endif #endif
#if defined(VIDEO_XV) #if defined(VIDEO_XV)
"X-Video;" "X-Video",
#endif #endif
#if defined(VIDEO_XSHM) #if defined(VIDEO_XSHM)
"XShm;" "XShm",
#endif #endif
#if defined(VIDEO_SDL) #if defined(VIDEO_SDL)
"SDL;" "SDL",
#endif #endif
"None"; "None"};
} }
auto VideoInterface::init() -> bool {
if(!p) driver();
return p->init();
} }
auto VideoInterface::term() -> void { /* Audio */
if(p) {
p->term();
delete p;
p = nullptr;
}
}
VideoInterface::~VideoInterface() { term(); } #if defined(AUDIO_ALSA)
auto VideoInterface::cap(const string& name) -> bool { return p ? p->cap(name) : false; } #include <ruby/audio/alsa.cpp>
auto VideoInterface::get(const string& name) -> any { return p ? p->get(name) : false; } #endif
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 */ #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::Device = "Device";
const string Audio::Handle = "Handle"; const string Audio::Handle = "Handle";
@ -208,80 +246,75 @@ const string Audio::Synchronize = "Synchronize";
const string Audio::Frequency = "Frequency"; const string Audio::Frequency = "Frequency";
const string Audio::Latency = "Latency"; const string Audio::Latency = "Latency";
auto AudioInterface::driver(string driver) -> void { auto Audio::create(const string& driver) -> Audio* {
if(p) term(); if(!driver) return create(optimalDriver());
if(!driver) driver = optimalDriver(); #if defined(AUDIO_ALSA)
if(driver == "ALSA") return new AudioALSA;
if(0);
#ifdef AUDIO_ALSA
else if(driver == "ALSA") p = new AudioALSA();
#endif #endif
#ifdef AUDIO_AO #if defined(AUDIO_AO)
else if(driver == "libao") p = new AudioAO(); if(driver == "libao") return new AudioAO;
#endif #endif
#ifdef AUDIO_DIRECTSOUND #if defined(AUDIO_DIRECTSOUND)
else if(driver == "DirectSound") p = new AudioDS(); if(driver == "DirectSound") return new AudioDS;
#endif #endif
#ifdef AUDIO_OPENAL #if defined(AUDIO_OPENAL)
else if(driver == "OpenAL") p = new AudioOpenAL(); if(driver == "OpenAL") return new AudioOpenAL;
#endif #endif
#ifdef AUDIO_OSS #if defined(AUDIO_OSS)
else if(driver == "OSS") p = new AudioOSS(); if(driver == "OSS") return new AudioOSS;
#endif #endif
#ifdef AUDIO_PULSEAUDIO #if defined(AUDIO_PULSEAUDIO)
else if(driver == "PulseAudio") p = new AudioPulseAudio(); if(driver == "PulseAudio") return new AudioPulseAudio;
#endif #endif
#ifdef AUDIO_PULSEAUDIOSIMPLE #if defined(AUDIO_PULSEAUDIOSIMPLE)
else if(driver == "PulseAudioSimple") p = new AudioPulseAudioSimple(); if(driver == "PulseAudioSimple") return new AudioPulseAudioSimple;
#endif #endif
#ifdef AUDIO_XAUDIO2 #if defined(AUDIO_XAUDIO2)
else if(driver == "XAudio2") p = new AudioXAudio2(); if(driver == "XAudio2") return new AudioXAudio2;
#endif #endif
else p = new Audio(); return new Audio;
} }
auto AudioInterface::optimalDriver() -> string { auto Audio::optimalDriver() -> string {
#if defined(AUDIO_XAUDIO2) #if defined(AUDIO_XAUDIO2)
return "XAudio2"; return "XAudio2";
#elif defined(AUDIO_DIRECTSOUND) #elif defined(AUDIO_DIRECTSOUND)
return "DirectSound"; return "DirectSound";
#elif defined(AUDIO_ALSA) #elif defined(AUDIO_ALSA)
return "ALSA"; return "ALSA";
#elif defined(AUDIO_OPENAL)
return "OpenAL";
#elif defined(AUDIO_OSS) #elif defined(AUDIO_OSS)
return "OSS"; return "OSS";
#elif defined(AUDIO_OPENAL)
return "OpenAL";
#elif defined(AUDIO_PULSEAUDIO) #elif defined(AUDIO_PULSEAUDIO)
return "PulseAudio"; return "PulseAudio";
#elif defined(AUDIO_PULSEAUDIOSIMPLE) #elif defined(AUDIO_PULSEAUDIOSIMPLE)
return "PulseAudioSimple"; return "PulseAudioSimple";
#elif defined(AUDIO_AO) #elif defined(AUDIO_AO)
return "libao"; return "libao";
#else #else
return "None"; return "None";
#endif #endif
} }
auto AudioInterface::safestDriver() -> string { auto Audio::safestDriver() -> string {
#if defined(AUDIO_DIRECTSOUND) #if defined(AUDIO_DIRECTSOUND)
return "DirectSound"; return "DirectSound";
#elif defined(AUDIO_XAUDIO2) #elif defined(AUDIO_XAUDIO2)
return "XAudio2"; return "XAudio2";
#elif defined(AUDIO_ALSA) #elif defined(AUDIO_ALSA)
return "ALSA"; return "ALSA";
#elif defined(AUDIO_OSS)
return "OSS";
#elif defined(AUDIO_OPENAL) #elif defined(AUDIO_OPENAL)
return "OpenAL"; return "OpenAL";
#elif defined(AUDIO_PULSEAUDIO) #elif defined(AUDIO_PULSEAUDIO)
@ -290,77 +323,74 @@ auto AudioInterface::safestDriver() -> string {
return "PulseAudioSimple"; return "PulseAudioSimple";
#elif defined(AUDIO_AO) #elif defined(AUDIO_AO)
return "libao"; return "libao";
#elif defined(AUDIO_OSS)
return "OSS";
#else #else
return "None"; return "None";
#endif #endif
} }
auto AudioInterface::availableDrivers() -> string { auto Audio::availableDrivers() -> lstring {
return return {
//Windows
#if defined(AUDIO_XAUDIO2) #if defined(AUDIO_XAUDIO2)
"XAudio2;" "XAudio2",
#endif #endif
#if defined(AUDIO_DIRECTSOUND) #if defined(AUDIO_DIRECTSOUND)
"DirectSound;" "DirectSound",
#endif #endif
//Linux
#if defined(AUDIO_ALSA) #if defined(AUDIO_ALSA)
"ALSA;" "ALSA",
#endif
#if defined(AUDIO_OPENAL)
"OpenAL;"
#endif #endif
#if defined(AUDIO_OSS) #if defined(AUDIO_OSS)
"OSS;" "OSS",
#endif
#if defined(AUDIO_OPENAL)
"OpenAL",
#endif #endif
#if defined(AUDIO_PULSEAUDIO) #if defined(AUDIO_PULSEAUDIO)
"PulseAudio;" "PulseAudio",
#endif #endif
#if defined(AUDIO_PULSEAUDIOSIMPLE) #if defined(AUDIO_PULSEAUDIOSIMPLE)
"PulseAudioSimple;" "PulseAudioSimple",
#endif #endif
#if defined(AUDIO_AO) #if defined(AUDIO_AO)
"libao;" "libao",
#endif #endif
"None"; "None"};
} }
auto AudioInterface::init() -> bool {
if(!p) driver();
return p->init();
} }
auto AudioInterface::term() -> void { /* Input */
if(p) {
p->term();
delete p;
p = nullptr;
}
}
AudioInterface::~AudioInterface() { term(); } #if defined(INPUT_CARBON)
auto AudioInterface::cap(const string& name) -> bool { return p ? p->cap(name) : false; } #include <ruby/input/carbon.cpp>
auto AudioInterface::get(const string& name) -> any { return p ? p->get(name) : false; } #endif
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 */ #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::Handle = "Handle";
const string Input::KeyboardSupport = "KeyboardSupport"; const string Input::KeyboardSupport = "KeyboardSupport";
@ -368,127 +398,88 @@ const string Input::MouseSupport = "MouseSupport";
const string Input::JoypadSupport = "JoypadSupport"; const string Input::JoypadSupport = "JoypadSupport";
const string Input::JoypadRumbleSupport = "JoypadRumbleSupport"; const string Input::JoypadRumbleSupport = "JoypadRumbleSupport";
auto InputInterface::driver(string driver) -> void { auto Input::create(const string& driver) -> Input* {
if(p) term(); if(!driver) return create(optimalDriver());
if(!driver) driver = optimalDriver(); #if defined(INPUT_WINDOWS)
if(driver == "Windows") return new InputWindows;
if(0);
#ifdef INPUT_WINDOWS
else if(driver == "Windows") p = new InputWindows();
#endif #endif
#ifdef INPUT_CARBON #if defined(INPUT_CARBON)
else if(driver == "Carbon") p = new InputCarbon(); if(driver == "Carbon") return new InputCarbon;
#endif #endif
#ifdef INPUT_UDEV #if defined(INPUT_UDEV)
else if(driver == "udev") p = new InputUdev(); if(driver == "udev") return new InputUdev;
#endif #endif
#ifdef INPUT_SDL #if defined(INPUT_SDL)
else if(driver == "SDL") p = new InputSDL(); if(driver == "SDL") return new InputSDL;
#endif #endif
#ifdef INPUT_XLIB #if defined(INPUT_XLIB)
else if(driver == "Xlib") p = new InputXlib(); if(driver == "Xlib") return new InputXlib;
#endif #endif
else p = new Input(); return new Input;
} }
auto InputInterface::optimalDriver() -> string { auto Input::optimalDriver() -> string {
#if defined(INPUT_WINDOWS) #if defined(INPUT_WINDOWS)
return "Windows"; return "Windows";
#elif defined(INPUT_CARBON) #elif defined(INPUT_CARBON)
return "Carbon"; return "Carbon";
#elif defined(INPUT_UDEV) #elif defined(INPUT_UDEV)
return "udev"; return "udev";
#elif defined(INPUT_SDL) #elif defined(INPUT_SDL)
return "SDL"; return "SDL";
#elif defined(INPUT_XLIB) #elif defined(INPUT_XLIB)
return "Xlib"; return "Xlib";
#else #else
return "None"; return "None";
#endif #endif
} }
auto InputInterface::safestDriver() -> string { auto Input::safestDriver() -> string {
#if defined(INPUT_WINDOWS) #if defined(INPUT_WINDOWS)
return "Windows"; return "Windows";
#elif defined(INPUT_CARBON) #elif defined(INPUT_CARBON)
return "Carbon"; return "Carbon";
#elif defined(INPUT_UDEV) #elif defined(INPUT_UDEV)
return "udev"; return "udev";
#elif defined(INPUT_SDL) #elif defined(INPUT_SDL)
return "SDL"; return "SDL";
#elif defined(INPUT_XLIB) #elif defined(INPUT_XLIB)
return "Xlib"; return "Xlib";
#else #else
return "none"; return "none";
#endif #endif
} }
auto InputInterface::availableDrivers() -> string { auto Input::availableDrivers() -> lstring {
return return {
//Windows
#if defined(INPUT_WINDOWS) #if defined(INPUT_WINDOWS)
"Windows;" "Windows",
#endif #endif
//OS X
#if defined(INPUT_CARBON) #if defined(INPUT_CARBON)
"Carbon;" "Carbon",
#endif #endif
//Linux
#if defined(INPUT_UDEV) #if defined(INPUT_UDEV)
"udev;" "udev",
#endif #endif
#if defined(INPUT_SDL) #if defined(INPUT_SDL)
"SDL;" "SDL",
#endif #endif
#if defined(INPUT_XLIB) #if defined(INPUT_XLIB)
"Xlib;" "Xlib",
#endif #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 /* ruby
* author: byuu * author: byuu
* license: ISC * license: ISC
* version: 0.12 (2015-05-24) * version: 0.13 (2015-06-18)
* *
* ruby is a cross-platform hardware abstraction layer * ruby is a cross-platform hardware abstraction layer
* it provides a common interface to video, audio and input devices * it provides a common interface to video, audio and input devices
@ -14,84 +14,97 @@
namespace ruby { namespace ruby {
#include <ruby/video.hpp> struct Video {
#include <ruby/audio.hpp> static const nall::string Handle;
#include <ruby/input.hpp> static const nall::string Synchronize;
static const nall::string Depth;
static const nall::string Filter;
static const nall::string Shader;
struct VideoInterface { static const unsigned FilterNearest;
~VideoInterface(); static const unsigned FilterLinear;
auto driver(nall::string driver = "") -> void; static auto create(const nall::string& driver = "") -> Video*;
auto optimalDriver() -> nall::string; static auto optimalDriver() -> nall::string;
auto safestDriver() -> nall::string; static auto safestDriver() -> nall::string;
auto availableDrivers() -> nall::string; static auto availableDrivers() -> nall::lstring;
auto init() -> bool;
auto term() -> void;
auto cap(const nall::string& name) -> bool; virtual ~Video() = default;
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; virtual auto cap(const nall::string& name) -> bool { return false; }
auto unlock() -> void; virtual auto get(const nall::string& name) -> nall::any { return false; }
auto clear() -> void; virtual auto set(const nall::string& name, const nall::any& value) -> bool { return false; }
auto refresh() -> void;
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: 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 #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" #include "opengl/opengl.hpp"
namespace ruby { struct VideoCGL;
struct pVideoCGL;
}
@interface RubyVideoCGL : NSOpenGLView { @interface RubyVideoCGL : NSOpenGLView {
@public @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; -(void) reshape;
@end @end
namespace ruby { struct VideoCGL : Video, OpenGL {
~VideoCGL() { term(); }
struct pVideoCGL : OpenGL {
RubyVideoCGL* view = nullptr; RubyVideoCGL* view = nullptr;
struct { struct {
@ -24,10 +22,6 @@ struct pVideoCGL : OpenGL {
string shader; string shader;
} settings; } settings;
~pVideoCGL() {
term();
}
auto cap(const string& name) -> bool { auto cap(const string& name) -> bool {
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true; if(name == Video::Synchronize) return true;
@ -113,8 +107,6 @@ struct pVideoCGL : OpenGL {
} }
auto init() -> bool { auto init() -> bool {
term();
@autoreleasepool { @autoreleasepool {
NSOpenGLPixelFormatAttribute attributes[] = { NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
@ -161,13 +153,9 @@ struct pVideoCGL : OpenGL {
} }
}; };
DeclareVideo(CGL)
}
@implementation RubyVideoCGL : NSOpenGLView @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]) { if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0) pixelFormat:pixelFormat]) {
video = videoPointer; 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* EffectProc)(LPDIRECT3DDEVICE9, LPCVOID, UINT, D3DXMACRO const*, LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL, LPD3DXEFFECT*, LPD3DXBUFFER*);
typedef HRESULT (__stdcall* TextureProc)(LPDIRECT3DDEVICE9, LPCTSTR, LPDIRECT3DTEXTURE9*); typedef HRESULT (__stdcall* TextureProc)(LPDIRECT3DDEVICE9, LPCTSTR, LPDIRECT3DTEXTURE9*);
namespace ruby { struct VideoD3D : Video {
~VideoD3D() { term(); }
struct pVideoD3D {
LPDIRECT3D9 lpd3d = nullptr; LPDIRECT3D9 lpd3d = nullptr;
LPDIRECT3DDEVICE9 device = nullptr; LPDIRECT3DDEVICE9 device = nullptr;
LPDIRECT3DVERTEXBUFFER9 vertex_buffer = nullptr; LPDIRECT3DVERTEXBUFFER9 vertex_buffer = nullptr;
@ -61,10 +61,6 @@ struct pVideoD3D {
unsigned height; unsigned height;
} state; } state;
~pVideoD3D() {
term();
}
auto cap(const string& name) -> bool { auto cap(const string& name) -> bool {
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true; if(name == Video::Synchronize) return true;
@ -378,8 +374,6 @@ struct pVideoD3D {
} }
auto init() -> bool { auto init() -> bool {
term();
RECT rd; RECT rd;
GetClientRect(settings.handle, &rd); GetClientRect(settings.handle, &rd);
state.width = rd.right; state.width = rd.right;
@ -446,8 +440,4 @@ struct pVideoD3D {
} }
}; };
DeclareVideo(D3D)
};
#undef D3DVERTEX #undef D3DVERTEX

View File

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

View File

@ -1,8 +1,8 @@
#include <assert.h> #include <assert.h>
namespace ruby { struct VideoGDI : Video {
~VideoGDI() { term(); }
struct pVideoGDI {
uint32_t* buffer = nullptr; uint32_t* buffer = nullptr;
HBITMAP bitmap = nullptr; HBITMAP bitmap = nullptr;
HDC bitmapdc = nullptr; HDC bitmapdc = nullptr;
@ -11,19 +11,10 @@ struct pVideoGDI {
struct { struct {
HWND handle = nullptr; HWND handle = nullptr;
unsigned width; unsigned width = 0;
unsigned height; unsigned height = 0;
} settings; } 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 { auto cap(const string& name) -> bool {
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
return false; return false;
@ -66,6 +57,8 @@ struct pVideoGDI {
} }
auto init() -> bool { auto init() -> bool {
buffer = (uint32_t*)memory::allocate(1024 * 1024 * sizeof(uint32_t));
HDC hdc = GetDC(settings.handle); HDC hdc = GetDC(settings.handle);
bitmapdc = CreateCompatibleDC(hdc); bitmapdc = CreateCompatibleDC(hdc);
assert(bitmapdc); assert(bitmapdc);
@ -91,9 +84,6 @@ struct pVideoGDI {
auto term() -> void { auto term() -> void {
DeleteObject(bitmap); DeleteObject(bitmap);
DeleteDC(bitmapdc); 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_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 #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 (*glXCreateContextAttribs)(Display*, GLXFBConfig, GLXContext, signed, const signed*) -> GLXContext = nullptr;
auto (*glXSwapInterval)(signed) -> signed = nullptr; auto (*glXSwapInterval)(signed) -> signed = nullptr;
@ -31,10 +31,6 @@ struct pVideoGLX : OpenGL {
string shader; string shader;
} settings; } settings;
~pVideoGLX() {
term();
}
auto cap(const string& name) -> bool { auto cap(const string& name) -> bool {
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true; if(name == Video::Synchronize) return true;
@ -128,8 +124,6 @@ struct pVideoGLX : OpenGL {
} }
auto init() -> bool { auto init() -> bool {
term();
display = XOpenDisplay(0); display = XOpenDisplay(0);
screen = DefaultScreen(display); screen = DefaultScreen(display);
@ -239,7 +233,3 @@ struct pVideoGLX : OpenGL {
} }
} }
}; };
DeclareVideo(GLX)
};

View File

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

View File

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

View File

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

View File

@ -3,9 +3,9 @@
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #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; HGLRC (APIENTRY* wglCreateContextAttribs)(HDC, HGLRC, const int*) = nullptr;
BOOL (APIENTRY* wglSwapInterval)(int) = nullptr; BOOL (APIENTRY* wglSwapInterval)(int) = nullptr;
@ -21,10 +21,6 @@ struct pVideoWGL : OpenGL {
string shader; string shader;
} settings; } settings;
~pVideoWGL() {
term();
}
auto cap(const string& name) -> bool { auto cap(const string& name) -> bool {
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
if(name == Video::Synchronize) return true; if(name == Video::Synchronize) return true;
@ -95,8 +91,6 @@ struct pVideoWGL : OpenGL {
} }
auto init() -> bool { auto init() -> bool {
term();
GLuint pixel_format; GLuint pixel_format;
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); 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 <sys/shm.h>
#include <X11/extensions/XShm.h> #include <X11/extensions/XShm.h>
namespace ruby { struct VideoXShm : Video {
~VideoXShm() { term(); }
struct pVideoXShm {
struct Device { struct Device {
Display* display = nullptr; Display* display = nullptr;
signed screen = 0; signed screen = 0;
@ -34,10 +34,6 @@ struct pVideoXShm {
unsigned height = 0; unsigned height = 0;
} settings; } settings;
~pVideoXShm() {
term();
}
auto cap(const string& name) -> bool { auto cap(const string& name) -> bool {
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
if(name == Video::Filter) return true; if(name == Video::Filter) return true;
@ -207,7 +203,3 @@ private:
return cr << 16 | cg << 8 | cb << 0; 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*; 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; uint32_t* buffer = nullptr;
uint8_t* ytable = nullptr; uint8_t* ytable = nullptr;
uint8_t* utable = nullptr; uint8_t* utable = nullptr;
@ -51,10 +51,6 @@ struct pVideoXv {
unsigned height = 0; unsigned height = 0;
} settings; } settings;
~pVideoXv() {
term();
}
auto cap(const string& name) -> bool { auto cap(const string& name) -> bool {
if(name == Video::Handle) return true; if(name == Video::Handle) return true;
if(name == Video::Synchronize) { if(name == Video::Synchronize) {
@ -481,7 +477,3 @@ private:
} }
} }
}; };
DeclareVideo(Xv)
};

View File

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

View File

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

View File

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

View File

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

View File

@ -63,7 +63,7 @@ auto Program::videoRefresh(const uint32* palette, const uint32* data, unsigned p
uint32* output; uint32* output;
unsigned length; unsigned length;
if(video.lock(output, length, width, height)) { if(video->lock(output, length, width, height)) {
pitch >>= 2, length >>= 2; pitch >>= 2, length >>= 2;
for(auto y : range(height)) { for(auto y : range(height)) {
@ -89,8 +89,8 @@ auto Program::videoRefresh(const uint32* palette, const uint32* data, unsigned p
} }
} }
video.unlock(); video->unlock();
video.refresh(); video->refresh();
} }
static unsigned frameCounter = 0; static unsigned frameCounter = 0;
@ -110,7 +110,7 @@ auto Program::audioSample(int16 lsample, int16 rsample) -> void {
dsp.sample(samples); dsp.sample(samples);
while(dsp.pending()) { while(dsp.pending()) {
dsp.read(samples); 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; program = this;
directory::create({configpath(), "tomoko/"}); directory::create({configpath(), "tomoko/"});
Application::onMain({&Program::main, this}); Application::onMain({&Program::main, this});
Application::Windows::onModalChange([](bool modal) { if(modal && audio) audio->clear(); });
emulators.append(new Famicom::Interface); emulators.append(new Famicom::Interface);
emulators.append(new SuperFamicom::Interface); emulators.append(new SuperFamicom::Interface);
@ -29,22 +30,32 @@ Program::Program() {
presentation->setVisible(); presentation->setVisible();
video.driver(config->video.driver); video = Video::create(config->video.driver);
video.set(Video::Handle, presentation->viewport.handle()); video->set(Video::Handle, presentation->viewport.handle());
video.set(Video::Synchronize, config->video.synchronize); video->set(Video::Synchronize, config->video.synchronize);
if(!video.init()) { video.driver("None"); video.init(); } if(!video->init()) {
delete video;
video = Video::create("None");
}
audio.driver(config->audio.driver); audio = Audio::create(config->audio.driver);
audio.set(Audio::Device, config->audio.device); audio->set(Audio::Device, config->audio.device);
audio.set(Audio::Handle, presentation->viewport.handle()); audio->set(Audio::Handle, presentation->viewport.handle());
audio.set(Audio::Synchronize, config->audio.synchronize); audio->set(Audio::Synchronize, config->audio.synchronize);
audio.set(Audio::Frequency, 96000u); audio->set(Audio::Frequency, 96000u);
audio.set(Audio::Latency, 80u); audio->set(Audio::Latency, 80u);
if(!audio.init()) { audio.driver("None"); audio.init(); } if(!audio->init()) {
delete audio;
audio = Audio::create("None");
}
input.driver(config->input.driver); input = Input::create(config->input.driver);
input.set(Input::Handle, presentation->viewport.handle()); input->set(Input::Handle, presentation->viewport.handle());
if(!input.init()) { input.driver("None"); input.init(); } input->onChange({&InputManager::onChange, inputManager});
if(!input->init()) {
delete input;
input = Input::create("None");
}
dsp.setPrecision(16); dsp.setPrecision(16);
dsp.setBalance(0.0); dsp.setBalance(0.0);
@ -63,7 +74,7 @@ auto Program::main() -> void {
inputManager->poll(); inputManager->poll();
if(!emulator || !emulator->loaded() || pause) { if(!emulator || !emulator->loaded() || pause) {
audio.clear(); audio->clear();
usleep(20 * 1000); usleep(20 * 1000);
return; return;
} }
@ -75,8 +86,8 @@ auto Program::quit() -> void {
unloadMedia(); unloadMedia();
config->quit(); config->quit();
inputManager->quit(); inputManager->quit();
video.term(); delete video;
audio.term(); delete audio;
input.term(); delete input;
Application::quit(); Application::quit();
} }

View File

@ -36,8 +36,8 @@ auto Program::updateStatusText() -> void {
} }
auto Program::updateVideoFilter() -> void { auto Program::updateVideoFilter() -> void {
if(config->video.filter == "None") video.set(Video::Filter, Video::FilterNearest); 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 == "Blur") video->set(Video::Filter, Video::FilterLinear);
} }
auto Program::updateVideoPalette() -> void { auto Program::updateVideoPalette() -> void {
@ -49,8 +49,9 @@ auto Program::updateVideoPalette() -> void {
} }
auto Program::updateAudio() -> void { auto Program::updateAudio() -> void {
audio.set(Audio::Frequency, config->audio.frequency); if(!audio) return;
audio.set(Audio::Latency, config->audio.latency); audio->set(Audio::Frequency, config->audio.frequency);
audio->set(Audio::Latency, config->audio.latency);
if(auto resampler = config->audio.resampler) { if(auto resampler = config->audio.resampler) {
if(resampler == "Linear" ) dsp.setResampler(DSP::ResampleEngine::Linear); if(resampler == "Linear" ) dsp.setResampler(DSP::ResampleEngine::Linear);
if(resampler == "Hermite") dsp.setResampler(DSP::ResampleEngine::Hermite); 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")); driverLabel.setText("Driver Selection").setFont(Font::sans(8, "Bold"));
videoLabel.setText("Video:"); videoLabel.setText("Video:");
videoDriver.onChange([&] { config->video.driver = videoDriver.selected()->text(); }); videoDriver.onChange([&] { config->video.driver = videoDriver.selected()->text(); });
for(auto& driver : string{video.availableDrivers()}.split(";")) { for(auto& driver : Video::availableDrivers()) {
ComboButtonItem item; ComboButtonItem item;
item.setText(driver); item.setText(driver);
videoDriver.append(item); videoDriver.append(item);
@ -15,7 +15,7 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
} }
audioLabel.setText("Audio:"); audioLabel.setText("Audio:");
audioDriver.onChange([&] { config->audio.driver = audioDriver.selected()->text(); }); audioDriver.onChange([&] { config->audio.driver = audioDriver.selected()->text(); });
for(auto& driver : string{audio.availableDrivers()}.split(";")) { for(auto& driver : Audio::availableDrivers()) {
ComboButtonItem item; ComboButtonItem item;
item.setText(driver); item.setText(driver);
audioDriver.append(item); audioDriver.append(item);
@ -23,7 +23,7 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
} }
inputLabel.setText("Input:"); inputLabel.setText("Input:");
inputDriver.onChange([&] { config->input.driver = inputDriver.selected()->text(); }); inputDriver.onChange([&] { config->input.driver = inputDriver.selected()->text(); });
for(auto& driver : string{input.availableDrivers()}.split(";")) { for(auto& driver : Input::availableDrivers()) {
ComboButtonItem item; ComboButtonItem item;
item.setText(driver); item.setText(driver);
inputDriver.append(item); inputDriver.append(item);

View File

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

View File

@ -1,12 +1,15 @@
#include <emulator/emulator.hpp>
extern Emulator::Interface* emulator;
#include <nall/nall.hpp> #include <nall/nall.hpp>
#include <ruby/ruby.hpp> #include <ruby/ruby.hpp>
#include <hiro/hiro.hpp> #include <hiro/hiro.hpp>
using namespace nall; using namespace nall;
using namespace ruby; using namespace ruby;
using namespace hiro; 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 "program/program.hpp"
#include "configuration/configuration.hpp" #include "configuration/configuration.hpp"