diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..2e423f9e1e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,75 @@ +{ + "files.associations": { + "__bit_reference": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__functional_base": "cpp", + "__locale": "cpp", + "__nullptr": "cpp", + "__split_buffer": "cpp", + "__string": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "algorithm": "cpp", + "array": "cpp", + "atomic": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "exception": "cpp", + "optional": "cpp", + "string_view": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "locale": "cpp", + "map": "cpp", + "memory": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "random": "cpp", + "ratio": "cpp", + "set": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "utility": "cpp", + "vector": "cpp", + "cstdarg": "cpp", + "*.tcc": "cpp", + "memory_resource": "cpp", + "cinttypes": "cpp", + "bit": "cpp", + "unordered_map": "cpp", + "ble.h": "c", + "deque": "cpp", + "fstream": "cpp", + "numeric": "cpp", + "queue": "cpp", + "sstream": "cpp", + "hash_map": "cpp", + "hash_set": "cpp", + "unordered_set": "cpp" + } +} \ No newline at end of file diff --git a/apps/examples/SoundPlayer/soundplayer_main.cpp b/apps/examples/SoundPlayer/soundplayer_main.cpp index 25dbe47e5f..faab1a6256 100644 --- a/apps/examples/SoundPlayer/soundplayer_main.cpp +++ b/apps/examples/SoundPlayer/soundplayer_main.cpp @@ -257,13 +257,14 @@ bool SoundPlayer::init(char *argv[]) printf("Current volume : %d new Volume : %d\n", cur_vol, volume); mp.setVolume(volume); stream_info_t *info; - stream_info_create(STREAM_TYPE_MEDIA, &info); + stream_info_create((stream_policy_t)(atoi(argv[4])), &info); auto deleter = [](stream_info_t *ptr) { stream_info_destroy(ptr); }; auto stream_info = std::shared_ptr(info, deleter); mFocusRequest = FocusRequest::Builder() .setStreamInfo(stream_info) .setFocusChangeListener(shared_from_this()) .build(); + mp.setStreamInfo(stream_info); mSampleRate = atoi(argv[3]); mTrackFinished = false; @@ -280,7 +281,6 @@ player_result_t SoundPlayer::startPlayback(void) player_result_t res = PLAYER_OK; string s = mList.at(mPlayIndex); printf("startPlayback... playIndex : %d path : %s\n", mPlayIndex, s.c_str()); - usleep(200000); auto source = std::move(unique_ptr(new FileInputDataSource((const string)s))); source->setSampleRate(mSampleRate); source->setChannels(DEFAULT_CHANNEL_NUM); @@ -343,11 +343,44 @@ bool SoundPlayer::checkTrackFinished(void) } extern "C" { +/* + This is guide to use MediaPlayer with focus request. + As MediaPlayer is updated and now without focus request, MediaPlayer can't use audio device!!! + + Steps to follow to play an audio data are as follows: + + 1) Application to create a listener to receive onFocusChange callback. Application needs to implement FocusChangeListener interface. + 2) Sample source code to create a FocusRequest object and requestFocus is as follows: + stream_info_t *info; + stream_info_create(STREAM_TYPE_BIXBY, &info); //refer to stream_policy_e for various stream types + auto deleter = [](stream_info_t *ptr) { stream_info_destroy(ptr); }; + auto stream_info = std::shared_ptr(info, deleter); + mFocusRequest = FocusRequest::Builder() + .setStreamInfo(stream_info) + .setFocusChangeListener(mFocusObserver) + .build(); + mp.setStreamInfo(stream_info); + auto &focusManager = FocusManager::getFocusManager(); + focusManager.requestFocus(mFocusRequest); +3) Application should handle onFocusChange for FOCUS_LOSS during playback. Application must pause/stop playaback when FOCUS_LOSS / FOCUS_LOSS_TRANSIENT recevied +4) When playback finsihes, application must call abandonFocus to release focus. +5) Mandatory condition, requestFocus must be done and onFocusChange with FOCUS_GAIN options received before calling mediaplayer.prepare +6) Sequence of MediaPlayer API calls are as follows: + mp.create(); + mp.setObserver(mMediaPlayerObserverInterface); + mp.setStreamInfo(stream_info); + mp.setDataSource(source); + mp.prepare(); + mp.start(); + mp.stop();/mp.pause(); + mp.unprepare(); + mp.destroy(); +*/ int soundplayer_main(int argc, char *argv[]) { auto player = std::shared_ptr(new SoundPlayer()); printf("cur SoundPlayer : %x\n", &player); - if (argc != 4) { + if (argc != 5) { printf("invalid input\n"); return -1; } diff --git a/framework/include/media/FocusManager.h b/framework/include/media/FocusManager.h index 59d3209d6f..bc6ff0ba29 100644 --- a/framework/include/media/FocusManager.h +++ b/framework/include/media/FocusManager.h @@ -40,6 +40,7 @@ namespace media { static const int FOCUS_REQUEST_SUCCESS = 0; static const int FOCUS_REQUEST_FAIL = -1; +static const int FOCUS_REQUEST_DELAY = -2; /** * @class @@ -69,17 +70,34 @@ class FocusManager * @brief Request Focus * @details @b #include * param[in] focusRequest FocusRequest to request - * @return return FOCUS_REQUEST_SUCCESS on Success, else return FOCUS_REQUEST_FAIL + * @return return FOCUS_REQUEST_SUCCESS on immediate GAIN and FOCUS_REQUEST_DELAY for GAIN later, else return FOCUS_REQUEST_FAIL * @since TizenRT v2.0 */ int requestFocus(std::shared_ptr focusRequest); + /** + * @brief Request Transient Focus + * @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 + * @since TizenRT v2.0 + */ + int requestFocusTransient(std::shared_ptr focusRequest); + + /** + * @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 + */ + stream_info_t getCurrentStreamInfo(void); + private: class FocusRequester { public: FocusRequester(std::shared_ptr stream_info, std::shared_ptr listener); bool hasSameId(std::shared_ptr focusRequest); + stream_info_t getStreamInfo(void); void notify(int focusChange); static bool compare(const FocusRequester a, const FocusRequester b); @@ -92,6 +110,7 @@ class FocusManager FocusManager() = default; virtual ~FocusManager() = default; + int insertFocusElement(std::shared_ptr focusRequest, bool isTransientRequest); 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 337047e7a1..b007167c87 100644 --- a/framework/include/media/MediaPlayer.h +++ b/framework/include/media/MediaPlayer.h @@ -43,7 +43,8 @@ namespace media { */ enum player_error_e : int { /** MediaPlayer Error case */ - PLAYER_ERROR_NOT_ALIVE = -9, + PLAYER_ERROR_NOT_ALIVE = -10, + PLAYER_ERROR_FOCUS_NOT_READY, PLAYER_ERROR_PLAYBACK_FINISHED, PLAYER_ERROR_INVALID_STATE, PLAYER_ERROR_INVALID_OPERATION, @@ -230,6 +231,15 @@ class MediaPlayer */ bool isPlaying(); + /** + * @brief set stream_info of MediaPlayer + * @details @b #include + * This function is a synchronous API + * param[in] stream_info shared_ptr of stream_info_t + * @return The result of the setStreamInfo operation + */ + player_result_t setStreamInfo(std::shared_ptr stream_info); + /** * @brief Set Playback to be looping or non-looping * @details @b #include @@ -238,9 +248,18 @@ class MediaPlayer * @since TizenRT v5.0 */ player_result_t setLooping(bool loop); + 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/OutputDataSource.h b/framework/include/media/OutputDataSource.h index 404f0b1229..03b889e4c9 100644 --- a/framework/include/media/OutputDataSource.h +++ b/framework/include/media/OutputDataSource.h @@ -29,6 +29,7 @@ #ifndef __MEDIA_OUTPUTDATASOURCE_H #define __MEDIA_OUTPUTDATASOURCE_H +#include #include #include #include diff --git a/framework/include/media/stream_info.h b/framework/include/media/stream_info.h index 43a6123b1c..beace820ec 100644 --- a/framework/include/media/stream_info.h +++ b/framework/include/media/stream_info.h @@ -52,11 +52,12 @@ typedef enum stream_focus_state_e stream_focus_state_t; * @brief Stream Policy, high value means higher priority */ enum stream_policy_e { - STREAM_TYPE_MEDIA = 0, - STREAM_TYPE_VOIP = 1, - STREAM_TYPE_NOTIFY = 2, - STREAM_TYPE_VOICE_RECOGNITION = 3, - STREAM_TYPE_EMERGENCY = 4 + STREAM_TYPE_MEDIA = 0, /* Default value, music play */ + STREAM_TYPE_NOTIFY = 1, /* For notification */ + STREAM_TYPE_BIXBY = 2, + STREAM_TYPE_VOICE_RECORD = 3, /* Record */ + STREAM_TYPE_VOIP = 4, /* Call */ + STREAM_TYPE_EMERGENCY = 5 }; typedef enum stream_policy_e stream_policy_t; diff --git a/framework/src/media/FocusManager.cpp b/framework/src/media/FocusManager.cpp index f5c78d6fab..43b1a1624e 100644 --- a/framework/src/media/FocusManager.cpp +++ b/framework/src/media/FocusManager.cpp @@ -17,7 +17,7 @@ ******************************************************************/ #include - +#include namespace media { FocusManager::FocusRequester::FocusRequester(std::shared_ptr stream_info, std::shared_ptr listener) @@ -30,9 +30,18 @@ bool FocusManager::FocusRequester::hasSameId(std::shared_ptr focus return mId == focusRequest->getStreamInfo()->id; } +stream_info_t FocusManager::FocusRequester::getStreamInfo(void) +{ + return {mId, mPolicy}; +} + bool FocusManager::FocusRequester::compare(const FocusManager::FocusRequester a, const FocusManager::FocusRequester b) { - return a.mPolicy >= b.mPolicy; + if (a.mPolicy <= STREAM_TYPE_BIXBY && b.mPolicy <= STREAM_TYPE_BIXBY) { + return true; + } else { + return a.mPolicy >= b.mPolicy; + } } void FocusManager::FocusRequester::notify(int focusChange) @@ -75,12 +84,31 @@ int FocusManager::requestFocus(std::shared_ptr focusRequest) return FOCUS_REQUEST_FAIL; } + return insertFocusElement(focusRequest, false); +} + +int FocusManager::requestFocusTransient(std::shared_ptr focusRequest) +{ + std::lock_guard lock(mFocusLock); + if (focusRequest == nullptr) { + return FOCUS_REQUEST_FAIL; + } + + return insertFocusElement(focusRequest, true); +} + +int FocusManager::insertFocusElement(std::shared_ptr focusRequest, bool isTransientRequest) +{ + medvdbg("insertFocusElement!!\n"); /* If list is empty, request always gain focus */ if (mFocusList.empty()) { auto focusRequester = std::make_shared(focusRequest->getStreamInfo(), focusRequest->getListener()); mFocusList.push_front(focusRequester); - focusRequester->notify(FOCUS_GAIN); - + if (isTransientRequest) { + focusRequester->notify(FOCUS_GAIN_TRANSIENT); + } else { + focusRequester->notify(FOCUS_GAIN); + } return FOCUS_REQUEST_SUCCESS; } @@ -96,13 +124,18 @@ int FocusManager::requestFocus(std::shared_ptr focusRequest) /* If the policy of request is the highest prio */ if (FocusRequester::compare(*focusRequester, *(*iter))) { - - mFocusList.front()->notify(FOCUS_LOSS); - /* TODO add usleep as a temp code. gain should not be shared until prev player stop properly */ - usleep(100000); + if (isTransientRequest) { + mFocusList.front()->notify(FOCUS_LOSS_TRANSIENT); + } else { + mFocusList.front()->notify(FOCUS_LOSS); + } mFocusList.push_front(focusRequester); - focusRequester->notify(FOCUS_GAIN); - usleep(100000); + + if (isTransientRequest) { + focusRequester->notify(FOCUS_GAIN_TRANSIENT); + } else { + focusRequester->notify(FOCUS_GAIN); + } return FOCUS_REQUEST_SUCCESS; } @@ -118,7 +151,20 @@ int FocusManager::requestFocus(std::shared_ptr focusRequest) mFocusList.push_back(focusRequester); } - return FOCUS_REQUEST_SUCCESS; + return FOCUS_REQUEST_DELAY; +} + +stream_info_t FocusManager::getCurrentStreamInfo(void) +{ + medvdbg("getCurrentStreamInfo!!\n"); + stream_info_t stream_info; + if (mFocusList.empty()) { + stream_info = {0, STREAM_TYPE_MEDIA}; + return stream_info; + } + auto iterator = mFocusList.begin(); + stream_info = (*iterator)->getStreamInfo(); + return stream_info; } void FocusManager::removeFocusElement(std::shared_ptr focusRequest) diff --git a/framework/src/media/Kconfig b/framework/src/media/Kconfig index a9d7d8d710..d7ab25e928 100644 --- a/framework/src/media/Kconfig +++ b/framework/src/media/Kconfig @@ -27,11 +27,23 @@ config MEDIA_PLAYER_STACKSIZE default 4096 ---help--- +config MEDIA_PLAYER_THREAD_PRIORITY + int "Priority of Player thread" + default 100 + ---help--- + Set the priority of player thread. + config MEDIA_PLAYER_OBSERVER_STACKSIZE int "Media Player Observer thread stack size" default 2048 ---help--- +config MEDIA_PLAYER_OBSERVER_THREAD_PRIORITY + int "Priority of Player Observer thread" + default 100 + ---help--- + Set the priority of player observer thread. + config INPUT_DATASOURCE_STACKSIZE int "InputDataSource thread stack size" default 4096 @@ -115,11 +127,19 @@ config MEDIA_RECORDER_STACKSIZE default 12288 ---help--- +config MEDIA_RECORDER_THREAD_PRIORITY + int "Media Recorder thread priority" + default 100 + config MEDIA_RECORDER_OBSERVER_STACKSIZE int "Media Recorder Observer thread stack size" default 2048 ---help--- +config MEDIA_RECORDER_OBSERVER_THREAD_PRIORITY + int "Media Recorder thread priority" + default 100 + config OUTPUT_DATASOURCE_STACKSIZE int "OutputDataSource thread stack size" default 4096 @@ -207,5 +227,9 @@ config HANDLER_STREAM_BUFFER_THRESHOLD int "Stream handler stream buffer threshold" default 2048 +config HANDLER_STREAM_THREAD_PRIORITY + int "Priority of Stream Handler thread" + default 100 + endif #MEDIA diff --git a/framework/src/media/MediaPlayer.cpp b/framework/src/media/MediaPlayer.cpp index 61d0444a6c..3fc1d3cc75 100644 --- a/framework/src/media/MediaPlayer.cpp +++ b/framework/src/media/MediaPlayer.cpp @@ -72,6 +72,11 @@ 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); @@ -102,6 +107,11 @@ bool MediaPlayer::isPlaying() return mPMpImpl->isPlaying(); } +player_result_t MediaPlayer::setStreamInfo(std::shared_ptr stream_info) +{ + return mPMpImpl->setStreamInfo(stream_info); +} + player_result_t MediaPlayer::setLooping(bool loop) { return mPMpImpl->setLooping(loop); @@ -111,3 +121,4 @@ MediaPlayer::~MediaPlayer() { } } // namespace media + diff --git a/framework/src/media/MediaPlayerImpl.cpp b/framework/src/media/MediaPlayerImpl.cpp index a21545d823..617e6b4f48 100644 --- a/framework/src/media/MediaPlayerImpl.cpp +++ b/framework/src/media/MediaPlayerImpl.cpp @@ -17,6 +17,7 @@ ******************************************************************/ #include +#include #include "PlayerWorker.h" #include "MediaPlayerImpl.h" @@ -36,6 +37,12 @@ MediaPlayerImpl::MediaPlayerImpl(MediaPlayer &player) : mPlayer(player) mBuffer = nullptr; mBufSize = 0; mPlaybackFinished = false; + stream_info_t *info; + int ret = stream_info_create(STREAM_TYPE_MEDIA, &info); + if (ret != OK) { + meddbg("stream_info_create failed ret : %d\n", ret); + } + mStreamInfo = std::shared_ptr(info, [](stream_info_t *ptr) { stream_info_destroy(ptr); }); } player_result_t MediaPlayerImpl::create() @@ -121,6 +128,13 @@ player_result_t MediaPlayerImpl::prepare() { player_result_t ret = PLAYER_OK; + stream_focus_state_t streamState = getStreamFocusState(); + if (streamState != STREAM_FOCUS_STATE_ACQUIRED) { + ret = PLAYER_ERROR_FOCUS_NOT_READY; + meddbg("MediaPlayer prepare failed. ret: %d, player: %x\n", ret, &mPlayer); + return ret; + } + std::unique_lock lock(mCmdMtx); medvdbg("MediaPlayer prepare mPlayer : %x\n", &mPlayer); @@ -155,7 +169,7 @@ void MediaPlayerImpl::preparePlayer(player_result_t &ret) auto source = mInputHandler.getDataSource(); if (set_audio_stream_out(source->getChannels(), source->getSampleRate(), - source->getPcmFormat()) != AUDIO_MANAGER_SUCCESS) { + 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(); @@ -187,6 +201,15 @@ void MediaPlayerImpl::preparePlayer(player_result_t &ret) player_result_t MediaPlayerImpl::prepareAsync() { + player_result_t ret = PLAYER_OK; + + stream_focus_state_t streamState = getStreamFocusState(); + if (streamState != STREAM_FOCUS_STATE_ACQUIRED) { + ret = PLAYER_ERROR_FOCUS_NOT_READY; + meddbg("MediaPlayer prepareAsync failed. ret: %d, player: %x\n", ret, &mPlayer); + return ret; + } + std::unique_lock lock(mCmdMtx); medvdbg("MediaPlayer prepareAsync\n"); @@ -251,7 +274,7 @@ void MediaPlayerImpl::unpreparePlayer(player_result_t &ret) return notifySync(); } - if (reset_audio_stream_out() != AUDIO_MANAGER_SUCCESS) { + if (reset_audio_stream_out(mStreamInfo->id) != AUDIO_MANAGER_SUCCESS) { meddbg("MediaPlayer unprepare fail : reset_audio_stream_out fail\n"); ret = PLAYER_ERROR_INTERNAL_OPERATION_FAILED; return notifySync(); @@ -270,6 +293,15 @@ void MediaPlayerImpl::unpreparePlayer(player_result_t &ret) player_result_t MediaPlayerImpl::start() { + player_result_t ret = PLAYER_OK; + + stream_focus_state_t streamState = getStreamFocusState(); + if (streamState != STREAM_FOCUS_STATE_ACQUIRED) { + ret = PLAYER_ERROR_FOCUS_NOT_READY; + meddbg("MediaPlayer start failed. ret: %d, player: %x\n", ret, &mPlayer); + return ret; + } + std::lock_guard lock(mCmdMtx); medvdbg("MediaPlayer start mPlayer : %x\n", &mPlayer); @@ -299,12 +331,25 @@ void MediaPlayerImpl::startPlayer() if (mCurState == PLAYER_STATE_PAUSED) { auto source = mInputHandler.getDataSource(); if (set_audio_stream_out(source->getChannels(), source->getSampleRate(), - source->getPcmFormat()) != AUDIO_MANAGER_SUCCESS) { + source->getPcmFormat(), mStreamInfo->id) != AUDIO_MANAGER_SUCCESS) { meddbg("MediaPlayer startPlayer fail : set_audio_stream_out fail\n"); notifyObserver(PLAYER_OBSERVER_COMMAND_START_ERROR, PLAYER_ERROR_INTERNAL_OPERATION_FAILED); return; } } + + 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); + } + return; + } + medvdbg("MediaPlayer set output stream volume success\n"); + mpw.setPlayer(shared_from_this()); mCurState = PLAYER_STATE_PLAYING; mPlaybackFinished = false; @@ -313,6 +358,15 @@ void MediaPlayerImpl::startPlayer() player_result_t MediaPlayerImpl::stop() { + player_result_t ret = PLAYER_OK; + + stream_focus_state_t streamState = getStreamFocusState(); + if (streamState != STREAM_FOCUS_STATE_ACQUIRED) { + ret = PLAYER_ERROR_FOCUS_NOT_READY; + meddbg("MediaPlayer stop failed!! Focus not acquired ret: %d, player: %x\n", ret, &mPlayer); + return ret; + } + std::lock_guard lock(mCmdMtx); medvdbg("MediaPlayer stop mPlayer : %x\n", &mPlayer); @@ -371,6 +425,15 @@ player_result_t MediaPlayerImpl::stopPlayback(bool drain) player_result_t MediaPlayerImpl::pause() { + player_result_t ret = PLAYER_OK; + + stream_focus_state_t streamState = getStreamFocusState(); + if (streamState != STREAM_FOCUS_STATE_ACQUIRED) { + ret = PLAYER_ERROR_FOCUS_NOT_READY; + meddbg("MediaPlayer pause failed. ret: %d, player: %x\n", ret, &mPlayer); + return ret; + } + std::lock_guard lock(mCmdMtx); medvdbg("MediaPlayer pause mPlayer : %x\n", &mPlayer); @@ -443,8 +506,46 @@ player_result_t MediaPlayerImpl::getVolume(uint8_t *vol) void MediaPlayerImpl::getPlayerVolume(uint8_t *vol, player_result_t &ret) { medvdbg("MediaPlayer Worker : getVolume\n"); - if (get_output_audio_volume(vol) != AUDIO_MANAGER_SUCCESS) { - meddbg("get_output_audio_volume() is failed, ret = %d\n", ret); + audio_manager_result_t res = get_output_audio_volume(vol); + if (res != AUDIO_MANAGER_SUCCESS) { + meddbg("get_output_audio_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()); + 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. ret = PLAYER_ERROR_INTERNAL_OPERATION_FAILED; } @@ -479,8 +580,9 @@ player_result_t MediaPlayerImpl::getMaxVolume(uint8_t *vol) void MediaPlayerImpl::getPlayerMaxVolume(uint8_t *vol, player_result_t &ret) { medvdbg("MediaPlayer Worker : getMaxVolume\n"); - if (get_max_audio_volume(vol) != AUDIO_MANAGER_SUCCESS) { - meddbg("get_max_audio_volume() is failed, ret = %d\n", ret); + audio_manager_result_t res = get_max_audio_volume(vol); + if (res != AUDIO_MANAGER_SUCCESS) { + meddbg("get_max_audio_volume() is failed, res = %d\n", res); ret = PLAYER_ERROR_INTERNAL_OPERATION_FAILED; } @@ -491,6 +593,13 @@ player_result_t MediaPlayerImpl::setVolume(uint8_t vol) { player_result_t ret = PLAYER_OK; + stream_focus_state_t streamState = getStreamFocusState(); + if (streamState != STREAM_FOCUS_STATE_ACQUIRED) { + ret = PLAYER_ERROR_FOCUS_NOT_READY; + meddbg("MediaPlayer setVolume failed. ret: %d, player: %x\n", ret, &mPlayer); + return ret; + } + std::unique_lock lock(mCmdMtx); medvdbg("MediaPlayer setVolume\n"); @@ -510,9 +619,9 @@ 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); + audio_manager_result_t result = set_output_audio_volume(vol, mStreamInfo.get()); if (result != AUDIO_MANAGER_SUCCESS) { - meddbg("set_input_audio_volume failed vol : %d ret : %d\n", vol, result); + meddbg("set_output_audio_volume failed vol : %d ret : %d\n", vol, result); if (result == AUDIO_MANAGER_DEVICE_NOT_SUPPORT) { ret = PLAYER_ERROR_DEVICE_NOT_SUPPORTED; } else { @@ -601,6 +710,51 @@ void MediaPlayerImpl::setPlayerObserver(std::shared_ptr stream_info) +{ + player_result_t ret = PLAYER_OK; + + std::unique_lock lock(mCmdMtx); + medvdbg("MediaPlayer setStreamInfo mPlayer : %x\n", &mPlayer); + + PlayerWorker &mpw = PlayerWorker::getWorker(); + if (!mpw.isAlive()) { + meddbg("PlayerWorker is not alive\n"); + return PLAYER_ERROR_NOT_ALIVE; + } + + mpw.enQueue(&MediaPlayerImpl::setPlayerStreamInfo, shared_from_this(), stream_info, std::ref(ret)); + mSyncCv.wait(lock); + + return ret; +} + +void MediaPlayerImpl::setPlayerStreamInfo(std::shared_ptr stream_info, player_result_t &ret) +{ + LOG_STATE_INFO(mCurState); + + if (mCurState != PLAYER_STATE_IDLE && mCurState != PLAYER_STATE_CONFIGURED) { + meddbg("%s Fail : invalid state mPlayer : %x\n", __func__, &mPlayer); + LOG_STATE_DEBUG(mCurState); + ret = PLAYER_ERROR_INVALID_STATE; + return notifySync(); + } + + mStreamInfo = stream_info; + notifySync(); +} + +stream_focus_state_t MediaPlayerImpl::getStreamFocusState(void) +{ + FocusManager &fm = FocusManager::getFocusManager(); + stream_info_t stream_info = fm.getCurrentStreamInfo(); + if (mStreamInfo->id == stream_info.id) { + return STREAM_FOCUS_STATE_ACQUIRED; + } else { + return STREAM_FOCUS_STATE_RELEASED; + } +} + bool MediaPlayerImpl::isPlaying() { bool ret = false; @@ -747,7 +901,7 @@ void MediaPlayerImpl::notifyAsync(player_event_t event) // Now setup audio manager and notify player observer the result. auto source = mInputHandler.getDataSource(); if (set_audio_stream_out(source->getChannels(), source->getSampleRate(), - source->getPcmFormat()) != AUDIO_MANAGER_SUCCESS) { + source->getPcmFormat(), mStreamInfo->id) != AUDIO_MANAGER_SUCCESS) { meddbg("MediaPlayer prepare fail : set_audio_stream_out fail\n"); return notifyObserver(PLAYER_OBSERVER_COMMAND_ASYNC_PREPARED, PLAYER_ERROR_INTERNAL_OPERATION_FAILED); } diff --git a/framework/src/media/MediaPlayerImpl.h b/framework/src/media/MediaPlayerImpl.h index 07faf24979..4423fd15be 100644 --- a/framework/src/media/MediaPlayerImpl.h +++ b/framework/src/media/MediaPlayerImpl.h @@ -101,11 +101,13 @@ class MediaPlayerImpl : public std::enable_shared_from_this 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); player_result_t setDataSource(std::unique_ptr); player_result_t setObserver(std::shared_ptr); + player_result_t setStreamInfo(std::shared_ptr stream_info); player_state_t getState(); bool isPlaying(); @@ -127,10 +129,13 @@ 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); void setPlayerDataSource(std::shared_ptr dataSource, player_result_t &ret); + void setPlayerStreamInfo(std::shared_ptr stream_info, player_result_t &ret); + stream_focus_state_t getStreamFocusState(void); void setPlayerLooping(bool loop, player_result_t &ret); private: diff --git a/framework/src/media/MediaRecorderImpl.cpp b/framework/src/media/MediaRecorderImpl.cpp index 313a6d2071..f632ce7d18 100644 --- a/framework/src/media/MediaRecorderImpl.cpp +++ b/framework/src/media/MediaRecorderImpl.cpp @@ -37,7 +37,8 @@ MediaRecorderImpl::MediaRecorderImpl(MediaRecorder &recorder) : mDuration(0), mFileSize(0), mTotalFrames(0), - mCapturedFrames(0) + mCapturedFrames(0), + mStreamInfo(nullptr) { medvdbg("MediaRecorderImpl::MediaRecorderImpl()\n"); } diff --git a/framework/src/media/MediaRecorderImpl.h b/framework/src/media/MediaRecorderImpl.h index a61f21d747..e458b09a89 100644 --- a/framework/src/media/MediaRecorderImpl.h +++ b/framework/src/media/MediaRecorderImpl.h @@ -33,6 +33,7 @@ #include "OutputHandler.h" #include "MediaQueue.h" #include "RecorderObserverWorker.h" +#include "media/stream_info.h" using namespace std; @@ -136,6 +137,7 @@ class MediaRecorderImpl : public enable_shared_from_this int mFileSize; uint32_t mTotalFrames; uint32_t mCapturedFrames; + std::shared_ptr mStreamInfo; }; } // namespace media diff --git a/framework/src/media/PlayerObserverWorker.cpp b/framework/src/media/PlayerObserverWorker.cpp index cc7cc3c17d..b8368862a0 100644 --- a/framework/src/media/PlayerObserverWorker.cpp +++ b/framework/src/media/PlayerObserverWorker.cpp @@ -24,12 +24,16 @@ #ifndef CONFIG_MEDIA_PLAYER_OBSERVER_STACKSIZE #define CONFIG_MEDIA_PLAYER_OBSERVER_STACKSIZE 2048 #endif +#ifndef CONFIG_MEDIA_PLAYER_OBSERVER_THREAD_PRIORITY +#define CONFIG_MEDIA_PLAYER_OBSERVER_THREAD_PRIORITY 199 +#endif namespace media { PlayerObserverWorker::PlayerObserverWorker() { mThreadName = "PlayerObserverWorker"; mStacksize = CONFIG_MEDIA_PLAYER_OBSERVER_STACKSIZE; + mPriority = CONFIG_MEDIA_PLAYER_OBSERVER_THREAD_PRIORITY; } PlayerObserverWorker::~PlayerObserverWorker() diff --git a/framework/src/media/PlayerWorker.cpp b/framework/src/media/PlayerWorker.cpp index f2bd7edeb7..69a39f5d38 100644 --- a/framework/src/media/PlayerWorker.cpp +++ b/framework/src/media/PlayerWorker.cpp @@ -26,6 +26,10 @@ #define CONFIG_MEDIA_PLAYER_STACKSIZE 4096 #endif +#ifndef CONFIG_MEDIA_PLAYER_THREAD_PRIORITY +#define CONFIG_MEDIA_PLAYER_THREAD_PRIORITY 199 +#endif + using namespace std; namespace media { @@ -33,6 +37,7 @@ PlayerWorker::PlayerWorker() : mCurPlayer(nullptr) { mThreadName = "PlayerWorker"; mStacksize = CONFIG_MEDIA_PLAYER_STACKSIZE; + mPriority = CONFIG_MEDIA_PLAYER_THREAD_PRIORITY; } PlayerWorker::~PlayerWorker() diff --git a/framework/src/media/RecorderObserverWorker.cpp b/framework/src/media/RecorderObserverWorker.cpp index 26dadd8f1a..0922aa847a 100644 --- a/framework/src/media/RecorderObserverWorker.cpp +++ b/framework/src/media/RecorderObserverWorker.cpp @@ -22,6 +22,9 @@ #ifndef CONFIG_MEDIA_RECORDER_OBSERVER_STACKSIZE #define CONFIG_MEDIA_RECORDER_OBSERVER_STACKSIZE 2048 #endif +#ifndef CONFIG_MEDIA_RECORDER_OBSERVER_THREAD_PRIORITY +#define CONFIG_MEDIA_RECORDER_OBSERVER_THREAD_PRIORITY 100 +#endif namespace media { @@ -29,6 +32,7 @@ RecorderObserverWorker::RecorderObserverWorker() { mThreadName = "RecorderObserverWorker"; mStacksize = CONFIG_MEDIA_RECORDER_OBSERVER_STACKSIZE; + mPriority = CONFIG_MEDIA_RECORDER_OBSERVER_THREAD_PRIORITY; } RecorderObserverWorker::~RecorderObserverWorker() { diff --git a/framework/src/media/RecorderWorker.cpp b/framework/src/media/RecorderWorker.cpp index cd75302f1e..d3b9af20bf 100644 --- a/framework/src/media/RecorderWorker.cpp +++ b/framework/src/media/RecorderWorker.cpp @@ -23,6 +23,9 @@ #ifndef CONFIG_MEDIA_RECORDER_STACKSIZE #define CONFIG_MEDIA_RECORDER_STACKSIZE 4096 #endif +#ifndef CONFIG_MEDIA_RECORDER_THREAD_PRIORITY +#define CONFIG_MEDIA_RECORDER_THREAD_PRIORITY 100 +#endif namespace media { @@ -31,6 +34,7 @@ RecorderWorker::RecorderWorker() medvdbg("RecorderWorker::RecorderWorker()\n"); mThreadName = "RecorderWorker"; mStacksize = CONFIG_MEDIA_RECORDER_STACKSIZE; + mPriority = CONFIG_MEDIA_RECORDER_THREAD_PRIORITY; } RecorderWorker::~RecorderWorker() { diff --git a/framework/src/media/StreamHandler.cpp b/framework/src/media/StreamHandler.cpp index 613697e952..fdb63c3ee0 100644 --- a/framework/src/media/StreamHandler.cpp +++ b/framework/src/media/StreamHandler.cpp @@ -20,6 +20,10 @@ #include +#ifndef CONFIG_HANDLER_STREAM_THREAD_PRIORITY +#define CONFIG_HANDLER_STREAM_THREAD_PRIORITY 199 +#endif + namespace media { namespace stream { @@ -106,9 +110,12 @@ void StreamHandler::createWorker() mStreamBuffer->reset(); mIsWorkerAlive = true; + struct sched_param sparam; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, mWorkerStackSize); + sparam.sched_priority = CONFIG_HANDLER_STREAM_THREAD_PRIORITY; + pthread_attr_setschedparam(&attr, &sparam); int ret = pthread_create(&mWorker, &attr, static_cast(StreamHandler::workerMain), this); if (ret != OK) { meddbg("Fail to create StreamHandler Worker thread, return value : %d\n", ret); diff --git a/framework/src/media/audio/audio_manager.c b/framework/src/media/audio/audio_manager.c index ba1ab67e72..833f99da82 100644 --- a/framework/src/media/audio/audio_manager.c +++ b/framework/src/media/audio/audio_manager.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "audio_manager.h" #include "resample/samplerate.h" @@ -97,6 +98,8 @@ #define INVALID_ID -1 +#define VOLUME_JSON_PATH "/mnt/volume_level.json" + /**************************************************************************** * Private Types ****************************************************************************/ @@ -138,12 +141,14 @@ struct audio_resample_s { uint8_t samprate_types; // sample rate types supported by card }; +// ToDo: Exapnd audio card structure to handle volume level struct audio_card_info_s { uint8_t card_id; //current card id uint8_t device_id; //current device id struct audio_device_config_s config[CONFIG_AUDIO_MAX_DEVICE_NUM]; struct pcm *pcm; stream_policy_t policy; + stream_info_id_t stream_id; struct audio_resample_s resample; pthread_mutex_t card_mutex; }; @@ -175,6 +180,9 @@ static const struct audio_samprate_map_entry_s g_audio_samprate_entry[] = { {AUDIO_SAMP_RATE_TYPE_96K, AUDIO_SAMP_RATE_96K} }; +static cJSON *gJSON = NULL; +static uint8_t gDefaultVolumeLevel = 0; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -188,6 +196,10 @@ static unsigned int resample_stream_in(audio_card_info_t *card, void *data, unsi static unsigned int resample_stream_out(audio_card_info_t *card, void *data, unsigned int frames); 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 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); +static const char *getJSONKey(stream_policy_t stream_policy); /**************************************************************************** * Private Functions @@ -584,6 +596,10 @@ static audio_manager_result_t set_audio_volume(audio_io_direction_t direct, uint } config = &card->config[card->device_id]; + if (volume == config->volume) { + medvdbg("Volume already set to %d\n", volume); + return AUDIO_MANAGER_SUCCESS; + } caps_desc.caps.ac_controls.hw[0] = volume * (config->max_volume / AUDIO_DEVICE_MAX_VOLUME); caps_desc.caps.ac_len = sizeof(struct audio_caps_s); caps_desc.caps.ac_type = AUDIO_TYPE_FEATURE; @@ -607,6 +623,122 @@ static audio_manager_result_t set_audio_volume(audio_io_direction_t direct, uint return ret; } +audio_manager_result_t create_volume_level_json(void) +{ + audio_manager_result_t ret = AUDIO_MANAGER_SUCCESS; + int fd = open(VOLUME_JSON_PATH, O_WRONLY | O_CREAT, 0777); + if (fd == -1) { + meddbg("Failed to open volume level json file. errno: %d\n", errno); + return AUDIO_MANAGER_OPERATION_FAIL; + } + cJSON *json = cJSON_CreateObject(); + if (!json) { + meddbg("Failed to create volume level json object\n"); + close(fd); + return AUDIO_MANAGER_OPERATION_FAIL; + } + char *jsonString = cJSON_Print(json); + if (!jsonString) { + meddbg("Failed to print volume level json object\n"); + cJSON_Delete(json); + close(fd); + return AUDIO_MANAGER_OPERATION_FAIL; + } + ssize_t bytesWritten = write(fd, jsonString, strlen(jsonString)); + if (bytesWritten == -1) { + meddbg("Failed to write volume level json file. errno: %d\n", errno); + ret = AUDIO_MANAGER_OPERATION_FAIL; + } else { + medvdbg("To be written JSON string: %s\n, bytes written: %zd\n", jsonString, bytesWritten); + } + free(jsonString); + close(fd); + cJSON_Delete(json); + return ret; +} + +audio_manager_result_t parse_volume_level_json(void) +{ + struct stat jsonFileStat; + if (stat(VOLUME_JSON_PATH, &jsonFileStat) != 0) { + meddbg("Failed to fetch volume level json file information. errno: %d\n", errno); + return AUDIO_MANAGER_OPERATION_FAIL; + } + char *buffer = (char *)malloc(jsonFileStat.st_size + 1); + if (!buffer) { + meddbg("Failed to allocate memory to hold volume level json file content\n"); + return AUDIO_MANAGER_OPERATION_FAIL; + } + int fd = open(VOLUME_JSON_PATH, O_RDONLY); + if (fd == -1) { + meddbg("Failed to open volume level json. errno: %d", errno); + free(buffer); + return AUDIO_MANAGER_OPERATION_FAIL; + } + ssize_t bytesRead = read(fd, buffer, jsonFileStat.st_size); + if (bytesRead == -1) { + meddbg("Failed to read from volume level json. errno: %d", errno); + close(fd); + free(buffer); + return AUDIO_MANAGER_OPERATION_FAIL; + } + medvdbg("Total bytes read from volume level json: %d\n", bytesRead); + gJSON = cJSON_Parse(buffer); + if (!gJSON) { + meddbg("Failed to parse volume level json file.\n"); + close(fd); + free(buffer); + return AUDIO_MANAGER_OPERATION_FAIL; + } + close(fd); + free(buffer); + return AUDIO_MANAGER_SUCCESS; +} + +audio_manager_result_t update_volume_level_json(void) +{ + int fd = open(VOLUME_JSON_PATH, O_WRONLY, 0777); + if (fd == -1) { + meddbg("Failed to open volume level json file. errno: %d\n", errno); + return AUDIO_MANAGER_OPERATION_FAIL; + } + char *jsonString = cJSON_Print(gJSON); + if (!jsonString) { + meddbg("Failed to print volume level json object\n"); + close(fd); + return AUDIO_MANAGER_OPERATION_FAIL; + } + ssize_t bytesWritten = write(fd, jsonString, strlen(jsonString)); + if (bytesWritten == -1) { + meddbg("Failed to write volume level json file. errno: %d\n", errno); + } else { + medvdbg("To be written JSON string: %s\n, bytes written: %zd\n", jsonString, bytesWritten); + } + free(jsonString); + close(fd); + return AUDIO_MANAGER_SUCCESS; +} + +const char *getJSONKey(stream_policy_t stream_policy) +{ + switch (stream_policy) { + case STREAM_TYPE_MEDIA: + return "STREAM_TYPE_MEDIA"; + case STREAM_TYPE_VOIP: + return "STREAM_TYPE_VOIP"; + case STREAM_TYPE_NOTIFY: + return "STREAM_TYPE_NOTIFY"; + case STREAM_TYPE_VOICE_RECORD: + return "STREAM_TYPE_VOICE_RECOGNITION"; + case STREAM_TYPE_EMERGENCY: + return "STREAM_TYPE_EMERGENCY"; + case STREAM_TYPE_BIXBY: + return "STREAM_TYPE_BIXBY"; + default: + return "STREAM_TYPE_NA"; + } +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -639,6 +771,39 @@ audio_manager_result_t audio_manager_init(void) return AUDIO_MANAGER_NO_AVAIL_CARD; } + int retVal; + struct stat jsonFileStat; + retVal = stat(VOLUME_JSON_PATH, &jsonFileStat); + if (retVal != OK) { + if (errno != ENOENT) { + meddbg("Failed to fetch json file information. errno: %d\n", errno); + return AUDIO_MANAGER_OPERATION_FAIL; + } + ret = create_volume_level_json(); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to create volume level json. ret: %d", ret); + return ret; + } + } else if (jsonFileStat.st_size == 0) { + 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; + } + + ret = get_output_audio_volume(&gDefaultVolumeLevel); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to get output audio volume. ret: %d\n", ret); + return ret; + } + return AUDIO_MANAGER_SUCCESS; } @@ -739,7 +904,7 @@ audio_manager_result_t set_audio_stream_in(unsigned int channels, unsigned int s return ret; } -audio_manager_result_t set_audio_stream_out(unsigned int channels, unsigned int sample_rate, int format) +audio_manager_result_t set_audio_stream_out(unsigned int channels, unsigned int sample_rate, int format, stream_info_id_t stream_id) { audio_card_info_t *card; audio_config_t *card_config; @@ -764,9 +929,14 @@ audio_manager_result_t set_audio_stream_out(unsigned int channels, unsigned int card = &g_audio_out_cards[g_actual_audio_out_card_id]; card_config = &card->config[card->device_id]; medvdbg("[%s] state : %d\n", __func__, card_config->status); + if (card->stream_id != stream_id) { + if (card_config->status != AUDIO_CARD_IDLE) { + reset_audio_stream_out(card->stream_id); + } + } if (card_config->status == AUDIO_CARD_PAUSE) { medvdbg("reset previous preparing\n"); - reset_audio_stream_out(); + reset_audio_stream_out(card->stream_id); } pthread_mutex_lock(&(card->card_mutex)); @@ -837,6 +1007,7 @@ audio_manager_result_t set_audio_stream_out(unsigned int channels, unsigned int inputput_card = &g_audio_in_cards[g_actual_audio_in_card_id]; start_stream_in_device_process_type(inputput_card->card_id, inputput_card->device_id, AUDIO_DEVICE_SPEECH_DETECT_AEC); + card->stream_id = stream_id; pthread_mutex_unlock(&(card->card_mutex)); return ret; @@ -1156,7 +1327,7 @@ audio_manager_result_t reset_audio_stream_in(void) return ret; } -audio_manager_result_t reset_audio_stream_out(void) +audio_manager_result_t reset_audio_stream_out(stream_info_id_t stream_id) { audio_card_info_t *card; audio_manager_result_t ret = AUDIO_MANAGER_SUCCESS; @@ -1167,6 +1338,10 @@ audio_manager_result_t reset_audio_stream_out(void) } card = &g_audio_out_cards[g_actual_audio_out_card_id]; + if (stream_id != card->stream_id) { + medvdbg("audio manager already got reset for stream_id = %d, currently being used by stream_id = %d\n", stream_id, card->stream_id); + return AUDIO_MANAGER_SUCCESS; + } pthread_mutex_lock(&(g_audio_out_cards[g_actual_audio_out_card_id].card_mutex)); medvdbg("[%s] state : %d\n", __func__, card->config[card->device_id].status); @@ -1384,13 +1559,74 @@ 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) +{ + 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; + } + const char *policyKey = getJSONKey(stream_info->policy); + cJSON *policy = cJSON_GetObjectItem(gJSON, policyKey); + if (!policy) { + *volume = gDefaultVolumeLevel; + } else { + *volume = policy->valueint; + } + return AUDIO_MANAGER_SUCCESS; +} + 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) +audio_manager_result_t set_output_audio_volume(uint8_t volume, stream_info_t *stream_info) +{ + if (!stream_info) { + meddbg("stream info is null\n"); + return AUDIO_MANAGER_INVALID_PARAM; + } + audio_manager_result_t ret; + 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); + } else { + if (policy->valueint != volume) { + cJSON *policyVolume = cJSON_CreateNumber(volume); + cJSON_ReplaceItemInObject(gJSON, policyKey, policyVolume); + } + } + ret = update_volume_level_json(); + if (ret != AUDIO_MANAGER_SUCCESS) { + meddbg("Failed to parse volume level json. ret: %d\n", ret); + return ret; + } + return set_audio_volume(OUTPUT, volume); +} + +audio_manager_result_t set_output_stream_volume(stream_info_t *stream_info) { + if (!stream_info) { + meddbg("stream info is null\n"); + return AUDIO_MANAGER_INVALID_PARAM; + } + uint8_t volume; + const char *policyKey = getJSONKey(stream_info->policy); + cJSON *policy = cJSON_GetObjectItem(gJSON, policyKey); + if (!policy) { + volume = gDefaultVolumeLevel; + cJSON *policyVolume = cJSON_CreateNumber(volume); + cJSON_AddItemToObject(gJSON, policyKey, policyVolume); + update_volume_level_json(); + } else { + volume = policy->valueint; + } return set_audio_volume(OUTPUT, volume); } diff --git a/framework/src/media/audio/audio_manager.h b/framework/src/media/audio/audio_manager.h index 9b5b5067fe..e151240c67 100644 --- a/framework/src/media/audio/audio_manager.h +++ b/framework/src/media/audio/audio_manager.h @@ -149,11 +149,12 @@ audio_manager_result_t set_audio_stream_in(unsigned int channels, unsigned int s * channels: number of channels * sample_rate: sample rate with which the stream is operated * format: audio file format to be streamed out + * stream_id: stream info id to be used for stream out * * Return Value: * On success, AUDIO_MANAGER_SUCCESS. Otherwise, a negative value. ****************************************************************************/ -audio_manager_result_t set_audio_stream_out(unsigned int channels, unsigned int sample_rate, int format); +audio_manager_result_t set_audio_stream_out(unsigned int channels, unsigned int sample_rate, int format, stream_info_id_t stream_id); /**************************************************************************** * Name: start_audio_stream_in @@ -270,7 +271,7 @@ audio_manager_result_t reset_audio_stream_in(void); * Return Value: * On success, AUDIO_MANAGER_SUCCESS. Otherwise, a negative value. ****************************************************************************/ -audio_manager_result_t reset_audio_stream_out(void); +audio_manager_result_t reset_audio_stream_out(stream_info_id_t stream_id); /**************************************************************************** * Name: get_input_frame_count @@ -445,6 +446,21 @@ audio_manager_result_t get_input_audio_gain(uint8_t *gain); ****************************************************************************/ 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. + * + * Input parameter: + * volume: the pointer to get the current volume value + * stream_info: pointer to structure containing stream information + * + * 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); + /**************************************************************************** * Name: set_input_audio_gain * @@ -464,14 +480,30 @@ audio_manager_result_t set_input_audio_gain(uint8_t gain); * * Description: * Adjust the volume level of the active output audio device. + * Also, updates volume level in the json corresponding to input stream info. * * Input parameter: * volume: volume value to set, Min = 0, Max = get_max_audio_volume() + * stream_info: pointer to structure containing stream information + * + * 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); + +/**************************************************************************** + * Name: set_output_stream_volume + * + * Description: + * Adjust the volume level of the active output audio device based on the stream policy type. + * + * Input parameter: + * stream_info: pointer to structure containing stream information * * Return Value: * On success, AUDIO_MANAGER_SUCCESS. Otherwise, a negative value. ****************************************************************************/ -audio_manager_result_t set_output_audio_volume(uint8_t volume); +audio_manager_result_t set_output_stream_volume(stream_info_t *stream_info); /**************************************************************************** * Name: find_stream_in_device_with_process_type diff --git a/framework/src/media/media_init.c b/framework/src/media/media_init.c index b9b2cebd70..ab04171c4e 100644 --- a/framework/src/media/media_init.c +++ b/framework/src/media/media_init.c @@ -26,3 +26,4 @@ int media_init(void) audio_manager_init(); return 0; } + diff --git a/framework/src/media/stream_info.c b/framework/src/media/stream_info.c index f95f376cc5..7d3ffcb836 100644 --- a/framework/src/media/stream_info.c +++ b/framework/src/media/stream_info.c @@ -24,7 +24,7 @@ #include static pthread_mutex_t g_stream_info_mutex; -static uint64_t g_stream_info_id; +static uint64_t g_stream_info_id = 0; int stream_info_init(void) { @@ -46,6 +46,9 @@ 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; diff --git a/framework/src/media/utils/MediaUtils.cpp b/framework/src/media/utils/MediaUtils.cpp index f0617f2ffb..383833b43d 100644 --- a/framework/src/media/utils/MediaUtils.cpp +++ b/framework/src/media/utils/MediaUtils.cpp @@ -644,8 +644,10 @@ static bool checkId3V2Header(const unsigned char *buffer, size_t size, FILE *fp } } else { meddbg("id3v2 tag not found\n"); - if (fseek(fp, 0, SEEK_SET) != OK) { - return false; + if(fp) { + if (fseek(fp, 0, SEEK_SET) != OK) { + return false; + } } } return true; @@ -1175,7 +1177,7 @@ bool file_header_parsing(FILE *fp, audio_type_t audioType, unsigned int *channel bool buffer_header_parsing(const unsigned char *buffer, unsigned int bufferSize, audio_type_t audioType, unsigned int *channel, unsigned int *sampleRate, audio_format_type_t *pcmFormat) { unsigned int headPoint; - unsigned int headPointBak; + unsigned int headPointBak = 0; unsigned int frameLength; unsigned int counter = 0; switch (audioType) { diff --git a/framework/src/media/voice/SpeechDetector.cpp b/framework/src/media/voice/SpeechDetector.cpp index ee0a259e90..bff9f8e8e4 100644 --- a/framework/src/media/voice/SpeechDetector.cpp +++ b/framework/src/media/voice/SpeechDetector.cpp @@ -63,6 +63,7 @@ class SpeechDetectorImpl : public SpeechDetector static speech_detect_event_type_e getSpeechDetectEvent(audio_device_process_unit_subtype_e event); void resetKeywordDetectorPtr(void); void resetEndPointDetectorPtr(void); + std::shared_ptr mKeywordDetector; std::shared_ptr mEndPointDetector; /* @todo: check static keyword usage */