Remove BlockingMediaPlayer.
No need to spawn a new thread for every audio item sent to the TTS class. Change-Id: Ia52b0951f4249b0da460a5ecaff5dd11a6e5d5fc
This commit is contained in:
@@ -15,27 +15,91 @@
|
||||
*/
|
||||
package android.speech.tts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.ConditionVariable;
|
||||
import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
|
||||
import android.util.Log;
|
||||
|
||||
class AudioPlaybackQueueItem extends PlaybackQueueItem {
|
||||
private final BlockingMediaPlayer mPlayer;
|
||||
private static final String TAG = "TTS.AudioQueueItem";
|
||||
|
||||
private final Context mContext;
|
||||
private final Uri mUri;
|
||||
private final int mStreamType;
|
||||
|
||||
private final ConditionVariable mDone;
|
||||
private MediaPlayer mPlayer;
|
||||
private volatile boolean mFinished;
|
||||
|
||||
AudioPlaybackQueueItem(UtteranceProgressDispatcher dispatcher,
|
||||
Object callerIdentity, BlockingMediaPlayer player) {
|
||||
Object callerIdentity,
|
||||
Context context, Uri uri, int streamType) {
|
||||
super(dispatcher, callerIdentity);
|
||||
mPlayer = player;
|
||||
|
||||
mContext = context;
|
||||
mUri = uri;
|
||||
mStreamType = streamType;
|
||||
|
||||
mDone = new ConditionVariable();
|
||||
mPlayer = null;
|
||||
mFinished = false;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
getDispatcher().dispatchOnStart();
|
||||
// TODO: This can be avoided. Will be fixed later in this CL.
|
||||
mPlayer.startAndWait();
|
||||
getDispatcher().dispatchOnDone();
|
||||
final UtteranceProgressDispatcher dispatcher = getDispatcher();
|
||||
|
||||
dispatcher.dispatchOnStart();
|
||||
mPlayer = MediaPlayer.create(mContext, mUri);
|
||||
if (mPlayer == null) {
|
||||
dispatcher.dispatchOnError();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
|
||||
@Override
|
||||
public boolean onError(MediaPlayer mp, int what, int extra) {
|
||||
Log.w(TAG, "Audio playback error: " + what + ", " + extra);
|
||||
mDone.open();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mFinished = true;
|
||||
mDone.open();
|
||||
}
|
||||
});
|
||||
mPlayer.setAudioStreamType(mStreamType);
|
||||
mPlayer.start();
|
||||
mDone.block();
|
||||
finish();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Log.w(TAG, "MediaPlayer failed", ex);
|
||||
mDone.open();
|
||||
}
|
||||
|
||||
if (mFinished) {
|
||||
dispatcher.dispatchOnDone();
|
||||
} else {
|
||||
dispatcher.dispatchOnError();
|
||||
}
|
||||
}
|
||||
|
||||
private void finish() {
|
||||
try {
|
||||
mPlayer.stop();
|
||||
} catch (IllegalStateException ex) {
|
||||
// Do nothing, the player is already stopped
|
||||
}
|
||||
mPlayer.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
void stop(boolean isError) {
|
||||
mPlayer.stop();
|
||||
mDone.open();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package android.speech.tts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.ConditionVariable;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A media player that allows blocking to wait for it to finish.
|
||||
*/
|
||||
class BlockingMediaPlayer {
|
||||
|
||||
private static final String TAG = "BlockMediaPlayer";
|
||||
|
||||
private static final String MEDIA_PLAYER_THREAD_NAME = "TTS-MediaPlayer";
|
||||
|
||||
private final Context mContext;
|
||||
private final Uri mUri;
|
||||
private final int mStreamType;
|
||||
private final ConditionVariable mDone;
|
||||
// Only accessed on the Handler thread
|
||||
private MediaPlayer mPlayer;
|
||||
private volatile boolean mFinished;
|
||||
|
||||
/**
|
||||
* Creates a new blocking media player.
|
||||
* Creating a blocking media player is a cheap operation.
|
||||
*
|
||||
* @param context
|
||||
* @param uri
|
||||
* @param streamType
|
||||
*/
|
||||
public BlockingMediaPlayer(Context context, Uri uri, int streamType) {
|
||||
mContext = context;
|
||||
mUri = uri;
|
||||
mStreamType = streamType;
|
||||
mDone = new ConditionVariable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts playback and waits for it to finish.
|
||||
* Can be called from any thread.
|
||||
*
|
||||
* @return {@code true} if the playback finished normally, {@code false} if the playback
|
||||
* failed or {@link #stop} was called before the playback finished.
|
||||
*/
|
||||
public boolean startAndWait() {
|
||||
HandlerThread thread = new HandlerThread(MEDIA_PLAYER_THREAD_NAME);
|
||||
thread.start();
|
||||
Handler handler = new Handler(thread.getLooper());
|
||||
mFinished = false;
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startPlaying();
|
||||
}
|
||||
});
|
||||
mDone.block();
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
finish();
|
||||
// No new messages should get posted to the handler thread after this
|
||||
Looper.myLooper().quit();
|
||||
}
|
||||
});
|
||||
return mFinished;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops playback. Can be called multiple times.
|
||||
* Can be called from any thread.
|
||||
*/
|
||||
public void stop() {
|
||||
mDone.open();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts playback.
|
||||
* Called on the handler thread.
|
||||
*/
|
||||
private void startPlaying() {
|
||||
mPlayer = MediaPlayer.create(mContext, mUri);
|
||||
if (mPlayer == null) {
|
||||
Log.w(TAG, "Failed to play " + mUri);
|
||||
mDone.open();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
|
||||
@Override
|
||||
public boolean onError(MediaPlayer mp, int what, int extra) {
|
||||
Log.w(TAG, "Audio playback error: " + what + ", " + extra);
|
||||
mDone.open();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mFinished = true;
|
||||
mDone.open();
|
||||
}
|
||||
});
|
||||
mPlayer.setAudioStreamType(mStreamType);
|
||||
mPlayer.start();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Log.w(TAG, "MediaPlayer failed", ex);
|
||||
mDone.open();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops playback and release the media player.
|
||||
* Called on the handler thread.
|
||||
*/
|
||||
private void finish() {
|
||||
try {
|
||||
mPlayer.stop();
|
||||
} catch (IllegalStateException ex) {
|
||||
// Do nothing, the player is already stopped
|
||||
}
|
||||
mPlayer.release();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package android.speech.tts;
|
||||
|
||||
import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
|
||||
|
||||
abstract class MessageParams {
|
||||
static final int TYPE_SYNTHESIS = 1;
|
||||
static final int TYPE_AUDIO = 2;
|
||||
static final int TYPE_SILENCE = 3;
|
||||
|
||||
private final UtteranceProgressDispatcher mDispatcher;
|
||||
private final Object mCallerIdentity;
|
||||
|
||||
MessageParams(UtteranceProgressDispatcher dispatcher, Object callerIdentity) {
|
||||
mDispatcher = dispatcher;
|
||||
mCallerIdentity = callerIdentity;
|
||||
}
|
||||
|
||||
UtteranceProgressDispatcher getDispatcher() {
|
||||
return mDispatcher;
|
||||
}
|
||||
|
||||
Object getCallerIdentity() {
|
||||
return mCallerIdentity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MessageParams[" + hashCode() + "]";
|
||||
}
|
||||
|
||||
abstract int getType();
|
||||
}
|
||||
@@ -694,12 +694,12 @@ public abstract class TextToSpeechService extends Service {
|
||||
}
|
||||
|
||||
private class AudioSpeechItem extends SpeechItem {
|
||||
private final BlockingMediaPlayer mPlayer;
|
||||
|
||||
private final AudioPlaybackQueueItem mItem;
|
||||
public AudioSpeechItem(Object callerIdentity, int callerUid, int callerPid,
|
||||
Bundle params, Uri uri) {
|
||||
super(callerIdentity, callerUid, callerPid, params);
|
||||
mPlayer = new BlockingMediaPlayer(TextToSpeechService.this, uri, getStreamType());
|
||||
mItem = new AudioPlaybackQueueItem(this, getCallerIdentity(),
|
||||
TextToSpeechService.this, uri, getStreamType());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -709,8 +709,7 @@ public abstract class TextToSpeechService extends Service {
|
||||
|
||||
@Override
|
||||
protected int playImpl() {
|
||||
mAudioPlaybackHandler.enqueue(new AudioPlaybackQueueItem(
|
||||
this, getCallerIdentity(), mPlayer));
|
||||
mAudioPlaybackHandler.enqueue(mItem);
|
||||
return TextToSpeech.SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user