1 /* 2 * Copyright (C) 2011 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 17 package com.android.inputmethod.deprecated.voice; 18 19 import android.content.Context; 20 import android.graphics.Bitmap; 21 import android.graphics.Bitmap.Config; 22 import android.graphics.Canvas; 23 import android.graphics.Paint; 24 import android.graphics.PorterDuff; 25 import android.graphics.PorterDuffXfermode; 26 import android.graphics.Rect; 27 import android.graphics.drawable.BitmapDrawable; 28 import android.graphics.drawable.Drawable; 29 import android.os.Handler; 30 import android.util.AttributeSet; 31 import android.widget.ImageView; 32 33 import com.android.inputmethod.latin.R; 34 35 /** 36 * A widget which shows the volume of audio using a microphone icon 37 */ 38 public class SoundIndicator extends ImageView { 39 @SuppressWarnings("unused") 40 private static final String TAG = "SoundIndicator"; 41 42 private static final float UP_SMOOTHING_FACTOR = 0.9f; 43 private static final float DOWN_SMOOTHING_FACTOR = 0.4f; 44 45 private static final float AUDIO_METER_MIN_DB = 7.0f; 46 private static final float AUDIO_METER_DB_RANGE = 20.0f; 47 48 private static final long FRAME_DELAY = 50; 49 50 private Bitmap mDrawingBuffer; 51 private Canvas mBufferCanvas; 52 private Bitmap mEdgeBitmap; 53 private float mLevel = 0.0f; 54 private Drawable mFrontDrawable; 55 private Paint mClearPaint; 56 private Paint mMultPaint; 57 private int mEdgeBitmapOffset; 58 59 private Handler mHandler; 60 61 private Runnable mDrawFrame = new Runnable() { 62 public void run() { 63 invalidate(); 64 mHandler.postDelayed(mDrawFrame, FRAME_DELAY); 65 } 66 }; 67 SoundIndicator(Context context)68 public SoundIndicator(Context context) { 69 this(context, null); 70 } 71 SoundIndicator(Context context, AttributeSet attrs)72 public SoundIndicator(Context context, AttributeSet attrs) { 73 super(context, attrs); 74 75 mFrontDrawable = getDrawable(); 76 BitmapDrawable edgeDrawable = 77 (BitmapDrawable) context.getResources().getDrawable(R.drawable.vs_popup_mic_edge); 78 mEdgeBitmap = edgeDrawable.getBitmap(); 79 mEdgeBitmapOffset = mEdgeBitmap.getHeight() / 2; 80 81 mDrawingBuffer = 82 Bitmap.createBitmap(mFrontDrawable.getIntrinsicWidth(), 83 mFrontDrawable.getIntrinsicHeight(), Config.ARGB_8888); 84 85 mBufferCanvas = new Canvas(mDrawingBuffer); 86 87 // Initialize Paints. 88 mClearPaint = new Paint(); 89 mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 90 91 mMultPaint = new Paint(); 92 mMultPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); 93 94 mHandler = new Handler(); 95 } 96 97 @Override onDraw(Canvas canvas)98 public void onDraw(Canvas canvas) { 99 //super.onDraw(canvas); 100 101 float w = getWidth(); 102 float h = getHeight(); 103 104 // Clear the buffer canvas 105 mBufferCanvas.drawRect(0, 0, w, h, mClearPaint); 106 107 // Set its clip so we don't draw the front image all the way to the top 108 Rect clip = new Rect(0, 109 (int) ((1.0 - mLevel) * (h + mEdgeBitmapOffset)) - mEdgeBitmapOffset, 110 (int) w, 111 (int) h); 112 113 mBufferCanvas.save(); 114 mBufferCanvas.clipRect(clip); 115 116 // Draw the front image 117 mFrontDrawable.setBounds(new Rect(0, 0, (int) w, (int) h)); 118 mFrontDrawable.draw(mBufferCanvas); 119 120 mBufferCanvas.restore(); 121 122 // Draw the edge image on top of the buffer image with a multiply mode 123 mBufferCanvas.drawBitmap(mEdgeBitmap, 0, clip.top, mMultPaint); 124 125 // Draw the buffer image (on top of the background image) 126 canvas.drawBitmap(mDrawingBuffer, 0, 0, null); 127 } 128 129 /** 130 * Sets the sound level 131 * 132 * @param rmsdB The level of the sound, in dB. 133 */ setRmsdB(float rmsdB)134 public void setRmsdB(float rmsdB) { 135 float level = ((rmsdB - AUDIO_METER_MIN_DB) / AUDIO_METER_DB_RANGE); 136 137 level = Math.min(Math.max(0.0f, level), 1.0f); 138 139 // We smooth towards the new level 140 if (level > mLevel) { 141 mLevel = (level - mLevel) * UP_SMOOTHING_FACTOR + mLevel; 142 } else { 143 mLevel = (level - mLevel) * DOWN_SMOOTHING_FACTOR + mLevel; 144 } 145 invalidate(); 146 } 147 start()148 public void start() { 149 mHandler.post(mDrawFrame); 150 } 151 stop()152 public void stop() { 153 mHandler.removeCallbacks(mDrawFrame); 154 } 155 } 156