summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorH. Lehmann <ByteHamster@users.noreply.github.com>2020-04-04 11:56:47 +0200
committerGitHub <noreply@github.com>2020-04-04 11:56:47 +0200
commit77efea895af62f71a02dad668b10a405b2d4c6b2 (patch)
tree9d098d4bbeedf03007927c69f2ee38908c446f6f /core/src
parenteebdd07c92ed5208da7d1db0071c07425929daac (diff)
parent94c69e31cdd6bb393de6b337b6be1d486b273c42 (diff)
downloadAntennaPod-77efea895af62f71a02dad668b10a405b2d4c6b2.zip
Merge pull request #4001 from ByteHamster/select-audio-tracks
Allow to select audio track
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java89
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java13
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java21
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java93
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java46
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java23
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java60
-rw-r--r--core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java16
9 files changed, 277 insertions, 91 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
index b177f9b92..42a193f0e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
@@ -9,6 +9,7 @@ import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayerFactory;
+import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SeekParameters;
@@ -17,7 +18,13 @@ import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
+import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
+import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
+import com.google.android.exoplayer2.trackselection.TrackSelection;
+import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
+import com.google.android.exoplayer2.ui.DefaultTrackNameProvider;
+import com.google.android.exoplayer2.ui.TrackNameProvider;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
@@ -30,6 +37,9 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import org.antennapod.audio.MediaPlayer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.TimeUnit;
public class ExoPlayerWrapper implements IPlayer {
@@ -45,11 +55,11 @@ public class ExoPlayerWrapper implements IPlayer {
private MediaPlayer.OnBufferingUpdateListener bufferingUpdateListener;
private PlaybackParameters playbackParameters;
private MediaPlayer.OnInfoListener infoListener;
-
+ private DefaultTrackSelector trackSelector;
ExoPlayerWrapper(Context context) {
this.context = context;
- exoPlayer = createPlayer();
+ createPlayer();
playbackParameters = exoPlayer.getPlaybackParameters();
bufferingUpdateDisposable = Observable.interval(2, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
@@ -60,16 +70,17 @@ public class ExoPlayerWrapper implements IPlayer {
});
}
- private SimpleExoPlayer createPlayer() {
+ private void createPlayer() {
DefaultLoadControl.Builder loadControl = new DefaultLoadControl.Builder();
loadControl.setBufferDurationsMs(30000, 120000,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
loadControl.setBackBuffer(UserPreferences.getRewindSecs() * 1000 + 500, true);
- SimpleExoPlayer p = ExoPlayerFactory.newSimpleInstance(context, new DefaultRenderersFactory(context),
- new DefaultTrackSelector(), loadControl.createDefaultLoadControl());
- p.setSeekParameters(SeekParameters.EXACT);
- p.addListener(new Player.EventListener() {
+ trackSelector = new DefaultTrackSelector();
+ exoPlayer = ExoPlayerFactory.newSimpleInstance(context, new DefaultRenderersFactory(context),
+ trackSelector, loadControl.createDefaultLoadControl());
+ exoPlayer.setSeekParameters(SeekParameters.EXACT);
+ exoPlayer.addListener(new Player.EventListener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (audioCompletionListener != null && playbackState == Player.STATE_ENDED) {
@@ -93,7 +104,6 @@ public class ExoPlayerWrapper implements IPlayer {
audioSeekCompleteListener.onSeekComplete(null);
}
});
- return p;
}
@Override
@@ -154,7 +164,7 @@ public class ExoPlayerWrapper implements IPlayer {
@Override
public void reset() {
exoPlayer.release();
- exoPlayer = createPlayer();
+ createPlayer();
}
@Override
@@ -226,6 +236,67 @@ public class ExoPlayerWrapper implements IPlayer {
exoPlayer.stop();
}
+ @Override
+ public List<String> getAudioTracks() {
+ List<String> trackNames = new ArrayList<>();
+ TrackNameProvider trackNameProvider = new DefaultTrackNameProvider(context.getResources());
+ for (Format format : getFormats()) {
+ trackNames.add(trackNameProvider.getTrackName(format));
+ }
+ return trackNames;
+ }
+
+ private List<Format> getFormats() {
+ List<Format> formats = new ArrayList<>();
+ MappingTrackSelector.MappedTrackInfo trackInfo = trackSelector.getCurrentMappedTrackInfo();
+ if (trackInfo == null) {
+ return Collections.emptyList();
+ }
+ TrackGroupArray trackGroups = trackInfo.getTrackGroups(getAudioRendererIndex());
+ for (int i = 0; i < trackGroups.length; i++) {
+ formats.add(trackGroups.get(i).getFormat(0));
+ }
+ return formats;
+ }
+
+ @Override
+ public void setAudioTrack(int track) {
+ MappingTrackSelector.MappedTrackInfo trackInfo = trackSelector.getCurrentMappedTrackInfo();
+ if (trackInfo == null) {
+ return;
+ }
+ TrackGroupArray trackGroups = trackInfo.getTrackGroups(getAudioRendererIndex());
+ DefaultTrackSelector.SelectionOverride override = new DefaultTrackSelector.SelectionOverride(track, 0);
+ DefaultTrackSelector.ParametersBuilder params = trackSelector.buildUponParameters()
+ .setSelectionOverride(getAudioRendererIndex(), trackGroups, override);
+ trackSelector.setParameters(params);
+ }
+
+ private int getAudioRendererIndex() {
+ for (int i = 0; i < exoPlayer.getRendererCount(); i++) {
+ if (exoPlayer.getRendererType(i) == C.TRACK_TYPE_AUDIO) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getSelectedAudioTrack() {
+ TrackSelectionArray trackSelections = exoPlayer.getCurrentTrackSelections();
+ List<Format> availableFormats = getFormats();
+ for (int i = 0; i < trackSelections.length; i++) {
+ TrackSelection track = trackSelections.get(i);
+ if (track == null) {
+ continue;
+ }
+ if (availableFormats.contains(track.getSelectedFormat())) {
+ return availableFormats.indexOf(track.getSelectedFormat());
+ }
+ }
+ return -1;
+ }
+
void setOnCompletionListener(MediaPlayer.OnCompletionListener audioCompletionListener) {
this.audioCompletionListener = audioCompletionListener;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
index 019893778..fbdc9a52b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
@@ -17,6 +17,7 @@ import org.antennapod.audio.MediaPlayer;
import java.io.File;
import java.io.IOException;
import java.util.EnumSet;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
@@ -828,6 +829,18 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
media = playable;
}
+ public List<String> getAudioTracks() {
+ return mediaPlayer.getAudioTracks();
+ }
+
+ public void setAudioTrack(int track) {
+ mediaPlayer.setAudioTrack(track);
+ }
+
+ public int getSelectedAudioTrack() {
+ return mediaPlayer.getSelectedAudioTrack();
+ }
+
private void createMediaPlayer() {
if (mediaPlayer != null) {
mediaPlayer.release();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
index 781791721..bd0315298 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
@@ -42,6 +42,7 @@ import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -1582,6 +1583,26 @@ public class PlaybackService extends MediaBrowserServiceCompat {
return mediaPlayer.getPosition();
}
+ public List<String> getAudioTracks() {
+ if (mediaPlayer == null) {
+ return Collections.emptyList();
+ }
+ return mediaPlayer.getAudioTracks();
+ }
+
+ public int getSelectedAudioTrack() {
+ if (mediaPlayer == null) {
+ return -1;
+ }
+ return mediaPlayer.getSelectedAudioTrack();
+ }
+
+ public void setAudioTrack(int track) {
+ if (mediaPlayer != null) {
+ mediaPlayer.setAudioTrack(track);
+ }
+ }
+
public boolean isStreaming() {
return mediaPlayer.isStreaming();
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
index bc009e2bc..1f047ceee 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java
@@ -8,6 +8,7 @@ import android.util.Log;
import android.util.Pair;
import android.view.SurfaceHolder;
+import java.util.List;
import java.util.concurrent.Future;
import de.danoeh.antennapod.core.feed.MediaType;
@@ -230,6 +231,12 @@ public abstract class PlaybackServiceMediaPlayer {
protected abstract void setPlayable(Playable playable);
+ public abstract List<String> getAudioTracks();
+
+ public abstract void setAudioTrack(int track);
+
+ public abstract int getSelectedAudioTrack();
+
public void skip() {
endPlayback(false, true, true, true);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java
index 2b3f38841..4b3ffa389 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java
@@ -10,45 +10,58 @@ import org.antennapod.audio.MediaPlayer;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import java.util.Collections;
+import java.util.List;
+
public class AudioPlayer extends MediaPlayer implements IPlayer {
- private static final String TAG = "AudioPlayer";
-
- public AudioPlayer(Context context) {
- super(context);
- PreferenceManager.getDefaultSharedPreferences(context)
- .registerOnSharedPreferenceChangeListener(sonicListener);
- }
-
- private final SharedPreferences.OnSharedPreferenceChangeListener sonicListener =
- (sharedPreferences, key) -> {
- if (key.equals(UserPreferences.PREF_MEDIA_PLAYER)) {
- checkMpi();
- }
- };
-
- @Override
- public void setDisplay(SurfaceHolder sh) {
- if (sh != null) {
- Log.e(TAG, "Setting display not supported in Audio Player");
- throw new UnsupportedOperationException("Setting display not supported in Audio Player");
- }
- }
-
- @Override
- public void setPlaybackParams(float speed, boolean skipSilence) {
- if(canSetSpeed()) {
- setPlaybackSpeed(speed);
- }
- //Default player does not support silence skipping
- }
-
- @Override
- protected boolean useSonic() {
- return UserPreferences.useSonic();
- }
-
- @Override
- protected boolean downmix() {
- return UserPreferences.stereoToMono();
- }
+ private static final String TAG = "AudioPlayer";
+
+ public AudioPlayer(Context context) {
+ super(context);
+ PreferenceManager.getDefaultSharedPreferences(context)
+ .registerOnSharedPreferenceChangeListener((sharedPreferences, key) -> {
+ if (key.equals(UserPreferences.PREF_MEDIA_PLAYER)) {
+ checkMpi();
+ }
+ });
+ }
+
+ @Override
+ public void setDisplay(SurfaceHolder sh) {
+ if (sh != null) {
+ Log.e(TAG, "Setting display not supported in Audio Player");
+ throw new UnsupportedOperationException("Setting display not supported in Audio Player");
+ }
+ }
+
+ @Override
+ public void setPlaybackParams(float speed, boolean skipSilence) {
+ if (canSetSpeed()) {
+ setPlaybackSpeed(speed);
+ }
+ //Default player does not support silence skipping
+ }
+
+ @Override
+ protected boolean useSonic() {
+ return UserPreferences.useSonic();
+ }
+
+ @Override
+ protected boolean downmix() {
+ return UserPreferences.stereoToMono();
+ }
+
+ public List<String> getAudioTracks() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void setAudioTrack(int track) {
+ }
+
+ @Override
+ public int getSelectedAudioTrack() {
+ return -1;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java
index c2b768ea8..363004709 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java
@@ -4,48 +4,54 @@ import android.content.Context;
import android.view.SurfaceHolder;
import java.io.IOException;
+import java.util.List;
public interface IPlayer {
- boolean canSetSpeed();
+ boolean canSetSpeed();
- boolean canDownmix();
+ boolean canDownmix();
+ int getCurrentPosition();
- int getCurrentPosition();
+ float getCurrentSpeedMultiplier();
- float getCurrentSpeedMultiplier();
+ int getDuration();
- int getDuration();
+ boolean isPlaying();
- boolean isPlaying();
+ void pause();
- void pause();
+ void prepare() throws IllegalStateException, IOException;
- void prepare() throws IllegalStateException, IOException;
+ void release();
- void release();
+ void reset();
- void reset();
+ void seekTo(int msec);
- void seekTo(int msec);
+ void setAudioStreamType(int streamtype);
- void setAudioStreamType(int streamtype);
-
- void setDataSource(String path) throws IllegalStateException, IOException,
+ void setDataSource(String path) throws IllegalStateException, IOException,
IllegalArgumentException, SecurityException;
- void setDisplay(SurfaceHolder sh);
+ void setDisplay(SurfaceHolder sh);
- void setPlaybackParams(float speed, boolean skipSilence);
+ void setPlaybackParams(float speed, boolean skipSilence);
- void setDownmix(boolean enable);
+ void setDownmix(boolean enable);
- void setVolume(float left, float right);
+ void setVolume(float left, float right);
- void start();
+ void start();
- void stop();
+ void stop();
void setWakeMode(Context context, int mode);
+
+ List<String> getAudioTracks();
+
+ void setAudioTrack(int track);
+
+ int getSelectedAudioTrack();
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
index 8ea08f463..8f7e5dc33 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
@@ -44,6 +44,9 @@ import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
+import java.util.Collections;
+import java.util.List;
+
/**
* Communicates with the playback service. GUI classes should use this class to
* control playback instead of communicating with the PlaybackService directly.
@@ -627,6 +630,26 @@ public class PlaybackController {
}
}
+ public List<String> getAudioTracks() {
+ if (playbackService == null) {
+ return Collections.emptyList();
+ }
+ return playbackService.getAudioTracks();
+ }
+
+ public int getSelectedAudioTrack() {
+ if (playbackService == null) {
+ return -1;
+ }
+ return playbackService.getSelectedAudioTrack();
+ }
+
+ public void setAudioTrack(int track) {
+ if (playbackService != null) {
+ playbackService.setAudioTrack(track);
+ }
+ }
+
public boolean isPlayingVideoLocally() {
if (PlaybackService.isCasting()) {
return false;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java
index f3c1c4f59..d18801870 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java
@@ -3,37 +3,53 @@ package de.danoeh.antennapod.core.util.playback;
import android.media.MediaPlayer;
import android.util.Log;
+import java.util.Collections;
+import java.util.List;
+
public class VideoPlayer extends MediaPlayer implements IPlayer {
- private static final String TAG = "VideoPlayer";
+ private static final String TAG = "VideoPlayer";
- @Override
- public boolean canSetSpeed() {
- return false;
- }
+ @Override
+ public boolean canSetSpeed() {
+ return false;
+ }
- @Override
- public boolean canDownmix() {
- return false;
- }
+ @Override
+ public boolean canDownmix() {
+ return false;
+ }
- @Override
- public float getCurrentSpeedMultiplier() {
- return 1;
- }
+ @Override
+ public float getCurrentSpeedMultiplier() {
+ return 1;
+ }
- @Override
- public void setPlaybackParams(float speed, boolean skipSilence) {
- //Ignore this for non ExoPlayer implementations
- }
+ @Override
+ public void setPlaybackParams(float speed, boolean skipSilence) {
+ //Ignore this for non ExoPlayer implementations
+ }
- @Override
- public void setDownmix(boolean b) {
- Log.e(TAG, "Setting downmix unsupported in video player");
- throw new UnsupportedOperationException("Setting downmix unsupported in video player");
- }
+ @Override
+ public void setDownmix(boolean b) {
+ Log.e(TAG, "Setting downmix unsupported in video player");
+ throw new UnsupportedOperationException("Setting downmix unsupported in video player");
+ }
@Override
public void setVideoScalingMode(int mode) {
super.setVideoScalingMode(mode);
}
+
+ public List<String> getAudioTracks() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void setAudioTrack(int track) {
+ }
+
+ @Override
+ public int getSelectedAudioTrack() {
+ return -1;
+ }
}
diff --git a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java
index 2a75f30a2..f629793e2 100644
--- a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java
+++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java
@@ -16,6 +16,9 @@ import com.google.android.libraries.cast.companionlibrary.cast.exceptions.NoConn
import com.google.android.libraries.cast.companionlibrary.cast.exceptions.TransientNetworkDisconnectionException;
import de.danoeh.antennapod.core.cast.MediaInfoCreator;
+
+import java.util.Collections;
+import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -603,6 +606,19 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
}
@Override
+ public List<String> getAudioTracks() {
+ return Collections.emptyList();
+ }
+
+ public void setAudioTrack(int track) {
+
+ }
+
+ public int getSelectedAudioTrack() {
+ return -1;
+ }
+
+ @Override
protected Future<?> endPlayback(boolean hasEnded, boolean wasSkipped, boolean shouldContinue,
boolean toStoppedState) {
Log.d(TAG, "endPlayback() called");