# -*- coding: utf-8 -*- """手表端:音色选择 + 播放电脑音乐(用真实的 client.call / sendCommand)。""" from __future__ import annotations import sys from pathlib import Path MAIN = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\android\src" r"\com\lanremote\watch\MainActivity.java") OLD_ROW = ''' addRow(grid, action("语音播报", new Runnable() { public void run() { promptSay(); } }), action("弹通知", new Runnable() { public void run() { promptNotify(); } })); ''' NEW_ROW = ''' addRow(grid, action("语音播报", new Runnable() { public void run() { promptSay(); } }), action("音色", new Runnable() { public void run() { pickVoice(); } })); addRow(grid, action("电脑音乐", new Runnable() { public void run() { pickLocalAudio(); } }), action("弹通知", new Runnable() { public void run() { promptNotify(); } })); ''' ANCHOR = ''' private void promptSay() {''' NEW_METHODS = ''' /** 选择电脑上的 TTS 音色。 */ private void pickVoice() { appendLog("正在获取电脑音色…"); io.execute(new Runnable() { @Override public void run() { try { final Map reply = client.call(Json.obj("cmd", "voice_list"), 12000); final List voices = stringList(reply, "voices"); ui.post(new Runnable() { @Override public void run() { if (voices.isEmpty()) { toast("电脑上没读到音色,或没连上"); return; } List labels = new ArrayList(); labels.add("系统默认"); labels.addAll(voices); showChooser("选择播报音色", labels, new Chooser() { @Override public void onPick(int index) { String chosen = index == 0 ? "" : voices.get(index - 1); sendCommand(Json.obj("cmd", "set_voice", "voice", chosen), "设置音色"); } }); } }); } catch (final IOException e) { postError("获取音色", e); } } }); } /** 选一个电脑上的音频文件直接播放。 */ private void pickLocalAudio() { appendLog("正在获取电脑音乐…"); io.execute(new Runnable() { @Override public void run() { try { final Map reply = client.call(Json.obj("cmd", "audio_list"), 15000); final List names = stringList(reply, "names"); final List paths = stringList(reply, "paths"); ui.post(new Runnable() { @Override public void run() { if (names.isEmpty() || names.size() != paths.size()) { toast("电脑音乐目录里没有音频文件"); return; } showChooser("选择要播放的音乐", names, new Chooser() { @Override public void onPick(int index) { sendCommand(Json.obj("cmd", "play_local", "path", paths.get(index)), "播放 " + names.get(index)); } }); } }); } catch (final IOException e) { postError("获取音乐列表", e); } } }); } /** 把回复里的字符串数组取出来。 */ @SuppressWarnings("unchecked") private static List stringList(Map reply, String key) { List out = new ArrayList(); try { Object raw = reply == null ? null : reply.get(key); if (raw instanceof List) { for (Object item : (List) raw) { if (item != null) { out.add(String.valueOf(item)); } } } } catch (Exception ignored) { // 结构不对就返回空 } return out; } private void promptSay() {''' DIALOG_ANCHOR = ''' private Button bigButton(String text, int color, float sizeSp) {''' DIALOG = ''' /** 简单的列表选择框。 */ private interface Chooser { void onPick(int index); } private void showChooser(String title, List items, final Chooser chooser) { final String[] array = items.toArray(new String[0]); new AlertDialog.Builder(this) .setTitle(title) .setItems(array, new android.content.DialogInterface.OnClickListener() { @Override public void onClick(android.content.DialogInterface dialog, int which) { chooser.onPick(which); } }) .setNegativeButton("取消", null) .show(); } private Button bigButton(String text, int color, float sizeSp) {''' def main() -> int: text = MAIN.read_text(encoding="utf-8") ok = True for old, new, tag in ((OLD_ROW, NEW_ROW, "按钮"), (ANCHOR, NEW_METHODS, "处理方法"), (DIALOG_ANCHOR, DIALOG, "选择框")): if old not in text: print(f" [失败] {tag} 锚点未匹配") ok = False else: text = text.replace(old, new, 1) print(f" {tag}: OK") if ok: MAIN.write_text(text, encoding="utf-8") return 0 if ok else 1 if __name__ == "__main__": sys.exit(main())