package me.barrasso.android.volume.popup;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.provider.Settings;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.text.TextUtils;
import android.util.Pair;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import me.barrasso.android.volume.R;
import me.barrasso.android.volume.VolumeAccessibilityService;
import me.barrasso.android.volume.media.StreamResources;
import me.barrasso.android.volume.media.VolumePanelInfo;
import me.barrasso.android.volume.ui.transition.TransitionCompat;
import me.barrasso.android.volume.utils.VolumeManager;
import static me.barrasso.android.volume.LogUtils.LOGD;
import static me.barrasso.android.volume.LogUtils.LOGE;
import static me.barrasso.android.volume.LogUtils.LOGI;
/**
* Blackberry style music/ volume_3 panel.
*/
public final class BlackberryVolumePanel extends VolumePanel {
public static final String TAG = BlackberryVolumePanel.class.getSimpleName();
public static final VolumePanelInfo<BlackberryVolumePanel> VOLUME_PANEL_INFO =
new VolumePanelInfo<BlackberryVolumePanel>(BlackberryVolumePanel.class);
public static int[] iconForStream(StreamResources res) {
switch (res) {
case NotificationStream:
return new int[] { R.drawable.ic_bb_notification, R.drawable.ic_bb_notification_mute };
case RingerStream:
case VoiceStream:
return new int[] { R.drawable.ic_bb_phone, R.drawable.ic_bb_phone_mute };
default:
return new int[] { R.drawable.ic_bb_speaker, R.drawable.ic_bb_speaker_mute };
}
}
public BlackberryVolumePanel(PopupWindowManager pWindowManager) {
super(pWindowManager);
}
private TransitionCompat transition;
ImageView albumArt;
ViewGroup albumArtContainer, mediaContainer;
TextView artist;
TextView song;
ImageView icon;
TextView streamName;
ProgressBar seekBar;
ViewGroup root, musicPanel;
ImageButton playPause, mBtnNext, mBtnPrev;
View divider;
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public void onCreate() {
super.onCreate();
Context context = getContext();
transition = TransitionCompat.get();
LayoutInflater inflater = LayoutInflater.from(context);
root = (ViewGroup) inflater.inflate(R.layout.bb_volume_adjust, null);
seekBar = (ProgressBar) root.findViewById(android.R.id.progress);
icon = (ImageView) root.findViewById(R.id.stream_icon);
divider = root.findViewById(R.id.divider);
streamName = (TextView) root.findViewById(R.id.streamName);
mediaContainer = (ViewGroup) root.findViewById(R.id.media_container);
albumArtContainer = (ViewGroup) root.findViewById(R.id.album_art_container);
albumArt = (ImageView) root.findViewById(R.id.album_art);
albumArt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openMusic();
}
});
artist = (TextView) root.findViewById(R.id.track_artist);
song = (TextView) root.findViewById(R.id.track_song);
musicPanel = (ViewGroup) root.findViewById(R.id.music_panel);
attachPlaybackListeners(root, new MediaButtonClickListener());
playPause = (ImageButton) root.findViewById(R.id.media_play_pause);
mBtnNext = (ImageButton) root.findViewById(R.id.media_next);
mBtnPrev = (ImageButton) root.findViewById(R.id.media_previous);
setEnableMarquee(true);
// Make sure we don't seek!
seekBar.setOnTouchListener(noTouchListener);
// Launch settings if the stream icon is clicked.
icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (view.getId() == R.id.stream_icon) {
hide();
Intent volumeSettings = new Intent(Settings.ACTION_SOUND_SETTINGS);
startActivity(volumeSettings);
}
}
});
transition.beginDelayedTransition((ViewGroup) root.findViewById(R.id.slider_group));
mLayout = root;
}
/*package*/ void openMusic() {
if (mMusicActive) {
hide();
launchMusicApp();
}
}
/*package*/ void updatePlayState() {
playPause.setImageResource(((mMusicActive) ? R.drawable.ic_bb_pause : R.drawable.ic_bb_play));
}
@Override
public void setTertiaryColor(final int newColor) {
super.setTertiaryColor(newColor);
streamName.setTextColor(newColor);
song.setTextColor(newColor);
artist.setTextColor(newColor);
}
// Used to keep track if we're displaying album art.
protected boolean hasAlbumArt = false;
protected boolean hideMusicWithPanel = false;
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public void onPlayStateChanged(Pair<MediaMetadataCompat, PlaybackStateCompat> mediaInfo) {
if (!created) return;
super.onPlayStateChanged(mediaInfo);
LOGI(TAG, "onPlayStateChanged()");
// if (mMusicActive) transition.beginDelayedTransition(mediaContainer, TransitionCompat.KEY_AUDIO_TRANSITION);
// Update button visibility based on the transport flags.
/*if (null == info || info.mTransportControlFlags <= 0) {
mBtnNext.setVisibility(View.VISIBLE);
mBtnPrev.setVisibility(View.VISIBLE);
playPause.setVisibility(View.VISIBLE);
} else {
final int flags = info.mTransportControlFlags;
setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT);
setVisibilityBasedOnFlag(playPause, flags,
RemoteControlClient.FLAG_KEY_MEDIA_PLAY
| RemoteControlClient.FLAG_KEY_MEDIA_PAUSE
| RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
| RemoteControlClient.FLAG_KEY_MEDIA_STOP);
}*/
// If we have album art, use it!
if (mMusicActive) {
Bitmap albumArtBitmap = mediaInfo.first.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART);
if (null != albumArtBitmap) {
LOGI(TAG, "Loading artwork bitmap.");
albumArt.setImageAlpha(0xFF);
albumArt.setColorFilter(null);
albumArt.setImageBitmap(albumArtBitmap);
hasAlbumArt = true;
} else {
hasAlbumArt = false;
}
}
// Next, we'll try to display the app's icon.
if (mMusicActive && !hasAlbumArt && !TextUtils.isEmpty(musicPackageName)) {
Drawable appIcon = getAppIcon(musicPackageName);
if (null != appIcon) {
LOGI(TAG, "Loading app icon instead of album art.");
final int bbColor = getResources().getColor(R.color.bb_icons);
final ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
albumArt.setColorFilter(new ColorMatrixColorFilter(cm));
appIcon.setColorFilter(bbColor, PorterDuff.Mode.MULTIPLY);
albumArt.setImageAlpha(0xEF);
albumArt.setImageDrawable(appIcon);
hasAlbumArt = true;
} else {
hasAlbumArt = false;
}
}
if (!mMusicActive) hasAlbumArt = false;
albumArtContainer.setVisibility((hasAlbumArt) ? View.VISIBLE : View.GONE);
if (mMusicActive) setMusicPanelVisibility(View.VISIBLE);
if (!mMusicActive) {
hideMusicWithPanel = true;
}
updatePlayState();
String sTitle = mediaInfo.first.getString(MediaMetadataCompat.METADATA_KEY_TITLE);
String sArtist = mediaInfo.first.getString(MediaMetadataCompat.METADATA_KEY_ARTIST);
song.setText(sTitle);
artist.setText(sArtist);
}
protected Drawable getAppIcon(String packageName) {
PackageManager mPM = getContext().getPackageManager();
try {
return mPM.getApplicationIcon(packageName);
} catch (PackageManager.NameNotFoundException nfe) {
LOGE(TAG, "Couldn't get app icon for `" + packageName + "`", nfe);
return null;
}
}
@Override
public void screen(boolean on) {
super.screen(on);
setEnableMarquee(on);
}
private void setEnableMarquee(boolean enabled) {
LOGD(TAG, "setEnableMarquee(" + enabled + ')');
if (artist != null) artist.setSelected(enabled);
if (song != null) song.setSelected(enabled);
}
@Override public void onRingerModeChange(int ringerMode) { }
@Override public void onStreamVolumeChange(int streamType, int volume, int max) {
StreamResources resources = StreamResources.resourceForStreamType(streamType);
resources.setVolume(volume);
LOGI(TAG, "onStreamVolumeChange(" + VolumeManager.getStreamName(streamType) +
", " + volume + ", " + max + ", musicActive=" + mMusicActive + ")");
resources.setVolume(volume);
LayerDrawable layer = (LayerDrawable) seekBar.getProgressDrawable();
layer.findDrawableByLayerId(android.R.id.progress).mutate().setColorFilter(color, PorterDuff.Mode.MULTIPLY);
updateIcon(resources);
seekBar.setMax(max);
seekBar.setProgress(volume);
streamName.setText(resources.getDescRes());
seekBar.setTag(resources);
setMusicPanelVisibility((mMusicActive) ? View.VISIBLE : View.GONE);
show();
}
protected void updateIcon(StreamResources sr) {
LOGI(TAG, "updateIcon(" + VolumeManager.getStreamName(sr.getStreamType()) + ")");
int[] icons = iconForStream(sr);
int iconRes = ((sr.getVolume() <= 0) ? icons[1] : icons[0]);
icon.setImageResource(iconRes);
}
@Override
public void show() {
// Don't show the music panel if we're in the music app.
if (!TextUtils.isEmpty(musicPackageName) && !TextUtils.isEmpty(mCurrentPackage)) {
if (mCurrentPackage.equals(musicPackageName)) {
setMusicPanelVisibility(View.GONE);
} else if (mMusicActive) {
setMusicPanelVisibility(View.VISIBLE);
}
}
super.show();
}
@Override public void onVisibilityChanged(int visibility) {
LOGI(TAG, "onVisibilityChanged(" + visibility + ')');
super.onVisibilityChanged(visibility);
switch (visibility) {
case View.GONE:
if (hideMusicWithPanel) {
hideMusicWithPanel = false;
setMusicPanelVisibility(View.GONE);
}
setEnableMarquee(false);
break;
case View.VISIBLE:
setEnableMarquee(true);
break;
}
}
protected void setMusicPanelVisibility(int visibility) {
LOGI(TAG, "setMusicPanelVisibility(" + visibility + ')');
mediaContainer.setVisibility(visibility);
divider.setVisibility(visibility);
mediaContainer.requestLayout();
mediaContainer.invalidate();
}
@SuppressWarnings("unused")
@Subscribe
public void onPlaybackEvent(Pair<MediaMetadataCompat, PlaybackStateCompat> mediaInfo) {
// NOTE: This MUST be added to the final descendant of VolumePanel!
LOGI(TAG, "onPlaybackEvent()");
this.onPlayStateChanged(mediaInfo);
}
protected String mCurrentPackage;
@Override
public void onTopAppChanged(VolumeAccessibilityService.TopApp app) {
super.onTopAppChanged(app);
mCurrentPackage = app.mCurrentPackage;
}
@Override public boolean supportsMediaPlayback() { return true; }
@Override public boolean isInteractive() { return true; }
@Override public void onRotationChanged(final int rotation) {
super.onRotationChanged(rotation);
mWindowAttributes = getWindowLayoutParams();
onWindowAttributesChanged();
}
@Override public WindowManager.LayoutParams getWindowLayoutParams() {
int flags = (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED );
WindowManager.LayoutParams WPARAMS = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT,
0, 0, WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, flags, PixelFormat.TRANSLUCENT);
WPARAMS.windowAnimations = android.R.style.Animation_Dialog;
WPARAMS.packageName = getContext().getPackageName();
WPARAMS.setTitle(TAG);
WPARAMS.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
Resources res = getResources();
final int maxWidth = res.getDimensionPixelSize(R.dimen.notification_panel_width);
final int menuWidth = res.getDimensionPixelSize(R.dimen.max_menu_width);
final int screenWidth = getWindowWidth();
if (maxWidth <= 0 && (!res.getBoolean(R.bool.isTablet) && screenWidth < menuWidth)) {
WPARAMS.gravity = (Gravity.FILL_HORIZONTAL | Gravity.CENTER_VERTICAL);
} else {
WPARAMS.gravity = (Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
WPARAMS.width = (maxWidth <= 0) ? menuWidth : maxWidth;
}
WPARAMS.screenBrightness = WPARAMS.buttonBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
return WPARAMS;
}
}