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