Skip to content

Commit 0336a9a

Browse files
authored
Merge pull request #64 from teamclouday/improve-adb
Improve adb and others
2 parents e0c833c + c30cf0f commit 0336a9a

File tree

6 files changed

+125
-53
lines changed

6 files changed

+125
-53
lines changed

Android/app/src/main/java/com/example/androidMic/domain/streaming/AdbStreamer.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.example.androidMic.domain.streaming
22

3+
import Message
34
import android.os.Messenger
45
import android.util.Log
56
import com.example.androidMic.domain.service.AudioPacket
@@ -31,7 +32,7 @@ class AdbStreamer(private val scope: CoroutineScope) : Streamer {
3132
// create socket
3233
socket = Socket()
3334
try {
34-
socket?.connect(InetSocketAddress(address, 6000), MAX_WAIT_TIME)
35+
socket?.connect(InetSocketAddress(address, 55555), MAX_WAIT_TIME)
3536
} catch (e: IOException) {
3637
Log.d(TAG, "connect [Socket]: ${e.message}")
3738
null

RustApp/src/app.rs

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ use crate::{
2222
message::{AppMsg, ConfigMsg},
2323
streamer::{self, ConnectOption, Status, StreamerCommand, StreamerMsg},
2424
utils::APP_ID,
25-
view::{advanced_window, view_app, AudioWave},
25+
view::{advanced_window, main_window, AudioWave},
2626
};
2727
use zconf::ConfigManager;
2828

2929
pub fn run_ui(config: ConfigManager<Config>) {
3030
let flags = Flags { config };
31+
let settings = Settings::default().no_main_window(true);
3132

32-
cosmic::app::run::<AppState>(Settings::default(), flags).unwrap();
33+
cosmic::app::run::<AppState>(settings, flags).unwrap();
3334
}
3435

3536
#[derive(Clone)]
@@ -98,11 +99,12 @@ pub struct AppState {
9899
pub audio_stream: Option<cpal::Stream>,
99100
pub audio_wave: AudioWave,
100101
pub state: State,
101-
pub advanced_window: Option<AdvancedWindow>,
102+
pub main_window: Option<CustomWindow>,
103+
pub advanced_window: Option<CustomWindow>,
102104
pub logs: String,
103105
}
104106

105-
pub struct AdvancedWindow {
107+
pub struct CustomWindow {
106108
pub window_id: window::Id,
107109
}
108110

@@ -196,6 +198,12 @@ impl Application for AppState {
196198
&self.core
197199
}
198200

201+
fn style(&self) -> Option<cosmic::iced_runtime::Appearance> {
202+
Some(cosmic::style::iced::application::appearance(
203+
&cosmic::theme::Theme::dark(),
204+
))
205+
}
206+
199207
fn core_mut(&mut self) -> &mut cosmic::app::Core {
200208
&mut self.core
201209
}
@@ -224,6 +232,15 @@ impl Application for AppState {
224232
None => audio_host.default_output_device(),
225233
};
226234

235+
let settings = window::Settings {
236+
size: Size::new(800.0, 600.0),
237+
position: window::Position::Centered,
238+
exit_on_close_request: true,
239+
..Default::default()
240+
};
241+
242+
let (new_id, command) = cosmic::iced::window::open(settings);
243+
227244
let app = Self {
228245
core,
229246
audio_stream: None,
@@ -234,11 +251,12 @@ impl Application for AppState {
234251
audio_devices,
235252
audio_wave: AudioWave::new(),
236253
state: State::Default,
254+
main_window: Some(CustomWindow { window_id: new_id }),
237255
advanced_window: None,
238256
logs: String::new(),
239257
};
240258

241-
(app, Task::none())
259+
(app, command.map(|_| cosmic::action::Action::None))
242260
}
243261

244262
fn update(&mut self, message: Self::Message) -> Task<Self::Message> {
@@ -309,17 +327,14 @@ impl Application for AppState {
309327
}
310328
None => {
311329
let settings = window::Settings {
312-
size: Size::new(500.0, 500.0),
313-
resizable: false,
330+
size: Size::new(500.0, 600.0),
314331
position: window::Position::Centered,
315-
decorations: false,
316-
transparent: true,
317-
level: window::Level::AlwaysOnTop,
332+
exit_on_close_request: true,
318333
..Default::default()
319334
};
320335

321-
let (new_id, command) = cosmic::iced::runtime::window::open(settings);
322-
self.advanced_window = Some(AdvancedWindow { window_id: new_id });
336+
let (new_id, command) = cosmic::iced::window::open(settings);
337+
self.advanced_window = Some(CustomWindow { window_id: new_id });
323338
return command.map(|_| cosmic::action::Action::None);
324339
}
325340
},
@@ -343,18 +358,27 @@ impl Application for AppState {
343358
self.config.update(|s| s.auto_connect = auto_connect);
344359
}
345360
},
361+
AppMsg::Shutdown => {
362+
return cosmic::iced_runtime::task::effect(Action::Exit);
363+
}
346364
}
347365

348366
Task::none()
349367
}
368+
350369
fn view(&self) -> Element<Self::Message> {
351-
view_app(self)
370+
self.view_window(self.core.main_window_id().unwrap())
352371
}
353372

354373
fn view_window(&self, id: window::Id) -> Element<Self::Message> {
355374
if let Some(window) = &self.advanced_window {
356375
if window.window_id == id {
357-
return advanced_window(self, window).map(AppMsg::Config);
376+
return advanced_window(self).map(AppMsg::Config);
377+
}
378+
}
379+
if let Some(window) = &self.main_window {
380+
if window.window_id == id {
381+
return main_window(self);
358382
}
359383
}
360384

@@ -364,4 +388,20 @@ impl Application for AppState {
364388
fn subscription(&self) -> cosmic::iced::Subscription<Self::Message> {
365389
Subscription::run(|| streamer::sub().map(AppMsg::Streamer))
366390
}
391+
392+
fn on_close_requested(&self, id: window::Id) -> Option<Self::Message> {
393+
if let Some(window) = &self.advanced_window {
394+
if window.window_id == id {
395+
return Some(AppMsg::AdvancedOptions);
396+
}
397+
}
398+
if let Some(window) = &self.main_window {
399+
if window.window_id == id {
400+
// close the app
401+
return Some(AppMsg::Shutdown);
402+
}
403+
}
404+
405+
None
406+
}
367407
}

RustApp/src/message.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub enum AppMsg {
1414
AdvancedOptions,
1515
Config(ConfigMsg),
1616
RefreshAudioDevices,
17+
Shutdown,
1718
}
1819

1920
#[derive(Debug, Clone)]

RustApp/src/streamer/adb_streamer.rs

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,38 @@ pub struct AdbStreamer {
1010
tcp_streamer: TcpStreamer,
1111
}
1212

13-
async fn remove_adb_reverse_proxy() -> Result<(), ConnectError> {
13+
async fn get_connected_devices() -> Result<Vec<String>, ConnectError> {
1414
let mut cmd = Command::new("adb");
15-
cmd.arg("reverse").arg("--remove").arg("tcp:6000");
15+
cmd.arg("devices");
16+
17+
let output = exec_cmd(cmd).await?;
18+
let mut devices = Vec::new();
19+
20+
// Skip the first line which is "List of devices attached"
21+
for line in output.lines().skip(1) {
22+
let parts: Vec<&str> = line.trim().split_whitespace().collect();
23+
if parts.len() >= 2 {
24+
devices.push(parts[0].to_string());
25+
}
26+
}
27+
28+
Ok(devices)
29+
}
30+
31+
async fn remove_adb_reverse_proxy(device_id: &str) -> Result<(), ConnectError> {
32+
let mut cmd = Command::new("adb");
33+
cmd.arg("-s")
34+
.arg(device_id)
35+
.arg("reverse")
36+
.arg("--remove")
37+
.arg("tcp:55555");
1638

1739
exec_cmd(cmd).await?;
1840

1941
Ok(())
2042
}
2143

22-
async fn exec_cmd(mut cmd: Command) -> Result<(), ConnectError> {
44+
async fn exec_cmd(mut cmd: Command) -> Result<String, ConnectError> {
2345
// https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
2446
#[cfg(target_os = "windows")]
2547
cmd.creation_flags(0x08000000);
@@ -34,22 +56,31 @@ async fn exec_cmd(mut cmd: Command) -> Result<(), ConnectError> {
3456
stderr,
3557
});
3658
}
37-
Ok(())
59+
let stdout = String::from_utf8_lossy(&status.stdout).trim().to_string();
60+
Ok(stdout)
3861
}
3962

4063
pub async fn new(producer: Producer<u8>) -> Result<AdbStreamer, ConnectError> {
4164
let tcp_streamer = tcp_streamer::new(str::parse("127.0.0.1").unwrap(), producer).await?;
4265

43-
if let Err(e) = remove_adb_reverse_proxy().await {
44-
warn!("remove adb reverse proxy: {e}");
66+
let devices = get_connected_devices().await?;
67+
if devices.is_empty() {
68+
return Err(ConnectError::NoAdbDevice);
4569
}
4670

47-
let mut cmd = Command::new("adb");
48-
cmd.arg("reverse")
49-
.arg(format!("tcp:{}", 6000))
50-
.arg(format!("tcp:{}", tcp_streamer.port));
51-
52-
exec_cmd(cmd).await?;
71+
for device_id in &devices {
72+
if let Err(e) = remove_adb_reverse_proxy(device_id).await {
73+
warn!("cannot remove adb proxy for device {device_id}: {e}");
74+
}
75+
76+
let mut cmd = Command::new("adb");
77+
cmd.arg("-s")
78+
.arg(device_id)
79+
.arg("reverse")
80+
.arg("tcp:55555")
81+
.arg(format!("tcp:{}", tcp_streamer.port));
82+
exec_cmd(cmd).await?;
83+
}
5384

5485
let streamer = AdbStreamer { tcp_streamer };
5586
Ok(streamer)
@@ -72,8 +103,12 @@ impl StreamerTrait for AdbStreamer {
72103
impl Drop for AdbStreamer {
73104
fn drop(&mut self) {
74105
tokio::task::spawn_blocking(|| async {
75-
if let Err(e) = remove_adb_reverse_proxy().await {
76-
warn!("drop AdbStreamer: {e}");
106+
let devices = get_connected_devices().await.unwrap_or_default();
107+
108+
for device_id in devices {
109+
if let Err(e) = remove_adb_reverse_proxy(&device_id).await {
110+
warn!("cannot remove adb proxy for device {device_id}: {e}");
111+
}
77112
}
78113
});
79114
}

RustApp/src/streamer/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ enum ConnectError {
7979
WriteError(#[from] WriteError),
8080
#[error("no usb device found: {0}")]
8181
NoUsbDevice(nusb::Error),
82+
#[error("no adb device found")]
83+
NoAdbDevice,
8284
#[error("can't open usb handle: {0}, make sure phone is set to charging only mode")]
8385
CantOpenUsbHandle(nusb::Error),
8486
#[error("can't open usb accessory: {0}")]

RustApp/src/view.rs

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,36 @@ use cosmic::{
44
Size,
55
},
66
widget::{
7-
button, canvas, column, container, horizontal_space, radio, row, scrollable, settings,
8-
text, toggler, vertical_space,
7+
button, canvas, column, container, radio, row, scrollable, settings, text, toggler,
8+
vertical_space,
99
},
1010
Element,
1111
};
1212
use cpal::traits::DeviceTrait;
1313

1414
use crate::{
15-
app::{AdvancedWindow, AppState, State},
15+
app::{AppState, State},
1616
config::{AudioFormat, ChannelCount, ConnectionMode, SampleRate},
1717
fl, icon_button,
1818
message::{AppMsg, ConfigMsg},
1919
};
2020

21-
pub fn view_app(app: &AppState) -> Element<'_, AppMsg> {
21+
pub fn main_window(app: &AppState) -> Element<'_, AppMsg> {
2222
row()
2323
.padding(50)
24+
.spacing(50)
2425
.push(
2526
column()
27+
.width(Length::FillPortion(2))
28+
.height(Length::Fill)
29+
.spacing(50)
2630
.push(logs(app))
27-
.push(vertical_space())
2831
.push(wave(app)),
2932
)
30-
.push(horizontal_space())
3133
.push(
3234
column()
35+
.width(Length::FillPortion(1))
36+
.height(Length::Fill)
3337
.align_x(Horizontal::Center)
3438
.push(audio(app))
3539
.push(vertical_space())
@@ -40,18 +44,17 @@ pub fn view_app(app: &AppState) -> Element<'_, AppMsg> {
4044

4145
fn logs(app: &AppState) -> Element<'_, AppMsg> {
4246
container(scrollable(text(&app.logs).width(Length::Fill)))
43-
.width(Length::FillPortion(2))
44-
.height(Length::FillPortion(2))
47+
.width(Length::Fill)
48+
.height(Length::FillPortion(3))
4549
.padding(13)
4650
.class(cosmic::theme::Container::Card)
4751
.into()
4852
}
4953

5054
fn wave(app: &AppState) -> Element<'_, AppMsg> {
5155
container(canvas(&app.audio_wave).width(Length::Fill))
52-
.width(Length::FillPortion(2))
56+
.width(Length::Fill)
5357
.height(Length::FillPortion(1))
54-
.padding(13)
5558
.into()
5659
}
5760

@@ -75,12 +78,7 @@ fn audio(app: &AppState) -> Element<'_, AppMsg> {
7578
))
7679
.push(icon_button!("refresh24").on_press(AppMsg::RefreshAudioDevices)),
7780
)
78-
.push(
79-
row()
80-
.spacing(20)
81-
.push(toggler(app.advanced_window.is_some()).on_toggle(|_| AppMsg::AdvancedOptions))
82-
.push(text(fl!("advanced"))),
83-
)
81+
.push(button::text(fl!("advanced")).on_press(AppMsg::AdvancedOptions))
8482
.into()
8583
}
8684

@@ -132,15 +130,13 @@ fn connect_button(app: &AppState) -> Element<'_, AppMsg> {
132130
.into()
133131
}
134132

135-
pub fn advanced_window<'a>(
136-
app: &'a AppState,
137-
_advanced_window: &'a AdvancedWindow,
138-
) -> Element<'a, ConfigMsg> {
133+
pub fn advanced_window(app: &AppState) -> Element<'_, ConfigMsg> {
139134
let config = app.config.data();
140135

141-
container(
136+
scrollable(
142137
column()
143138
.padding(50)
139+
.spacing(20)
144140
.push(settings::section().title(fl!("sample_rate")).add(pick_list(
145141
SampleRate::VALUES,
146142
Some(&config.sample_rate),
@@ -179,9 +175,6 @@ pub fn advanced_window<'a>(
179175
.add(toggler(config.auto_connect).on_toggle(ConfigMsg::AutoConnect)),
180176
),
181177
)
182-
.class(cosmic::theme::Container::Background)
183-
.center_x(Length::Fill)
184-
.center_y(Length::Fill)
185178
.into()
186179
}
187180

0 commit comments

Comments
 (0)