Split UI components into separate module

Issue: #2139

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=150623215
This commit is contained in:
olly 2017-03-20 07:30:14 -07:00 committed by Oliver Woodman
parent de6e47f7e6
commit 7b08e972e4
133 changed files with 36 additions and 5061 deletions

View File

@ -27,6 +27,7 @@ android {
dependencies {
compile project(':library-core')
compile project(':library-ui')
}
android.libraryVariants.all { variant ->

View File

@ -1,149 +0,0 @@
/*
* 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 com.google.android.exoplayer2.core.R;
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.
* <p>
* 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));
}
}

View File

@ -1,181 +0,0 @@
/*
* 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;
}
}

View File

@ -1,813 +0,0 @@
/*
* 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.core.R;
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.
* <p>
* 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.
*
* <h3>Attributes</h3>
* The following attributes can be set on a PlaybackControlView when used in a layout XML file:
* <p>
* <ul>
* <li><b>{@code show_timeout}</b> - The time between the last user interaction and the controls
* being automatically hidden, in milliseconds. Use zero if the controls should not
* automatically timeout.
* <ul>
* <li>Corresponding method: {@link #setShowTimeoutMs(int)}</li>
* <li>Default: {@link #DEFAULT_SHOW_TIMEOUT_MS}</li>
* </ul>
* </li>
* <li><b>{@code rewind_increment}</b> - The duration of the rewind applied when the user taps the
* rewind button, in milliseconds. Use zero to disable the rewind button.
* <ul>
* <li>Corresponding method: {@link #setRewindIncrementMs(int)}</li>
* <li>Default: {@link #DEFAULT_REWIND_MS}</li>
* </ul>
* </li>
* <li><b>{@code fastforward_increment}</b> - Like {@code rewind_increment}, but for fast forward.
* <ul>
* <li>Corresponding method: {@link #setFastForwardIncrementMs(int)}</li>
* <li>Default: {@link #DEFAULT_FAST_FORWARD_MS}</li>
* </ul>
* </li>
* <li><b>{@code controller_layout_id}</b> - Specifies the id of the layout to be inflated. See
* below for more details.
* <ul>
* <li>Corresponding method: None</li>
* <li>Default: {@code R.id.exo_playback_control_view}</li>
* </ul>
* </li>
* </ul>
*
* <h3>Overriding the layout file</h3>
* To customize the layout of PlaybackControlView throughout your app, or just for certain
* configurations, you can define {@code exo_playback_control_view.xml} layout files in your
* application {@code res/layout*} directories. These layouts will override the one provided by the
* ExoPlayer library, and will be inflated for use by PlaybackControlView. The view identifies and
* binds its children by looking for the following ids:
* <p>
* <ul>
* <li><b>{@code exo_play}</b> - The play button.
* <ul>
* <li>Type: {@link View}</li>
* </ul>
* </li>
* <li><b>{@code exo_pause}</b> - The pause button.
* <ul>
* <li>Type: {@link View}</li>
* </ul>
* </li>
* <li><b>{@code exo_ffwd}</b> - The fast forward button.
* <ul>
* <li>Type: {@link View}</li>
* </ul>
* </li>
* <li><b>{@code exo_rew}</b> - The rewind button.
* <ul>
* <li>Type: {@link View}</li>
* </ul>
* </li>
* <li><b>{@code exo_prev}</b> - The previous track button.
* <ul>
* <li>Type: {@link View}</li>
* </ul>
* </li>
* <li><b>{@code exo_next}</b> - The next track button.
* <ul>
* <li>Type: {@link View}</li>
* </ul>
* </li>
* <li><b>{@code exo_position}</b> - Text view displaying the current playback position.
* <ul>
* <li>Type: {@link TextView}</li>
* </ul>
* </li>
* <li><b>{@code exo_duration}</b> - Text view displaying the current media duration.
* <ul>
* <li>Type: {@link TextView}</li>
* </ul>
* </li>
* <li><b>{@code exo_progress}</b> - Seek bar that's updated during playback and allows seeking.
* <ul>
* <li>Type: {@link SeekBar}</li>
* </ul>
* </li>
* </ul>
* <p>
* All child views are optional and so can be omitted if not required, however where defined they
* must be of the expected type.
*
* <h3>Specifying a custom layout file</h3>
* Defining your own {@code exo_playback_control_view.xml} is useful to customize the layout of
* PlaybackControlView throughout your application. It's also possible to customize the layout for a
* single instance in a layout file. This is achieved by setting the {@code controller_layout_id}
* attribute on a PlaybackControlView. This will cause the specified layout to be inflated instead
* of {@code exo_playback_control_view.xml} for only the instance on which the attribute is set.
*/
public class PlaybackControlView extends FrameLayout {
/**
* Listener to be notified about changes of the visibility of the UI control.
*/
public interface VisibilityListener {
/**
* Called when the visibility changes.
*
* @param visibility The new visibility. Either {@link View#VISIBLE} or {@link View#GONE}.
*/
void onVisibilityChange(int visibility);
}
/**
* Dispatches seek operations to the player.
*/
public interface SeekDispatcher {
/**
* @param player The player to seek.
* @param windowIndex The index of the window.
* @param positionMs The seek position in the specified window, or {@link C#TIME_UNSET} to seek
* to the window's default position.
* @return True if the seek was dispatched. False otherwise.
*/
boolean dispatchSeek(ExoPlayer player, int windowIndex, long positionMs);
}
/**
* Default {@link SeekDispatcher} that dispatches seeks to the player without modification.
*/
public static final SeekDispatcher DEFAULT_SEEK_DISPATCHER = new SeekDispatcher() {
@Override
public boolean dispatchSeek(ExoPlayer player, int windowIndex, long positionMs) {
player.seekTo(windowIndex, positionMs);
return true;
}
};
public static final int DEFAULT_FAST_FORWARD_MS = 15000;
public static final int DEFAULT_REWIND_MS = 5000;
public static final int DEFAULT_SHOW_TIMEOUT_MS = 5000;
private static final int PROGRESS_BAR_MAX = 1000;
private static final long MAX_POSITION_FOR_SEEK_TO_PREVIOUS = 3000;
private final ComponentListener componentListener;
private final View previousButton;
private final View nextButton;
private final View playButton;
private final View pauseButton;
private final View fastForwardButton;
private final View rewindButton;
private final TextView durationView;
private final TextView positionView;
private final SeekBar progressBar;
private final StringBuilder formatBuilder;
private final Formatter formatter;
private final Timeline.Window currentWindow;
private ExoPlayer player;
private SeekDispatcher seekDispatcher;
private VisibilityListener visibilityListener;
private boolean isAttachedToWindow;
private boolean dragging;
private int rewindMs;
private int fastForwardMs;
private int showTimeoutMs;
private long hideAtMs;
private final Runnable updateProgressAction = new Runnable() {
@Override
public void run() {
updateProgress();
}
};
private final Runnable hideAction = new Runnable() {
@Override
public void run() {
hide();
}
};
public PlaybackControlView(Context context) {
this(context, null);
}
public PlaybackControlView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PlaybackControlView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
int controllerLayoutId = R.layout.exo_playback_control_view;
rewindMs = DEFAULT_REWIND_MS;
fastForwardMs = DEFAULT_FAST_FORWARD_MS;
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.PlaybackControlView, 0, 0);
try {
rewindMs = a.getInt(R.styleable.PlaybackControlView_rewind_increment, rewindMs);
fastForwardMs = a.getInt(R.styleable.PlaybackControlView_fastforward_increment,
fastForwardMs);
showTimeoutMs = a.getInt(R.styleable.PlaybackControlView_show_timeout, showTimeoutMs);
controllerLayoutId = a.getResourceId(R.styleable.PlaybackControlView_controller_layout_id,
controllerLayoutId);
} finally {
a.recycle();
}
}
currentWindow = new Timeline.Window();
formatBuilder = new StringBuilder();
formatter = new Formatter(formatBuilder, Locale.getDefault());
componentListener = new ComponentListener();
seekDispatcher = DEFAULT_SEEK_DISPATCHER;
LayoutInflater.from(context).inflate(controllerLayoutId, this);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
durationView = (TextView) findViewById(R.id.exo_duration);
positionView = (TextView) findViewById(R.id.exo_position);
progressBar = (SeekBar) findViewById(R.id.exo_progress);
if (progressBar != null) {
progressBar.setOnSeekBarChangeListener(componentListener);
progressBar.setMax(PROGRESS_BAR_MAX);
}
playButton = findViewById(R.id.exo_play);
if (playButton != null) {
playButton.setOnClickListener(componentListener);
}
pauseButton = findViewById(R.id.exo_pause);
if (pauseButton != null) {
pauseButton.setOnClickListener(componentListener);
}
previousButton = findViewById(R.id.exo_prev);
if (previousButton != null) {
previousButton.setOnClickListener(componentListener);
}
nextButton = findViewById(R.id.exo_next);
if (nextButton != null) {
nextButton.setOnClickListener(componentListener);
}
rewindButton = findViewById(R.id.exo_rew);
if (rewindButton != null) {
rewindButton.setOnClickListener(componentListener);
}
fastForwardButton = findViewById(R.id.exo_ffwd);
if (fastForwardButton != null) {
fastForwardButton.setOnClickListener(componentListener);
}
}
/**
* Returns the player currently being controlled by this view, or null if no player is set.
*/
public ExoPlayer getPlayer() {
return player;
}
/**
* Sets the {@link ExoPlayer} to control.
*
* @param player the {@code ExoPlayer} to control.
*/
public void setPlayer(ExoPlayer player) {
if (this.player == player) {
return;
}
if (this.player != null) {
this.player.removeListener(componentListener);
}
this.player = player;
if (player != null) {
player.addListener(componentListener);
}
updateAll();
}
/**
* Sets the {@link VisibilityListener}.
*
* @param listener The listener to be notified about visibility changes.
*/
public void setVisibilityListener(VisibilityListener listener) {
this.visibilityListener = listener;
}
/**
* Sets the {@link SeekDispatcher}.
*
* @param seekDispatcher The {@link SeekDispatcher}, or null to use
* {@link #DEFAULT_SEEK_DISPATCHER}.
*/
public void setSeekDispatcher(SeekDispatcher seekDispatcher) {
this.seekDispatcher = seekDispatcher == null ? DEFAULT_SEEK_DISPATCHER : seekDispatcher;
}
/**
* Sets the rewind increment in milliseconds.
*
* @param rewindMs The rewind increment in milliseconds. A non-positive value will cause the
* rewind button to be disabled.
*/
public void setRewindIncrementMs(int rewindMs) {
this.rewindMs = rewindMs;
updateNavigation();
}
/**
* Sets the fast forward increment in milliseconds.
*
* @param fastForwardMs The fast forward increment in milliseconds. A non-positive value will
* cause the fast forward button to be disabled.
*/
public void setFastForwardIncrementMs(int fastForwardMs) {
this.fastForwardMs = fastForwardMs;
updateNavigation();
}
/**
* Returns the playback controls timeout. The playback controls are automatically hidden after
* this duration of time has elapsed without user input.
*
* @return The duration in milliseconds. A non-positive value indicates that the controls will
* remain visible indefinitely.
*/
public int getShowTimeoutMs() {
return showTimeoutMs;
}
/**
* Sets the playback controls timeout. The playback controls are automatically hidden after this
* duration of time has elapsed without user input.
*
* @param showTimeoutMs The duration in milliseconds. A non-positive value will cause the controls
* to remain visible indefinitely.
*/
public void setShowTimeoutMs(int showTimeoutMs) {
this.showTimeoutMs = showTimeoutMs;
}
/**
* Shows the playback controls. If {@link #getShowTimeoutMs()} is positive then the controls will
* be automatically hidden after this duration of time has elapsed without user input.
*/
public void show() {
if (!isVisible()) {
setVisibility(VISIBLE);
if (visibilityListener != null) {
visibilityListener.onVisibilityChange(getVisibility());
}
updateAll();
requestPlayPauseFocus();
}
// Call hideAfterTimeout even if already visible to reset the timeout.
hideAfterTimeout();
}
/**
* Hides the controller.
*/
public void hide() {
if (isVisible()) {
setVisibility(GONE);
if (visibilityListener != null) {
visibilityListener.onVisibilityChange(getVisibility());
}
removeCallbacks(updateProgressAction);
removeCallbacks(hideAction);
hideAtMs = C.TIME_UNSET;
}
}
/**
* Returns whether the controller is currently visible.
*/
public boolean isVisible() {
return getVisibility() == VISIBLE;
}
private void hideAfterTimeout() {
removeCallbacks(hideAction);
if (showTimeoutMs > 0) {
hideAtMs = SystemClock.uptimeMillis() + showTimeoutMs;
if (isAttachedToWindow) {
postDelayed(hideAction, showTimeoutMs);
}
} else {
hideAtMs = C.TIME_UNSET;
}
}
private void updateAll() {
updatePlayPauseButton();
updateNavigation();
updateProgress();
}
private void updatePlayPauseButton() {
if (!isVisible() || !isAttachedToWindow) {
return;
}
boolean requestPlayPauseFocus = false;
boolean playing = player != null && player.getPlayWhenReady();
if (playButton != null) {
requestPlayPauseFocus |= playing && playButton.isFocused();
playButton.setVisibility(playing ? View.GONE : View.VISIBLE);
}
if (pauseButton != null) {
requestPlayPauseFocus |= !playing && pauseButton.isFocused();
pauseButton.setVisibility(!playing ? View.GONE : View.VISIBLE);
}
if (requestPlayPauseFocus) {
requestPlayPauseFocus();
}
}
private void updateNavigation() {
if (!isVisible() || !isAttachedToWindow) {
return;
}
Timeline currentTimeline = player != null ? player.getCurrentTimeline() : null;
boolean haveNonEmptyTimeline = currentTimeline != null && !currentTimeline.isEmpty();
boolean isSeekable = false;
boolean enablePrevious = false;
boolean enableNext = false;
if (haveNonEmptyTimeline) {
int currentWindowIndex = player.getCurrentWindowIndex();
currentTimeline.getWindow(currentWindowIndex, currentWindow);
isSeekable = currentWindow.isSeekable;
enablePrevious = currentWindowIndex > 0 || isSeekable || !currentWindow.isDynamic;
enableNext = (currentWindowIndex < currentTimeline.getWindowCount() - 1)
|| currentWindow.isDynamic;
}
setButtonEnabled(enablePrevious , previousButton);
setButtonEnabled(enableNext, nextButton);
setButtonEnabled(fastForwardMs > 0 && isSeekable, fastForwardButton);
setButtonEnabled(rewindMs > 0 && isSeekable, rewindButton);
if (progressBar != null) {
progressBar.setEnabled(isSeekable);
}
}
private void updateProgress() {
if (!isVisible() || !isAttachedToWindow) {
return;
}
long duration = player == null ? 0 : player.getDuration();
long position = player == null ? 0 : player.getCurrentPosition();
if (durationView != null) {
durationView.setText(stringForTime(duration));
}
if (positionView != null && !dragging) {
positionView.setText(stringForTime(position));
}
if (progressBar != null) {
if (!dragging) {
progressBar.setProgress(progressBarValue(position));
}
long bufferedPosition = player == null ? 0 : player.getBufferedPosition();
progressBar.setSecondaryProgress(progressBarValue(bufferedPosition));
// Remove scheduled updates.
}
removeCallbacks(updateProgressAction);
// Schedule an update if necessary.
int playbackState = player == null ? ExoPlayer.STATE_IDLE : player.getPlaybackState();
if (playbackState != ExoPlayer.STATE_IDLE && playbackState != ExoPlayer.STATE_ENDED) {
long delayMs;
if (player.getPlayWhenReady() && playbackState == ExoPlayer.STATE_READY) {
delayMs = 1000 - (position % 1000);
if (delayMs < 200) {
delayMs += 1000;
}
} else {
delayMs = 1000;
}
postDelayed(updateProgressAction, delayMs);
}
}
private void requestPlayPauseFocus() {
boolean playing = player != null && player.getPlayWhenReady();
if (!playing && playButton != null) {
playButton.requestFocus();
} else if (playing && pauseButton != null) {
pauseButton.requestFocus();
}
}
private void setButtonEnabled(boolean enabled, View view) {
if (view == null) {
return;
}
view.setEnabled(enabled);
if (Util.SDK_INT >= 11) {
setViewAlphaV11(view, enabled ? 1f : 0.3f);
view.setVisibility(VISIBLE);
} else {
view.setVisibility(enabled ? VISIBLE : INVISIBLE);
}
}
@TargetApi(11)
private void setViewAlphaV11(View view, float alpha) {
view.setAlpha(alpha);
}
private String stringForTime(long timeMs) {
if (timeMs == C.TIME_UNSET) {
timeMs = 0;
}
long totalSeconds = (timeMs + 500) / 1000;
long seconds = totalSeconds % 60;
long minutes = (totalSeconds / 60) % 60;
long hours = totalSeconds / 3600;
formatBuilder.setLength(0);
return hours > 0 ? formatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()
: formatter.format("%02d:%02d", minutes, seconds).toString();
}
private int progressBarValue(long position) {
long duration = player == null ? C.TIME_UNSET : player.getDuration();
return duration == C.TIME_UNSET || duration == 0 ? 0
: (int) ((position * PROGRESS_BAR_MAX) / duration);
}
private long positionValue(int progress) {
long duration = player == null ? C.TIME_UNSET : player.getDuration();
return duration == C.TIME_UNSET ? 0 : ((duration * progress) / PROGRESS_BAR_MAX);
}
private void previous() {
Timeline currentTimeline = player.getCurrentTimeline();
if (currentTimeline.isEmpty()) {
return;
}
int currentWindowIndex = player.getCurrentWindowIndex();
currentTimeline.getWindow(currentWindowIndex, currentWindow);
if (currentWindowIndex > 0 && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS
|| (currentWindow.isDynamic && !currentWindow.isSeekable))) {
seekTo(currentWindowIndex - 1, C.TIME_UNSET);
} else {
seekTo(0);
}
}
private void next() {
Timeline currentTimeline = player.getCurrentTimeline();
if (currentTimeline.isEmpty()) {
return;
}
int currentWindowIndex = player.getCurrentWindowIndex();
if (currentWindowIndex < currentTimeline.getWindowCount() - 1) {
seekTo(currentWindowIndex + 1, C.TIME_UNSET);
} else if (currentTimeline.getWindow(currentWindowIndex, currentWindow, false).isDynamic) {
seekTo(currentWindowIndex, C.TIME_UNSET);
}
}
private void rewind() {
if (rewindMs <= 0) {
return;
}
seekTo(Math.max(player.getCurrentPosition() - rewindMs, 0));
}
private void fastForward() {
if (fastForwardMs <= 0) {
return;
}
seekTo(Math.min(player.getCurrentPosition() + fastForwardMs, player.getDuration()));
}
private void seekTo(long positionMs) {
seekTo(player.getCurrentWindowIndex(), positionMs);
}
private void seekTo(int windowIndex, long positionMs) {
boolean dispatched = seekDispatcher.dispatchSeek(player, windowIndex, positionMs);
if (!dispatched) {
// The seek wasn't dispatched. If the progress bar was dragged by the user to perform the
// seek then it'll now be in the wrong position. Trigger a progress update to snap it back.
updateProgress();
}
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
isAttachedToWindow = true;
if (hideAtMs != C.TIME_UNSET) {
long delayMs = hideAtMs - SystemClock.uptimeMillis();
if (delayMs <= 0) {
hide();
} else {
postDelayed(hideAction, delayMs);
}
}
updateAll();
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
isAttachedToWindow = false;
removeCallbacks(updateProgressAction);
removeCallbacks(hideAction);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
boolean handled = dispatchMediaKeyEvent(event) || super.dispatchKeyEvent(event);
if (handled) {
show();
}
return handled;
}
/**
* Called to process media key events. Any {@link KeyEvent} can be passed but only media key
* events will be handled.
*
* @param event A key event.
* @return Whether the key event was handled.
*/
public boolean dispatchMediaKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode();
if (player == null || !isHandledMediaKey(keyCode)) {
return false;
}
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
fastForward();
break;
case KeyEvent.KEYCODE_MEDIA_REWIND:
rewind();
break;
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
player.setPlayWhenReady(!player.getPlayWhenReady());
break;
case KeyEvent.KEYCODE_MEDIA_PLAY:
player.setPlayWhenReady(true);
break;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
player.setPlayWhenReady(false);
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
next();
break;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
previous();
break;
default:
break;
}
}
show();
return true;
}
private static boolean isHandledMediaKey(int keyCode) {
return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
|| keyCode == KeyEvent.KEYCODE_MEDIA_REWIND
|| keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
|| keyCode == KeyEvent.KEYCODE_MEDIA_PLAY
|| keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE
|| keyCode == KeyEvent.KEYCODE_MEDIA_NEXT
|| keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS;
}
private final class ComponentListener implements ExoPlayer.EventListener,
SeekBar.OnSeekBarChangeListener, OnClickListener {
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
removeCallbacks(hideAction);
dragging = true;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
long position = positionValue(progress);
if (positionView != null) {
positionView.setText(stringForTime(position));
}
if (player != null && !dragging) {
seekTo(position);
}
}
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
dragging = false;
if (player != null) {
seekTo(positionValue(seekBar.getProgress()));
}
hideAfterTimeout();
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
updatePlayPauseButton();
updateProgress();
}
@Override
public void onPositionDiscontinuity() {
updateNavigation();
updateProgress();
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
updateNavigation();
updateProgress();
}
@Override
public void onLoadingChanged(boolean isLoading) {
// Do nothing.
}
@Override
public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selections) {
// Do nothing.
}
@Override
public void onPlayerError(ExoPlaybackException error) {
// Do nothing.
}
@Override
public void onClick(View view) {
if (player != null) {
if (nextButton == view) {
next();
} else if (previousButton == view) {
previous();
} else if (fastForwardButton == view) {
fastForward();
} else if (rewindButton == view) {
rewind();
} else if (playButton == view) {
player.setPlayWhenReady(true);
} else if (pauseButton == view) {
player.setPlayWhenReady(false);
}
}
hideAfterTimeout();
}
}
}

View File

@ -1,718 +0,0 @@
/*
* 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.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.core.R;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextRenderer;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
import com.google.android.exoplayer2.ui.PlaybackControlView.SeekDispatcher;
import com.google.android.exoplayer2.util.Assertions;
import java.util.List;
/**
* A high level view for {@link SimpleExoPlayer} media playbacks. It displays video, subtitles and
* album art during playback, and displays playback controls using a {@link PlaybackControlView}.
* <p>
* 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.
*
* <h3>Attributes</h3>
* The following attributes can be set on a SimpleExoPlayerView when used in a layout XML file:
* <p>
* <ul>
* <li><b>{@code use_artwork}</b> - Whether artwork is used if available in audio streams.
* <ul>
* <li>Corresponding method: {@link #setUseArtwork(boolean)}</li>
* <li>Default: {@code true}</li>
* </ul>
* </li>
* <li><b>{@code default_artwork}</b> - Default artwork to use if no artwork available in audio
* streams.
* <ul>
* <li>Corresponding method: {@link #setDefaultArtwork(Bitmap)}</li>
* <li>Default: {@code null}</li>
* </ul>
* </li>
* <li><b>{@code use_controller}</b> - Whether playback controls are displayed.
* <ul>
* <li>Corresponding method: {@link #setUseController(boolean)}</li>
* <li>Default: {@code true}</li>
* </ul>
* </li>
* <li><b>{@code resize_mode}</b> - Controls how video and album art is resized within the view.
* Valid values are {@code fit}, {@code fixed_width}, {@code fixed_height} and {@code fill}.
* <ul>
* <li>Corresponding method: {@link #setResizeMode(int)}</li>
* <li>Default: {@code fit}</li>
* </ul>
* </li>
* <li><b>{@code surface_type}</b> - The type of surface view used for video playbacks. Valid
* values are {@code surface_view}, {@code texture_view} and {@code none}. Using {@code none}
* is recommended for audio only applications, since creating the surface can be expensive.
* Using {@code surface_view} is recommended for video applications.
* <ul>
* <li>Corresponding method: None</li>
* <li>Default: {@code surface_view}</li>
* </ul>
* </li>
* <li><b>{@code player_layout_id}</b> - Specifies the id of the layout to be inflated. See below
* for more details.
* <ul>
* <li>Corresponding method: None</li>
* <li>Default: {@code R.id.exo_simple_player_view}</li>
* </ul>
* <li><b>{@code controller_layout_id}</b> - Specifies the id of the layout resource to be
* inflated by the child {@link PlaybackControlView}. See below for more details.
* <ul>
* <li>Corresponding method: None</li>
* <li>Default: {@code R.id.exo_playback_control_view}</li>
* </ul>
* <li>All attributes that can be set on a {@link PlaybackControlView} can also be set on a
* SimpleExoPlayerView, and will be propagated to the inflated {@link PlaybackControlView}.
* </li>
* </ul>
*
* <h3>Overriding the layout file</h3>
* To customize the layout of SimpleExoPlayerView throughout your app, or just for certain
* configurations, you can define {@code exo_simple_player_view.xml} layout files in your
* application {@code res/layout*} directories. These layouts will override the one provided by the
* ExoPlayer library, and will be inflated for use by SimpleExoPlayerView. The view identifies and
* binds its children by looking for the following ids:
* <p>
* <ul>
* <li><b>{@code exo_content_frame}</b> - A frame whose aspect ratio is resized based on the video
* or album art of the media being played, and the configured {@code resize_mode}. The video
* surface view is inflated into this frame as its first child.
* <ul>
* <li>Type: {@link AspectRatioFrameLayout}</li>
* </ul>
* </li>
* <li><b>{@code exo_shutter}</b> - A view that's made visible when video should be hidden. This
* view is typically an opaque view that covers the video surface view, thereby obscuring it
* when visible.
* <ul>
* <li>Type: {@link View}</li>
* </ul>
* </li>
* <li><b>{@code exo_subtitles}</b> - Displays subtitles.
* <ul>
* <li>Type: {@link SubtitleView}</li>
* </ul>
* </li>
* <li><b>{@code exo_artwork}</b> - Displays album art.
* <ul>
* <li>Type: {@link ImageView}</li>
* </ul>
* </li>
* <li><b>{@code exo_controller_placeholder}</b> - A placeholder that's replaced with the inflated
* {@link PlaybackControlView}.
* <ul>
* <li>Type: {@link View}</li>
* </ul>
* </li>
* <li><b>{@code exo_overlay}</b> - A {@link FrameLayout} positioned on top of the player which
* the app can access via {@link #getOverlayFrameLayout()}, provided for convenience.
* <ul>
* <li>Type: {@link FrameLayout}</li>
* </ul>
* </li>
* </ul>
* <p>
* All child views are optional and so can be omitted if not required, however where defined they
* must be of the expected type.
*
* <h3>Specifying a custom layout file</h3>
* Defining your own {@code exo_simple_player_view.xml} is useful to customize the layout of
* SimpleExoPlayerView throughout your application. It's also possible to customize the layout for a
* single instance in a layout file. This is achieved by setting the {@code player_layout_id}
* attribute on a SimpleExoPlayerView. This will cause the specified layout to be inflated instead
* of {@code exo_simple_player_view.xml} for only the instance on which the attribute is set.
*/
@TargetApi(16)
public final class SimpleExoPlayerView extends FrameLayout {
private static final int SURFACE_TYPE_NONE = 0;
private static final int SURFACE_TYPE_SURFACE_VIEW = 1;
private static final int SURFACE_TYPE_TEXTURE_VIEW = 2;
private final AspectRatioFrameLayout contentFrame;
private final View shutterView;
private final View surfaceView;
private final ImageView artworkView;
private final SubtitleView subtitleView;
private final PlaybackControlView controller;
private final ComponentListener componentListener;
private final FrameLayout overlayFrameLayout;
private SimpleExoPlayer player;
private boolean useController;
private boolean useArtwork;
private Bitmap defaultArtwork;
private int controllerShowTimeoutMs;
public SimpleExoPlayerView(Context context) {
this(context, null);
}
public SimpleExoPlayerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SimpleExoPlayerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
int playerLayoutId = R.layout.exo_simple_player_view;
boolean useArtwork = true;
int defaultArtworkId = 0;
boolean useController = true;
int surfaceType = SURFACE_TYPE_SURFACE_VIEW;
int resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT;
int controllerShowTimeoutMs = PlaybackControlView.DEFAULT_SHOW_TIMEOUT_MS;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SimpleExoPlayerView, 0, 0);
try {
playerLayoutId = a.getResourceId(R.styleable.SimpleExoPlayerView_player_layout_id,
playerLayoutId);
useArtwork = a.getBoolean(R.styleable.SimpleExoPlayerView_use_artwork, useArtwork);
defaultArtworkId = a.getResourceId(R.styleable.SimpleExoPlayerView_default_artwork,
defaultArtworkId);
useController = a.getBoolean(R.styleable.SimpleExoPlayerView_use_controller, useController);
surfaceType = a.getInt(R.styleable.SimpleExoPlayerView_surface_type, surfaceType);
resizeMode = a.getInt(R.styleable.SimpleExoPlayerView_resize_mode, resizeMode);
controllerShowTimeoutMs = a.getInt(R.styleable.SimpleExoPlayerView_show_timeout,
controllerShowTimeoutMs);
} finally {
a.recycle();
}
}
LayoutInflater.from(context).inflate(playerLayoutId, this);
componentListener = new ComponentListener();
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
// Content frame.
contentFrame = (AspectRatioFrameLayout) findViewById(R.id.exo_content_frame);
if (contentFrame != null) {
setResizeModeRaw(contentFrame, resizeMode);
}
// Shutter view.
shutterView = findViewById(R.id.exo_shutter);
// Create a surface view and insert it into the content frame, if there is one.
if (contentFrame != null && surfaceType != SURFACE_TYPE_NONE) {
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
surfaceView = surfaceType == SURFACE_TYPE_TEXTURE_VIEW ? new TextureView(context)
: new SurfaceView(context);
surfaceView.setLayoutParams(params);
contentFrame.addView(surfaceView, 0);
} else {
surfaceView = null;
}
// Overlay frame layout.
overlayFrameLayout = (FrameLayout) findViewById(R.id.exo_overlay);
// Artwork view.
artworkView = (ImageView) findViewById(R.id.exo_artwork);
this.useArtwork = useArtwork && artworkView != null;
if (defaultArtworkId != 0) {
defaultArtwork = BitmapFactory.decodeResource(context.getResources(), defaultArtworkId);
}
// Subtitle view.
subtitleView = (SubtitleView) findViewById(R.id.exo_subtitles);
if (subtitleView != null) {
subtitleView.setUserDefaultStyle();
subtitleView.setUserDefaultTextSize();
}
// Playback control view.
View controllerPlaceholder = findViewById(R.id.exo_controller_placeholder);
if (controllerPlaceholder != null) {
// Note: rewindMs and fastForwardMs are passed via attrs, so we don't need to make explicit
// calls to set them.
this.controller = new PlaybackControlView(context, attrs);
controller.setLayoutParams(controllerPlaceholder.getLayoutParams());
ViewGroup parent = ((ViewGroup) controllerPlaceholder.getParent());
int controllerIndex = parent.indexOfChild(controllerPlaceholder);
parent.removeView(controllerPlaceholder);
parent.addView(controller, controllerIndex);
} else {
this.controller = null;
}
this.controllerShowTimeoutMs = controller != null ? controllerShowTimeoutMs : 0;
this.useController = useController && controller != null;
hideController();
}
/**
* Returns the player currently set on this view, or null if no player is set.
*/
public SimpleExoPlayer getPlayer() {
return player;
}
/**
* Set the {@link SimpleExoPlayer} to use. The {@link SimpleExoPlayer#setTextOutput} and
* {@link SimpleExoPlayer#setVideoListener} method of the player will be called and previous
* assignments are overridden.
*
* @param player The {@link SimpleExoPlayer} to use.
*/
public void setPlayer(SimpleExoPlayer player) {
if (this.player == player) {
return;
}
if (this.player != null) {
this.player.setTextOutput(null);
this.player.setVideoListener(null);
this.player.removeListener(componentListener);
this.player.setVideoSurface(null);
}
this.player = player;
if (useController) {
controller.setPlayer(player);
}
if (shutterView != null) {
shutterView.setVisibility(VISIBLE);
}
if (player != null) {
if (surfaceView instanceof TextureView) {
player.setVideoTextureView((TextureView) surfaceView);
} else if (surfaceView instanceof SurfaceView) {
player.setVideoSurfaceView((SurfaceView) surfaceView);
}
player.setVideoListener(componentListener);
player.addListener(componentListener);
player.setTextOutput(componentListener);
maybeShowController(false);
updateForCurrentTrackSelections();
} else {
hideController();
hideArtwork();
}
}
/**
* Sets the resize mode.
*
* @param resizeMode The resize mode.
*/
public void setResizeMode(@ResizeMode int resizeMode) {
Assertions.checkState(contentFrame != null);
contentFrame.setResizeMode(resizeMode);
}
/**
* Returns whether artwork is displayed if present in the media.
*/
public boolean getUseArtwork() {
return useArtwork;
}
/**
* Sets whether artwork is displayed if present in the media.
*
* @param useArtwork Whether artwork is displayed.
*/
public void setUseArtwork(boolean useArtwork) {
Assertions.checkState(!useArtwork || artworkView != null);
if (this.useArtwork != useArtwork) {
this.useArtwork = useArtwork;
updateForCurrentTrackSelections();
}
}
/**
* Returns the default artwork to display.
*/
public Bitmap getDefaultArtwork() {
return defaultArtwork;
}
/**
* Sets the default artwork to display if {@code useArtwork} is {@code true} and no artwork is
* present in the media.
*
* @param defaultArtwork the default artwork to display.
*/
public void setDefaultArtwork(Bitmap defaultArtwork) {
if (this.defaultArtwork != defaultArtwork) {
this.defaultArtwork = defaultArtwork;
updateForCurrentTrackSelections();
}
}
/**
* Returns whether the playback controls are enabled.
*/
public boolean getUseController() {
return useController;
}
/**
* Sets whether playback controls are enabled. If set to {@code false} the playback controls are
* never visible and are disconnected from the player.
*
* @param useController Whether playback controls should be enabled.
*/
public void setUseController(boolean useController) {
Assertions.checkState(!useController || controller != null);
if (this.useController == useController) {
return;
}
this.useController = useController;
if (useController) {
controller.setPlayer(player);
} else if (controller != null) {
controller.hide();
controller.setPlayer(null);
}
}
/**
* Called to process media key events. Any {@link KeyEvent} can be passed but only media key
* events will be handled. Does nothing if playback controls are disabled.
*
* @param event A key event.
* @return Whether the key event was handled.
*/
public boolean dispatchMediaKeyEvent(KeyEvent event) {
return useController && controller.dispatchMediaKeyEvent(event);
}
/**
* Shows the playback controls. Does nothing if playback controls are disabled.
*/
public void showController() {
if (useController) {
maybeShowController(true);
}
}
/**
* Hides the playback controls. Does nothing if playback controls are disabled.
*/
public void hideController() {
if (controller != null) {
controller.hide();
}
}
/**
* Returns the playback controls timeout. The playback controls are automatically hidden after
* this duration of time has elapsed without user input and with playback or buffering in
* progress.
*
* @return The timeout in milliseconds. A non-positive value will cause the controller to remain
* visible indefinitely.
*/
public int getControllerShowTimeoutMs() {
return controllerShowTimeoutMs;
}
/**
* Sets the playback controls timeout. The playback controls are automatically hidden after this
* duration of time has elapsed without user input and with playback or buffering in progress.
*
* @param controllerShowTimeoutMs The timeout in milliseconds. A non-positive value will cause
* the controller to remain visible indefinitely.
*/
public void setControllerShowTimeoutMs(int controllerShowTimeoutMs) {
Assertions.checkState(controller != null);
this.controllerShowTimeoutMs = controllerShowTimeoutMs;
}
/**
* Set the {@link PlaybackControlView.VisibilityListener}.
*
* @param listener The listener to be notified about visibility changes.
*/
public void setControllerVisibilityListener(PlaybackControlView.VisibilityListener listener) {
Assertions.checkState(controller != null);
controller.setVisibilityListener(listener);
}
/**
* Sets the {@link SeekDispatcher}.
*
* @param seekDispatcher The {@link SeekDispatcher}, or null to use
* {@link PlaybackControlView#DEFAULT_SEEK_DISPATCHER}.
*/
public void setSeekDispatcher(SeekDispatcher seekDispatcher) {
Assertions.checkState(controller != null);
controller.setSeekDispatcher(seekDispatcher);
}
/**
* Sets the rewind increment in milliseconds.
*
* @param rewindMs The rewind increment in milliseconds.
*/
public void setRewindIncrementMs(int rewindMs) {
Assertions.checkState(controller != null);
controller.setRewindIncrementMs(rewindMs);
}
/**
* Sets the fast forward increment in milliseconds.
*
* @param fastForwardMs The fast forward increment in milliseconds.
*/
public void setFastForwardIncrementMs(int fastForwardMs) {
Assertions.checkState(controller != null);
controller.setFastForwardIncrementMs(fastForwardMs);
}
/**
* Gets the view onto which video is rendered. This is either a {@link SurfaceView} (default)
* or a {@link TextureView} if the {@code use_texture_view} view attribute has been set to true.
*
* @return Either a {@link SurfaceView} or a {@link TextureView}.
*/
public View getVideoSurfaceView() {
return surfaceView;
}
/**
* Gets the overlay {@link FrameLayout}, which can be populated with UI elements to show on top of
* the player.
*
* @return The overlay {@link FrameLayout}, or {@code null} if the layout has been customized and
* the overlay is not present.
*/
public FrameLayout getOverlayFrameLayout() {
return overlayFrameLayout;
}
/**
* Gets the {@link SubtitleView}.
*
* @return The {@link SubtitleView}, or {@code null} if the layout has been customized and the
* subtitle view is not present.
*/
public SubtitleView getSubtitleView() {
return subtitleView;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (!useController || player == null || ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
return false;
}
if (controller.isVisible()) {
controller.hide();
} else {
maybeShowController(true);
}
return true;
}
@Override
public boolean onTrackballEvent(MotionEvent ev) {
if (!useController || player == null) {
return false;
}
maybeShowController(true);
return true;
}
private void maybeShowController(boolean isForced) {
if (!useController || player == null) {
return;
}
int playbackState = player.getPlaybackState();
boolean showIndefinitely = playbackState == ExoPlayer.STATE_IDLE
|| playbackState == ExoPlayer.STATE_ENDED || !player.getPlayWhenReady();
boolean wasShowingIndefinitely = controller.isVisible() && controller.getShowTimeoutMs() <= 0;
controller.setShowTimeoutMs(showIndefinitely ? 0 : controllerShowTimeoutMs);
if (isForced || showIndefinitely || wasShowingIndefinitely) {
controller.show();
}
}
private void updateForCurrentTrackSelections() {
if (player == null) {
return;
}
TrackSelectionArray selections = player.getCurrentTrackSelections();
for (int i = 0; i < selections.length; i++) {
if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) {
// Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in
// onRenderedFirstFrame().
hideArtwork();
return;
}
}
// Video disabled so the shutter must be closed.
if (shutterView != null) {
shutterView.setVisibility(VISIBLE);
}
// Display artwork if enabled and available, else hide it.
if (useArtwork) {
for (int i = 0; i < selections.length; i++) {
TrackSelection selection = selections.get(i);
if (selection != null) {
for (int j = 0; j < selection.length(); j++) {
Metadata metadata = selection.getFormat(j).metadata;
if (metadata != null && setArtworkFromMetadata(metadata)) {
return;
}
}
}
}
if (setArtworkFromBitmap(defaultArtwork)) {
return;
}
}
// Artwork disabled or unavailable.
hideArtwork();
}
private boolean setArtworkFromMetadata(Metadata metadata) {
for (int i = 0; i < metadata.length(); i++) {
Metadata.Entry metadataEntry = metadata.get(i);
if (metadataEntry instanceof ApicFrame) {
byte[] bitmapData = ((ApicFrame) metadataEntry).pictureData;
Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length);
return setArtworkFromBitmap(bitmap);
}
}
return false;
}
private boolean setArtworkFromBitmap(Bitmap bitmap) {
if (bitmap != null) {
int bitmapWidth = bitmap.getWidth();
int bitmapHeight = bitmap.getHeight();
if (bitmapWidth > 0 && bitmapHeight > 0) {
if (contentFrame != null) {
contentFrame.setAspectRatio((float) bitmapWidth / bitmapHeight);
}
artworkView.setImageBitmap(bitmap);
artworkView.setVisibility(VISIBLE);
return true;
}
}
return false;
}
private void hideArtwork() {
if (artworkView != null) {
artworkView.setImageResource(android.R.color.transparent); // Clears any bitmap reference.
artworkView.setVisibility(INVISIBLE);
}
}
@SuppressWarnings("ResourceType")
private static void setResizeModeRaw(AspectRatioFrameLayout aspectRatioFrame, int resizeMode) {
aspectRatioFrame.setResizeMode(resizeMode);
}
private final class ComponentListener implements SimpleExoPlayer.VideoListener,
TextRenderer.Output, ExoPlayer.EventListener {
// TextRenderer.Output implementation
@Override
public void onCues(List<Cue> 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.
}
}
}

View File

@ -1,405 +0,0 @@
/*
* 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.
* <p>
* 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));
}
}

View File

@ -1,265 +0,0 @@
/*
* 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<SubtitlePainter> painters;
private List<Cue> 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<Cue> cues) {
setCues(cues);
}
/**
* Sets the cues to be displayed by the view.
*
* @param cues The cues to display.
*/
public void setCues(List<Cue> 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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());
}
}

View File

@ -1,25 +0,0 @@
<!-- Copyright (C) 2017 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
</vector>

View File

@ -1,25 +0,0 @@
<!-- Copyright (C) 2017 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
</vector>

View File

@ -1,25 +0,0 @@
<!-- Copyright (C) 2017 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
</vector>

View File

@ -1,25 +0,0 @@
<!-- Copyright (C) 2017 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M8,5v14l11,-7z"/>
</vector>

View File

@ -1,25 +0,0 @@
<!-- Copyright (C) 2017 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z"/>
</vector>

View File

@ -1,25 +0,0 @@
<!-- Copyright (C) 2017 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 571 B

View File

@ -1,87 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layoutDirection="ltr"
android:background="#CC000000"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="4dp"
android:orientation="horizontal">
<ImageButton android:id="@id/exo_prev"
style="@style/ExoMediaButton.Previous"/>
<ImageButton android:id="@id/exo_rew"
style="@style/ExoMediaButton.Rewind"/>
<ImageButton android:id="@id/exo_play"
style="@style/ExoMediaButton.Play"/>
<ImageButton android:id="@id/exo_pause"
style="@style/ExoMediaButton.Pause"/>
<ImageButton android:id="@id/exo_ffwd"
style="@style/ExoMediaButton.FastForward"/>
<ImageButton android:id="@id/exo_next"
style="@style/ExoMediaButton.Next"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView android:id="@id/exo_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:includeFontPadding="false"
android:textColor="#FFBEBEBE"/>
<SeekBar android:id="@id/exo_progress"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="32dp"
android:focusable="false"
style="?android:attr/progressBarStyleHorizontal"/>
<TextView android:id="@id/exo_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:includeFontPadding="false"
android:textColor="#FFBEBEBE"/>
</LinearLayout>
</LinearLayout>

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout android:id="@id/exo_content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<!-- Video surface will be inserted as the first child of the content frame. -->
<View android:id="@id/exo_shutter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"/>
<ImageView android:id="@id/exo_artwork"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"/>
<com.google.android.exoplayer2.ui.SubtitleView android:id="@id/exo_subtitles"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
<View android:id="@id/exo_controller_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout android:id="@id/exo_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</merge>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Vorige snit"</string>
<string name="exo_controls_next_description">"Volgende snit"</string>
<string name="exo_controls_pause_description">"Wag"</string>
<string name="exo_controls_play_description">"Speel"</string>
<string name="exo_controls_stop_description">"Stop"</string>
<string name="exo_controls_rewind_description">"Spoel terug"</string>
<string name="exo_controls_fastforward_description">"Vinnig vorentoe"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"ቀዳሚ ትራክ"</string>
<string name="exo_controls_next_description">"ቀጣይ ትራክ"</string>
<string name="exo_controls_pause_description">"ለአፍታ አቁም"</string>
<string name="exo_controls_play_description">"አጫውት"</string>
<string name="exo_controls_stop_description">"አቁም"</string>
<string name="exo_controls_rewind_description">"ወደኋላ አጠንጥን"</string>
<string name="exo_controls_fastforward_description">"በፍጥነት አሳልፍ"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"المقطع الصوتي السابق"</string>
<string name="exo_controls_next_description">"المقطع الصوتي التالي"</string>
<string name="exo_controls_pause_description">"إيقاف مؤقت"</string>
<string name="exo_controls_play_description">"تشغيل"</string>
<string name="exo_controls_stop_description">"إيقاف"</string>
<string name="exo_controls_rewind_description">"إرجاع"</string>
<string name="exo_controls_fastforward_description">"تقديم سريع"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Öncəki trek"</string>
<string name="exo_controls_next_description">"Növbəti trek"</string>
<string name="exo_controls_pause_description">"Pauza"</string>
<string name="exo_controls_play_description">"Oyun"</string>
<string name="exo_controls_stop_description">"Dayandır"</string>
<string name="exo_controls_rewind_description">"Geri sarıma"</string>
<string name="exo_controls_fastforward_description">"Sürətlə irəli"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Prethodna pesma"</string>
<string name="exo_controls_next_description">"Sledeća pesma"</string>
<string name="exo_controls_pause_description">"Pauza"</string>
<string name="exo_controls_play_description">"Pusti"</string>
<string name="exo_controls_stop_description">"Zaustavi"</string>
<string name="exo_controls_rewind_description">"Premotaj unazad"</string>
<string name="exo_controls_fastforward_description">"Premotaj unapred"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Папярэдні трэк"</string>
<string name="exo_controls_next_description">"Наступны трэк"</string>
<string name="exo_controls_pause_description">"Прыпыніць"</string>
<string name="exo_controls_play_description">"Прайграць"</string>
<string name="exo_controls_stop_description">"Спыніць"</string>
<string name="exo_controls_rewind_description">"Перамотка назад"</string>
<string name="exo_controls_fastforward_description">"Перамотка ўперад"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Предишен запис"</string>
<string name="exo_controls_next_description">"Следващ запис"</string>
<string name="exo_controls_pause_description">"Пауза"</string>
<string name="exo_controls_play_description">"Пускане"</string>
<string name="exo_controls_stop_description">"Спиране"</string>
<string name="exo_controls_rewind_description">"Превъртане назад"</string>
<string name="exo_controls_fastforward_description">"Превъртане напред"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"পূর্ববর্তী ট্র্যাক"</string>
<string name="exo_controls_next_description">"পরবর্তী ট্র্যাক"</string>
<string name="exo_controls_pause_description">"বিরাম দিন"</string>
<string name="exo_controls_play_description">"প্লে করুন"</string>
<string name="exo_controls_stop_description">"থামান"</string>
<string name="exo_controls_rewind_description">"গুটিয়ে নিন"</string>
<string name="exo_controls_fastforward_description">"দ্রুত সামনে এগোন"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Prethodna numera"</string>
<string name="exo_controls_next_description">"Sljedeća numera"</string>
<string name="exo_controls_pause_description">"Pauziraj"</string>
<string name="exo_controls_play_description">"Reproduciraj"</string>
<string name="exo_controls_stop_description">"Zaustavi"</string>
<string name="exo_controls_rewind_description">"Premotaj"</string>
<string name="exo_controls_fastforward_description">"Ubrzaj"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Ruta anterior"</string>
<string name="exo_controls_next_description">"Ruta següent"</string>
<string name="exo_controls_pause_description">"Posa en pausa"</string>
<string name="exo_controls_play_description">"Reprodueix"</string>
<string name="exo_controls_stop_description">"Atura"</string>
<string name="exo_controls_rewind_description">"Rebobina"</string>
<string name="exo_controls_fastforward_description">"Avança ràpidament"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Předchozí skladba"</string>
<string name="exo_controls_next_description">"Další skladba"</string>
<string name="exo_controls_pause_description">"Pozastavit"</string>
<string name="exo_controls_play_description">"Přehrát"</string>
<string name="exo_controls_stop_description">"Zastavit"</string>
<string name="exo_controls_rewind_description">"Přetočit zpět"</string>
<string name="exo_controls_fastforward_description">"Přetočit vpřed"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Forrige nummer"</string>
<string name="exo_controls_next_description">"Næste nummer"</string>
<string name="exo_controls_pause_description">"Pause"</string>
<string name="exo_controls_play_description">"Afspil"</string>
<string name="exo_controls_stop_description">"Stop"</string>
<string name="exo_controls_rewind_description">"Spol tilbage"</string>
<string name="exo_controls_fastforward_description">"Spol frem"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Vorheriger Titel"</string>
<string name="exo_controls_next_description">"Nächster Titel"</string>
<string name="exo_controls_pause_description">"Pausieren"</string>
<string name="exo_controls_play_description">"Wiedergabe"</string>
<string name="exo_controls_stop_description">"Beenden"</string>
<string name="exo_controls_rewind_description">"Zurückspulen"</string>
<string name="exo_controls_fastforward_description">"Vorspulen"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Προηγούμενο κομμάτι"</string>
<string name="exo_controls_next_description">"Επόμενο κομμάτι"</string>
<string name="exo_controls_pause_description">"Παύση"</string>
<string name="exo_controls_play_description">"Αναπαραγωγή"</string>
<string name="exo_controls_stop_description">"Διακοπή"</string>
<string name="exo_controls_rewind_description">"Επαναφορά"</string>
<string name="exo_controls_fastforward_description">"Γρήγορη προώθηση"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Previous track"</string>
<string name="exo_controls_next_description">"Next track"</string>
<string name="exo_controls_pause_description">"Pause"</string>
<string name="exo_controls_play_description">"Play"</string>
<string name="exo_controls_stop_description">"Stop"</string>
<string name="exo_controls_rewind_description">"Rewind"</string>
<string name="exo_controls_fastforward_description">"Fast-forward"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Previous track"</string>
<string name="exo_controls_next_description">"Next track"</string>
<string name="exo_controls_pause_description">"Pause"</string>
<string name="exo_controls_play_description">"Play"</string>
<string name="exo_controls_stop_description">"Stop"</string>
<string name="exo_controls_rewind_description">"Rewind"</string>
<string name="exo_controls_fastforward_description">"Fast-forward"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Previous track"</string>
<string name="exo_controls_next_description">"Next track"</string>
<string name="exo_controls_pause_description">"Pause"</string>
<string name="exo_controls_play_description">"Play"</string>
<string name="exo_controls_stop_description">"Stop"</string>
<string name="exo_controls_rewind_description">"Rewind"</string>
<string name="exo_controls_fastforward_description">"Fast-forward"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Pista anterior"</string>
<string name="exo_controls_next_description">"Siguiente pista"</string>
<string name="exo_controls_pause_description">"Pausar"</string>
<string name="exo_controls_play_description">"Reproducir"</string>
<string name="exo_controls_stop_description">"Detener"</string>
<string name="exo_controls_rewind_description">"Retroceder"</string>
<string name="exo_controls_fastforward_description">"Avanzar"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Canción anterior"</string>
<string name="exo_controls_next_description">"Siguiente canción"</string>
<string name="exo_controls_pause_description">"Pausar"</string>
<string name="exo_controls_play_description">"Reproducir"</string>
<string name="exo_controls_stop_description">"Detener"</string>
<string name="exo_controls_rewind_description">"Rebobinar"</string>
<string name="exo_controls_fastforward_description">"Avance rápido"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Eelmine lugu"</string>
<string name="exo_controls_next_description">"Järgmine lugu"</string>
<string name="exo_controls_pause_description">"Peata"</string>
<string name="exo_controls_play_description">"Esita"</string>
<string name="exo_controls_stop_description">"Peata"</string>
<string name="exo_controls_rewind_description">"Keri tagasi"</string>
<string name="exo_controls_fastforward_description">"Keri edasi"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Aurreko pista"</string>
<string name="exo_controls_next_description">"Hurrengo pista"</string>
<string name="exo_controls_pause_description">"Pausatu"</string>
<string name="exo_controls_play_description">"Erreproduzitu"</string>
<string name="exo_controls_stop_description">"Gelditu"</string>
<string name="exo_controls_rewind_description">"Atzeratu"</string>
<string name="exo_controls_fastforward_description">"Aurreratu"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"آهنگ قبلی"</string>
<string name="exo_controls_next_description">"آهنگ بعدی"</string>
<string name="exo_controls_pause_description">"مکث"</string>
<string name="exo_controls_play_description">"پخش"</string>
<string name="exo_controls_stop_description">"توقف"</string>
<string name="exo_controls_rewind_description">"عقب بردن"</string>
<string name="exo_controls_fastforward_description">"جلو بردن سریع"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Edellinen raita"</string>
<string name="exo_controls_next_description">"Seuraava raita"</string>
<string name="exo_controls_pause_description">"Tauko"</string>
<string name="exo_controls_play_description">"Toista"</string>
<string name="exo_controls_stop_description">"Seis"</string>
<string name="exo_controls_rewind_description">"Kelaa taakse"</string>
<string name="exo_controls_fastforward_description">"Kelaa eteen"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Chanson précédente"</string>
<string name="exo_controls_next_description">"Chanson suivante"</string>
<string name="exo_controls_pause_description">"Pause"</string>
<string name="exo_controls_play_description">"Lecture"</string>
<string name="exo_controls_stop_description">"Arrêter"</string>
<string name="exo_controls_rewind_description">"Reculer"</string>
<string name="exo_controls_fastforward_description">"Avance rapide"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Piste précédente"</string>
<string name="exo_controls_next_description">"Piste suivante"</string>
<string name="exo_controls_pause_description">"Interrompre"</string>
<string name="exo_controls_play_description">"Lire"</string>
<string name="exo_controls_stop_description">"Arrêter"</string>
<string name="exo_controls_rewind_description">"Retour arrière"</string>
<string name="exo_controls_fastforward_description">"Avance rapide"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Pista anterior"</string>
<string name="exo_controls_next_description">"Seguinte pista"</string>
<string name="exo_controls_pause_description">"Pausar"</string>
<string name="exo_controls_play_description">"Reproducir"</string>
<string name="exo_controls_stop_description">"Deter"</string>
<string name="exo_controls_rewind_description">"Rebobinar"</string>
<string name="exo_controls_fastforward_description">"Avance rápido"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"પહેલાનો ટ્રૅક"</string>
<string name="exo_controls_next_description">"આગલો ટ્રૅક"</string>
<string name="exo_controls_pause_description">"થોભો"</string>
<string name="exo_controls_play_description">"ચલાવો"</string>
<string name="exo_controls_stop_description">"રોકો"</string>
<string name="exo_controls_rewind_description">"રીવાઇન્ડ કરો"</string>
<string name="exo_controls_fastforward_description">"ઝડપી ફોરવર્ડ કરો"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"पिछला ट्रैक"</string>
<string name="exo_controls_next_description">"अगला ट्रैक"</string>
<string name="exo_controls_pause_description">"रोकें"</string>
<string name="exo_controls_play_description">"चलाएं"</string>
<string name="exo_controls_stop_description">"बंद करें"</string>
<string name="exo_controls_rewind_description">"रिवाइंड करें"</string>
<string name="exo_controls_fastforward_description">"फ़ास्ट फ़ॉरवर्ड"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Prethodna pjesma"</string>
<string name="exo_controls_next_description">"Sljedeća pjesma"</string>
<string name="exo_controls_pause_description">"Pauziraj"</string>
<string name="exo_controls_play_description">"Reproduciraj"</string>
<string name="exo_controls_stop_description">"Zaustavi"</string>
<string name="exo_controls_rewind_description">"Unatrag"</string>
<string name="exo_controls_fastforward_description">"Brzo unaprijed"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Előző szám"</string>
<string name="exo_controls_next_description">"Következő szám"</string>
<string name="exo_controls_pause_description">"Szünet"</string>
<string name="exo_controls_play_description">"Lejátszás"</string>
<string name="exo_controls_stop_description">"Leállítás"</string>
<string name="exo_controls_rewind_description">"Visszatekerés"</string>
<string name="exo_controls_fastforward_description">"Előretekerés"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Նախորդը"</string>
<string name="exo_controls_next_description">"Հաջորդը"</string>
<string name="exo_controls_pause_description">"Դադարեցնել"</string>
<string name="exo_controls_play_description">"Նվագարկել"</string>
<string name="exo_controls_stop_description">"Դադարեցնել"</string>
<string name="exo_controls_rewind_description">"Հետ փաթաթել"</string>
<string name="exo_controls_fastforward_description">"Արագ առաջ անցնել"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Lagu sebelumnya"</string>
<string name="exo_controls_next_description">"Lagu berikutnya"</string>
<string name="exo_controls_pause_description">"Jeda"</string>
<string name="exo_controls_play_description">"Putar"</string>
<string name="exo_controls_stop_description">"Berhenti"</string>
<string name="exo_controls_rewind_description">"Putar Ulang"</string>
<string name="exo_controls_fastforward_description">"Maju cepat"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Fyrra lag"</string>
<string name="exo_controls_next_description">"Næsta lag"</string>
<string name="exo_controls_pause_description">"Hlé"</string>
<string name="exo_controls_play_description">"Spila"</string>
<string name="exo_controls_stop_description">"Stöðva"</string>
<string name="exo_controls_rewind_description">"Spóla til baka"</string>
<string name="exo_controls_fastforward_description">"Spóla áfram"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Traccia precedente"</string>
<string name="exo_controls_next_description">"Traccia successiva"</string>
<string name="exo_controls_pause_description">"Metti in pausa"</string>
<string name="exo_controls_play_description">"Riproduci"</string>
<string name="exo_controls_stop_description">"Interrompi"</string>
<string name="exo_controls_rewind_description">"Riavvolgi"</string>
<string name="exo_controls_fastforward_description">"Avanti veloce"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"הרצועה הקודמת"</string>
<string name="exo_controls_next_description">"הרצועה הבאה"</string>
<string name="exo_controls_pause_description">"השהה"</string>
<string name="exo_controls_play_description">"הפעל"</string>
<string name="exo_controls_stop_description">"הפסק"</string>
<string name="exo_controls_rewind_description">"הרץ אחורה"</string>
<string name="exo_controls_fastforward_description">"הרץ קדימה"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"前のトラック"</string>
<string name="exo_controls_next_description">"次のトラック"</string>
<string name="exo_controls_pause_description">"一時停止"</string>
<string name="exo_controls_play_description">"再生"</string>
<string name="exo_controls_stop_description">"停止"</string>
<string name="exo_controls_rewind_description">"巻き戻し"</string>
<string name="exo_controls_fastforward_description">"早送り"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"წინა ჩანაწერი"</string>
<string name="exo_controls_next_description">"შემდეგი ჩანაწერი"</string>
<string name="exo_controls_pause_description">"პაუზა"</string>
<string name="exo_controls_play_description">"დაკვრა"</string>
<string name="exo_controls_stop_description">"შეწყვეტა"</string>
<string name="exo_controls_rewind_description">"უკან გადახვევა"</string>
<string name="exo_controls_fastforward_description">"წინ გადახვევა"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Алдыңғы трек"</string>
<string name="exo_controls_next_description">"Келесі трек"</string>
<string name="exo_controls_pause_description">"Кідірту"</string>
<string name="exo_controls_play_description">"Ойнату"</string>
<string name="exo_controls_stop_description">"Тоқтату"</string>
<string name="exo_controls_rewind_description">"Кері айналдыру"</string>
<string name="exo_controls_fastforward_description">"Жылдам алға айналдыру"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"បទ​មុន"</string>
<string name="exo_controls_next_description">"បទ​បន្ទាប់"</string>
<string name="exo_controls_pause_description">"ផ្អាក"</string>
<string name="exo_controls_play_description">"ចាក់"</string>
<string name="exo_controls_stop_description">"បញ្ឈប់"</string>
<string name="exo_controls_rewind_description">"ខា​ថយក្រោយ"</string>
<string name="exo_controls_fastforward_description">"ទៅ​មុខ​​​រហ័ស"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"ಹಿಂದಿನ ಟ್ರ್ಯಾಕ್"</string>
<string name="exo_controls_next_description">"ಮುಂದಿನ ಟ್ರ್ಯಾಕ್"</string>
<string name="exo_controls_pause_description">"ವಿರಾಮಗೊಳಿಸು"</string>
<string name="exo_controls_play_description">"ಪ್ಲೇ ಮಾಡು"</string>
<string name="exo_controls_stop_description">"ನಿಲ್ಲಿಸು"</string>
<string name="exo_controls_rewind_description">"ರಿವೈಂಡ್ ಮಾಡು"</string>
<string name="exo_controls_fastforward_description">"ವೇಗವಾಗಿ ಮುಂದಕ್ಕೆ"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"이전 트랙"</string>
<string name="exo_controls_next_description">"다음 트랙"</string>
<string name="exo_controls_pause_description">"일시중지"</string>
<string name="exo_controls_play_description">"재생"</string>
<string name="exo_controls_stop_description">"중지"</string>
<string name="exo_controls_rewind_description">"되감기"</string>
<string name="exo_controls_fastforward_description">"빨리 감기"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Мурунку трек"</string>
<string name="exo_controls_next_description">"Кийинки трек"</string>
<string name="exo_controls_pause_description">"Тындыруу"</string>
<string name="exo_controls_play_description">"Ойнотуу"</string>
<string name="exo_controls_stop_description">"Токтотуу"</string>
<string name="exo_controls_rewind_description">"Артка түрүү"</string>
<string name="exo_controls_fastforward_description">"Алдыга түрүү"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"​ເພງ​ກ່ອນ​ໜ້າ"</string>
<string name="exo_controls_next_description">"​ເພງ​ຕໍ່​ໄປ"</string>
<string name="exo_controls_pause_description">"ຢຸດຊົ່ວຄາວ"</string>
<string name="exo_controls_play_description">"ຫຼິ້ນ"</string>
<string name="exo_controls_stop_description">"ຢຸດ"</string>
<string name="exo_controls_rewind_description">"​ຣີ​​ວາຍກັບ"</string>
<string name="exo_controls_fastforward_description">"ເລື່ອນ​ໄປ​ໜ້າ"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Ankstesnis takelis"</string>
<string name="exo_controls_next_description">"Kitas takelis"</string>
<string name="exo_controls_pause_description">"Pristabdyti"</string>
<string name="exo_controls_play_description">"Leisti"</string>
<string name="exo_controls_stop_description">"Stabdyti"</string>
<string name="exo_controls_rewind_description">"Sukti atgal"</string>
<string name="exo_controls_fastforward_description">"Sukti pirmyn"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Iepriekšējais ieraksts"</string>
<string name="exo_controls_next_description">"Nākamais ieraksts"</string>
<string name="exo_controls_pause_description">"Pārtraukt"</string>
<string name="exo_controls_play_description">"Atskaņot"</string>
<string name="exo_controls_stop_description">"Apturēt"</string>
<string name="exo_controls_rewind_description">"Attīt atpakaļ"</string>
<string name="exo_controls_fastforward_description">"Ātri patīt"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Претходна песна"</string>
<string name="exo_controls_next_description">"Следна песна"</string>
<string name="exo_controls_pause_description">"Пауза"</string>
<string name="exo_controls_play_description">"Пушти"</string>
<string name="exo_controls_stop_description">"Запри"</string>
<string name="exo_controls_rewind_description">"Премотај назад"</string>
<string name="exo_controls_fastforward_description">"Брзо премотај напред"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"മുമ്പത്തെ ട്രാക്ക്"</string>
<string name="exo_controls_next_description">"അടുത്ത ട്രാക്ക്"</string>
<string name="exo_controls_pause_description">"താൽക്കാലികമായി നിർത്തുക"</string>
<string name="exo_controls_play_description">"പ്ലേ ചെയ്യുക"</string>
<string name="exo_controls_stop_description">"നിര്‍ത്തുക"</string>
<string name="exo_controls_rewind_description">"റിവൈൻഡുചെയ്യുക"</string>
<string name="exo_controls_fastforward_description">"വേഗത്തിലുള്ള കൈമാറൽ"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Өмнөх трек"</string>
<string name="exo_controls_next_description">"Дараагийн трек"</string>
<string name="exo_controls_pause_description">"Түр зогсоох"</string>
<string name="exo_controls_play_description">"Тоглуулах"</string>
<string name="exo_controls_stop_description">"Зогсоох"</string>
<string name="exo_controls_rewind_description">"Буцааж хураах"</string>
<string name="exo_controls_fastforward_description">"Хурдан урагшлуулах"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"मागील ट्रॅक"</string>
<string name="exo_controls_next_description">"पुढील ट्रॅक"</string>
<string name="exo_controls_pause_description">"विराम द्या"</string>
<string name="exo_controls_play_description">"प्ले करा"</string>
<string name="exo_controls_stop_description">"थांबा"</string>
<string name="exo_controls_rewind_description">"रिवाईँड करा"</string>
<string name="exo_controls_fastforward_description">"फास्ट फॉरवर्ड करा"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Lagu sebelumnya"</string>
<string name="exo_controls_next_description">"Lagu seterusnya"</string>
<string name="exo_controls_pause_description">"Jeda"</string>
<string name="exo_controls_play_description">"Main"</string>
<string name="exo_controls_stop_description">"Berhenti"</string>
<string name="exo_controls_rewind_description">"Gulung semula"</string>
<string name="exo_controls_fastforward_description">"Mara laju"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"ယခင် တစ်ပုဒ်"</string>
<string name="exo_controls_next_description">"နောက် တစ်ပုဒ်"</string>
<string name="exo_controls_pause_description">"ခဏရပ်ရန်"</string>
<string name="exo_controls_play_description">"ဖွင့်ရန်"</string>
<string name="exo_controls_stop_description">"ရပ်ရန်"</string>
<string name="exo_controls_rewind_description">"ပြန်ရစ်ရန်"</string>
<string name="exo_controls_fastforward_description">"ရှေ့သို့ သွားရန်"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Forrige spor"</string>
<string name="exo_controls_next_description">"Neste spor"</string>
<string name="exo_controls_pause_description">"Sett på pause"</string>
<string name="exo_controls_play_description">"Spill av"</string>
<string name="exo_controls_stop_description">"Stopp"</string>
<string name="exo_controls_rewind_description">"Tilbakespoling"</string>
<string name="exo_controls_fastforward_description">"Fremoverspoling"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"अघिल्लो ट्रयाक"</string>
<string name="exo_controls_next_description">"अर्को ट्रयाक"</string>
<string name="exo_controls_pause_description">"रोक्नुहोस्"</string>
<string name="exo_controls_play_description">"चलाउनुहोस्"</string>
<string name="exo_controls_stop_description">"रोक्नुहोस्"</string>
<string name="exo_controls_rewind_description">"दोहोर्याउनुहोस्"</string>
<string name="exo_controls_fastforward_description">"फास्ट फर्वार्ड"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"Vorig nummer"</string>
<string name="exo_controls_next_description">"Volgend nummer"</string>
<string name="exo_controls_pause_description">"Onderbreken"</string>
<string name="exo_controls_play_description">"Afspelen"</string>
<string name="exo_controls_stop_description">"Stoppen"</string>
<string name="exo_controls_rewind_description">"Terugspoelen"</string>
<string name="exo_controls_fastforward_description">"Vooruitspoelen"</string>
</resources>

View File

@ -1,25 +0,0 @@
<?xml version="1.0"?>
<!--
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.
-->
<resources>
<string name="exo_controls_previous_description">"ਪਿਛਲਾ ਟਰੈਕ"</string>
<string name="exo_controls_next_description">"ਅਗਲਾ ਟਰੈਕ"</string>
<string name="exo_controls_pause_description">"ਰੋਕੋ"</string>
<string name="exo_controls_play_description">"ਪਲੇ ਕਰੋ"</string>
<string name="exo_controls_stop_description">"ਰੋਕੋ"</string>
<string name="exo_controls_rewind_description">"ਰੀਵਾਈਂਡ ਕਰੋ"</string>
<string name="exo_controls_fastforward_description">"ਅੱਗੇ ਭੇਜੋ"</string>
</resources>

Some files were not shown because too many files have changed in this diff Show More