Removing the parameter 'void* user_data' in ttse_send_personal_voice
[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
22 void PlayerThread::runThread(PlayerThread* player)
23 {
24         pthread_t thread = pthread_self();
25         int nameSetResult = pthread_setname_np(thread, "ttsd_play_thread");
26         SLOG(LOG_INFO, tts_tag(), "Name : %d %lu", nameSetResult, thread);
27
28         SLOG(LOG_INFO, tts_tag(), "[Player] Run player thread");
29         player->runPlayer();
30         SLOG(LOG_INFO, tts_tag(), "[Player] Exit player thread");
31 }
32
33 PlayerThread::PlayerThread(PlayUtteranceCallback threadFucntion)
34 {
35         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Constructor");
36         mCurrentUid = TTS_INVALID_UID;
37         mPlayerAvailable = true;
38         mPlayUtterance = threadFucntion;
39
40         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Start thread");
41         mPlayerThread = thread(runThread, this);
42 }
43
44 PlayerThread::~PlayerThread()
45 {
46         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Destructor");
47         unique_lock<mutex> controlLock(mControlMutex);
48         mPlayerAvailable = false;
49         mPlayUtterance = nullptr;
50
51         tryToStopPlayer();
52         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Thread is stopped or waiting");
53
54         mThreadCond.notify_all();
55         mPlayerThread.join();
56         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Finish thread");
57 }
58
59 void PlayerThread::tryToStopPlayer()
60 {
61         mCurrentUid = TTS_INVALID_UID;
62
63         std::unique_lock<std::timed_mutex> thread_lock(mThreadMutex, std::defer_lock);
64         if (false == thread_lock.try_lock_for(std::chrono::milliseconds(500))) {
65                 SLOG(LOG_WARN, tts_tag(), "[PlayerThread] Timeout stop request");
66         }
67 }
68
69 bool PlayerThread::isPlayerAvailable()
70 {
71         return mPlayerAvailable.load();
72 }
73
74 unsigned int PlayerThread::getCurrentUid()
75 {
76         return mCurrentUid.load();
77 }
78
79 bool PlayerThread::isCurrentUid(unsigned int uid)
80 {
81         if (0 > ttsd_data_is_client(uid)) {
82                 return false;
83         }
84
85         if (uid != mCurrentUid.load()) {
86                 return false;
87         }
88
89         return true;
90 }
91
92 void PlayerThread::requestPlay(unsigned int uid)
93 {
94         lock_guard<mutex> lock(mControlMutex);
95         if (false == isPlayerAvailable()) {
96                 SLOG(LOG_ERROR, tts_tag(), "[PlayerThread] Player is already finished.");
97                 return;
98         }
99
100         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Play request. uid(%u)", uid);
101         mCurrentUid = uid;
102         mThreadCond.notify_all();
103 }
104
105 void PlayerThread::requestStop()
106 {
107         lock_guard<mutex> lock(mControlMutex);
108         if (false == isPlayerAvailable()) {
109                 SLOG(LOG_ERROR, tts_tag(), "[PlayerThread] Player is already finished.");
110                 return;
111         }
112
113         unsigned int uid = mCurrentUid.load();
114         if (uid == TTS_INVALID_UID) {
115                 SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Thread is already stopped");
116                 return;
117         }
118
119         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Stop request. current played uid(%u)", uid);
120         tryToStopPlayer();
121         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Stop playing");
122 }
123
124 void PlayerThread::runPlayer()
125 {
126         std::unique_lock<std::timed_mutex> lock(mThreadMutex);
127         if (nullptr == mPlayUtterance) {
128                 SLOG(LOG_ERROR, tts_tag(), "[PlayerThread] Play utterance callback is not set");
129                 return;
130         }
131
132         while (isPlayerAvailable()) {
133                 if (isThreadStopped()) {
134                         SLOG(LOG_INFO, tts_tag(), "[PlayerThread] Wait for playing");
135                         mThreadCond.wait(lock);
136                 } else {
137                         unsigned int uid = getCurrentUid();
138                         SLOG(LOG_INFO, tts_tag(), "[Player] Current player uid(%u)", uid);
139                         mPlayUtterance(this, uid);
140                 }
141         }
142 }
143
144 bool PlayerThread::isThreadStopped()
145 {
146         bool isStopped = (TTS_INVALID_UID == mCurrentUid.load()) || (false == isPlayerAvailable());
147         return isStopped;
148 }