Import minamp 1.0 source

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xockoandClaude Opus 5.5 committed 2026-10-14 19:38:37 +02:00
commit 0df8124629
194 files changed
+7319

No files matched your search

+290
View File
@@ -0,0 +1,290 @@
package com.minamp;
import java.util.List;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.minamp.plex.Plex;
import com.minamp.plex.Server;
import com.minamp.util.Json;
/** Sign in with a plex.tv/link code (or a manual address), then pick a server and a music library. */
public class SetupActivity extends BaseActivity {
public static final String EXTRA_MODE = "mode";
public static final int MODE_WELCOME = 0, MODE_SERVER = 1, MODE_LIBRARY = 2;
private View welcome, pinPage, manual, choose, busy;
private TextView pinCode, pinStatus, busyText, chooseTitle, chooseSub;
private LinearLayout chooseList;
private Runnable chooseBack;
private long pinId;
private long pinStarted;
private int pinSeq;
@Override
protected void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.activity_setup);
welcome = findViewById(R.id.page_welcome);
pinPage = findViewById(R.id.page_pin);
manual = findViewById(R.id.page_manual);
choose = findViewById(R.id.page_choose);
busy = findViewById(R.id.page_busy);
pinCode = (TextView) findViewById(R.id.pin_code);
pinStatus = (TextView) findViewById(R.id.pin_status);
busyText = (TextView) findViewById(R.id.busy_text);
chooseTitle = (TextView) findViewById(R.id.choose_title);
chooseSub = (TextView) findViewById(R.id.choose_sub);
chooseList = (LinearLayout) findViewById(R.id.choose_list);
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_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() {
public void onClick(View v) { if (chooseBack != null) chooseBack.run(); else show(welcome); }
});
int mode = getIntent().getIntExtra(EXTRA_MODE, MODE_WELCOME);
String account = app.prefs.getString("account", null);
if (mode == MODE_LIBRARY && app.server != null) {
loadSections(app.server, null);
} else if (mode == MODE_SERVER && account != null) {
loadServers(account);
} else {
show(welcome);
}
}
@Override
protected void onDestroy() {
pinSeq++;
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(android.view.Menu menu) { return false; }
private void show(View page) {
View[] all = {welcome, pinPage, manual, choose, busy};
for (int i = 0; i < all.length; i++) all[i].setVisibility(all[i] == page ? View.VISIBLE : View.GONE);
}
private void showBusy(String text) {
busyText.setText(text);
show(busy);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && welcome.getVisibility() != View.VISIBLE && app.isConfigured() == false) {
pinSeq++;
show(welcome);
return true;
}
return super.onKeyDown(keyCode, event);
}
// ------------------------------------------------------------------ PIN sign-in
private void startPin() {
showBusy("Contacting plex.tv…\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);
}
public void fail(Exception e) {
if (my != pinSeq) return;
show(welcome);
toast("Couldn't reach plex.tv: " + msg(e));
}
});
}
private void pollPin(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");
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);
}
});
}
}, 2500);
}
private void signedIn(final String account) {
showBusy("Signed in. Finding your servers…");
app.prefs.edit().putString("account", account).commit();
run(new Task<String>() {
public String work() throws Exception { return Plex.username(account); }
public void done(String u) { app.prefs.edit().putString("username", u).commit(); }
});
loadServers(account);
}
private void loadServers(final String account) {
showBusy("Finding your servers…");
run(new Task<List<Server>>() {
public List<Server> work() throws Exception { return Plex.servers(account); }
public void done(final List<Server> servers) {
if (servers.isEmpty()) {
show(welcome);
toast("No Plex Media Servers on this account");
return;
}
if (servers.size() == 1) { pickServer(servers.get(0), null); return; }
chooseTitle.setText("Choose a server");
chooseSub.setText("Signed in as " + app.prefs.getString("username", "you"));
chooseList.removeAllViews();
for (int i = 0; i < servers.size(); i++) {
final Server s = servers.get(i);
int remote = 0, local = 0;
for (int k = 0; k < s.connections.size(); k++) {
int kind = s.connections.get(k).kind;
if (kind == Server.LOCAL || kind == Server.LOCAL_HTTP) local++; else remote++;
}
String sub = (s.owned ? "Yours" : "Shared with you") + " · " + (local > 0 ? "home + " : "") + (remote > 0 ? "remote" : "local only");
addChoice(s.name, sub, new View.OnClickListener() {
public void onClick(View v) { pickServer(s, new Runnable() { public void run() { done(servers); } }); }
});
}
chooseBack = new Runnable() { public void run() { show(welcome); } };
show(choose);
}
public void fail(Exception e) {
show(welcome);
toast("Couldn't list servers: " + msg(e));
}
});
}
private void addChoice(String title, String sub, View.OnClickListener l) {
View row = getLayoutInflater().inflate(R.layout.row_choice, chooseList, false);
((TextView) row.findViewById(R.id.choice_title)).setText(title);
((TextView) row.findViewById(R.id.choice_sub)).setText(sub);
row.setOnClickListener(l);
chooseList.addView(row);
}
private void pickServer(final Server s, final Runnable back) {
showBusy("Connecting to " + s.name + "…\nTrying home network, then remote, then relay.");
run(new Task<Server.Conn>() {
public Server.Conn work() throws Exception { return s.pick(); }
public void done(Server.Conn c) {
loadSections(s, back);
}
public void fail(Exception e) {
if (back != null) back.run(); else show(welcome);
toast(msg(e));
}
});
}
// ------------------------------------------------------------------ manual
private void connectManual() {
String url = ((EditText) findViewById(R.id.edit_url)).getText().toString().trim();
String token = ((EditText) findViewById(R.id.edit_token)).getText().toString().trim();
if (url.length() == 0) { toast("Enter your server's address"); return; }
final Server s = new Server();
s.name = "Plex server";
s.token = token;
s.add(Server.normalizeManual(url), Server.MANUAL);
showBusy("Connecting…");
run(new Task<String>() {
public String work() throws Exception {
s.pick();
Json.Obj mc = s.get("/");
return mc == null ? "" : mc.optString("friendlyName", "");
}
public void done(String name) {
if (name.length() > 0) s.name = name;
loadSections(s, new Runnable() { public void run() { show(manual); } });
}
public void fail(Exception e) {
show(manual);
boolean auth = e instanceof Plex.PlexException && ((Plex.PlexException) e).code == 401;
toast(auth ? "The server wants a token (or sign in with Plex instead)" : msg(e));
}
});
}
// ------------------------------------------------------------------ libraries
private void loadSections(final Server s, final Runnable back) {
showBusy("Loading libraries…");
run(new Task<List<Server.Section>>() {
public List<Server.Section> work() throws Exception { return s.musicSections(); }
public void done(List<Server.Section> secs) {
if (secs.isEmpty()) {
if (back != null) back.run(); else show(welcome);
toast(s.name + " has no music libraries");
return;
}
if (secs.size() == 1) { finishWith(s, secs.get(0)); return; }
chooseTitle.setText("Choose a music library");
chooseSub.setText(s.name);
chooseList.removeAllViews();
for (int i = 0; i < secs.size(); i++) {
final Server.Section sec = secs.get(i);
addChoice(sec.title, "Music", new View.OnClickListener() {
public void onClick(View v) { finishWith(s, sec); }
});
}
chooseBack = back != null ? back : new Runnable() { public void run() { finish(); } };
show(choose);
}
public void fail(Exception e) {
if (back != null) back.run(); else show(welcome);
toast(msg(e));
}
});
}
private void finishWith(Server s, Server.Section sec) {
boolean sameServer = app.server != null && app.server.machineId.equals(s.machineId) && s.machineId.length() > 0;
if (!sameServer || app.server != s) {
if (!sameServer) {
PlayerService.send(this, PlayerService.ACTION_STOP);
PlayQueue.get().clear();
}
app.saveServer(s);
}
app.saveSection(sec.key, sec.title);
startActivity(new Intent(this, HomeActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
finish();
}
}