Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ExoPlayer #2655

Merged
merged 19 commits into from Jul 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -52,7 +52,7 @@ private static void showGetPluginDialog(final Context context, boolean showSpeed
builder.neutralText(R.string.close_label);
builder.onPositive((dialog, which) -> {
if (Build.VERSION.SDK_INT >= 16) { // just to be safe
UserPreferences.enableSonic(true);
UserPreferences.enableSonic();
if(showSpeedSelector) {
showSpeedSelectorDialog(context);
}
Expand Down
Expand Up @@ -147,12 +147,7 @@ public PreferenceController(PreferenceUI ui) {

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals(UserPreferences.PREF_SONIC)) {
CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC);
if(prefSonic != null) {
prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false));
}
}

}


Expand Down Expand Up @@ -891,11 +886,10 @@ private void checkAutodownloadItemVisibility(boolean autoDownload) {
}

private void checkSonicItemVisibility() {
if (Build.VERSION.SDK_INT >= 16) {
ui.findPreference(UserPreferences.PREF_SONIC).setEnabled(true);
} else {
Preference prefSonic = ui.findPreference(UserPreferences.PREF_SONIC);
prefSonic.setSummary("[Android 4.1+]\n" + prefSonic.getSummary());
if (Build.VERSION.SDK_INT < 16) {
ListPreference p = (ListPreference) ui.findPreference(UserPreferences.PREF_MEDIA_PLAYER);
p.setEntries(R.array.media_player_options_no_sonic);
p.setEntryValues(R.array.media_player_values_no_sonic);
}
}

Expand Down
14 changes: 8 additions & 6 deletions app/src/main/res/xml/preferences_playback.xml
Expand Up @@ -109,12 +109,14 @@
</PreferenceCategory>

<PreferenceCategory android:title="@string/media_player">
<SwitchPreference
android:defaultValue="true"
android:enabled="false"
android:key="prefSonic"
android:summary="@string/pref_sonic_message"
android:title="@string/pref_sonic_title"/>
<ListPreference
android:defaultValue="sonic"
android:entries="@array/media_player_options"
android:key="prefMediaPlayer"
android:title="@string/media_player"
android:summary="@string/pref_media_player_message"
android:entryValues="@array/media_player_values"
app:useStockLayout="true"/>
</PreferenceCategory>

<PreferenceCategory android:title="@string/experimental_pref">
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/templates/about.html
Expand Up @@ -64,6 +64,9 @@ <h2>Apache Commons <a href="http://commons.apache.org/">(Link)</a></h2>
<h2>EventBus <a href="https://github.com/greenrobot/EventBus">(Link)</a></h2>
by greenrobot, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>

<h2>ExoPlayer <a href="https://github.com/google/ExoPlayer">(Link)</a></h2>
by Google, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>

<h2>flattr4j <a href="http://www.shredzone.org/projects/flattr4j/wiki">(Link)</a></h2>
licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>

Expand Down
1 change: 1 addition & 0 deletions build.gradle
Expand Up @@ -62,6 +62,7 @@ project.ext {
rxJavaRulesVersion = "1.3.3.0"
triangleLabelViewVersion = "1.1.2"

exoPlayerVersion = "2.7.3"
audioPlayerVersion = "v1.0.17"

castCompanionLibVer = "2.9.1"
Expand Down
1 change: 1 addition & 0 deletions core/build.gradle
Expand Up @@ -67,6 +67,7 @@ dependencies {
implementation "de.greenrobot:eventbus:$eventbusVersion"
implementation "io.reactivex:rxandroid:$rxAndroidVersion"

implementation "com.google.android.exoplayer:exoplayer:$exoPlayerVersion"
implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"

// Add casting features
Expand Down
Expand Up @@ -65,7 +65,7 @@ private static void setCurrentVersionCode() {
private static void onUpgrade(final int oldVersionCode, final int newVersionCode) {
if(oldVersionCode < 1050004) {
if(MediaPlayer.isPrestoLibraryInstalled(context) && Build.VERSION.SDK_INT >= 16) {
UserPreferences.enableSonic(true);
UserPreferences.enableSonic();
}
}
}
Expand Down
Expand Up @@ -97,6 +97,7 @@ public class UserPreferences {
public static final String PREF_IMAGE_CACHE_SIZE = "prefImageCacheSize";

// Mediaplayer
public static final String PREF_MEDIA_PLAYER = "prefMediaPlayer";
private static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed";
private static final String PREF_FAST_FORWARD_SECS = "prefFastForwardSecs";
private static final String PREF_REWIND_SECS = "prefRewindSecs";
Expand All @@ -107,7 +108,6 @@ public class UserPreferences {
private static final String PREF_RIGHT_VOLUME = "prefRightVolume";

// Experimental
public static final String PREF_SONIC = "prefSonic";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this has already been merged, but I just wanted to say that the sonic player test still depends on this.
https://github.com/AntennaPod/AntennaPod/blob/develop/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java#L62

That being said, I just started looking into this codebase this evening and as of right now all tests are still failing for me, so I'm not sure whether I should make a PR for that. 😅

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm currently working on fixing the tests in #2870 ;)

private static final String PREF_STEREO_TO_MONO = "PrefStereoToMono";
public static final String PREF_CAST_ENABLED = "prefCast"; //Used for enabling Chromecast support
public static final int EPISODE_CLEANUP_QUEUE = -1;
Expand Down Expand Up @@ -638,13 +638,15 @@ private static String[] readPlaybackSpeedArray(String valueFromPrefs) {
}

public static boolean useSonic() {
return prefs.getBoolean(PREF_SONIC, false);
return prefs.getString(PREF_MEDIA_PLAYER, "sonic").equals("sonic");
}

public static void enableSonic(boolean enable) {
prefs.edit()
.putBoolean(PREF_SONIC, enable)
.apply();
public static boolean useExoplayer() {
return prefs.getString(PREF_MEDIA_PLAYER, "sonic").equals("exoplayer");
}

public static void enableSonic() {
prefs.edit().putString(PREF_MEDIA_PLAYER, "sonic").apply();
}

public static boolean stereoToMono() {
Expand Down
@@ -0,0 +1,245 @@
package de.danoeh.antennapod.core.service.playback;

import android.content.Context;
import android.net.Uri;
import android.view.SurfaceHolder;
import com.google.android.exoplayer2.C;
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.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import de.danoeh.antennapod.core.util.playback.IPlayer;
import org.antennapod.audio.MediaPlayer;


public class ExoPlayerWrapper implements IPlayer {
private final Context mContext;
private SimpleExoPlayer mExoPlayer;
private MediaSource mediaSource;
private MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener;
private MediaPlayer.OnCompletionListener audioCompletionListener;
private MediaPlayer.OnErrorListener audioErrorListener;

ExoPlayerWrapper(Context context) {
mContext = context;
mExoPlayer = createPlayer();
}

private SimpleExoPlayer createPlayer() {
SimpleExoPlayer p = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(mContext),
new DefaultTrackSelector(), new DefaultLoadControl());
p.setSeekParameters(SeekParameters.PREVIOUS_SYNC);
p.addListener(new Player.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {

}

@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

}

@Override
public void onLoadingChanged(boolean isLoading) {

}

@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == Player.STATE_ENDED) {
audioCompletionListener.onCompletion(null);
}
}

@Override
public void onRepeatModeChanged(int repeatMode) {

}

@Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {

}

@Override
public void onPlayerError(ExoPlaybackException error) {
audioErrorListener.onError(null, 0, 0);
}

@Override
public void onPositionDiscontinuity(int reason) {

}

@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {

}

@Override
public void onSeekProcessed() {
audioSeekCompleteListener.onSeekComplete(null);
}
});
return p;
}

@Override
public boolean canSetSpeed() {
return true;
}

@Override
public boolean canDownmix() {
return false;
}

@Override
public int getCurrentPosition() {
return (int) mExoPlayer.getCurrentPosition();
}

@Override
public float getCurrentSpeedMultiplier() {
return mExoPlayer.getPlaybackParameters().speed;
}

@Override
public int getDuration() {
if (mExoPlayer.getDuration() == C.TIME_UNSET) {
return PlaybackServiceMediaPlayer.INVALID_TIME;
}
return (int) mExoPlayer.getDuration();
}

@Override
public boolean isPlaying() {
return mExoPlayer.getPlayWhenReady();
}

@Override
public void pause() {
mExoPlayer.setPlayWhenReady(false);
}

@Override
public void prepare() throws IllegalStateException {
mExoPlayer.prepare(mediaSource);
}

@Override
public void release() {
if (mExoPlayer != null) {
mExoPlayer.release();
}
audioSeekCompleteListener = null;
audioCompletionListener = null;
audioErrorListener = null;
}

@Override
public void reset() {
mExoPlayer.release();
mExoPlayer = createPlayer();
}

@Override
public void seekTo(int i) throws IllegalStateException {
mExoPlayer.seekTo(i);
}

@Override
public void setAudioStreamType(int i) {
AudioAttributes a = mExoPlayer.getAudioAttributes();
AudioAttributes.Builder b = new AudioAttributes.Builder();
b.setContentType(i);
b.setFlags(a.flags);
b.setUsage(a.usage);
mExoPlayer.setAudioAttributes(b.build());
}

@Override
public void setDataSource(String s) throws IllegalArgumentException, IllegalStateException {
DataSource.Factory dataSourceFactory =
new DefaultDataSourceFactory(mContext, Util.getUserAgent(mContext, mContext.getPackageName()), null);
ExtractorMediaSource.Factory f = new ExtractorMediaSource.Factory(dataSourceFactory);
mediaSource = f.createMediaSource(Uri.parse(s));
}

@Override
public void setDisplay(SurfaceHolder sh) {
mExoPlayer.setVideoSurfaceHolder(sh);
}

@Override
public void setPlaybackSpeed(float v) {
PlaybackParameters params = mExoPlayer.getPlaybackParameters();
mExoPlayer.setPlaybackParameters(new PlaybackParameters(v, params.pitch));
}

@Override
public void setDownmix(boolean b) {

}

@Override
public void setVolume(float v, float v1) {
mExoPlayer.setVolume(v);
}

@Override
public void setWakeMode(Context context, int i) {

}

@Override
public void start() {
mExoPlayer.setPlayWhenReady(true);
}

@Override
public void stop() {
mExoPlayer.stop();
}

void setOnCompletionListener(MediaPlayer.OnCompletionListener audioCompletionListener) {
this.audioCompletionListener = audioCompletionListener;
}

void setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener) {
this.audioSeekCompleteListener = audioSeekCompleteListener;
}

void setOnErrorListener(MediaPlayer.OnErrorListener audioErrorListener) {
this.audioErrorListener = audioErrorListener;
}

int getVideoWidth() {
if (mExoPlayer.getVideoFormat() == null) {
return 0;
}
return mExoPlayer.getVideoFormat().width;
}

int getVideoHeight() {
if (mExoPlayer.getVideoFormat() == null) {
return 0;
}
return mExoPlayer.getVideoFormat().height;
}
}