Move AudioComponent to ExoPlayer leaving key methods in Player

PiperOrigin-RevId: 368413660
This commit is contained in:
krocard 2021-04-14 13:54:48 +01:00 committed by Andrew Lewis
parent d359882871
commit 4fc4ddbc6a
12 changed files with 240 additions and 164 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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.

View File

@ -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() {

View File

@ -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.

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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.
*

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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();