Make prev/next headset buttons configurable

Also changes behavior of A13+ player notification buttons.

Fixes #7880 and improves #9764
This commit is contained in:
dvalter 2024-05-06 21:36:32 +00:00
parent 879d7a24f0
commit e59f934903
6 changed files with 107 additions and 3 deletions

View File

@ -176,6 +176,10 @@ public final class Player implements PlaybackListener, Listener {
public static final int RENDERER_UNAVAILABLE = -1;
private static final String PICASSO_PLAYER_THUMBNAIL_TAG = "PICASSO_PLAYER_THUMBNAIL_TAG";
public static final int DEFAULT_PREV_NEXT_MODE = 0;
public static final int SMART_PREV_NEXT_MODE = 1;
public static final int SEEK_PREV_NEXT_MODE = 2;
/*//////////////////////////////////////////////////////////////////////////
// Playback
//////////////////////////////////////////////////////////////////////////*/
@ -222,6 +226,8 @@ public final class Player implements PlaybackListener, Listener {
private PlayerType playerType = PlayerType.MAIN;
private int currentState = STATE_PREFLIGHT;
private int queueActionsArePrevNext = DEFAULT_PREV_NEXT_MODE;
// audio only mode does not mean that player type is background, but that the player was
// minimized to background but will resume automatically to the original player type
private boolean isAudioOnly = false;
@ -1719,6 +1725,40 @@ public final class Player implements PlaybackListener, Listener {
seekBy(-retrieveSeekDurationFromPreferences(this));
triggerProgressUpdate();
}
public void playerActionNext() {
switch (queueActionsArePrevNext) {
case SMART_PREV_NEXT_MODE:
if (playQueue != null && playQueue.size() > 1) {
playNext();
} else {
fastForward();
}
break;
case SEEK_PREV_NEXT_MODE:
fastForward();
break;
default:
playNext();
}
}
public void playerActionPrevious() {
switch (queueActionsArePrevNext) {
case SMART_PREV_NEXT_MODE:
if (playQueue != null && playQueue.size() > 1) {
playPrevious();
} else {
fastRewind();
}
break;
case SEEK_PREV_NEXT_MODE:
fastRewind();
break;
default:
playPrevious();
}
}
//endregion
@ -2237,6 +2277,9 @@ public final class Player implements PlaybackListener, Listener {
reloadPlayQueueManager();
}
public void setQueueActionsPrevNext(final int state) {
queueActionsArePrevNext = state;
}
@NonNull
public Context getContext() {

View File

@ -42,6 +42,13 @@ public class MediaSessionPlayerUi extends PlayerUi
private MediaSessionConnector sessionConnector;
private final String ignoreHardwareMediaButtonsKey;
private final String prevNextButtonModeKey;
private final String smartModeKey;
private final String fwRwModeKey;
private boolean shouldIgnoreHardwareMediaButtons = false;
// used to check whether any notification action changed, before sending costly updates
@ -52,6 +59,9 @@ public class MediaSessionPlayerUi extends PlayerUi
super(player);
ignoreHardwareMediaButtonsKey =
context.getString(R.string.ignore_hardware_media_buttons_key);
prevNextButtonModeKey = context.getString(R.string.prev_next_button_mode_key);
smartModeKey = context.getString(R.string.prev_next_mode_smart_key);
fwRwModeKey = context.getString(R.string.prev_next_mode_seek_key);
}
@Override
@ -73,6 +83,7 @@ public class MediaSessionPlayerUi extends PlayerUi
// listen to changes to ignore_hardware_media_buttons_key
updateShouldIgnoreHardwareMediaButtons(player.getPrefs());
updatePrevNextMode(player.getPrefs());
player.getPrefs().registerOnSharedPreferenceChangeListener(this);
sessionConnector.setMetadataDeduplicationEnabled(true);
@ -114,8 +125,14 @@ public class MediaSessionPlayerUi extends PlayerUi
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences,
final String key) {
if (key == null || key.equals(ignoreHardwareMediaButtonsKey)) {
if (key == null) {
updateShouldIgnoreHardwareMediaButtons(sharedPreferences);
updatePrevNextMode(sharedPreferences);
} else if (key.equals(ignoreHardwareMediaButtonsKey)) {
updateShouldIgnoreHardwareMediaButtons(sharedPreferences);
} else if (key.equals(prevNextButtonModeKey)) {
updatePrevNextMode(sharedPreferences);
}
}
@ -124,6 +141,18 @@ public class MediaSessionPlayerUi extends PlayerUi
sharedPreferences.getBoolean(ignoreHardwareMediaButtonsKey, false);
}
public void updatePrevNextMode(final SharedPreferences sharedPreferences) {
final var modeString = sharedPreferences.getString(prevNextButtonModeKey, "");
int prevNextButtonMode = Player.DEFAULT_PREV_NEXT_MODE;
if (modeString.equals(smartModeKey)) {
prevNextButtonMode = Player.SMART_PREV_NEXT_MODE;
} else if (modeString.equals(fwRwModeKey)) {
prevNextButtonMode = Player.SEEK_PREV_NEXT_MODE;
}
player.setQueueActionsPrevNext(prevNextButtonMode);
}
public void handleMediaButtonIntent(final Intent intent) {
MediaButtonReceiver.handleIntent(mediaSession, intent);

View File

@ -73,7 +73,7 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator
@Override
public void onSkipToPrevious(@NonNull final com.google.android.exoplayer2.Player exoPlayer) {
player.playPrevious();
player.playerActionPrevious();
}
@Override
@ -86,7 +86,7 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator
@Override
public void onSkipToNext(@NonNull final com.google.android.exoplayer2.Player exoPlayer) {
player.playNext();
player.playerActionNext();
}
private void publishFloatingQueueWindow() {

View File

@ -24,6 +24,7 @@
<string name="screen_brightness_timestamp_key">screen_brightness_timestamp_key</string>
<string name="clear_queue_confirmation_key">clear_queue_confirmation_key</string>
<string name="ignore_hardware_media_buttons_key">ignore_hardware_media_buttons_key</string>
<string name="_key">prev_next_button_mode_key</string>
<string name="popup_saved_width_key">popup_saved_width</string>
<string name="popup_saved_x_key">popup_saved_x</string>
@ -229,6 +230,22 @@
<item>@string/none_control_key</item>
</string-array>
<string name="prev_next_button_mode_key">prev_next_button_mode</string>
<string name="default_default_prev_next_button_mode_default_value">@string/prev_next_mode_default_key</string>
<string name="prev_next_mode_default_key">default_mode</string>
<string name="prev_next_mode_seek_key">seek_mode</string>
<string name="prev_next_mode_smart_key">smart_mode</string>
<string-array name="prev_next_button_mode_description">
<item>@string/prev_next_mode_default</item>
<item>@string/prev_next_mode_seek</item>
<item>@string/prev_next_mode_smart</item>
</string-array>
<string-array name="default_prev_next_button_mode_default_values">
<item>@string/prev_next_mode_default_key</item>
<item>@string/prev_next_mode_seek_key</item>
<item>@string/prev_next_mode_smart_key</item>
</string-array>
<string name="prefer_original_audio_key">prefer_original_audio</string>
<string name="prefer_descriptive_audio_key">prefer_descriptive_audio</string>
<string name="last_resize_mode">last_resize_mode</string>

View File

@ -857,4 +857,9 @@
<string name="show_more">Show more</string>
<string name="show_less">Show less</string>
<string name="import_settings_vulnerable_format">The settings in the export being imported use a vulnerable format that was deprecated since NewPipe 0.27.0. Make sure the export being imported is from a trusted source, and prefer using only exports obtained from NewPipe 0.27.0 or newer in the future. Support for importing settings in this vulnerable format will soon be removed completely, and then old versions of NewPipe will not be able to import settings of exports from new versions anymore.</string>
<string name="prev_next_button_mode_settings_title">Previous/Next button behavior</string>
<string name="prev_next_button_mode_settings_summary">Previous/Next headset and notification mode behavior</string>
<string name="prev_next_mode_default">Next/Previous track</string>
<string name="prev_next_mode_smart">Smart Next/Prev or Fw/Rw</string>
<string name="prev_next_mode_seek">Forward/Rewind</string>
</resources>

View File

@ -144,6 +144,16 @@
app:singleLineTitle="false"
app:iconSpaceReserved="false" />
<ListPreference
android:defaultValue="@string/default_default_prev_next_button_mode_default_value"
android:entries="@array/prev_next_button_mode_description"
android:entryValues="@array/default_prev_next_button_mode_default_values"
android:key="@string/prev_next_button_mode_key"
android:summary="@string/prev_next_button_mode_settings_summary"
android:title="@string/prev_next_button_mode_settings_title"
app:singleLineTitle="false"
app:iconSpaceReserved="false" />
<ListPreference
android:defaultValue="@string/minimize_on_exit_value"
android:entries="@array/minimize_on_exit_action_description"