blob: 1f1863c9dfbc7a4238366b5e09a2461ea185a388 [file] [log] [blame]
Narayan Kamath8d1fc242011-06-03 18:11:54 +01001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16package android.speech.tts;
17
Narayan Kamath8d1fc242011-06-03 18:11:54 +010018import android.util.Log;
19
Narayan Kamath4924fe32011-06-09 11:35:13 +010020import java.util.Iterator;
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000021import java.util.concurrent.LinkedBlockingQueue;
Narayan Kamath4924fe32011-06-09 11:35:13 +010022
23class AudioPlaybackHandler {
Narayan Kamath8d1fc242011-06-03 18:11:54 +010024 private static final String TAG = "TTS.AudioPlaybackHandler";
25 private static final boolean DBG = false;
26
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000027 private final LinkedBlockingQueue<PlaybackQueueItem> mQueue =
28 new LinkedBlockingQueue<PlaybackQueueItem>();
Narayan Kamath4924fe32011-06-09 11:35:13 +010029 private final Thread mHandlerThread;
30
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000031 private volatile PlaybackQueueItem mCurrentWorkItem = null;
Narayan Kamath4924fe32011-06-09 11:35:13 +010032
33 AudioPlaybackHandler() {
34 mHandlerThread = new Thread(new MessageLoop(), "TTS.AudioPlaybackThread");
Narayan Kamath8d1fc242011-06-03 18:11:54 +010035 }
36
Narayan Kamath4924fe32011-06-09 11:35:13 +010037 public void start() {
38 mHandlerThread.start();
Narayan Kamath8d1fc242011-06-03 18:11:54 +010039 }
40
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000041 private void stop(PlaybackQueueItem item) {
42 if (item == null) {
Narayan Kamath4924fe32011-06-09 11:35:13 +010043 return;
44 }
45
Przemyslaw Szczepaniakfc4b2892014-06-26 11:52:20 +010046 item.stop(TextToSpeech.STOPPED);
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000047 }
Narayan Kamath8d1fc242011-06-03 18:11:54 +010048
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000049 public void enqueue(PlaybackQueueItem item) {
50 try {
51 mQueue.put(item);
52 } catch (InterruptedException ie) {
53 // This exception will never be thrown, since we allow our queue
54 // to be have an unbounded size. put() will therefore never block.
Narayan Kamath8d1fc242011-06-03 18:11:54 +010055 }
56 }
57
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000058 public void stopForApp(Object callerIdentity) {
59 if (DBG) Log.d(TAG, "Removing all callback items for : " + callerIdentity);
60 removeWorkItemsFor(callerIdentity);
Narayan Kamathbe4ad4a2011-07-15 13:01:09 +010061
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000062 final PlaybackQueueItem current = mCurrentWorkItem;
Narayan Kamath492b7f02011-11-29 17:02:06 +000063 if (current != null && (current.getCallerIdentity() == callerIdentity)) {
Narayan Kamathbe4ad4a2011-07-15 13:01:09 +010064 stop(current);
65 }
Narayan Kamath4924fe32011-06-09 11:35:13 +010066 }
67
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000068 public void stop() {
69 if (DBG) Log.d(TAG, "Stopping all items");
Narayan Kamath4924fe32011-06-09 11:35:13 +010070 removeAllMessages();
Narayan Kamath40f71f02011-11-23 16:42:53 +000071
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000072 stop(mCurrentWorkItem);
Narayan Kamath4924fe32011-06-09 11:35:13 +010073 }
74
Narayan Kamath8d1fc242011-06-03 18:11:54 +010075 /**
Narayan Kamathc34f76f2011-07-15 11:13:10 +010076 * @return false iff the queue is empty and no queue item is currently
77 * being handled, true otherwise.
78 */
79 public boolean isSpeaking() {
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000080 return (mQueue.peek() != null) || (mCurrentWorkItem != null);
Narayan Kamathc34f76f2011-07-15 11:13:10 +010081 }
82
83 /**
Narayan Kamath8d1fc242011-06-03 18:11:54 +010084 * Shut down the audio playback thread.
85 */
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000086 public void quit() {
Narayan Kamathbe4ad4a2011-07-15 13:01:09 +010087 removeAllMessages();
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000088 stop(mCurrentWorkItem);
89 mHandlerThread.interrupt();
Narayan Kamath8d1fc242011-06-03 18:11:54 +010090 }
91
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000092 /*
93 * Atomically clear the queue of all messages.
94 */
95 private void removeAllMessages() {
96 mQueue.clear();
Narayan Kamath8d1fc242011-06-03 18:11:54 +010097 }
98
Narayan Kamath67ae6bc2011-11-30 14:51:00 +000099 /*
100 * Remove all messages that originate from a given calling app.
101 */
102 private void removeWorkItemsFor(Object callerIdentity) {
103 Iterator<PlaybackQueueItem> it = mQueue.iterator();
104
105 while (it.hasNext()) {
106 final PlaybackQueueItem item = it.next();
107 if (item.getCallerIdentity() == callerIdentity) {
108 it.remove();
109 }
110 }
Narayan Kamath8d1fc242011-06-03 18:11:54 +0100111 }
112
Narayan Kamath4924fe32011-06-09 11:35:13 +0100113 /*
114 * The MessageLoop is a handler like implementation that
115 * processes messages from a priority queue.
116 */
117 private final class MessageLoop implements Runnable {
118 @Override
119 public void run() {
120 while (true) {
Narayan Kamath67ae6bc2011-11-30 14:51:00 +0000121 PlaybackQueueItem item = null;
Narayan Kamath4924fe32011-06-09 11:35:13 +0100122 try {
Narayan Kamath67ae6bc2011-11-30 14:51:00 +0000123 item = mQueue.take();
Narayan Kamath4924fe32011-06-09 11:35:13 +0100124 } catch (InterruptedException ie) {
Narayan Kamath67ae6bc2011-11-30 14:51:00 +0000125 if (DBG) Log.d(TAG, "MessageLoop : Shutting down (interrupted)");
Narayan Kamath4924fe32011-06-09 11:35:13 +0100126 return;
127 }
128
Narayan Kamath67ae6bc2011-11-30 14:51:00 +0000129 // If stop() or stopForApp() are called between mQueue.take()
130 // returning and mCurrentWorkItem being set, the current work item
131 // will be run anyway.
Narayan Kamath4924fe32011-06-09 11:35:13 +0100132
Narayan Kamath67ae6bc2011-11-30 14:51:00 +0000133 mCurrentWorkItem = item;
134 item.run();
135 mCurrentWorkItem = null;
Narayan Kamath4924fe32011-06-09 11:35:13 +0100136 }
137 }
138 }
139
Narayan Kamath8d1fc242011-06-03 18:11:54 +0100140}