| /* |
| * 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.AudioManager; |
| import android.media.MediaPlayer; |
| import android.net.Uri; |
| import android.os.ConditionVariable; |
| import android.speech.tts.TextToSpeechService.AudioOutputParams; |
| import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher; |
| import android.util.Log; |
| |
| class AudioPlaybackQueueItem extends PlaybackQueueItem { |
| private static final String TAG = "TTS.AudioQueueItem"; |
| |
| private final Context mContext; |
| private final Uri mUri; |
| private final AudioOutputParams mAudioParams; |
| |
| private final ConditionVariable mDone; |
| private MediaPlayer mPlayer; |
| private volatile boolean mFinished; |
| |
| AudioPlaybackQueueItem(UtteranceProgressDispatcher dispatcher, |
| Object callerIdentity, |
| Context context, Uri uri, AudioOutputParams audioParams) { |
| super(dispatcher, callerIdentity); |
| |
| mContext = context; |
| mUri = uri; |
| mAudioParams = audioParams; |
| |
| mDone = new ConditionVariable(); |
| mPlayer = null; |
| mFinished = false; |
| } |
| @Override |
| public void run() { |
| final UtteranceProgressDispatcher dispatcher = getDispatcher(); |
| |
| dispatcher.dispatchOnStart(); |
| |
| int sessionId = mAudioParams.mSessionId; |
| mPlayer = MediaPlayer.create( |
| mContext, mUri, null, mAudioParams.mAudioAttributes, |
| sessionId > 0 ? sessionId : AudioManager.AUDIO_SESSION_ID_GENERATE); |
| if (mPlayer == null) { |
| dispatcher.dispatchOnError(TextToSpeech.ERROR_OUTPUT); |
| 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(); |
| } |
| }); |
| |
| setupVolume(mPlayer, mAudioParams.mVolume, mAudioParams.mPan); |
| mPlayer.start(); |
| mDone.block(); |
| finish(); |
| } catch (IllegalArgumentException ex) { |
| Log.w(TAG, "MediaPlayer failed", ex); |
| mDone.open(); |
| } |
| |
| if (mFinished) { |
| dispatcher.dispatchOnSuccess(); |
| } else { |
| dispatcher.dispatchOnStop(); |
| } |
| } |
| |
| private static void setupVolume(MediaPlayer player, float volume, float pan) { |
| final float vol = clip(volume, 0.0f, 1.0f); |
| final float panning = clip(pan, -1.0f, 1.0f); |
| |
| float volLeft = vol, volRight = vol; |
| if (panning > 0.0f) { |
| volLeft *= (1.0f - panning); |
| } else if (panning < 0.0f) { |
| volRight *= (1.0f + panning); |
| } |
| player.setVolume(volLeft, volRight); |
| } |
| |
| private static final float clip(float value, float min, float max) { |
| return value < min ? min : (value < max ? value : max); |
| } |
| |
| private void finish() { |
| try { |
| mPlayer.stop(); |
| } catch (IllegalStateException ex) { |
| // Do nothing, the player is already stopped |
| } |
| mPlayer.release(); |
| } |
| |
| @Override |
| void stop(int errorCode) { |
| mDone.open(); |
| } |
| } |