diff options
Diffstat (limited to 'src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java')
-rw-r--r-- | src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java | 133 |
1 files changed, 83 insertions, 50 deletions
diff --git a/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java b/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java index 477eea9a6..49f20012d 100644 --- a/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java +++ b/src/de/danoeh/antennapod/service/playback/PlaybackServiceMediaPlayer.java @@ -4,12 +4,23 @@ import android.content.ComponentName; import android.content.Context; import android.media.AudioManager; import android.media.RemoteControlClient; +import android.net.wifi.WifiManager; +import android.os.PowerManager; +import android.telephony.TelephonyManager; import android.util.Log; import android.util.Pair; import android.view.SurfaceHolder; import org.apache.commons.lang3.Validate; +import java.io.IOException; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.ReentrantLock; + import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.feed.Chapter; import de.danoeh.antennapod.feed.MediaType; @@ -20,14 +31,6 @@ import de.danoeh.antennapod.util.playback.IPlayer; import de.danoeh.antennapod.util.playback.Playable; import de.danoeh.antennapod.util.playback.VideoPlayer; -import java.io.IOException; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.ReentrantLock; - /** * Manages the MediaPlayer object of the PlaybackService. */ @@ -63,6 +66,11 @@ public class PlaybackServiceMediaPlayer { private final ThreadPoolExecutor executor; + /** + * A wifi-lock that is acquired if the media file is being streamed. + */ + private WifiManager.WifiLock wifiLock; + public PlaybackServiceMediaPlayer(Context context, PSMPCallback callback) { Validate.notNull(context); Validate.notNull(callback); @@ -227,7 +235,7 @@ public class PlaybackServiceMediaPlayer { audioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); if (focusGained == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { - + acquireWifiLockIfNecessary(); setSpeed(Float.parseFloat(UserPreferences.getPlaybackSpeed())); mediaPlayer.start(); if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) { @@ -273,7 +281,7 @@ public class PlaybackServiceMediaPlayer { @Override public void run() { playerLock.lock(); - + releaseWifiLockIfNecessary(); if (playerStatus == PlayerStatus.PLAYING) { if (BuildConfig.DEBUG) Log.d(TAG, "Pausing playback."); @@ -374,13 +382,14 @@ public class PlaybackServiceMediaPlayer { @Override public void run() { playerLock.lock(); - + releaseWifiLockIfNecessary(); if (media != null) { playMediaObject(media, true, stream, startWhenPrepared.get(), false); } else if (mediaPlayer != null) { mediaPlayer.reset(); } else { - if (BuildConfig.DEBUG) Log.d(TAG, "Call to reinit was ignored: media and mediaPlayer were null"); + if (BuildConfig.DEBUG) + Log.d(TAG, "Call to reinit was ignored: media and mediaPlayer were null"); } playerLock.unlock(); } @@ -590,6 +599,7 @@ public class PlaybackServiceMediaPlayer { if (mediaPlayer != null) { mediaPlayer.release(); } + releaseWifiLockIfNecessary(); } public void setVideoSurface(final SurfaceHolder surface) { @@ -682,6 +692,7 @@ public class PlaybackServiceMediaPlayer { mediaPlayer = new AudioPlayer(context); } mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK); return setMediaPlayerListeners(mediaPlayer); } @@ -694,59 +705,62 @@ public class PlaybackServiceMediaPlayer { public void run() { playerLock.lock(); - switch (focusChange) { - case AudioManager.AUDIOFOCUS_LOSS: - if (BuildConfig.DEBUG) - Log.d(TAG, "Lost audio focus"); - pause(true, false); - callback.shouldStop(); - break; - case AudioManager.AUDIOFOCUS_GAIN: - if (BuildConfig.DEBUG) - Log.d(TAG, "Gained audio focus"); - if (pausedBecauseOfTransientAudiofocusLoss) // we paused => play now - resume(); - else // we ducked => raise audio level back + // If there is an incoming call, playback should be paused permanently + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + final int callState = (tm != null) ? tm.getCallState() : 0; + if (BuildConfig.DEBUG) Log.d(TAG, "Call state: " + callState); + Log.i(TAG, "Call state:" + callState); + + if (focusChange == AudioManager.AUDIOFOCUS_LOSS || callState != TelephonyManager.CALL_STATE_IDLE) { + if (BuildConfig.DEBUG) + Log.d(TAG, "Lost audio focus"); + pause(true, false); + callback.shouldStop(); + } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { + if (BuildConfig.DEBUG) + Log.d(TAG, "Gained audio focus"); + if (pausedBecauseOfTransientAudiofocusLoss) { // we paused => play now + resume(); + } else { // we ducked => raise audio level back + audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, + AudioManager.ADJUST_RAISE, 0); + } + } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { + if (playerStatus == PlayerStatus.PLAYING) { + if (!UserPreferences.shouldPauseForFocusLoss()) { + if (BuildConfig.DEBUG) + Log.d(TAG, "Lost audio focus temporarily. Ducking..."); audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, - AudioManager.ADJUST_RAISE, 0); - break; - case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: - if (playerStatus == PlayerStatus.PLAYING) { - if (!UserPreferences.shouldPauseForFocusLoss()) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Lost audio focus temporarily. Ducking..."); - audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, - AudioManager.ADJUST_LOWER, 0); - pausedBecauseOfTransientAudiofocusLoss = false; - } else { - if (BuildConfig.DEBUG) - Log.d(TAG, "Lost audio focus temporarily. Could duck, but won't, pausing..."); - pause(false, false); - pausedBecauseOfTransientAudiofocusLoss = true; - } - } - break; - case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: - if (playerStatus == PlayerStatus.PLAYING) { + AudioManager.ADJUST_LOWER, 0); + pausedBecauseOfTransientAudiofocusLoss = false; + } else { if (BuildConfig.DEBUG) - Log.d(TAG, "Lost audio focus temporarily. Pausing..."); + Log.d(TAG, "Lost audio focus temporarily. Could duck, but won't, pausing..."); pause(false, false); pausedBecauseOfTransientAudiofocusLoss = true; } + } + } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { + if (playerStatus == PlayerStatus.PLAYING) { + if (BuildConfig.DEBUG) + Log.d(TAG, "Lost audio focus temporarily. Pausing..."); + pause(false, false); + pausedBecauseOfTransientAudiofocusLoss = true; + } + playerLock.unlock(); } - - playerLock.unlock(); } }); - } }; + public void endPlayback() { executor.submit(new Runnable() { @Override public void run() { playerLock.lock(); + releaseWifiLockIfNecessary(); if (playerStatus != PlayerStatus.INDETERMINATE) { setPlayerStatus(PlayerStatus.INDETERMINATE, media); @@ -774,11 +788,13 @@ public class PlaybackServiceMediaPlayer { @Override public void run() { playerLock.lock(); + releaseWifiLockIfNecessary(); if (playerStatus == PlayerStatus.INDETERMINATE) { setPlayerStatus(PlayerStatus.STOPPED, null); } else { - if (BuildConfig.DEBUG) Log.d(TAG, "Ignored call to stop: Current player state is: " + playerStatus); + if (BuildConfig.DEBUG) + Log.d(TAG, "Ignored call to stop: Current player state is: " + playerStatus); } playerLock.unlock(); @@ -786,6 +802,23 @@ public class PlaybackServiceMediaPlayer { }); } + private synchronized void acquireWifiLockIfNecessary() { + if (stream) { + if (wifiLock == null) { + wifiLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)) + .createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); + wifiLock.setReferenceCounted(false); + } + wifiLock.acquire(); + } + } + + private synchronized void releaseWifiLockIfNecessary() { + if (wifiLock != null && wifiLock.isHeld()) { + wifiLock.release(); + } + } + /** * Holds information about a PSMP object. */ |