Class MediaControls

java.lang.Object
limn.scene.Widget
limn.components.MediaControls

public class MediaControls extends Widget
Playback controls for a VideoView: play/pause, a scrub bar and a position clock — the bar every player lays over its picture. Everything here drives the view and only the view (VideoView.setPaused(boolean), VideoView.seek(long, VideoStreamSource.SeekMode), VideoView.positionMicros()), so it works with a frozen capture, a source with no soundtrack, and a player the application built itself.

It reads left to right in either direction, by default. The playback cluster inherits its arrangement from tape decks and the scrub bar advances the way the tape ran; media playback is the standing exception in every platform's bidi guidance, so this widget declares LTR for itself when it is built. That is a declaration and not a law: an application that wants the controls to follow the tree (some platforms do mirror them) calls setLayoutDirection(null) to inherit, or passes an explicit direction — the same knob every widget has (see docs/design/direction-axis.md).

Sound, and which half of it is the toolkit's. A mute button and a volume slider are built in, because a gain on the soundtrack the player already holds is the toolkit's to turn (MediaPlayer.audio()). By default they appear only while the media can actually sound (MediaControls.Sound.AUTO) and step aside otherwise, so a silent clip does not carry a dead volume; setSound(limn.components.MediaControls.Sound) forces them MediaControls.Sound.ON or MediaControls.Sound.OFF. Muting is gain zero and never a teardown. Everything behind the gain stays the application's: one that opens its soundtrack lazily, switches audio tracks or offers subtitles turns the built-ins off and wires its own widgets into the slots.

The slots. addLeading(limn.scene.Widget) places a widget between the play button and the scrub bar (where players put their volume), addTrailing(limn.scene.Widget) between the scrub bar and the clock, and setOnRefresh(java.lang.Runnable) gives injected controls a ride on the same heartbeat the built-in ones update on. setShowPosition(boolean) and setBackdrop(boolean) trim the built-ins.

The bar polls on a timer rather than a ticker, so parked over a paused picture it costs nothing: every write below is guarded, and a frame is only asked for when a number actually moved.

  • Constructor Details

    • MediaControls

      public MediaControls(VideoView view)
  • Method Details

    • view

      public VideoView view()
      The view these controls drive.
    • addLeading

      public MediaControls addLeading(Widget widget)
      Adds a widget between the play button and the scrub bar — where players put their volume. Order of calls is the order on screen.
    • addTrailing

      public MediaControls addTrailing(Widget widget)
      Adds a widget between the scrub bar and the position clock.
    • setShowPosition

      public MediaControls setShowPosition(boolean show)
      Whether the position clock is shown (default true).
    • setBackdrop

      public MediaControls setBackdrop(boolean paint)
      Whether the bar paints its own translucent panel (default true). A host that already draws chrome behind the controls — a glass strip over the picture — turns it off.
    • setOnRefresh

      public MediaControls setOnRefresh(Runnable listener)
      Runs on every refresh of the built-in controls, so a widget injected through addLeading(limn.scene.Widget)/addTrailing(limn.scene.Widget) can update on the same heartbeat instead of arming a timer of its own.
    • setInk

      public MediaControls setInk(Color newInk, Color newMutedInk)
      Overrides the ink the built-ins write in — the play glyph and the clock. A bar drawn over someone else's chrome (a glass strip over the picture) sits on a surface the palette knows nothing about, and a theme ink chosen for the theme's own surfaces can land near-black on it. nulls restore the theme's answer.
    • setSound

      public MediaControls setSound(MediaControls.Sound mode)
      Whether the mute button and volume slider are offered (default MediaControls.Sound.AUTO).
    • setVolume

      public MediaControls setVolume(float newLevel)
      Volume in [0, 1], applied as a gain on the soundtrack the player holds; zero also mutes. This is what unmuting restores.
    • volume

      public float volume()
      The volume unmuting restores, in [0, 1].
    • setMuted

      public MediaControls setMuted(boolean newMuted)
      Gain zero and never a teardown: a mute that closed the stream would cost a decoder flush every time somebody silenced a video for a moment.
    • isMuted

      public boolean isMuted()
      Whether the soundtrack is silenced (gain zero; the stream keeps running).
    • onMeasure

      protected Size onMeasure(Constraints constraints)
      Description copied from class: Widget
      Reports the size this widget wants within constraints. Called once per layout pass, and the result is cached against the constraints and the resolved axes (size step, layout direction, locale), so it must be a pure function of them and of this widget's own state.

      Resolve the ControlSize and the LayoutDirection once each here and thread them down; never read either in a constructor. The locale needs no threading: it is in scope, and I18n.locale() answers it wherever text is resolved.

      Specified by:
      onMeasure in class Widget
    • onLayout

      protected void onLayout()
      Description copied from class: Widget
      Containers position children here (measure + Widget.layoutBox(float, float, float, float) per child).
      Overrides:
      onLayout in class Widget
    • onPaint

      protected void onPaint(Canvas canvas)
      Description copied from class: Widget
      Widget's own background/content, in local coordinates.
      Overrides:
      onPaint in class Widget