Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix linux build, add a portaudio and a pulseaudio backend #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.idea
cmake-build*
.DS_Store
*.user
build
29 changes: 25 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,42 @@ cmake_minimum_required(VERSION 3.12)
project(libstdaudio)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -O0 -fsanitize=undefined")
if (APPLE)
set(CMAKE_EXE_LINKER_FLAGS "-framework CoreAudio")
endif ()

# add the headers to at least one target so that they get
# parsed as part of the project in some IDEs
set(headers
include/__audio_base.h
include/__audio_buffer.h
include/__audio_device.h
include/__audio_exception.h
include/__dynamic_library.h
include/audio
include/cpp/span.hpp
include/audio_backend/__coreaudio_backend.h
include/audio_backend/__null_backend.h
include/audio_backend/__portaudio_backend.h
include/audio_backend/__pulseaudio_backend.h
)
include_directories(include)

add_executable(white_noise examples/white_noise.cpp)
add_executable(white_noise examples/white_noise.cpp ${headers})
target_link_libraries(white_noise PRIVATE ${CMAKE_DL_LIBS})
add_executable(print_devices examples/print_devices.cpp)
target_link_libraries(print_devices PRIVATE ${CMAKE_DL_LIBS})
add_executable(sine_wave examples/sine_wave.cpp)
target_link_libraries(sine_wave PRIVATE ${CMAKE_DL_LIBS})
add_executable(melody examples/melody.cpp)
target_link_libraries(melody PRIVATE ${CMAKE_DL_LIBS})
add_executable(level_meter examples/level_meter.cpp)
target_link_libraries(level_meter PRIVATE ${CMAKE_DL_LIBS})

add_executable(test
test/test_main.cpp
# test/null_backend_test.cpp // TODO: fix linker error when uncommenting this one!
test/default_backend_test.cpp)
test/default_backend_test.cpp)

target_link_libraries(test PRIVATE ${CMAKE_DL_LIBS})
4 changes: 2 additions & 2 deletions examples/print_devices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#include <iostream>
#include <audio>

#include <cassert>
using namespace std::experimental;

void print_device_info(const audio_device& d) {
Expand All @@ -27,4 +27,4 @@ int main() {

std::cout << "\nOutput devices:\n===============\n";
print_device_list(get_audio_output_device_list());
}
}
41 changes: 41 additions & 0 deletions include/__audio_base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include <optional>
#include <cassert>
#include <string_view>
#include <atomic>

// TODO: this is a temporary measure until std::span becomes available
#include "cpp/span.hpp"
using namespace TCB_SPAN_NAMESPACE_NAME;

#define _LIBSTDAUDIO_NAMESPACE std::experimental

#define _LIBSTDAUDIO_NAMESPACE_BEGIN namespace _LIBSTDAUDIO_NAMESPACE {
#define _LIBSTDAUDIO_NAMESPACE_END }

_LIBSTDAUDIO_NAMESPACE_BEGIN

struct audio_null_driver_t {};

#ifdef __APPLE__
struct __coreaudio_driver_t {};
using audio_default_driver_t = __coreaudio_driver_t;
#else

#if __has_include(<pulse/pulseaudio.h>)
struct __pulseaudio_driver_t {};
#endif
#if __has_include(<portaudio.h>)
struct __portaudio_driver_t {};
#endif

#if __has_include(<pulse/pulseaudio.h>)
using audio_default_driver_t = __pulseaudio_driver_t;
#elif __has_include(<portaudio.h>)
using audio_default_driver_t = __portaudio_driver_t;
#endif
#endif // __APPLE__

_LIBSTDAUDIO_NAMESPACE_END

1 change: 1 addition & 0 deletions include/__audio_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#pragma once
#include <__audio_base.h>

_LIBSTDAUDIO_NAMESPACE_BEGIN

Expand Down
1 change: 1 addition & 0 deletions include/__audio_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#pragma once
#include <__audio_base.h>

_LIBSTDAUDIO_NAMESPACE_BEGIN

Expand Down
13 changes: 13 additions & 0 deletions include/__audio_exception.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once
#include <__audio_base.h>
#include <stdexcept>

_LIBSTDAUDIO_NAMESPACE_BEGIN

struct audio_device_exception : public runtime_error {
explicit audio_device_exception(const char* what)
: runtime_error(what) {
}
};

_LIBSTDAUDIO_NAMESPACE_END
70 changes: 70 additions & 0 deletions include/__dynamic_library.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#pragma once
#include <__audio_base.h>

#if defined(_WIN32)
#define __STDAUDIO_HAS_DYLIB 1
#include <windows.h>
#elif __has_include(<dlfcn.h>)
#define __STDAUDIO_HAS_DYLIB 1
#include <dlfcn.h>
#endif

_LIBSTDAUDIO_NAMESPACE_BEGIN
#if __STDAUDIO_HAS_DYLIB
class __dynamic_library
{
public:
explicit __dynamic_library(const char* const so) /* not noexcept - some DLL constructors can throw */
{
#ifdef _WIN32
impl = (void*)LoadLibraryA(so);
#else
impl = dlopen(so, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE);
#endif
}

__dynamic_library(const __dynamic_library&) noexcept = delete;
__dynamic_library& operator=(const __dynamic_library&) noexcept = delete;
__dynamic_library(__dynamic_library&& other)
{
impl = other.impl;
other.impl = nullptr;
}

__dynamic_library& operator=(__dynamic_library&& other) noexcept
{
impl = other.impl;
other.impl = nullptr;
return *this;
}

~__dynamic_library()
{
if (impl)
{
#ifdef _WIN32
FreeLibrary((HMODULE)impl);
#else
dlclose(impl);
#endif
}
}

template <typename T>
T symbol(const char* const sym) const noexcept
{
#ifdef _WIN32
return (T)GetProcAddress((HMODULE)impl, sym);
#else
return (T)dlsym(impl, sym);
#endif
}

operator bool() const { return bool(impl); }

private:
void* impl{};
};
#endif

_LIBSTDAUDIO_NAMESPACE_END
32 changes: 7 additions & 25 deletions include/audio
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,17 @@
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#pragma once

#include <optional>

// TODO: this is a temporary measure until std::span becomes available
#include "cpp/span.hpp"
using namespace TCB_SPAN_NAMESPACE_NAME;

#define _LIBSTDAUDIO_NAMESPACE std::experimental

#define _LIBSTDAUDIO_NAMESPACE_BEGIN namespace _LIBSTDAUDIO_NAMESPACE {
#define _LIBSTDAUDIO_NAMESPACE_END }

_LIBSTDAUDIO_NAMESPACE_BEGIN

struct audio_null_driver_t {};

#ifdef __APPLE__
struct __coreaudio_driver_t {};
using audio_default_driver_t = __coreaudio_driver_t;
#else
using audio_default_driver_t = audio_null_driver_t;
#endif // __APPLE__

_LIBSTDAUDIO_NAMESPACE_END

#include <__audio_base.h>
#include <__audio_buffer.h>
#include <__audio_device.h>
#include <audio_backend/__null_backend.h>

#ifdef __APPLE__
#include <audio_backend/__coreaudio_backend.h>
#endif // __APPLE__
#if __has_include(<portaudio.h>)
#include <audio_backend/__portaudio_backend.h>
#endif
#if __has_include(<pulse/pulseaudio.h>)
#include <audio_backend/__pulseaudio_backend.h>
#endif
10 changes: 4 additions & 6 deletions include/audio_backend/__coreaudio_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

#pragma once

#include <__audio_base.h>
#include <__audio_device.h>
#include <__audio_buffer.h>
#include <__audio_exception.h>
#include <cctype>
#include <string>
#include <iostream>
Expand Down Expand Up @@ -72,12 +76,6 @@ class __coreaudio_util {
}
};

struct audio_device_exception : public runtime_error {
explicit audio_device_exception(const char* what)
: runtime_error(what) {
}
};

using __coreaudio_device = audio_basic_device<__coreaudio_driver_t>;

template<>
Expand Down
99 changes: 79 additions & 20 deletions include/audio_backend/__null_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,90 @@
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#pragma once

#include <forward_list>
_LIBSTDAUDIO_NAMESPACE_BEGIN

template<>
class audio_basic_device<audio_null_driver_t> {};
class audio_basic_device<audio_null_driver_t>
{
public:
audio_basic_device() = delete;

using sample_rate_t = double;
sample_rate_t get_sample_rate() const noexcept { return 0; }
bool set_sample_rate(sample_rate_t new_sample_rate) {
return false;
}

bool start() { return false; }
bool stop() { return false; }

using buffer_size_t = uint32_t;

buffer_size_t get_buffer_size_frames() const noexcept
{
return 0;
}

string_view name() const noexcept {
return {};
}

using device_id_t = int;
device_id_t device_id() const noexcept {
return -1;
}

bool is_input() const noexcept {
return false;
}

bool is_output() const noexcept {
return false;
}
int get_num_input_channels() const noexcept {
return 0;
}

int get_num_output_channels() const noexcept {
return 0;
}

template<typename T>
void connect(T) {

}

constexpr bool can_connect() const noexcept {
return false;
}

constexpr bool can_process() const noexcept {
return false;
}

constexpr bool is_running() const noexcept {
return false;
}

span<const sample_rate_t> get_supported_sample_rates() const noexcept {
return { };
}

span<const buffer_size_t> get_supported_buffer_sizes_frames() const noexcept {
return { };
}

bool set_buffer_size_frames(buffer_size_t new_buffer_size) {
return false;
}

};

using __null_device = audio_basic_device<audio_null_driver_t>;
template<>
class audio_basic_device_list<audio_null_driver_t>
class audio_basic_device_list<audio_null_driver_t> : public forward_list<__null_device>
{
private:
class iterator {
public:
auto operator==(const iterator&) const noexcept { return true; }
auto operator!=(const iterator&) const noexcept { return false; }
auto operator++() -> const iterator& { assert(false); return *this; }
auto operator*() -> audio_basic_device<audio_null_driver_t>& {
assert(false); static audio_basic_device<audio_null_driver_t> device{};
return device;
}
};

public:
auto begin() -> iterator { return {}; }
auto end() -> iterator { return {}; }
auto empty() -> bool { return true; }
};

template<>
Expand Down Expand Up @@ -59,4 +118,4 @@ auto get_audio_output_device_list<audio_null_driver_t>()
return {};
}

_LIBSTDAUDIO_NAMESPACE_END
_LIBSTDAUDIO_NAMESPACE_END
Loading