Mercurial > hg > ccmiandroid
view src/uk/ac/qmul/eecs/ccmi/accessibility/AccessibilityService.java @ 0:e0ee6ac3a45f
first import
author | Fiore Martin <fiore@eecs.qmul.ac.uk> |
---|---|
date | Thu, 13 Dec 2012 20:00:21 +0000 |
parents | |
children |
line wrap: on
line source
/* CCmI Diagram Editor for Android Copyright (C) 2012 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package uk.ac.qmul.eecs.ccmi.accessibility; import java.util.EnumMap; import java.util.Locale; import uk.ac.qmul.eecs.ccmi.activities.R; import android.content.Context; import android.media.AudioManager; import android.media.SoundPool; import android.os.Vibrator; import android.speech.tts.TextToSpeech; import android.util.Log; /** * Encloses all the services needed to implement a custom accessibility system. Text-to-speech synthesis, sound and * device vibration. * */ public class AccessibilityService { private static final long VIBRATE_TIME = 200; private static final float SPEECH_RATE = 2.0f; private TextToSpeech tts; private SoundPool soundPool; private AudioManager audioManager; private Vibrator vibrator; private Context context; private EnumMap<SoundEvent,Integer> soundIDs; private boolean soundLoaded; /** * * A list of events that have a sound associated. The sounds are built in and cannot be modified. * * */ public enum SoundEvent { V_CANCEL, V_COLLAPSE, V_DRAG, V_EDITING_MODE, V_ENDOFLIST, V_ERROR, V_EXPAND, V_HOOK_OFF, V_HOOK_ON, V_JUMP, V_MAGNET_OFF, V_MAGNET_ON, V_OK } private static AccessibilityService singleton; /** * Creates an instance of {@code AccessibilityService}. It implements the singleton pattern, therefore * successive calls to this method will always return the same object. * * @param context The context to use. Usually your {@code Application} or {@code Activity} object. * * @return a singleton instance of {@code AccessibilityService} */ public static AccessibilityService getInstance(Context context){ if(singleton == null){ singleton = new AccessibilityService(context); } return singleton; } /** * Constructs a new {@code AccessibilityService}. * * @param context The current context */ public AccessibilityService(Context context){ soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0); this.context = context; audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); soundIDs = new EnumMap<SoundEvent,Integer>(SoundEvent.class); tts = new TextToSpeech(context, new TextToSpeech.OnInitListener(){ @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { int result = tts.setLanguage(Locale.UK); if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) { Log.w("TEXT TO SPEECH", "Text to Speech UK language not supported"); } } } }); tts.setSpeechRate(SPEECH_RATE); vibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); } /** * Loads the built in sound library. This method must be called before any call to * {@code playSound} or {@code stopSound}. */ public void loadSounds(){ if(soundLoaded) return; soundIDs.put(SoundEvent.V_CANCEL,soundPool.load(context, R.raw.cancel, 1)); soundIDs.put(SoundEvent.V_COLLAPSE,soundPool.load(context, R.raw.collapse, 1)); soundIDs.put(SoundEvent.V_EXPAND,soundPool.load(context, R.raw.expand, 1)); soundIDs.put(SoundEvent.V_ENDOFLIST,soundPool.load(context, R.raw.endoflist, 1)); soundIDs.put(SoundEvent.V_OK,soundPool.load(context, R.raw.ok, 1)); soundIDs.put(SoundEvent.V_DRAG,soundPool.load(context, R.raw.drag, 1)); soundIDs.put(SoundEvent.V_EDITING_MODE,soundPool.load(context, R.raw.editingmode, 1)); soundIDs.put(SoundEvent.V_ERROR,soundPool.load(context, R.raw.error, 1)); soundIDs.put(SoundEvent.V_HOOK_OFF,soundPool.load(context, R.raw.hookoff, 1)); soundIDs.put(SoundEvent.V_HOOK_ON,soundPool.load(context, R.raw.hookon, 1)); soundIDs.put(SoundEvent.V_JUMP,soundPool.load(context, R.raw.jump, 1)); soundIDs.put(SoundEvent.V_MAGNET_OFF,soundPool.load(context, R.raw.magnetoff, 1)); soundLoaded = true; } /** * Plays the sound associated to a {@code SoundEvent}. * * @param event the event to play the sound of * @param loop whether to play the sound in a continuous loop or not */ public void playSound(SoundEvent event, boolean loop){ if(!soundLoaded) throw new IllegalStateException("loadSounds() must be called before any call to playSound"); float streamVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); streamVolume = streamVolume / audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); soundPool.play(soundIDs.get(event), streamVolume, streamVolume, 1, loop ? -1 : 0, 1f); } /** * Plays the sound associated to a {@code SoundEvent} once. This call is equivalent to * {@code playSound(event,false)}. * * @param event the event to play the sound of */ public void playSound(SoundEvent event){ playSound(event,false); } /** * Stop all the sounds being played at the moment of the call. Useful to stop a sound that is looping * after a call to {@code playSound(event,true)}. */ public void stopSound(){ if(!soundLoaded) throw new IllegalStateException("loadSounds() must be called before any call to pauseSound"); soundPool.autoPause(); } /** * Utters a text via android text to speech synthesizer * * @param text the string to be uttered **/ public void speak(String text){ tts.speak(text, TextToSpeech.QUEUE_FLUSH, null); } /** * Make the device vibrate */ public void vibrate(){ vibrator.vibrate(VIBRATE_TIME); } /** * Dispose the resources allocated during initialization. To be called when the class * is no longer needed by client classes. */ public void dispose(){ /* dispose sound */ for(SoundEvent evt : soundIDs.keySet()){ soundPool.unload(soundIDs.get(evt)); } /* dispose tts */ if(tts != null){ tts.stop(); tts.shutdown(); } } }