summaryrefslogtreecommitdiff
path: root/src/de/danoeh/antennapod/service
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/danoeh/antennapod/service')
-rw-r--r--src/de/danoeh/antennapod/service/PlaybackService.java404
-rw-r--r--src/de/danoeh/antennapod/service/PlayerStatus.java1
-rw-r--r--src/de/danoeh/antennapod/service/PlayerWidgetService.java8
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadService.java48
4 files changed, 244 insertions, 217 deletions
diff --git a/src/de/danoeh/antennapod/service/PlaybackService.java b/src/de/danoeh/antennapod/service/PlaybackService.java
index 62370ff6d..450f7f65d 100644
--- a/src/de/danoeh/antennapod/service/PlaybackService.java
+++ b/src/de/danoeh/antennapod/service/PlaybackService.java
@@ -28,6 +28,7 @@ import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.media.RemoteControlClient;
import android.media.RemoteControlClient.MetadataEditor;
+import android.os.AsyncTask;
import android.os.Binder;
import android.os.IBinder;
import android.preference.PreferenceManager;
@@ -36,52 +37,32 @@ import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import de.danoeh.antennapod.AppConfig;
-import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.AudioplayerActivity;
import de.danoeh.antennapod.activity.VideoplayerActivity;
import de.danoeh.antennapod.feed.Chapter;
import de.danoeh.antennapod.feed.Feed;
+import de.danoeh.antennapod.feed.FeedComponent;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedManager;
import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.feed.MediaType;
+import de.danoeh.antennapod.preferences.PlaybackPreferences;
+import de.danoeh.antennapod.preferences.UserPreferences;
import de.danoeh.antennapod.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.receiver.PlayerWidget;
import de.danoeh.antennapod.util.BitmapDecoder;
-import de.danoeh.antennapod.util.ChapterUtils;
+import de.danoeh.antennapod.util.flattr.FlattrUtils;
+import de.danoeh.antennapod.util.playback.Playable;
+import de.danoeh.antennapod.util.playback.Playable.PlayableException;
/** Controls the MediaPlayer that plays a FeedMedia-file */
public class PlaybackService extends Service {
/** Logging tag */
private static final String TAG = "PlaybackService";
- /** Contains the id of the media that was played last. */
- public static final String PREF_LAST_PLAYED_ID = "de.danoeh.antennapod.preferences.lastPlayedId";
- /** Contains the feed id of the last played item. */
- public static final String PREF_LAST_PLAYED_FEED_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedId";
- /**
- * ID of the media object that is currently being played. This preference is
- * set to NO_MEDIA_PLAYING after playback has been completed and is set as
- * soon as the 'play' button is pressed.
- */
- public static final String PREF_CURRENTLY_PLAYING_MEDIA = "de.danoeh.antennapod.preferences.currentlyPlayingMedia";
- /** True if last played media was streamed. */
- public static final String PREF_LAST_IS_STREAM = "de.danoeh.antennapod.preferences.lastIsStream";
- /** True if last played media was a video. */
- public static final String PREF_LAST_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
- /** True if playback of last played media has been completed. */
- public static final String PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED = "de.danoeh.antennapod.preferences.lastPlaybackCompleted";
- /**
- * ID of the last played media which should be auto-deleted as soon as
- * PREF_LAST_PLAYED_ID changes.
- */
- public static final String PREF_AUTODELETE_MEDIA_ID = "de.danoeh.antennapod.preferences.autoDeleteMediaId";
-
- /** Contains the id of the FeedMedia object. */
- public static final String EXTRA_MEDIA_ID = "extra.de.danoeh.antennapod.service.mediaId";
- /** Contains the id of the Feed object of the FeedMedia. */
- public static final String EXTRA_FEED_ID = "extra.de.danoeh.antennapod.service.feedId";
+ /** Parcelable of type Playable. */
+ public static final String EXTRA_PLAYABLE = "PlaybackService.PlayableExtra";
/** True if media should be streamed. */
public static final String EXTRA_SHOULD_STREAM = "extra.de.danoeh.antennapod.service.shouldStream";
/**
@@ -134,8 +115,8 @@ public class PlaybackService extends Service {
private MediaPlayer player;
private RemoteControlClient remoteControlClient;
- private FeedMedia media;
- private Feed feed;
+ private Playable media;
+
/** True if media should be streamed (Extracted from Intent Extra) . */
private boolean shouldStream;
@@ -154,8 +135,6 @@ public class PlaybackService extends Service {
private SleepTimer sleepTimer;
private Future sleepTimerFuture;
- private Thread chapterLoader;
-
private static final int SCHED_EX_POOL_SIZE = 3;
private ScheduledThreadPoolExecutor schedExecutor;
@@ -166,9 +145,6 @@ public class PlaybackService extends Service {
/** True if mediaplayer was paused because it lost audio focus temporarily */
private boolean pausedBecauseOfTransientAudiofocusLoss;
- /** Value of PREF_CURRENTLY_PLAYING_MEDIA if no media is playing. */
- public static final long NO_MEDIA_PLAYING = -1;
-
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
@@ -197,11 +173,7 @@ public class PlaybackService extends Service {
return new Intent(context, AudioplayerActivity.class);
}
} else {
- SharedPreferences pref = PreferenceManager
- .getDefaultSharedPreferences(context
- .getApplicationContext());
- boolean isVideo = pref.getBoolean(PREF_LAST_IS_VIDEO, false);
- if (isVideo) {
+ if (PlaybackPreferences.isLastIsVideo()) {
return new Intent(context, VideoplayerActivity.class);
} else {
return new Intent(context, AudioplayerActivity.class);
@@ -213,8 +185,7 @@ public class PlaybackService extends Service {
* Same as getPlayerActivityIntent(context), but here the type of activity
* depends on the FeedMedia that is provided as an argument.
*/
- public static Intent getPlayerActivityIntent(Context context,
- FeedMedia media) {
+ public static Intent getPlayerActivityIntent(Context context, Playable media) {
MediaType mt = media.getMediaType();
if (mt == MediaType.VIDEO) {
return new Intent(context, VideoplayerActivity.class);
@@ -227,9 +198,8 @@ public class PlaybackService extends Service {
public static FeedMedia getLastPlayedMediaFromPreferences(Context context) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context.getApplicationContext());
- long mediaId = prefs.getLong(PlaybackService.PREF_LAST_PLAYED_ID, -1);
- long feedId = prefs.getLong(PlaybackService.PREF_LAST_PLAYED_FEED_ID,
- -1);
+ long mediaId = PlaybackPreferences.getLastPlayedId();
+ long feedId = PlaybackPreferences.getLastPlayedFeedId();
FeedManager manager = FeedManager.getInstance();
if (mediaId != -1 && feedId != -1) {
Feed feed = manager.getFeed(feedId);
@@ -243,12 +213,13 @@ public class PlaybackService extends Service {
private void setLastPlayedMediaId(long mediaId) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
- long autoDeleteId = prefs.getLong(PREF_AUTODELETE_MEDIA_ID, -1);
+ long autoDeleteId = PlaybackPreferences.getAutoDeleteMediaId();
SharedPreferences.Editor editor = prefs.edit();
if (mediaId == autoDeleteId) {
- editor.putBoolean(PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED, false);
+ editor.putBoolean(
+ PlaybackPreferences.PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED,
+ false);
}
- editor.putLong(PREF_LAST_PLAYED_ID, mediaId);
editor.commit();
}
@@ -350,7 +321,7 @@ public class PlaybackService extends Service {
case AudioManager.AUDIOFOCUS_LOSS:
if (AppConfig.DEBUG)
Log.d(TAG, "Lost audio focus");
- pause(true, true);
+ pause(true, false);
stopSelf();
break;
case AudioManager.AUDIOFOCUS_GAIN:
@@ -393,26 +364,24 @@ public class PlaybackService extends Service {
handleKeycode(keycode);
} else {
- long mediaId = intent.getLongExtra(EXTRA_MEDIA_ID, -1);
- long feedId = intent.getLongExtra(EXTRA_FEED_ID, -1);
+ Playable playable = intent.getParcelableExtra(EXTRA_PLAYABLE);
boolean playbackType = intent.getBooleanExtra(EXTRA_SHOULD_STREAM,
true);
- if (mediaId == -1 || feedId == -1) {
- Log.e(TAG,
- "Media ID or Feed ID wasn't provided to the Service.");
- if (media == null || feed == null) {
+ if (playable == null) {
+ Log.e(TAG, "Playable extra wasn't sent to the service");
+ if (media == null) {
stopSelf();
}
// Intent values appear to be valid
// check if already playing and playbackType is the same
- } else if (media == null || mediaId != media.getId()
+ } else if (media == null || playable != media
|| playbackType != shouldStream) {
pause(true, false);
player.reset();
sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0);
- if (media == null || mediaId != media.getId()) {
- feed = manager.getFeed(feedId);
- media = manager.getFeedMedia(mediaId, feed);
+ if (media == null
+ || playable.getIdentifier() != media.getIdentifier()) {
+ media = playable;
}
if (media != null) {
@@ -487,23 +456,45 @@ public class PlaybackService extends Service {
if (status == PlayerStatus.STOPPED
|| status == PlayerStatus.AWAITING_VIDEO_SURFACE) {
try {
- if (shouldStream) {
- player.setDataSource(media.getDownload_url());
- setStatus(PlayerStatus.PREPARING);
- player.prepareAsync();
- } else {
- player.setDataSource(media.getFile_url());
- setStatus(PlayerStatus.PREPARING);
- player.prepare();
- }
+ InitTask initTask = new InitTask() {
+
+ @Override
+ protected void onPostExecute(Playable result) {
+ if (result != null) {
+ try {
+ if (shouldStream) {
+ player.setDataSource(media.getStreamUrl());
+ setStatus(PlayerStatus.PREPARING);
+ player.prepareAsync();
+ } else {
+ player.setDataSource(media
+ .getLocalMediaUrl());
+ setStatus(PlayerStatus.PREPARING);
+ player.prepareAsync();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ setStatus(PlayerStatus.ERROR);
+ sendBroadcast(new Intent(
+ ACTION_SHUTDOWN_PLAYBACK_SERVICE));
+ }
+ }
+
+ @Override
+ protected void onPreExecute() {
+ setStatus(PlayerStatus.INITIALIZING);
+ }
+
+ };
+ initTask.executeAsync(media);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
}
}
@@ -535,18 +526,50 @@ public class PlaybackService extends Service {
if (mediaType == MediaType.AUDIO) {
if (AppConfig.DEBUG)
Log.d(TAG, "Mime type is audio");
- playingVideo = false;
- if (shouldStream) {
- player.setDataSource(media.getDownload_url());
- } else if (media.getFile_url() != null) {
- player.setDataSource(media.getFile_url());
- }
- if (prepareImmediately) {
- setStatus(PlayerStatus.PREPARING);
- player.prepareAsync();
- } else {
- setStatus(PlayerStatus.INITIALIZED);
- }
+
+ InitTask initTask = new InitTask() {
+
+ @Override
+ protected void onPostExecute(Playable result) {
+ if (result != null) {
+ playingVideo = false;
+ try {
+ if (shouldStream) {
+ player.setDataSource(media.getStreamUrl());
+ } else if (media.localFileAvailable()) {
+ player.setDataSource(media
+ .getLocalMediaUrl());
+ }
+
+ if (prepareImmediately) {
+ setStatus(PlayerStatus.PREPARING);
+ player.prepareAsync();
+ } else {
+ setStatus(PlayerStatus.INITIALIZED);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ media = null;
+ setStatus(PlayerStatus.ERROR);
+ sendBroadcast(new Intent(
+ ACTION_SHUTDOWN_PLAYBACK_SERVICE));
+ }
+ } else {
+ Log.e(TAG, "InitTask could not load metadata");
+ media = null;
+ setStatus(PlayerStatus.ERROR);
+ sendBroadcast(new Intent(
+ ACTION_SHUTDOWN_PLAYBACK_SERVICE));
+ }
+ }
+
+ @Override
+ protected void onPreExecute() {
+ setStatus(PlayerStatus.INITIALIZING);
+ }
+
+ };
+ initTask.executeAsync(media);
} else if (mediaType == MediaType.VIDEO) {
if (AppConfig.DEBUG)
Log.d(TAG, "Mime type is video");
@@ -561,8 +584,6 @@ public class PlaybackService extends Service {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
}
}
@@ -601,39 +622,6 @@ public class PlaybackService extends Service {
if (startWhenPrepared) {
play();
}
- if (shouldStream && media.getItem().getChapters() == null) {
- // load chapters if available
- if (chapterLoader != null) {
- chapterLoader.interrupt();
- }
- chapterLoader = new Thread() {
-
- @Override
- public void run() {
- if (AppConfig.DEBUG)
- Log.d(TAG, "Starting chapterLoader thread");
- ChapterUtils
- .readID3ChaptersFromFeedMediaDownloadUrl(media
- .getItem());
- if (media.getItem().getChapters() == null) {
- ChapterUtils
- .readOggChaptersFromMediaDownloadUrl(media
- .getItem());
- }
- if (media.getItem().getChapters() != null
- && !interrupted()) {
- sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD,
- 0);
- manager.setFeedItem(PlaybackService.this,
- media.getItem());
- }
- if (AppConfig.DEBUG)
- Log.d(TAG, "ChapterLoaderThread has finished");
- }
-
- };
- chapterLoader.start();
- }
}
};
@@ -675,7 +663,7 @@ public class PlaybackService extends Service {
pause(true, true);
}
sendNotificationBroadcast(NOTIFICATION_TYPE_ERROR, what);
- setCurrentlyPlayingMedia(NO_MEDIA_PLAYING);
+ setCurrentlyPlayingMedia(PlaybackPreferences.NO_MEDIA_PLAYING);
stopSelf();
return true;
}
@@ -690,42 +678,53 @@ public class PlaybackService extends Service {
audioManager.abandonAudioFocus(audioFocusChangeListener);
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
+ SharedPreferences.Editor editor = prefs.edit();
+
// Save state
cancelPositionSaver();
- media.setPlaybackCompletionDate(new Date());
- manager.markItemRead(PlaybackService.this, media.getItem(), true,
- true);
- FeedItem nextItem = manager
- .getQueueSuccessorOfItem(media.getItem());
- boolean isInQueue = manager.isInQueue(media.getItem());
- if (isInQueue) {
- manager.removeQueueItem(PlaybackService.this, media.getItem());
- }
- manager.addItemToPlaybackHistory(PlaybackService.this,
- media.getItem());
- manager.setFeedMedia(PlaybackService.this, media);
-
- long autoDeleteMediaId = media.getId();
- if (shouldStream) {
- autoDeleteMediaId = -1;
+ boolean isInQueue = false;
+ FeedItem nextItem = null;
+
+ if (media instanceof FeedMedia) {
+ FeedItem item = ((FeedMedia) media).getItem();
+ ((FeedMedia) media).setPlaybackCompletionDate(new Date());
+ manager.markItemRead(PlaybackService.this, item, true, true);
+ nextItem = manager.getQueueSuccessorOfItem(item);
+ isInQueue = media instanceof FeedMedia
+ && manager.isInQueue(((FeedMedia) media).getItem());
+ if (isInQueue) {
+ manager.removeQueueItem(PlaybackService.this, item);
+ }
+ manager.addItemToPlaybackHistory(PlaybackService.this, item);
+ manager.setFeedMedia(PlaybackService.this, (FeedMedia) media);
+ long autoDeleteMediaId = ((FeedComponent) media).getId();
+ if (shouldStream) {
+ autoDeleteMediaId = -1;
+ }
+ editor.putLong(PlaybackPreferences.PREF_AUTODELETE_MEDIA_ID,
+ autoDeleteMediaId);
}
- SharedPreferences.Editor editor = prefs.edit();
- editor.putLong(PREF_CURRENTLY_PLAYING_MEDIA, NO_MEDIA_PLAYING);
- editor.putLong(PREF_AUTODELETE_MEDIA_ID, autoDeleteMediaId);
- editor.putBoolean(PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED, true);
+ editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
+ editor.putBoolean(
+ PlaybackPreferences.PREF_AUTO_DELETE_MEDIA_PLAYBACK_COMPLETED,
+ true);
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
+ editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
editor.commit();
// Prepare for playing next item
- boolean followQueue = prefs.getBoolean(
- PodcastApp.PREF_FOLLOW_QUEUE, false);
- boolean playNextItem = isInQueue && followQueue && nextItem != null;
+ boolean playNextItem = isInQueue && UserPreferences.isFollowQueue()
+ && nextItem != null;
if (playNextItem) {
if (AppConfig.DEBUG)
Log.d(TAG, "Loading next item in queue");
media = nextItem.getMedia();
- feed = nextItem.getFeed();
- shouldStream = !media.isDownloaded();
+ shouldStream = !media.localFileAvailable();
prepareImmediately = startWhenPrepared = true;
} else {
if (AppConfig.DEBUG)
@@ -814,8 +813,12 @@ public class PlaybackService extends Service {
public void stop() {
if (AppConfig.DEBUG)
Log.d(TAG, "Stopping playback");
- player.stop();
- setCurrentlyPlayingMedia(NO_MEDIA_PLAYING);
+ if (status == PlayerStatus.PREPARED || status == PlayerStatus.PAUSED
+ || status == PlayerStatus.STOPPED
+ || status == PlayerStatus.PLAYING) {
+ player.stop();
+ }
+ setCurrentlyPlayingMedia(PlaybackPreferences.NO_MEDIA_PLAYING);
stopSelf();
}
@@ -856,12 +859,37 @@ public class PlaybackService extends Service {
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext())
.edit();
- editor.putLong(PREF_CURRENTLY_PLAYING_MEDIA, media.getId());
- editor.putLong(PREF_LAST_PLAYED_FEED_ID, feed.getId());
- editor.putBoolean(PREF_LAST_IS_STREAM, shouldStream);
- editor.putBoolean(PREF_LAST_IS_VIDEO, playingVideo);
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA,
+ media.getPlayableType());
+ editor.putBoolean(PlaybackPreferences.PREF_LAST_IS_STREAM,
+ shouldStream);
+ editor.putBoolean(PlaybackPreferences.PREF_LAST_IS_VIDEO,
+ playingVideo);
+ editor.putLong(PlaybackPreferences.PREF_LAST_PLAYED_ID,
+ media.getPlayableType());
+ if (media instanceof FeedMedia) {
+ FeedMedia fMedia = (FeedMedia) media;
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
+ fMedia.getItem().getFeed().getId());
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
+ fMedia.getId());
+ } else {
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
+ editor.putLong(
+ PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID,
+ PlaybackPreferences.NO_MEDIA_PLAYING);
+ }
+ media.writeToPreferences(editor);
+
editor.commit();
- setLastPlayedMediaId(media.getId());
+ if (media instanceof FeedMedia) {
+ setLastPlayedMediaId(((FeedMedia) media).getId());
+ }
player.start();
if (status != PlayerStatus.PAUSED) {
player.seekTo((int) media.getPosition());
@@ -877,9 +905,7 @@ public class PlaybackService extends Service {
}
audioManager
.registerMediaButtonEventReceiver(mediaButtonReceiver);
- if (media.getItem().isRead() == false) {
- manager.markItemRead(this, media.getItem(), true, false);
- }
+ media.onPlaybackStart();
} else {
if (AppConfig.DEBUG)
Log.d(TAG, "Failed to request Audiofocus");
@@ -917,12 +943,11 @@ public class PlaybackService extends Service {
Bitmap icon = null;
if (android.os.Build.VERSION.SDK_INT >= 11) {
- if (media != null && media.getImage() != null
- && media.getImage().getFile_url() != null) {
+ if (media != null && media.getImageFileUrl() != null) {
int iconSize = getResources().getDimensionPixelSize(
android.R.dimen.notification_large_icon_width);
- icon = BitmapDecoder.decodeBitmap(iconSize, media.getImage()
- .getFile_url());
+ icon = BitmapDecoder.decodeBitmap(iconSize,
+ media.getImageFileUrl());
}
}
if (icon == null) {
@@ -930,15 +955,16 @@ public class PlaybackService extends Service {
R.drawable.ic_stat_antenna);
}
- String contentText = media.getItem().getFeed().getTitle();
- String contentTitle = media.getItem().getTitle();
+ String contentText = media.getFeedTitle();
+ String contentTitle = media.getEpisodeTitle();
Notification notification = null;
if (android.os.Build.VERSION.SDK_INT >= 16) {
Intent pauseButtonIntent = new Intent(this, PlaybackService.class);
pauseButtonIntent.putExtra(MediaButtonReceiver.EXTRA_KEYCODE,
KeyEvent.KEYCODE_MEDIA_PAUSE);
- PendingIntent pauseButtonPendingIntent = PendingIntent
- .getService(this, 0, pauseButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent pauseButtonPendingIntent = PendingIntent.getService(
+ this, 0, pauseButtonIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder notificationBuilder = new Notification.Builder(
this)
.setContentTitle(contentTitle)
@@ -1006,8 +1032,9 @@ public class PlaybackService extends Service {
if (position != INVALID_TIME) {
if (AppConfig.DEBUG)
Log.d(TAG, "Saving current position to " + position);
- media.setPosition(position);
- manager.setFeedMedia(this, media);
+ media.saveCurrentPosition(PreferenceManager
+ .getDefaultSharedPreferences(getApplicationContext()),
+ position);
}
}
@@ -1101,10 +1128,10 @@ public class PlaybackService extends Service {
MetadataEditor editor = remoteControlClient
.editMetadata(false);
editor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE,
- media.getItem().getTitle());
+ media.getEpisodeTitle());
editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM,
- media.getItem().getFeed().getTitle());
+ media.getFeedTitle());
editor.apply();
}
@@ -1155,10 +1182,8 @@ public class PlaybackService extends Service {
/** Pauses playback if PREF_PAUSE_ON_HEADSET_DISCONNECT was set to true. */
private void pauseIfPauseOnDisconnect() {
- boolean pauseOnDisconnect = PreferenceManager
- .getDefaultSharedPreferences(getApplicationContext())
- .getBoolean(PodcastApp.PREF_PAUSE_ON_HEADSET_DISCONNECT, false);
- if (pauseOnDisconnect && status == PlayerStatus.PLAYING) {
+ if (UserPreferences.isPauseOnHeadsetDisconnect()
+ && status == PlayerStatus.PLAYING) {
pause(true, true);
}
}
@@ -1169,12 +1194,8 @@ public class PlaybackService extends Service {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_SHUTDOWN_PLAYBACK_SERVICE)) {
schedExecutor.shutdownNow();
- if (chapterLoader != null) {
- chapterLoader.interrupt();
- }
stop();
media = null;
- feed = null;
}
}
@@ -1276,7 +1297,7 @@ public class PlaybackService extends Service {
return status;
}
- public FeedMedia getMedia() {
+ public Playable getMedia() {
return media;
}
@@ -1343,7 +1364,40 @@ public class PlaybackService extends Service {
private void setCurrentlyPlayingMedia(long id) {
SharedPreferences.Editor editor = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext()).edit();
- editor.putLong(PREF_CURRENTLY_PLAYING_MEDIA, id);
+ editor.putLong(PlaybackPreferences.PREF_CURRENTLY_PLAYING_MEDIA, id);
editor.commit();
}
+
+ private static class InitTask extends AsyncTask<Playable, Void, Playable> {
+ private Playable playable;
+ public PlayableException exception;
+
+ @Override
+ protected Playable doInBackground(Playable... params) {
+ if (params[0] == null) {
+ throw new IllegalArgumentException("Playable must not be null");
+ }
+ playable = params[0];
+
+ try {
+ playable.loadMetadata();
+ } catch (PlayableException e) {
+ e.printStackTrace();
+ exception = e;
+ return null;
+ }
+ return playable;
+ }
+
+ @SuppressLint("NewApi")
+ public void executeAsync(Playable playable) {
+ FlattrUtils.hasToken();
+ if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
+ executeOnExecutor(THREAD_POOL_EXECUTOR, playable);
+ } else {
+ execute(playable);
+ }
+ }
+
+ }
}
diff --git a/src/de/danoeh/antennapod/service/PlayerStatus.java b/src/de/danoeh/antennapod/service/PlayerStatus.java
index 17e42f847..fbf5b1505 100644
--- a/src/de/danoeh/antennapod/service/PlayerStatus.java
+++ b/src/de/danoeh/antennapod/service/PlayerStatus.java
@@ -9,5 +9,6 @@ public enum PlayerStatus {
PREPARED,
SEEKING,
AWAITING_VIDEO_SURFACE, // player has been initialized and the media type to be played is a video.
+ INITIALIZING, // playback service is loading the Playable's metadata
INITIALIZED // playback service was started, data source of media player was set.
}
diff --git a/src/de/danoeh/antennapod/service/PlayerWidgetService.java b/src/de/danoeh/antennapod/service/PlayerWidgetService.java
index dd4598e9c..475af9655 100644
--- a/src/de/danoeh/antennapod/service/PlayerWidgetService.java
+++ b/src/de/danoeh/antennapod/service/PlayerWidgetService.java
@@ -13,10 +13,10 @@ import android.view.View;
import android.widget.RemoteViews;
import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.receiver.PlayerWidget;
import de.danoeh.antennapod.util.Converter;
+import de.danoeh.antennapod.util.playback.Playable;
/** Updates the state of the player widget */
public class PlayerWidgetService extends Service {
@@ -83,11 +83,11 @@ public class PlayerWidgetService extends Service {
PlaybackService.getPlayerActivityIntent(this), 0);
views.setOnClickPendingIntent(R.id.layout_left, startMediaplayer);
- if (playbackService != null) {
- FeedMedia media = playbackService.getMedia();
+ if (playbackService != null && playbackService.getMedia() != null) {
+ Playable media = playbackService.getMedia();
PlayerStatus status = playbackService.getStatus();
- views.setTextViewText(R.id.txtvTitle, media.getItem().getTitle());
+ views.setTextViewText(R.id.txtvTitle, media.getEpisodeTitle());
if (status == PlayerStatus.PLAYING) {
String progressString = getProgressString(playbackService);
diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java
index 59f0a5b97..986491fb5 100644
--- a/src/de/danoeh/antennapod/service/download/DownloadService.java
+++ b/src/de/danoeh/antennapod/service/download/DownloadService.java
@@ -30,7 +30,6 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
-import android.app.Notification.Builder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -52,6 +51,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.DownloadActivity;
import de.danoeh.antennapod.activity.DownloadLogActivity;
import de.danoeh.antennapod.asynctask.DownloadStatus;
+import de.danoeh.antennapod.feed.EventDistributor;
import de.danoeh.antennapod.feed.Feed;
import de.danoeh.antennapod.feed.FeedFile;
import de.danoeh.antennapod.feed.FeedImage;
@@ -78,7 +78,6 @@ public class DownloadService extends Service {
/** Extra for ACTION_CANCEL_DOWNLOAD */
public static final String EXTRA_DOWNLOAD_URL = "downloadUrl";
- public static final String ACTION_DOWNLOAD_HANDLED = "action.de.danoeh.antennapod.service.download_handled";
/**
* Sent by the DownloadService when the content of the downloads list
* changes.
@@ -90,12 +89,6 @@ public class DownloadService extends Service {
/** Extra for ACTION_ENQUEUE_DOWNLOAD intent. */
public static final String EXTRA_REQUEST = "request";
- // Download types for ACTION_DOWNLOAD_HANDLED
- public static final String EXTRA_DOWNLOAD_TYPE = "extra.de.danoeh.antennapod.service.downloadType";
- public static final int DOWNLOAD_TYPE_FEED = 1;
- public static final int DOWNLOAD_TYPE_MEDIA = 2;
- public static final int DOWNLOAD_TYPE_IMAGE = 3;
-
private CopyOnWriteArrayList<DownloadStatus> completedDownloads;
private ExecutorService syncExecutor;
@@ -463,7 +456,7 @@ public class DownloadService extends Service {
Log.e(TAG, "Download failed");
saveDownloadStatus(status);
}
- sendDownloadHandledIntent(getDownloadType(download));
+ sendDownloadHandledIntent();
downloadsBeingHandled -= 1;
}
}
@@ -505,24 +498,8 @@ public class DownloadService extends Service {
manager.addDownloadStatus(this, status);
}
- /** Returns correct value for EXTRA_DOWNLOAD_TYPE. */
- private int getDownloadType(FeedFile f) {
- if (f.getClass() == Feed.class) {
- return DOWNLOAD_TYPE_FEED;
- } else if (f.getClass() == FeedImage.class) {
- return DOWNLOAD_TYPE_IMAGE;
- } else if (f.getClass() == FeedMedia.class) {
- return DOWNLOAD_TYPE_MEDIA;
- } else {
- return 0;
- }
- }
-
- private void sendDownloadHandledIntent(int type) {
- Intent intent = new Intent(ACTION_DOWNLOAD_HANDLED);
- intent.putExtra(EXTRA_DOWNLOAD_TYPE, type);
-
- sendBroadcast(intent);
+ private void sendDownloadHandledIntent() {
+ EventDistributor.getInstance().sendDownloadHandledBroadcast();
}
/**
@@ -727,7 +704,7 @@ public class DownloadService extends Service {
saveDownloadStatus(new DownloadStatus(savedFeed,
savedFeed.getHumanReadableIdentifier(), reason, successful,
reasonDetailed));
- sendDownloadHandledIntent(DOWNLOAD_TYPE_FEED);
+ sendDownloadHandledIntent();
downloadsBeingHandled -= 1;
handler.post(new Runnable() {
@@ -756,7 +733,7 @@ public class DownloadService extends Service {
}
private boolean hasValidFeedItems(Feed feed) {
- for (FeedItem item : feed.getItems()) {
+ for (FeedItem item : feed.getItemsArray()) {
if (item.getTitle() == null) {
Log.e(TAG, "Item has no title");
return false;
@@ -804,7 +781,7 @@ public class DownloadService extends Service {
image.setDownloaded(true);
saveDownloadStatus(status);
- sendDownloadHandledIntent(DOWNLOAD_TYPE_IMAGE);
+ sendDownloadHandledIntent();
manager.setFeedImage(DownloadService.this, image);
if (image.getFeed() != null) {
manager.setFeed(DownloadService.this, image.getFeed());
@@ -854,21 +831,16 @@ public class DownloadService extends Service {
} finally {
mediaplayer.release();
}
-
+
if (media.getItem().getChapters() == null) {
- ChapterUtils.readID3ChaptersFromFeedMediaFileUrl(media
- .getItem());
- if (media.getItem().getChapters() == null) {
- ChapterUtils.readOggChaptersFromMediaFileUrl(media
- .getItem());
- }
+ ChapterUtils.loadChaptersFromFileUrl(media);
if (media.getItem().getChapters() != null) {
chaptersRead = true;
}
}
saveDownloadStatus(status);
- sendDownloadHandledIntent(DOWNLOAD_TYPE_MEDIA);
+ sendDownloadHandledIntent();
if (chaptersRead) {
manager.setFeedItem(DownloadService.this, media.getItem());
} else {