diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/NowPlayingFragment.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/NowPlayingFragment.java index 9935b93a9..cb37683a1 100644 --- a/Squeezer/src/main/java/uk/org/ngo/squeezer/NowPlayingFragment.java +++ b/Squeezer/src/main/java/uk/org/ngo/squeezer/NowPlayingFragment.java @@ -38,7 +38,6 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.CheckBox; @@ -606,14 +605,7 @@ private void updatePlayerDropDown(@NonNull List connectedPlayers, @Nulla actionBar.setCustomView(R.layout.action_bar_custom_view); AutoCompleteTextView spinner = actionBar.getCustomView().findViewById(R.id.player); final Context actionBarContext = actionBar.getThemedContext(); - final ArrayAdapter playerAdapter = new ArrayAdapter<>(actionBarContext, R.layout.dropdown_item, connectedPlayers) { - @Override - public @NonNull View getView(int position, View convertView, @NonNull ViewGroup parent) { - TextView view = (TextView) requireActivity().getLayoutInflater().inflate(R.layout.dropdown_item, parent, false); - view.setText(getItem(position).getName()); - return view; - } - }; + final PlayerDropdownAdapter playerAdapter = new PlayerDropdownAdapter(actionBarContext, connectedPlayers, activePlayer); spinner.setAdapter(playerAdapter); playerAdapter.notifyDataSetChanged(); spinner.setText((activePlayer != null) ? activePlayer.getName() : "", false); @@ -621,7 +613,7 @@ private void updatePlayerDropDown(@NonNull List connectedPlayers, @Nulla Player selectedItem = playerAdapter.getItem(position); spinner.setText(selectedItem.getName(), false); if (getActivePlayer() != selectedItem) { - requireService().setActivePlayer(selectedItem); + requireService().setActivePlayer(selectedItem, playerAdapter.continuePlayback()); } }); } else { @@ -1200,6 +1192,7 @@ public void onEventMainThread(@SuppressWarnings("unused") RegisterSqueezeNetwork @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) public void onEventMainThread(ActivePlayerChanged event) { updateUiFromPlayerState(event.player != null ? event.player.getPlayerState() : new PlayerState()); + updatePlayerDropDown(requireService().getPlayers(), requireService().getActivePlayer()); } @MainThread diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/PlayerDropdownAdapter.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/PlayerDropdownAdapter.java new file mode 100644 index 000000000..87faf998e --- /dev/null +++ b/Squeezer/src/main/java/uk/org/ngo/squeezer/PlayerDropdownAdapter.java @@ -0,0 +1,54 @@ +package uk.org.ngo.squeezer; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import java.util.List; + +import uk.org.ngo.squeezer.model.Player; + +class PlayerDropdownAdapter extends ArrayAdapter { + private final Player activePlayer; + private boolean continuePlayback; + + public PlayerDropdownAdapter(Context actionBarContext, List connectedPlayers, Player activePlayer) { + super(actionBarContext, 0); + add(null); + addAll(connectedPlayers); + this.activePlayer = activePlayer; + } + + @Override + public @NonNull View getView(int position, View convertView, @NonNull ViewGroup parent) { + Player item = getItem(position); + if (item == null) { + View view = LayoutInflater.from(getContext()).inflate(R.layout.continue_playback, parent, false); + view.setOnClickListener(v -> { + continuePlayback = !continuePlayback; + view.findViewById(R.id.checkbox).setChecked(continuePlayback); + }); + return view; + } else { + TextView view = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.dropdown_item, parent, false); + view.setText(item.getName()); + return view; + } + } + + @Override + public boolean isEnabled(int position) { + Player item = getItem(position); + return !(item == null || item.equals(activePlayer)); + } + + public boolean continuePlayback() { + return continuePlayback; + } +} diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/homescreenwidgets/RemoteButton.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/homescreenwidgets/RemoteButton.java index 1381ec759..699557ff7 100644 --- a/Squeezer/src/main/java/uk/org/ngo/squeezer/homescreenwidgets/RemoteButton.java +++ b/Squeezer/src/main/java/uk/org/ngo/squeezer/homescreenwidgets/RemoteButton.java @@ -15,21 +15,21 @@ public enum RemoteButton { OPEN((context, service, player) -> { - service.setActivePlayer(service.getPlayer(player.getId())); + service.setActivePlayer(service.getPlayer(player.getId()), false); Handler handler = new Handler(); float animationDelay = Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f); handler.postDelayed(() -> HomeActivity.show(context), (long) (300 * animationDelay)); }, R.string.remote_openPlayer, R.drawable.ic_home), OPEN_NOW_PLAYING((context, service, player) -> { - service.setActivePlayer(service.getPlayer(player.getId())); + service.setActivePlayer(service.getPlayer(player.getId()), false); Handler handler = new Handler(); float animationDelay = Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f); handler.postDelayed(() -> NowPlayingActivity.show(context), (long) (300 * animationDelay)); }, R.string.remote_openNowPlaying, R.drawable.ic_action_nowplaying), OPEN_CURRENT_PLAYLIST((context, service, player) -> { - service.setActivePlayer(service.getPlayer(player.getId())); + service.setActivePlayer(service.getPlayer(player.getId()), false); Handler handler = new Handler(); float animationDelay = Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f); diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/homescreenwidgets/SqueezerInfoScreen.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/homescreenwidgets/SqueezerInfoScreen.java index f4bf92637..81d26faa0 100644 --- a/Squeezer/src/main/java/uk/org/ngo/squeezer/homescreenwidgets/SqueezerInfoScreen.java +++ b/Squeezer/src/main/java/uk/org/ngo/squeezer/homescreenwidgets/SqueezerInfoScreen.java @@ -104,7 +104,7 @@ public void onReceive(final Context context, Intent intent) { if (SQUEEZER_REMOTE_OPEN.equals(action)) { runOnService(context, service -> { Log.d(TAG, "setting active player: " + playerId); - service.setActivePlayer(service.getPlayer(playerId)); + service.setActivePlayer(service.getPlayer(playerId), false); Handler handler = new Handler(); float animationDelay = Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f); diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/service/ISqueezeService.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/service/ISqueezeService.java index 2a6c027ad..036622e91 100644 --- a/Squeezer/src/main/java/uk/org/ngo/squeezer/service/ISqueezeService.java +++ b/Squeezer/src/main/java/uk/org/ngo/squeezer/service/ISqueezeService.java @@ -59,8 +59,9 @@ public interface ISqueezeService { * Change the player that is controlled by Squeezer (the "active" player). * * @param player May be null, in which case no players are controlled. + * @param continuePlaying Continue playback on the supplied player */ - void setActivePlayer(@NonNull Player player); + void setActivePlayer(@NonNull Player player, boolean continuePlaying); // Returns the player we are currently controlling @Nullable diff --git a/Squeezer/src/main/java/uk/org/ngo/squeezer/service/SqueezeService.java b/Squeezer/src/main/java/uk/org/ngo/squeezer/service/SqueezeService.java index c44b17af4..f8586ed46 100644 --- a/Squeezer/src/main/java/uk/org/ngo/squeezer/service/SqueezeService.java +++ b/Squeezer/src/main/java/uk/org/ngo/squeezer/service/SqueezeService.java @@ -317,10 +317,10 @@ private boolean isPlaying() { /** * Change the player that is controlled by Squeezer (the "active" player). * - * @param newActivePlayer The new active player. May be null, in which case no players - * are controlled. + * @param newActivePlayer The new active player. May be null, in which case no players are controlled. + * @param continuePlaying Continue playback on the supplied player */ - private void changeActivePlayer(@Nullable final Player newActivePlayer) { + private void changeActivePlayer(@Nullable final Player newActivePlayer, boolean continuePlaying) { Player prevActivePlayer = mDelegate.getActivePlayer(); // Do nothing if the player hasn't actually changed. @@ -338,9 +338,15 @@ private void changeActivePlayer(@Nullable final Player newActivePlayer) { updateAllPlayerSubscriptionStates(); requestPlayerData(); + if (continuePlaying && prevActivePlayer != null) moveCurrentPlaylist(prevActivePlayer, newActivePlayer); Squeezer.getPreferences().setLastPlayer(newActivePlayer); } + private void moveCurrentPlaylist(Player from, Player to) { + squeezeService.syncPlayerToPlayer(to, from.getId()); + squeezeService.unsyncPlayer(from); + } + class HomeMenuReceiver implements IServiceItemListCallback { private final List homeMenu = new ArrayList<>(); @@ -805,7 +811,7 @@ public void onEvent(PlayersChanged event) { Player activePlayer = mDelegate.getActivePlayer(); if (activePlayer == null) { // Figure out the new active player, let everyone know. - changeActivePlayer(getPreferredPlayer(mDelegate.getPlayers().values())); + changeActivePlayer(getPreferredPlayer(mDelegate.getPlayers().values()), false); } else { activePlayer = mDelegate.getPlayer(activePlayer.getId()); mDelegate.setActivePlayer(activePlayer); @@ -1323,8 +1329,8 @@ public boolean button(Player player, IRButton button) { } @Override - public void setActivePlayer(@Nullable final Player newActivePlayer) { - changeActivePlayer(newActivePlayer); + public void setActivePlayer(@Nullable final Player newActivePlayer, boolean continuePlaying) { + changeActivePlayer(newActivePlayer, continuePlaying); } @Override diff --git a/Squeezer/src/main/res/layout/continue_playback.xml b/Squeezer/src/main/res/layout/continue_playback.xml new file mode 100644 index 000000000..de71c057a --- /dev/null +++ b/Squeezer/src/main/res/layout/continue_playback.xml @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/Squeezer/src/main/res/layout/dropdown_item.xml b/Squeezer/src/main/res/layout/dropdown_item.xml index 428370b22..fffdbc268 100644 --- a/Squeezer/src/main/res/layout/dropdown_item.xml +++ b/Squeezer/src/main/res/layout/dropdown_item.xml @@ -1,10 +1,7 @@ \ No newline at end of file + xmlns:tools="http://schemas.android.com/tools" + style="@style/SqueezerWidget.DropdownText" + android:layout_width="match_parent" + android:padding="12dp" + tools:text="text" /> \ No newline at end of file diff --git a/Squeezer/src/main/res/values-da/strings.xml b/Squeezer/src/main/res/values-da/strings.xml index c1b11c7c3..0f510e671 100644 --- a/Squeezer/src/main/res/values-da/strings.xml +++ b/Squeezer/src/main/res/values-da/strings.xml @@ -274,5 +274,6 @@ Sekunder frem Fejl ved start af tilfældig afspilning Tilfældig afspilning er start + Fortsæt afspilning diff --git a/Squeezer/src/main/res/values-de/strings.xml b/Squeezer/src/main/res/values-de/strings.xml index 921088df6..34c606a99 100644 --- a/Squeezer/src/main/res/values-de/strings.xml +++ b/Squeezer/src/main/res/values-de/strings.xml @@ -269,5 +269,6 @@ Lautstärke für synchronisierte Player anpassen Lautstärke für ausgewählte Player anpassen Einschlaftimer setzen + Wiedergabe fortsetzen diff --git a/Squeezer/src/main/res/values-fr/strings.xml b/Squeezer/src/main/res/values-fr/strings.xml index 9f76f5934..a806cc45e 100644 --- a/Squeezer/src/main/res/values-fr/strings.xml +++ b/Squeezer/src/main/res/values-fr/strings.xml @@ -153,4 +153,5 @@ Nombre. Artiste - Titre n\'a pas pu être ajouté à la base de données multimédia de l\'appareil Intégration tierce + Continue playback diff --git a/Squeezer/src/main/res/values/strings.xml b/Squeezer/src/main/res/values/strings.xml index acacbbbfe..b05a6d7cf 100644 --- a/Squeezer/src/main/res/values/strings.xml +++ b/Squeezer/src/main/res/values/strings.xml @@ -462,4 +462,5 @@ of your accepting any such warranty or additional liability.</p> Forward seconds Unable to start Random Play Random Play started + Continue playback diff --git a/Squeezer/src/main/res/values/styles.xml b/Squeezer/src/main/res/values/styles.xml index de82b089a..cc00a14f4 100644 --- a/Squeezer/src/main/res/values/styles.xml +++ b/Squeezer/src/main/res/values/styles.xml @@ -165,6 +165,14 @@ true + + +