Home | History | Annotate | Download | only in compat
      1 /*
      2  * Copyright (C) 2010 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  */
     16 package com.android.tts.compat;
     17 
     18 import android.database.Cursor;
     19 import android.net.Uri;
     20 import android.speech.tts.SynthesisCallback;
     21 import android.speech.tts.SynthesisRequest;
     22 import android.speech.tts.TextToSpeech;
     23 import android.speech.tts.TextToSpeechService;
     24 import android.util.Log;
     25 
     26 import java.io.File;
     27 
     28 public abstract class CompatTtsService extends TextToSpeechService {
     29 
     30     private static final boolean DBG = false;
     31     private static final String TAG = "CompatTtsService";
     32 
     33     private SynthProxy mNativeSynth = null;
     34 
     35     protected abstract String getSoFilename();
     36 
     37     @Override
     38     public void onCreate() {
     39         if (DBG) Log.d(TAG, "onCreate()");
     40 
     41         String soFilename = getSoFilename();
     42 
     43         if (mNativeSynth != null) {
     44             mNativeSynth.stopSync();
     45             mNativeSynth.shutdown();
     46             mNativeSynth = null;
     47         }
     48 
     49         // Load the engineConfig from the plugin if it has any special configuration
     50         // to be loaded. By convention, if an engine wants the TTS framework to pass
     51         // in any configuration, it must put it into its content provider which has the URI:
     52         // content://<packageName>.providers.SettingsProvider
     53         // That content provider must provide a Cursor which returns the String that
     54         // is to be passed back to the native .so file for the plugin when getString(0) is
     55         // called on it.
     56         // Note that the TTS framework does not care what this String data is: it is something
     57         // that comes from the engine plugin and is consumed only by the engine plugin itself.
     58         String engineConfig = "";
     59         Cursor c = getContentResolver().query(Uri.parse("content://" + getPackageName()
     60                 + ".providers.SettingsProvider"), null, null, null, null);
     61         if (c != null){
     62             c.moveToFirst();
     63             engineConfig = c.getString(0);
     64             c.close();
     65         }
     66         mNativeSynth = new SynthProxy(soFilename, engineConfig);
     67 
     68         // mNativeSynth is used by TextToSpeechService#onCreate so it must be set prior
     69         // to that call.
     70         // getContentResolver() is also moved prior to super.onCreate(), and it works
     71         // because the super method don't sets a field or value that affects getContentResolver();
     72         // (including the content resolver itself).
     73         super.onCreate();
     74     }
     75 
     76     @Override
     77     public void onDestroy() {
     78         if (DBG) Log.d(TAG, "onDestroy()");
     79         super.onDestroy();
     80 
     81         if (mNativeSynth != null) {
     82             mNativeSynth.shutdown();
     83         }
     84         mNativeSynth = null;
     85     }
     86 
     87     @Override
     88     protected String[] onGetLanguage() {
     89         if (mNativeSynth == null) return null;
     90         return mNativeSynth.getLanguage();
     91     }
     92 
     93     @Override
     94     protected int onIsLanguageAvailable(String lang, String country, String variant) {
     95         if (DBG) Log.d(TAG, "onIsLanguageAvailable(" + lang + "," + country + "," + variant + ")");
     96         if (mNativeSynth == null) return TextToSpeech.ERROR;
     97         return mNativeSynth.isLanguageAvailable(lang, country, variant);
     98     }
     99 
    100     @Override
    101     protected int onLoadLanguage(String lang, String country, String variant) {
    102         if (DBG) Log.d(TAG, "onLoadLanguage(" + lang + "," + country + "," + variant + ")");
    103         int result = onIsLanguageAvailable(lang, country, variant);
    104         if (result >= TextToSpeech.LANG_AVAILABLE) {
    105             mNativeSynth.setLanguage(lang, country, variant);
    106         }
    107 
    108         return result;
    109     }
    110 
    111     @Override
    112     protected void onSynthesizeText(SynthesisRequest request, SynthesisCallback callback) {
    113         if (mNativeSynth == null) {
    114             callback.error();
    115             return;
    116         }
    117 
    118         // Set language
    119         String lang = request.getLanguage();
    120         String country = request.getCountry();
    121         String variant = request.getVariant();
    122         if (mNativeSynth.setLanguage(lang, country, variant) != TextToSpeech.SUCCESS) {
    123             Log.e(TAG, "setLanguage(" + lang + "," + country + "," + variant + ") failed");
    124             callback.error();
    125             return;
    126         }
    127 
    128         // Set speech rate
    129         int speechRate = request.getSpeechRate();
    130         if (mNativeSynth.setSpeechRate(speechRate) != TextToSpeech.SUCCESS) {
    131             Log.e(TAG, "setSpeechRate(" + speechRate + ") failed");
    132             callback.error();
    133             return;
    134         }
    135 
    136         // Set speech
    137         int pitch = request.getPitch();
    138         if (mNativeSynth.setPitch(pitch) != TextToSpeech.SUCCESS) {
    139             Log.e(TAG, "setPitch(" + pitch + ") failed");
    140             callback.error();
    141             return;
    142         }
    143 
    144         // Synthesize
    145         if (mNativeSynth.speak(request, callback) != TextToSpeech.SUCCESS) {
    146             callback.error();
    147             return;
    148         }
    149     }
    150 
    151     @Override
    152     protected void onStop() {
    153         if (DBG) Log.d(TAG, "onStop()");
    154         if (mNativeSynth == null) return;
    155         mNativeSynth.stop();
    156     }
    157 
    158 }
    159