Adapted remaining classes to new playback service model

This commit is contained in:
daniel oeh 2013-12-29 01:27:18 +01:00
parent e05a5c265b
commit b864927709
11 changed files with 776 additions and 716 deletions

View File

@ -11,15 +11,10 @@ import android.support.v4.app.ListFragment;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.Window;
import android.view.View.OnLongClickListener; import android.view.View.OnLongClickListener;
import android.widget.ArrayAdapter; import android.view.Window;
import android.widget.Button; import android.widget.*;
import android.widget.ImageButton;
import android.widget.ImageView.ScaleType; import android.widget.ImageView.ScaleType;
import android.widget.ListView;
import android.widget.TextView;
import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.ChapterListAdapter; import de.danoeh.antennapod.adapter.ChapterListAdapter;
@ -35,496 +30,506 @@ import de.danoeh.antennapod.service.playback.PlaybackService;
import de.danoeh.antennapod.util.playback.ExternalMedia; import de.danoeh.antennapod.util.playback.ExternalMedia;
import de.danoeh.antennapod.util.playback.Playable; import de.danoeh.antennapod.util.playback.Playable;
/** Activity for playing audio files. */ /**
* Activity for playing audio files.
*/
public class AudioplayerActivity extends MediaplayerActivity { public class AudioplayerActivity extends MediaplayerActivity {
private static final int POS_COVER = 0; private static final int POS_COVER = 0;
private static final int POS_DESCR = 1; private static final int POS_DESCR = 1;
private static final int POS_CHAPTERS = 2; private static final int POS_CHAPTERS = 2;
private static final int NUM_CONTENT_FRAGMENTS = 3; private static final int NUM_CONTENT_FRAGMENTS = 3;
final String TAG = "AudioplayerActivity"; final String TAG = "AudioplayerActivity";
private static final String PREFS = "AudioPlayerActivityPreferences"; private static final String PREFS = "AudioPlayerActivityPreferences";
private static final String PREF_KEY_SELECTED_FRAGMENT_POSITION = "selectedFragmentPosition"; private static final String PREF_KEY_SELECTED_FRAGMENT_POSITION = "selectedFragmentPosition";
private static final String PREF_PLAYABLE_ID = "playableId"; private static final String PREF_PLAYABLE_ID = "playableId";
private Fragment[] detachedFragments; private Fragment[] detachedFragments;
private CoverFragment coverFragment; private CoverFragment coverFragment;
private ItemDescriptionFragment descriptionFragment; private ItemDescriptionFragment descriptionFragment;
private ListFragment chapterFragment; private ListFragment chapterFragment;
private Fragment currentlyShownFragment; private Fragment currentlyShownFragment;
private int currentlyShownPosition = -1; private int currentlyShownPosition = -1;
/** Used if onResume was called without loadMediaInfo. */ /**
private int savedPosition = -1; * Used if onResume was called without loadMediaInfo.
*/
private int savedPosition = -1;
private TextView txtvTitle; private TextView txtvTitle;
private TextView txtvFeed; private TextView txtvFeed;
private Button butPlaybackSpeed; private Button butPlaybackSpeed;
private ImageButton butNavLeft; private ImageButton butNavLeft;
private ImageButton butNavRight; private ImageButton butNavRight;
private void resetFragmentView() { private void resetFragmentView() {
FragmentTransaction fT = getSupportFragmentManager().beginTransaction(); FragmentTransaction fT = getSupportFragmentManager().beginTransaction();
if (coverFragment != null) { if (coverFragment != null) {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Removing cover fragment"); Log.d(TAG, "Removing cover fragment");
fT.remove(coverFragment); fT.remove(coverFragment);
} }
if (descriptionFragment != null) { if (descriptionFragment != null) {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Removing description fragment"); Log.d(TAG, "Removing description fragment");
fT.remove(descriptionFragment); fT.remove(descriptionFragment);
} }
if (chapterFragment != null) { if (chapterFragment != null) {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Removing chapter fragment"); Log.d(TAG, "Removing chapter fragment");
fT.remove(chapterFragment); fT.remove(chapterFragment);
} }
if (currentlyShownFragment != null) { if (currentlyShownFragment != null) {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Removing currently shown fragment"); Log.d(TAG, "Removing currently shown fragment");
fT.remove(currentlyShownFragment); fT.remove(currentlyShownFragment);
} }
for (int i = 0; i < detachedFragments.length; i++) { for (int i = 0; i < detachedFragments.length; i++) {
Fragment f = detachedFragments[i]; Fragment f = detachedFragments[i];
if (f != null) { if (f != null) {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Removing detached fragment"); Log.d(TAG, "Removing detached fragment");
fT.remove(f); fT.remove(f);
} }
} }
fT.commit(); fT.commit();
currentlyShownFragment = null; currentlyShownFragment = null;
coverFragment = null; coverFragment = null;
descriptionFragment = null; descriptionFragment = null;
chapterFragment = null; chapterFragment = null;
currentlyShownPosition = -1; currentlyShownPosition = -1;
detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS]; detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
} }
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop(); super.onStop();
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "onStop"); Log.d(TAG, "onStop");
} }
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayShowTitleEnabled(false); getSupportActionBar().setDisplayShowTitleEnabled(false);
detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS]; detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
} }
private void savePreferences() { private void savePreferences() {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Saving preferences"); Log.d(TAG, "Saving preferences");
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE); SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit(); SharedPreferences.Editor editor = prefs.edit();
if (currentlyShownPosition >= 0 && controller != null if (currentlyShownPosition >= 0 && controller != null
&& controller.getMedia() != null) { && controller.getMedia() != null) {
editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION,
currentlyShownPosition); currentlyShownPosition);
editor.putString(PREF_PLAYABLE_ID, controller.getMedia() editor.putString(PREF_PLAYABLE_ID, controller.getMedia()
.getIdentifier().toString()); .getIdentifier().toString());
} else { } else {
editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, -1); editor.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, -1);
editor.putString(PREF_PLAYABLE_ID, ""); editor.putString(PREF_PLAYABLE_ID, "");
} }
editor.commit(); editor.commit();
savedPosition = currentlyShownPosition; savedPosition = currentlyShownPosition;
} }
@Override @Override
public void onConfigurationChanged(Configuration newConfig) { public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig); super.onConfigurationChanged(newConfig);
} }
@Override @Override
protected void onSaveInstanceState(Bundle outState) { protected void onSaveInstanceState(Bundle outState) {
// super.onSaveInstanceState(outState); would cause crash // super.onSaveInstanceState(outState); would cause crash
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "onSaveInstanceState"); Log.d(TAG, "onSaveInstanceState");
} }
@Override @Override
protected void onPause() { protected void onPause() {
savePreferences(); savePreferences();
resetFragmentView(); resetFragmentView();
super.onPause(); super.onPause();
} }
@Override @Override
protected void onRestoreInstanceState(Bundle savedInstanceState) { protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState); super.onRestoreInstanceState(savedInstanceState);
restoreFromPreferences(); restoreFromPreferences();
} }
/** /**
* Tries to restore the selected fragment position from the Activity's * Tries to restore the selected fragment position from the Activity's
* preferences. * preferences.
* *
* @return true if restoreFromPrefernces changed the activity's state * @return true if restoreFromPrefernces changed the activity's state
* */ */
private boolean restoreFromPreferences() { private boolean restoreFromPreferences() {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Restoring instance state"); Log.d(TAG, "Restoring instance state");
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE); SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
int savedPosition = prefs.getInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, int savedPosition = prefs.getInt(PREF_KEY_SELECTED_FRAGMENT_POSITION,
-1); -1);
String playableId = prefs.getString(PREF_PLAYABLE_ID, ""); String playableId = prefs.getString(PREF_PLAYABLE_ID, "");
if (savedPosition != -1 if (savedPosition != -1
&& controller != null && controller != null
&& controller.getMedia() != null && controller.getMedia() != null
&& controller.getMedia().getIdentifier().toString() && controller.getMedia().getIdentifier().toString()
.equals(playableId)) { .equals(playableId)) {
switchToFragment(savedPosition); switchToFragment(savedPosition);
return true; return true;
} else if (controller == null || controller.getMedia() == null) { } else if (controller == null || controller.getMedia() == null) {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, Log.d(TAG,
"Couldn't restore from preferences: controller or media was null"); "Couldn't restore from preferences: controller or media was null");
} else { } else {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, Log.d(TAG,
"Couldn't restore from preferences: savedPosition was -1 or saved identifier and playable identifier didn't match.\nsavedPosition: " "Couldn't restore from preferences: savedPosition was -1 or saved identifier and playable identifier didn't match.\nsavedPosition: "
+ savedPosition + ", id: " + playableId); + savedPosition + ", id: " + playableId);
} }
return false; return false;
} }
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
if (getIntent().getAction() != null if (getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_VIEW)) { && getIntent().getAction().equals(Intent.ACTION_VIEW)) {
Intent intent = getIntent(); Intent intent = getIntent();
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Received VIEW intent: " Log.d(TAG, "Received VIEW intent: "
+ intent.getData().getPath()); + intent.getData().getPath());
ExternalMedia media = new ExternalMedia(intent.getData().getPath(), ExternalMedia media = new ExternalMedia(intent.getData().getPath(),
MediaType.AUDIO); MediaType.AUDIO);
Intent launchIntent = new Intent(this, PlaybackService.class); Intent launchIntent = new Intent(this, PlaybackService.class);
launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media); launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED, launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
true); true);
launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false); launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false);
launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY, launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
true); true);
startService(launchIntent); startService(launchIntent);
} }
if (savedPosition != -1) { if (savedPosition != -1) {
switchToFragment(savedPosition); switchToFragment(savedPosition);
} }
} }
@Override @Override
protected void onNewIntent(Intent intent) { protected void onNewIntent(Intent intent) {
super.onNewIntent(intent); super.onNewIntent(intent);
setIntent(intent); setIntent(intent);
} }
@Override @Override
protected void onAwaitingVideoSurface() { protected void onAwaitingVideoSurface() {
startActivity(new Intent(this, VideoplayerActivity.class)); if (AppConfig.DEBUG) Log.d(TAG, "onAwaitingVideoSurface was called in audio player -> switching to video player");
} startActivity(new Intent(this, VideoplayerActivity.class));
}
@Override @Override
protected void postStatusMsg(int resId) { protected void postStatusMsg(int resId) {
setSupportProgressBarIndeterminateVisibility(resId == R.string.player_preparing_msg setSupportProgressBarIndeterminateVisibility(resId == R.string.player_preparing_msg
|| resId == R.string.player_seeking_msg || resId == R.string.player_seeking_msg
|| resId == R.string.player_buffering_msg); || resId == R.string.player_buffering_msg);
} }
@Override @Override
protected void clearStatusMsg() { protected void clearStatusMsg() {
setSupportProgressBarIndeterminateVisibility(false); setSupportProgressBarIndeterminateVisibility(false);
} }
/** /**
* Changes the currently displayed fragment. * Changes the currently displayed fragment.
* *
* @param pos Must be POS_COVER, POS_DESCR, or POS_CHAPTERS * @param pos Must be POS_COVER, POS_DESCR, or POS_CHAPTERS
* */ */
private void switchToFragment(int pos) { private void switchToFragment(int pos) {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Switching contentView to position " + pos); Log.d(TAG, "Switching contentView to position " + pos);
if (currentlyShownPosition != pos && controller != null) { if (currentlyShownPosition != pos && controller != null) {
Playable media = controller.getMedia(); Playable media = controller.getMedia();
if (media != null) { if (media != null) {
FragmentTransaction ft = getSupportFragmentManager() FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction(); .beginTransaction();
if (currentlyShownFragment != null) { if (currentlyShownFragment != null) {
detachedFragments[currentlyShownPosition] = currentlyShownFragment; detachedFragments[currentlyShownPosition] = currentlyShownFragment;
ft.detach(currentlyShownFragment); ft.detach(currentlyShownFragment);
} }
switch (pos) { switch (pos) {
case POS_COVER: case POS_COVER:
if (coverFragment == null) { if (coverFragment == null) {
Log.i(TAG, "Using new coverfragment"); Log.i(TAG, "Using new coverfragment");
coverFragment = CoverFragment.newInstance(media); coverFragment = CoverFragment.newInstance(media);
} }
currentlyShownFragment = coverFragment; currentlyShownFragment = coverFragment;
break; break;
case POS_DESCR: case POS_DESCR:
if (descriptionFragment == null) { if (descriptionFragment == null) {
descriptionFragment = ItemDescriptionFragment descriptionFragment = ItemDescriptionFragment
.newInstance(media, true); .newInstance(media, true);
} }
currentlyShownFragment = descriptionFragment; currentlyShownFragment = descriptionFragment;
break; break;
case POS_CHAPTERS: case POS_CHAPTERS:
if (chapterFragment == null) { if (chapterFragment == null) {
chapterFragment = new ListFragment() { chapterFragment = new ListFragment() {
@Override @Override
public void onListItemClick(ListView l, View v, public void onListItemClick(ListView l, View v,
int position, long id) { int position, long id) {
super.onListItemClick(l, v, position, id); super.onListItemClick(l, v, position, id);
Chapter chapter = (Chapter) this Chapter chapter = (Chapter) this
.getListAdapter().getItem(position); .getListAdapter().getItem(position);
controller.seekToChapter(chapter); controller.seekToChapter(chapter);
} }
}; };
chapterFragment.setListAdapter(new ChapterListAdapter( chapterFragment.setListAdapter(new ChapterListAdapter(
AudioplayerActivity.this, 0, media AudioplayerActivity.this, 0, media
.getChapters(), media)); .getChapters(), media));
} }
currentlyShownFragment = chapterFragment; currentlyShownFragment = chapterFragment;
break; break;
} }
if (currentlyShownFragment != null) { if (currentlyShownFragment != null) {
currentlyShownPosition = pos; currentlyShownPosition = pos;
if (detachedFragments[pos] != null) { if (detachedFragments[pos] != null) {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Reattaching fragment at position " Log.d(TAG, "Reattaching fragment at position "
+ pos); + pos);
ft.attach(detachedFragments[pos]); ft.attach(detachedFragments[pos]);
} else { } else {
ft.add(R.id.contentView, currentlyShownFragment); ft.add(R.id.contentView, currentlyShownFragment);
} }
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.disallowAddToBackStack(); ft.disallowAddToBackStack();
ft.commit(); ft.commit();
updateNavButtonDrawable(); updateNavButtonDrawable();
} }
} }
} }
} }
private void updateNavButtonDrawable() { private void updateNavButtonDrawable() {
TypedArray drawables = obtainStyledAttributes(new int[] { TypedArray drawables = obtainStyledAttributes(new int[]{
R.attr.navigation_shownotes, R.attr.navigation_chapters }); R.attr.navigation_shownotes, R.attr.navigation_chapters});
final Playable media = controller.getMedia(); final Playable media = controller.getMedia();
if (butNavLeft != null && butNavRight != null && media != null) { if (butNavLeft != null && butNavRight != null && media != null) {
switch (currentlyShownPosition) { switch (currentlyShownPosition) {
case POS_COVER: case POS_COVER:
butNavLeft.setScaleType(ScaleType.CENTER); butNavLeft.setScaleType(ScaleType.CENTER);
butNavLeft.setImageDrawable(drawables.getDrawable(0)); butNavLeft.setImageDrawable(drawables.getDrawable(0));
butNavRight.setImageDrawable(drawables.getDrawable(1)); butNavRight.setImageDrawable(drawables.getDrawable(1));
break; break;
case POS_DESCR: case POS_DESCR:
butNavLeft.setScaleType(ScaleType.CENTER_CROP); butNavLeft.setScaleType(ScaleType.CENTER_CROP);
butNavLeft.post(new Runnable() { butNavLeft.post(new Runnable() {
@Override @Override
public void run() { public void run() {
ImageLoader.getInstance().loadThumbnailBitmap(media, ImageLoader.getInstance().loadThumbnailBitmap(media,
butNavLeft); butNavLeft);
} }
}); });
butNavRight.setImageDrawable(drawables.getDrawable(1)); butNavRight.setImageDrawable(drawables.getDrawable(1));
break; break;
case POS_CHAPTERS: case POS_CHAPTERS:
butNavLeft.setScaleType(ScaleType.CENTER_CROP); butNavLeft.setScaleType(ScaleType.CENTER_CROP);
butNavLeft.post(new Runnable() { butNavLeft.post(new Runnable() {
@Override @Override
public void run() { public void run() {
ImageLoader.getInstance().loadThumbnailBitmap(media, ImageLoader.getInstance().loadThumbnailBitmap(media,
butNavLeft); butNavLeft);
} }
}); });
butNavRight.setImageDrawable(drawables.getDrawable(0)); butNavRight.setImageDrawable(drawables.getDrawable(0));
break; break;
} }
} }
} }
@Override @Override
protected void setupGUI() { protected void setupGUI() {
super.setupGUI(); super.setupGUI();
resetFragmentView(); resetFragmentView();
txtvTitle = (TextView) findViewById(R.id.txtvTitle); txtvTitle = (TextView) findViewById(R.id.txtvTitle);
txtvFeed = (TextView) findViewById(R.id.txtvFeed); txtvFeed = (TextView) findViewById(R.id.txtvFeed);
butNavLeft = (ImageButton) findViewById(R.id.butNavLeft); butNavLeft = (ImageButton) findViewById(R.id.butNavLeft);
butNavRight = (ImageButton) findViewById(R.id.butNavRight); butNavRight = (ImageButton) findViewById(R.id.butNavRight);
butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed); butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed);
butNavLeft.setOnClickListener(new OnClickListener() { butNavLeft.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (currentlyShownFragment == null
|| currentlyShownPosition == POS_DESCR) {
switchToFragment(POS_COVER);
} else if (currentlyShownPosition == POS_COVER) {
switchToFragment(POS_DESCR);
} else if (currentlyShownPosition == POS_CHAPTERS) {
switchToFragment(POS_COVER);
}
}
});
butNavRight.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (currentlyShownPosition == POS_CHAPTERS) {
switchToFragment(POS_DESCR);
} else {
switchToFragment(POS_CHAPTERS);
}
}
});
butPlaybackSpeed.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (controller != null && controller.canSetPlaybackSpeed()) { if (currentlyShownFragment == null
String[] availableSpeeds = UserPreferences || currentlyShownPosition == POS_DESCR) {
.getPlaybackSpeedArray(); switchToFragment(POS_COVER);
String currentSpeed = UserPreferences.getPlaybackSpeed(); } else if (currentlyShownPosition == POS_COVER) {
switchToFragment(POS_DESCR);
// Provide initial value in case the speed list has changed } else if (currentlyShownPosition == POS_CHAPTERS) {
// out from under us switchToFragment(POS_COVER);
// and our current speed isn't in the new list
String newSpeed;
if (availableSpeeds.length > 0) {
newSpeed = availableSpeeds[0];
} else {
newSpeed = "1.0";
}
for (int i = 0; i < availableSpeeds.length; i++) {
if (availableSpeeds[i].equals(currentSpeed)) {
if (i == availableSpeeds.length - 1) {
newSpeed = availableSpeeds[0];
} else {
newSpeed = availableSpeeds[i + 1];
}
break;
}
}
UserPreferences.setPlaybackSpeed(newSpeed);
controller.setPlaybackSpeed(Float.parseFloat(newSpeed));
} }
} }
}); });
butPlaybackSpeed.setOnLongClickListener(new OnLongClickListener() { butNavRight.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (currentlyShownPosition == POS_CHAPTERS) {
switchToFragment(POS_DESCR);
} else {
switchToFragment(POS_CHAPTERS);
}
}
});
butPlaybackSpeed.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (controller != null && controller.canSetPlaybackSpeed()) {
String[] availableSpeeds = UserPreferences
.getPlaybackSpeedArray();
String currentSpeed = UserPreferences.getPlaybackSpeed();
// Provide initial value in case the speed list has changed
// out from under us
// and our current speed isn't in the new list
String newSpeed;
if (availableSpeeds.length > 0) {
newSpeed = availableSpeeds[0];
} else {
newSpeed = "1.0";
}
for (int i = 0; i < availableSpeeds.length; i++) {
if (availableSpeeds[i].equals(currentSpeed)) {
if (i == availableSpeeds.length - 1) {
newSpeed = availableSpeeds[0];
} else {
newSpeed = availableSpeeds[i + 1];
}
break;
}
}
UserPreferences.setPlaybackSpeed(newSpeed);
controller.setPlaybackSpeed(Float.parseFloat(newSpeed));
}
}
});
butPlaybackSpeed.setOnLongClickListener(new OnLongClickListener() {
@Override @Override
public boolean onLongClick(View v) { public boolean onLongClick(View v) {
VariableSpeedDialog.showDialog(AudioplayerActivity.this); VariableSpeedDialog.showDialog(AudioplayerActivity.this);
return true; return true;
} }
}); });
} }
@Override @Override
protected void onPlaybackSpeedChange() { protected void onPlaybackSpeedChange() {
super.onPlaybackSpeedChange(); super.onPlaybackSpeedChange();
updateButPlaybackSpeed(); updateButPlaybackSpeed();
} }
private void updateButPlaybackSpeed() { private void updateButPlaybackSpeed() {
if (controller == null if (controller == null
|| (controller.getCurrentPlaybackSpeedMultiplier() == -1)) { || (controller.getCurrentPlaybackSpeedMultiplier() == -1)) {
butPlaybackSpeed.setVisibility(View.GONE); butPlaybackSpeed.setVisibility(View.GONE);
} else { } else {
butPlaybackSpeed.setVisibility(View.VISIBLE); butPlaybackSpeed.setVisibility(View.VISIBLE);
butPlaybackSpeed.setText(UserPreferences.getPlaybackSpeed()); butPlaybackSpeed.setText(UserPreferences.getPlaybackSpeed());
} }
} }
@Override @Override
protected void onPositionObserverUpdate() { protected void onPositionObserverUpdate() {
super.onPositionObserverUpdate(); super.onPositionObserverUpdate();
notifyMediaPositionChanged(); notifyMediaPositionChanged();
} }
@Override @Override
protected void loadMediaInfo() { protected boolean loadMediaInfo() {
super.loadMediaInfo(); if (!super.loadMediaInfo()) {
final Playable media = controller.getMedia(); return false;
if (media != null) { }
txtvTitle.setText(media.getEpisodeTitle()); final Playable media = controller.getMedia();
txtvFeed.setText(media.getFeedTitle()); if (media == null) {
if (media.getChapters() != null) { return false;
butNavRight.setVisibility(View.VISIBLE); }
} else { txtvTitle.setText(media.getEpisodeTitle());
butNavRight.setVisibility(View.GONE); txtvFeed.setText(media.getFeedTitle());
} if (media.getChapters() != null) {
butNavRight.setVisibility(View.VISIBLE);
} else {
butNavRight.setVisibility(View.GONE);
}
}
if (currentlyShownPosition == -1) {
if (!restoreFromPreferences()) {
switchToFragment(POS_COVER);
}
}
if (currentlyShownFragment instanceof AudioplayerContentFragment) {
((AudioplayerContentFragment) currentlyShownFragment)
.onDataSetChanged(media);
}
updateButPlaybackSpeed();
}
public void notifyMediaPositionChanged() { if (currentlyShownPosition == -1) {
if (chapterFragment != null) { if (!restoreFromPreferences()) {
ArrayAdapter<SimpleChapter> adapter = (ArrayAdapter<SimpleChapter>) chapterFragment switchToFragment(POS_COVER);
.getListAdapter(); }
adapter.notifyDataSetChanged(); }
} if (currentlyShownFragment instanceof AudioplayerContentFragment) {
} ((AudioplayerContentFragment) currentlyShownFragment)
.onDataSetChanged(media);
}
updateButPlaybackSpeed();
return true;
}
@Override public void notifyMediaPositionChanged() {
protected void onReloadNotification(int notificationCode) { if (chapterFragment != null) {
if (notificationCode == PlaybackService.EXTRA_CODE_VIDEO) { ArrayAdapter<SimpleChapter> adapter = (ArrayAdapter<SimpleChapter>) chapterFragment
if (AppConfig.DEBUG) .getListAdapter();
Log.d(TAG, adapter.notifyDataSetChanged();
"ReloadNotification received, switching to Videoplayer now"); }
startActivity(new Intent(this, VideoplayerActivity.class)); }
} @Override
} protected void onReloadNotification(int notificationCode) {
if (notificationCode == PlaybackService.EXTRA_CODE_VIDEO) {
if (AppConfig.DEBUG)
Log.d(TAG,
"ReloadNotification received, switching to Videoplayer now");
startActivity(new Intent(this, VideoplayerActivity.class));
@Override }
protected void onBufferStart() { }
postStatusMsg(R.string.player_buffering_msg);
}
@Override @Override
protected void onBufferEnd() { protected void onBufferStart() {
clearStatusMsg(); postStatusMsg(R.string.player_buffering_msg);
} }
public interface AudioplayerContentFragment { @Override
public void onDataSetChanged(Playable media); protected void onBufferEnd() {
} clearStatusMsg();
}
@Override public interface AudioplayerContentFragment {
protected int getContentViewResourceId() { public void onDataSetChanged(Playable media);
return R.layout.audioplayer_activity; }
}
@Override
protected int getContentViewResourceId() {
return R.layout.audioplayer_activity;
}
} }

View File

@ -106,8 +106,8 @@ public abstract class MediaplayerActivity extends ActionBarActivity
} }
@Override @Override
public void loadMediaInfo() { public boolean loadMediaInfo() {
MediaplayerActivity.this.loadMediaInfo(); return MediaplayerActivity.this.loadMediaInfo();
} }
@Override @Override
@ -339,8 +339,9 @@ public abstract class MediaplayerActivity extends ActionBarActivity
} }
/** /**
* Called by 'handleStatus()' when the PlaybackService is in the * Called by 'handleStatus()' when the PlaybackService is waiting for
* AWAITING_VIDEO_SURFACE state. * a video surface.
*
*/ */
protected abstract void onAwaitingVideoSurface(); protected abstract void onAwaitingVideoSurface();
@ -380,7 +381,7 @@ public abstract class MediaplayerActivity extends ActionBarActivity
* to the PlaybackService to ensure that the activity has the right * to the PlaybackService to ensure that the activity has the right
* FeedMedia object. * FeedMedia object.
*/ */
protected void loadMediaInfo() { protected boolean loadMediaInfo() {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Loading media info"); Log.d(TAG, "Loading media info");
Playable media = controller.getMedia(); Playable media = controller.getMedia();
@ -395,7 +396,10 @@ public abstract class MediaplayerActivity extends ActionBarActivity
/ media.getDuration(); / media.getDuration();
sbPosition.setProgress((int) (progress * sbPosition.getMax())); sbPosition.setProgress((int) (progress * sbPosition.getMax()));
} }
} return true;
} else {
return false;
}
} }
protected void setupGUI() { protected void setupGUI() {

View File

@ -11,7 +11,6 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.SeekBar; import android.widget.SeekBar;
import android.widget.VideoView; import android.widget.VideoView;
import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.feed.MediaType; import de.danoeh.antennapod.feed.MediaType;
@ -21,270 +20,283 @@ import de.danoeh.antennapod.service.playback.PlayerStatus;
import de.danoeh.antennapod.util.playback.ExternalMedia; import de.danoeh.antennapod.util.playback.ExternalMedia;
import de.danoeh.antennapod.util.playback.Playable; import de.danoeh.antennapod.util.playback.Playable;
/** Activity for playing audio files. */ /**
public class VideoplayerActivity extends MediaplayerActivity implements * Activity for playing audio files.
SurfaceHolder.Callback { */
private static final String TAG = "VideoplayerActivity"; public class VideoplayerActivity extends MediaplayerActivity {
private static final String TAG = "VideoplayerActivity";
/** True if video controls are currently visible. */ /**
private boolean videoControlsShowing = true; * True if video controls are currently visible.
private boolean videoSurfaceCreated = false; */
private VideoControlsHider videoControlsToggler; private boolean videoControlsShowing = true;
private boolean videoSurfaceCreated = false;
private VideoControlsHider videoControlsToggler;
private LinearLayout videoOverlay; private LinearLayout videoOverlay;
private VideoView videoview; private VideoView videoview;
private ProgressBar progressIndicator; private ProgressBar progressIndicator;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
setTheme(UserPreferences.getTheme()); setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@Override @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
if (videoControlsToggler != null) { if (videoControlsToggler != null) {
videoControlsToggler.cancel(true); videoControlsToggler.cancel(true);
} }
} }
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
if (getIntent().getAction() != null if (getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_VIEW)) { && getIntent().getAction().equals(Intent.ACTION_VIEW)) {
Intent intent = getIntent(); Intent intent = getIntent();
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Received VIEW intent: " Log.d(TAG, "Received VIEW intent: "
+ intent.getData().getPath()); + intent.getData().getPath());
ExternalMedia media = new ExternalMedia(intent.getData().getPath(), ExternalMedia media = new ExternalMedia(intent.getData().getPath(),
MediaType.VIDEO); MediaType.VIDEO);
Intent launchIntent = new Intent(this, PlaybackService.class); Intent launchIntent = new Intent(this, PlaybackService.class);
launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media); launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED, launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
true); true);
launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false); launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false);
launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY, launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
true); true);
startService(launchIntent); startService(launchIntent);
} }
} }
@Override @Override
protected void loadMediaInfo() { protected boolean loadMediaInfo() {
super.loadMediaInfo(); if (!super.loadMediaInfo()) {
Playable media = controller.getMedia(); return false;
if (media != null) { }
getSupportActionBar().setSubtitle(media.getEpisodeTitle()); Playable media = controller.getMedia();
getSupportActionBar().setTitle(media.getFeedTitle()); if (media != null) {
} getSupportActionBar().setSubtitle(media.getEpisodeTitle());
} getSupportActionBar().setTitle(media.getFeedTitle());
return true;
}
@Override return false;
protected void setupGUI() { }
super.setupGUI();
videoOverlay = (LinearLayout) findViewById(R.id.overlay);
videoview = (VideoView) findViewById(R.id.videoview);
progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator);
videoview.getHolder().addCallback(this);
videoview.setOnTouchListener(onVideoviewTouched);
setupVideoControlsToggler(); @Override
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, protected void setupGUI() {
WindowManager.LayoutParams.FLAG_FULLSCREEN); super.setupGUI();
} videoOverlay = (LinearLayout) findViewById(R.id.overlay);
videoview = (VideoView) findViewById(R.id.videoview);
progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator);
videoview.getHolder().addCallback(surfaceHolderCallback);
videoview.setOnTouchListener(onVideoviewTouched);
@Override setupVideoControlsToggler();
protected void onAwaitingVideoSurface() { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
if (videoSurfaceCreated) { WindowManager.LayoutParams.FLAG_FULLSCREEN);
if (AppConfig.DEBUG) }
Log.d(TAG,
"Videosurface already created, setting videosurface now");
controller.setVideoSurface(videoview.getHolder());
}
}
@Override @Override
protected void postStatusMsg(int resId) { protected void onAwaitingVideoSurface() {
if (resId == R.string.player_preparing_msg) { if (videoSurfaceCreated) {
progressIndicator.setVisibility(View.VISIBLE); if (AppConfig.DEBUG)
} else { Log.d(TAG,
progressIndicator.setVisibility(View.INVISIBLE); "Videosurface already created, setting videosurface now");
} controller.setVideoSurface(videoview.getHolder());
}
}
} @Override
protected void postStatusMsg(int resId) {
if (resId == R.string.player_preparing_msg) {
progressIndicator.setVisibility(View.VISIBLE);
} else {
progressIndicator.setVisibility(View.INVISIBLE);
}
@Override }
protected void clearStatusMsg() {
progressIndicator.setVisibility(View.INVISIBLE);
}
View.OnTouchListener onVideoviewTouched = new View.OnTouchListener() { @Override
protected void clearStatusMsg() {
progressIndicator.setVisibility(View.INVISIBLE);
}
@Override View.OnTouchListener onVideoviewTouched = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (videoControlsToggler != null) {
videoControlsToggler.cancel(true);
}
toggleVideoControlsVisibility();
if (videoControlsShowing) {
setupVideoControlsToggler();
}
return true; @Override
} else { public boolean onTouch(View v, MotionEvent event) {
return false; if (event.getAction() == MotionEvent.ACTION_DOWN) {
} if (videoControlsToggler != null) {
} videoControlsToggler.cancel(true);
}; }
toggleVideoControlsVisibility();
if (videoControlsShowing) {
setupVideoControlsToggler();
}
@SuppressLint("NewApi") return true;
void setupVideoControlsToggler() { } else {
if (videoControlsToggler != null) { return false;
videoControlsToggler.cancel(true); }
} }
videoControlsToggler = new VideoControlsHider(); };
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
videoControlsToggler
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
videoControlsToggler.execute();
}
}
private void toggleVideoControlsVisibility() { @SuppressLint("NewApi")
if (videoControlsShowing) { void setupVideoControlsToggler() {
getSupportActionBar().hide(); if (videoControlsToggler != null) {
hideVideoControls(); videoControlsToggler.cancel(true);
} else { }
getSupportActionBar().show(); videoControlsToggler = new VideoControlsHider();
showVideoControls(); if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
} videoControlsToggler
videoControlsShowing = !videoControlsShowing; .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} } else {
videoControlsToggler.execute();
}
}
/** Hides the videocontrols after a certain period of time. */ private void toggleVideoControlsVisibility() {
public class VideoControlsHider extends AsyncTask<Void, Void, Void> { if (videoControlsShowing) {
@Override getSupportActionBar().hide();
protected void onCancelled() { hideVideoControls();
videoControlsToggler = null; } else {
} getSupportActionBar().show();
showVideoControls();
}
videoControlsShowing = !videoControlsShowing;
}
@Override /**
protected void onPostExecute(Void result) { * Hides the videocontrols after a certain period of time.
videoControlsToggler = null; */
} public class VideoControlsHider extends AsyncTask<Void, Void, Void> {
@Override
protected void onCancelled() {
videoControlsToggler = null;
}
private static final int WAITING_INTERVALL = 5000; @Override
private static final String TAG = "VideoControlsToggler"; protected void onPostExecute(Void result) {
videoControlsToggler = null;
}
@Override private static final int WAITING_INTERVALL = 5000;
protected void onProgressUpdate(Void... values) { private static final String TAG = "VideoControlsToggler";
if (videoControlsShowing) {
if (AppConfig.DEBUG)
Log.d(TAG, "Hiding video controls");
getSupportActionBar().hide();
hideVideoControls();
videoControlsShowing = false;
}
}
@Override @Override
protected Void doInBackground(Void... params) { protected void onProgressUpdate(Void... values) {
try { if (videoControlsShowing) {
Thread.sleep(WAITING_INTERVALL); if (AppConfig.DEBUG)
} catch (InterruptedException e) { Log.d(TAG, "Hiding video controls");
return null; getSupportActionBar().hide();
} hideVideoControls();
publishProgress(); videoControlsShowing = false;
return null; }
} }
} @Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(WAITING_INTERVALL);
} catch (InterruptedException e) {
return null;
}
publishProgress();
return null;
}
@Override }
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
holder.setFixedSize(width, height);
}
@Override private final SurfaceHolder.Callback surfaceHolderCallback = new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) { @Override
if (AppConfig.DEBUG) public void surfaceChanged(SurfaceHolder holder, int format, int width,
Log.d(TAG, "Videoview holder created"); int height) {
videoSurfaceCreated = true; holder.setFixedSize(width, height);
if (controller.getStatus() == PlayerStatus.AWAITING_VIDEO_SURFACE) { }
if (controller.serviceAvailable()) {
controller.setVideoSurface(holder);
} else {
Log.e(TAG,
"Could'nt attach surface to mediaplayer - reference to service was null");
}
}
} @Override
public void surfaceCreated(SurfaceHolder holder) {
if (AppConfig.DEBUG)
Log.d(TAG, "Videoview holder created");
videoSurfaceCreated = true;
if (controller.getStatus() == PlayerStatus.PLAYING) {
if (controller.serviceAvailable()) {
controller.setVideoSurface(holder);
} else {
Log.e(TAG,
"Could'nt attach surface to mediaplayer - reference to service was null");
}
}
@Override }
public void surfaceDestroyed(SurfaceHolder holder) {
if (AppConfig.DEBUG)
Log.d(TAG, "Videosurface was destroyed");
videoSurfaceCreated = false;
controller.notifyVideoSurfaceAbandoned();
}
@Override @Override
protected void onReloadNotification(int notificationCode) { public void surfaceDestroyed(SurfaceHolder holder) {
if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) { if (AppConfig.DEBUG)
if (AppConfig.DEBUG) Log.d(TAG, "Videosurface was destroyed");
Log.d(TAG, videoSurfaceCreated = false;
"ReloadNotification received, switching to Audioplayer now"); controller.notifyVideoSurfaceAbandoned();
startActivity(new Intent(this, AudioplayerActivity.class)); }
} };
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
super.onStartTrackingTouch(seekBar);
if (videoControlsToggler != null) {
videoControlsToggler.cancel(true);
}
}
@Override @Override
public void onStopTrackingTouch(SeekBar seekBar) { protected void onReloadNotification(int notificationCode) {
super.onStopTrackingTouch(seekBar); if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) {
setupVideoControlsToggler(); if (AppConfig.DEBUG)
} Log.d(TAG,
"ReloadNotification received, switching to Audioplayer now");
startActivity(new Intent(this, AudioplayerActivity.class));
}
}
@Override @Override
protected void onBufferStart() { public void onStartTrackingTouch(SeekBar seekBar) {
progressIndicator.setVisibility(View.VISIBLE); super.onStartTrackingTouch(seekBar);
} if (videoControlsToggler != null) {
videoControlsToggler.cancel(true);
}
}
@Override @Override
protected void onBufferEnd() { public void onStopTrackingTouch(SeekBar seekBar) {
progressIndicator.setVisibility(View.INVISIBLE); super.onStopTrackingTouch(seekBar);
} setupVideoControlsToggler();
}
private void showVideoControls() { @Override
videoOverlay.setVisibility(View.VISIBLE); protected void onBufferStart() {
videoOverlay.startAnimation(AnimationUtils.loadAnimation(this, progressIndicator.setVisibility(View.VISIBLE);
R.anim.fade_in)); }
}
private void hideVideoControls() { @Override
videoOverlay.startAnimation(AnimationUtils.loadAnimation(this, protected void onBufferEnd() {
R.anim.fade_out)); progressIndicator.setVisibility(View.INVISIBLE);
videoOverlay.setVisibility(View.GONE); }
}
@Override private void showVideoControls() {
protected int getContentViewResourceId() { videoOverlay.setVisibility(View.VISIBLE);
return R.layout.videoplayer_activity; videoOverlay.startAnimation(AnimationUtils.loadAnimation(this,
} R.anim.fade_in));
}
private void hideVideoControls() {
videoOverlay.startAnimation(AnimationUtils.loadAnimation(this,
R.anim.fade_out));
videoOverlay.setVisibility(View.GONE);
}
@Override
protected int getContentViewResourceId() {
return R.layout.videoplayer_activity;
}
} }

View File

@ -137,10 +137,12 @@ public class ExternalPlayerFragment extends Fragment {
} }
@Override @Override
public void loadMediaInfo() { public boolean loadMediaInfo() {
ExternalPlayerFragment fragment = ExternalPlayerFragment.this; ExternalPlayerFragment fragment = ExternalPlayerFragment.this;
if (fragment != null) { if (fragment != null) {
fragment.loadMediaInfo(); return fragment.loadMediaInfo();
} else {
return false;
} }
} }
@ -209,7 +211,7 @@ public class ExternalPlayerFragment extends Fragment {
} }
} }
private void loadMediaInfo() { private boolean loadMediaInfo() {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Loading media info"); Log.d(TAG, "Loading media info");
if (controller.serviceAvailable()) { if (controller.serviceAvailable()) {
@ -230,13 +232,16 @@ public class ExternalPlayerFragment extends Fragment {
} else { } else {
butPlay.setVisibility(View.VISIBLE); butPlay.setVisibility(View.VISIBLE);
} }
return true;
} else { } else {
Log.w(TAG, Log.w(TAG,
"loadMediaInfo was called while the media object of playbackService was null!"); "loadMediaInfo was called while the media object of playbackService was null!");
return false;
} }
} else { } else {
Log.w(TAG, Log.w(TAG,
"loadMediaInfo was called while playbackService was null!"); "loadMediaInfo was called while playbackService was null!");
return false;
} }
} }

View File

@ -14,6 +14,7 @@ import android.media.RemoteControlClient;
import android.media.RemoteControlClient.MetadataEditor; import android.media.RemoteControlClient.MetadataEditor;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Binder; import android.os.Binder;
import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
@ -133,8 +134,6 @@ public class PlaybackService extends Service {
private final IBinder mBinder = new LocalBinder(); private final IBinder mBinder = new LocalBinder();
private volatile List<FeedItem> queue;
public class LocalBinder extends Binder { public class LocalBinder extends Binder {
public PlaybackService getService() { public PlaybackService getService() {
return PlaybackService.this; return PlaybackService.this;
@ -322,6 +321,7 @@ public class PlaybackService extends Service {
} }
public void notifyVideoSurfaceAbandoned() { public void notifyVideoSurfaceAbandoned() {
stopForeground(true);
mediaPlayer.resetVideoSurface(); mediaPlayer.resetVideoSurface();
} }
@ -352,6 +352,7 @@ public class PlaybackService extends Service {
private final PlaybackServiceMediaPlayer.PSMPCallback mediaPlayerCallback = new PlaybackServiceMediaPlayer.PSMPCallback() { private final PlaybackServiceMediaPlayer.PSMPCallback mediaPlayerCallback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override @Override
public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) { public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
currentMediaType = mediaPlayer.getCurrentMediaType();
switch (newInfo.playerStatus) { switch (newInfo.playerStatus) {
case PREPARED: case PREPARED:
taskManager.startChapterLoader(newInfo.playable); taskManager.startChapterLoader(newInfo.playable);
@ -365,8 +366,8 @@ public class PlaybackService extends Service {
break; break;
case STOPPED: case STOPPED:
setCurrentlyPlayingMedia(PlaybackPreferences.NO_MEDIA_PLAYING); //setCurrentlyPlayingMedia(PlaybackPreferences.NO_MEDIA_PLAYING);
stopSelf(); //stopSelf();
break; break;
case PLAYING: case PLAYING:
@ -375,7 +376,6 @@ public class PlaybackService extends Service {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Resuming/Starting playback"); Log.d(TAG, "Resuming/Starting playback");
currentMediaType = mediaPlayer.getCurrentMediaType();
writePlaybackPreferences(); writePlaybackPreferences();
taskManager.startPositionSaver(); taskManager.startPositionSaver();
taskManager.startWidgetUpdater(); taskManager.startWidgetUpdater();
@ -463,16 +463,19 @@ public class PlaybackService extends Service {
if (media instanceof FeedMedia) { if (media instanceof FeedMedia) {
FeedItem item = ((FeedMedia) media).getItem(); FeedItem item = ((FeedMedia) media).getItem();
DBWriter.markItemRead(PlaybackService.this, item, true, true); DBWriter.markItemRead(PlaybackService.this, item, true, true);
nextItem = DBTasks.getQueueSuccessorOfItem(this, item.getId(), queue);
isInQueue = QueueAccess.ItemListAccess(queue).contains(((FeedMedia) media).getItem().getId()); try {
final List<FeedItem> queue = taskManager.getQueue();
isInQueue = QueueAccess.ItemListAccess(queue).contains(((FeedMedia) media).getItem().getId());
nextItem = DBTasks.getQueueSuccessorOfItem(this, item.getId(), queue);
} catch (InterruptedException e) {
e.printStackTrace();
// isInQueue remains false
}
if (isInQueue) { if (isInQueue) {
DBWriter.removeQueueItem(PlaybackService.this, item.getId(), true); DBWriter.removeQueueItem(PlaybackService.this, item.getId(), true);
} }
DBWriter.addItemToPlaybackHistory(PlaybackService.this, (FeedMedia) media); DBWriter.addItemToPlaybackHistory(PlaybackService.this, (FeedMedia) media);
long autoDeleteMediaId = ((FeedComponent) media).getId();
if (mediaPlayer.isStreaming()) {
autoDeleteMediaId = -1;
}
} }
// Load next episode if previous episode was in the queue and if there // Load next episode if previous episode was in the queue and if there
@ -514,7 +517,7 @@ public class PlaybackService extends Service {
notificationCode); notificationCode);
} else { } else {
sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0); sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0);
stopSelf(); //stopSelf();
} }
} }
@ -713,8 +716,6 @@ public class PlaybackService extends Service {
} }
private void updateWidget() { private void updateWidget() {
if (AppConfig.DEBUG)
Log.d(TAG, "Sending widget update request");
PlaybackService.this.sendBroadcast(new Intent( PlaybackService.this.sendBroadcast(new Intent(
PlayerWidget.FORCE_WIDGET_UPDATE)); PlayerWidget.FORCE_WIDGET_UPDATE));
} }
@ -729,6 +730,10 @@ public class PlaybackService extends Service {
@SuppressLint("NewApi") @SuppressLint("NewApi")
private RemoteControlClient setupRemoteControlClient() { private RemoteControlClient setupRemoteControlClient() {
if (Build.VERSION.SDK_INT < 14) {
return null;
}
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setComponent(new ComponentName(getPackageName(), mediaButtonIntent.setComponent(new ComponentName(getPackageName(),
MediaButtonReceiver.class.getName())); MediaButtonReceiver.class.getName()));
@ -806,6 +811,7 @@ public class PlaybackService extends Service {
i.putExtra("album", info.playable.getFeedTitle()); i.putExtra("album", info.playable.getFeedTitle());
i.putExtra("track", info.playable.getEpisodeTitle()); i.putExtra("track", info.playable.getEpisodeTitle());
i.putExtra("playing", isPlaying); i.putExtra("playing", isPlaying);
final List<FeedItem> queue = taskManager.getQueueIfLoaded();
if (queue != null) { if (queue != null) {
i.putExtra("ListSize", queue.size()); i.putExtra("ListSize", queue.size());
} }
@ -896,6 +902,10 @@ public class PlaybackService extends Service {
mediaPlayer.resume(); mediaPlayer.resume();
} }
public void prepare() {
mediaPlayer.prepare();
}
public void pause(boolean abandonAudioFocus, boolean reinit) { public void pause(boolean abandonAudioFocus, boolean reinit) {
mediaPlayer.pause(abandonAudioFocus, reinit); mediaPlayer.pause(abandonAudioFocus, reinit);
} }
@ -904,6 +914,10 @@ public class PlaybackService extends Service {
mediaPlayer.reinit(); mediaPlayer.reinit();
} }
public PlaybackServiceMediaPlayer.PSMPInfo getPSMPInfo() {
return mediaPlayer.getPSMPInfo();
}
public PlayerStatus getStatus() { public PlayerStatus getStatus() {
return mediaPlayer.getPSMPInfo().playerStatus; return mediaPlayer.getPSMPInfo().playerStatus;
} }

View File

@ -144,15 +144,16 @@ public class PlaybackServiceMediaPlayer {
return; return;
} else { } else {
// stop playback of this episode // stop playback of this episode
setPlayerStatus(PlayerStatus.STOPPED, null);
if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PLAYING || playerStatus == PlayerStatus.PREPARED) { if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PLAYING || playerStatus == PlayerStatus.PREPARED) {
mediaPlayer.stop(); mediaPlayer.stop();
} }
setPlayerStatus(PlayerStatus.INDETERMINATE, null);
} }
} }
createMediaPlayer(); createMediaPlayer();
this.media = playable; this.media = playable;
this.stream = stream; this.stream = stream;
this.mediaType = media.getMediaType();
PlaybackServiceMediaPlayer.this.startWhenPrepared.set(startWhenPrepared); PlaybackServiceMediaPlayer.this.startWhenPrepared.set(startWhenPrepared);
setPlayerStatus(PlayerStatus.INITIALIZING, media); setPlayerStatus(PlayerStatus.INITIALIZING, media);
try { try {
@ -372,8 +373,8 @@ public class PlaybackServiceMediaPlayer {
|| playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PAUSED
|| playerStatus == PlayerStatus.PREPARED) { || playerStatus == PlayerStatus.PREPARED) {
if (stream) { if (stream) {
statusBeforeSeeking = playerStatus; // statusBeforeSeeking = playerStatus;
setPlayerStatus(PlayerStatus.SEEKING, media); // setPlayerStatus(PlayerStatus.SEEKING, media);
} }
mediaPlayer.seekTo(t); mediaPlayer.seekTo(t);
@ -505,9 +506,8 @@ public class PlaybackServiceMediaPlayer {
private void setSpeedSync(float speed) { private void setSpeedSync(float speed) {
playerLock.lock(); playerLock.lock();
if (media != null && media.getMediaType() == MediaType.AUDIO) { if (media != null && media.getMediaType() == MediaType.AUDIO) {
AudioPlayer audioPlayer = (AudioPlayer) mediaPlayer; if (mediaPlayer.canSetSpeed()) {
if (audioPlayer.canSetSpeed()) { mediaPlayer.setPlaybackSpeed((float) speed);
audioPlayer.setPlaybackSpeed((float) speed);
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Playback speed was set to " + speed); Log.d(TAG, "Playback speed was set to " + speed);
callback.playbackSpeedChanged(speed); callback.playbackSpeedChanged(speed);

View File

@ -102,6 +102,23 @@ public class PlaybackServiceTaskManager {
} }
} }
/**
* Returns the queue if it is already loaded or null if it hasn't been loaded yet.
* In order to wait until the queue has been loaded, use getQueue()
*/
public synchronized List<FeedItem> getQueueIfLoaded() {
if (queueFuture.isDone()) {
try {
return queueFuture.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return null;
}
/** /**
* Returns the queue or waits until the PSTM has loaded the queue from the database. * Returns the queue or waits until the PSTM has loaded the queue from the database.
*/ */

View File

@ -1,14 +1,14 @@
package de.danoeh.antennapod.service.playback; package de.danoeh.antennapod.service.playback;
public enum PlayerStatus { public enum PlayerStatus {
INDETERMINATE, // player is currently changing its state, listeners should wait until the player has left this state.
ERROR, ERROR,
PREPARING, PREPARING,
PAUSED, PAUSED,
PLAYING, PLAYING,
STOPPED, STOPPED,
PREPARED, PREPARED,
SEEKING, 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 INITIALIZING, // playback service is loading the Playable's metadata
INITIALIZED // playback service was started, data source of media player was set. INITIALIZED // playback service was started, data source of media player was set.
} }

View File

@ -72,9 +72,11 @@ public class PlayerWidgetService extends Service {
} }
private void updateViews() { private void updateViews() {
if (playbackService == null) {
return;
}
isUpdating = true; isUpdating = true;
if (AppConfig.DEBUG)
Log.d(TAG, "Updating widget views");
ComponentName playerWidget = new ComponentName(this, PlayerWidget.class); ComponentName playerWidget = new ComponentName(this, PlayerWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this); AppWidgetManager manager = AppWidgetManager.getInstance(this);
RemoteViews views = new RemoteViews(getPackageName(), RemoteViews views = new RemoteViews(getPackageName(),
@ -101,8 +103,6 @@ public class PlayerWidgetService extends Service {
views.setOnClickPendingIntent(R.id.butPlay, views.setOnClickPendingIntent(R.id.butPlay,
createMediaButtonIntent()); createMediaButtonIntent());
} else { } else {
if (AppConfig.DEBUG)
Log.d(TAG, "No media playing. Displaying defaultt views");
views.setViewVisibility(R.id.txtvProgress, View.INVISIBLE); views.setViewVisibility(R.id.txtvProgress, View.INVISIBLE);
views.setTextViewText(R.id.txtvTitle, views.setTextViewText(R.id.txtvTitle,
this.getString(R.string.no_media_playing_label)); this.getString(R.string.no_media_playing_label));

View File

@ -33,6 +33,7 @@ import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.feed.MediaType; import de.danoeh.antennapod.feed.MediaType;
import de.danoeh.antennapod.preferences.PlaybackPreferences; import de.danoeh.antennapod.preferences.PlaybackPreferences;
import de.danoeh.antennapod.service.playback.PlaybackService; import de.danoeh.antennapod.service.playback.PlaybackService;
import de.danoeh.antennapod.service.playback.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.service.playback.PlayerStatus; import de.danoeh.antennapod.service.playback.PlayerStatus;
import de.danoeh.antennapod.storage.DBTasks; import de.danoeh.antennapod.storage.DBTasks;
import de.danoeh.antennapod.util.Converter; import de.danoeh.antennapod.util.Converter;
@ -48,7 +49,7 @@ public abstract class PlaybackController {
public static final int DEFAULT_SEEK_DELTA = 30000; public static final int DEFAULT_SEEK_DELTA = 30000;
public static final int INVALID_TIME = -1; public static final int INVALID_TIME = -1;
private Activity activity; private final Activity activity;
private PlaybackService playbackService; private PlaybackService playbackService;
private Playable media; private Playable media;
@ -70,6 +71,8 @@ public abstract class PlaybackController {
private boolean reinitOnPause; private boolean reinitOnPause;
public PlaybackController(Activity activity, boolean reinitOnPause) { public PlaybackController(Activity activity, boolean reinitOnPause) {
if (activity == null)
throw new IllegalArgumentException("activity = null");
this.activity = activity; this.activity = activity;
this.reinitOnPause = reinitOnPause; this.reinitOnPause = reinitOnPause;
schedExecutor = new ScheduledThreadPoolExecutor(SCHED_EX_POOLSIZE, schedExecutor = new ScheduledThreadPoolExecutor(SCHED_EX_POOLSIZE,
@ -298,7 +301,9 @@ public abstract class PlaybackController {
if (AppConfig.DEBUG) if (AppConfig.DEBUG)
Log.d(TAG, "Received statusUpdate Intent."); Log.d(TAG, "Received statusUpdate Intent.");
if (isConnectedToPlaybackService()) { if (isConnectedToPlaybackService()) {
status = playbackService.getStatus(); PlaybackServiceMediaPlayer.PSMPInfo info = playbackService.getPSMPInfo();
status = info.playerStatus;
media = info.playable;
handleStatus(); handleStatus();
} else { } else {
Log.w(TAG, Log.w(TAG,
@ -422,6 +427,9 @@ public abstract class PlaybackController {
case PLAYING: case PLAYING:
clearStatusMsg(); clearStatusMsg();
checkMediaInfoLoaded(); checkMediaInfoLoaded();
if (PlaybackService.getCurrentMediaType() == MediaType.VIDEO) {
onAwaitingVideoSurface();
}
setupPositionObserver(); setupPositionObserver();
updatePlayButtonAppearance(pauseResource); updatePlayButtonAppearance(pauseResource);
break; break;
@ -447,9 +455,6 @@ public abstract class PlaybackController {
case SEEKING: case SEEKING:
postStatusMsg(R.string.player_seeking_msg); postStatusMsg(R.string.player_seeking_msg);
break; break;
case AWAITING_VIDEO_SURFACE:
onAwaitingVideoSurface();
break;
case INITIALIZED: case INITIALIZED:
checkMediaInfoLoaded(); checkMediaInfoLoaded();
clearStatusMsg(); clearStatusMsg();
@ -459,10 +464,7 @@ public abstract class PlaybackController {
} }
private void checkMediaInfoLoaded() { private void checkMediaInfoLoaded() {
if (!mediaInfoLoaded) { mediaInfoLoaded = (mediaInfoLoaded || loadMediaInfo());
loadMediaInfo();
}
mediaInfoLoaded = true;
} }
private void updatePlayButtonAppearance(int resource) { private void updatePlayButtonAppearance(int resource) {
@ -476,7 +478,7 @@ public abstract class PlaybackController {
public abstract void clearStatusMsg(); public abstract void clearStatusMsg();
public abstract void loadMediaInfo(); public abstract boolean loadMediaInfo();
public abstract void onAwaitingVideoSurface(); public abstract void onAwaitingVideoSurface();
@ -490,6 +492,7 @@ public abstract class PlaybackController {
if (playbackService != null) { if (playbackService != null) {
status = playbackService.getStatus(); status = playbackService.getStatus();
media = playbackService.getPlayable(); media = playbackService.getPlayable();
/*
if (media == null) { if (media == null) {
Log.w(TAG, Log.w(TAG,
"PlaybackService has no media object. Trying to restore last played media."); "PlaybackService has no media object. Trying to restore last played media.");
@ -498,6 +501,7 @@ public abstract class PlaybackController {
activity.startService(serviceIntent); activity.startService(serviceIntent);
} }
} }
*/
onServiceQueried(); onServiceQueried();
setupGUI(); setupGUI();
@ -570,7 +574,7 @@ public abstract class PlaybackController {
break; break;
case INITIALIZED: case INITIALIZED:
playbackService.setStartWhenPrepared(true); playbackService.setStartWhenPrepared(true);
playbackService.resume(); playbackService.prepare();
break; break;
} }
} else { } else {

View File

@ -82,7 +82,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
case INITIALIZED: case INITIALIZED:
case INITIALIZING: case INITIALIZING:
case SEEKING: case SEEKING:
case AWAITING_VIDEO_SURFACE:
assertNotNull(info.playable); assertNotNull(info.playable);
break; break;
case STOPPED: case STOPPED: