1 /*
2  * Copyright (C) 2016 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 
17 package com.android.car.radio.widget;
18 
19 import android.content.Context;
20 import android.graphics.drawable.Drawable;
21 import android.media.session.PlaybackState;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.widget.ImageView;
25 
26 import androidx.annotation.Nullable;
27 
28 import com.android.car.radio.R;
29 import com.android.car.radio.util.Log;
30 
31 /**
32  * An {@link ImageView} that renders a play/pause button like a floating action button.
33  */
34 public class PlayPauseButton extends ImageView {
35     private static final String TAG = "BcRadioApp.PlayPauseBtn";
36 
37     private static final int[] STATE_PLAYING = {R.attr.state_playing};
38     private static final int[] STATE_PAUSED = {R.attr.state_paused};
39     private static final int[] STATE_DISABLED = {R.attr.state_disabled};
40 
41     @Nullable private Callback mCallback;
42 
43     @PlaybackState.State
44     private int mPlaybackState = PlaybackState.STATE_NONE;
45 
46     /**
47      * Callback for toggle event.
48      */
49     public interface Callback {
50         /**
51          * Called when the button was clicked.
52          *
53          * @param newPlayState New playback state to switch to.
54          */
onSwitchTo(@laybackState.State int newPlayState)55         void onSwitchTo(@PlaybackState.State int newPlayState);
56     }
57 
PlayPauseButton(Context context, AttributeSet attrs)58     public PlayPauseButton(Context context, AttributeSet attrs) {
59         super(context, attrs);
60         setOnClickListener(this::onClick);
61     }
62 
setCallback(@ullable Callback callback)63     public void setCallback(@Nullable Callback callback) {
64         mCallback = callback;
65     }
66 
67     /**
68      * Set the current play state of the button.
69      *
70      * @param playState Current playback state
71      */
setPlayState(@laybackState.State int playState)72     public void setPlayState(@PlaybackState.State int playState) {
73         Log.v(TAG, "New playback state: " + playState);
74         mPlaybackState = playState;
75     }
76 
onClick(View v)77     private void onClick(View v) {
78         Callback callback = mCallback;
79         if (callback == null) return;
80 
81         int switchTo;
82         switch(mPlaybackState) {
83             case PlaybackState.STATE_PLAYING:
84             case PlaybackState.STATE_CONNECTING:
85             case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
86             case PlaybackState.STATE_SKIPPING_TO_NEXT:
87                 switchTo = PlaybackState.STATE_PAUSED;
88                 break;
89             case PlaybackState.STATE_NONE:
90             case PlaybackState.STATE_PAUSED:
91             case PlaybackState.STATE_STOPPED:
92             case PlaybackState.STATE_ERROR:
93                 switchTo = PlaybackState.STATE_PLAYING;
94                 break;
95             default:
96                 Log.e(TAG, "Unsupported PlaybackState: " + mPlaybackState);
97                 return;
98         }
99 
100         Log.v(TAG, "Requesting switch to playback state: " + switchTo);
101         callback.onSwitchTo(switchTo);
102     }
103 
104     @Override
onCreateDrawableState(int extraSpace)105     public int[] onCreateDrawableState(int extraSpace) {
106         // + 1 so we can potentially add our custom PlayState
107         final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
108 
109         switch(mPlaybackState) {
110             case PlaybackState.STATE_PLAYING:
111                 mergeDrawableStates(drawableState, STATE_PLAYING);
112                 break;
113             case PlaybackState.STATE_STOPPED:
114             case PlaybackState.STATE_PAUSED:
115             case PlaybackState.STATE_CONNECTING:
116             case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
117             case PlaybackState.STATE_SKIPPING_TO_NEXT:
118                 mergeDrawableStates(drawableState, STATE_PAUSED);
119                 break;
120             case PlaybackState.STATE_NONE:
121             case PlaybackState.STATE_ERROR:
122                 mergeDrawableStates(drawableState, STATE_DISABLED);
123                 break;
124             default:
125                 Log.e(TAG, "Unsupported PlaybackState: " + mPlaybackState);
126         }
127 
128         Drawable background = getBackground();
129         if (background != null) background.setState(drawableState);
130 
131         return drawableState;
132     }
133 }
134