MediaRouteControllerDialog.java revision f4575634e9f3c2b61c2e6bceaeed6cabb378803f
111417b1cfde8f1749905f2d735623af9214148afJeff Brown/* 211417b1cfde8f1749905f2d735623af9214148afJeff Brown * Copyright (C) 2013 The Android Open Source Project 311417b1cfde8f1749905f2d735623af9214148afJeff Brown * 411417b1cfde8f1749905f2d735623af9214148afJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 511417b1cfde8f1749905f2d735623af9214148afJeff Brown * you may not use this file except in compliance with the License. 611417b1cfde8f1749905f2d735623af9214148afJeff Brown * You may obtain a copy of the License at 711417b1cfde8f1749905f2d735623af9214148afJeff Brown * 811417b1cfde8f1749905f2d735623af9214148afJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 911417b1cfde8f1749905f2d735623af9214148afJeff Brown * 1011417b1cfde8f1749905f2d735623af9214148afJeff Brown * Unless required by applicable law or agreed to in writing, software 1111417b1cfde8f1749905f2d735623af9214148afJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1211417b1cfde8f1749905f2d735623af9214148afJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1311417b1cfde8f1749905f2d735623af9214148afJeff Brown * See the License for the specific language governing permissions and 1411417b1cfde8f1749905f2d735623af9214148afJeff Brown * limitations under the License. 1511417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 1611417b1cfde8f1749905f2d735623af9214148afJeff Brown 1711417b1cfde8f1749905f2d735623af9214148afJeff Brownpackage android.support.v7.app; 1811417b1cfde8f1749905f2d735623af9214148afJeff Brown 19bfb90b6717bb46535d747aa50045a206965542d0Jae Seoimport static android.widget.SeekBar.OnSeekBarChangeListener; 20bfb90b6717bb46535d747aa50045a206965542d0Jae Seo 21005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.content.ContentResolver; 2211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.Context; 236051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.content.res.TypedArray; 24005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.Bitmap; 25005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.BitmapFactory; 2686a802c8d09983d8725cccf59217e65d3e0c6373Jae Seoimport android.graphics.PorterDuff; 2713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.graphics.drawable.BitmapDrawable; 282ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brownimport android.graphics.drawable.Drawable; 29005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.net.Uri; 30005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.os.AsyncTask; 31418c688351713e9349227262163eef752a8e7ce6Jae Seoimport android.os.Build; 3211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.os.Bundle; 3394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.os.RemoteException; 3494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaDescriptionCompat; 3594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaMetadataCompat; 3694be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaControllerCompat; 3794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaSessionCompat; 3894be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.PlaybackStateCompat; 39005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.support.v7.graphics.Palette; 4011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouteSelector; 4111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouter; 42418c688351713e9349227262163eef752a8e7ce6Jae Seoimport android.support.v7.media.SeekBarJellybean; 4311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.mediarouter.R; 4494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.text.TextUtils; 4513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.util.DisplayMetrics; 4694be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.util.Log; 4706991009e52024cbb3dde550988e06149e77a269Jae Seoimport android.util.TypedValue; 4811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.KeyEvent; 496051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.LayoutInflater; 5011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.View; 5140dd800ece983a94ea6a26a27481da50f489e7c8Jaewan Kimimport android.view.View.MeasureSpec; 526051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.ViewGroup; 536051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ArrayAdapter; 5411417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Button; 5511417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.FrameLayout; 5694be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageButton; 5794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageView; 58f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.LinearLayout; 596051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ListView; 607ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Limimport android.widget.RelativeLayout; 61f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.SeekBar; 6294be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.TextView; 6311417b1cfde8f1749905f2d735623af9214148afJeff Brown 64005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.BufferedInputStream; 65005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.IOException; 666051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport java.util.List; 67005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 6811417b1cfde8f1749905f2d735623af9214148afJeff Brown/** 6911417b1cfde8f1749905f2d735623af9214148afJeff Brown * This class implements the route controller dialog for {@link MediaRouter}. 7011417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p> 7111417b1cfde8f1749905f2d735623af9214148afJeff Brown * This dialog allows the user to control or disconnect from the currently selected route. 7211417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p> 7311417b1cfde8f1749905f2d735623af9214148afJeff Brown * 7411417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteButton 7511417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider 7611417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 7789530d511efd566d53bedd9178454dd01d227c61Jae Seopublic class MediaRouteControllerDialog extends AlertDialog { 7811417b1cfde8f1749905f2d735623af9214148afJeff Brown private static final String TAG = "MediaRouteControllerDialog"; 7911417b1cfde8f1749905f2d735623af9214148afJeff Brown 80a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo // STOPSHIP: Remove the flag when the group volume control implementation completes. 81a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo private static final boolean USE_GROUP = false; 82a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo 83f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // Time to wait before updating the volume when the user lets go of the seek bar 84f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // to allow the route provider time to propagate the change and publish a new 85f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // route descriptor. 86f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private static final int VOLUME_UPDATE_DELAY_MILLIS = 250; 87f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 8806991009e52024cbb3dde550988e06149e77a269Jae Seo private static final int BUTTON_NEUTRAL_RES_ID = android.R.id.button3; 8906991009e52024cbb3dde550988e06149e77a269Jae Seo private static final int BUTTON_DISCONNECT_RES_ID = android.R.id.button2; 9006991009e52024cbb3dde550988e06149e77a269Jae Seo private static final int BUTTON_STOP_RES_ID = android.R.id.button1; 9106991009e52024cbb3dde550988e06149e77a269Jae Seo 9211417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouter mRouter; 9311417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouterCallback mCallback; 9411417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouter.RouteInfo mRoute; 9511417b1cfde8f1749905f2d735623af9214148afJeff Brown 96eff7719415542ba819054863b0995f07742a7a8aJeff Brown private boolean mCreated; 97e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private boolean mAttachedToWindow; 98e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo 99f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo private int mDialogContentWidth; 10011417b1cfde8f1749905f2d735623af9214148afJeff Brown 1017ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private View mCustomControlView; 10211417b1cfde8f1749905f2d735623af9214148afJeff Brown 10311417b1cfde8f1749905f2d735623af9214148afJeff Brown private Button mDisconnectButton; 10494be6100218126ce6a08bf1f56209578500b361fRoboErik private Button mStopCastingButton; 1051ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private ImageButton mPlayPauseButton; 106b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim private ImageButton mCloseButton; 1071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private ImageButton mGroupExpandCollapseButton; 10894be6100218126ce6a08bf1f56209578500b361fRoboErik 1091ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private FrameLayout mCustomControlLayout; 1102b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang private FrameLayout mDefaultControlLayout; 11194be6100218126ce6a08bf1f56209578500b361fRoboErik private ImageView mArtView; 1121ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private TextView mTitleView; 1131ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private TextView mSubtitleView; 1147ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private TextView mRouteNameTextView; 11594be6100218126ce6a08bf1f56209578500b361fRoboErik 116f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private boolean mVolumeControlEnabled = true; 1178e1281a26eaabd6422fd84c11010134a0a9c3338Jaewan Kim private LinearLayout mMediaControlLayout; 1181ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private RelativeLayout mPlaybackControl; 1191ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private LinearLayout mVolumeControl; 1201ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private View mDividerView; 1211ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 1226051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private ListView mVolumeGroupList; 1231ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private SeekBar mVolumeSlider; 1241ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private boolean mVolumeSliderTouched; 12586a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo private int mVolumeSliderColor; 126f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 12794be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaControllerCompat mMediaController; 12894be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaControllerCallback mControllerCallback; 12994be6100218126ce6a08bf1f56209578500b361fRoboErik private PlaybackStateCompat mState; 13094be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaDescriptionCompat mDescription; 13194be6100218126ce6a08bf1f56209578500b361fRoboErik 132005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private FetchArtTask mFetchArtTask; 1338bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo private Bitmap mArtIconBitmap; 1348bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo private Uri mArtIconUri; 1352b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang private boolean mIsGroupExpanded; 13611417b1cfde8f1749905f2d735623af9214148afJeff Brown 13711417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteControllerDialog(Context context) { 13811417b1cfde8f1749905f2d735623af9214148afJeff Brown this(context, 0); 13911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 14011417b1cfde8f1749905f2d735623af9214148afJeff Brown 14111417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteControllerDialog(Context context, int theme) { 14294be6100218126ce6a08bf1f56209578500b361fRoboErik super(MediaRouterThemeHelper.createThemedContext(context), theme); 14311417b1cfde8f1749905f2d735623af9214148afJeff Brown context = getContext(); 14411417b1cfde8f1749905f2d735623af9214148afJeff Brown 14594be6100218126ce6a08bf1f56209578500b361fRoboErik mControllerCallback = new MediaControllerCallback(); 14611417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter = MediaRouter.getInstance(context); 14711417b1cfde8f1749905f2d735623af9214148afJeff Brown mCallback = new MediaRouterCallback(); 14811417b1cfde8f1749905f2d735623af9214148afJeff Brown mRoute = mRouter.getSelectedRoute(); 149e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(mRouter.getMediaSessionToken()); 15011417b1cfde8f1749905f2d735623af9214148afJeff Brown } 15111417b1cfde8f1749905f2d735623af9214148afJeff Brown 15211417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 15311417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets the route that this dialog is controlling. 15411417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 15511417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouter.RouteInfo getRoute() { 15611417b1cfde8f1749905f2d735623af9214148afJeff Brown return mRoute; 15711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 15811417b1cfde8f1749905f2d735623af9214148afJeff Brown 1596051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private MediaRouter.RouteGroup getGroup() { 1606051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (mRoute instanceof MediaRouter.RouteGroup) { 1616051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return (MediaRouter.RouteGroup) mRoute; 1626051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 1636051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return null; 1646051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 1656051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 16611417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 16711417b1cfde8f1749905f2d735623af9214148afJeff Brown * Provides the subclass an opportunity to create a view that will 16811417b1cfde8f1749905f2d735623af9214148afJeff Brown * be included within the body of the dialog to offer additional media controls 16911417b1cfde8f1749905f2d735623af9214148afJeff Brown * for the currently playing content. 17011417b1cfde8f1749905f2d735623af9214148afJeff Brown * 17111417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param savedInstanceState The dialog's saved instance state. 17211417b1cfde8f1749905f2d735623af9214148afJeff Brown * @return The media control view, or null if none. 17311417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 17411417b1cfde8f1749905f2d735623af9214148afJeff Brown public View onCreateMediaControlView(Bundle savedInstanceState) { 17511417b1cfde8f1749905f2d735623af9214148afJeff Brown return null; 17611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 17711417b1cfde8f1749905f2d735623af9214148afJeff Brown 17811417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 17911417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}. 18011417b1cfde8f1749905f2d735623af9214148afJeff Brown * 18111417b1cfde8f1749905f2d735623af9214148afJeff Brown * @return The media control view, or null if none. 18211417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 18311417b1cfde8f1749905f2d735623af9214148afJeff Brown public View getMediaControlView() { 1847ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim return mCustomControlView; 18511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 18611417b1cfde8f1749905f2d735623af9214148afJeff Brown 187eff7719415542ba819054863b0995f07742a7a8aJeff Brown /** 188f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * Sets whether to enable the volume slider and volume control using the volume keys 189f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * when the route supports it. 190f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * <p> 191f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * The default value is true. 192f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * </p> 193f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah */ 194f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public void setVolumeControlEnabled(boolean enable) { 195f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (mVolumeControlEnabled != enable) { 196f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeControlEnabled = enable; 197f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (mCreated) { 1981ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim updateVolumeControl(); 199f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 200f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 201f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 202f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 203f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah /** 204f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * Returns whether to enable the volume slider and volume control using the volume keys 205f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * when the route supports it. 206f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah */ 207f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public boolean isVolumeControlEnabled() { 208f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah return mVolumeControlEnabled; 209f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 210f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 211f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah /** 21294be6100218126ce6a08bf1f56209578500b361fRoboErik * Set the session to use for metadata and transport controls. The dialog 21394be6100218126ce6a08bf1f56209578500b361fRoboErik * will listen to changes on this session and update the UI automatically in 21494be6100218126ce6a08bf1f56209578500b361fRoboErik * response to changes. 21594be6100218126ce6a08bf1f56209578500b361fRoboErik * 21694be6100218126ce6a08bf1f56209578500b361fRoboErik * @param sessionToken The token for the session to use. 217eff7719415542ba819054863b0995f07742a7a8aJeff Brown */ 218e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void setMediaSession(MediaSessionCompat.Token sessionToken) { 21994be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 22094be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.unregisterCallback(mControllerCallback); 22194be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = null; 22294be6100218126ce6a08bf1f56209578500b361fRoboErik } 22394be6100218126ce6a08bf1f56209578500b361fRoboErik if (sessionToken == null) { 22494be6100218126ce6a08bf1f56209578500b361fRoboErik return; 22594be6100218126ce6a08bf1f56209578500b361fRoboErik } 226e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (!mAttachedToWindow) { 227e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return; 228e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 22994be6100218126ce6a08bf1f56209578500b361fRoboErik try { 23094be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = new MediaControllerCompat(getContext(), sessionToken); 23194be6100218126ce6a08bf1f56209578500b361fRoboErik } catch (RemoteException e) { 23294be6100218126ce6a08bf1f56209578500b361fRoboErik Log.e(TAG, "Error creating media controller in setMediaSession.", e); 23394be6100218126ce6a08bf1f56209578500b361fRoboErik } 23494be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 23594be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.registerCallback(mControllerCallback); 236eff7719415542ba819054863b0995f07742a7a8aJeff Brown } 23794be6100218126ce6a08bf1f56209578500b361fRoboErik MediaMetadataCompat metadata = mMediaController == null ? null 23894be6100218126ce6a08bf1f56209578500b361fRoboErik : mMediaController.getMetadata(); 23994be6100218126ce6a08bf1f56209578500b361fRoboErik mDescription = metadata == null ? null : metadata.getDescription(); 24094be6100218126ce6a08bf1f56209578500b361fRoboErik mState = mMediaController == null ? null : mMediaController.getPlaybackState(); 24194be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 242eff7719415542ba819054863b0995f07742a7a8aJeff Brown } 243eff7719415542ba819054863b0995f07742a7a8aJeff Brown 244eff7719415542ba819054863b0995f07742a7a8aJeff Brown /** 24594be6100218126ce6a08bf1f56209578500b361fRoboErik * Gets the description being used by the default UI. 24694be6100218126ce6a08bf1f56209578500b361fRoboErik * 24794be6100218126ce6a08bf1f56209578500b361fRoboErik * @return The current description. 248eff7719415542ba819054863b0995f07742a7a8aJeff Brown */ 24994be6100218126ce6a08bf1f56209578500b361fRoboErik public MediaSessionCompat.Token getMediaSession() { 25094be6100218126ce6a08bf1f56209578500b361fRoboErik return mMediaController == null ? null : mMediaController.getSessionToken(); 251eff7719415542ba819054863b0995f07742a7a8aJeff Brown } 252eff7719415542ba819054863b0995f07742a7a8aJeff Brown 25311417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 25411417b1cfde8f1749905f2d735623af9214148afJeff Brown protected void onCreate(Bundle savedInstanceState) { 25511417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onCreate(savedInstanceState); 25611417b1cfde8f1749905f2d735623af9214148afJeff Brown 257a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim setContentView(R.layout.mr_controller_material_dialog_b); 258f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo 259f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo int dialogWidth = MediaRouteDialogHelper.getDialogWidth(getContext()); 260f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo getWindow().setLayout(dialogWidth, ViewGroup.LayoutParams.WRAP_CONTENT); 261f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo 262f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo View decorView = getWindow().getDecorView(); 263f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo mDialogContentWidth = 264f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo dialogWidth - decorView.getPaddingLeft() - decorView.getPaddingRight(); 26511417b1cfde8f1749905f2d735623af9214148afJeff Brown 26606991009e52024cbb3dde550988e06149e77a269Jae Seo // Remove the neutral button. 26706991009e52024cbb3dde550988e06149e77a269Jae Seo findViewById(BUTTON_NEUTRAL_RES_ID).setVisibility(View.GONE); 26806991009e52024cbb3dde550988e06149e77a269Jae Seo 26994be6100218126ce6a08bf1f56209578500b361fRoboErik ClickListener listener = new ClickListener(); 270d6748a7926ebb2450337f9f0ff4d445c980344e5Jeff Brown 27106991009e52024cbb3dde550988e06149e77a269Jae Seo mDisconnectButton = (Button) findViewById(BUTTON_DISCONNECT_RES_ID); 27206991009e52024cbb3dde550988e06149e77a269Jae Seo mDisconnectButton.setText(R.string.mr_controller_disconnect); 27394be6100218126ce6a08bf1f56209578500b361fRoboErik mDisconnectButton.setOnClickListener(listener); 27411417b1cfde8f1749905f2d735623af9214148afJeff Brown 27506991009e52024cbb3dde550988e06149e77a269Jae Seo mStopCastingButton = (Button) findViewById(BUTTON_STOP_RES_ID); 27606991009e52024cbb3dde550988e06149e77a269Jae Seo mStopCastingButton.setText(R.string.mr_controller_stop); 27794be6100218126ce6a08bf1f56209578500b361fRoboErik mStopCastingButton.setOnClickListener(listener); 27811417b1cfde8f1749905f2d735623af9214148afJeff Brown 27906991009e52024cbb3dde550988e06149e77a269Jae Seo TypedValue value = new TypedValue(); 28006991009e52024cbb3dde550988e06149e77a269Jae Seo if (getContext().getTheme().resolveAttribute(R.attr.colorPrimary, value, true)) { 28106991009e52024cbb3dde550988e06149e77a269Jae Seo mDisconnectButton.setTextColor(value.data); 28206991009e52024cbb3dde550988e06149e77a269Jae Seo mStopCastingButton.setTextColor(value.data); 28306991009e52024cbb3dde550988e06149e77a269Jae Seo } 28406991009e52024cbb3dde550988e06149e77a269Jae Seo 2851ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mRouteNameTextView = (TextView) findViewById(R.id.mr_name); 2861ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mCloseButton = (ImageButton) findViewById(R.id.mr_close); 287b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim mCloseButton.setOnClickListener(listener); 2881ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mCustomControlLayout = (FrameLayout) findViewById(R.id.mr_custom_control); 2892b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang mDefaultControlLayout = (FrameLayout) findViewById(R.id.mr_default_control); 2907ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mArtView = (ImageView) findViewById(R.id.mr_art); 2916051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 2928e1281a26eaabd6422fd84c11010134a0a9c3338Jaewan Kim mMediaControlLayout = (LinearLayout) findViewById(R.id.mr_media_control); 2931ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mDividerView = findViewById(R.id.mr_control_divider); 2941ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 2951ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlaybackControl = (RelativeLayout) findViewById(R.id.mr_playback_control); 2961ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView = (TextView) findViewById(R.id.mr_control_title); 2971ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mSubtitleView = (TextView) findViewById(R.id.mr_control_subtitle); 2981ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton = (ImageButton) findViewById(R.id.mr_control_play_pause); 2991ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setOnClickListener(listener); 3001ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3011ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeControl = (LinearLayout) findViewById(R.id.mr_volume_control); 3021ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider = (SeekBar) findViewById(R.id.mr_volume_slider); 3031ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 3041ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private final Runnable mStopTrackingTouch = new Runnable() { 3051ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 3061ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void run() { 3071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mVolumeSliderTouched) { 3081ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSliderTouched = false; 3091ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim updateVolumeControl(); 3101ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3111ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3121ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim }; 3131ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3141ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 3151ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void onStartTrackingTouch(SeekBar seekBar) { 3161ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mVolumeSliderTouched) { 3171ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.removeCallbacks(mStopTrackingTouch); 3181ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 3191ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSliderTouched = true; 3201ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3211ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3221ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3231ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 3241ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void onStopTrackingTouch(SeekBar seekBar) { 3251ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // Defer resetting mVolumeSliderTouched to allow the media route provider 3261ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // a little time to settle into its new state and publish the final 3271ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // volume update. 3281ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS); 3291ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3301ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3311ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 3321ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 3331ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (fromUser) { 3341ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mRoute.requestSetVolume(progress); 3351ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3361ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3371ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim }); 33886a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo mVolumeSliderColor = MediaRouterThemeHelper.getVolumeSliderColor(getContext()); 3390b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo setVolumeSliderColor(getContext(), mVolumeSlider, mVolumeSliderColor); 3401ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3411ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim TypedArray styledAttributes = getContext().obtainStyledAttributes(new int[] { 3421ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim R.attr.mediaRouteExpandGroupDrawable, 3431ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim R.attr.mediaRouteCollapseGroupDrawable 3441ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim }); 3451ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim final Drawable expandGroupDrawable = styledAttributes.getDrawable(0); 3461ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim final Drawable collapseGroupDrawable = styledAttributes.getDrawable(1); 3471ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim styledAttributes.recycle(); 3481ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3497ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeGroupList = (ListView)findViewById(R.id.mr_volume_group_list); 3501ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton = (ImageButton) findViewById(R.id.mr_group_expand_collapse); 3511ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() { 3521ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 3531ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void onClick(View v) { 3542b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang mIsGroupExpanded = !mIsGroupExpanded; 3552b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang if (mIsGroupExpanded) { 3561ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setImageDrawable(collapseGroupDrawable); 3571ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeGroupList.setVisibility(View.VISIBLE); 3581ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeGroupList.setAdapter( 3591ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim new VolumeGroupAdapter(getContext(), getGroup().getRoutes())); 3601ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 3611ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setImageDrawable(expandGroupDrawable); 3621ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeGroupList.setVisibility(View.GONE); 3631ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3640d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang updateControlFrameLayout(); 3651ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3661ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim }); 36711417b1cfde8f1749905f2d735623af9214148afJeff Brown 3687ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mCustomControlView = onCreateMediaControlView(savedInstanceState); 3697ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mCustomControlView != null) { 3701ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mCustomControlLayout.addView(mCustomControlView); 3711ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mCustomControlLayout.setVisibility(View.VISIBLE); 3727ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mArtView.setVisibility(View.GONE); 37311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 37486a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo mCreated = true; 3757ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim update(); 37611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 37711417b1cfde8f1749905f2d735623af9214148afJeff Brown 37811417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 37911417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onAttachedToWindow() { 38011417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onAttachedToWindow(); 381e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAttachedToWindow = true; 38211417b1cfde8f1749905f2d735623af9214148afJeff Brown 38311417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback, 38411417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS); 385e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(mRouter.getMediaSessionToken()); 38611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 38711417b1cfde8f1749905f2d735623af9214148afJeff Brown 38811417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 38911417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onDetachedFromWindow() { 39011417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter.removeCallback(mCallback); 391e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(null); 392e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAttachedToWindow = false; 39311417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onDetachedFromWindow(); 39411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 39511417b1cfde8f1749905f2d735623af9214148afJeff Brown 39611417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 39711417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean onKeyDown(int keyCode, KeyEvent event) { 398ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 399ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 400ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1); 401ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown return true; 40211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 40311417b1cfde8f1749905f2d735623af9214148afJeff Brown return super.onKeyDown(keyCode, event); 40411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 40511417b1cfde8f1749905f2d735623af9214148afJeff Brown 40611417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 40711417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean onKeyUp(int keyCode, KeyEvent event) { 408ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 409ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 410ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown return true; 41111417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41211417b1cfde8f1749905f2d735623af9214148afJeff Brown return super.onKeyUp(keyCode, event); 41311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41411417b1cfde8f1749905f2d735623af9214148afJeff Brown 4157ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private void update() { 41611417b1cfde8f1749905f2d735623af9214148afJeff Brown if (!mRoute.isSelected() || mRoute.isDefault()) { 41711417b1cfde8f1749905f2d735623af9214148afJeff Brown dismiss(); 4187ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim return; 41911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 42094be6100218126ce6a08bf1f56209578500b361fRoboErik if (!mCreated) { 4217ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim return; 42294be6100218126ce6a08bf1f56209578500b361fRoboErik } 4232ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown 4247ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mRouteNameTextView.setText(mRoute.getName()); 42506991009e52024cbb3dde550988e06149e77a269Jae Seo mDisconnectButton.setVisibility(mRoute.canDisconnect() ? View.VISIBLE : View.GONE); 42694be6100218126ce6a08bf1f56209578500b361fRoboErik 4277ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mCustomControlView == null) { 428005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mFetchArtTask != null) { 429005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask.cancel(true); 43066937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang } 431005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = new FetchArtTask(); 432005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask.execute(); 433f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 4341ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim updateVolumeControl(); 4351ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim updatePlaybackControl(); 4361ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4371ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 4381ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private void updateVolumeControl() { 4391ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (!mVolumeSliderTouched) { 4401ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (isVolumeControlAvailable()) { 4411ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeControl.setVisibility(View.VISIBLE); 4421ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.setMax(mRoute.getVolumeMax()); 4431ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.setProgress(mRoute.getVolume()); 4441ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (USE_GROUP) { 4451ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (getGroup() == null) { 4461ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setVisibility(View.GONE); 4471ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 4481ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setVisibility(View.VISIBLE); 4491ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim VolumeGroupAdapter adapter = 4501ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim (VolumeGroupAdapter) mVolumeGroupList.getAdapter(); 4511ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (adapter != null) { 4521ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim adapter.notifyDataSetChanged(); 4531ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4541ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4551ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4561ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 4571ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeControl.setVisibility(View.GONE); 4581ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 459b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim updateControlLayoutHeight(); 4601ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4611ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4621ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 4631ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private void updatePlaybackControl() { 4641ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mCustomControlView == null && (mDescription != null || mState != null)) { 4651ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlaybackControl.setVisibility(View.VISIBLE); 4661ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim CharSequence title = mDescription == null ? null : mDescription.getTitle(); 4671ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean hasTitle = !TextUtils.isEmpty(title); 4681ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 4691ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle(); 4701ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean hasSubtitle = !TextUtils.isEmpty(subtitle); 4711ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 4721ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (!hasTitle && !hasSubtitle) { 4731ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mRoute.getPresentationDisplayId() 4741ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim != MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) { 4751ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // The user is currently casting screen. 4761ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setText(R.string.mr_controller_casting_screen); 4771ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 4781ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setText((mState == null 4791ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim || mState.getState() == PlaybackStateCompat.STATE_NONE) 4801ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim ? R.string.mr_controller_no_media_selected 4811ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim : R.string.mr_controller_no_info_available); 4821ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4831ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setVisibility(View.VISIBLE); 4841ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mSubtitleView.setVisibility(View.GONE); 4851ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 4861ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setText(title); 4871ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setVisibility(hasTitle ? View.VISIBLE : View.GONE); 4881ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mSubtitleView.setText(subtitle); 4891ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mSubtitleView.setVisibility(hasSubtitle ? View.VISIBLE : View.GONE); 4901ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4911ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mState != null) { 4921ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING 4931ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim || mState.getState() == PlaybackStateCompat.STATE_PLAYING; 4941ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY 4951ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; 4961ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE 4971ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; 4981ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (isPlaying && supportsPause) { 4991ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setVisibility(View.VISIBLE); 5001ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource( 5011ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim getContext(), R.attr.mediaRoutePauseDrawable)); 5021ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setContentDescription(getContext().getResources() 5031ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim .getText(R.string.mr_controller_pause)); 5041ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else if (!isPlaying && supportsPlay) { 5051ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setVisibility(View.VISIBLE); 5061ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource( 5071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim getContext(), R.attr.mediaRoutePlayDrawable)); 5081ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setContentDescription(getContext().getResources() 5091ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim .getText(R.string.mr_controller_play)); 5101ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 5111ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setVisibility(View.GONE); 5121ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 5131ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 5141ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 5151ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlaybackControl.setVisibility(View.GONE); 5161ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 517b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim updateControlLayoutHeight(); 5181ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 5191ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 520b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim private void updateControlLayoutHeight() { 521b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim // TODO: Update the top and bottom padding of the control layout according to the display 5221ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // height. 5231ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mDividerView.setVisibility((mVolumeControl.getVisibility() == View.VISIBLE 5241ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim && mPlaybackControl.getVisibility() == View.VISIBLE) 5251ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim ? View.VISIBLE : View.GONE); 5268e1281a26eaabd6422fd84c11010134a0a9c3338Jaewan Kim mMediaControlLayout.setVisibility((mVolumeControl.getVisibility() == View.GONE 5271ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim && mPlaybackControl.getVisibility() == View.GONE) 5281ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim ? View.GONE : View.VISIBLE); 529f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 530f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 5312b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang private void updateControlFrameLayout() { 5322b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang int height; 5332b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang if (mArtView.getVisibility() == View.GONE) { 5342b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang height = LinearLayout.LayoutParams.WRAP_CONTENT; 5352b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } else { 536f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo measureAndGetDecorView(); 5370d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang if (!mIsGroupExpanded) { 5380d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang height = mArtView.getMeasuredHeight() + mMediaControlLayout.getMeasuredHeight(); 5392b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } else { 5400d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang if (mVolumeGroupList.getAdapter().getCount() <= 2 5410d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang && mArtView.getMeasuredHeight() > mVolumeGroupList.getMeasuredHeight()) { 5420d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang // Push the controls up and partially cover the artwork. 5430d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang height = mArtView.getMeasuredHeight() + mMediaControlLayout.getMeasuredHeight() 5440d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang - mVolumeGroupList.getMeasuredHeight(); 5450d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang } else { 5460d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang // Completely cover the artwork. 5470d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang height = LinearLayout.LayoutParams.WRAP_CONTENT; 5480d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang } 5492b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } 5502b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } 5510d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang mDefaultControlLayout.setLayoutParams(new LinearLayout.LayoutParams( 5520d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang LinearLayout.LayoutParams.FILL_PARENT, height)); 5532b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } 5542b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang 555f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private boolean isVolumeControlAvailable() { 556f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah return mVolumeControlEnabled && mRoute.getVolumeHandling() == 557f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE; 558f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 559f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 560f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo private View measureAndGetDecorView() { 5610d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang View decorView = getWindow().getDecorView(); 562f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo decorView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); 5630d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang return decorView; 5640d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang } 5650d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang 56613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim private void updateArtView() { 56713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (!(mArtView.getDrawable() instanceof BitmapDrawable)) { 568bfb90b6717bb46535d747aa50045a206965542d0Jae Seo mArtView.setVisibility(View.GONE); 56913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return; 57013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 57113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim Bitmap art = ((BitmapDrawable) mArtView.getDrawable()).getBitmap(); 57213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (art == null) { 573bfb90b6717bb46535d747aa50045a206965542d0Jae Seo mArtView.setVisibility(View.GONE); 57413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return; 57513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 57613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int desiredArtHeight = getDesiredArtHeight(art.getWidth(), art.getHeight()); 57713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics(); 578f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo View decorView = measureAndGetDecorView(); 57913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Show art if and only if it fits in the screen. 58013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (mArtView.getVisibility() == View.GONE) { 58113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (decorView.getMeasuredHeight() + desiredArtHeight <= displayMetrics.heightPixels) { 58213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setVisibility(View.VISIBLE); 58313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setMaxHeight(desiredArtHeight); 58413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 58513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } else { 58613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (decorView.getMeasuredHeight() - mArtView.getMeasuredHeight() + desiredArtHeight 58713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim <= displayMetrics.heightPixels) { 58813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setMaxHeight(desiredArtHeight); 58913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } else { 59013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setVisibility(View.GONE); 59113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 59213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 59313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 59413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim 5950b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo private static void setVolumeSliderColor(Context context, SeekBar volumeSlider, int color) { 59686a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo volumeSlider.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN); 59786a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo if (Build.VERSION.SDK_INT >= 16) { 59886a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo SeekBarJellybean.getThumb(volumeSlider).setColorFilter(color, PorterDuff.Mode.SRC_IN); 5990b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo } else { 6000b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo // In case getThumb() isn't available, use the thumb drawable from AppCompat. 6010b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo Drawable thumb = 6020b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo context.getResources().getDrawable(R.drawable.abc_seekbar_thumb_material); 6030b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo thumb.setColorFilter(color, PorterDuff.Mode.SRC_IN); 6040b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo volumeSlider.setThumb(thumb); 60586a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo } 60686a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo } 60786a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo 60813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim /** 60913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim * Returns desired art height to fit into controller dialog. 61013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim */ 61113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim private int getDesiredArtHeight(int originalWidth, int originalHeight) { 61213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (originalWidth >= originalHeight) { 61313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // For landscape art, fit width to dialog width. 614f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo return (int) ((float) mDialogContentWidth * originalHeight / originalWidth + 0.5f); 61513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 61613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // For portrait art, fit height to 16:9 ratio case's height. 617f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo return (int) ((float) mDialogContentWidth * 9 / 16 + 0.5f); 61813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 61913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim 62011417b1cfde8f1749905f2d735623af9214148afJeff Brown private final class MediaRouterCallback extends MediaRouter.Callback { 62111417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 62211417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) { 62311417b1cfde8f1749905f2d735623af9214148afJeff Brown update(); 62411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 62511417b1cfde8f1749905f2d735623af9214148afJeff Brown 62611417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 62711417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) { 62811417b1cfde8f1749905f2d735623af9214148afJeff Brown update(); 62911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 63011417b1cfde8f1749905f2d735623af9214148afJeff Brown 63111417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 63211417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) { 63311417b1cfde8f1749905f2d735623af9214148afJeff Brown if (route == mRoute) { 6341ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim updateVolumeControl(); 63594be6100218126ce6a08bf1f56209578500b361fRoboErik } 63694be6100218126ce6a08bf1f56209578500b361fRoboErik } 63794be6100218126ce6a08bf1f56209578500b361fRoboErik } 63894be6100218126ce6a08bf1f56209578500b361fRoboErik 63994be6100218126ce6a08bf1f56209578500b361fRoboErik private final class MediaControllerCallback extends MediaControllerCompat.Callback { 64094be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 64194be6100218126ce6a08bf1f56209578500b361fRoboErik public void onSessionDestroyed() { 64294be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 64394be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.unregisterCallback(mControllerCallback); 64494be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = null; 64594be6100218126ce6a08bf1f56209578500b361fRoboErik } 64694be6100218126ce6a08bf1f56209578500b361fRoboErik } 64794be6100218126ce6a08bf1f56209578500b361fRoboErik 64894be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 64994be6100218126ce6a08bf1f56209578500b361fRoboErik public void onPlaybackStateChanged(PlaybackStateCompat state) { 65094be6100218126ce6a08bf1f56209578500b361fRoboErik mState = state; 65194be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 65294be6100218126ce6a08bf1f56209578500b361fRoboErik } 65394be6100218126ce6a08bf1f56209578500b361fRoboErik 65494be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 65594be6100218126ce6a08bf1f56209578500b361fRoboErik public void onMetadataChanged(MediaMetadataCompat metadata) { 65694be6100218126ce6a08bf1f56209578500b361fRoboErik mDescription = metadata == null ? null : metadata.getDescription(); 65794be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 65894be6100218126ce6a08bf1f56209578500b361fRoboErik } 65994be6100218126ce6a08bf1f56209578500b361fRoboErik } 66094be6100218126ce6a08bf1f56209578500b361fRoboErik 66194be6100218126ce6a08bf1f56209578500b361fRoboErik private final class ClickListener implements View.OnClickListener { 66294be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 66394be6100218126ce6a08bf1f56209578500b361fRoboErik public void onClick(View v) { 66494be6100218126ce6a08bf1f56209578500b361fRoboErik int id = v.getId(); 66506991009e52024cbb3dde550988e06149e77a269Jae Seo if (id == BUTTON_STOP_RES_ID || id == BUTTON_DISCONNECT_RES_ID) { 66694be6100218126ce6a08bf1f56209578500b361fRoboErik if (mRoute.isSelected()) { 66706991009e52024cbb3dde550988e06149e77a269Jae Seo mRouter.unselect(id == BUTTON_STOP_RES_ID ? 66894be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_STOPPED : 66994be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_DISCONNECTED); 67094be6100218126ce6a08bf1f56209578500b361fRoboErik } 67194be6100218126ce6a08bf1f56209578500b361fRoboErik dismiss(); 6727ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else if (id == R.id.mr_control_play_pause) { 67394be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null && mState != null) { 67494be6100218126ce6a08bf1f56209578500b361fRoboErik if (mState.getState() == PlaybackStateCompat.STATE_PLAYING) { 67594be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.getTransportControls().pause(); 67694be6100218126ce6a08bf1f56209578500b361fRoboErik } else { 67794be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.getTransportControls().play(); 67894be6100218126ce6a08bf1f56209578500b361fRoboErik } 67994be6100218126ce6a08bf1f56209578500b361fRoboErik } 6801ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else if (id == R.id.mr_close) { 681b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim dismiss(); 68211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 68311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 68411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 685005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 6866051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> { 6870e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo final static float DISABLED_ALPHA = .3f; 6880e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo 6896051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo final OnSeekBarChangeListener mOnSeekBarChangeListener = new OnSeekBarChangeListener() { 6906051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 6916051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 6926051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (fromUser) { 6936051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo int position = (int) seekBar.getTag(); 6946051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo getGroup().getRouteAt(position).requestSetVolume(progress); 6956051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 6966051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 6976051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 6986051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 6996051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onStartTrackingTouch(SeekBar seekBar) { 7006051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo // TODO: Implement 7016051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7026051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7036051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 7046051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onStopTrackingTouch(SeekBar seekBar) { 7056051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo // TODO: Implement 7066051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7076051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo }; 7086051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7096051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public VolumeGroupAdapter(Context context, List<MediaRouter.RouteInfo> objects) { 7106051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo super(context, 0, objects); 7116051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7126051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7136051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 7146051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public View getView(final int position, View convertView, ViewGroup parent) { 7156051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo View v = convertView; 7166051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (v == null) { 7176051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo v = LayoutInflater.from(getContext()).inflate( 718a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim R.layout.mr_controller_volume_item, null); 7190b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo setVolumeSliderColor(getContext(), (SeekBar) v.findViewById(R.id.mr_volume_slider), 7200b0446251d63e184a1bb9ee62ddac0b344e7e571Jae Seo mVolumeSliderColor); 7216051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7226051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo MediaRouter.RouteInfo route = getItem(position); 7236051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (route != null) { 7240e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo boolean isEnabled = route.isEnabled(); 7250e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo 7267ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim TextView routeName = (TextView) v.findViewById(R.id.mr_name); 7270e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo routeName.setEnabled(isEnabled); 7280e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo routeName.setText(route.getName()); 7296051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7307ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim SeekBar volumeSlider = (SeekBar) v.findViewById(R.id.mr_volume_slider); 7310e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setEnabled(isEnabled); 7326051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo volumeSlider.setTag(position); 7330e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo if (isEnabled) { 7340e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo if (route.getVolumeHandling() 7350e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) { 7360e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setMax(route.getVolumeMax()); 7370e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setProgress(route.getVolume()); 7380e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setOnSeekBarChangeListener(mOnSeekBarChangeListener); 7390e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo } else { 7400e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setMax(100); 7410e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setProgress(100); 7420e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setEnabled(false); 7430e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo } 7440e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo } 745418c688351713e9349227262163eef752a8e7ce6Jae Seo if (Build.VERSION.SDK_INT >= 16) { 746418c688351713e9349227262163eef752a8e7ce6Jae Seo SeekBarJellybean.getThumb(volumeSlider).mutate().setAlpha(isEnabled ? 255 : 0); 747418c688351713e9349227262163eef752a8e7ce6Jae Seo // TODO: Still see an artifact even though the thumb is transparent. Remove it. 748418c688351713e9349227262163eef752a8e7ce6Jae Seo } 7490e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo 7500e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo ImageView volumeItemIcon = 7517ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim (ImageView) v.findViewById(R.id.mr_volume_item_icon); 75277367b4a1871417198d0399d9ad074314c758567Jae Seo volumeItemIcon.setAlpha(isEnabled ? 255 : (int) (255 * DISABLED_ALPHA)); 7536051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7546051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return v; 7556051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7566051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7576051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 758005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private class FetchArtTask extends AsyncTask<Void, Void, Bitmap> { 7598bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo final Bitmap mIconBitmap; 7608bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo final Uri mIconUri; 7618bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo int mBackgroundColor; 7628bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo 7638bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo FetchArtTask() { 7648bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo mIconBitmap = mDescription == null ? null : mDescription.getIconBitmap(); 7658bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo mIconUri = mDescription == null ? null : mDescription.getIconUri(); 7668bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo } 7678bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo 7688bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo @Override 7698bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo protected void onPreExecute() { 7708bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo if (mArtIconBitmap == mIconBitmap && mArtIconUri == mIconUri) { 7718bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo // Already handled the current art. 7728bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo cancel(true); 7738bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo } 7748bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo } 775005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 776005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 777005482649154d0970693b3967241eb4d2cb22003Jaewan Kim protected Bitmap doInBackground(Void... arg) { 77813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim Bitmap art = null; 7798bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo if (mIconBitmap != null) { 7808bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo art = mIconBitmap; 7818bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo } else if (mIconUri != null) { 7828bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo String scheme = mIconUri.getScheme(); 783005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (!(ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme) 784005482649154d0970693b3967241eb4d2cb22003Jaewan Kim || ContentResolver.SCHEME_CONTENT.equals(scheme) 785005482649154d0970693b3967241eb4d2cb22003Jaewan Kim || ContentResolver.SCHEME_FILE.equals(scheme))) { 786005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Log.w(TAG, "Icon Uri should point to local resources."); 787005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 788005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 789005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BufferedInputStream stream = null; 790005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 791005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream = new BufferedInputStream( 7928bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo getContext().getContentResolver().openInputStream(mIconUri)); 793005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 79413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Query art size. 795005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BitmapFactory.Options options = new BitmapFactory.Options(); 796005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inJustDecodeBounds = true; 797005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BitmapFactory.decodeStream(stream, null, options); 79813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (options.outWidth == 0 || options.outHeight == 0) { 79913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return null; 80013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 80113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Rewind the stream in order to restart art decoding. 802005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 803005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.reset(); 804005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e) { 805005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // Failed to rewind the stream, try to reopen it. 806005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.close(); 807005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream = new BufferedInputStream(getContext().getContentResolver() 8088bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo .openInputStream(mIconUri)); 809005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 81013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Calculate required size to decode the art and possibly resize it. 811005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inJustDecodeBounds = false; 81213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int reqHeight = getDesiredArtHeight(options.outWidth, options.outHeight); 81313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int ratio = options.outHeight / reqHeight; 814005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inSampleSize = Math.max(1, Integer.highestOneBit(ratio)); 815005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (isCancelled()) { 816005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 817005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 81813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim art = BitmapFactory.decodeStream(stream, null, options); 819005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e){ 8208bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo Log.w(TAG, "Unable to open: " + mIconUri, e); 821005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } finally { 822005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (stream != null) { 823005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 824005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.close(); 825005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e) { 826005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 827005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 828005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 829005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 830145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim if (art != null && art.getWidth() < art.getHeight()) { 831145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim // Portrait art requires background color. 832145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim Palette palette = new Palette.Builder(art).maximumColorCount(1).generate(); 833145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim mBackgroundColor = (palette.getSwatches() == null) 834145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim ? 0 : palette.getSwatches().get(0).getRgb(); 835005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 83613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return art; 837005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 838005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 839005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 840005482649154d0970693b3967241eb4d2cb22003Jaewan Kim protected void onCancelled() { 841005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = null; 842005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 843005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 844005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 84513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim protected void onPostExecute(Bitmap art) { 846005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = null; 8478bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo if (mArtIconBitmap != mIconBitmap || mArtIconUri != mIconUri) { 8488bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo mArtIconBitmap = mIconBitmap; 8498bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo mArtIconUri = mIconUri; 8508bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo 8518bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo mArtView.setImageBitmap(art); 8528bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo mArtView.setBackgroundColor(mBackgroundColor); 8538bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo updateArtView(); 8540d35e8e4de45b751f979d40aa9ffad3875ba9f66Dongwon Kang updateControlFrameLayout(); 8558bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo } 856005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 857005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 8586051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo} 859