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
17package com.android.car.radio;
18
19import android.content.Context;
20import android.media.session.PlaybackState;
21import android.text.TextUtils;
22import android.view.View;
23import android.view.ViewStub;
24import android.widget.ImageView;
25import android.widget.TextView;
26
27/**
28 * Controller that controls the appearance state of various UI elements in the radio.
29 */
30public class RadioDisplayController {
31    private final Context mContext;
32
33    private TextView mChannelBand;
34    private TextView mChannelNumber;
35
36    private TextView mCurrentSongTitleAndArtist;
37    private TextView mCurrentStation;
38
39    private ImageView mBackwardSeekButton;
40    private ImageView mForwardSeekButton;
41
42    private PlayPauseButton mPlayButton;
43    private PlayPauseButton mPresetPlayButton;
44
45    private ImageView mPresetsListButton;
46    private ImageView mAddPresetsButton;
47
48    public RadioDisplayController(Context context) {
49        mContext = context;
50    }
51
52    public void initialize(View container) {
53        // Note that the band and channel number can exist without the stub
54        // single_channel_view_stub. Refer to setSingleChannelDisplay() for more information.
55        mChannelBand = container.findViewById(R.id.radio_station_band);
56        mChannelNumber = container.findViewById(R.id.radio_station_channel);
57
58        mCurrentSongTitleAndArtist = container.findViewById(R.id.radio_station_song_artist);
59        mCurrentStation = container.findViewById(R.id.radio_station_name);
60
61        mBackwardSeekButton = container.findViewById(R.id.radio_back_button);
62        mForwardSeekButton = container.findViewById(R.id.radio_forward_button);
63
64        mPlayButton = container.findViewById(R.id.radio_play_button);
65        mPresetPlayButton = container.findViewById(R.id.preset_radio_play_button);
66
67        mPresetsListButton = container.findViewById(R.id.radio_presets_list);
68        mAddPresetsButton = container.findViewById(R.id.radio_add_presets_button);
69    }
70
71    /**
72     * Sets this radio controller to display with a single box representing the current radio
73     * station.
74     */
75    public void setSingleChannelDisplay(View container) {
76        ViewStub stub = container.findViewById(R.id.single_channel_view_stub);
77
78        if (stub != null) {
79            container = stub.inflate();
80        }
81
82        // Update references to the band and channel number.
83        mChannelBand = container.findViewById(R.id.radio_station_band);
84        mChannelNumber = container.findViewById(R.id.radio_station_channel);
85    }
86
87    /**
88     * Set whether or not the buttons controlled by this controller are enabled. If {@code false}
89     * is passed to this method, then no {@link View.OnClickListener}s will be
90     * triggered when the buttons are pressed. In addition, the look of the button wil be updated
91     * to reflect their disabled state.
92     */
93    public void setEnabled(boolean enabled) {
94        // Color the buttons so that they are grey in appearance if they are disabled.
95        int tint = enabled
96                ? mContext.getColor(R.color.car_radio_control_button)
97                : mContext.getColor(R.color.car_radio_control_button_disabled);
98
99        if (mPlayButton != null) {
100            // No need to tint the play button because its drawable already contains a disabled
101            // state.
102            mPlayButton.setEnabled(enabled);
103        }
104
105        if (mPresetPlayButton != null) {
106            // No need to tint the play button because its drawable already contains a disabled
107            // state.
108            mPresetPlayButton.setEnabled(enabled);
109        }
110
111        if (mForwardSeekButton != null) {
112            mForwardSeekButton.setEnabled(enabled);
113            mForwardSeekButton.setColorFilter(tint);
114        }
115
116        if (mBackwardSeekButton != null) {
117            mBackwardSeekButton.setEnabled(enabled);
118            mBackwardSeekButton.setColorFilter(tint);
119        }
120
121        if (mPresetsListButton != null) {
122            mPresetsListButton.setEnabled(enabled);
123            mPresetsListButton.setColorFilter(tint);
124        }
125
126        if (mAddPresetsButton != null) {
127            mAddPresetsButton.setEnabled(enabled);
128            mAddPresetsButton.setColorFilter(tint);
129        }
130    }
131
132    /**
133     * Sets the {@link android.view.View.OnClickListener} for the backwards seek button.
134     */
135    public void setBackwardSeekButtonListener(View.OnClickListener listener) {
136        if (mBackwardSeekButton != null) {
137            mBackwardSeekButton.setOnClickListener(listener);
138        }
139    }
140
141    /**
142     * Sets the {@link android.view.View.OnClickListener} for the forward seek button.
143     */
144    public void setForwardSeekButtonListener(View.OnClickListener listener) {
145        if (mForwardSeekButton != null) {
146            mForwardSeekButton.setOnClickListener(listener);
147        }
148    }
149
150    /**
151     * Sets the {@link android.view.View.OnClickListener} for the play button. Clicking on this
152     * button should toggle the radio from muted to un-muted.
153     */
154    public void setPlayButtonListener(View.OnClickListener listener) {
155        if (mPlayButton != null) {
156            mPlayButton.setOnClickListener(listener);
157        }
158
159        if (mPresetPlayButton != null) {
160            mPresetPlayButton.setOnClickListener(listener);
161        }
162    }
163
164    /**
165     * Sets the {@link android.view.View.OnClickListener} for the button that will add the current
166     * radio station to a list of stored presets.
167     */
168    public void setAddPresetButtonListener(View.OnClickListener listener) {
169        if (mAddPresetsButton != null) {
170            mAddPresetsButton.setOnClickListener(listener);
171        }
172    }
173
174    /**
175     * Sets the current radio channel (e.g. 88.5).
176     */
177    public void setChannelNumber(String channel) {
178        if (mChannelNumber != null) {
179            mChannelNumber.setText(channel);
180        }
181    }
182
183    /**
184     * Sets the radio channel band (e.g. FM).
185     */
186    public void setChannelBand(String channelBand) {
187        if (mChannelBand != null) {
188            mChannelBand.setText(channelBand);
189            mChannelBand.setVisibility(
190                    !TextUtils.isEmpty(channelBand) ? View.VISIBLE : View.GONE);
191        }
192    }
193
194    /**
195     * Sets the title of the currently playing song.
196     */
197    public void setCurrentSongTitleAndArtist(String songTitle, String songArtist) {
198        if (mCurrentSongTitleAndArtist != null) {
199            boolean isTitleEmpty = TextUtils.isEmpty(songTitle);
200            boolean isArtistEmpty = TextUtils.isEmpty(songArtist);
201            String titleAndArtist = null;
202            if (!isTitleEmpty) {
203                titleAndArtist = songTitle.trim();
204                if (!isArtistEmpty) {
205                    titleAndArtist += '\u2014' + songArtist.trim();
206                }
207            } else if (!isArtistEmpty) {
208                titleAndArtist = songArtist.trim();
209            }
210            mCurrentSongTitleAndArtist.setText(titleAndArtist);
211            mCurrentSongTitleAndArtist.setVisibility(
212                    (isTitleEmpty && isArtistEmpty)? View.INVISIBLE : View.VISIBLE);
213        }
214    }
215
216    /**
217     * Sets the artist(s) of the currently playing song or current radio station information
218     * (e.g. KOIT).
219     */
220    public void setCurrentStation(String stationName) {
221        if (mCurrentStation != null) {
222            boolean isEmpty = TextUtils.isEmpty(stationName);
223            mCurrentStation.setText(isEmpty ? null : stationName.trim());
224            mCurrentStation.setVisibility(isEmpty ? View.INVISIBLE : View.VISIBLE);
225        }
226    }
227
228    /**
229     * Sets the current state of the play button. If the given {@code muted} value is {@code true},
230     * then the button display a play icon. If {@code false}, then the button will display a
231     * pause icon.
232     */
233    public void setPlayPauseButtonState(boolean muted) {
234        if (mPlayButton != null) {
235            mPlayButton.setPlayState(muted
236                    ? PlaybackState.STATE_PAUSED : PlaybackState.STATE_PLAYING);
237            mPlayButton.refreshDrawableState();
238        }
239
240        if (mPresetPlayButton != null) {
241            mPresetPlayButton.setPlayState(muted
242                    ? PlaybackState.STATE_PAUSED : PlaybackState.STATE_PLAYING);
243            mPresetPlayButton.refreshDrawableState();
244        }
245    }
246
247    /**
248     * Sets whether or not the current channel that is playing is a preset. If it is, then the
249     * icon in {@link #mPresetsListButton} will be updatd to reflect this state.
250     */
251    public void setChannelIsPreset(boolean isPreset) {
252        if (mAddPresetsButton != null) {
253            mAddPresetsButton.setImageResource(isPreset
254                    ? R.drawable.ic_star_filled
255                    : R.drawable.ic_star_empty);
256        }
257    }
258}
259