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