From 68853eb5a841043d2120c17a3cf98b7dc3bf00a9 Mon Sep 17 00:00:00 2001 From: casey langen Date: Wed, 29 Jan 2020 19:18:15 -0800 Subject: [PATCH] Added C support for Stream and Player -- low-level playback is now possible. --- src/core/audio/IStream.h | 12 +- src/core/audio/Player.cpp | 5 +- src/core/audio/Player.h | 3 +- src/core/audio/Stream.cpp | 17 +- src/core/audio/Stream.h | 22 +- src/core/c_interface_wrappers.cpp | 352 ++++++++++++++++++++++++------ src/core/library/Indexer.cpp | 4 +- src/core/musikcore_c.h | 165 +++++++------- src/core/sdk/constants.h | 5 + src/core_c_demo/main.c | 34 ++- src/plugins/alsaout/AlsaOut.cpp | 2 +- 11 files changed, 441 insertions(+), 180 deletions(-) diff --git a/src/core/audio/IStream.h b/src/core/audio/IStream.h index 3d8012e69..19ba35a9d 100644 --- a/src/core/audio/IStream.h +++ b/src/core/audio/IStream.h @@ -35,8 +35,7 @@ #pragma once #include -#include -#include +#include #include #include #include @@ -47,18 +46,15 @@ namespace musik { namespace core { namespace audio { class IStream { public: - typedef enum { - NoDSP = 1 - } Options; - - virtual Buffer* GetNextProcessedOutputBuffer() = 0; - virtual void OnBufferProcessedByPlayer(Buffer* buffer) = 0; + virtual musik::core::sdk::IBuffer* GetNextProcessedOutputBuffer() = 0; + virtual void OnBufferProcessedByPlayer(musik::core::sdk::IBuffer* buffer) = 0; virtual double SetPosition(double seconds) = 0; virtual double GetDuration() = 0; virtual bool OpenStream(std::string uri) = 0; virtual void Interrupt() = 0; virtual int GetCapabilities() = 0; virtual bool Eof() = 0; + virtual void Release() = 0; }; typedef std::shared_ptr IStreamPtr; diff --git a/src/core/audio/Player.cpp b/src/core/audio/Player.cpp index 0688b6b9e..e600bbcef 100644 --- a/src/core/audio/Player.cpp +++ b/src/core/audio/Player.cpp @@ -124,6 +124,7 @@ Player::Player( EventListener *listener, Gain gain) : state(Player::Idle) +, stream(Stream::Create()) , url(url) , currentPosition(0) , output(output) @@ -287,9 +288,7 @@ void musik::core::audio::playerThreadLoop(Player* player) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); #endif - player->stream = Stream::Create(); - - Buffer* buffer = nullptr; + IBuffer* buffer = nullptr; float gain = player->gain.preamp * player->gain.gain; if (gain > 1.0f && player->gain.peakValid) { diff --git a/src/core/audio/Player.h b/src/core/audio/Player.h index 2c0749b51..14c070c5f 100644 --- a/src/core/audio/Player.h +++ b/src/core/audio/Player.h @@ -53,7 +53,7 @@ namespace musik { namespace core { namespace audio { class Player : public musik::core::sdk::IBufferProvider { public: - enum DestroyMode { Drain, NoDrain }; + enum DestroyMode { Drain = 0, NoDrain = 1 }; struct Gain { Gain() { @@ -168,6 +168,7 @@ namespace musik { namespace core { namespace audio { DestroyMode destroyMode; Gain gain; int pendingBufferCount; + bool threadFinished; FftContext* fftContext; }; diff --git a/src/core/audio/Stream.cpp b/src/core/audio/Stream.cpp index 8e100b062..e61e88561 100644 --- a/src/core/audio/Stream.cpp +++ b/src/core/audio/Stream.cpp @@ -36,7 +36,6 @@ #include "Stream.h" #include "Streams.h" -#include #include using namespace musik::core::audio; @@ -47,7 +46,7 @@ static std::string TAG = "Stream"; #define MIN_BUFFER_COUNT 30 -Stream::Stream(int samplesPerChannel, double bufferLengthSeconds, unsigned int options) +Stream::Stream(int samplesPerChannel, double bufferLengthSeconds, StreamFlags options) : options(options) , samplesPerChannel(samplesPerChannel) , bufferLengthSeconds(bufferLengthSeconds) @@ -60,7 +59,7 @@ Stream::Stream(int samplesPerChannel, double bufferLengthSeconds, unsigned int o , done(false) , capabilities(0) , rawBuffer(nullptr) { - if ((this->options & NoDSP) == 0) { + if (((int) this->options & (int) StreamFlags::NoDSP) == 0) { dsps = streams::GetDspPlugins(); } @@ -81,10 +80,14 @@ Stream::~Stream() { } } -IStreamPtr Stream::Create(int samplesPerChannel, double bufferLengthSeconds, unsigned int options) { +IStreamPtr Stream::Create(int samplesPerChannel, double bufferLengthSeconds, StreamFlags options) { return IStreamPtr(new Stream(samplesPerChannel, bufferLengthSeconds, options)); } +IStream* Stream::CreateUnmanaged(int samplesPerChannel, double bufferLengthSeconds, StreamFlags options) { + return new Stream(samplesPerChannel, bufferLengthSeconds, options); +} + double Stream::SetPosition(double requestedSeconds) { double actualSeconds = this->decoder->SetPosition(requestedSeconds); @@ -146,8 +149,8 @@ void Stream::Interrupt() { } } -void Stream::OnBufferProcessedByPlayer(Buffer* buffer) { - this->recycledBuffers.push_back(buffer); +void Stream::OnBufferProcessedByPlayer(IBuffer* buffer) { + this->recycledBuffers.push_back((Buffer*) buffer); } bool Stream::GetNextBufferFromDecoder() { @@ -188,7 +191,7 @@ inline Buffer* Stream::GetEmptyBuffer() { return nullptr; } -Buffer* Stream::GetNextProcessedOutputBuffer() { +IBuffer* Stream::GetNextProcessedOutputBuffer() { this->RefillInternalBuffers(); /* in the normal case we have buffers available in the filled queue. */ diff --git a/src/core/audio/Stream.h b/src/core/audio/Stream.h index daa78045e..de58a013e 100644 --- a/src/core/audio/Stream.h +++ b/src/core/audio/Stream.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -49,27 +50,38 @@ namespace musik { namespace core { namespace audio { class Stream : public IStream { using IDSP = musik::core::sdk::IDSP; using IDecoder = musik::core::sdk::IDecoder; + using IBuffer = musik::core::sdk::IBuffer; + using StreamFlags = musik::core::sdk::StreamFlags; public: static IStreamPtr Create( int samplesPerChannel = 2048, double bufferLengthSeconds = 5, - unsigned int options = 0); + StreamFlags options = StreamFlags::None); + + static IStream* CreateUnmanaged( + int samplesPerChannel = 2048, + double bufferLengthSeconds = 5, + StreamFlags options = StreamFlags::None); private: - Stream(int samplesPerChannel, double bufferLengthSeconds, unsigned int options); + Stream( + int samplesPerChannel, + double bufferLengthSeconds, + StreamFlags options); public: virtual ~Stream(); - virtual Buffer* GetNextProcessedOutputBuffer() override; - virtual void OnBufferProcessedByPlayer(Buffer* buffer) override; + virtual IBuffer* GetNextProcessedOutputBuffer() override; + virtual void OnBufferProcessedByPlayer(IBuffer* buffer) override; virtual double SetPosition(double seconds) override; virtual double GetDuration() override; virtual bool OpenStream(std::string uri) override; virtual void Interrupt() override; virtual int GetCapabilities() override; virtual bool Eof() override { return this->done; } + virtual void Release() override { delete this; } private: bool GetNextBufferFromDecoder(); @@ -94,7 +106,7 @@ namespace musik { namespace core { namespace audio { long decoderSamplesRemain; uint64_t decoderPosition; - unsigned int options; + musik::core::sdk::StreamFlags options; int samplesPerChannel; long samplesPerBuffer; int bufferCount; diff --git a/src/core/c_interface_wrappers.cpp b/src/core/c_interface_wrappers.cpp index 0a3996720..c62230bca 100644 --- a/src/core/c_interface_wrappers.cpp +++ b/src/core/c_interface_wrappers.cpp @@ -57,9 +57,16 @@ #include #include #include +#include +#include +#include + +#include using namespace musik; +using namespace musik::core; using namespace musik::core::sdk; +using namespace musik::core::audio; #define ENV musik::core::plugin::Environment() @@ -84,13 +91,12 @@ using namespace musik::core::sdk; #define DEVICE(x) reinterpret_cast(x.opaque) #define DEVICELIST(x) reinterpret_cast(x.opaque) #define OUTPUT(x) reinterpret_cast(x.opaque) +#define AUDIOSTREAM(x) reinterpret_cast(x.opaque) #define RELEASE(x, type) if (mcsdk_handle_ok(x)) { type(x)->Release(); x.opaque = nullptr; } /* - * * IResource - * */ mcsdk_export int64_t mcsdk_resource_get_id(mcsdk_resource r) { @@ -106,9 +112,7 @@ mcsdk_export void mcsdk_resource_release(mcsdk_resource r) { } /* - * * IValue - * */ mcsdk_export size_t mcsdk_value_get_value(mcsdk_value v, char* dst, size_t size) { @@ -120,9 +124,7 @@ mcsdk_export void mcsdk_value_release(mcsdk_value v) { } /* - * * IValueList - * */ mcsdk_export size_t mcsdk_value_list_count(mcsdk_value_list vl) { @@ -138,9 +140,7 @@ mcsdk_export void mcsdk_value_list_release(mcsdk_value_list vl) { } /* - * * IMap - * */ mcsdk_export int mcsdk_map_get_string(mcsdk_map m, const char* key, char* dst, int size) { @@ -164,9 +164,7 @@ mcsdk_export void mcsdk_map_release(mcsdk_map m) { } /* - * * IMapList - * */ mcsdk_export size_t mcsdk_map_list_get_count(mcsdk_map_list ml) { @@ -182,9 +180,7 @@ mcsdk_export void mcsdk_map_list_release(mcsdk_map_list ml) { } /* - * * ITrack - * */ mcsdk_export void mcsdk_track_retain(mcsdk_track t) { @@ -200,9 +196,7 @@ mcsdk_export void mcsdk_track_release(mcsdk_track t) { } /* - * * ITrackList - * */ mcsdk_export size_t mcsdk_track_list_get_count(mcsdk_track_list tl) { @@ -226,9 +220,7 @@ mcsdk_export void mcsdk_track_list_release(mcsdk_track_list tl) { } /* - * * ITrackListEditor - * */ mcsdk_export bool mcsdk_track_list_editor_insert(mcsdk_track_list_editor tle, int64_t id, size_t index) { @@ -264,9 +256,7 @@ mcsdk_export void mcsdk_track_list_editor_release(mcsdk_track_list_editor tle) { } /* - * * IMetadataProxy - * */ mcsdk_export mcsdk_track_list mcsdk_svc_metadata_query_tracks(mcsdk_svc_metadata mp, const char* keyword, int limit, int offset) { @@ -358,9 +348,7 @@ mcsdk_export void mcsdk_svc_metadata_release(mcsdk_svc_metadata mp) { } /* - * * IPlaybackService - * */ mcsdk_export void mcsdk_svc_playback_play_at(mcsdk_svc_playback pb, size_t index) { @@ -480,9 +468,7 @@ mcsdk_export mcsdk_track_list mcsdk_svc_playback_clone(mcsdk_svc_playback pb) { } /* - * * IPreferences - * */ mcsdk_export bool mcsdk_prefs_get_bool(mcsdk_prefs p, const char* key, bool defaultValue) { @@ -522,9 +508,7 @@ mcsdk_export void mcsdk_prefs_release(mcsdk_prefs p) { } /* - * * IDataStream - * */ mcsdk_export bool mcsdk_data_stream_open(mcsdk_data_stream ds, const char *uri, mcsdk_stream_open_flags flags) { @@ -592,9 +576,7 @@ mcsdk_export void mcsdk_data_stream_release(mcsdk_data_stream ds) { } /* - * * IBuffer - * */ mcsdk_export long mcsdk_audio_buffer_get_sample_rate(mcsdk_audio_buffer ab) { @@ -634,9 +616,7 @@ mcsdk_export void mcsdk_audio_buffer_release(mcsdk_audio_buffer ab) { } /* - * * IBufferProvider - * */ mcsdk_export void mcsdk_audio_buffer_provider_notify_processed(mcsdk_audio_buffer_provider abp, mcsdk_audio_buffer ab) { @@ -644,9 +624,7 @@ mcsdk_export void mcsdk_audio_buffer_provider_notify_processed(mcsdk_audio_buffe } /* - * * IDevice - * */ mcsdk_export const char* mcsdk_device_get_name(mcsdk_device d) { @@ -662,9 +640,7 @@ mcsdk_export void mcsdk_device_release(mcsdk_device d) { } /* - * * IDeviceList - * */ mcsdk_export size_t mcsdk_device_list_get_count(mcsdk_device_list dl) { @@ -679,69 +655,64 @@ mcsdk_export void mcsdk_device_list_release(mcsdk_device_list dl) { RELEASE(dl, DEVICELIST); } - /* - * * IOutput - * */ -mcsdk_export void mcsdk_output_pause(mcsdk_output o) { +mcsdk_export void mcsdk_audio_output_pause(mcsdk_audio_output o) { OUTPUT(o)->Pause(); } -mcsdk_export void mcsdk_output_resume(mcsdk_output o) { +mcsdk_export void mcsdk_audio_output_resume(mcsdk_audio_output o) { OUTPUT(o)->Resume(); } -mcsdk_export void mcsdk_output_set_volume(mcsdk_output o, double volume) { +mcsdk_export void mcsdk_audio_output_set_volume(mcsdk_audio_output o, double volume) { OUTPUT(o)->SetVolume(volume); } -mcsdk_export double mcsdk_output_get_volume(mcsdk_output o) { +mcsdk_export double mcsdk_audio_output_get_volume(mcsdk_audio_output o) { return OUTPUT(o)->GetVolume(); } -mcsdk_export void mcsdk_output_stop(mcsdk_output o) { +mcsdk_export void mcsdk_audio_output_stop(mcsdk_audio_output o) { OUTPUT(o)->Stop(); } -mcsdk_export int mcsdk_output_play(mcsdk_output o, mcsdk_audio_buffer ab, mcsdk_audio_buffer_provider abp) { +mcsdk_export int mcsdk_audio_output_play(mcsdk_audio_output o, mcsdk_audio_buffer ab, mcsdk_audio_buffer_provider abp) { return OUTPUT(o)->Play(BUFFER(ab), BUFFERPROVIDER(abp)); } -mcsdk_export void mcsdk_output_drain(mcsdk_output o) { +mcsdk_export void mcsdk_audio_output_drain(mcsdk_audio_output o) { OUTPUT(o)->Drain(); } -mcsdk_export double mcsdk_output_get_latency(mcsdk_output o) { +mcsdk_export double mcsdk_audio_output_get_latency(mcsdk_audio_output o) { return OUTPUT(o)->Latency(); } -mcsdk_export const char* mcsdk_output_get_name(mcsdk_output o) { +mcsdk_export const char* mcsdk_audio_output_get_name(mcsdk_audio_output o) { return OUTPUT(o)->Name(); } -mcsdk_export mcsdk_device_list mcsdk_output_get_device_list(mcsdk_output o) { +mcsdk_export mcsdk_device_list mcsdk_audio_output_get_device_list(mcsdk_audio_output o) { return mcsdk_device_list { OUTPUT(o)->GetDeviceList() }; } -mcsdk_export bool mcsdk_output_set_default_device(mcsdk_output o, const char* device_id) { +mcsdk_export bool mcsdk_audio_output_set_default_device(mcsdk_audio_output o, const char* device_id) { return OUTPUT(o)->SetDefaultDevice(device_id); } -mcsdk_export mcsdk_device mcsdk_output_get_default_device(mcsdk_output o) { +mcsdk_export mcsdk_device mcsdk_audio_output_get_default_device(mcsdk_audio_output o) { return mcsdk_device { OUTPUT(o)->GetDefaultDevice() }; } -mcsdk_export void mcsdk_output_release(mcsdk_output o) { +mcsdk_export void mcsdk_audio_output_release(mcsdk_audio_output o) { RELEASE(o, OUTPUT); } /* - * * IDecoder - * */ mcsdk_export double mcsdk_decoder_set_position(mcsdk_decoder d, double seconds) { @@ -769,9 +740,7 @@ mcsdk_export void mcsdk_decoder_release(mcsdk_decoder d) { } /* - * * IEncoder - * */ mcsdk_export void mcsdk_encoder_release(mcsdk_encoder e) { @@ -787,9 +756,7 @@ mcsdk_export mcsdk_encoder_type mcsdk_encoder_get_type(mcsdk_encoder e) { } /* - * * IBlockingEncoder - * */ mcsdk_export bool mcsdk_blocking_encoder_initialize(mcsdk_blocking_encoder be, mcsdk_data_stream out, size_t rate, size_t channels, size_t bitrate) { @@ -809,9 +776,7 @@ mcsdk_export void mcsdk_blocking_encoder_release(mcsdk_blocking_encoder be, mcsd } /* - * * IStreamingEncoder - * */ mcsdk_export bool mcsdk_streaming_encoder_initialize(mcsdk_streaming_encoder se, size_t rate, size_t channels, size_t bitrate) { @@ -835,9 +800,7 @@ mcsdk_export void mcsdk_streaming_encoder_release(mcsdk_streaming_encoder se, mc } /* - * * IDebug - * */ mcsdk_export void mcsdk_debug_verbose(const char* tag, const char* message) { @@ -857,9 +820,7 @@ mcsdk_export void mcsdk_debug_error(const char* tag, const char* message) { } /* - * - * IEnvironment (TODO) - * + * IEnvironment */ mcsdk_export size_t mcsdk_env_get_path(mcsdk_path_type type, char* dst, int size) { @@ -890,12 +851,12 @@ mcsdk_export size_t mcsdk_env_get_output_count() { return ENV.GetOutputCount(); } -mcsdk_export mcsdk_output mcsdk_env_get_output_at_index(size_t index) { - return mcsdk_output { ENV.GetOutputAtIndex(index) }; +mcsdk_export mcsdk_audio_output mcsdk_env_get_output_at_index(size_t index) { + return mcsdk_audio_output { ENV.GetOutputAtIndex(index) }; } -mcsdk_export mcsdk_output mcsdk_env_get_output_with_name(const char* name) { - return mcsdk_output { ENV.GetOutputWithName(name) }; +mcsdk_export mcsdk_audio_output mcsdk_env_get_output_with_name(const char* name) { + return mcsdk_audio_output { ENV.GetOutputWithName(name) }; } mcsdk_export mcsdk_replay_gain_mode mcsdk_env_get_replay_gain_mode() { @@ -934,12 +895,12 @@ mcsdk_export void mcsdk_env_reload_playback_output() { ENV.ReloadPlaybackOutput(); } -mcsdk_export void mcsdk_env_set_default_output(mcsdk_output output) { +mcsdk_export void mcsdk_env_set_default_output(mcsdk_audio_output output) { ENV.SetDefaultOutput(OUTPUT(output)); } -mcsdk_export mcsdk_output mcsdk_env_get_default_output() { - return mcsdk_output { ENV.GetDefaultOutput() }; +mcsdk_export mcsdk_audio_output mcsdk_env_get_default_output() { + return mcsdk_audio_output { ENV.GetDefaultOutput() }; } mcsdk_export mcsdk_transport_type mcsdk_env_get_transport_type() { @@ -950,3 +911,258 @@ mcsdk_export void mcsdk_env_set_transport_type(mcsdk_transport_type type) { ENV.SetTransportType((TransportType) type); } +/* + * IStream + */ + +mcsdk_export mcsdk_audio_stream mcsdk_audio_stream_create(int samples_per_channel, double buffer_length_seconds, mcsdk_audio_stream_flags options) { + return mcsdk_audio_stream { Stream::CreateUnmanaged(samples_per_channel, buffer_length_seconds, (StreamFlags) options) }; +} + +mcsdk_export mcsdk_audio_buffer mcsdk_audio_stream_get_next_buffer(mcsdk_audio_stream as) { + return mcsdk_audio_buffer { AUDIOSTREAM(as)->GetNextProcessedOutputBuffer() }; +} + +mcsdk_export void mcsdk_audio_stream_recycle_buffer(mcsdk_audio_stream as, mcsdk_audio_buffer ab) { + AUDIOSTREAM(as)->OnBufferProcessedByPlayer(BUFFER(ab)); +} + +mcsdk_export double mcsdk_audio_stream_set_position(mcsdk_audio_stream as, double seconds) { + return AUDIOSTREAM(as)->SetPosition(seconds); +} + +mcsdk_export double mcsdk_audio_stream_get_duration(mcsdk_audio_stream as) { + return AUDIOSTREAM(as)->GetDuration(); +} + +mcsdk_export bool mcsdk_audio_stream_open_uri(mcsdk_audio_stream as, const char* uri) { + return AUDIOSTREAM(as)->OpenStream(uri); +} + +mcsdk_export void mcsdk_audio_stream_interrupt(mcsdk_audio_stream as) { + AUDIOSTREAM(as)->Interrupt(); +} +mcsdk_export mcsdk_stream_capability mcsdk_audio_stream_get_capabilities(mcsdk_audio_stream as) { + return (mcsdk_stream_capability) AUDIOSTREAM(as)->GetCapabilities(); +} + +mcsdk_export bool mcsdk_audio_stream_is_eof(mcsdk_audio_stream as) { + return AUDIOSTREAM(as)->Eof(); +} + +mcsdk_export void mcsdk_audio_stream_release(mcsdk_audio_stream as) { + RELEASE(as, AUDIOSTREAM); +} + +/* + * Player + */ + +struct mcsdk_internal_player_context { + Player::EventListener* event_listener; + std::shared_ptr output; + std::mutex event_mutex; + std::condition_variable finished_condition; + Player* player; + bool player_finished; +}; + +class mcsdk_audio_player_callback_proxy: public Player::EventListener { + public: + std::set callbacks; + mcsdk_internal_player_context* context; + virtual void OnPlayerPrepared(Player *player) { + std::unique_lock lock(this->context->event_mutex); + for (auto c : callbacks) { + if (c->on_prepared) { + c->on_prepared(mcsdk_audio_player { context }); + } + } + } + virtual void OnPlayerStarted(Player *player) { + std::unique_lock lock(this->context->event_mutex); + for (auto c : callbacks) { + if (c->on_started) { + c->on_started(mcsdk_audio_player { context }); + } + } + } + virtual void OnPlayerAlmostEnded(Player *player) { + std::unique_lock lock(this->context->event_mutex); + for (auto c : callbacks) { + if (c->on_almost_ended) { + c->on_almost_ended(mcsdk_audio_player { context }); + } + } + } + virtual void OnPlayerFinished(Player *player) { + std::unique_lock lock(this->context->event_mutex); + for (auto c : callbacks) { + if (c->on_finished) { + c->on_finished(mcsdk_audio_player { context }); + } + } + } + virtual void OnPlayerError(Player *player) { + std::unique_lock lock(this->context->event_mutex); + for (auto c : callbacks) { + if (c->on_error) { + c->on_error(mcsdk_audio_player { context }); + } + } + } + virtual void OnPlayerDestroying(Player *player) { + std::unique_lock lock(this->context->event_mutex); + for (auto c : callbacks) { + if (c->on_destroying) { + c->on_destroying(mcsdk_audio_player { context }); + } + } + this->context->player_finished = true; + this->context->finished_condition.notify_all(); + } + virtual void OnPlayerMixPoint(Player *player, int id, double time) { + std::unique_lock lock(this->context->event_mutex); + for (auto c : callbacks) { + if (c->on_mixpoint) { + c->on_mixpoint(mcsdk_audio_player { context }, id, time); + } + } + } +}; + +#define PLAYER(x) reinterpret_cast(x.opaque) + +mcsdk_export mcsdk_audio_player mcsdk_audio_player_create(const char* url, mcsdk_audio_output output, mcsdk_audio_player_callbacks* callbacks, mcsdk_audio_player_gain gain) { + Player::Gain playerGain; + playerGain.gain = gain.gain; + playerGain.preamp = gain.preamp; + playerGain.peak = gain.peak; + playerGain.peakValid = gain.peakValid; + + auto callbackProxy = new mcsdk_audio_player_callback_proxy(); + + mcsdk_internal_player_context* playerContext = new mcsdk_internal_player_context(); + playerContext->event_listener = callbackProxy; + playerContext->player_finished = false; + + playerContext->output = std::shared_ptr(OUTPUT(output), [](IOutput*){}); + + playerContext->player = Player::Create( + url, + playerContext->output, + Player::DestroyMode::Drain, + playerContext->event_listener, + playerGain); + + callbackProxy->context = playerContext; + + if (callbacks) { + callbackProxy->callbacks.insert(callbacks); + } + + return mcsdk_audio_player { playerContext };; +} + +mcsdk_export int mcsdk_audio_player_get_url(mcsdk_audio_player ap, char* dst, int size) { + mcsdk_internal_player_context* context = PLAYER(ap); + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + return (int) CopyString(context->player->GetUrl(), dst, size); + } + return (int) CopyString("", dst, size); +} + +mcsdk_export void mcsdk_audio_player_detach(mcsdk_audio_player ap, mcsdk_audio_player_callbacks* callbacks) { + mcsdk_internal_player_context* context = PLAYER(ap); + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + auto proxy = reinterpret_cast(context->event_listener); + auto it = proxy->callbacks.find(callbacks); + if (it != proxy->callbacks.end()) { + proxy->callbacks.erase(it); + } + } +} + +mcsdk_export void mcsdk_audio_player_attach(mcsdk_audio_player ap, mcsdk_audio_player_callbacks* callbacks) { + mcsdk_internal_player_context* context = PLAYER(ap); + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + reinterpret_cast(context->event_listener)->callbacks.insert(callbacks); + } +} + +mcsdk_export void mcsdk_audio_player_play(mcsdk_audio_player ap) { + mcsdk_internal_player_context* context = PLAYER(ap); + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + context->player->Play(); + } +} + +mcsdk_export double mcsdk_audio_player_get_position(mcsdk_audio_player ap) { + mcsdk_internal_player_context* context = PLAYER(ap); + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + return context->player->GetPosition(); + } + return 0.0; +} + +mcsdk_export void mcsdk_audio_player_set_position(mcsdk_audio_player ap, double seconds) { + mcsdk_internal_player_context* context = PLAYER(ap); + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + context->player->SetPosition(seconds); + } +} + +mcsdk_export double mcsdk_audio_player_get_duration(mcsdk_audio_player ap) { + mcsdk_internal_player_context* context = PLAYER(ap); + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + return context->player->GetDuration(); + } + return 0.0; +} + +mcsdk_export void mcsdk_audio_player_add_mix_point(mcsdk_audio_player ap, int id, double time) { + mcsdk_internal_player_context* context = PLAYER(ap); + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + context->player->AddMixPoint(id, time); + } +} + +mcsdk_export bool mcsdk_audio_player_has_capability(mcsdk_audio_player ap, mcsdk_stream_capability capability) { + mcsdk_internal_player_context* context = PLAYER(ap); + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + return PLAYER(ap)->player->HasCapability((Capability) capability); + } + return false; +} + +mcsdk_export void mcsdk_audio_player_release(mcsdk_audio_player ap, mcsdk_audio_player_release_mode mode) { + mcsdk_internal_player_context* context = PLAYER(ap); + + { + std::unique_lock lock(context->event_mutex); + if (!context->player_finished) { + context->player->Destroy((Player::DestroyMode) mode); + while (!context->player_finished) { + context->finished_condition.wait(lock); + } + } + } + + delete context->event_listener; + delete context; + + ap.opaque = nullptr; +} + +mcsdk_export mcsdk_audio_player_gain mcsdk_audio_player_get_default_gain() { + return mcsdk_audio_player_gain { 1.0, 1.0, 0.0, false }; +} \ No newline at end of file diff --git a/src/core/library/Indexer.cpp b/src/core/library/Indexer.cpp index 9e10146f9..5872985dd 100644 --- a/src/core/library/Indexer.cpp +++ b/src/core/library/Indexer.cpp @@ -895,14 +895,14 @@ void Indexer::RunAnalyzers() { } if (!runningAnalyzers.empty()) { - audio::IStreamPtr stream = audio::Stream::Create(audio::IStream::NoDSP); + audio::IStreamPtr stream = audio::Stream::Create(2048, 2.0, StreamFlags::NoDSP); if (stream) { if (stream->OpenStream(track.Uri())) { /* decode the stream quickly, passing to all analyzers */ - audio::Buffer* buffer; + IBuffer* buffer; while ((buffer = stream->GetNextProcessedOutputBuffer()) && !runningAnalyzers.empty()) { PluginVector::iterator plugin = runningAnalyzers.begin(); diff --git a/src/core/musikcore_c.h b/src/core/musikcore_c.h index e9ac915c7..5f6af1f58 100644 --- a/src/core/musikcore_c.h +++ b/src/core/musikcore_c.h @@ -51,17 +51,13 @@ #endif /* - * * version - * */ static const int mcsdk_version = 18; /* - * * constants - * */ typedef enum mcsdk_playback_state { @@ -87,12 +83,12 @@ typedef enum mcsdk_repeat_mode { mcsdk_repeat_list = 2 } mcsdk_repeat_mode; -typedef enum mcsdk_output_code { - mcsdk_output_error_invalid_format = -4, - mcsdk_output_error_invalid_state = -3, - mcsdk_output_error_buffer_full = -2, - mcsdk_output_error_buffer_written = -1 -} mcsdk_output_code; +typedef enum mcsdk_audio_output_code { + mcsdk_audio_output_error_invalid_format = -4, + mcsdk_audio_output_error_invalid_state = -3, + mcsdk_audio_output_error_buffer_full = -2, + mcsdk_audio_output_error_buffer_written = -1 +} mcsdk_audio_output_code; typedef enum mcsdk_time_change_mode { mcsdk_time_change_mode_seek = 0, @@ -133,6 +129,11 @@ typedef enum mcsdk_stream_open_flags { mcsdk_stream_open_flags_write = 2 } mcsdk_stream_open_flags; +typedef enum mcsdk_audio_stream_flags { + mcsdk_audio_stream_flags_none = 0, + mcsdk_audio_stream_flags_no_dsp = 1 +} mcsdk_audio_stream_flags; + typedef enum mcsdk_resource_class { mcsdk_resource_type_value = 0, mcsdk_resource_type_map = 1 @@ -143,6 +144,11 @@ typedef enum mcsdk_encoder_type { mcsdk_encoder_type_streaming = 1 } mcsdk_encoder_type; +typedef enum mcsdk_audio_player_release_mode { + mcsdk_audio_player_release_mode_drain = 0, + mcsdk_audio_player_release_mode_no_drain = 1 +} mcsdk_audio_player_release_mode; + static const size_t mcsdk_equalizer_band_count = 18; static const size_t mcsdk_equalizer_bands[] = { @@ -182,9 +188,7 @@ static const char* mcsdk_track_field_source_id = "source_id"; static const char* mcsdk_track_field_external_id = "external_id"; /* - * * types - * */ #define mcsdk_define_handle(x) \ @@ -196,6 +200,8 @@ static const char* mcsdk_track_field_external_id = "external_id"; #define mcsdk_cast_handle(x) { x.opaque } +#define mcsdk_handle_equals(x, y) x.opaque == y.opaque + mcsdk_define_handle(mcsdk_internal); mcsdk_define_handle(mcsdk_resource); mcsdk_define_handle(mcsdk_value); @@ -213,16 +219,33 @@ mcsdk_define_handle(mcsdk_audio_buffer_provider); mcsdk_define_handle(mcsdk_data_stream); mcsdk_define_handle(mcsdk_device); mcsdk_define_handle(mcsdk_device_list); -mcsdk_define_handle(mcsdk_output); +mcsdk_define_handle(mcsdk_audio_output); mcsdk_define_handle(mcsdk_decoder); mcsdk_define_handle(mcsdk_encoder); mcsdk_define_handle(mcsdk_blocking_encoder); mcsdk_define_handle(mcsdk_streaming_encoder); +mcsdk_define_handle(mcsdk_audio_stream); +mcsdk_define_handle(mcsdk_audio_player); + +typedef struct mcsdk_audio_player_callbacks { + void (*on_prepared)(mcsdk_audio_player p); + void (*on_started)(mcsdk_audio_player p); + void (*on_almost_ended)(mcsdk_audio_player p); + void (*on_finished)(mcsdk_audio_player p); + void (*on_error)(mcsdk_audio_player p); + void (*on_destroying)(mcsdk_audio_player p); + void (*on_mixpoint)(mcsdk_audio_player p, int id, double time); +} mcsdk_audio_player_callbacks; + +typedef struct mcsdk_audio_player_gain { + float preamp; + float gain; + float peak; + float peakValid; +} mcsdk_audio_player_gain; /* - * * instance context - * */ typedef struct mcsdk_context { @@ -238,9 +261,7 @@ mcsdk_export void mcsdk_set_plugin_context(mcsdk_context* context); mcsdk_export bool mcsdk_is_plugin_context(mcsdk_context* context); /* - * * IResource - * */ mcsdk_export int64_t mcsdk_resource_get_id(mcsdk_resource r); @@ -248,18 +269,14 @@ mcsdk_export mcsdk_resource_class mcsdk_resource_get_class(mcsdk_resource r); mcsdk_export void mcsdk_resource_release(mcsdk_resource r); /* - * * IValue - * */ mcsdk_export size_t mcsdk_value_get_value(mcsdk_value v, char* dst, size_t size); mcsdk_export void mcsdk_value_release(mcsdk_value v); /* - * * IValueList - * */ mcsdk_export size_t mcsdk_value_list_count(mcsdk_value_list vl); @@ -267,9 +284,7 @@ mcsdk_export mcsdk_value mcsdk_value_list_get_at(mcsdk_value_list vl, size_t ind mcsdk_export void mcsdk_value_list_release(mcsdk_value_list vl); /* - * * IMap - * */ mcsdk_export int mcsdk_map_get_string(mcsdk_map m, const char* key, char* dst, int size); @@ -279,9 +294,7 @@ mcsdk_export double mcsdk_map_get_double(mcsdk_map m, const char* key, double de mcsdk_export void mcsdk_map_release(mcsdk_map m); /* - * * IMapList - * */ mcsdk_export size_t mcsdk_map_list_get_count(mcsdk_map_list ml); @@ -289,9 +302,7 @@ mcsdk_export mcsdk_map mcsdk_map_list_get_at(mcsdk_map_list ml, size_t index); mcsdk_export void mcsdk_map_list_release(mcsdk_map_list ml); /* - * * ITrack - * */ mcsdk_export void mcsdk_track_retain(mcsdk_track t); @@ -299,9 +310,7 @@ mcsdk_export int mcsdk_track_get_uri(mcsdk_track t, char* dst, int size); mcsdk_export void mcsdk_track_release(mcsdk_track t); /* - * * ITrackList - * */ mcsdk_export size_t mcsdk_track_list_get_count(mcsdk_track_list tl); @@ -311,9 +320,7 @@ mcsdk_export mcsdk_track mcsdk_track_list_get_track_at(mcsdk_track_list tl, size mcsdk_export void mcsdk_track_list_release(mcsdk_track_list tl); /* - * * ITrackListEditor - * */ mcsdk_export bool mcsdk_track_list_editor_insert(mcsdk_track_list_editor tle, int64_t id, size_t index); @@ -326,9 +333,7 @@ mcsdk_export void mcsdk_track_list_editor_shuffle(mcsdk_track_list_editor tle); mcsdk_export void mcsdk_track_list_editor_release(mcsdk_track_list_editor tle); /* - * * IMetadataProxy - * */ mcsdk_export mcsdk_track_list mcsdk_svc_metadata_query_tracks(mcsdk_svc_metadata mp, const char* keyword, int limit, int offset); @@ -355,9 +360,7 @@ mcsdk_export size_t mcsdk_svc_metadata_remove_tracks_from_playlist(mcsdk_svc_met mcsdk_export void mcsdk_svc_metadata_release(mcsdk_svc_metadata mp); /* - * * IPlaybackService - * */ mcsdk_export void mcsdk_svc_playback_play_at(mcsdk_svc_playback pb, size_t index); @@ -391,9 +394,7 @@ mcsdk_export void mcsdk_svc_playback_reload_output(mcsdk_svc_playback pb); mcsdk_export mcsdk_track_list mcsdk_svc_playback_clone(mcsdk_svc_playback pb); /* - * * IPreferences - * */ mcsdk_export bool mcsdk_prefs_get_bool(mcsdk_prefs p, const char* key, bool defaultValue); @@ -407,9 +408,7 @@ mcsdk_export void mcsdk_prefs_save(mcsdk_prefs p); mcsdk_export void mcsdk_prefs_release(mcsdk_prefs p); /* - * * IDataStream - * */ mcsdk_export bool mcsdk_data_stream_open(mcsdk_data_stream ds, const char *uri, mcsdk_stream_open_flags flags); @@ -430,9 +429,7 @@ mcsdk_export bool mcsdk_data_stream_can_prefetch(mcsdk_data_stream ds); mcsdk_export void mcsdk_data_stream_release(mcsdk_data_stream ds); /* - * * IBuffer - * */ mcsdk_export long mcsdk_audio_buffer_get_sample_rate(mcsdk_audio_buffer ab); @@ -446,17 +443,13 @@ mcsdk_export long mcsdk_audio_buffer_get_byte_count(mcsdk_audio_buffer ab); mcsdk_export void mcsdk_audio_buffer_release(mcsdk_audio_buffer ab); /* - * * IBufferProvider - * */ mcsdk_export void mcsdk_audio_buffer_provider_notify_processed(mcsdk_audio_buffer_provider abp, mcsdk_audio_buffer ab); /* - * * IDevice - * */ mcsdk_export const char* mcsdk_device_get_name(mcsdk_device d); @@ -464,9 +457,7 @@ mcsdk_export const char* mcsdk_device_get_id(mcsdk_device d); mcsdk_export void mcsdk_device_release(mcsdk_device d); /* - * * IDeviceList - * */ mcsdk_export size_t mcsdk_device_list_get_count(mcsdk_device_list dl); @@ -474,29 +465,25 @@ mcsdk_export const mcsdk_device mcsdk_device_list_get_at(mcsdk_device_list dl, s mcsdk_export void mcsdk_device_list_release(mcsdk_device_list dl); /* - * * IOutput - * */ -mcsdk_export void mcsdk_output_pause(mcsdk_output o); -mcsdk_export void mcsdk_output_resume(mcsdk_output o); -mcsdk_export void mcsdk_output_set_volume(mcsdk_output o, double volume); -mcsdk_export double mcsdk_output_get_volume(mcsdk_output o); -mcsdk_export void mcsdk_output_stop(mcsdk_output o); -mcsdk_export int mcsdk_output_play(mcsdk_output o, mcsdk_audio_buffer ab, mcsdk_audio_buffer_provider abp); -mcsdk_export void mcsdk_output_drain(mcsdk_output o); -mcsdk_export double mcsdk_output_get_latency(mcsdk_output o); -mcsdk_export const char* mcsdk_output_get_name(mcsdk_output o); -mcsdk_export mcsdk_device_list mcsdk_output_get_device_list(mcsdk_output o); -mcsdk_export bool mcsdk_output_set_default_device(mcsdk_output o, const char* device_id); -mcsdk_export mcsdk_device mcsdk_output_get_default_device(mcsdk_output o); -mcsdk_export void mcsdk_output_release(mcsdk_output o); +mcsdk_export void mcsdk_audio_output_pause(mcsdk_audio_output o); +mcsdk_export void mcsdk_audio_output_resume(mcsdk_audio_output o); +mcsdk_export void mcsdk_audio_output_set_volume(mcsdk_audio_output o, double volume); +mcsdk_export double mcsdk_audio_output_get_volume(mcsdk_audio_output o); +mcsdk_export void mcsdk_audio_output_stop(mcsdk_audio_output o); +mcsdk_export int mcsdk_audio_output_play(mcsdk_audio_output o, mcsdk_audio_buffer ab, mcsdk_audio_buffer_provider abp); +mcsdk_export void mcsdk_audio_output_drain(mcsdk_audio_output o); +mcsdk_export double mcsdk_audio_output_get_latency(mcsdk_audio_output o); +mcsdk_export const char* mcsdk_audio_output_get_name(mcsdk_audio_output o); +mcsdk_export mcsdk_device_list mcsdk_audio_output_get_device_list(mcsdk_audio_output o); +mcsdk_export bool mcsdk_audio_output_set_default_device(mcsdk_audio_output o, const char* device_id); +mcsdk_export mcsdk_device mcsdk_audio_output_get_default_device(mcsdk_audio_output o); +mcsdk_export void mcsdk_audio_output_release(mcsdk_audio_output o); /* - * * IDecoder - * */ mcsdk_export double mcsdk_decoder_set_position(mcsdk_decoder d, double seconds); @@ -507,18 +494,14 @@ mcsdk_export bool mcsdk_decoder_is_eof(mcsdk_decoder d); mcsdk_export void mcsdk_decoder_release(mcsdk_decoder d); /* - * * IEncoder - * */ mcsdk_export mcsdk_encoder_type mcsdk_encoder_get_type(mcsdk_encoder e); mcsdk_export void mcsdk_encoder_release(mcsdk_encoder e); /* - * * IBlockingEncoder - * */ mcsdk_export bool mcsdk_blocking_encoder_initialize(mcsdk_blocking_encoder be, mcsdk_data_stream out, size_t rate, size_t channels, size_t bitrate); @@ -527,9 +510,7 @@ mcsdk_export void mcsdk_blocking_encoder_finalize(mcsdk_blocking_encoder be); mcsdk_export void mcsdk_blocking_encoder_release(mcsdk_blocking_encoder be, mcsdk_encoder e); /* - * * IStreamingEncoder - * */ mcsdk_export bool mcsdk_streaming_encoder_initialize(mcsdk_streaming_encoder se, size_t rate, size_t channels, size_t bitrate); @@ -539,9 +520,7 @@ mcsdk_export void mcsdk_streaming_encoder_finalize(mcsdk_streaming_encoder se, c mcsdk_export void mcsdk_streaming_encoder_release(mcsdk_streaming_encoder se, mcsdk_encoder e); /* - * * IDebug - * */ mcsdk_export void mcsdk_debug_verbose(const char* tag, const char* message); @@ -550,9 +529,7 @@ mcsdk_export void mcsdk_debug_warning(const char* tag, const char* message); mcsdk_export void mcsdk_debug_error(const char* tag, const char* message); /* - * * IEnvironment - * */ mcsdk_export size_t mcsdk_env_get_path(mcsdk_path_type type, char* dst, int size); @@ -562,8 +539,8 @@ mcsdk_export mcsdk_encoder mcsdk_env_open_encoder(const char* type) ; mcsdk_export mcsdk_audio_buffer mcsdk_env_create_audio_buffer(size_t samples, size_t rate, size_t channels); mcsdk_export mcsdk_prefs mcsdk_env_open_preferences(const char* name); mcsdk_export size_t mcsdk_env_get_output_count(); -mcsdk_export mcsdk_output mcsdk_env_get_output_at_index(size_t index); -mcsdk_export mcsdk_output mcsdk_env_get_output_with_name(const char* name); +mcsdk_export mcsdk_audio_output mcsdk_env_get_output_at_index(size_t index); +mcsdk_export mcsdk_audio_output mcsdk_env_get_output_with_name(const char* name); mcsdk_export mcsdk_replay_gain_mode mcsdk_env_get_replay_gain_mode(); mcsdk_export void mcsdk_env_set_replay_gain_mode(mcsdk_replay_gain_mode mode); mcsdk_export float mcsdk_env_get_preamp_gain(); @@ -573,9 +550,41 @@ mcsdk_export void mcsdk_env_set_equalizer_enabled(bool enabled); mcsdk_export bool mcsdk_env_get_equalizer_band_values(double target[], size_t count); mcsdk_export bool mcsdk_env_set_equalizer_band_values(double values[], size_t count); mcsdk_export void mcsdk_env_reload_playback_output(); -mcsdk_export void mcsdk_env_set_default_output(mcsdk_output output); -mcsdk_export mcsdk_output mcsdk_env_get_default_output(); +mcsdk_export void mcsdk_env_set_default_output(mcsdk_audio_output output); +mcsdk_export mcsdk_audio_output mcsdk_env_get_default_output(); mcsdk_export mcsdk_transport_type mcsdk_env_get_transport_type(); mcsdk_export void mcsdk_env_set_transport_type(mcsdk_transport_type type); +/* + * IStream + */ + +mcsdk_export mcsdk_audio_stream mcsdk_audio_stream_create(int samples_per_channel, double buffer_length_seconds, mcsdk_audio_stream_flags options); +mcsdk_export mcsdk_audio_buffer mcsdk_audio_stream_get_next_buffer(mcsdk_audio_stream as); +mcsdk_export void mcsdk_audio_stream_recycle_buffer(mcsdk_audio_stream as, mcsdk_audio_buffer ab); +mcsdk_export double mcsdk_audio_stream_set_position(mcsdk_audio_stream as, double seconds); +mcsdk_export double mcsdk_audio_stream_get_duration(mcsdk_audio_stream as); +mcsdk_export bool mcsdk_audio_stream_open_uri(mcsdk_audio_stream as, const char* uri); +mcsdk_export void mcsdk_audio_stream_interrupt(mcsdk_audio_stream as); +mcsdk_export mcsdk_stream_capability mcsdk_audio_stream_get_capabilities(mcsdk_audio_stream as); +mcsdk_export bool mcsdk_audio_stream_is_eof(mcsdk_audio_stream as); +mcsdk_export void mcsdk_audio_stream_release(mcsdk_audio_stream as); + +/* + * Player + */ + +mcsdk_export mcsdk_audio_player mcsdk_audio_player_create(const char* url, mcsdk_audio_output output, mcsdk_audio_player_callbacks* callbacks, mcsdk_audio_player_gain gain); +mcsdk_export int mcsdk_audio_player_get_url(mcsdk_audio_player ap, char* dst, int size); +mcsdk_export void mcsdk_audio_player_detach(mcsdk_audio_player ap, mcsdk_audio_player_callbacks* callbacks); +mcsdk_export void mcsdk_audio_player_attach(mcsdk_audio_player ap, mcsdk_audio_player_callbacks* callbacks); +mcsdk_export void mcsdk_audio_player_play(mcsdk_audio_player ap); +mcsdk_export double mcsdk_audio_player_get_position(mcsdk_audio_player ap); +mcsdk_export void mcsdk_audio_player_set_position(mcsdk_audio_player ap, double seconds); +mcsdk_export double mcsdk_audio_player_get_duration(mcsdk_audio_player ap); +mcsdk_export void mcsdk_audio_player_add_mix_point(mcsdk_audio_player ap, int id, double time); +mcsdk_export bool mcsdk_audio_player_has_capability(mcsdk_audio_player ap, mcsdk_stream_capability capability); +mcsdk_export mcsdk_audio_player_gain mcsdk_audio_player_get_default_gain(); +mcsdk_export void mcsdk_audio_player_release(mcsdk_audio_player ap, mcsdk_audio_player_release_mode mode); + #endif \ No newline at end of file diff --git a/src/core/sdk/constants.h b/src/core/sdk/constants.h index 76b9b3a76..e4e03a5f7 100644 --- a/src/core/sdk/constants.h +++ b/src/core/sdk/constants.h @@ -109,6 +109,11 @@ namespace musik { Write = 2 }; + enum class StreamFlags: int { + None = 0, + NoDSP = 1 + }; + static const size_t EqualizerBandCount = 18; static const size_t EqualizerBands[] = { diff --git a/src/core_c_demo/main.c b/src/core_c_demo/main.c index 6a77b55cd..a7efa99cd 100644 --- a/src/core_c_demo/main.c +++ b/src/core_c_demo/main.c @@ -1,5 +1,7 @@ #ifdef WIN32 #include +#else +#include #endif #include @@ -20,7 +22,7 @@ static void internal_sleep(int seconds) { #ifdef WIN32 Sleep(seconds * 1000); #else - usleep(1000000); + usleep(seconds * 1000000); #endif } @@ -54,19 +56,36 @@ static void test_decode_encode() { printf("test_decode_encode: done.\n"); } -static void test_playback(mcsdk_context* context) { +static void test_low_level_playback() { + mcsdk_audio_player_gain gain = mcsdk_audio_player_get_default_gain(); + mcsdk_audio_output output = mcsdk_env_get_default_output(); + mcsdk_audio_player player = mcsdk_audio_player_create(INPUT_FILE, output, NULL, gain); + mcsdk_audio_output_set_volume(output, 0.75); + mcsdk_audio_output_resume(output); + mcsdk_audio_player_play(player); + printf("test_low_level_playback: playing for 5 seconds...\n"); + for (int i = 0; i < 5; i++) { + internal_sleep(1); + printf(" %d\n", i + 1); + } + mcsdk_audio_player_release(player, mcsdk_audio_player_release_mode_no_drain); + mcsdk_audio_output_release(output); + printf("test_low_level_playback: done.\n"); +} + +static void test_high_level_playback(mcsdk_context* context) { printf("test_playback: loading 'a day in the life' tracks\n"); mcsdk_track_list tl = mcsdk_svc_metadata_query_tracks( context->metadata, "a day in the life", mcsdk_no_limit, mcsdk_no_offset); mcsdk_svc_playback_play(context->playback, tl, 0); mcsdk_track_list_release(tl); - printf("test_playback: playing for 5 seconds...\n"); + printf("test_high_level_playback: playing for 5 seconds...\n"); for (int i = 0; i < 5; i++) { internal_sleep(1); - printf(" %d\n", i + 1); + printf(" %d\n", i + 1); } mcsdk_svc_playback_stop(context->playback); - printf("test_playback: done.\n"); + printf("test_high_level_playback: done.\n"); } static void test_metadata(mcsdk_context* context) { @@ -91,8 +110,9 @@ int main(int argc, char** argv) { if (context) { printf("main: context initialized\n"); test_metadata(context); - test_playback(context); - test_decode_encode(context); + test_low_level_playback(); + test_high_level_playback(context); + test_decode_encode(); mcsdk_context_release(&context); printf("main: context released\n"); } diff --git a/src/plugins/alsaout/AlsaOut.cpp b/src/plugins/alsaout/AlsaOut.cpp index ee86d102a..4cb6fbe03 100755 --- a/src/plugins/alsaout/AlsaOut.cpp +++ b/src/plugins/alsaout/AlsaOut.cpp @@ -315,7 +315,7 @@ double AlsaOut::Latency() { snd_pcm_get_params(this->pcmHandle, &bufferSize, &periodSize); if (bufferSize) { - this->latency = + this->latency = (double) bufferSize / (double) (this->rate * this->channels * sizeof(float)); }