added audio enabled flag

This commit is contained in:
Noel Berry 2022-11-20 19:32:38 -08:00
parent b161457c66
commit 4d7f7a993a
4 changed files with 880 additions and 875 deletions

View File

@ -1,161 +1,162 @@
#pragma once #pragma once
#include <blah_common.h> #include <blah_common.h>
#include <blah_graphics.h> #include <blah_graphics.h>
#include <blah_spatial.h> #include <blah_spatial.h>
namespace Blah namespace Blah
{ {
// Application Event Functions // Application Event Functions
using AppEventFn = Func<void>; using AppEventFn = Func<void>;
// Application Logging Functions // Application Logging Functions
using AppLogFn = Func<void, const char*, Log::Category>; using AppLogFn = Func<void, const char*, Log::Category>;
// Application flags // Application flags
namespace Flags namespace Flags
{ {
constexpr u32 FixedTimestep = 1 << 0; constexpr u32 FixedTimestep = 1 << 0;
constexpr u32 VSync = 1 << 1; constexpr u32 VSync = 1 << 1;
constexpr u32 Fullscreen = 1 << 2; constexpr u32 Fullscreen = 1 << 2;
constexpr u32 Resizable = 1 << 3; constexpr u32 Resizable = 1 << 3;
} constexpr u32 AudioEnabled = 1 << 4;
}
// Application Configuration
struct Config // Application Configuration
{ struct Config
// Application name. {
const char* name = "blah"; // Application name.
const char* name = "blah";
// Which renderer to use
// Default depends on the Platform // Which renderer to use
RendererType renderer_type = RendererType::None; // Default depends on the Platform
RendererType renderer_type = RendererType::None;
// Starting width, in pixels.
// Depending on the OS DPI, the true window size may be a multiple of this. // Starting width, in pixels.
int width = 1280; // Depending on the OS DPI, the true window size may be a multiple of this.
int width = 1280;
// Starting height, in pixels.
// Depending on the OS DPI, the true window size may be a multiple of this. // Starting height, in pixels.
int height = 720; // Depending on the OS DPI, the true window size may be a multiple of this.
int height = 720;
// maximum updates to run before "giving up" and reducing frame rate.
// this avoids the 'spiral of death'. // maximum updates to run before "giving up" and reducing frame rate.
// defaults to 5. // this avoids the 'spiral of death'.
int max_updates = 5; // defaults to 5.
int max_updates = 5;
// target framerate when running with Fixed Timestep
// defaults to 60. // target framerate when running with Fixed Timestep
int target_framerate = 60; // defaults to 60.
int target_framerate = 60;
// The expected freqeuncy of audio files and how quickly to play audio.
int audio_frequency_in_Hz = 44100; // The expected freqeuncy of audio files and how quickly to play audio.
int audio_frequency_in_Hz = 44100;
// default starting flags
u32 flags = Flags::VSync | Flags::Resizable | Flags::FixedTimestep; // default starting flags
u32 flags = Flags::VSync | Flags::Resizable | Flags::FixedTimestep | Flags::AudioEnabled;
// Callback on application startup
AppEventFn on_startup = nullptr; // Callback on application startup
AppEventFn on_startup = nullptr;
// Callback on application shutdown
AppEventFn on_shutdown = nullptr; // Callback on application shutdown
AppEventFn on_shutdown = nullptr;
// Callback on application update
AppEventFn on_update = nullptr; // Callback on application update
AppEventFn on_update = nullptr;
// Callback on application render
AppEventFn on_render = nullptr; // Callback on application render
AppEventFn on_render = nullptr;
// Callback when the user has requested the application close.
// For example, pressing the Close button, ALT+F4, etc. // Callback when the user has requested the application close.
// By default this calls `App::exit()` // For example, pressing the Close button, ALT+F4, etc.
AppEventFn on_exit_request = nullptr; // By default this calls `App::exit()`
AppEventFn on_exit_request = nullptr;
// Callback when the application logs info/warning/errors
// Defaults to printf. // Callback when the application logs info/warning/errors
AppLogFn on_log = nullptr; // Defaults to printf.
}; AppLogFn on_log = nullptr;
};
// Application
namespace App // Application
{ namespace App
// Runs the application {
bool run(const Config* config); // Runs the application
bool run(const Config* config);
// Checks if the Application is running yet
bool is_running(); // Checks if the Application is running yet
bool is_running();
// Exits the application.
// This only signals for the application to close, it will not stop // Exits the application.
// until the current update and render calls are finished. // This only signals for the application to close, it will not stop
void exit(); // until the current update and render calls are finished.
void exit();
// Gets the config data used to run the application
const Config& config(); // Gets the config data used to run the application
const Config& config();
// Gets the working path
const char* path(); // Gets the working path
const char* path();
// Gets the user path
const char* user_path(); // Gets the user path
const char* user_path();
// Gets the Window Title
const char* get_title(); // Gets the Window Title
const char* get_title();
// Sets the Window Title
void set_title(const char* title); // Sets the Window Title
void set_title(const char* title);
// Gets the Window Position in Screen Coordinates
Point get_position(); // Gets the Window Position in Screen Coordinates
Point get_position();
// Sets the Window Position in Screen Coordinates
void set_position(Point point); // Sets the Window Position in Screen Coordinates
void set_position(Point point);
// Gets the size of the Window in Screen Coordinates.
// On High DPI displays this may not be 1:1 with pixels. // Gets the size of the Window in Screen Coordinates.
// For the size in pixels, use App::get_backbuffer_size() // On High DPI displays this may not be 1:1 with pixels.
Point get_size(); // For the size in pixels, use App::get_backbuffer_size()
Point get_size();
// Sets the Window Size in Screen Coordinates
void set_size(Point point); // Sets the Window Size in Screen Coordinates
void set_size(Point point);
// Gets the size of the BackBuffer, in pixels
Point get_backbuffer_size(); // Gets the size of the BackBuffer, in pixels
Point get_backbuffer_size();
// Gets the content scale based on the platform.
// macOS is usually 2.0, other platforms vary. // Gets the content scale based on the platform.
float content_scale(); // macOS is usually 2.0, other platforms vary.
float content_scale();
// If the window is currently focused or has mouse input
bool focused(); // If the window is currently focused or has mouse input
bool focused();
// Toggles a specific flag
void set_flag(u32 flag, bool enabled); // Toggles a specific flag
void set_flag(u32 flag, bool enabled);
// Gets whether a specific flag is enabled
bool get_flag(u32 flag); // Gets whether a specific flag is enabled
bool get_flag(u32 flag);
// Toggles the fullscreen flag
inline void set_fullscreen(bool enabled) { set_flag(Flags::Fullscreen, enabled); } // Toggles the fullscreen flag
inline void set_fullscreen(bool enabled) { set_flag(Flags::Fullscreen, enabled); }
// Toggles the V-Sync flag
inline void set_vsync(bool enabled) { set_flag(Flags::VSync, enabled); } // Toggles the V-Sync flag
inline void set_vsync(bool enabled) { set_flag(Flags::VSync, enabled); }
// Toggles the resizable flag
inline void set_resizable(bool enabled) { set_flag(Flags::Resizable, enabled); } // Toggles the resizable flag
inline void set_resizable(bool enabled) { set_flag(Flags::Resizable, enabled); }
// Toggles whether to update with Fixed Timestep
inline void set_fixedtimestep(bool enabled) { set_flag(Flags::FixedTimestep, enabled); } // Toggles whether to update with Fixed Timestep
inline void set_fixedtimestep(bool enabled) { set_flag(Flags::FixedTimestep, enabled); }
// Retrieves the Renderer Information
const RendererInfo& renderer(); // Retrieves the Renderer Information
const RendererInfo& renderer();
// Gets the BackBuffer
const TargetRef& backbuffer(); // Gets the BackBuffer
} const TargetRef& backbuffer();
}
namespace System
{ namespace System
// Tries to open the given URL in a web browser {
void open_url(const char* url); // Tries to open the given URL in a web browser
} void open_url(const char* url);
}
} }

View File

@ -1,442 +1,448 @@
#include <blah_app.h> #include <blah_app.h>
#include <blah_common.h> #include <blah_common.h>
#include <blah_time.h> #include <blah_time.h>
#include "internal/blah_internal.h" #include "internal/blah_internal.h"
#include "internal/blah_platform.h" #include "internal/blah_platform.h"
#include "internal/blah_renderer.h" #include "internal/blah_renderer.h"
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
#include <emscripten.h> #include <emscripten.h>
#include <emscripten/html5.h> #include <emscripten/html5.h>
#endif #endif
using namespace Blah; using namespace Blah;
// Internal Audio bool namespace
bool Internal::audio_is_init = false; {
// Global App State
namespace Config app_config;
{ bool app_is_running = false;
// Global App State bool app_is_exiting = false;
Config app_config; bool app_is_audio_running = false;
bool app_is_running = false; u64 app_time_last;
bool app_is_exiting = false; u64 app_time_accumulator = 0;
u64 app_time_last; u32 app_flags = 0;
u64 app_time_accumulator = 0; TargetRef app_backbuffer;
u32 app_flags = 0; Renderer* app_renderer_api;
TargetRef app_backbuffer;
Renderer* app_renderer_api; void get_drawable_size(int* w, int* h)
{
void get_drawable_size(int* w, int* h) // Some renderer implementations might return their own size
{ if (app_renderer_api->get_draw_size(w, h))
// Some renderer implementations might return their own size return;
if (app_renderer_api->get_draw_size(w, h))
return; // otherwise fallback to the platform size
Platform::get_draw_size(w, h);
// otherwise fallback to the platform size }
Platform::get_draw_size(w, h);
} void set_audio_system(bool on)
{
// A dummy Target that represents the Back Buffer. if (on && !app_is_audio_running)
// It doesn't contain any data, rather it forwards calls along to the actual BackBuffer. {
class BackBuffer final : public Target int more_on_emscripten = 1;
{ #ifdef __EMSCRIPTEN__
public: more_on_emscripten = 4;
Attachments empty_textures; #endif
Attachments& textures() override { BLAH_ASSERT(false, "Backbuffer doesn't have any textures"); return empty_textures; } app_is_audio_running = Internal::audio_init(app_config.audio_frequency_in_Hz, 1024 * more_on_emscripten);
const Attachments& textures() const override { BLAH_ASSERT(false, "Backbuffer doesn't have any textures"); return empty_textures; } }
int width() const override { int w, h; get_drawable_size(&w, &h); return w; } else if (!on && app_is_audio_running)
int height() const override { int w, h; get_drawable_size(&w, &h); return h; } {
void clear(Color color, float depth, u8 stencil, ClearMask mask) override Internal::audio_shutdown();
{ app_is_audio_running = false;
BLAH_ASSERT_RENDERER(); }
if (app_renderer_api) }
app_renderer_api->clear_backbuffer(color, depth, stencil, mask);
} // A dummy Target that represents the Back Buffer.
}; // It doesn't contain any data, rather it forwards calls along to the actual BackBuffer.
} class BackBuffer final : public Target
{
bool App::run(const Config* c) public:
{ Attachments empty_textures;
BLAH_ASSERT(!app_is_running, "The Application is already running"); Attachments& textures() override { BLAH_ASSERT(false, "Backbuffer doesn't have any textures"); return empty_textures; }
const Attachments& textures() const override { BLAH_ASSERT(false, "Backbuffer doesn't have any textures"); return empty_textures; }
// copy config over int width() const override { int w, h; get_drawable_size(&w, &h); return w; }
app_config = *c; int height() const override { int w, h; get_drawable_size(&w, &h); return h; }
void clear(Color color, float depth, u8 stencil, ClearMask mask) override
// exit the application by default {
if (!app_config.on_exit_request) BLAH_ASSERT_RENDERER();
app_config.on_exit_request = App::exit; if (app_renderer_api)
app_renderer_api->clear_backbuffer(color, depth, stencil, mask);
// default renderer type }
if (app_config.renderer_type == RendererType::None) };
app_config.renderer_type = Renderer::default_type(); }
// exit out if setup is wrong bool App::run(const Config* c)
BLAH_ASSERT(c != nullptr, "The Application requires a valid Config"); {
BLAH_ASSERT(c->name != nullptr, "The Application Name cannot be null"); BLAH_ASSERT(!app_is_running, "The Application is already running");
BLAH_ASSERT(c->width > 0 && c->height > 0, "The Width and Height must be larget than 0");
BLAH_ASSERT(c->max_updates > 0, "Max Updates must be >= 1"); // copy config over
BLAH_ASSERT(c->target_framerate > 0, "Target Framerate must be >= 1"); app_config = *c;
if (app_is_running || c == nullptr || c->width <= 0 || c->height <= 0 || c->max_updates <= 0 || c->target_framerate <= 0) // exit the application by default
{ if (!app_config.on_exit_request)
Internal::app_shutdown(); app_config.on_exit_request = App::exit;
return false;
} // default renderer type
if (app_config.renderer_type == RendererType::None)
// default values app_config.renderer_type = Renderer::default_type();
app_is_running = true;
app_is_exiting = false; // exit out if setup is wrong
app_flags = app_config.flags; BLAH_ASSERT(c != nullptr, "The Application requires a valid Config");
app_backbuffer = TargetRef(new BackBuffer()); BLAH_ASSERT(c->name != nullptr, "The Application Name cannot be null");
BLAH_ASSERT(c->width > 0 && c->height > 0, "The Width and Height must be larget than 0");
// initialize the system BLAH_ASSERT(c->max_updates > 0, "Max Updates must be >= 1");
{ BLAH_ASSERT(c->target_framerate > 0, "Target Framerate must be >= 1");
if (!Platform::init(app_config))
{ if (app_is_running || c == nullptr || c->width <= 0 || c->height <= 0 || c->max_updates <= 0 || c->target_framerate <= 0)
Log::error("Failed to initialize Platform module"); {
Internal::app_shutdown(); Internal::app_shutdown();
return false; return false;
} }
}
// default values
// initialize audio app_is_running = true;
{ app_is_exiting = false;
if (!Internal::audio_is_init) { app_flags = app_config.flags;
int more_on_emscripten = 1; app_backbuffer = TargetRef(new BackBuffer());
#ifdef __EMSCRIPTEN__
more_on_emscripten = 4; // initialize the system
#endif {
Internal::audio_is_init = Internal::audio_init(c->audio_frequency_in_Hz, 1024 * more_on_emscripten); if (!Platform::init(app_config))
} {
} Log::error("Failed to initialize Platform module");
Internal::app_shutdown();
// initialize graphics return false;
{ }
app_renderer_api = Renderer::try_make_renderer(app_config.renderer_type); }
if (app_renderer_api == nullptr)
{ // initialize audio
Log::error("Renderer module was not found"); if (get_flag(Flags::AudioEnabled))
Internal::app_shutdown(); set_audio_system(true);
return false;
} // initialize graphics
{
if (!app_renderer_api->init()) app_renderer_api = Renderer::try_make_renderer(app_config.renderer_type);
{ if (app_renderer_api == nullptr)
Log::error("Failed to initialize Renderer module"); {
Internal::app_shutdown(); Log::error("Renderer module was not found");
return false; Internal::app_shutdown();
} return false;
} }
// apply default flags if (!app_renderer_api->init())
Platform::set_app_flags(app_flags); {
app_renderer_api->set_app_flags(app_flags); Log::error("Failed to initialize Renderer module");
Internal::app_shutdown();
// input + poll the platform once return false;
Internal::input_init(); }
Internal::input_step_state(); }
Platform::update(Input::state);
// apply default flags
// startup Platform::set_app_flags(app_flags);
if (app_config.on_startup != nullptr) app_renderer_api->set_app_flags(app_flags);
app_config.on_startup();
app_time_last = Platform::ticks(); // input + poll the platform once
app_time_accumulator = 0; Internal::input_init();
Internal::input_step_state();
// display window Platform::update(Input::state);
Platform::ready();
// startup
// Begin main loop if (app_config.on_startup != nullptr)
#ifdef __EMSCRIPTEN__ app_config.on_startup();
emscripten_set_main_loop(Internal::iterate, 0, 1); app_time_last = Platform::ticks();
#else app_time_accumulator = 0;
while (!app_is_exiting)
Internal::app_step(); // display window
#endif Platform::ready();
// shutdown // Begin main loop
if (app_config.on_shutdown != nullptr) #ifdef __EMSCRIPTEN__
app_config.on_shutdown(); emscripten_set_main_loop(Internal::iterate, 0, 1);
Internal::app_shutdown(); #else
return true; while (!app_is_exiting)
} Internal::app_step();
#endif
bool App::is_running()
{ // shutdown
return app_is_running; if (app_config.on_shutdown != nullptr)
} app_config.on_shutdown();
Internal::app_shutdown();
void Internal::app_step() return true;
{ }
static const auto step = []()
{ bool App::is_running()
Internal::input_step_state(); {
Platform::update(Input::state); return app_is_running;
Internal::input_step_bindings(); }
app_renderer_api->update();
if (app_config.on_update != nullptr) void Internal::app_step()
app_config.on_update(); {
}; static const auto step = []()
{
bool is_fixed_timestep = App::get_flag(Flags::FixedTimestep); Internal::input_step_state();
Platform::update(Input::state);
// Update in Fixed Timestep Internal::input_step_bindings();
if (is_fixed_timestep) app_renderer_api->update();
{ if (app_config.on_update != nullptr)
u64 time_target = (u64)((1.0 / app_config.target_framerate) * Time::ticks_per_second); app_config.on_update();
u64 ticks_curr = Platform::ticks(); };
u64 ticks_diff = ticks_curr - app_time_last;
app_time_last = ticks_curr; bool is_fixed_timestep = App::get_flag(Flags::FixedTimestep);
app_time_accumulator += ticks_diff;
// Update in Fixed Timestep
// do not let us run too fast if (is_fixed_timestep)
while (app_time_accumulator < time_target) {
{ u64 time_target = (u64)((1.0 / app_config.target_framerate) * Time::ticks_per_second);
int milliseconds = (int)(time_target - app_time_accumulator) / (Time::ticks_per_second / 1000); u64 ticks_curr = Platform::ticks();
Platform::sleep(milliseconds); u64 ticks_diff = ticks_curr - app_time_last;
app_time_last = ticks_curr;
ticks_curr = Platform::ticks(); app_time_accumulator += ticks_diff;
ticks_diff = ticks_curr - app_time_last;
app_time_last = ticks_curr; // do not let us run too fast
app_time_accumulator += ticks_diff; while (app_time_accumulator < time_target)
} {
int milliseconds = (int)(time_target - app_time_accumulator) / (Time::ticks_per_second / 1000);
// Do not allow us to fall behind too many updates Platform::sleep(milliseconds);
// (otherwise we'll get spiral of death)
u64 time_maximum = app_config.max_updates * time_target; ticks_curr = Platform::ticks();
if (app_time_accumulator > time_maximum) ticks_diff = ticks_curr - app_time_last;
app_time_accumulator = time_maximum; app_time_last = ticks_curr;
app_time_accumulator += ticks_diff;
// do as many updates as we can }
while (app_time_accumulator >= time_target)
{ // Do not allow us to fall behind too many updates
app_time_accumulator -= time_target; // (otherwise we'll get spiral of death)
u64 time_maximum = app_config.max_updates * time_target;
Time::delta = (1.0f / app_config.target_framerate); if (app_time_accumulator > time_maximum)
app_time_accumulator = time_maximum;
if (Time::pause_timer > 0)
{ // do as many updates as we can
Time::pause_timer -= Time::delta; while (app_time_accumulator >= time_target)
if (Time::pause_timer <= -0.0001) {
Time::delta = -Time::pause_timer; app_time_accumulator -= time_target;
else
continue; Time::delta = (1.0f / app_config.target_framerate);
}
if (Time::pause_timer > 0)
Time::previous_ticks = Time::ticks; {
Time::ticks += time_target; Time::pause_timer -= Time::delta;
Time::previous_seconds = Time::seconds; if (Time::pause_timer <= -0.0001)
Time::seconds += Time::delta; Time::delta = -Time::pause_timer;
else
step(); continue;
} }
}
// Update with Variable Timestep Time::previous_ticks = Time::ticks;
else Time::ticks += time_target;
{ Time::previous_seconds = Time::seconds;
u64 ticks_curr = Platform::ticks(); Time::seconds += Time::delta;
u64 ticks_diff = ticks_curr - app_time_last;
app_time_last = ticks_curr; step();
app_time_accumulator += ticks_diff; }
}
Time::delta = ticks_diff / (float)Time::ticks_per_second; // Update with Variable Timestep
else
if (Time::pause_timer > 0) {
{ u64 ticks_curr = Platform::ticks();
Time::pause_timer -= Time::delta; u64 ticks_diff = ticks_curr - app_time_last;
} app_time_last = ticks_curr;
else app_time_accumulator += ticks_diff;
{
Time::previous_ticks = Time::ticks; Time::delta = ticks_diff / (float)Time::ticks_per_second;
Time::ticks += ticks_diff;
Time::previous_seconds = Time::seconds; if (Time::pause_timer > 0)
Time::seconds += Time::delta; {
Time::pause_timer -= Time::delta;
step(); }
} else
} {
Time::previous_ticks = Time::ticks;
// Draw Frame Time::ticks += ticks_diff;
{ Time::previous_seconds = Time::seconds;
app_renderer_api->before_render(); Time::seconds += Time::delta;
if (app_config.on_render != nullptr)
app_config.on_render(); step();
app_renderer_api->after_render(); }
Platform::present(); }
}
// Draw Frame
// Update audio {
if (Internal::audio_is_init) app_renderer_api->before_render();
Blah::Internal::audio_update(); if (app_config.on_render != nullptr)
} app_config.on_render();
app_renderer_api->after_render();
void Internal::app_shutdown() Platform::present();
{ }
Internal::input_shutdown();
// Update audio
if (app_renderer_api) if (app_is_audio_running)
{ Blah::Internal::audio_update();
app_renderer_api->shutdown(); }
delete app_renderer_api;
} void Internal::app_shutdown()
app_renderer_api = nullptr; {
// shutdown systems
if (Internal::audio_is_init) Internal::input_shutdown();
{ if (app_renderer_api)
Internal::audio_shutdown(); {
Internal::audio_is_init = false; app_renderer_api->shutdown();
} delete app_renderer_api;
app_renderer_api = nullptr;
Platform::shutdown(); }
set_audio_system(false);
// clear static App state Platform::shutdown();
app_config = Config();
app_is_running = false; // clear static App state
app_is_exiting = false; app_config = Config();
app_time_last = 0; app_is_running = false;
app_time_accumulator = 0; app_is_exiting = false;
app_backbuffer = TargetRef(); app_time_last = 0;
app_time_accumulator = 0;
// clear static Time state app_backbuffer = TargetRef();
Time::ticks = 0;
Time::seconds = 0; // clear static Time state
Time::previous_ticks = 0; Time::ticks = 0;
Time::previous_seconds = 0; Time::seconds = 0;
Time::delta = 0; Time::previous_ticks = 0;
} Time::previous_seconds = 0;
Time::delta = 0;
Renderer* Internal::app_renderer() }
{
BLAH_ASSERT_RUNNING(); Renderer* Internal::app_renderer()
return app_renderer_api; {
} BLAH_ASSERT_RUNNING();
return app_renderer_api;
void App::exit() }
{
BLAH_ASSERT_RUNNING(); void App::exit()
if (!app_is_exiting && app_is_running) {
app_is_exiting = true; BLAH_ASSERT_RUNNING();
} if (!app_is_exiting && app_is_running)
app_is_exiting = true;
const Config& App::config() }
{
BLAH_ASSERT_RUNNING(); const Config& App::config()
return app_config; {
} BLAH_ASSERT_RUNNING();
return app_config;
const char* App::path() }
{
BLAH_ASSERT_RUNNING(); const char* App::path()
return Platform::app_path(); {
} BLAH_ASSERT_RUNNING();
return Platform::app_path();
const char* App::user_path() }
{
BLAH_ASSERT_RUNNING(); const char* App::user_path()
return Platform::user_path(); {
} BLAH_ASSERT_RUNNING();
return Platform::user_path();
const char* App::get_title() }
{
BLAH_ASSERT_RUNNING(); const char* App::get_title()
return Platform::get_title(); {
} BLAH_ASSERT_RUNNING();
return Platform::get_title();
void App::set_title(const char* title) }
{
BLAH_ASSERT_RUNNING(); void App::set_title(const char* title)
Platform::set_title(title); {
} BLAH_ASSERT_RUNNING();
Platform::set_title(title);
Point App::get_position() }
{
BLAH_ASSERT_RUNNING(); Point App::get_position()
Point result; {
Platform::get_position(&result.x, &result.y); BLAH_ASSERT_RUNNING();
return result; Point result;
} Platform::get_position(&result.x, &result.y);
return result;
void App::set_position(Point point) }
{
BLAH_ASSERT_RUNNING(); void App::set_position(Point point)
Platform::set_position(point.x, point.y); {
} BLAH_ASSERT_RUNNING();
Platform::set_position(point.x, point.y);
Point App::get_size() }
{
BLAH_ASSERT_RUNNING(); Point App::get_size()
Point result; {
Platform::get_size(&result.x, &result.y); BLAH_ASSERT_RUNNING();
return result; Point result;
} Platform::get_size(&result.x, &result.y);
return result;
void App::set_size(Point point) }
{
BLAH_ASSERT_RUNNING(); void App::set_size(Point point)
Platform::set_size(point.x, point.y); {
} BLAH_ASSERT_RUNNING();
Platform::set_size(point.x, point.y);
Point App::get_backbuffer_size() }
{
BLAH_ASSERT_RUNNING(); Point App::get_backbuffer_size()
if (app_renderer_api) {
return Point(app_backbuffer->width(), app_backbuffer->height()); BLAH_ASSERT_RUNNING();
return Point(0, 0); if (app_renderer_api)
} return Point(app_backbuffer->width(), app_backbuffer->height());
return Point(0, 0);
float App::content_scale() }
{
BLAH_ASSERT_RUNNING(); float App::content_scale()
return Platform::get_content_scale(); {
} BLAH_ASSERT_RUNNING();
return Platform::get_content_scale();
bool App::focused() }
{
BLAH_ASSERT_RUNNING(); bool App::focused()
return Platform::get_focused(); {
} BLAH_ASSERT_RUNNING();
return Platform::get_focused();
void App::set_flag(u32 flag, bool enabled) }
{
BLAH_ASSERT_RUNNING(); void App::set_flag(u32 flag, bool enabled)
{
u32 was = app_flags; BLAH_ASSERT_RUNNING();
if (enabled) u32 was = app_flags;
app_flags |= flag;
else if (enabled)
app_flags &= ~flag; app_flags |= flag;
else
if (was != app_flags) app_flags &= ~flag;
{
Platform::set_app_flags(app_flags); if (was != app_flags)
if (app_renderer_api) {
app_renderer_api->set_app_flags(app_flags); // tell platform & renderer
} Platform::set_app_flags(app_flags);
} if (app_renderer_api)
app_renderer_api->set_app_flags(app_flags);
bool App::get_flag(u32 flag)
{ // potentially toggle audio system
BLAH_ASSERT_RUNNING(); set_audio_system(get_flag(Flags::AudioEnabled));
return ((app_flags & flag) == flag); }
} }
const RendererInfo& App::renderer() bool App::get_flag(u32 flag)
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
BLAH_ASSERT_RENDERER(); return ((app_flags & flag) == flag);
return app_renderer_api->info; }
}
const RendererInfo& App::renderer()
const TargetRef& App::backbuffer() {
{ BLAH_ASSERT_RUNNING();
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RENDERER();
return app_backbuffer; return app_renderer_api->info;
} }
void System::open_url(const char* url) const TargetRef& App::backbuffer()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
Platform::open_url(url); return app_backbuffer;
}
void System::open_url(const char* url)
{
BLAH_ASSERT_RUNNING();
Platform::open_url(url);
} }

View File

@ -1,272 +1,272 @@
#include "blah_audio.h" #include "blah_audio.h"
#include "blah_time.h" #include "blah_time.h"
#include "internal/blah_internal.h" #include "internal/blah_internal.h"
#define STB_VORBIS_HEADER_ONLY #define STB_VORBIS_HEADER_ONLY
#include "third_party/stb_vorbis.c" #include "third_party/stb_vorbis.c"
#ifdef BLAH_PLATFORM_SDL2 #ifdef BLAH_PLATFORM_SDL2
#define CUTE_SOUND_FORCE_SDL #define CUTE_SOUND_FORCE_SDL
#endif #endif
#define CUTE_SOUND_IMPLEMENTATION #define CUTE_SOUND_IMPLEMENTATION
#include "third_party/cute_sound.h" #include "third_party/cute_sound.h"
namespace Blah namespace Blah
{ {
namespace Internal namespace Internal
{ {
bool audio_init(unsigned play_frequency_in_Hz, int buffered_samples) bool audio_init(unsigned play_frequency_in_Hz, int buffered_samples)
{ {
cs_error_t err = cs_init(Platform::d3d11_get_hwnd(), play_frequency_in_Hz, buffered_samples, NULL); cs_error_t err = cs_init(Platform::d3d11_get_hwnd(), play_frequency_in_Hz, buffered_samples, NULL);
if (err != CUTE_SOUND_ERROR_NONE) { if (err != CUTE_SOUND_ERROR_NONE)
Log::error(cs_error_as_string(err)); {
return false; Log::error(cs_error_as_string(err));
} else { return false;
return true; }
}
#ifndef BLAH_NO_THREADING
#ifndef BLAH_NO_THREADING cs_spawn_mix_thread();
cs_spawn_mix_thread(); #endif
#endif return true;
} }
void audio_shutdown() void audio_shutdown()
{ {
cs_shutdown(); cs_shutdown();
} }
void audio_update() void audio_update()
{ {
cs_update(Time::delta); cs_update(Time::delta);
} }
} }
Audio::Audio(void* audio) Audio::Audio(void* audio)
{ {
m_ptr = audio; m_ptr = audio;
} }
Audio::~Audio() Audio::~Audio()
{ {
cs_free_audio_source((cs_audio_source_t*)m_ptr); cs_free_audio_source((cs_audio_source_t*)m_ptr);
} }
u64 Audio::get_sample_count() u64 Audio::get_sample_count()
{ {
return m_ptr ? ((cs_audio_source_t*)m_ptr)->sample_count : 0; return m_ptr ? ((cs_audio_source_t*)m_ptr)->sample_count : 0;
} }
AudioRef Audio::create(const FilePath& path) AudioRef Audio::create(const FilePath& path)
{ {
FileStream fs(path, FileMode::OpenRead); FileStream fs(path, FileMode::OpenRead);
if (!fs.is_readable()) if (!fs.is_readable())
return AudioRef(); return AudioRef();
if (path.ends_with(".ogg")) { if (path.ends_with(".ogg")) {
return create_from_ogg(fs); return create_from_ogg(fs);
} else if (path.ends_with(".wav")) { } else if (path.ends_with(".wav")) {
return create_from_wav(fs); return create_from_wav(fs);
} }
Log::error("Unable to load unrecognized audio file type."); Log::error("Unable to load unrecognized audio file type.");
return AudioRef(); return AudioRef();
} }
AudioRef Audio::create_from_wav(Stream& stream) AudioRef Audio::create_from_wav(Stream& stream)
{ {
if (!stream.is_readable()) if (!stream.is_readable())
{ {
Log::error("Unable to load audio as the Stream was not readable"); Log::error("Unable to load audio as the Stream was not readable");
return AudioRef(); return AudioRef();
} }
// read into buffer // read into buffer
Vector<u8> buffer; Vector<u8> buffer;
buffer.reserve((int)stream.length()); buffer.reserve((int)stream.length());
stream.read(buffer.data(), stream.length()); stream.read(buffer.data(), stream.length());
// load wav file from memory using cute_sound.h // load wav file from memory using cute_sound.h
cs_error_t err; cs_error_t err;
void* audio = cs_read_mem_wav((void*)buffer.data(), stream.length(), &err); void* audio = cs_read_mem_wav((void*)buffer.data(), stream.length(), &err);
if (!audio) { if (!audio) {
Log::error(cs_error_as_string(err)); Log::error(cs_error_as_string(err));
return AudioRef(); return AudioRef();
} }
else else
return AudioRef(new Audio(audio)); return AudioRef(new Audio(audio));
} }
AudioRef Audio::create_from_ogg(Stream& stream) AudioRef Audio::create_from_ogg(Stream& stream)
{ {
if (!stream.is_readable()) if (!stream.is_readable())
{ {
Log::error("Unable to load audio as the Stream was not readable"); Log::error("Unable to load audio as the Stream was not readable");
return AudioRef(); return AudioRef();
} }
// read into buffer // read into buffer
Vector<u8> buffer; Vector<u8> buffer;
buffer.reserve((int)stream.length()); buffer.reserve((int)stream.length());
stream.read(buffer.data(), stream.length()); stream.read(buffer.data(), stream.length());
// load ogg file from memory using cute_sound.h // load ogg file from memory using cute_sound.h
cs_error_t err; cs_error_t err;
void* audio = cs_read_mem_ogg((void*)buffer.data(), stream.length(), &err); void* audio = cs_read_mem_ogg((void*)buffer.data(), stream.length(), &err);
if (!audio) { if (!audio) {
Log::error(cs_error_as_string(err)); Log::error(cs_error_as_string(err));
return AudioRef(); return AudioRef();
} }
else else
return AudioRef(new Audio(audio)); return AudioRef(new Audio(audio));
} }
void set_global_pan(float pan) void set_global_pan(float pan)
{ {
cs_set_global_pan(pan); cs_set_global_pan(pan);
} }
void set_global_volume(float volume) void set_global_volume(float volume)
{ {
cs_set_global_volume(volume); cs_set_global_volume(volume);
} }
void set_global_pause(bool true_for_paused) void set_global_pause(bool true_for_paused)
{ {
cs_set_global_pause(true_for_paused); cs_set_global_pause(true_for_paused);
} }
void set_sound_volume(float volume) void set_sound_volume(float volume)
{ {
cs_set_playing_sounds_volume(volume); cs_set_playing_sounds_volume(volume);
} }
void set_music_volume(float volume) void set_music_volume(float volume)
{ {
cs_music_set_volume(volume); cs_music_set_volume(volume);
} }
namespace Music namespace Music
{ {
void play(AudioRef audio, float fade_in_time) void play(AudioRef audio, float fade_in_time)
{ {
cs_music_play((cs_audio_source_t*)audio->get_backend_handle(), fade_in_time); cs_music_play((cs_audio_source_t*)audio->get_backend_handle(), fade_in_time);
} }
void stop(float fade_out_time) void stop(float fade_out_time)
{ {
cs_music_stop(fade_out_time); cs_music_stop(fade_out_time);
} }
void set_volume(float volume) void set_volume(float volume)
{ {
cs_music_set_volume(volume); cs_music_set_volume(volume);
} }
void set_loop(bool true_to_loop) void set_loop(bool true_to_loop)
{ {
cs_music_set_loop(true_to_loop); cs_music_set_loop(true_to_loop);
} }
void pause() void pause()
{ {
cs_music_pause(); cs_music_pause();
} }
void resume() void resume()
{ {
cs_music_resume(); cs_music_resume();
} }
void switch_to(AudioRef audio, float fade_out_time, float fade_in_time) void switch_to(AudioRef audio, float fade_out_time, float fade_in_time)
{ {
cs_music_switch_to((cs_audio_source_t*)audio->get_backend_handle(), fade_out_time, fade_in_time); cs_music_switch_to((cs_audio_source_t*)audio->get_backend_handle(), fade_out_time, fade_in_time);
} }
void crossfade(AudioRef audio, float cross_fade_time) void crossfade(AudioRef audio, float cross_fade_time)
{ {
cs_music_crossfade((cs_audio_source_t*)audio->get_backend_handle(), cross_fade_time); cs_music_crossfade((cs_audio_source_t*)audio->get_backend_handle(), cross_fade_time);
} }
u64 get_sample_index() u64 get_sample_index()
{ {
return cs_music_get_sample_index(); return cs_music_get_sample_index();
} }
void set_sample_index(u64 sample_index) void set_sample_index(u64 sample_index)
{ {
cs_music_set_sample_index(sample_index); cs_music_set_sample_index(sample_index);
} }
} }
Sound Sound::play(AudioRef audio, SoundParams params) Sound Sound::play(AudioRef audio, SoundParams params)
{ {
cs_sound_params_t csparams; cs_sound_params_t csparams;
csparams.paused = params.paused; csparams.paused = params.paused;
csparams.looped = params.looped; csparams.looped = params.looped;
csparams.volume = params.volume; csparams.volume = params.volume;
csparams.pan = params.pan; csparams.pan = params.pan;
csparams.delay = params.delay; csparams.delay = params.delay;
cs_playing_sound_t cssound = cs_play_sound((cs_audio_source_t*)audio->get_backend_handle(), csparams); cs_playing_sound_t cssound = cs_play_sound((cs_audio_source_t*)audio->get_backend_handle(), csparams);
Sound sound; Sound sound;
sound.id = cssound.id; sound.id = cssound.id;
return sound; return sound;
} }
bool Sound::is_active() bool Sound::is_active()
{ {
cs_playing_sound_t cssound = { id }; cs_playing_sound_t cssound = { id };
return cs_sound_is_active(cssound); return cs_sound_is_active(cssound);
} }
bool Sound::is_paused() bool Sound::is_paused()
{ {
cs_playing_sound_t cssound = { id }; cs_playing_sound_t cssound = { id };
return cs_sound_get_is_paused(cssound); return cs_sound_get_is_paused(cssound);
} }
bool Sound::is_looped() bool Sound::is_looped()
{ {
cs_playing_sound_t cssound = { id }; cs_playing_sound_t cssound = { id };
return cs_sound_get_is_looped(cssound); return cs_sound_get_is_looped(cssound);
} }
float Sound::get_volume() float Sound::get_volume()
{ {
cs_playing_sound_t cssound = { id }; cs_playing_sound_t cssound = { id };
return cs_sound_get_volume(cssound); return cs_sound_get_volume(cssound);
} }
u64 Sound::get_sample_index() u64 Sound::get_sample_index()
{ {
cs_playing_sound_t cssound = { id }; cs_playing_sound_t cssound = { id };
return cs_sound_get_sample_index(cssound); return cs_sound_get_sample_index(cssound);
} }
void Sound::set_is_paused(bool true_for_paused) void Sound::set_is_paused(bool true_for_paused)
{ {
cs_playing_sound_t cssound = { id }; cs_playing_sound_t cssound = { id };
cs_sound_set_is_paused(cssound, true_for_paused); cs_sound_set_is_paused(cssound, true_for_paused);
} }
void Sound::set_is_looped(bool true_for_looped) void Sound::set_is_looped(bool true_for_looped)
{ {
cs_playing_sound_t cssound = { id }; cs_playing_sound_t cssound = { id };
cs_sound_set_is_looped(cssound, true_for_looped); cs_sound_set_is_looped(cssound, true_for_looped);
} }
void Sound::set_volume(float volume) void Sound::set_volume(float volume)
{ {
cs_playing_sound_t cssound = { id }; cs_playing_sound_t cssound = { id };
cs_sound_set_volume(cssound, volume); cs_sound_set_volume(cssound, volume);
} }
void Sound::set_sample_index(u64 sample_index) void Sound::set_sample_index(u64 sample_index)
{ {
cs_playing_sound_t cssound = { id }; cs_playing_sound_t cssound = { id };
cs_sound_set_sample_index(cssound, sample_index); cs_sound_set_sample_index(cssound, sample_index);
} }
} }
#undef STB_VORBIS_HEADER_ONLY #undef STB_VORBIS_HEADER_ONLY
#include "third_party/stb_vorbis.c" #include "third_party/stb_vorbis.c"

View File

@ -9,8 +9,6 @@ namespace Blah
{ {
namespace Internal namespace Internal
{ {
extern bool audio_is_init;
void app_step(); void app_step();
void app_shutdown(); void app_shutdown();
Renderer* app_renderer(); Renderer* app_renderer();