Skip to content

Commit 493e2cb

Browse files
committed
adding Gstreamer plugin for handling asset:// (linux specific)
asset:// is registered as a custom protocol through WebKit, but when an audio or video is got from that protocol, gstreamer is used in the background and can't play the media because there is no handler for asset://
1 parent b80f9de commit 493e2cb

File tree

9 files changed

+591
-191
lines changed

9 files changed

+591
-191
lines changed

Cargo.lock

Lines changed: 427 additions & 191 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ members = [
1414
"crates/tauri-bundler",
1515
"crates/tauri-macos-sign",
1616
"crates/tauri-driver",
17+
"crates/tauri-asset-gst-plugin",
18+
1719

1820
# @tauri-apps/cli rust project
1921
"packages/cli",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "tauri-asset-gst-plugin"
3+
version = "0.1.0"
4+
authors = ["Alexander Yanovskyy <[email protected]>"]
5+
license = "MIT OR Apache-2.0"
6+
edition = "2018"
7+
repository = "https://github.com/tauri-apps/tauri"
8+
description = "Gstreamer plugin for asset protocol"
9+
10+
[dependencies]
11+
gstreamer = "0.24"
12+
gstreamer-base = "0.24"
13+
14+
[lib]
15+
name = "gsttauriasset"
16+
crate-type = ["cdylib"]
17+
path = "src/lib.rs"
18+
19+
[build-dependencies]
20+
gst-plugin-version-helper = "0.8.3"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
gst_plugin_version_helper::info();
3+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[toolchain]
2+
channel = "stable-2025-10-30"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use gst::glib;
2+
use gstreamer_base::gst;
3+
4+
mod tauri_asset;
5+
// https://github.com/sdroege/gst-plugin-rs/blob/main/net/aws/src/lib.rs
6+
7+
fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
8+
tauri_asset::register(plugin)
9+
}
10+
11+
gst::plugin_define!(
12+
tauriasset,
13+
env!("CARGO_PKG_DESCRIPTION"),
14+
plugin_init,
15+
concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")),
16+
"The Plugin's License",
17+
env!("CARGO_PKG_NAME"),
18+
env!("CARGO_PKG_NAME"),
19+
env!("CARGO_PKG_REPOSITORY"),
20+
env!("BUILD_REL_DATE")
21+
);
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
use gst::glib::subclass::types::ObjectSubclassExt;
2+
use gst::prelude::{ElementExt, GhostPadExt, GstBinExt, PadExt};
3+
use gst::subclass::prelude::{BinImpl, ElementImpl, ObjectImpl, URIHandlerImpl};
4+
use gst::subclass::prelude::{GstObjectImpl, ObjectSubclass};
5+
use gst::{glib, GhostPad, PadDirection};
6+
use gstreamer_base::gst;
7+
8+
const ASSET_URI_SCHEME: &str = "asset";
9+
10+
#[derive(Default)]
11+
pub struct TauriAsset {
12+
// uri: Option<String>,
13+
}
14+
15+
impl TauriAsset {
16+
pub fn new() -> Self {
17+
Self::default()
18+
}
19+
}
20+
21+
#[glib::object_subclass]
22+
impl ObjectSubclass for TauriAsset {
23+
const NAME: &'static str = "GstTauriAsset";
24+
type Type = super::TauriAsset;
25+
type ParentType = gst::Bin;
26+
type Interfaces = (gst::URIHandler,);
27+
}
28+
29+
impl GstObjectImpl for TauriAsset {}
30+
impl ObjectImpl for TauriAsset {}
31+
impl BinImpl for TauriAsset {}
32+
impl ElementImpl for TauriAsset {}
33+
34+
impl URIHandlerImpl for TauriAsset {
35+
const URI_TYPE: gst::URIType = gst::URIType::Src;
36+
37+
fn protocols() -> &'static [&'static str] {
38+
&[ASSET_URI_SCHEME]
39+
}
40+
41+
fn uri(&self) -> Option<String> {
42+
None
43+
}
44+
45+
fn set_uri(&self, uri: &str) -> Result<(), glib::Error> {
46+
// uri is like: asset://path/to/asset or asset://localhost/path/to/asset
47+
48+
let sep = format!("{}://", ASSET_URI_SCHEME);
49+
let mut split = uri.split(sep.as_str());
50+
let location = split
51+
.nth(1)
52+
.ok_or_else(|| glib::Error::new(gst::URIError::BadUri, "Could not get location from URI"))?;
53+
54+
// directly having full path after asset:// or having localhost
55+
let location = location.strip_prefix("localhost").unwrap_or(location);
56+
57+
// now location is like: /path/to/asset
58+
let internal_src = gst::ElementFactory::make("filesrc")
59+
.name("filesrc")
60+
.property("location", location)
61+
.build()
62+
.ok();
63+
64+
let element = self.obj();
65+
element
66+
.add(internal_src.as_ref().unwrap())
67+
.expect("Failed to add internal source");
68+
69+
let srcpad = internal_src
70+
.as_ref()
71+
.and_then(|src| src.static_pad("src"))
72+
.ok_or_else(|| {
73+
glib::Error::new(
74+
gst::URIError::BadUri,
75+
"Could not get src pad from internal source",
76+
)
77+
})?;
78+
79+
let ghostpad = GhostPad::new(PadDirection::Src);
80+
ghostpad
81+
.set_target(Some(&srcpad))
82+
.ok()
83+
.ok_or_else(|| glib::Error::new(gst::URIError::BadUri, "Could not create ghost pad"))?;
84+
85+
ghostpad
86+
.set_active(true)
87+
.ok()
88+
.ok_or_else(|| glib::Error::new(gst::URIError::BadUri, "Could not activate ghost pad"))?;
89+
90+
let element = self.obj();
91+
element.add_pad(&ghostpad).expect("Failed to add ghost pad");
92+
println!("Set URI to location: {}", location);
93+
Ok(())
94+
}
95+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use gst::glib;
2+
use gst::prelude::*;
3+
use gstreamer_base::gst;
4+
5+
mod imp;
6+
7+
glib::wrapper! {
8+
pub struct TauriAsset(ObjectSubclass<imp::TauriAsset>)
9+
@extends gst::Bin, gst::Element, gst::Object,
10+
@implements gst::URIHandler;
11+
}
12+
13+
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
14+
gst::Element::register(
15+
Some(plugin),
16+
"tauriasset",
17+
gst::Rank::PRIMARY,
18+
TauriAsset::static_type(),
19+
)
20+
}

0 commit comments

Comments
 (0)