mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-19 08:31:11 +00:00
Factor out machine wiring.
This commit is contained in:
parent
6d40549c0c
commit
8ae38991b0
@ -479,6 +479,44 @@ class DynamicWindowTitler {
|
|||||||
const std::string file_name_;
|
const std::string file_name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Provides a wrapper for SDL_Joystick pointers that can keep track
|
||||||
|
of historic hat values.
|
||||||
|
*/
|
||||||
|
class SDLJoystick {
|
||||||
|
public:
|
||||||
|
SDLJoystick(SDL_Joystick *joystick) : joystick_(joystick) {
|
||||||
|
hat_values_.resize(SDL_JoystickNumHats(joystick));
|
||||||
|
}
|
||||||
|
|
||||||
|
~SDLJoystick() {
|
||||||
|
SDL_JoystickClose(joystick_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns The underlying SDL_Joystick.
|
||||||
|
SDL_Joystick *get() {
|
||||||
|
return joystick_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns A reference to the storage for the previous state of hat @c c.
|
||||||
|
Uint8 &last_hat_value(int c) {
|
||||||
|
return hat_values_[c];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @returns The logic OR of all stored hat states.
|
||||||
|
Uint8 hat_values() {
|
||||||
|
Uint8 value = 0;
|
||||||
|
for(const auto hat_value: hat_values_) {
|
||||||
|
value |= hat_value;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_Joystick *joystick_;
|
||||||
|
std::vector<Uint8> hat_values_;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
@ -844,91 +882,66 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// Setup output, assuming a CRT machine for now, and prepare a best-effort updater.
|
// Setup output, assuming a CRT machine for now, and prepare a best-effort updater.
|
||||||
Outputs::Display::OpenGL::ScanTarget scan_target(target_framebuffer);
|
Outputs::Display::OpenGL::ScanTarget scan_target(target_framebuffer);
|
||||||
machine->scan_producer()->set_scan_target(&scan_target);
|
std::unique_ptr<ActivityObserver> activity_observer;
|
||||||
|
bool uses_mouse;
|
||||||
|
std::vector<SDLJoystick> joysticks;
|
||||||
|
|
||||||
// For now, lie about audio output intentions.
|
const auto setup_machine_input_output = [&scan_target, &machine, &speaker_delegate, &activity_observer, &joysticks, &uses_mouse] {
|
||||||
auto speaker = machine->audio_producer()->get_speaker();
|
machine->scan_producer()->set_scan_target(&scan_target);
|
||||||
if(speaker) {
|
|
||||||
// Create an audio pipe.
|
|
||||||
SDL_AudioSpec desired_audio_spec;
|
|
||||||
SDL_AudioSpec obtained_audio_spec;
|
|
||||||
|
|
||||||
SDL_zero(desired_audio_spec);
|
// For now, lie about audio output intentions.
|
||||||
desired_audio_spec.freq = 48000; // TODO: how can I get SDL to reveal the output rate of this machine?
|
auto speaker = machine->audio_producer()->get_speaker();
|
||||||
desired_audio_spec.format = AUDIO_S16;
|
if(speaker) {
|
||||||
desired_audio_spec.channels = 1 + int(speaker->get_is_stereo());
|
// Create an audio pipe.
|
||||||
desired_audio_spec.samples = Uint16(SpeakerDelegate::buffered_samples);
|
SDL_AudioSpec desired_audio_spec;
|
||||||
desired_audio_spec.callback = SpeakerDelegate::SDL_audio_callback;
|
SDL_AudioSpec obtained_audio_spec;
|
||||||
desired_audio_spec.userdata = &speaker_delegate;
|
|
||||||
|
|
||||||
speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
SDL_zero(desired_audio_spec);
|
||||||
|
desired_audio_spec.freq = 48000; // TODO: how can I get SDL to reveal the output rate of this machine?
|
||||||
|
desired_audio_spec.format = AUDIO_S16;
|
||||||
|
desired_audio_spec.channels = 1 + int(speaker->get_is_stereo());
|
||||||
|
desired_audio_spec.samples = Uint16(SpeakerDelegate::buffered_samples);
|
||||||
|
desired_audio_spec.callback = SpeakerDelegate::SDL_audio_callback;
|
||||||
|
desired_audio_spec.userdata = &speaker_delegate;
|
||||||
|
|
||||||
speaker->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples, obtained_audio_spec.channels == 2);
|
speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||||
speaker_delegate.is_stereo = obtained_audio_spec.channels == 2;
|
|
||||||
speaker->set_delegate(&speaker_delegate);
|
speaker->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples, obtained_audio_spec.channels == 2);
|
||||||
SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
|
speaker_delegate.is_stereo = obtained_audio_spec.channels == 2;
|
||||||
}
|
speaker->set_delegate(&speaker_delegate);
|
||||||
|
SDL_PauseAudioDevice(speaker_delegate.audio_device, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the machine offers anything for activity observation,
|
||||||
|
create and register an activity observer.
|
||||||
|
*/
|
||||||
|
Activity::Source *const activity_source = machine->activity_source();
|
||||||
|
if(activity_source) {
|
||||||
|
activity_observer = std::make_unique<ActivityObserver>(activity_source, 4.0f / 3.0f);
|
||||||
|
} else {
|
||||||
|
activity_observer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a joystick machine, check for and open attached joysticks.
|
||||||
|
const auto joystick_machine = machine->joystick_machine();
|
||||||
|
if(joystick_machine) {
|
||||||
|
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
|
for(int c = 0; c < SDL_NumJoysticks(); ++c) {
|
||||||
|
joysticks.emplace_back(SDL_JoystickOpen(c));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
joysticks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep a record of whether mouse events can be forwarded.
|
||||||
|
uses_mouse = !!machine->mouse_machine();
|
||||||
|
};
|
||||||
|
setup_machine_input_output();
|
||||||
|
|
||||||
int window_width, window_height;
|
int window_width, window_height;
|
||||||
SDL_GetWindowSize(window, &window_width, &window_height);
|
SDL_GetWindowSize(window, &window_width, &window_height);
|
||||||
|
|
||||||
// If this is a joystick machine, check for and open attached joysticks.
|
|
||||||
/*!
|
|
||||||
Provides a wrapper for SDL_Joystick pointers that can keep track
|
|
||||||
of historic hat values.
|
|
||||||
*/
|
|
||||||
class SDLJoystick {
|
|
||||||
public:
|
|
||||||
SDLJoystick(SDL_Joystick *joystick) : joystick_(joystick) {
|
|
||||||
hat_values_.resize(SDL_JoystickNumHats(joystick));
|
|
||||||
}
|
|
||||||
|
|
||||||
~SDLJoystick() {
|
|
||||||
SDL_JoystickClose(joystick_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @returns The underlying SDL_Joystick.
|
|
||||||
SDL_Joystick *get() {
|
|
||||||
return joystick_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @returns A reference to the storage for the previous state of hat @c c.
|
|
||||||
Uint8 &last_hat_value(int c) {
|
|
||||||
return hat_values_[c];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @returns The logic OR of all stored hat states.
|
|
||||||
Uint8 hat_values() {
|
|
||||||
Uint8 value = 0;
|
|
||||||
for(const auto hat_value: hat_values_) {
|
|
||||||
value |= hat_value;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
SDL_Joystick *joystick_;
|
|
||||||
std::vector<Uint8> hat_values_;
|
|
||||||
};
|
|
||||||
std::vector<SDLJoystick> joysticks;
|
|
||||||
const auto joystick_machine = machine->joystick_machine();
|
|
||||||
if(joystick_machine) {
|
|
||||||
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
|
||||||
for(int c = 0; c < SDL_NumJoysticks(); ++c) {
|
|
||||||
joysticks.emplace_back(SDL_JoystickOpen(c));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
If the machine offers anything for activity observation,
|
|
||||||
create and register an activity observer.
|
|
||||||
*/
|
|
||||||
std::unique_ptr<ActivityObserver> activity_observer;
|
|
||||||
Activity::Source *const activity_source = machine->activity_source();
|
|
||||||
if(activity_source) {
|
|
||||||
activity_observer = std::make_unique<ActivityObserver>(activity_source, 4.0f / 3.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SDL 2.x delivers key up/down events and text inputs separately even when they're correlated;
|
// SDL 2.x delivers key up/down events and text inputs separately even when they're correlated;
|
||||||
// this struct and map is used to correlate them by time.
|
// this struct and map is used to correlate them by time.
|
||||||
struct KeyPress {
|
struct KeyPress {
|
||||||
@ -945,7 +958,6 @@ int main(int argc, char *argv[]) {
|
|||||||
std::vector<KeyPress> keypresses;
|
std::vector<KeyPress> keypresses;
|
||||||
|
|
||||||
// Run the main event loop until the OS tells us to quit.
|
// Run the main event loop until the OS tells us to quit.
|
||||||
const bool uses_mouse = !!machine->mouse_machine();
|
|
||||||
bool should_quit = false;
|
bool should_quit = false;
|
||||||
Uint32 fullscreen_mode = 0;
|
Uint32 fullscreen_mode = 0;
|
||||||
machine_runner.start();
|
machine_runner.start();
|
||||||
|
Loading…
Reference in New Issue
Block a user