diff --git a/library/ui/src/main/AndroidManifest.xml b/library/ui/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..72189e22a7
--- /dev/null
+++ b/library/ui/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+
+
+
+
diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java
new file mode 100644
index 0000000000..38294f5208
--- /dev/null
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.android.exoplayer2.ui;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.annotation.IntDef;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A {@link FrameLayout} that resizes itself to match a specified aspect ratio.
+ */
+public final class AspectRatioFrameLayout extends FrameLayout {
+
+ /**
+ * Resize modes for {@link AspectRatioFrameLayout}.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({RESIZE_MODE_FIT, RESIZE_MODE_FIXED_WIDTH, RESIZE_MODE_FIXED_HEIGHT, RESIZE_MODE_FILL})
+ public @interface ResizeMode {}
+
+ /**
+ * Either the width or height is decreased to obtain the desired aspect ratio.
+ */
+ public static final int RESIZE_MODE_FIT = 0;
+ /**
+ * The width is fixed and the height is increased or decreased to obtain the desired aspect ratio.
+ */
+ public static final int RESIZE_MODE_FIXED_WIDTH = 1;
+ /**
+ * The height is fixed and the width is increased or decreased to obtain the desired aspect ratio.
+ */
+ public static final int RESIZE_MODE_FIXED_HEIGHT = 2;
+ /**
+ * The specified aspect ratio is ignored.
+ */
+ public static final int RESIZE_MODE_FILL = 3;
+
+ /**
+ * The {@link FrameLayout} will not resize itself if the fractional difference between its natural
+ * aspect ratio and the requested aspect ratio falls below this threshold.
+ *
+ * This tolerance allows the view to occupy the whole of the screen when the requested aspect
+ * ratio is very close, but not exactly equal to, the aspect ratio of the screen. This may reduce
+ * the number of view layers that need to be composited by the underlying system, which can help
+ * to reduce power consumption.
+ */
+ private static final float MAX_ASPECT_RATIO_DEFORMATION_FRACTION = 0.01f;
+
+ private float videoAspectRatio;
+ private int resizeMode;
+
+ public AspectRatioFrameLayout(Context context) {
+ this(context, null);
+ }
+
+ public AspectRatioFrameLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ resizeMode = RESIZE_MODE_FIT;
+ if (attrs != null) {
+ TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
+ R.styleable.AspectRatioFrameLayout, 0, 0);
+ try {
+ resizeMode = a.getInt(R.styleable.AspectRatioFrameLayout_resize_mode, RESIZE_MODE_FIT);
+ } finally {
+ a.recycle();
+ }
+ }
+ }
+
+ /**
+ * Set the aspect ratio that this view should satisfy.
+ *
+ * @param widthHeightRatio The width to height ratio.
+ */
+ public void setAspectRatio(float widthHeightRatio) {
+ if (this.videoAspectRatio != widthHeightRatio) {
+ this.videoAspectRatio = widthHeightRatio;
+ requestLayout();
+ }
+ }
+
+ /**
+ * Sets the resize mode.
+ *
+ * @param resizeMode The resize mode.
+ */
+ public void setResizeMode(@ResizeMode int resizeMode) {
+ if (this.resizeMode != resizeMode) {
+ this.resizeMode = resizeMode;
+ requestLayout();
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ if (resizeMode == RESIZE_MODE_FILL || videoAspectRatio <= 0) {
+ // Aspect ratio not set.
+ return;
+ }
+
+ int width = getMeasuredWidth();
+ int height = getMeasuredHeight();
+ float viewAspectRatio = (float) width / height;
+ float aspectDeformation = videoAspectRatio / viewAspectRatio - 1;
+ if (Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION) {
+ // We're within the allowed tolerance.
+ return;
+ }
+
+ switch (resizeMode) {
+ case RESIZE_MODE_FIXED_WIDTH:
+ height = (int) (width / videoAspectRatio);
+ break;
+ case RESIZE_MODE_FIXED_HEIGHT:
+ width = (int) (height * videoAspectRatio);
+ break;
+ default:
+ if (aspectDeformation > 0) {
+ height = (int) (width / videoAspectRatio);
+ } else {
+ width = (int) (height * videoAspectRatio);
+ }
+ break;
+ }
+ super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ }
+
+}
diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DebugTextViewHelper.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DebugTextViewHelper.java
new file mode 100644
index 0000000000..1bf5b59a4a
--- /dev/null
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DebugTextViewHelper.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.android.exoplayer2.ui;
+
+import android.widget.TextView;
+import com.google.android.exoplayer2.ExoPlaybackException;
+import com.google.android.exoplayer2.ExoPlayer;
+import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.SimpleExoPlayer;
+import com.google.android.exoplayer2.Timeline;
+import com.google.android.exoplayer2.decoder.DecoderCounters;
+import com.google.android.exoplayer2.source.TrackGroupArray;
+import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
+
+/**
+ * A helper class for periodically updating a {@link TextView} with debug information obtained from
+ * a {@link SimpleExoPlayer}.
+ */
+public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListener {
+
+ private static final int REFRESH_INTERVAL_MS = 1000;
+
+ private final SimpleExoPlayer player;
+ private final TextView textView;
+
+ private boolean started;
+
+ /**
+ * @param player The {@link SimpleExoPlayer} from which debug information should be obtained.
+ * @param textView The {@link TextView} that should be updated to display the information.
+ */
+ public DebugTextViewHelper(SimpleExoPlayer player, TextView textView) {
+ this.player = player;
+ this.textView = textView;
+ }
+
+ /**
+ * Starts periodic updates of the {@link TextView}. Must be called from the application's main
+ * thread.
+ */
+ public void start() {
+ if (started) {
+ return;
+ }
+ started = true;
+ player.addListener(this);
+ updateAndPost();
+ }
+
+ /**
+ * Stops periodic updates of the {@link TextView}. Must be called from the application's main
+ * thread.
+ */
+ public void stop() {
+ if (!started) {
+ return;
+ }
+ started = false;
+ player.removeListener(this);
+ textView.removeCallbacks(this);
+ }
+
+ // ExoPlayer.EventListener implementation.
+
+ @Override
+ public void onLoadingChanged(boolean isLoading) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
+ updateAndPost();
+ }
+
+ @Override
+ public void onPositionDiscontinuity() {
+ updateAndPost();
+ }
+
+ @Override
+ public void onTimelineChanged(Timeline timeline, Object manifest) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onPlayerError(ExoPlaybackException error) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selections) {
+ // Do nothing.
+ }
+
+ // Runnable implementation.
+
+ @Override
+ public void run() {
+ updateAndPost();
+ }
+
+ // Private methods.
+
+ private void updateAndPost() {
+ textView.setText(getPlayerStateString() + getPlayerWindowIndexString() + getVideoString()
+ + getAudioString());
+ textView.removeCallbacks(this);
+ textView.postDelayed(this, REFRESH_INTERVAL_MS);
+ }
+
+ private String getPlayerStateString() {
+ String text = "playWhenReady:" + player.getPlayWhenReady() + " playbackState:";
+ switch (player.getPlaybackState()) {
+ case ExoPlayer.STATE_BUFFERING:
+ text += "buffering";
+ break;
+ case ExoPlayer.STATE_ENDED:
+ text += "ended";
+ break;
+ case ExoPlayer.STATE_IDLE:
+ text += "idle";
+ break;
+ case ExoPlayer.STATE_READY:
+ text += "ready";
+ break;
+ default:
+ text += "unknown";
+ break;
+ }
+ return text;
+ }
+
+ private String getPlayerWindowIndexString() {
+ return " window:" + player.getCurrentWindowIndex();
+ }
+
+ private String getVideoString() {
+ Format format = player.getVideoFormat();
+ if (format == null) {
+ return "";
+ }
+ return "\n" + format.sampleMimeType + "(id:" + format.id + " r:" + format.width + "x"
+ + format.height + getDecoderCountersBufferCountString(player.getVideoDecoderCounters())
+ + ")";
+ }
+
+ private String getAudioString() {
+ Format format = player.getAudioFormat();
+ if (format == null) {
+ return "";
+ }
+ return "\n" + format.sampleMimeType + "(id:" + format.id + " hz:" + format.sampleRate + " ch:"
+ + format.channelCount
+ + getDecoderCountersBufferCountString(player.getAudioDecoderCounters()) + ")";
+ }
+
+ private static String getDecoderCountersBufferCountString(DecoderCounters counters) {
+ if (counters == null) {
+ return "";
+ }
+ counters.ensureUpdated();
+ return " rb:" + counters.renderedOutputBufferCount
+ + " sb:" + counters.skippedOutputBufferCount
+ + " db:" + counters.droppedOutputBufferCount
+ + " mcdb:" + counters.maxConsecutiveDroppedOutputBufferCount;
+ }
+
+}
diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
new file mode 100644
index 0000000000..88a65589fc
--- /dev/null
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
@@ -0,0 +1,812 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.android.exoplayer2.ui;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import com.google.android.exoplayer2.C;
+import com.google.android.exoplayer2.ExoPlaybackException;
+import com.google.android.exoplayer2.ExoPlayer;
+import com.google.android.exoplayer2.Timeline;
+import com.google.android.exoplayer2.source.TrackGroupArray;
+import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
+import com.google.android.exoplayer2.util.Util;
+import java.util.Formatter;
+import java.util.Locale;
+
+/**
+ * A view for controlling {@link ExoPlayer} instances.
+ *
+ * A PlaybackControlView can be customized by setting attributes (or calling corresponding methods),
+ * overriding the view's layout file or by specifying a custom view layout file, as outlined below.
+ *
+ *
+ * All child views are optional and so can be omitted if not required, however where defined they
+ * must be of the expected type.
+ *
+ *
+ * A SimpleExoPlayerView can be customized by setting attributes (or calling corresponding methods),
+ * overriding the view's layout file or by specifying a custom view layout file, as outlined below.
+ *
+ *
+ * All child views are optional and so can be omitted if not required, however where defined they
+ * must be of the expected type.
+ *
+ *
cues) {
+ if (subtitleView != null) {
+ subtitleView.onCues(cues);
+ }
+ }
+
+ // SimpleExoPlayer.VideoListener implementation
+
+ @Override
+ public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
+ float pixelWidthHeightRatio) {
+ if (contentFrame != null) {
+ float aspectRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height;
+ contentFrame.setAspectRatio(aspectRatio);
+ }
+ }
+
+ @Override
+ public void onRenderedFirstFrame() {
+ if (shutterView != null) {
+ shutterView.setVisibility(INVISIBLE);
+ }
+ }
+
+ @Override
+ public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selections) {
+ updateForCurrentTrackSelections();
+ }
+
+ // ExoPlayer.EventListener implementation
+
+ @Override
+ public void onLoadingChanged(boolean isLoading) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
+ maybeShowController(false);
+ }
+
+ @Override
+ public void onPlayerError(ExoPlaybackException e) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onPositionDiscontinuity() {
+ // Do nothing.
+ }
+
+ @Override
+ public void onTimelineChanged(Timeline timeline, Object manifest) {
+ // Do nothing.
+ }
+
+ }
+
+}
diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java
new file mode 100644
index 0000000000..d4f09b1721
--- /dev/null
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.android.exoplayer2.ui;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Join;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.text.Layout.Alignment;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import com.google.android.exoplayer2.text.CaptionStyleCompat;
+import com.google.android.exoplayer2.text.Cue;
+import com.google.android.exoplayer2.util.Util;
+
+/**
+ * Paints subtitle {@link Cue}s.
+ */
+/* package */ final class SubtitlePainter {
+
+ private static final String TAG = "SubtitlePainter";
+
+ /**
+ * Ratio of inner padding to font size.
+ */
+ private static final float INNER_PADDING_RATIO = 0.125f;
+
+ /**
+ * Temporary rectangle used for computing line bounds.
+ */
+ private final RectF lineBounds = new RectF();
+
+ // Styled dimensions.
+ private final float cornerRadius;
+ private final float outlineWidth;
+ private final float shadowRadius;
+ private final float shadowOffset;
+ private final float spacingMult;
+ private final float spacingAdd;
+
+ private final TextPaint textPaint;
+ private final Paint paint;
+
+ // Previous input variables.
+ private CharSequence cueText;
+ private Alignment cueTextAlignment;
+ private Bitmap cueBitmap;
+ private float cueLine;
+ @Cue.LineType
+ private int cueLineType;
+ @Cue.AnchorType
+ private int cueLineAnchor;
+ private float cuePosition;
+ @Cue.AnchorType
+ private int cuePositionAnchor;
+ private float cueSize;
+ private boolean applyEmbeddedStyles;
+ private int foregroundColor;
+ private int backgroundColor;
+ private int windowColor;
+ private int edgeColor;
+ @CaptionStyleCompat.EdgeType
+ private int edgeType;
+ private float textSizePx;
+ private float bottomPaddingFraction;
+ private int parentLeft;
+ private int parentTop;
+ private int parentRight;
+ private int parentBottom;
+
+ // Derived drawing variables.
+ private StaticLayout textLayout;
+ private int textLeft;
+ private int textTop;
+ private int textPaddingX;
+ private Rect bitmapRect;
+
+ @SuppressWarnings("ResourceType")
+ public SubtitlePainter(Context context) {
+ int[] viewAttr = {android.R.attr.lineSpacingExtra, android.R.attr.lineSpacingMultiplier};
+ TypedArray styledAttributes = context.obtainStyledAttributes(null, viewAttr, 0, 0);
+ spacingAdd = styledAttributes.getDimensionPixelSize(0, 0);
+ spacingMult = styledAttributes.getFloat(1, 1);
+ styledAttributes.recycle();
+
+ Resources resources = context.getResources();
+ DisplayMetrics displayMetrics = resources.getDisplayMetrics();
+ int twoDpInPx = Math.round((2f * displayMetrics.densityDpi) / DisplayMetrics.DENSITY_DEFAULT);
+ cornerRadius = twoDpInPx;
+ outlineWidth = twoDpInPx;
+ shadowRadius = twoDpInPx;
+ shadowOffset = twoDpInPx;
+
+ textPaint = new TextPaint();
+ textPaint.setAntiAlias(true);
+ textPaint.setSubpixelText(true);
+
+ paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setStyle(Style.FILL);
+ }
+
+ /**
+ * Draws the provided {@link Cue} into a canvas with the specified styling.
+ *
+ * A call to this method is able to use cached results of calculations made during the previous
+ * call, and so an instance of this class is able to optimize repeated calls to this method in
+ * which the same parameters are passed.
+ *
+ * @param cue The cue to draw.
+ * @param applyEmbeddedStyles Whether styling embedded within the cue should be applied.
+ * @param style The style to use when drawing the cue text.
+ * @param textSizePx The text size to use when drawing the cue text, in pixels.
+ * @param bottomPaddingFraction The bottom padding fraction to apply when {@link Cue#line} is
+ * {@link Cue#DIMEN_UNSET}, as a fraction of the viewport height
+ * @param canvas The canvas into which to draw.
+ * @param cueBoxLeft The left position of the enclosing cue box.
+ * @param cueBoxTop The top position of the enclosing cue box.
+ * @param cueBoxRight The right position of the enclosing cue box.
+ * @param cueBoxBottom The bottom position of the enclosing cue box.
+ */
+ public void draw(Cue cue, boolean applyEmbeddedStyles, CaptionStyleCompat style, float textSizePx,
+ float bottomPaddingFraction, Canvas canvas, int cueBoxLeft, int cueBoxTop, int cueBoxRight,
+ int cueBoxBottom) {
+ boolean isTextCue = cue.bitmap == null;
+ CharSequence cueText = null;
+ Bitmap cueBitmap = null;
+ int windowColor = Color.BLACK;
+ if (isTextCue) {
+ cueText = cue.text;
+ if (TextUtils.isEmpty(cueText)) {
+ // Nothing to draw.
+ return;
+ }
+ windowColor = cue.windowColorSet ? cue.windowColor : style.windowColor;
+ if (!applyEmbeddedStyles) {
+ // Strip out any embedded styling.
+ cueText = cueText.toString();
+ windowColor = style.windowColor;
+ }
+ } else {
+ cueBitmap = cue.bitmap;
+ }
+ if (areCharSequencesEqual(this.cueText, cueText)
+ && Util.areEqual(this.cueTextAlignment, cue.textAlignment)
+ && this.cueBitmap == cueBitmap
+ && this.cueLine == cue.line
+ && this.cueLineType == cue.lineType
+ && Util.areEqual(this.cueLineAnchor, cue.lineAnchor)
+ && this.cuePosition == cue.position
+ && Util.areEqual(this.cuePositionAnchor, cue.positionAnchor)
+ && this.cueSize == cue.size
+ && this.applyEmbeddedStyles == applyEmbeddedStyles
+ && this.foregroundColor == style.foregroundColor
+ && this.backgroundColor == style.backgroundColor
+ && this.windowColor == windowColor
+ && this.edgeType == style.edgeType
+ && this.edgeColor == style.edgeColor
+ && Util.areEqual(this.textPaint.getTypeface(), style.typeface)
+ && this.textSizePx == textSizePx
+ && this.bottomPaddingFraction == bottomPaddingFraction
+ && this.parentLeft == cueBoxLeft
+ && this.parentTop == cueBoxTop
+ && this.parentRight == cueBoxRight
+ && this.parentBottom == cueBoxBottom) {
+ // We can use the cached layout.
+ drawLayout(canvas, isTextCue);
+ return;
+ }
+
+ this.cueText = cueText;
+ this.cueTextAlignment = cue.textAlignment;
+ this.cueBitmap = cueBitmap;
+ this.cueLine = cue.line;
+ this.cueLineType = cue.lineType;
+ this.cueLineAnchor = cue.lineAnchor;
+ this.cuePosition = cue.position;
+ this.cuePositionAnchor = cue.positionAnchor;
+ this.cueSize = cue.size;
+ this.applyEmbeddedStyles = applyEmbeddedStyles;
+ this.foregroundColor = style.foregroundColor;
+ this.backgroundColor = style.backgroundColor;
+ this.windowColor = windowColor;
+ this.edgeType = style.edgeType;
+ this.edgeColor = style.edgeColor;
+ this.textPaint.setTypeface(style.typeface);
+ this.textSizePx = textSizePx;
+ this.bottomPaddingFraction = bottomPaddingFraction;
+ this.parentLeft = cueBoxLeft;
+ this.parentTop = cueBoxTop;
+ this.parentRight = cueBoxRight;
+ this.parentBottom = cueBoxBottom;
+
+ if (isTextCue) {
+ setupTextLayout();
+ } else {
+ setupBitmapLayout();
+ }
+ drawLayout(canvas, isTextCue);
+ }
+
+ private void setupTextLayout() {
+ int parentWidth = parentRight - parentLeft;
+ int parentHeight = parentBottom - parentTop;
+
+ textPaint.setTextSize(textSizePx);
+ int textPaddingX = (int) (textSizePx * INNER_PADDING_RATIO + 0.5f);
+
+ int availableWidth = parentWidth - textPaddingX * 2;
+ if (cueSize != Cue.DIMEN_UNSET) {
+ availableWidth = (int) (availableWidth * cueSize);
+ }
+ if (availableWidth <= 0) {
+ Log.w(TAG, "Skipped drawing subtitle cue (insufficient space)");
+ return;
+ }
+
+ Alignment textAlignment = cueTextAlignment == null ? Alignment.ALIGN_CENTER : cueTextAlignment;
+ textLayout = new StaticLayout(cueText, textPaint, availableWidth, textAlignment, spacingMult,
+ spacingAdd, true);
+ int textHeight = textLayout.getHeight();
+ int textWidth = 0;
+ int lineCount = textLayout.getLineCount();
+ for (int i = 0; i < lineCount; i++) {
+ textWidth = Math.max((int) Math.ceil(textLayout.getLineWidth(i)), textWidth);
+ }
+ if (cueSize != Cue.DIMEN_UNSET && textWidth < availableWidth) {
+ textWidth = availableWidth;
+ }
+ textWidth += textPaddingX * 2;
+
+ int textLeft;
+ int textRight;
+ if (cuePosition != Cue.DIMEN_UNSET) {
+ int anchorPosition = Math.round(parentWidth * cuePosition) + parentLeft;
+ textLeft = cuePositionAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textWidth
+ : cuePositionAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textWidth) / 2
+ : anchorPosition;
+ textLeft = Math.max(textLeft, parentLeft);
+ textRight = Math.min(textLeft + textWidth, parentRight);
+ } else {
+ textLeft = (parentWidth - textWidth) / 2;
+ textRight = textLeft + textWidth;
+ }
+
+ textWidth = textRight - textLeft;
+ if (textWidth <= 0) {
+ Log.w(TAG, "Skipped drawing subtitle cue (invalid horizontal positioning)");
+ return;
+ }
+
+ int textTop;
+ if (cueLine != Cue.DIMEN_UNSET) {
+ int anchorPosition;
+ if (cueLineType == Cue.LINE_TYPE_FRACTION) {
+ anchorPosition = Math.round(parentHeight * cueLine) + parentTop;
+ } else {
+ // cueLineType == Cue.LINE_TYPE_NUMBER
+ int firstLineHeight = textLayout.getLineBottom(0) - textLayout.getLineTop(0);
+ if (cueLine >= 0) {
+ anchorPosition = Math.round(cueLine * firstLineHeight) + parentTop;
+ } else {
+ anchorPosition = Math.round((cueLine + 1) * firstLineHeight) + parentBottom;
+ }
+ }
+ textTop = cueLineAnchor == Cue.ANCHOR_TYPE_END ? anchorPosition - textHeight
+ : cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorPosition * 2 - textHeight) / 2
+ : anchorPosition;
+ if (textTop + textHeight > parentBottom) {
+ textTop = parentBottom - textHeight;
+ } else if (textTop < parentTop) {
+ textTop = parentTop;
+ }
+ } else {
+ textTop = parentBottom - textHeight - (int) (parentHeight * bottomPaddingFraction);
+ }
+
+ // Update the derived drawing variables.
+ this.textLayout = new StaticLayout(cueText, textPaint, textWidth, textAlignment, spacingMult,
+ spacingAdd, true);
+ this.textLeft = textLeft;
+ this.textTop = textTop;
+ this.textPaddingX = textPaddingX;
+ }
+
+ private void setupBitmapLayout() {
+ int parentWidth = parentRight - parentLeft;
+ int parentHeight = parentBottom - parentTop;
+ float anchorX = parentLeft + (parentWidth * cuePosition);
+ float anchorY = parentTop + (parentHeight * cueLine);
+ int width = Math.round(parentWidth * cueSize);
+ int height = Math.round(width * ((float) cueBitmap.getHeight() / cueBitmap.getWidth()));
+ int x = Math.round(cueLineAnchor == Cue.ANCHOR_TYPE_END ? (anchorX - width)
+ : cueLineAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorX - (width / 2)) : anchorX);
+ int y = Math.round(cuePositionAnchor == Cue.ANCHOR_TYPE_END ? (anchorY - height)
+ : cuePositionAnchor == Cue.ANCHOR_TYPE_MIDDLE ? (anchorY - (height / 2)) : anchorY);
+ bitmapRect = new Rect(x, y, x + width, y + height);
+ }
+
+ private void drawLayout(Canvas canvas, boolean isTextCue) {
+ if (isTextCue) {
+ drawTextLayout(canvas);
+ } else {
+ drawBitmapLayout(canvas);
+ }
+ }
+
+ private void drawTextLayout(Canvas canvas) {
+ StaticLayout layout = textLayout;
+ if (layout == null) {
+ // Nothing to draw.
+ return;
+ }
+
+ int saveCount = canvas.save();
+ canvas.translate(textLeft, textTop);
+
+ if (Color.alpha(windowColor) > 0) {
+ paint.setColor(windowColor);
+ canvas.drawRect(-textPaddingX, 0, layout.getWidth() + textPaddingX, layout.getHeight(),
+ paint);
+ }
+
+ if (Color.alpha(backgroundColor) > 0) {
+ paint.setColor(backgroundColor);
+ float previousBottom = layout.getLineTop(0);
+ int lineCount = layout.getLineCount();
+ for (int i = 0; i < lineCount; i++) {
+ lineBounds.left = layout.getLineLeft(i) - textPaddingX;
+ lineBounds.right = layout.getLineRight(i) + textPaddingX;
+ lineBounds.top = previousBottom;
+ lineBounds.bottom = layout.getLineBottom(i);
+ previousBottom = lineBounds.bottom;
+ canvas.drawRoundRect(lineBounds, cornerRadius, cornerRadius, paint);
+ }
+ }
+
+ if (edgeType == CaptionStyleCompat.EDGE_TYPE_OUTLINE) {
+ textPaint.setStrokeJoin(Join.ROUND);
+ textPaint.setStrokeWidth(outlineWidth);
+ textPaint.setColor(edgeColor);
+ textPaint.setStyle(Style.FILL_AND_STROKE);
+ layout.draw(canvas);
+ } else if (edgeType == CaptionStyleCompat.EDGE_TYPE_DROP_SHADOW) {
+ textPaint.setShadowLayer(shadowRadius, shadowOffset, shadowOffset, edgeColor);
+ } else if (edgeType == CaptionStyleCompat.EDGE_TYPE_RAISED
+ || edgeType == CaptionStyleCompat.EDGE_TYPE_DEPRESSED) {
+ boolean raised = edgeType == CaptionStyleCompat.EDGE_TYPE_RAISED;
+ int colorUp = raised ? Color.WHITE : edgeColor;
+ int colorDown = raised ? edgeColor : Color.WHITE;
+ float offset = shadowRadius / 2f;
+ textPaint.setColor(foregroundColor);
+ textPaint.setStyle(Style.FILL);
+ textPaint.setShadowLayer(shadowRadius, -offset, -offset, colorUp);
+ layout.draw(canvas);
+ textPaint.setShadowLayer(shadowRadius, offset, offset, colorDown);
+ }
+
+ textPaint.setColor(foregroundColor);
+ textPaint.setStyle(Style.FILL);
+ layout.draw(canvas);
+ textPaint.setShadowLayer(0, 0, 0, 0);
+
+ canvas.restoreToCount(saveCount);
+ }
+
+ private void drawBitmapLayout(Canvas canvas) {
+ canvas.drawBitmap(cueBitmap, null, bitmapRect, null);
+ }
+
+ /**
+ * This method is used instead of {@link TextUtils#equals(CharSequence, CharSequence)} because the
+ * latter only checks the text of each sequence, and does not check for equality of styling that
+ * may be embedded within the {@link CharSequence}s.
+ */
+ private static boolean areCharSequencesEqual(CharSequence first, CharSequence second) {
+ // Some CharSequence implementations don't perform a cheap referential equality check in their
+ // equals methods, so we perform one explicitly here.
+ return first == second || (first != null && first.equals(second));
+ }
+
+}
diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitleView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitleView.java
new file mode 100644
index 0000000000..49516ab6f4
--- /dev/null
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitleView.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.android.exoplayer2.ui;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.accessibility.CaptioningManager;
+import com.google.android.exoplayer2.text.CaptionStyleCompat;
+import com.google.android.exoplayer2.text.Cue;
+import com.google.android.exoplayer2.text.TextRenderer;
+import com.google.android.exoplayer2.util.Util;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A view for displaying subtitle {@link Cue}s.
+ */
+public final class SubtitleView extends View implements TextRenderer.Output {
+
+ /**
+ * The default fractional text size.
+ *
+ * @see #setFractionalTextSize(float, boolean)
+ */
+ public static final float DEFAULT_TEXT_SIZE_FRACTION = 0.0533f;
+
+ /**
+ * The default bottom padding to apply when {@link Cue#line} is {@link Cue#DIMEN_UNSET}, as a
+ * fraction of the viewport height.
+ *
+ * @see #setBottomPaddingFraction(float)
+ */
+ public static final float DEFAULT_BOTTOM_PADDING_FRACTION = 0.08f;
+
+ private static final int FRACTIONAL = 0;
+ private static final int FRACTIONAL_IGNORE_PADDING = 1;
+ private static final int ABSOLUTE = 2;
+
+ private final List painters;
+
+ private List cues;
+ private int textSizeType;
+ private float textSize;
+ private boolean applyEmbeddedStyles;
+ private CaptionStyleCompat style;
+ private float bottomPaddingFraction;
+
+ public SubtitleView(Context context) {
+ this(context, null);
+ }
+
+ public SubtitleView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ painters = new ArrayList<>();
+ textSizeType = FRACTIONAL;
+ textSize = DEFAULT_TEXT_SIZE_FRACTION;
+ applyEmbeddedStyles = true;
+ style = CaptionStyleCompat.DEFAULT;
+ bottomPaddingFraction = DEFAULT_BOTTOM_PADDING_FRACTION;
+ }
+
+ @Override
+ public void onCues(List cues) {
+ setCues(cues);
+ }
+
+ /**
+ * Sets the cues to be displayed by the view.
+ *
+ * @param cues The cues to display.
+ */
+ public void setCues(List cues) {
+ if (this.cues == cues) {
+ return;
+ }
+ this.cues = cues;
+ // Ensure we have sufficient painters.
+ int cueCount = (cues == null) ? 0 : cues.size();
+ while (painters.size() < cueCount) {
+ painters.add(new SubtitlePainter(getContext()));
+ }
+ // Invalidate to trigger drawing.
+ invalidate();
+ }
+
+ /**
+ * Set the text size to a given unit and value.
+ *
+ * See {@link TypedValue} for the possible dimension units.
+ *
+ * @param unit The desired dimension unit.
+ * @param size The desired size in the given units.
+ */
+ public void setFixedTextSize(int unit, float size) {
+ Context context = getContext();
+ Resources resources;
+ if (context == null) {
+ resources = Resources.getSystem();
+ } else {
+ resources = context.getResources();
+ }
+ setTextSize(ABSOLUTE, TypedValue.applyDimension(unit, size, resources.getDisplayMetrics()));
+ }
+
+ /**
+ * Sets the text size to one derived from {@link CaptioningManager#getFontScale()}, or to a
+ * default size before API level 19.
+ */
+ public void setUserDefaultTextSize() {
+ float fontScale = Util.SDK_INT >= 19 && !isInEditMode() ? getUserCaptionFontScaleV19() : 1f;
+ setFractionalTextSize(DEFAULT_TEXT_SIZE_FRACTION * fontScale);
+ }
+
+ /**
+ * Sets the text size to be a fraction of the view's remaining height after its top and bottom
+ * padding have been subtracted.
+ *
+ * Equivalent to {@code #setFractionalTextSize(fractionOfHeight, false)}.
+ *
+ * @param fractionOfHeight A fraction between 0 and 1.
+ */
+ public void setFractionalTextSize(float fractionOfHeight) {
+ setFractionalTextSize(fractionOfHeight, false);
+ }
+
+ /**
+ * Sets the text size to be a fraction of the height of this view.
+ *
+ * @param fractionOfHeight A fraction between 0 and 1.
+ * @param ignorePadding Set to true if {@code fractionOfHeight} should be interpreted as a
+ * fraction of this view's height ignoring any top and bottom padding. Set to false if
+ * {@code fractionOfHeight} should be interpreted as a fraction of this view's remaining
+ * height after the top and bottom padding has been subtracted.
+ */
+ public void setFractionalTextSize(float fractionOfHeight, boolean ignorePadding) {
+ setTextSize(ignorePadding ? FRACTIONAL_IGNORE_PADDING : FRACTIONAL, fractionOfHeight);
+ }
+
+ private void setTextSize(int textSizeType, float textSize) {
+ if (this.textSizeType == textSizeType && this.textSize == textSize) {
+ return;
+ }
+ this.textSizeType = textSizeType;
+ this.textSize = textSize;
+ // Invalidate to trigger drawing.
+ invalidate();
+ }
+
+ /**
+ * Sets whether styling embedded within the cues should be applied. Enabled by default.
+ *
+ * @param applyEmbeddedStyles Whether styling embedded within the cues should be applied.
+ */
+ public void setApplyEmbeddedStyles(boolean applyEmbeddedStyles) {
+ if (this.applyEmbeddedStyles == applyEmbeddedStyles) {
+ return;
+ }
+ this.applyEmbeddedStyles = applyEmbeddedStyles;
+ // Invalidate to trigger drawing.
+ invalidate();
+ }
+
+ /**
+ * Sets the caption style to be equivalent to the one returned by
+ * {@link CaptioningManager#getUserStyle()}, or to a default style before API level 19.
+ */
+ public void setUserDefaultStyle() {
+ setStyle(Util.SDK_INT >= 19 && !isInEditMode()
+ ? getUserCaptionStyleV19() : CaptionStyleCompat.DEFAULT);
+ }
+
+ /**
+ * Sets the caption style.
+ *
+ * @param style A style for the view.
+ */
+ public void setStyle(CaptionStyleCompat style) {
+ if (this.style == style) {
+ return;
+ }
+ this.style = style;
+ // Invalidate to trigger drawing.
+ invalidate();
+ }
+
+ /**
+ * Sets the bottom padding fraction to apply when {@link Cue#line} is {@link Cue#DIMEN_UNSET},
+ * as a fraction of the view's remaining height after its top and bottom padding have been
+ * subtracted.
+ *
+ * Note that this padding is applied in addition to any standard view padding.
+ *
+ * @param bottomPaddingFraction The bottom padding fraction.
+ */
+ public void setBottomPaddingFraction(float bottomPaddingFraction) {
+ if (this.bottomPaddingFraction == bottomPaddingFraction) {
+ return;
+ }
+ this.bottomPaddingFraction = bottomPaddingFraction;
+ // Invalidate to trigger drawing.
+ invalidate();
+ }
+
+ @Override
+ public void dispatchDraw(Canvas canvas) {
+ int cueCount = (cues == null) ? 0 : cues.size();
+ int rawTop = getTop();
+ int rawBottom = getBottom();
+
+ // Calculate the bounds after padding is taken into account.
+ int left = getLeft() + getPaddingLeft();
+ int top = rawTop + getPaddingTop();
+ int right = getRight() + getPaddingRight();
+ int bottom = rawBottom - getPaddingBottom();
+ if (bottom <= top || right <= left) {
+ // No space to draw subtitles.
+ return;
+ }
+
+ float textSizePx = textSizeType == ABSOLUTE ? textSize
+ : textSize * (textSizeType == FRACTIONAL ? (bottom - top) : (rawBottom - rawTop));
+ if (textSizePx <= 0) {
+ // Text has no height.
+ return;
+ }
+
+ for (int i = 0; i < cueCount; i++) {
+ painters.get(i).draw(cues.get(i), applyEmbeddedStyles, style, textSizePx,
+ bottomPaddingFraction, canvas, left, top, right, bottom);
+ }
+ }
+
+ @TargetApi(19)
+ private float getUserCaptionFontScaleV19() {
+ CaptioningManager captioningManager =
+ (CaptioningManager) getContext().getSystemService(Context.CAPTIONING_SERVICE);
+ return captioningManager.getFontScale();
+ }
+
+ @TargetApi(19)
+ private CaptionStyleCompat getUserCaptionStyleV19() {
+ CaptioningManager captioningManager =
+ (CaptioningManager) getContext().getSystemService(Context.CAPTIONING_SERVICE);
+ return CaptionStyleCompat.createFromCaptionStyle(captioningManager.getUserStyle());
+ }
+
+}
diff --git a/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_fastforward.xml b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_fastforward.xml
new file mode 100644
index 0000000000..4b86e109e9
--- /dev/null
+++ b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_fastforward.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_next.xml b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_next.xml
new file mode 100644
index 0000000000..6305bcbc90
--- /dev/null
+++ b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_next.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_pause.xml b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_pause.xml
new file mode 100644
index 0000000000..45cd68bed6
--- /dev/null
+++ b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_pause.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_play.xml b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_play.xml
new file mode 100644
index 0000000000..c8c4cdb127
--- /dev/null
+++ b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_play.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_previous.xml b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_previous.xml
new file mode 100644
index 0000000000..9564a2a350
--- /dev/null
+++ b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_previous.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_rewind.xml b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_rewind.xml
new file mode 100644
index 0000000000..976b706170
--- /dev/null
+++ b/library/ui/src/main/res/drawable-anydpi-v21/exo_controls_rewind.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/drawable-hdpi/exo_controls_fastforward.png b/library/ui/src/main/res/drawable-hdpi/exo_controls_fastforward.png
new file mode 100644
index 0000000000..843df84091
Binary files /dev/null and b/library/ui/src/main/res/drawable-hdpi/exo_controls_fastforward.png differ
diff --git a/library/ui/src/main/res/drawable-hdpi/exo_controls_next.png b/library/ui/src/main/res/drawable-hdpi/exo_controls_next.png
new file mode 100644
index 0000000000..c37541472e
Binary files /dev/null and b/library/ui/src/main/res/drawable-hdpi/exo_controls_next.png differ
diff --git a/library/ui/src/main/res/drawable-hdpi/exo_controls_pause.png b/library/ui/src/main/res/drawable-hdpi/exo_controls_pause.png
new file mode 100644
index 0000000000..0a23452746
Binary files /dev/null and b/library/ui/src/main/res/drawable-hdpi/exo_controls_pause.png differ
diff --git a/library/ui/src/main/res/drawable-hdpi/exo_controls_play.png b/library/ui/src/main/res/drawable-hdpi/exo_controls_play.png
new file mode 100644
index 0000000000..e98e2b9cbe
Binary files /dev/null and b/library/ui/src/main/res/drawable-hdpi/exo_controls_play.png differ
diff --git a/library/ui/src/main/res/drawable-hdpi/exo_controls_previous.png b/library/ui/src/main/res/drawable-hdpi/exo_controls_previous.png
new file mode 100644
index 0000000000..3eae5c883b
Binary files /dev/null and b/library/ui/src/main/res/drawable-hdpi/exo_controls_previous.png differ
diff --git a/library/ui/src/main/res/drawable-hdpi/exo_controls_rewind.png b/library/ui/src/main/res/drawable-hdpi/exo_controls_rewind.png
new file mode 100644
index 0000000000..36537d3b73
Binary files /dev/null and b/library/ui/src/main/res/drawable-hdpi/exo_controls_rewind.png differ
diff --git a/library/ui/src/main/res/drawable-ldpi/exo_controls_fastforward.png b/library/ui/src/main/res/drawable-ldpi/exo_controls_fastforward.png
new file mode 100644
index 0000000000..19b9e6015c
Binary files /dev/null and b/library/ui/src/main/res/drawable-ldpi/exo_controls_fastforward.png differ
diff --git a/library/ui/src/main/res/drawable-ldpi/exo_controls_next.png b/library/ui/src/main/res/drawable-ldpi/exo_controls_next.png
new file mode 100644
index 0000000000..d4872037aa
Binary files /dev/null and b/library/ui/src/main/res/drawable-ldpi/exo_controls_next.png differ
diff --git a/library/ui/src/main/res/drawable-ldpi/exo_controls_pause.png b/library/ui/src/main/res/drawable-ldpi/exo_controls_pause.png
new file mode 100644
index 0000000000..616ec42f39
Binary files /dev/null and b/library/ui/src/main/res/drawable-ldpi/exo_controls_pause.png differ
diff --git a/library/ui/src/main/res/drawable-ldpi/exo_controls_play.png b/library/ui/src/main/res/drawable-ldpi/exo_controls_play.png
new file mode 100644
index 0000000000..5d1c702892
Binary files /dev/null and b/library/ui/src/main/res/drawable-ldpi/exo_controls_play.png differ
diff --git a/library/ui/src/main/res/drawable-ldpi/exo_controls_previous.png b/library/ui/src/main/res/drawable-ldpi/exo_controls_previous.png
new file mode 100644
index 0000000000..930534d312
Binary files /dev/null and b/library/ui/src/main/res/drawable-ldpi/exo_controls_previous.png differ
diff --git a/library/ui/src/main/res/drawable-ldpi/exo_controls_rewind.png b/library/ui/src/main/res/drawable-ldpi/exo_controls_rewind.png
new file mode 100644
index 0000000000..83d71782f6
Binary files /dev/null and b/library/ui/src/main/res/drawable-ldpi/exo_controls_rewind.png differ
diff --git a/library/ui/src/main/res/drawable-mdpi/exo_controls_fastforward.png b/library/ui/src/main/res/drawable-mdpi/exo_controls_fastforward.png
new file mode 100644
index 0000000000..ee3efe1d69
Binary files /dev/null and b/library/ui/src/main/res/drawable-mdpi/exo_controls_fastforward.png differ
diff --git a/library/ui/src/main/res/drawable-mdpi/exo_controls_next.png b/library/ui/src/main/res/drawable-mdpi/exo_controls_next.png
new file mode 100644
index 0000000000..9d4d7469ed
Binary files /dev/null and b/library/ui/src/main/res/drawable-mdpi/exo_controls_next.png differ
diff --git a/library/ui/src/main/res/drawable-mdpi/exo_controls_pause.png b/library/ui/src/main/res/drawable-mdpi/exo_controls_pause.png
new file mode 100644
index 0000000000..f54c942201
Binary files /dev/null and b/library/ui/src/main/res/drawable-mdpi/exo_controls_pause.png differ
diff --git a/library/ui/src/main/res/drawable-mdpi/exo_controls_play.png b/library/ui/src/main/res/drawable-mdpi/exo_controls_play.png
new file mode 100644
index 0000000000..dd0c142859
Binary files /dev/null and b/library/ui/src/main/res/drawable-mdpi/exo_controls_play.png differ
diff --git a/library/ui/src/main/res/drawable-mdpi/exo_controls_previous.png b/library/ui/src/main/res/drawable-mdpi/exo_controls_previous.png
new file mode 100644
index 0000000000..950e213d2f
Binary files /dev/null and b/library/ui/src/main/res/drawable-mdpi/exo_controls_previous.png differ
diff --git a/library/ui/src/main/res/drawable-mdpi/exo_controls_rewind.png b/library/ui/src/main/res/drawable-mdpi/exo_controls_rewind.png
new file mode 100644
index 0000000000..e75efae189
Binary files /dev/null and b/library/ui/src/main/res/drawable-mdpi/exo_controls_rewind.png differ
diff --git a/library/ui/src/main/res/drawable-xhdpi/exo_controls_fastforward.png b/library/ui/src/main/res/drawable-xhdpi/exo_controls_fastforward.png
new file mode 100644
index 0000000000..ead712cfe9
Binary files /dev/null and b/library/ui/src/main/res/drawable-xhdpi/exo_controls_fastforward.png differ
diff --git a/library/ui/src/main/res/drawable-xhdpi/exo_controls_next.png b/library/ui/src/main/res/drawable-xhdpi/exo_controls_next.png
new file mode 100644
index 0000000000..bc1ebf83c5
Binary files /dev/null and b/library/ui/src/main/res/drawable-xhdpi/exo_controls_next.png differ
diff --git a/library/ui/src/main/res/drawable-xhdpi/exo_controls_pause.png b/library/ui/src/main/res/drawable-xhdpi/exo_controls_pause.png
new file mode 100644
index 0000000000..1c868f1831
Binary files /dev/null and b/library/ui/src/main/res/drawable-xhdpi/exo_controls_pause.png differ
diff --git a/library/ui/src/main/res/drawable-xhdpi/exo_controls_play.png b/library/ui/src/main/res/drawable-xhdpi/exo_controls_play.png
new file mode 100644
index 0000000000..f2f934413e
Binary files /dev/null and b/library/ui/src/main/res/drawable-xhdpi/exo_controls_play.png differ
diff --git a/library/ui/src/main/res/drawable-xhdpi/exo_controls_previous.png b/library/ui/src/main/res/drawable-xhdpi/exo_controls_previous.png
new file mode 100644
index 0000000000..d197eff873
Binary files /dev/null and b/library/ui/src/main/res/drawable-xhdpi/exo_controls_previous.png differ
diff --git a/library/ui/src/main/res/drawable-xhdpi/exo_controls_rewind.png b/library/ui/src/main/res/drawable-xhdpi/exo_controls_rewind.png
new file mode 100644
index 0000000000..3340ef9bd2
Binary files /dev/null and b/library/ui/src/main/res/drawable-xhdpi/exo_controls_rewind.png differ
diff --git a/library/ui/src/main/res/drawable-xxhdpi/exo_controls_fastforward.png b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_fastforward.png
new file mode 100644
index 0000000000..e1c6cae292
Binary files /dev/null and b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_fastforward.png differ
diff --git a/library/ui/src/main/res/drawable-xxhdpi/exo_controls_next.png b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_next.png
new file mode 100644
index 0000000000..232f09e910
Binary files /dev/null and b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_next.png differ
diff --git a/library/ui/src/main/res/drawable-xxhdpi/exo_controls_pause.png b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_pause.png
new file mode 100644
index 0000000000..50a545db4d
Binary files /dev/null and b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_pause.png differ
diff --git a/library/ui/src/main/res/drawable-xxhdpi/exo_controls_play.png b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_play.png
new file mode 100644
index 0000000000..08508c5015
Binary files /dev/null and b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_play.png differ
diff --git a/library/ui/src/main/res/drawable-xxhdpi/exo_controls_previous.png b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_previous.png
new file mode 100644
index 0000000000..f71acc4875
Binary files /dev/null and b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_previous.png differ
diff --git a/library/ui/src/main/res/drawable-xxhdpi/exo_controls_rewind.png b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_rewind.png
new file mode 100644
index 0000000000..db0555f9e5
Binary files /dev/null and b/library/ui/src/main/res/drawable-xxhdpi/exo_controls_rewind.png differ
diff --git a/library/ui/src/main/res/layout/exo_playback_control_view.xml b/library/ui/src/main/res/layout/exo_playback_control_view.xml
new file mode 100644
index 0000000000..f8ef5a6fdd
--- /dev/null
+++ b/library/ui/src/main/res/layout/exo_playback_control_view.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/layout/exo_simple_player_view.xml b/library/ui/src/main/res/layout/exo_simple_player_view.xml
new file mode 100644
index 0000000000..1f59b7796d
--- /dev/null
+++ b/library/ui/src/main/res/layout/exo_simple_player_view.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/values-af/strings.xml b/library/ui/src/main/res/values-af/strings.xml
new file mode 100644
index 0000000000..9f1bce53d9
--- /dev/null
+++ b/library/ui/src/main/res/values-af/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Vorige snit"
+ "Volgende snit"
+ "Wag"
+ "Speel"
+ "Stop"
+ "Spoel terug"
+ "Vinnig vorentoe"
+
diff --git a/library/ui/src/main/res/values-am/strings.xml b/library/ui/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000000..f06c2a664e
--- /dev/null
+++ b/library/ui/src/main/res/values-am/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "ቀዳሚ ትራክ"
+ "ቀጣይ ትራክ"
+ "ለአፍታ አቁም"
+ "አጫውት"
+ "አቁም"
+ "ወደኋላ አጠንጥን"
+ "በፍጥነት አሳልፍ"
+
diff --git a/library/ui/src/main/res/values-ar/strings.xml b/library/ui/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000000..a40c961bf7
--- /dev/null
+++ b/library/ui/src/main/res/values-ar/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "المقطع الصوتي السابق"
+ "المقطع الصوتي التالي"
+ "إيقاف مؤقت"
+ "تشغيل"
+ "إيقاف"
+ "إرجاع"
+ "تقديم سريع"
+
diff --git a/library/ui/src/main/res/values-az-rAZ/strings.xml b/library/ui/src/main/res/values-az-rAZ/strings.xml
new file mode 100644
index 0000000000..7b3b9366b5
--- /dev/null
+++ b/library/ui/src/main/res/values-az-rAZ/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Öncəki trek"
+ "Növbəti trek"
+ "Pauza"
+ "Oyun"
+ "Dayandır"
+ "Geri sarıma"
+ "Sürətlə irəli"
+
diff --git a/library/ui/src/main/res/values-b+sr+Latn/strings.xml b/library/ui/src/main/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000000..b5fdd74402
--- /dev/null
+++ b/library/ui/src/main/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Prethodna pesma"
+ "Sledeća pesma"
+ "Pauza"
+ "Pusti"
+ "Zaustavi"
+ "Premotaj unazad"
+ "Premotaj unapred"
+
diff --git a/library/ui/src/main/res/values-be-rBY/strings.xml b/library/ui/src/main/res/values-be-rBY/strings.xml
new file mode 100644
index 0000000000..890c23ebd5
--- /dev/null
+++ b/library/ui/src/main/res/values-be-rBY/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Папярэдні трэк"
+ "Наступны трэк"
+ "Прыпыніць"
+ "Прайграць"
+ "Спыніць"
+ "Перамотка назад"
+ "Перамотка ўперад"
+
diff --git a/library/ui/src/main/res/values-bg/strings.xml b/library/ui/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000000..30b905fb8e
--- /dev/null
+++ b/library/ui/src/main/res/values-bg/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Предишен запис"
+ "Следващ запис"
+ "Пауза"
+ "Пускане"
+ "Спиране"
+ "Превъртане назад"
+ "Превъртане напред"
+
diff --git a/library/ui/src/main/res/values-bn-rBD/strings.xml b/library/ui/src/main/res/values-bn-rBD/strings.xml
new file mode 100644
index 0000000000..ca5d9461d3
--- /dev/null
+++ b/library/ui/src/main/res/values-bn-rBD/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "পূর্ববর্তী ট্র্যাক"
+ "পরবর্তী ট্র্যাক"
+ "বিরাম দিন"
+ "প্লে করুন"
+ "থামান"
+ "গুটিয়ে নিন"
+ "দ্রুত সামনে এগোন"
+
diff --git a/library/ui/src/main/res/values-bs-rBA/strings.xml b/library/ui/src/main/res/values-bs-rBA/strings.xml
new file mode 100644
index 0000000000..9cb0ca4d76
--- /dev/null
+++ b/library/ui/src/main/res/values-bs-rBA/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Prethodna numera"
+ "Sljedeća numera"
+ "Pauziraj"
+ "Reproduciraj"
+ "Zaustavi"
+ "Premotaj"
+ "Ubrzaj"
+
diff --git a/library/ui/src/main/res/values-ca/strings.xml b/library/ui/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000000..0816c76b12
--- /dev/null
+++ b/library/ui/src/main/res/values-ca/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Ruta anterior"
+ "Ruta següent"
+ "Posa en pausa"
+ "Reprodueix"
+ "Atura"
+ "Rebobina"
+ "Avança ràpidament"
+
diff --git a/library/ui/src/main/res/values-cs/strings.xml b/library/ui/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000000..22cff4041e
--- /dev/null
+++ b/library/ui/src/main/res/values-cs/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Předchozí skladba"
+ "Další skladba"
+ "Pozastavit"
+ "Přehrát"
+ "Zastavit"
+ "Přetočit zpět"
+ "Přetočit vpřed"
+
diff --git a/library/ui/src/main/res/values-da/strings.xml b/library/ui/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000000..a6710bea50
--- /dev/null
+++ b/library/ui/src/main/res/values-da/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Forrige nummer"
+ "Næste nummer"
+ "Pause"
+ "Afspil"
+ "Stop"
+ "Spol tilbage"
+ "Spol frem"
+
diff --git a/library/ui/src/main/res/values-de/strings.xml b/library/ui/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000000..cdfd2d4baf
--- /dev/null
+++ b/library/ui/src/main/res/values-de/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Vorheriger Titel"
+ "Nächster Titel"
+ "Pausieren"
+ "Wiedergabe"
+ "Beenden"
+ "Zurückspulen"
+ "Vorspulen"
+
diff --git a/library/ui/src/main/res/values-el/strings.xml b/library/ui/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000000..1e11df3b14
--- /dev/null
+++ b/library/ui/src/main/res/values-el/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Προηγούμενο κομμάτι"
+ "Επόμενο κομμάτι"
+ "Παύση"
+ "Αναπαραγωγή"
+ "Διακοπή"
+ "Επαναφορά"
+ "Γρήγορη προώθηση"
+
diff --git a/library/ui/src/main/res/values-en-rAU/strings.xml b/library/ui/src/main/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000000..5077cf2b94
--- /dev/null
+++ b/library/ui/src/main/res/values-en-rAU/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Previous track"
+ "Next track"
+ "Pause"
+ "Play"
+ "Stop"
+ "Rewind"
+ "Fast-forward"
+
diff --git a/library/ui/src/main/res/values-en-rGB/strings.xml b/library/ui/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000000..5077cf2b94
--- /dev/null
+++ b/library/ui/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Previous track"
+ "Next track"
+ "Pause"
+ "Play"
+ "Stop"
+ "Rewind"
+ "Fast-forward"
+
diff --git a/library/ui/src/main/res/values-en-rIN/strings.xml b/library/ui/src/main/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000000..5077cf2b94
--- /dev/null
+++ b/library/ui/src/main/res/values-en-rIN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Previous track"
+ "Next track"
+ "Pause"
+ "Play"
+ "Stop"
+ "Rewind"
+ "Fast-forward"
+
diff --git a/library/ui/src/main/res/values-es-rUS/strings.xml b/library/ui/src/main/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000000..72b176e538
--- /dev/null
+++ b/library/ui/src/main/res/values-es-rUS/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Pista anterior"
+ "Siguiente pista"
+ "Pausar"
+ "Reproducir"
+ "Detener"
+ "Retroceder"
+ "Avanzar"
+
diff --git a/library/ui/src/main/res/values-es/strings.xml b/library/ui/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000000..3b188d266d
--- /dev/null
+++ b/library/ui/src/main/res/values-es/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Canción anterior"
+ "Siguiente canción"
+ "Pausar"
+ "Reproducir"
+ "Detener"
+ "Rebobinar"
+ "Avance rápido"
+
diff --git a/library/ui/src/main/res/values-et-rEE/strings.xml b/library/ui/src/main/res/values-et-rEE/strings.xml
new file mode 100644
index 0000000000..7a01bd9d5a
--- /dev/null
+++ b/library/ui/src/main/res/values-et-rEE/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Eelmine lugu"
+ "Järgmine lugu"
+ "Peata"
+ "Esita"
+ "Peata"
+ "Keri tagasi"
+ "Keri edasi"
+
diff --git a/library/ui/src/main/res/values-eu-rES/strings.xml b/library/ui/src/main/res/values-eu-rES/strings.xml
new file mode 100644
index 0000000000..3dd51d2138
--- /dev/null
+++ b/library/ui/src/main/res/values-eu-rES/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Aurreko pista"
+ "Hurrengo pista"
+ "Pausatu"
+ "Erreproduzitu"
+ "Gelditu"
+ "Atzeratu"
+ "Aurreratu"
+
diff --git a/library/ui/src/main/res/values-fa/strings.xml b/library/ui/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000000..a8955ca2f3
--- /dev/null
+++ b/library/ui/src/main/res/values-fa/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "آهنگ قبلی"
+ "آهنگ بعدی"
+ "مکث"
+ "پخش"
+ "توقف"
+ "عقب بردن"
+ "جلو بردن سریع"
+
diff --git a/library/ui/src/main/res/values-fi/strings.xml b/library/ui/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000000..5f1352d1af
--- /dev/null
+++ b/library/ui/src/main/res/values-fi/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Edellinen raita"
+ "Seuraava raita"
+ "Tauko"
+ "Toista"
+ "Seis"
+ "Kelaa taakse"
+ "Kelaa eteen"
+
diff --git a/library/ui/src/main/res/values-fr-rCA/strings.xml b/library/ui/src/main/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000000..51ba11e0c0
--- /dev/null
+++ b/library/ui/src/main/res/values-fr-rCA/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Chanson précédente"
+ "Chanson suivante"
+ "Pause"
+ "Lecture"
+ "Arrêter"
+ "Reculer"
+ "Avance rapide"
+
diff --git a/library/ui/src/main/res/values-fr/strings.xml b/library/ui/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000000..d55b32b6f7
--- /dev/null
+++ b/library/ui/src/main/res/values-fr/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Piste précédente"
+ "Piste suivante"
+ "Interrompre"
+ "Lire"
+ "Arrêter"
+ "Retour arrière"
+ "Avance rapide"
+
diff --git a/library/ui/src/main/res/values-gl-rES/strings.xml b/library/ui/src/main/res/values-gl-rES/strings.xml
new file mode 100644
index 0000000000..99ae59c7f9
--- /dev/null
+++ b/library/ui/src/main/res/values-gl-rES/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Pista anterior"
+ "Seguinte pista"
+ "Pausar"
+ "Reproducir"
+ "Deter"
+ "Rebobinar"
+ "Avance rápido"
+
diff --git a/library/ui/src/main/res/values-gu-rIN/strings.xml b/library/ui/src/main/res/values-gu-rIN/strings.xml
new file mode 100644
index 0000000000..6feab0a3a6
--- /dev/null
+++ b/library/ui/src/main/res/values-gu-rIN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "પહેલાનો ટ્રૅક"
+ "આગલો ટ્રૅક"
+ "થોભો"
+ "ચલાવો"
+ "રોકો"
+ "રીવાઇન્ડ કરો"
+ "ઝડપી ફોરવર્ડ કરો"
+
diff --git a/library/ui/src/main/res/values-hi/strings.xml b/library/ui/src/main/res/values-hi/strings.xml
new file mode 100644
index 0000000000..5229b67d0e
--- /dev/null
+++ b/library/ui/src/main/res/values-hi/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "पिछला ट्रैक"
+ "अगला ट्रैक"
+ "रोकें"
+ "चलाएं"
+ "बंद करें"
+ "रिवाइंड करें"
+ "फ़ास्ट फ़ॉरवर्ड"
+
diff --git a/library/ui/src/main/res/values-hr/strings.xml b/library/ui/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000000..c0b075edde
--- /dev/null
+++ b/library/ui/src/main/res/values-hr/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Prethodna pjesma"
+ "Sljedeća pjesma"
+ "Pauziraj"
+ "Reproduciraj"
+ "Zaustavi"
+ "Unatrag"
+ "Brzo unaprijed"
+
diff --git a/library/ui/src/main/res/values-hu/strings.xml b/library/ui/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000000..2a34684edb
--- /dev/null
+++ b/library/ui/src/main/res/values-hu/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Előző szám"
+ "Következő szám"
+ "Szünet"
+ "Lejátszás"
+ "Leállítás"
+ "Visszatekerés"
+ "Előretekerés"
+
diff --git a/library/ui/src/main/res/values-hy-rAM/strings.xml b/library/ui/src/main/res/values-hy-rAM/strings.xml
new file mode 100644
index 0000000000..05f9d04ab7
--- /dev/null
+++ b/library/ui/src/main/res/values-hy-rAM/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Նախորդը"
+ "Հաջորդը"
+ "Դադարեցնել"
+ "Նվագարկել"
+ "Դադարեցնել"
+ "Հետ փաթաթել"
+ "Արագ առաջ անցնել"
+
diff --git a/library/ui/src/main/res/values-in/strings.xml b/library/ui/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000000..062933a0a8
--- /dev/null
+++ b/library/ui/src/main/res/values-in/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Lagu sebelumnya"
+ "Lagu berikutnya"
+ "Jeda"
+ "Putar"
+ "Berhenti"
+ "Putar Ulang"
+ "Maju cepat"
+
diff --git a/library/ui/src/main/res/values-is-rIS/strings.xml b/library/ui/src/main/res/values-is-rIS/strings.xml
new file mode 100644
index 0000000000..9c4421a272
--- /dev/null
+++ b/library/ui/src/main/res/values-is-rIS/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Fyrra lag"
+ "Næsta lag"
+ "Hlé"
+ "Spila"
+ "Stöðva"
+ "Spóla til baka"
+ "Spóla áfram"
+
diff --git a/library/ui/src/main/res/values-it/strings.xml b/library/ui/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000000..71525a2b3e
--- /dev/null
+++ b/library/ui/src/main/res/values-it/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Traccia precedente"
+ "Traccia successiva"
+ "Metti in pausa"
+ "Riproduci"
+ "Interrompi"
+ "Riavvolgi"
+ "Avanti veloce"
+
diff --git a/library/ui/src/main/res/values-iw/strings.xml b/library/ui/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000000..f33cc2adb0
--- /dev/null
+++ b/library/ui/src/main/res/values-iw/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "הרצועה הקודמת"
+ "הרצועה הבאה"
+ "השהה"
+ "הפעל"
+ "הפסק"
+ "הרץ אחורה"
+ "הרץ קדימה"
+
diff --git a/library/ui/src/main/res/values-ja/strings.xml b/library/ui/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000000..baa459aeca
--- /dev/null
+++ b/library/ui/src/main/res/values-ja/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "前のトラック"
+ "次のトラック"
+ "一時停止"
+ "再生"
+ "停止"
+ "巻き戻し"
+ "早送り"
+
diff --git a/library/ui/src/main/res/values-ka-rGE/strings.xml b/library/ui/src/main/res/values-ka-rGE/strings.xml
new file mode 100644
index 0000000000..5b87f86c34
--- /dev/null
+++ b/library/ui/src/main/res/values-ka-rGE/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "წინა ჩანაწერი"
+ "შემდეგი ჩანაწერი"
+ "პაუზა"
+ "დაკვრა"
+ "შეწყვეტა"
+ "უკან გადახვევა"
+ "წინ გადახვევა"
+
diff --git a/library/ui/src/main/res/values-kk-rKZ/strings.xml b/library/ui/src/main/res/values-kk-rKZ/strings.xml
new file mode 100644
index 0000000000..c1bf5c8b4b
--- /dev/null
+++ b/library/ui/src/main/res/values-kk-rKZ/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Алдыңғы трек"
+ "Келесі трек"
+ "Кідірту"
+ "Ойнату"
+ "Тоқтату"
+ "Кері айналдыру"
+ "Жылдам алға айналдыру"
+
diff --git a/library/ui/src/main/res/values-km-rKH/strings.xml b/library/ui/src/main/res/values-km-rKH/strings.xml
new file mode 100644
index 0000000000..dbeeab60a6
--- /dev/null
+++ b/library/ui/src/main/res/values-km-rKH/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "បទមុន"
+ "បទបន្ទាប់"
+ "ផ្អាក"
+ "ចាក់"
+ "បញ្ឈប់"
+ "ខាថយក្រោយ"
+ "ទៅមុខរហ័ស"
+
diff --git a/library/ui/src/main/res/values-kn-rIN/strings.xml b/library/ui/src/main/res/values-kn-rIN/strings.xml
new file mode 100644
index 0000000000..b73cf0fdb0
--- /dev/null
+++ b/library/ui/src/main/res/values-kn-rIN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "ಹಿಂದಿನ ಟ್ರ್ಯಾಕ್"
+ "ಮುಂದಿನ ಟ್ರ್ಯಾಕ್"
+ "ವಿರಾಮಗೊಳಿಸು"
+ "ಪ್ಲೇ ಮಾಡು"
+ "ನಿಲ್ಲಿಸು"
+ "ರಿವೈಂಡ್ ಮಾಡು"
+ "ವೇಗವಾಗಿ ಮುಂದಕ್ಕೆ"
+
diff --git a/library/ui/src/main/res/values-ko/strings.xml b/library/ui/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000000..7097e2d9f7
--- /dev/null
+++ b/library/ui/src/main/res/values-ko/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "이전 트랙"
+ "다음 트랙"
+ "일시중지"
+ "재생"
+ "중지"
+ "되감기"
+ "빨리 감기"
+
diff --git a/library/ui/src/main/res/values-ky-rKG/strings.xml b/library/ui/src/main/res/values-ky-rKG/strings.xml
new file mode 100644
index 0000000000..7090c178c3
--- /dev/null
+++ b/library/ui/src/main/res/values-ky-rKG/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Мурунку трек"
+ "Кийинки трек"
+ "Тындыруу"
+ "Ойнотуу"
+ "Токтотуу"
+ "Артка түрүү"
+ "Алдыга түрүү"
+
diff --git a/library/ui/src/main/res/values-lo-rLA/strings.xml b/library/ui/src/main/res/values-lo-rLA/strings.xml
new file mode 100644
index 0000000000..44095e4323
--- /dev/null
+++ b/library/ui/src/main/res/values-lo-rLA/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "ເພງກ່ອນໜ້າ"
+ "ເພງຕໍ່ໄປ"
+ "ຢຸດຊົ່ວຄາວ"
+ "ຫຼິ້ນ"
+ "ຢຸດ"
+ "ຣີວາຍກັບ"
+ "ເລື່ອນໄປໜ້າ"
+
diff --git a/library/ui/src/main/res/values-lt/strings.xml b/library/ui/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000000..138caec322
--- /dev/null
+++ b/library/ui/src/main/res/values-lt/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Ankstesnis takelis"
+ "Kitas takelis"
+ "Pristabdyti"
+ "Leisti"
+ "Stabdyti"
+ "Sukti atgal"
+ "Sukti pirmyn"
+
diff --git a/library/ui/src/main/res/values-lv/strings.xml b/library/ui/src/main/res/values-lv/strings.xml
new file mode 100644
index 0000000000..4c91da86cc
--- /dev/null
+++ b/library/ui/src/main/res/values-lv/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Iepriekšējais ieraksts"
+ "Nākamais ieraksts"
+ "Pārtraukt"
+ "Atskaņot"
+ "Apturēt"
+ "Attīt atpakaļ"
+ "Ātri patīt"
+
diff --git a/library/ui/src/main/res/values-mk-rMK/strings.xml b/library/ui/src/main/res/values-mk-rMK/strings.xml
new file mode 100644
index 0000000000..e9fedf689f
--- /dev/null
+++ b/library/ui/src/main/res/values-mk-rMK/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Претходна песна"
+ "Следна песна"
+ "Пауза"
+ "Пушти"
+ "Запри"
+ "Премотај назад"
+ "Брзо премотај напред"
+
diff --git a/library/ui/src/main/res/values-ml-rIN/strings.xml b/library/ui/src/main/res/values-ml-rIN/strings.xml
new file mode 100644
index 0000000000..acc33934fb
--- /dev/null
+++ b/library/ui/src/main/res/values-ml-rIN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "മുമ്പത്തെ ട്രാക്ക്"
+ "അടുത്ത ട്രാക്ക്"
+ "താൽക്കാലികമായി നിർത്തുക"
+ "പ്ലേ ചെയ്യുക"
+ "നിര്ത്തുക"
+ "റിവൈൻഡുചെയ്യുക"
+ "വേഗത്തിലുള്ള കൈമാറൽ"
+
diff --git a/library/ui/src/main/res/values-mn-rMN/strings.xml b/library/ui/src/main/res/values-mn-rMN/strings.xml
new file mode 100644
index 0000000000..6434e9ea16
--- /dev/null
+++ b/library/ui/src/main/res/values-mn-rMN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Өмнөх трек"
+ "Дараагийн трек"
+ "Түр зогсоох"
+ "Тоглуулах"
+ "Зогсоох"
+ "Буцааж хураах"
+ "Хурдан урагшлуулах"
+
diff --git a/library/ui/src/main/res/values-mr-rIN/strings.xml b/library/ui/src/main/res/values-mr-rIN/strings.xml
new file mode 100644
index 0000000000..8f4d0d75b1
--- /dev/null
+++ b/library/ui/src/main/res/values-mr-rIN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "मागील ट्रॅक"
+ "पुढील ट्रॅक"
+ "विराम द्या"
+ "प्ले करा"
+ "थांबा"
+ "रिवाईँड करा"
+ "फास्ट फॉरवर्ड करा"
+
diff --git a/library/ui/src/main/res/values-ms-rMY/strings.xml b/library/ui/src/main/res/values-ms-rMY/strings.xml
new file mode 100644
index 0000000000..91f74bbc1c
--- /dev/null
+++ b/library/ui/src/main/res/values-ms-rMY/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Lagu sebelumnya"
+ "Lagu seterusnya"
+ "Jeda"
+ "Main"
+ "Berhenti"
+ "Gulung semula"
+ "Mara laju"
+
diff --git a/library/ui/src/main/res/values-my-rMM/strings.xml b/library/ui/src/main/res/values-my-rMM/strings.xml
new file mode 100644
index 0000000000..4b68e6e950
--- /dev/null
+++ b/library/ui/src/main/res/values-my-rMM/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "ယခင် တစ်ပုဒ်"
+ "နောက် တစ်ပုဒ်"
+ "ခဏရပ်ရန်"
+ "ဖွင့်ရန်"
+ "ရပ်ရန်"
+ "ပြန်ရစ်ရန်"
+ "ရှေ့သို့ သွားရန်"
+
diff --git a/library/ui/src/main/res/values-nb/strings.xml b/library/ui/src/main/res/values-nb/strings.xml
new file mode 100644
index 0000000000..37454235ad
--- /dev/null
+++ b/library/ui/src/main/res/values-nb/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Forrige spor"
+ "Neste spor"
+ "Sett på pause"
+ "Spill av"
+ "Stopp"
+ "Tilbakespoling"
+ "Fremoverspoling"
+
diff --git a/library/ui/src/main/res/values-ne-rNP/strings.xml b/library/ui/src/main/res/values-ne-rNP/strings.xml
new file mode 100644
index 0000000000..375e44afce
--- /dev/null
+++ b/library/ui/src/main/res/values-ne-rNP/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "अघिल्लो ट्रयाक"
+ "अर्को ट्रयाक"
+ "रोक्नुहोस्"
+ "चलाउनुहोस्"
+ "रोक्नुहोस्"
+ "दोहोर्याउनुहोस्"
+ "फास्ट फर्वार्ड"
+
diff --git a/library/ui/src/main/res/values-nl/strings.xml b/library/ui/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000000..2bdbf0bdae
--- /dev/null
+++ b/library/ui/src/main/res/values-nl/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Vorig nummer"
+ "Volgend nummer"
+ "Onderbreken"
+ "Afspelen"
+ "Stoppen"
+ "Terugspoelen"
+ "Vooruitspoelen"
+
diff --git a/library/ui/src/main/res/values-pa-rIN/strings.xml b/library/ui/src/main/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000000..143508e071
--- /dev/null
+++ b/library/ui/src/main/res/values-pa-rIN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "ਪਿਛਲਾ ਟਰੈਕ"
+ "ਅਗਲਾ ਟਰੈਕ"
+ "ਰੋਕੋ"
+ "ਪਲੇ ਕਰੋ"
+ "ਰੋਕੋ"
+ "ਰੀਵਾਈਂਡ ਕਰੋ"
+ "ਅੱਗੇ ਭੇਜੋ"
+
diff --git a/library/ui/src/main/res/values-pl/strings.xml b/library/ui/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000000..64f52d5d09
--- /dev/null
+++ b/library/ui/src/main/res/values-pl/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Poprzedni utwór"
+ "Następny utwór"
+ "Wstrzymaj"
+ "Odtwórz"
+ "Zatrzymaj"
+ "Przewiń do tyłu"
+ "Przewiń do przodu"
+
diff --git a/library/ui/src/main/res/values-pt-rBR/strings.xml b/library/ui/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000000..51bcf4d723
--- /dev/null
+++ b/library/ui/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Faixa anterior"
+ "Próxima faixa"
+ "Pausar"
+ "Reproduzir"
+ "Parar"
+ "Retroceder"
+ "Avançar"
+
diff --git a/library/ui/src/main/res/values-pt-rPT/strings.xml b/library/ui/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000000..5b3c9131d0
--- /dev/null
+++ b/library/ui/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Faixa anterior"
+ "Faixa seguinte"
+ "Interromper"
+ "Reproduzir"
+ "Parar"
+ "Rebobinar"
+ "Avançar"
+
diff --git a/library/ui/src/main/res/values-pt/strings.xml b/library/ui/src/main/res/values-pt/strings.xml
new file mode 100644
index 0000000000..51bcf4d723
--- /dev/null
+++ b/library/ui/src/main/res/values-pt/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Faixa anterior"
+ "Próxima faixa"
+ "Pausar"
+ "Reproduzir"
+ "Parar"
+ "Retroceder"
+ "Avançar"
+
diff --git a/library/ui/src/main/res/values-ro/strings.xml b/library/ui/src/main/res/values-ro/strings.xml
new file mode 100644
index 0000000000..5a7feda78c
--- /dev/null
+++ b/library/ui/src/main/res/values-ro/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Melodia anterioară"
+ "Melodia următoare"
+ "Pauză"
+ "Redați"
+ "Opriți"
+ "Derulați"
+ "Derulați rapid înainte"
+
diff --git a/library/ui/src/main/res/values-ru/strings.xml b/library/ui/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000000..da47546a8b
--- /dev/null
+++ b/library/ui/src/main/res/values-ru/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Предыдущий трек"
+ "Следующий трек"
+ "Приостановить"
+ "Воспроизвести"
+ "Остановить"
+ "Перемотать назад"
+ "Перемотать вперед"
+
diff --git a/library/ui/src/main/res/values-si-rLK/strings.xml b/library/ui/src/main/res/values-si-rLK/strings.xml
new file mode 100644
index 0000000000..0b579240e8
--- /dev/null
+++ b/library/ui/src/main/res/values-si-rLK/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "පෙර ගීතය"
+ "ඊළඟ ගීතය"
+ "විරාමය"
+ "ධාවනය කරන්න"
+ "නතර කරන්න"
+ "නැවත ඔතන්න"
+ "වේගයෙන් ඉදිරියට යන"
+
diff --git a/library/ui/src/main/res/values-sk/strings.xml b/library/ui/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000000..7596497e06
--- /dev/null
+++ b/library/ui/src/main/res/values-sk/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Predchádzajúca stopa"
+ "Ďalšia stopa"
+ "Pozastaviť"
+ "Prehrať"
+ "Zastaviť"
+ "Pretočiť späť"
+ "Pretočiť dopredu"
+
diff --git a/library/ui/src/main/res/values-sl/strings.xml b/library/ui/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000000..a77586b50c
--- /dev/null
+++ b/library/ui/src/main/res/values-sl/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Prejšnja skladba"
+ "Naslednja skladba"
+ "Zaustavi"
+ "Predvajaj"
+ "Ustavi"
+ "Previj nazaj"
+ "Previj naprej"
+
diff --git a/library/ui/src/main/res/values-sq-rAL/strings.xml b/library/ui/src/main/res/values-sq-rAL/strings.xml
new file mode 100644
index 0000000000..1fb824366d
--- /dev/null
+++ b/library/ui/src/main/res/values-sq-rAL/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Kënga e mëparshme"
+ "Kënga tjetër"
+ "Pauzë"
+ "Luaj"
+ "Ndalo"
+ "Kthehu pas"
+ "Përparo me shpejtësi"
+
diff --git a/library/ui/src/main/res/values-sr/strings.xml b/library/ui/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000000..175ad4fe7f
--- /dev/null
+++ b/library/ui/src/main/res/values-sr/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Претходна песма"
+ "Следећа песма"
+ "Пауза"
+ "Пусти"
+ "Заустави"
+ "Премотај уназад"
+ "Премотај унапред"
+
diff --git a/library/ui/src/main/res/values-sv/strings.xml b/library/ui/src/main/res/values-sv/strings.xml
new file mode 100644
index 0000000000..e6a8960458
--- /dev/null
+++ b/library/ui/src/main/res/values-sv/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Föregående spår"
+ "Nästa spår"
+ "Pausa"
+ "Spela upp"
+ "Avbryt"
+ "Spola tillbaka"
+ "Snabbspola framåt"
+
diff --git a/library/ui/src/main/res/values-sw/strings.xml b/library/ui/src/main/res/values-sw/strings.xml
new file mode 100644
index 0000000000..8055b7daff
--- /dev/null
+++ b/library/ui/src/main/res/values-sw/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Wimbo uliotangulia"
+ "Wimbo unaofuata"
+ "Sitisha"
+ "Cheza"
+ "Simamisha"
+ "Rudisha nyuma"
+ "Peleka mbele kwa kasi"
+
diff --git a/library/ui/src/main/res/values-ta-rIN/strings.xml b/library/ui/src/main/res/values-ta-rIN/strings.xml
new file mode 100644
index 0000000000..3eb995d467
--- /dev/null
+++ b/library/ui/src/main/res/values-ta-rIN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "முந்தைய ட்ராக்"
+ "அடுத்த ட்ராக்"
+ "இடைநிறுத்து"
+ "இயக்கு"
+ "நிறுத்து"
+ "மீண்டும் காட்டு"
+ "வேகமாக முன்செல்"
+
diff --git a/library/ui/src/main/res/values-te-rIN/strings.xml b/library/ui/src/main/res/values-te-rIN/strings.xml
new file mode 100644
index 0000000000..fe7930455a
--- /dev/null
+++ b/library/ui/src/main/res/values-te-rIN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "మునుపటి ట్రాక్"
+ "తదుపరి ట్రాక్"
+ "పాజ్ చేయి"
+ "ప్లే చేయి"
+ "ఆపివేయి"
+ "రివైండ్ చేయి"
+ "వేగంగా ఫార్వార్డ్ చేయి"
+
diff --git a/library/ui/src/main/res/values-th/strings.xml b/library/ui/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000000..deb2aac87d
--- /dev/null
+++ b/library/ui/src/main/res/values-th/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "แทร็กก่อนหน้า"
+ "แทร็กถัดไป"
+ "หยุดชั่วคราว"
+ "เล่น"
+ "หยุด"
+ "กรอกลับ"
+ "กรอไปข้างหน้า"
+
diff --git a/library/ui/src/main/res/values-tl/strings.xml b/library/ui/src/main/res/values-tl/strings.xml
new file mode 100644
index 0000000000..28dcb3267e
--- /dev/null
+++ b/library/ui/src/main/res/values-tl/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Nakaraang track"
+ "Susunod na track"
+ "I-pause"
+ "I-play"
+ "Ihinto"
+ "I-rewind"
+ "I-fast forward"
+
diff --git a/library/ui/src/main/res/values-tr/strings.xml b/library/ui/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000000..4265d796fe
--- /dev/null
+++ b/library/ui/src/main/res/values-tr/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Önceki parça"
+ "Sonraki parça"
+ "Duraklat"
+ "Çal"
+ "Durdur"
+ "Geri sar"
+ "İleri sar"
+
diff --git a/library/ui/src/main/res/values-uk/strings.xml b/library/ui/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000000..487ca07556
--- /dev/null
+++ b/library/ui/src/main/res/values-uk/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Попередня композиція"
+ "Наступна композиція"
+ "Пауза"
+ "Відтворити"
+ "Зупинити"
+ "Перемотати назад"
+ "Перемотати вперед"
+
diff --git a/library/ui/src/main/res/values-ur-rPK/strings.xml b/library/ui/src/main/res/values-ur-rPK/strings.xml
new file mode 100644
index 0000000000..55fa908bcd
--- /dev/null
+++ b/library/ui/src/main/res/values-ur-rPK/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "پچھلا ٹریک"
+ "اگلا ٹریک"
+ "موقوف کریں"
+ "چلائیں"
+ "روکیں"
+ "ریوائینڈ کریں"
+ "تیزی سے فارورڈ کریں"
+
diff --git a/library/ui/src/main/res/values-uz-rUZ/strings.xml b/library/ui/src/main/res/values-uz-rUZ/strings.xml
new file mode 100644
index 0000000000..9cee926844
--- /dev/null
+++ b/library/ui/src/main/res/values-uz-rUZ/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Avvalgi musiqa"
+ "Keyingi musiqa"
+ "To‘xtatib turish"
+ "Ijro qilish"
+ "To‘xtatish"
+ "Orqaga o‘tkazish"
+ "Oldinga o‘tkazish"
+
diff --git a/library/ui/src/main/res/values-v11/styles.xml b/library/ui/src/main/res/values-v11/styles.xml
new file mode 100644
index 0000000000..6f77440287
--- /dev/null
+++ b/library/ui/src/main/res/values-v11/styles.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/values-vi/strings.xml b/library/ui/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000000..917ec8e95c
--- /dev/null
+++ b/library/ui/src/main/res/values-vi/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Bản nhạc trước"
+ "Bản nhạc tiếp theo"
+ "Tạm dừng"
+ "Phát"
+ "Ngừng"
+ "Tua lại"
+ "Tua đi"
+
diff --git a/library/ui/src/main/res/values-zh-rCN/strings.xml b/library/ui/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000000..41e02409e2
--- /dev/null
+++ b/library/ui/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "上一曲"
+ "下一曲"
+ "暂停"
+ "播放"
+ "停止"
+ "快退"
+ "快进"
+
diff --git a/library/ui/src/main/res/values-zh-rHK/strings.xml b/library/ui/src/main/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000000..a3244bcd70
--- /dev/null
+++ b/library/ui/src/main/res/values-zh-rHK/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "上一首曲目"
+ "下一首曲目"
+ "暫停"
+ "播放"
+ "停止"
+ "倒帶"
+ "向前快轉"
+
diff --git a/library/ui/src/main/res/values-zh-rTW/strings.xml b/library/ui/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000000..ee915c5d9d
--- /dev/null
+++ b/library/ui/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "上一首曲目"
+ "下一首曲目"
+ "暫停"
+ "播放"
+ "停止"
+ "倒轉"
+ "快轉"
+
diff --git a/library/ui/src/main/res/values-zu/strings.xml b/library/ui/src/main/res/values-zu/strings.xml
new file mode 100644
index 0000000000..e998846454
--- /dev/null
+++ b/library/ui/src/main/res/values-zu/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+ "Ithrekhi yangaphambilini"
+ "Ithrekhi elandelayo"
+ "Misa isikhashana"
+ "Dlala"
+ "Misa"
+ "Buyisela emumva"
+ "Ukudlulisa ngokushesha"
+
diff --git a/library/ui/src/main/res/values/attrs.xml b/library/ui/src/main/res/values/attrs.xml
new file mode 100644
index 0000000000..c73bfb0a3c
--- /dev/null
+++ b/library/ui/src/main/res/values/attrs.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/values/constants.xml b/library/ui/src/main/res/values/constants.xml
new file mode 100644
index 0000000000..5c86696ea0
--- /dev/null
+++ b/library/ui/src/main/res/values/constants.xml
@@ -0,0 +1,21 @@
+
+
+
+
+ 71dp
+ 52dp
+
+
diff --git a/library/ui/src/main/res/values/ids.xml b/library/ui/src/main/res/values/ids.xml
new file mode 100644
index 0000000000..61db83825e
--- /dev/null
+++ b/library/ui/src/main/res/values/ids.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/ui/src/main/res/values/strings.xml b/library/ui/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..1e652dddb3
--- /dev/null
+++ b/library/ui/src/main/res/values/strings.xml
@@ -0,0 +1,24 @@
+
+
+
+ Previous track
+ Next track
+ Pause
+ Play
+ Stop
+ Rewind
+ Fast forward
+
diff --git a/library/ui/src/main/res/values/styles.xml b/library/ui/src/main/res/values/styles.xml
new file mode 100644
index 0000000000..a67cffe420
--- /dev/null
+++ b/library/ui/src/main/res/values/styles.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/settings.gradle b/settings.gradle
index 9578420959..4961921068 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -13,6 +13,7 @@
// limitations under the License.
include ':library'
include ':library-core'
+include ':library-ui'
include ':testutils'
include ':demo'
include ':playbacktests'
@@ -27,6 +28,7 @@ include ':extension-vp9'
project(':library').projectDir = new File(settingsDir, 'library/all')
project(':library-core').projectDir = new File(settingsDir, 'library/core')
+project(':library-ui').projectDir = new File(settingsDir, 'library/ui')
project(':extension-ffmpeg').projectDir = new File(settingsDir, 'extensions/ffmpeg')
project(':extension-flac').projectDir = new File(settingsDir, 'extensions/flac')
project(':extension-gvr').projectDir = new File(settingsDir, 'extensions/gvr')