diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 3a2d578..b9812cc 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,8 +1,8 @@ diff --git a/README.md b/README.md index 70d72cd..3be4a28 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -# Minamp +# Plexamp Lite A small Plexamp-style music player for Plex, built for the Samsung Galaxy Mini (GT-S5570: Android 2.2/2.3, 240×320 ldpi screen, 600 MHz ARMv6, 384 MB RAM). Runs on any Android 2.2+ phone. +Formerly Minamp (the package name, `com.minamp`, stays so updates install over it). ## Language @@ -13,21 +14,21 @@ log stays in English since it's meant for troubleshooting. ## Install 1. On the phone: **Settings → Applications → Unknown sources** (tick it). -2. Copy `Minamp.apk` to the SD card (USB cable, or download it in the browser) and open it - with a file manager, or from a computer: `adb install Minamp.apk`. -3. Minamp installs to internal storage (about 1 MB): an app on the SD card is killed whenever the +2. Copy `PlexampLite.apk` to the SD card (USB cable, or download it in the browser) and open it + with a file manager, or from a computer: `adb install PlexampLite.apk`. +3. Plexamp Lite installs to internal storage (about 1 MB): an app on the SD card is killed whenever the phone shares its SD card over USB, which stopped the music. ## Sign in -Open Minamp → **Sign in with Plex**. It shows a 4-character code; on any other device go to -**plex.tv/link** and type it in. Minamp then lists your servers (owned and shared) and music libraries. +Open Plexamp Lite → **Sign in with Plex**. It shows a 4-character code; on any other device go to +**plex.tv/link** and type it in. Plexamp Lite then lists your servers (owned and shared) and music libraries. *Connect to a server address* is the manual fallback: an IP/hostname plus an optional X-Plex-Token. ## Streaming from anywhere -After sign-in Minamp knows every address Plex advertises for your server and picks the best +After sign-in Plexamp Lite knows every address Plex advertises for your server and picks the best working one, re-checking whenever the phone switches network: | Order | Connection | When it's used | @@ -36,16 +37,16 @@ working one, re-checking whenever the phone switches network: | 2 | Home network, plain HTTP | On your Wi-Fi (fast: no encryption work for the phone) | | 3 | Home network, HTTPS (`*.plex.direct`) | On your Wi-Fi if plain HTTP is refused, or if *Settings → Encrypt at home too* is on | | 4 | Remote, HTTPS | Away, if Remote Access is set up on the server | -| 5 | Plex Relay | Away, when the server isn't reachable directly (bandwidth-capped; Minamp caps itself at 192 kbps) | +| 5 | Plex Relay | Away, when the server isn't reachable directly (bandwidth-capped; Plexamp Lite caps itself at 192 kbps) | Secure addresses are tried one at a time: on a 600 MHz phone a TLS handshake takes seconds, and -several at once make each of them time out. Minamp uses TLS 1.2 with session resumption, so only +several at once make each of them time out. Plexamp Lite uses TLS 1.2 with session resumption, so only the first connection to each server pays the full cost; later ones resume in a fraction of it. For the best remote experience enable **Settings → Remote Access** on your Plex Media Server. Without it, Relay still works. -Android 2.x can't do modern TLS, so Minamp bundles its own TLS 1.2/1.3 stack (Bouncy Castle, +Android 2.x can't do modern TLS, so Plexamp Lite bundles its own TLS 1.2/1.3 stack (Bouncy Castle, renamed to `com.minamp.bc` so it doesn't clash with the old copy inside Android) and verifies certificates against Mozilla's root store (from `certifi`). A tiny loopback proxy feeds the phone's media player, so HTTPS streams and relay work the same as local ones. If the phone's @@ -60,12 +61,16 @@ clock has been reset to before 2024 the certificate date check is skipped rather (default 192 kbps) caps both while the sound goes to a Bluetooth speaker: on the Mini, Wi-Fi and Bluetooth share one radio, and a lighter stream keeps the speaker from stuttering. * Seeking in a transcoded track restarts the transcode at the new position. -* If a stream fails, Minamp re-picks the connection and resumes; if it fails again it downloads +* **Read-ahead:** while a track plays, the next one is fetched whole in the background and then + played from the file. Android 2.x's player keeps only a few seconds of stream buffer, so on weak + Wi-Fi shared with a Bluetooth speaker it used to go silent for seconds at a time. +* If a stream fails, Plexamp Lite re-picks the connection and resumes; if it fails again it downloads the whole track first and plays from the SD card. "Download tracks before playing" forces that mode (useful on flaky mobile data). Playback that stalls ("playing" but the time doesn't move for 10 s) is recovered the same way. -* A Bluetooth speaker that drops its link for a moment pauses Minamp, which resumes by itself if the - speaker is back within 20 s. Why playback paused or stopped is written to the connection log. +* A Bluetooth speaker that drops its link for a moment pauses Plexamp Lite, which resumes by itself if the + speaker is back within 20 s. Why playback paused or stopped is written to the connection log, + which also goes to logcat (tag `PlexampLite`, readable over USB with `adb logcat`). * Plays are reported to Plex (Now Playing in the Plex dashboard, play counts, resume position). ## Features @@ -83,7 +88,7 @@ clock has been reset to before 2024 the certificate date check is skipped rather the SD card. MP3 originals are kept as they are (unless above a lower *Download quality* in Settings); everything else is transcoded to MP3, 320 kbps by default. Downloaded tracks play from the SD card, offline too, and plays made offline are reported to Plex later. -* *Menu -> Close Minamp* stops the music and closes every screen. +* *Menu -> Close Plexamp Lite* stops the music and closes every screen. * Wired headset button: 1 click play/pause, 2 next, 3 previous; Bluetooth media keys; pauses for calls and when headphones are unplugged. @@ -91,7 +96,7 @@ clock has been reset to before 2024 the certificate date check is skipped rather ``` tools/setup_toolchain.sh # once: fetches aapt2, the API 8 android.jar, builds dx, renames Bouncy Castle -./build.sh # -> build/Minamp.apk +./build.sh # -> build/PlexampLite.apk ``` `build.sh` runs `aapt2` (resources), `javac` (Java 8 bytecode checked against the API 8 @@ -108,6 +113,10 @@ Tests (desktop JVM, no device): untrusted-root rejection, browsing, search, artwork, and the stream proxy (Range requests over TLS, de-chunking transcodes, aborting). * `test/QueueTest.java`: shuffle/unshuffle, repeat modes, play next, remove, move, clear. +* `test/PreferHomeTest.java` + `test/identity_server.py`: after being away, the home address wins + again as soon as it answers. +* `test/NetTest.java`: the bundled TLS + HTTP client against real servers; `test/HandshakeProfile.java` + samples where handshake time goes (run with `-Xint`). ## Limits diff --git a/art/icon-512.png b/art/icon-512.png index 86463e1..093c254 100644 Binary files a/art/icon-512.png and b/art/icon-512.png differ diff --git a/art/icon-master.png b/art/icon-master.png index 8a8f100..8e9d4ea 100644 Binary files a/art/icon-master.png and b/art/icon-master.png differ diff --git a/build.sh b/build.sh index c9fcbdb..6109a67 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Builds Minamp.apk for Android 2.2+ without the Android SDK/Gradle: +# Builds PlexampLite.apk for Android 2.2+ without the Android SDK/Gradle: # aapt2 (resources) -> javac (Java 8 bytecode vs android-8 API) -> dx (dex 035) -> signapk.py (v1/SHA-1 + zipalign). set -euo pipefail cd "$(dirname "$0")" @@ -42,5 +42,5 @@ echo "== package" cp $OUT/base.apk $OUT/unsigned.apk (cd $OUT && zip -q unsigned.apk classes.dex) # v1 signature in the classic Android SignApk format (jarsigner's modern output won't install on Android <= 4.2) -python3 tools/signapk.py ${KEYSTORE:-$T/minamp.keystore} ${KEYPASS:-minamp123} $OUT/unsigned.apk $OUT/Minamp.apk -ls -la $OUT/Minamp.apk +python3 tools/signapk.py ${KEYSTORE:-$T/minamp.keystore} ${KEYPASS:-minamp123} $OUT/unsigned.apk $OUT/PlexampLite.apk +ls -la $OUT/PlexampLite.apk diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png index 2f78b59..58f7de7 100644 Binary files a/res/drawable-hdpi/ic_launcher.png and b/res/drawable-hdpi/ic_launcher.png differ diff --git a/res/drawable-ldpi/ic_launcher.png b/res/drawable-ldpi/ic_launcher.png index d4fb1f9..8e0bdae 100644 Binary files a/res/drawable-ldpi/ic_launcher.png and b/res/drawable-ldpi/ic_launcher.png differ diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png index e163909..f96837a 100644 Binary files a/res/drawable-mdpi/ic_launcher.png and b/res/drawable-mdpi/ic_launcher.png differ diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png index f64a108..deae16d 100644 Binary files a/res/drawable-xhdpi/ic_launcher.png and b/res/drawable-xhdpi/ic_launcher.png differ diff --git a/res/values-en/strings.xml b/res/values-en/strings.xml index 03051d0..51e6bbc 100644 --- a/res/values-en/strings.xml +++ b/res/values-en/strings.xml @@ -8,7 +8,7 @@ Album Album › Already downloaded - Minamp + Plexamp Lite Applies from the next track Artist Radio @@ -57,7 +57,7 @@ Downloads End of track Enter your server\'s address - Minamp hit an error last time + Plexamp Lite hit an error last time Finding decades… Finding your servers… Go to album @@ -124,11 +124,12 @@ Playlist Plex server Quality away / mobile + Quality over Bluetooth Quality at home Original The queue is empty %1$d tracks added to downloads - Close Minamp + Close Plexamp Lite Random album Feeling lucky Recently added @@ -141,7 +142,7 @@ Repeat queue Repeat track Save to SD card - Saved as Minamp-log.txt on the SD card + Saved as PlexampLite-log.txt on the SD card Search Search music Search %1$s @@ -164,6 +165,7 @@ Library: %1$s Connection log & streaming test Quality away / mobile data: %1$s + Quality over Bluetooth: %1$s Quality at home: %1$s Encrypt at home too (slower): %1$s Server: %1$s @@ -236,6 +238,4 @@ Removed from favourites Queue you - Quality over Bluetooth - Quality over Bluetooth: %1$s diff --git a/res/values/strings.xml b/res/values/strings.xml index a99b0b6..87027ff 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8,7 +8,7 @@ Álbum Álbum › Xa está descargado - Minamp + Plexamp Lite Aplícase desde a seguinte pista Artista Radio @@ -57,7 +57,7 @@ Descargas Fin da pista Escribe o enderezo do teu servidor - Minamp tivo un erro a última vez + Plexamp Lite tivo un erro a última vez Buscando décadas… Buscando os teus servidores… Ir ao álbum @@ -124,11 +124,12 @@ Lista de reprodución Servidor Plex Calidade fóra / datos móbiles + Calidade por Bluetooth Calidade na casa Orixinal A cola está baleira %1$d pistas engadidas ás descargas - Pechar Minamp + Pechar Plexamp Lite Álbum ao chou Proba sorte Novidades @@ -141,7 +142,7 @@ Repetir a cola Repetir a pista Gardar na tarxeta SD - Gardado como Minamp-log.txt na tarxeta SD + Gardado como PlexampLite-log.txt na tarxeta SD Buscar Buscar música Buscar en %1$s @@ -164,6 +165,7 @@ Biblioteca: %1$s Rexistro de conexión e proba de reprodución Calidade fóra / datos móbiles: %1$s + Calidade por Bluetooth: %1$s Calidade na casa: %1$s Cifrar tamén na casa (máis lento): %1$s Servidor: %1$s @@ -236,6 +238,4 @@ Quitada de favoritas Cola ti - Calidade por Bluetooth - Calidade por Bluetooth: %1$s diff --git a/src/com/minamp/App.java b/src/com/minamp/App.java index 69ec321..286d194 100644 --- a/src/com/minamp/App.java +++ b/src/com/minamp/App.java @@ -176,7 +176,7 @@ public class App extends Application { try { java.io.StringWriter sw = new java.io.StringWriter(); java.io.PrintWriter pw = new java.io.PrintWriter(sw); - pw.println("Minamp " + Plex.version + " on " + Build.MODEL + ", Android " + Build.VERSION.RELEASE); + pw.println("Plexamp Lite " + Plex.version + " on " + Build.MODEL + ", Android " + Build.VERSION.RELEASE); pw.println(new java.util.Date() + " - " + where); e.printStackTrace(pw); pw.flush(); @@ -186,7 +186,7 @@ public class App extends Application { out.close(); try { if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState())) { - java.io.File f = new java.io.File(android.os.Environment.getExternalStorageDirectory(), "Minamp-error.txt"); + java.io.File f = new java.io.File(android.os.Environment.getExternalStorageDirectory(), "PlexampLite-error.txt"); java.io.FileOutputStream o2 = new java.io.FileOutputStream(f); o2.write(text); o2.close(); diff --git a/src/com/minamp/BaseActivity.java b/src/com/minamp/BaseActivity.java index c864984..b5b832c 100644 --- a/src/com/minamp/BaseActivity.java +++ b/src/com/minamp/BaseActivity.java @@ -80,7 +80,7 @@ public abstract class BaseActivity extends Activity implements PlayerService.Lis super.onCreate(b); } - /** If the last run hit an error, show it so it can be reported (also saved as Minamp-error.txt on the SD card). */ + /** If the last run hit an error, show it so it can be reported (also saved as PlexampLite-error.txt on the SD card). */ protected void showCrashReportIfAny() { final String report = app.takeCrashReport(); if (report == null) return; @@ -530,9 +530,9 @@ public abstract class BaseActivity extends Activity implements PlayerService.Lis toast(str(R.string.no_sd)); return; } - java.io.File f = new java.io.File(android.os.Environment.getExternalStorageDirectory(), "Minamp-log.txt"); + java.io.File f = new java.io.File(android.os.Environment.getExternalStorageDirectory(), "PlexampLite-log.txt"); java.io.FileOutputStream o = new java.io.FileOutputStream(f); - String head = "Minamp " + com.minamp.plex.Plex.version + " on " + android.os.Build.MODEL + String head = "Plexamp Lite " + com.minamp.plex.Plex.version + " on " + android.os.Build.MODEL + ", Android " + android.os.Build.VERSION.RELEASE + "\n"; o.write((head + com.minamp.net.DiagLog.dump()).getBytes("UTF-8")); o.close(); diff --git a/src/com/minamp/HomeActivity.java b/src/com/minamp/HomeActivity.java index 66826d8..d0d0b42 100644 --- a/src/com/minamp/HomeActivity.java +++ b/src/com/minamp/HomeActivity.java @@ -90,7 +90,7 @@ public class HomeActivity extends BaseActivity { @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); - if (intent.getBooleanExtra("exit", false)) { finish(); return; } // "Close Minamp" + if (intent.getBooleanExtra("exit", false)) { finish(); return; } // "Close Plexamp Lite" if (intent.getBooleanExtra("relaunch", false)) { // language changed: rebuild from scratch so every inflated text is re-read finish(); diff --git a/src/com/minamp/PlayerService.java b/src/com/minamp/PlayerService.java index 1895a84..9039f6d 100644 --- a/src/com/minamp/PlayerService.java +++ b/src/com/minamp/PlayerService.java @@ -147,7 +147,17 @@ public class PlayerService extends Service implements MediaPlayer.OnPreparedList private boolean pausedByRoute; // the Bluetooth speaker dropped: resume if it's back soon private long routeLostAt; private boolean btOn; - private long failedAtPos = -1; // where the last failure/stall was recovered from // audio was going to Bluetooth (A2DP), as last seen while playing + private long failedAtPos = -1; + + // Read-ahead: the next track is fetched whole while this one plays, then played from the file. + // Android 2.x's player keeps only seconds of stream buffered; on weak Wi-Fi shared with Bluetooth + // audio it runs dry and goes silent for 6-7 s at a time (and some speakers then hang up). + private volatile boolean prefetchBusy; + private String prefetchKey; // track in prefetchFile (complete), main thread + private File prefetchFile; + private String prefetchExt; + private int prefetchKbps; + private File playingPrefetch; // the prefetched file being played: not to be overwritten // where the last failure/stall was recovered from // audio was going to Bluetooth (A2DP), as last seen while playing private WifiManager.WifiLock wifiLock; private boolean noisyRegistered; private boolean foreground; @@ -285,6 +295,18 @@ public class PlayerService extends Service implements MediaPlayer.OnPreparedList begin(new java.util.ArrayList(), "mp3", saved, 0, posMs); return; } + if (prefetchKey != null && prefetchKey.equals(it.ratingKey) && prefetchFile != null && prefetchFile.exists()) { + com.minamp.net.DiagLog.log("playing \"" + it.title + "\" from the read-ahead file"); + transcoding = false; + session = null; + variantOrder = null; + kbps = prefetchKbps; + playingPrefetch = prefetchFile; + prefetchKey = null; + begin(new java.util.ArrayList(), prefetchExt, playingPrefetch, 0, posMs); + return; + } + playingPrefetch = null; final boolean download = forceDownload || app.downloadFirst(); worker.execute(new Runnable() { public void run() { @@ -331,6 +353,77 @@ public class PlayerService extends Service implements MediaPlayer.OnPreparedList }); } + /** Fetches the next track whole in the background (Wi-Fi or mobile data: it's the same bytes as streaming, + * only earlier; a skipped track is the only waste), if it isn't here yet. Main thread. */ + private void maybePrefetch() { + final App app = App.get(); + if (prefetchBusy || app.library == null) return; + PlayQueue q = PlayQueue.get(); + final Item next = q.peekNext(); + if (next == null || next == track || next.ratingKey.equals(prefetchKey) || Downloads.get().fileFor(next) != null) return; + // two slots: never overwrite the file that's playing + File base = null; + if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) base = getExternalCacheDir(); + if (base == null) base = getCacheDir(); + File a = new File(base, "ahead-a.tmp"), b = new File(base, "ahead-b.tmp"); + final File target = a.equals(playingPrefetch) ? b : a; + prefetchBusy = true; + prefetchKey = null; + com.minamp.net.Threads.start(new Runnable() { + public void run() { + String ext = "mp3"; + int k = 0; + boolean ok = false; + long t0 = System.currentTimeMillis(); + try { + Library lib = app.library; + lib.ensureMedia(next); + lib.server.base(); + int max = app.currentMaxKbps(); + boolean direct = Library.canDirectPlay(next, max); + java.util.List urls; + if (direct) { urls = new java.util.ArrayList(); urls.add(lib.directUrl(next)); ext = extFor(next); } + else urls = lib.transcodeUrls(next, max, 0, "minamp-ahead-" + Long.toString(System.currentTimeMillis(), 36)); + k = direct ? 0 : (max <= 0 ? 320 : max); + for (String u : urls) { + Http.Response r = Http.get(u, lib.server.mediaHeaders(), 30000); + if (r.code != 200) { r.close(); continue; } + FileOutputStream out = new FileOutputStream(target); + long got = 0; + try { + byte[] buf = new byte[16384]; + int n; + while ((n = r.body.read(buf)) > 0) { out.write(buf, 0, n); got += n; } + } finally { + out.close(); + r.close(); + } + // a stream cut short leaves a truncated file: only a plausible length counts + ok = got > 0 && (r.contentLength <= 0 || got >= r.contentLength); + com.minamp.net.DiagLog.log("read ahead \"" + next.title + "\": " + got / 1024 + " KB in " + + (System.currentTimeMillis() - t0) / 1000 + " s" + (ok ? "" : " (incomplete)")); + break; + } + } catch (Throwable e) { + com.minamp.net.DiagLog.log("read ahead failed: " + com.minamp.net.Threads.describe(e)); + } + final boolean done = ok; + final String fext = ext; + final int fk = k; + post(new Runnable() { + public void run() { + prefetchBusy = false; + if (!done) return; + prefetchKey = next.ratingKey; + prefetchFile = target; + prefetchExt = fext; + prefetchKbps = fk; + } + }); + } + }, "ahead"); + } + private static String extFor(Item it) { String c = it.container.toLowerCase(); if ("mp4".equals(c) || "m4a".equals(c) || "m4b".equals(c)) return "m4a"; @@ -618,7 +711,10 @@ public class PlayerService extends Service implements MediaPlayer.OnPreparedList private final Runnable ticker = new Runnable() { public void run() { - if (state == PLAYING) btOn = audio.isBluetoothA2dpOn(); + if (state == PLAYING) { + btOn = audio.isBluetoothA2dpOn(); + maybePrefetch(); + } App.get().handler.postDelayed(this, 1000); long now = System.currentTimeMillis(); if (sleepAt > 0 && now >= sleepAt) { diff --git a/src/com/minamp/SetupActivity.java b/src/com/minamp/SetupActivity.java index 9f5a138..e3a4a34 100644 --- a/src/com/minamp/SetupActivity.java +++ b/src/com/minamp/SetupActivity.java @@ -109,7 +109,7 @@ public class SetupActivity extends BaseActivity { public Plex.Pin work() throws Exception { return Plex.createPin(); } public void done(Plex.Pin p) { if (my != pinSeq) return; - // Remember the code: the phone may close Minamp while you type it in elsewhere. + // Remember the code: the phone may close Plexamp Lite while you type it in elsewhere. app.prefs.edit().putLong("pinId", p.id).putString("pinCode", p.code) .putLong("pinStart", System.currentTimeMillis()).commit(); showPin(p.id, p.code, System.currentTimeMillis()); @@ -122,7 +122,7 @@ public class SetupActivity extends BaseActivity { }); } - /** Resume waiting for a code created earlier (Minamp was closed while the user typed it in). */ + /** Resume waiting for a code created earlier (Plexamp Lite was closed while the user typed it in). */ private boolean resumePendingPin() { long id = app.prefs.getLong("pinId", 0); String code = app.prefs.getString("pinCode", null); diff --git a/src/com/minamp/net/DiagLog.java b/src/com/minamp/net/DiagLog.java index bd6b30a..abab088 100644 --- a/src/com/minamp/net/DiagLog.java +++ b/src/com/minamp/net/DiagLog.java @@ -19,6 +19,7 @@ public final class DiagLog { private DiagLog() {} public static void log(String msg) { + android.util.Log.i("PlexampLite", msg); // also in logcat: readable over USB after the fact String line; synchronized (fmt) { line = fmt.format(new Date()) + " " + msg; } synchronized (lines) { diff --git a/src/com/minamp/net/Http.java b/src/com/minamp/net/Http.java index eeaa32e..6050a93 100644 --- a/src/com/minamp/net/Http.java +++ b/src/com/minamp/net/Http.java @@ -37,7 +37,7 @@ import com.minamp.bc.tls.crypto.impl.bc.BcTlsCrypto; */ public final class Http { - public static final String USER_AGENT = "Minamp/1.0"; + public static final String USER_AGENT = "PlexampLite/1.0"; /** Optional HTTP CONNECT proxy, only used when running the networking code on a desktop JVM. */ public static String proxyHost; diff --git a/src/com/minamp/plex/Plex.java b/src/com/minamp/plex/Plex.java index d7d9d1d..afdac8c 100644 --- a/src/com/minamp/plex/Plex.java +++ b/src/com/minamp/plex/Plex.java @@ -14,7 +14,7 @@ import com.minamp.util.Json; /** Client identity + plex.tv account calls (PIN sign-in, server discovery). */ public final class Plex { - public static String product = "Minamp"; + public static String product = "Plexamp Lite"; public static String version = "1.0"; public static String clientId = "minamp-dev"; public static String platform = "Android"; diff --git a/test/mock_plex.py b/test/mock_plex.py index f1c2d20..910402a 100644 --- a/test/mock_plex.py +++ b/test/mock_plex.py @@ -1,4 +1,4 @@ -"""Mock plex.tv + Plex Media Server for exercising Minamp's networking code on a desktop JVM. +"""Mock plex.tv + Plex Media Server for exercising Plexamp Lite's networking code on a desktop JVM. Serves: https://plex.tv:443 pins, user, resources @@ -26,7 +26,7 @@ NOW = datetime.datetime.now(datetime.timezone.utc) def name(cn): - return x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Minamp Test"), x509.NameAttribute(NameOID.COMMON_NAME, cn)]) + return x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Plexamp Lite Test"), x509.NameAttribute(NameOID.COMMON_NAME, cn)]) def cert(subject, issuer, pub, signer, hashalg, ca, sans=None): diff --git a/tools/setup_toolchain.sh b/tools/setup_toolchain.sh index 7f95e77..73c1f50 100755 --- a/tools/setup_toolchain.sh +++ b/tools/setup_toolchain.sh @@ -66,6 +66,6 @@ echo "== signing key" if [ ! -f minamp.keystore ]; then if [ -f "$PROJ/signing/minamp.keystore" ]; then cp "$PROJ/signing/minamp.keystore" .; else keytool -genkeypair -keystore minamp.keystore -storepass minamp123 -keypass minamp123 -alias minamp \ - -keyalg RSA -keysize 2048 -sigalg SHA1withRSA -validity 20000 -dname "CN=Minamp, O=Minamp"; fi + -keyalg RSA -keysize 2048 -sigalg SHA1withRSA -validity 20000 -dname "CN=Plexamp Lite, O=Plexamp Lite"; fi fi echo "Toolchain ready in $T — build with: TOOLS=$T ./build.sh" diff --git a/tools/strings.py b/tools/strings.py index 36b1419..c338134 100644 --- a/tools/strings.py +++ b/tools/strings.py @@ -7,7 +7,7 @@ Run: python3 tools/strings.py import os S = { - "app_name": ("Minamp", "Minamp"), + "app_name": ("Plexamp Lite", "Plexamp Lite"), # tabs / headers "tab_home": ("Home", "Inicio"), @@ -75,7 +75,7 @@ S = { "cant_load_tap": ("Couldn't load: %1$s (tap to retry)", "Non se puido cargar: %1$s (toca para tentar de novo)"), "on": ("On", "Activado"), "off": ("Off", "Desactivado"), - "error_last_time": ("Minamp hit an error last time", "Minamp tivo un erro a última vez"), + "error_last_time": ("Plexamp Lite hit an error last time", "Plexamp Lite tivo un erro a última vez"), "min": ("%1$d min", "%1$d min"), "h_min": ("%1$d h %2$d min", "%1$d h %2$d min"), @@ -153,7 +153,7 @@ S = { "save_to_sd": ("Save to SD card", "Gardar na tarxeta SD"), "test_streaming": ("Test streaming", "Probar reprodución"), "no_sd": ("No SD card available", "Non hai tarxeta SD dispoñible"), - "saved_log": ("Saved as Minamp-log.txt on the SD card", "Gardado como Minamp-log.txt na tarxeta SD"), + "saved_log": ("Saved as PlexampLite-log.txt on the SD card", "Gardado como PlexampLite-log.txt na tarxeta SD"), "cant_save": ("Couldn't save: %1$s", "Non se puido gardar: %1$s"), "testing": ("Testing… (about 30 s)", "Probando… (uns 30 s)"), @@ -255,8 +255,10 @@ S = { "dl_quality_original": ("Original MP3s, others 320 kbps", "MP3 orixinais, o resto a 320 kbps"), "set_delete_downloads": ("Delete all downloads (%1$s)", "Borrar todas as descargas (%1$s)"), "downloaded": ("Downloaded", "Descargada"), - "quit_app": ("Close Minamp", "Pechar Minamp"), - "stalled": ("Playback is stuck. Try pausing and playing again.", "A reprodución quedou parada. Proba a pausar e reproducir de novo."), + "quit_app": ("Close Plexamp Lite", "Pechar Plexamp Lite"), + "stalled": ("Playback got stuck: the network isn't keeping up.", "A reprodución quedou parada: a rede non dá abasto."), + "quality_bt_title": ("Quality over Bluetooth", "Calidade por Bluetooth"), + "set_quality_bt": ("Quality over Bluetooth: %1$s", "Calidade por Bluetooth: %1$s"), # pure-Java layers (looked up by name through com.minamp.util.Tr) "tr_kind_home": ("Home network", "Rede da casa"),