Move AudioComponent to ExoPlayer leaving key methods in Player
PiperOrigin-RevId: 368413660
This commit is contained in:
parent
d359882871
commit
4fc4ddbc6a
@ -30,6 +30,7 @@ import com.google.android.exoplayer2.MediaMetadata;
|
||||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||
import com.google.android.exoplayer2.metadata.Metadata;
|
||||
import com.google.android.exoplayer2.source.TrackGroup;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
@ -251,14 +252,13 @@ public final class CastPlayer extends BasePlayer {
|
||||
public MediaQueueItem getItem(int periodId) {
|
||||
MediaStatus mediaStatus = getMediaStatus();
|
||||
return mediaStatus != null && currentTimeline.getIndexOfPeriod(periodId) != C.INDEX_UNSET
|
||||
? mediaStatus.getItemById(periodId) : null;
|
||||
? mediaStatus.getItemById(periodId)
|
||||
: null;
|
||||
}
|
||||
|
||||
// CastSession methods.
|
||||
|
||||
/**
|
||||
* Returns whether a cast session is available.
|
||||
*/
|
||||
/** Returns whether a cast session is available. */
|
||||
public boolean isCastSessionAvailable() {
|
||||
return remoteMediaClient != null;
|
||||
}
|
||||
@ -274,12 +274,6 @@ public final class CastPlayer extends BasePlayer {
|
||||
|
||||
// Player implementation.
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AudioComponent getAudioComponent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public VideoComponent getVideoComponent() {
|
||||
@ -461,8 +455,10 @@ public final class CastPlayer extends BasePlayer {
|
||||
positionMs = positionMs != C.TIME_UNSET ? positionMs : 0;
|
||||
if (mediaStatus != null) {
|
||||
if (getCurrentWindowIndex() != windowIndex) {
|
||||
remoteMediaClient.queueJumpToItem((int) currentTimeline.getPeriod(windowIndex, period).uid,
|
||||
positionMs, null).setResultCallback(seekResultCallback);
|
||||
remoteMediaClient
|
||||
.queueJumpToItem(
|
||||
(int) currentTimeline.getPeriod(windowIndex, period).uid, positionMs, null)
|
||||
.setResultCallback(seekResultCallback);
|
||||
} else {
|
||||
remoteMediaClient.seek(positionMs).setResultCallback(seekResultCallback);
|
||||
}
|
||||
@ -545,7 +541,8 @@ public final class CastPlayer extends BasePlayer {
|
||||
}
|
||||
|
||||
@Override
|
||||
@RepeatMode public int getRepeatMode() {
|
||||
@RepeatMode
|
||||
public int getRepeatMode() {
|
||||
return repeatMode.value;
|
||||
}
|
||||
|
||||
@ -657,6 +654,22 @@ public final class CastPlayer extends BasePlayer {
|
||||
return getBufferedPosition();
|
||||
}
|
||||
|
||||
/** This method is not supported and returns {@link AudioAttributes#DEFAULT}. */
|
||||
@Override
|
||||
public AudioAttributes getAudioAttributes() {
|
||||
return AudioAttributes.DEFAULT;
|
||||
}
|
||||
|
||||
/** This method is not supported and does nothing. */
|
||||
@Override
|
||||
public void setVolume(float audioVolume) {}
|
||||
|
||||
/** This method is not supported and returns 1. */
|
||||
@Override
|
||||
public float getVolume() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Internal methods.
|
||||
|
||||
// Call deprecated callbacks.
|
||||
@ -897,7 +910,8 @@ public final class CastPlayer extends BasePlayer {
|
||||
long id = mediaTrack.getId();
|
||||
int trackType = MimeTypes.getTrackType(mediaTrack.getContentType());
|
||||
int rendererIndex = getRendererIndexForTrackType(trackType);
|
||||
if (isTrackActive(id, activeTrackIds) && rendererIndex != C.INDEX_UNSET
|
||||
if (isTrackActive(id, activeTrackIds)
|
||||
&& rendererIndex != C.INDEX_UNSET
|
||||
&& trackSelections[rendererIndex] == null) {
|
||||
trackSelections[rendererIndex] = new CastTrackSelection(trackGroups[i]);
|
||||
}
|
||||
@ -1097,8 +1111,8 @@ public final class CastPlayer extends BasePlayer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the repeat mode from {@code remoteMediaClient} and maps it into a
|
||||
* {@link Player.RepeatMode}.
|
||||
* Retrieves the repeat mode from {@code remoteMediaClient} and maps it into a {@link
|
||||
* Player.RepeatMode}.
|
||||
*/
|
||||
@RepeatMode
|
||||
private static int fetchRepeatMode(RemoteMediaClient remoteMediaClient) {
|
||||
@ -1238,8 +1252,12 @@ public final class CastPlayer extends BasePlayer {
|
||||
|
||||
@Override
|
||||
public void onSessionResumeFailed(CastSession castSession, int statusCode) {
|
||||
Log.e(TAG, "Session resume failed. Error code " + statusCode + ": "
|
||||
+ CastUtils.getLogString(statusCode));
|
||||
Log.e(
|
||||
TAG,
|
||||
"Session resume failed. Error code "
|
||||
+ statusCode
|
||||
+ ": "
|
||||
+ CastUtils.getLogString(statusCode));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1249,8 +1267,12 @@ public final class CastPlayer extends BasePlayer {
|
||||
|
||||
@Override
|
||||
public void onSessionStartFailed(CastSession castSession, int statusCode) {
|
||||
Log.e(TAG, "Session start failed. Error code " + statusCode + ": "
|
||||
+ CastUtils.getLogString(statusCode));
|
||||
Log.e(
|
||||
TAG,
|
||||
"Session start failed. Error code "
|
||||
+ statusCode
|
||||
+ ": "
|
||||
+ CastUtils.getLogString(statusCode));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1262,7 +1284,6 @@ public final class CastPlayer extends BasePlayer {
|
||||
public void onSessionResuming(CastSession castSession, String s) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class SeekResultCallback implements ResultCallback<MediaChannelResult> {
|
||||
@ -1274,8 +1295,9 @@ public final class CastPlayer extends BasePlayer {
|
||||
public void onResult(MediaChannelResult result) {
|
||||
int statusCode = result.getStatus().getStatusCode();
|
||||
if (statusCode != CastStatusCodes.SUCCESS && statusCode != CastStatusCodes.REPLACED) {
|
||||
Log.e(TAG, "Seek failed. Error code " + statusCode + ": "
|
||||
+ CastUtils.getLogString(statusCode));
|
||||
Log.e(
|
||||
TAG,
|
||||
"Seek failed. Error code " + statusCode + ": " + CastUtils.getLogString(statusCode));
|
||||
}
|
||||
if (--pendingSeekCount == 0) {
|
||||
currentWindowIndex = pendingSeekWindowIndex;
|
||||
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.ext.cast;
|
||||
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_ADJUST_DEVICE_VOLUME;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_CHANGE_MEDIA_ITEMS;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_GET_AUDIO_ATTRIBUTES;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_GET_CURRENT_MEDIA_ITEM;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_GET_DEVICE_VOLUME;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_GET_MEDIA_ITEMS;
|
||||
@ -102,6 +103,7 @@ public class CastPlayerTest {
|
||||
@Captor
|
||||
private ArgumentCaptor<ResultCallback<RemoteMediaClient.MediaChannelResult>>
|
||||
setResultCallbackArgumentCaptor;
|
||||
|
||||
@Captor private ArgumentCaptor<RemoteMediaClient.Callback> callbackArgumentCaptor;
|
||||
@Captor private ArgumentCaptor<MediaQueueItem[]> queueItemsArgumentCaptor;
|
||||
@Captor private ArgumentCaptor<MediaItem> mediaItemCaptor;
|
||||
@ -1119,6 +1121,7 @@ public class CastPlayerTest {
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS)).isTrue();
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)).isTrue();
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_CHANGE_MEDIA_ITEMS)).isTrue();
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_GET_AUDIO_ATTRIBUTES)).isFalse();
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_GET_VOLUME)).isFalse();
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_GET_DEVICE_VOLUME)).isFalse();
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_SET_VOLUME)).isFalse();
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.ext.ima;
|
||||
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_GET_VOLUME;
|
||||
import static com.google.android.exoplayer2.ext.ima.ImaUtil.BITRATE_UNSET;
|
||||
import static com.google.android.exoplayer2.ext.ima.ImaUtil.TIMEOUT_UNSET;
|
||||
import static com.google.android.exoplayer2.ext.ima.ImaUtil.getAdGroupTimesUsForCuePoints;
|
||||
@ -700,9 +701,8 @@ import java.util.Map;
|
||||
return lastVolumePercent;
|
||||
}
|
||||
|
||||
@Nullable Player.AudioComponent audioComponent = player.getAudioComponent();
|
||||
if (audioComponent != null) {
|
||||
return (int) (audioComponent.getVolume() * 100);
|
||||
if (player.isCommandAvailable(COMMAND_GET_VOLUME)) {
|
||||
return (int) (player.getVolume() * 100);
|
||||
}
|
||||
|
||||
// Check for a selected track using an audio renderer.
|
||||
|
@ -194,6 +194,17 @@ import com.google.android.exoplayer2.util.ListenerSet;
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCommandAvailable(@Command int command) {
|
||||
// Only support querrying the minimal set of command for testing.
|
||||
switch (command) {
|
||||
case COMMAND_GET_VOLUME:
|
||||
return false;
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Player.State
|
||||
public int getPlaybackState() {
|
||||
|
@ -33,7 +33,6 @@ import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||
import com.google.android.exoplayer2.audio.AudioListener;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Log;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
@ -138,10 +137,6 @@ import java.util.List;
|
||||
controlDispatcher = new DefaultControlDispatcher();
|
||||
componentListener = new ComponentListener();
|
||||
player.addListener(componentListener);
|
||||
@Nullable Player.AudioComponent audioComponent = player.getAudioComponent();
|
||||
if (audioComponent != null) {
|
||||
audioComponent.addAudioListener(componentListener);
|
||||
}
|
||||
|
||||
handler = new Handler(player.getApplicationLooper());
|
||||
pollBufferRunnable = new PollBufferRunnable();
|
||||
@ -455,15 +450,15 @@ import java.util.List;
|
||||
}
|
||||
|
||||
public void setAudioAttributes(AudioAttributesCompat audioAttributes) {
|
||||
Player.AudioComponent audioComponent = Assertions.checkStateNotNull(player.getAudioComponent());
|
||||
audioComponent.setAudioAttributes(
|
||||
Utils.getAudioAttributes(audioAttributes), /* handleAudioFocus= */ true);
|
||||
// Player interface doesn't support setting audio attributes.
|
||||
}
|
||||
|
||||
public AudioAttributesCompat getAudioAttributes() {
|
||||
@Nullable Player.AudioComponent audioComponent = player.getAudioComponent();
|
||||
return Utils.getAudioAttributesCompat(
|
||||
audioComponent != null ? audioComponent.getAudioAttributes() : AudioAttributes.DEFAULT);
|
||||
AudioAttributes audioAttributes = AudioAttributes.DEFAULT;
|
||||
if (player.isCommandAvailable(Player.COMMAND_GET_AUDIO_ATTRIBUTES)) {
|
||||
audioAttributes = player.getAudioAttributes();
|
||||
}
|
||||
return Utils.getAudioAttributesCompat(audioAttributes);
|
||||
}
|
||||
|
||||
public void setPlaybackSpeed(float playbackSpeed) {
|
||||
@ -483,11 +478,6 @@ import java.util.List;
|
||||
public void close() {
|
||||
handler.removeCallbacks(pollBufferRunnable);
|
||||
player.removeListener(componentListener);
|
||||
|
||||
@Nullable Player.AudioComponent audioComponent = player.getAudioComponent();
|
||||
if (audioComponent != null) {
|
||||
audioComponent.removeAudioListener(componentListener);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCurrentMediaItemSeekable() {
|
||||
@ -584,7 +574,7 @@ import java.util.List;
|
||||
}
|
||||
}
|
||||
|
||||
private final class ComponentListener implements Player.EventListener, AudioListener {
|
||||
private final class ComponentListener implements Player.Listener {
|
||||
|
||||
// Player.EventListener implementation.
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
@ -25,7 +24,6 @@ import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||
import com.google.android.exoplayer2.audio.AudioListener;
|
||||
import com.google.android.exoplayer2.audio.AuxEffectInfo;
|
||||
import com.google.android.exoplayer2.device.DeviceInfo;
|
||||
import com.google.android.exoplayer2.device.DeviceListener;
|
||||
import com.google.android.exoplayer2.metadata.Metadata;
|
||||
@ -68,95 +66,6 @@ import java.util.List;
|
||||
*/
|
||||
public interface Player {
|
||||
|
||||
/** The audio component of a {@link Player}. */
|
||||
interface AudioComponent {
|
||||
|
||||
/**
|
||||
* Adds a listener to receive audio events.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
*/
|
||||
void addAudioListener(AudioListener listener);
|
||||
|
||||
/**
|
||||
* Removes a listener of audio events.
|
||||
*
|
||||
* @param listener The listener to unregister.
|
||||
*/
|
||||
void removeAudioListener(AudioListener listener);
|
||||
|
||||
/**
|
||||
* Sets the attributes for audio playback, used by the underlying audio track. If not set, the
|
||||
* default audio attributes will be used. They are suitable for general media playback.
|
||||
*
|
||||
* <p>Setting the audio attributes during playback may introduce a short gap in audio output as
|
||||
* the audio track is recreated. A new audio session id will also be generated.
|
||||
*
|
||||
* <p>If tunneling is enabled by the track selector, the specified audio attributes will be
|
||||
* ignored, but they will take effect if audio is later played without tunneling.
|
||||
*
|
||||
* <p>If the device is running a build before platform API version 21, audio attributes cannot
|
||||
* be set directly on the underlying audio track. In this case, the usage will be mapped onto an
|
||||
* equivalent stream type using {@link Util#getStreamTypeForAudioUsage(int)}.
|
||||
*
|
||||
* <p>If audio focus should be handled, the {@link AudioAttributes#usage} must be {@link
|
||||
* C#USAGE_MEDIA} or {@link C#USAGE_GAME}. Other usages will throw an {@link
|
||||
* IllegalArgumentException}.
|
||||
*
|
||||
* @param audioAttributes The attributes to use for audio playback.
|
||||
* @param handleAudioFocus True if the player should handle audio focus, false otherwise.
|
||||
*/
|
||||
void setAudioAttributes(AudioAttributes audioAttributes, boolean handleAudioFocus);
|
||||
|
||||
/** Returns the attributes for audio playback. */
|
||||
AudioAttributes getAudioAttributes();
|
||||
|
||||
/**
|
||||
* Sets the ID of the audio session to attach to the underlying {@link
|
||||
* android.media.AudioTrack}.
|
||||
*
|
||||
* <p>The audio session ID can be generated using {@link C#generateAudioSessionIdV21(Context)}
|
||||
* for API 21+.
|
||||
*
|
||||
* @param audioSessionId The audio session ID, or {@link C#AUDIO_SESSION_ID_UNSET} if it should
|
||||
* be generated by the framework.
|
||||
*/
|
||||
void setAudioSessionId(int audioSessionId);
|
||||
|
||||
/** Returns the audio session identifier, or {@link C#AUDIO_SESSION_ID_UNSET} if not set. */
|
||||
int getAudioSessionId();
|
||||
|
||||
/** Sets information on an auxiliary audio effect to attach to the underlying audio track. */
|
||||
void setAuxEffectInfo(AuxEffectInfo auxEffectInfo);
|
||||
|
||||
/** Detaches any previously attached auxiliary audio effect from the underlying audio track. */
|
||||
void clearAuxEffectInfo();
|
||||
|
||||
/**
|
||||
* Sets the audio volume, with 0 being silence and 1 being unity gain (signal unchanged).
|
||||
*
|
||||
* @param audioVolume Linear output gain to apply to all audio channels.
|
||||
*/
|
||||
void setVolume(float audioVolume);
|
||||
|
||||
/**
|
||||
* Returns the audio volume, with 0 being silence and 1 being unity gain (signal unchanged).
|
||||
*
|
||||
* @return The linear gain applied to all audio channels.
|
||||
*/
|
||||
float getVolume();
|
||||
|
||||
/**
|
||||
* Sets whether skipping silences in the audio stream is enabled.
|
||||
*
|
||||
* @param skipSilenceEnabled Whether skipping silences in the audio stream is enabled.
|
||||
*/
|
||||
void setSkipSilenceEnabled(boolean skipSilenceEnabled);
|
||||
|
||||
/** Returns whether skipping silences in the audio stream is enabled. */
|
||||
boolean getSkipSilenceEnabled();
|
||||
}
|
||||
|
||||
/** The video component of a {@link Player}. */
|
||||
interface VideoComponent {
|
||||
|
||||
@ -354,8 +263,7 @@ public interface Player {
|
||||
* <p>For devices with {@link DeviceInfo#PLAYBACK_TYPE_LOCAL local playback}, the volume
|
||||
* returned by this method varies according to the current {@link C.StreamType stream type}. The
|
||||
* stream type is determined by {@link AudioAttributes#usage} which can be converted to stream
|
||||
* type with {@link Util#getStreamTypeForAudioUsage(int)}. The audio attributes can be set to
|
||||
* the player by calling {@link AudioComponent#setAudioAttributes}.
|
||||
* type with {@link Util#getStreamTypeForAudioUsage(int)}.
|
||||
*
|
||||
* <p>For devices with {@link DeviceInfo#PLAYBACK_TYPE_REMOTE remote playback}, the volume of
|
||||
* the remote device is returned.
|
||||
@ -930,11 +838,12 @@ public interface Player {
|
||||
DeviceListener,
|
||||
EventListener {
|
||||
|
||||
@Override
|
||||
default void onMetadata(Metadata metadata) {}
|
||||
|
||||
// For backward compatibility TextOutput and MetadataOutput must stay functional interfaces.
|
||||
@Override
|
||||
default void onCues(List<Cue> cues) {}
|
||||
|
||||
@Override
|
||||
default void onMetadata(Metadata metadata) {}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1179,10 +1088,10 @@ public interface Player {
|
||||
* #COMMAND_SET_SPEED_AND_PITCH}, {@link #COMMAND_SET_SHUFFLE_MODE}, {@link
|
||||
* #COMMAND_SET_REPEAT_MODE}, {@link #COMMAND_GET_CURRENT_MEDIA_ITEM}, {@link
|
||||
* #COMMAND_GET_MEDIA_ITEMS}, {@link #COMMAND_GET_MEDIA_ITEMS_METADATA}, {@link
|
||||
* #COMMAND_CHANGE_MEDIA_ITEMS}, {@link #COMMAND_GET_VOLUME}, {@link #COMMAND_GET_DEVICE_VOLUME},
|
||||
* {@link #COMMAND_SET_VOLUME}, {@link #COMMAND_SET_DEVICE_VOLUME}, {@link
|
||||
* #COMMAND_ADJUST_DEVICE_VOLUME}, {@link #COMMAND_SET_VIDEO_SURFACE} or {@link
|
||||
* #COMMAND_GET_TEXT}.
|
||||
* #COMMAND_CHANGE_MEDIA_ITEMS}, {@link #COMMAND_GET_AUDIO_ATTRIBUTES}, {@link
|
||||
* #COMMAND_GET_VOLUME}, {@link #COMMAND_GET_DEVICE_VOLUME}, {@link #COMMAND_SET_VOLUME}, {@link
|
||||
* #COMMAND_SET_DEVICE_VOLUME}, {@link #COMMAND_ADJUST_DEVICE_VOLUME}, {@link
|
||||
* #COMMAND_SET_VIDEO_SURFACE} or {@link #COMMAND_GET_TEXT}.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@ -1201,6 +1110,7 @@ public interface Player {
|
||||
COMMAND_GET_MEDIA_ITEMS,
|
||||
COMMAND_GET_MEDIA_ITEMS_METADATA,
|
||||
COMMAND_CHANGE_MEDIA_ITEMS,
|
||||
COMMAND_GET_AUDIO_ATTRIBUTES,
|
||||
COMMAND_GET_VOLUME,
|
||||
COMMAND_GET_DEVICE_VOLUME,
|
||||
COMMAND_SET_VOLUME,
|
||||
@ -1238,24 +1148,22 @@ public interface Player {
|
||||
int COMMAND_GET_MEDIA_ITEMS_METADATA = 13;
|
||||
/** Command to change the {@link MediaItem MediaItems} in the playlist. */
|
||||
int COMMAND_CHANGE_MEDIA_ITEMS = 14;
|
||||
/** Command to get the player current {@link AudioAttributes}. */
|
||||
int COMMAND_GET_AUDIO_ATTRIBUTES = 15;
|
||||
/** Command to get the player volume. */
|
||||
int COMMAND_GET_VOLUME = 15;
|
||||
int COMMAND_GET_VOLUME = 16;
|
||||
/** Command to get the device volume and whether it is muted. */
|
||||
int COMMAND_GET_DEVICE_VOLUME = 16;
|
||||
int COMMAND_GET_DEVICE_VOLUME = 17;
|
||||
/** Command to set the player volume. */
|
||||
int COMMAND_SET_VOLUME = 17;
|
||||
int COMMAND_SET_VOLUME = 18;
|
||||
/** Command to set the device volume and mute it. */
|
||||
int COMMAND_SET_DEVICE_VOLUME = 18;
|
||||
int COMMAND_SET_DEVICE_VOLUME = 19;
|
||||
/** Command to increase and decrease the device volume and mute it. */
|
||||
int COMMAND_ADJUST_DEVICE_VOLUME = 19;
|
||||
int COMMAND_ADJUST_DEVICE_VOLUME = 20;
|
||||
/** Command to set and clear the surface on which to render the video. */
|
||||
int COMMAND_SET_VIDEO_SURFACE = 20;
|
||||
int COMMAND_SET_VIDEO_SURFACE = 21;
|
||||
/** Command to get the text that should currently be displayed by the player. */
|
||||
int COMMAND_GET_TEXT = 21;
|
||||
|
||||
/** Returns the component of this player for audio output, or null if audio is not supported. */
|
||||
@Nullable
|
||||
AudioComponent getAudioComponent();
|
||||
int COMMAND_GET_TEXT = 22;
|
||||
|
||||
/** Returns the component of this player for video output, or null if video is not supported. */
|
||||
@Nullable
|
||||
@ -1293,11 +1201,6 @@ public interface Player {
|
||||
/**
|
||||
* Registers a listener to receive all events from the player.
|
||||
*
|
||||
* <p>Do not register the listener additionally in individual `Player` components (such as {@link
|
||||
* Player.AudioComponent#addAudioListener(AudioListener)}, {@link
|
||||
* Player.VideoComponent#addVideoListener(VideoListener)}) as it will already receive all their
|
||||
* events.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
*/
|
||||
void addListener(Listener listener);
|
||||
@ -1936,4 +1839,21 @@ public interface Player {
|
||||
* playing, the returned position is the same as that returned by {@link #getBufferedPosition()}.
|
||||
*/
|
||||
long getContentBufferedPosition();
|
||||
|
||||
/** Returns the attributes for audio playback. */
|
||||
AudioAttributes getAudioAttributes();
|
||||
|
||||
/**
|
||||
* Sets the audio volume, with 0 being silence and 1 being unity gain (signal unchanged).
|
||||
*
|
||||
* @param audioVolume Linear output gain to apply to all audio channels.
|
||||
*/
|
||||
void setVolume(float audioVolume);
|
||||
|
||||
/**
|
||||
* Returns the audio volume, with 0 being silence and 1 being unity gain (signal unchanged).
|
||||
*
|
||||
* @return The linear gain applied to all audio channels.
|
||||
*/
|
||||
float getVolume();
|
||||
}
|
||||
|
@ -15,9 +15,7 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.metadata;
|
||||
|
||||
/**
|
||||
* Receives metadata output.
|
||||
*/
|
||||
/** Receives metadata output. */
|
||||
public interface MetadataOutput {
|
||||
|
||||
/**
|
||||
@ -26,5 +24,4 @@ public interface MetadataOutput {
|
||||
* @param metadata The metadata.
|
||||
*/
|
||||
void onMetadata(Metadata metadata);
|
||||
|
||||
}
|
||||
|
@ -21,8 +21,11 @@ import android.os.Looper;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import com.google.android.exoplayer2.analytics.AnalyticsCollector;
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||
import com.google.android.exoplayer2.audio.AudioCapabilities;
|
||||
import com.google.android.exoplayer2.audio.AudioListener;
|
||||
import com.google.android.exoplayer2.audio.AudioSink;
|
||||
import com.google.android.exoplayer2.audio.AuxEffectInfo;
|
||||
import com.google.android.exoplayer2.audio.DefaultAudioSink;
|
||||
import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer;
|
||||
import com.google.android.exoplayer2.metadata.MetadataRenderer;
|
||||
@ -126,6 +129,95 @@ import java.util.List;
|
||||
*/
|
||||
public interface ExoPlayer extends Player {
|
||||
|
||||
/** The audio component of an {@link ExoPlayer}. */
|
||||
interface AudioComponent {
|
||||
|
||||
/**
|
||||
* Adds a listener to receive audio events.
|
||||
*
|
||||
* @param listener The listener to register.
|
||||
*/
|
||||
void addAudioListener(AudioListener listener);
|
||||
|
||||
/**
|
||||
* Removes a listener of audio events.
|
||||
*
|
||||
* @param listener The listener to unregister.
|
||||
*/
|
||||
void removeAudioListener(AudioListener listener);
|
||||
|
||||
/**
|
||||
* Sets the attributes for audio playback, used by the underlying audio track. If not set, the
|
||||
* default audio attributes will be used. They are suitable for general media playback.
|
||||
*
|
||||
* <p>Setting the audio attributes during playback may introduce a short gap in audio output as
|
||||
* the audio track is recreated. A new audio session id will also be generated.
|
||||
*
|
||||
* <p>If tunneling is enabled by the track selector, the specified audio attributes will be
|
||||
* ignored, but they will take effect if audio is later played without tunneling.
|
||||
*
|
||||
* <p>If the device is running a build before platform API version 21, audio attributes cannot
|
||||
* be set directly on the underlying audio track. In this case, the usage will be mapped onto an
|
||||
* equivalent stream type using {@link Util#getStreamTypeForAudioUsage(int)}.
|
||||
*
|
||||
* <p>If audio focus should be handled, the {@link AudioAttributes#usage} must be {@link
|
||||
* C#USAGE_MEDIA} or {@link C#USAGE_GAME}. Other usages will throw an {@link
|
||||
* IllegalArgumentException}.
|
||||
*
|
||||
* @param audioAttributes The attributes to use for audio playback.
|
||||
* @param handleAudioFocus True if the player should handle audio focus, false otherwise.
|
||||
*/
|
||||
void setAudioAttributes(AudioAttributes audioAttributes, boolean handleAudioFocus);
|
||||
|
||||
/** Returns the attributes for audio playback. */
|
||||
AudioAttributes getAudioAttributes();
|
||||
|
||||
/**
|
||||
* Sets the ID of the audio session to attach to the underlying {@link
|
||||
* android.media.AudioTrack}.
|
||||
*
|
||||
* <p>The audio session ID can be generated using {@link C#generateAudioSessionIdV21(Context)}
|
||||
* for API 21+.
|
||||
*
|
||||
* @param audioSessionId The audio session ID, or {@link C#AUDIO_SESSION_ID_UNSET} if it should
|
||||
* be generated by the framework.
|
||||
*/
|
||||
void setAudioSessionId(int audioSessionId);
|
||||
|
||||
/** Returns the audio session identifier, or {@link C#AUDIO_SESSION_ID_UNSET} if not set. */
|
||||
int getAudioSessionId();
|
||||
|
||||
/** Sets information on an auxiliary audio effect to attach to the underlying audio track. */
|
||||
void setAuxEffectInfo(AuxEffectInfo auxEffectInfo);
|
||||
|
||||
/** Detaches any previously attached auxiliary audio effect from the underlying audio track. */
|
||||
void clearAuxEffectInfo();
|
||||
|
||||
/**
|
||||
* Sets the audio volume, with 0 being silence and 1 being unity gain (signal unchanged).
|
||||
*
|
||||
* @param audioVolume Linear output gain to apply to all audio channels.
|
||||
*/
|
||||
void setVolume(float audioVolume);
|
||||
|
||||
/**
|
||||
* Returns the audio volume, with 0 being silence and 1 being unity gain (signal unchanged).
|
||||
*
|
||||
* @return The linear gain applied to all audio channels.
|
||||
*/
|
||||
float getVolume();
|
||||
|
||||
/**
|
||||
* Sets whether skipping silences in the audio stream is enabled.
|
||||
*
|
||||
* @param skipSilenceEnabled Whether skipping silences in the audio stream is enabled.
|
||||
*/
|
||||
void setSkipSilenceEnabled(boolean skipSilenceEnabled);
|
||||
|
||||
/** Returns whether skipping silences in the audio stream is enabled. */
|
||||
boolean getSkipSilenceEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* The default timeout for calls to {@link #release} and {@link #setForegroundMode}, in
|
||||
* milliseconds.
|
||||
@ -465,6 +557,10 @@ public interface ExoPlayer extends Player {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the component of this player for audio output, or null if audio is not supported. */
|
||||
@Nullable
|
||||
AudioComponent getAudioComponent();
|
||||
|
||||
/**
|
||||
* Adds a listener to receive audio offload events.
|
||||
*
|
||||
|
@ -28,6 +28,7 @@ import android.util.Pair;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.PlayerMessage.Target;
|
||||
import com.google.android.exoplayer2.analytics.AnalyticsCollector;
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||
import com.google.android.exoplayer2.metadata.Metadata;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||
@ -985,6 +986,22 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
return playbackInfo.timeline;
|
||||
}
|
||||
|
||||
/** This method is not supported and returns {@link AudioAttributes#DEFAULT}. */
|
||||
@Override
|
||||
public AudioAttributes getAudioAttributes() {
|
||||
return AudioAttributes.DEFAULT;
|
||||
}
|
||||
|
||||
/** This method is not supported and does nothing. */
|
||||
@Override
|
||||
public void setVolume(float audioVolume) {}
|
||||
|
||||
/** This method is not supported and returns 1. */
|
||||
@Override
|
||||
public float getVolume() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int getCurrentWindowIndexInternal() {
|
||||
if (playbackInfo.timeline.isEmpty()) {
|
||||
return maskingWindowIndex;
|
||||
|
@ -78,7 +78,7 @@ import java.util.concurrent.TimeoutException;
|
||||
*/
|
||||
public class SimpleExoPlayer extends BasePlayer
|
||||
implements ExoPlayer,
|
||||
Player.AudioComponent,
|
||||
ExoPlayer.AudioComponent,
|
||||
Player.VideoComponent,
|
||||
Player.TextComponent,
|
||||
Player.MetadataComponent,
|
||||
@ -676,6 +676,7 @@ public class SimpleExoPlayer extends BasePlayer
|
||||
Commands additionalPermanentAvailableCommands =
|
||||
new Commands.Builder()
|
||||
.addAll(
|
||||
COMMAND_GET_AUDIO_ATTRIBUTES,
|
||||
COMMAND_GET_VOLUME,
|
||||
COMMAND_GET_DEVICE_VOLUME,
|
||||
COMMAND_SET_VOLUME,
|
||||
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2;
|
||||
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_ADJUST_DEVICE_VOLUME;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_CHANGE_MEDIA_ITEMS;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_GET_AUDIO_ATTRIBUTES;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_GET_CURRENT_MEDIA_ITEM;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_GET_DEVICE_VOLUME;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_GET_MEDIA_ITEMS;
|
||||
@ -8086,6 +8087,7 @@ public final class ExoPlayerTest {
|
||||
assertThat(player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_CHANGE_MEDIA_ITEMS)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_GET_AUDIO_ATTRIBUTES)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_GET_VOLUME)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_GET_DEVICE_VOLUME)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_SET_VOLUME)).isTrue();
|
||||
@ -10275,6 +10277,7 @@ public final class ExoPlayerTest {
|
||||
COMMAND_GET_MEDIA_ITEMS,
|
||||
COMMAND_GET_MEDIA_ITEMS_METADATA,
|
||||
COMMAND_CHANGE_MEDIA_ITEMS,
|
||||
COMMAND_GET_AUDIO_ATTRIBUTES,
|
||||
COMMAND_GET_VOLUME,
|
||||
COMMAND_GET_DEVICE_VOLUME,
|
||||
COMMAND_SET_VOLUME,
|
||||
|
@ -27,6 +27,7 @@ import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.PlayerMessage;
|
||||
import com.google.android.exoplayer2.SeekParameters;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||
import com.google.android.exoplayer2.metadata.Metadata;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
import com.google.android.exoplayer2.source.ShuffleOrder;
|
||||
@ -422,6 +423,21 @@ public class StubExoPlayer extends BasePlayer implements ExoPlayer {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AudioAttributes getAudioAttributes() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolume(float audioVolume) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getVolume() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForegroundMode(boolean foregroundMode) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
Loading…
x
Reference in New Issue
Block a user