mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #6132 from ligfx/updatecubeb
Externals: update cubeb to kinetiknz/cubeb@c2bd582
This commit is contained in:
Vendored
+45
-4
@@ -43,9 +43,11 @@ add_library(cubeb
|
||||
src/cubeb_resampler.cpp
|
||||
src/cubeb_panner.cpp
|
||||
src/cubeb_log.cpp
|
||||
src/cubeb_utils.c
|
||||
src/cubeb_strings.c
|
||||
$<TARGET_OBJECTS:speex>)
|
||||
target_include_directories(cubeb PUBLIC include)
|
||||
target_include_directories(cubeb
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>
|
||||
)
|
||||
target_include_directories(cubeb PRIVATE src)
|
||||
target_compile_definitions(cubeb PRIVATE OUTSIDE_SPEEX)
|
||||
target_compile_definitions(cubeb PRIVATE FLOATING_POINT)
|
||||
@@ -56,7 +58,42 @@ add_sanitizers(cubeb)
|
||||
|
||||
include(GenerateExportHeader)
|
||||
generate_export_header(cubeb EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/exports/cubeb_export.h)
|
||||
target_include_directories(cubeb PUBLIC ${CMAKE_BINARY_DIR}/exports)
|
||||
target_include_directories(cubeb
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/exports>
|
||||
)
|
||||
|
||||
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
install(DIRECTORY ${CMAKE_BINARY_DIR}/exports/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/cubeb)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
configure_package_config_file(
|
||||
"Config.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION "lib/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
install(TARGETS cubeb
|
||||
EXPORT "${PROJECT_NAME}Targets"
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||
LIBRARY DESTINATION "lib"
|
||||
ARCHIVE DESTINATION "lib"
|
||||
RUNTIME DESTINATION "bin"
|
||||
INCLUDES DESTINATION "include"
|
||||
)
|
||||
install(
|
||||
FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
DESTINATION "lib/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
install(
|
||||
EXPORT "${PROJECT_NAME}Targets"
|
||||
NAMESPACE "${PROJECT_NAME}::"
|
||||
DESTINATION "lib/cmake/${PROJECT_NAME}"
|
||||
)
|
||||
|
||||
add_library(speex OBJECT
|
||||
src/speex/resample.c)
|
||||
@@ -82,6 +119,7 @@ if(USE_PULSE)
|
||||
target_sources(cubeb PRIVATE
|
||||
src/cubeb_pulse.c)
|
||||
target_compile_definitions(cubeb PRIVATE USE_PULSE)
|
||||
target_link_libraries(cubeb PRIVATE pulse)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
target_link_libraries(cubeb PRIVATE dl)
|
||||
endif()
|
||||
@@ -93,6 +131,9 @@ if(USE_ALSA)
|
||||
src/cubeb_alsa.c)
|
||||
target_compile_definitions(cubeb PRIVATE USE_ALSA)
|
||||
target_link_libraries(cubeb PRIVATE asound pthread)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
target_link_libraries(cubeb PRIVATE dl)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_include_files(jack/jack.h USE_JACK)
|
||||
@@ -100,10 +141,10 @@ if(USE_JACK)
|
||||
target_sources(cubeb PRIVATE
|
||||
src/cubeb_jack.cpp)
|
||||
target_compile_definitions(cubeb PRIVATE USE_JACK)
|
||||
target_link_libraries(cubeb PRIVATE jack pthread)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
target_link_libraries(cubeb PRIVATE dl)
|
||||
endif()
|
||||
target_link_libraries(cubeb PRIVATE pthread)
|
||||
endif()
|
||||
|
||||
check_include_files(audioclient.h USE_WASAPI)
|
||||
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/cubebTargets.cmake")
|
||||
check_required_components(cubeb)
|
||||
+22
-39
@@ -33,11 +33,11 @@ extern "C" {
|
||||
cubeb * app_ctx;
|
||||
cubeb_init(&app_ctx, "Example Application");
|
||||
int rv;
|
||||
int rate;
|
||||
int latency_frames;
|
||||
uint32_t rate;
|
||||
uint32_t latency_frames;
|
||||
uint64_t ts;
|
||||
|
||||
rv = cubeb_get_min_latency(app_ctx, output_params, &latency_frames);
|
||||
rv = cubeb_get_min_latency(app_ctx, &output_params, &latency_frames);
|
||||
if (rv != CUBEB_OK) {
|
||||
fprintf(stderr, "Could not get minimum latency");
|
||||
return rv;
|
||||
@@ -144,28 +144,6 @@ typedef enum {
|
||||
#endif
|
||||
} cubeb_sample_format;
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
/**
|
||||
* This maps to the underlying stream types on supported platforms, e.g.
|
||||
* Android.
|
||||
*/
|
||||
typedef enum {
|
||||
CUBEB_STREAM_TYPE_VOICE_CALL = 0,
|
||||
CUBEB_STREAM_TYPE_SYSTEM = 1,
|
||||
CUBEB_STREAM_TYPE_RING = 2,
|
||||
CUBEB_STREAM_TYPE_MUSIC = 3,
|
||||
CUBEB_STREAM_TYPE_ALARM = 4,
|
||||
CUBEB_STREAM_TYPE_NOTIFICATION = 5,
|
||||
CUBEB_STREAM_TYPE_BLUETOOTH_SCO = 6,
|
||||
CUBEB_STREAM_TYPE_SYSTEM_ENFORCED = 7,
|
||||
CUBEB_STREAM_TYPE_DTMF = 8,
|
||||
CUBEB_STREAM_TYPE_TTS = 9,
|
||||
CUBEB_STREAM_TYPE_FM = 10,
|
||||
|
||||
CUBEB_STREAM_TYPE_MAX
|
||||
} cubeb_stream_type;
|
||||
#endif
|
||||
|
||||
/** An opaque handle used to refer a particular input or output device
|
||||
* across calls. */
|
||||
typedef void const * cubeb_devid;
|
||||
@@ -239,12 +217,9 @@ typedef enum {
|
||||
typedef struct {
|
||||
cubeb_sample_format format; /**< Requested sample format. One of
|
||||
#cubeb_sample_format. */
|
||||
unsigned int rate; /**< Requested sample rate. Valid range is [1000, 192000]. */
|
||||
unsigned int channels; /**< Requested channel count. Valid range is [1, 8]. */
|
||||
uint32_t rate; /**< Requested sample rate. Valid range is [1000, 192000]. */
|
||||
uint32_t channels; /**< Requested channel count. Valid range is [1, 8]. */
|
||||
cubeb_channel_layout layout; /**< Requested channel layout. This must be consistent with the provided channels. */
|
||||
#if defined(__ANDROID__)
|
||||
cubeb_stream_type stream_type; /**< Used to map Android audio stream types */
|
||||
#endif
|
||||
} cubeb_stream_params;
|
||||
|
||||
/** Audio device description */
|
||||
@@ -348,13 +323,13 @@ typedef struct {
|
||||
|
||||
cubeb_device_fmt format; /**< Sample format supported. */
|
||||
cubeb_device_fmt default_format; /**< The default sample format for this device. */
|
||||
unsigned int max_channels; /**< Channels. */
|
||||
unsigned int default_rate; /**< Default/Preferred sample rate. */
|
||||
unsigned int max_rate; /**< Maximum sample rate supported. */
|
||||
unsigned int min_rate; /**< Minimum sample rate supported. */
|
||||
uint32_t max_channels; /**< Channels. */
|
||||
uint32_t default_rate; /**< Default/Preferred sample rate. */
|
||||
uint32_t max_rate; /**< Maximum sample rate supported. */
|
||||
uint32_t min_rate; /**< Minimum sample rate supported. */
|
||||
|
||||
unsigned int latency_lo; /**< Lowest possible latency in frames. */
|
||||
unsigned int latency_hi; /**< Higest possible latency in frames. */
|
||||
uint32_t latency_lo; /**< Lowest possible latency in frames. */
|
||||
uint32_t latency_hi; /**< Higest possible latency in frames. */
|
||||
} cubeb_device_info;
|
||||
|
||||
/** Device collection.
|
||||
@@ -405,7 +380,7 @@ typedef void (* cubeb_device_changed_callback)(void * user_ptr);
|
||||
/**
|
||||
* User supplied callback called when the underlying device collection changed.
|
||||
* @param context A pointer to the cubeb context.
|
||||
* @param user_ptr The pointer passed to cubeb_stream_init. */
|
||||
* @param user_ptr The pointer passed to cubeb_register_device_collection_changed. */
|
||||
typedef void (* cubeb_device_collection_changed_callback)(cubeb * context,
|
||||
void * user_ptr);
|
||||
|
||||
@@ -455,7 +430,7 @@ CUBEB_EXPORT int cubeb_get_max_channel_count(cubeb * context, uint32_t * max_cha
|
||||
@retval CUBEB_ERROR_INVALID_PARAMETER
|
||||
@retval CUBEB_ERROR_NOT_SUPPORTED */
|
||||
CUBEB_EXPORT int cubeb_get_min_latency(cubeb * context,
|
||||
cubeb_stream_params params,
|
||||
cubeb_stream_params * params,
|
||||
uint32_t * latency_frames);
|
||||
|
||||
/** Get the preferred sample rate for this backend: this is hardware and
|
||||
@@ -512,7 +487,7 @@ CUBEB_EXPORT int cubeb_stream_init(cubeb * context,
|
||||
cubeb_stream_params * input_stream_params,
|
||||
cubeb_devid output_device,
|
||||
cubeb_stream_params * output_stream_params,
|
||||
unsigned int latency_frames,
|
||||
uint32_t latency_frames,
|
||||
cubeb_data_callback data_callback,
|
||||
cubeb_state_callback state_callback,
|
||||
void * user_ptr);
|
||||
@@ -534,6 +509,14 @@ CUBEB_EXPORT int cubeb_stream_start(cubeb_stream * stream);
|
||||
@retval CUBEB_ERROR */
|
||||
CUBEB_EXPORT int cubeb_stream_stop(cubeb_stream * stream);
|
||||
|
||||
/** Reset stream to the default device.
|
||||
@param stream
|
||||
@retval CUBEB_OK
|
||||
@retval CUBEB_ERROR_INVALID_PARAMETER
|
||||
@retval CUBEB_ERROR_NOT_SUPPORTED
|
||||
@retval CUBEB_ERROR */
|
||||
CUBEB_EXPORT int cubeb_stream_reset_default_device(cubeb_stream * stream);
|
||||
|
||||
/** Get the current stream playback position.
|
||||
@param stream
|
||||
@param position Playback position in frames.
|
||||
|
||||
Vendored
+2
-1
@@ -57,6 +57,7 @@
|
||||
<ClInclude Include="..\src\cubeb_resampler_internal.h" />
|
||||
<ClInclude Include="..\src\cubeb_ringbuffer.h" />
|
||||
<ClInclude Include="..\src\cubeb_ring_array.h" />
|
||||
<ClInclude Include="..\src\cubeb_strings.h" />
|
||||
<ClInclude Include="..\src\cubeb_utils.h" />
|
||||
<ClInclude Include="..\src\cubeb_utils_unix.h" />
|
||||
<ClInclude Include="..\src\cubeb_utils_win.h" />
|
||||
@@ -74,7 +75,7 @@
|
||||
<ClCompile Include="..\src\cubeb_mixer.cpp" />
|
||||
<ClCompile Include="..\src\cubeb_panner.cpp" />
|
||||
<ClCompile Include="..\src\cubeb_resampler.cpp" />
|
||||
<ClCompile Include="..\src\cubeb_utils.c" />
|
||||
<ClCompile Include="..\src\cubeb_strings.c" />
|
||||
<ClCompile Include="..\src\cubeb_wasapi.cpp" />
|
||||
<ClCompile Include="..\src\cubeb_winmm.c" />
|
||||
<ClCompile Include="..\src\speex\resample.c" />
|
||||
|
||||
+3
-2
@@ -11,6 +11,7 @@
|
||||
<ClInclude Include="..\src\cubeb_resampler_internal.h" />
|
||||
<ClInclude Include="..\src\cubeb_ring_array.h" />
|
||||
<ClInclude Include="..\src\cubeb_ringbuffer.h" />
|
||||
<ClInclude Include="..\src\cubeb_strings.h" />
|
||||
<ClInclude Include="..\src\cubeb_utils.h" />
|
||||
<ClInclude Include="..\src\cubeb_utils_unix.h" />
|
||||
<ClInclude Include="..\src\cubeb_utils_win.h" />
|
||||
@@ -45,7 +46,7 @@
|
||||
<ClCompile Include="..\src\cubeb_mixer.cpp" />
|
||||
<ClCompile Include="..\src\cubeb_panner.cpp" />
|
||||
<ClCompile Include="..\src\cubeb_resampler.cpp" />
|
||||
<ClCompile Include="..\src\cubeb_utils.c" />
|
||||
<ClCompile Include="..\src\cubeb_strings.c" />
|
||||
<ClCompile Include="..\src\cubeb_wasapi.cpp" />
|
||||
<ClCompile Include="..\src\cubeb_winmm.c" />
|
||||
<ClCompile Include="..\src\speex\resample.c">
|
||||
@@ -57,4 +58,4 @@
|
||||
<UniqueIdentifier>{caf7c7d0-0918-4299-8423-b287285d6fd0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
Vendored
+1
@@ -69,6 +69,7 @@ struct cubeb_ops {
|
||||
void (* stream_destroy)(cubeb_stream * stream);
|
||||
int (* stream_start)(cubeb_stream * stream);
|
||||
int (* stream_stop)(cubeb_stream * stream);
|
||||
int (* stream_reset_default_device)(cubeb_stream * stream);
|
||||
int (* stream_get_position)(cubeb_stream * stream, uint64_t * position);
|
||||
int (* stream_get_latency)(cubeb_stream * stream, uint32_t * latency);
|
||||
int (* stream_set_volume)(cubeb_stream * stream, float volumes);
|
||||
|
||||
Vendored
+29
-4
@@ -245,9 +245,9 @@ cubeb_get_max_channel_count(cubeb * context, uint32_t * max_channels)
|
||||
}
|
||||
|
||||
int
|
||||
cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * latency_ms)
|
||||
cubeb_get_min_latency(cubeb * context, cubeb_stream_params * params, uint32_t * latency_ms)
|
||||
{
|
||||
if (!context || !latency_ms) {
|
||||
if (!context || !params || !latency_ms) {
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * la
|
||||
return CUBEB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return context->ops->get_min_latency(context, params, latency_ms);
|
||||
return context->ops->get_min_latency(context, *params, latency_ms);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -368,6 +368,20 @@ cubeb_stream_stop(cubeb_stream * stream)
|
||||
return stream->context->ops->stream_stop(stream);
|
||||
}
|
||||
|
||||
int
|
||||
cubeb_stream_reset_default_device(cubeb_stream * stream)
|
||||
{
|
||||
if (!stream) {
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!stream->context->ops->stream_reset_default_device) {
|
||||
return CUBEB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return stream->context->ops->stream_reset_default_device(stream);
|
||||
}
|
||||
|
||||
int
|
||||
cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position)
|
||||
{
|
||||
@@ -574,13 +588,24 @@ int cubeb_enumerate_devices(cubeb * context,
|
||||
int cubeb_device_collection_destroy(cubeb * context,
|
||||
cubeb_device_collection * collection)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (context == NULL || collection == NULL)
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (!context->ops->device_collection_destroy)
|
||||
return CUBEB_ERROR_NOT_SUPPORTED;
|
||||
|
||||
return context->ops->device_collection_destroy(context, collection);
|
||||
if (!collection->device)
|
||||
return CUBEB_OK;
|
||||
|
||||
r = context->ops->device_collection_destroy(context, collection);
|
||||
if (r == CUBEB_OK) {
|
||||
collection->device = NULL;
|
||||
collection->count = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int cubeb_register_device_collection_changed(cubeb * context,
|
||||
|
||||
Vendored
+1
-1
@@ -17,7 +17,6 @@
|
||||
#include <alsa/asoundlib.h>
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "cubeb-internal.h"
|
||||
#include "cubeb_utils.h"
|
||||
|
||||
#define CUBEB_STREAM_MAX 16
|
||||
#define CUBEB_WATCHDOG_MS 10000
|
||||
@@ -1361,6 +1360,7 @@ static struct cubeb_ops const alsa_ops = {
|
||||
.stream_destroy = alsa_stream_destroy,
|
||||
.stream_start = alsa_stream_start,
|
||||
.stream_stop = alsa_stream_stop,
|
||||
.stream_reset_default_device = NULL,
|
||||
.stream_get_position = alsa_stream_get_position,
|
||||
.stream_get_latency = alsa_stream_get_latency,
|
||||
.stream_set_volume = alsa_stream_set_volume,
|
||||
|
||||
+4
-3
@@ -145,9 +145,9 @@ audiotrack_get_min_frame_count(cubeb * ctx, cubeb_stream_params * params, int *
|
||||
status_t status;
|
||||
/* Recent Android have a getMinFrameCount method. */
|
||||
if (!audiotrack_version_is_gingerbread(ctx)) {
|
||||
status = ctx->klass.get_min_frame_count(min_frame_count, params->stream_type, params->rate);
|
||||
status = ctx->klass.get_min_frame_count(min_frame_count, AUDIO_STREAM_TYPE_MUSIC, params->rate);
|
||||
} else {
|
||||
status = ctx->klass.get_min_frame_count_gingerbread(min_frame_count, params->stream_type, params->rate);
|
||||
status = ctx->klass.get_min_frame_count_gingerbread(min_frame_count, AUDIO_STREAM_TYPE_MUSIC, params->rate);
|
||||
}
|
||||
if (status != 0) {
|
||||
ALOG("error getting the min frame count");
|
||||
@@ -325,7 +325,7 @@ audiotrack_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_
|
||||
channels = stm->params.channels == 2 ? AUDIO_CHANNEL_OUT_STEREO_ICS : AUDIO_CHANNEL_OUT_MONO_ICS;
|
||||
}
|
||||
|
||||
ctx->klass.ctor(stm->instance, stm->params.stream_type, stm->params.rate,
|
||||
ctx->klass.ctor(stm->instance, AUDIO_STREAM_TYPE_MUSIC, stm->params.rate,
|
||||
AUDIO_FORMAT_PCM_16_BIT, channels, min_frame_count, 0,
|
||||
audiotrack_refill, stm, 0, 0);
|
||||
|
||||
@@ -429,6 +429,7 @@ static struct cubeb_ops const audiotrack_ops = {
|
||||
.stream_destroy = audiotrack_stream_destroy,
|
||||
.stream_start = audiotrack_stream_start,
|
||||
.stream_stop = audiotrack_stream_stop,
|
||||
.stream_reset_default_device = NULL,
|
||||
.stream_get_position = audiotrack_stream_get_position,
|
||||
.stream_get_latency = audiotrack_stream_get_latency,
|
||||
.stream_set_volume = audiotrack_stream_set_volume,
|
||||
|
||||
+309
-292
File diff suppressed because it is too large
Load Diff
Vendored
+27
-12
@@ -96,6 +96,8 @@ static int cbjack_stream_device_destroy(cubeb_stream * stream,
|
||||
static int cbjack_stream_get_current_device(cubeb_stream * stm, cubeb_device ** const device);
|
||||
static int cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
cubeb_device_collection * collection);
|
||||
static int cbjack_device_collection_destroy(cubeb * context,
|
||||
cubeb_device_collection * collection);
|
||||
static int cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name,
|
||||
cubeb_devid input_device,
|
||||
cubeb_stream_params * input_stream_params,
|
||||
@@ -119,12 +121,13 @@ static struct cubeb_ops const cbjack_ops = {
|
||||
.get_preferred_sample_rate = cbjack_get_preferred_sample_rate,
|
||||
.get_preferred_channel_layout = NULL,
|
||||
.enumerate_devices = cbjack_enumerate_devices,
|
||||
.device_collection_destroy = cubeb_utils_default_device_collection_destroy,
|
||||
.device_collection_destroy = cbjack_device_collection_destroy,
|
||||
.destroy = cbjack_destroy,
|
||||
.stream_init = cbjack_stream_init,
|
||||
.stream_destroy = cbjack_stream_destroy,
|
||||
.stream_start = cbjack_stream_start,
|
||||
.stream_stop = cbjack_stream_stop,
|
||||
.stream_reset_default_device = NULL,
|
||||
.stream_get_position = cbjack_stream_get_position,
|
||||
.stream_get_latency = cbjack_get_latency,
|
||||
.stream_set_volume = cbjack_stream_set_volume,
|
||||
@@ -973,6 +976,9 @@ cbjack_stream_device_destroy(cubeb_stream * /*stream*/,
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
#define JACK_DEFAULT_IN "JACK capture"
|
||||
#define JACK_DEFAULT_OUT "JACK playback"
|
||||
|
||||
static int
|
||||
cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
cubeb_device_collection * collection)
|
||||
@@ -982,20 +988,20 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
|
||||
uint32_t rate;
|
||||
cbjack_get_preferred_sample_rate(context, &rate);
|
||||
const char * j_in = "JACK capture";
|
||||
const char * j_out = "JACK playback";
|
||||
|
||||
cubeb_device_info * devices = new cubeb_device_info[2];
|
||||
reinterpret_cast<cubeb_device_info *>(calloc(2, sizeof(cubeb_device_info)));
|
||||
if (!devices)
|
||||
return CUBEB_ERROR;
|
||||
PodZero(devices, 2);
|
||||
collection->count = 0;
|
||||
|
||||
if (type & CUBEB_DEVICE_TYPE_OUTPUT) {
|
||||
cubeb_device_info * cur = &devices[collection->count];
|
||||
cur->device_id = strdup(j_out);
|
||||
cur->device_id = JACK_DEFAULT_OUT;
|
||||
cur->devid = (cubeb_devid) cur->device_id;
|
||||
cur->friendly_name = strdup(j_out);
|
||||
cur->group_id = strdup(j_out);
|
||||
cur->vendor_name = strdup(j_out);
|
||||
cur->friendly_name = JACK_DEFAULT_OUT;
|
||||
cur->group_id = JACK_DEFAULT_OUT;
|
||||
cur->vendor_name = JACK_DEFAULT_OUT;
|
||||
cur->type = CUBEB_DEVICE_TYPE_OUTPUT;
|
||||
cur->state = CUBEB_DEVICE_STATE_ENABLED;
|
||||
cur->preferred = CUBEB_DEVICE_PREF_ALL;
|
||||
@@ -1012,11 +1018,11 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
|
||||
if (type & CUBEB_DEVICE_TYPE_INPUT) {
|
||||
cubeb_device_info * cur = &devices[collection->count];
|
||||
cur->device_id = strdup(j_in);
|
||||
cur->device_id = JACK_DEFAULT_IN;
|
||||
cur->devid = (cubeb_devid) cur->device_id;
|
||||
cur->friendly_name = strdup(j_in);
|
||||
cur->group_id = strdup(j_in);
|
||||
cur->vendor_name = strdup(j_in);
|
||||
cur->friendly_name = JACK_DEFAULT_IN;
|
||||
cur->group_id = JACK_DEFAULT_IN;
|
||||
cur->vendor_name = JACK_DEFAULT_IN;
|
||||
cur->type = CUBEB_DEVICE_TYPE_INPUT;
|
||||
cur->state = CUBEB_DEVICE_STATE_ENABLED;
|
||||
cur->preferred = CUBEB_DEVICE_PREF_ALL;
|
||||
@@ -1035,3 +1041,12 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
cbjack_device_collection_destroy(cubeb * /*ctx*/,
|
||||
cubeb_device_collection * collection)
|
||||
{
|
||||
XASSERT(collection);
|
||||
delete [] collection->device;
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
Vendored
+1
@@ -351,6 +351,7 @@ static struct cubeb_ops const kai_ops = {
|
||||
/*.stream_destroy =*/ kai_stream_destroy,
|
||||
/*.stream_start =*/ kai_stream_start,
|
||||
/*.stream_stop =*/ kai_stream_stop,
|
||||
/*.stream_reset_default_device =*/ NULL,
|
||||
/*.stream_get_position =*/ kai_stream_get_position,
|
||||
/*.stream_get_latency = */ kai_stream_get_latency,
|
||||
/*.stream_set_volume =*/ kai_stream_set_volume,
|
||||
|
||||
Vendored
+14
@@ -95,6 +95,12 @@ public:
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
// Tell the underlying queue the producer thread has changed, so it does not
|
||||
// assert in debug. This should be called with the thread stopped.
|
||||
void reset_producer_thread()
|
||||
{
|
||||
msg_queue.reset_thread_ids();
|
||||
}
|
||||
private:
|
||||
#ifndef _WIN32
|
||||
const struct timespec sleep_for = {
|
||||
@@ -128,3 +134,11 @@ void cubeb_async_log(char const * fmt, ...)
|
||||
cubeb_async_logger::get().push(msg);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void cubeb_async_log_reset_threads()
|
||||
{
|
||||
if (!g_cubeb_log_callback) {
|
||||
return;
|
||||
}
|
||||
cubeb_async_logger::get().reset_producer_thread();
|
||||
}
|
||||
|
||||
Vendored
+1
@@ -23,6 +23,7 @@ extern "C" {
|
||||
extern cubeb_log_level g_cubeb_log_level;
|
||||
extern cubeb_log_callback g_cubeb_log_callback PRINTF_FORMAT(1, 2);
|
||||
void cubeb_async_log(const char * fmt, ...);
|
||||
void cubeb_async_log_reset_threads();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Vendored
+12
-10
@@ -299,7 +299,7 @@ mix_remap(long inframes,
|
||||
T * out, unsigned long out_len,
|
||||
cubeb_channel_layout in_layout, cubeb_channel_layout out_layout)
|
||||
{
|
||||
assert(in_layout != out_layout);
|
||||
assert(in_layout != out_layout && inframes >= 0);
|
||||
|
||||
// We might overwrite the data before we copied them to the mapped index
|
||||
// (e.g. upmixing from stereo to 2F1 or mapping [L, R] to [R, L])
|
||||
@@ -325,15 +325,16 @@ mix_remap(long inframes,
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned long i = 0, out_index = 0; i < inframes * in_channels; i += in_channels, out_index += out_channels) {
|
||||
for (unsigned long i = 0, out_index = 0; i < (unsigned long)inframes * in_channels; i += in_channels, out_index += out_channels) {
|
||||
for (unsigned int j = 0; j < out_channels; ++j) {
|
||||
cubeb_channel channel = CHANNEL_INDEX_TO_ORDER[out_layout][j];
|
||||
uint32_t channel_mask = 1 << channel;
|
||||
int channel_index = CHANNEL_ORDER_TO_INDEX[in_layout][channel];
|
||||
assert(channel_index >= -1);
|
||||
assert(out_index + j < out_len);
|
||||
if (in_layout_mask & channel_mask) {
|
||||
assert(i + channel_index < in_len);
|
||||
assert(channel_index != -1);
|
||||
assert(i + channel_index < in_len);
|
||||
out[out_index + j] = in[i + channel_index];
|
||||
} else {
|
||||
assert(channel_index == -1);
|
||||
@@ -353,13 +354,13 @@ downmix_fallback(long inframes,
|
||||
T * out, unsigned long out_len,
|
||||
unsigned int in_channels, unsigned int out_channels)
|
||||
{
|
||||
assert(in_channels >= out_channels);
|
||||
assert(in_channels >= out_channels && inframes >= 0);
|
||||
|
||||
if (in_channels == out_channels && in == out) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned long i = 0, out_index = 0; i < inframes * in_channels; i += in_channels, out_index += out_channels) {
|
||||
for (unsigned long i = 0, out_index = 0; i < (unsigned long)inframes * in_channels; i += in_channels, out_index += out_channels) {
|
||||
for (unsigned int j = 0; j < out_channels; ++j) {
|
||||
assert(i + j < in_len && out_index + j < out_len);
|
||||
out[out_index + j] = in[i + j];
|
||||
@@ -416,7 +417,7 @@ mono_to_stereo(long insamples, T const * in, unsigned long in_len,
|
||||
T * out, unsigned long out_len, unsigned int out_channels)
|
||||
{
|
||||
for (long i = 0, j = 0; i < insamples; ++i, j += out_channels) {
|
||||
assert(i < in_len && j + 1 < out_len);
|
||||
assert((unsigned long)i < in_len && (unsigned long)j + 1 < out_len);
|
||||
out[j] = out[j + 1] = in[i];
|
||||
}
|
||||
}
|
||||
@@ -460,7 +461,7 @@ cubeb_upmix(long inframes,
|
||||
/* Put silence in remaining channels. */
|
||||
for (long i = 0, o = 0; i < inframes; ++i, o += out_channels) {
|
||||
for (unsigned int j = 2; j < out_channels; ++j) {
|
||||
assert(o + j < out_len);
|
||||
assert((unsigned long)o + j < out_len);
|
||||
out[o + j] = 0.0;
|
||||
}
|
||||
}
|
||||
@@ -490,7 +491,8 @@ cubeb_should_downmix(cubeb_stream_params const * stream, cubeb_stream_params con
|
||||
bool
|
||||
cubeb_should_mix(cubeb_stream_params const * stream, cubeb_stream_params const * mixer)
|
||||
{
|
||||
return cubeb_should_upmix(stream, mixer) || cubeb_should_downmix(stream, mixer);
|
||||
return stream->layout != CUBEB_LAYOUT_UNDEFINED &&
|
||||
(cubeb_should_upmix(stream, mixer) || cubeb_should_downmix(stream, mixer));
|
||||
}
|
||||
|
||||
struct cubeb_mixer {
|
||||
@@ -559,11 +561,11 @@ void cubeb_mixer_destroy(cubeb_mixer * mixer)
|
||||
|
||||
void cubeb_mixer_mix(cubeb_mixer * mixer, long frames,
|
||||
void * input_buffer, unsigned long input_buffer_length,
|
||||
void * output_buffer, unsigned long outputput_buffer_length,
|
||||
void * output_buffer, unsigned long output_buffer_length,
|
||||
cubeb_stream_params const * stream_params,
|
||||
cubeb_stream_params const * mixer_params)
|
||||
{
|
||||
assert(mixer);
|
||||
mixer->mix(frames, input_buffer, input_buffer_length, output_buffer, outputput_buffer_length,
|
||||
mixer->mix(frames, input_buffer, input_buffer_length, output_buffer, output_buffer_length,
|
||||
stream_params, mixer_params);
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -79,7 +79,7 @@ cubeb_mixer * cubeb_mixer_create(cubeb_sample_format format,
|
||||
void cubeb_mixer_destroy(cubeb_mixer * mixer);
|
||||
void cubeb_mixer_mix(cubeb_mixer * mixer, long frames,
|
||||
void * input_buffer, unsigned long input_buffer_length,
|
||||
void * output_buffer, unsigned long outputput_buffer_length,
|
||||
void * output_buffer, unsigned long output_buffer_length,
|
||||
cubeb_stream_params const * stream_params,
|
||||
cubeb_stream_params const * mixer_params);
|
||||
|
||||
|
||||
Vendored
+38
-74
@@ -105,7 +105,6 @@ struct cubeb_stream {
|
||||
/* Flag indicating draining. Synchronized
|
||||
* by stream::mutex lock. */
|
||||
int draining;
|
||||
cubeb_stream_type stream_type;
|
||||
/* Flags to determine in/out.*/
|
||||
uint32_t input_enabled;
|
||||
uint32_t output_enabled;
|
||||
@@ -187,6 +186,29 @@ opensl_set_draining(cubeb_stream * stm, int value)
|
||||
stm->draining = value;
|
||||
}
|
||||
|
||||
static void
|
||||
opensl_notify_drained(cubeb_stream * stm)
|
||||
{
|
||||
assert(stm);
|
||||
int r = pthread_mutex_lock(&stm->mutex);
|
||||
assert(r == 0);
|
||||
int draining = opensl_get_draining(stm);
|
||||
r = pthread_mutex_unlock(&stm->mutex);
|
||||
assert(r == 0);
|
||||
if (draining) {
|
||||
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
|
||||
if (stm->play) {
|
||||
LOG("stop player in play_callback");
|
||||
r = opensl_stop_player(stm);
|
||||
assert(r == CUBEB_OK);
|
||||
}
|
||||
if (stm->recorderItf) {
|
||||
r = opensl_stop_recorder(stm);
|
||||
assert(r == CUBEB_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
opensl_get_shutdown(cubeb_stream * stm)
|
||||
{
|
||||
@@ -217,24 +239,7 @@ play_callback(SLPlayItf caller, void * user_ptr, SLuint32 event)
|
||||
assert(stm);
|
||||
switch (event) {
|
||||
case SL_PLAYEVENT_HEADATMARKER:
|
||||
{
|
||||
int r = pthread_mutex_lock(&stm->mutex);
|
||||
assert(r == 0);
|
||||
draining = opensl_get_draining(stm);
|
||||
r = pthread_mutex_unlock(&stm->mutex);
|
||||
assert(r == 0);
|
||||
if (draining) {
|
||||
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
|
||||
if (stm->play) {
|
||||
r = opensl_stop_player(stm);
|
||||
assert(r == CUBEB_OK);
|
||||
}
|
||||
if (stm->recorderItf) {
|
||||
r = opensl_stop_recorder(stm);
|
||||
assert(r == CUBEB_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
opensl_notify_drained(stm);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -330,9 +335,16 @@ bufferqueue_callback(SLBufferQueueItf caller, void * user_ptr)
|
||||
opensl_set_draining(stm, 1);
|
||||
r = pthread_mutex_unlock(&stm->mutex);
|
||||
assert(r == 0);
|
||||
// Use SL_PLAYEVENT_HEADATMARKER event from slPlayCallback of SLPlayItf
|
||||
// to make sure all the data has been processed.
|
||||
(*stm->play)->SetMarkerPosition(stm->play, (SLmillisecond)written_duration);
|
||||
|
||||
if (written_duration == 0) {
|
||||
// since we didn't write any sample, it's not possible to reach the marker
|
||||
// time and trigger the callback. We should initiative notify drained.
|
||||
opensl_notify_drained(stm);
|
||||
} else {
|
||||
// Use SL_PLAYEVENT_HEADATMARKER event from slPlayCallback of SLPlayItf
|
||||
// to make sure all the data has been processed.
|
||||
(*stm->play)->SetMarkerPosition(stm->play, (SLmillisecond)written_duration);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -586,31 +598,6 @@ player_fullduplex_callback(SLBufferQueueItf caller, void * user_ptr)
|
||||
TIMESTAMP("EXIT");
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
static SLuint32
|
||||
convert_stream_type_to_sl_stream(cubeb_stream_type stream_type)
|
||||
{
|
||||
switch(stream_type) {
|
||||
case CUBEB_STREAM_TYPE_SYSTEM:
|
||||
return SL_ANDROID_STREAM_SYSTEM;
|
||||
case CUBEB_STREAM_TYPE_MUSIC:
|
||||
return SL_ANDROID_STREAM_MEDIA;
|
||||
case CUBEB_STREAM_TYPE_NOTIFICATION:
|
||||
return SL_ANDROID_STREAM_NOTIFICATION;
|
||||
case CUBEB_STREAM_TYPE_ALARM:
|
||||
return SL_ANDROID_STREAM_ALARM;
|
||||
case CUBEB_STREAM_TYPE_VOICE_CALL:
|
||||
return SL_ANDROID_STREAM_VOICE;
|
||||
case CUBEB_STREAM_TYPE_RING:
|
||||
return SL_ANDROID_STREAM_RING;
|
||||
case CUBEB_STREAM_TYPE_SYSTEM_ENFORCED:
|
||||
return SL_ANDROID_STREAM_SYSTEM_ENFORCED;
|
||||
default:
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void opensl_destroy(cubeb * ctx);
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
@@ -899,7 +886,7 @@ opensl_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
|
||||
if (get_primary_output_frame_count) {
|
||||
primary_buffer_size = get_primary_output_frame_count();
|
||||
} else {
|
||||
if (get_output_frame_count(&primary_buffer_size, params.stream_type) != 0) {
|
||||
if (get_output_frame_count(&primary_buffer_size, AUDIO_STREAM_TYPE_MUSIC) != 0) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -1127,7 +1114,6 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) {
|
||||
assert(params);
|
||||
|
||||
stm->inputrate = params->rate;
|
||||
stm->stream_type = params->stream_type;
|
||||
stm->framesize = params->channels * sizeof(int16_t);
|
||||
stm->lastPosition = -1;
|
||||
stm->lastPositionTimeStamp = 0;
|
||||
@@ -1228,29 +1214,6 @@ opensl_configure_playback(cubeb_stream * stm, cubeb_stream_params * params) {
|
||||
assert(stm->queuebuf[i]);
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
SLuint32 stream_type = convert_stream_type_to_sl_stream(params->stream_type);
|
||||
if (stream_type != 0xFFFFFFFF) {
|
||||
SLAndroidConfigurationItf playerConfig;
|
||||
res = (*stm->playerObj)->GetInterface(stm->playerObj,
|
||||
stm->context->SL_IID_ANDROIDCONFIGURATION,
|
||||
&playerConfig);
|
||||
if (res != SL_RESULT_SUCCESS) {
|
||||
LOG("Failed to get android configuration interface. Error code: %lu", res);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
res = (*playerConfig)->SetConfiguration(playerConfig,
|
||||
SL_ANDROID_KEY_STREAM_TYPE,
|
||||
&stream_type,
|
||||
sizeof(SLint32));
|
||||
if (res != SL_RESULT_SUCCESS) {
|
||||
LOG("Failed to set android configuration interface. Error code: %lu", res);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
res = (*stm->playerObj)->Realize(stm->playerObj, SL_BOOLEAN_FALSE);
|
||||
if (res != SL_RESULT_SUCCESS) {
|
||||
LOG("Failed to realize player object. Error code: %lu", res);
|
||||
@@ -1654,7 +1617,7 @@ opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
|
||||
|
||||
samplerate = stm->inputrate;
|
||||
|
||||
r = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
|
||||
r = stm->context->get_output_latency(&mixer_latency, AUDIO_STREAM_TYPE_MUSIC);
|
||||
if (r) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
@@ -1690,7 +1653,7 @@ opensl_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
||||
uint32_t mixer_latency; // The latency returned by AudioFlinger is in ms.
|
||||
|
||||
/* audio_stream_type_t is an int, so this is okay. */
|
||||
r = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
|
||||
r = stm->context->get_output_latency(&mixer_latency, AUDIO_STREAM_TYPE_MUSIC);
|
||||
if (r) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
@@ -1746,6 +1709,7 @@ static struct cubeb_ops const opensl_ops = {
|
||||
.stream_destroy = opensl_stream_destroy,
|
||||
.stream_start = opensl_stream_start,
|
||||
.stream_stop = opensl_stream_stop,
|
||||
.stream_reset_default_device = NULL,
|
||||
.stream_get_position = opensl_stream_get_position,
|
||||
.stream_get_latency = opensl_stream_get_latency,
|
||||
.stream_set_volume = opensl_stream_set_volume,
|
||||
|
||||
Vendored
+95
-20
@@ -13,7 +13,7 @@
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "cubeb-internal.h"
|
||||
#include "cubeb_mixer.h"
|
||||
#include "cubeb_utils.h"
|
||||
#include "cubeb_strings.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef DISABLE_LIBPULSE_DLOPEN
|
||||
@@ -102,6 +102,7 @@ struct cubeb {
|
||||
int error;
|
||||
cubeb_device_collection_changed_callback collection_changed_callback;
|
||||
void * collection_changed_user_ptr;
|
||||
cubeb_strings * device_ids;
|
||||
};
|
||||
|
||||
struct cubeb_stream {
|
||||
@@ -127,6 +128,24 @@ enum cork_state {
|
||||
NOTIFY = 1 << 1
|
||||
};
|
||||
|
||||
static int
|
||||
intern_device_id(cubeb * ctx, char const ** id)
|
||||
{
|
||||
char const * interned;
|
||||
|
||||
assert(ctx);
|
||||
assert(id);
|
||||
|
||||
interned = cubeb_strings_intern(ctx->device_ids, *id);
|
||||
if (!interned) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
*id = interned;
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
sink_info_callback(pa_context * context, const pa_sink_info * info, int eol, void * u)
|
||||
{
|
||||
@@ -608,6 +627,10 @@ pulse_init(cubeb ** context, char const * context_name)
|
||||
|
||||
ctx->ops = &pulse_ops;
|
||||
ctx->libpulse = libpulse;
|
||||
if (cubeb_strings_init(&ctx->device_ids) != CUBEB_OK) {
|
||||
pulse_destroy(ctx);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
ctx->mainloop = WRAP(pa_threaded_mainloop_new)();
|
||||
ctx->default_sink_info = NULL;
|
||||
@@ -630,7 +653,6 @@ pulse_init(cubeb ** context, char const * context_name)
|
||||
WRAP(pa_operation_unref)(o);
|
||||
}
|
||||
WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);
|
||||
assert(ctx->default_sink_info);
|
||||
|
||||
*context = ctx;
|
||||
|
||||
@@ -650,6 +672,9 @@ pulse_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
|
||||
(void)ctx;
|
||||
assert(ctx && max_channels);
|
||||
|
||||
if (!ctx->default_sink_info)
|
||||
return CUBEB_ERROR;
|
||||
|
||||
*max_channels = ctx->default_sink_info->channel_map.channels;
|
||||
|
||||
return CUBEB_OK;
|
||||
@@ -661,6 +686,9 @@ pulse_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
|
||||
assert(ctx && rate);
|
||||
(void)ctx;
|
||||
|
||||
if (!ctx->default_sink_info)
|
||||
return CUBEB_ERROR;
|
||||
|
||||
*rate = ctx->default_sink_info->sample_spec.rate;
|
||||
|
||||
return CUBEB_OK;
|
||||
@@ -672,6 +700,9 @@ pulse_get_preferred_channel_layout(cubeb * ctx, cubeb_channel_layout * layout)
|
||||
assert(ctx && layout);
|
||||
(void)ctx;
|
||||
|
||||
if (!ctx->default_sink_info)
|
||||
return CUBEB_ERROR;
|
||||
|
||||
*layout = channel_map_to_layout(&ctx->default_sink_info->channel_map);
|
||||
|
||||
return CUBEB_OK;
|
||||
@@ -717,6 +748,10 @@ pulse_destroy(cubeb * ctx)
|
||||
WRAP(pa_threaded_mainloop_free)(ctx->mainloop);
|
||||
}
|
||||
|
||||
if (ctx->device_ids) {
|
||||
cubeb_strings_destroy(ctx->device_ids);
|
||||
}
|
||||
|
||||
if (ctx->libpulse) {
|
||||
dlclose(ctx->libpulse);
|
||||
}
|
||||
@@ -751,8 +786,9 @@ create_pa_stream(cubeb_stream * stm,
|
||||
{
|
||||
assert(stm && stream_params);
|
||||
assert(&stm->input_stream == pa_stm || (&stm->output_stream == pa_stm &&
|
||||
stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
|
||||
CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].channels == stream_params->channels));
|
||||
(stream_params->layout == CUBEB_LAYOUT_UNDEFINED ||
|
||||
(stream_params->layout != CUBEB_LAYOUT_UNDEFINED &&
|
||||
CUBEB_CHANNEL_LAYOUT_MAPS[stream_params->layout].channels == stream_params->channels))));
|
||||
*pa_stm = NULL;
|
||||
pa_sample_spec ss;
|
||||
ss.format = to_pulse_format(stream_params->format);
|
||||
@@ -1049,6 +1085,7 @@ pulse_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
pa_volume_t vol;
|
||||
pa_cvolume cvol;
|
||||
const pa_sample_spec * ss;
|
||||
cubeb * ctx;
|
||||
|
||||
if (!stm->output_stream) {
|
||||
return CUBEB_ERROR;
|
||||
@@ -1058,7 +1095,9 @@ pulse_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
|
||||
/* if the pulse daemon is configured to use flat volumes,
|
||||
* apply our own gain instead of changing the input volume on the sink. */
|
||||
if (stm->context->default_sink_info->flags & PA_SINK_FLAT_VOLUME) {
|
||||
ctx = stm->context;
|
||||
if (ctx->default_sink_info &&
|
||||
(ctx->default_sink_info->flags & PA_SINK_FLAT_VOLUME)) {
|
||||
stm->volume = volume;
|
||||
} else {
|
||||
ss = WRAP(pa_stream_get_sample_spec)(stm->output_stream);
|
||||
@@ -1068,16 +1107,16 @@ pulse_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
|
||||
index = WRAP(pa_stream_get_index)(stm->output_stream);
|
||||
|
||||
op = WRAP(pa_context_set_sink_input_volume)(stm->context->context,
|
||||
op = WRAP(pa_context_set_sink_input_volume)(ctx->context,
|
||||
index, &cvol, volume_success,
|
||||
stm);
|
||||
if (op) {
|
||||
operation_wait(stm->context, stm->output_stream, op);
|
||||
operation_wait(ctx, stm->output_stream, op);
|
||||
WRAP(pa_operation_unref)(op);
|
||||
}
|
||||
}
|
||||
|
||||
WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
|
||||
WRAP(pa_threaded_mainloop_unlock)(ctx->mainloop);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
@@ -1202,18 +1241,30 @@ pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
|
||||
{
|
||||
pulse_dev_list_data * list_data = user_data;
|
||||
cubeb_device_info * devinfo;
|
||||
const char * prop;
|
||||
char const * prop = NULL;
|
||||
char const * device_id = NULL;
|
||||
|
||||
(void)context;
|
||||
|
||||
if (eol || info == NULL)
|
||||
if (eol) {
|
||||
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
device_id = info->name;
|
||||
if (intern_device_id(list_data->context, &device_id) != CUBEB_OK) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
pulse_ensure_dev_list_data_list_size(list_data);
|
||||
devinfo = &list_data->devinfo[list_data->count];
|
||||
memset(devinfo, 0, sizeof(cubeb_device_info));
|
||||
|
||||
devinfo->device_id = strdup(info->name);
|
||||
devinfo->device_id = device_id;
|
||||
devinfo->devid = (cubeb_devid) devinfo->device_id;
|
||||
devinfo->friendly_name = strdup(info->description);
|
||||
prop = WRAP(pa_proplist_gets)(info->proplist, "sysfs.path");
|
||||
@@ -1239,8 +1290,6 @@ pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
|
||||
devinfo->latency_hi = 0;
|
||||
|
||||
list_data->count += 1;
|
||||
|
||||
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
|
||||
}
|
||||
|
||||
static cubeb_device_state
|
||||
@@ -1264,18 +1313,27 @@ pulse_source_info_cb(pa_context * context, const pa_source_info * info,
|
||||
{
|
||||
pulse_dev_list_data * list_data = user_data;
|
||||
cubeb_device_info * devinfo;
|
||||
const char * prop;
|
||||
char const * prop = NULL;
|
||||
char const * device_id = NULL;
|
||||
|
||||
(void)context;
|
||||
|
||||
if (eol)
|
||||
if (eol) {
|
||||
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
device_id = info->name;
|
||||
if (intern_device_id(list_data->context, &device_id) != CUBEB_OK) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
pulse_ensure_dev_list_data_list_size(list_data);
|
||||
devinfo = &list_data->devinfo[list_data->count];
|
||||
memset(devinfo, 0, sizeof(cubeb_device_info));
|
||||
|
||||
devinfo->device_id = strdup(info->name);
|
||||
devinfo->device_id = device_id;
|
||||
devinfo->devid = (cubeb_devid) devinfo->device_id;
|
||||
devinfo->friendly_name = strdup(info->description);
|
||||
prop = WRAP(pa_proplist_gets)(info->proplist, "sysfs.path");
|
||||
@@ -1301,7 +1359,6 @@ pulse_source_info_cb(pa_context * context, const pa_source_info * info,
|
||||
devinfo->latency_hi = 0;
|
||||
|
||||
list_data->count += 1;
|
||||
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1313,8 +1370,10 @@ pulse_server_info_cb(pa_context * c, const pa_server_info * i, void * userdata)
|
||||
|
||||
free(list_data->default_sink_name);
|
||||
free(list_data->default_source_name);
|
||||
list_data->default_sink_name = strdup(i->default_sink_name);
|
||||
list_data->default_source_name = strdup(i->default_source_name);
|
||||
list_data->default_sink_name =
|
||||
i->default_sink_name ? strdup(i->default_sink_name) : NULL;
|
||||
list_data->default_source_name =
|
||||
i->default_source_name ? strdup(i->default_source_name) : NULL;
|
||||
|
||||
WRAP(pa_threaded_mainloop_signal)(list_data->context->mainloop, 0);
|
||||
}
|
||||
@@ -1363,6 +1422,21 @@ pulse_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
pulse_device_collection_destroy(cubeb * ctx, cubeb_device_collection * collection)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
for (n = 0; n < collection->count; n++) {
|
||||
free((void *) collection->device[n].friendly_name);
|
||||
free((void *) collection->device[n].vendor_name);
|
||||
free((void *) collection->device[n].group_id);
|
||||
}
|
||||
|
||||
free(collection->device);
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
pulse_stream_get_current_device(cubeb_stream * stm, cubeb_device ** const device)
|
||||
{
|
||||
@@ -1492,12 +1566,13 @@ static struct cubeb_ops const pulse_ops = {
|
||||
.get_preferred_sample_rate = pulse_get_preferred_sample_rate,
|
||||
.get_preferred_channel_layout = pulse_get_preferred_channel_layout,
|
||||
.enumerate_devices = pulse_enumerate_devices,
|
||||
.device_collection_destroy = cubeb_utils_default_device_collection_destroy,
|
||||
.device_collection_destroy = pulse_device_collection_destroy,
|
||||
.destroy = pulse_destroy,
|
||||
.stream_init = pulse_stream_init,
|
||||
.stream_destroy = pulse_stream_destroy,
|
||||
.stream_start = pulse_stream_start,
|
||||
.stream_stop = pulse_stream_stop,
|
||||
.stream_reset_default_device = NULL,
|
||||
.stream_get_position = pulse_stream_get_position,
|
||||
.stream_get_latency = pulse_stream_get_latency,
|
||||
.stream_set_volume = pulse_stream_set_volume,
|
||||
|
||||
+16
-2
@@ -35,15 +35,22 @@ to_speex_quality(cubeb_resampler_quality q)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t min_buffered_audio_frame(uint32_t sample_rate)
|
||||
{
|
||||
return sample_rate / 20;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
passthrough_resampler<T>::passthrough_resampler(cubeb_stream * s,
|
||||
cubeb_data_callback cb,
|
||||
void * ptr,
|
||||
uint32_t input_channels)
|
||||
uint32_t input_channels,
|
||||
uint32_t sample_rate)
|
||||
: processor(input_channels)
|
||||
, stream(s)
|
||||
, data_callback(cb)
|
||||
, user_ptr(ptr)
|
||||
, sample_rate(sample_rate)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -73,6 +80,7 @@ long passthrough_resampler<T>::fill(void * input_buffer, long * input_frames_cou
|
||||
if (input_buffer) {
|
||||
internal_input_buffer.pop(nullptr, frames_to_samples(output_frames));
|
||||
*input_frames_count = output_frames;
|
||||
drop_audio_if_needed();
|
||||
}
|
||||
|
||||
return rv;
|
||||
@@ -242,9 +250,15 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
|
||||
|
||||
output_processor->written(got);
|
||||
|
||||
input_processor->drop_audio_if_needed();
|
||||
|
||||
/* Process the output. If not enough frames have been returned from the
|
||||
* callback, drain the processors. */
|
||||
return output_processor->output(out_buffer, output_frames_needed);
|
||||
got = output_processor->output(out_buffer, output_frames_needed);
|
||||
|
||||
output_processor->drop_audio_if_needed();
|
||||
|
||||
return got;
|
||||
}
|
||||
|
||||
/* Resampler C API */
|
||||
|
||||
+51
-6
@@ -39,6 +39,13 @@ MOZ_END_STD_NAMESPACE
|
||||
|
||||
/* This header file contains the internal C++ API of the resamplers, for testing. */
|
||||
|
||||
// When dropping audio input frames to prevent building
|
||||
// an input delay, this function returns the number of frames
|
||||
// to keep in the buffer.
|
||||
// @parameter sample_rate The sample rate of the stream.
|
||||
// @return A number of frames to keep.
|
||||
uint32_t min_buffered_audio_frame(uint32_t sample_rate);
|
||||
|
||||
int to_speex_quality(cubeb_resampler_quality q);
|
||||
|
||||
struct cubeb_resampler {
|
||||
@@ -75,7 +82,8 @@ public:
|
||||
passthrough_resampler(cubeb_stream * s,
|
||||
cubeb_data_callback cb,
|
||||
void * ptr,
|
||||
uint32_t input_channels);
|
||||
uint32_t input_channels,
|
||||
uint32_t sample_rate);
|
||||
|
||||
virtual long fill(void * input_buffer, long * input_frames_count,
|
||||
void * output_buffer, long output_frames);
|
||||
@@ -85,6 +93,15 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drop_audio_if_needed()
|
||||
{
|
||||
uint32_t to_keep = min_buffered_audio_frame(sample_rate);
|
||||
uint32_t available = samples_to_frames(internal_input_buffer.length());
|
||||
if (available > to_keep) {
|
||||
internal_input_buffer.pop(nullptr, frames_to_samples(available - to_keep));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
cubeb_stream * const stream;
|
||||
const cubeb_data_callback data_callback;
|
||||
@@ -92,6 +109,7 @@ private:
|
||||
/* This allows to buffer some input to account for the fact that we buffer
|
||||
* some inputs. */
|
||||
auto_array<T> internal_input_buffer;
|
||||
uint32_t sample_rate;
|
||||
};
|
||||
|
||||
/** Bidirectional resampler, can resample an input and an output stream, or just
|
||||
@@ -164,6 +182,7 @@ public:
|
||||
int quality)
|
||||
: processor(channels)
|
||||
, resampling_ratio(static_cast<float>(source_rate) / target_rate)
|
||||
, source_rate(source_rate)
|
||||
, additional_latency(0)
|
||||
, leftover_samples(0)
|
||||
{
|
||||
@@ -296,6 +315,16 @@ public:
|
||||
resampling_in_buffer.set_length(leftover_samples +
|
||||
frames_to_samples(written_frames));
|
||||
}
|
||||
|
||||
void drop_audio_if_needed()
|
||||
{
|
||||
// Keep at most 100ms buffered.
|
||||
uint32_t available = samples_to_frames(resampling_in_buffer.length());
|
||||
uint32_t to_keep = min_buffered_audio_frame(source_rate);
|
||||
if (available > to_keep) {
|
||||
resampling_in_buffer.pop(nullptr, frames_to_samples(available - to_keep));
|
||||
}
|
||||
}
|
||||
private:
|
||||
/** Wrapper for the speex resampling functions to have a typed
|
||||
* interface. */
|
||||
@@ -332,6 +361,7 @@ private:
|
||||
SpeexResamplerState * speex_resampler;
|
||||
/** Source rate / target rate. */
|
||||
const float resampling_ratio;
|
||||
const uint32_t source_rate;
|
||||
/** Storage for the input frames, to be resampled. Also contains
|
||||
* any unresampled frames after resampling. */
|
||||
auto_array<T> resampling_in_buffer;
|
||||
@@ -350,11 +380,13 @@ class delay_line : public processor {
|
||||
public:
|
||||
/** Constructor
|
||||
* @parameter frames the number of frames of delay.
|
||||
* @parameter channels the number of channels of this delay line. */
|
||||
delay_line(uint32_t frames, uint32_t channels)
|
||||
* @parameter channels the number of channels of this delay line.
|
||||
* @parameter sample_rate sample-rate of the audio going through this delay line */
|
||||
delay_line(uint32_t frames, uint32_t channels, uint32_t sample_rate)
|
||||
: processor(channels)
|
||||
, length(frames)
|
||||
, leftover_samples(0)
|
||||
, sample_rate(sample_rate)
|
||||
{
|
||||
/* Fill the delay line with some silent frames to add latency. */
|
||||
delay_input_buffer.push_silence(frames * channels);
|
||||
@@ -444,6 +476,15 @@ public:
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
void drop_audio_if_needed()
|
||||
{
|
||||
size_t available = samples_to_frames(delay_input_buffer.length());
|
||||
uint32_t to_keep = min_buffered_audio_frame(sample_rate);
|
||||
if (available > to_keep) {
|
||||
delay_input_buffer.pop(nullptr, frames_to_samples(available - to_keep));
|
||||
}
|
||||
}
|
||||
private:
|
||||
/** The length, in frames, of this delay line */
|
||||
uint32_t length;
|
||||
@@ -455,6 +496,7 @@ private:
|
||||
/** The output buffer. This is only ever used if using the ::output with a
|
||||
* single argument. */
|
||||
auto_array<T> delay_output_buffer;
|
||||
uint32_t sample_rate;
|
||||
};
|
||||
|
||||
/** This sits behind the C API and is more typed. */
|
||||
@@ -485,7 +527,8 @@ cubeb_resampler_create_internal(cubeb_stream * stream,
|
||||
(output_params && !input_params && (output_params->rate == target_rate))) {
|
||||
return new passthrough_resampler<T>(stream, callback,
|
||||
user_ptr,
|
||||
input_params ? input_params->channels : 0);
|
||||
input_params ? input_params->channels : 0,
|
||||
target_rate);
|
||||
}
|
||||
|
||||
/* Determine if we need to resampler one or both directions, and create the
|
||||
@@ -517,13 +560,15 @@ cubeb_resampler_create_internal(cubeb_stream * stream,
|
||||
* other direction so that the streams are synchronized. */
|
||||
if (input_resampler && !output_resampler && input_params && output_params) {
|
||||
output_delay.reset(new delay_line<T>(input_resampler->latency(),
|
||||
output_params->channels));
|
||||
output_params->channels,
|
||||
output_params->rate));
|
||||
if (!output_delay) {
|
||||
return NULL;
|
||||
}
|
||||
} else if (output_resampler && !input_resampler && input_params && output_params) {
|
||||
input_delay.reset(new delay_line<T>(output_resampler->latency(),
|
||||
input_params->channels));
|
||||
input_params->channels,
|
||||
output_params->rate));
|
||||
if (!input_delay) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user