From 0a28f05d535e6fa92489506d396fd587b2eea715 Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 26 Oct 2026 11:13:08 -0400 Subject: [PATCH] Don't share phone videos and screen recordings as now-playing General-purpose players (VLC, MX Player, Photos, galleries) report a local file's name as the title. Skip sessions whose title looks like a video file or camera/recorder name, or that come from such a player without a real artist tag. Co-Authored-By: Claude Opus 5.5 --- .gitignore | 2 + .../nowplaying/MediaListenerService.kt | 6 ++- .../musicshare/nowplaying/NonMusicFilter.kt | 46 +++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 apps/mobile/modules/now-playing-reader/android/src/main/java/tech/chrisedwards/musicshare/nowplaying/NonMusicFilter.kt diff --git a/.gitignore b/.gitignore index 09a5939..9c0a8fb 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ next-env.d.ts # Production secrets and database backups deploy/production.env backups/ +.aider* +deploy/gitea-runner/data/ diff --git a/apps/mobile/modules/now-playing-reader/android/src/main/java/tech/chrisedwards/musicshare/nowplaying/MediaListenerService.kt b/apps/mobile/modules/now-playing-reader/android/src/main/java/tech/chrisedwards/musicshare/nowplaying/MediaListenerService.kt index 365790e..d13b4eb 100644 --- a/apps/mobile/modules/now-playing-reader/android/src/main/java/tech/chrisedwards/musicshare/nowplaying/MediaListenerService.kt +++ b/apps/mobile/modules/now-playing-reader/android/src/main/java/tech/chrisedwards/musicshare/nowplaying/MediaListenerService.kt @@ -121,9 +121,11 @@ class MediaListenerService : NotificationListenerService() { private fun snapshot(controller: MediaController): Playback? { val metadata = controller.metadata val title = metadata?.text(MediaMetadata.METADATA_KEY_TITLE) ?: metadata?.text(MediaMetadata.METADATA_KEY_DISPLAY_TITLE) - val artist = metadata?.text(MediaMetadata.METADATA_KEY_ARTIST) + val realArtist = metadata?.text(MediaMetadata.METADATA_KEY_ARTIST) ?: metadata?.text(MediaMetadata.METADATA_KEY_ALBUM_ARTIST) - ?: metadata?.text(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE) + val artist = realArtist ?: metadata?.text(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE) + // A phone video or other non-song: treat the session as if it weren't there. + if (NonMusicFilter.isNonMusic(controller.packageName, title, realArtist)) return null val playbackState = controller.playbackState val state = when (playbackState?.state) { PlaybackState.STATE_PLAYING, PlaybackState.STATE_BUFFERING, diff --git a/apps/mobile/modules/now-playing-reader/android/src/main/java/tech/chrisedwards/musicshare/nowplaying/NonMusicFilter.kt b/apps/mobile/modules/now-playing-reader/android/src/main/java/tech/chrisedwards/musicshare/nowplaying/NonMusicFilter.kt new file mode 100644 index 0000000..f2672c9 --- /dev/null +++ b/apps/mobile/modules/now-playing-reader/android/src/main/java/tech/chrisedwards/musicshare/nowplaying/NonMusicFilter.kt @@ -0,0 +1,46 @@ +package tech.chrisedwards.musicshare.nowplaying + +/** + * Keeps things that aren't songs (phone videos, screen recordings) out of what we share. + * General-purpose players report a local file's name as its title, so a video played + * in VLC would otherwise show up as "VID_20261025_181502.mp4". + */ +internal object NonMusicFilter { + /** Players that also open videos and arbitrary files: only share from them when there's a real artist. */ + private val GENERAL_PLAYERS = setOf( + "org.videolan.vlc", + "org.videolan.vlc.debug", + "com.mxtech.videoplayer.ad", + "com.mxtech.videoplayer.pro", + "is.xyz.mpv", + "com.brouken.player", // Just Player + "com.google.android.apps.photos", + "com.sec.android.gallery3d", + "com.android.gallery3d", + "com.miui.gallery", + "com.google.android.apps.nbu.files", + "com.sec.android.app.myfiles", + ) + + private val FILE_NAME = Regex( + """.*\.(mp4|m4v|mkv|mov|webm|avi|3gp|3g2|wmv|flv|ts|mts|m2ts|mpg|mpeg)$""", + RegexOption.IGNORE_CASE, + ) + + /** Camera, screen-recorder and messaging-app naming schemes. */ + private val RECORDING_NAME = Regex( + """^(VID|PXL|IMG|MVIMG|MOV|DSC|GOPR|GX\d{2}|Screen[_ ]?Recording|Screenrecorder|Record|signal|WhatsApp Video)[-_ ]?\d.*""", + RegexOption.IGNORE_CASE, + ) + + /** + * [realArtist] is the artist/album-artist tag only, not the display-subtitle fallback, + * which players fill with folder names and the like. + */ + fun isNonMusic(packageName: String, title: String?, realArtist: String?): Boolean { + val name = title?.trim().orEmpty() + if (name.isEmpty()) return false + if (FILE_NAME.matches(name) || RECORDING_NAME.matches(name)) return true + return packageName in GENERAL_PLAYERS && realArtist.isNullOrBlank() + } +}