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