Skip to content

Commit

Permalink
Merge pull request #1219 from BKasin/windows
Browse files Browse the repository at this point in the history
Add Windows Support
  • Loading branch information
eladyn authored Oct 19, 2023
2 parents 0a15027 + 7a6200f commit 9e3a7b0
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 39 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ tags

.idea
.vscode
# Windows logs
*.log
46 changes: 39 additions & 7 deletions Cargo.lock

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

14 changes: 6 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ rust-version = "1.67"
[dependencies]
alsa = { version = "0.7", optional = true }
chrono = "0.4"
daemonize = "0.5"
dbus = { version = "0.9", optional = true }
dbus-tokio = { version = "0.7.3", optional = true }
dbus-crossroads = { version = "0.5.0", optional = true }
Expand All @@ -26,18 +25,21 @@ rspotify = { version = "0.12.0", features = ["client-ureq", "ureq-rustls-tls"],
serde = { version = "1.0.115", features = ["derive"] }
sha-1 = "0.10"
structopt = "0.3.17"
syslog = "6"
tokio = {version = "1.26.0", features = ["signal", "rt-multi-thread", "process", "io-std"] }
tokio-stream = "0.1.7"
url = "2.2.2"
xdg = "2.2"
librespot-audio = { version = "0.4", default-features = false }
librespot-playback = { version = "0.4", default-features = false }
librespot-core = { version = "0.4" }
librespot-discovery = { version = "0.4" }
librespot-connect = { version = "0.4" }
toml = "0.7"
color-eyre = "0.6"
directories = "5.0.1"

[target."cfg(unix)".dependencies]
daemonize = "0.5"
syslog = "6"

[target."cfg(target_os = \"macos\")".dependencies]
whoami = "1"
Expand All @@ -56,11 +58,7 @@ rodio_backend = ["librespot-playback/rodio-backend"]

[package.metadata.deb]
depends = "$auto, systemd, pulseaudio"
features = [
"pulseaudio_backend",
"dbus_keyring",
"dbus_mpris",
]
features = ["pulseaudio_backend", "dbus_keyring", "dbus_mpris"]
assets = [
["target/release/spotifyd", "usr/bin/", "755"],
["README.md", "usr/share/doc/spotifyd/README", "644"],
Expand Down
26 changes: 15 additions & 11 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use librespot_playback::config::{
use log::{error, info, warn};
use serde::{de::Error, de::Unexpected, Deserialize, Deserializer};
use sha1::{Digest, Sha1};
use std::{fmt, fs, path::PathBuf, str::FromStr, string::ToString};
use std::{fmt, fs, path::Path, path::PathBuf, str::FromStr, string::ToString};
use structopt::{clap::AppSettings, StructOpt};
use url::Url;

Expand Down Expand Up @@ -655,16 +655,19 @@ impl SharedConfigValues {

pub(crate) fn get_config_file() -> Option<PathBuf> {
let etc_conf = format!("/etc/{}", CONFIG_FILE_NAME);
let xdg_dirs = xdg::BaseDirectories::with_prefix("spotifyd").ok()?;
xdg_dirs.find_config_file(CONFIG_FILE_NAME).or_else(|| {
fs::metadata(&*etc_conf).ok().and_then(|meta| {
if meta.is_file() {
Some(etc_conf.into())
} else {
None
}
})
})
let dirs = directories::BaseDirs::new()?;
let mut path = dirs.config_dir().to_path_buf();
path.push("spotifyd");
path.push(CONFIG_FILE_NAME);

if path.exists() {
Some(path)
} else if Path::new(&etc_conf).exists() {
let path: PathBuf = etc_conf.into();
Some(path)
} else {
None
}
}

fn device_id(name: &str) -> String {
Expand Down Expand Up @@ -693,6 +696,7 @@ pub(crate) struct SpotifydConfig {
pub(crate) player_config: PlayerConfig,
pub(crate) session_config: SessionConfig,
pub(crate) onevent: Option<String>,
#[allow(unused)]
pub(crate) pid: Option<String>,
pub(crate) shell: String,
pub(crate) zeroconf_port: Option<u16>,
Expand Down
90 changes: 77 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
#![cfg(unix)]

use crate::config::CliConfig;
#[cfg(unix)]
use color_eyre::eyre::eyre;
use color_eyre::{
eyre::{self, eyre, Context},
eyre::{self, Context},
Help, SectionExt,
};
#[cfg(unix)]
use daemonize::Daemonize;
use log::{error, info, trace, LevelFilter};
#[cfg(unix)]
use log::error;
use log::{info, trace, LevelFilter};
#[cfg(windows)]
use std::fs;
use structopt::StructOpt;
use tokio::runtime::Runtime;

Expand Down Expand Up @@ -42,6 +47,7 @@ fn setup_logger(log_target: LogTarget, verbose: bool) -> eyre::Result<()> {

let logger = match log_target {
LogTarget::Terminal => logger.chain(std::io::stdout()),
#[cfg(unix)]
LogTarget::Syslog => {
let log_format = syslog::Formatter3164 {
facility: syslog::Facility::LOG_DAEMON,
Expand All @@ -54,6 +60,25 @@ fn setup_logger(log_target: LogTarget, verbose: bool) -> eyre::Result<()> {
.map_err(|e| eyre!("Couldn't connect to syslog instance: {}", e))?,
)
}
#[cfg(target_os = "windows")]
LogTarget::Syslog => {
let dirs = directories::BaseDirs::new().unwrap();
let mut log_file = dirs.data_local_dir().to_path_buf();
log_file.push("spotifyd");
log_file.push(".spotifyd.log");

if let Some(p) = log_file.parent() {
fs::create_dir_all(p)?
};
logger.chain(
fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(log_file)
.expect("Couldn't initialize logger"),
)
}
};

logger.apply().wrap_err("Couldn't initialize logger")
Expand All @@ -67,9 +92,27 @@ fn main() -> eyre::Result<()> {
let is_daemon = !cli_config.no_daemon;

let log_target = if is_daemon {
LogTarget::Syslog
#[cfg(unix)]
{
LogTarget::Syslog
}
#[cfg(target_os = "windows")]
{
LogTarget::Terminal
}
} else {
LogTarget::Terminal
#[cfg(unix)]
{
LogTarget::Terminal
}
#[cfg(target_os = "windows")]
{
if std::env::var("SPOTIFYD_CHILD").is_ok() {
LogTarget::Syslog
} else {
LogTarget::Terminal
}
}
};

setup_logger(log_target, cli_config.verbose)?;
Expand All @@ -92,14 +135,35 @@ fn main() -> eyre::Result<()> {
if is_daemon {
info!("Daemonizing running instance");

let mut daemonize = Daemonize::new();
if let Some(pid) = internal_config.pid.as_ref() {
daemonize = daemonize.pid_file(pid);
#[cfg(unix)]
{
let mut daemonize = Daemonize::new();
if let Some(pid) = internal_config.pid.as_ref() {
daemonize = daemonize.pid_file(pid);
}
match daemonize.start() {
Ok(_) => info!("Detached from shell, now running in background."),
Err(e) => error!("Something went wrong while daemonizing: {}", e),
};
}
#[cfg(target_os = "windows")]
{
use std::os::windows::process::CommandExt;
use std::process::{exit, Command};

let mut args = std::env::args().collect::<Vec<_>>();
args.remove(0);
args.push("--no-daemon".to_string());

Command::new(std::env::current_exe().unwrap())
.args(args)
.env("SPOTIFYD_CHILD", "1")
.creation_flags(8 /* DETACHED_PROCESS */)
.spawn()
.expect("Couldn't spawn daemon");

exit(0);
}
match daemonize.start() {
Ok(_) => info!("Detached from shell, now running in background."),
Err(e) => error!("Something went wrong while daemonizing: {}", e),
};
}

let runtime = Runtime::new().unwrap();
Expand Down
5 changes: 5 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ fn get_shell_ffi() -> Option<String> {
None
}

#[cfg(target_os = "windows")]
fn get_shell_ffi() -> Option<String> {
Some(String::from("cmd"))
}

pub(crate) fn get_shell() -> Option<String> {
let shell = env::var("SHELL").ok().or_else(get_shell_ffi);
trace!("Found user shell: {:?}", &shell);
Expand Down

0 comments on commit 9e3a7b0

Please sign in to comment.