Skip to content

Commit

Permalink
Merge branch 'master' into string_view
Browse files Browse the repository at this point in the history
  • Loading branch information
jhasse committed Apr 20, 2024
2 parents 7252144 + e7ff92d commit bb4b87b
Show file tree
Hide file tree
Showing 50 changed files with 832 additions and 257 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,12 @@ jobs:
image: registry.gitlab.com/jhasse/android-ndk-docker:r26b
steps:
- uses: actions/checkout@v4
- name: Cache CPM.cmake packages
uses: actions/cache@v4
with:
path: .cache/cpm
key: cpm
- name: Build
run: make -C android
env:
CPM_SOURCE_CACHE: ${{ github.workspace }}/.cache/cpm
7 changes: 7 additions & 0 deletions .github/workflows/ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Cache CPM.cmake packages
uses: actions/cache@v4
with:
path: .cache/cpm
key: cpm
- name: Checkout submodules
shell: bash
run: |
Expand All @@ -19,3 +24,5 @@ jobs:
run: cmake -Bbuild-tvossimulator -GXcode -DCMAKE_TOOLCHAIN_FILE=cmake/tvOS.toolchain.cmake -DIOS_PLATFORM=SIMULATOR
- name: Build with Xcode (tvOS)
run: xcodebuild -quiet -project build-tvossimulator/jngl.xcodeproj -sdk appletvsimulator -arch x86_64 -target jngl-test
env:
CPM_SOURCE_CACHE: ${{ github.workspace }}/.cache/cpm
23 changes: 22 additions & 1 deletion .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@ jobs:
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
- name: Cache CPM.cmake packages
uses: actions/cache@v4
with:
path: .cache/cpm
key: cpm
- uses: ilammy/msvc-dev-cmd@v1
- name: Configure
run: cmake -Bbuild -G"Ninja Multi-Config" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
- name: Build (Debug)
run: cmake --build build --config Debug
- name: Unittest (Debug)
run: |
build/Debug/jngl-unittest Color
build/Debug/jngl-unittest Rgb
build/Debug/jngl-unittest Drawable
build/Debug/jngl-unittest ImageData
build/Debug/jngl-unittest FinallyTest
Expand All @@ -22,6 +29,8 @@ jobs:
run: cmake --build build --config Release
- name: Unittest (Release)
run: |
build/Release/jngl-unittest Color
build/Release/jngl-unittest Rgb
build/Release/jngl-unittest Drawable
build/Release/jngl-unittest ImageData
build/Release/jngl-unittest FinallyTest
Expand All @@ -33,12 +42,19 @@ jobs:
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
- name: Cache CPM.cmake packages
uses: actions/cache@v4
with:
path: .cache/cpm
key: cpm
- name: Configure
run: cmake -Bbuild
- name: Build (Debug)
run: cmake --build build --config Debug
- name: Unittest (Debug)
run: |
build/Debug/jngl-unittest Color
build/Debug/jngl-unittest Rgb
build/Debug/jngl-unittest Drawable
build/Debug/jngl-unittest ImageData
build/Debug/jngl-unittest FinallyTest
Expand All @@ -49,6 +65,8 @@ jobs:
run: cmake --build build --config Release
- name: Unittest (Release)
run: |
build/Release/jngl-unittest Color
build/Release/jngl-unittest Rgb
build/Release/jngl-unittest Drawable
build/Release/jngl-unittest ImageData
build/Release/jngl-unittest FinallyTest
Expand All @@ -65,7 +83,7 @@ jobs:
mingw-sdl:
runs-on: [ubuntu-latest]
container:
image: registry.fedoraproject.org/fedora-minimal:37
image: registry.fedoraproject.org/fedora-minimal:39
steps:
- name: Install dependencies
run: microdnf install -y cmake ninja-build mingw64-pkg-config mingw64-libvorbis mingw64-SDL2 mingw64-fontconfig mingw64-libwebp mingw64-dlfcn mingw32-nsis mingw64-gcc-c++ tar gzip
Expand All @@ -74,3 +92,6 @@ jobs:
run: |
mingw64-cmake -Bbuild-windows -GNinja -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=0 -DJNGL_SDL2=1
ninja -Cbuild-windows
env:
CPM_SOURCE_CACHE: ${{ github.workspace }}/.cache/cpm
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ endif()
get_directory_property(hasParent PARENT_DIRECTORY)
if(ANDROID OR MSVC OR IOS)
CPMAddPackage(NAME freetype
URL https://download.savannah.gnu.org/releases/freetype/freetype-2.11.1.tar.xz
URL https://sourceforge.net/projects/freetype/files/freetype2/2.11.1/freetype-2.11.1.tar.xz/download
URL_HASH SHA256=3333ae7cfda88429c97a7ae63b7d01ab398076c3b67182e960e5684050f2c5c8
OPTIONS "FT_DISABLE_HARFBUZZ 1"
)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ libwebp-dev git libsdl2-dev

```
sudo dnf install fontconfig-devel freetype-devel libvorbis-devel libwebp-devel \
cmake SDL2-devel gcc-c++
cmake SDL2-devel gcc-c++ libatomic
```

### Arch Linux
Expand Down
3 changes: 3 additions & 0 deletions src/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ void mainLoop(AppParameters params) {
#if (!defined(__EMSCRIPTEN__) && defined(NDEBUG)) || defined(__ANDROID__)
fullscreen = true;
#endif
if (params.fullscreen) {
fullscreen = *params.fullscreen;
}
std::pair<int, int> minAspectRatio{ 1, 3 };
std::pair<int, int> maxAspectRatio{ 3, 1 };
if (params.screenSize) {
Expand Down
9 changes: 8 additions & 1 deletion src/App.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,14 @@ class App {

static App* self;

/// Not part of Impl so that jngl::atExit works even before jnglInit() has been called
/// Not part of Impl so that jngl::atExit works even before jnglInit() has been called.
/// The lifecycle order is the following:
///
/// * App::App()
/// * jnglInit()
/// * App::init()
/// * Window::Window()
/// * appParameters.start()
std::vector<std::function<void()>> callAtExit;
};

Expand Down
8 changes: 4 additions & 4 deletions src/android/windowimpl.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015-2023 Jan Niklas Hasse <jhasse@bixense.com>
// Copyright 2015-2024 Jan Niklas Hasse <jhasse@bixense.com>
// For conditions of distribution and use, see copyright notice in LICENSE.txt

#include "windowimpl.hpp"
Expand All @@ -7,9 +7,9 @@
#include "../jngl/other.hpp"
#include "../jngl/debug.hpp"
#include "../jngl/screen.hpp"
#include "../jngl/sound.hpp"
#include "../jngl/window.hpp"
#include "../jngl/work.hpp"
#include "../audio.hpp"
#include "../windowptr.hpp"
#include "../main.hpp"
#include "fopen.hpp"
Expand Down Expand Up @@ -332,7 +332,7 @@ void WindowImpl::pause() {
if (display) {
display->surface = std::nullopt;
}
pauseAudioDevice();
pauseAudio = jngl::pauseAudio();
}

void WindowImpl::makeCurrent() {
Expand All @@ -342,7 +342,7 @@ void WindowImpl::makeCurrent() {
if (!display->surface) {
display->surface.emplace(*display);
}
resumeAudioDevice();
pauseAudio = {};
}

int WindowImpl::handleKeyEvent(AInputEvent* const event) {
Expand Down
4 changes: 3 additions & 1 deletion src/android/windowimpl.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright 2015-2020 Jan Niklas Hasse <jhasse@bixense.com>
// Copyright 2015-2024 Jan Niklas Hasse <jhasse@bixense.com>
// For conditions of distribution and use, see copyright notice in LICENSE.txt

#pragma once

#include "../jngl/Finally.hpp"
#include "../jngl/Vec2.hpp"

#include <EGL/egl.h>
Expand Down Expand Up @@ -49,6 +50,7 @@ class WindowImpl {
const std::pair<int, int> maxAspectRatio;
android_app* app;
Window* window;
std::optional<Finally> pauseAudio;

bool firstFrame = true;

Expand Down
46 changes: 38 additions & 8 deletions src/audio.hpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
// Copyright 2010-2023 Jan Niklas Hasse <jhasse@bixense.com>
// Copyright 2010-2024 Jan Niklas Hasse <jhasse@bixense.com>
// For conditions of distribution and use, see copyright notice in LICENSE.txt

#pragma once

#include "audio/mixer.hpp"
#include "audio/engine.hpp"
#include "jngl/Singleton.hpp"

#include <memory>

namespace jngl {

void checkAlError();
void pauseAudioDevice();
void resumeAudioDevice();
class Mixer;
class Sound;

namespace audio {
struct pitch_control;
struct volume_control;
} // namespace audio

class Audio;
void checkAlError();

Audio& GetAudio();
std::shared_ptr<Mixer> getMixer();
class Audio : public jngl::Singleton<Audio> {
public:
Audio();
Audio(const Audio&) = delete;
Audio& operator=(const Audio&) = delete;
Audio(Audio&&) = delete;
Audio& operator=(Audio&&) = delete;
~Audio();

void play(std::shared_ptr<Sound> sound);
void stop(std::shared_ptr<Sound>& sound);
void increasePauseDeviceCount();
void decreasePauseDeviceCount();
void setPitch(float pitch);
float getVolume() const;
void setVolume(float volume);
std::shared_ptr<Mixer> getMixer();
void step();

private:
std::vector<std::shared_ptr<Sound>> sounds_;
std::shared_ptr<Mixer> mixer;
std::shared_ptr<audio::pitch_control> pitchControl;
std::shared_ptr<audio::volume_control> volumeControl;
audio::engine engine;
uint8_t pauseDeviceCount = 0; //< if >0 audio device is paused
};

} // namespace jngl
4 changes: 1 addition & 3 deletions src/audio/Stream.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// Copyright 2023 Jan Niklas Hasse <jhasse@bixense.com>
// Copyright 2023-2024 Jan Niklas Hasse <jhasse@bixense.com>
// For conditions of distribution and use, see copyright notice in LICENSE.txt
// Based on the audio implementation of the psemek engine, see
// https://lisyarus.github.io/blog/programming/2022/10/15/audio-mixing.html
#pragma once

#include <cstddef>
#include <memory>
#include <optional>

namespace jngl {

Expand Down
62 changes: 38 additions & 24 deletions src/audio/android/engine.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 Jan Niklas Hasse <jhasse@bixense.com>
// Copyright 2023-2024 Jan Niklas Hasse <jhasse@bixense.com>
// For conditions of distribution and use, see copyright notice in LICENSE.txt
#include "../engine.hpp"
#include "../constants.hpp"
Expand All @@ -20,6 +20,24 @@ struct engine::Impl {

Impl(std::shared_ptr<Stream> output);

void start() {
if (oboeStream) {
assert(oboeStream->getState() == oboe::StreamState::Started);
return;
}
const auto result = builder.openStream(oboeStream);
if (result != oboe::Result::OK) {
throw std::runtime_error(oboe::convertToText(result));
}
oboeStream->requestStart();
}
void stop() {
if (oboeStream) {
oboeStream->close();
oboeStream.reset();
}
}

class Callback : public oboe::AudioStreamCallback {
public:
Callback(Impl& self) : self(self) {
Expand All @@ -29,21 +47,28 @@ struct engine::Impl {
oboe::DataCallbackResult onAudioReady(oboe::AudioStream*, void* data,
int32_t len) override {
float* dst = reinterpret_cast<float*>(data);
self.output->read(dst, len * 2);
self.output->read(dst, len * 2);
return oboe::DataCallbackResult::Continue;
}

void onErrorAfterClose(oboe::AudioStream*, oboe::Result error) override {
if (error == oboe::Result::ErrorDisconnected) {
assert(self.oboeStream->getState() == oboe::StreamState::Closed);
self.oboeStream.reset();
self.start();
}
}

Impl& self;
};

private:
Callback callback;
oboe::AudioStreamBuilder builder;
std::shared_ptr<oboe::AudioStream> oboeStream;
};

engine::Impl::Impl(std::shared_ptr<Stream> output)
: output(std::move(output)), callback(*this)
{
engine::Impl::Impl(std::shared_ptr<Stream> output) : output(std::move(output)), callback(*this) {
builder.setDirection(oboe::Direction::Output);
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
builder.setSharingMode(oboe::SharingMode::Exclusive);
Expand All @@ -52,36 +77,25 @@ engine::Impl::Impl(std::shared_ptr<Stream> output)
builder.setSampleRate(frequency);
// desired.samples = 256;
builder.setCallback(&callback);
const auto result = builder.openStream(oboeStream);
if (result != oboe::Result::OK) {
throw std::runtime_error(oboe::convertToText(result));
}

oboeStream->requestStart();
start();
}

engine::engine(std::shared_ptr<Stream> output) : impl(std::make_unique<Impl>(std::move(output))) {
}

engine::~engine() {
impl->oboeStream->close();
impl->stop();
}

void engine::setPause(bool pause) {
if (pause) {
if (impl->oboeStream) {
impl->oboeStream->close();
impl->oboeStream.reset();
}
impl->stop();
} else {
if (!impl->oboeStream) {
const auto result = impl->builder.openStream(impl->oboeStream);
if (result == oboe::Result::OK) {
impl->oboeStream->requestStart();
} else {
debugLn(std::string("WARNING: ") + oboe::convertToText(result));
}
}
impl->start();
}
}

void engine::step() {
}

} // namespace jngl::audio
Loading

0 comments on commit bb4b87b

Please sign in to comment.