Cubeb: add recipe

This commit is contained in:
Gerasim Troeglazov
2020-12-26 16:41:25 +10:00
parent d7449aa4a8
commit 384f269798
3 changed files with 552 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
SUMMARY="Cross platform audio library"
DESCRIPTION="Cubeb is a cross-platform library, written in C/C++, that was \
created and has been maintained by the Firefox Media Team.
The functionality of the library is not limited to audio input and output. \
In addition, it is possible to enumerate all audio devices in the system, as \
well as to register notifications such as device unplugs. It is also possible \
to switch between devices at a lower level with a minimal transition gap."
HOMEPAGE="https://github.com/mozilla/cubeb/"
COPYRIGHT="Mozilla Foundation"
LICENSE="ISC"
REVISION="1"
gitRevision="860bf2b31531e4ef49478a433ff22ffb4303b805"
SOURCE_URI="https://github.com/mozilla/cubeb/archive/$gitRevision.tar.gz"
CHECKSUM_SHA256="104e875c7073953a8dc7a8db8ed221f243c18a7572ee05b052cf0bf8888e150c"
SOURCE_DIR="cubeb-$gitRevision"
PATCHES="cubeb-$portVersion.patchset"
ARCHITECTURES="?x86_gcc2 x86_64"
SECONDARY_ARCHITECTURES="?x86"
PROVIDES="
cubeb$secondaryArchSuffix = $portVersion
cmd:cubeb_test$secondaryArchSuffix = $portVersion
lib:libcubeb$secondaryArchSuffix = $portVersion compat >= 0
"
REQUIRES="
haiku$secondaryArchSuffix
"
PROVIDES_devel="
cubeb${secondaryArchSuffix}_devel = $portVersion
devel:libcubeb$secondaryArchSuffix = $portVersion compat >= 0
"
REQUIRES_devel="
haiku$secondaryArchSuffix
lib:libcubeb$secondaryArchSuffix == $portVersion base
"
BUILD_REQUIRES="
haiku${secondaryArchSuffix}_devel
"
BUILD_PREREQUIRES="
cmd:cmake
cmd:gcc$secondaryArchSuffix
cmd:ld$secondaryArchSuffix
cmd:make
"
BUILD()
{
mkdir -p build
cd build
cmake .. $cmakeDirArgs \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_BINDIR=$binDir \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTS=OFF
make $jobArgs
}
INSTALL()
{
cd build
make install
prepareInstalledDevelLib libcubeb
# devel package
packageEntries devel \
$developDir \
$libDir/cmake
}

View File

@@ -0,0 +1,13 @@
Copyright (c) 2002,2003,2007 Martin Hedenfalk <martin@bzero.se>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE

View File

@@ -0,0 +1,466 @@
From 56556730def233b69fdfbb07a98a7bb79e9c77c8 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sat, 26 Dec 2020 16:00:08 +1000
Subject: Remove sanitizers for haiku, fix bindir
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c6c3309..f037cf5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,7 +22,7 @@ set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
-if(NOT COMMAND add_sanitizers)
+if(NOT COMMAND add_sanitizers AND NOT HAIKU)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/sanitizers-cmake/cmake")
find_package(Sanitizers)
if(NOT COMMAND add_sanitizers)
@@ -83,7 +83,9 @@ target_compile_definitions(cubeb PRIVATE FLOATING_POINT)
target_compile_definitions(cubeb PRIVATE EXPORT=)
target_compile_definitions(cubeb PRIVATE RANDOM_PREFIX=speex)
+if(NOT HAIKU)
add_sanitizers(cubeb)
+endif()
include(GenerateExportHeader)
generate_export_header(cubeb EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/exports/cubeb_export.h)
@@ -322,8 +324,10 @@ if(BUILD_TESTS)
target_include_directories(test_${NAME} PRIVATE src)
target_link_libraries(test_${NAME} PRIVATE cubeb gtest_main)
add_test(${NAME} test_${NAME})
+if(NOT HAIKU)
add_sanitizers(test_${NAME})
- install(TARGETS test_${NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
+endif()
+ install(TARGETS test_${NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
endmacro(cubeb_add_test)
cubeb_add_test(sanity)
@@ -342,8 +346,10 @@ if(BUILD_TESTS)
target_compile_definitions(test_resampler PRIVATE RANDOM_PREFIX=speex)
target_link_libraries(test_resampler PRIVATE cubeb gtest_main)
add_test(resampler test_resampler)
+if(NOT HAIKU)
add_sanitizers(test_resampler)
- install(TARGETS test_resampler DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
+endif()
+ install(TARGETS test_resampler DESTINATION ${CMAKE_INSTALL_BINDIR})
cubeb_add_test(duplex)
@@ -364,6 +370,8 @@ if(BUILD_TOOLS)
add_executable(cubeb-test tools/cubeb-test.cpp)
target_include_directories(cubeb-test PRIVATE src)
target_link_libraries(cubeb-test PRIVATE cubeb)
+if(NOT HAIKU)
add_sanitizers(cubeb-test)
- install(TARGETS cubeb-test DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
+endif()
+ install(TARGETS cubeb-test DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
--
2.28.0
From 96258033f42c422f2cc2c72da9c36cb9a025df1a Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sat, 26 Dec 2020 16:03:40 +1000
Subject: Add haiku backend
diff --git a/src/cubeb_haiku.cpp b/src/cubeb_haiku.cpp
new file mode 100644
index 0000000..7bfbc3b
--- /dev/null
+++ b/src/cubeb_haiku.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright © 2020 Gerasim Troeglazov
+ *
+ * This program is made available under an ISC-style license. See the
+ * accompanying file LICENSE for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include <SoundPlayer.h>
+
+#include "cubeb/cubeb.h"
+#include "cubeb-internal.h"
+
+#define DEFAULT_RATE 48000
+#define MAX_CHANNELS 32
+#define FRAME_SIZE 2048
+
+extern "C" {
+int haiku_init(cubeb ** context, char const * context_name);
+}
+
+static char const *haiku_get_backend_id(cubeb * ctx);
+static int haiku_get_max_channel_count(cubeb * ctx, uint32_t * max_channels);
+static int haiku_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency);
+static int haiku_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate);
+static void haiku_destroy(cubeb * ctx);
+static void haiku_stream_destroy(cubeb_stream * stm);
+static int haiku_stream_init(cubeb * context, cubeb_stream ** stream,
+ char const * stream_name,
+ cubeb_devid input_device,
+ cubeb_stream_params * input_stream_params,
+ cubeb_devid output_device,
+ cubeb_stream_params * output_stream_params,
+ unsigned int latency, cubeb_data_callback data_callback,
+ cubeb_state_callback state_callback, void * user_ptr);
+static int haiku_stream_start(cubeb_stream * stm);
+static int haiku_stream_stop(cubeb_stream * stm);
+static int haiku_stream_get_position(cubeb_stream * stm, uint64_t * position);
+static int haiku_stream_get_latency(cubeb_stream * stm, uint32_t * latency);
+static int haiku_enumerate_devices(cubeb *context, cubeb_device_type type,
+ cubeb_device_collection *collection);
+static int haiku_device_collection_destroy(cubeb * context,
+ cubeb_device_collection * collection);
+static int haiku_stream_set_volume(cubeb_stream * stm, float volume);
+
+struct cubeb_stream_item {
+ cubeb_stream * stream;
+};
+
+static struct cubeb_ops const haiku_ops = {
+ /*.init =*/ haiku_init,
+ /*.get_backend_id =*/ haiku_get_backend_id,
+ /*.get_max_channel_count=*/ haiku_get_max_channel_count,
+ /*.get_min_latency=*/ haiku_get_min_latency,
+ /*.get_preferred_sample_rate =*/ haiku_get_preferred_sample_rate,
+ /*.enumerate_devices =*/ haiku_enumerate_devices,
+ /*.device_collection_destroy =*/ haiku_device_collection_destroy,
+ /*.destroy =*/ haiku_destroy,
+ /*.stream_init =*/ haiku_stream_init,
+ /*.stream_destroy =*/ haiku_stream_destroy,
+ /*.stream_start =*/ haiku_stream_start,
+ /*.stream_stop =*/ haiku_stream_stop,
+ /*.stream_reset_default_device =*/ NULL,
+ /*.stream_get_position =*/ haiku_stream_get_position,
+ /*.stream_get_latency = */ haiku_stream_get_latency,
+ /*.stream_get_input_latency = */ NULL,
+ /*.stream_set_volume =*/ haiku_stream_set_volume,
+ /*.stream_set_name =*/ NULL,
+ /*.stream_get_current_device =*/ NULL,
+ /*.stream_device_destroy =*/ NULL,
+ /*.stream_register_device_changed_callback=*/ NULL,
+ /*.register_device_collection_changed=*/ NULL
+};
+
+struct cubeb {
+ struct cubeb_ops const * ops;
+};
+
+struct cubeb_stream {
+ cubeb * context;
+ cubeb_stream_params params;
+ cubeb_data_callback data_callback;
+ cubeb_state_callback state_callback;
+ void * user_ptr;
+
+ BSoundPlayer *player;
+ uint64_t total_frames;
+ float float_buffer[FRAME_SIZE * MAX_CHANNELS];
+};
+
+int
+haiku_init(cubeb ** context, char const * context_name)
+{
+ cubeb * ctx;
+
+ XASSERT(context);
+ *context = NULL;
+
+ ctx = (cubeb*)calloc(1, sizeof(*ctx));
+ XASSERT(ctx);
+
+ ctx->ops = &haiku_ops;
+
+ *context = ctx;
+
+ return CUBEB_OK;
+}
+
+static char const *
+haiku_get_backend_id(cubeb * ctx)
+{
+ return "haiku";
+}
+
+static void
+haiku_destroy(cubeb * ctx)
+{
+ free(ctx);
+}
+
+static void
+haiku_callback(void *cookie, void *buffer, size_t len, const media_raw_audio_format &format)
+{
+ cubeb_stream * stm = (cubeb_stream*)cookie;
+ int framesize = stm->params.format == CUBEB_SAMPLE_FLOAT32NE ? sizeof(float) : sizeof(int16_t);
+ long wanted_frames = len / framesize / stm->params.channels;
+ long frames = stm->data_callback(stm, stm->user_ptr, NULL, buffer, wanted_frames);
+
+ stm->total_frames += frames;
+
+ if (frames < wanted_frames)
+ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
+}
+
+static int
+haiku_stream_init(cubeb * context, cubeb_stream ** stream,
+ char const * stream_name,
+ cubeb_devid input_device,
+ cubeb_stream_params * input_stream_params,
+ cubeb_devid output_device,
+ cubeb_stream_params * output_stream_params,
+ unsigned int latency, cubeb_data_callback data_callback,
+ cubeb_state_callback state_callback, void * user_ptr)
+{
+ cubeb_stream * stm;
+
+ if (input_device || output_device)
+ return CUBEB_ERROR_DEVICE_UNAVAILABLE;
+
+ if (output_stream_params
+ && (output_stream_params->format != CUBEB_SAMPLE_FLOAT32NE &&
+ output_stream_params->format != CUBEB_SAMPLE_S16NE)
+ ) {
+ return CUBEB_ERROR_INVALID_FORMAT;
+ }
+
+ if (output_stream_params->channels < 1 ||
+ output_stream_params->channels > MAX_CHANNELS)
+ return CUBEB_ERROR_INVALID_FORMAT;
+
+ XASSERT(context);
+ XASSERT(stream);
+
+ *stream = NULL;
+
+ stm = (cubeb_stream*)calloc(1, sizeof(*stm));
+ XASSERT(stm);
+
+ stm->context = context;
+ stm->params = *output_stream_params;
+ stm->data_callback = data_callback;
+ stm->state_callback = state_callback;
+ stm->user_ptr = user_ptr;
+
+ int framesize = output_stream_params->format == CUBEB_SAMPLE_FLOAT32NE ? sizeof(float) : sizeof(int16_t);
+
+ media_raw_audio_format mediaKitFormat = {
+ (float)stm->params.rate,
+ (uint32)stm->params.channels,
+ framesize == sizeof(float) ? (media_raw_audio_format::B_AUDIO_FLOAT) : (media_raw_audio_format::B_AUDIO_SHORT),
+ B_MEDIA_LITTLE_ENDIAN,
+ (uint32)(FRAME_SIZE * framesize * output_stream_params->channels)
+ };
+
+ stm->player = new BSoundPlayer(&mediaKitFormat, "cubeb", haiku_callback, NULL, (void*)stm);
+
+ if(stm->player->InitCheck() != B_OK) {
+ delete stm->player;
+ free(stm);
+ return CUBEB_ERROR;
+ }
+
+ *stream = stm;
+
+ return CUBEB_OK;
+}
+
+static void
+haiku_stream_destroy(cubeb_stream * stm)
+{
+ stm->player->Stop();
+ stm->player->SetHasData(false);
+
+ delete stm->player;
+ free(stm);
+}
+
+static int
+haiku_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
+{
+ XASSERT(ctx && max_channels);
+ *max_channels = MAX_CHANNELS;
+ return CUBEB_OK;
+}
+
+static int
+haiku_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency)
+{
+ *latency = FRAME_SIZE;
+ return CUBEB_OK;
+}
+
+static int
+haiku_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
+{
+ *rate = DEFAULT_RATE;
+ return CUBEB_OK;
+}
+
+static int
+haiku_enumerate_devices(cubeb *context, cubeb_device_type type,
+ cubeb_device_collection *collection)
+{
+ static char dev[] = "MediaKit";
+ static char vendor[] = "Haiku";
+ cubeb_device_info *device;
+
+ device = (cubeb_device_info*)malloc(sizeof(cubeb_device_info));
+ if (device == NULL)
+ return CUBEB_ERROR;
+
+ device->devid = dev;
+ device->device_id = dev;
+ device->friendly_name = dev;
+ device->group_id = dev;
+ device->vendor_name = vendor;
+ device->type = type;
+ device->state = CUBEB_DEVICE_STATE_ENABLED;
+ device->preferred = CUBEB_DEVICE_PREF_ALL;
+ device->format = CUBEB_DEVICE_FMT_S16NE;
+ device->default_format = CUBEB_DEVICE_FMT_S16NE;
+ device->max_channels = MAX_CHANNELS;
+ device->default_rate = DEFAULT_RATE;
+ device->min_rate = 4000;
+ device->max_rate = 192000;
+ device->latency_lo = 480;
+ device->latency_hi = 9600;
+ collection->device = device;
+ collection->count = 1;
+ return CUBEB_OK;
+}
+
+static int
+haiku_device_collection_destroy(cubeb * context,
+ cubeb_device_collection * collection)
+{
+ free(collection->device);
+ return CUBEB_OK;
+}
+
+static int
+haiku_stream_start(cubeb_stream * stm)
+{
+ stm->player->Start();
+ stm->player->SetHasData(true);
+
+ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
+
+ return CUBEB_OK;
+}
+
+static int
+haiku_stream_stop(cubeb_stream * stm)
+{
+ stm->player->Stop();
+ stm->player->SetHasData(false);
+
+ stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
+
+ return CUBEB_OK;
+}
+
+static int
+haiku_stream_get_position(cubeb_stream * stm, uint64_t * position)
+{
+ *position = stm->total_frames;
+ return CUBEB_OK;
+}
+
+static int
+haiku_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
+{
+ *latency = stm->player->Latency();
+ return CUBEB_OK;
+}
+
+static int
+haiku_stream_set_volume(cubeb_stream * stm, float volume)
+{
+ float dbMin = -40;
+ float dbMax = 18;
+ float logBase = 10;
+ float dbVol = log((volume * (logBase - 1)) / 2) / log(logBase) * (dbMax - dbMin) + dbMin;
+ stm->player->SetVolumeDB(dbVol);
+ return CUBEB_OK;
+}
+
--
2.28.0
From 2439418440412340f6a5e249b201b53798662461 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sat, 26 Dec 2020 16:08:46 +1000
Subject: Enable Haiku backend
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f037cf5..5bd31a1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -268,6 +268,14 @@ if(USE_KAI)
target_link_libraries(cubeb PRIVATE kai)
endif()
+check_include_files(os/media/MediaDefs.h USE_HAIKU)
+if(USE_HAIKU)
+ target_sources(cubeb PRIVATE
+ src/cubeb_haiku.cpp)
+ target_compile_definitions(cubeb PRIVATE USE_HAIKU)
+ target_link_libraries(cubeb PRIVATE media)
+endif()
+
if(USE_PULSE AND USE_PULSE_RUST)
include(ExternalProject)
set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/rust)
diff --git a/src/cubeb.c b/src/cubeb.c
index 8757440..bba1256 100644
--- a/src/cubeb.c
+++ b/src/cubeb.c
@@ -72,6 +72,9 @@ int audiotrack_init(cubeb ** context, char const * context_name);
#if defined(USE_KAI)
int kai_init(cubeb ** context, char const * context_name);
#endif
+#if defined(USE_HAIKU)
+int haiku_init(cubeb ** context, char const * context_name);
+#endif
static int
validate_stream_params(cubeb_stream_params * input_stream_params,
@@ -187,6 +190,10 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam
} else if (!strcmp(backend_name, "kai")) {
#if defined(USE_KAI)
init_oneshot = kai_init;
+#endif
+ } else if (!strcmp(backend_name, "haiku")) {
+#if defined(USE_HAIKU)
+ init_oneshot = haiku_init;
#endif
} else {
/* Already set */
@@ -245,6 +252,9 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam
#endif
#if defined(USE_KAI)
kai_init,
+#endif
+#if defined(USE_HAIKU)
+ haiku_init,
#endif
};
int i;
--
2.28.0