• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.support.v4.media.session;
17 
18 import android.os.Build;
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 import android.os.SystemClock;
22 import android.text.TextUtils;
23 
24 /**
25  * Playback state for a {@link MediaSessionCompat}. This includes a state like
26  * {@link PlaybackStateCompat#STATE_PLAYING}, the current playback position,
27  * and the current control capabilities.
28  */
29 public final class PlaybackStateCompat implements Parcelable {
30 
31     /**
32      * Indicates this session supports the stop command.
33      *
34      * @see Builder#setActions(long)
35      */
36     public static final long ACTION_STOP = 1 << 0;
37 
38     /**
39      * Indicates this session supports the pause command.
40      *
41      * @see Builder#setActions(long)
42      */
43     public static final long ACTION_PAUSE = 1 << 1;
44 
45     /**
46      * Indicates this session supports the play command.
47      *
48      * @see Builder#setActions(long)
49      */
50     public static final long ACTION_PLAY = 1 << 2;
51 
52     /**
53      * Indicates this session supports the rewind command.
54      *
55      * @see Builder#setActions(long)
56      */
57     public static final long ACTION_REWIND = 1 << 3;
58 
59     /**
60      * Indicates this session supports the previous command.
61      *
62      * @see Builder#setActions(long)
63      */
64     public static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4;
65 
66     /**
67      * Indicates this session supports the next command.
68      *
69      * @see Builder#setActions(long)
70      */
71     public static final long ACTION_SKIP_TO_NEXT = 1 << 5;
72 
73     /**
74      * Indicates this session supports the fast forward command.
75      *
76      * @see Builder#setActions(long)
77      */
78     public static final long ACTION_FAST_FORWARD = 1 << 6;
79 
80     /**
81      * Indicates this session supports the set rating command.
82      *
83      * @see Builder#setActions(long)
84      */
85     public static final long ACTION_SET_RATING = 1 << 7;
86 
87     /**
88      * Indicates this session supports the seek to command.
89      *
90      * @see Builder#setActions(long)
91      */
92     public static final long ACTION_SEEK_TO = 1 << 8;
93 
94     /**
95      * Indicates this session supports the play/pause toggle command.
96      *
97      * @see Builder#setActions(long)
98      */
99     public static final long ACTION_PLAY_PAUSE = 1 << 9;
100 
101     /**
102      * Indicates this session supports the play from media id command.
103      *
104      * @see Builder#setActions(long)
105      */
106     public static final long ACTION_PLAY_FROM_MEDIA_ID = 1 << 10;
107 
108     /**
109      * Indicates this session supports the play from search command.
110      *
111      * @see Builder#setActions(long)
112      */
113     public static final long ACTION_PLAY_FROM_SEARCH = 1 << 11;
114 
115     /**
116      * Indicates this session supports the skip to queue item command.
117      *
118      * @see Builder#setActions(long)
119      */
120     public static final long ACTION_SKIP_TO_QUEUE_ITEM = 1 << 12;
121 
122     /**
123      * This is the default playback state and indicates that no media has been
124      * added yet, or the performer has been reset and has no content to play.
125      *
126      * @see Builder#setState
127      */
128     public final static int STATE_NONE = 0;
129 
130     /**
131      * State indicating this item is currently stopped.
132      *
133      * @see Builder#setState
134      */
135     public final static int STATE_STOPPED = 1;
136 
137     /**
138      * State indicating this item is currently paused.
139      *
140      * @see Builder#setState
141      */
142     public final static int STATE_PAUSED = 2;
143 
144     /**
145      * State indicating this item is currently playing.
146      *
147      * @see Builder#setState
148      */
149     public final static int STATE_PLAYING = 3;
150 
151     /**
152      * State indicating this item is currently fast forwarding.
153      *
154      * @see Builder#setState
155      */
156     public final static int STATE_FAST_FORWARDING = 4;
157 
158     /**
159      * State indicating this item is currently rewinding.
160      *
161      * @see Builder#setState
162      */
163     public final static int STATE_REWINDING = 5;
164 
165     /**
166      * State indicating this item is currently buffering and will begin playing
167      * when enough data has buffered.
168      *
169      * @see Builder#setState
170      */
171     public final static int STATE_BUFFERING = 6;
172 
173     /**
174      * State indicating this item is currently in an error state. The error
175      * message should also be set when entering this state.
176      *
177      * @see Builder#setState
178      */
179     public final static int STATE_ERROR = 7;
180 
181     /**
182      * State indicating the class doing playback is currently connecting to a
183      * route. Depending on the implementation you may return to the previous
184      * state when the connection finishes or enter {@link #STATE_NONE}. If
185      * the connection failed {@link #STATE_ERROR} should be used.
186      * @hide
187      */
188     public final static int STATE_CONNECTING = 8;
189 
190     /**
191      * State indicating the player is currently skipping to the previous item.
192      *
193      * @see Builder#setState
194      */
195     public final static int STATE_SKIPPING_TO_PREVIOUS = 9;
196 
197     /**
198      * State indicating the player is currently skipping to the next item.
199      *
200      * @see Builder#setState
201      */
202     public final static int STATE_SKIPPING_TO_NEXT = 10;
203 
204     /**
205      * Use this value for the position to indicate the position is not known.
206      */
207     public final static long PLAYBACK_POSITION_UNKNOWN = -1;
208 
209     private final int mState;
210     private final long mPosition;
211     private final long mBufferedPosition;
212     private final float mSpeed;
213     private final long mActions;
214     private final CharSequence mErrorMessage;
215     private final long mUpdateTime;
216 
217     private Object mStateObj;
218 
PlaybackStateCompat(int state, long position, long bufferedPosition, float rate, long actions, CharSequence errorMessage, long updateTime)219     private PlaybackStateCompat(int state, long position, long bufferedPosition,
220             float rate, long actions, CharSequence errorMessage, long updateTime) {
221         mState = state;
222         mPosition = position;
223         mBufferedPosition = bufferedPosition;
224         mSpeed = rate;
225         mActions = actions;
226         mErrorMessage = errorMessage;
227         mUpdateTime = updateTime;
228     }
229 
PlaybackStateCompat(Parcel in)230     private PlaybackStateCompat(Parcel in) {
231         mState = in.readInt();
232         mPosition = in.readLong();
233         mSpeed = in.readFloat();
234         mUpdateTime = in.readLong();
235         mBufferedPosition = in.readLong();
236         mActions = in.readLong();
237         mErrorMessage = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
238     }
239 
240     @Override
toString()241     public String toString() {
242         StringBuilder bob = new StringBuilder("PlaybackState {");
243         bob.append("state=").append(mState);
244         bob.append(", position=").append(mPosition);
245         bob.append(", buffered position=").append(mBufferedPosition);
246         bob.append(", speed=").append(mSpeed);
247         bob.append(", updated=").append(mUpdateTime);
248         bob.append(", actions=").append(mActions);
249         bob.append(", error=").append(mErrorMessage);
250         bob.append("}");
251         return bob.toString();
252     }
253 
254     @Override
describeContents()255     public int describeContents() {
256         return 0;
257     }
258 
259     @Override
writeToParcel(Parcel dest, int flags)260     public void writeToParcel(Parcel dest, int flags) {
261         dest.writeInt(mState);
262         dest.writeLong(mPosition);
263         dest.writeFloat(mSpeed);
264         dest.writeLong(mUpdateTime);
265         dest.writeLong(mBufferedPosition);
266         dest.writeLong(mActions);
267         TextUtils.writeToParcel(mErrorMessage, dest, flags);
268     }
269 
270     /**
271      * Get the current state of playback. One of the following:
272      * <ul>
273      * <li> {@link PlaybackStateCompat#STATE_NONE}</li>
274      * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li>
275      * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li>
276      * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li>
277      * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li>
278      * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li>
279      * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li>
280      * <li> {@link PlaybackStateCompat#STATE_ERROR}</li>
281      */
getState()282     public int getState() {
283         return mState;
284     }
285 
286     /**
287      * Get the current playback position in ms.
288      */
getPosition()289     public long getPosition() {
290         return mPosition;
291     }
292 
293     /**
294      * Get the current buffered position in ms. This is the farthest playback
295      * point that can be reached from the current position using only buffered
296      * content.
297      */
getBufferedPosition()298     public long getBufferedPosition() {
299         return mBufferedPosition;
300     }
301 
302     /**
303      * Get the current playback speed as a multiple of normal playback. This
304      * should be negative when rewinding. A value of 1 means normal playback and
305      * 0 means paused.
306      *
307      * @return The current speed of playback.
308      */
getPlaybackSpeed()309     public float getPlaybackSpeed() {
310         return mSpeed;
311     }
312 
313     /**
314      * Get the current actions available on this session. This should use a
315      * bitmask of the available actions.
316      * <ul>
317      * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}</li>
318      * <li> {@link PlaybackStateCompat#ACTION_REWIND}</li>
319      * <li> {@link PlaybackStateCompat#ACTION_PLAY}</li>
320      * <li> {@link PlaybackStateCompat#ACTION_PAUSE}</li>
321      * <li> {@link PlaybackStateCompat#ACTION_STOP}</li>
322      * <li> {@link PlaybackStateCompat#ACTION_FAST_FORWARD}</li>
323      * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT}</li>
324      * <li> {@link PlaybackStateCompat#ACTION_SEEK_TO}</li>
325      * <li> {@link PlaybackStateCompat#ACTION_SET_RATING}</li>
326      * </ul>
327      */
getActions()328     public long getActions() {
329         return mActions;
330     }
331 
332     /**
333      * Get a user readable error message. This should be set when the state is
334      * {@link PlaybackStateCompat#STATE_ERROR}.
335      */
getErrorMessage()336     public CharSequence getErrorMessage() {
337         return mErrorMessage;
338     }
339 
340     /**
341      * Get the elapsed real time at which position was last updated. If the
342      * position has never been set this will return 0;
343      *
344      * @return The last time the position was updated.
345      */
getLastPositionUpdateTime()346     public long getLastPositionUpdateTime() {
347         return mUpdateTime;
348     }
349 
350     /**
351      * Creates an instance from a framework {@link android.media.session.PlaybackState} object.
352      * <p>
353      * This method is only supported on API 21+.
354      * </p>
355      *
356      * @param stateObj A {@link android.media.session.PlaybackState} object, or null if none.
357      * @return An equivalent {@link PlaybackStateCompat} object, or null if none.
358      */
fromPlaybackState(Object stateObj)359     public static PlaybackStateCompat fromPlaybackState(Object stateObj) {
360         if (stateObj == null || Build.VERSION.SDK_INT < 21) {
361             return null;
362         }
363 
364         PlaybackStateCompat state = new PlaybackStateCompat(
365                 PlaybackStateCompatApi21.getState(stateObj),
366                 PlaybackStateCompatApi21.getPosition(stateObj),
367                 PlaybackStateCompatApi21.getBufferedPosition(stateObj),
368                 PlaybackStateCompatApi21.getPlaybackSpeed(stateObj),
369                 PlaybackStateCompatApi21.getActions(stateObj),
370                 PlaybackStateCompatApi21.getErrorMessage(stateObj),
371                 PlaybackStateCompatApi21.getLastPositionUpdateTime(stateObj));
372         state.mStateObj = stateObj;
373         return state;
374     }
375 
376     /**
377      * Gets the underlying framework {@link android.media.session.PlaybackState} object.
378      * <p>
379      * This method is only supported on API 21+.
380      * </p>
381      *
382      * @return An equivalent {@link android.media.session.PlaybackState} object, or null if none.
383      */
getPlaybackState()384     public Object getPlaybackState() {
385         if (mStateObj != null || Build.VERSION.SDK_INT < 21) {
386             return mStateObj;
387         }
388 
389         mStateObj = PlaybackStateCompatApi21.newInstance(mState, mPosition, mBufferedPosition,
390                 mSpeed, mActions, mErrorMessage, mUpdateTime);
391         return mStateObj;
392     }
393 
394     public static final Parcelable.Creator<PlaybackStateCompat> CREATOR =
395             new Parcelable.Creator<PlaybackStateCompat>() {
396         @Override
397         public PlaybackStateCompat createFromParcel(Parcel in) {
398             return new PlaybackStateCompat(in);
399         }
400 
401         @Override
402         public PlaybackStateCompat[] newArray(int size) {
403             return new PlaybackStateCompat[size];
404         }
405     };
406 
407     /**
408      * Builder for {@link PlaybackStateCompat} objects.
409      */
410     public static final class Builder {
411         private int mState;
412         private long mPosition;
413         private long mBufferedPosition;
414         private float mRate;
415         private long mActions;
416         private CharSequence mErrorMessage;
417         private long mUpdateTime;
418 
419         /**
420          * Create an empty Builder.
421          */
Builder()422         public Builder() {
423         }
424 
425         /**
426          * Create a Builder using a {@link PlaybackStateCompat} instance to set the
427          * initial values.
428          *
429          * @param source The playback state to copy.
430          */
Builder(PlaybackStateCompat source)431         public Builder(PlaybackStateCompat source) {
432             mState = source.mState;
433             mPosition = source.mPosition;
434             mRate = source.mSpeed;
435             mUpdateTime = source.mUpdateTime;
436             mBufferedPosition = source.mBufferedPosition;
437             mActions = source.mActions;
438             mErrorMessage = source.mErrorMessage;
439         }
440 
441         /**
442          * Set the current state of playback.
443          * <p>
444          * The position must be in ms and indicates the current playback position
445          * within the track. If the position is unknown use
446          * {@link #PLAYBACK_POSITION_UNKNOWN}.
447          * <p>
448          * The rate is a multiple of normal playback and should be 0 when paused and
449          * negative when rewinding. Normal playback rate is 1.0.
450          * <p>
451          * The state must be one of the following:
452          * <ul>
453          * <li> {@link PlaybackStateCompat#STATE_NONE}</li>
454          * <li> {@link PlaybackStateCompat#STATE_STOPPED}</li>
455          * <li> {@link PlaybackStateCompat#STATE_PLAYING}</li>
456          * <li> {@link PlaybackStateCompat#STATE_PAUSED}</li>
457          * <li> {@link PlaybackStateCompat#STATE_FAST_FORWARDING}</li>
458          * <li> {@link PlaybackStateCompat#STATE_REWINDING}</li>
459          * <li> {@link PlaybackStateCompat#STATE_BUFFERING}</li>
460          * <li> {@link PlaybackStateCompat#STATE_ERROR}</li>
461          * </ul>
462          *
463          * @param state The current state of playback.
464          * @param position The position in the current track in ms.
465          * @param playbackRate The current rate of playback as a multiple of normal
466          *            playback.
467          */
setState(int state, long position, float playbackRate)468         public void setState(int state, long position, float playbackRate) {
469             this.mState = state;
470             this.mPosition = position;
471             this.mRate = playbackRate;
472             mUpdateTime = SystemClock.elapsedRealtime();
473         }
474 
475         /**
476          * Set the current buffered position in ms. This is the farthest
477          * playback point that can be reached from the current position using
478          * only buffered content.
479          */
setBufferedPosition(long bufferPosition)480         public void setBufferedPosition(long bufferPosition) {
481             mBufferedPosition = bufferPosition;
482         }
483 
484         /**
485          * Set the current capabilities available on this session. This should use a
486          * bitmask of the available capabilities.
487          * <ul>
488          * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_PREVIOUS}</li>
489          * <li> {@link PlaybackStateCompat#ACTION_REWIND}</li>
490          * <li> {@link PlaybackStateCompat#ACTION_PLAY}</li>
491          * <li> {@link PlaybackStateCompat#ACTION_PAUSE}</li>
492          * <li> {@link PlaybackStateCompat#ACTION_STOP}</li>
493          * <li> {@link PlaybackStateCompat#ACTION_FAST_FORWARD}</li>
494          * <li> {@link PlaybackStateCompat#ACTION_SKIP_TO_NEXT}</li>
495          * <li> {@link PlaybackStateCompat#ACTION_SEEK_TO}</li>
496          * <li> {@link PlaybackStateCompat#ACTION_SET_RATING}</li>
497          * </ul>
498          */
setActions(long capabilities)499         public void setActions(long capabilities) {
500             mActions = capabilities;
501         }
502 
503         /**
504          * Set a user readable error message. This should be set when the state is
505          * {@link PlaybackStateCompat#STATE_ERROR}.
506          */
setErrorMessage(CharSequence errorMessage)507         public void setErrorMessage(CharSequence errorMessage) {
508             mErrorMessage = errorMessage;
509         }
510 
511         /**
512          * Creates the playback state object.
513          */
build()514         public PlaybackStateCompat build() {
515             return new PlaybackStateCompat(mState, mPosition, mBufferedPosition,
516                     mRate, mActions, mErrorMessage, mUpdateTime);
517         }
518     }
519 }
520