Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Pinned style for OALS. Tuned to match what's already in the tree
# (4-space indent, K&R braces, ref/pointer attached to the variable,
# no hard column cap). Apply to new code via editor-on-save; do NOT
# mass-format existing files in a single sweep.
---
BasedOnStyle: LLVM
Language: Cpp
Standard: c++20

IndentWidth: 4
TabWidth: 4
UseTab: Never
ColumnLimit: 100

BreakBeforeBraces: Attach
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
SpaceAfterCStyleCast: false
PointerAlignment: Left
ReferenceAlignment: Left
DerivePointerAlignment: false

AccessModifierOffset: -4
NamespaceIndentation: None
FixNamespaceComments: true

IncludeBlocks: Preserve
SortIncludes: false

AlignAfterOpenBracket: Align
BinPackParameters: false
BinPackArguments: true
AllowAllParametersOfDeclarationOnNextLine: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true

EmptyLineBeforeAccessModifier: LogicalBlock
SeparateDefinitionBlocks: Leave
49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: CI

on:
push:
branches: ['**']
pull_request:
branches: ['**']

jobs:
build-test:
name: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install deps (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
cmake ninja-build pkg-config \
qt6-base-dev libsndfile1-dev libgtest-dev

- name: Install deps (macOS)
if: runner.os == 'macOS'
run: |
brew update
brew install cmake ninja qt6 libsndfile googletest

- name: Configure
run: |
cmake -G Ninja -B build \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DOAN_HOST_BACKENDS=ON \
-DCMAKE_PREFIX_PATH="$(brew --prefix qt6 2>/dev/null || echo /usr)"

- name: Build
run: cmake --build build

- name: Test
working-directory: build
run: ctest --output-on-failure
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/build/
23 changes: 23 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# pre-commit hooks for OALS. Install once per clone:
# pip install pre-commit && pre-commit install
# After that, every commit runs the hooks on staged files only.
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v17.0.6
hooks:
- id: clang-format
types_or: [c++, c]
# Exclude vendored / build trees and the OpenAudioNetwork submodule
# (it has its own .pre-commit-config.yaml and own clang-format
# invocation when committing inside it).
exclude: '^(build/|OpenAudioNetwork/|.*\.kicad_.*)'

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
- id: check-yaml
- id: check-added-large-files
args: ['--maxkb=512']
25 changes: 22 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,38 @@ project(OALiveSystem)

set(CMAKE_CXX_STANDARD 20)

if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64" AND NOT APPLE)
message("Added arm gcc optim")
add_compile_options(-ftree-vectorize)
endif()

set(ENGINE_PLUGIN_SYSLOCATION "/core_plugins")
option(OAN_HOST_BACKENDS "Build host dev transports + RT shim" OFF)
if(APPLE)
set(OAN_HOST_BACKENDS ON CACHE BOOL "Build host dev transports + RT shim" FORCE)
endif()
if(OAN_HOST_BACKENDS)
add_compile_definitions(OAN_HOST_BACKENDS)
endif()

if(APPLE)
# macOS root volume is read-only (SIP), so the Linux target's /core_plugins
# path can't be created. Use a per-user dir under $HOME instead — keeps
# the dev loop sudo-free.
set(ENGINE_PLUGIN_SYSLOCATION "$ENV{HOME}/.osst/core_plugins")
else()
set(ENGINE_PLUGIN_SYSLOCATION "/core_plugins")
endif()
add_compile_definitions(ENGINE_PLUGIN_SYSLOCATION="${ENGINE_PLUGIN_SYSLOCATION}")

enable_testing()

add_subdirectory(OpenDSP)
add_subdirectory(OpenAudioNetwork)

add_subdirectory(plugins)
add_subdirectory(coreui)
add_subdirectory(engine)
add_subdirectory(io_sim)
add_subdirectory(debugger)
add_subdirectory(debugger)
add_subdirectory(tools/sim_switch)
add_subdirectory(tools/oaninspect)
2 changes: 1 addition & 1 deletion coreui/surface_config/surface.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"network": {
"eth_interface": "virbr0",
"eth_interface": "sim:default",
"uid": 200
},

Expand Down
3 changes: 2 additions & 1 deletion debugger/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ qt_add_executable(debugger
DebuggerWindow.ui
)

target_include_directories(debugger PUBLIC ${PROJECT_SOURCE_DIR})
target_include_directories(debugger PUBLIC ${PROJECT_SOURCE_DIR} ${SNDFILE_INCLUDE_DIRS})
target_link_directories(debugger PUBLIC ${SNDFILE_LIBRARY_DIRS})
target_link_libraries(debugger PUBLIC Qt6::Core Qt6::Widgets)
target_link_libraries(debugger PUBLIC oancommon oannetutils)
target_link_libraries(debugger PUBLIC ${SNDFILE_LIBRARIES})
2 changes: 2 additions & 0 deletions debugger/DebuggerWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//
// This project is distributed under the Creative Commons CC-BY-NC-SA licence. https://creativecommons.org/licenses/by-nc-sa/4.0

#include <iostream>

#include "DebuggerWindow.h"
#include "ui_DebuggerWindow.h"

Expand Down
26 changes: 26 additions & 0 deletions engine/AudioEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

#include "AudioEngine.h"

#ifdef OAN_HOST_BACKENDS
#include <chrono>
#endif

AudioEngine::AudioEngine() {

}
Expand All @@ -26,6 +30,9 @@ void AudioEngine::feed_pipe(AudioPacket &packet) {
pipe->push_packet(packet);
}
}
#ifdef OAN_HOST_BACKENDS
notify_block_ready();
#endif
}

std::optional<uint8_t> AudioEngine::install_pipe(std::shared_ptr<AudioPipe> audio_pipe) {
Expand Down Expand Up @@ -99,3 +106,22 @@ void AudioEngine::update_processes() {
}
}

#ifdef OAN_HOST_BACKENDS
void AudioEngine::notify_block_ready() {
{
std::lock_guard<std::mutex> lk{m_wakeup_mtx};
m_block_ready = true;
}
m_wakeup_cv.notify_one();
}

bool AudioEngine::wait_for_block(int timeout_us) {
std::unique_lock<std::mutex> lk{m_wakeup_mtx};
bool woken = m_wakeup_cv.wait_for(
lk, std::chrono::microseconds(timeout_us),
[this]() { return m_block_ready; });
m_block_ready = false;
return woken;
}
#endif

26 changes: 26 additions & 0 deletions engine/AudioEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
#include <memory>
#include <iostream>

#ifdef OAN_HOST_BACKENDS
#include <condition_variable>
#include <mutex>
#endif

#include "plugins/loader/AudioPipe.h"
#include "engine/piping/io/AudioInPipe.h"
#include "OpenAudioNetwork/common/packet_structs.h"
Expand All @@ -39,8 +44,29 @@ class AudioEngine {
bool reset_pipes();

uint64_t get_channel_usage_map();

#ifdef OAN_HOST_BACKENDS
// Producer side: called from the audio recv callback after feed_pipe.
// Wakes the pipe_updater thread so it can drain the block instead of
// busy-ticking. No-op on Linux — Linux RT thread layout is unchanged.
void notify_block_ready();

// Consumer side: pipe_updater blocks here until a block arrives or
// the timeout elapses. Timeout acts as a heartbeat so time-driven
// work in continuous_process() (release envelopes, etc.) still runs
// when the wire is idle. Returns true if woken by notify, false on
// timeout. timeout_us = 0 means no wait.
bool wait_for_block(int timeout_us);
#endif

private:
std::array<std::shared_ptr<AudioPipe>, AUDIO_ENGINE_MAX_PIPES> m_pipes;

#ifdef OAN_HOST_BACKENDS
std::mutex m_wakeup_mtx;
std::condition_variable m_wakeup_cv;
bool m_block_ready{false};
#endif
};

#endif //AUDIOENGINE_H
14 changes: 14 additions & 0 deletions engine/NetMan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//
// This project is distributed under the Creative Commons CC-BY-NC-SA licence. https://creativecommons.org/licenses/by-nc-sa/4.0

#include <iostream>

#include "NetMan.h"

NetMan::NetMan(AudioPlumber* plumber) {
Expand Down Expand Up @@ -59,6 +61,18 @@ void NetMan::update_self_topo(NodeTopology new_topo) {
m_nmapper->update_resource_mapping(new_topo);
}

#ifdef OAN_HOST_BACKENDS
void NetMan::clock_wait_or_tick(int timeout_ms) {
// Drain the sync poll-spin: block until the sync socket has data
// (or timeout), then let clock_master_process handle the 1 s
// heartbeat + recv. Result is ignored — recv inside
// clock_master_process is still non-blocking and returns 0 cleanly
// on spurious wakeups / timeouts.
m_cm->wait_sync_readable(timeout_ms);
clock_master_process();
}
#endif

void NetMan::clock_master_process() {
constexpr uint64_t sync_interval = 1000000;
static uint64_t last_sync = NetworkMapper::local_now_us();
Expand Down
9 changes: 9 additions & 0 deletions engine/NetMan.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ class NetMan {
std::shared_ptr<NetworkMapper> get_net_mapper();

void clock_master_process();

#ifdef OAN_HOST_BACKENDS
// Wait up to timeout_ms for a sync packet to arrive, then run the
// 1 s heartbeat tick. Replaces the busy-loop on the engine's
// clock_syncer thread when running over host backends — the Linux
// RT path keeps using clock_master_process directly.
void clock_wait_or_tick(int timeout_ms);
#endif

private:
std::shared_ptr<NetworkMapper> m_nmapper;
PeerConf m_pconf;
Expand Down
Loading
Loading