The Android half of andTunes had been paused on a 1 GB toolchain download (Gradle wrapper, Android Gradle Plugin, Kotlin). None of that was needed: platform 33 and build-tools 34 were already in ~/Android/Sdk, and an app that links no libraries needs five SDK steps, not a build system. andtunes/build.py runs aapt2 -> javac -> R8 -> zipalign -> apksigner and produces a 61 KiB APK. andTunes 0.1.0 is framework-only Java: a six-tile menu that loads nothing, a streaming library.json parse grouped into artists and albums in one pass, one ListActivity for every list (songs and artist songs open with Shuffle all, albums carry art thumbs, search as you type), a Now playing bar under every list, and a white Now Playing screen with square art, a slim scrubber, prev/play/next, shuffle and repeat, and no back button. A foreground PlaybackService owns the queue: audio focus, becoming-noisy, MediaSession and a MediaStyle notification, end of queue pauses, missing files skip, and the last queue and position come back on launch. Black on white, and every size doubled for the R1's override density. Cold start to the menu: 313-338 ms. The scroll wheel turned out to be DPAD_UP/DOWN (stock Generic.kl), not volume. The app takes both in dispatchKeyEvent: lists scroll a row per detent, and the menu and Now Playing get volume. LinTunes side: Connections > Install andTunes on Rabbit... installs the committed APK over adb and grants all-files access, or copies it to Download/ over MTP when there's no adb. Sync fills Buttons/ with default artwork only where a file is missing, so trav's own art is never overwritten. Verified against the dev library only, synced to the R1 and driven with adb input + screencap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KSsYtRn4WZx6xj4GEdVPt9
41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
import re
|
|
from pathlib import Path
|
|
|
|
from setuptools import setup, find_packages
|
|
|
|
# Single source of truth for the version is lintunes/__init__.py; read it
|
|
# textually so setup.py doesn't import the package (and its Qt deps).
|
|
_init = (Path(__file__).parent / "lintunes" / "__init__.py").read_text()
|
|
_version = re.search(r'^__version__ = "([^"]+)"', _init, re.MULTILINE)[1]
|
|
|
|
setup(
|
|
name="lintunes",
|
|
version=_version,
|
|
packages=find_packages(),
|
|
# The web-mix templates (player.js/css, the player sprite GIF and
|
|
# the placeholder image) must ride along in an installed copy.
|
|
# The andTunes APK LinTunes installs, and the default button artwork
|
|
# sync ships to the device.
|
|
package_data={
|
|
"lintunes.export": ["templates/*"],
|
|
"lintunes.android": ["andTunes.apk", "andTunes.json"],
|
|
"lintunes.andtunes": ["buttons/*.png"],
|
|
},
|
|
install_requires=[
|
|
"PyQt6>=6.8.0", # QAudioBufferOutput (visualizer) needs Qt 6.8+
|
|
"mutagen>=1.46",
|
|
"numpy>=1.24",
|
|
"requests>=2.28",
|
|
"pychromecast>=14.0.10",
|
|
],
|
|
data_files=[
|
|
("share/applications", ["packaging/lintunes.desktop"]),
|
|
],
|
|
entry_points={
|
|
"console_scripts": [
|
|
"lintunes=lintunes.main:main",
|
|
],
|
|
},
|
|
python_requires=">=3.11",
|
|
)
|