Microphone support

This commit is contained in:
Caten
2026-01-08 22:55:51 +08:00
parent 68ca11e7ed
commit 8e07f57998
12 changed files with 317 additions and 11 deletions

View File

@@ -109,5 +109,7 @@
"updateRequest": "Please try to use the latest version. Visit the project address to check for the latest version.",
"avncScreenResize": "Adaptive Screen Size",
"avncResizeFactor": "Screen Scaling Ratio",
"avncResizeFactorValue": "Current scaling is"
"avncResizeFactorValue": "Current scaling is",
"microphoneSupport": "Microphone Support",
"startStreaming": "Start Microphone"
}

View File

@@ -109,5 +109,7 @@
"updateRequest": "请尽量使用最新版本。前往项目地址可查看最新版本。",
"avncScreenResize": "自适应屏幕尺寸",
"avncResizeFactor": "屏幕缩放比",
"avncResizeFactorValue": "当前缩放为"
"avncResizeFactorValue": "当前缩放为",
"microphoneSupport": "麦克风支持",
"startStreaming": "开启麦克风"
}

View File

@@ -109,5 +109,7 @@
"updateRequest": "請盡量使用最新版本。前往專案網址查看最新版本。",
"avncScreenResize": "自適應螢幕尺寸",
"avncResizeFactor": "螢幕縮放比",
"avncResizeFactorValue": "目前縮放為"
"avncResizeFactorValue": "目前縮放為",
"microphoneSupport": "麥克風支援",
"startStreaming": "開啟麥克風"
}

View File

@@ -170,7 +170,7 @@ class SettingPage extends StatefulWidget {
class _SettingPageState extends State<SettingPage> {
final List<bool> _expandState = [false, false, false, false, false, false];
final List<bool> _expandState = [false, false, false, false, false, false, false];
double _avncScaleFactor = Util.getGlobal("avncScaleFactor") as double;
@@ -602,6 +602,37 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
setState(() {});
},),
],))),
ExpansionPanel(
isExpanded: _expandState[6],
headerBuilder: ((context, isExpanded) {
return ListTile(title: Text(AppLocalizations.of(context)!.microphoneSupport), subtitle: Text(AppLocalizations.of(context)!.experimentalFeature));
}), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [
const SizedBox.square(dimension: 16),
SwitchListTile(title: Text(AppLocalizations.of(context)!.startStreaming), value: G.isStreaming, onChanged:(value) async {
if (value) {
await Permission.microphone.request();
if (await Permission.microphone.isGranted) {
String path = "/tmp/android_audio";
D.androidChannel.invokeMethod("startStreaming", {"path": "${G.dataPath}/containers/${G.currentContainer}$path"});
Util.termWrite("""
pactl load-module module-null-sink sink_name=AndroidSink sink_properties=device.description="Android_Audio_Stream"
pactl load-module module-remap-source master=AndroidSink.monitor source_name=AndroidMic source_properties=device.description="Android_Virtual_Mic"
pkill -f tiny_virtual_mic
tiny_virtual_mic $path AndroidSink &""");
G.pageIndex.value = 0;
}
} else {
Util.termWrite("""
pactl list short modules | grep "Android" | cut -f1 | xargs -L1 pactl unload-module
pkill -f tiny_virtual_mic""");
G.pageIndex.value = 0;
D.androidChannel.invokeMethod("stopStreaming", {});
}
G.isStreaming = value;
setState(() {});
},),
const SizedBox.square(dimension: 16),
],))),
],);
}
}

View File

@@ -123,7 +123,6 @@ class Util {
case "avncResizeDesktop" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(true);
case "avncScaleFactor" : return b ? G.prefs.getDouble(key)!.clamp(-1.0, 1.0) : (value){G.prefs.setDouble(key, value); return value;}(-0.5);
case "useX11" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
case "defaultFFmpegCommand" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("-hide_banner -an -max_delay 1000000 -r 30 -f android_camera -camera_index 0 -i 0:0 -vf scale=iw/2:-1 -rtsp_transport udp -f rtsp rtsp://127.0.0.1:8554/stream");
case "defaultVirglCommand" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("--use-egl-surfaceless --use-gles --socket-path=\$CONTAINER_DIR/tmp/.virgl_test");
case "defaultVirglOpt" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("GALLIUM_DRIVER=virpipe");
case "defaultTurnipOpt" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("MESA_LOADER_DRIVER_OVERRIDE=zink VK_ICD_FILENAMES=/home/tiny/.local/share/tiny/extra/freedreno_icd.aarch64.json TU_DEBUG=noconform");
@@ -512,11 +511,7 @@ class G {
static late VirtualKeyboard keyboard; //存储ctrl, shift, alt状态
static bool maybeCtrlJ = false; //为了区分按下的ctrl+J和enter而准备的变量
static ValueNotifier<double> termFontScale = ValueNotifier(1); //终端字体大小存储为G.prefs的termFontScale
static bool isStreamServerStarted = false;
static bool isStreaming = false;
//static int? streamingPid;
static String streamingOutput = "";
static late Pty streamServerPty;
//static int? virglPid;
static ValueNotifier<int> pageIndex = ValueNotifier(0); //主界面索引
static ValueNotifier<bool> terminalPageChange = ValueNotifier(true); //更改值,用于刷新小键盘
@@ -527,7 +522,6 @@ class G {
static bool wasAvncEnabled = false;
static bool wasX11Enabled = false;
static late SharedPreferences prefs;
}
@@ -776,6 +770,7 @@ ${G.dataPath}/bin/virgl_test_server ${Util.getGlobal("defaultVirglCommand")}""")
}
extraMount += "--mount=\$DATA_DIR/tiny/font:/usr/share/fonts/tiny ";
extraMount += "--mount=\$DATA_DIR/tiny/extra/cmatrix:/home/tiny/.local/bin/cmatrix ";
extraMount += "--mount=\$DATA_DIR/tiny/extra/tiny_virtual_mic:/home/tiny/.local/bin/tiny_virtual_mic ";
Util.termWrite(
"""
export DATA_DIR=${G.dataPath}