1/*
2 * Copyright (C) 2014 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.settings.notification;
18
19import android.content.ContentResolver;
20import android.content.Context;
21import android.media.AudioManager;
22import android.net.Uri;
23import android.preference.PreferenceManager;
24import android.preference.SeekBarPreference;
25import android.preference.SeekBarVolumizer;
26import android.util.AttributeSet;
27import android.util.Log;
28import android.view.View;
29import android.widget.ImageView;
30import android.widget.SeekBar;
31
32import com.android.settings.R;
33
34/** A slider preference that directly controls an audio stream volume (no dialog) **/
35public class VolumeSeekBarPreference extends SeekBarPreference
36        implements PreferenceManager.OnActivityStopListener {
37    private static final String TAG = "VolumeSeekBarPreference";
38
39    private int mStream;
40    private SeekBar mSeekBar;
41    private SeekBarVolumizer mVolumizer;
42    private Callback mCallback;
43    private ImageView mIconView;
44
45    public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
46            int defStyleRes) {
47        super(context, attrs, defStyleAttr, defStyleRes);
48    }
49
50    public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
51        this(context, attrs, defStyleAttr, 0);
52    }
53
54    public VolumeSeekBarPreference(Context context, AttributeSet attrs) {
55        this(context, attrs, 0);
56    }
57
58    public VolumeSeekBarPreference(Context context) {
59        this(context, null);
60    }
61
62    public void setStream(int stream) {
63        mStream = stream;
64    }
65
66    public void setCallback(Callback callback) {
67        mCallback = callback;
68    }
69
70    @Override
71    public void onActivityStop() {
72        if (mVolumizer != null) {
73            mVolumizer.stop();
74        }
75    }
76
77    @Override
78    protected void onBindView(View view) {
79        super.onBindView(view);
80        if (mStream == 0) {
81            Log.w(TAG, "No stream found, not binding volumizer");
82            return;
83        }
84        getPreferenceManager().registerOnActivityStopListener(this);
85        final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
86        if (seekBar == mSeekBar) return;
87        mSeekBar = seekBar;
88        final SeekBarVolumizer.Callback sbvc = new SeekBarVolumizer.Callback() {
89            @Override
90            public void onSampleStarting(SeekBarVolumizer sbv) {
91                if (mCallback != null) {
92                    mCallback.onSampleStarting(sbv);
93                }
94            }
95        };
96        final Uri sampleUri = mStream == AudioManager.STREAM_MUSIC ? getMediaVolumeUri() : null;
97        if (mVolumizer == null) {
98            mVolumizer = new SeekBarVolumizer(getContext(), mStream, sampleUri, sbvc) {
99                // we need to piggyback on SBV's SeekBar listener to update our icon
100                @Override
101                public void onProgressChanged(SeekBar seekBar, int progress,
102                        boolean fromTouch) {
103                    super.onProgressChanged(seekBar, progress, fromTouch);
104                    mCallback.onStreamValueChanged(mStream, progress);
105                }
106            };
107        }
108        mVolumizer.setSeekBar(mSeekBar);
109        mIconView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
110        mCallback.onStreamValueChanged(mStream, mSeekBar.getProgress());
111    }
112
113    // during initialization, this preference is the SeekBar listener
114    @Override
115    public void onProgressChanged(SeekBar seekBar, int progress,
116            boolean fromTouch) {
117        super.onProgressChanged(seekBar, progress, fromTouch);
118        mCallback.onStreamValueChanged(mStream, progress);
119    }
120
121    public void showIcon(int resId) {
122        // Instead of using setIcon, which will trigger listeners, this just decorates the
123        // preference temporarily with a new icon.
124        if (mIconView != null) {
125            mIconView.setImageResource(resId);
126        }
127    }
128
129    private Uri getMediaVolumeUri() {
130        return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
131                + getContext().getPackageName()
132                + "/" + R.raw.media_volume);
133    }
134
135    public interface Callback {
136        void onSampleStarting(SeekBarVolumizer sbv);
137        void onStreamValueChanged(int stream, int progress);
138    }
139}
140