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