From e9b9b91f2ca523d24ae5f03c3aecf99e6b803ea9 Mon Sep 17 00:00:00 2001 From: k-saikrishna Date: Tue, 17 Dec 2024 16:00:57 +0530 Subject: [PATCH 1/3] framework/media, apps/examples: sync from ecode Sync Media F/W & test applications code upto following commit https://github.ecodesamsung.com/TizenRT/Media/commit/e0811517ddefc8d9a6d1c28943c7ea259e6b8626 --- .../examples/SoundPlayer/soundplayer_main.cpp | 27 +- apps/examples/wakerec/wakerec.cxx | 27 +- build/configs/rtl8730e/audio/defconfig | 4 +- .../configs/rtl8730e/loadable_audio/defconfig | 4 +- framework/include/audio/SoundManager.h | 16 + framework/include/media/FocusManager.h | 37 +- framework/include/media/MediaPlayer.h | 17 +- framework/include/media/MediaRecorder.h | 9 + framework/src/audio/Make.defs | 4 +- .../{SoundManager.cpp => SoundManager.c} | 44 +- framework/src/media/FocusManager.cpp | 78 +++- framework/src/media/FocusManagerWorker.cpp | 49 +++ framework/src/media/FocusManagerWorker.h | 36 ++ framework/src/media/Make.defs | 2 +- framework/src/media/MediaPlayer.cpp | 10 +- framework/src/media/MediaPlayerImpl.cpp | 104 +++-- framework/src/media/MediaPlayerImpl.h | 3 +- framework/src/media/MediaRecorder.cpp | 5 + framework/src/media/MediaRecorderImpl.cpp | 31 ++ framework/src/media/MediaRecorderImpl.h | 1 + framework/src/media/audio/audio_manager.c | 407 +++++++++++++----- framework/src/media/audio/audio_manager.h | 76 +++- framework/src/media/media_init.c | 1 - framework/src/media/stream_info.c | 36 +- 24 files changed, 744 insertions(+), 284 deletions(-) rename framework/src/audio/{SoundManager.cpp => SoundManager.c} (50%) create mode 100644 framework/src/media/FocusManagerWorker.cpp create mode 100644 framework/src/media/FocusManagerWorker.h diff --git a/apps/examples/SoundPlayer/soundplayer_main.cpp b/apps/examples/SoundPlayer/soundplayer_main.cpp index 33862b5385..0f079d0654 100644 --- a/apps/examples/SoundPlayer/soundplayer_main.cpp +++ b/apps/examples/SoundPlayer/soundplayer_main.cpp @@ -55,9 +55,9 @@ class SoundPlayer : public MediaPlayerObserverInterface, { public: SoundPlayer() : mNumContents(0), mPlayIndex(-1), mHasFocus(false), mSampleRate(DEFAULT_SAMPLERATE_TYPE), \ - mPaused(false), mIsPlaying(false), mStopped(false), mTrackFinished(false), mVolume(DEFAULT_VOLUME) {}; + mPaused(false), mIsPlaying(false), mStopped(false), mTrackFinished(false), mVolume(DEFAULT_VOLUME), mLooping(false) {}; ~SoundPlayer() {}; - bool init(char *argv[]); + bool init(int argc, char *argv[]); player_result_t startPlayback(void); bool checkTrackFinished(void); void handleError(player_error_t error); @@ -85,6 +85,7 @@ class SoundPlayer : public MediaPlayerObserverInterface, bool mTrackFinished; unsigned int mSampleRate; uint8_t mVolume; + bool mLooping; void loadContents(const char *path); }; @@ -149,6 +150,7 @@ void SoundPlayer::handleError(player_error_t error) if (mHasFocus) { auto &focusManager = FocusManager::getFocusManager(); focusManager.abandonFocus(mFocusRequest); + mHasFocus = false; } mp.unprepare(); mp.destroy(); @@ -195,7 +197,7 @@ void SoundPlayer::onFocusChange(int focusChange) printf("it was paused, just start playback now\n"); res = mp.start(); if (res != PLAYER_OK) { - printf("start failed res : %d\n", res); + printf("player start failed res : %d\n", res); } } else { res = startPlayback(); @@ -219,7 +221,7 @@ void SoundPlayer::onFocusChange(int focusChange) } } -bool SoundPlayer::init(char *argv[]) +bool SoundPlayer::init(int argc, char *argv[]) { struct stat st; int ret; @@ -266,6 +268,10 @@ bool SoundPlayer::init(char *argv[]) mSampleRate = atoi(argv[3]); mTrackFinished = false; + if (argc > 5 && strcmp(argv[5], "1") == 0) { + mLooping = true; + } + auto &focusManager = FocusManager::getFocusManager(); printf("mp : %x request focus!!\n", &mp); focusManager.requestFocus(mFocusRequest); @@ -284,12 +290,18 @@ player_result_t SoundPlayer::startPlayback(void) source->setPcmFormat(DEFAULT_FORMAT_TYPE); res = mp.setDataSource(std::move(source)); if (res != PLAYER_OK) { + handleError((player_error_t)res); printf("set Data source failed. res : %d\n", res); return res; } + if (mLooping) { + mp.setLooping(true); + printf("Looping is set to true\n"); + } res = mp.prepare(); if (res != PLAYER_OK) { + handleError((player_error_t)res); printf("prepare failed res : %d\n", res); return res; } @@ -384,11 +396,13 @@ int soundplayer_main(int argc, char *argv[]) auto player = std::shared_ptr(new SoundPlayer()); printf("cur SoundPlayer : %x\n", &player); - if (argc != 5) { + if (argc != 6 && argc != 5) { printf("invalid input\n"); + printf("Usage : soundplayer [contents path] [volume] [sample rate] [stream policy] [looping]\n"); + printf("looping argument is optional\n"); return -1; } - if (!player->init(argv)) { + if (!player->init(argc, argv)) { return -1; } @@ -401,3 +415,4 @@ int soundplayer_main(int argc, char *argv[]) return 0; } } + diff --git a/apps/examples/wakerec/wakerec.cxx b/apps/examples/wakerec/wakerec.cxx index c4a30c39d7..5a4de79597 100644 --- a/apps/examples/wakerec/wakerec.cxx +++ b/apps/examples/wakerec/wakerec.cxx @@ -1,6 +1,6 @@ /**************************************************************************** * - * Copyright 2023 Samsung Electronics All Rights Reserved. + * Copyright 2024 Samsung Electronics All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,8 +39,7 @@ #include #include #include - -#define CONFIG_SUPPORT_GET_KD 0 +#include using namespace std; using namespace media; @@ -109,7 +108,7 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu printf("##################################\n"); printf("#### onRecordStopped ####\n"); printf("##################################\n"); - + if (errCode == RECORDER_ERROR_DEVICE_DEAD) { printf("#### Mic is unreachable ####\n"); mr.unprepare(); @@ -172,6 +171,13 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu void onPlaybackStopped(media::MediaPlayer &mediaPlayer) override { mPaused = false; + mp.unprepare(); + mp.destroy(); + printf("###################################\n"); + printf("#### Wait for wakeup triggered ####\n"); + printf("###################################\n"); + sd->startKeywordDetect(); + pm_resume(PM_IDLE_DOMAIN); } void onPlaybackError(media::MediaPlayer &mediaPlayer, media::player_error_t error) override @@ -243,7 +249,9 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu printf("it was paused, just start playback now\n"); res = mp.start(); if (res != PLAYER_OK) { - printf("start failed res : %d\n", res); + printf("player start failed res : %d\n", res); + auto &focusManager = FocusManager::getFocusManager(); + focusManager.abandonFocus(mFocusRequest); } } else { auto source = std::move(unique_ptr(new media::stream::FileInputDataSource(filePath))); @@ -253,11 +261,18 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu mp.setDataSource(std::move(source)); mp.prepare(); mp.setVolume(10); - mp.start(); + res = mp.start(); + if (res != PLAYER_OK) { + printf("player start failed res : %d\n", res); + auto &focusManager = FocusManager::getFocusManager(); + focusManager.abandonFocus(mFocusRequest); + } } } break; case FOCUS_LOSS: { mp.stop(); + auto &focusManager = FocusManager::getFocusManager(); + focusManager.abandonFocus(mFocusRequest); // call abandon focus when FOCUS_GAIN callback not required. } break; case FOCUS_LOSS_TRANSIENT: { mp.pause(); //it will be played again diff --git a/build/configs/rtl8730e/audio/defconfig b/build/configs/rtl8730e/audio/defconfig index 06ec369a1a..9b428c5e53 100644 --- a/build/configs/rtl8730e/audio/defconfig +++ b/build/configs/rtl8730e/audio/defconfig @@ -1030,6 +1030,8 @@ CONFIG_HTTPSOURCE_DOWNLOAD_BUFFER_THRESHOLD=2048 CONFIG_HTTPSOURCE_DOWNLOAD_STACKSIZE=8192 CONFIG_DATASOURCE_PREPARSE_BUFFER_SIZE=4096 CONFIG_CONTAINER_FORMAT=y +CONFIG_FOCUS_MANAGER_STACKSIZE=4096 +CONFIG_FOCUS_MANAGER_THREAD_PRIORITY=199 # # Containers for multi-media @@ -1063,7 +1065,7 @@ CONFIG_FILE_DATASOURCE_STREAM_BUFFER_SIZE=4096 CONFIG_FILE_DATASOURCE_STREAM_BUFFER_THRESHOLD=2048 CONFIG_BUFFER_DATASOURCE_STREAM_BUFFER_SIZE=4096 CONFIG_BUFFER_DATASOURCE_STREAM_BUFFER_THRESHOLD=1 -CONFIG_HANDLER_STREAM_BUFFER_SIZE=4096 +CONFIG_HANDLER_STREAM_BUFFER_SIZE=16384 CONFIG_HANDLER_STREAM_BUFFER_THRESHOLD=2048 CONFIG_AUDIO_CODEC=y CONFIG_AUDIO_CODEC_RINGBUFFER_SIZE=16384 diff --git a/build/configs/rtl8730e/loadable_audio/defconfig b/build/configs/rtl8730e/loadable_audio/defconfig index a3326291e9..3af9012766 100644 --- a/build/configs/rtl8730e/loadable_audio/defconfig +++ b/build/configs/rtl8730e/loadable_audio/defconfig @@ -1061,6 +1061,8 @@ CONFIG_HTTPSOURCE_DOWNLOAD_BUFFER_THRESHOLD=2048 CONFIG_HTTPSOURCE_DOWNLOAD_STACKSIZE=8192 CONFIG_DATASOURCE_PREPARSE_BUFFER_SIZE=4096 CONFIG_CONTAINER_FORMAT=y +CONFIG_FOCUS_MANAGER_STACKSIZE=4096 +CONFIG_FOCUS_MANAGER_THREAD_PRIORITY=199 # # Containers for multi-media @@ -1094,7 +1096,7 @@ CONFIG_FILE_DATASOURCE_STREAM_BUFFER_SIZE=4096 CONFIG_FILE_DATASOURCE_STREAM_BUFFER_THRESHOLD=2048 CONFIG_BUFFER_DATASOURCE_STREAM_BUFFER_SIZE=4096 CONFIG_BUFFER_DATASOURCE_STREAM_BUFFER_THRESHOLD=1 -CONFIG_HANDLER_STREAM_BUFFER_SIZE=4096 +CONFIG_HANDLER_STREAM_BUFFER_SIZE=16384 CONFIG_HANDLER_STREAM_BUFFER_THRESHOLD=2048 # diff --git a/framework/include/audio/SoundManager.h b/framework/include/audio/SoundManager.h index 037eee7955..b150995907 100644 --- a/framework/include/audio/SoundManager.h +++ b/framework/include/audio/SoundManager.h @@ -66,6 +66,22 @@ bool setMicMute(void); */ bool setMicUnmute(void); +/** + * @brief Sets mute state for the given stream. + * @param[in] stream_policy Policy of the stream. + * @param[in] mute The mute state to be set. true for mute, false for unmute. + * @return true if the operation was successful, false otherwise. + */ +bool setStreamMute(stream_policy_t stream_policy, bool mute); + +/** + * @brief Gets mute state for the given stream. + * @param[in] stream_policy Policy of the stream. + * @param[in] mute Pointer to store the mute state. true for mute, false for unmute. + * @return true if the operation was successful, false otherwise. + */ +bool getStreamMuteState(stream_policy_t stream_policy, bool *mute); + #if defined(__cplusplus) } #endif diff --git a/framework/include/media/FocusManager.h b/framework/include/media/FocusManager.h index bc6ff0ba29..3be6c10afa 100644 --- a/framework/include/media/FocusManager.h +++ b/framework/include/media/FocusManager.h @@ -38,9 +38,11 @@ namespace media { -static const int FOCUS_REQUEST_SUCCESS = 0; -static const int FOCUS_REQUEST_FAIL = -1; -static const int FOCUS_REQUEST_DELAY = -2; +static const int FOCUS_REQUEST_SUCCESS = 0; /* Request accepted, onFocusChange will be called with appropriate values */ +static const int FOCUS_REQUEST_GAINED = 1; /* Focus already gained. */ +static const int FOCUS_REQUEST_FAIL = -1; /* Requested operation failed */ +/*@ToDo: change FOCUS_REQUEST_DELAY value to positive number as it is not a failure case.*/ +static const int FOCUS_REQUEST_DELAY = -2; /* Requested operation delayed. onFocusChange will be called with appropriate values */ /** * @class @@ -59,27 +61,32 @@ class FocusManager */ static FocusManager &getFocusManager(); /** - * @brief Abandon Focus + * @brief Abandon focus by passing it's Focus Request variable as argument. This is asynchronous function call. Focus will be revoked and request wll be removed from queue. * @details @b #include * param[in] focusRequest FocusRequest to abandon - * @return return FOCUS_REQUEST_SUCCESS on Success, else return FOCUS_REQUEST_FAIL + * @return FOCUS_REQUEST_SUCCESS: successful request and there is no callback for abandon focus. + * FOCUS_REQUEST_FAIL: parameter is not valid. Request is ignored. * @since TizenRT v2.0 */ int abandonFocus(std::shared_ptr focusRequest); /** - * @brief Request Focus + * @brief Requests focus by passing it's Focus Request variable as argument. This is asynchronous function call. Focus gained / lost is shared in onFocusChange callback. An application must have gained focus before calling MediaPlayer API. MediaPlayer API without focus gain may return error. * @details @b #include - * param[in] focusRequest FocusRequest to request - * @return return FOCUS_REQUEST_SUCCESS on immediate GAIN and FOCUS_REQUEST_DELAY for GAIN later, else return FOCUS_REQUEST_FAIL + * param[in] focusRequest FocusRequest object corresponding to a media type + * @return FOCUS_REQUEST_GAINED: if requesting application already has gained focus. No callback will be called in this case. + * FOCUS_REQUEST_FAIL: parameter is not valid. Request is ignored. Callback function will not be called. + * FOCUS_REQUEST_SUCCESS: successful request and result will be shared via callback function. FOCUS_REQUEST_SUCCESS does not mean focus is gained and application must wait for callback function before proceeding further. * @since TizenRT v2.0 */ int requestFocus(std::shared_ptr focusRequest); /** - * @brief Request Transient Focus + * @brief Requests Transient focus by passing it's Focus Request variable as argument. This is asynchronous function call. Focus gained / lost is shared in onFocusChange callback. An application must have gained focus before calling MediaPlayer API. MediaPlayer API without focus gained may return error. * @details @b #include - * param[in] focusRequest FocusRequest to request - * @return return FOCUS_REQUEST_SUCCESS on immediate GAIN and FOCUS_REQUEST_DELAY for GAIN later, else return FOCUS_REQUEST_FAIL + * param[in] focusRequest FocusRequest object corresponding to a media type + * @return FOCUS_REQUEST_GAINED: if requesting application already has gained focus. No callback will be called in this case. + * FOCUS_REQUEST_FAIL: parameter is not valid. Request is ignored. Callback function will not be called. + * FOCUS_REQUEST_SUCCESS: successful request and result will be shared via callback function. FOCUS_REQUEST_SUCCESS does not mean focus is gained and application must wait for callback function before proceeding further. * @since TizenRT v2.0 */ int requestFocusTransient(std::shared_ptr focusRequest); @@ -87,7 +94,8 @@ class FocusManager /** * @brief Get current focussed stream info * @details @b #include - * @return return STREAM_FOCUS_STATE_ACQUIRED if stream has focus, else return STREAM_FOCUS_STATE_RELEASED + * @return STREAM_FOCUS_STATE_ACQUIRED: if stream has focus. + * STREAM_FOCUS_STATE_RELEASED: if stream does not have focus. */ stream_info_t getCurrentStreamInfo(void); @@ -108,9 +116,10 @@ class FocusManager std::shared_ptr mListener; }; - FocusManager() = default; + FocusManager(); virtual ~FocusManager() = default; - int insertFocusElement(std::shared_ptr focusRequest, bool isTransientRequest); + void insertFocusElement(std::shared_ptr focusRequest, bool isTransientRequest); + void removeFocusAndNotify(std::shared_ptr focusRequest); void removeFocusElement(std::shared_ptr focusRequest); std::list> mFocusList; std::mutex mFocusLock; diff --git a/framework/include/media/MediaPlayer.h b/framework/include/media/MediaPlayer.h index b007167c87..68d9dd1c64 100644 --- a/framework/include/media/MediaPlayer.h +++ b/framework/include/media/MediaPlayer.h @@ -134,6 +134,15 @@ class MediaPlayer */ player_result_t unprepare(); + /** + * @brief Reset allocated resources related to the player, after the API, player is in state PLAYER_STATE_IDLE. + * @details @b #include + * This function is a synchronous API + * @return The result of the reset operation + * @since TizenLite v5.0 + */ + player_result_t reset(); + /** * @brief Start playback. * @details @b #include @@ -252,14 +261,6 @@ class MediaPlayer private: std::shared_ptr mPMpImpl; uint64_t mId; - - /** - * @brief Get the current set volume of player stream type - * @details @b #include - * This function is a synchronous API - * @return The current set volume of player stream type - */ - player_result_t getStreamVolume(uint8_t *volume); }; } // namespace media #endif diff --git a/framework/include/media/MediaRecorder.h b/framework/include/media/MediaRecorder.h index f10c37a87b..6bab4856ad 100644 --- a/framework/include/media/MediaRecorder.h +++ b/framework/include/media/MediaRecorder.h @@ -121,6 +121,15 @@ class MediaRecorder * @since TizenRT v2.0 */ recorder_result_t unprepare(); + + /** + * @brief Reset allocated resources related to the recorder, after the API, recorder is in state RECORDER_STATE_IDLE. + * @details @b #include + * This function is a synchronous API + * @return The result of the reset operation + * @since TizenLite v5.0 + */ + recorder_result_t reset(); /** * @brief Start recording. diff --git a/framework/src/audio/Make.defs b/framework/src/audio/Make.defs index 2d7972ae99..2eec0e6176 100644 --- a/framework/src/audio/Make.defs +++ b/framework/src/audio/Make.defs @@ -16,8 +16,8 @@ # ########################################################################### ifeq ($(CONFIG_MEDIA), y) -CXXSRCS += SoundManager.cpp -CXXFLAGS += -I${TOPDIR}/../framework/src/media/audio +CSRCS += SoundManager.c +CFLAGS += -I${TOPDIR}/../framework/src/media/audio DEPPATH += --dep-path src/audio VPATH += :src/audio endif diff --git a/framework/src/audio/SoundManager.cpp b/framework/src/audio/SoundManager.c similarity index 50% rename from framework/src/audio/SoundManager.cpp rename to framework/src/audio/SoundManager.c index 90fa6de9f0..558e7e2c77 100644 --- a/framework/src/audio/SoundManager.cpp +++ b/framework/src/audio/SoundManager.c @@ -22,10 +22,10 @@ bool getVolume(uint8_t *volume, stream_info_t *stream_info) { - medvdbg("SoundManager : getVolume\n"); - audio_manager_result_t res = get_output_stream_volume(volume, stream_info); + medvdbg("SoundManager : getVolume. stream_policy: %d\n", stream_info->policy); + audio_manager_result_t res = get_output_stream_volume(volume, stream_info->policy); if (res != AUDIO_MANAGER_SUCCESS) { - meddbg("get_output_stream_volume() is failed, res = %d\n", res); + meddbg("get_output_stream_volume failed stream_policy : %d, ret : %d\n", stream_info->policy, res); return false; } return true; @@ -33,10 +33,10 @@ bool getVolume(uint8_t *volume, stream_info_t *stream_info) bool setVolume(uint8_t volume, stream_info_t *stream_info) { - medvdbg("SoundManager : setVolume. volume: %d\n", volume); - audio_manager_result_t res = set_output_audio_volume(volume, stream_info); + medvdbg("SoundManager : setVolume. volume: %d, stream_policy: %d\n", volume, stream_info->policy); + audio_manager_result_t res = set_output_audio_volume(volume, stream_info->policy); if (res != AUDIO_MANAGER_SUCCESS) { - meddbg("set_output_audio_volume failed volume : %d ret : %d\n", volume, res); + meddbg("set_output_audio_volume failed volume : %d, stream_policy: %d, ret : %d\n", volume, stream_info->policy, res); return false; } return true; @@ -47,7 +47,7 @@ bool setEqualizer(uint32_t preset) medvdbg("SoundManager : setEqulizer. preset: %d\n", preset); audio_manager_result_t res = set_output_audio_equalizer(preset); if (res != AUDIO_MANAGER_SUCCESS) { - meddbg("set_output_audio_equalizer failed preset : %d ret : %d\n", preset, res); + meddbg("set_output_audio_equalizer failed preset : %d, ret : %d\n", preset, res); return false; } return true; @@ -56,9 +56,9 @@ bool setEqualizer(uint32_t preset) bool setMicMute(void) { medvdbg("SoundManager : setMicMute\n"); - audio_manager_result_t res = set_mic_mute(); + audio_manager_result_t res = set_audio_stream_mute(STREAM_TYPE_VOICE_RECORD, true); if (res != AUDIO_MANAGER_SUCCESS) { - meddbg("set_mic_mute failed ret : %d\n", res); + meddbg("set_audio_stream_mute failed stream_policy : %d, mute : %d, ret : %d\n", STREAM_TYPE_VOICE_RECORD, true, res); return false; } return true; @@ -67,9 +67,31 @@ bool setMicMute(void) bool setMicUnmute(void) { medvdbg("SoundManager : setMicUnmute\n"); - audio_manager_result_t res = set_mic_unmute(); + audio_manager_result_t res = set_audio_stream_mute(STREAM_TYPE_VOICE_RECORD, false); if (res != AUDIO_MANAGER_SUCCESS) { - meddbg("set_mic_unmute failed ret : %d\n", res); + meddbg("set_audio_stream_mute failed stream_policy : %d, mute : %d, ret : %d\n", STREAM_TYPE_VOICE_RECORD, false, res); + return false; + } + return true; +} + +bool setStreamMute(stream_policy_t stream_policy, bool mute) +{ + medvdbg("SoundManager : setStreamMute. stream_policy: %d, mute: %d\n", stream_policy, mute); + audio_manager_result_t res = set_audio_stream_mute(stream_policy, mute); + if (res != AUDIO_MANAGER_SUCCESS) { + meddbg("set_audio_stream_mute failed stream_policy : %d, mute : %d, ret : %d\n", stream_policy, mute, res); + return false; + } + return true; +} + +bool getStreamMuteState(stream_policy_t stream_policy, bool *mute) +{ + medvdbg("SoundManager : getStreamMuteState. stream_policy: %d\n", stream_policy); + audio_manager_result_t res = get_audio_stream_mute_state(stream_policy, mute); + if (res != AUDIO_MANAGER_SUCCESS) { + meddbg("set_audio_stream_mute failed stream_policy : %d, ret : %d\n", stream_policy, res); return false; } return true; diff --git a/framework/src/media/FocusManager.cpp b/framework/src/media/FocusManager.cpp index 43b1a1624e..52ca26f435 100644 --- a/framework/src/media/FocusManager.cpp +++ b/framework/src/media/FocusManager.cpp @@ -18,6 +18,8 @@ #include #include +#include "FocusManagerWorker.h" + namespace media { FocusManager::FocusRequester::FocusRequester(std::shared_ptr stream_info, std::shared_ptr listener) @@ -51,19 +53,20 @@ void FocusManager::FocusRequester::notify(int focusChange) } } +FocusManager ::FocusManager() +{ + FocusManagerWorker &fmw = FocusManagerWorker::getWorker(); + fmw.startWorker(); +} + FocusManager &FocusManager::getFocusManager() { static FocusManager focusManager; return focusManager; } -int FocusManager::abandonFocus(std::shared_ptr focusRequest) +void FocusManager::removeFocusAndNotify(std::shared_ptr focusRequest) { - std::lock_guard lock(mFocusLock); - if (focusRequest == nullptr) { - return FOCUS_REQUEST_FAIL; - } - if ((!mFocusList.empty()) && (mFocusList.front()->hasSameId(focusRequest))) { /* Remove focus from list */ mFocusList.pop_front(); @@ -73,7 +76,25 @@ int FocusManager::abandonFocus(std::shared_ptr focusRequest) } else { removeFocusElement(focusRequest); } +} +int FocusManager::abandonFocus(std::shared_ptr focusRequest) +{ + std::lock_guard lock(mFocusLock); + if (focusRequest == nullptr) { + return FOCUS_REQUEST_FAIL; + } + FocusManagerWorker &fmw = FocusManagerWorker::getWorker(); + if (!fmw.isAlive()) { + meddbg("FocusManagerWorker is not alive\n"); + return FOCUS_REQUEST_FAIL; + } + fmw.enQueue(&FocusManager::removeFocusAndNotify, this, focusRequest); + /* + @ToDo + return value FOCUS_REQUEST_SUCCESS means, focusrequest item is removed from queue, however now it is scheduled for removal. + removeFocusAndNotify -> function is simple and will mostly succeed but we should not assume it + */ return FOCUS_REQUEST_SUCCESS; } @@ -83,8 +104,20 @@ int FocusManager::requestFocus(std::shared_ptr focusRequest) if (focusRequest == nullptr) { return FOCUS_REQUEST_FAIL; } - - return insertFocusElement(focusRequest, false); + /* If request already gained focus, just return gained */ + if (!mFocusList.empty() && mFocusList.front()->hasSameId(focusRequest)) { + return FOCUS_REQUEST_GAINED; + } + FocusManagerWorker &fmw = FocusManagerWorker::getWorker(); + if (!fmw.isAlive()) { + meddbg("FocusManagerWorker is not alive\n"); + return FOCUS_REQUEST_FAIL; + } + fmw.enQueue(&FocusManager::insertFocusElement, this, focusRequest,false); + /* + @ToDo: to be discussed whether to return FOCUS_REQUEST_SUCCESS or FOCUS_REQUEST_DELAY. + */ + return FOCUS_REQUEST_SUCCESS; } int FocusManager::requestFocusTransient(std::shared_ptr focusRequest) @@ -93,11 +126,23 @@ int FocusManager::requestFocusTransient(std::shared_ptr focusReque if (focusRequest == nullptr) { return FOCUS_REQUEST_FAIL; } - - return insertFocusElement(focusRequest, true); + /* If request already gained focus, just return gained */ + if (!mFocusList.empty() && mFocusList.front()->hasSameId(focusRequest)) { + return FOCUS_REQUEST_GAINED; + } + FocusManagerWorker &fmw = FocusManagerWorker::getWorker(); + if (!fmw.isAlive()) { + meddbg("FocusManagerWorker is not alive\n"); + return FOCUS_REQUEST_FAIL; + } + fmw.enQueue(&FocusManager::insertFocusElement, this, focusRequest,true); + /* + @ToDo: to be discussed whether to return FOCUS_REQUEST_SUCCESS or FOCUS_REQUEST_DELAY. + */ + return FOCUS_REQUEST_SUCCESS; } -int FocusManager::insertFocusElement(std::shared_ptr focusRequest, bool isTransientRequest) +void FocusManager::insertFocusElement(std::shared_ptr focusRequest, bool isTransientRequest) { medvdbg("insertFocusElement!!\n"); /* If list is empty, request always gain focus */ @@ -109,12 +154,7 @@ int FocusManager::insertFocusElement(std::shared_ptr focusRequest, } else { focusRequester->notify(FOCUS_GAIN); } - return FOCUS_REQUEST_SUCCESS; - } - - /* If request already gained focus, just return success */ - if (mFocusList.front()->hasSameId(focusRequest)) { - return FOCUS_REQUEST_SUCCESS; + return; } removeFocusElement(focusRequest); @@ -136,7 +176,7 @@ int FocusManager::insertFocusElement(std::shared_ptr focusRequest, } else { focusRequester->notify(FOCUS_GAIN); } - return FOCUS_REQUEST_SUCCESS; + return; } while (++iter != mFocusList.end()) { @@ -151,7 +191,7 @@ int FocusManager::insertFocusElement(std::shared_ptr focusRequest, mFocusList.push_back(focusRequester); } - return FOCUS_REQUEST_DELAY; + return ; } stream_info_t FocusManager::getCurrentStreamInfo(void) diff --git a/framework/src/media/FocusManagerWorker.cpp b/framework/src/media/FocusManagerWorker.cpp new file mode 100644 index 0000000000..83f804e951 --- /dev/null +++ b/framework/src/media/FocusManagerWorker.cpp @@ -0,0 +1,49 @@ +/* **************************************************************** + * + * Copyright 2024 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#include +#include + +#include "FocusManagerWorker.h" +#include "media/FocusManager.h" + +#ifndef CONFIG_FOCUS_MANAGER_STACKSIZE +#define CONFIG_FOCUS_MANAGER_STACKSIZE 4096 +#endif + +#ifndef CONFIG_FOCUS_MANAGER_THREAD_PRIORITY +#define CONFIG_FOCUS_MANAGER_THREAD_PRIORITY 199 +#endif + +using namespace std; + +namespace media { +FocusManagerWorker::FocusManagerWorker() +{ + mThreadName = "FocusManagerWorker"; + mStacksize = CONFIG_FOCUS_MANAGER_STACKSIZE; + mPriority = CONFIG_FOCUS_MANAGER_THREAD_PRIORITY; +} + +FocusManagerWorker& FocusManagerWorker::getWorker() +{ + static FocusManagerWorker worker; + return worker; +} + +} // namespace media diff --git a/framework/src/media/FocusManagerWorker.h b/framework/src/media/FocusManagerWorker.h new file mode 100644 index 0000000000..e96cea9ca3 --- /dev/null +++ b/framework/src/media/FocusManagerWorker.h @@ -0,0 +1,36 @@ +/* **************************************************************** + * + * Copyright 2024 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ + +#ifndef __FOCUS_MANAGERWORKER_H +#define __FOCUS_MANAGERWORKER_H + +#include +#include +#include "MediaWorker.h" + +namespace media { +class FocusManagerWorker : public MediaWorker +{ +public: + static FocusManagerWorker &getWorker(); +private: + FocusManagerWorker(); + +}; +} // namespace media +#endif diff --git a/framework/src/media/Make.defs b/framework/src/media/Make.defs index 67315a1f66..e2213fdfbd 100644 --- a/framework/src/media/Make.defs +++ b/framework/src/media/Make.defs @@ -29,7 +29,7 @@ CFLAGS += -D__TINYARA__ CXXSRCS += MediaQueue.cpp DataSource.cpp MediaWorker.cpp CXXSRCS += StreamBuffer.cpp StreamBufferReader.cpp StreamBufferWriter.cpp CXXSRCS += MediaUtils.cpp remix.cpp -CXXSRCS += FocusRequest.cpp FocusManager.cpp +CXXSRCS += FocusRequest.cpp FocusManager.cpp FocusManagerWorker.cpp CSRCS += rb.c rbs.c CSRCS += stream_info.c DEPPATH += --dep-path src/media/utils diff --git a/framework/src/media/MediaPlayer.cpp b/framework/src/media/MediaPlayer.cpp index 3fc1d3cc75..2d94d079ac 100644 --- a/framework/src/media/MediaPlayer.cpp +++ b/framework/src/media/MediaPlayer.cpp @@ -52,6 +52,11 @@ player_result_t MediaPlayer::unprepare() return mPMpImpl->unprepare(); } +player_result_t MediaPlayer::reset() +{ + return mPMpImpl->reset(); +} + player_result_t MediaPlayer::start() { return mPMpImpl->start(); @@ -72,11 +77,6 @@ player_result_t MediaPlayer::getVolume(uint8_t *vol) return mPMpImpl->getVolume(vol); } -player_result_t MediaPlayer::getStreamVolume(uint8_t *vol) -{ - return mPMpImpl->getStreamVolume(vol); -} - player_result_t MediaPlayer::getMaxVolume(uint8_t *vol) { return mPMpImpl->getMaxVolume(vol); diff --git a/framework/src/media/MediaPlayerImpl.cpp b/framework/src/media/MediaPlayerImpl.cpp index cf68c7915e..ec43c241b0 100644 --- a/framework/src/media/MediaPlayerImpl.cpp +++ b/framework/src/media/MediaPlayerImpl.cpp @@ -168,17 +168,17 @@ void MediaPlayerImpl::preparePlayer(player_result_t &ret) return notifySync(); } - auto source = mInputHandler.getDataSource(); - if (set_audio_stream_out(source->getChannels(), source->getSampleRate(), - source->getPcmFormat(), mStreamInfo->id) != AUDIO_MANAGER_SUCCESS) { - meddbg("MediaPlayer prepare fail : set_audio_stream_out fail\n"); + audio_manager_result_t res = set_stream_out_policy(mStreamInfo->policy); + if (res != AUDIO_MANAGER_SUCCESS) { + meddbg("MediaPlayer prepare fail : set_stream_out_policy fail. res: %d\n", res); ret = PLAYER_ERROR_INTERNAL_OPERATION_FAILED; return notifySync(); } - audio_manager_result_t res = set_stream_out_policy(mStreamInfo->policy); - if (res != AUDIO_MANAGER_SUCCESS) { - meddbg("MediaPlayer prepare fail : set_stream_out_policy fail. res: %d\n", res); + auto source = mInputHandler.getDataSource(); + if (set_audio_stream_out(source->getChannels(), source->getSampleRate(), + source->getPcmFormat(), mStreamInfo->id) != AUDIO_MANAGER_SUCCESS) { + meddbg("MediaPlayer prepare fail : set_audio_stream_out fail\n"); ret = PLAYER_ERROR_INTERNAL_OPERATION_FAILED; return notifySync(); } @@ -299,6 +299,29 @@ void MediaPlayerImpl::unpreparePlayer(player_result_t &ret) return notifySync(); } +player_result_t MediaPlayerImpl::reset() +{ + LOG_STATE_INFO(mCurState); + meddbg("MediaPlayer reset mPlayer : %x\n", &mPlayer); + + if (mCurState == PLAYER_STATE_READY || mCurState == PLAYER_STATE_PLAYING || mCurState == PLAYER_STATE_PAUSED) { + mInputHandler.close(); + if (reset_audio_stream_out(mStreamInfo->id) != AUDIO_MANAGER_SUCCESS) { + meddbg("MediaPlayer reset fail : reset_audio_stream_out fail\n"); + return PLAYER_ERROR_INTERNAL_OPERATION_FAILED; + } + + if (mBuffer) { + delete[] mBuffer; + mBuffer = nullptr; + } + mBufSize = 0; + } + + mCurState = PLAYER_STATE_IDLE; + return PLAYER_OK; +} + player_result_t MediaPlayerImpl::start() { player_result_t ret = PLAYER_OK; @@ -346,17 +369,24 @@ void MediaPlayerImpl::startPlayer() } } - audio_manager_result_t result = set_output_stream_volume(mStreamInfo.get()); - if (result != AUDIO_MANAGER_SUCCESS) { - meddbg("set_output_stream_volume failed ret : %d\n", result); - if (result == AUDIO_MANAGER_DEVICE_NOT_SUPPORT) { - notifyObserver(PLAYER_OBSERVER_COMMAND_START_ERROR, PLAYER_ERROR_DEVICE_NOT_SUPPORTED); - } else { - notifyObserver(PLAYER_OBSERVER_COMMAND_START_ERROR, PLAYER_ERROR_INTERNAL_OPERATION_FAILED); - } + audio_manager_result_t res; + player_error_t ret; + + res = set_output_stream_volume(mStreamInfo->policy); + if (res != AUDIO_MANAGER_SUCCESS) { + meddbg("MediaPlayer prepare fail : set_output_stream_volume fail. ret: %d\n", res); + ret = (res == AUDIO_MANAGER_DEVICE_NOT_SUPPORT) ? PLAYER_ERROR_DEVICE_NOT_SUPPORTED : PLAYER_ERROR_INTERNAL_OPERATION_FAILED; + notifyObserver(PLAYER_OBSERVER_COMMAND_START_ERROR, ret); + return; + } + + res = set_audio_stream_mute_from_json(mStreamInfo->policy); + if (res != AUDIO_MANAGER_SUCCESS) { + meddbg("MediaPlayer prepare fail : set_audio_stream_mute_from_json fail. policy: %d, ret: %d\n", mStreamInfo->policy, res); + ret = (res == AUDIO_MANAGER_DEVICE_NOT_SUPPORT) ? PLAYER_ERROR_DEVICE_NOT_SUPPORTED : PLAYER_ERROR_INTERNAL_OPERATION_FAILED; + notifyObserver(PLAYER_OBSERVER_COMMAND_START_ERROR, ret); return; } - medvdbg("MediaPlayer set output stream volume success\n"); mpw.setPlayer(shared_from_this()); mCurState = PLAYER_STATE_PLAYING; @@ -491,7 +521,7 @@ player_result_t MediaPlayerImpl::getVolume(uint8_t *vol) player_result_t ret = PLAYER_OK; std::unique_lock lock(mCmdMtx); - medvdbg("MediaPlayer getVolume\n"); + medvdbg("MediaPlayer getVolume mPlayer : %x\n", &mPlayer); if (vol == nullptr) { meddbg("The given argument is invalid.\n"); @@ -514,43 +544,7 @@ player_result_t MediaPlayerImpl::getVolume(uint8_t *vol) void MediaPlayerImpl::getPlayerVolume(uint8_t *vol, player_result_t &ret) { medvdbg("MediaPlayer Worker : getVolume\n"); - audio_manager_result_t res = get_output_stream_volume(vol, mStreamInfo.get()); - if (res != AUDIO_MANAGER_SUCCESS) { - meddbg("get_output_stream_volume() is failed, res = %d\n", res); - ret = PLAYER_ERROR_INTERNAL_OPERATION_FAILED; - } - - notifySync(); -} - -player_result_t MediaPlayerImpl::getStreamVolume(uint8_t *vol) -{ - player_result_t ret = PLAYER_OK; - - std::unique_lock lock(mCmdMtx); - medvdbg("MediaPlayer getStreamVolume mPlayer : %x\n", &mPlayer); - - if (vol == nullptr) { - meddbg("The given argument is invalid.\n"); - return PLAYER_ERROR_INVALID_PARAMETER; - } - - PlayerWorker &mpw = PlayerWorker::getWorker(); - - if (!mpw.isAlive()) { - meddbg("PlayerWorker is not alive\n"); - return PLAYER_ERROR_NOT_ALIVE; - } - - mpw.enQueue(&MediaPlayerImpl::getPlayerStreamVolume, shared_from_this(), vol, std::ref(ret)); - mSyncCv.wait(lock); - - return ret; -} - -void MediaPlayerImpl::getPlayerStreamVolume(uint8_t *vol, player_result_t &ret) -{ - audio_manager_result_t res = get_output_stream_volume(vol, mStreamInfo.get()); + audio_manager_result_t res = get_output_stream_volume(vol, mStreamInfo->policy); if (res != AUDIO_MANAGER_SUCCESS) { meddbg("get_output_stream_volume() is failed, res = %d\n", res); // ToDo: Lets think if some other error type is required or not. @@ -627,7 +621,7 @@ void MediaPlayerImpl::setPlayerVolume(uint8_t vol, player_result_t &ret) { medvdbg("MediaPlayer Worker : setVolume %d\n", vol); - audio_manager_result_t result = set_output_audio_volume(vol, mStreamInfo.get()); + audio_manager_result_t result = set_output_audio_volume(vol, mStreamInfo->policy); if (result != AUDIO_MANAGER_SUCCESS) { meddbg("set_output_audio_volume failed vol : %d ret : %d\n", vol, result); if (result == AUDIO_MANAGER_DEVICE_NOT_SUPPORT) { diff --git a/framework/src/media/MediaPlayerImpl.h b/framework/src/media/MediaPlayerImpl.h index 4423fd15be..3e89861c62 100644 --- a/framework/src/media/MediaPlayerImpl.h +++ b/framework/src/media/MediaPlayerImpl.h @@ -96,12 +96,12 @@ class MediaPlayerImpl : public std::enable_shared_from_this player_result_t prepare(); player_result_t prepareAsync(); player_result_t unprepare(); + player_result_t reset(); player_result_t start(); player_result_t pause(); player_result_t stop(); player_result_t getVolume(uint8_t *vol); - player_result_t getStreamVolume(uint8_t *vol); player_result_t getMaxVolume(uint8_t *vol); player_result_t setVolume(uint8_t vol); @@ -129,7 +129,6 @@ class MediaPlayerImpl : public std::enable_shared_from_this player_result_t stopPlayback(bool drain); void pausePlayer(); void getPlayerVolume(uint8_t *vol, player_result_t &ret); - void getPlayerStreamVolume(uint8_t *vol, player_result_t &ret); void getPlayerMaxVolume(uint8_t *vol, player_result_t &ret); void setPlayerVolume(uint8_t vol, player_result_t &ret); void setPlayerObserver(std::shared_ptr observer); diff --git a/framework/src/media/MediaRecorder.cpp b/framework/src/media/MediaRecorder.cpp index df562ec0b7..a2981f2b77 100644 --- a/framework/src/media/MediaRecorder.cpp +++ b/framework/src/media/MediaRecorder.cpp @@ -47,6 +47,11 @@ recorder_result_t MediaRecorder::unprepare() return mPMrImpl->unprepare(); } +recorder_result_t MediaRecorder::reset() +{ + return mPMrImpl->reset(); +} + recorder_result_t MediaRecorder::start() { return mPMrImpl->start(); diff --git a/framework/src/media/MediaRecorderImpl.cpp b/framework/src/media/MediaRecorderImpl.cpp index 61e796c301..8f4831014f 100644 --- a/framework/src/media/MediaRecorderImpl.cpp +++ b/framework/src/media/MediaRecorderImpl.cpp @@ -244,6 +244,36 @@ void MediaRecorderImpl::unprepareRecorder(recorder_result_t& ret) notifySync(); } +recorder_result_t MediaRecorderImpl::reset() +{ + LOG_STATE_INFO(mCurState); + meddbg("MediaRecorderImpl::reset()\n"); + + if (mCurState == RECORDER_STATE_READY || mCurState == RECORDER_STATE_RECORDING || mCurState == RECORDER_STATE_PAUSED) { + audio_manager_result_t result = reset_audio_stream_in(); + if (result != AUDIO_MANAGER_SUCCESS) { + meddbg("reset_audio_stream_in failed ret : %d\n", result); + return RECORDER_ERROR_INTERNAL_OPERATION_FAILED; + } + auto source = mOutputHandler.getDataSource(); + if (source->isPrepared()) { + mOutputHandler.close(); + } + if (mBuffer) { + delete[] mBuffer; + mBuffer = nullptr; + } + mBuffSize = 0; + mDuration = 0; + mFileSize = 0; + mTotalFrames = 0; + mCapturedFrames = 0; + } + + mCurState = RECORDER_STATE_IDLE; + return RECORDER_OK; +} + recorder_result_t MediaRecorderImpl::start() { std::lock_guard lock(mCmdMtx); @@ -320,6 +350,7 @@ void MediaRecorderImpl::stopRecorder(recorder_result_t ret) } return; } + meddbg("Total record size : %lu\n", get_user_input_frames_to_byte(mCapturedFrames)); mCurState = RECORDER_STATE_READY; RecorderWorker &mrw = RecorderWorker::getWorker(); diff --git a/framework/src/media/MediaRecorderImpl.h b/framework/src/media/MediaRecorderImpl.h index 8159b93a87..27b96f6b65 100644 --- a/framework/src/media/MediaRecorderImpl.h +++ b/framework/src/media/MediaRecorderImpl.h @@ -90,6 +90,7 @@ class MediaRecorderImpl : public enable_shared_from_this recorder_result_t destroy(); recorder_result_t prepare(); recorder_result_t unprepare(); + recorder_result_t reset(); recorder_result_t start(); recorder_result_t pause(); diff --git a/framework/src/media/audio/audio_manager.c b/framework/src/media/audio/audio_manager.c index 3963f1103e..686cec52ca 100644 --- a/framework/src/media/audio/audio_manager.c +++ b/framework/src/media/audio/audio_manager.c @@ -184,12 +184,12 @@ static const struct audio_samprate_map_entry_s g_audio_samprate_entry[] = { }; static const uint8_t g_audio_stream_volume_entry[6][16] = { - {0, 50, 55, 60, 65, 70, 75, 80, 82, 83, 85, 90, 92, 93, 95, 100}, //STREAM_TYPE_MEDIA - {0, 50, 55, 60, 65, 70, 75, 80, 82, 83, 85, 90, 92, 93, 95, 100}, //STREAM_TYPE_NOTIFY - {0, 50, 55, 60, 65, 70, 75, 80, 82, 83, 85, 90, 92, 93, 95, 100}, //STREAM_TYPE_BIXBY + {0, 54, 58, 65, 70, 73, 76, 79, 81, 84, 86, 88, 90, 92, 94, 97}, //STREAM_TYPE_MEDIA + {0, 66, 69, 72, 75, 78, 81, 84, 86, 88, 90, 92, 94, 96, 98, 100}, //STREAM_TYPE_NOTIFY + {0, 66, 69, 72, 75, 78, 81, 84, 86, 88, 90, 92, 94, 96, 98, 100}, //STREAM_TYPE_BIXBY {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0},//STREAM_TYPE_RECORDER, not available for now - {0, 50, 55, 60, 65, 70, 75, 80, 82, 83, 85, 90, 92, 93, 95, 100}, //STREAM_TYPE_VOIP - {0, 50, 55, 60, 65, 70, 75, 80, 82, 83, 85, 90, 92, 93, 95, 100}, //STREAM_TYPE_EMERGENCY + {0, 54, 64, 69, 74, 79, 83, 88, 88, 88, 88, 88, 88, 88, 88, 88}, //STREAM_TYPE_VOIP + {0, 66, 69, 72, 75, 78, 81, 84, 86, 88, 90, 92, 94, 96, 98, 100}, //STREAM_TYPE_EMERGENCY }; static cJSON *gJSON = NULL; @@ -209,6 +209,7 @@ static unsigned int resample_stream_out(audio_card_info_t *card, void *data, uns static audio_manager_result_t get_audio_volume(audio_io_direction_t direct); static audio_manager_result_t set_audio_volume(audio_io_direction_t direct, uint8_t volume); static audio_manager_result_t set_audio_equalizer(audio_io_direction_t direct, uint32_t preset); +static audio_manager_result_t set_audio_mute(audio_io_direction_t direct, stream_policy_t stream_policy, bool mute); static audio_manager_result_t create_volume_level_json(void); static audio_manager_result_t parse_volume_level_json(void); static audio_manager_result_t update_volume_level_json(void); @@ -688,6 +689,54 @@ static audio_manager_result_t set_audio_equalizer(audio_io_direction_t direct, u return ret; } +static audio_manager_result_t set_audio_mute(audio_io_direction_t direct, stream_policy_t stream_policy, bool mute) +{ + audio_manager_result_t ret; + struct audio_caps_desc_s caps_desc; + audio_card_info_t *card; + char card_path[AUDIO_DEVICE_FULL_PATH_LENGTH]; + + if (direct == INPUT) { + if (g_actual_audio_in_card_id < 0) { + meddbg("Found no active input audio card\n"); + return AUDIO_MANAGER_NO_AVAIL_CARD; + } + card = &g_audio_in_cards[g_actual_audio_in_card_id]; + } else { + if (g_actual_audio_out_card_id < 0) { + meddbg("Found no active output audio card\n"); + return AUDIO_MANAGER_NO_AVAIL_CARD; + } + card = &g_audio_out_cards[g_actual_audio_out_card_id]; + if (stream_policy != card->policy) { + meddbg("Policy mismatch, given_policy: %d, card_policy: %d. Mute state for given policy will be set when it will play\n", stream_policy, card->policy); + return AUDIO_MANAGER_SUCCESS; + } + } + + caps_desc.caps.ac_type = AUDIO_TYPE_FEATURE; + caps_desc.caps.ac_format.hw = AUDIO_FU_MUTE; + caps_desc.caps.ac_controls.b[0] = mute; + + get_card_path(card_path, card->card_id, card->device_id, direct); + + pthread_mutex_lock(&(card->card_mutex)); + + ret = control_audio_stream_device(card_path, AUDIOIOC_CONFIGURE, (unsigned long)&caps_desc); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Fail to mute audio, ret = %d errno : %d\n", ret, get_errno()); + if (get_errno() == EACCES) { + ret = AUDIO_MANAGER_DEVICE_NOT_SUPPORT; + } + pthread_mutex_unlock(&(card->card_mutex)); + return ret; + } + medvdbg("Audio Mute Success\n"); + + pthread_mutex_unlock(&(card->card_mutex)); + return ret; +} + audio_manager_result_t create_volume_level_json(void) { audio_manager_result_t ret = AUDIO_MANAGER_SUCCESS; @@ -702,9 +751,24 @@ audio_manager_result_t create_volume_level_json(void) close(fd); return AUDIO_MANAGER_OPERATION_FAIL; } + cJSON *muteStatusJsonObj = cJSON_CreateObject(); + if (!muteStatusJsonObj) { + meddbg("Failed to create json object for stream mute status\n"); + cJSON_Delete(json); + close(fd); + return AUDIO_MANAGER_OPERATION_FAIL; + } + const char *jsonKey; + for (uint8_t i = 0; i < MAX_STREAM_POLICY_NUM; i++) { + jsonKey = getJSONKey((stream_policy_t)i); + cJSON_AddNumberToObject(json, jsonKey, gDefaultVolumeLevel); + cJSON_AddBoolToObject(muteStatusJsonObj, jsonKey, false); + } + cJSON_AddItemToObject(json, "STREAM_TYPE_MUTE_STATUS", muteStatusJsonObj); char *jsonString = cJSON_Print(json); if (!jsonString) { meddbg("Failed to print volume level json object\n"); + cJSON_Delete(muteStatusJsonObj); cJSON_Delete(json); close(fd); return AUDIO_MANAGER_OPERATION_FAIL; @@ -717,8 +781,9 @@ audio_manager_result_t create_volume_level_json(void) medvdbg("To be written JSON string: %s\n, bytes written: %zd\n", jsonString, bytesWritten); } free(jsonString); - close(fd); + cJSON_Delete(muteStatusJsonObj); cJSON_Delete(json); + close(fd); return ret; } @@ -796,7 +861,7 @@ const char *getJSONKey(stream_policy_t stream_policy) case STREAM_TYPE_NOTIFY: return "STREAM_TYPE_NOTIFY"; case STREAM_TYPE_VOICE_RECORD: - return "STREAM_TYPE_VOICE_RECOGNITION"; + return "STREAM_TYPE_VOICE_RECORD"; case STREAM_TYPE_EMERGENCY: return "STREAM_TYPE_EMERGENCY"; case STREAM_TYPE_BIXBY: @@ -815,7 +880,11 @@ audio_manager_result_t audio_manager_init(void) audio_manager_result_t ret; static int am_initialized = 0; int found_card = 0; - + int retVal; + struct stat jsonFileStat; + const char *jsonKey; + cJSON *jsonValue; + if (am_initialized) { return AUDIO_MANAGER_SUCCESS; } @@ -838,8 +907,12 @@ audio_manager_result_t audio_manager_init(void) return AUDIO_MANAGER_NO_AVAIL_CARD; } - int retVal; - struct stat jsonFileStat; + ret = get_output_audio_volume(&gDefaultVolumeLevel); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to get output audio volume. ret: %d\n", ret); + return ret; + } + retVal = stat(VOLUME_JSON_PATH, &jsonFileStat); if (retVal != OK) { if (errno != ENOENT) { @@ -865,24 +938,34 @@ audio_manager_result_t audio_manager_init(void) return ret; } - ret = get_output_audio_volume(&gDefaultVolumeLevel); - if (ret != AUDIO_MANAGER_SUCCESS) { - meddbg("Failed to get output audio volume. ret: %d\n", ret); - return ret; + jsonValue = cJSON_GetObjectItem(gJSON, "STREAM_TYPE_MUTE_STATUS"); + if (!jsonValue) { + medvdbg("No STREAM_TYPE_MUTE_STATUS in the file, creating it."); + cJSON_Delete(gJSON); + ret = create_volume_level_json(); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to create volume level json. ret: %d", ret); + return ret; + } + ret = parse_volume_level_json(); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to parse volume level json. ret: %d\n", ret); + return ret; + } } - audio_card_info_t *card = &g_audio_out_cards[g_actual_audio_out_card_id]; for (uint16_t i = 0; i < MAX_STREAM_POLICY_NUM; i++) { - const char *policyKey = getJSONKey((stream_policy_t)i); - cJSON *policy = cJSON_GetObjectItem(gJSON, policyKey); - if (!policy) { - card->volume[i] = gDefaultVolumeLevel; - } else { - card->volume[i] = policy->valueint; - } + jsonKey = getJSONKey((stream_policy_t)i); + jsonValue = cJSON_GetObjectItem(gJSON, jsonKey); + card->volume[i] = jsonValue->valueint; } - return AUDIO_MANAGER_SUCCESS; + ret = set_audio_stream_mute_from_json(STREAM_TYPE_VOICE_RECORD); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to set mic mute status from json. ret: %d\n", ret); + } + + return ret; } audio_manager_result_t set_audio_stream_in(unsigned int channels, unsigned int sample_rate, int format) @@ -1640,19 +1723,21 @@ audio_manager_result_t get_output_audio_volume(uint8_t *volume) return ret; } -audio_manager_result_t get_output_stream_volume(uint8_t *volume, stream_info_t *stream_info) +audio_manager_result_t get_output_stream_volume(uint8_t *volume, stream_policy_t stream_policy) { + audio_card_info_t *card; + if (!volume) { meddbg("volume ptr is null\n"); return AUDIO_MANAGER_INVALID_PARAM; } - if (!stream_info) { - meddbg("stream info is null\n"); - return AUDIO_MANAGER_INVALID_PARAM; + if (g_actual_audio_out_card_id) { + meddbg("Found no active output audio card\n"); + return AUDIO_MANAGER_NO_AVAIL_CARD; } - audio_card_info_t *card = &g_audio_out_cards[g_actual_audio_out_card_id]; - *volume = card->volume[stream_info->policy]; + card = &g_audio_out_cards[g_actual_audio_out_card_id]; + *volume = card->volume[stream_policy]; return AUDIO_MANAGER_SUCCESS; } @@ -1662,79 +1747,75 @@ audio_manager_result_t set_input_audio_gain(uint8_t gain) return set_audio_volume(INPUT, gain); } -audio_manager_result_t set_output_audio_volume(uint8_t volume, stream_info_t *stream_info) +audio_manager_result_t set_output_audio_volume(uint8_t volume, stream_policy_t stream_policy) { - if (!stream_info) { - meddbg("stream info is null\n"); - return AUDIO_MANAGER_INVALID_PARAM; - } - audio_manager_result_t ret = set_audio_volume(OUTPUT, volume); - if (ret != AUDIO_MANAGER_SUCCESS) { - meddbg("set_audio_volume failed, ret: %d\n", ret); - return ret; + audio_manager_result_t ret = AUDIO_MANAGER_SUCCESS; + audio_card_info_t *card; + const char *jsonKey; + cJSON *jsonValue; + cJSON *streamMuteStatus; + + if (g_actual_audio_out_card_id) { + meddbg("Found no active output audio card\n"); + return AUDIO_MANAGER_NO_AVAIL_CARD; } - const char *policyKey = getJSONKey(stream_info->policy); - cJSON *policy = cJSON_GetObjectItem(gJSON, policyKey); - if (!policy) { - cJSON *policyVolume = cJSON_CreateNumber(volume); - cJSON_AddItemToObject(gJSON, policyKey, policyVolume); + jsonValue = cJSON_GetObjectItem(gJSON, "STREAM_TYPE_MUTE_STATUS"); + jsonKey = getJSONKey(stream_policy); + streamMuteStatus = cJSON_GetObjectItem(jsonValue, jsonKey); + if (streamMuteStatus->type == cJSON_True) { + cJSON_ReplaceItemInObject(jsonValue, jsonKey, cJSON_CreateBool(false)); + jsonValue = cJSON_GetObjectItem(gJSON, jsonKey); + if (jsonValue->valueint != volume) { + cJSON_ReplaceItemInObject(gJSON, jsonKey, cJSON_CreateNumber(volume)); + } + ret = update_volume_level_json(); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to update volume level json. ret: %d\n", ret); + return ret; + } } else { - if (policy->valueint != volume) { - cJSON *policyVolume = cJSON_CreateNumber(volume); - cJSON_ReplaceItemInObject(gJSON, policyKey, policyVolume); - } else { + jsonValue = cJSON_GetObjectItem(gJSON, jsonKey); + if (jsonValue->valueint == volume) { + return ret; + } + cJSON_ReplaceItemInObject(gJSON, jsonKey, cJSON_CreateNumber(volume)); + ret = update_volume_level_json(); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to update volume level json. ret: %d\n", ret); return ret; } } - ret = update_volume_level_json(); - if (ret != AUDIO_MANAGER_SUCCESS) { - meddbg("Failed to update volume level json. ret: %d\n", ret); + + card = &g_audio_out_cards[g_actual_audio_out_card_id]; + card->volume[stream_policy] = volume; + + if (stream_policy != card->policy) { + meddbg("Policy mismatch, given_policy: %d, card_policy: %d. Volume for given policy will be set when it will play\n", stream_policy, card->policy); return ret; } - audio_card_info_t *card = &g_audio_out_cards[g_actual_audio_out_card_id]; - card->volume[stream_info->policy] = volume; + ret = set_audio_volume(OUTPUT, volume); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("set_audio_volume failed, ret: %d\n", ret); + } return ret; } -audio_manager_result_t set_output_stream_volume(stream_info_t *stream_info) +audio_manager_result_t set_output_stream_volume(stream_policy_t stream_policy) { - if (!stream_info) { - meddbg("stream info is null\n"); - return AUDIO_MANAGER_INVALID_PARAM; - } - uint8_t volume; - const char *policyKey = getJSONKey(stream_info->policy); + const char *policyKey = getJSONKey(stream_policy); cJSON *policy = cJSON_GetObjectItem(gJSON, policyKey); - if (!policy) { - volume = gDefaultVolumeLevel; - } else { - volume = policy->valueint; - } + uint8_t volume = policy->valueint; audio_manager_result_t ret; ret = set_audio_volume(OUTPUT, volume); if (ret != AUDIO_MANAGER_SUCCESS) { meddbg("set_audio_volume failed, ret: %d\n", ret); - return ret; } - if (!policy) { - cJSON *policyVolume = cJSON_CreateNumber(volume); - cJSON_AddItemToObject(gJSON, policyKey, policyVolume); - ret = update_volume_level_json(); - if (ret != AUDIO_MANAGER_SUCCESS) { - meddbg("Failed to update volume level json. ret: %d\n", ret); - return ret; - } - - audio_card_info_t *card = &g_audio_out_cards[g_actual_audio_out_card_id]; - card->volume[stream_info->policy] = volume; - } - - return AUDIO_MANAGER_SUCCESS; + return ret; } //ToDo: In the future, driver will be changed to load the script that exists in each product app. @@ -2358,54 +2439,168 @@ audio_manager_result_t get_keyword_data(uint8_t *buffer) audio_manager_result_t set_mic_mute(void) { + audio_manager_result_t ret; + struct audio_caps_desc_s caps_desc; audio_card_info_t *card; - char path[AUDIO_DEVICE_FULL_PATH_LENGTH]; - int fd; + char card_path[AUDIO_DEVICE_FULL_PATH_LENGTH]; + cJSON *jsonValue; + cJSON *micMuteStatus; + if (g_actual_audio_in_card_id < 0) { - meddbg("card id is not valid\n"); - return AUDIO_MANAGER_INVALID_DEVICE; + meddbg("Found no active input audio card\n"); + return AUDIO_MANAGER_NO_AVAIL_CARD; } + card = &g_audio_in_cards[g_actual_audio_in_card_id]; - get_card_path(path, card->card_id, card->device_id, INPUT); - fd = open(path, O_RDONLY); - if (fd < 0) { - meddbg("card open fail.. path : %s errno : %d\n", path, errno); - return AUDIO_MANAGER_OPERATION_FAIL; + caps_desc.caps.ac_type = AUDIO_TYPE_FEATURE; + caps_desc.caps.ac_format.hw = AUDIO_FU_MUTE; + caps_desc.caps.ac_controls.b[0] = true; + + get_card_path(card_path, card->card_id, card->device_id, INPUT); + + pthread_mutex_lock(&(card->card_mutex)); + + ret = control_audio_stream_device(card_path, AUDIOIOC_CONFIGURE, (unsigned long)&caps_desc); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Fail to mute mic, ret = %d errno : %d\n", ret, get_errno()); + if (get_errno() == EACCES) { + ret = AUDIO_MANAGER_DEVICE_NOT_SUPPORT; + } + return ret; } - audio_manager_result_t ret = AUDIO_MANAGER_SUCCESS; - if (ioctl(fd, AUDIOIOC_MICMUTE, 0UL) < 0) { - meddbg("mic mute ioctl failed. errno : %d\n", errno); - ret = AUDIO_MANAGER_OPERATION_FAIL; + medvdbg("Mic Mute Success\n"); + + pthread_mutex_unlock(&(card->card_mutex)); + + jsonValue = cJSON_GetObjectItem(gJSON, "STREAM_TYPE_MUTE_STATUS"); + micMuteStatus = cJSON_GetObjectItem(jsonValue, "STREAM_TYPE_VOICE_RECORD"); + if (micMuteStatus->type == cJSON_False) { + cJSON_ReplaceItemInObject(jsonValue, "STREAM_TYPE_VOICE_RECORD", cJSON_CreateBool(true)); + ret = update_volume_level_json(); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to update volume level json. ret: %d\n", ret); + } } - close(fd); return ret; } audio_manager_result_t set_mic_unmute(void) { + audio_manager_result_t ret; + struct audio_caps_desc_s caps_desc; audio_card_info_t *card; - char path[AUDIO_DEVICE_FULL_PATH_LENGTH]; - int fd; + char card_path[AUDIO_DEVICE_FULL_PATH_LENGTH]; + cJSON *jsonValue; + cJSON *micMuteStatus; + if (g_actual_audio_in_card_id < 0) { - meddbg("card id is not valid\n"); - return AUDIO_MANAGER_INVALID_DEVICE; + meddbg("Found no active input audio card\n"); + return AUDIO_MANAGER_NO_AVAIL_CARD; } + card = &g_audio_in_cards[g_actual_audio_in_card_id]; - get_card_path(path, card->card_id, card->device_id, INPUT); - fd = open(path, O_RDONLY); - if (fd < 0) { - meddbg("card open fail.. path : %s errno : %d\n", path, errno); - return AUDIO_MANAGER_OPERATION_FAIL; + caps_desc.caps.ac_type = AUDIO_TYPE_FEATURE; + caps_desc.caps.ac_format.hw = AUDIO_FU_MUTE; + caps_desc.caps.ac_controls.b[0] = false; + + get_card_path(card_path, card->card_id, card->device_id, INPUT); + + pthread_mutex_lock(&(card->card_mutex)); + + ret = control_audio_stream_device(card_path, AUDIOIOC_CONFIGURE, (unsigned long)&caps_desc); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Fail to unmute mic, ret = %d errno : %d\n", ret, get_errno()); + if (get_errno() == EACCES) { + ret = AUDIO_MANAGER_DEVICE_NOT_SUPPORT; + } + return ret; + } + medvdbg("Mic Unmute Success\n"); + + pthread_mutex_unlock(&(card->card_mutex)); + + jsonValue = cJSON_GetObjectItem(gJSON, "STREAM_TYPE_MUTE_STATUS"); + micMuteStatus = cJSON_GetObjectItem(jsonValue, "STREAM_TYPE_VOICE_RECORD"); + if (micMuteStatus->type == cJSON_True) { + cJSON_ReplaceItemInObject(jsonValue, "STREAM_TYPE_VOICE_RECORD", cJSON_CreateBool(false)); + ret = update_volume_level_json(); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to update volume level json. ret: %d\n", ret); + } } + return ret; +} + +audio_manager_result_t set_audio_stream_mute(stream_policy_t stream_policy, bool mute) +{ audio_manager_result_t ret = AUDIO_MANAGER_SUCCESS; - if (ioctl(fd, AUDIOIOC_MICUNMUTE, 0UL) < 0) { - meddbg("mic unmute ioctl failed. errno : %d\n", errno); - ret = AUDIO_MANAGER_OPERATION_FAIL; + audio_io_direction_t direct; + cJSON *jsonValue; + const char *jsonKey; + cJSON *streamMuteStatus; + + if (stream_policy != STREAM_TYPE_VOICE_RECORD && stream_policy != STREAM_TYPE_NOTIFY) { + meddbg("Invalid stream policy for set stream mute. policy: %d\n", stream_policy); + return AUDIO_MANAGER_INVALID_PARAM; } - close(fd); + + jsonValue = cJSON_GetObjectItem(gJSON, "STREAM_TYPE_MUTE_STATUS"); + jsonKey = getJSONKey(stream_policy); + streamMuteStatus = cJSON_GetObjectItem(jsonValue, jsonKey); + if ((streamMuteStatus->type == cJSON_True) != mute) { + cJSON_ReplaceItemInObject(jsonValue, jsonKey, cJSON_CreateBool(mute)); + ret = update_volume_level_json(); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to update volume level json. ret: %d\n", ret); + return ret; + } + direct = (stream_policy == STREAM_TYPE_VOICE_RECORD) ? INPUT : OUTPUT; + ret = set_audio_mute(direct, stream_policy, mute); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to set audio to mute. direct: %d, stream_policy: %d, mute: %d, ret: %d\n", direct, stream_policy, mute, ret); + } + } + return ret; } +audio_manager_result_t set_audio_stream_mute_from_json(stream_policy_t stream_policy) +{ + audio_manager_result_t ret; + audio_io_direction_t direct; + cJSON *jsonValue; + const char *jsonKey; + cJSON *streamMuteStatus; + bool mute; + + jsonValue = cJSON_GetObjectItem(gJSON, "STREAM_TYPE_MUTE_STATUS"); + jsonKey = getJSONKey(stream_policy); + streamMuteStatus = cJSON_GetObjectItem(jsonValue, jsonKey); + mute = (streamMuteStatus->type == cJSON_True) ? true : false; + direct = (stream_policy == STREAM_TYPE_VOICE_RECORD) ? INPUT : OUTPUT; + + ret = set_audio_mute(direct, stream_policy, mute); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to set audio to mute. direct: %d, stream_policy: %d, mute: %d, ret: %d\n", direct, stream_policy, mute, ret); + } + + return ret; +} + +audio_manager_result_t get_audio_stream_mute_state(stream_policy_t stream_policy, bool *mute) +{ + cJSON *jsonValue; + const char *jsonKey; + cJSON *streamMuteStatus; + + jsonValue = cJSON_GetObjectItem(gJSON, "STREAM_TYPE_MUTE_STATUS"); + jsonKey = getJSONKey(stream_policy); + streamMuteStatus = cJSON_GetObjectItem(jsonValue, jsonKey); + *mute = (streamMuteStatus->type == cJSON_True) ? true : false; + + return AUDIO_MANAGER_SUCCESS; +} + #ifdef CONFIG_DEBUG_MEDIA_INFO void print_audio_card_info(audio_io_direction_t direct) { diff --git a/framework/src/media/audio/audio_manager.h b/framework/src/media/audio/audio_manager.h index 1ebdcbc5c6..e3fca10d8a 100644 --- a/framework/src/media/audio/audio_manager.h +++ b/framework/src/media/audio/audio_manager.h @@ -451,16 +451,16 @@ audio_manager_result_t get_output_audio_volume(uint8_t *volume); * Name: get_output_stream_volume * * Description: - * Get current volume level set for the given stream info. + * Get current volume level stored in active output audio card for the given stream policy. * * Input parameter: - * volume: the pointer to get the current volume value - * stream_info: pointer to structure containing stream information + * volume: the pointer to get the volume level + * stream_policy: policy of the stream * * Return Value: * On success, AUDIO_MANAGER_SUCCESS. Otherwise, a negative value. ****************************************************************************/ -audio_manager_result_t get_output_stream_volume(uint8_t *volume, stream_info_t *stream_info); +audio_manager_result_t get_output_stream_volume(uint8_t *volume, stream_policy_t stream_policy); /**************************************************************************** * Name: set_input_audio_gain @@ -480,31 +480,34 @@ audio_manager_result_t set_input_audio_gain(uint8_t gain); * Name: set_output_audio_volume * * Description: - * Adjust the volume level of the active output audio device. - * Also, updates volume level in the json corresponding to input stream info. + * Updates the volume level in json & in active output audio card volume array + * for the given stream policy type. If card policy matches with the given policy, + * it also adjusts the volume level of the active output audio device. Otherwise, + * adjust later when given policy stream is played. * * Input parameter: * volume: volume value to set, Min = 0, Max = get_max_audio_volume() - * stream_info: pointer to structure containing stream information + * stream_policy: policy of the stream * * Return Value: * On success, AUDIO_MANAGER_SUCCESS. Otherwise, a negative value. ****************************************************************************/ -audio_manager_result_t set_output_audio_volume(uint8_t volume, stream_info_t *stream_info); +audio_manager_result_t set_output_audio_volume(uint8_t volume, stream_policy_t stream_policy); /**************************************************************************** * Name: set_output_stream_volume * * Description: - * Adjust the volume level of the active output audio device based on the stream policy type. + * Adjust the volume level of the active output audio device based on the volume level + * stored in json for the given stream policy type. * * Input parameter: - * stream_info: pointer to structure containing stream information + * stream_policy: policy of the stream * * Return Value: * On success, AUDIO_MANAGER_SUCCESS. Otherwise, a negative value. ****************************************************************************/ -audio_manager_result_t set_output_stream_volume(stream_info_t *stream_info); +audio_manager_result_t set_output_stream_volume(stream_policy_t stream_policy); /**************************************************************************** * Name: set_output_audio_equalizer @@ -802,6 +805,57 @@ audio_manager_result_t set_mic_mute(void); ****************************************************************************/ audio_manager_result_t set_mic_unmute(void); +/**************************************************************************** + * Name: set_audio_stream_mute + * + * Description: + * Sets the mute state for given stream policy. Valid only for STREAM_TYPE_NOTIFY + * and STREAM_TYPE_VOICE_RECORD. For other stream policies, it will return error. + * First, it updates the mute state of given stream policy in json and then sets + * the mute state in active i/o audio device. + * In case of output stream, if card policy doesnot matches with the given stream + * policy, mute state will be set later in the active output audio device when given + * policy stream is played. + * + * Input parameter: + * stream_policy: policy of the stream + * mute: mute state to be set + * + * Return Value: + * On success, AUDIO_MANAGER_SUCCESS. Otherwise, a negative value. + ****************************************************************************/ +audio_manager_result_t set_audio_stream_mute(stream_policy_t stream_policy, bool mute); + +/**************************************************************************** + * Name: set_audio_stream_mute_from_json + * + * Description: + * It fetches the mute state of given stream policy from json and then sets it in + * active i/o audio device. + * + * Input parameter: + * stream_policy: policy of the stream + * + * Return Value: + * On success, AUDIO_MANAGER_SUCCESS. Otherwise, a negative value. + ****************************************************************************/ +audio_manager_result_t set_audio_stream_mute_from_json(stream_policy_t stream_policy); + +/**************************************************************************** + * Name: get_audio_stream_mute_state + * + * Description: + * It gets the mute state of given stream policy stored in json. + * + * Input parameter: + * stream_policy: policy of the stream + * mute: pointer to store the mute state of given stream policy + * + * Return Value: + * On success, AUDIO_MANAGER_SUCCESS. Otherwise, a negative value. + ****************************************************************************/ +audio_manager_result_t get_audio_stream_mute_state(stream_policy_t stream_policy, bool *mute); + #ifdef CONFIG_DEBUG_MEDIA_INFO /**************************************************************************** * Name: dump_audio_card_info diff --git a/framework/src/media/media_init.c b/framework/src/media/media_init.c index ab04171c4e..7b935bf142 100644 --- a/framework/src/media/media_init.c +++ b/framework/src/media/media_init.c @@ -22,7 +22,6 @@ int media_init(void) { - stream_info_init(); audio_manager_init(); return 0; } diff --git a/framework/src/media/stream_info.c b/framework/src/media/stream_info.c index 7d3ffcb836..1e860644e0 100644 --- a/framework/src/media/stream_info.c +++ b/framework/src/media/stream_info.c @@ -17,43 +17,9 @@ ****************************************************************************/ #include -#include -#include #include -#include #include -static pthread_mutex_t g_stream_info_mutex; -static uint64_t g_stream_info_id = 0; - -int stream_info_init(void) -{ - int ret; - static bool is_stream_info_init = false; - if (is_stream_info_init) { - return OK; - } - - ret = pthread_mutex_init(&g_stream_info_mutex, NULL); - if (ret != OK) { - return ret; - } - is_stream_info_init = true; - return ret; -} - -static uint64_t stream_info_id_generate(void) -{ - uint64_t id; - pthread_mutex_lock(&g_stream_info_mutex); - /** - * ToDo: Handle overflow condition of uint64_t type. - */ - id = ++g_stream_info_id; - pthread_mutex_unlock(&g_stream_info_mutex); - return id; -} - int stream_info_create(stream_policy_t stream_policy, stream_info_t **stream_info) { if (stream_info == NULL) { @@ -64,7 +30,7 @@ int stream_info_create(stream_policy_t stream_policy, stream_info_t **stream_inf if (*stream_info == NULL) { return -ENOMEM; } - (*stream_info)->id = stream_info_id_generate(); + (*stream_info)->id = (uint64_t)(*stream_info); (*stream_info)->policy = stream_policy; return OK; From a8da23439e32d00166975daf95d8cc2a85e8bd2b Mon Sep 17 00:00:00 2001 From: tjkwon Date: Fri, 6 Dec 2024 18:12:59 +0900 Subject: [PATCH 2/3] apps/examples/wakerec : Update wakerec to support record without KD --- apps/examples/wakerec/wakerec.cxx | 190 +++++++++++++++++------------- 1 file changed, 105 insertions(+), 85 deletions(-) diff --git a/apps/examples/wakerec/wakerec.cxx b/apps/examples/wakerec/wakerec.cxx index 5a4de79597..6e48beb75b 100644 --- a/apps/examples/wakerec/wakerec.cxx +++ b/apps/examples/wakerec/wakerec.cxx @@ -52,22 +52,66 @@ static const char *filePath = "/tmp/record.pcm"; uint8_t *gBuffer = NULL; uint32_t bufferSize = 0; -static bool isRecording = true; - -static void playRecordVoice(void); -static void startRecord(void); - class WakeRec : public media::voice::SpeechDetectorListenerInterface,public FocusChangeListener, public media::MediaRecorderObserverInterface, public media::MediaPlayerObserverInterface, public std::enable_shared_from_this { +public: + void initWakeRec(bool set) + { + mKDEnabled = set; + printf("open file path : %s\n", filePath); + fp = fopen(filePath, "wb"); + if (fp == NULL) { + printf("FILE OPEN FAILED\n"); + return; + } + } + + void startRecord(void) + { + media::recorder_result_t mret = mr.create(); + if (mret == media::RECORDER_OK) { + printf("#### [MR] create succeeded.\n"); + } else { + printf("#### [MR] create failed.\n"); + return; + } + + mret = mr.setDataSource(std::unique_ptr( + new media::stream::BufferOutputDataSource(1, 16000, media::AUDIO_FORMAT_TYPE_S16_LE))); + if (mret == media::RECORDER_OK) { + printf("#### [MR] setDataSource succeeded.\n"); + } else { + printf("#### [MR] setDataSource failed.\n"); + return; + } + + mret = mr.setObserver(shared_from_this()); + if (mret == media::RECORDER_OK) { + printf("#### [MR] setObserver succeeded.\n"); + } else { + printf("#### [MR] setObserver failed.\n"); + return; + } + + if (mr.setDuration(7) == RECORDER_ERROR_NONE && mr.prepare() == RECORDER_ERROR_NONE) { + printf("#### [MR] prepare succeeded.\n"); + } else { + printf("#### [MR] prepare failed.\n"); + return; + } + + mr.start(); + } + private: MediaPlayer mp; MediaRecorder mr; shared_ptr mFocusRequest; - FILE *fp; bool mPaused; - + bool mKDEnabled; + FILE *fp; void onRecordStarted(media::MediaRecorder &mediaRecorder) override { printf("##################################\n"); @@ -120,9 +164,6 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu void onRecordBufferDataReached(media::MediaRecorder &mediaRecorder, std::shared_ptr data, size_t size) override { - if (!isRecording) { - return; - } printf("###########################################\n"); printf("#### onRecordBufferDataReached ####\n"); printf("###########################################\n"); @@ -131,6 +172,8 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu if (fp != NULL) { int sz_written = fwrite(sdata, sizeof(short), size / 2, fp); printf("\n********Size written to file= %d *********\n", sz_written); + } else { + printf("fp is null!!\n"); } } @@ -156,16 +199,17 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu printf("##################################\n"); printf("#### Playback done!! ####\n"); printf("##################################\n"); - - printf("###################################\n"); - printf("#### Wait for wakeup triggered ####\n"); - printf("###################################\n"); - - sd->startKeywordDetect(); + if (mKDEnabled) { + printf("###################################\n"); + printf("#### Wait for wakeup triggered ####\n"); + printf("###################################\n"); + sd->startKeywordDetect(); + } /* Now that we finished playback, we can go to sleep */ sleep(3); //for test, add sleep. - - pm_resume(PM_IDLE_DOMAIN); + if (mKDEnabled) { + pm_resume(PM_IDLE_DOMAIN); + } } void onPlaybackStopped(media::MediaPlayer &mediaPlayer) override @@ -173,11 +217,13 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu mPaused = false; mp.unprepare(); mp.destroy(); - printf("###################################\n"); - printf("#### Wait for wakeup triggered ####\n"); - printf("###################################\n"); - sd->startKeywordDetect(); - pm_resume(PM_IDLE_DOMAIN); + if (mKDEnabled) { + printf("###################################\n"); + printf("#### Wait for wakeup triggered ####\n"); + printf("###################################\n"); + sd->startKeywordDetect(); + pm_resume(PM_IDLE_DOMAIN); + } } void onPlaybackError(media::MediaPlayer &mediaPlayer, media::player_error_t error) override @@ -212,12 +258,6 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu pm_suspend(PM_IDLE_DOMAIN); printf("Event SPEECH_DETECT_KD\n"); printf("#### [SD] keyword detected.\n"); - fp = fopen(filePath, "wb"); - if (fp == NULL) { - printf("FILE OPEN FAILED\n"); - return; - } - if (gBuffer) { if (sd->getKeywordData(gBuffer) == true) { /* consume buffer */ @@ -282,43 +322,6 @@ class WakeRec : public media::voice::SpeechDetectorListenerInterface,public Focu } } - void startRecord(void) - { - media::recorder_result_t mret = mr.create(); - if (mret == media::RECORDER_OK) { - printf("#### [MR] create succeeded.\n"); - } else { - printf("#### [MR] create failed.\n"); - return; - } - - mret = mr.setDataSource(std::unique_ptr( - new media::stream::BufferOutputDataSource(1, 16000, media::AUDIO_FORMAT_TYPE_S16_LE))); - if (mret == media::RECORDER_OK) { - printf("#### [MR] setDataSource succeeded.\n"); - } else { - printf("#### [MR] setDataSource failed.\n"); - return; - } - - mret = mr.setObserver(shared_from_this()); - if (mret == media::RECORDER_OK) { - printf("#### [MR] setObserver succeeded.\n"); - } else { - printf("#### [MR] setObserver failed.\n"); - return; - } - - if (mr.setDuration(7) == RECORDER_ERROR_NONE && mr.prepare() == RECORDER_ERROR_NONE) { - printf("#### [MR] prepare succeeded.\n"); - } else { - printf("#### [MR] prepare failed.\n"); - return; - } - - mr.start(); - } - void playRecordVoice(void) { mp.create(); @@ -342,34 +345,51 @@ extern "C" { int wakerec_main(int argc, char *argv[]) { printf("wakerec_main Entry\n"); - sd = media::voice::SpeechDetector::instance(); - if (!sd->initKeywordDetect(16000, 1)) { - printf("#### [SD] init failed.\n"); - return 0; + + if (argc > 3) { + printf("invalid input\n"); + printf("Usage : wakerec [mode]\n"); + printf("mode is optional 0 Disable wakeup\n"); + return -1; } + auto recorder = std::shared_ptr(new WakeRec()); + if (argc == 2 && atoi(argv[1]) == 0) { + printf("disable KD!!\n"); + recorder->initWakeRec(false); + recorder->startRecord(); + } else { + recorder->initWakeRec(true); + sd = media::voice::SpeechDetector::instance(); + if (!sd->initKeywordDetect(16000, 1)) { + printf("#### [SD] init failed.\n"); + return 0; + } - sd->addListener(std::make_shared()); + sd->addListener(recorder); - printf("###################################\n"); - printf("#### Wait for wakeup triggered ####\n"); - printf("###################################\n"); - - if (sd->getKeywordBufferSize(&bufferSize) == true) { - printf("KD buffer size %d\n", bufferSize); - gBuffer = new uint8_t[bufferSize]; - if (!gBuffer) { - printf("memory allocation failed\n"); + printf("###################################\n"); + printf("#### Wait for wakeup triggered ####\n"); + printf("###################################\n"); + + if (sd->getKeywordBufferSize(&bufferSize) == true) { + printf("KD buffer size %d\n", bufferSize); + gBuffer = new uint8_t[bufferSize]; + if (!gBuffer) { + printf("memory allocation failed\n"); + } } + sd->startKeywordDetect(); + /* similar to wake lock, we release wake lock as we started our thread */ + pm_resume(PM_IDLE_DOMAIN); } - sd->startKeywordDetect(); - /* similar to wake lock, we release wake lock as we started our thread */ - pm_resume(PM_IDLE_DOMAIN); while (1) { sleep(67); } - delete[] gBuffer; - gBuffer = NULL; + if (gBuffer) { + delete[] gBuffer; + gBuffer = NULL; + } return 0; } } From b16b6e9c87dff98229d2ef21596130acd35eb561 Mon Sep 17 00:00:00 2001 From: k-saikrishna Date: Thu, 2 Jan 2025 16:54:35 +0530 Subject: [PATCH 3/3] framework/media: resolve build_error --- framework/include/media/stream_info.h | 2 +- framework/src/media/stream_info.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/include/media/stream_info.h b/framework/include/media/stream_info.h index beace820ec..89635394fc 100644 --- a/framework/include/media/stream_info.h +++ b/framework/include/media/stream_info.h @@ -61,7 +61,7 @@ enum stream_policy_e { }; typedef enum stream_policy_e stream_policy_t; -typedef uint64_t stream_info_id_t; +typedef size_t stream_info_id_t; struct stream_info_s { stream_info_id_t id; diff --git a/framework/src/media/stream_info.c b/framework/src/media/stream_info.c index 1e860644e0..23931414f9 100644 --- a/framework/src/media/stream_info.c +++ b/framework/src/media/stream_info.c @@ -30,7 +30,7 @@ int stream_info_create(stream_policy_t stream_policy, stream_info_t **stream_inf if (*stream_info == NULL) { return -ENOMEM; } - (*stream_info)->id = (uint64_t)(*stream_info); + (*stream_info)->id = (size_t)(*stream_info); (*stream_info)->policy = stream_policy; return OK;