diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 9a3e85597..208f49861 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -479,6 +479,44 @@ class DynamicWindowTitler { 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 hat_values_; +}; + } 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. Outputs::Display::OpenGL::ScanTarget scan_target(target_framebuffer); - machine->scan_producer()->set_scan_target(&scan_target); + std::unique_ptr activity_observer; + bool uses_mouse; + std::vector joysticks; - // For now, lie about audio output intentions. - auto speaker = machine->audio_producer()->get_speaker(); - if(speaker) { - // Create an audio pipe. - SDL_AudioSpec desired_audio_spec; - SDL_AudioSpec obtained_audio_spec; + const auto setup_machine_input_output = [&scan_target, &machine, &speaker_delegate, &activity_observer, &joysticks, &uses_mouse] { + machine->scan_producer()->set_scan_target(&scan_target); - 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; + // For now, lie about audio output intentions. + auto speaker = machine->audio_producer()->get_speaker(); + if(speaker) { + // Create an audio pipe. + SDL_AudioSpec desired_audio_spec; + SDL_AudioSpec obtained_audio_spec; - 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.is_stereo = obtained_audio_spec.channels == 2; - speaker->set_delegate(&speaker_delegate); - SDL_PauseAudioDevice(speaker_delegate.audio_device, 0); - } + speaker_delegate.audio_device = SDL_OpenAudioDevice(nullptr, 0, &desired_audio_spec, &obtained_audio_spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + + speaker->set_output_rate(obtained_audio_spec.freq, desired_audio_spec.samples, obtained_audio_spec.channels == 2); + 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(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; 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 hat_values_; - }; - std::vector 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 activity_observer; - Activity::Source *const activity_source = machine->activity_source(); - if(activity_source) { - activity_observer = std::make_unique(activity_source, 4.0f / 3.0f); - } - // 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. struct KeyPress { @@ -945,7 +958,6 @@ int main(int argc, char *argv[]) { std::vector keypresses; // Run the main event loop until the OS tells us to quit. - const bool uses_mouse = !!machine->mouse_machine(); bool should_quit = false; Uint32 fullscreen_mode = 0; machine_runner.start();