No backends support this yet.
This commit is contained in:
Haakon Sporsheim 2015-09-09 10:07:45 +02:00
Родитель 8d27b7e03b
Коммит 65fee6d192
16 изменённых файлов: 452 добавлений и 4 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -45,6 +45,8 @@ test/test_sanity
test/test_sanity.exe
test/test_tone
test/test_tone.exe
test/test_devices
test/test_devices.exe
include/cubeb/cubeb-stdint.h
test-suite.log
test/test_sanity.log

Просмотреть файл

@ -64,17 +64,23 @@ src_libcubeb_la_SOURCES += src/cubeb_resampler.cpp src/speex/resample.c
endif
EXTRA_src_libcubeb_la_SOURCES = \
src/cubeb.c \
src/cubeb.c \
src/cubeb_jack.cpp \
src/cubeb_alsa.c src/cubeb_pulse.c \
src/cubeb_audiounit.c src/cubeb_audioqueue.c \
src/cubeb_sndio.c src/cubeb_directsound.cpp \
src/cubeb_winmm.c src/cubeb_wasapi.cpp src/speex/resample.c \
src/cubeb_opensl.c src/cubeb_audiotrack.c
src/cubeb_opensl.c src/cubeb_audiotrack.c \
$(NULL)
src_libcubeb_la_LDFLAGS = -export-symbols-regex '^cubeb_' $(platform_lib) -no-undefined
check_PROGRAMS = test/test_sanity test/test_tone test/test_audio test/test_latency
check_PROGRAMS = test/test_sanity \
test/test_tone \
test/test_audio \
test/test_latency \
test/test_devices \
$(NULL)
test_test_sanity_SOURCES = test/test_sanity.cpp
test_test_sanity_LDADD = -lm src/libcubeb.la $(platform_lib)
@ -88,6 +94,9 @@ test_test_audio_LDADD = -lm src/libcubeb.la $(platform_lib)
test_test_latency_SOURCES = test/test_latency.cpp
test_test_latency_LDADD = -lm src/libcubeb.la $(platform_lib)
test_test_devices_SOURCES = test/test_devices.cpp
test_test_devices_LDADD = -lm src/libcubeb.la $(platform_lib)
TESTS = test/test_sanity
DISTCLEANFILES = include/cubeb/cubeb-stdint.h

Просмотреть файл

@ -152,6 +152,74 @@ enum {
CUBEB_ERROR_NOT_SUPPORTED = -4 /**< Optional function not implemented in current backend. */
};
typedef enum {
CUBEB_DEVICE_TYPE_UNKNOWN,
CUBEB_DEVICE_TYPE_INPUT,
CUBEB_DEVICE_TYPE_OUTPUT
} cubeb_device_type;
typedef enum {
CUBEB_DEVICE_STATE_DISABLED,
CUBEB_DEVICE_STATE_UNPLUGGED,
CUBEB_DEVICE_STATE_ENABLED
} cubeb_device_state;
typedef void * cubeb_devid;
typedef enum {
CUBEB_DEVICE_FMT_S16LE = 0x0010,
CUBEB_DEVICE_FMT_S16BE = 0x0020,
CUBEB_DEVICE_FMT_F32LE = 0x1000,
CUBEB_DEVICE_FMT_F32BE = 0x2000
} cubeb_device_fmt;
#if defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__)
#define CUBEB_DEVICE_FMT_S16NE CUBEB_DEVICE_FMT_S16BE
#define CUBEB_DEVICE_FMT_F32NE CUBEB_DEVICE_FMT_F32BE
#else
#define CUBEB_DEVICE_FMT_S16NE CUBEB_DEVICE_FMT_S16LE
#define CUBEB_DEVICE_FMT_F32NE CUBEB_DEVICE_FMT_F32LE
#endif
#define CUBEB_DEVICE_FMT_S16_MASK (CUBEB_DEVICE_FMT_S16LE | CUBEB_DEVICE_FMT_S16BE)
#define CUBEB_DEVICE_FMT_F32_MASK (CUBEB_DEVICE_FMT_F32LE | CUBEB_DEVICE_FMT_F32BE)
#define CUBEB_DEVICE_FMT_ALL (CUBEB_DEVICE_FMT_S16_MASK | CUBEB_DEVICE_FMT_F32_MASK)
typedef enum {
CUBEB_DEVICE_PREF_NONE = 0x00,
CUBEB_DEVICE_PREF_MULTIMEDIA = 0x01,
CUBEB_DEVICE_PREF_VOICE = 0x02,
CUBEB_DEVICE_PREF_NOTIFICATION = 0x04,
CUBEB_DEVICE_PREF_ALL = 0x0F
} cubeb_device_pref;
typedef struct {
cubeb_devid device_id; /* Device identifier */
char * friendly_name; /* Friendly device name which might be presented in a UI */
char * group_id; /* Two devices have the same group identifier if they belong to the same physical device; for example a headset and microphone. */
char * vendor_name; /* Optional vendor name, may be NULL */
cubeb_device_type type; /* Type of device (Input/Output) */
cubeb_device_state state; /* State of device disabled/enabled/unplugged */
cubeb_device_pref preferred;/* Preferred device */
cubeb_device_fmt format; /* Sample format supported */
cubeb_device_fmt default_format;
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 */
unsigned int latency_lo_ms; /* Lowest possible latency in milliseconds */
unsigned int latency_hi_ms; /* Higest possible latency in milliseconds */
} cubeb_device_info;
typedef struct _cubeb_device_entry cubeb_device_entry;
struct _cubeb_device_entry {
cubeb_device_info device;
cubeb_device_entry * next;
};
typedef struct _cubeb_device_entry cubeb_device_list;
/** User supplied data callback.
@param stream
@param user_ptr
@ -179,6 +247,12 @@ typedef void (* cubeb_state_callback)(cubeb_stream * stream,
* @param user */
typedef void (* cubeb_device_changed_callback)(void * user_ptr);
/**
* User supplied callback called when the underlying device list changed.
* @param context
* @param user_ptr */
typedef void (* cubeb_device_list_changed_callback)(cubeb * context, void * user_ptr);
/** Initialize an application context. This will perform any library or
application scoped initialization.
@param context
@ -337,6 +411,52 @@ int cubeb_stream_device_destroy(cubeb_stream * stream,
int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
cubeb_device_changed_callback device_changed_callback);
/** Returns enumerated devices.
@param context
@param devtype device type to include
@param list output list. Must be destroyed with cubeb_device_list_destroy
@param count optional parameter which will return number of devices in list
@retval CUBEB_OK in case of success
@retval CUBEB_ERROR_INVALID_PARAMETER if list is an invalid pointer
@retval CUBEB_ERROR_NOT_SUPPORTED */
int cubeb_enumerate_devices(cubeb * context,
cubeb_device_type devtype,
cubeb_device_list ** list,
uint32_t * count);
/** Destroy a cubeb_device_list list.
The whole list is destroyed.
@param context
@param list list to destroy
@retval CUBEB_OK */
int cubeb_device_list_destroy(cubeb * context, cubeb_device_list * list);
/** Retrieves the device id as string.
The string must be free()ed by the caller.
@param context
@param devid device id
@param str pointer to string
@retval CUBEB_OK */
int cubeb_device_id_to_str(cubeb * context, const cubeb_devid devid, char ** str);
/** Registers a callback which is called when device list changes..
@param context
@param callback
@param user_ptr
@retval CUBEB_ERROR_NOT_SUPPORTED */
int cubeb_register_device_list_changed(cubeb * context,
cubeb_device_list_changed_callback callback,
void * user_ptr);
/** Removes a already registered callback/user_ptr pair.
@param context
@param callback
@param user_ptr
@retval CUBEB_ERROR_NOT_SUPPORTED */
int cubeb_deregister_device_list_changed(cubeb * context,
cubeb_device_list_changed_callback callback,
void * user_ptr);
#if defined(__cplusplus)
}
#endif

Просмотреть файл

@ -8,6 +8,8 @@
#define CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5
#include "cubeb/cubeb.h"
#include <stdio.h>
#include <string.h>
struct cubeb_ops {
int (* init)(cubeb ** context, char const * context_name);
@ -17,6 +19,10 @@ struct cubeb_ops {
cubeb_stream_params params,
uint32_t * latency_ms);
int (* get_preferred_sample_rate)(cubeb * context, uint32_t * rate);
int (* enumerate_devices)(cubeb * context, cubeb_device_type type,
cubeb_device_list ** devices, uint32_t * count);
int (* device_info_destroy)(cubeb * context, cubeb_device_info * info);
int (* device_id_to_str)(cubeb * context, const cubeb_devid devid, char ** str);
void (* destroy)(cubeb * context);
int (* stream_init)(cubeb * context, cubeb_stream ** stream, char const * stream_name,
cubeb_stream_params stream_params, unsigned int latency,
@ -36,7 +42,6 @@ struct cubeb_ops {
cubeb_device * device);
int (* stream_register_device_changed_callback)(cubeb_stream * stream,
cubeb_device_changed_callback device_changed_callback);
};
#define XASSERT(expr) do { \
@ -47,4 +52,50 @@ struct cubeb_ops {
} \
} while (0)
static inline int
cubeb_device_info_destroy (cubeb * context, cubeb_device_info * info)
{
free(info->device_id);
free(info->friendly_name);
free(info->group_id);
free(info->vendor_name);
return CUBEB_OK;
}
static inline int
cubeb_device_info_destroy_no_devid (cubeb * context, cubeb_device_info * info)
{
free(info->friendly_name);
free(info->group_id);
free(info->vendor_name);
return CUBEB_OK;
}
static inline int
cubeb_device_id_str (cubeb * context, cubeb_devid devid, char ** str)
{
size_t size = strlen((const char *)devid);
*str = (char *)malloc(size + 1);
strncpy(*str, (const char *)devid, size);
return CUBEB_OK;
}
static inline int
cubeb_device_id_idx (cubeb * context, cubeb_devid devid, char ** str)
{
*str = (char *)malloc(sizeof(char)*16);
snprintf(*str, 16, "%u", (unsigned int)(size_t)devid);
return CUBEB_OK;
}
static inline int
cubeb_device_id_ptr (cubeb * context, cubeb_devid devid, char ** str)
{
*str = (char *)malloc(sizeof(char)*16);
snprintf(*str, 16, "%p", (const char *)devid);
return CUBEB_OK;
}
#endif /* CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5 */

Просмотреть файл

@ -7,6 +7,7 @@
#undef NDEBUG
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
@ -362,3 +363,58 @@ int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
return stream->context->ops->stream_register_device_changed_callback(stream, device_changed_callback);
}
int cubeb_enumerate_devices(cubeb * context,
cubeb_device_type devtype,
cubeb_device_list ** list,
uint32_t * count)
{
if ((devtype & (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT)) == 0)
return CUBEB_ERROR_INVALID_PARAMETER;
if (list == NULL)
return CUBEB_ERROR_INVALID_PARAMETER;
if (!context->ops->enumerate_devices)
return CUBEB_ERROR_NOT_SUPPORTED;
return context->ops->enumerate_devices(context, devtype, list, count);
}
int cubeb_device_list_destroy(cubeb * context, cubeb_device_list * list)
{
cubeb_device_list * cur;
if (context == NULL)
return CUBEB_ERROR_INVALID_PARAMETER;
while (list != NULL) {
cur = list;
list = list->next;
context->ops->device_info_destroy(context, &cur->device);
free(cur);
}
return CUBEB_OK;
}
int cubeb_device_id_to_str(cubeb * context, const cubeb_devid devid, char ** str)
{
if (context == NULL || str == NULL)
return CUBEB_ERROR_INVALID_PARAMETER;
return context->ops->device_id_to_str(context, devid, str);
}
int cubeb_register_device_list_changed(cubeb * context,
cubeb_device_list_changed_callback callback,
void * user_ptr)
{
return CUBEB_ERROR_NOT_SUPPORTED;
}
int cubeb_deregister_device_list_changed(cubeb * context,
cubeb_device_list_changed_callback callback,
void * user_ptr)
{
return CUBEB_ERROR_NOT_SUPPORTED;
}

Просмотреть файл

@ -1116,6 +1116,9 @@ static struct cubeb_ops const alsa_ops = {
.get_max_channel_count = alsa_get_max_channel_count,
.get_min_latency = alsa_get_min_latency,
.get_preferred_sample_rate = alsa_get_preferred_sample_rate,
.enumerate_devices = NULL,
.device_info_destroy = NULL,
.device_id_to_str = NULL,
.destroy = alsa_destroy,
.stream_init = alsa_stream_init,
.stream_destroy = alsa_stream_destroy,

Просмотреть файл

@ -489,6 +489,9 @@ static struct cubeb_ops const audiotrack_ops = {
.get_max_channel_count = audiotrack_get_max_channel_count,
.get_min_latency = audiotrack_get_min_latency,
.get_preferred_sample_rate = audiotrack_get_preferred_sample_rate,
.enumerate_devices = NULL,
.device_info_destroy = NULL,
.device_id_to_str = NULL,
.destroy = audiotrack_destroy,
.stream_init = audiotrack_stream_init,
.stream_destroy = audiotrack_stream_destroy,

Просмотреть файл

@ -1005,6 +1005,9 @@ static struct cubeb_ops const audiounit_ops = {
.get_max_channel_count = audiounit_get_max_channel_count,
.get_min_latency = audiounit_get_min_latency,
.get_preferred_sample_rate = audiounit_get_preferred_sample_rate,
.enumerate_devices = NULL,
.device_info_destroy = NULL,
.device_id_to_str = NULL,
.destroy = audiounit_destroy,
.stream_init = audiounit_stream_init,
.stream_destroy = audiounit_stream_destroy,

Просмотреть файл

@ -132,6 +132,9 @@ static struct cubeb_ops const cbjack_ops = {
.get_max_channel_count = cbjack_get_max_channel_count,
.get_min_latency = cbjack_get_min_latency,
.get_preferred_sample_rate = cbjack_get_preferred_sample_rate,
.enumerate_devices = NULL,
.device_info_destroy = NULL,
.device_id_to_str = NULL,
.destroy = cbjack_destroy,
.stream_init = cbjack_stream_init,
.stream_destroy = cbjack_stream_destroy,

Просмотреть файл

@ -270,6 +270,21 @@ kai_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
return CUBEB_OK;
}
static int
kai_enumerate_devices(cubeb * context, cubeb_device_type type,
cubeb_device_list ** devices, uint32_t * count)
{
(void)context;
(void)type;
*devices = NULL;
if (count != NULL)
*count = 0;
return CUBEB_ERROR_NOT_SUPPORTED;
}
static int
kai_stream_start(cubeb_stream * stm)
{
@ -329,6 +344,9 @@ static struct cubeb_ops const kai_ops = {
/*.get_max_channel_count=*/ kai_get_max_channel_count,
/*.get_min_latency=*/ kai_get_min_latency,
/*.get_preferred_sample_rate =*/ kai_get_preferred_sample_rate,
/*.enumerate_devices =*/ kai_enumerate_devices,
/*.device_info_destroy =*/ cubeb_device_info_destroy_no_devid,
/*.device_id_to_str =*/ cubeb_device_id_idx,
/*.destroy =*/ kai_destroy,
/*.stream_init =*/ kai_stream_init,
/*.stream_destroy =*/ kai_stream_destroy,

Просмотреть файл

@ -814,6 +814,9 @@ static struct cubeb_ops const opensl_ops = {
.get_max_channel_count = opensl_get_max_channel_count,
.get_min_latency = opensl_get_min_latency,
.get_preferred_sample_rate = opensl_get_preferred_sample_rate,
.enumerate_devices = NULL,
.device_info_destroy = NULL,
.device_id_to_str = NULL,
.destroy = opensl_destroy,
.stream_init = opensl_stream_init,
.stream_destroy = opensl_stream_destroy,

Просмотреть файл

@ -730,6 +730,9 @@ static struct cubeb_ops const pulse_ops = {
.get_max_channel_count = pulse_get_max_channel_count,
.get_min_latency = pulse_get_min_latency,
.get_preferred_sample_rate = pulse_get_preferred_sample_rate,
.enumerate_devices = NULL,
.device_info_destroy = NULL,
.device_id_to_str = NULL,
.destroy = pulse_destroy,
.stream_init = pulse_stream_init,
.stream_destroy = pulse_stream_destroy,

Просмотреть файл

@ -356,6 +356,9 @@ static struct cubeb_ops const sndio_ops = {
.get_max_channel_count = sndio_get_max_channel_count,
.get_min_latency = sndio_get_min_latency,
.get_preferred_sample_rate = sndio_get_preferred_sample_rate,
.enumerate_devices = NULL,
.device_info_destroy = NULL,
.device_id_to_str = NULL,
.destroy = sndio_destroy,
.stream_init = sndio_stream_init,
.stream_destroy = sndio_stream_destroy,

Просмотреть файл

@ -1431,6 +1431,9 @@ cubeb_ops const wasapi_ops = {
/*.get_max_channel_count =*/ wasapi_get_max_channel_count,
/*.get_min_latency =*/ wasapi_get_min_latency,
/*.get_preferred_sample_rate =*/ wasapi_get_preferred_sample_rate,
/*.enumerate_devices =*/ NULL,
/*.device_info_destroy */= NULL,
/*.device_id_to_str */= NULL,
/*.destroy =*/ wasapi_destroy,
/*.stream_init =*/ wasapi_stream_init,
/*.stream_destroy =*/ wasapi_stream_destroy,

Просмотреть файл

@ -677,6 +677,9 @@ static struct cubeb_ops const winmm_ops = {
/*.get_max_channel_count=*/ winmm_get_max_channel_count,
/*.get_min_latency=*/ winmm_get_min_latency,
/*.get_preferred_sample_rate =*/ winmm_get_preferred_sample_rate,
/*.enumerate_devices =*/ NULL,
/*.device_info_destroy */= NULL,
/*.device_id_to_str */= NULL,
/*.destroy =*/ winmm_destroy,
/*.stream_init =*/ winmm_stream_init,
/*.stream_destroy =*/ winmm_stream_destroy,

165
test/test_devices.c Normal file
Просмотреть файл

@ -0,0 +1,165 @@
/*
* Copyright © 2015 Haakon Sporsheim <haakon.sporsheim@telenordigital.com>
*
* This program is made available under an ISC-style license. See the
* accompanying file LICENSE for details.
*/
/* libcubeb enumerate device test/example.
* Prints out a list of devices enumerated. */
#ifdef NDEBUG
#undef NDEBUG
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cubeb/cubeb.h"
static void
print_device_list(cubeb * context, cubeb_device_list * devices, FILE * f)
{
char * devid = NULL, devfmts[64] = "";
const char * devtype, * devstate, * devdeffmt;
if (devices == NULL)
return;
cubeb_device_id_to_str(context, devices->device.device_id, &devid);
switch (devices->device.type) {
case CUBEB_DEVICE_TYPE_INPUT:
devtype = "input";
break;
case CUBEB_DEVICE_TYPE_OUTPUT:
devtype = "output";
break;
case CUBEB_DEVICE_TYPE_UNKNOWN:
default:
devtype = "unknown?";
break;
};
switch (devices->device.state) {
case CUBEB_DEVICE_STATE_DISABLED:
devstate = "disabled";
break;
case CUBEB_DEVICE_STATE_UNPLUGGED:
devstate = "unplugged";
break;
case CUBEB_DEVICE_STATE_ENABLED:
devstate = "enabled";
break;
default:
devstate = "unknown?";
break;
};
switch (devices->device.default_format) {
case CUBEB_DEVICE_FMT_S16LE:
devdeffmt = "S16LE";
break;
case CUBEB_DEVICE_FMT_S16BE:
devdeffmt = "S16BE";
break;
case CUBEB_DEVICE_FMT_F32LE:
devdeffmt = "F32LE";
break;
case CUBEB_DEVICE_FMT_F32BE:
devdeffmt = "F32BE";
break;
default:
devdeffmt = "unknown?";
break;
};
if (devices->device.format & CUBEB_DEVICE_FMT_S16LE)
strcat(devfmts, " S16LE");
if (devices->device.format & CUBEB_DEVICE_FMT_S16BE)
strcat(devfmts, " S16BE");
if (devices->device.format & CUBEB_DEVICE_FMT_F32LE)
strcat(devfmts, " F32LE");
if (devices->device.format & CUBEB_DEVICE_FMT_F32BE)
strcat(devfmts, " F32BE");
fprintf(f,
"dev: \"%s\"%s\n"
"\tName: \"%s\"\n"
"\tGroup: \"%s\"\n"
"\tVendor: \"%s\"\n"
"\tType: %s\n"
"\tState: %s\n"
"\tCh: %u\n"
"\tFormat: %s (0x%x) (default: %s)\n"
"\tRate: %u - %u (default: %u)\n"
"\tLatency: lo %ums, hi %ums\n",
devid, devices->device.preferred ? " (PREFERRED)" : "",
devices->device.friendly_name, devices->device.group_id,
devices->device.vendor_name, devtype, devstate,
devices->device.max_channels,
(devfmts[0] == ' ') ? &devfmts[1] : devfmts,
(unsigned int)devices->device.format, devdeffmt,
devices->device.min_rate, devices->device.max_rate,
devices->device.default_rate,
devices->device.latency_lo_ms, devices->device.latency_hi_ms);
free(devid);
print_device_list(context, devices->next, f);
}
static int
run_enumerate_devices(void)
{
int r = CUBEB_OK;
cubeb * ctx = NULL;
cubeb_device_list * devices = NULL;
uint32_t count = 0;
r = cubeb_init(&ctx, "Cubeb audio test");
if (r != CUBEB_OK) {
fprintf(stderr, "Error initializing cubeb library\n");
return r;
}
fprintf(stdout, "Enumerating input devices for backend %s\n",
cubeb_get_backend_id (ctx));
r = cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_INPUT, &devices, &count);
if (r != CUBEB_OK) {
fprintf(stderr, "Error enumerating devices %d\n", r);
goto cleanup;
}
fprintf(stdout, "Found %u input devices\n", count);
print_device_list (ctx, devices, stdout);
cubeb_device_list_destroy (ctx, devices);
fprintf(stdout, "Enumerating output devices for backend %s\n",
cubeb_get_backend_id (ctx));
r = cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &devices, &count);
if (r != CUBEB_OK) {
fprintf(stderr, "Error enumerating devices %d\n", r);
goto cleanup;
}
fprintf(stdout, "Found %u output devices\n", count);
print_device_list (ctx, devices, stdout);
cubeb_device_list_destroy (ctx, devices);
cleanup:
cubeb_destroy(ctx);
return r;
}
int main(int argc, char *argv[])
{
int ret;
ret = run_enumerate_devices();
return ret;
}