mirror of https://github.com/ErsatzTV/ErsatzTV.git
Browse Source
* convert windows project from dotnet to rust * update pr jobs * pr job fixes * don't bother building mac app in prs for now * build windows wrapper with rustpull/1088/head
11 changed files with 1229 additions and 139 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@ |
|||||||
|
[package] |
||||||
|
name = "ersatztv_windows" |
||||||
|
version = "0.1.0" |
||||||
|
edition = "2021" |
||||||
|
|
||||||
|
[dependencies] |
||||||
|
tray-item = { git = "https://github.com/olback/tray-item-rs" } |
||||||
|
special-folder = { git = "https://github.com/masinc/special-folder-rs" } |
||||||
|
process_path = "0.1.4" |
||||||
|
|
||||||
|
[dependencies.windows] |
||||||
|
version = "0.43.0" |
||||||
|
features = [ |
||||||
|
"Win32_System_Console", |
||||||
|
"Win32_Foundation" |
||||||
|
] |
||||||
|
|
||||||
|
[build-dependencies] |
||||||
|
windres = "*" |
||||||
@ -1,33 +0,0 @@ |
|||||||
<Project Sdk="Microsoft.NET.Sdk"> |
|
||||||
|
|
||||||
<PropertyGroup> |
|
||||||
<OutputType>WinExe</OutputType> |
|
||||||
<TargetFramework>net7.0-windows</TargetFramework> |
|
||||||
<RootNamespace>ErsatzTV_Windows</RootNamespace> |
|
||||||
<Nullable>enable</Nullable> |
|
||||||
<UseWindowsForms>true</UseWindowsForms> |
|
||||||
<ImplicitUsings>enable</ImplicitUsings> |
|
||||||
<ApplicationIcon>Ersatztv.ico</ApplicationIcon> |
|
||||||
</PropertyGroup> |
|
||||||
|
|
||||||
<ItemGroup> |
|
||||||
<Content Include="Ersatztv.ico"> |
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
|
||||||
</Content> |
|
||||||
</ItemGroup> |
|
||||||
|
|
||||||
<ItemGroup> |
|
||||||
<PackageReference Include="CliWrap" Version="3.6.0" /> |
|
||||||
</ItemGroup> |
|
||||||
|
|
||||||
<ItemGroup> |
|
||||||
<ProjectReference Include="..\ErsatzTV.Core\ErsatzTV.Core.csproj" /> |
|
||||||
</ItemGroup> |
|
||||||
|
|
||||||
<ItemGroup> |
|
||||||
<Compile Update="Program.cs"> |
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
|
||||||
</Compile> |
|
||||||
</ItemGroup> |
|
||||||
|
|
||||||
</Project> |
|
||||||
@ -1,14 +0,0 @@ |
|||||||
namespace ErsatzTV_Windows; |
|
||||||
|
|
||||||
public static class Program |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// The main entry point for the application.
|
|
||||||
/// </summary>
|
|
||||||
[STAThread] |
|
||||||
public static void Main() |
|
||||||
{ |
|
||||||
ApplicationConfiguration.Initialize(); |
|
||||||
Application.Run(new TrayApplicationContext()); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,81 +0,0 @@ |
|||||||
using ErsatzTV.Core; |
|
||||||
using System.Diagnostics; |
|
||||||
using CliWrap; |
|
||||||
|
|
||||||
namespace ErsatzTV_Windows; |
|
||||||
|
|
||||||
public class TrayApplicationContext : ApplicationContext |
|
||||||
{ |
|
||||||
private readonly NotifyIcon _trayIcon; |
|
||||||
private readonly CancellationTokenSource _tokenSource; |
|
||||||
|
|
||||||
public TrayApplicationContext() |
|
||||||
{ |
|
||||||
_trayIcon = new NotifyIcon |
|
||||||
{ |
|
||||||
Icon = new Icon("./Ersatztv.ico"), |
|
||||||
ContextMenuStrip = new ContextMenuStrip(), |
|
||||||
Visible = true |
|
||||||
}; |
|
||||||
|
|
||||||
_tokenSource = new CancellationTokenSource(); |
|
||||||
|
|
||||||
AddMenuItem("Launch Web UI", LaunchWebUI); |
|
||||||
AddMenuItem("Show Logs", ShowLogs); |
|
||||||
_trayIcon.ContextMenuStrip.Items.Add(new ToolStripSeparator()); |
|
||||||
AddMenuItem("Exit", Exit); |
|
||||||
|
|
||||||
string folder = AppContext.BaseDirectory; |
|
||||||
string exe = Path.Combine(folder, "ErsatzTV.exe"); |
|
||||||
|
|
||||||
if (File.Exists(exe)) |
|
||||||
{ |
|
||||||
|
|
||||||
Cli.Wrap(exe) |
|
||||||
.WithWorkingDirectory(folder) |
|
||||||
.WithValidation(CommandResultValidation.None) |
|
||||||
.ExecuteAsync(_tokenSource.Token); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void AddMenuItem(string name, EventHandler action) |
|
||||||
{ |
|
||||||
var item = new ToolStripMenuItem(name); |
|
||||||
item.Click += action; |
|
||||||
_trayIcon.ContextMenuStrip.Items.Add(item); |
|
||||||
} |
|
||||||
|
|
||||||
private void LaunchWebUI(object? sender, EventArgs e) |
|
||||||
{ |
|
||||||
var process = new Process(); |
|
||||||
process.StartInfo.UseShellExecute = true; |
|
||||||
process.StartInfo.FileName = "http://localhost:8409"; |
|
||||||
process.Start(); |
|
||||||
} |
|
||||||
|
|
||||||
private void ShowLogs(object? sender, EventArgs e) |
|
||||||
{ |
|
||||||
if (!Directory.Exists(FileSystemLayout.LogsFolder)) |
|
||||||
{ |
|
||||||
Directory.CreateDirectory(FileSystemLayout.LogsFolder); |
|
||||||
} |
|
||||||
|
|
||||||
var process = new Process(); |
|
||||||
process.StartInfo.UseShellExecute = true; |
|
||||||
process.StartInfo.FileName = FileSystemLayout.LogsFolder; |
|
||||||
process.Start(); |
|
||||||
} |
|
||||||
|
|
||||||
protected override void Dispose(bool disposing) |
|
||||||
{ |
|
||||||
_tokenSource?.Cancel(); |
|
||||||
base.Dispose(disposing); |
|
||||||
} |
|
||||||
|
|
||||||
private void Exit(object? sender, EventArgs e) |
|
||||||
{ |
|
||||||
// Hide tray icon, otherwise it will remain shown until user mouses over it
|
|
||||||
_trayIcon.Visible = false; |
|
||||||
Application.Exit(); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,5 @@ |
|||||||
|
use windres::Build; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
Build::new().compile("ersatztv_windows.rc").unwrap(); |
||||||
|
} |
||||||
@ -0,0 +1,2 @@ |
|||||||
|
id ICON "ersatztv.ico" |
||||||
|
ersatztv-icon ICON "ersatztv.ico" |
||||||
@ -0,0 +1,101 @@ |
|||||||
|
use special_folder::SpecialFolder; |
||||||
|
use std::fs; |
||||||
|
use std::process::Child; |
||||||
|
use std::process::Command; |
||||||
|
use std::process::Stdio; |
||||||
|
use {std::sync::mpsc, tray_item::TrayItem}; |
||||||
|
use windows::Win32::System::Console; |
||||||
|
|
||||||
|
enum Message { |
||||||
|
Exit, |
||||||
|
} |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let mut tray = TrayItem::new("ErsatzTV", "ersatztv-icon").unwrap(); |
||||||
|
|
||||||
|
let (tx, rx) = mpsc::channel(); |
||||||
|
|
||||||
|
tray.add_menu_item("Launch Web UI", || { |
||||||
|
let _ = Command::new("cmd") |
||||||
|
.arg("/C") |
||||||
|
.arg("start") |
||||||
|
.arg("http://localhost:8409") |
||||||
|
.stdin(Stdio::null()) |
||||||
|
.stdout(Stdio::null()) |
||||||
|
.stderr(Stdio::null()) |
||||||
|
.spawn(); |
||||||
|
}) |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
tray.add_menu_item("Show Logs", || { |
||||||
|
let path = SpecialFolder::LocalApplicationData |
||||||
|
.get() |
||||||
|
.unwrap() |
||||||
|
.join("ersatztv") |
||||||
|
.join("logs"); |
||||||
|
match path.to_str() { |
||||||
|
None => {} |
||||||
|
Some(folder) => { |
||||||
|
fs::create_dir_all(folder).unwrap(); |
||||||
|
let _ = Command::new("cmd") |
||||||
|
.arg("/C") |
||||||
|
.arg("start") |
||||||
|
.arg(folder) |
||||||
|
.stdin(Stdio::null()) |
||||||
|
.stdout(Stdio::null()) |
||||||
|
.stderr(Stdio::null()) |
||||||
|
.spawn(); |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
tray.inner_mut().add_separator().unwrap(); |
||||||
|
|
||||||
|
tray.add_menu_item("Exit", move || { |
||||||
|
tx.send(Message::Exit).unwrap(); |
||||||
|
}) |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
let path = process_path::get_executable_path(); |
||||||
|
let mut child: Option<Child> = None; |
||||||
|
match path { |
||||||
|
None => {} |
||||||
|
Some(path) => { |
||||||
|
let etv = path.parent().unwrap().join("ErsatzTV.exe"); |
||||||
|
if etv.exists() { |
||||||
|
match etv.to_str() { |
||||||
|
None => {} |
||||||
|
Some(etv) => { |
||||||
|
child = Some( |
||||||
|
Command::new(etv) |
||||||
|
.stdin(Stdio::null()) |
||||||
|
.stdout(Stdio::null()) |
||||||
|
.stderr(Stdio::null()) |
||||||
|
.spawn() |
||||||
|
.unwrap(), |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
loop { |
||||||
|
match rx.recv() { |
||||||
|
Ok(Message::Exit) => { |
||||||
|
match child { |
||||||
|
None => {} |
||||||
|
Some(mut child) => { |
||||||
|
unsafe { |
||||||
|
Console::GenerateConsoleCtrlEvent(Console::CTRL_C_EVENT, 0); |
||||||
|
} |
||||||
|
child.wait().unwrap(); |
||||||
|
} |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
_ => {} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue