gstreamer/sys/magicleap/mlaudiowrapper.cpp
2019-12-06 15:29:29 +00:00

205 lines
5.1 KiB
C++

/*
* Copyright (C) 2019 Collabora Ltd.
* Author: Xavier Claessens <xavier.claessens@collabora.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mlaudiowrapper.h"
#include <ml_audio.h>
#include <lumin/node/AudioNode.h>
#include <lumin/BaseApp.h>
#include <lumin/Prism.h>
GST_DEBUG_CATEGORY_EXTERN (mgl_debug);
#define GST_CAT_DEFAULT mgl_debug
using lumin::BaseApp;
using lumin::AudioNode;
using lumin::AudioBuffer;
using lumin::AudioBufferFormat;
using lumin::AudioSampleFormat;
struct _GstMLAudioWrapper
{
BaseApp *app;
AudioNode *node;
MLHandle handle;
};
AudioBufferFormat
convert_buffer_format(const MLAudioBufferFormat *format)
{
AudioBufferFormat ret;
ret.channel_count = format->channel_count;
ret.samples_per_second = format->samples_per_second;
ret.bits_per_sample = format->bits_per_sample;
ret.valid_bits_per_sample = format->valid_bits_per_sample;
switch (format->sample_format) {
case MLAudioSampleFormat_Int:
ret.sample_format = AudioSampleFormat::Integer;
break;
case MLAudioSampleFormat_Float:
ret.sample_format = AudioSampleFormat::Float;
break;
default:
g_warn_if_reached ();
ret.sample_format = (AudioSampleFormat)format->sample_format;
};
ret.reserved = format->reserved;
return ret;
}
GstMLAudioWrapper *
gst_ml_audio_wrapper_new (gpointer app)
{
GstMLAudioWrapper *self;
self = g_new0 (GstMLAudioWrapper, 1);
self->app = reinterpret_cast<BaseApp *>(app);
self->node = nullptr;
self->handle = ML_INVALID_HANDLE;
return self;
}
void
gst_ml_audio_wrapper_free (GstMLAudioWrapper *self)
{
if (self->node) {
self->app->RunOnMainThreadSync ([self] {
/* Stop playing sound, but user is responsible to destroy the node */
self->node->stopSound ();
});
} else {
MLAudioDestroySound (self->handle);
}
g_free (self);
}
MLResult
gst_ml_audio_wrapper_create_sound (GstMLAudioWrapper *self,
const MLAudioBufferFormat *format,
uint32_t buffer_size,
MLAudioBufferCallback callback,
gpointer user_data)
{
if (self->node) {
auto format2 = convert_buffer_format (format);
bool success = FALSE;
success = self->node->createSoundWithOutputStream (&format2,
buffer_size, callback, user_data);
if (success)
self->node->startSound ();
return success ? MLResult_Ok : MLResult_UnspecifiedFailure;
}
MLResult result = MLAudioCreateSoundWithOutputStream (format, buffer_size,
callback, user_data, &self->handle);
if (result == MLResult_Ok)
result = MLAudioStartSound (self->handle);
return result;
}
MLResult
gst_ml_audio_wrapper_pause_sound (GstMLAudioWrapper *self)
{
g_return_val_if_fail (self->handle != ML_INVALID_HANDLE,
MLResult_UnspecifiedFailure);
return MLAudioPauseSound (self->handle);
}
MLResult
gst_ml_audio_wrapper_resume_sound (GstMLAudioWrapper *self)
{
g_return_val_if_fail (self->handle != ML_INVALID_HANDLE,
MLResult_UnspecifiedFailure);
return MLAudioResumeSound (self->handle);
}
MLResult
gst_ml_audio_wrapper_stop_sound (GstMLAudioWrapper *self)
{
g_return_val_if_fail (self->handle != ML_INVALID_HANDLE,
MLResult_UnspecifiedFailure);
return MLAudioStopSound (self->handle);
}
MLResult
gst_ml_audio_wrapper_get_latency (GstMLAudioWrapper *self,
float *out_latency_in_msec)
{
if (self->handle == ML_INVALID_HANDLE) {
*out_latency_in_msec = 0;
return MLResult_Ok;
}
return MLAudioGetOutputStreamLatency (self->handle, out_latency_in_msec);
}
MLResult
gst_ml_audio_wrapper_get_buffer (GstMLAudioWrapper *self,
MLAudioBuffer *out_buffer)
{
return MLAudioGetOutputStreamBuffer (self->handle, out_buffer);
}
MLResult
gst_ml_audio_wrapper_release_buffer (GstMLAudioWrapper *self)
{
return MLAudioReleaseOutputStreamBuffer (self->handle);
}
void
gst_ml_audio_wrapper_set_handle (GstMLAudioWrapper *self, MLHandle handle)
{
g_return_if_fail (self->handle == ML_INVALID_HANDLE || self->handle == handle);
self->handle = handle;
}
void
gst_ml_audio_wrapper_set_node (GstMLAudioWrapper *self,
gpointer node)
{
g_return_if_fail (self->node == nullptr);
self->node = reinterpret_cast<AudioNode *>(node);
}
gboolean
gst_ml_audio_wrapper_invoke_sync (GstMLAudioWrapper *self,
GstMLAudioWrapperCallback callback, gpointer user_data)
{
gboolean ret;
if (self->app) {
self->app->RunOnMainThreadSync ([self, callback, user_data, &ret] {
ret = callback (self, user_data);
});
} else {
ret = callback (self, user_data);
}
return ret;
}