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
@@ -47,7 +47,9 @@ public class SetupActivity extends BaseActivity {
|
||||
|
||||
findViewById(R.id.btn_signin).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { startPin(); } });
|
||||
findViewById(R.id.btn_manual).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { show(manual); } });
|
||||
findViewById(R.id.btn_pin_cancel).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { pinSeq++; show(welcome); } });
|
||||
findViewById(R.id.btn_pin_cancel).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { pinSeq++; clearPendingPin(); show(welcome); } });
|
||||
findViewById(R.id.btn_pin_check).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { checkPinNow(pinSeq); } });
|
||||
findViewById(R.id.btn_setup_log).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { showDiagnostics(); } });
|
||||
findViewById(R.id.btn_manual_back).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { show(welcome); } });
|
||||
findViewById(R.id.btn_manual_go).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { connectManual(); } });
|
||||
findViewById(R.id.btn_choose_back).setOnClickListener(new View.OnClickListener() {
|
||||
@@ -60,7 +62,7 @@ public class SetupActivity extends BaseActivity {
|
||||
loadSections(app.server, null);
|
||||
} else if (mode == MODE_SERVER && account != null) {
|
||||
loadServers(account);
|
||||
} else {
|
||||
} else if (!resumePendingPin()) {
|
||||
show(welcome);
|
||||
}
|
||||
}
|
||||
@@ -96,21 +98,21 @@ public class SetupActivity extends BaseActivity {
|
||||
|
||||
// ------------------------------------------------------------------ PIN sign-in
|
||||
|
||||
private int pinChecks;
|
||||
private boolean pinCheckRunning;
|
||||
|
||||
private void startPin() {
|
||||
showBusy("Contacting plex.tv…\n(the first secure connection takes a few seconds on this phone)");
|
||||
clearPendingPin();
|
||||
showBusy("Contacting plex.tv\u2026\n(the first secure connection takes a few seconds on this phone)");
|
||||
final int my = ++pinSeq;
|
||||
run(new Task<Plex.Pin>() {
|
||||
public Plex.Pin work() throws Exception { return Plex.createPin(); }
|
||||
public void done(Plex.Pin p) {
|
||||
if (my != pinSeq) return;
|
||||
pinId = p.id;
|
||||
pinStarted = System.currentTimeMillis();
|
||||
StringBuilder spaced = new StringBuilder();
|
||||
for (int i = 0; i < p.code.length(); i++) { if (i > 0) spaced.append(' '); spaced.append(p.code.charAt(i)); }
|
||||
pinCode.setText(spaced.toString());
|
||||
pinStatus.setText("Waiting for you to link…");
|
||||
show(pinPage);
|
||||
pollPin(my);
|
||||
// Remember the code: the phone may close Minamp 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());
|
||||
}
|
||||
public void fail(Exception e) {
|
||||
if (my != pinSeq) return;
|
||||
@@ -120,30 +122,84 @@ public class SetupActivity extends BaseActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void pollPin(final int my) {
|
||||
/** Resume waiting for a code created earlier (Minamp 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);
|
||||
long start = app.prefs.getLong("pinStart", 0);
|
||||
if (id == 0 || code == null || System.currentTimeMillis() - start > 14 * 60 * 1000) {
|
||||
clearPendingPin();
|
||||
return false;
|
||||
}
|
||||
com.minamp.net.DiagLog.log("resuming sign-in code " + code);
|
||||
showPin(id, code, start);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void clearPendingPin() {
|
||||
app.prefs.edit().remove("pinId").remove("pinCode").remove("pinStart").commit();
|
||||
}
|
||||
|
||||
private void showPin(long id, String code, long started) {
|
||||
pinId = id;
|
||||
pinStarted = started;
|
||||
pinChecks = 0;
|
||||
StringBuilder spaced = new StringBuilder();
|
||||
for (int i = 0; i < code.length(); i++) { if (i > 0) spaced.append(' '); spaced.append(code.charAt(i)); }
|
||||
pinCode.setText(spaced.toString());
|
||||
pinStatus.setText("Waiting for you to link\u2026");
|
||||
show(pinPage);
|
||||
int my = ++pinSeq;
|
||||
checkPinNow(my);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
// back from typing the code somewhere else: check straight away
|
||||
if (pinPage != null && pinPage.getVisibility() == View.VISIBLE && !pinCheckRunning) checkPinNow(pinSeq);
|
||||
}
|
||||
|
||||
private void schedulePinCheck(final int my) {
|
||||
app.handler.postDelayed(new Runnable() {
|
||||
public void run() {
|
||||
if (my != pinSeq || destroyed) return;
|
||||
if (System.currentTimeMillis() - pinStarted > 14 * 60 * 1000) {
|
||||
pinStatus.setText("Code expired — go back and try again");
|
||||
public void run() { checkPinNow(my); }
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
private void checkPinNow(final int my) {
|
||||
if (my != pinSeq || destroyed || pinCheckRunning) return;
|
||||
long age = System.currentTimeMillis() - pinStarted;
|
||||
if (age > 14 * 60 * 1000) {
|
||||
pinStatus.setText("Code expired \u2014 press Cancel and sign in again");
|
||||
clearPendingPin();
|
||||
return;
|
||||
}
|
||||
pinCheckRunning = true;
|
||||
run(new Task<String>() {
|
||||
public String work() throws Exception { return Plex.checkPin(pinId); }
|
||||
public void done(String token) {
|
||||
pinCheckRunning = false;
|
||||
if (my != pinSeq) return;
|
||||
pinChecks++;
|
||||
if (token == null) {
|
||||
long left = (14 * 60 * 1000 - (System.currentTimeMillis() - pinStarted)) / 60000;
|
||||
pinStatus.setText("Not linked yet \u00b7 checked " + pinChecks + "\u00d7 \u00b7 " + left + " min left");
|
||||
schedulePinCheck(my);
|
||||
return;
|
||||
}
|
||||
SetupActivity.this.run(new Task<String>() {
|
||||
public String work() throws Exception { return Plex.checkPin(pinId); }
|
||||
public void done(String token) {
|
||||
if (my != pinSeq) return;
|
||||
if (token == null) { pollPin(my); return; }
|
||||
pinSeq++;
|
||||
signedIn(token);
|
||||
}
|
||||
public void fail(Exception e) {
|
||||
if (my != pinSeq) return;
|
||||
pinStatus.setText("Retrying… (" + msg(e) + ")");
|
||||
pollPin(my);
|
||||
}
|
||||
});
|
||||
pinStatus.setText("Linked!");
|
||||
pinSeq++;
|
||||
clearPendingPin();
|
||||
signedIn(token);
|
||||
}
|
||||
}, 2500);
|
||||
public void fail(Exception e) {
|
||||
pinCheckRunning = false;
|
||||
if (my != pinSeq) return;
|
||||
pinChecks++;
|
||||
pinStatus.setText("Check " + pinChecks + " failed: " + msg(e) + " \u2014 retrying");
|
||||
schedulePinCheck(my);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void signedIn(final String account) {
|
||||
|
||||
Reference in new issue
Block a user