Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
      5  * in compliance with the License. You may obtain a copy of the License at
      6  *
      7  * http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the License
     10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
     11  * or implied. See the License for the specific language governing permissions and limitations under
     12  * the License.
     13  */
     14 
     15 package android.support.v17.leanback.supportleanbackshowcase.app.media;
     16 
     17 import android.content.Context;
     18 import android.content.res.Resources;
     19 import android.graphics.drawable.Drawable;
     20 import android.net.Uri;
     21 import android.os.Bundle;
     22 import android.support.v17.leanback.app.PlaybackOverlayFragment;
     23 import android.support.v17.leanback.supportleanbackshowcase.utils.Constants;
     24 import android.support.v17.leanback.supportleanbackshowcase.R;
     25 import android.support.v17.leanback.supportleanbackshowcase.utils.Utils;
     26 import android.support.v17.leanback.supportleanbackshowcase.models.Song;
     27 import android.support.v17.leanback.supportleanbackshowcase.models.SongList;
     28 import android.support.v17.leanback.widget.*;
     29 import android.support.v17.leanback.widget.AbstractMediaItemPresenter;
     30 import android.util.Log;
     31 
     32 import com.google.gson.Gson;
     33 
     34 import java.util.List;
     35 
     36 /**
     37  * This example shows how to play music files and build a simple track list.
     38  */
     39 public class MusicConsumptionExampleFragment extends PlaybackOverlayFragment implements
     40         BaseOnItemViewClickedListener, BaseOnItemViewSelectedListener,
     41         MediaPlayerGlue.OnMediaFileFinishedPlayingListener {
     42 
     43     private static final String TAG = "MusicConsumptionExampleFragment";
     44     private static final int PLAYLIST_ACTION_ID = 0;
     45     private static final int FAVORITE_ACTION_ID = 1;
     46     private ArrayObjectAdapter mRowsAdapter;
     47     private MediaPlayerGlue mGlue;
     48     private int mCurrentSongIndex = 0;
     49     private List<Song> mSongList;
     50     private boolean mAdapterNotified = false;
     51 
     52     @Override public void onCreate(Bundle savedInstanceState) {
     53         super.onCreate(savedInstanceState);
     54         if (Constants.LOCAL_LOGD) Log.d(TAG, "onCreate");
     55 
     56         mGlue = new MediaPlayerGlue(getActivity(), this) {
     57 
     58             @Override protected void onRowChanged(PlaybackControlsRow row) {
     59                 if (mRowsAdapter == null || mAdapterNotified) return;
     60                 //mAdapterNotified = true;
     61                 mRowsAdapter.notifyArrayItemRangeChanged(0, 1);
     62             }
     63         };
     64         mGlue.setOnMediaFileFinishedPlayingListener(this);
     65 
     66         String json = Utils.inputStreamToString(
     67                 getResources().openRawResource(R.raw.music_consumption_example));
     68 
     69 
     70         mSongList = new Gson().fromJson(json, SongList.class).getSongs();
     71 
     72         Resources res = getActivity().getResources();
     73 
     74         // For each song add a playlist and favorite actions.
     75         for(Song song : mSongList) {
     76             MultiActionsProvider.MultiAction[] mediaRowActions = new
     77                     MultiActionsProvider.MultiAction[2];
     78             MultiActionsProvider.MultiAction playlistAction = new
     79                     MultiActionsProvider.MultiAction(PLAYLIST_ACTION_ID);
     80             Drawable[] playlistActionDrawables = new Drawable[] {
     81                     res.getDrawable(R.drawable.ic_playlist_add_white_24dp,
     82                             getActivity().getTheme()),
     83                     res.getDrawable(R.drawable.ic_playlist_add_filled_24dp,
     84                             getActivity().getTheme())};
     85             playlistAction.setDrawables(playlistActionDrawables);
     86             mediaRowActions[0] = playlistAction;
     87 
     88             MultiActionsProvider.MultiAction favoriteAction = new
     89                     MultiActionsProvider.MultiAction(FAVORITE_ACTION_ID);
     90             Drawable[] favoriteActionDrawables = new Drawable[] {
     91                     res.getDrawable(R.drawable.ic_favorite_border_white_24dp,
     92                             getActivity().getTheme()),
     93                     res.getDrawable(R.drawable.ic_favorite_filled_24dp,
     94                             getActivity().getTheme())};
     95             favoriteAction.setDrawables(favoriteActionDrawables);
     96             mediaRowActions[1] = favoriteAction;
     97             song.setMediaRowActions(mediaRowActions);
     98         }
     99 
    100         Song song = mSongList.get(mCurrentSongIndex);
    101         MediaPlayerGlue.MetaData metaData = new MediaPlayerGlue.MetaData();
    102         metaData.setArtist(song.getDescription());
    103         metaData.setTitle(song.getTitle());
    104         metaData.setCover(getResources().getDrawable(song.getImageResource(getActivity()), null));
    105         Uri uri = Utils.getResourceUri(getActivity(), song.getFileResource(getActivity()));
    106         mGlue.setMetaData(metaData);
    107         mGlue.setMediaSource(uri);
    108         mGlue.prepareMediaForPlaying();
    109 
    110         addPlaybackControlsRow();
    111     }
    112 
    113     @Override public void onStart() {
    114         super.onStart();
    115         mGlue.enableProgressUpdating(mGlue.hasValidMedia() && mGlue.isMediaPlaying());
    116     }
    117 
    118     @Override public void onStop() {
    119         super.onStop();
    120         mGlue.enableProgressUpdating(false);
    121         mGlue.reset();
    122     }
    123 
    124     static class SongPresenter extends AbstractMediaItemPresenter {
    125 
    126         SongPresenter() {
    127             super();
    128         }
    129 
    130         SongPresenter(Context context, int themeResId) {
    131             super(themeResId);
    132             setHasMediaRowSeparator(true);
    133         }
    134 
    135         @Override
    136         protected void onBindMediaDetails(ViewHolder vh, Object item) {
    137 
    138             int favoriteTextColor =  vh.view.getContext().getResources().getColor(
    139                     R.color.song_row_favorite_color);
    140             Song song = (Song) item;
    141             vh.getMediaItemNumberView().setText("" + song.getNumber());
    142 
    143             String songTitle = song.getTitle() + " / " + song.getDescription();
    144             vh.getMediaItemNameView().setText(songTitle);
    145 
    146             vh.getMediaItemDurationView().setText("" + song.getDuration());
    147 
    148             if (song.isFavorite()) {
    149                 vh.getMediaItemNumberView().setTextColor(favoriteTextColor);
    150                 vh.getMediaItemNameView().setTextColor(favoriteTextColor);
    151                 vh.getMediaItemDurationView().setTextColor(favoriteTextColor);
    152             } else {
    153                 Context context = vh.getMediaItemNumberView().getContext();
    154                 vh.getMediaItemNumberView().setTextAppearance(context,
    155                         R.style.TextAppearance_Leanback_PlaybackMediaItemNumber);
    156                 vh.getMediaItemNameView().setTextAppearance(context,
    157                         R.style.TextAppearance_Leanback_PlaybackMediaItemName);
    158                 vh.getMediaItemDurationView().setTextAppearance(context,
    159                         R.style.TextAppearance_Leanback_PlaybackMediaItemDuration);
    160             }
    161         }
    162     };
    163 
    164     static class SongPresenterSelector extends PresenterSelector {
    165         Presenter mRegularPresenter;
    166         Presenter mFavoritePresenter;
    167 
    168         /**
    169          * Adds a presenter to be used for the given class.
    170          */
    171         public SongPresenterSelector setSongPresenterRegular(Presenter presenter) {
    172             mRegularPresenter = presenter;
    173             return this;
    174         }
    175 
    176         /**
    177          * Adds a presenter to be used for the given class.
    178          */
    179         public SongPresenterSelector setSongPresenterFavorite(Presenter presenter) {
    180             mFavoritePresenter = presenter;
    181             return this;
    182         }
    183 
    184         @Override
    185         public Presenter[] getPresenters() {
    186             return new Presenter[]{mRegularPresenter, mFavoritePresenter};
    187         }
    188 
    189         @Override
    190         public Presenter getPresenter(Object item) {
    191             return ( (Song) item).isFavorite() ? mFavoritePresenter : mRegularPresenter;
    192         }
    193 
    194     }
    195 
    196     static class TrackListHeaderPresenter extends AbstractMediaListHeaderPresenter {
    197 
    198         TrackListHeaderPresenter() {
    199             super();
    200         }
    201 
    202         @Override
    203         protected void onBindMediaListHeaderViewHolder(ViewHolder vh, Object item) {
    204             vh.getHeaderView().setText("Tracklist");
    205         }
    206     };
    207 
    208     private void addPlaybackControlsRow() {
    209         mRowsAdapter = new ArrayObjectAdapter(new ClassPresenterSelector()
    210                 .addClassPresenterSelector(Song.class, new SongPresenterSelector()
    211                         .setSongPresenterRegular(new SongPresenter(getActivity(),
    212                                 R.style.Theme_Example_LeanbackMusic_RegularSongNumbers))
    213                         .setSongPresenterFavorite(new SongPresenter(getActivity(),
    214                                 R.style.Theme_Example_LeanbackMusic_FavoriteSongNumbers)))
    215                 .addClassPresenter(TrackListHeader.class, new TrackListHeaderPresenter())
    216                 .addClassPresenter(PlaybackControlsRow.class,
    217                         mGlue.createControlsRowAndPresenter()));
    218         mRowsAdapter.add(mGlue.getControlsRow());
    219         mRowsAdapter.add(new TrackListHeader());
    220         mRowsAdapter.addAll(2, mSongList);
    221         setAdapter(mRowsAdapter);
    222         setOnItemViewClickedListener(this);
    223         setOnItemViewSelectedListener(this);
    224     }
    225 
    226     public MusicConsumptionExampleFragment() {
    227         super();
    228     }
    229 
    230 
    231 
    232     @Override public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
    233                                         RowPresenter.ViewHolder rowViewHolder, Object row) {
    234 
    235         if (item instanceof  Action) {
    236             // if the clicked item is a primary or secondary action in the playback controller
    237             mGlue.onActionClicked((Action) item);
    238         } else if (row instanceof  Song) {
    239             // if a media item row is clicked
    240             Song clickedSong = (Song) row;
    241             AbstractMediaItemPresenter.ViewHolder songRowVh =
    242                     (AbstractMediaItemPresenter.ViewHolder) rowViewHolder;
    243 
    244             // if an action within a media item row is clicked
    245             if (item instanceof MultiActionsProvider.MultiAction) {
    246                 if ( ((MultiActionsProvider.MultiAction) item).getId() == FAVORITE_ACTION_ID) {
    247                     MultiActionsProvider.MultiAction favoriteAction =
    248                             (MultiActionsProvider.MultiAction) item;
    249                     MultiActionsProvider.MultiAction playlistAction =
    250                             songRowVh.getMediaItemRowActions()[0];
    251                     favoriteAction.incrementIndex();
    252                     playlistAction.incrementIndex();;
    253 
    254                     clickedSong.setFavorite(!clickedSong.isFavorite());
    255                     songRowVh.notifyDetailsChanged();
    256                     songRowVh.notifyActionChanged(playlistAction);
    257                     songRowVh.notifyActionChanged(favoriteAction);
    258                 }
    259             } else if (item == null){
    260                 // if a media item details is clicked, start playing that media item
    261                 onSongDetailsClicked(clickedSong);
    262             }
    263 
    264         }
    265 
    266 
    267     }
    268 
    269     @Override
    270     public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
    271                                RowPresenter.ViewHolder rowViewHolder, Object row) {
    272     }
    273 
    274 
    275     public void onSongDetailsClicked(Song song) {
    276         int nextSongIndex = mSongList.indexOf(song);
    277         mCurrentSongIndex = nextSongIndex;
    278         startPlayback();
    279     }
    280 
    281 
    282     @Override public void onMediaFileFinishedPlaying(MediaPlayerGlue.MetaData song) {
    283         if (mGlue.repeatOne()) {
    284         } else if (mGlue.useShuffle()) {
    285             mCurrentSongIndex = (int) (Math.random() * mSongList.size());
    286         } else {
    287             mCurrentSongIndex++;
    288             if (mCurrentSongIndex >= mSongList.size()) {
    289                 mCurrentSongIndex = 0;
    290                 if (!mGlue.repeatAll()) {
    291                     return;
    292                 }
    293             }
    294         }
    295         startPlayback();
    296     }
    297 
    298     private void startPlayback() {
    299         Song song = mSongList.get(mCurrentSongIndex);
    300         MediaPlayerGlue.MetaData metaData = new MediaPlayerGlue.MetaData();
    301         metaData.setArtist(song.getDescription());
    302         metaData.setTitle(song.getTitle());
    303         metaData.setCover(getResources().getDrawable(song.getImageResource(getActivity()), null));
    304 
    305         Uri uri = Utils.getResourceUri(getActivity(), song.getFileResource(getActivity()));
    306         mGlue.setMetaData(metaData);
    307 
    308         if (mGlue.setMediaSource(uri)) {
    309             mGlue.prepareMediaForPlaying();
    310         }
    311         mGlue.startPlayback();
    312     }
    313 }
    314