Skip to content

Commit fe7ee73

Browse files
committed
show all ips
1 parent 8ecf3f8 commit fe7ee73

File tree

9 files changed

+99
-25
lines changed

9 files changed

+99
-25
lines changed

src-tauri/Cargo.lock

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ rusqlite_migration = "1.3.1"
4242
base64 = "0.22.1"
4343
tauri-plugin-notification = "2.2.0"
4444
warp = "0.3.7"
45+
if-addrs = "0.13.3"
4546
[target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies]
4647
shell-words = "1.1.0"
4748
[target.'cfg(target_os = "windows")'.dependencies]

src-tauri/src/lib.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use tauri::{
77
use tokio::sync::Mutex;
88
use types::{
99
AppState, Channel, CustomChannel, CustomChannelExtraData, EPGNotify, Filters, Group, IdName,
10-
Settings, Source, EPG,
10+
NetworkInfo, Settings, Source, EPG,
1111
};
1212

1313
pub mod epg;
@@ -83,7 +83,8 @@ pub fn run() {
8383
on_start_check_epg,
8484
start_restream,
8585
stop_restream,
86-
watch_self
86+
watch_self,
87+
get_network_info
8788
])
8889
.setup(|app| {
8990
app.manage(Mutex::new(AppState {
@@ -417,6 +418,11 @@ async fn stop_restream(state: State<'_, Mutex<AppState>>) -> Result<(), String>
417418
}
418419

419420
#[tauri::command]
420-
async fn watch_self() -> Result<(), String> {
421-
restream::watch_self().await.map_err(map_err_frontend)
421+
async fn watch_self(port: u16) -> Result<(), String> {
422+
restream::watch_self(port).await.map_err(map_err_frontend)
423+
}
424+
425+
#[tauri::command]
426+
async fn get_network_info() -> Result<NetworkInfo, String> {
427+
restream::get_network_info().await.map_err(map_err_frontend)
422428
}

src-tauri/src/restream.rs

+35-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::{
44
};
55

66
use anyhow::{Context, Result};
7+
use if_addrs::IfAddr;
78
use tauri::State;
89
use tokio::{
910
fs,
@@ -15,10 +16,14 @@ use tokio::{
1516

1617
use crate::{
1718
log::log,
18-
mpv, sql,
19-
types::{AppState, Channel},
19+
mpv,
20+
settings::get_settings,
21+
sql,
22+
types::{AppState, Channel, NetworkInfo},
2023
};
2124

25+
const WAN_IP_API: &str = "https://api.ipify.org";
26+
2227
fn start_ffmpeg_listening(channel: Channel, restream_dir: PathBuf) -> Result<Child> {
2328
let headers = sql::get_channel_headers_by_id(channel.id.context("no channel id")?)?;
2429
let playlist_dir = get_playlist_dir(restream_dir);
@@ -128,9 +133,9 @@ async fn delete_old_segments(dir: &Path) -> Result<()> {
128133
Ok(())
129134
}
130135

131-
pub async fn watch_self() -> Result<()> {
136+
pub async fn watch_self(port: u16) -> Result<()> {
132137
let channel = Channel {
133-
url: Some("http://127.0.0.1:3000/stream.m3u8".to_string()),
138+
url: Some(format!("http://127.0.0.1:{port}/stream.m3u8").to_string()),
134139
name: "Local livestream".to_string(),
135140
favorite: false,
136141
group: None,
@@ -145,11 +150,11 @@ pub async fn watch_self() -> Result<()> {
145150
mpv::play(channel, false).await
146151
}
147152

148-
fn share_restream(ip: String, channel: Channel) -> Result<()> {
153+
fn share_restream(address: String, channel: Channel) -> Result<()> {
149154
crate::share::share_custom_channel(Channel {
150155
id: Some(-1),
151156
name: format!("RST | {}", channel.name).to_string(),
152-
url: Some(format!("http://{ip}/stream.m3u8").to_string()),
157+
url: Some(address),
153158
group: None,
154159
image: channel.image,
155160
media_type: crate::media_type::LIVESTREAM,
@@ -160,3 +165,27 @@ fn share_restream(ip: String, channel: Channel) -> Result<()> {
160165
stream_id: None,
161166
})
162167
}
168+
169+
pub async fn get_network_info() -> Result<NetworkInfo> {
170+
let port = get_settings()?.restream_port.unwrap_or(3000);
171+
Ok(NetworkInfo {
172+
port,
173+
local_ips: get_ips(port)?,
174+
wan_ip: get_wan_ip(port).await?,
175+
})
176+
}
177+
178+
fn get_ips(port: u16) -> Result<Vec<String>> {
179+
Ok(if_addrs::get_if_addrs()?
180+
.iter()
181+
.filter(|i| i.ip().is_ipv4() && !i.ip().is_loopback())
182+
.map(|i| format!("http://{}:{port}/stream.m3u8", i.ip().to_string()))
183+
.collect())
184+
}
185+
186+
async fn get_wan_ip(port: u16) -> Result<String> {
187+
Ok(format!(
188+
"http://{}:{port}/stream.m3u8",
189+
reqwest::get(WAN_IP_API).await?.text().await?
190+
))
191+
}

src-tauri/src/settings.rs

+5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub const RECORDING_PATH: &str = "recordingPath";
1111
pub const DEFAULT_VIEW: &str = "defaultView";
1212
pub const VOLUME: &str = "volume";
1313
pub const REFRESH_ON_START: &str = "refreshOnStart";
14+
pub const RESTREAM_PORT: &str = "restreamPort";
1415

1516
pub fn get_settings() -> Result<Settings> {
1617
let map = sql::get_settings()?;
@@ -21,6 +22,7 @@ pub fn get_settings() -> Result<Settings> {
2122
default_view: map.get(DEFAULT_VIEW).and_then(|s| s.parse().ok()),
2223
volume: map.get(VOLUME).and_then(|s| s.parse().ok()),
2324
refresh_on_start: map.get(REFRESH_ON_START).and_then(|s| s.parse().ok()),
25+
restream_port: map.get(RESTREAM_PORT).and_then(|s| s.parse().ok()),
2426
};
2527
Ok(settings)
2628
}
@@ -48,6 +50,9 @@ pub fn update_settings(settings: Settings) -> Result<()> {
4850
if let Some(refresh_on_start) = settings.refresh_on_start {
4951
map.insert(REFRESH_ON_START.to_string(), refresh_on_start.to_string());
5052
}
53+
if let Some(port) = settings.restream_port {
54+
map.insert(RESTREAM_PORT.to_string(), port.to_string());
55+
}
5156
sql::update_settings(map)?;
5257
Ok(())
5358
}

src-tauri/src/types.rs

+8
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub struct Settings {
5050
pub default_view: Option<u8>,
5151
pub volume: Option<u8>,
5252
pub refresh_on_start: Option<bool>,
53+
pub restream_port: Option<u16>,
5354
}
5455

5556
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
@@ -144,3 +145,10 @@ pub struct AppState {
144145
pub web_server_tx: Option<tokio::sync::oneshot::Sender<bool>>,
145146
pub web_server_handle: Option<tokio::task::JoinHandle<()>>,
146147
}
148+
149+
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
150+
pub struct NetworkInfo {
151+
pub port: u16,
152+
pub local_ips: Vec<String>,
153+
pub wan_ip: String,
154+
}

src/app/models/networkInfo.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export class NetworkInfo {
2+
port!: number;
3+
local_ips!: Array<string>;
4+
wan_ip!: Array<string>;
5+
}

src/app/restream-modal/restream-modal.component.html

+9-10
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,15 @@ <h4 class="modal-title lbl">Re-streaming: {{ channel?.name }}</h4>
1414
</p>
1515
</div>
1616
<div *ngIf="started" class="selectable box mt-3">
17-
<p>Running...</p>
17+
<p>Running and accessible from the following ips...</p>
1818
<br />
19-
<div class="row">
20-
<div class="col-5 col-lg-3 col-xl-2">LAN service address:</div>
21-
<div class="col">{{ address }}</div>
22-
</div>
23-
<div class="row">
24-
<div class="col-5 col-lg-3 col-xl-2">WAN service address:</div>
25-
<div class="col">{{ wanAddress }}</div>
26-
</div>
19+
<p>Local ips:</p>
20+
<p *ngFor="let local of networkInfo?.local_ips">
21+
{{ local }}
22+
</p>
23+
<br />
24+
<p>WAN address:</p>
25+
<p>{{ networkInfo?.wan_ip }}</p>
2726
</div>
2827
<div *ngIf="started">
2928
<br />
@@ -64,7 +63,7 @@ <h4 class="modal-title lbl">Re-streaming: {{ channel?.name }}</h4>
6463
<button
6564
class="btn btn-success d-inline-flex align-items-center"
6665
(click)="watch()"
67-
[disabled]="loading"
66+
[disabled]="loading || watching"
6867
*ngIf="started"
6968
>
7069
<span>Watch</span>

src/app/restream-modal/restream-modal.component.ts

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
1-
import { Component } from "@angular/core";
1+
import { Component, OnInit } from "@angular/core";
22
import { Channel } from "../models/channel";
33
import { invoke } from "@tauri-apps/api/core";
44
import { ErrorService } from "../error.service";
5+
import { NetworkInfo } from "../models/networkInfo";
56

67
@Component({
78
selector: "app-restream-modal",
89
templateUrl: "./restream-modal.component.html",
910
styleUrl: "./restream-modal.component.css",
1011
})
11-
export class RestreamModalComponent {
12+
export class RestreamModalComponent implements OnInit {
1213
channel?: Channel;
1314
loading = false;
15+
watching = false;
1416
started = false;
1517
address = "http://192.168.2.10/stream.m3u8";
1618
wanAddress = "http://10.145.22.12/stream.m3u8";
19+
networkInfo?: NetworkInfo;
1720
constructor(private error: ErrorService) {}
21+
22+
ngOnInit(): void {
23+
invoke("get_network_info").then((network) => {
24+
this.networkInfo = network as NetworkInfo;
25+
});
26+
}
27+
1828
async start() {
1929
this.loading = true;
2030
try {
@@ -40,13 +50,13 @@ export class RestreamModalComponent {
4050
}
4151

4252
async watch() {
43-
this.loading = true;
53+
this.watching = true;
4454
try {
45-
await invoke("watch_self");
55+
await invoke("watch_self", { port: this.networkInfo?.port });
4656
} catch (e) {
4757
this.error.handleError(e);
4858
}
49-
this.loading = false;
59+
this.watching = false;
5060
}
5161

5262
share() {}

0 commit comments

Comments
 (0)