/** * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr) * Copyright (C) 2010 Robert B. Denny, Mesa, AZ, USA * This file is part of CSipSimple. * * CSipSimple 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. * If you own a pjsip commercial license you can also redistribute it * and/or modify it under the terms of the GNU Lesser General Public License * as an android library. * * CSipSimple 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 CSipSimple. If not, see <http://www.gnu.org/licenses/>. */ /** * This file contains relicensed code from Apache copyright of * Copyright (C) 2008 The Android Open Source Project */ package com.csipsimple.utils; import android.app.Activity; import android.content.Context; import android.media.AudioManager; import android.media.ToneGenerator; import android.os.Vibrator; import java.util.Timer; import java.util.TimerTask; public class DialingFeedback { /** The length of vibrate (haptic) feedback in milliseconds */ private static final int HAPTIC_LENGTH_MS = 50; /** The length of DTMF tones in milliseconds */ private static final int TONE_LENGTH_MS = 150; /** The DTMF tone volume relative to other sounds in the stream */ private static final int TONE_RELATIVE_VOLUME = 80; private boolean inCall; private int toneStream; private Activity context; private ToneGenerator toneGenerator = null; private Object toneGeneratorLock = new Object(); private Vibrator vibrator = null; private Timer toneTimer = null; private PreferencesWrapper prefsWrapper; private boolean dialPressTone = false; private boolean dialPressVibrate = false; private int ringerMode; public DialingFeedback(Activity context, boolean inCall) { this.context = context; this.inCall = inCall; toneStream = inCall ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_MUSIC; prefsWrapper = new PreferencesWrapper(context); } public void resume() { dialPressTone = prefsWrapper.dialPressTone(inCall); dialPressVibrate = prefsWrapper.dialPressVibrate(); if (dialPressTone) { // Create dialtone just for user feedback synchronized (toneGeneratorLock) { if (toneTimer == null) { toneTimer = new Timer("Dialtone-timer"); } if (toneGenerator == null) { try { toneGenerator = new ToneGenerator(toneStream, TONE_RELATIVE_VOLUME); // Allow user to control dialtone if (!inCall) { context.setVolumeControlStream(toneStream); } } catch (RuntimeException e) { // If impossible, nothing to do toneGenerator = null; } } } } else { toneTimer = null; toneGenerator = null; } //Create the vibrator if (dialPressVibrate) { if (vibrator == null) { vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); } } else { vibrator = null; } //Store the current ringer mode AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); ringerMode = am.getRingerMode(); } public void pause() { //Destroy dialtone synchronized (toneGeneratorLock) { if (toneGenerator != null) { toneGenerator.stopTone(); toneGenerator.release(); toneGenerator = null; } if(toneTimer != null) { toneTimer.cancel(); toneTimer.purge(); toneTimer = null; } } } /** * Tone play to be used when a button in dialpad * is pressed * @param tone The tone associated to the button */ public void giveFeedback(int tone) { switch (ringerMode) { case AudioManager.RINGER_MODE_NORMAL: if (dialPressVibrate) { vibrator.vibrate(HAPTIC_LENGTH_MS); } if (dialPressTone) { ThreadedTonePlay threadedTone = new ThreadedTonePlay(tone); threadedTone.start(); } break; case AudioManager.RINGER_MODE_VIBRATE: if (dialPressVibrate) { vibrator.vibrate(HAPTIC_LENGTH_MS); } break; case AudioManager.RINGER_MODE_SILENT: break; } } /** * Haptic vibration to be used when a button in dialpad * is long pressed for example. */ public void hapticFeedback() { if (dialPressVibrate && ringerMode != AudioManager.RINGER_MODE_SILENT) { vibrator.vibrate(HAPTIC_LENGTH_MS); } } class ThreadedTonePlay extends Thread { private final int tone; ThreadedTonePlay(int t){ tone = t; } @Override public void run() { synchronized (toneGeneratorLock) { if (toneGenerator == null) { return; } toneGenerator.stopTone(); toneGenerator.startTone(tone); toneTimer.schedule(new StopTimerTask(), TONE_LENGTH_MS); } } } class StopTimerTask extends TimerTask{ @Override public void run() { synchronized (toneGeneratorLock) { if (toneGenerator == null) { return; } toneGenerator.stopTone(); } } } }