1bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen/* 2bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * Copyright (C) 2009 The Android Open Source Project 3bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * 4bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License"); 5bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * you may not use this file except in compliance with the License. 6bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * You may obtain a copy of the License at 7bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * 8bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * http://www.apache.org/licenses/LICENSE-2.0 9bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * 10bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * Unless required by applicable law or agreed to in writing, software 11bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS, 12bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * See the License for the specific language governing permissions and 14bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen * limitations under the License. 15bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen */ 16bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 17bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenpackage com.android.musicvis.vis1; 18bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 19f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurentimport com.android.musicvis.AudioCapture; 20f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 21bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.graphics.Canvas; 22bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.graphics.Paint; 23bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.graphics.Rect; 24bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.media.MediaPlayer; 25bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.os.Handler; 26bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.os.SystemClock; 27bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.service.wallpaper.WallpaperService; 28bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.util.Log; 29bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.view.MotionEvent; 30bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenimport android.view.SurfaceHolder; 31bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 32f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurentimport java.util.Arrays; 33f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent 34bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissenpublic class Visualization1 extends WallpaperService { 35bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 36bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private final Handler mHandler = new Handler(); 37bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 38bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 39bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void onCreate() { 40bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen super.onCreate(); 41bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 42bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 43bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 44bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void onDestroy() { 45bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen super.onDestroy(); 46bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 47bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 48bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 49bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public Engine onCreateEngine() { 50bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen return new CubeEngine(); 51bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 52bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 53bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen class CubeEngine extends Engine { 54bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 55bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private final Paint mPaint = new Paint(); 56bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private float mOffset; 57bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private float mTouchX = -1; 58bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private float mTouchY = -1; 59bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private long mStartTime; 60bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private int mWidth; 61bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private float mCenterX; 62bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private float mCenterY; 63f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent private AudioCapture mAudioCapture; 64f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent private int [] mVizData = new int[1024]; 65bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 66bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private final Runnable mDrawCube = new Runnable() { 67bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void run() { 68bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen drawFrame(); 69bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 70bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen }; 71bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen private boolean mVisible; 72bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 73bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen CubeEngine() { 74bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 75bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 76bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 77bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void onCreate(SurfaceHolder surfaceHolder) { 78bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen super.onCreate(surfaceHolder); 79bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 80bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen final Paint paint = mPaint; 81bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen paint.setColor(0xffffffff); 82bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen paint.setAntiAlias(true); 83bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen paint.setStrokeWidth(2); 84bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen paint.setStrokeCap(Paint.Cap.ROUND); 85bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen paint.setStyle(Paint.Style.STROKE); 86bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 87bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mStartTime = SystemClock.elapsedRealtime(); 88bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 89bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 90bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 91bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void onDestroy() { 92bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen super.onDestroy(); 93bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mHandler.removeCallbacks(mDrawCube); 94f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mAudioCapture != null) { 95f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mAudioCapture.stop(); 96f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mAudioCapture.release(); 97f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mAudioCapture = null; 98f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 99bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 100bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 101bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 102bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void onVisibilityChanged(boolean visible) { 103bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mVisible = visible; 104bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen if (visible) { 105f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mAudioCapture == null) { 106f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mAudioCapture = new AudioCapture(AudioCapture.TYPE_PCM, 1024); 107f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 108f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mAudioCapture.start(); 109bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen drawFrame(); 110bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } else { 111bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mHandler.removeCallbacks(mDrawCube); 112f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mAudioCapture != null) { 113f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mAudioCapture.stop(); 114f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mAudioCapture.release(); 115f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mAudioCapture = null; 116f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 117bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 118bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 119bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 120bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 121bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { 122bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen super.onSurfaceChanged(holder, format, width, height); 123bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mWidth = width; 124bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mCenterX = width/2.0f; 125bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mCenterY = height/2.0f; 126bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen drawFrame(); 127bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 128bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 129bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 130bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void onSurfaceCreated(SurfaceHolder holder) { 131bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen super.onSurfaceCreated(holder); 132bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 133bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 134bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 135bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void onSurfaceDestroyed(SurfaceHolder holder) { 136bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen super.onSurfaceDestroyed(holder); 137bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mVisible = false; 138bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mHandler.removeCallbacks(mDrawCube); 139bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 140bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 141bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 142af20a0f6ea8460d3d33b1d3dab405eeab3862c4cMarco Nelissen public void onOffsetsChanged(float xOffset, float yOffset, 143af20a0f6ea8460d3d33b1d3dab405eeab3862c4cMarco Nelissen float xStep, float yStep, int xPixels, int yPixels) { 144bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mOffset = xOffset; 145bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen drawFrame(); 146bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 147bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 148bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen @Override 149bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen public void onTouchEvent(MotionEvent event) { 150bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen // touch events don't actually work for wallpapers, but if they did, 151bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen // we'd be using them to draw a circle around the touch point 152bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen if (event.getAction() == MotionEvent.ACTION_MOVE) { 153bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mTouchX = event.getX(); 154bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mTouchY = event.getY(); 155bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } else { 156bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mTouchX = -1; 157bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mTouchY = -1; 158bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 159bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen super.onTouchEvent(event); 160bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 161bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 162bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen void drawFrame() { 163bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen final SurfaceHolder holder = getSurfaceHolder(); 164bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen final Rect frame = holder.getSurfaceFrame(); 165bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen final int width = frame.width(); 166bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen final int height = frame.height(); 167bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 168bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen Canvas c = null; 169bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen try { 170bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen c = holder.lockCanvas(); 171bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen if (c != null) { 172bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen // draw something 173bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen drawCube(c); 174bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen drawTouchPoint(c); 175bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 176bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } finally { 177bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen if (c != null) holder.unlockCanvasAndPost(c); 178bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 179bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 180bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mHandler.removeCallbacks(mDrawCube); 181bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen if (mVisible) { 182bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen mHandler.postDelayed(mDrawCube, 1000 / 25); 183bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 184bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 185bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 186bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen void drawCube(Canvas c) { 187bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen c.save(); 188bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen c.drawColor(0xff000000); 189bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 190f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent if (mAudioCapture != null) { 191f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent mVizData = mAudioCapture.getFormattedData(1, 1); 192f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } else { 193f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent Arrays.fill(mVizData, (int)0); 194f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent } 195bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 196bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen for (int i = 0; i < mWidth; i++) { 197f6b1bdc03ede37217da23aafeb55ab8635ccaaefEric Laurent c.drawPoint(i, mCenterY + mVizData[i], mPaint); 198bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 199bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen c.restore(); 200bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 201bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 202bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen void drawTouchPoint(Canvas c) { 203bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen if (mTouchX >=0 && mTouchY >= 0) { 204bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen c.drawCircle(mTouchX, mTouchY, 50, mPaint); 205bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 206bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 207bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen 208bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen } 209bb362b27cbcccf8f845e6ec83d0540b477fece08Marco Nelissen} 210