Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ x11rb = "0.13.1"

[target.'cfg(target_os = "windows")'.dependencies]
str0m = { version = "0.8.0", default-features = false, features = ["sha1", "wincrypto"] }
windows-service = "0.8.0"
windows = { version = "0.61.1", features = [
"Win32_Foundation",
"Win32_System_RemoteDesktop",
"Win32_Security",
"Win32_System_Threading",
"Win32_System_Services",
"Win32_System_SystemServices",
"Win32_System_Environment",
"Win32_UI_WindowsAndMessaging",
"Win32_System_Environment",
"Win32_System_StationsAndDesktops",
"Win32_System_SystemServices"
] }

[target.'cfg(not(target_os = "windows"))'.dependencies]
str0m = { version = "0.8.0" }
Expand All @@ -50,3 +64,6 @@ bindgen = "0.69.4"
[profile.dist]
inherits = "release"
lto = "thin"

[profile.release]
debug = true
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,23 @@ Tenebra uses GStreamer to record the screen in a cross-platform way, and to enco

[GStreamer Installs](https://gstreamer.freedesktop.org/download/)

To use a Github release, you only need the runtime package. To build Tenebra, you need to install both the development and the runtime packages.
To use a Github release, you only need the runtime package. To build Tenebra, you need to install both the development and the runtime packages. On Windows, GStreamer's bin folder must be added to the PATH.

After the server is built with `cargo build --release`, you may run it:
After the server is built with `cargo build --release`, you may run it. On macOS and Windows, this is as easy as:
```
./target/release/tenebra
```

But on Windows, Tenebra must run as a service in order to have the necessary integrity level to interact with all parts of the desktop. First, a service must be registered:
```
sc create Tenebra binPath= "C:\path\to\tenebra\exe"
```

Then, starting Tenebra is as easy as:
```
sc start Tenebra
```

However, Tenebra reads from a config file which must be populated before running Tenebra. If it is not populated, Tenebra will fail before copying the default config file to the config file directory.

* On **Linux** the config file is at `$XDG_CONFIG_HOME`/tenebra/config.toml or `$HOME`/.config/tenebra/config.toml (e.g. /home/alice/.config/tenebra/config.toml)
Expand All @@ -56,8 +66,8 @@ On macOS, [VideoToolbox](https://developer.apple.com/documentation/videotoolbox)

On Windows, [Media Foundation](https://learn.microsoft.com/en-us/windows/win32/medfound/microsoft-media-foundation-sdk) can be used to perform hardware accelerated H.264 encoding. This can be enabled by setting the `hwencode` property in the config.toml to `true`. The `mfh264enc` GStreamer element must be installed and USABLE. Enable `hwencode` will also automatically enable the use of D3D11 for video format conversion.

## Touch input
## Touch input & pen input

On Linux and Windows, Tenebra has support for receiving and emulating touch events (e.g. from an iPad client).
On Linux and Windows, Tenebra has support for receiving and emulating touch and pen events (e.g. from an iPad client).

On Linux, this requires permission to access uinput. Reference your distribution's documentation for details.
3 changes: 3 additions & 0 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ pub fn do_input(
let mut held: HashSet<Key> = HashSet::new();

while let Some(msg) = rx.blocking_recv() {
#[cfg(target_os = "windows")]
let _ = crate::windows_service::sync_thread_desktop();

match msg {
InputCommand {
r#type,
Expand Down
39 changes: 38 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ pub mod keys;
mod rtc;
mod stun;

// This module contains all code related to Windows service functionality
#[cfg(target_os = "windows")]
pub mod windows_service;

pub struct AppError(anyhow::Error);

impl IntoResponse for AppError {
Expand Down Expand Up @@ -447,12 +451,37 @@ fn default_vbv_buf_capacity() -> u32 {
120
}


#[cfg(target_os = "windows")]
fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
let option: Option<&str> = args.get(1).map(|s| s.as_str());
if let Some("--console") = option {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
.block_on(crate::entrypoint())?;
} else {
windows_service::run()?;
}
Ok(())
}

#[cfg(not(target_os = "windows"))]
#[tokio::main]
async fn main() -> Result<()> {
entrypoint().await
}

async fn entrypoint() -> Result<()> {
// WinCrypto simplifies build significantly on Windows
#[cfg(target_os = "windows")]
str0m::config::CryptoProvider::WinCrypto.install_process_default();

#[cfg(target_os = "windows")]
let _ = windows_service::sync_thread_desktop();

// check if we're behind symmetric NAT
if stun::is_symmetric_nat()
.await
Expand All @@ -467,11 +496,19 @@ async fn main() -> Result<()> {
gstreamer::init().unwrap();

// get the config path
#[cfg(not(target_os = "windows"))]
let mut config_path = dirs::config_dir()
.context("Failed to find config directory")?
.join("tenebra");
std::fs::create_dir_all(&config_path).context("Failed to create config directory")?;
#[cfg(not(target_os = "windows"))]
config_path.push("config.toml");

#[cfg(target_os = "windows")]
let mut config_path = std::path::Path::new("C:\\tenebra.toml");

#[cfg(not(target_os = "windows"))]
std::fs::create_dir_all(&config_path).context("Failed to create config directory")?;

if !config_path.exists() {
std::fs::write(&config_path, include_bytes!("default.toml"))
.context("Failed to write default config")?;
Expand Down
Loading