/* * Copyright (C) 2010 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 com.android.tts.compat; import android.database.Cursor; import android.net.Uri; import android.speech.tts.SynthesisCallback; import android.speech.tts.SynthesisRequest; import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeechService; import android.util.Log; import java.io.File; public abstract class CompatTtsService extends TextToSpeechService { private static final boolean DBG = false; private static final String TAG = "CompatTtsService"; private SynthProxy mNativeSynth = null; protected abstract String getSoFilename(); @Override public void onCreate() { if (DBG) Log.d(TAG, "onCreate()"); super.onCreate(); String soFilename = getSoFilename(); File f = new File(soFilename); if (!f.exists()) { Log.e(TAG, "Invalid TTS Binary: " + soFilename); return; } if (mNativeSynth != null) { mNativeSynth.stopSync(); mNativeSynth.shutdown(); mNativeSynth = null; } // Load the engineConfig from the plugin if it has any special configuration // to be loaded. By convention, if an engine wants the TTS framework to pass // in any configuration, it must put it into its content provider which has the URI: // content://.providers.SettingsProvider // That content provider must provide a Cursor which returns the String that // is to be passed back to the native .so file for the plugin when getString(0) is // called on it. // Note that the TTS framework does not care what this String data is: it is something // that comes from the engine plugin and is consumed only by the engine plugin itself. String engineConfig = ""; Cursor c = getContentResolver().query(Uri.parse("content://" + getPackageName() + ".providers.SettingsProvider"), null, null, null, null); if (c != null){ c.moveToFirst(); engineConfig = c.getString(0); c.close(); } mNativeSynth = new SynthProxy(soFilename, engineConfig); } @Override public void onDestroy() { if (DBG) Log.d(TAG, "onDestroy()"); super.onDestroy(); if (mNativeSynth != null) { mNativeSynth.shutdown(); } mNativeSynth = null; } @Override protected String[] onGetLanguage() { if (mNativeSynth == null) return null; return mNativeSynth.getLanguage(); } @Override protected int onIsLanguageAvailable(String lang, String country, String variant) { if (DBG) Log.d(TAG, "onIsLanguageAvailable(" + lang + "," + country + "," + variant + ")"); if (mNativeSynth == null) return TextToSpeech.ERROR; return mNativeSynth.isLanguageAvailable(lang, country, variant); } @Override protected int onLoadLanguage(String lang, String country, String variant) { if (DBG) Log.d(TAG, "onLoadLanguage(" + lang + "," + country + "," + variant + ")"); int result = onIsLanguageAvailable(lang, country, variant); // TODO: actually load language return result; } @Override protected void onSynthesizeText(SynthesisRequest request, SynthesisCallback callback) { if (mNativeSynth == null) { callback.error(); return; } // Set language String lang = request.getLanguage(); String country = request.getCountry(); String variant = request.getVariant(); if (mNativeSynth.setLanguage(lang, country, variant) != TextToSpeech.SUCCESS) { Log.e(TAG, "setLanguage(" + lang + "," + country + "," + variant + ") failed"); callback.error(); return; } // Set speech rate int speechRate = request.getSpeechRate(); if (mNativeSynth.setSpeechRate(speechRate) != TextToSpeech.SUCCESS) { Log.e(TAG, "setSpeechRate(" + speechRate + ") failed"); callback.error(); return; } // Set speech int pitch = request.getPitch(); if (mNativeSynth.setPitch(pitch) != TextToSpeech.SUCCESS) { Log.e(TAG, "setPitch(" + pitch + ") failed"); callback.error(); return; } // Synthesize if (mNativeSynth.speak(request, callback) != TextToSpeech.SUCCESS) { callback.error(); return; } } @Override protected void onStop() { if (DBG) Log.d(TAG, "onStop()"); if (mNativeSynth == null) return; mNativeSynth.stop(); } }