PlaybackControlsRow.java revision a00bada00bff4a58436a39472ab14ccb7a8f619d
1/* 2 * Copyright (C) 2014 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 */ 14package android.support.v17.leanback.widget; 15 16import android.support.v17.leanback.R; 17import android.util.TypedValue; 18import android.content.Context; 19import android.content.res.TypedArray; 20import android.graphics.Bitmap; 21import android.graphics.BitmapFactory; 22import android.graphics.Canvas; 23import android.graphics.Color; 24import android.graphics.Paint; 25import android.graphics.PorterDuff; 26import android.graphics.PorterDuffColorFilter; 27import android.graphics.drawable.BitmapDrawable; 28import android.graphics.drawable.Drawable; 29import android.view.KeyEvent; 30 31/** 32 * A {@link Row} of playback controls to be displayed by a {@link PlaybackControlsRowPresenter}. 33 * 34 * This row consists of some optional item detail, a series of primary actions, 35 * and an optional series of secondary actions. 36 * 37 * <p> 38 * Controls are specified via an {@link ObjectAdapter} containing one or more 39 * {@link Action}s. 40 * </p> 41 * <p> 42 * Adapters should have their {@link PresenterSelector} set to an instance of 43 * {@link ControlButtonPresenterSelector}. 44 * </p> 45 */ 46public class PlaybackControlsRow extends Row { 47 48 /** 49 * Base class for an action comprised of a series of icons. 50 */ 51 public static abstract class MultiAction extends Action { 52 private int mIndex; 53 private Drawable[] mDrawables; 54 private String[] mLabels; 55 private String[] mLabels2; 56 57 /** 58 * Constructor 59 * @param id The id of the Action. 60 */ 61 public MultiAction(int id) { 62 super(id); 63 } 64 65 /** 66 * Sets the array of drawables. The size of the array defines the range 67 * of valid indices for this action. 68 */ 69 public void setDrawables(Drawable[] drawables) { 70 mDrawables = drawables; 71 setIndex(0); 72 } 73 74 /** 75 * Sets the array of strings used as labels. The size of the array defines the range 76 * of valid indices for this action. The labels are used to define the accessibility 77 * content description unless secondary labels are provided. 78 */ 79 public void setLabels(String[] labels) { 80 mLabels = labels; 81 setIndex(0); 82 } 83 84 /** 85 * Sets the array of strings used as secondary labels. These labels are used 86 * in place of the primary labels for accessibility content description only. 87 */ 88 public void setSecondaryLabels(String[] labels) { 89 mLabels2 = labels; 90 setIndex(0); 91 } 92 93 /** 94 * Returns the number of actions. 95 */ 96 public int getActionCount() { 97 if (mDrawables != null) { 98 return mDrawables.length; 99 } 100 if (mLabels != null) { 101 return mLabels.length; 102 } 103 return 0; 104 } 105 106 /** 107 * Returns the drawable at the given index. 108 */ 109 public Drawable getDrawable(int index) { 110 return mDrawables == null ? null : mDrawables[index]; 111 } 112 113 /** 114 * Returns the label at the given index. 115 */ 116 public String getLabel(int index) { 117 return mLabels == null ? null : mLabels[index]; 118 } 119 120 /** 121 * Returns the secondary label at the given index. 122 */ 123 public String getSecondaryLabel(int index) { 124 return mLabels2 == null ? null : mLabels2[index]; 125 } 126 127 /** 128 * Increments the index, wrapping to zero once the end is reached. 129 */ 130 public void nextIndex() { 131 setIndex(mIndex < getActionCount() - 1 ? mIndex + 1 : 0); 132 } 133 134 /** 135 * Sets the current index. 136 */ 137 public void setIndex(int index) { 138 mIndex = index; 139 if (mDrawables != null) { 140 setIcon(mDrawables[mIndex]); 141 } 142 if (mLabels != null) { 143 setLabel1(mLabels[mIndex]); 144 } 145 if (mLabels2 != null) { 146 setLabel2(mLabels2[mIndex]); 147 } 148 } 149 150 /** 151 * Returns the current index. 152 */ 153 public int getIndex() { 154 return mIndex; 155 } 156 } 157 158 /** 159 * An action displaying icons for play and pause. 160 */ 161 public static class PlayPauseAction extends MultiAction { 162 /** 163 * Action index for the play icon. 164 */ 165 public static int PLAY = 0; 166 167 /** 168 * Action index for the pause icon. 169 */ 170 public static int PAUSE = 1; 171 172 /** 173 * Constructor 174 * @param context Context used for loading resources. 175 */ 176 public PlayPauseAction(Context context) { 177 super(R.id.lb_control_play_pause); 178 Drawable[] drawables = new Drawable[2]; 179 drawables[PLAY] = getStyledDrawable(context, 180 R.styleable.lbPlaybackControlsActionIcons_play); 181 drawables[PAUSE] = getStyledDrawable(context, 182 R.styleable.lbPlaybackControlsActionIcons_pause); 183 setDrawables(drawables); 184 185 String[] labels = new String[drawables.length]; 186 labels[PLAY] = context.getString(R.string.lb_playback_controls_play); 187 labels[PAUSE] = context.getString(R.string.lb_playback_controls_pause); 188 setLabels(labels); 189 addKeyCode(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE); 190 addKeyCode(KeyEvent.KEYCODE_MEDIA_PLAY); 191 addKeyCode(KeyEvent.KEYCODE_MEDIA_PAUSE); 192 } 193 } 194 195 /** 196 * An action displaying an icon for fast forward. 197 */ 198 public static class FastForwardAction extends MultiAction { 199 /** 200 * Constructor 201 * @param context Context used for loading resources. 202 */ 203 public FastForwardAction(Context context) { 204 this(context, 1); 205 } 206 207 /** 208 * Constructor 209 * @param context Context used for loading resources. 210 * @param numSpeeds Number of supported fast forward speeds. 211 */ 212 public FastForwardAction(Context context, int numSpeeds) { 213 super(R.id.lb_control_fast_forward); 214 215 if (numSpeeds < 1) { 216 throw new IllegalArgumentException("numSpeeds must be > 0"); 217 } 218 Drawable[] drawables = new Drawable[numSpeeds]; 219 drawables[0] = getStyledDrawable(context, 220 R.styleable.lbPlaybackControlsActionIcons_fast_forward); 221 setDrawables(drawables); 222 223 String[] labels = new String[getActionCount()]; 224 labels[0] = context.getString(R.string.lb_playback_controls_fast_forward); 225 226 String[] labels2 = new String[getActionCount()]; 227 labels2[0] = labels[0]; 228 229 for (int i = 1; i < numSpeeds; i++) { 230 int multiplier = i + 1; 231 labels[i] = context.getResources().getString( 232 R.string.lb_control_display_fast_forward_multiplier, multiplier); 233 labels2[i] = context.getResources().getString( 234 R.string.lb_playback_controls_fast_forward_multiplier, multiplier); 235 } 236 setLabels(labels); 237 setSecondaryLabels(labels2); 238 addKeyCode(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD); 239 } 240 } 241 242 /** 243 * An action displaying an icon for rewind. 244 */ 245 public static class RewindAction extends MultiAction { 246 /** 247 * Constructor 248 * @param context Context used for loading resources. 249 */ 250 public RewindAction(Context context) { 251 this(context, 1); 252 } 253 254 /** 255 * Constructor 256 * @param context Context used for loading resources. 257 * @param numSpeeds Number of supported fast forward speeds. 258 */ 259 public RewindAction(Context context, int numSpeeds) { 260 super(R.id.lb_control_fast_rewind); 261 262 if (numSpeeds < 1) { 263 throw new IllegalArgumentException("numSpeeds must be > 0"); 264 } 265 Drawable[] drawables = new Drawable[numSpeeds]; 266 drawables[0] = getStyledDrawable(context, 267 R.styleable.lbPlaybackControlsActionIcons_rewind); 268 setDrawables(drawables); 269 270 String[] labels = new String[getActionCount()]; 271 labels[0] = context.getString(R.string.lb_playback_controls_rewind); 272 273 String[] labels2 = new String[getActionCount()]; 274 labels2[0] = labels[0]; 275 276 for (int i = 1; i < numSpeeds; i++) { 277 int multiplier = i + 1; 278 labels[i] = labels[i] = context.getResources().getString( 279 R.string.lb_control_display_rewind_multiplier, multiplier); 280 labels2[i] = context.getResources().getString( 281 R.string.lb_playback_controls_rewind_multiplier, multiplier); 282 } 283 setLabels(labels); 284 setSecondaryLabels(labels2); 285 addKeyCode(KeyEvent.KEYCODE_MEDIA_REWIND); 286 } 287 } 288 289 /** 290 * An action displaying an icon for skip next. 291 */ 292 public static class SkipNextAction extends Action { 293 /** 294 * Constructor 295 * @param context Context used for loading resources. 296 */ 297 public SkipNextAction(Context context) { 298 super(R.id.lb_control_skip_next); 299 setIcon(getStyledDrawable(context, 300 R.styleable.lbPlaybackControlsActionIcons_skip_next)); 301 setLabel1(context.getString(R.string.lb_playback_controls_skip_next)); 302 addKeyCode(KeyEvent.KEYCODE_MEDIA_NEXT); 303 } 304 } 305 306 /** 307 * An action displaying an icon for skip previous. 308 */ 309 public static class SkipPreviousAction extends Action { 310 /** 311 * Constructor 312 * @param context Context used for loading resources. 313 */ 314 public SkipPreviousAction(Context context) { 315 super(R.id.lb_control_skip_previous); 316 setIcon(getStyledDrawable(context, 317 R.styleable.lbPlaybackControlsActionIcons_skip_previous)); 318 setLabel1(context.getString(R.string.lb_playback_controls_skip_previous)); 319 addKeyCode(KeyEvent.KEYCODE_MEDIA_PREVIOUS); 320 } 321 } 322 323 /** 324 * An action displaying an icon for "more actions". 325 */ 326 public static class MoreActions extends Action { 327 /** 328 * Constructor 329 * @param context Context used for loading resources. 330 */ 331 public MoreActions(Context context) { 332 super(R.id.lb_control_more_actions); 333 setIcon(context.getResources().getDrawable(R.drawable.lb_ic_more)); 334 setLabel1(context.getString(R.string.lb_playback_controls_more_actions)); 335 } 336 } 337 338 /** 339 * A base class for displaying a thumbs action. 340 */ 341 public static abstract class ThumbsAction extends MultiAction { 342 /** 343 * Action index for the solid thumb icon. 344 */ 345 public static int SOLID = 0; 346 347 /** 348 * Action index for the outline thumb icon. 349 */ 350 public static int OUTLINE = 1; 351 352 /** 353 * Constructor 354 * @param context Context used for loading resources. 355 */ 356 public ThumbsAction(int id, Context context, int solidIconIndex, int outlineIconIndex) { 357 super(id); 358 Drawable[] drawables = new Drawable[2]; 359 drawables[SOLID] = getStyledDrawable(context, solidIconIndex); 360 drawables[OUTLINE] = getStyledDrawable(context, outlineIconIndex); 361 setDrawables(drawables); 362 } 363 } 364 365 /** 366 * An action displaying an icon for thumbs up. 367 */ 368 public static class ThumbsUpAction extends ThumbsAction { 369 public ThumbsUpAction(Context context) { 370 super(R.id.lb_control_thumbs_up, context, 371 R.styleable.lbPlaybackControlsActionIcons_thumb_up, 372 R.styleable.lbPlaybackControlsActionIcons_thumb_up_outline); 373 String[] labels = new String[getActionCount()]; 374 labels[SOLID] = context.getString(R.string.lb_playback_controls_thumb_up); 375 labels[OUTLINE] = context.getString(R.string.lb_playback_controls_thumb_up_outline); 376 setLabels(labels); 377 } 378 } 379 380 /** 381 * An action displaying an icon for thumbs down. 382 */ 383 public static class ThumbsDownAction extends ThumbsAction { 384 public ThumbsDownAction(Context context) { 385 super(R.id.lb_control_thumbs_down, context, 386 R.styleable.lbPlaybackControlsActionIcons_thumb_down, 387 R.styleable.lbPlaybackControlsActionIcons_thumb_down_outline); 388 String[] labels = new String[getActionCount()]; 389 labels[SOLID] = context.getString(R.string.lb_playback_controls_thumb_down); 390 labels[OUTLINE] = context.getString(R.string.lb_playback_controls_thumb_down_outline); 391 setLabels(labels); 392 } 393 } 394 395 /** 396 * An action for displaying three repeat states: none, one, or all. 397 */ 398 public static class RepeatAction extends MultiAction { 399 /** 400 * Action index for the repeat-none icon. 401 */ 402 public static int NONE = 0; 403 404 /** 405 * Action index for the repeat-all icon. 406 */ 407 public static int ALL = 1; 408 409 /** 410 * Action index for the repeat-one icon. 411 */ 412 public static int ONE = 2; 413 414 /** 415 * Constructor 416 * @param context Context used for loading resources. 417 */ 418 public RepeatAction(Context context) { 419 this(context, getIconHighlightColor(context)); 420 } 421 422 /** 423 * Constructor 424 * @param context Context used for loading resources 425 * @param highlightColor Color to display the repeat-all and repeat0one icons. 426 */ 427 public RepeatAction(Context context, int highlightColor) { 428 this(context, highlightColor, highlightColor); 429 } 430 431 /** 432 * Constructor 433 * @param context Context used for loading resources 434 * @param repeatAllColor Color to display the repeat-all icon. 435 * @param repeatOneColor Color to display the repeat-one icon. 436 */ 437 public RepeatAction(Context context, int repeatAllColor, int repeatOneColor) { 438 super(R.id.lb_control_repeat); 439 Drawable[] drawables = new Drawable[3]; 440 BitmapDrawable repeatDrawable = (BitmapDrawable) getStyledDrawable(context, 441 R.styleable.lbPlaybackControlsActionIcons_repeat); 442 BitmapDrawable repeatOneDrawable = (BitmapDrawable) getStyledDrawable(context, 443 R.styleable.lbPlaybackControlsActionIcons_repeat_one); 444 drawables[NONE] = repeatDrawable; 445 drawables[ALL] = repeatDrawable == null ? null 446 : new BitmapDrawable(context.getResources(), 447 createBitmap(repeatDrawable.getBitmap(), repeatAllColor)); 448 drawables[ONE] = repeatOneDrawable == null ? null 449 : new BitmapDrawable(context.getResources(), 450 createBitmap(repeatOneDrawable.getBitmap(), repeatOneColor)); 451 setDrawables(drawables); 452 453 String[] labels = new String[drawables.length]; 454 // Note, labels denote the action taken when clicked 455 labels[NONE] = context.getString(R.string.lb_playback_controls_repeat_all); 456 labels[ALL] = context.getString(R.string.lb_playback_controls_repeat_one); 457 labels[ONE] = context.getString(R.string.lb_playback_controls_repeat_none); 458 setLabels(labels); 459 } 460 } 461 462 /** 463 * An action for displaying a shuffle icon. 464 */ 465 public static class ShuffleAction extends MultiAction { 466 public static int OFF = 0; 467 public static int ON = 1; 468 469 /** 470 * Constructor 471 * @param context Context used for loading resources. 472 */ 473 public ShuffleAction(Context context) { 474 this(context, getIconHighlightColor(context)); 475 } 476 477 /** 478 * Constructor 479 * @param context Context used for loading resources. 480 * @param highlightColor Color for the highlighted icon state. 481 */ 482 public ShuffleAction(Context context, int highlightColor) { 483 super(R.id.lb_control_shuffle); 484 BitmapDrawable uncoloredDrawable = (BitmapDrawable) getStyledDrawable(context, 485 R.styleable.lbPlaybackControlsActionIcons_shuffle); 486 Drawable[] drawables = new Drawable[2]; 487 drawables[OFF] = uncoloredDrawable; 488 drawables[ON] = new BitmapDrawable(context.getResources(), 489 createBitmap(uncoloredDrawable.getBitmap(), highlightColor)); 490 setDrawables(drawables); 491 492 String[] labels = new String[drawables.length]; 493 labels[OFF] = context.getString(R.string.lb_playback_controls_shuffle_enable); 494 labels[ON] = context.getString(R.string.lb_playback_controls_shuffle_disable); 495 setLabels(labels); 496 } 497 } 498 499 /** 500 * An action for displaying a HQ (High Quality) icon. 501 */ 502 public static class HighQualityAction extends MultiAction { 503 public static int OFF = 0; 504 public static int ON = 1; 505 506 /** 507 * Constructor 508 * @param context Context used for loading resources. 509 */ 510 public HighQualityAction(Context context) { 511 this(context, getIconHighlightColor(context)); 512 } 513 514 /** 515 * Constructor 516 * @param context Context used for loading resources. 517 * @param highlightColor Color for the highlighted icon state. 518 */ 519 public HighQualityAction(Context context, int highlightColor) { 520 super(R.id.lb_control_high_quality); 521 BitmapDrawable uncoloredDrawable = (BitmapDrawable) getStyledDrawable(context, 522 R.styleable.lbPlaybackControlsActionIcons_high_quality); 523 Drawable[] drawables = new Drawable[2]; 524 drawables[OFF] = uncoloredDrawable; 525 drawables[ON] = new BitmapDrawable(context.getResources(), 526 createBitmap(uncoloredDrawable.getBitmap(), highlightColor)); 527 setDrawables(drawables); 528 529 String[] labels = new String[drawables.length]; 530 labels[OFF] = context.getString(R.string.lb_playback_controls_high_quality_enable); 531 labels[ON] = context.getString(R.string.lb_playback_controls_high_quality_disable); 532 setLabels(labels); 533 } 534 } 535 536 /** 537 * An action for displaying a CC (Closed Captioning) icon. 538 */ 539 public static class ClosedCaptioningAction extends MultiAction { 540 public static int OFF = 0; 541 public static int ON = 1; 542 543 /** 544 * Constructor 545 * @param context Context used for loading resources. 546 */ 547 public ClosedCaptioningAction(Context context) { 548 this(context, getIconHighlightColor(context)); 549 } 550 551 /** 552 * Constructor 553 * @param context Context used for loading resources. 554 * @param highlightColor Color for the highlighted icon state. 555 */ 556 public ClosedCaptioningAction(Context context, int highlightColor) { 557 super(R.id.lb_control_high_quality); 558 BitmapDrawable uncoloredDrawable = (BitmapDrawable) getStyledDrawable(context, 559 R.styleable.lbPlaybackControlsActionIcons_closed_captioning); 560 Drawable[] drawables = new Drawable[2]; 561 drawables[OFF] = uncoloredDrawable; 562 drawables[ON] = new BitmapDrawable(context.getResources(), 563 createBitmap(uncoloredDrawable.getBitmap(), highlightColor)); 564 setDrawables(drawables); 565 566 String[] labels = new String[drawables.length]; 567 labels[OFF] = context.getString(R.string.lb_playback_controls_closed_captioning_enable); 568 labels[ON] = context.getString(R.string.lb_playback_controls_closed_captioning_disable); 569 setLabels(labels); 570 } 571 } 572 573 private static Bitmap createBitmap(Bitmap bitmap, int color) { 574 Bitmap dst = bitmap.copy(bitmap.getConfig(), true); 575 Canvas canvas = new Canvas(dst); 576 Paint paint = new Paint(); 577 paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)); 578 canvas.drawBitmap(bitmap, 0, 0, paint); 579 return dst; 580 } 581 582 private static int getIconHighlightColor(Context context) { 583 TypedValue outValue = new TypedValue(); 584 if (context.getTheme().resolveAttribute(R.attr.playbackControlsIconHighlightColor, 585 outValue, true)) { 586 return outValue.data; 587 } 588 return context.getResources().getColor(R.color.lb_playback_icon_highlight_no_theme); 589 } 590 591 private static Drawable getStyledDrawable(Context context, int index) { 592 TypedValue outValue = new TypedValue(); 593 if (!context.getTheme().resolveAttribute( 594 R.attr.playbackControlsActionIcons, outValue, false)) { 595 return null; 596 } 597 TypedArray array = context.getTheme().obtainStyledAttributes(outValue.data, 598 R.styleable.lbPlaybackControlsActionIcons); 599 Drawable drawable = array.getDrawable(index); 600 array.recycle(); 601 return drawable; 602 } 603 604 private Object mItem; 605 private Drawable mImageDrawable; 606 private ObjectAdapter mPrimaryActionsAdapter; 607 private ObjectAdapter mSecondaryActionsAdapter; 608 private int mTotalTimeMs; 609 private int mCurrentTimeMs; 610 private int mBufferedProgressMs; 611 private OnPlaybackStateChangedListener mListener; 612 613 /** 614 * Constructor for a PlaybackControlsRow that displays some details from 615 * the given item. 616 * 617 * @param item The main item for the row. 618 */ 619 public PlaybackControlsRow(Object item) { 620 mItem = item; 621 } 622 623 /** 624 * Constructor for a PlaybackControlsRow that has no item details. 625 */ 626 public PlaybackControlsRow() { 627 } 628 629 /** 630 * Returns the main item for the details page. 631 */ 632 public final Object getItem() { 633 return mItem; 634 } 635 636 /** 637 * Sets a {link @Drawable} image for this row. 638 * <p>If set after the row has been bound to a view, the adapter must be notified that 639 * this row has changed.</p> 640 * 641 * @param drawable The drawable to set. 642 */ 643 public final void setImageDrawable(Drawable drawable) { 644 mImageDrawable = drawable; 645 } 646 647 /** 648 * Sets a {@link Bitmap} for this row. 649 * <p>If set after the row has been bound to a view, the adapter must be notified that 650 * this row has changed.</p> 651 * 652 * @param context The context to retrieve display metrics from. 653 * @param bm The bitmap to set. 654 */ 655 public final void setImageBitmap(Context context, Bitmap bm) { 656 mImageDrawable = new BitmapDrawable(context.getResources(), bm); 657 } 658 659 /** 660 * Returns the image {@link Drawable} of this row. 661 * 662 * @return The overview's image drawable, or null if no drawable has been 663 * assigned. 664 */ 665 public final Drawable getImageDrawable() { 666 return mImageDrawable; 667 } 668 669 /** 670 * Sets the primary actions {@link ObjectAdapter}. 671 * <p>If set after the row has been bound to a view, the adapter must be notified that 672 * this row has changed.</p> 673 */ 674 public final void setPrimaryActionsAdapter(ObjectAdapter adapter) { 675 mPrimaryActionsAdapter = adapter; 676 } 677 678 /** 679 * Sets the secondary actions {@link ObjectAdapter}. 680 * <p>If set after the row has been bound to a view, the adapter must be notified that 681 * this row has changed.</p> 682 */ 683 public final void setSecondaryActionsAdapter(ObjectAdapter adapter) { 684 mSecondaryActionsAdapter = adapter; 685 } 686 687 /** 688 * Returns the primary actions {@link ObjectAdapter}. 689 */ 690 public final ObjectAdapter getPrimaryActionsAdapter() { 691 return mPrimaryActionsAdapter; 692 } 693 694 /** 695 * Returns the secondary actions {@link ObjectAdapter}. 696 */ 697 public final ObjectAdapter getSecondaryActionsAdapter() { 698 return mSecondaryActionsAdapter; 699 } 700 701 /** 702 * Sets the total time in milliseconds for the playback controls row. 703 * <p>If set after the row has been bound to a view, the adapter must be notified that 704 * this row has changed.</p> 705 */ 706 public void setTotalTime(int ms) { 707 mTotalTimeMs = ms; 708 } 709 710 /** 711 * Returns the total time in milliseconds for the playback controls row. 712 */ 713 public int getTotalTime() { 714 return mTotalTimeMs; 715 } 716 717 /** 718 * Sets the current time in milliseconds for the playback controls row. 719 * If this row is bound to a view, the view will automatically 720 * be updated to reflect the new value. 721 */ 722 public void setCurrentTime(int ms) { 723 if (mCurrentTimeMs != ms) { 724 mCurrentTimeMs = ms; 725 currentTimeChanged(); 726 } 727 } 728 729 /** 730 * Returns the current time in milliseconds for the playback controls row. 731 */ 732 public int getCurrentTime() { 733 return mCurrentTimeMs; 734 } 735 736 /** 737 * Sets the buffered progress for the playback controls row. 738 * If this row is bound to a view, the view will automatically 739 * be updated to reflect the new value. 740 */ 741 public void setBufferedProgress(int ms) { 742 if (mBufferedProgressMs != ms) { 743 mBufferedProgressMs = ms; 744 bufferedProgressChanged(); 745 } 746 } 747 748 /** 749 * Returns the buffered progress for the playback controls row. 750 */ 751 public int getBufferedProgress() { 752 return mBufferedProgressMs; 753 } 754 755 /** 756 * Returns the Action associated with the given keycode, or null if no associated action exists. 757 * Searches the primary adapter first, then the secondary adapter. 758 */ 759 public Action getActionForKeyCode(int keyCode) { 760 Action action = getActionForKeyCode(getPrimaryActionsAdapter(), keyCode); 761 if (action != null) { 762 return action; 763 } 764 return getActionForKeyCode(getSecondaryActionsAdapter(), keyCode); 765 } 766 767 /** 768 * Returns the Action associated with the given keycode, or null if no associated action exists. 769 */ 770 public Action getActionForKeyCode(ObjectAdapter adapter, int keyCode) { 771 if (adapter != mPrimaryActionsAdapter && adapter != mSecondaryActionsAdapter) { 772 throw new IllegalArgumentException("Invalid adapter"); 773 } 774 for (int i = 0; i < adapter.size(); i++) { 775 Action action = (Action) adapter.get(i); 776 if (action.respondsToKeyCode(keyCode)) { 777 return action; 778 } 779 } 780 return null; 781 } 782 783 interface OnPlaybackStateChangedListener { 784 public void onCurrentTimeChanged(int currentTimeMs); 785 public void onBufferedProgressChanged(int bufferedProgressMs); 786 } 787 788 /** 789 * Sets a listener to be called when the playback state changes. 790 */ 791 void setOnPlaybackStateChangedListener(OnPlaybackStateChangedListener listener) { 792 mListener = listener; 793 } 794 795 /** 796 * Returns the playback state listener. 797 */ 798 OnPlaybackStateChangedListener getOnPlaybackStateChangedListener() { 799 return mListener; 800 } 801 802 private void currentTimeChanged() { 803 if (mListener != null) { 804 mListener.onCurrentTimeChanged(mCurrentTimeMs); 805 } 806 } 807 808 private void bufferedProgressChanged() { 809 if (mListener != null) { 810 mListener.onBufferedProgressChanged(mBufferedProgressMs); 811 } 812 } 813} 814