Define class for managing audio stream
[platform/core/uifw/tts.git] / server / AudioStream.cpp
1 /*
2 *  Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14 #include <dlog.h>
15
16 #include "ttsd_main.h"
17
18 #include "AudioStream.h"
19
20 using namespace std;
21
22
23 static const char* FOCUS_SERVER_READY = "/tmp/.sound_server_ready";
24
25
26 AudioStream::AudioStream(focusReleaseCallback focusReleaseCb)
27 {
28         __prepared = false;
29         __focusReleaseCallback = focusReleaseCb;
30         __focusAquired = false;
31
32         createSoundStreamInfo();
33         createAudioHandle(TTSE_AUDIO_TYPE_RAW_S16, 16000);
34 }
35
36 void AudioStream::createSoundStreamInfo()
37 {
38         int cnt = 0;
39         while (1) {
40                 if (0 == access(FOCUS_SERVER_READY, F_OK)) {
41                         SLOG(LOG_ERROR, tts_tag(), "[AudioStream] focus server is available");
42                         break;
43                 } else {
44                         if (0 == cnt++ % 10)
45                                 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] focus server is not available");
46                         usleep(50000);
47                 }
48         }
49
50         int ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_VOICE_INFORMATION, __focusStateChangedCallback, this, &__streamInfo);
51         if (SOUND_MANAGER_ERROR_NONE != ret) {
52                 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to create stream info");
53                 return;
54         }
55
56         __focusAquired = false;
57         SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Create stream info");
58 }
59
60 AudioStream::~AudioStream()
61 {
62         __focusReleaseCallback = nullptr;
63         __focusAquired = false;
64
65         unprepareAudioOut();
66         destroyAudioHandle();
67         destroySoundStreamInfo();
68 }
69
70 void AudioStream::destroySoundStreamInfo()
71 {
72         int ret = sound_manager_destroy_stream_information(__streamInfo);
73         if (SOUND_MANAGER_ERROR_NONE != ret) {
74                 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to destroy stream info");
75         }
76         __streamInfo = nullptr;
77         __focusAquired = false;
78 }
79
80 int AudioStream::setAudioFormat(ttse_audio_type_e type, int rate)
81 {
82         if (__audioType == type && __audioRate == rate) {
83                 return TTSD_ERROR_NONE;
84         }
85
86         SLOG(LOG_INFO, tts_tag(), "[AudioStream] Audio info is different. type:(%d)/(%d), rate:(%d)/(%d)",
87                         __audioType, type, __audioRate, rate);
88
89         destroyAudioHandle();
90         if (TTSD_ERROR_NONE != createAudioHandle(type, rate)) {
91                 return TTSD_ERROR_OPERATION_FAILED;
92         }
93
94         if (__focusAquired) {
95                 const char* extra_info = __currentExtraInfo.empty() ? nullptr : __currentExtraInfo.c_str();
96                 acquireSoundFocus(extra_info);
97         }
98
99         __state = AUDIO_STATE_READY;
100         return TTSD_ERROR_NONE;
101 }
102
103 int AudioStream::acquireSoundFocus(const char* extra_info)
104 {
105         if (nullptr == extra_info) {
106                 __currentExtraInfo.clear();
107         } else {
108                 __currentExtraInfo.assign(extra_info);
109         }
110
111         int ret = sound_manager_acquire_focus(__streamInfo, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, extra_info);
112         if (SOUND_MANAGER_ERROR_NONE != ret) {
113                 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to acquire focus");
114         } else {
115                 SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Success to acquire focus");
116         }
117
118         ret = audio_out_set_sound_stream_info(__audioHandle, __streamInfo);
119         if (AUDIO_IO_ERROR_NONE != ret) {
120                 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to set stream info");
121                 return TTSD_ERROR_OPERATION_FAILED;
122         }
123
124         __focusAquired = true;
125         return TTSD_ERROR_NONE;
126 }
127
128 int AudioStream::releaseSoundFocus()
129 {
130         sound_stream_focus_state_e focusState = SOUND_STREAM_FOCUS_STATE_ACQUIRED;
131         int ret = sound_manager_get_focus_state(__streamInfo, &focusState, nullptr);
132         if (SOUND_MANAGER_ERROR_NONE != ret) {
133                 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to get focus state: %d", ret);
134         }
135
136         if (SOUND_STREAM_FOCUS_STATE_ACQUIRED != focusState) {
137                 SLOG(LOG_INFO, tts_tag(), "[AudioStream] This handle has no focus");
138                 return TTSD_ERROR_NONE;
139         }
140
141         ret = sound_manager_release_focus(__streamInfo, SOUND_STREAM_FOCUS_FOR_PLAYBACK, SOUND_BEHAVIOR_NONE, nullptr);
142         if (SOUND_MANAGER_ERROR_NONE != ret) {
143                 SLOG(LOG_WARN, tts_tag(), "[AudioStream] Fail to release focus");
144                 return TTSD_ERROR_OPERATION_FAILED;
145         }
146
147         __focusAquired = false;
148         return TTSD_ERROR_NONE;
149 }
150
151 int AudioStream::prepareAudioOut()
152 {
153         if (__prepared) {
154                 SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Audio is already prepared");
155                 return TTSD_ERROR_NONE;
156         }
157
158         int ret = audio_out_prepare(__audioHandle);
159         if (AUDIO_IO_ERROR_NONE != ret) {
160                 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to prepare audio : %d", ret);
161                 return TTSD_ERROR_OPERATION_FAILED;
162         }
163
164         __prepared = true;
165         __state = AUDIO_STATE_PLAY;
166         return TTSD_ERROR_NONE;
167 }
168
169 int AudioStream::playAudioData(char* buffer, unsigned int length)
170 {
171         if (false == __prepared) {
172                 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Audio is not prepared");
173                 return TTSD_ERROR_OPERATION_FAILED;
174         }
175
176         int ret = audio_out_write(__audioHandle, static_cast<void*>(buffer), length);
177         if (0 > ret) {
178                 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to audio write - %d", ret);
179                 return TTSD_ERROR_OPERATION_FAILED;
180         }
181
182         return TTSD_ERROR_NONE;
183 }
184
185 int AudioStream::unprepareAudioOut()
186 {
187         if (false == __prepared) {
188                 SLOG(LOG_DEBUG, tts_tag(), "[AudioStream] Audio is not prepared");
189                 return TTSD_ERROR_NONE;
190         }
191
192         int ret = audio_out_unprepare(__audioHandle);
193         if (AUDIO_IO_ERROR_NONE != ret) {
194                 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to prepare audio : %d", ret);
195                 return TTSD_ERROR_OPERATION_FAILED;
196         }
197
198         __prepared = false;
199         __state = AUDIO_STATE_READY;
200         return TTSD_ERROR_NONE;
201 }
202
203 void AudioStream::waitForPlay()
204 {
205         __state = AUDIO_STATE_WAIT_FOR_PLAYING;
206 }
207
208 AudioStream::AudioState AudioStream::getState()
209 {
210         return __state;
211 }
212
213 int AudioStream::createAudioHandle(ttse_audio_type_e type, int rate)
214 {
215         audio_sample_type_e sample_type;
216         if (TTSE_AUDIO_TYPE_RAW_S16 == type) {
217                 sample_type = AUDIO_SAMPLE_TYPE_S16_LE;
218         } else {
219                 sample_type = AUDIO_SAMPLE_TYPE_U8;
220         }
221
222         int ret = audio_out_create_new(rate, AUDIO_CHANNEL_MONO, sample_type, &__audioHandle);
223         if (AUDIO_IO_ERROR_NONE != ret) {
224                 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to create audio out handle. ret(%s)", get_error_message(ret));
225                 return TTSD_ERROR_OPERATION_FAILED;
226         }
227
228         __audioType = type;
229         __audioRate = rate;
230         __state = AUDIO_STATE_READY;
231
232         SLOG(LOG_INFO, tts_tag(), "[AudioStream] Create audio");
233         return TTSD_ERROR_NONE;
234 }
235
236 void AudioStream::destroyAudioHandle()
237 {
238         if (nullptr == __audioHandle) {
239                 SLOG(LOG_INFO, tts_tag(), "[AudioStream] Audio handle is not exist");
240                 return;
241         }
242
243         int ret = audio_out_destroy(__audioHandle);
244         if (AUDIO_IO_ERROR_NONE != ret) {
245                 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Fail to destroy audio out handle. ret(%s)", get_error_message(ret));
246         } else {
247                 SLOG(LOG_INFO, tts_tag(), "[AudioStream] Destroy audio");
248         }
249
250         __state = AUDIO_STATE_NONE;
251 }
252
253 void AudioStream::__focusStateChangedCallback(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask,
254                 sound_stream_focus_state_e focus_state, sound_stream_focus_change_reason_e reason_for_change,
255                 int sound_behavior, const char *extra_info, void *user_data)
256 {
257         SLOG(LOG_INFO, tts_tag(), "[AudioStream] focus state changed to (%d) with reason(%d) and extra info(%s)",
258                         (int)focus_state, (int)reason_for_change, extra_info);
259
260         AudioStream* audioOut = static_cast<AudioStream*>(user_data);
261         if (stream_info != audioOut->__streamInfo) {
262                 SLOG(LOG_ERROR, tts_tag(), "[AudioStream] Invalid stream info handle");
263                 return;
264         }
265
266         if (false == audioOut->__prepared || AUDIO_STATE_NONE == audioOut->__state || AUDIO_STATE_READY == audioOut->__state) {
267                 return;
268         }
269
270         if (SOUND_STREAM_FOCUS_FOR_PLAYBACK != focus_mask || SOUND_STREAM_FOCUS_STATE_RELEASED != focus_state) {
271                 return;
272         }
273
274         SLOG(LOG_INFO, tts_tag(), "[AudioStream] Focus is released on playing. Invoke callback");
275         if (audioOut->__focusReleaseCallback) {
276                 audioOut->__focusReleaseCallback();
277         }
278 }