Merge "Add codes in client side to set/unset callback for retrieving sythesized pcm...
[platform/core/uifw/tts.git] / server / PlayerThread.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 "ttsd_main.h"
15 #include "ttsd_data.h"
16 #include "PlayerThread.h"
17
18
19 using namespace std;
20
21 void PlayerThread::runThread(PlayerThread* player)
22 {
23         SLOG(LOG_INFO, tts_tag(), "[Player] Run player thread");
24         player->runPlayer();
25         SLOG(LOG_INFO, tts_tag(), "[Player] Exit player thread");
26 }
27
28 PlayerThread::PlayerThread(PlayUtteranceCallback threadFucntion)
29 {
30         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Constructor");
31         __currentUid = TTS_INVALID_UID;
32         __playerAvailable = true;
33         __playUtterance = threadFucntion;
34
35         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Start thread");
36         __playerThread = thread(runThread, this);
37 }
38
39 PlayerThread::~PlayerThread()
40 {
41         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Destructor");
42         unique_lock<mutex> controlLock(__controlMutex);
43         __playerAvailable = false;
44         __playUtterance = nullptr;
45
46         tryToStopPlayer();
47         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Thread is stopped or waiting");
48
49         __threadCond.notify_all();
50         __playerThread.join();
51         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Finish thread");
52 }
53
54 void PlayerThread::tryToStopPlayer()
55 {
56         __currentUid = TTS_INVALID_UID;
57
58         unique_lock<mutex> stopCheckLock(__stopCheckMutex);
59         cv_status ret = __stopCheckCond.wait_for(stopCheckLock, chrono::milliseconds(500));
60         if (ret == cv_status::timeout) {
61                 SLOG(LOG_WARN, tts_tag(), "[PlayerThread] Timeout stop request");
62         }
63 }
64
65 bool PlayerThread::isPlayerAvailable()
66 {
67         return __playerAvailable.load();
68 }
69
70 unsigned int PlayerThread::getCurrentUid()
71 {
72         return __currentUid.load();
73 }
74
75 bool PlayerThread::isCurrentUid(unsigned int uid)
76 {
77         if (0 > ttsd_data_is_client(uid)) {
78                 return false;
79         }
80
81         if (uid != __currentUid.load()) {
82                 return false;
83         }
84
85         return true;
86 }
87
88 void PlayerThread::requestPlay(unsigned int uid)
89 {
90         lock_guard<mutex> lock(__controlMutex);
91         if (false == isPlayerAvailable()) {
92                 SLOG(LOG_ERROR, tts_tag(), "[PlayerThread] Player is already finished.");
93                 return;
94         }
95
96         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Play request. uid(%u)", uid);
97         __currentUid = uid;
98         __threadCond.notify_all();
99 }
100
101 void PlayerThread::requestStop()
102 {
103         lock_guard<mutex> lock(__controlMutex);
104         if (false == isPlayerAvailable()) {
105                 SLOG(LOG_ERROR, tts_tag(), "[PlayerThread] Player is already finished.");
106                 return;
107         }
108
109         unsigned int uid = __currentUid.load();
110         if (uid == TTS_INVALID_UID) {
111                 SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Thread is already stopped");
112                 return;
113         }
114
115         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Stop request. current played uid(%u)", uid);
116         tryToStopPlayer();
117         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Stop playing");
118 }
119
120 void PlayerThread::runPlayer()
121 {
122         unique_lock<mutex> lock(__threadMutex);
123         if (nullptr == __playUtterance) {
124                 SLOG(LOG_ERROR, tts_tag(), "[PlayerThread] Play utterance callback is not set");
125                 return;
126         }
127
128         while (isPlayerAvailable()) {
129                 SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Wait playing");
130                 if (isThreadStopped()) {
131                         __threadCond.wait(lock);
132                 }
133
134                 while (false == isThreadStopped()) {
135                         unsigned int uid = getCurrentUid();
136                         SLOG(LOG_INFO, tts_tag(), "[Player] Current player uid(%u)", uid);
137                         __playUtterance(this, uid);
138                 }
139
140                 __stopCheckCond.notify_all();
141         }
142 }
143
144 bool PlayerThread::isThreadStopped()
145 {
146         bool isStopped = (TTS_INVALID_UID == __currentUid.load()) || (false == isPlayerAvailable());
147         return isStopped;
148 }