summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--src/libOpenSLES.c417
2 files changed, 420 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index c7d0515..cb0f63f 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,9 @@ runtime/liblog.so: src/liblog.c
runtime/libEGL.so: private override CPPFLAGS += -D_GNU_SOURCE
runtime/libEGL.so: private override LDLIBS += -lEGL `pkg-config --libs glfw3`
runtime/libEGL.so: src/libEGL.c
-native: runtime/libdl.so runtime/libc.so runtime/libpthread.so runtime/libandroid.so runtime/liblog.so runtime/libEGL.so
+runtime/libOpenSLES.so: private override CFLAGS += -Wno-pedantic
+runtime/libOpenSLES.so: wrapper.a src/libOpenSLES.c
+native: runtime/libdl.so runtime/libc.so runtime/libpthread.so runtime/libandroid.so runtime/liblog.so runtime/libEGL.so runtime/libOpenSLES.so
jvm.a: private override CPPFLAGS += -D_GNU_SOURCE
jvm.a: private override CFLAGS += -Wno-unused-variable -Wno-pedantic
diff --git a/src/libOpenSLES.c b/src/libOpenSLES.c
new file mode 100644
index 0000000..b2e4f0e
--- /dev/null
+++ b/src/libOpenSLES.c
@@ -0,0 +1,417 @@
+#include <stdint.h>
+#include "wrapper/wrapper.h"
+#include "wrapper/verbose.h"
+
+// https://developer.android.com/ndk/guides/audio/opensl/opensl-for-android
+// https://www.khronos.org/registry/OpenSL-ES/specs/OpenSL_ES_Specification_1.1.pdf
+
+typedef uint8_t SLuint8;
+typedef uint16_t SLuint16;
+typedef uint32_t SLuint32;
+typedef SLuint8 SLchar;
+typedef SLuint32 SLboolean;
+typedef SLuint32 SLresult;
+
+#define SL_BOOLEAN_FALSE ((SLboolean) 0x00000000)
+#define SL_BOOLEAN_TRUE ((SLboolean) 0x00000001)
+
+#define SL_RESULT_SUCCESS ((SLuint32) 0x00000000)
+#define SL_RESULT_PRECONDITIONS_VIOLATED ((SLuint32) 0x00000001)
+#define SL_RESULT_PARAMETER_INVALID ((SLuint32) 0x00000002)
+#define SL_RESULT_MEMORY_FAILURE ((SLuint32) 0x00000003)
+#define SL_RESULT_RESOURCE_ERROR ((SLuint32) 0x00000004)
+#define SL_RESULT_RESOURCE_LOST ((SLuint32) 0x00000005)
+#define SL_RESULT_IO_ERROR ((SLuint32) 0x00000006)
+#define SL_RESULT_BUFFER_INSUFFICIENT ((SLuint32) 0x00000007)
+#define SL_RESULT_CONTENT_CORRUPTED ((SLuint32) 0x00000008)
+#define SL_RESULT_CONTENT_UNSUPPORTED ((SLuint32) 0x00000009)
+#define SL_RESULT_CONTENT_NOT_FOUND ((SLuint32) 0x0000000A)
+#define SL_RESULT_PERMISSION_DENIED ((SLuint32) 0x0000000B)
+#define SL_RESULT_FEATURE_UNSUPPORTED ((SLuint32) 0x0000000C)
+#define SL_RESULT_INTERNAL_ERROR ((SLuint32) 0x0000000D)
+#define SL_RESULT_UNKNOWN_ERROR ((SLuint32) 0x0000000E)
+#define SL_RESULT_OPERATION_ABORTED ((SLuint32) 0x0000000F)
+#define SL_RESULT_CONTROL_LOST ((SLuint32) 0x00000010)
+
+#define SL_OBJECT_STATE_UNREALIZED ((SLuint32) 0x00000001)
+#define SL_OBJECT_STATE_REALIZED ((SLuint32) 0x00000002)
+#define SL_OBJECT_STATE_SUSPENDED ((SLuint32) 0x00000003)
+
+#define SL_DEFAULTDEVICEID_LED ((SLuint32) 0xFFFFFFFD)
+#define SL_DEFAULTDEVICEID_VIBRA ((SLuint32) 0xFFFFFFFC)
+
+struct SLInterfaceID {
+ SLuint32 time_low;
+ SLuint16 time_mid;
+ SLuint16 time_hi_and_version;
+ SLuint16 clock_seq;
+ uint8_t node[6];
+};
+
+struct SLInterfaceID *SL_IID_BUFFERQUEUE;
+struct SLInterfaceID *SL_IID_ENGINE;
+struct SLInterfaceID *SL_IID_PLAY;
+struct SLInterfaceID *SL_IID_VOLUME;
+
+struct SLObjectItf {
+ SLresult (*Realize)(struct SLObjectItf**, SLboolean);
+ SLresult (*Resume)(struct SLObjectItf**, SLboolean);
+ SLresult (*GetState)(struct SLObjectItf**, SLuint32*);
+ SLresult (*GetInterface)(struct SLObjectItf**, const struct SLInterfaceID*, struct SLObjectItf***);
+ SLresult (*RegisterCallback)(struct SLObjectItf**, void*, void*);
+ SLresult (*AbortAsyncOperation)(struct SLObjectItf**);
+ SLresult (*Destroy)(struct SLObjectItf**);
+ SLresult (*SetPriority)(struct SLObjectItf**, SLuint32, SLboolean);
+ SLresult (*GetPriority)(struct SLObjectItf**, SLuint32*, SLboolean*);
+ SLresult (*SetLossOfControlInterfaces)(struct SLObjectItf**, SLuint16, const struct SLInterfaceID**, SLboolean);
+};
+
+static struct SLObjectItf**
+sl_object(void);
+
+struct SLEngineItf {
+ SLresult (*CreateLEDDevice)(struct SLEngineItf**, struct SLObjectItf***, SLuint32, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*CreateVibraDevice)(struct SLEngineItf**, struct SLObjectItf***, SLuint32, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*CreateAudioPlayer)(struct SLEngineItf**, struct SLObjectItf***, void*, void*, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*CreateAudioRecorder)(struct SLEngineItf**, struct SLObjectItf***, void*, void*, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*CreateMidiPlayer)(struct SLEngineItf**, struct SLObjectItf***, void*, void*, void*, void*, void*, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*CreateListener)(struct SLEngineItf**, struct SLObjectItf***, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*Create3DGroup)(struct SLEngineItf**, struct SLObjectItf***, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*CreateOutputMix)(struct SLEngineItf**, struct SLObjectItf***, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*CreateMetadataExtractor)(struct SLEngineItf**, struct SLObjectItf***, void*, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*CreateExtensionObject)(struct SLEngineItf**, struct SLObjectItf***, void*, SLuint32, SLuint32, const struct SLInterfaceID**, const SLboolean*);
+ SLresult (*QueryNumSupportedInterfaces)(struct SLEngineItf**, SLuint32, SLuint32*);
+ SLresult (*QuerySupportedInterfaces)(struct SLEngineItf**, SLuint32, SLuint32, const struct SLInterfaceID**);
+ SLresult (*QueryNumSupportedExtensions)(struct SLEngineItf**, SLuint32, SLuint32*);
+ SLresult (*QuerySupportedExtensions)(struct SLEngineItf**, SLuint32, const char*, SLuint16*);
+ SLresult (*IsExtensionSupported)(struct SLEngineItf**, const char*, SLboolean*);
+};
+
+static SLresult
+sl_engine_create_led_device(struct SLEngineItf **engine, struct SLObjectItf ***device, SLuint32 device_id, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %u, %u %p, %p", (void*)engine, (void*)device, device_id, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device || device_id != SL_DEFAULTDEVICEID_LED)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_create_vibra_device(struct SLEngineItf **engine, struct SLObjectItf ***device, SLuint32 device_id, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %u, %u %p, %p", (void*)engine, (void*)device, device_id, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device || device_id != SL_DEFAULTDEVICEID_VIBRA)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_create_audio_player(struct SLEngineItf **engine, struct SLObjectItf ***device, void *src, void *snk, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %p, %p, %u %p, %p", (void*)engine, (void*)device, src, snk, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_create_audio_recorder(struct SLEngineItf **engine, struct SLObjectItf ***device, void *src, void *snk, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %p, %p, %u %p, %p", (void*)engine, (void*)device, src, snk, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_create_midi_player(struct SLEngineItf **engine, struct SLObjectItf ***device, void *midi_src, void *bank_src, void *audio_out, void *vibra, void *led_array, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %p, %p, %p, %p, %p, %u %p, %p", (void*)engine, (void*)device, midi_src, bank_src, audio_out, vibra, led_array, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_create_listener(struct SLEngineItf **engine, struct SLObjectItf ***device, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %u, %p, %p", (void*)engine, (void*)device, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_create_3d_group(struct SLEngineItf **engine, struct SLObjectItf ***device, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %u, %p, %p", (void*)engine, (void*)device, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_create_output_mix(struct SLEngineItf **engine, struct SLObjectItf ***device, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %u, %p, %p", (void*)engine, (void*)device, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_create_metadata_extractor(struct SLEngineItf **engine, struct SLObjectItf ***device, void *source, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %p, %u, %p, %p", (void*)engine, (void*)device, source, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device || !source)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_create_extension_object(struct SLEngineItf **engine, struct SLObjectItf ***device, void *params, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %p, %p, %u, %p, %p", (void*)engine, (void*)device, params, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!device || !params)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *device = sl_object();
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_query_num_supported_interfaces(struct SLEngineItf **engine, SLuint32 *out_num_supported)
+{
+ verbose("%p, %p", (void*)engine, (void*)out_num_supported);
+
+ if (!out_num_supported)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *out_num_supported = 0;
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_query_supported_interfaces(struct SLEngineItf **engine, SLuint32 index, const SLchar *name, SLuint16 *out_name_len)
+{
+ verbose("%p, %u, %s, %p", (void*)engine, index, name, (void*)out_name_len);
+
+ if (!name || !out_name_len)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *out_name_len = 0;
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_query_num_supported_extensions(struct SLEngineItf **engine, SLuint32 *out_num_supported)
+{
+ verbose("%p, %p", (void*)engine, (void*)out_num_supported);
+
+ if (!out_num_supported)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *out_num_supported = 0;
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_query_supported_extensions(struct SLEngineItf **engine, SLuint32 index, const SLchar *name, SLuint16 *out_name_len)
+{
+ verbose("%p, %u, %s, %p", (void*)engine, index, name, (void*)out_name_len);
+
+ if (!name || !out_name_len)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *out_name_len = 0;
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_engine_is_extension_supported(struct SLEngineItf **engine, const SLchar *name, SLboolean *out_supported)
+{
+ verbose("%p, %s, %p", (void*)engine, name, (void*)out_supported);
+
+ if (!name || !out_supported)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *out_supported = SL_BOOLEAN_FALSE;
+ return SL_RESULT_SUCCESS;
+}
+
+static struct SLEngineItf**
+sl_engine(void)
+{
+ static struct SLEngineItf itf, *itfp;
+ if (!itfp) {
+#define WRAP(x) wrapper_create(#x, x)
+ itf.CreateLEDDevice = WRAP(sl_engine_create_led_device);
+ itf.CreateVibraDevice = WRAP(sl_engine_create_vibra_device);
+ itf.CreateAudioPlayer = WRAP(sl_engine_create_audio_player);
+ itf.CreateAudioRecorder = WRAP(sl_engine_create_audio_recorder);
+ itf.CreateMidiPlayer = WRAP(sl_engine_create_midi_player);
+ itf.CreateListener = WRAP(sl_engine_create_listener);
+ itf.Create3DGroup = WRAP(sl_engine_create_3d_group);
+ itf.CreateOutputMix = WRAP(sl_engine_create_output_mix);
+ itf.CreateMetadataExtractor = WRAP(sl_engine_create_metadata_extractor);
+ itf.CreateExtensionObject = WRAP(sl_engine_create_extension_object);
+ itf.QueryNumSupportedInterfaces = WRAP(sl_engine_query_num_supported_interfaces);
+ itf.QuerySupportedInterfaces = WRAP(sl_engine_query_supported_interfaces);
+ itf.QueryNumSupportedExtensions = WRAP(sl_engine_query_num_supported_extensions);
+ itf.QuerySupportedExtensions = WRAP(sl_engine_query_supported_extensions);
+ itf.IsExtensionSupported = WRAP(sl_engine_is_extension_supported);
+#undef WRAP
+ itfp = &itf;
+ }
+ return &itfp;
+}
+
+static SLresult
+sl_object_realize(struct SLObjectItf **object, SLboolean async)
+{
+ verbose("%p, %u", (void*)object, async);
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_object_resume(struct SLObjectItf **object, SLboolean async)
+{
+ verbose("%p, %u", (void*)object, async);
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_object_get_state(struct SLObjectItf **object, SLuint32 *out_state)
+{
+ verbose("%p, %p", (void*)object, (void*)out_state);
+
+ if (!out_state)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *out_state = SL_OBJECT_STATE_REALIZED;
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_object_get_interface(struct SLObjectItf **object, const struct SLInterfaceID *iid, struct SLObjectItf ***out_interface)
+{
+ verbose("%p, %p", (void*)object, (void*)out_interface);
+
+ if (iid == SL_IID_ENGINE) {
+ *out_interface = (struct SLObjectItf**)sl_engine();
+ } else {
+ return SL_RESULT_PARAMETER_INVALID;
+ }
+
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_object_register_callback(struct SLObjectItf **object, void *cb, void *ctx)
+{
+ verbose("%p, %p, %p", (void*)object, cb, ctx);
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_object_abort_async_operation(struct SLObjectItf **object)
+{
+ verbose("%p", (void*)object);
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_object_destroy(struct SLObjectItf **object)
+{
+ verbose("%p", (void*)object);
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_object_set_priority(struct SLObjectItf **object, SLuint32 priority, SLboolean preemptable)
+{
+ verbose("%p, %u, %u", (void*)object, priority, preemptable);
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_object_get_priority(struct SLObjectItf **object, SLuint32 *out_priority, SLboolean *out_preemptable)
+{
+ verbose("%p, %p, %p", (void*)object, (void*)out_priority, (void*)out_preemptable);
+
+ if (!out_priority || !out_preemptable)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *out_priority = 0;
+ *out_preemptable = SL_BOOLEAN_FALSE;
+ return SL_RESULT_SUCCESS;
+}
+
+static SLresult
+sl_object_set_loss_of_control_interfaces(struct SLObjectItf **object, SLuint16 num_interfaces, struct SLInterfaceID **interface_ids, SLboolean enabled)
+{
+ verbose("%p, %u, %p, %u", (void*)object, num_interfaces, (void*)interface_ids, enabled);
+ return SL_RESULT_SUCCESS;
+}
+
+static struct SLObjectItf**
+sl_object(void)
+{
+ static struct SLObjectItf itf, *itfp;
+ if (!itfp) {
+#define WRAP(x) wrapper_create(#x, x)
+ itf.Realize = WRAP(sl_object_realize);
+ itf.Resume = WRAP(sl_object_resume);
+ itf.GetState = WRAP(sl_object_get_state);
+ itf.GetInterface = WRAP(sl_object_get_interface);
+ itf.RegisterCallback = WRAP(sl_object_register_callback);
+ itf.AbortAsyncOperation = WRAP(sl_object_abort_async_operation);
+ itf.Destroy = WRAP(sl_object_destroy);
+ itf.SetPriority = WRAP(sl_object_set_priority);
+ itf.GetPriority = WRAP(sl_object_get_priority);
+ itf.SetLossOfControlInterfaces = WRAP(sl_object_set_loss_of_control_interfaces);
+#undef WRAP
+ itfp = &itf;
+ }
+ return &itfp;
+}
+
+SLresult
+slCreateEngine(struct SLObjectItf ***engine, SLuint32 num_options, void *options, SLuint32 num_interfaces, const struct SLInterfaceID **interface_ids, const SLboolean *interface_required)
+{
+ verbose("%p, %u, %p, %u, %p, %p", (void*)engine, num_options, options, num_interfaces, (void*)interface_ids, (void*)interface_required);
+
+ if (!engine)
+ return SL_RESULT_PARAMETER_INVALID;
+
+ *engine = sl_object();
+ return SL_RESULT_SUCCESS;
+}