diff options
Diffstat (limited to 'src/de/danoeh/antennapod/service')
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 { |