1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
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 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "audio_player.h"
16 #include <errno.h>
17 #include <pthread.h>
18 #include <sys/time.h>
19 #include <unistd.h>
20 #include "js_async_work.h"
21 #include "media_log.h"
22
23 #define DELETE_NOT_NULL(pointer) \
24 if (pointer != nullptr) \
25 { \
26 delete pointer; \
27 pointer = nullptr; \
28 }
29
30 namespace OHOS {
31 namespace ACELite {
32 constexpr char STATUS_PLAY[] = "play";
33 constexpr char STATUS_PAUSE[] = "pause";
34 constexpr char STATUS_STOP[] = "stop";
35 constexpr uint16_t MAX_VOLUME = 300;
36 constexpr double DEFAULT_VOLUME = 1.0;
37 constexpr double MILLISECONDS_PER_SECOND = 1000.0;
38
TriggerEventListener(const AudioEventListener * listener)39 void TriggerEventListener(const AudioEventListener *listener)
40 {
41 if (!JsAsyncWork::DispatchAsyncWork(AsyncExecuteCallback, const_cast<AudioEventListener *>(listener))) {
42 MEDIA_ERR_LOG("dispatch async work failed.");
43 }
44 }
45
AsyncExecuteCallback(void * arg)46 void AsyncExecuteCallback(void *arg)
47 {
48 AudioEventListener *listener = static_cast<AudioEventListener *>(arg);
49 if (listener == nullptr) {
50 MEDIA_ERR_LOG("async execute callback failed.");
51 return;
52 }
53 listener->OnTrigger();
54 }
55
AudioEventListener(JSIValue callback)56 AudioEventListener::AudioEventListener(JSIValue callback) : callback_(JSI::AcquireValue(callback)) {}
57
~AudioEventListener()58 AudioEventListener::~AudioEventListener()
59 {
60 if (!JSI::ValueIsUndefined(callback_)) {
61 JSI::ReleaseValue(callback_);
62 }
63 }
64
GetCallback() const65 JSIValue AudioEventListener::GetCallback() const
66 {
67 return callback_;
68 }
69
OnTrigger() const70 void AudioEventListener::OnTrigger() const
71 {
72 if (JSI::ValueIsFunction(callback_)) {
73 JSI::CallFunction(callback_, JSI::CreateUndefined(), nullptr, 0);
74 }
75 }
76
AudioPlayerCallback(AudioPlayer * audioPlayer)77 AudioPlayerCallback::AudioPlayerCallback(AudioPlayer *audioPlayer) : PlayerCallback(), audioPlayer_(audioPlayer) {}
78
PlaybackCompleteHandler(void * arg)79 void *AudioPlayerCallback::PlaybackCompleteHandler(void *arg)
80 {
81 int32_t ret = pthread_setname_np((pthread_t)pthread_self(), "PlaybackCom");
82 if (ret != 0) {
83 MEDIA_ERR_LOG("fail to set thread name.");
84 return nullptr;
85 }
86
87 AudioPlayer *audioPlayer_ = (AudioPlayer *)arg;
88 if (!audioPlayer_->ResetPlayer()) {
89 MEDIA_ERR_LOG("fail to reset player.");
90 TriggerEventListener(audioPlayer_->GetOnErrorListener());
91 }
92 TriggerEventListener(audioPlayer_->GetOnEndedListener());
93 return nullptr;
94 }
95
OnPlaybackComplete()96 void AudioPlayerCallback::OnPlaybackComplete()
97 {
98 MEDIA_DEBUG_LOG("fork playback complete handler thread.");
99 pthread_t threadId;
100 pthread_attr_t attr;
101 pthread_attr_init(&attr);
102 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
103 int retCode = pthread_create(&threadId, &attr, AudioPlayerCallback::PlaybackCompleteHandler, audioPlayer_);
104 if (retCode != 0) {
105 MEDIA_ERR_LOG("fork thread failed: %d.", retCode);
106 return;
107 }
108 MEDIA_DEBUG_LOG("fork thread success: %lu", threadId);
109 }
110
OnError(int32_t errorType,int32_t errorCode)111 void AudioPlayerCallback::OnError(int32_t errorType, int32_t errorCode)
112 {
113 TriggerEventListener(audioPlayer_->GetOnErrorListener());
114 }
115
OnInfo(int type,int extra)116 void AudioPlayerCallback::OnInfo(int type, int extra)
117 {
118 TriggerEventListener(audioPlayer_->GetOnLoadedDataListener());
119 }
120
OnVideoSizeChanged(int width,int height)121 void AudioPlayerCallback::OnVideoSizeChanged(int width, int height) {}
122
OnRewindToComplete()123 void AudioPlayerCallback::OnRewindToComplete()
124 {
125 TriggerEventListener(audioPlayer_->GetOnTimeUpdateListener());
126 }
127
128 pthread_mutex_t AudioPlayer::lock_ = PTHREAD_MUTEX_INITIALIZER;
129 pthread_cond_t AudioPlayer::condition_ = PTHREAD_COND_INITIALIZER;
130
GetInstance()131 AudioPlayer *AudioPlayer::GetInstance()
132 {
133 static AudioPlayer audioPlayer;
134 return &audioPlayer;
135 }
136
AudioPlayer()137 AudioPlayer::AudioPlayer() : player_(nullptr),
138 onPlayListener_(nullptr),
139 onPauseListener_(nullptr),
140 onStopListener_(nullptr),
141 onLoadedDataListener_(nullptr),
142 onEndedListener_(nullptr),
143 onErrorListener_(nullptr),
144 onTimeUpdateListener_(nullptr),
145 src_(nullptr),
146 status_(const_cast<char *>(STATUS_STOP)),
147 volume_(DEFAULT_VOLUME),
148 autoPlay_(false),
149 muted_(false),
150 isRunning_(false) {}
151
ForkUpdateTimeThread()152 void AudioPlayer::ForkUpdateTimeThread()
153 {
154 MEDIA_DEBUG_LOG("fork update time thread.");
155 pthread_t threadId;
156 if (isRunning_) {
157 return;
158 }
159 isRunning_ = true;
160 int retCode = pthread_mutex_init(&lock_, nullptr);
161 if (retCode != 0) {
162 MEDIA_ERR_LOG("init mutex lock failed: %d.", retCode);
163 return;
164 }
165 retCode = pthread_cond_init(&condition_, nullptr);
166 if (retCode != 0) {
167 MEDIA_ERR_LOG("init condition failed: %d.", retCode);
168 (void)pthread_mutex_destroy(&lock_);
169 return;
170 }
171 retCode = pthread_create(&threadId, nullptr, AudioPlayer::UpdateTimeHandler, this);
172 if (retCode != 0) {
173 MEDIA_ERR_LOG("fork thread failed: %d.", retCode);
174 (void)pthread_mutex_destroy(&lock_);
175 (void)pthread_cond_destroy(&condition_);
176 return;
177 }
178 MEDIA_DEBUG_LOG("fork thread success: %lu", threadId);
179 }
180
UpdateTimeHandler(void * arg)181 void *AudioPlayer::UpdateTimeHandler(void *arg)
182 {
183 int32_t ret = pthread_setname_np((pthread_t)pthread_self(), "UpdateTime");
184 if (ret != 0) {
185 MEDIA_ERR_LOG("fail to set thread name.");
186 return nullptr;
187 }
188 if (arg == nullptr) {
189 MEDIA_ERR_LOG("audio player is null.");
190 return nullptr;
191 }
192 AudioPlayer *audioPlayer = static_cast<AudioPlayer *>(arg);
193
194 struct timespec timeout;
195 int retCode;
196 while (audioPlayer->isRunning_) {
197 retCode = pthread_mutex_lock(&lock_);
198 if (retCode != 0) {
199 MEDIA_ERR_LOG("mutex lock failed: %d", retCode);
200 break;
201 }
202 if (!audioPlayer->IsPlaying()) {
203 // waiting for playing
204 (void)pthread_cond_wait(&condition_, &lock_);
205 } else {
206 retCode = clock_gettime(CLOCK_REALTIME, &timeout);
207 if (retCode != 0) {
208 MEDIA_ERR_LOG("get current time failed: %d", retCode);
209 (void)pthread_mutex_unlock(&lock_);
210 continue;
211 }
212 timeout.tv_sec += 1;
213 retCode = pthread_cond_timedwait(&condition_, &lock_, &timeout);
214 if (retCode == ETIMEDOUT) {
215 TriggerEventListener(audioPlayer->GetOnTimeUpdateListener());
216 }
217 }
218 retCode = pthread_mutex_unlock(&lock_);
219 if (retCode != 0) {
220 MEDIA_ERR_LOG("unlock faild: %d", retCode);
221 break;
222 }
223 }
224 audioPlayer->StopUpdateTimeThread();
225 (void)pthread_cond_destroy(&condition_);
226 (void)pthread_mutex_destroy(&lock_);
227 return nullptr;
228 }
229
StopUpdateTimeThread()230 void AudioPlayer::StopUpdateTimeThread()
231 {
232 isRunning_ = false;
233 }
234
CreatePlayer()235 bool AudioPlayer::CreatePlayer()
236 {
237 player_ = new Media::Player();
238 if (player_ == nullptr) {
239 MEDIA_ERR_LOG("fail to create player");
240 return false;
241 }
242 if (muted_) {
243 player_->SetVolume(0, 0);
244 } else {
245 double volume = volume_ * 100;
246 if (player_->SetVolume(volume, volume) != 0) {
247 MEDIA_ERR_LOG("fail to reset volume");
248 }
249 }
250 if (!callback_) {
251 MEDIA_INFO_LOG("Create Callback");
252 callback_ = std::make_shared<AudioPlayerCallback>(this);
253 }
254 player_->SetPlayerCallback(callback_);
255 return true;
256 }
257
DestoryPlayer()258 bool AudioPlayer::DestoryPlayer()
259 {
260 if (player_ != nullptr) {
261 if (player_->IsPlaying() && player_->Stop() != 0) {
262 MEDIA_ERR_LOG("fail to stop audio.");
263 }
264 if (player_->Reset() != 0) {
265 MEDIA_ERR_LOG("fail to reset audio player.");
266 }
267 if (player_->Release() != 0) {
268 MEDIA_ERR_LOG("fail to release audio player.");
269 }
270 delete player_;
271 player_ = nullptr;
272 }
273 ReleaseSrc();
274 status_ = const_cast<char *>(STATUS_STOP);
275 return true;
276 }
277
ResetPlayer()278 bool AudioPlayer::ResetPlayer()
279 {
280 (void)pthread_mutex_lock(&lock_);
281 bool ret = DestoryPlayer();
282 if (!ret) {
283 MEDIA_ERR_LOG("fail to destory player.");
284 }
285 ret = CreatePlayer();
286 if (!ret) {
287 MEDIA_ERR_LOG("fail to re-create audio.");
288 }
289 (void)pthread_mutex_unlock(&lock_);
290 return ret;
291 }
292
ReleaseEventListeners()293 void AudioPlayer::ReleaseEventListeners()
294 {
295 DELETE_NOT_NULL(onPlayListener_);
296 DELETE_NOT_NULL(onPauseListener_);
297 DELETE_NOT_NULL(onStopListener_);
298 DELETE_NOT_NULL(onLoadedDataListener_);
299 DELETE_NOT_NULL(onEndedListener_);
300 DELETE_NOT_NULL(onErrorListener_);
301 DELETE_NOT_NULL(onTimeUpdateListener_);
302 }
303
ReleaseSrc()304 void AudioPlayer::ReleaseSrc()
305 {
306 if (src_ != nullptr) {
307 ace_free(src_);
308 src_ = nullptr;
309 }
310 }
311
Play()312 bool AudioPlayer::Play()
313 {
314 if (player_->IsPlaying()) {
315 MEDIA_DEBUG_LOG("audio is playing.");
316 return true;
317 }
318 if (src_ == nullptr) {
319 MEDIA_ERR_LOG("audio src is required.");
320 return false;
321 }
322 if (player_->Play() != 0) {
323 MEDIA_ERR_LOG("fail to play audio.");
324 return false;
325 }
326 int retCode = pthread_cond_signal(&condition_);
327 if (retCode != 0) {
328 MEDIA_ERR_LOG("fail to signal condition: %d.", retCode);
329 }
330 status_ = const_cast<char *>(STATUS_PLAY);
331 TriggerEventListener(onPlayListener_);
332 return true;
333 }
334
Pause()335 bool AudioPlayer::Pause()
336 {
337 if (!player_->IsPlaying()) {
338 MEDIA_DEBUG_LOG("player is not playing");
339 return false;
340 }
341 if (player_->Pause() != 0) {
342 MEDIA_ERR_LOG("fail to pause audio.");
343 return false;
344 }
345 status_ = const_cast<char *>(STATUS_PAUSE);
346 TriggerEventListener(onPauseListener_);
347 return true;
348 }
349
Stop()350 bool AudioPlayer::Stop()
351 {
352 TriggerEventListener(onStopListener_);
353 if (!DestoryPlayer()) {
354 MEDIA_ERR_LOG("fail to destory player.");
355 }
356 if (!CreatePlayer()) {
357 MEDIA_ERR_LOG("fail to re-create audio.");
358 return false;
359 }
360 return true;
361 }
362
GetSrc() const363 char *AudioPlayer::GetSrc() const
364 {
365 return src_;
366 }
367
GetCurrentTime() const368 double AudioPlayer::GetCurrentTime() const
369 {
370 if (status_ == STATUS_STOP) {
371 return -1;
372 }
373 int64_t currentTime = 0;
374 if (player_->GetCurrentTime(currentTime) != 0) {
375 MEDIA_ERR_LOG("fail to get audio currentTime property.");
376 }
377 return currentTime / MILLISECONDS_PER_SECOND;
378 }
379
GetDuration() const380 double AudioPlayer::GetDuration() const
381 {
382 if (status_ == STATUS_STOP) {
383 return -1;
384 }
385
386 int64_t duation = 0;
387 if (player_->GetDuration(duation) != 0) {
388 MEDIA_ERR_LOG("fail to get audio duaiton property.");
389 }
390 return duation / MILLISECONDS_PER_SECOND;
391 }
392
GetAutoPlay() const393 bool AudioPlayer::GetAutoPlay() const
394 {
395 return autoPlay_;
396 }
397
IsLooping() const398 bool AudioPlayer::IsLooping() const
399 {
400 return player_->IsSingleLooping();
401 }
402
IsMuted() const403 bool AudioPlayer::IsMuted() const
404 {
405 return muted_;
406 }
407
GetStatus() const408 const char *AudioPlayer::GetStatus() const
409 {
410 return status_;
411 }
412
GetVolume() const413 double AudioPlayer::GetVolume() const
414 {
415 return volume_;
416 }
417
IsPlaying() const418 bool AudioPlayer::IsPlaying() const
419 {
420 if (player_ == nullptr) {
421 return false;
422 }
423
424 return player_->IsPlaying();
425 }
426
SetSrc(char * src)427 bool AudioPlayer::SetSrc(char *src)
428 {
429 if (src_ != nullptr) {
430 if (!DestoryPlayer()) {
431 MEDIA_ERR_LOG("fail to destory player.");
432 }
433 if (!CreatePlayer()) {
434 MEDIA_ERR_LOG("fail to re-create audio.");
435 }
436 }
437
438 if (src == nullptr) {
439 MEDIA_ERR_LOG("set audio src to null.");
440 return true;
441 }
442
443 std::string uri(src);
444 std::map<std::string, std::string> header;
445 Media::Source source(uri, header);
446 if (player_->SetSource(source) != 0) {
447 MEDIA_ERR_LOG("fail to set audio src property.");
448 return false;
449 }
450 src_ = src;
451 if (player_->Prepare() != 0) {
452 MEDIA_ERR_LOG("fail to prepare.");
453 return false;
454 }
455 if (autoPlay_) {
456 this->Play();
457 }
458 return true;
459 }
460
SetCurrentTime(double currentTime) const461 bool AudioPlayer::SetCurrentTime(double currentTime) const
462 {
463 if (currentTime < 0) {
464 MEDIA_ERR_LOG("currentTime must be larger than or equals 0.");
465 return false;
466 }
467 int64_t position = static_cast<int64_t>(currentTime * MILLISECONDS_PER_SECOND);
468 if (player_->Rewind(position, Media::PlayerSeekMode::PLAYER_SEEK_CLOSEST_SYNC) != 0) {
469 MEDIA_ERR_LOG("fail to set audio currentTime property.");
470 return false;
471 }
472 return true;
473 }
474
SetAutoPlay(bool autoPlay)475 bool AudioPlayer::SetAutoPlay(bool autoPlay)
476 {
477 if (autoPlay && src_ != nullptr && status_ == STATUS_STOP) {
478 if (!Play()) {
479 MEDIA_ERR_LOG("fail to auto play audio.");
480 }
481 }
482 autoPlay_ = autoPlay;
483 return true;
484 }
485
SetLoop(bool loop) const486 bool AudioPlayer::SetLoop(bool loop) const
487 {
488 if (player_->EnableSingleLooping(loop) != 0) {
489 MEDIA_ERR_LOG("1 argument is required.");
490 return false;
491 }
492 return true;
493 }
494
SetVolume(double volume)495 bool AudioPlayer::SetVolume(double volume)
496 {
497 if (volume < 0 || volume > 1) {
498 MEDIA_ERR_LOG("invalid parameter.");
499 return false;
500 }
501 float parsedVolume = static_cast<float>(volume * MAX_VOLUME) ;
502 if (player_->SetVolume(parsedVolume, parsedVolume) != 0) {
503 MEDIA_ERR_LOG("fail to set volume.");
504 return false;
505 }
506 volume_ = volume;
507 return true;
508 }
509
SetMuted(bool muted)510 bool AudioPlayer::SetMuted(bool muted)
511 {
512 double volume = muted ? 0.0 : (volume_ * MILLISECONDS_PER_SECOND);
513 if (player_->SetVolume(volume, volume) != 0) {
514 MEDIA_ERR_LOG("fail to set volume.");
515 return false;
516 }
517 muted_ = muted;
518 return true;
519 }
520
GetOnPlayListener() const521 const AudioEventListener *AudioPlayer::GetOnPlayListener() const
522 {
523 return onPlayListener_;
524 }
525
GetOnPauseListener() const526 const AudioEventListener *AudioPlayer::GetOnPauseListener() const
527 {
528 return onPauseListener_;
529 }
530
GetOnStopListener() const531 const AudioEventListener *AudioPlayer::GetOnStopListener() const
532 {
533 return onStopListener_;
534 }
535
GetOnLoadedDataListener() const536 const AudioEventListener *AudioPlayer::GetOnLoadedDataListener() const
537 {
538 return onLoadedDataListener_;
539 }
540
GetOnEndedListener() const541 const AudioEventListener *AudioPlayer::GetOnEndedListener() const
542 {
543 return onEndedListener_;
544 }
545
GetOnErrorListener() const546 const AudioEventListener *AudioPlayer::GetOnErrorListener() const
547 {
548 return onErrorListener_;
549 }
550
GetOnTimeUpdateListener() const551 const AudioEventListener *AudioPlayer::GetOnTimeUpdateListener() const
552 {
553 return onTimeUpdateListener_;
554 }
555
SetOnPlayListener(AudioEventListener * onPlayListener)556 void AudioPlayer::SetOnPlayListener(AudioEventListener *onPlayListener)
557 {
558 if (onPlayListener_ != nullptr) {
559 delete onPlayListener_;
560 }
561 onPlayListener_ = onPlayListener;
562 }
563
SetOnPauseListener(AudioEventListener * onPauseListener)564 void AudioPlayer::SetOnPauseListener(AudioEventListener *onPauseListener)
565 {
566 if (onPauseListener_ != nullptr) {
567 delete onPauseListener_;
568 }
569 onPauseListener_ = onPauseListener;
570 }
571
SetOnStopListener(AudioEventListener * onStopListener)572 void AudioPlayer::SetOnStopListener(AudioEventListener *onStopListener)
573 {
574 if (onStopListener_ != nullptr) {
575 delete onStopListener_;
576 }
577 onStopListener_ = onStopListener;
578 }
579
SetOnLoadedDataListener(AudioEventListener * onLoadedDataListener)580 void AudioPlayer::SetOnLoadedDataListener(AudioEventListener *onLoadedDataListener)
581 {
582 if (onLoadedDataListener_ != nullptr) {
583 delete onLoadedDataListener_;
584 }
585 onLoadedDataListener_ = onLoadedDataListener;
586 }
587
SetOnEndedListener(AudioEventListener * onEndedListener)588 void AudioPlayer::SetOnEndedListener(AudioEventListener *onEndedListener)
589 {
590 if (onEndedListener_ != nullptr) {
591 delete onEndedListener_;
592 }
593 onEndedListener_ = onEndedListener;
594 }
595
SetOnErrorListener(AudioEventListener * onErrorListener)596 void AudioPlayer::SetOnErrorListener(AudioEventListener *onErrorListener)
597 {
598 if (onErrorListener_ != nullptr) {
599 delete onErrorListener_;
600 }
601 onErrorListener_ = onErrorListener;
602 }
603
SetOnTimeUpdateListener(AudioEventListener * onTimeUpdateListener)604 void AudioPlayer::SetOnTimeUpdateListener(AudioEventListener *onTimeUpdateListener)
605 {
606 if (onTimeUpdateListener_ != nullptr) {
607 delete onTimeUpdateListener_;
608 }
609 onTimeUpdateListener_ = onTimeUpdateListener;
610 }
611 } // namespace ACELite
612 } // namespace OHOS
613