1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/*
2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project
3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License");
5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License.
6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at
7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *      http://www.apache.org/licenses/LICENSE-2.0
9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software
11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS,
12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and
14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License.
15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.ui;
17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.animation.ObjectAnimator;
19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.animation.TimeAnimator;
20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.animation.TimeAnimator.TimeListener;
21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context;
22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.drawable.ClipDrawable;
23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.drawable.Drawable;
24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.os.SystemClock;
25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.util.AttributeSet;
26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.Gravity;
27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.ProgressBar;
28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/**
30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Shows a styled progress bar that is synchronized with the playback state of an audio attachment.
31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class AudioPlaybackProgressBar extends ProgressBar implements PlaybackStateView {
33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private long mDurationInMillis;
34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private final TimeAnimator mUpdateAnimator;
35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private long mCumulativeTime = 0;
36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private long mCurrentPlayStartTime = 0;
37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private boolean mIncoming = false;
38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public AudioPlaybackProgressBar(final Context context, final AttributeSet attrs) {
40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super(context, attrs);
41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mUpdateAnimator = new TimeAnimator();
43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mUpdateAnimator.setRepeatCount(ObjectAnimator.INFINITE);
44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mUpdateAnimator.setTimeListener(new TimeListener() {
45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            @Override
46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            public void onTimeUpdate(final TimeAnimator animation, final long totalTime,
47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    final long deltaTime) {
48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                int progress = 0;
49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (mDurationInMillis > 0) {
50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    progress = (int) (((mCumulativeTime + SystemClock.elapsedRealtime() -
51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            mCurrentPlayStartTime) * 1.0f / mDurationInMillis) * 100);
52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    progress = Math.max(Math.min(progress, 100), 0);
53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                setProgress(progress);
55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        });
57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        updateAppearance();
58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Sets the duration of the audio that's being played, in milliseconds.
62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void setDuration(final long durationInMillis) {
64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mDurationInMillis = durationInMillis;
65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void restart() {
69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        reset();
70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        resume();
71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void reset() {
75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        stopUpdateTicks();
76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        setProgress(0);
77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mCumulativeTime = 0;
78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mCurrentPlayStartTime = 0;
79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void resume() {
83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mCurrentPlayStartTime = SystemClock.elapsedRealtime();
84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        startUpdateTicks();
85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void pause() {
89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mCumulativeTime += SystemClock.elapsedRealtime() - mCurrentPlayStartTime;
90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        stopUpdateTicks();
91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private void startUpdateTicks() {
94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (!mUpdateAnimator.isStarted()) {
95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mUpdateAnimator.start();
96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private void stopUpdateTicks() {
100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mUpdateAnimator.isStarted()) {
101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mUpdateAnimator.end();
102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private void updateAppearance() {
106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final Drawable drawable =
107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                ConversationDrawables.get().getAudioProgressDrawable(mIncoming);
108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final ClipDrawable clipDrawable = new ClipDrawable(drawable, Gravity.START,
109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                ClipDrawable.HORIZONTAL);
110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        setProgressDrawable(clipDrawable);
111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        setBackground(ConversationDrawables.get()
112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                .getAudioProgressBackgroundDrawable(mIncoming));
113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void setVisualStyle(final boolean incoming) {
116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mIncoming != incoming) {
117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mIncoming = incoming;
118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            updateAppearance();
119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd}
122