MediaRouteControllerDialog.java revision 86a802c8d09983d8725cccf59217e65d3e0c6373
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; 236e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kimimport android.content.res.Configuration; 246e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kimimport android.content.res.Resources; 256051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.content.res.TypedArray; 26005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.Bitmap; 27005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.BitmapFactory; 2886a802c8d09983d8725cccf59217e65d3e0c6373Jae Seoimport android.graphics.Color; 2986a802c8d09983d8725cccf59217e65d3e0c6373Jae Seoimport android.graphics.PorterDuff; 3013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.graphics.drawable.BitmapDrawable; 312ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brownimport android.graphics.drawable.Drawable; 32005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.net.Uri; 33005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.os.AsyncTask; 34418c688351713e9349227262163eef752a8e7ce6Jae Seoimport android.os.Build; 3511417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.os.Bundle; 3694be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.os.RemoteException; 3794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaDescriptionCompat; 3894be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaMetadataCompat; 3994be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaControllerCompat; 4094be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaSessionCompat; 4194be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.PlaybackStateCompat; 42005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.support.v7.graphics.Palette; 4311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouteSelector; 4411417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouter; 45418c688351713e9349227262163eef752a8e7ce6Jae Seoimport android.support.v7.media.SeekBarJellybean; 4611417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.mediarouter.R; 4794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.text.TextUtils; 4813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.util.DisplayMetrics; 4994be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.util.Log; 5011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.KeyEvent; 516051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.LayoutInflater; 5211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.View; 536051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.ViewGroup; 542b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kangimport android.view.ViewTreeObserver; 556051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ArrayAdapter; 5611417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Button; 5711417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.FrameLayout; 5894be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageButton; 5994be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageView; 60f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.LinearLayout; 616051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ListView; 627ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Limimport android.widget.RelativeLayout; 63f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.SeekBar; 6494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.TextView; 6511417b1cfde8f1749905f2d735623af9214148afJeff Brown 66005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.BufferedInputStream; 67005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.IOException; 686051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport java.util.List; 69005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 7011417b1cfde8f1749905f2d735623af9214148afJeff Brown/** 7111417b1cfde8f1749905f2d735623af9214148afJeff Brown * This class implements the route controller dialog for {@link MediaRouter}. 7211417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p> 7311417b1cfde8f1749905f2d735623af9214148afJeff Brown * This dialog allows the user to control or disconnect from the currently selected route. 7411417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p> 7511417b1cfde8f1749905f2d735623af9214148afJeff Brown * 7611417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteButton 7711417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider 7811417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 7989530d511efd566d53bedd9178454dd01d227c61Jae Seopublic class MediaRouteControllerDialog extends AlertDialog { 8011417b1cfde8f1749905f2d735623af9214148afJeff Brown private static final String TAG = "MediaRouteControllerDialog"; 8111417b1cfde8f1749905f2d735623af9214148afJeff Brown 82a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo // STOPSHIP: Remove the flag when the group volume control implementation completes. 83a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo private static final boolean USE_GROUP = false; 84a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo 85f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // Time to wait before updating the volume when the user lets go of the seek bar 86f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // to allow the route provider time to propagate the change and publish a new 87f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // route descriptor. 88f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private static final int VOLUME_UPDATE_DELAY_MILLIS = 250; 89f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 9011417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouter mRouter; 9111417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouterCallback mCallback; 9211417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouter.RouteInfo mRoute; 9311417b1cfde8f1749905f2d735623af9214148afJeff Brown 94eff7719415542ba819054863b0995f07742a7a8aJeff Brown private boolean mCreated; 95e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private boolean mAttachedToWindow; 96e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo 976e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim private int mOrientation; 986e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim private int mDialogWidthPortrait; 996e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim private int mDialogWidthLandscape; 1004ec1a0371ebb43ba1537354becb9241c105d2fb8Jaewan Kim private int mDialogPaddingHorizontal; 10111417b1cfde8f1749905f2d735623af9214148afJeff Brown 1027ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private View mCustomControlView; 10311417b1cfde8f1749905f2d735623af9214148afJeff Brown 10411417b1cfde8f1749905f2d735623af9214148afJeff Brown private Button mDisconnectButton; 10594be6100218126ce6a08bf1f56209578500b361fRoboErik private Button mStopCastingButton; 1061ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private ImageButton mPlayPauseButton; 107b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim private ImageButton mCloseButton; 1081ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private ImageButton mGroupExpandCollapseButton; 10994be6100218126ce6a08bf1f56209578500b361fRoboErik 1101ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private FrameLayout mCustomControlLayout; 1112b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang private FrameLayout mDefaultControlLayout; 1122b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang private boolean mNeedToAdjustControlFrameLayout = true; 11394be6100218126ce6a08bf1f56209578500b361fRoboErik private ImageView mArtView; 1141ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private TextView mTitleView; 1151ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private TextView mSubtitleView; 1167ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private TextView mRouteNameTextView; 11794be6100218126ce6a08bf1f56209578500b361fRoboErik 118f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private boolean mVolumeControlEnabled = true; 1191ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private LinearLayout mControlLayout; 1201ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private RelativeLayout mPlaybackControl; 1211ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private LinearLayout mVolumeControl; 1221ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private View mDividerView; 1231ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 1246051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private ListView mVolumeGroupList; 1251ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private SeekBar mVolumeSlider; 1261ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private boolean mVolumeSliderTouched; 12786a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo private int mVolumeSliderColor; 128f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 12994be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaControllerCompat mMediaController; 13094be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaControllerCallback mControllerCallback; 13194be6100218126ce6a08bf1f56209578500b361fRoboErik private PlaybackStateCompat mState; 13294be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaDescriptionCompat mDescription; 13394be6100218126ce6a08bf1f56209578500b361fRoboErik 134005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private FetchArtTask mFetchArtTask; 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); 2586e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim Resources res = getContext().getResources(); 259e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo mDialogWidthPortrait = res.getDimensionPixelSize(R.dimen.mr_dialog_content_width_portrait); 2606e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim mDialogWidthLandscape = res.getDimensionPixelSize( 261e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo R.dimen.mr_dialog_content_width_landscape); 26211417b1cfde8f1749905f2d735623af9214148afJeff Brown 26394be6100218126ce6a08bf1f56209578500b361fRoboErik ClickListener listener = new ClickListener(); 264d6748a7926ebb2450337f9f0ff4d445c980344e5Jeff Brown 2651ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mDisconnectButton = (Button) findViewById(R.id.mr_button_disconnect); 26694be6100218126ce6a08bf1f56209578500b361fRoboErik mDisconnectButton.setOnClickListener(listener); 26711417b1cfde8f1749905f2d735623af9214148afJeff Brown 2681ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mStopCastingButton = (Button) findViewById(R.id.mr_button_stop); 26994be6100218126ce6a08bf1f56209578500b361fRoboErik mStopCastingButton.setOnClickListener(listener); 27011417b1cfde8f1749905f2d735623af9214148afJeff Brown 2711ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mRouteNameTextView = (TextView) findViewById(R.id.mr_name); 2721ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mCloseButton = (ImageButton) findViewById(R.id.mr_close); 273b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim mCloseButton.setOnClickListener(listener); 2741ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mCustomControlLayout = (FrameLayout) findViewById(R.id.mr_custom_control); 2752b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang mDefaultControlLayout = (FrameLayout) findViewById(R.id.mr_default_control); 2762b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang ViewTreeObserver observer = mDefaultControlLayout.getViewTreeObserver(); 2772b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 2782b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang @Override 2792b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang public void onGlobalLayout() { 2802b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang updateControlFrameLayout(); 2812b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } 2822b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang }); 2837ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mArtView = (ImageView) findViewById(R.id.mr_art); 2846051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 2851ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mControlLayout = (LinearLayout) findViewById(R.id.mr_control); 2861ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mDividerView = findViewById(R.id.mr_control_divider); 2871ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 2881ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlaybackControl = (RelativeLayout) findViewById(R.id.mr_playback_control); 2891ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView = (TextView) findViewById(R.id.mr_control_title); 2901ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mSubtitleView = (TextView) findViewById(R.id.mr_control_subtitle); 2911ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton = (ImageButton) findViewById(R.id.mr_control_play_pause); 2921ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setOnClickListener(listener); 2931ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 2941ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeControl = (LinearLayout) findViewById(R.id.mr_volume_control); 2951ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider = (SeekBar) findViewById(R.id.mr_volume_slider); 2961ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 2971ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private final Runnable mStopTrackingTouch = new Runnable() { 2981ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 2991ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void run() { 3001ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mVolumeSliderTouched) { 3011ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSliderTouched = false; 3021ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim updateVolumeControl(); 3031ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3041ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3051ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim }; 3061ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 3081ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void onStartTrackingTouch(SeekBar seekBar) { 3091ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mVolumeSliderTouched) { 3101ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.removeCallbacks(mStopTrackingTouch); 3111ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 3121ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSliderTouched = true; 3131ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3141ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3151ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3161ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 3171ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void onStopTrackingTouch(SeekBar seekBar) { 3181ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // Defer resetting mVolumeSliderTouched to allow the media route provider 3191ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // a little time to settle into its new state and publish the final 3201ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // volume update. 3211ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS); 3221ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3231ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3241ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 3251ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 3261ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (fromUser) { 3271ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mRoute.requestSetVolume(progress); 3281ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3291ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3301ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim }); 33186a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo mVolumeSliderColor = MediaRouterThemeHelper.getVolumeSliderColor(getContext()); 33286a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo setVolumeSliderColor(mVolumeSlider, mVolumeSliderColor); 3331ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3341ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim TypedArray styledAttributes = getContext().obtainStyledAttributes(new int[] { 3351ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim R.attr.mediaRouteExpandGroupDrawable, 3361ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim R.attr.mediaRouteCollapseGroupDrawable 3371ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim }); 3381ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim final Drawable expandGroupDrawable = styledAttributes.getDrawable(0); 3391ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim final Drawable collapseGroupDrawable = styledAttributes.getDrawable(1); 3401ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim styledAttributes.recycle(); 3411ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 3427ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeGroupList = (ListView)findViewById(R.id.mr_volume_group_list); 3431ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton = (ImageButton) findViewById(R.id.mr_group_expand_collapse); 3441ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() { 3451ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim @Override 3461ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim public void onClick(View v) { 3472b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang mIsGroupExpanded = !mIsGroupExpanded; 3482b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang if (mIsGroupExpanded) { 3491ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setImageDrawable(collapseGroupDrawable); 3501ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeGroupList.setVisibility(View.VISIBLE); 3511ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeGroupList.setAdapter( 3521ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim new VolumeGroupAdapter(getContext(), getGroup().getRoutes())); 3531ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 3541ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setImageDrawable(expandGroupDrawable); 3551ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeGroupList.setVisibility(View.GONE); 3561ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3572b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang mNeedToAdjustControlFrameLayout = true; 3581ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 3591ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim }); 36011417b1cfde8f1749905f2d735623af9214148afJeff Brown 3617ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mCustomControlView = onCreateMediaControlView(savedInstanceState); 3627ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mCustomControlView != null) { 3631ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mCustomControlLayout.addView(mCustomControlView); 3641ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mCustomControlLayout.setVisibility(View.VISIBLE); 3657ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mArtView.setVisibility(View.GONE); 36611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 36786a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo 36886a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo mCreated = true; 3697ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim update(); 37011417b1cfde8f1749905f2d735623af9214148afJeff Brown } 37111417b1cfde8f1749905f2d735623af9214148afJeff Brown 3726e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim /** 3736e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim * Called by {@link MediaRouteControllerDialogFragment} when the device configuration 3746e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim * is changed. 3756e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim */ 3766e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim void onConfigurationChanged(Configuration newConfig) { 3776e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim onOrientationChanged(newConfig.orientation); 3786e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim } 3796e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim 3806e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim private void onOrientationChanged(int orientation) { 3816e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim if (!mAttachedToWindow || mOrientation == orientation) { 3826e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim return; 3836e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim } 3846e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim mOrientation = orientation; 385b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim int dialogWidth = mOrientation == Configuration.ORIENTATION_LANDSCAPE 386b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim ? mDialogWidthLandscape : mDialogWidthPortrait; 387b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim getWindow().setLayout(dialogWidth, ViewGroup.LayoutParams.WRAP_CONTENT); 388b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim 389e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo View decorView = getWindow().getDecorView(); 390e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo mDialogPaddingHorizontal = decorView.getPaddingLeft() + decorView.getPaddingRight(); 391e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo 392b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim // Manually set the width of buttons to workaround unexpected text alignment changes. 393e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo int buttonWidth = (dialogWidth - mDialogPaddingHorizontal) / 2; 394e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo 395b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim ViewGroup.LayoutParams lp = mStopCastingButton.getLayoutParams(); 396b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim lp.width = buttonWidth; 397b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim mStopCastingButton.setLayoutParams(lp); 398b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim 399b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim lp = mDisconnectButton.getLayoutParams(); 400b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim lp.width = buttonWidth; 401b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim mDisconnectButton.setLayoutParams(lp); 402b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim 40313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim updateArtView(); 4046e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim } 4056e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim 40611417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 40711417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onAttachedToWindow() { 40811417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onAttachedToWindow(); 409e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAttachedToWindow = true; 41011417b1cfde8f1749905f2d735623af9214148afJeff Brown 41111417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback, 41211417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS); 413e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(mRouter.getMediaSessionToken()); 4146e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim onOrientationChanged(getContext().getResources().getConfiguration().orientation); 41511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41611417b1cfde8f1749905f2d735623af9214148afJeff Brown 41711417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 41811417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onDetachedFromWindow() { 41911417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter.removeCallback(mCallback); 420e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(null); 421e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAttachedToWindow = false; 42211417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onDetachedFromWindow(); 42311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 42411417b1cfde8f1749905f2d735623af9214148afJeff Brown 42511417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 42611417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean onKeyDown(int keyCode, KeyEvent event) { 427ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 428ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 429ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1); 430ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown return true; 43111417b1cfde8f1749905f2d735623af9214148afJeff Brown } 43211417b1cfde8f1749905f2d735623af9214148afJeff Brown return super.onKeyDown(keyCode, event); 43311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 43411417b1cfde8f1749905f2d735623af9214148afJeff Brown 43511417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 43611417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean onKeyUp(int keyCode, KeyEvent event) { 437ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 438ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 439ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown return true; 44011417b1cfde8f1749905f2d735623af9214148afJeff Brown } 44111417b1cfde8f1749905f2d735623af9214148afJeff Brown return super.onKeyUp(keyCode, event); 44211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 44311417b1cfde8f1749905f2d735623af9214148afJeff Brown 4447ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private void update() { 44511417b1cfde8f1749905f2d735623af9214148afJeff Brown if (!mRoute.isSelected() || mRoute.isDefault()) { 44611417b1cfde8f1749905f2d735623af9214148afJeff Brown dismiss(); 4477ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim return; 44811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 44994be6100218126ce6a08bf1f56209578500b361fRoboErik if (!mCreated) { 4507ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim return; 45194be6100218126ce6a08bf1f56209578500b361fRoboErik } 4522ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown 4537ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mRouteNameTextView.setText(mRoute.getName()); 4545c6a5799fca3b622ad82ac77d8dfbed7dfd4ec7fSungsoo Lim mDisconnectButton.setVisibility(mRoute.canDisconnect() ? View.VISIBLE : View.INVISIBLE); 45594be6100218126ce6a08bf1f56209578500b361fRoboErik 4567ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mCustomControlView == null) { 457005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mFetchArtTask != null) { 458005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask.cancel(true); 45966937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang } 460005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = new FetchArtTask(); 461005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask.execute(); 462f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 4631ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim updateVolumeControl(); 4641ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim updatePlaybackControl(); 4651ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4661ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 4671ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private void updateVolumeControl() { 4681ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (!mVolumeSliderTouched) { 4691ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (isVolumeControlAvailable()) { 4701ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeControl.setVisibility(View.VISIBLE); 4711ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.setMax(mRoute.getVolumeMax()); 4721ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeSlider.setProgress(mRoute.getVolume()); 4731ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (USE_GROUP) { 4741ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (getGroup() == null) { 4751ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setVisibility(View.GONE); 4761ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 4771ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mGroupExpandCollapseButton.setVisibility(View.VISIBLE); 4781ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim VolumeGroupAdapter adapter = 4791ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim (VolumeGroupAdapter) mVolumeGroupList.getAdapter(); 4801ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (adapter != null) { 4811ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim adapter.notifyDataSetChanged(); 4821ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4831ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4841ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4851ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 4861ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mVolumeControl.setVisibility(View.GONE); 4871ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 488b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim updateControlLayoutHeight(); 4891ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4901ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 4911ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 4921ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim private void updatePlaybackControl() { 4931ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mCustomControlView == null && (mDescription != null || mState != null)) { 4941ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlaybackControl.setVisibility(View.VISIBLE); 4951ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim CharSequence title = mDescription == null ? null : mDescription.getTitle(); 4961ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean hasTitle = !TextUtils.isEmpty(title); 4971ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 4981ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle(); 4991ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean hasSubtitle = !TextUtils.isEmpty(subtitle); 5001ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 5011ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (!hasTitle && !hasSubtitle) { 5021ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mRoute.getPresentationDisplayId() 5031ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim != MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) { 5041ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // The user is currently casting screen. 5051ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setText(R.string.mr_controller_casting_screen); 5061ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 5071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setText((mState == null 5081ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim || mState.getState() == PlaybackStateCompat.STATE_NONE) 5091ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim ? R.string.mr_controller_no_media_selected 5101ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim : R.string.mr_controller_no_info_available); 5111ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 5121ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setEnabled(false); 5131ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setVisibility(View.VISIBLE); 5141ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mSubtitleView.setVisibility(View.GONE); 5151ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 5161ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setText(title); 5171ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setEnabled(hasTitle); 5181ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mTitleView.setVisibility(hasTitle ? View.VISIBLE : View.GONE); 5191ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mSubtitleView.setText(subtitle); 5201ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mSubtitleView.setVisibility(hasSubtitle ? View.VISIBLE : View.GONE); 5211ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 5221ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (mState != null) { 5231ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING 5241ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim || mState.getState() == PlaybackStateCompat.STATE_PLAYING; 5251ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY 5261ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; 5271ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE 5281ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; 5291ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (isPlaying && supportsPause) { 5301ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setVisibility(View.VISIBLE); 5311ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource( 5321ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim getContext(), R.attr.mediaRoutePauseDrawable)); 5331ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setContentDescription(getContext().getResources() 5341ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim .getText(R.string.mr_controller_pause)); 5351ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else if (!isPlaying && supportsPlay) { 5361ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setVisibility(View.VISIBLE); 5371ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource( 5381ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim getContext(), R.attr.mediaRoutePlayDrawable)); 5391ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setContentDescription(getContext().getResources() 5401ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim .getText(R.string.mr_controller_play)); 5411ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 5421ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlayPauseButton.setVisibility(View.GONE); 5431ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 5441ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 5451ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else { 5461ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mPlaybackControl.setVisibility(View.GONE); 5471ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 548b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim updateControlLayoutHeight(); 5491ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } 5501ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim 551b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim private void updateControlLayoutHeight() { 552b7b02f5cac8b760805d98ddbfe03e0730bee6709Sungsoo Lim // TODO: Update the top and bottom padding of the control layout according to the display 5531ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim // height. 5541ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mDividerView.setVisibility((mVolumeControl.getVisibility() == View.VISIBLE 5551ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim && mPlaybackControl.getVisibility() == View.VISIBLE) 5561ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim ? View.VISIBLE : View.GONE); 5571ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mControlLayout.setVisibility((mVolumeControl.getVisibility() == View.GONE 5581ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim && mPlaybackControl.getVisibility() == View.GONE) 5591ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim ? View.GONE : View.VISIBLE); 560f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 561f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 5622b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang private void updateControlFrameLayout() { 5632b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang if (!mNeedToAdjustControlFrameLayout) { 5642b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang return; 5652b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } 5662b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang int height; 5672b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang if (mArtView.getVisibility() == View.GONE) { 5682b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang height = LinearLayout.LayoutParams.WRAP_CONTENT; 5692b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } else if (!mIsGroupExpanded) { 5702b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang height = mArtView.getHeight() + mControlLayout.getHeight(); 5712b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } else { 5722b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang if (mVolumeGroupList.getAdapter().getCount() <= 2) { 5732b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang // Push the controls up and cover the artwork. 5742b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang height = mArtView.getHeight() + mControlLayout.getHeight() 5752b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang - mVolumeGroupList.getHeight(); 5762b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } else { 5772b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang // If there are 3 or more, the controls completely cover the artwork. 5782b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang height = mControlLayout.getHeight(); 5792b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } 5802b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } 58186a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo mDefaultControlLayout.setLayoutParams( 58286a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, height)); 5832b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang mNeedToAdjustControlFrameLayout = false; 5842b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang } 5852b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang 586f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private boolean isVolumeControlAvailable() { 587f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah return mVolumeControlEnabled && mRoute.getVolumeHandling() == 588f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE; 589f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 590f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 59113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim private void updateArtView() { 5922b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang mNeedToAdjustControlFrameLayout = true; 59313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (!(mArtView.getDrawable() instanceof BitmapDrawable)) { 594bfb90b6717bb46535d747aa50045a206965542d0Jae Seo mArtView.setVisibility(View.GONE); 59513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return; 59613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 59713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim Bitmap art = ((BitmapDrawable) mArtView.getDrawable()).getBitmap(); 59813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (art == null) { 599bfb90b6717bb46535d747aa50045a206965542d0Jae Seo mArtView.setVisibility(View.GONE); 60013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return; 60113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 60213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int desiredArtHeight = getDesiredArtHeight(art.getWidth(), art.getHeight()); 60313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics(); 60413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int dialogWidth = displayMetrics.widthPixels < displayMetrics.heightPixels 60513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim ? mDialogWidthPortrait : mDialogWidthLandscape; 60613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim View decorView = getWindow().getDecorView(); 60713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim decorView.measure(dialogWidth, View.MeasureSpec.UNSPECIFIED); 60813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Show art if and only if it fits in the screen. 60913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (mArtView.getVisibility() == View.GONE) { 61013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (decorView.getMeasuredHeight() + desiredArtHeight <= displayMetrics.heightPixels) { 61113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setVisibility(View.VISIBLE); 61213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setMaxHeight(desiredArtHeight); 61313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 61413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } else { 61513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (decorView.getMeasuredHeight() - mArtView.getMeasuredHeight() + desiredArtHeight 61613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim <= displayMetrics.heightPixels) { 61713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setMaxHeight(desiredArtHeight); 61813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } else { 61913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setVisibility(View.GONE); 62013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 62113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 62213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 62313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim 62486a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo private static void setVolumeSliderColor(SeekBar volumeSlider, int color) { 62586a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo volumeSlider.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN); 62686a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo if (Build.VERSION.SDK_INT >= 16) { 62786a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo SeekBarJellybean.getThumb(volumeSlider).setColorFilter(color, PorterDuff.Mode.SRC_IN); 62886a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo } 62986a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo } 63086a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo 63113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim /** 63213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim * Returns desired art height to fit into controller dialog. 63313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim */ 63413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim private int getDesiredArtHeight(int originalWidth, int originalHeight) { 6354ec1a0371ebb43ba1537354becb9241c105d2fb8Jaewan Kim int dialogWidth = getWindow().getAttributes().width - mDialogPaddingHorizontal; 63613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (originalWidth >= originalHeight) { 63713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // For landscape art, fit width to dialog width. 6385716b49c08ac172c06fdced848ec8ab599174970Jaewan Kim return (int) ((float) dialogWidth * originalHeight / originalWidth + 0.5f); 63913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 64013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // For portrait art, fit height to 16:9 ratio case's height. 6415716b49c08ac172c06fdced848ec8ab599174970Jaewan Kim return (int) ((float) dialogWidth * 9 / 16 + 0.5f); 64213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 64313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim 64411417b1cfde8f1749905f2d735623af9214148afJeff Brown private final class MediaRouterCallback extends MediaRouter.Callback { 64511417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 64611417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) { 64711417b1cfde8f1749905f2d735623af9214148afJeff Brown update(); 64811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 64911417b1cfde8f1749905f2d735623af9214148afJeff Brown 65011417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 65111417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) { 65211417b1cfde8f1749905f2d735623af9214148afJeff Brown update(); 65311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 65411417b1cfde8f1749905f2d735623af9214148afJeff Brown 65511417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 65611417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) { 65711417b1cfde8f1749905f2d735623af9214148afJeff Brown if (route == mRoute) { 6581ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim updateVolumeControl(); 65994be6100218126ce6a08bf1f56209578500b361fRoboErik } 66094be6100218126ce6a08bf1f56209578500b361fRoboErik } 66194be6100218126ce6a08bf1f56209578500b361fRoboErik } 66294be6100218126ce6a08bf1f56209578500b361fRoboErik 66394be6100218126ce6a08bf1f56209578500b361fRoboErik private final class MediaControllerCallback extends MediaControllerCompat.Callback { 66494be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 66594be6100218126ce6a08bf1f56209578500b361fRoboErik public void onSessionDestroyed() { 66694be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 66794be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.unregisterCallback(mControllerCallback); 66894be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = null; 66994be6100218126ce6a08bf1f56209578500b361fRoboErik } 67094be6100218126ce6a08bf1f56209578500b361fRoboErik } 67194be6100218126ce6a08bf1f56209578500b361fRoboErik 67294be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 67394be6100218126ce6a08bf1f56209578500b361fRoboErik public void onPlaybackStateChanged(PlaybackStateCompat state) { 67494be6100218126ce6a08bf1f56209578500b361fRoboErik mState = state; 67594be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 67694be6100218126ce6a08bf1f56209578500b361fRoboErik } 67794be6100218126ce6a08bf1f56209578500b361fRoboErik 67894be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 67994be6100218126ce6a08bf1f56209578500b361fRoboErik public void onMetadataChanged(MediaMetadataCompat metadata) { 68094be6100218126ce6a08bf1f56209578500b361fRoboErik mDescription = metadata == null ? null : metadata.getDescription(); 68194be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 68294be6100218126ce6a08bf1f56209578500b361fRoboErik } 68394be6100218126ce6a08bf1f56209578500b361fRoboErik } 68494be6100218126ce6a08bf1f56209578500b361fRoboErik 68594be6100218126ce6a08bf1f56209578500b361fRoboErik private final class ClickListener implements View.OnClickListener { 68694be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 68794be6100218126ce6a08bf1f56209578500b361fRoboErik public void onClick(View v) { 68894be6100218126ce6a08bf1f56209578500b361fRoboErik int id = v.getId(); 6891ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim if (id == R.id.mr_button_stop || id == R.id.mr_button_disconnect) { 69094be6100218126ce6a08bf1f56209578500b361fRoboErik if (mRoute.isSelected()) { 6911ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim mRouter.unselect(id == R.id.mr_button_stop ? 69294be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_STOPPED : 69394be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_DISCONNECTED); 69494be6100218126ce6a08bf1f56209578500b361fRoboErik } 69594be6100218126ce6a08bf1f56209578500b361fRoboErik dismiss(); 6967ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else if (id == R.id.mr_control_play_pause) { 69794be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null && mState != null) { 69894be6100218126ce6a08bf1f56209578500b361fRoboErik if (mState.getState() == PlaybackStateCompat.STATE_PLAYING) { 69994be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.getTransportControls().pause(); 70094be6100218126ce6a08bf1f56209578500b361fRoboErik } else { 70194be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.getTransportControls().play(); 70294be6100218126ce6a08bf1f56209578500b361fRoboErik } 70394be6100218126ce6a08bf1f56209578500b361fRoboErik } 7041ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim } else if (id == R.id.mr_close) { 705b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim dismiss(); 70611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 70711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 70811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 709005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 7106051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> { 7110e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo final static float DISABLED_ALPHA = .3f; 7120e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo 7136051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo final OnSeekBarChangeListener mOnSeekBarChangeListener = new OnSeekBarChangeListener() { 7146051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 7156051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 7166051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (fromUser) { 7176051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo int position = (int) seekBar.getTag(); 7186051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo getGroup().getRouteAt(position).requestSetVolume(progress); 7196051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7206051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7216051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7226051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 7236051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onStartTrackingTouch(SeekBar seekBar) { 7246051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo // TODO: Implement 7256051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7266051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7276051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 7286051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onStopTrackingTouch(SeekBar seekBar) { 7296051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo // TODO: Implement 7306051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7316051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo }; 7326051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7336051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public VolumeGroupAdapter(Context context, List<MediaRouter.RouteInfo> objects) { 7346051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo super(context, 0, objects); 7356051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7366051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7376051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 7386051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public View getView(final int position, View convertView, ViewGroup parent) { 7396051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo View v = convertView; 7406051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (v == null) { 7416051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo v = LayoutInflater.from(getContext()).inflate( 742a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim R.layout.mr_controller_volume_item, null); 74386a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo setVolumeSliderColor( 74486a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo (SeekBar) v.findViewById(R.id.mr_volume_slider), mVolumeSliderColor); 7456051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7466051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo MediaRouter.RouteInfo route = getItem(position); 7476051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (route != null) { 7480e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo boolean isEnabled = route.isEnabled(); 7490e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo 7507ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim TextView routeName = (TextView) v.findViewById(R.id.mr_name); 7510e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo routeName.setEnabled(isEnabled); 7520e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo routeName.setText(route.getName()); 7536051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7547ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim SeekBar volumeSlider = (SeekBar) v.findViewById(R.id.mr_volume_slider); 7550e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setEnabled(isEnabled); 7566051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo volumeSlider.setTag(position); 7570e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo if (isEnabled) { 7580e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo if (route.getVolumeHandling() 7590e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) { 7600e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setMax(route.getVolumeMax()); 7610e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setProgress(route.getVolume()); 7620e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setOnSeekBarChangeListener(mOnSeekBarChangeListener); 7630e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo } else { 7640e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setMax(100); 7650e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setProgress(100); 7660e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setEnabled(false); 7670e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo } 7680e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo } 769418c688351713e9349227262163eef752a8e7ce6Jae Seo if (Build.VERSION.SDK_INT >= 16) { 770418c688351713e9349227262163eef752a8e7ce6Jae Seo SeekBarJellybean.getThumb(volumeSlider).mutate().setAlpha(isEnabled ? 255 : 0); 771418c688351713e9349227262163eef752a8e7ce6Jae Seo // TODO: Still see an artifact even though the thumb is transparent. Remove it. 772418c688351713e9349227262163eef752a8e7ce6Jae Seo } 7730e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo 7740e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo ImageView volumeItemIcon = 7757ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim (ImageView) v.findViewById(R.id.mr_volume_item_icon); 77677367b4a1871417198d0399d9ad074314c758567Jae Seo volumeItemIcon.setAlpha(isEnabled ? 255 : (int) (255 * DISABLED_ALPHA)); 7776051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7786051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return v; 7796051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7806051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7816051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 782005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private class FetchArtTask extends AsyncTask<Void, Void, Bitmap> { 783005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private int mBackgroundColor; 784005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 785005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 786005482649154d0970693b3967241eb4d2cb22003Jaewan Kim protected Bitmap doInBackground(Void... arg) { 78713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim Bitmap art = null; 788005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mDescription == null) { 789005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 790005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 791005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mDescription.getIconBitmap() != null) { 79213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim art = mDescription.getIconBitmap(); 793005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } else if (mDescription.getIconUri() != null) { 794005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Uri iconUri = mDescription.getIconUri(); 795005482649154d0970693b3967241eb4d2cb22003Jaewan Kim String scheme = iconUri.getScheme(); 796005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (!(ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme) 797005482649154d0970693b3967241eb4d2cb22003Jaewan Kim || ContentResolver.SCHEME_CONTENT.equals(scheme) 798005482649154d0970693b3967241eb4d2cb22003Jaewan Kim || ContentResolver.SCHEME_FILE.equals(scheme))) { 799005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Log.w(TAG, "Icon Uri should point to local resources."); 800005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 801005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 802005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BufferedInputStream stream = null; 803005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 804005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream = new BufferedInputStream( 805005482649154d0970693b3967241eb4d2cb22003Jaewan Kim getContext().getContentResolver().openInputStream(iconUri)); 806005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 80713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Query art size. 808005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BitmapFactory.Options options = new BitmapFactory.Options(); 809005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inJustDecodeBounds = true; 810005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BitmapFactory.decodeStream(stream, null, options); 81113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (options.outWidth == 0 || options.outHeight == 0) { 81213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return null; 81313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 81413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Rewind the stream in order to restart art decoding. 815005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 816005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.reset(); 817005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e) { 818005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // Failed to rewind the stream, try to reopen it. 819005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.close(); 820005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream = new BufferedInputStream(getContext().getContentResolver() 821005482649154d0970693b3967241eb4d2cb22003Jaewan Kim .openInputStream(iconUri)); 822005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 82313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Calculate required size to decode the art and possibly resize it. 824005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inJustDecodeBounds = false; 82513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int reqHeight = getDesiredArtHeight(options.outWidth, options.outHeight); 82613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int ratio = options.outHeight / reqHeight; 827005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inSampleSize = Math.max(1, Integer.highestOneBit(ratio)); 828005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (isCancelled()) { 829005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 830005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 83113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim art = BitmapFactory.decodeStream(stream, null, options); 832005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e){ 833005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Log.w(TAG, "Unable to open content: " + iconUri, e); 834005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } finally { 835005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (stream != null) { 836005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 837005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.close(); 838005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e) { 839005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 840005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 841005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 842005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 843145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim if (art != null && art.getWidth() < art.getHeight()) { 844145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim // Portrait art requires background color. 845145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim Palette palette = new Palette.Builder(art).maximumColorCount(1).generate(); 846145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim mBackgroundColor = (palette.getSwatches() == null) 847145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim ? 0 : palette.getSwatches().get(0).getRgb(); 848005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 84913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return art; 850005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 851005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 852005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 853005482649154d0970693b3967241eb4d2cb22003Jaewan Kim protected void onCancelled() { 854005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = null; 855005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 856005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 857005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 85813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim protected void onPostExecute(Bitmap art) { 859005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = null; 86013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setImageBitmap(art); 86113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setBackgroundColor(mBackgroundColor); 86213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim updateArtView(); 863005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 864005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 8656051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo} 866