diff --git a/.gitignore b/.gitignore index 7b071798..be7205c6 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,8 @@ inner.rs /test /log* /build_event_debug.sh + + +# OHOS + +phira/dist/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 4f8d510d..63698cdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2618,6 +2618,12 @@ dependencies = [ "napi-sys-ohos", ] +[[package]] +name = "ohos-audio-sys" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "892313a2851bbb13c11ba075768ef0d0a9a6a8ae53e54641c9c56eda726dc87f" + [[package]] name = "ohos-display-binding" version = "0.0.1" @@ -2905,6 +2911,8 @@ dependencies = [ "lyon", "macroquad", "nalgebra", + "napi-derive-ohos", + "napi-ohos", "ndk-context", "ndk-sys 0.2.2", "objc", @@ -3740,11 +3748,12 @@ dependencies = [ [[package]] name = "sasa" version = "0.1.0" -source = "git+https://github.com/Mivik/sasa?rev=fcbe721#fcbe7218144a13bc4a595ae7e0527caaf272b0ea" +source = "git+https://github.com/Mivik/sasa?rev=5c110595bd0a1f0d299602c4ab85fe3e349addc7#5c110595bd0a1f0d299602c4ab85fe3e349addc7" dependencies = [ "anyhow", "cpal", "oboe", + "ohos-audio-sys", "ringbuf", "symphonia", "thiserror 2.0.18", diff --git a/Cargo.toml b/Cargo.toml index ed11541e..1d1d4466 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,7 @@ phira-mp-common = { git = "https://github.com/TeamFlos/phira-mp", rev = "6967475 prpr = { path = "prpr", default-features = false } prpr-avc = { path = "prpr-avc" } prpr-l10n = { path = "prpr-l10n" } -sasa = { git = "https://github.com/Mivik/sasa", rev = "fcbe721", default-features = false } +sasa = { git = "https://github.com/Mivik/sasa", rev = "5c110595bd0a1f0d299602c4ab85fe3e349addc7", default-features = false } [profile.release] opt-level = 2 diff --git a/phira/Cargo.toml b/phira/Cargo.toml index f42cd7d2..00d27cdf 100644 --- a/phira/Cargo.toml +++ b/phira/Cargo.toml @@ -80,7 +80,15 @@ ndk-sys = "0.2" ndk-context = "0.1" sasa = { workspace = true, default-features = false, features = ["oboe"] } -[target.'cfg(not(target_os = "android"))'.dependencies] +[target.'cfg(target_env = "ohos")'.dependencies] +sasa = { workspace = true, default-features = false, features = ["ohos"] } +napi-derive-ohos = { version = "1.1.3" } +napi-ohos = { version = "1.1.3", default-features = false, features = [ + "napi8", + "async", +] } + +[target.'cfg(not(any(target_os = "android", target_env = "ohos")))'.dependencies] sasa = { workspace = true, default-features = true } [target.'cfg(target_os = "ios")'.dependencies] diff --git a/phira/src/images.rs b/phira/src/images.rs index 355341f6..1e8cbc79 100644 --- a/phira/src/images.rs +++ b/phira/src/images.rs @@ -31,7 +31,17 @@ impl Images { image::load_from_memory(&tokio::fs::read(path).await.context("Failed to read image")?)? } else { let image = task.await?; - image.save_with_format(path, image::ImageFormat::Jpeg).context("Failed to save image")?; + #[cfg(not(target_env = "ohos"))] + { + image.save_with_format(path, image::ImageFormat::Jpeg).context("Failed to save image")?; + } + #[cfg(target_env = "ohos")] + { + let rgb_image = DynamicImage::ImageRgb8(image.to_rgb8()); + rgb_image + .save_with_format(path, image::ImageFormat::Jpeg) + .context("Failed to save image")?; + } image }) } diff --git a/phira/src/lib.rs b/phira/src/lib.rs index f18be3ee..2be9898b 100644 --- a/phira/src/lib.rs +++ b/phira/src/lib.rs @@ -45,6 +45,9 @@ static DATA_PATH: Mutex> = Mutex::new(None); static CACHE_DIR: Mutex> = Mutex::new(None); pub static mut DATA: Option = None; +#[cfg(target_env = "ohos")] +use napi_derive_ohos::napi; + #[cfg(feature = "closed")] pub async fn load_res(name: &str) -> Vec { let bytes = load_file(name).await.unwrap(); @@ -143,6 +146,12 @@ mod dir { async fn the_main() -> Result<()> { log::register(); + #[cfg(target_env = "ohos")] + unsafe { + *DATA_PATH.lock().unwrap() = Some("/data/storage/el2/base".to_owned()); + *CACHE_DIR.lock().unwrap() = Some("/data/storage/el2/base/cache".to_owned()); + prpr::core::DPI_VALUE.store(250, std::sync::atomic::Ordering::Relaxed); + }; init_assets(); @@ -437,3 +446,32 @@ pub unsafe extern "C" fn Java_quad_1native_QuadNative_antiAddictionCallback( } } } + +#[cfg(target_env = "ohos")] +#[napi] +pub fn set_input_text(text: String) { + use prpr::scene::INPUT_TEXT; + INPUT_TEXT.lock().unwrap().1 = Some(text); +} + +#[cfg(target_env = "ohos")] +#[napi] +pub fn set_chosen_file(file: String) { + use prpr::scene::CHOSEN_FILE; + CHOSEN_FILE.lock().unwrap().1 = Some(file); +} + +#[cfg(target_env = "ohos")] +#[napi] +pub fn mark_import() { + use prpr::scene::CHOSEN_FILE; + CHOSEN_FILE.lock().unwrap().0 = Some("_import".to_owned()); +} + +#[cfg(target_env = "ohos")] +#[napi] +pub fn mark_import_respack() { + use prpr::scene::CHOSEN_FILE; + CHOSEN_FILE.lock().unwrap().0 = Some("_import_respack".to_owned()); +} + diff --git a/phira/src/page/settings.rs b/phira/src/page/settings.rs index 4da7b22a..9fa9b21e 100644 --- a/phira/src/page/settings.rs +++ b/phira/src/page/settings.rs @@ -280,6 +280,7 @@ struct GeneralList { server_status_btn: DRectButton, mp_btn: DRectButton, mp_addr_btn: DRectButton, + #[cfg(not(target_env = "ohos"))] lowq_btn: DRectButton, insecure_btn: DRectButton, enable_anys_btn: DRectButton, @@ -313,6 +314,7 @@ impl GeneralList { server_status_btn: DRectButton::new(), mp_btn: DRectButton::new(), mp_addr_btn: DRectButton::new(), + #[cfg(not(target_env = "ohos"))] lowq_btn: DRectButton::new(), insecure_btn: DRectButton::new(), enable_anys_btn: DRectButton::new(), @@ -390,6 +392,7 @@ impl GeneralList { request_input("mp_addr", &config.mp_address); return Ok(Some(true)); } + #[cfg(not(target_env = "ohos"))] if self.lowq_btn.touch(touch, t) { config.sample_count = if config.sample_count == 1 { 2 } else { 1 }; return Ok(Some(true)); @@ -491,6 +494,7 @@ impl GeneralList { render_title(ui, tl!("item-mp-addr"), Some(tl!("item-mp-addr-sub"))); self.mp_addr_btn.render_text(ui, rr, t, &config.mp_address, 0.4, false); } + #[cfg(not(target_env = "ohos"))] item! { render_title(ui, tl!("item-lowq"), Some(tl!("item-lowq-sub"))); render_switch(ui, rr, t, &mut self.lowq_btn, config.sample_count == 1); diff --git a/prpr-avc/Cargo.toml b/prpr-avc/Cargo.toml index ac1e871d..eea4b7b9 100644 --- a/prpr-avc/Cargo.toml +++ b/prpr-avc/Cargo.toml @@ -6,6 +6,11 @@ edition = "2021" [lib] [dependencies] -sasa = { workspace = true, default-features = false } thiserror = "2.0.18" tracing = { workspace = true } + +[target.'cfg(target_env = "ohos")'.dependencies] +sasa = { workspace = true, default-features = false, features = ["ohos"] } + +[target.'cfg(not(target_env = "ohos"))'.dependencies] +sasa = { workspace = true, default-features = false } diff --git a/prpr/Cargo.toml b/prpr/Cargo.toml index 5a98bf3d..f26c3739 100644 --- a/prpr/Cargo.toml +++ b/prpr/Cargo.toml @@ -76,7 +76,7 @@ miniquad = { workspace = true } prpr-avc = { workspace = true, optional = true } prpr-l10n = { workspace = true } -[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] +[target.'cfg(not(any(target_os = "android", target_os = "ios", target_env = "ohos")))'.dependencies] open = "5.3.3" rfd = "0.17.2" @@ -91,7 +91,10 @@ ndk-sys = "0.2" ndk-context = "0.1" sasa = { workspace = true, default-features = false, features = ["oboe"] } -[target.'cfg(not(target_os = "android"))'.dependencies] +[target.'cfg(target_env = "ohos")'.dependencies] +sasa = { workspace = true, default-features = false, features = ["ohos"] } + +[target.'cfg(not(any(target_os = "android", target_env = "ohos")))'.dependencies] sasa = { workspace = true, default-features = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/prpr/src/config.rs b/prpr/src/config.rs index 327b5f2b..30753b66 100644 --- a/prpr/src/config.rs +++ b/prpr/src/config.rs @@ -99,6 +99,11 @@ impl Config { if let Some(flag) = self.autoplay { self.mods.set(Mods::AUTOPLAY, flag); } + #[cfg(target_env = "ohos")] + { + // Due to the fucking poor performance of the Maloon GPU, the sample count must be set to 1. + self.sample_count = 1; + } } #[inline] diff --git a/prpr/src/core.rs b/prpr/src/core.rs index 7f9d4dbf..a8b6bcfc 100644 --- a/prpr/src/core.rs +++ b/prpr/src/core.rs @@ -68,6 +68,7 @@ thread_local! { } pub fn init_assets() { + #[cfg(not(target_env = "ohos"))] if let Ok(mut exe) = std::env::current_exe() { while exe.pop() { if exe.join("assets").exists() { @@ -76,6 +77,8 @@ pub fn init_assets() { } } } + #[cfg(target_env = "ohos")] + let _ = std::env::set_current_dir("/data/storage/el1/bundle/entry/resources/resfile/"); set_pc_assets_folder("assets"); } diff --git a/prpr/src/ext.rs b/prpr/src/ext.rs index 2e5940c8..fbe86306 100644 --- a/prpr/src/ext.rs +++ b/prpr/src/ext.rs @@ -400,7 +400,16 @@ pub fn create_audio_manger(config: &Config) -> Result { usage: Usage::Game, })) } - #[cfg(not(target_os = "android"))] + #[cfg(target_env = "ohos")] + { + use sasa::backend::ohos::*; + AudioManager::new(OhosBackend::new(OhosSettings { + buffer_size: Some(512), + sample_rate: Some(48000), + channels: 2, + })) + } + #[cfg(not(any(target_os = "android", target_env = "ohos")))] { use sasa::backend::cpal::*; AudioManager::new(CpalBackend::new(CpalSettings { @@ -547,7 +556,10 @@ pub fn open_url(url: &str) -> Result<()> { let url: ObjcId = msg_send![class!(NSURL), URLWithString: str_to_ns(url)]; let _: () = msg_send![application, openURL: url]; } - } else { + } else if #[cfg(target_env = "ohos")] { + miniquad::native::call_request_callback(format!("{{\"action\":\"openurl\",\"payload\":\"{}\"}}", url)); + } + else { open::that(url)?; } } diff --git a/prpr/src/scene.rs b/prpr/src/scene.rs index 42e420d9..b3f61afa 100644 --- a/prpr/src/scene.rs +++ b/prpr/src/scene.rs @@ -218,6 +218,8 @@ pub fn request_input_full(id: impl Into, #[allow(unused_variables)] text completion: 0 as ObjcId ]; } + }else if #[cfg(target_env = "ohos")]{ + miniquad::native::call_request_callback(r#"{"action": "show_input_window"}"#.to_string()); } else { INPUT_TEXT.lock().unwrap().1 = Some(unsafe { get_internal_gl() }.quad_context.clipboard_get().unwrap_or_default()); show_message(ttl!("pasted")).ok(); @@ -313,6 +315,8 @@ pub fn request_file(id: impl Into) { completion: 0 as ObjcId ]; } + } else if #[cfg(target_env = "ohos")]{ + miniquad::native::call_request_callback(r#"{"action": "chooseFile"}"#.to_string()); } else { // desktop CHOSEN_FILE.lock().unwrap().1 = rfd::FileDialog::new().pick_file().map(|it| it.display().to_string()); } diff --git a/prpr/src/ui.rs b/prpr/src/ui.rs index 5267d19d..5f7d0d4b 100644 --- a/prpr/src/ui.rs +++ b/prpr/src/ui.rs @@ -1193,7 +1193,16 @@ fn build_audio() -> AudioManager { ..Default::default() })) } - #[cfg(not(target_os = "android"))] + #[cfg(target_env = "ohos")] + { + use sasa::backend::ohos::*; + AudioManager::new(OhosBackend::new(OhosSettings { + buffer_size: Some(512), + sample_rate: Some(48000), + channels: 2, + })) + } + #[cfg(not(any(target_os = "android", target_env = "ohos")))] { use sasa::backend::cpal::*; AudioManager::new(CpalBackend::new(CpalSettings::default()))