App 2.45.0: now playing on the Overview
NowPlayingWatcher follows the head unit's media sessions (listening only, never connecting to a player); NowPlaying picks what plays and cleans the text. Tiles shows source, title, artist, cover and progress under the battery; Halloween carves title and artist into the hill. Settings: "Show what's playing", on by default. Nothing is logged or sent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
@@ -78,6 +78,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
/** The pane of each Overview style, by its {@link OverviewStyle} ordinal. */
|
||||
private View[] stylePanes;
|
||||
private MusicTap musicTap;
|
||||
private NowPlayingWatcher nowPlaying;
|
||||
private View consumptionPane;
|
||||
private View chargingPane;
|
||||
/** Display, battery, charging price and Wi-Fi. */
|
||||
@@ -197,6 +198,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
markCurrentPage(position);
|
||||
applyOverviewFullScreen(position);
|
||||
updateMusicTap();
|
||||
updateNowPlaying();
|
||||
}
|
||||
});
|
||||
findViewById(R.id.edge_tab).setOnClickListener(v -> leaveOverviewFullScreen());
|
||||
@@ -215,6 +217,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
/** Whether the Overview hides the navigation (the button in the navigation's header). */
|
||||
static final String PREF_OVERVIEW_FULLSCREEN = "overview_fullscreen";
|
||||
/** The Overview shows what plays (Tiles, Halloween); on by default. */
|
||||
static final String PREF_NOW_PLAYING = "now_playing";
|
||||
/** The Halloween pumpkin's light follows the music; off by default, so the analyser stays off. */
|
||||
static final String PREF_MUSIC_LIGHT = "music_light";
|
||||
|
||||
@@ -359,6 +363,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
visorView = new VisorView(this);
|
||||
HalloweenView halloweenView = new HalloweenView(this);
|
||||
musicTap = new MusicTap(this);
|
||||
nowPlaying = new NowPlayingWatcher(this);
|
||||
halloweenView.setMusic(musicTap);
|
||||
java.util.Collections.addAll(canvasStyles, new MinimalView(this), terminalView,
|
||||
new NixieView(this), new ChronographView(this), gridView, gridMapView, new TimeCircuitsView(this),
|
||||
@@ -514,6 +519,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
inFront = true;
|
||||
updateMapLocation();
|
||||
updateMusicTap();
|
||||
updateNowPlaying();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -564,6 +570,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
inFront = false;
|
||||
updateMapLocation();
|
||||
updateMusicTap();
|
||||
updateNowPlaying();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1225,6 +1232,12 @@ public class MainActivity extends AppCompatActivity {
|
||||
bindDriveMode();
|
||||
bindOverviewStyle();
|
||||
bindAccentColor();
|
||||
SwitchMaterial showPlaying = settingsPane.findViewById(R.id.now_playing_switch);
|
||||
showPlaying.setChecked(prefs.getBoolean(PREF_NOW_PLAYING, true));
|
||||
showPlaying.setOnCheckedChangeListener((btn, checked) -> {
|
||||
prefs.edit().putBoolean(PREF_NOW_PLAYING, checked).apply();
|
||||
updateNowPlaying();
|
||||
});
|
||||
SwitchMaterial musicLight = settingsPane.findViewById(R.id.music_light_switch);
|
||||
musicLight.setChecked(prefs.getBoolean(PREF_MUSIC_LIGHT, false));
|
||||
musicLight.setOnCheckedChangeListener((btn, checked) -> {
|
||||
@@ -1767,6 +1780,57 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (settingsPane != null) bindAccentColor();
|
||||
updateMapLocation();
|
||||
updateMusicTap();
|
||||
updateNowPlaying();
|
||||
}
|
||||
|
||||
/** The styles that show what plays. */
|
||||
private static boolean showsNowPlaying(OverviewStyle style) {
|
||||
return style == OverviewStyle.TILES || style == OverviewStyle.HALLOWEEN;
|
||||
}
|
||||
|
||||
/** The media sessions are watched only while what plays can be seen, and the switch is on. */
|
||||
private void updateNowPlaying() {
|
||||
ViewPager2 pager = findViewById(R.id.content);
|
||||
nowPlaying.setRunning(inFront && showsNowPlaying(overviewStyle())
|
||||
&& prefs.getBoolean(PREF_NOW_PLAYING, true)
|
||||
&& pager != null && pager.getCurrentItem() == 0);
|
||||
if (!nowPlaying.isRunning()) showNowPlaying(null);
|
||||
}
|
||||
|
||||
/** The Tiles tile: source, title, artist, a cover when there is one, and how far the song is. */
|
||||
private void showNowPlaying(NowPlaying.Track t) {
|
||||
if (vehiclePane == null) return;
|
||||
View tile = vehiclePane.findViewById(R.id.now_playing_tile);
|
||||
if (tile == null) return; // the narrow layout has no room for it
|
||||
if (t == null) {
|
||||
tile.setVisibility(View.INVISIBLE);
|
||||
return;
|
||||
}
|
||||
tile.setVisibility(View.VISIBLE);
|
||||
String source = getString(t.source == NowPlaying.Source.BLUETOOTH ? R.string.now_playing_bluetooth
|
||||
: t.source == NowPlaying.Source.CARPLAY ? R.string.now_playing_carplay
|
||||
: t.source == NowPlaying.Source.RADIO ? R.string.now_playing_radio : R.string.now_playing_other);
|
||||
setIfChanged(vehiclePane.findViewById(R.id.now_playing_source),
|
||||
t.playing ? source : getString(R.string.now_playing_paused, source));
|
||||
setIfChanged(vehiclePane.findViewById(R.id.now_playing_title), t.title);
|
||||
TextView artist = vehiclePane.findViewById(R.id.now_playing_artist);
|
||||
setIfChanged(artist, t.subtitle == null ? "" : t.subtitle);
|
||||
artist.setVisibility(t.subtitle == null ? View.GONE : View.VISIBLE);
|
||||
android.widget.ImageView cover = vehiclePane.findViewById(R.id.now_playing_cover);
|
||||
android.graphics.Bitmap art = nowPlaying.cover(t);
|
||||
if (cover.getTag() != art) {
|
||||
cover.setTag(art);
|
||||
cover.setImageBitmap(art);
|
||||
cover.setVisibility(art == null ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
android.widget.ProgressBar bar = vehiclePane.findViewById(R.id.now_playing_progress);
|
||||
float progress = t.progressAt(android.os.SystemClock.elapsedRealtime());
|
||||
bar.setVisibility(progress < 0f ? View.INVISIBLE : View.VISIBLE);
|
||||
if (progress >= 0f) bar.setProgress(Math.round(progress * bar.getMax()));
|
||||
}
|
||||
|
||||
private static void setIfChanged(TextView view, CharSequence text) {
|
||||
if (!android.text.TextUtils.equals(view.getText(), text)) view.setText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1840,6 +1904,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
TextView note = settingsPane.findViewById(R.id.accent_note);
|
||||
note.setVisibility(style.usesAccent ? View.GONE : View.VISIBLE);
|
||||
note.setText(getString(R.string.accent_not_used, styleLabels()[style.ordinal()]));
|
||||
int playing = showsNowPlaying(style) ? View.VISIBLE : View.GONE;
|
||||
settingsPane.findViewById(R.id.now_playing_switch).setVisibility(playing);
|
||||
settingsPane.findViewById(R.id.now_playing_hint).setVisibility(playing);
|
||||
int music = style == OverviewStyle.HALLOWEEN ? View.VISIBLE : View.GONE;
|
||||
settingsPane.findViewById(R.id.music_light_switch).setVisibility(music);
|
||||
settingsPane.findViewById(R.id.music_light_hint).setVisibility(music);
|
||||
@@ -1925,6 +1992,10 @@ public class MainActivity extends AppCompatActivity {
|
||||
v.tyreRl = unit.format(s.getTirePressures().getRearLeftKpa());
|
||||
v.tyreRr = unit.format(s.getTirePressures().getRearRightKpa());
|
||||
v.powerTrail = cockpitTrace.snapshot();
|
||||
NowPlaying.Track track = nowPlaying.isRunning() ? nowPlaying.current() : null;
|
||||
v.songTitle = track == null ? null : track.title;
|
||||
v.songArtist = track == null ? null : track.subtitle;
|
||||
showNowPlaying(track);
|
||||
retroView.setValues(v);
|
||||
flowView.setValues(v);
|
||||
sciFiView.setValues(v);
|
||||
|
||||
Reference in New Issue
Block a user