From 1e7bf213ae6ad58e144f2d4e031669d471738857 Mon Sep 17 00:00:00 2001 From: DoumanAsh Date: Sun, 21 Aug 2022 14:00:34 +0900 Subject: [PATCH 01/16] Add gstreamer based audioplayers plugin --- CMakeLists.txt | 15 +- include/plugins/audioplayers.h | 53 ++++ src/plugins/audioplayers/player.c | 413 ++++++++++++++++++++++++++++++ src/plugins/audioplayers/plugin.c | 211 +++++++++++++++ 4 files changed, 688 insertions(+), 4 deletions(-) create mode 100644 include/plugins/audioplayers.h create mode 100644 src/plugins/audioplayers/player.c create mode 100644 src/plugins/audioplayers/plugin.c diff --git a/CMakeLists.txt b/CMakeLists.txt index cd51cf1d..07ffe8d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,8 +40,8 @@ option(BUILD_TEXT_INPUT_PLUGIN "Include the text input plugin in the finished bi option(BUILD_RAW_KEYBOARD_PLUGIN "Include the raw keyboard plugin in the finished binary. Enables raw keycode listening in flutter via the flutter RawKeyboard interface." ON) option(BUILD_TEST_PLUGIN "Include the test plugin in the finished binary. Allows testing platform channel communication." OFF) option(BUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN "Include the omxplayer_video_player plugin in the finished binary. Allows for hardware accelerated video playback in flutter using omxplayer." ON) -option(BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN "Include the gstreamer_video_player plugin in the finished binary. Allows for more stable, hardware accelerated video playback in flutter using gstreamer." ON) -option(TRY_BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN "Don't throw an error if the gstreamer libs aren't found, instead just don't build the gstreamer video player plugin in that case." ON) +option(BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN "Include the gstreamer based video and audio plugins in the finished binary. Allows for more stable, hardware accelerated video playback in flutter using gstreamer." ON) +option(TRY_BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN "Don't throw an error if the gstreamer libs aren't found, instead just don't build the gstreamer audio and video player plugin in that case." ON) option(DUMP_ENGINE_LAYERS "True if flutter-pi should dump the list of rendering layers that the flutter engine sends to flutter-pi on each draw." OFF) option(ENABLE_TSAN "True to build & link with -fsanitize=thread" OFF) option(ENABLE_ASAN "True to build & link with -fsanitize=address" OFF) @@ -191,19 +191,21 @@ endif() if (OMXPLAYER_SUPPORTS_RUNTIME_ROTATION) target_compile_definitions(flutter-pi PRIVATE "OMXPLAYER_SUPPORTS_RUNTIME_ROTATION") endif() -if (BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN) - if (TRY_BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN) +if (BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN) + if (TRY_BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN) pkg_check_modules(LIBGSTREAMER gstreamer-1.0) pkg_check_modules(LIBGSTREAMER_PLUGINS_BASE gstreamer-plugins-base-1.0) pkg_check_modules(LIBGSTREAMER_APP gstreamer-app-1.0) pkg_check_modules(LIBGSTREAMER_ALLOCATORS gstreamer-allocators-1.0) pkg_check_modules(LIBGSTREAMER_VIDEO gstreamer-video-1.0) + pkg_check_modules(LIBGSTREAMER-AUDIO REQUIRED gstreamer-audio-1.0) else() pkg_check_modules(LIBGSTREAMER REQUIRED gstreamer-1.0) pkg_check_modules(LIBGSTREAMER_PLUGINS_BASE REQUIRED gstreamer-plugins-base-1.0) pkg_check_modules(LIBGSTREAMER_APP REQUIRED gstreamer-app-1.0) pkg_check_modules(LIBGSTREAMER_ALLOCATORS REQUIRED gstreamer-allocators-1.0) pkg_check_modules(LIBGSTREAMER_VIDEO REQUIRED gstreamer-video-1.0) + pkg_check_modules(LIBGSTREAMER-AUDIO REQUIRED gstreamer-audio-1.0) endif() if (LIBGSTREAMER_FOUND AND LIBGSTREAMER_PLUGINS_BASE_FOUND AND LIBGSTREAMER_APP_FOUND AND LIBGSTREAMER_ALLOCATORS_FOUND AND LIBGSTREAMER_VIDEO_FOUND) @@ -211,6 +213,8 @@ if (BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN) src/plugins/gstreamer_video_player/plugin.c src/plugins/gstreamer_video_player/player.c src/plugins/gstreamer_video_player/frame.c + src/plugins/audioplayers/plugin.c + src/plugins/audioplayers/player.c ) target_compile_definitions(flutter-pi PRIVATE "BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN") target_link_libraries(flutter-pi @@ -219,6 +223,7 @@ if (BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN) ${LIBGSTREAMER_APP_LDFLAGS} ${LIBGSTREAMER_ALLOCATORS_LDFLAGS} ${LIBGSTREAMER_VIDEO_LDFLAGS} + ${LIBGSTREAMER-AUDIO_LIBRARY_DIRS} ) target_include_directories(flutter-pi PRIVATE ${LIBGSTREAMER_INCLUDE_DIRS} @@ -226,6 +231,7 @@ if (BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN) ${LIBGSTREAMER_APP_INCLUDE_DIRS} ${LIBGSTREAMER_ALLOCATORS_INCLUDE_DIRS} ${LIBGSTREAMER_VIDEO_INCLUDE_DIRS} + ${LIBGSTREAMER-AUDIO_INCLUDE_DIRS} ) target_compile_options(flutter-pi PRIVATE ${LIBGSTREAMER_CFLAGS} @@ -233,6 +239,7 @@ if (BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN) ${LIBGSTREAMER_APP_CFLAGS} ${LIBGSTREAMER_ALLOCATORS_CFLAGS} ${LIBGSTREAMER_VIDEO_CFLAGS} + ${LIBGSTREAMER_AUDIO_CFLAGS} ) else() message(NOTICE "Couldn't find gstreamer libraries. Gstreamer video player plugin won't be build.") diff --git a/include/plugins/audioplayers.h b/include/plugins/audioplayers.h new file mode 100644 index 00000000..2e48843e --- /dev/null +++ b/include/plugins/audioplayers.h @@ -0,0 +1,53 @@ +#ifndef AUDIOPLAYERS_H_ +#define AUDIOPLAYERS_H_ + +#include +#include + +typedef struct AudioPlayer +{ + GstElement* playbin; + GstElement* source; + GstBus* bus; + + bool _isInitialized; + bool _isLooping; + bool _isSeekCompleted; + double _playbackRate; + + char* url; + char* playerId; + /* FlMethodChannel* _channel; */ + char* _channel; + +} AudioPlayer; + +AudioPlayer* AudioPlayer_new(char* playerId, char* channel); + +// Instance function + +int64_t AudioPlayer_GetPosition(AudioPlayer* self); + +int64_t AudioPlayer_GetDuration(AudioPlayer* self); + +bool AudioPlayer_GetLooping(AudioPlayer* self); + +void AudioPlayer_Play(AudioPlayer* self); + +void AudioPlayer_Pause(AudioPlayer* self); + +void AudioPlayer_Resume(AudioPlayer* self); + +void AudioPlayer_Dispose(AudioPlayer* self); + +void AudioPlayer_SetLooping(AudioPlayer* self, bool isLooping); + +void AudioPlayer_SetVolume(AudioPlayer* self, double volume); + +void AudioPlayer_SetPlaybackRate(AudioPlayer* self, double rate); + +void AudioPlayer_SetPosition(AudioPlayer* self, int64_t position); + +void AudioPlayer_SetSourceUrl(AudioPlayer* self, char* url); + +#endif // AUDIOPLAYERS_H_ diff --git a/src/plugins/audioplayers/player.c b/src/plugins/audioplayers/player.c new file mode 100644 index 00000000..da3dfca1 --- /dev/null +++ b/src/plugins/audioplayers/player.c @@ -0,0 +1,413 @@ +#include "gst/gst.h" +#include "gst/gstelementfactory.h" +#include "gst/gstmessage.h" +#include "gst/gstsegment.h" +#include "platformchannel.h" +#include +#include +#include + +FILE_DESCR("AudioPlayer::player") + +// Private Class functions +void AudioPlayer_SourceSetup(GstElement* playbin, GstElement* source, GstElement** p_src); +gboolean AudioPlayer_OnBusMessage(GstBus* bus, GstMessage* message, AudioPlayer* data); +gboolean AudioPlayer_OnRefresh(AudioPlayer* data); + +// Private methods +void AudioPlayer_SetPlayback(AudioPlayer* self, int64_t seekTo, double rate); +void AudioPlayer_OnMediaError(AudioPlayer* self, GError* error, gchar* debug); +void AudioPlayer_OnMediaStateChange(AudioPlayer* self, GstObject* src, GstState* old_state, GstState* new_state); +void AudioPlayer_OnPositionUpdate(AudioPlayer* self); +void AudioPlayer_OnDurationUpdate(AudioPlayer* self); +void AudioPlayer_OnSeekCompleted(AudioPlayer* self); +void AudioPlayer_OnPlaybackEnded(AudioPlayer* self); + +static int on_bus_fd_ready(sd_event_source* s, int fd, uint32_t revents, void* userdata) +{ + struct AudioPlayer* player = userdata; + GstMessage* msg; + + (void)s; + (void)fd; + (void)revents; + + /* DEBUG_TRACE_BEGIN(player, "on_bus_fd_ready"); */ + + msg = gst_bus_pop(player->bus); + if (msg != NULL) { + AudioPlayer_OnBusMessage(player->bus, msg, player); + gst_message_unref(msg); + } + + /* DEBUG_TRACE_END(player, "on_bus_fd_ready"); */ + + return 0; +} + +AudioPlayer* AudioPlayer_new(char* playerId, char* channel) +{ + AudioPlayer* self = malloc(sizeof(AudioPlayer)); + if (self == NULL) { + return NULL; + } + + self->url = NULL; + self->_isInitialized = false; + self->_isLooping = false; + self->_isSeekCompleted = false; + self->_playbackRate = 1.0; + + gst_init(NULL, NULL); + self->playbin = gst_element_factory_make("playbin", "playbin"); + if (!self->playbin) { + LOG_ERROR("Not all elements could be created"); + } + g_signal_connect(self->playbin, "source-setup", G_CALLBACK(AudioPlayer_SourceSetup), &self->source); + + self->bus = gst_element_get_bus(self->playbin); + + // Watch bus messages for one time events + // gst_bus_add_watch(self->bus, (GstBusFunc)AudioPlayer_OnBusMessage, self); + + GPollFD fd; + sd_event_source* busfd_event_source; + gst_bus_get_pollfd(self->bus, &fd); + + flutterpi_sd_event_add_io(&busfd_event_source, fd.fd, EPOLLIN, on_bus_fd_ready, self); + + // Refresh continuously to emit reoccuring events + g_timeout_add(1000, (GSourceFunc)AudioPlayer_OnRefresh, self); + + self->playerId = malloc(strlen(playerId) + 1); + if (self->playerId == NULL) + goto deinit_ptr; + strcpy(self->playerId, playerId); + + self->_channel = malloc(strlen(channel) + 1); + if (self->_channel == NULL) + goto deinit_player_id; + strcpy(self->_channel, channel); + + return self; + + // NOTE: deinit other stuff? + +deinit_player_id: + free(self->playerId); + +deinit_ptr: + free(self); + return NULL; +} + +void AudioPlayer_SourceSetup(GstElement* playbin, GstElement* source, GstElement** p_src) +{ + (void)playbin; + (void)p_src; + if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "ssl-strict") != 0) { + g_object_set(G_OBJECT(source), "ssl-strict", FALSE, NULL); + } +} + +gboolean AudioPlayer_OnBusMessage(GstBus* bus, GstMessage* message, AudioPlayer* data) +{ + (void)bus; + switch (GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_ERROR: { + GError* err; + gchar* debug; + + gst_message_parse_error(message, &err, &debug); + AudioPlayer_OnMediaError(data, err, debug); + g_error_free(err); + g_free(debug); + break; + } + case GST_MESSAGE_STATE_CHANGED: { + GstState old_state, new_state; + + gst_message_parse_state_changed(message, &old_state, &new_state, NULL); + AudioPlayer_OnMediaStateChange(data, message->src, &old_state, &new_state); + break; + } + case GST_MESSAGE_EOS: + gst_element_set_state(data->playbin, GST_STATE_READY); + AudioPlayer_OnPlaybackEnded(data); + break; + case GST_MESSAGE_DURATION_CHANGED: + AudioPlayer_OnDurationUpdate(data); + break; + case GST_MESSAGE_ASYNC_DONE: + if (!data->_isSeekCompleted) { + AudioPlayer_OnSeekCompleted(data); + data->_isSeekCompleted = true; + } + break; + default: + // For more GstMessage types see: + // https://gstreamer.freedesktop.org/documentation/gstreamer/gstmessage.html?gi-language=c#enumerations + break; + } + + // Continue watching for messages + return TRUE; +} + +gboolean AudioPlayer_OnRefresh(AudioPlayer* data) +{ + if (data->playbin->current_state == GST_STATE_PLAYING) { + AudioPlayer_OnPositionUpdate(data); + } + return TRUE; +} + +void AudioPlayer_SetPlayback(AudioPlayer* self, int64_t seekTo, double rate) +{ + if (!self->_isInitialized) { + return; + } + // See: + // https://gstreamer.freedesktop.org/documentation/tutorials/basic/playback-speed.html?gi-language=c + if (!self->_isSeekCompleted) { + return; + } + if (rate == 0) { + // Do not set rate if it's 0, rather pause. + AudioPlayer_Pause(self); + return; + } + + if (self->_playbackRate != rate) { + self->_playbackRate = rate; + } + self->_isSeekCompleted = false; + + GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE; + GstEvent* seek_event; + if (rate > 0) { + seek_event = + gst_event_new_seek(rate, GST_FORMAT_TIME, seek_flags, GST_SEEK_TYPE_SET, seekTo * GST_MSECOND, GST_SEEK_TYPE_NONE, -1); + } else { + seek_event = + gst_event_new_seek(rate, GST_FORMAT_TIME, seek_flags, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, seekTo * GST_MSECOND); + } + if (!gst_element_send_event(self->playbin, seek_event)) { + // FIXME + LOG_ERROR("Could not set playback to position %ld and rate %f.", seekTo, rate); + self->_isSeekCompleted = true; + } +} +void AudioPlayer_OnMediaError(AudioPlayer* self, GError* error, gchar* debug) +{ + (void)debug; + char* error_message = malloc(256 * sizeof(char)); + snprintf(error_message, 256, "Error: %d; message=%s", error->code, error->message); + LOG_ERROR("%s", error_message); + if (self->_channel) { + platch_call_std( + self->_channel, + "audio.onError", + &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDSTRING(error_message)), + NULL, + NULL); + } +} + +void AudioPlayer_OnMediaStateChange(AudioPlayer* self, GstObject* src, GstState* old_state, GstState* new_state) +{ + (void)old_state; + if (strcmp(GST_OBJECT_NAME(src), "playbin") == 0) { + if (*new_state >= GST_STATE_READY) { + if (!self->_isInitialized) { + self->_isInitialized = true; + AudioPlayer_Pause(self); // Need to set to pause state, in order to get duration + } + } else if (self->_isInitialized) { + self->_isInitialized = false; + } + } +} +void AudioPlayer_OnPositionUpdate(AudioPlayer* self) +{ + if (self->_channel) { + platch_call_std( + self->_channel, + "audio.onCurrentPosition", + &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDINT64(AudioPlayer_GetPosition(self))), + NULL, + NULL); + } +} +void AudioPlayer_OnDurationUpdate(AudioPlayer* self) +{ + if (self->_channel) { + platch_call_std( + self->_channel, + "audio.onDuration", + &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDINT64(AudioPlayer_GetDuration(self))), + NULL, + NULL); + } +} +void AudioPlayer_OnSeekCompleted(AudioPlayer* self) +{ + if (self->_channel) { + AudioPlayer_OnPositionUpdate(self); + platch_call_std( + self->_channel, + "audio.onSeekComplete", + &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDBOOL(true)), + NULL, + NULL); + } +} +void AudioPlayer_OnPlaybackEnded(AudioPlayer* self) +{ + AudioPlayer_SetPosition(self, 0); + if (AudioPlayer_GetLooping(self)) { + AudioPlayer_Play(self); + } + if (self->_channel) { + platch_call_std( + self->_channel, + "audio.onComplete", + &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDBOOL(true)), + NULL, + NULL); + } +} + +void AudioPlayer_SetLooping(AudioPlayer* self, bool isLooping) +{ + self->_isLooping = isLooping; +} + +bool AudioPlayer_GetLooping(AudioPlayer* self) +{ + return self->_isLooping; +} + +void AudioPlayer_Play(AudioPlayer* self) +{ + if (!self->_isInitialized) { + return; + } + AudioPlayer_SetPosition(self, 0); + AudioPlayer_Resume(self); +} + +void AudioPlayer_Pause(AudioPlayer* self) +{ + GstStateChangeReturn ret = gst_element_set_state(self->playbin, GST_STATE_PAUSED); + if (ret == GST_STATE_CHANGE_FAILURE) { + LOG_ERROR("Unable to set the pipeline to the paused state."); + return; + } + AudioPlayer_OnPositionUpdate(self); // Update to exact position when pausing +} + +void AudioPlayer_Resume(AudioPlayer* self) +{ + if (!self->_isInitialized) { + return; + } + GstStateChangeReturn ret = gst_element_set_state(self->playbin, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) { + LOG_ERROR("Unable to set the pipeline to the playing state."); + return; + } + AudioPlayer_OnDurationUpdate(self); // Update duration when start playing, as no event is emitted elsewhere +} + +void AudioPlayer_Dispose(AudioPlayer* self) +{ + if (self->_isInitialized) { + AudioPlayer_Pause(self); + } + gst_object_unref(self->bus); + gst_object_unref(self->source); + + gst_element_set_state(self->playbin, GST_STATE_NULL); + gst_object_unref(self->playbin); + + self->_isInitialized = false; + + if (self->url != NULL) { + free(self->url); + self->url = NULL; + } + + if (self->playerId != NULL) { + free(self->playerId); + self->playerId = NULL; + } + + if (self->_channel != NULL) { + free(self->_channel); + self->_channel = NULL; + } +} + +int64_t AudioPlayer_GetPosition(AudioPlayer* self) +{ + gint64 current = 0; + if (!gst_element_query_position(self->playbin, GST_FORMAT_TIME, ¤t)) { + LOG_ERROR("Could not query current position."); + return 0; + } + return current / 1000000; +} + +int64_t AudioPlayer_GetDuration(AudioPlayer* self) +{ + gint64 duration = 0; + if (!gst_element_query_duration(self->playbin, GST_FORMAT_TIME, &duration)) { + LOG_ERROR("Could not query current duration."); + return 0; + } + return duration / 1000000; +} + +void AudioPlayer_SetVolume(AudioPlayer* self, double volume) +{ + if (volume > 1) { + volume = 1; + } else if (volume < 0) { + volume = 0; + } + g_object_set(G_OBJECT(self->playbin), "volume", volume, NULL); +} + +void AudioPlayer_SetPlaybackRate(AudioPlayer* self, double rate) +{ + AudioPlayer_SetPlayback(self, AudioPlayer_GetPosition(self), rate); +} + +void AudioPlayer_SetPosition(AudioPlayer* self, int64_t position) +{ + if (!self->_isInitialized) { + return; + } + AudioPlayer_SetPlayback(self, position, self->_playbackRate); +} + +void AudioPlayer_SetSourceUrl(AudioPlayer* self, char* url) +{ + if (self->url == NULL || strcmp(self->url, url)) { + if (self->url != NULL) { + free(self->url); + self->url = NULL; + } + self->url = malloc(strlen(url) + 1); + strcpy(self->url, url); + gst_element_set_state(self->playbin, GST_STATE_NULL); + if (strlen(self->url) != 0) { + g_object_set(self->playbin, "uri", self->url, NULL); + if (self->playbin->current_state != GST_STATE_READY) { + gst_element_set_state(self->playbin, GST_STATE_READY); + } + } + self->_isInitialized = false; + } +} diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c new file mode 100644 index 00000000..890976d7 --- /dev/null +++ b/src/plugins/audioplayers/plugin.c @@ -0,0 +1,211 @@ +#include +#include +#include +#include + +#include "plugins/audioplayers.h" + +FILE_DESCR("Audioplayers") + +#define AUDIOPLAYERS_LOCAL_CHANNEL "xyz.luan/audioplayers" +#define AUDIOPLAYERS_GLOBAL_CHANNEL "xyz.luan/audioplayers.global" + +static AudioPlayer* audioplayers_linux_plugin_get_player(char* playerId, char* mode); + +static struct plugin +{ + struct flutterpi* flutterpi; + bool initialized; + struct concurrent_pointer_set players; +} plugin; + +static int on_local_method_call(char* channel, struct platch_obj* object, FlutterPlatformMessageResponseHandle* responsehandle) +{ + const char* method; + int result = 1; + + (void)responsehandle; + (void)channel; + + method = object->method; + struct std_value* flPlayerId = stdmap_get_str(&object->std_arg, "playerId"); + if (flPlayerId == NULL) { + LOG_ERROR("Call missing mandatory parameter playerId."); + result = 0; + } + char* playerId = STDVALUE_AS_STRING(*flPlayerId); + + struct std_value* args = &object->std_arg; + struct std_value* flMode = stdmap_get_str(args, "mode"); + + char* mode = flMode == NULL ? "" : STDVALUE_AS_STRING(*flMode); + + // CONTINE + AudioPlayer* player = audioplayers_linux_plugin_get_player(playerId, mode); + + if (strcmp(method, "pause") == 0) { + AudioPlayer_Pause(player); + result = 1; + } else if (strcmp(method, "resume") == 0) { + AudioPlayer_Resume(player); + result = 1; + } else if (strcmp(method, "stop") == 0) { + AudioPlayer_Pause(player); + AudioPlayer_SetPosition(player, 0); + result = 1; + } else if (strcmp(method, "release") == 0) { + AudioPlayer_Pause(player); + AudioPlayer_SetPosition(player, 0); + result = 1; + } else if (strcmp(method, "seek") == 0) { + struct std_value* flPosition = stdmap_get_str(args, "position"); + int position = flPosition == NULL ? (int)(AudioPlayer_GetPosition(player)) : STDVALUE_AS_INT(*flPosition); + AudioPlayer_SetPosition(player, position); + result = 1; + } else if (strcmp(method, "setSourceUrl") == 0) { + struct std_value* flUrl = stdmap_get_str(args, "url"); + if (flUrl == NULL) { + LOG_ERROR("Null URL received on setSourceUrl"); + result = 0; + return platch_respond_illegal_arg_std(responsehandle, "URL is NULL"); + } + char* url = STDVALUE_AS_STRING(*flUrl); + + struct std_value* flIsLocal = stdmap_get_str(args, "isLocal"); + bool isLocal = (flIsLocal == NULL) ? false : STDVALUE_AS_BOOL(*flIsLocal); + if (isLocal) { + size_t size = strlen(url) + 7 + 1; + char* tmp = malloc(size); + snprintf(tmp, size, "file://%s", url); + url = tmp; + } + AudioPlayer_SetSourceUrl(player, url); + result = 1; + } else if (strcmp(method, "getDuration") == 0) { + result = AudioPlayer_GetDuration(player); + } else if (strcmp(method, "setVolume") == 0) { + struct std_value* flVolume = stdmap_get_str(args, "volume"); + if (flVolume == NULL) { + LOG_ERROR("setVolume called with NULL arg, setting vol to 1.0"); + AudioPlayer_SetVolume(player, 1.0); + } else if (!STDVALUE_IS_FLOAT(*flVolume)) { + LOG_ERROR("setVolume called with non float arg, setting vol to 1.0"); + AudioPlayer_SetVolume(player, 1.0); + } else { + double volume = STDVALUE_AS_FLOAT(*flVolume); + AudioPlayer_SetVolume(player, volume); + } + result = 1; + } else if (strcmp(method, "getCurrentPosition") == 0) { + result = AudioPlayer_GetPosition(player); + } else if (strcmp(method, "setPlaybackRate") == 0) { + struct std_value* flPlaybackRate = stdmap_get_str(args, "playbackRate"); + double playbackRate = flPlaybackRate == NULL ? 1.0 : STDVALUE_AS_FLOAT(*flPlaybackRate); + AudioPlayer_SetPlaybackRate(player, playbackRate); + result = 1; + } else if (strcmp(method, "setReleaseMode") == 0) { + struct std_value* flReleaseMode = stdmap_get_str(args, "releaseMode"); + char* releaseMode = flReleaseMode == NULL ? "" : STDVALUE_AS_STRING(*flReleaseMode); + if (releaseMode == NULL) { + LOG_ERROR("Error calling setReleaseMode, releaseMode cannot be null"); + result = 0; + return platch_respond_illegal_arg_std(responsehandle, "releaseMode cannot be null"); + } + bool looping = strstr(releaseMode, "loop") != NULL; + AudioPlayer_SetLooping(player, looping); + result = 1; + } else if (strcmp(method, "setPlayerMode") == 0) { + // TODO check support for low latency mode: + // https://gstreamer.freedesktop.org/documentation/additional/design/latency.html?gi-language=c + result = 1; + } else { + return platch_respond_not_implemented(responsehandle); + } + + return platch_respond_success_std(responsehandle, &STDINT64(result)); +} + +static int on_global_method_call(char* channel, struct platch_obj* object, FlutterPlatformMessageResponseHandle* responsehandle) +{ + const char* method; + + (void)responsehandle; + (void)channel; + + method = object->method; + + return platch_respond( + responsehandle, + &(struct platch_obj){ .codec = kStandardMethodCallResponse, .success = true, .std_result = { .type = kStdTrue } }); +} + +enum plugin_init_result audioplayers_plugin_init(struct flutterpi* flutterpi, void** userdata_out) +{ + (void)userdata_out; + int ok; + plugin.flutterpi = flutterpi; + plugin.initialized = false; + + ok = cpset_init(&plugin.players, CPSET_DEFAULT_MAX_SIZE); + if (ok != 0) + return kError_PluginInitResult; + + ok = plugin_registry_set_receiver(AUDIOPLAYERS_GLOBAL_CHANNEL, kStandardMethodCall, on_global_method_call); + if (ok != 0) { + goto fail_deinit_cpset; + } + + ok = plugin_registry_set_receiver(AUDIOPLAYERS_LOCAL_CHANNEL, kStandardMethodCall, on_local_method_call); + if (ok != 0) { + goto fail_remove_global_receiver; + } + + return kInitialized_PluginInitResult; + +fail_remove_global_receiver: + plugin_registry_remove_receiver(AUDIOPLAYERS_GLOBAL_CHANNEL); + +fail_deinit_cpset: + cpset_deinit(&plugin.players); + + return kError_PluginInitResult; +} + +void audioplayers_plugin_deinit(struct flutterpi* flutterpi, void* userdata) +{ + (void)flutterpi; + (void)userdata; + plugin_registry_remove_receiver(AUDIOPLAYERS_GLOBAL_CHANNEL); + plugin_registry_remove_receiver(AUDIOPLAYERS_LOCAL_CHANNEL); + + AudioPlayer* ptr; + for_each_pointer_in_cpset(&plugin.players, ptr) + { + AudioPlayer_Dispose(ptr); + } + + cpset_deinit(&plugin.players); +} + +static AudioPlayer* audioplayers_linux_plugin_get_player(char* playerId, char* mode) +{ + (void)mode; + AudioPlayer* player = NULL; + AudioPlayer* p; + for_each_pointer_in_cpset(&plugin.players, p) + { + if (!strcmp(p->playerId, playerId)) { + player = p; + break; + } + } + if (player != NULL) { + return player; + } else { + AudioPlayer* player = AudioPlayer_new(playerId, AUDIOPLAYERS_LOCAL_CHANNEL); + cpset_put_locked(&plugin.players, player); + return player; + } +} + +FLUTTERPI_PLUGIN("audioplayers_flutter_pi", audioplayers, audioplayers_plugin_init, audioplayers_plugin_deinit) From 7dabe5b78d34b1c170b929c823a46f3042c93e9a Mon Sep 17 00:00:00 2001 From: DoumanAsh Date: Mon, 22 Aug 2022 21:27:32 +0900 Subject: [PATCH 02/16] Apply comments --- include/plugins/audioplayers.h | 49 ++-- src/plugins/audioplayers/player.c | 366 ++++++++++++++++++------------ src/plugins/audioplayers/plugin.c | 116 +++++----- 3 files changed, 292 insertions(+), 239 deletions(-) diff --git a/include/plugins/audioplayers.h b/include/plugins/audioplayers.h index 2e48843e..97402e3d 100644 --- a/include/plugins/audioplayers.h +++ b/include/plugins/audioplayers.h @@ -1,53 +1,40 @@ #ifndef AUDIOPLAYERS_H_ #define AUDIOPLAYERS_H_ -#include #include +#include +#include -typedef struct AudioPlayer -{ - GstElement* playbin; - GstElement* source; - GstBus* bus; - - bool _isInitialized; - bool _isLooping; - bool _isSeekCompleted; - double _playbackRate; - - char* url; - char* playerId; - /* FlMethodChannel* _channel; */ - char* _channel; - -} AudioPlayer; +struct audio_player; -AudioPlayer* AudioPlayer_new(char* playerId, char* channel); +struct audio_player* audio_player_new(char* playerId, char* channel); // Instance function -int64_t AudioPlayer_GetPosition(AudioPlayer* self); +int64_t audio_player_get_position(struct audio_player* self); + +int64_t audio_player_get_duration(struct audio_player* self); -int64_t AudioPlayer_GetDuration(AudioPlayer* self); +bool audio_player_get_loopin(struct audio_player* self); -bool AudioPlayer_GetLooping(AudioPlayer* self); +void audio_player_play(struct audio_player* self); -void AudioPlayer_Play(AudioPlayer* self); +void audio_player_pause(struct audio_player* self); -void AudioPlayer_Pause(AudioPlayer* self); +void audio_player_resume(struct audio_player* self); -void AudioPlayer_Resume(AudioPlayer* self); +void audio_player_dispose(struct audio_player* self); -void AudioPlayer_Dispose(AudioPlayer* self); +void audio_player_set_looping(struct audio_player* self, bool isLooping); -void AudioPlayer_SetLooping(AudioPlayer* self, bool isLooping); +void audio_player_set_volume(struct audio_player* self, double volume); -void AudioPlayer_SetVolume(AudioPlayer* self, double volume); +void audio_player_set_playback_rate(struct audio_player* self, double rate); -void AudioPlayer_SetPlaybackRate(AudioPlayer* self, double rate); +void audio_player_set_position(struct audio_player* self, int64_t position); -void AudioPlayer_SetPosition(AudioPlayer* self, int64_t position); +void audio_player_set_source_url(struct audio_player* self, char* url); -void AudioPlayer_SetSourceUrl(AudioPlayer* self, char* url); +bool audio_player_is_id(struct audio_player* self, char* id); #endif // AUDIOPLAYERS_H_ diff --git a/src/plugins/audioplayers/player.c b/src/plugins/audioplayers/player.c index da3dfca1..39a72671 100644 --- a/src/plugins/audioplayers/player.c +++ b/src/plugins/audioplayers/player.c @@ -7,28 +7,41 @@ #include #include -FILE_DESCR("AudioPlayer::player") +FILE_DESCR("audioplayers player") + +struct audio_player { + GstElement *playbin; + GstElement *source; + GstBus *bus; + + bool is_initialized; + bool is_looping; + bool is_seek_completed; + double playback_rate; + + char *url; + char *player_id; + char *channel; +}; // Private Class functions -void AudioPlayer_SourceSetup(GstElement* playbin, GstElement* source, GstElement** p_src); -gboolean AudioPlayer_OnBusMessage(GstBus* bus, GstMessage* message, AudioPlayer* data); -gboolean AudioPlayer_OnRefresh(AudioPlayer* data); - -// Private methods -void AudioPlayer_SetPlayback(AudioPlayer* self, int64_t seekTo, double rate); -void AudioPlayer_OnMediaError(AudioPlayer* self, GError* error, gchar* debug); -void AudioPlayer_OnMediaStateChange(AudioPlayer* self, GstObject* src, GstState* old_state, GstState* new_state); -void AudioPlayer_OnPositionUpdate(AudioPlayer* self); -void AudioPlayer_OnDurationUpdate(AudioPlayer* self); -void AudioPlayer_OnSeekCompleted(AudioPlayer* self); -void AudioPlayer_OnPlaybackEnded(AudioPlayer* self); - -static int on_bus_fd_ready(sd_event_source* s, int fd, uint32_t revents, void* userdata) +static void audio_player_source_setup(GstElement* playbin, GstElement* source, GstElement** p_src); +static gboolean audio_player_on_bus_message(GstBus* bus, GstMessage* message, struct audio_player* data); +static gboolean audio_player_on_refresh(struct audio_player* data); +static void audio_player_set_playback(struct audio_player* self, int64_t seekTo, double rate); +static void audio_player_on_media_error(struct audio_player* self, GError* error, gchar* debug); +static void audio_player_on_media_state_change(struct audio_player* self, GstObject* src, GstState* old_state, GstState* new_state); +static void audio_player_on_position_update(struct audio_player* self); +static void audio_player_on_duration_update(struct audio_player* self); +static void audio_player_on_seek_completed(struct audio_player* self); +static void audio_player_on_playback_ended(struct audio_player* self); + +static int on_bus_fd_ready(sd_event_source* src, int fd, uint32_t revents, void* userdata) { - struct AudioPlayer* player = userdata; + struct audio_player* player = userdata; GstMessage* msg; - (void)s; + (void)src; (void)fd; (void)revents; @@ -36,7 +49,7 @@ static int on_bus_fd_ready(sd_event_source* s, int fd, uint32_t revents, void* u msg = gst_bus_pop(player->bus); if (msg != NULL) { - AudioPlayer_OnBusMessage(player->bus, msg, player); + audio_player_on_bus_message(player->bus, msg, player); gst_message_unref(msg); } @@ -45,63 +58,67 @@ static int on_bus_fd_ready(sd_event_source* s, int fd, uint32_t revents, void* u return 0; } -AudioPlayer* AudioPlayer_new(char* playerId, char* channel) +struct audio_player* audio_player_new(char* player_id, char* channel) { - AudioPlayer* self = malloc(sizeof(AudioPlayer)); + GPollFD fd; + sd_event_source* busfd_event_source; + + struct audio_player* self = malloc(sizeof(struct audio_player)); if (self == NULL) { return NULL; } self->url = NULL; - self->_isInitialized = false; - self->_isLooping = false; - self->_isSeekCompleted = false; - self->_playbackRate = 1.0; + self->is_initialized = false; + self->is_looping = false; + self->is_seek_completed = false; + self->playback_rate = 1.0; gst_init(NULL, NULL); self->playbin = gst_element_factory_make("playbin", "playbin"); if (!self->playbin) { LOG_ERROR("Not all elements could be created"); } - g_signal_connect(self->playbin, "source-setup", G_CALLBACK(AudioPlayer_SourceSetup), &self->source); + g_signal_connect(self->playbin, "source-setup", G_CALLBACK(audio_player_source_setup), &self->source); self->bus = gst_element_get_bus(self->playbin); - // Watch bus messages for one time events - // gst_bus_add_watch(self->bus, (GstBusFunc)AudioPlayer_OnBusMessage, self); - - GPollFD fd; - sd_event_source* busfd_event_source; gst_bus_get_pollfd(self->bus, &fd); flutterpi_sd_event_add_io(&busfd_event_source, fd.fd, EPOLLIN, on_bus_fd_ready, self); - // Refresh continuously to emit reoccuring events - g_timeout_add(1000, (GSourceFunc)AudioPlayer_OnRefresh, self); + // Refresh continuously to emit recurring events + g_timeout_add(1000, (GSourceFunc)audio_player_on_refresh, self); - self->playerId = malloc(strlen(playerId) + 1); - if (self->playerId == NULL) - goto deinit_ptr; - strcpy(self->playerId, playerId); + self->player_id = malloc(strlen(player_id) + 1); + if (self->player_id == NULL) + goto deinit_player; + strcpy(self->player_id, player_id); - self->_channel = malloc(strlen(channel) + 1); - if (self->_channel == NULL) + self->channel = malloc(strlen(channel) + 1); + if (self->channel == NULL) goto deinit_player_id; - strcpy(self->_channel, channel); + strcpy(self->channel, channel); return self; - // NOTE: deinit other stuff? - + //Deinit doesn't require to NULL, as we just delete player. deinit_player_id: - free(self->playerId); + free(self->player_id); + +deinit_player: + free(self->channel); + + gst_object_unref(self->bus); + gst_object_unref(self->source); + gst_element_set_state(self->playbin, GST_STATE_NULL); + gst_object_unref(self->playbin); -deinit_ptr: free(self); return NULL; } -void AudioPlayer_SourceSetup(GstElement* playbin, GstElement* source, GstElement** p_src) +void audio_player_source_setup(GstElement* playbin, GstElement* source, GstElement** p_src) { (void)playbin; (void)p_src; @@ -110,7 +127,7 @@ void AudioPlayer_SourceSetup(GstElement* playbin, GstElement* source, GstElement } } -gboolean AudioPlayer_OnBusMessage(GstBus* bus, GstMessage* message, AudioPlayer* data) +gboolean audio_player_on_bus_message(GstBus* bus, GstMessage* message, struct audio_player* data) { (void)bus; switch (GST_MESSAGE_TYPE(message)) { @@ -119,7 +136,7 @@ gboolean AudioPlayer_OnBusMessage(GstBus* bus, GstMessage* message, AudioPlayer* gchar* debug; gst_message_parse_error(message, &err, &debug); - AudioPlayer_OnMediaError(data, err, debug); + audio_player_on_media_error(data, err, debug); g_error_free(err); g_free(debug); break; @@ -128,20 +145,20 @@ gboolean AudioPlayer_OnBusMessage(GstBus* bus, GstMessage* message, AudioPlayer* GstState old_state, new_state; gst_message_parse_state_changed(message, &old_state, &new_state, NULL); - AudioPlayer_OnMediaStateChange(data, message->src, &old_state, &new_state); + audio_player_on_media_state_change(data, message->src, &old_state, &new_state); break; } case GST_MESSAGE_EOS: gst_element_set_state(data->playbin, GST_STATE_READY); - AudioPlayer_OnPlaybackEnded(data); + audio_player_on_playback_ended(data); break; case GST_MESSAGE_DURATION_CHANGED: - AudioPlayer_OnDurationUpdate(data); + audio_player_on_duration_update(data); break; case GST_MESSAGE_ASYNC_DONE: - if (!data->_isSeekCompleted) { - AudioPlayer_OnSeekCompleted(data); - data->_isSeekCompleted = true; + if (!data->is_seek_completed) { + audio_player_on_seek_completed(data); + data->is_seek_completed = true; } break; default: @@ -154,162 +171,214 @@ gboolean AudioPlayer_OnBusMessage(GstBus* bus, GstMessage* message, AudioPlayer* return TRUE; } -gboolean AudioPlayer_OnRefresh(AudioPlayer* data) +gboolean audio_player_on_refresh(struct audio_player* data) { if (data->playbin->current_state == GST_STATE_PLAYING) { - AudioPlayer_OnPositionUpdate(data); + audio_player_on_position_update(data); } return TRUE; } -void AudioPlayer_SetPlayback(AudioPlayer* self, int64_t seekTo, double rate) +void audio_player_set_playback(struct audio_player* self, int64_t seekTo, double rate) { - if (!self->_isInitialized) { + const GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE; + + if (!self->is_initialized) { return; } // See: // https://gstreamer.freedesktop.org/documentation/tutorials/basic/playback-speed.html?gi-language=c - if (!self->_isSeekCompleted) { + if (!self->is_seek_completed) { return; } if (rate == 0) { // Do not set rate if it's 0, rather pause. - AudioPlayer_Pause(self); + audio_player_pause(self); return; } - if (self->_playbackRate != rate) { - self->_playbackRate = rate; + if (self->playback_rate != rate) { + self->playback_rate = rate; } - self->_isSeekCompleted = false; + self->is_seek_completed = false; - GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE; GstEvent* seek_event; if (rate > 0) { - seek_event = - gst_event_new_seek(rate, GST_FORMAT_TIME, seek_flags, GST_SEEK_TYPE_SET, seekTo * GST_MSECOND, GST_SEEK_TYPE_NONE, -1); + seek_event = gst_event_new_seek( + rate, + GST_FORMAT_TIME, + seek_flags, + GST_SEEK_TYPE_SET, seekTo * GST_MSECOND, + GST_SEEK_TYPE_NONE, + -1 + ); } else { - seek_event = - gst_event_new_seek(rate, GST_FORMAT_TIME, seek_flags, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, seekTo * GST_MSECOND); + seek_event = gst_event_new_seek( + rate, + GST_FORMAT_TIME, + seek_flags, + GST_SEEK_TYPE_SET, 0, + GST_SEEK_TYPE_SET, seekTo * GST_MSECOND + ); } if (!gst_element_send_event(self->playbin, seek_event)) { // FIXME LOG_ERROR("Could not set playback to position %ld and rate %f.", seekTo, rate); - self->_isSeekCompleted = true; + self->is_seek_completed = true; } } -void AudioPlayer_OnMediaError(AudioPlayer* self, GError* error, gchar* debug) +void audio_player_on_media_error(struct audio_player* self, GError* error, gchar* debug) { (void)debug; char* error_message = malloc(256 * sizeof(char)); snprintf(error_message, 256, "Error: %d; message=%s", error->code, error->message); LOG_ERROR("%s", error_message); - if (self->_channel) { + if (self->channel) { + // clang-format off platch_call_std( - self->_channel, - "audio.onError", - &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDSTRING(error_message)), - NULL, - NULL); + self->channel, + "audio.onError", + &STDMAP2( + STDSTRING("player_id"), + STDSTRING(self->player_id), + STDSTRING("value"), + STDSTRING(error_message) + ), + NULL, + NULL + ); + // clang-format on } } -void AudioPlayer_OnMediaStateChange(AudioPlayer* self, GstObject* src, GstState* old_state, GstState* new_state) +void audio_player_on_media_state_change(struct audio_player* self, GstObject* src, GstState* old_state, GstState* new_state) { (void)old_state; if (strcmp(GST_OBJECT_NAME(src), "playbin") == 0) { if (*new_state >= GST_STATE_READY) { - if (!self->_isInitialized) { - self->_isInitialized = true; - AudioPlayer_Pause(self); // Need to set to pause state, in order to get duration + if (!self->is_initialized) { + self->is_initialized = true; + audio_player_pause(self); // Need to set to pause state, in order to get duration } - } else if (self->_isInitialized) { - self->_isInitialized = false; + } else if (self->is_initialized) { + self->is_initialized = false; } } } -void AudioPlayer_OnPositionUpdate(AudioPlayer* self) +void audio_player_on_position_update(struct audio_player* self) { - if (self->_channel) { + if (self->channel) { + // clang-format off platch_call_std( - self->_channel, - "audio.onCurrentPosition", - &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDINT64(AudioPlayer_GetPosition(self))), - NULL, - NULL); + self->channel, + "audio.onCurrentPosition", + &STDMAP2( + STDSTRING("player_id"), + STDSTRING(self->player_id), + STDSTRING("value"), + STDINT64(audio_player_get_position(self)) + ), + NULL, + NULL + ); + // clang-format on } } -void AudioPlayer_OnDurationUpdate(AudioPlayer* self) +void audio_player_on_duration_update(struct audio_player* self) { - if (self->_channel) { + if (self->channel) { + // clang-format off platch_call_std( - self->_channel, - "audio.onDuration", - &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDINT64(AudioPlayer_GetDuration(self))), - NULL, - NULL); + self->channel, + "audio.onDuration", + &STDMAP2( + STDSTRING("player_id"), + STDSTRING(self->player_id), + STDSTRING("value"), + STDINT64(audio_player_get_duration(self)) + ), + NULL, + NULL + ); + // clang-format on } } -void AudioPlayer_OnSeekCompleted(AudioPlayer* self) +void audio_player_on_seek_completed(struct audio_player* self) { - if (self->_channel) { - AudioPlayer_OnPositionUpdate(self); + if (self->channel) { + audio_player_on_position_update(self); + // clang-format off platch_call_std( - self->_channel, - "audio.onSeekComplete", - &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDBOOL(true)), - NULL, - NULL); + self->channel, + "audio.onSeekComplete", + &STDMAP2( + STDSTRING("player_id"), + STDSTRING(self->player_id), + STDSTRING("value"), + STDBOOL(true) + ), + NULL, + NULL + ); + // clang-format on } } -void AudioPlayer_OnPlaybackEnded(AudioPlayer* self) +void audio_player_on_playback_ended(struct audio_player* self) { - AudioPlayer_SetPosition(self, 0); - if (AudioPlayer_GetLooping(self)) { - AudioPlayer_Play(self); + audio_player_set_position(self, 0); + if (audio_player_get_loopin(self)) { + audio_player_play(self); } - if (self->_channel) { + if (self->channel) { + // clang-format off platch_call_std( - self->_channel, - "audio.onComplete", - &STDMAP2(STDSTRING("playerId"), STDSTRING(self->playerId), STDSTRING("value"), STDBOOL(true)), - NULL, - NULL); + self->channel, + "audio.onComplete", + &STDMAP2( + STDSTRING("player_id"), + STDSTRING(self->player_id), + STDSTRING("value"), + STDBOOL(true) + ), + NULL, + NULL + ); + // clang-format on } } -void AudioPlayer_SetLooping(AudioPlayer* self, bool isLooping) +void audio_player_set_looping(struct audio_player* self, bool is_looping) { - self->_isLooping = isLooping; + self->is_looping = is_looping; } -bool AudioPlayer_GetLooping(AudioPlayer* self) +bool audio_player_get_loopin(struct audio_player* self) { - return self->_isLooping; + return self->is_looping; } -void AudioPlayer_Play(AudioPlayer* self) +void audio_player_play(struct audio_player* self) { - if (!self->_isInitialized) { + if (!self->is_initialized) { return; } - AudioPlayer_SetPosition(self, 0); - AudioPlayer_Resume(self); + audio_player_set_position(self, 0); + audio_player_resume(self); } -void AudioPlayer_Pause(AudioPlayer* self) +void audio_player_pause(struct audio_player* self) { GstStateChangeReturn ret = gst_element_set_state(self->playbin, GST_STATE_PAUSED); if (ret == GST_STATE_CHANGE_FAILURE) { LOG_ERROR("Unable to set the pipeline to the paused state."); return; } - AudioPlayer_OnPositionUpdate(self); // Update to exact position when pausing + audio_player_on_position_update(self); // Update to exact position when pausing } -void AudioPlayer_Resume(AudioPlayer* self) +void audio_player_resume(struct audio_player* self) { - if (!self->_isInitialized) { + if (!self->is_initialized) { return; } GstStateChangeReturn ret = gst_element_set_state(self->playbin, GST_STATE_PLAYING); @@ -317,39 +386,42 @@ void AudioPlayer_Resume(AudioPlayer* self) LOG_ERROR("Unable to set the pipeline to the playing state."); return; } - AudioPlayer_OnDurationUpdate(self); // Update duration when start playing, as no event is emitted elsewhere + audio_player_on_duration_update(self); // Update duration when start playing, as no event is emitted elsewhere } -void AudioPlayer_Dispose(AudioPlayer* self) +void audio_player_dispose(struct audio_player* self) { - if (self->_isInitialized) { - AudioPlayer_Pause(self); + if (self->is_initialized) { + audio_player_pause(self); } gst_object_unref(self->bus); + self->bus = NULL; gst_object_unref(self->source); + self->source = NULL; gst_element_set_state(self->playbin, GST_STATE_NULL); gst_object_unref(self->playbin); + self->playbin = NULL; - self->_isInitialized = false; + self->is_initialized = false; if (self->url != NULL) { free(self->url); self->url = NULL; } - if (self->playerId != NULL) { - free(self->playerId); - self->playerId = NULL; + if (self->player_id != NULL) { + free(self->player_id); + self->player_id = NULL; } - if (self->_channel != NULL) { - free(self->_channel); - self->_channel = NULL; + if (self->channel != NULL) { + free(self->channel); + self->channel = NULL; } } -int64_t AudioPlayer_GetPosition(AudioPlayer* self) +int64_t audio_player_get_position(struct audio_player* self) { gint64 current = 0; if (!gst_element_query_position(self->playbin, GST_FORMAT_TIME, ¤t)) { @@ -359,7 +431,7 @@ int64_t AudioPlayer_GetPosition(AudioPlayer* self) return current / 1000000; } -int64_t AudioPlayer_GetDuration(AudioPlayer* self) +int64_t audio_player_get_duration(struct audio_player* self) { gint64 duration = 0; if (!gst_element_query_duration(self->playbin, GST_FORMAT_TIME, &duration)) { @@ -369,7 +441,7 @@ int64_t AudioPlayer_GetDuration(AudioPlayer* self) return duration / 1000000; } -void AudioPlayer_SetVolume(AudioPlayer* self, double volume) +void audio_player_set_volume(struct audio_player* self, double volume) { if (volume > 1) { volume = 1; @@ -379,20 +451,20 @@ void AudioPlayer_SetVolume(AudioPlayer* self, double volume) g_object_set(G_OBJECT(self->playbin), "volume", volume, NULL); } -void AudioPlayer_SetPlaybackRate(AudioPlayer* self, double rate) +void audio_player_set_playback_rate(struct audio_player* self, double rate) { - AudioPlayer_SetPlayback(self, AudioPlayer_GetPosition(self), rate); + audio_player_set_playback(self, audio_player_get_position(self), rate); } -void AudioPlayer_SetPosition(AudioPlayer* self, int64_t position) +void audio_player_set_position(struct audio_player* self, int64_t position) { - if (!self->_isInitialized) { + if (!self->is_initialized) { return; } - AudioPlayer_SetPlayback(self, position, self->_playbackRate); + audio_player_set_playback(self, position, self->playback_rate); } -void AudioPlayer_SetSourceUrl(AudioPlayer* self, char* url) +void audio_player_set_source_url(struct audio_player* self, char* url) { if (self->url == NULL || strcmp(self->url, url)) { if (self->url != NULL) { @@ -408,6 +480,10 @@ void AudioPlayer_SetSourceUrl(AudioPlayer* self, char* url) gst_element_set_state(self->playbin, GST_STATE_READY); } } - self->_isInitialized = false; + self->is_initialized = false; } } + +bool audio_player_is_id(struct audio_player* self, char* player_id) { + return strcmp(self->player_id, player_id) == 0; +} diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index 890976d7..4400c908 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -5,12 +5,12 @@ #include "plugins/audioplayers.h" -FILE_DESCR("Audioplayers") +FILE_DESCR("audioplayers plugin") #define AUDIOPLAYERS_LOCAL_CHANNEL "xyz.luan/audioplayers" #define AUDIOPLAYERS_GLOBAL_CHANNEL "xyz.luan/audioplayers.global" -static AudioPlayer* audioplayers_linux_plugin_get_player(char* playerId, char* mode); +static struct audio_player* audioplayers_linux_plugin_get_player(char* player_id, char* mode); static struct plugin { @@ -28,96 +28,86 @@ static int on_local_method_call(char* channel, struct platch_obj* object, Flutte (void)channel; method = object->method; - struct std_value* flPlayerId = stdmap_get_str(&object->std_arg, "playerId"); - if (flPlayerId == NULL) { - LOG_ERROR("Call missing mandatory parameter playerId."); - result = 0; + struct std_value* fl_player_id = stdmap_get_str(&object->std_arg, "player_id"); + if (fl_player_id == NULL) { + LOG_ERROR("Call missing mandatory parameter player_id."); + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['player_id'] to be a string."); } - char* playerId = STDVALUE_AS_STRING(*flPlayerId); + char* player_id = STDVALUE_AS_STRING(*fl_player_id); struct std_value* args = &object->std_arg; - struct std_value* flMode = stdmap_get_str(args, "mode"); + struct std_value* fl_mode = stdmap_get_str(args, "mode"); - char* mode = flMode == NULL ? "" : STDVALUE_AS_STRING(*flMode); + char* mode = fl_mode == NULL ? "" : STDVALUE_AS_STRING(*fl_mode); // CONTINE - AudioPlayer* player = audioplayers_linux_plugin_get_player(playerId, mode); + struct audio_player* player = audioplayers_linux_plugin_get_player(player_id, mode); if (strcmp(method, "pause") == 0) { - AudioPlayer_Pause(player); - result = 1; + audio_player_pause(player); } else if (strcmp(method, "resume") == 0) { - AudioPlayer_Resume(player); - result = 1; + audio_player_resume(player); } else if (strcmp(method, "stop") == 0) { - AudioPlayer_Pause(player); - AudioPlayer_SetPosition(player, 0); - result = 1; + audio_player_pause(player); + audio_player_set_position(player, 0); } else if (strcmp(method, "release") == 0) { - AudioPlayer_Pause(player); - AudioPlayer_SetPosition(player, 0); - result = 1; + audio_player_pause(player); + audio_player_set_position(player, 0); } else if (strcmp(method, "seek") == 0) { - struct std_value* flPosition = stdmap_get_str(args, "position"); - int position = flPosition == NULL ? (int)(AudioPlayer_GetPosition(player)) : STDVALUE_AS_INT(*flPosition); - AudioPlayer_SetPosition(player, position); - result = 1; + struct std_value* fl_position = stdmap_get_str(args, "position"); + int position = fl_position == NULL ? (int)(audio_player_get_position(player)) : STDVALUE_AS_INT(*fl_position); + audio_player_set_position(player, position); } else if (strcmp(method, "setSourceUrl") == 0) { - struct std_value* flUrl = stdmap_get_str(args, "url"); - if (flUrl == NULL) { + struct std_value* fl_url = stdmap_get_str(args, "url"); + if (fl_url == NULL) { LOG_ERROR("Null URL received on setSourceUrl"); result = 0; return platch_respond_illegal_arg_std(responsehandle, "URL is NULL"); } - char* url = STDVALUE_AS_STRING(*flUrl); + char* url = STDVALUE_AS_STRING(*fl_url); - struct std_value* flIsLocal = stdmap_get_str(args, "isLocal"); - bool isLocal = (flIsLocal == NULL) ? false : STDVALUE_AS_BOOL(*flIsLocal); - if (isLocal) { + struct std_value* fl_is_local = stdmap_get_str(args, "is_local"); + bool is_local = (fl_is_local == NULL) ? false : STDVALUE_AS_BOOL(*fl_is_local); + if (is_local) { size_t size = strlen(url) + 7 + 1; char* tmp = malloc(size); snprintf(tmp, size, "file://%s", url); url = tmp; } - AudioPlayer_SetSourceUrl(player, url); - result = 1; + audio_player_set_source_url(player, url); } else if (strcmp(method, "getDuration") == 0) { - result = AudioPlayer_GetDuration(player); + result = audio_player_get_duration(player); } else if (strcmp(method, "setVolume") == 0) { - struct std_value* flVolume = stdmap_get_str(args, "volume"); - if (flVolume == NULL) { + struct std_value* fl_volume = stdmap_get_str(args, "volume"); + if (fl_volume == NULL) { LOG_ERROR("setVolume called with NULL arg, setting vol to 1.0"); - AudioPlayer_SetVolume(player, 1.0); - } else if (!STDVALUE_IS_FLOAT(*flVolume)) { + audio_player_set_volume(player, 1.0); + } else if (!STDVALUE_IS_FLOAT(*fl_volume)) { LOG_ERROR("setVolume called with non float arg, setting vol to 1.0"); - AudioPlayer_SetVolume(player, 1.0); + audio_player_set_volume(player, 1.0); } else { - double volume = STDVALUE_AS_FLOAT(*flVolume); - AudioPlayer_SetVolume(player, volume); + double volume = STDVALUE_AS_FLOAT(*fl_volume); + audio_player_set_volume(player, volume); } - result = 1; } else if (strcmp(method, "getCurrentPosition") == 0) { - result = AudioPlayer_GetPosition(player); + result = audio_player_get_position(player); } else if (strcmp(method, "setPlaybackRate") == 0) { - struct std_value* flPlaybackRate = stdmap_get_str(args, "playbackRate"); - double playbackRate = flPlaybackRate == NULL ? 1.0 : STDVALUE_AS_FLOAT(*flPlaybackRate); - AudioPlayer_SetPlaybackRate(player, playbackRate); - result = 1; + struct std_value* fl_playback_rate = stdmap_get_str(args, "playback_rate"); + double playback_rate = fl_playback_rate == NULL ? 1.0 : STDVALUE_AS_FLOAT(*fl_playback_rate); + audio_player_set_playback_rate(player, playback_rate); } else if (strcmp(method, "setReleaseMode") == 0) { - struct std_value* flReleaseMode = stdmap_get_str(args, "releaseMode"); - char* releaseMode = flReleaseMode == NULL ? "" : STDVALUE_AS_STRING(*flReleaseMode); - if (releaseMode == NULL) { - LOG_ERROR("Error calling setReleaseMode, releaseMode cannot be null"); + struct std_value* fl_release_mode = stdmap_get_str(args, "release_mode"); + char* release_mode = fl_release_mode == NULL ? "" : STDVALUE_AS_STRING(*fl_release_mode); + if (release_mode == NULL) { + LOG_ERROR("Error calling setReleaseMode, release_mode cannot be null"); result = 0; - return platch_respond_illegal_arg_std(responsehandle, "releaseMode cannot be null"); + return platch_respond_illegal_arg_std(responsehandle, "release_mode cannot be null"); } - bool looping = strstr(releaseMode, "loop") != NULL; - AudioPlayer_SetLooping(player, looping); - result = 1; + bool looping = strstr(release_mode, "loop") != NULL; + audio_player_set_looping(player, looping); } else if (strcmp(method, "setPlayerMode") == 0) { // TODO check support for low latency mode: // https://gstreamer.freedesktop.org/documentation/additional/design/latency.html?gi-language=c - result = 1; } else { return platch_respond_not_implemented(responsehandle); } @@ -178,23 +168,23 @@ void audioplayers_plugin_deinit(struct flutterpi* flutterpi, void* userdata) plugin_registry_remove_receiver(AUDIOPLAYERS_GLOBAL_CHANNEL); plugin_registry_remove_receiver(AUDIOPLAYERS_LOCAL_CHANNEL); - AudioPlayer* ptr; + struct audio_player* ptr; for_each_pointer_in_cpset(&plugin.players, ptr) { - AudioPlayer_Dispose(ptr); + audio_player_dispose(ptr); } cpset_deinit(&plugin.players); } -static AudioPlayer* audioplayers_linux_plugin_get_player(char* playerId, char* mode) +static struct audio_player* audioplayers_linux_plugin_get_player(char* player_id, char* mode) { (void)mode; - AudioPlayer* player = NULL; - AudioPlayer* p; + struct audio_player* player = NULL; + struct audio_player* p; for_each_pointer_in_cpset(&plugin.players, p) { - if (!strcmp(p->playerId, playerId)) { + if (audio_player_is_id(p, player_id)) { player = p; break; } @@ -202,10 +192,10 @@ static AudioPlayer* audioplayers_linux_plugin_get_player(char* playerId, char* m if (player != NULL) { return player; } else { - AudioPlayer* player = AudioPlayer_new(playerId, AUDIOPLAYERS_LOCAL_CHANNEL); + player = audio_player_new(player_id, AUDIOPLAYERS_LOCAL_CHANNEL); cpset_put_locked(&plugin.players, player); return player; } } -FLUTTERPI_PLUGIN("audioplayers_flutter_pi", audioplayers, audioplayers_plugin_init, audioplayers_plugin_deinit) +FLUTTERPI_PLUGIN("audioplayers", audioplayers, audioplayers_plugin_init, audioplayers_plugin_deinit) From ec494eaa6a1f8e954b31b2f42fe960357739d709 Mon Sep 17 00:00:00 2001 From: DoumanAsh Date: Mon, 22 Aug 2022 21:28:45 +0900 Subject: [PATCH 03/16] Apply clang-fmt --- include/plugins/audioplayers.h | 31 +++--- src/plugins/audioplayers/player.c | 163 ++++++++++++------------------ src/plugins/audioplayers/plugin.c | 95 ++++++++--------- 3 files changed, 123 insertions(+), 166 deletions(-) diff --git a/include/plugins/audioplayers.h b/include/plugins/audioplayers.h index 97402e3d..33ba64a3 100644 --- a/include/plugins/audioplayers.h +++ b/include/plugins/audioplayers.h @@ -3,38 +3,39 @@ #include #include + #include struct audio_player; -struct audio_player* audio_player_new(char* playerId, char* channel); +struct audio_player *audio_player_new(char *playerId, char *channel); // Instance function -int64_t audio_player_get_position(struct audio_player* self); +int64_t audio_player_get_position(struct audio_player *self); -int64_t audio_player_get_duration(struct audio_player* self); +int64_t audio_player_get_duration(struct audio_player *self); -bool audio_player_get_loopin(struct audio_player* self); +bool audio_player_get_loopin(struct audio_player *self); -void audio_player_play(struct audio_player* self); +void audio_player_play(struct audio_player *self); -void audio_player_pause(struct audio_player* self); +void audio_player_pause(struct audio_player *self); -void audio_player_resume(struct audio_player* self); +void audio_player_resume(struct audio_player *self); -void audio_player_dispose(struct audio_player* self); +void audio_player_dispose(struct audio_player *self); -void audio_player_set_looping(struct audio_player* self, bool isLooping); +void audio_player_set_looping(struct audio_player *self, bool isLooping); -void audio_player_set_volume(struct audio_player* self, double volume); +void audio_player_set_volume(struct audio_player *self, double volume); -void audio_player_set_playback_rate(struct audio_player* self, double rate); +void audio_player_set_playback_rate(struct audio_player *self, double rate); -void audio_player_set_position(struct audio_player* self, int64_t position); +void audio_player_set_position(struct audio_player *self, int64_t position); -void audio_player_set_source_url(struct audio_player* self, char* url); +void audio_player_set_source_url(struct audio_player *self, char *url); -bool audio_player_is_id(struct audio_player* self, char* id); +bool audio_player_is_id(struct audio_player *self, char *id); -#endif // AUDIOPLAYERS_H_ +#endif // AUDIOPLAYERS_H_ diff --git a/src/plugins/audioplayers/player.c b/src/plugins/audioplayers/player.c index 39a72671..0163e202 100644 --- a/src/plugins/audioplayers/player.c +++ b/src/plugins/audioplayers/player.c @@ -1,11 +1,13 @@ +#include + #include "gst/gst.h" #include "gst/gstelementfactory.h" #include "gst/gstmessage.h" #include "gst/gstsegment.h" #include "platformchannel.h" + #include #include -#include FILE_DESCR("audioplayers player") @@ -25,25 +27,24 @@ struct audio_player { }; // Private Class functions -static void audio_player_source_setup(GstElement* playbin, GstElement* source, GstElement** p_src); -static gboolean audio_player_on_bus_message(GstBus* bus, GstMessage* message, struct audio_player* data); -static gboolean audio_player_on_refresh(struct audio_player* data); -static void audio_player_set_playback(struct audio_player* self, int64_t seekTo, double rate); -static void audio_player_on_media_error(struct audio_player* self, GError* error, gchar* debug); -static void audio_player_on_media_state_change(struct audio_player* self, GstObject* src, GstState* old_state, GstState* new_state); -static void audio_player_on_position_update(struct audio_player* self); -static void audio_player_on_duration_update(struct audio_player* self); -static void audio_player_on_seek_completed(struct audio_player* self); -static void audio_player_on_playback_ended(struct audio_player* self); - -static int on_bus_fd_ready(sd_event_source* src, int fd, uint32_t revents, void* userdata) -{ - struct audio_player* player = userdata; - GstMessage* msg; - - (void)src; - (void)fd; - (void)revents; +static void audio_player_source_setup(GstElement *playbin, GstElement *source, GstElement **p_src); +static gboolean audio_player_on_bus_message(GstBus *bus, GstMessage *message, struct audio_player *data); +static gboolean audio_player_on_refresh(struct audio_player *data); +static void audio_player_set_playback(struct audio_player *self, int64_t seekTo, double rate); +static void audio_player_on_media_error(struct audio_player *self, GError *error, gchar *debug); +static void audio_player_on_media_state_change(struct audio_player *self, GstObject *src, GstState *old_state, GstState *new_state); +static void audio_player_on_position_update(struct audio_player *self); +static void audio_player_on_duration_update(struct audio_player *self); +static void audio_player_on_seek_completed(struct audio_player *self); +static void audio_player_on_playback_ended(struct audio_player *self); + +static int on_bus_fd_ready(sd_event_source *src, int fd, uint32_t revents, void *userdata) { + struct audio_player *player = userdata; + GstMessage *msg; + + (void) src; + (void) fd; + (void) revents; /* DEBUG_TRACE_BEGIN(player, "on_bus_fd_ready"); */ @@ -58,12 +59,11 @@ static int on_bus_fd_ready(sd_event_source* src, int fd, uint32_t revents, void* return 0; } -struct audio_player* audio_player_new(char* player_id, char* channel) -{ +struct audio_player *audio_player_new(char *player_id, char *channel) { GPollFD fd; - sd_event_source* busfd_event_source; + sd_event_source *busfd_event_source; - struct audio_player* self = malloc(sizeof(struct audio_player)); + struct audio_player *self = malloc(sizeof(struct audio_player)); if (self == NULL) { return NULL; } @@ -88,7 +88,7 @@ struct audio_player* audio_player_new(char* player_id, char* channel) flutterpi_sd_event_add_io(&busfd_event_source, fd.fd, EPOLLIN, on_bus_fd_ready, self); // Refresh continuously to emit recurring events - g_timeout_add(1000, (GSourceFunc)audio_player_on_refresh, self); + g_timeout_add(1000, (GSourceFunc) audio_player_on_refresh, self); self->player_id = malloc(strlen(player_id) + 1); if (self->player_id == NULL) @@ -118,22 +118,20 @@ struct audio_player* audio_player_new(char* player_id, char* channel) return NULL; } -void audio_player_source_setup(GstElement* playbin, GstElement* source, GstElement** p_src) -{ - (void)playbin; - (void)p_src; +void audio_player_source_setup(GstElement *playbin, GstElement *source, GstElement **p_src) { + (void) playbin; + (void) p_src; if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "ssl-strict") != 0) { g_object_set(G_OBJECT(source), "ssl-strict", FALSE, NULL); } } -gboolean audio_player_on_bus_message(GstBus* bus, GstMessage* message, struct audio_player* data) -{ - (void)bus; +gboolean audio_player_on_bus_message(GstBus *bus, GstMessage *message, struct audio_player *data) { + (void) bus; switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_ERROR: { - GError* err; - gchar* debug; + GError *err; + gchar *debug; gst_message_parse_error(message, &err, &debug); audio_player_on_media_error(data, err, debug); @@ -152,9 +150,7 @@ gboolean audio_player_on_bus_message(GstBus* bus, GstMessage* message, struct au gst_element_set_state(data->playbin, GST_STATE_READY); audio_player_on_playback_ended(data); break; - case GST_MESSAGE_DURATION_CHANGED: - audio_player_on_duration_update(data); - break; + case GST_MESSAGE_DURATION_CHANGED: audio_player_on_duration_update(data); break; case GST_MESSAGE_ASYNC_DONE: if (!data->is_seek_completed) { audio_player_on_seek_completed(data); @@ -171,16 +167,14 @@ gboolean audio_player_on_bus_message(GstBus* bus, GstMessage* message, struct au return TRUE; } -gboolean audio_player_on_refresh(struct audio_player* data) -{ +gboolean audio_player_on_refresh(struct audio_player *data) { if (data->playbin->current_state == GST_STATE_PLAYING) { audio_player_on_position_update(data); } return TRUE; } -void audio_player_set_playback(struct audio_player* self, int64_t seekTo, double rate) -{ +void audio_player_set_playback(struct audio_player *self, int64_t seekTo, double rate) { const GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE; if (!self->is_initialized) { @@ -202,24 +196,11 @@ void audio_player_set_playback(struct audio_player* self, int64_t seekTo, double } self->is_seek_completed = false; - GstEvent* seek_event; + GstEvent *seek_event; if (rate > 0) { - seek_event = gst_event_new_seek( - rate, - GST_FORMAT_TIME, - seek_flags, - GST_SEEK_TYPE_SET, seekTo * GST_MSECOND, - GST_SEEK_TYPE_NONE, - -1 - ); + seek_event = gst_event_new_seek(rate, GST_FORMAT_TIME, seek_flags, GST_SEEK_TYPE_SET, seekTo * GST_MSECOND, GST_SEEK_TYPE_NONE, -1); } else { - seek_event = gst_event_new_seek( - rate, - GST_FORMAT_TIME, - seek_flags, - GST_SEEK_TYPE_SET, 0, - GST_SEEK_TYPE_SET, seekTo * GST_MSECOND - ); + seek_event = gst_event_new_seek(rate, GST_FORMAT_TIME, seek_flags, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, seekTo * GST_MSECOND); } if (!gst_element_send_event(self->playbin, seek_event)) { // FIXME @@ -227,10 +208,9 @@ void audio_player_set_playback(struct audio_player* self, int64_t seekTo, double self->is_seek_completed = true; } } -void audio_player_on_media_error(struct audio_player* self, GError* error, gchar* debug) -{ - (void)debug; - char* error_message = malloc(256 * sizeof(char)); +void audio_player_on_media_error(struct audio_player *self, GError *error, gchar *debug) { + (void) debug; + char *error_message = malloc(256 * sizeof(char)); snprintf(error_message, 256, "Error: %d; message=%s", error->code, error->message); LOG_ERROR("%s", error_message); if (self->channel) { @@ -251,22 +231,20 @@ void audio_player_on_media_error(struct audio_player* self, GError* error, gchar } } -void audio_player_on_media_state_change(struct audio_player* self, GstObject* src, GstState* old_state, GstState* new_state) -{ - (void)old_state; +void audio_player_on_media_state_change(struct audio_player *self, GstObject *src, GstState *old_state, GstState *new_state) { + (void) old_state; if (strcmp(GST_OBJECT_NAME(src), "playbin") == 0) { if (*new_state >= GST_STATE_READY) { if (!self->is_initialized) { self->is_initialized = true; - audio_player_pause(self); // Need to set to pause state, in order to get duration + audio_player_pause(self); // Need to set to pause state, in order to get duration } } else if (self->is_initialized) { self->is_initialized = false; } } } -void audio_player_on_position_update(struct audio_player* self) -{ +void audio_player_on_position_update(struct audio_player *self) { if (self->channel) { // clang-format off platch_call_std( @@ -284,8 +262,7 @@ void audio_player_on_position_update(struct audio_player* self) // clang-format on } } -void audio_player_on_duration_update(struct audio_player* self) -{ +void audio_player_on_duration_update(struct audio_player *self) { if (self->channel) { // clang-format off platch_call_std( @@ -303,8 +280,7 @@ void audio_player_on_duration_update(struct audio_player* self) // clang-format on } } -void audio_player_on_seek_completed(struct audio_player* self) -{ +void audio_player_on_seek_completed(struct audio_player *self) { if (self->channel) { audio_player_on_position_update(self); // clang-format off @@ -323,8 +299,7 @@ void audio_player_on_seek_completed(struct audio_player* self) // clang-format on } } -void audio_player_on_playback_ended(struct audio_player* self) -{ +void audio_player_on_playback_ended(struct audio_player *self) { audio_player_set_position(self, 0); if (audio_player_get_loopin(self)) { audio_player_play(self); @@ -347,18 +322,15 @@ void audio_player_on_playback_ended(struct audio_player* self) } } -void audio_player_set_looping(struct audio_player* self, bool is_looping) -{ +void audio_player_set_looping(struct audio_player *self, bool is_looping) { self->is_looping = is_looping; } -bool audio_player_get_loopin(struct audio_player* self) -{ +bool audio_player_get_loopin(struct audio_player *self) { return self->is_looping; } -void audio_player_play(struct audio_player* self) -{ +void audio_player_play(struct audio_player *self) { if (!self->is_initialized) { return; } @@ -366,18 +338,16 @@ void audio_player_play(struct audio_player* self) audio_player_resume(self); } -void audio_player_pause(struct audio_player* self) -{ +void audio_player_pause(struct audio_player *self) { GstStateChangeReturn ret = gst_element_set_state(self->playbin, GST_STATE_PAUSED); if (ret == GST_STATE_CHANGE_FAILURE) { LOG_ERROR("Unable to set the pipeline to the paused state."); return; } - audio_player_on_position_update(self); // Update to exact position when pausing + audio_player_on_position_update(self); // Update to exact position when pausing } -void audio_player_resume(struct audio_player* self) -{ +void audio_player_resume(struct audio_player *self) { if (!self->is_initialized) { return; } @@ -386,11 +356,10 @@ void audio_player_resume(struct audio_player* self) LOG_ERROR("Unable to set the pipeline to the playing state."); return; } - audio_player_on_duration_update(self); // Update duration when start playing, as no event is emitted elsewhere + audio_player_on_duration_update(self); // Update duration when start playing, as no event is emitted elsewhere } -void audio_player_dispose(struct audio_player* self) -{ +void audio_player_dispose(struct audio_player *self) { if (self->is_initialized) { audio_player_pause(self); } @@ -421,8 +390,7 @@ void audio_player_dispose(struct audio_player* self) } } -int64_t audio_player_get_position(struct audio_player* self) -{ +int64_t audio_player_get_position(struct audio_player *self) { gint64 current = 0; if (!gst_element_query_position(self->playbin, GST_FORMAT_TIME, ¤t)) { LOG_ERROR("Could not query current position."); @@ -431,8 +399,7 @@ int64_t audio_player_get_position(struct audio_player* self) return current / 1000000; } -int64_t audio_player_get_duration(struct audio_player* self) -{ +int64_t audio_player_get_duration(struct audio_player *self) { gint64 duration = 0; if (!gst_element_query_duration(self->playbin, GST_FORMAT_TIME, &duration)) { LOG_ERROR("Could not query current duration."); @@ -441,8 +408,7 @@ int64_t audio_player_get_duration(struct audio_player* self) return duration / 1000000; } -void audio_player_set_volume(struct audio_player* self, double volume) -{ +void audio_player_set_volume(struct audio_player *self, double volume) { if (volume > 1) { volume = 1; } else if (volume < 0) { @@ -451,21 +417,18 @@ void audio_player_set_volume(struct audio_player* self, double volume) g_object_set(G_OBJECT(self->playbin), "volume", volume, NULL); } -void audio_player_set_playback_rate(struct audio_player* self, double rate) -{ +void audio_player_set_playback_rate(struct audio_player *self, double rate) { audio_player_set_playback(self, audio_player_get_position(self), rate); } -void audio_player_set_position(struct audio_player* self, int64_t position) -{ +void audio_player_set_position(struct audio_player *self, int64_t position) { if (!self->is_initialized) { return; } audio_player_set_playback(self, position, self->playback_rate); } -void audio_player_set_source_url(struct audio_player* self, char* url) -{ +void audio_player_set_source_url(struct audio_player *self, char *url) { if (self->url == NULL || strcmp(self->url, url)) { if (self->url != NULL) { free(self->url); @@ -484,6 +447,6 @@ void audio_player_set_source_url(struct audio_player* self, char* url) } } -bool audio_player_is_id(struct audio_player* self, char* player_id) { +bool audio_player_is_id(struct audio_player *self, char *player_id) { return strcmp(self->player_id, player_id) == 0; } diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index 4400c908..b9eeb69c 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -1,47 +1,45 @@ +#include "plugins/audioplayers.h" + #include #include #include #include -#include "plugins/audioplayers.h" - FILE_DESCR("audioplayers plugin") #define AUDIOPLAYERS_LOCAL_CHANNEL "xyz.luan/audioplayers" #define AUDIOPLAYERS_GLOBAL_CHANNEL "xyz.luan/audioplayers.global" -static struct audio_player* audioplayers_linux_plugin_get_player(char* player_id, char* mode); +static struct audio_player *audioplayers_linux_plugin_get_player(char *player_id, char *mode); -static struct plugin -{ - struct flutterpi* flutterpi; +static struct plugin { + struct flutterpi *flutterpi; bool initialized; struct concurrent_pointer_set players; } plugin; -static int on_local_method_call(char* channel, struct platch_obj* object, FlutterPlatformMessageResponseHandle* responsehandle) -{ - const char* method; +static int on_local_method_call(char *channel, struct platch_obj *object, FlutterPlatformMessageResponseHandle *responsehandle) { + const char *method; int result = 1; - (void)responsehandle; - (void)channel; + (void) responsehandle; + (void) channel; method = object->method; - struct std_value* fl_player_id = stdmap_get_str(&object->std_arg, "player_id"); + struct std_value *fl_player_id = stdmap_get_str(&object->std_arg, "player_id"); if (fl_player_id == NULL) { LOG_ERROR("Call missing mandatory parameter player_id."); return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['player_id'] to be a string."); } - char* player_id = STDVALUE_AS_STRING(*fl_player_id); + char *player_id = STDVALUE_AS_STRING(*fl_player_id); - struct std_value* args = &object->std_arg; - struct std_value* fl_mode = stdmap_get_str(args, "mode"); + struct std_value *args = &object->std_arg; + struct std_value *fl_mode = stdmap_get_str(args, "mode"); - char* mode = fl_mode == NULL ? "" : STDVALUE_AS_STRING(*fl_mode); + char *mode = fl_mode == NULL ? "" : STDVALUE_AS_STRING(*fl_mode); // CONTINE - struct audio_player* player = audioplayers_linux_plugin_get_player(player_id, mode); + struct audio_player *player = audioplayers_linux_plugin_get_player(player_id, mode); if (strcmp(method, "pause") == 0) { audio_player_pause(player); @@ -54,23 +52,23 @@ static int on_local_method_call(char* channel, struct platch_obj* object, Flutte audio_player_pause(player); audio_player_set_position(player, 0); } else if (strcmp(method, "seek") == 0) { - struct std_value* fl_position = stdmap_get_str(args, "position"); - int position = fl_position == NULL ? (int)(audio_player_get_position(player)) : STDVALUE_AS_INT(*fl_position); + struct std_value *fl_position = stdmap_get_str(args, "position"); + int position = fl_position == NULL ? (int) (audio_player_get_position(player)) : STDVALUE_AS_INT(*fl_position); audio_player_set_position(player, position); } else if (strcmp(method, "setSourceUrl") == 0) { - struct std_value* fl_url = stdmap_get_str(args, "url"); + struct std_value *fl_url = stdmap_get_str(args, "url"); if (fl_url == NULL) { LOG_ERROR("Null URL received on setSourceUrl"); result = 0; return platch_respond_illegal_arg_std(responsehandle, "URL is NULL"); } - char* url = STDVALUE_AS_STRING(*fl_url); + char *url = STDVALUE_AS_STRING(*fl_url); - struct std_value* fl_is_local = stdmap_get_str(args, "is_local"); + struct std_value *fl_is_local = stdmap_get_str(args, "is_local"); bool is_local = (fl_is_local == NULL) ? false : STDVALUE_AS_BOOL(*fl_is_local); if (is_local) { size_t size = strlen(url) + 7 + 1; - char* tmp = malloc(size); + char *tmp = malloc(size); snprintf(tmp, size, "file://%s", url); url = tmp; } @@ -78,7 +76,7 @@ static int on_local_method_call(char* channel, struct platch_obj* object, Flutte } else if (strcmp(method, "getDuration") == 0) { result = audio_player_get_duration(player); } else if (strcmp(method, "setVolume") == 0) { - struct std_value* fl_volume = stdmap_get_str(args, "volume"); + struct std_value *fl_volume = stdmap_get_str(args, "volume"); if (fl_volume == NULL) { LOG_ERROR("setVolume called with NULL arg, setting vol to 1.0"); audio_player_set_volume(player, 1.0); @@ -92,12 +90,12 @@ static int on_local_method_call(char* channel, struct platch_obj* object, Flutte } else if (strcmp(method, "getCurrentPosition") == 0) { result = audio_player_get_position(player); } else if (strcmp(method, "setPlaybackRate") == 0) { - struct std_value* fl_playback_rate = stdmap_get_str(args, "playback_rate"); + struct std_value *fl_playback_rate = stdmap_get_str(args, "playback_rate"); double playback_rate = fl_playback_rate == NULL ? 1.0 : STDVALUE_AS_FLOAT(*fl_playback_rate); audio_player_set_playback_rate(player, playback_rate); } else if (strcmp(method, "setReleaseMode") == 0) { - struct std_value* fl_release_mode = stdmap_get_str(args, "release_mode"); - char* release_mode = fl_release_mode == NULL ? "" : STDVALUE_AS_STRING(*fl_release_mode); + struct std_value *fl_release_mode = stdmap_get_str(args, "release_mode"); + char *release_mode = fl_release_mode == NULL ? "" : STDVALUE_AS_STRING(*fl_release_mode); if (release_mode == NULL) { LOG_ERROR("Error calling setReleaseMode, release_mode cannot be null"); result = 0; @@ -115,23 +113,22 @@ static int on_local_method_call(char* channel, struct platch_obj* object, Flutte return platch_respond_success_std(responsehandle, &STDINT64(result)); } -static int on_global_method_call(char* channel, struct platch_obj* object, FlutterPlatformMessageResponseHandle* responsehandle) -{ - const char* method; +static int on_global_method_call(char *channel, struct platch_obj *object, FlutterPlatformMessageResponseHandle *responsehandle) { + const char *method; - (void)responsehandle; - (void)channel; + (void) responsehandle; + (void) channel; method = object->method; return platch_respond( - responsehandle, - &(struct platch_obj){ .codec = kStandardMethodCallResponse, .success = true, .std_result = { .type = kStdTrue } }); + responsehandle, + &(struct platch_obj){ .codec = kStandardMethodCallResponse, .success = true, .std_result = { .type = kStdTrue } } + ); } -enum plugin_init_result audioplayers_plugin_init(struct flutterpi* flutterpi, void** userdata_out) -{ - (void)userdata_out; +enum plugin_init_result audioplayers_plugin_init(struct flutterpi *flutterpi, void **userdata_out) { + (void) userdata_out; int ok; plugin.flutterpi = flutterpi; plugin.initialized = false; @@ -161,29 +158,25 @@ enum plugin_init_result audioplayers_plugin_init(struct flutterpi* flutterpi, vo return kError_PluginInitResult; } -void audioplayers_plugin_deinit(struct flutterpi* flutterpi, void* userdata) -{ - (void)flutterpi; - (void)userdata; +void audioplayers_plugin_deinit(struct flutterpi *flutterpi, void *userdata) { + (void) flutterpi; + (void) userdata; plugin_registry_remove_receiver(AUDIOPLAYERS_GLOBAL_CHANNEL); plugin_registry_remove_receiver(AUDIOPLAYERS_LOCAL_CHANNEL); - struct audio_player* ptr; - for_each_pointer_in_cpset(&plugin.players, ptr) - { + struct audio_player *ptr; + for_each_pointer_in_cpset(&plugin.players, ptr) { audio_player_dispose(ptr); } cpset_deinit(&plugin.players); } -static struct audio_player* audioplayers_linux_plugin_get_player(char* player_id, char* mode) -{ - (void)mode; - struct audio_player* player = NULL; - struct audio_player* p; - for_each_pointer_in_cpset(&plugin.players, p) - { +static struct audio_player *audioplayers_linux_plugin_get_player(char *player_id, char *mode) { + (void) mode; + struct audio_player *player = NULL; + struct audio_player *p; + for_each_pointer_in_cpset(&plugin.players, p) { if (audio_player_is_id(p, player_id)) { player = p; break; From c733a49b502abc80d56070005248060c7b114aa7 Mon Sep 17 00:00:00 2001 From: DoumanAsh Date: Mon, 22 Aug 2022 21:31:27 +0900 Subject: [PATCH 04/16] CI: explicitely disable gstreamer plugins --- .github/workflows/cmake.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index fef84518..59a6682c 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -21,14 +21,14 @@ jobs: steps: - uses: actions/checkout@v2 - + - name: Install dependencies run: sudo apt-get install -y cmake libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev ttf-mscorefonts-installer fontconfig libsystemd-dev libinput-dev libudev-dev libxkbcommon-dev ninja-build - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -DBUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN=On -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -GNinja + run: cmake -B ${{github.workspace}}/build -DBUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN=On -DBUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN=off -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -GNinja - name: Build # Build your program with the given configuration @@ -37,7 +37,7 @@ jobs: - name: Test if: false working-directory: ${{github.workspace}}/build - # Execute tests defined by the CMake configuration. + # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: ctest -C ${{env.BUILD_TYPE}} - + From 5eb6cd7c2fdd545954feca0d88de8c950e79a1b9 Mon Sep 17 00:00:00 2001 From: DoumanAsh Date: Tue, 23 Aug 2022 00:03:03 +0900 Subject: [PATCH 05/16] Apply comments --- .github/workflows/cmake.yml | 4 +- include/plugins/audioplayers.h | 4 +- src/plugins/audioplayers/player.c | 43 +++++++++--------- src/plugins/audioplayers/plugin.c | 72 +++++++++++++++---------------- 4 files changed, 63 insertions(+), 60 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 59a6682c..c6a2a2b2 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -23,12 +23,12 @@ jobs: - uses: actions/checkout@v2 - name: Install dependencies - run: sudo apt-get install -y cmake libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev ttf-mscorefonts-installer fontconfig libsystemd-dev libinput-dev libudev-dev libxkbcommon-dev ninja-build + run: sudo apt-get install -y cmake libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev ttf-mscorefonts-installer fontconfig libsystemd-dev libinput-dev libudev-dev libxkbcommon-dev ninja-build libgstreamer-plugins-base1.0-dev - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -DBUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN=On -DBUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN=off -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -GNinja + run: cmake -B ${{github.workspace}}/build -DBUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN=On -DBUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN=on -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -GNinja - name: Build # Build your program with the given configuration diff --git a/include/plugins/audioplayers.h b/include/plugins/audioplayers.h index 33ba64a3..99596e21 100644 --- a/include/plugins/audioplayers.h +++ b/include/plugins/audioplayers.h @@ -16,7 +16,7 @@ int64_t audio_player_get_position(struct audio_player *self); int64_t audio_player_get_duration(struct audio_player *self); -bool audio_player_get_loopin(struct audio_player *self); +bool audio_player_get_looping(struct audio_player *self); void audio_player_play(struct audio_player *self); @@ -24,7 +24,7 @@ void audio_player_pause(struct audio_player *self); void audio_player_resume(struct audio_player *self); -void audio_player_dispose(struct audio_player *self); +void audio_player_destroy(struct audio_player *self); void audio_player_set_looping(struct audio_player *self, bool isLooping); diff --git a/src/plugins/audioplayers/player.c b/src/plugins/audioplayers/player.c index 0163e202..6108dfda 100644 --- a/src/plugins/audioplayers/player.c +++ b/src/plugins/audioplayers/player.c @@ -77,7 +77,8 @@ struct audio_player *audio_player_new(char *player_id, char *channel) { gst_init(NULL, NULL); self->playbin = gst_element_factory_make("playbin", "playbin"); if (!self->playbin) { - LOG_ERROR("Not all elements could be created"); + LOG_ERROR("Could not create gstreamer playbin.\n"); + goto deinit_self; } g_signal_connect(self->playbin, "source-setup", G_CALLBACK(audio_player_source_setup), &self->source); @@ -90,15 +91,13 @@ struct audio_player *audio_player_new(char *player_id, char *channel) { // Refresh continuously to emit recurring events g_timeout_add(1000, (GSourceFunc) audio_player_on_refresh, self); - self->player_id = malloc(strlen(player_id) + 1); + self->player_id = strdup(player_id); if (self->player_id == NULL) goto deinit_player; - strcpy(self->player_id, player_id); - self->channel = malloc(strlen(channel) + 1); + self->channel = strdup(channel); if (self->channel == NULL) goto deinit_player_id; - strcpy(self->channel, channel); return self; @@ -114,16 +113,21 @@ struct audio_player *audio_player_new(char *player_id, char *channel) { gst_element_set_state(self->playbin, GST_STATE_NULL); gst_object_unref(self->playbin); +deinit_self: free(self); return NULL; } void audio_player_source_setup(GstElement *playbin, GstElement *source, GstElement **p_src) { (void) playbin; + (void) source; (void) p_src; + /** + * Consider if we want to add option to enable strict SSL check. if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "ssl-strict") != 0) { g_object_set(G_OBJECT(source), "ssl-strict", FALSE, NULL); } + */ } gboolean audio_player_on_bus_message(GstBus *bus, GstMessage *message, struct audio_player *data) { @@ -203,16 +207,15 @@ void audio_player_set_playback(struct audio_player *self, int64_t seekTo, double seek_event = gst_event_new_seek(rate, GST_FORMAT_TIME, seek_flags, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, seekTo * GST_MSECOND); } if (!gst_element_send_event(self->playbin, seek_event)) { - // FIXME - LOG_ERROR("Could not set playback to position %ld and rate %f.", seekTo, rate); + // Not clear how to treat this error? + LOG_ERROR("Could not set playback to position " GST_TIME_FORMAT " and rate %u.\n", GST_TIME_ARGS(seekTo * GST_MSECOND), rate); self->is_seek_completed = true; } } void audio_player_on_media_error(struct audio_player *self, GError *error, gchar *debug) { (void) debug; - char *error_message = malloc(256 * sizeof(char)); - snprintf(error_message, 256, "Error: %d; message=%s", error->code, error->message); - LOG_ERROR("%s", error_message); + char error_message[256] = {0}; + snprintf(error_message, sizeof(error_message), "Error: %d; message=%s", error->code, error->message); if (self->channel) { // clang-format off platch_call_std( @@ -301,7 +304,7 @@ void audio_player_on_seek_completed(struct audio_player *self) { } void audio_player_on_playback_ended(struct audio_player *self) { audio_player_set_position(self, 0); - if (audio_player_get_loopin(self)) { + if (audio_player_get_looping(self)) { audio_player_play(self); } if (self->channel) { @@ -326,7 +329,7 @@ void audio_player_set_looping(struct audio_player *self, bool is_looping) { self->is_looping = is_looping; } -bool audio_player_get_loopin(struct audio_player *self) { +bool audio_player_get_looping(struct audio_player *self) { return self->is_looping; } @@ -341,7 +344,7 @@ void audio_player_play(struct audio_player *self) { void audio_player_pause(struct audio_player *self) { GstStateChangeReturn ret = gst_element_set_state(self->playbin, GST_STATE_PAUSED); if (ret == GST_STATE_CHANGE_FAILURE) { - LOG_ERROR("Unable to set the pipeline to the paused state."); + LOG_ERROR("Unable to set the pipeline to the paused state.\n"); return; } audio_player_on_position_update(self); // Update to exact position when pausing @@ -353,13 +356,14 @@ void audio_player_resume(struct audio_player *self) { } GstStateChangeReturn ret = gst_element_set_state(self->playbin, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { - LOG_ERROR("Unable to set the pipeline to the playing state."); + LOG_ERROR("Unable to set the pipeline to the playing state.\n"); return; } - audio_player_on_duration_update(self); // Update duration when start playing, as no event is emitted elsewhere + // Update duration when start playing, as no event is emitted elsewhere + audio_player_on_duration_update(self); } -void audio_player_dispose(struct audio_player *self) { +void audio_player_destroy(struct audio_player *self) { if (self->is_initialized) { audio_player_pause(self); } @@ -393,7 +397,7 @@ void audio_player_dispose(struct audio_player *self) { int64_t audio_player_get_position(struct audio_player *self) { gint64 current = 0; if (!gst_element_query_position(self->playbin, GST_FORMAT_TIME, ¤t)) { - LOG_ERROR("Could not query current position."); + LOG_ERROR("Could not query current position.\n"); return 0; } return current / 1000000; @@ -402,7 +406,7 @@ int64_t audio_player_get_position(struct audio_player *self) { int64_t audio_player_get_duration(struct audio_player *self) { gint64 duration = 0; if (!gst_element_query_duration(self->playbin, GST_FORMAT_TIME, &duration)) { - LOG_ERROR("Could not query current duration."); + LOG_ERROR("Could not query current duration.\n"); return 0; } return duration / 1000000; @@ -434,8 +438,7 @@ void audio_player_set_source_url(struct audio_player *self, char *url) { free(self->url); self->url = NULL; } - self->url = malloc(strlen(url) + 1); - strcpy(self->url, url); + self->url = strdup(url); gst_element_set_state(self->playbin, GST_STATE_NULL); if (strlen(self->url) != 0) { g_object_set(self->playbin, "uri", self->url, NULL); diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index b9eeb69c..f6671047 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -19,28 +19,36 @@ static struct plugin { } plugin; static int on_local_method_call(char *channel, struct platch_obj *object, FlutterPlatformMessageResponseHandle *responsehandle) { + struct audio_player *player; + struct std_value *args, *tmp; const char *method; + char *player_id, *mode; int result = 1; - (void) responsehandle; (void) channel; - method = object->method; - struct std_value *fl_player_id = stdmap_get_str(&object->std_arg, "player_id"); - if (fl_player_id == NULL) { - LOG_ERROR("Call missing mandatory parameter player_id."); - return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['player_id'] to be a string."); - } - char *player_id = STDVALUE_AS_STRING(*fl_player_id); + args = &object->std_arg; - struct std_value *args = &object->std_arg; - struct std_value *fl_mode = stdmap_get_str(args, "mode"); - - char *mode = fl_mode == NULL ? "" : STDVALUE_AS_STRING(*fl_mode); + if (args == NULL || !STDVALUE_IS_MAP(*args)) { + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg` to be a map."); + } - // CONTINE - struct audio_player *player = audioplayers_linux_plugin_get_player(player_id, mode); + tmp = stdmap_get_str(&object->std_arg, "player_id"); + if (tmp == NULL || !STDVALUE_IS_STRING(*tmp)) { + LOG_ERROR("Call missing mandatory parameter player_id.\n"); + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['player_id'] to be a string."); + } + player_id = STDVALUE_AS_STRING(*tmp); + tmp = stdmap_get_str(args, "mode"); + if (tmp == NULL) { + mode = ""; + } else if (STDVALUE_IS_STRING(*tmp)) { + mode = STDVALUE_AS_STRING(*tmp); + } else { + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['mode']` to be a string or null."); + } + player = audioplayers_linux_plugin_get_player(player_id, mode); if (strcmp(method, "pause") == 0) { audio_player_pause(player); } else if (strcmp(method, "resume") == 0) { @@ -58,7 +66,7 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte } else if (strcmp(method, "setSourceUrl") == 0) { struct std_value *fl_url = stdmap_get_str(args, "url"); if (fl_url == NULL) { - LOG_ERROR("Null URL received on setSourceUrl"); + LOG_ERROR("Null URL received on setSourceUrl\n"); result = 0; return platch_respond_illegal_arg_std(responsehandle, "URL is NULL"); } @@ -78,10 +86,10 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte } else if (strcmp(method, "setVolume") == 0) { struct std_value *fl_volume = stdmap_get_str(args, "volume"); if (fl_volume == NULL) { - LOG_ERROR("setVolume called with NULL arg, setting vol to 1.0"); + LOG_ERROR("setVolume called with NULL arg, setting vol to 1.0\n"); audio_player_set_volume(player, 1.0); } else if (!STDVALUE_IS_FLOAT(*fl_volume)) { - LOG_ERROR("setVolume called with non float arg, setting vol to 1.0"); + LOG_ERROR("setVolume called with non float arg, setting vol to 1.0\n"); audio_player_set_volume(player, 1.0); } else { double volume = STDVALUE_AS_FLOAT(*fl_volume); @@ -97,7 +105,7 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte struct std_value *fl_release_mode = stdmap_get_str(args, "release_mode"); char *release_mode = fl_release_mode == NULL ? "" : STDVALUE_AS_STRING(*fl_release_mode); if (release_mode == NULL) { - LOG_ERROR("Error calling setReleaseMode, release_mode cannot be null"); + LOG_ERROR("Error calling setReleaseMode, release_mode cannot be null\n"); result = 0; return platch_respond_illegal_arg_std(responsehandle, "release_mode cannot be null"); } @@ -121,10 +129,7 @@ static int on_global_method_call(char *channel, struct platch_obj *object, Flutt method = object->method; - return platch_respond( - responsehandle, - &(struct platch_obj){ .codec = kStandardMethodCallResponse, .success = true, .std_result = { .type = kStdTrue } } - ); + return platch_respond_success_std(responsehandle, &STDBOOL(true)); } enum plugin_init_result audioplayers_plugin_init(struct flutterpi *flutterpi, void **userdata_out) { @@ -166,7 +171,7 @@ void audioplayers_plugin_deinit(struct flutterpi *flutterpi, void *userdata) { struct audio_player *ptr; for_each_pointer_in_cpset(&plugin.players, ptr) { - audio_player_dispose(ptr); + audio_player_destroy(ptr); } cpset_deinit(&plugin.players); @@ -174,21 +179,16 @@ void audioplayers_plugin_deinit(struct flutterpi *flutterpi, void *userdata) { static struct audio_player *audioplayers_linux_plugin_get_player(char *player_id, char *mode) { (void) mode; - struct audio_player *player = NULL; - struct audio_player *p; - for_each_pointer_in_cpset(&plugin.players, p) { - if (audio_player_is_id(p, player_id)) { - player = p; - break; + struct audio_player *player; + for_each_pointer_in_cpset(&plugin.players, player) { + if (audio_player_is_id(player, player_id)) { + return player; } } - if (player != NULL) { - return player; - } else { - player = audio_player_new(player_id, AUDIOPLAYERS_LOCAL_CHANNEL); - cpset_put_locked(&plugin.players, player); - return player; - } + + player = audio_player_new(player_id, AUDIOPLAYERS_LOCAL_CHANNEL); + cpset_put_locked(&plugin.players, player); + return player; } FLUTTERPI_PLUGIN("audioplayers", audioplayers, audioplayers_plugin_init, audioplayers_plugin_deinit) From 6c8d96ca1e73843b4292a43986d66191480a95c0 Mon Sep 17 00:00:00 2001 From: DoumanAsh Date: Tue, 23 Aug 2022 00:11:12 +0900 Subject: [PATCH 06/16] Apply comments --- src/plugins/audioplayers/player.c | 3 ++- src/plugins/audioplayers/plugin.c | 5 +---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/plugins/audioplayers/player.c b/src/plugins/audioplayers/player.c index 6108dfda..d7ac7904 100644 --- a/src/plugins/audioplayers/player.c +++ b/src/plugins/audioplayers/player.c @@ -208,7 +208,8 @@ void audio_player_set_playback(struct audio_player *self, int64_t seekTo, double } if (!gst_element_send_event(self->playbin, seek_event)) { // Not clear how to treat this error? - LOG_ERROR("Could not set playback to position " GST_TIME_FORMAT " and rate %u.\n", GST_TIME_ARGS(seekTo * GST_MSECOND), rate); + const int64_t seekMs = seekTo * GST_MSECOND; + LOG_ERROR("Could not set playback to position " GST_STIME_FORMAT " and rate %f.\n", GST_TIME_ARGS(seekMs), rate); self->is_seek_completed = true; } } diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index f6671047..a31384c0 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -122,12 +122,9 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte } static int on_global_method_call(char *channel, struct platch_obj *object, FlutterPlatformMessageResponseHandle *responsehandle) { - const char *method; - (void) responsehandle; (void) channel; - - method = object->method; + (void) object; return platch_respond_success_std(responsehandle, &STDBOOL(true)); } From c78ba6de4ae69edf50c2318d0e65b94d52b14f73 Mon Sep 17 00:00:00 2001 From: Douman Date: Tue, 23 Aug 2022 04:34:44 -0700 Subject: [PATCH 07/16] Update src/plugins/audioplayers/player.c Co-authored-by: Hannes Winkler --- src/plugins/audioplayers/player.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/audioplayers/player.c b/src/plugins/audioplayers/player.c index d7ac7904..64321a58 100644 --- a/src/plugins/audioplayers/player.c +++ b/src/plugins/audioplayers/player.c @@ -434,6 +434,7 @@ void audio_player_set_position(struct audio_player *self, int64_t position) { } void audio_player_set_source_url(struct audio_player *self, char *url) { + DEBUG_ASSERT_NOT_NULL(url); if (self->url == NULL || strcmp(self->url, url)) { if (self->url != NULL) { free(self->url); From f7a283cb239ecf359c3c0698303e2d4b75d8ef79 Mon Sep 17 00:00:00 2001 From: Douman Date: Thu, 25 Aug 2022 05:58:44 -0700 Subject: [PATCH 08/16] Update src/plugins/audioplayers/plugin.c Co-authored-by: Hannes Winkler --- src/plugins/audioplayers/plugin.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index a31384c0..af12880b 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -60,8 +60,12 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte audio_player_pause(player); audio_player_set_position(player, 0); } else if (strcmp(method, "seek") == 0) { - struct std_value *fl_position = stdmap_get_str(args, "position"); - int position = fl_position == NULL ? (int) (audio_player_get_position(player)) : STDVALUE_AS_INT(*fl_position); + tmp = stdmap_get_str(args, "position"); + if (tmp == NULL || !STDVALUE_IS_INT(*tmp)) { + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['position']` to be an int."); + } + + int64_t position = STDVALUE_AS_INT(*tmp); audio_player_set_position(player, position); } else if (strcmp(method, "setSourceUrl") == 0) { struct std_value *fl_url = stdmap_get_str(args, "url"); From 10b9aa01c8e45096791f7a73f75200375c2ee600 Mon Sep 17 00:00:00 2001 From: Douman Date: Thu, 25 Aug 2022 05:58:52 -0700 Subject: [PATCH 09/16] Update src/plugins/audioplayers/plugin.c Co-authored-by: Hannes Winkler --- src/plugins/audioplayers/plugin.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index af12880b..9bd918b2 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -68,13 +68,11 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte int64_t position = STDVALUE_AS_INT(*tmp); audio_player_set_position(player, position); } else if (strcmp(method, "setSourceUrl") == 0) { - struct std_value *fl_url = stdmap_get_str(args, "url"); - if (fl_url == NULL) { - LOG_ERROR("Null URL received on setSourceUrl\n"); - result = 0; - return platch_respond_illegal_arg_std(responsehandle, "URL is NULL"); + tmp = stdmap_get_str(args, "url"); + if (tmp == NULL || !STDVALUE_IS_STRING(*tmp)) { + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['url']` to be a string."); } - char *url = STDVALUE_AS_STRING(*fl_url); + char *url = STDVALUE_AS_STRING(*tmp); struct std_value *fl_is_local = stdmap_get_str(args, "is_local"); bool is_local = (fl_is_local == NULL) ? false : STDVALUE_AS_BOOL(*fl_is_local); From fc6535c177f13d65e364a1a51a259db481fe0228 Mon Sep 17 00:00:00 2001 From: Douman Date: Thu, 25 Aug 2022 05:59:04 -0700 Subject: [PATCH 10/16] Update src/plugins/audioplayers/plugin.c Co-authored-by: Hannes Winkler --- src/plugins/audioplayers/plugin.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index 9bd918b2..981efb14 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -74,14 +74,18 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte } char *url = STDVALUE_AS_STRING(*tmp); - struct std_value *fl_is_local = stdmap_get_str(args, "is_local"); - bool is_local = (fl_is_local == NULL) ? false : STDVALUE_AS_BOOL(*fl_is_local); + tmp = stdmap_get_str(args, "is_local"); + if (tmp == NULL || !STDVALUE_IS_BOOL(*tmp)) { + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['is_local']` to be a bool."); + } + + bool is_local = STDVALUE_AS_BOOL(*tmp); if (is_local) { - size_t size = strlen(url) + 7 + 1; - char *tmp = malloc(size); - snprintf(tmp, size, "file://%s", url); - url = tmp; + char *local_url = NULL; + asprintf(&local_url, "file://%s", url); + url = local_url; } + audio_player_set_source_url(player, url); } else if (strcmp(method, "getDuration") == 0) { result = audio_player_get_duration(player); From deb4ab6585b5da3e344323e49eddbfec4e751f37 Mon Sep 17 00:00:00 2001 From: Douman Date: Thu, 25 Aug 2022 05:59:13 -0700 Subject: [PATCH 11/16] Update src/plugins/audioplayers/plugin.c Co-authored-by: Hannes Winkler --- src/plugins/audioplayers/plugin.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index 981efb14..3a89cf81 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -90,16 +90,11 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte } else if (strcmp(method, "getDuration") == 0) { result = audio_player_get_duration(player); } else if (strcmp(method, "setVolume") == 0) { - struct std_value *fl_volume = stdmap_get_str(args, "volume"); - if (fl_volume == NULL) { - LOG_ERROR("setVolume called with NULL arg, setting vol to 1.0\n"); - audio_player_set_volume(player, 1.0); - } else if (!STDVALUE_IS_FLOAT(*fl_volume)) { - LOG_ERROR("setVolume called with non float arg, setting vol to 1.0\n"); - audio_player_set_volume(player, 1.0); - } else { - double volume = STDVALUE_AS_FLOAT(*fl_volume); - audio_player_set_volume(player, volume); + tmp = stdmap_get_str(args, "volume"); + if (tmp != NULL && STDVALUE_IS_FLOAT(*tmp)) { + audio_player_set_volume(player, STDVALUE_AS_FLOAT(*tmp)); + } else if { + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['volume']` to be a float."); } } else if (strcmp(method, "getCurrentPosition") == 0) { result = audio_player_get_position(player); From 3198904e8376c378561168d0dee1903da01b24c4 Mon Sep 17 00:00:00 2001 From: Douman Date: Thu, 25 Aug 2022 05:59:22 -0700 Subject: [PATCH 12/16] Update src/plugins/audioplayers/plugin.c Co-authored-by: Hannes Winkler --- src/plugins/audioplayers/plugin.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index 3a89cf81..22bd5c50 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -103,15 +103,14 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte double playback_rate = fl_playback_rate == NULL ? 1.0 : STDVALUE_AS_FLOAT(*fl_playback_rate); audio_player_set_playback_rate(player, playback_rate); } else if (strcmp(method, "setReleaseMode") == 0) { - struct std_value *fl_release_mode = stdmap_get_str(args, "release_mode"); - char *release_mode = fl_release_mode == NULL ? "" : STDVALUE_AS_STRING(*fl_release_mode); - if (release_mode == NULL) { - LOG_ERROR("Error calling setReleaseMode, release_mode cannot be null\n"); - result = 0; - return platch_respond_illegal_arg_std(responsehandle, "release_mode cannot be null"); + tmp = stdmap_get_str(args, "release_mode"); + if (tmp != NULL && STDVALUE_IS_STRING(*tmp)) { + char *release_mode = STDVALUE_AS_STRING(*tmp); + bool looping = strstr(release_mode, "loop") != NULL; + audio_player_set_looping(player, looping); + } else { + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['release_mode']` to be a string."); } - bool looping = strstr(release_mode, "loop") != NULL; - audio_player_set_looping(player, looping); } else if (strcmp(method, "setPlayerMode") == 0) { // TODO check support for low latency mode: // https://gstreamer.freedesktop.org/documentation/additional/design/latency.html?gi-language=c From 25b07efbb4586659360441bab496dd07cef8d2ff Mon Sep 17 00:00:00 2001 From: Douman Date: Thu, 25 Aug 2022 05:59:35 -0700 Subject: [PATCH 13/16] Update src/plugins/audioplayers/plugin.c Co-authored-by: Hannes Winkler --- src/plugins/audioplayers/plugin.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index 22bd5c50..09178ef7 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -99,9 +99,12 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte } else if (strcmp(method, "getCurrentPosition") == 0) { result = audio_player_get_position(player); } else if (strcmp(method, "setPlaybackRate") == 0) { - struct std_value *fl_playback_rate = stdmap_get_str(args, "playback_rate"); - double playback_rate = fl_playback_rate == NULL ? 1.0 : STDVALUE_AS_FLOAT(*fl_playback_rate); - audio_player_set_playback_rate(player, playback_rate); + tmp = stdmap_get_str(args, "playback_rate"); + if (tmp != NULL && STDVALUE_IS_FLOAT(*tmp)) { + audio_player_set_playback_rate(player, STDVALUE_AS_FLOAT(*tmp)); + } else { + return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['playback_rate']` to be a float."); + } } else if (strcmp(method, "setReleaseMode") == 0) { tmp = stdmap_get_str(args, "release_mode"); if (tmp != NULL && STDVALUE_IS_STRING(*tmp)) { From decfdc22f972eb03e546ce6573ad0b8d96ad9790 Mon Sep 17 00:00:00 2001 From: DoumanAsh Date: Thu, 25 Aug 2022 22:13:41 +0900 Subject: [PATCH 14/16] Apply comments and add extra error handling --- src/plugins/audioplayers/player.c | 8 ++------ src/plugins/audioplayers/plugin.c | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/plugins/audioplayers/player.c b/src/plugins/audioplayers/player.c index 64321a58..20f847aa 100644 --- a/src/plugins/audioplayers/player.c +++ b/src/plugins/audioplayers/player.c @@ -13,7 +13,6 @@ FILE_DESCR("audioplayers player") struct audio_player { GstElement *playbin; - GstElement *source; GstBus *bus; bool is_initialized; @@ -27,7 +26,6 @@ struct audio_player { }; // Private Class functions -static void audio_player_source_setup(GstElement *playbin, GstElement *source, GstElement **p_src); static gboolean audio_player_on_bus_message(GstBus *bus, GstMessage *message, struct audio_player *data); static gboolean audio_player_on_refresh(struct audio_player *data); static void audio_player_set_playback(struct audio_player *self, int64_t seekTo, double rate); @@ -80,7 +78,6 @@ struct audio_player *audio_player_new(char *player_id, char *channel) { LOG_ERROR("Could not create gstreamer playbin.\n"); goto deinit_self; } - g_signal_connect(self->playbin, "source-setup", G_CALLBACK(audio_player_source_setup), &self->source); self->bus = gst_element_get_bus(self->playbin); @@ -109,7 +106,6 @@ struct audio_player *audio_player_new(char *player_id, char *channel) { free(self->channel); gst_object_unref(self->bus); - gst_object_unref(self->source); gst_element_set_state(self->playbin, GST_STATE_NULL); gst_object_unref(self->playbin); @@ -370,8 +366,6 @@ void audio_player_destroy(struct audio_player *self) { } gst_object_unref(self->bus); self->bus = NULL; - gst_object_unref(self->source); - self->source = NULL; gst_element_set_state(self->playbin, GST_STATE_NULL); gst_object_unref(self->playbin); @@ -393,6 +387,8 @@ void audio_player_destroy(struct audio_player *self) { free(self->channel); self->channel = NULL; } + + free(self); } int64_t audio_player_get_position(struct audio_player *self) { diff --git a/src/plugins/audioplayers/plugin.c b/src/plugins/audioplayers/plugin.c index 09178ef7..17499abc 100644 --- a/src/plugins/audioplayers/plugin.c +++ b/src/plugins/audioplayers/plugin.c @@ -1,3 +1,5 @@ +#define _GNU_SOURCE + #include "plugins/audioplayers.h" #include @@ -49,6 +51,10 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte } player = audioplayers_linux_plugin_get_player(player_id, mode); + if (player == NULL) { + return platch_respond_native_error_std(responsehandle, ENOMEM); + } + if (strcmp(method, "pause") == 0) { audio_player_pause(player); } else if (strcmp(method, "resume") == 0) { @@ -64,7 +70,7 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte if (tmp == NULL || !STDVALUE_IS_INT(*tmp)) { return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['position']` to be an int."); } - + int64_t position = STDVALUE_AS_INT(*tmp); audio_player_set_position(player, position); } else if (strcmp(method, "setSourceUrl") == 0) { @@ -78,14 +84,17 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte if (tmp == NULL || !STDVALUE_IS_BOOL(*tmp)) { return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['is_local']` to be a bool."); } - + bool is_local = STDVALUE_AS_BOOL(*tmp); if (is_local) { char *local_url = NULL; asprintf(&local_url, "file://%s", url); + if (local_url == NULL) { + return platch_respond_native_error_std(responsehandle, ENOMEM); + } url = local_url; } - + audio_player_set_source_url(player, url); } else if (strcmp(method, "getDuration") == 0) { result = audio_player_get_duration(player); @@ -93,7 +102,7 @@ static int on_local_method_call(char *channel, struct platch_obj *object, Flutte tmp = stdmap_get_str(args, "volume"); if (tmp != NULL && STDVALUE_IS_FLOAT(*tmp)) { audio_player_set_volume(player, STDVALUE_AS_FLOAT(*tmp)); - } else if { + } else { return platch_respond_illegal_arg_std(responsehandle, "Expected `arg['volume']` to be a float."); } } else if (strcmp(method, "getCurrentPosition") == 0) { From ab208846f5d62696822c12b724ab606747469e49 Mon Sep 17 00:00:00 2001 From: DoumanAsh Date: Fri, 26 Aug 2022 00:32:29 +0900 Subject: [PATCH 15/16] Final comment --- include/plugins/audioplayers.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/plugins/audioplayers.h b/include/plugins/audioplayers.h index 99596e21..c5a3c547 100644 --- a/include/plugins/audioplayers.h +++ b/include/plugins/audioplayers.h @@ -4,8 +4,6 @@ #include #include -#include - struct audio_player; struct audio_player *audio_player_new(char *playerId, char *channel); From acbb2f3c413647a4f40f94c8493e0cbb455bcb92 Mon Sep 17 00:00:00 2001 From: DoumanAsh Date: Fri, 26 Aug 2022 01:11:37 +0900 Subject: [PATCH 16/16] Separate video and audio plugins --- .github/workflows/cmake.yml | 2 +- CMakeLists.txt | 61 +++++++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index c6a2a2b2..e7f0ea21 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -28,7 +28,7 @@ jobs: - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -DBUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN=On -DBUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN=on -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -GNinja + run: cmake -B ${{github.workspace}}/build -DBUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN=On -DBUILD_GSTREAMER_AUDIO_PLAYER_PLUGIN=On -DBUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN=On -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -GNinja - name: Build # Build your program with the given configuration diff --git a/CMakeLists.txt b/CMakeLists.txt index 07ffe8d4..40efee21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,8 +40,10 @@ option(BUILD_TEXT_INPUT_PLUGIN "Include the text input plugin in the finished bi option(BUILD_RAW_KEYBOARD_PLUGIN "Include the raw keyboard plugin in the finished binary. Enables raw keycode listening in flutter via the flutter RawKeyboard interface." ON) option(BUILD_TEST_PLUGIN "Include the test plugin in the finished binary. Allows testing platform channel communication." OFF) option(BUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN "Include the omxplayer_video_player plugin in the finished binary. Allows for hardware accelerated video playback in flutter using omxplayer." ON) -option(BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN "Include the gstreamer based video and audio plugins in the finished binary. Allows for more stable, hardware accelerated video playback in flutter using gstreamer." ON) -option(TRY_BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN "Don't throw an error if the gstreamer libs aren't found, instead just don't build the gstreamer audio and video player plugin in that case." ON) +option(BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN "Include the gstreamer based video plugins in the finished binary. Allows for more stable, hardware accelerated video playback in flutter using gstreamer." ON) +option(BUILD_GSTREAMER_AUDIO_PLAYER_PLUGIN "Include the gstreamer based audio plugins in the finished binary." ON) +option(TRY_BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN "Don't throw an error if the gstreamer libs aren't found, instead just don't build the gstreamer video player plugin in that case." ON) +option(TRY_BUILD_GSTREAMER_AUDIO_PLAYER_PLUGIN "Don't throw an error if the gstreamer libs aren't found, instead just don't build gstreamer audio plugin." ON) option(DUMP_ENGINE_LAYERS "True if flutter-pi should dump the list of rendering layers that the flutter engine sends to flutter-pi on each draw." OFF) option(ENABLE_TSAN "True to build & link with -fsanitize=thread" OFF) option(ENABLE_ASAN "True to build & link with -fsanitize=address" OFF) @@ -130,7 +132,7 @@ target_link_libraries(flutter-pi ${GBM_LDFLAGS} ${EGL_LDFLAGS} ${GLESV2_LDFLAGS} - EGL + EGL systemd #${LIBSYSTEMD_LDFLAGS} input #${LIBINPUT_LDFLAGS} xkbcommon #${LIBUDEV_LDFLAGS} @@ -153,7 +155,7 @@ target_include_directories(flutter-pi PRIVATE ) target_compile_options(flutter-pi PRIVATE - ${DRM_CFLAGS} + ${DRM_CFLAGS} ${GBM_CFLAGS} ${EGL_CFLAGS} ${GLESV2_CFLAGS} @@ -166,7 +168,7 @@ target_compile_options(flutter-pi PRIVATE $<$:-O2 -Wall -Wextra -Wno-unused-function -Wno-sign-compare -Wno-missing-field-initializers -ggdb> ) -# TODO: Just unconditionally define those, make them optional later +# TODO: Just unconditionally define those, make them optional later target_compile_definitions(flutter-pi PRIVATE HAS_KMS HAS_EGL HAS_GBM HAS_FBDEV) # TODO: We actually don't need the compile definitions anymore, except for @@ -191,21 +193,19 @@ endif() if (OMXPLAYER_SUPPORTS_RUNTIME_ROTATION) target_compile_definitions(flutter-pi PRIVATE "OMXPLAYER_SUPPORTS_RUNTIME_ROTATION") endif() -if (BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN) - if (TRY_BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN) +if (BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN) + if (TRY_BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN) pkg_check_modules(LIBGSTREAMER gstreamer-1.0) pkg_check_modules(LIBGSTREAMER_PLUGINS_BASE gstreamer-plugins-base-1.0) pkg_check_modules(LIBGSTREAMER_APP gstreamer-app-1.0) pkg_check_modules(LIBGSTREAMER_ALLOCATORS gstreamer-allocators-1.0) pkg_check_modules(LIBGSTREAMER_VIDEO gstreamer-video-1.0) - pkg_check_modules(LIBGSTREAMER-AUDIO REQUIRED gstreamer-audio-1.0) else() pkg_check_modules(LIBGSTREAMER REQUIRED gstreamer-1.0) pkg_check_modules(LIBGSTREAMER_PLUGINS_BASE REQUIRED gstreamer-plugins-base-1.0) pkg_check_modules(LIBGSTREAMER_APP REQUIRED gstreamer-app-1.0) pkg_check_modules(LIBGSTREAMER_ALLOCATORS REQUIRED gstreamer-allocators-1.0) pkg_check_modules(LIBGSTREAMER_VIDEO REQUIRED gstreamer-video-1.0) - pkg_check_modules(LIBGSTREAMER-AUDIO REQUIRED gstreamer-audio-1.0) endif() if (LIBGSTREAMER_FOUND AND LIBGSTREAMER_PLUGINS_BASE_FOUND AND LIBGSTREAMER_APP_FOUND AND LIBGSTREAMER_ALLOCATORS_FOUND AND LIBGSTREAMER_VIDEO_FOUND) @@ -213,8 +213,6 @@ if (BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN) src/plugins/gstreamer_video_player/plugin.c src/plugins/gstreamer_video_player/player.c src/plugins/gstreamer_video_player/frame.c - src/plugins/audioplayers/plugin.c - src/plugins/audioplayers/player.c ) target_compile_definitions(flutter-pi PRIVATE "BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN") target_link_libraries(flutter-pi @@ -223,7 +221,7 @@ if (BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN) ${LIBGSTREAMER_APP_LDFLAGS} ${LIBGSTREAMER_ALLOCATORS_LDFLAGS} ${LIBGSTREAMER_VIDEO_LDFLAGS} - ${LIBGSTREAMER-AUDIO_LIBRARY_DIRS} + ${LIBGSTREAMER_AUDIO_LIBRARY_DIRS} ) target_include_directories(flutter-pi PRIVATE ${LIBGSTREAMER_INCLUDE_DIRS} @@ -231,7 +229,7 @@ if (BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN) ${LIBGSTREAMER_APP_INCLUDE_DIRS} ${LIBGSTREAMER_ALLOCATORS_INCLUDE_DIRS} ${LIBGSTREAMER_VIDEO_INCLUDE_DIRS} - ${LIBGSTREAMER-AUDIO_INCLUDE_DIRS} + ${LIBGSTREAMER_AUDIO_INCLUDE_DIRS} ) target_compile_options(flutter-pi PRIVATE ${LIBGSTREAMER_CFLAGS} @@ -246,6 +244,43 @@ if (BUILD_GSTREAMER_AUDIO_VIDEO_PLAYER_PLUGIN) endif() endif() +if (BUILD_GSTREAMER_AUDIO_PLAYER_PLUGIN) + if (TRY_BUILD_GSTREAMER_AUDIO_PLAYER_PLUGIN) + pkg_check_modules(LIBGSTREAMER gstreamer-1.0) + pkg_check_modules(LIBGSTREAMER_APP gstreamer-app-1.0) + pkg_check_modules(LIBGSTREAMER_AUDIO gstreamer-audio-1.0) + else() + pkg_check_modules(LIBGSTREAMER REQUIRED gstreamer-1.0) + pkg_check_modules(LIBGSTREAMER_APP REQUIRED gstreamer-app-1.0) + pkg_check_modules(LIBGSTREAMER_AUDIO REQUIRED gstreamer-audio-1.0) + endif() + + if (LIBGSTREAMER_FOUND AND LIBGSTREAMER_APP_FOUND AND LIBGSTREAMER_AUDIO_FOUND) + target_sources(flutter-pi PRIVATE + src/plugins/audioplayers/plugin.c + src/plugins/audioplayers/player.c + ) + target_compile_definitions(flutter-pi PRIVATE "BUILD_GSTREAMER_AUDIO_PLAYER_PLUGIN") + target_link_libraries(flutter-pi + ${LIBGSTREAMER_LDFLAGS} + ${LIBGSTREAMER_APP_LDFLAGS} + ${LIBGSTREAMER_AUDIO_LIBRARY_DIRS} + ) + target_include_directories(flutter-pi PRIVATE + ${LIBGSTREAMER_INCLUDE_DIRS} + ${LIBGSTREAMER_APP_INCLUDE_DIRS} + ${LIBGSTREAMER_AUDIO_INCLUDE_DIRS} + ) + target_compile_options(flutter-pi PRIVATE + ${LIBGSTREAMER_CFLAGS} + ${LIBGSTREAMER_APP_CFLAGS} + ${LIBGSTREAMER_AUDIO_CFLAGS} + ) + else() + message(NOTICE "Couldn't find gstreamer libraries. Gstreamer audio player plugin won't be build.") + endif() +endif() + # Needed so dart VM can actually resolve symbols in the same # executable. target_link_options(flutter-pi PRIVATE