Private
Public Access
Minamp 1.2
- Transcoding: send client identities Plex has a profile for (unknown ones get 400 "unable to find a matching profile"), with a fresh session id per variant - Stream proxy: fetch transcodes once into a temp file and serve every player request from it, so reconnects no longer restart the transcode (503s, tracks cut short); original files still pass Range requests through - Sign-in: remember the pending link code so it survives Minamp being closed while the code is entered elsewhere; add "I've entered it - check now" - Diagnostics: in-app connection log (DiagLog) with a streaming test and save to SD card; tokens are never logged Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0a2ac901bd
commit
a4b875ef34
12 files changed
+701
-196
No files matched your search
@@ -397,6 +397,7 @@ public abstract class BaseActivity extends Activity implements PlayerService.Lis
|
||||
"Library: " + app.sectionTitle(),
|
||||
"Server: " + (s == null ? "-" : s.name),
|
||||
"Connection: " + conn,
|
||||
"Connection log & streaming test",
|
||||
"Sign out",
|
||||
};
|
||||
new AlertDialog.Builder(this)
|
||||
@@ -424,7 +425,8 @@ public abstract class BaseActivity extends Activity implements PlayerService.Lis
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 6: confirmSignOut(); break;
|
||||
case 6: showDiagnostics(); break;
|
||||
case 7: confirmSignOut(); break;
|
||||
}
|
||||
}
|
||||
}).show();
|
||||
@@ -432,6 +434,108 @@ public abstract class BaseActivity extends Activity implements PlayerService.Lis
|
||||
|
||||
protected void onConnectionChanged() {}
|
||||
|
||||
// ------------------------------------------------------------------ diagnostics
|
||||
|
||||
/** Connection log with "test streaming" and "save to SD card", for reporting problems. */
|
||||
protected void showDiagnostics() {
|
||||
final android.widget.ScrollView sv = new android.widget.ScrollView(this);
|
||||
final TextView tv = new TextView(this);
|
||||
tv.setTextSize(9);
|
||||
tv.setTextColor(0xFFDDDDDD);
|
||||
tv.setTypeface(android.graphics.Typeface.MONOSPACE);
|
||||
int p = Ui.dp(this, 6);
|
||||
tv.setPadding(p, p, p, p);
|
||||
String log = com.minamp.net.DiagLog.dump();
|
||||
tv.setText(log.length() > 0 ? log : "Nothing logged yet.");
|
||||
sv.addView(tv);
|
||||
AlertDialog.Builder b = new AlertDialog.Builder(this)
|
||||
.setTitle("Connection log")
|
||||
.setView(sv)
|
||||
.setNegativeButton("Save to SD card", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface d, int w) { saveDiagnostics(); }
|
||||
})
|
||||
.setPositiveButton("Close", null);
|
||||
if (app.library != null) {
|
||||
b.setNeutralButton("Test streaming", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface d, int w) { testStreaming(); }
|
||||
});
|
||||
}
|
||||
AlertDialog dlg = b.create();
|
||||
dlg.show();
|
||||
sv.post(new Runnable() { public void run() { sv.fullScroll(View.FOCUS_DOWN); } });
|
||||
}
|
||||
|
||||
private void saveDiagnostics() {
|
||||
try {
|
||||
if (!android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState())) {
|
||||
toast("No SD card available");
|
||||
return;
|
||||
}
|
||||
java.io.File f = new java.io.File(android.os.Environment.getExternalStorageDirectory(), "Minamp-log.txt");
|
||||
java.io.FileOutputStream o = new java.io.FileOutputStream(f);
|
||||
String head = "Minamp " + 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();
|
||||
toast("Saved as Minamp-log.txt on the SD card");
|
||||
} catch (Exception e) {
|
||||
toast("Couldn't save: " + msg(e));
|
||||
}
|
||||
}
|
||||
|
||||
/** Asks the server about every transcode variant for one track, and logs exactly what it says. */
|
||||
private void testStreaming() {
|
||||
final Library lib = lib();
|
||||
final Item current = PlayQueue.get().current();
|
||||
toast("Testing\u2026 (about 30 s)");
|
||||
run(new Task<Object>() {
|
||||
public Object work() throws Exception {
|
||||
com.minamp.net.DiagLog.log("=== streaming test ===");
|
||||
Item t = current;
|
||||
if (t == null) {
|
||||
List<Item> r = lib.libraryRadio();
|
||||
if (r.isEmpty()) throw new Exception("no tracks in the library");
|
||||
t = r.get(0);
|
||||
}
|
||||
lib.ensureMedia(t);
|
||||
com.minamp.net.DiagLog.log("track: " + t.title + " [" + t.codec + "/" + t.container + " " + t.bitrate + " kbps] via "
|
||||
+ (lib.server.active() == null ? "?" : Server.kindLabel(lib.server.active().kind)));
|
||||
int kbps = app.currentMaxKbps();
|
||||
if (kbps <= 0) kbps = 320;
|
||||
for (int v = 0; v < Library.VARIANTS; v++) {
|
||||
com.minamp.net.DiagLog.log("variant " + v + " (" + Library.VARIANT_NAMES[v] + ") decision: " + lib.decision(t, kbps, v));
|
||||
String session = "minamp-test-" + System.currentTimeMillis() + "-" + v;
|
||||
String url = lib.transcodeUrl(t, kbps, 0, session, v);
|
||||
com.minamp.net.Http.Response r = null;
|
||||
try {
|
||||
r = com.minamp.net.Http.get(url, null, 30000);
|
||||
if (r.code < 400) {
|
||||
byte[] buf = new byte[4096];
|
||||
int n = r.body.read(buf);
|
||||
boolean mp3 = n > 3 && ((buf[0] == 'I' && buf[1] == 'D' && buf[2] == '3') || ((buf[0] & 0xFF) == 0xFF && (buf[1] & 0xE0) == 0xE0));
|
||||
com.minamp.net.DiagLog.log("variant " + v + " start: " + r.code + ", " + r.header("content-type")
|
||||
+ ", first bytes " + (mp3 ? "look like MP3" : "are NOT MP3"));
|
||||
} else {
|
||||
com.minamp.net.DiagLog.log("variant " + v + " start: " + r.code + " " + com.minamp.plex.Plex.snippet(r.readString()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
com.minamp.net.DiagLog.log("variant " + v + " start failed: " + com.minamp.net.Threads.describe(e));
|
||||
} finally {
|
||||
com.minamp.net.Http.abort(r);
|
||||
lib.stopTranscode(session);
|
||||
}
|
||||
}
|
||||
com.minamp.net.DiagLog.log("=== end of test ===");
|
||||
return null;
|
||||
}
|
||||
public void done(Object o) { showDiagnostics(); }
|
||||
public void fail(Exception e) {
|
||||
com.minamp.net.DiagLog.log("streaming test failed: " + msg(e));
|
||||
showDiagnostics();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String qualityLabel(int kbps) {
|
||||
for (int i = 0; i < App.QUALITIES.length; i++) if (App.QUALITIES[i] == kbps) return App.QUALITY_LABELS[i];
|
||||
return kbps + " kbps";
|
||||
|
||||
Reference in new issue
Block a user