Refactor audio handling in Controller; replace LoadAudioDevice with backend audio initialization and shutdown methods
This commit is contained in:
@@ -22,7 +22,12 @@ absl::Status Controller::OnEntry(std::string filename) {
|
|||||||
RETURN_IF_ERROR(CreateWindow())
|
RETURN_IF_ERROR(CreateWindow())
|
||||||
RETURN_IF_ERROR(CreateRenderer())
|
RETURN_IF_ERROR(CreateRenderer())
|
||||||
RETURN_IF_ERROR(CreateGuiContext())
|
RETURN_IF_ERROR(CreateGuiContext())
|
||||||
RETURN_IF_ERROR(LoadAudioDevice())
|
backend_.init_audio();
|
||||||
|
// cast to Sdl2backend to access audio buffer and device
|
||||||
|
auto &sdl2_backend = static_cast<Sdl2Backend &>(backend_);
|
||||||
|
editor_manager_.emulator().set_audio_buffer(
|
||||||
|
sdl2_backend.audio_buffer().get());
|
||||||
|
editor_manager_.emulator().set_audio_device_id(sdl2_backend.audio_device());
|
||||||
Initialize(filename);
|
Initialize(filename);
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
@@ -108,10 +113,6 @@ absl::Status Controller::OnLoad() {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Controller::DoRender() const {
|
void Controller::DoRender() const {
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
SDL_RenderClear(Renderer::GetInstance().renderer());
|
SDL_RenderClear(Renderer::GetInstance().renderer());
|
||||||
@@ -121,8 +122,7 @@ void Controller::DoRender() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Controller::OnExit() {
|
void Controller::OnExit() {
|
||||||
SDL_PauseAudioDevice(audio_device_, 1);
|
backend_.shutdown_audio();
|
||||||
SDL_CloseAudioDevice(audio_device_);
|
|
||||||
ImGui_ImplSDLRenderer2_Shutdown();
|
ImGui_ImplSDLRenderer2_Shutdown();
|
||||||
ImGui_ImplSDL2_Shutdown();
|
ImGui_ImplSDL2_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
@@ -180,32 +180,11 @@ absl::Status Controller::CreateGuiContext() {
|
|||||||
gui::ColorsYaze();
|
gui::ColorsYaze();
|
||||||
|
|
||||||
// Build a new ImGui frame
|
// Build a new ImGui frame
|
||||||
ImGui_ImplSDLRenderer2_NewFrame();
|
backend_.new_frame();
|
||||||
ImGui_ImplSDL2_NewFrame();
|
|
||||||
|
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Controller::LoadAudioDevice() {
|
|
||||||
SDL_AudioSpec want, have;
|
|
||||||
SDL_memset(&want, 0, sizeof(want));
|
|
||||||
want.freq = audio_frequency_;
|
|
||||||
want.format = AUDIO_S16;
|
|
||||||
want.channels = 2;
|
|
||||||
want.samples = 2048;
|
|
||||||
want.callback = NULL; // Uses the queue
|
|
||||||
audio_device_ = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
|
|
||||||
if (audio_device_ == 0) {
|
|
||||||
return absl::InternalError(
|
|
||||||
absl::StrFormat("Failed to open audio: %s\n", SDL_GetError()));
|
|
||||||
}
|
|
||||||
audio_buffer_ = std::make_shared<int16_t>(audio_frequency_ / 50 * 4);
|
|
||||||
SDL_PauseAudioDevice(audio_device_, 0);
|
|
||||||
editor_manager_.emulator().set_audio_buffer(audio_buffer_.get());
|
|
||||||
editor_manager_.emulator().set_audio_device_id(audio_device_);
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status Controller::LoadConfigFiles() {
|
absl::Status Controller::LoadConfigFiles() {
|
||||||
// Create and load a dotfile for the application
|
// Create and load a dotfile for the application
|
||||||
// This will store the user's preferences and settings
|
// This will store the user's preferences and settings
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
|
#include "app/core/platform/backend.h"
|
||||||
#include "app/core/platform/file_dialog.h"
|
#include "app/core/platform/file_dialog.h"
|
||||||
#include "app/core/platform/renderer.h"
|
#include "app/core/platform/renderer.h"
|
||||||
#include "app/editor/editor.h"
|
|
||||||
#include "app/editor/editor_manager.h"
|
#include "app/editor/editor_manager.h"
|
||||||
#include "imgui/backends/imgui_impl_sdl2.h"
|
#include "imgui/backends/imgui_impl_sdl2.h"
|
||||||
#include "imgui/backends/imgui_impl_sdlrenderer2.h"
|
#include "imgui/backends/imgui_impl_sdlrenderer2.h"
|
||||||
@@ -39,7 +39,6 @@ class Controller {
|
|||||||
absl::Status CreateWindow();
|
absl::Status CreateWindow();
|
||||||
absl::Status CreateRenderer();
|
absl::Status CreateRenderer();
|
||||||
absl::Status CreateGuiContext();
|
absl::Status CreateGuiContext();
|
||||||
absl::Status LoadAudioDevice();
|
|
||||||
absl::Status LoadConfigFiles();
|
absl::Status LoadConfigFiles();
|
||||||
|
|
||||||
auto window() -> SDL_Window * { return window_.get(); }
|
auto window() -> SDL_Window * { return window_.get(); }
|
||||||
@@ -51,11 +50,8 @@ class Controller {
|
|||||||
|
|
||||||
bool active_ = false;
|
bool active_ = false;
|
||||||
editor::EditorManager editor_manager_;
|
editor::EditorManager editor_manager_;
|
||||||
|
|
||||||
int audio_frequency_ = 48000;
|
|
||||||
SDL_AudioDeviceID audio_device_;
|
|
||||||
std::shared_ptr<int16_t> audio_buffer_;
|
|
||||||
std::shared_ptr<SDL_Window> window_;
|
std::shared_ptr<SDL_Window> window_;
|
||||||
|
core::PlatformBackend<Sdl2Backend> backend_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace core
|
} // namespace core
|
||||||
|
|||||||
125
src/app/core/platform/backend.h
Normal file
125
src/app/core/platform/backend.h
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
#ifndef YAZE_APP_CORE_PLATFORM_BACKEND_H
|
||||||
|
#define YAZE_APP_CORE_PLATFORM_BACKEND_H
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "app/core/platform/renderer.h"
|
||||||
|
#include "app/core/platform/sdl_deleter.h"
|
||||||
|
#include "imgui/backends/imgui_impl_sdl2.h"
|
||||||
|
#include "imgui/backends/imgui_impl_sdlrenderer2.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace core {
|
||||||
|
|
||||||
|
template <typename Derived>
|
||||||
|
class PlatformBackend {
|
||||||
|
public:
|
||||||
|
PlatformBackend() = default;
|
||||||
|
~PlatformBackend() = default;
|
||||||
|
|
||||||
|
void init() { static_cast<Derived *>(this)->init(); }
|
||||||
|
void init_audio() { static_cast<Derived *>(this)->init_audio(); }
|
||||||
|
void shutdown_audio() { static_cast<Derived *>(this)->shutdown_audio(); }
|
||||||
|
void shutdown() { static_cast<Derived *>(this)->shutdown(); }
|
||||||
|
void new_frame() { static_cast<Derived *>(this)->new_frame(); }
|
||||||
|
void render() { static_cast<Derived *>(this)->render(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Sdl2Backend : public PlatformBackend<Sdl2Backend> {
|
||||||
|
public:
|
||||||
|
Sdl2Backend() = default;
|
||||||
|
~Sdl2Backend() = default;
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) !=
|
||||||
|
0) {
|
||||||
|
throw std::runtime_error("Failed to initialize SDL2");
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_DisplayMode display_mode;
|
||||||
|
SDL_GetCurrentDisplayMode(0, &display_mode);
|
||||||
|
int screen_width = display_mode.w * 0.8;
|
||||||
|
int screen_height = display_mode.h * 0.8;
|
||||||
|
|
||||||
|
window = std::unique_ptr<SDL_Window, core::SDL_Deleter>(
|
||||||
|
SDL_CreateWindow("Yet Another Zelda3 Editor", // window title
|
||||||
|
SDL_WINDOWPOS_UNDEFINED, // initial x position
|
||||||
|
SDL_WINDOWPOS_UNDEFINED, // initial y position
|
||||||
|
screen_width, // width, in pixels
|
||||||
|
screen_height, // height, in pixels
|
||||||
|
SDL_WINDOW_RESIZABLE),
|
||||||
|
core::SDL_Deleter());
|
||||||
|
if (!window) {
|
||||||
|
throw std::runtime_error("Failed to create window");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Renderer::GetInstance().CreateRenderer(window.get()).ok()) {
|
||||||
|
throw std::runtime_error("Failed to create renderer");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplSDL2_InitForSDLRenderer(window.get(),
|
||||||
|
Renderer::GetInstance().renderer());
|
||||||
|
ImGui_ImplSDLRenderer2_Init(Renderer::GetInstance().renderer());
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_audio() {
|
||||||
|
const int audio_frequency = 48000;
|
||||||
|
SDL_AudioSpec want, have;
|
||||||
|
SDL_memset(&want, 0, sizeof(want));
|
||||||
|
want.freq = audio_frequency;
|
||||||
|
want.format = AUDIO_S16;
|
||||||
|
want.channels = 2;
|
||||||
|
want.samples = 2048;
|
||||||
|
want.callback = NULL; // Uses the queue
|
||||||
|
audio_device_ = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
|
||||||
|
if (audio_device_ == 0) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
absl::StrFormat("Failed to open audio: %s\n", SDL_GetError()));
|
||||||
|
}
|
||||||
|
audio_buffer_ = std::make_shared<int16_t>(audio_frequency / 50 * 4);
|
||||||
|
SDL_PauseAudioDevice(audio_device_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shutdown_audio() {
|
||||||
|
SDL_PauseAudioDevice(audio_device_, 1);
|
||||||
|
SDL_CloseAudioDevice(audio_device_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shutdown() {
|
||||||
|
ImGui_ImplSDL2_Shutdown();
|
||||||
|
ImGui_ImplSDLRenderer2_Shutdown();
|
||||||
|
SDL_DestroyRenderer(Renderer::GetInstance().renderer());
|
||||||
|
SDL_DestroyWindow(window.get());
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void new_frame() {
|
||||||
|
ImGui_ImplSDLRenderer2_NewFrame();
|
||||||
|
ImGui_ImplSDL2_NewFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void render() {
|
||||||
|
ImGui::Render();
|
||||||
|
SDL_RenderClear(Renderer::GetInstance().renderer());
|
||||||
|
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(),
|
||||||
|
Renderer::GetInstance().renderer());
|
||||||
|
SDL_RenderPresent(Renderer::GetInstance().renderer());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto window_ptr() -> SDL_Window * { return window.get(); }
|
||||||
|
auto audio_device() -> SDL_AudioDeviceID { return audio_device_; }
|
||||||
|
auto audio_buffer() -> std::shared_ptr<int16_t> { return audio_buffer_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_AudioDeviceID audio_device_;
|
||||||
|
std::shared_ptr<int16_t> audio_buffer_;
|
||||||
|
std::unique_ptr<SDL_Window, SDL_Deleter> window;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif // YAZE_APP_CORE_PLATFORM_BACKEND_H
|
||||||
Reference in New Issue
Block a user