summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-05-25 18:49:20 -0400
committerAndrew Opalach <andrew@akon.city> 2025-05-25 18:49:20 -0400
commit2fa7ea95c891981684a55b41977172d040c2cc55 (patch)
treed349e810b3178045a420b625f6dbe5634b64807b
parent01f852081b1291da7fc342976bf5228ffb618736 (diff)
downloadcamu-2fa7ea95c891981684a55b41977172d040c2cc55.tar.gz
camu-2fa7ea95c891981684a55b41977172d040c2cc55.tar.bz2
camu-2fa7ea95c891981684a55b41977172d040c2cc55.zip
Support Windows XP (Old FFmpeg and build fixes)
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--.gitignore4
-rw-r--r--cross/i686-w64-mingw32.txt6
-rw-r--r--cross/x86_64-w64-mingw32.txt6
-rw-r--r--cross/x86_64-w64-msvc-clang.txt24
-rw-r--r--env/mingw_build.sh12
-rw-r--r--env/msvc_build.sh13
-rw-r--r--flake.lock18
-rw-r--r--flake.nix53
-rw-r--r--meson.build18
-rw-r--r--meson_options.txt5
-rw-r--r--src/codec/codec.h47
-rw-r--r--src/codec/ffmpeg/avio.c12
-rw-r--r--src/codec/ffmpeg/avio.h5
-rw-r--r--src/codec/ffmpeg/common.c4
-rw-r--r--src/codec/ffmpeg/decoder.c4
-rw-r--r--src/codec/ffmpeg/decoder.h4
-rw-r--r--src/codec/ffmpeg/demuxer.c7
-rw-r--r--src/codec/ffmpeg/encoder.c25
-rw-r--r--src/codec/ffmpeg/encoder.h2
-rw-r--r--src/codec/ffmpeg/meson.build20
-rw-r--r--src/codec/ffmpeg/packet_ext.c18
-rw-r--r--src/codec/ffmpeg/packet_ext.h3
-rw-r--r--src/codec/ffmpeg/resampler.c33
-rw-r--r--src/fruits/cmc/meson.build2
-rw-r--r--src/fruits/cmc/ui/util/waveform.c2
-rw-r--r--src/fruits/cmsrv/meson.build2
-rw-r--r--src/fruits/cmv/cmv.c14
-rw-r--r--src/fruits/cmv/meson.build2
-rw-r--r--src/fruits/droid/ctv/gradle/libs.versions.toml2
-rw-r--r--src/liana/client.c13
-rw-r--r--src/liana/handlers/codec_client.c2
-rw-r--r--src/liana/handlers/codec_server.c2
-rw-r--r--src/liana/process.c8
-rw-r--r--src/liana/vcr.c6
-rw-r--r--src/libsink/desktop.c17
-rw-r--r--src/libsink/sink.c23
-rw-r--r--src/mixer/audio_miniaudio.c7
-rw-r--r--src/mixer/audio_null.c2
-rw-r--r--src/mixer/meson.build6
-rw-r--r--src/render/meson.build53
-rw-r--r--src/render/momo/meson.build12
-rw-r--r--src/render/momo/momo.c35
-rw-r--r--src/render/momo/momo.h25
-rw-r--r--src/render/queue_libplacebo.c1
-rw-r--r--src/render/queue_momo.c68
-rw-r--r--src/render/queue_momo.h9
-rw-r--r--src/render/queue_tiger.c130
-rw-r--r--src/render/queue_tiger.h18
-rw-r--r--src/render/renderer.h20
-rw-r--r--src/render/renderer_libplacebo.c73
-rw-r--r--src/render/renderer_libplacebo.h12
-rw-r--r--src/render/renderer_momo.c97
-rw-r--r--src/render/renderer_momo.h19
-rw-r--r--src/render/renderer_tiger.c320
-rw-r--r--src/render/renderer_tiger.h31
-rw-r--r--src/screen/screen.c33
-rw-r--r--src/screen/screen.h1
-rw-r--r--src/server/server.c3
-rw-r--r--subprojects/SPIRV-Cross.wrap2
-rw-r--r--subprojects/SPIRV-Tools.wrap6
-rw-r--r--subprojects/ffmpeg-compat.wrap7
-rw-r--r--subprojects/ffmpeg.wrap1
-rw-r--r--subprojects/fontconfig.wrap4
-rw-r--r--subprojects/glslang.wrap4
-rw-r--r--subprojects/harfbuzz.wrap4
-rw-r--r--subprojects/libalabaster.wrap2
-rw-r--r--subprojects/libnaunet.wrap2
-rw-r--r--subprojects/miniaudio.wrap6
-rw-r--r--subprojects/msvc-wine.wrap7
-rw-r--r--subprojects/packagefiles/SPIRV-Cross/msvc_static_build.diff17
-rw-r--r--subprojects/packagefiles/ffmpeg-compat/ffmpeg.git-effadce6c756247ea8bae32dc13bb3e6f464f0eb.patch73
-rw-r--r--subprojects/packagefiles/ffmpeg-compat/meson.build197
-rw-r--r--subprojects/packagefiles/ffmpeg/meson.build100
-rw-r--r--subprojects/packagefiles/ffmpeg/msvc_build_conform.diff20
-rw-r--r--subprojects/packagefiles/libplacebo/max_align_msvc.diff14
-rw-r--r--subprojects/packagefiles/miniaudio/meson.build2
-rw-r--r--subprojects/packagefiles/miniaudio/miniaudio_wasapi_drain_tweak.diff13
-rw-r--r--subprojects/packagefiles/msvc-wine/msvc-wine-shebang-nixos.diff405
-rw-r--r--subprojects/packagefiles/shaderc/no_hlsl_compile.diff13
-rw-r--r--subprojects/shaderc.wrap6
-rw-r--r--subprojects/stela.wrap2
81 files changed, 1584 insertions, 736 deletions
diff --git a/.gitignore b/.gitignore
index 1f4ec79..e2836a2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,7 @@ build*/
compile_commands.json
data/
docs/**/*.html
-env/bin/
+env/msvc-root/
result
src/portal/cpy/portal.c
src/portal/cpy/portal.h
@@ -13,6 +13,7 @@ src/portal/py/config.py
src/portal/vendor/*
subprojects/BLAKE3-*/
subprojects/SPIRV-Cross-*/
+subprojects/SPIRV-Tools-*/
subprojects/c89atomic-*/
subprojects/c89atomic.wrap
subprojects/cairo.wrap
@@ -60,6 +61,7 @@ subprojects/libxml2-*/
subprojects/libxml2.wrap
subprojects/linmath.h-*/
subprojects/miniaudio-*/
+subprojects/msvc-wine/
subprojects/notcurses-*/
subprojects/packagecache/
subprojects/pcre2-*/
diff --git a/cross/i686-w64-mingw32.txt b/cross/i686-w64-mingw32.txt
index e07fa49..159c662 100644
--- a/cross/i686-w64-mingw32.txt
+++ b/cross/i686-w64-mingw32.txt
@@ -1,15 +1,15 @@
[binaries]
c = 'i686-w64-mingw32-gcc'
cpp = 'i686-w64-mingw32-g++'
-ar = 'i686-w64-mingw32-gcc-ar'
+ar = 'i686-w64-mingw32-ar'
strip = 'i686-w64-mingw32-strip'
windres = 'i686-w64-mingw32-windres'
dlltool = 'i686-w64-mingw32-dlltool'
exe_wrapper = 'wine'
[properties]
-nm = 'i686-w64-mingw32-gcc-nm'
-ar = 'i686-w64-mingw32-gcc-ar'
+ar = 'i686-w64-mingw32-ar'
+nm = 'i686-w64-mingw32-nm'
needs_exe_wrapper = true
[host_machine]
diff --git a/cross/x86_64-w64-mingw32.txt b/cross/x86_64-w64-mingw32.txt
index 37e4e24..2bc8756 100644
--- a/cross/x86_64-w64-mingw32.txt
+++ b/cross/x86_64-w64-mingw32.txt
@@ -3,15 +3,15 @@
[binaries]
c = 'x86_64-w64-mingw32-gcc'
cpp = 'x86_64-w64-mingw32-g++'
-ar = 'x86_64-w64-mingw32-gcc-ar'
+ar = 'x86_64-w64-mingw32-ar'
strip = 'x86_64-w64-mingw32-strip'
windres = 'x86_64-w64-mingw32-windres'
dlltool = 'x86_64-w64-mingw32-dlltool'
exe_wrapper = 'wine64'
[properties]
-nm = 'x86_64-w64-mingw32-gcc-nm'
-ar = 'x86_64-w64-mingw32-gcc-ar'
+ar = 'x86_64-w64-mingw32-ar'
+nm = 'x86_64-w64-mingw32-nm'
needs_exe_wrapper = true
[host_machine]
diff --git a/cross/x86_64-w64-msvc-clang.txt b/cross/x86_64-w64-msvc-clang.txt
new file mode 100644
index 0000000..f269f63
--- /dev/null
+++ b/cross/x86_64-w64-msvc-clang.txt
@@ -0,0 +1,24 @@
+[binaries]
+c = 'clang-cl'
+c_ld = 'lld-link'
+cpp = 'clang-cl'
+cpp_ld = 'lld-link'
+ar = 'llvm-lib'
+nm = 'llvm-objdump'
+dlltool = 'llvm-dlltool'
+windres = 'llvm-rc'
+pkg-config = ''
+exe_wrapper = 'wine64'
+
+[properties]
+c_args = ['--target=x86_64-windows-msvc', '-fuse-ld=lld']
+cpp_args = ['--target=x86_64-windows-msvc', '-fuse-ld=lld']
+ar = 'llvm-lib'
+nm = 'llvm-objdump'
+needs_exe_wrapper = true
+
+[host_machine]
+system = 'windows'
+cpu_family = 'x86_64'
+cpu = 'x86_64'
+endian = 'little'
diff --git a/env/mingw_build.sh b/env/mingw_build.sh
new file mode 100644
index 0000000..805c4f5
--- /dev/null
+++ b/env/mingw_build.sh
@@ -0,0 +1,12 @@
+#! /usr/bin/env sh
+meson setup build-mingw64 -Drenderer-api=vulkan -Drenderer=libplacebo \
+ -Dsink-only=false -Dserver=enabled -Dportal=disabled -Dclient=disabled \
+ -Dcodecs=ffmpeg -Dcodec-hwaccel=enabled -Dsubtitles=enabled \
+ -Dtests=disabled -Dwin32-compat=false --cross-file ./cross/x86_64-w64-mingw32.txt \
+ --default-library=static --buildtype=release --optimization=2 -Ddebug=false --strip
+
+meson setup build-mingw32-min -Drenderer-api=gl -Drenderer=momo \
+ -Dsink-only=false -Dserver=enabled -Dportal=disabled -Dclient=disabled \
+ -Dcodecs=ffmpeg -Dcodec-hwaccel=disabled -Dsubtitles=enabled \
+ -Dtests=disabled -Dwin32-compat=true --cross-file ./cross/i686-w64-mingw32.txt \
+ --default-library=static --buildtype=release --optimization=s -Ddebug=false --strip
diff --git a/env/msvc_build.sh b/env/msvc_build.sh
new file mode 100644
index 0000000..ccc5625
--- /dev/null
+++ b/env/msvc_build.sh
@@ -0,0 +1,13 @@
+#! /usr/bin/env sh
+
+# meson subprojects download msvc-wine
+# ./vsdownload.py --dest env/msvc-root
+# ./install.sh env/msvc-root
+
+BIN=env/msvc-root/bin/x64 . subprojects/msvc-wine/msvcenv-native.sh
+export INCLUDE="$HOME/c/camu/subprojects/vulkan-headers-1.4.313/include;/nix/store/jx7aqhh225lhxdxdbiw42mrf2awvpdsq-clang-19.1.7-lib/lib/clang/19/include;$INCLUDE"
+CC=clang-cl CXX=clang-cl meson setup build-clang-cl -Drenderer-api=dx11 \
+ -Dsink-only=false -Dserver=enabled -Dportal=disabled -Dclient=disabled \
+ -Dcodecs=ffmpeg -Dcodec-hwaccel=enabled -Dsubtitles=enabled \
+ -Dtests=disabled --cross-file ./cross/x86_64-w64-msvc-clang.txt --default-library=static --buildtype=release \
+ --optimization=2 -Ddebug=false --strip -Db_vscrt=static_from_buildtype
diff --git a/flake.lock b/flake.lock
index 58e0db0..7bcd673 100644
--- a/flake.lock
+++ b/flake.lock
@@ -23,11 +23,11 @@
]
},
"locked": {
- "lastModified": 1747279714,
- "narHash": "sha256-UdxlE8yyrKiGq3bgGyJ78AdFwh+fuRAruKtyFY5Zq5I=",
+ "lastModified": 1748134483,
+ "narHash": "sha256-5PBK1nV8X39K3qUj8B477Aa2RdbLq3m7wRxUKRtggX4=",
"owner": "nix-community",
"repo": "home-manager",
- "rev": "954615c510c9faa3ee7fb6607ff72e55905e69f2",
+ "rev": "c1e671036224089937e111e32ea899f59181c383",
"type": "github"
},
"original": {
@@ -39,11 +39,11 @@
},
"nixos-hardware": {
"locked": {
- "lastModified": 1747129300,
- "narHash": "sha256-L3clA5YGeYCF47ghsI7Tcex+DnaaN/BbQ4dR2wzoiKg=",
+ "lastModified": 1747900541,
+ "narHash": "sha256-dn64Pg9xLETjblwZs9Euu/SsjW80pd6lr5qSiyLY1pg=",
"owner": "NixOS",
"repo": "nixos-hardware",
- "rev": "e81fd167b33121269149c57806599045fd33eeed",
+ "rev": "11f2d9ea49c3e964315215d6baa73a8d42672f06",
"type": "github"
},
"original": {
@@ -91,11 +91,11 @@
},
"nixpkgs_2": {
"locked": {
- "lastModified": 1747179050,
- "narHash": "sha256-qhFMmDkeJX9KJwr5H32f1r7Prs7XbQWtO0h3V0a0rFY=",
+ "lastModified": 1748026106,
+ "narHash": "sha256-6m1Y3/4pVw1RWTsrkAK2VMYSzG4MMIj7sqUy7o8th1o=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "adaa24fbf46737f3f1b5497bf64bae750f82942e",
+ "rev": "063f43f2dbdef86376cc29ad646c45c46e93234c",
"type": "github"
},
"original": {
diff --git a/flake.nix b/flake.nix
index 4a94a91..8cd0d95 100644
--- a/flake.nix
+++ b/flake.nix
@@ -18,7 +18,7 @@
outputs = { self, nixpkgs, nixos-hardware, nixos-wsl, home-manager }: let
overlays = [
(self: super: {
- libplacebo = super.libplacebo.overrideAttrs (old: {
+ libplacebo = super.libplacebo.overrideAttrs (oldAttrs: {
patches = [
./subprojects/packagefiles/libplacebo/cache_ref_rect.diff
./subprojects/packagefiles/libplacebo/compiler_warnings.diff
@@ -27,7 +27,7 @@
./subprojects/packagefiles/libplacebo/info_priv_hash.diff
];
});
- libcue = super.libcue.overrideAttrs (old: {
+ libcue = super.libcue.overrideAttrs (oldAttrs: {
patches = [
./subprojects/packagefiles/libcue/55.diff
# https://github.com/lipnitsk/libcue/pull/4
@@ -52,13 +52,22 @@
"i686-linux"
"aarch64-linux"
] (system:
- function (import nixpkgs {
+ function (import (nixpkgs.legacyPackages.${system}.applyPatches {
+ src = nixpkgs;
+ name = "nixpkgs-camu";
+ patches = [ ];
+ }) {
inherit system;
config = {
allowUnfree = true;
android_sdk.accept_license = true;
};
}));
+ buildWithFlags = (pkg: flags:
+ pkg.overrideAttrs (oldAttrs: {
+ env.NIX_CFLAGS_COMPILE = (oldAttrs.env.NIX_CFLAGS_COMPILE or "") + " ${flags}";
+ })
+ );
in rec {
packages = forAllSupportedSystems (pkgs: {
default = with pkgs; stdenv.mkDerivation {
@@ -228,10 +237,11 @@
};
mingw64 = with pkgs; let
- gcc = pkgsCross.ucrt64.buildPackages.wrapCC
- (pkgsCross.ucrt64.buildPackages.gcc-unwrapped.override ({
+ gcc = pkgsCross.ucrt64.buildPackages.wrapCCWith {
+ cc = (pkgsCross.ucrt64.buildPackages.gcc-unwrapped.override ({
threadsCross = { model = "win32"; package = null; };
}));
+ };
gccWin32Stdenv = overrideCC pkgsCross.ucrt64.stdenv gcc;
in mkShell.override { stdenv = gccWin32Stdenv; } {
# Note that `cc` has to invoke a native compiler not a cross compiler.
@@ -251,6 +261,11 @@
cmake
gdb
wineWowPackages.staging
+ # clang-cl
+ clang
+ msitools
+ lld
+ libllvm
# wine build
flex
bison
@@ -270,16 +285,22 @@
];
buildInputs = with pkgsCross.ucrt64; [
(zlib.override { static = true; shared = false; })
+ (bzip2.override { enableStatic = true; enableShared = false; })
+ #(shaderc.overrideAttrs (oldAttrs: {
+ # cmakeFlags = oldAttrs.cmakeFlags ++ [ "-DBUILD_STATIC_LIBS=ON" "-DBUILD_SHARED_LIBS=OFF" ];
+ #}))
(soxr.overrideAttrs (oldAttrs: {
- cmakeFlags = [ "-DBUILD_STATIC_LIBS=ON" "-DBUILD_SHARED_LIBS=OFF" ];
+ cmakeFlags = oldAttrs.cmakeFlags ++ [ "-DBUILD_STATIC_LIBS=ON" "-DBUILD_SHARED_LIBS=OFF" ];
}))
(openssl.override { static = true; })
xxHash
(libiconv.override { enableStatic = true; enableShared = false; })
vulkan-headers
];
+ # https://old.reddit.com/r/NixOS/comments/1c4lc1n/how_to_run_this_minimal_python_script_with/kzpao62/
shellHook = ''
export SHELL="${pkgs.bashInteractive}/bin/bash"
+ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.stdenv.cc.cc.lib}/lib"
export NIX_BUILD_SHELL=$SHELL
export NIX_SHELL="camu-mingw64"
export PS1="(\$NIX_SHELL)"$PS1
@@ -287,25 +308,29 @@
};
mingw32 = with pkgs; let
- gcc = pkgsCross.mingw32.buildPackages.wrapCC
- (pkgsCross.mingw32.buildPackages.gcc-unwrapped.override ({
+ gcc = pkgsCross.mingw32.buildPackages.wrapCCWith {
+ cc = (pkgsCross.mingw32.buildPackages.gcc-unwrapped.override (old: {
threadsCross = { model = "win32"; package = null; };
}));
+ };
gccWin32Stdenv = overrideCC pkgsCross.mingw32.stdenv gcc;
in mkShell.override { stdenv = gccWin32Stdenv; } {
NIX_HARDENING_ENABLE = "";
nativeBuildInputs = mingw64.nativeBuildInputs;
buildInputs = with pkgsCross.mingw32; [
- (zlib.override { static = true; shared = false; })
- (soxr.overrideAttrs (oldAttrs: {
- cmakeFlags = [ "-DBUILD_STATIC_LIBS=ON" "-DBUILD_SHARED_LIBS=OFF" ];
+ ((buildWithFlags zlib "-Os").override { static = true; shared = false; })
+ ((buildWithFlags bzip2 "-Os").override { enableStatic = true; enableShared = false; })
+ ((buildWithFlags soxr "-Os").overrideAttrs (oldAttrs: {
+ cmakeFlags = oldAttrs.cmakeFlags ++ [ "-DBUILD_STATIC_LIBS=ON" "-DBUILD_SHARED_LIBS=OFF" ];
}))
- (openssl.override { static = true; })
- xxHash
- (libiconv.override { enableStatic = true; enableShared = false; })
+ ((buildWithFlags openssl "-Os").override { static = true; })
+ (buildWithFlags xxHash "-Os")
+ ((buildWithFlags libiconv "-Os").override { enableStatic = true; enableShared = false; })
+ vulkan-headers
];
shellHook = ''
export SHELL="${pkgs.bashInteractive}/bin/bash"
+ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.stdenv.cc.cc.lib}/lib"
export NIX_BUILD_SHELL=$SHELL
export NIX_SHELL="camu-mingw32"
export PS1="(\$NIX_SHELL)"$PS1
diff --git a/meson.build b/meson.build
index 947fd9a..0c136ee 100644
--- a/meson.build
+++ b/meson.build
@@ -1,8 +1,13 @@
-project('camu', 'c', version: '0.01',
+project('camu', ['c', 'cpp'], # Marking cpp here is required for subproject cross-builds.
+ version: '0.01',
meson_version: '>=0.63.0',
default_options: ['warning_level=2', 'c_std=c99'],
license: 'GPL-3.0-only')
+# Fail early if 'Compiler for build machine not found'.
+add_languages('c', native: true)
+add_languages('cpp', native: true)
+
compiler = meson.get_compiler('c')
cmake = import('cmake')
@@ -10,10 +15,11 @@ is_debug = get_option('debug')
is_minsize = get_option('optimization') == 's'
is_linux = host_machine.system() == 'linux'
is_windows = host_machine.system() == 'windows'
+is_msvc = compiler.get_id() == 'msvc' or compiler.get_id() == 'clang-cl'
is_android = host_machine.system() == 'android'
-alabaster = subproject('libalabaster', default_options: ['tests=false'])
-naunet_opts = ['tests=false']
+alabaster = subproject('libalabaster')
+naunet_opts = []
if get_option('portal').enabled()
naunet_opts += ['json=enabled', 'curl=enabled']
endif
@@ -30,7 +36,7 @@ no_video = meson.is_subproject()
stela_opts += get_option('renderer-api') == 'vulkan' ? 'window=glfw' : 'window=wayland'
elif is_android
stela_opts += 'window=glfm'
- elif is_windows and get_option('renderer-api') == 'dx11'
+ elif is_windows
stela_opts += 'window=win32'
else
stela_opts += 'window=glfw'
@@ -40,7 +46,7 @@ no_video = meson.is_subproject()
elif get_option('renderer-api') == 'dx11'
stela_opts += 'api=dx11'
else
- stela_opts += get_option('renderer') == 'tiger' ? 'api=gles' : 'api=gl'
+ stela_opts += 'api=gl'
endif
if get_option('renderer-api') == 'gl-rpi'
stela_opts += 'egl-brcm=true'
@@ -81,6 +87,6 @@ if not meson.is_subproject()
subdir('src/fruits')
endif
-if get_option('tests')
+if get_option('tests').auto() and not meson.is_subproject()
subdir('tests')
endif
diff --git a/meson_options.txt b/meson_options.txt
index a9053ce..47ea575 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,6 +1,6 @@
option('codecs', type: 'array', choices: ['ffmpeg', 'stb_image', 'spng', 'wuffs'], value: ['ffmpeg'])
option('codec-hwaccel', type: 'feature', value: 'disabled')
-option('renderer', type: 'combo', choices: ['libplacebo', 'tiger'], value: 'libplacebo')
+option('renderer', type: 'combo', choices: ['libplacebo', 'momo'], value: 'libplacebo')
option('renderer-api', type: 'combo', choices: ['vulkan', 'dx11', 'gl', 'gl-rpi'], value: 'gl')
option('subtitles', type: 'feature', value: 'enabled')
@@ -10,4 +10,5 @@ option('sink', type: 'feature', value: 'enabled')
option('sink-only', type: 'boolean', value: false)
option('client', type: 'feature', value: 'disabled')
-option('tests', type: 'boolean', value: false)
+option('win32-compat', type: 'boolean', value: false, yield: true)
+option('tests', type: 'feature', value: 'auto', yield: true)
diff --git a/src/codec/codec.h b/src/codec/codec.h
index 14727d3..16e408c 100644
--- a/src/codec/codec.h
+++ b/src/codec/codec.h
@@ -35,8 +35,8 @@ enum {
enum {
CAMU_STREAM_UNKNOWN = AVMEDIA_TYPE_UNKNOWN,
- CAMU_STREAM_AUDIO = AVMEDIA_TYPE_AUDIO, // 1
CAMU_STREAM_VIDEO = AVMEDIA_TYPE_VIDEO, // 0
+ CAMU_STREAM_AUDIO = AVMEDIA_TYPE_AUDIO, // 1
CAMU_STREAM_SUBTITLE = AVMEDIA_TYPE_SUBTITLE,
CAMU_STREAM_ATTACHMENT = AVMEDIA_TYPE_ATTACHMENT
};
@@ -77,12 +77,13 @@ enum {
CAMU_SEEK_SIZE = 0x10000
};
+// Using values from FFmpeg for potentially less confusing errors.
enum {
CAMU_STREAM_UNKNOWN = -1,
- CAMU_STREAM_AUDIO,
- CAMU_STREAM_VIDEO,
- CAMU_STREAM_SUBTITLE,
- CAMU_STREAM_ATTACHMENT
+ CAMU_STREAM_VIDEO = 0,
+ CAMU_STREAM_AUDIO = 1,
+ CAMU_STREAM_SUBTITLE = 3,
+ CAMU_STREAM_ATTACHMENT = 4
};
enum {
@@ -126,7 +127,11 @@ struct camu_audio_format {
s32 format;
s32 sample_rate;
#ifdef CAMU_HAVE_FFMPEG
+#ifndef CAMU_OLD_FFMPEG
AVChannelLayout channel_layout;
+#else
+ u64 channel_layout;
+#endif
#endif
s32 channel_count;
};
@@ -239,17 +244,49 @@ static inline bool camu_resampler_format_matches(struct camu_resampler_format *f
return fmt->in.format == fmt->req.format
&& fmt->in.sample_rate == fmt->req.sample_rate
#ifdef CAMU_HAVE_FFMPEG
+#ifndef CAMU_OLD_FFMPEG
&& av_channel_layout_compare(&fmt->in.channel_layout, &fmt->req.channel_layout) == 0
+#else
+ && fmt->in.channel_layout == fmt->req.channel_layout
+#endif
#endif
&& fmt->in.channel_count == fmt->req.channel_count;
}
+#ifndef CAMU_OLD_FFMPEG
+#define AV_CODECPAR_CHANNEL_LAYOUT(codecpar) ((codecpar)->ch_layout)
+#define AV_CODECPAR_CHANNELS(codecpar) ((codecpar)->ch_layout.nb_channels)
+static inline void camu_default_channel_layout(AVChannelLayout *ch_layout, s32 channels)
+{
+ av_channel_layout_default(ch_layout, channels);
+}
+static inline void camu_copy_channel_layout(AVChannelLayout *dest, AVChannelLayout *src)
+{
+ av_channel_layout_copy(dest, src);
+}
+#else
+#define AV_CODECPAR_CHANNEL_LAYOUT(codecpar) ((codecpar)->channel_layout)
+#define AV_CODECPAR_CHANNELS(codecpar) ((codecpar)->channels)
+static inline void camu_default_channel_layout(u64 *channel_layout, s32 channels)
+{
+ *channel_layout = av_get_default_channel_layout(channels);
+}
+static inline void camu_copy_channel_layout(u64 *dest, u64 *src)
+{
+ *dest = *src;
+}
+#endif
+
static inline void camu_audio_format_copy(struct camu_audio_format *dest, struct camu_audio_format *src)
{
dest->format = src->format;
dest->sample_rate = src->sample_rate;
#ifdef CAMU_HAVE_FFMPEG
+#ifndef CAMU_OLD_FFMPEG
av_channel_layout_copy(&dest->channel_layout, &src->channel_layout);
+#else
+ dest->channel_layout = src->channel_layout;
+#endif
#endif
dest->channel_count = src->channel_count;
}
diff --git a/src/codec/ffmpeg/avio.c b/src/codec/ffmpeg/avio.c
index 154152e..86130d8 100644
--- a/src/codec/ffmpeg/avio.c
+++ b/src/codec/ffmpeg/avio.c
@@ -2,20 +2,20 @@
#include "../../cache/handle.h"
-s32 camu_avio_read(void *data, u8 *buf, s32 count)
+s32 camu_avio_read(void *opaque, u8 *buf, s32 count)
{
- struct cch_handle *handle = (struct cch_handle *)data;
+ struct cch_handle *handle = (struct cch_handle *)opaque;
return cch_handle_read(handle, buf, count);
}
-s32 camu_avio_write(void *data, const u8 *buf, s32 count)
+s32 camu_avio_write(void *opaque, u8 *buf, s32 count)
{
- struct cch_handle *handle = (struct cch_handle *)data;
+ struct cch_handle *handle = (struct cch_handle *)opaque;
return cch_handle_write(handle, buf, count);
}
-s64 camu_avio_seek(void *data, s64 offset, s32 whence)
+s64 camu_avio_seek(void *opaque, s64 offset, s32 whence)
{
- struct cch_handle *handle = (struct cch_handle *)data;
+ struct cch_handle *handle = (struct cch_handle *)opaque;
return (s64)cch_handle_seek(handle, offset, whence);
}
diff --git a/src/codec/ffmpeg/avio.h b/src/codec/ffmpeg/avio.h
index 04aeeb4..bb67c58 100644
--- a/src/codec/ffmpeg/avio.h
+++ b/src/codec/ffmpeg/avio.h
@@ -2,5 +2,6 @@
#include <al/types.h>
-s32 camu_avio_read(void *data, u8 *buf, s32 buf_size);
-s64 camu_avio_seek(void *data, s64 offset, s32 whence);
+s32 camu_avio_read(void *opaque, u8 *buf, s32 buf_size);
+s32 camu_avio_write(void *opaque, u8 *buf, s32 count);
+s64 camu_avio_seek(void *opaque, s64 offset, s32 whence);
diff --git a/src/codec/ffmpeg/common.c b/src/codec/ffmpeg/common.c
index 259ba90..5226df6 100644
--- a/src/codec/ffmpeg/common.c
+++ b/src/codec/ffmpeg/common.c
@@ -2,6 +2,7 @@
#include <al/log.h>
#include <al/lib.h>
#include <libavutil/log.h>
+#include <libavformat/avformat.h>
#include "common.h"
@@ -55,5 +56,8 @@ void camu_ff_set_log_callback(void (*callback)(void *, s32, const char *, va_lis
void camu_ff_common_init(void)
{
log_info("Using FFmpeg version "FFMPEG_VERSION".");
+#ifdef CAMU_OLD_FFMPEG
+ av_register_all();
+#endif
camu_ff_set_log_callback(av_log_callback);
}
diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c
index c22d1c1..e097e0c 100644
--- a/src/codec/ffmpeg/decoder.c
+++ b/src/codec/ffmpeg/decoder.c
@@ -10,11 +10,11 @@
#endif
#ifdef CAMU_FF_DECODER_HWACCEL
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
static const char *hwdevces[] = { "vulkan" };
#elif defined NAUNET_ON_WINDOWS
static const char *hwdevces[] = { "d3d11va" };
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
static const char *hwdevces[] = { "vaapi" };
#endif
diff --git a/src/codec/ffmpeg/decoder.h b/src/codec/ffmpeg/decoder.h
index ab60ef3..4797060 100644
--- a/src/codec/ffmpeg/decoder.h
+++ b/src/codec/ffmpeg/decoder.h
@@ -4,8 +4,8 @@
#include "../codec.h"
-#ifndef CAMU_SINK_NO_VIDEO
-//#define CAMU_FF_DECODER_HWACCEL
+#ifdef CAMU_USE_HWACCEL
+#define CAMU_FF_DECODER_HWACCEL
#endif
struct camu_ff_decoder {
diff --git a/src/codec/ffmpeg/demuxer.c b/src/codec/ffmpeg/demuxer.c
index bf2039f..a5821a2 100644
--- a/src/codec/ffmpeg/demuxer.c
+++ b/src/codec/ffmpeg/demuxer.c
@@ -88,6 +88,13 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl
for (u32 i = 0; i < av->format_context->nb_streams; i++) {
AVStream *stream = av->format_context->streams[i];
enum AVMediaType type = stream->codecpar->codec_type;
+#ifdef CAMU_OLD_FFMPEG
+ // This is probably not correct.
+ if (stream->codecpar->channel_layout == 0) {
+ stream->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+ stream->codecpar->channels = 2;
+ }
+#endif
u64 duration = 0;
if (type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_SUBTITLE) {
// Try to detect attached images.
diff --git a/src/codec/ffmpeg/encoder.c b/src/codec/ffmpeg/encoder.c
index 50e80e4..5d90785 100644
--- a/src/codec/ffmpeg/encoder.c
+++ b/src/codec/ffmpeg/encoder.c
@@ -32,7 +32,7 @@ bool camu_ff_encoder_init(struct camu_ff_encoder *enc, char *encoder_name, char
}
enc->codec_context->sample_rate = 48000;
- av_channel_layout_default(&enc->codec_context->ch_layout, CHANNELS);
+ camu_default_channel_layout(&AV_CODECPAR_CHANNEL_LAYOUT(enc->codec_context), CHANNELS);
enc->codec_context->sample_fmt = AV_SAMPLE_FMT_FLT;
enc->codec_context->bit_rate = bitrate;
enc->codec_context->frame_size = SAMPLES_PER_FRAME;
@@ -62,19 +62,20 @@ bool camu_ff_encoder_init(struct camu_ff_encoder *enc, char *encoder_name, char
av_dict_free(&opts);
AVCodecContext *out_codec = enc->codec_context;
+ AVFrame *frame = av_frame_alloc();
+ frame->format = out_codec->sample_fmt;
+ frame->sample_rate = out_codec->sample_rate;
+ camu_copy_channel_layout(&AV_CODECPAR_CHANNEL_LAYOUT(frame), &AV_CODECPAR_CHANNEL_LAYOUT(out_codec));
+ av_samples_alloc(frame->data, NULL, AV_CODECPAR_CHANNELS(out_codec), SAMPLES_PER_FRAME, frame->format, 1);
+ frame->nb_samples = SAMPLES_PER_FRAME;
+ frame->pts = 0;
- enc->fmt.req.format = out_codec->sample_fmt;
- enc->fmt.req.sample_rate = out_codec->sample_rate;
- av_channel_layout_copy(&enc->fmt.req.channel_layout, &out_codec->ch_layout);
- enc->fmt.req.channel_count = out_codec->ch_layout.nb_channels;
+ enc->fmt.format = frame->format;
+ enc->fmt.sample_rate = frame->sample_rate;
+ camu_copy_channel_layout(&enc->fmt.channel_layout, &AV_CODECPAR_CHANNEL_LAYOUT(frame));
+ enc->fmt.channel_count = AV_CODECPAR_CHANNELS(frame);
- enc->frame = av_frame_alloc();
- enc->frame->format = enc->fmt.req.format;
- enc->frame->sample_rate = enc->fmt.req.sample_rate;
- av_channel_layout_copy(&enc->frame->ch_layout, &enc->fmt.req.channel_layout);
- av_samples_alloc(enc->frame->data, NULL, enc->frame->ch_layout.nb_channels, SAMPLES_PER_FRAME, enc->frame->format, 1);
- enc->frame->nb_samples = SAMPLES_PER_FRAME;
- enc->frame->pts = 0;
+ enc->frame = frame;
return true;
err:
diff --git a/src/codec/ffmpeg/encoder.h b/src/codec/ffmpeg/encoder.h
index 5f7d06f..3ace4d8 100644
--- a/src/codec/ffmpeg/encoder.h
+++ b/src/codec/ffmpeg/encoder.h
@@ -9,7 +9,7 @@ struct camu_ff_encoder {
AVCodecContext *codec_context;
const AVOutputFormat *output_format;
- struct camu_resampler_format fmt;
+ struct camu_audio_format fmt;
AVFrame *frame;
void (*callback)(void *, AVPacket *);
diff --git a/src/codec/ffmpeg/meson.build b/src/codec/ffmpeg/meson.build
index eb68fad..56a75b2 100644
--- a/src/codec/ffmpeg/meson.build
+++ b/src/codec/ffmpeg/meson.build
@@ -3,6 +3,9 @@ ffmpeg_src = [
'packet_ext.c',
]
ffmpeg_args = ['-DCAMU_HAVE_FFMPEG']
+if get_option('codec-hwaccel').enabled()
+ ffmpeg_args += ['-DCAMU_USE_HWACCEL']
+endif
ffmpeg_deps = []
ffmpeg_server_src = [
@@ -16,8 +19,7 @@ ffmpeg_client_src = [
ffmpeg_src,
'decoder.c',
'resampler.c',
- 'scaler.c',
- 'encoder.c'
+ 'scaler.c'
]
ffmpeg_client_deps = []
@@ -38,7 +40,12 @@ libavcodec = dependency('libavcodec', required: false)
libswresample = dependency('libswresample', required: false)
libswscale = dependency('libswscale', required: false)
if not (libavutil.found() and libavformat.found() and libavcodec.found() and libswresample.found() and libswscale.found())
- ffmpeg_proj = subproject('ffmpeg', required: false)
+ if get_option('win32-compat')
+ ffmpeg_proj = subproject('ffmpeg-compat', required: false)
+ ffmpeg_args += ['-DCAMU_OLD_FFMPEG']
+ else
+ ffmpeg_proj = subproject('ffmpeg', required: false)
+ endif
if ffmpeg_proj.found()
libavutil = ffmpeg_proj.get_variable('avutil')
libavformat = ffmpeg_proj.get_variable('avformat')
@@ -48,9 +55,12 @@ if not (libavutil.found() and libavformat.found() and libavcodec.found() and lib
libswscale = ffmpeg_proj.get_variable('swscale')
# Only used to set include dirs for FFmpeg.
ffmpeg_deps += [ffmpeg_proj.get_variable('ffmpeg_include')]
- # We explicitly enable zlib in the FFmpeg build.
+ # We explicitly enable zlib and maybe bzlib in the FFmpeg build.
ffmpeg_deps += [dependency('zlib')]
- if is_windows
+ if not get_option('sink-only')
+ ffmpeg_deps += [dependency('bzip2')]
+ endif
+ if is_windows and not get_option('win32-compat')
# Extra static dependencies for Windows.
ffmpeg_client_deps += [compiler.find_library('bcrypt')]
elif is_android
diff --git a/src/codec/ffmpeg/packet_ext.c b/src/codec/ffmpeg/packet_ext.c
index acf5bbd..a1a6a5e 100644
--- a/src/codec/ffmpeg/packet_ext.c
+++ b/src/codec/ffmpeg/packet_ext.c
@@ -16,7 +16,7 @@ void nn_packet_write_av_codec_parameters(struct nn_packet *packet, AVCodecParame
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->width);
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->height);
NNWT_PACKET_WRITE_TYPE(packet, AVRational, codecpar->sample_aspect_ratio);
-#if LIBAVCODEC_VERSION_INT >= 60
+#if !defined CAMU_OLD_FFMPEG && LIBAVCODEC_VERSION_INT >= 60
NNWT_PACKET_WRITE_TYPE(packet, AVRational, codecpar->framerate);
#endif
NNWT_PACKET_WRITE_TYPE(packet, enum AVFieldOrder, codecpar->field_order);
@@ -26,6 +26,7 @@ void nn_packet_write_av_codec_parameters(struct nn_packet *packet, AVCodecParame
NNWT_PACKET_WRITE_TYPE(packet, enum AVColorSpace, codecpar->color_space);
NNWT_PACKET_WRITE_TYPE(packet, enum AVChromaLocation, codecpar->chroma_location);
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->video_delay);
+#ifndef CAMU_OLD_FFMPEG
// Incomplete.
NNWT_PACKET_WRITE_TYPE(packet, enum AVChannelOrder, codecpar->ch_layout.order);
if (codecpar->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
@@ -33,6 +34,10 @@ void nn_packet_write_av_codec_parameters(struct nn_packet *packet, AVCodecParame
} else {
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->ch_layout.nb_channels);
}
+#else
+ NNWT_PACKET_WRITE_TYPE(packet, u64, codecpar->channel_layout);
+ NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->channels);
+#endif
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->sample_rate);
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->block_align);
NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->frame_size);
@@ -98,7 +103,9 @@ void nn_packet_write_av_packet(struct nn_packet *packet, AVPacket *pkt)
}
NNWT_PACKET_WRITE_TYPE(packet, s64, pkt->duration);
NNWT_PACKET_WRITE_TYPE(packet, s64, pkt->pos);
+#ifndef CAMU_OLD_FFMPEG
NNWT_PACKET_WRITE_TYPE(packet, AVRational, pkt->time_base);
+#endif
}
void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParameters *codecpar)
@@ -120,7 +127,7 @@ void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParamet
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->width);
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->height);
NNWT_PACKET_READ_TYPE(packet, AVRational, codecpar->sample_aspect_ratio);
-#if LIBAVCODEC_VERSION_INT >= 60
+#if !defined CAMU_OLD_FFMPEG && LIBAVCODEC_VERSION_INT >= 60
NNWT_PACKET_READ_TYPE(packet, AVRational, codecpar->framerate);
#endif
NNWT_PACKET_READ_TYPE(packet, enum AVFieldOrder, codecpar->field_order);
@@ -130,6 +137,7 @@ void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParamet
NNWT_PACKET_READ_TYPE(packet, enum AVColorSpace, codecpar->color_space);
NNWT_PACKET_READ_TYPE(packet, enum AVChromaLocation, codecpar->chroma_location);
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->video_delay);
+#ifndef CAMU_OLD_FFMPEG
enum AVChannelOrder order;
NNWT_PACKET_READ_TYPE(packet, enum AVChannelOrder, order);
if (order == AV_CHANNEL_ORDER_NATIVE) {
@@ -141,6 +149,10 @@ void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParamet
NNWT_PACKET_READ_TYPE(packet, s32, nb_channels);
av_channel_layout_default(&codecpar->ch_layout, nb_channels);
}
+#else
+ NNWT_PACKET_READ_TYPE(packet, u64, codecpar->channel_layout);
+ NNWT_PACKET_READ_TYPE(packet, s32, codecpar->channels);
+#endif
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->sample_rate);
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->block_align);
NNWT_PACKET_READ_TYPE(packet, s32, codecpar->frame_size);
@@ -214,5 +226,7 @@ void nn_packet_read_av_packet(struct nn_packet *packet, AVPacket *pkt)
}
NNWT_PACKET_READ_TYPE(packet, s64, pkt->duration);
NNWT_PACKET_READ_TYPE(packet, s64, pkt->pos);
+#ifndef CAMU_OLD_FFMPEG
NNWT_PACKET_READ_TYPE(packet, AVRational, pkt->time_base);
+#endif
}
diff --git a/src/codec/ffmpeg/packet_ext.h b/src/codec/ffmpeg/packet_ext.h
index fab9b36..540cdcb 100644
--- a/src/codec/ffmpeg/packet_ext.h
+++ b/src/codec/ffmpeg/packet_ext.h
@@ -1,8 +1,7 @@
#pragma once
#include <nnwt/packet.h>
-#include <libavcodec/packet.h>
-#include <libavcodec/codec_par.h>
+#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
diff --git a/src/codec/ffmpeg/resampler.c b/src/codec/ffmpeg/resampler.c
index eacc75b..48cca8e 100644
--- a/src/codec/ffmpeg/resampler.c
+++ b/src/codec/ffmpeg/resampler.c
@@ -12,26 +12,35 @@ static bool ff_resampler_init(struct camu_resampler *resamp, struct camu_resampl
camu_audio_format_copy(&av->fmt, &fmt->req);
- s32 ret = swr_alloc_set_opts2(&av->resample_context,
- &fmt->req.channel_layout, fmt->req.format, fmt->req.sample_rate,
- &fmt->in.channel_layout, fmt->in.format, fmt->in.sample_rate, 0, NULL);
- if (ret != 0) {
- log_error("Failed to configure resampler context.");
- return false;
- }
+ SwrContext *swr = swr_alloc();
+
+#ifndef CAMU_OLD_FFMPEG
+ av_opt_set_chlayout(swr, "in_chlayout", &fmt->in.channel_layout, 0);
+ av_opt_set_chlayout(swr, "out_chlayout", &fmt->req.channel_layout, 0);
+#else
+ av_opt_set_channel_layout(swr, "in_channel_layout", fmt->in.channel_layout, 0);
+ av_opt_set_channel_layout(swr, "out_channel_layout", fmt->req.channel_layout, 0);
+#endif
+ av_opt_set_int(swr, "in_sample_rate", fmt->in.sample_rate, 0);
+ av_opt_set_int(swr, "out_sample_rate", fmt->req.sample_rate, 0);
+ av_opt_set_sample_fmt(swr, "in_sample_fmt", fmt->in.format, 0);
+ av_opt_set_sample_fmt(swr, "out_sample_fmt", fmt->req.format, 0);
#ifdef CAMU_HAVE_SOXR
// Slower but more accurate resampler.
- av_opt_set_int(av->resample_context, "resampler", SWR_ENGINE_SOXR, 0);
+ av_opt_set_int(swr, "resampler", SWR_ENGINE_SOXR, 0);
log_info("Using SoX resampler.");
#endif
- if (swr_init(av->resample_context) != 0) {
- swr_free(&av->resample_context);
- log_error("Failed to init resampler context.");
+ s32 ret = swr_init(swr);
+ if (ret != 0) {
+ swr_free(&swr);
+ log_error("Failed to init resampler context (%s).", av_err2str(ret));
return false;
}
+ av->resample_context = swr;
+
return true;
}
@@ -44,7 +53,7 @@ static inline void alloc_sample_data(struct camu_ff_resampler *av, s32 sample_co
{
if (av->sample_count >= sample_count) return;
free_sample_data(av);
- s32 nb_channels = av->fmt.channel_layout.nb_channels;
+ s32 nb_channels = av->fmt.channel_count;
av_samples_alloc(av->data, NULL, nb_channels, sample_count, av->fmt.format, 32);
av->sample_count = sample_count;
}
diff --git a/src/fruits/cmc/meson.build b/src/fruits/cmc/meson.build
index 864af8a..de6d335 100644
--- a/src/fruits/cmc/meson.build
+++ b/src/fruits/cmc/meson.build
@@ -19,7 +19,7 @@ if use_tui
cmc_deps += [notcurses, notcurses_core, codecs_client]
endif
-if is_windows and meson.is_cross_build()
+if is_windows and not is_msvc
cmc_args += ['-static', '-static-libgcc', '-static-libstdc++', '-municode', '-mwindows']
endif
diff --git a/src/fruits/cmc/ui/util/waveform.c b/src/fruits/cmc/ui/util/waveform.c
index 535f219..b114a5e 100644
--- a/src/fruits/cmc/ui/util/waveform.c
+++ b/src/fruits/cmc/ui/util/waveform.c
@@ -5,7 +5,7 @@
#define WITHIN_RMS(low, high, rms) \
((low >= 0 && low <= rms) || (high < 0 && high >= -rms) || (low < 0 && high > 0 && rms > 0))
-#define OUTPUT_WAVEFORM_PNG
+//#define OUTPUT_WAVEFORM_PNG
//#define WAVEFORM_REFERENCE_MODE
#ifdef OUTPUT_WAVEFORM_PNG
#include <nnwt/file.h>
diff --git a/src/fruits/cmsrv/meson.build b/src/fruits/cmsrv/meson.build
index dce3d94..b12d00d 100644
--- a/src/fruits/cmsrv/meson.build
+++ b/src/fruits/cmsrv/meson.build
@@ -8,7 +8,7 @@ if use_tui
cmsrv_deps += [notcurses_core]
endif
-if is_windows and meson.is_cross_build()
+if is_windows and not is_msvc
cmsrv_args += ['-static', '-static-libgcc', '-static-libstdc++', '-municode', '-mwindows']
endif
diff --git a/src/fruits/cmv/cmv.c b/src/fruits/cmv/cmv.c
index 70a0b28..28dcbb5 100644
--- a/src/fruits/cmv/cmv.c
+++ b/src/fruits/cmv/cmv.c
@@ -3,14 +3,16 @@
#include <nnwt/event_loop.h>
#include <nnwt/thread.h>
-#include "../../util/color_palette.h"
-#include "../../codec/ffmpeg/common.h"
#include "../../libsink/desktop.h"
#include "../../server/common.h"
#ifndef CAMU_SINK_ONLY
#include "../../server/server.h"
#endif
#include "../../server/common.h"
+#include "../../util/color_palette.h"
+#ifdef CAMU_HAVE_FFMPEG
+#include "../../codec/ffmpeg/common.h"
+#endif
#include "../common.h"
@@ -95,7 +97,11 @@ static bool parse_exe_name_params(str *exe_name, str *addr, struct lia_prefs *pr
return true;
def:
+#ifdef CAMU_HAVE_SUBTITLES
prefs->enabled_mask = CAMU_MASK_AUDIO | CAMU_MASK_VIDEO | CAMU_MASK_SUBTITLE;
+#else
+ prefs->enabled_mask = CAMU_MASK_AUDIO | CAMU_MASK_VIDEO;
+#endif
prefs->audio_lang = CAMU_LANG_JAPANESE;
prefs->subtitle_lang = CAMU_LANG_ENGLISH;
@@ -175,8 +181,10 @@ s32 window_system_main(u32 argc, str *argv, void *extra)
c.desktop.exit_callback = exit_callback;
c.desktop.userdata = &c;
}
-#endif
str *name = local ? &al_str_c("local") : &al_str_c("desktop");
+#else
+ str *name = &al_str_c("desktop");
+#endif
if (!camu_desktop_connect(&c.desktop, name, &c.loop, type, &addr, CAMU_PORT)) {
return EXIT_FAILURE;
}
diff --git a/src/fruits/cmv/meson.build b/src/fruits/cmv/meson.build
index 870345e..bfd2182 100644
--- a/src/fruits/cmv/meson.build
+++ b/src/fruits/cmv/meson.build
@@ -14,7 +14,7 @@ if use_tui
endif
cmv_link_args = []
-if is_windows and meson.is_cross_build()
+if is_windows and not is_msvc
cmv_link_args += ['-static', '-static-libgcc', '-static-libstdc++', '-municode', '-mwindows']
endif
diff --git a/src/fruits/droid/ctv/gradle/libs.versions.toml b/src/fruits/droid/ctv/gradle/libs.versions.toml
index 4a8d0bc..95dfb43 100644
--- a/src/fruits/droid/ctv/gradle/libs.versions.toml
+++ b/src/fruits/droid/ctv/gradle/libs.versions.toml
@@ -1,5 +1,5 @@
[versions]
-agp = "8.9.1"
+agp = "8.10.0"
[libraries]
diff --git a/src/liana/client.c b/src/liana/client.c
index 164a4d1..626a752 100644
--- a/src/liana/client.c
+++ b/src/liana/client.c
@@ -27,7 +27,12 @@ static void data_packet_callback(void *userdata, struct nn_packet_stream *stream
static s32 stream_compare(const void *a, const void *b)
{
- return (s32)((struct camu_codec_stream *)a)->type - (s32)((struct camu_codec_stream *)b)->type;
+ struct camu_codec_stream *aa = (struct camu_codec_stream *)a;
+ struct camu_codec_stream *bb = (struct camu_codec_stream *)b;
+ if (aa->type == bb->type) {
+ return aa->index - bb->index;
+ }
+ return aa->type - bb->type;
}
static void collect_streams(struct lia_client *client, struct nn_packet *packet)
@@ -49,7 +54,7 @@ static void collect_streams(struct lia_client *client, struct nn_packet *packet)
fmt->sample_rate = nn_packet_read_s32(packet);
fmt->channel_count = nn_packet_read_s32(packet);
#ifdef CAMU_HAVE_FFMPEG
- av_channel_layout_default(&fmt->channel_layout, fmt->channel_count);
+ camu_default_channel_layout(&fmt->channel_layout, fmt->channel_count);
#endif
} else if (type == CAMU_STREAM_VIDEO) {
struct camu_video_format *fmt = &stream.video.fmt;
@@ -80,8 +85,8 @@ static void collect_streams(struct lia_client *client, struct nn_packet *packet)
struct camu_audio_format *fmt = &stream.audio.fmt;
fmt->format = codecpar->format;
fmt->sample_rate = codecpar->sample_rate;
- av_channel_layout_copy(&fmt->channel_layout, &codecpar->ch_layout);
- fmt->channel_count = codecpar->ch_layout.nb_channels;
+ camu_copy_channel_layout(&fmt->channel_layout, &AV_CODECPAR_CHANNEL_LAYOUT(codecpar));
+ fmt->channel_count = AV_CODECPAR_CHANNELS(codecpar);
break;
}
case CAMU_STREAM_VIDEO: {
diff --git a/src/liana/handlers/codec_client.c b/src/liana/handlers/codec_client.c
index fd2569b..38b5d3b 100644
--- a/src/liana/handlers/codec_client.c
+++ b/src/liana/handlers/codec_client.c
@@ -132,9 +132,9 @@ static bool codec_client_handle_packet(struct lia_client_handler *handler, struc
#endif
break;
}
+#endif
default:
al_assert_and_return(false);
-#endif
}
// Restore packet rindex in case we resue it.
diff --git a/src/liana/handlers/codec_server.c b/src/liana/handlers/codec_server.c
index de2c927..3b7d31e 100644
--- a/src/liana/handlers/codec_server.c
+++ b/src/liana/handlers/codec_server.c
@@ -149,7 +149,7 @@ static void codec_server_write_packet(struct lia_server_handler *handler, struct
nn_packet_write_u8(packet, LIANA_PACKET_EOF);
#ifdef LIANA_SERVER_LOOP
codec->pts_offset += codec->demux->get_duration(codec->demux);
- codec->demux->seek(codec->demux, 0);
+ codec->demux->seek(codec->demux, 0, false);
#endif
} else {
nn_packet_write_u8(packet, LIANA_PACKET_ERROR);
diff --git a/src/liana/process.c b/src/liana/process.c
index 0a6d6b6..a8b57d0 100644
--- a/src/liana/process.c
+++ b/src/liana/process.c
@@ -65,10 +65,10 @@ bool lia_prepare_visual_data(struct cch_handle *handle, struct lia_visual_data *
fmt.req.format = CAMU_SAMPLE_FORMAT_S16;
fmt.in.sample_rate = codecpar->sample_rate;
fmt.req.sample_rate = codecpar->sample_rate;
- av_channel_layout_copy(&fmt.in.channel_layout, &codecpar->ch_layout);
- av_channel_layout_copy(&fmt.req.channel_layout, &codecpar->ch_layout);
- fmt.in.channel_count = codecpar->ch_layout.nb_channels;
- fmt.req.channel_count = codecpar->ch_layout.nb_channels;
+ camu_copy_channel_layout(&fmt.in.channel_layout, &AV_CODECPAR_CHANNEL_LAYOUT(codecpar));
+ camu_copy_channel_layout(&fmt.req.channel_layout, &AV_CODECPAR_CHANNEL_LAYOUT(codecpar));
+ fmt.in.channel_count = AV_CODECPAR_CHANNELS(codecpar);
+ fmt.req.channel_count = AV_CODECPAR_CHANNELS(codecpar);
struct raw_samples_data raw;
raw.resampler = resampler;
diff --git a/src/liana/vcr.c b/src/liana/vcr.c
index 4500681..78c2b9c 100644
--- a/src/liana/vcr.c
+++ b/src/liana/vcr.c
@@ -126,9 +126,11 @@ static nn_thread_result NNWT_THREADCALL vcr_track_thread(void *userdata)
continue;
}
- index++; // Count of packets consumed.
+ index++; // Count of packets consumed, also increment for WHOLE_FILE mode.
+#ifndef VCR_BUFFER_WHOLE_FILE
nn_packet_stream_return_packets(vcr->data, al_array_offset(track->cache.cache, 0), index);
al_array_remove_range(track->cache.cache, 0, index);
+#endif
nn_packet_cache_unlock(&track->cache);
@@ -153,7 +155,9 @@ static nn_thread_result NNWT_THREADCALL vcr_track_thread(void *userdata)
if (corked) {
// The cache is already unlocked here.
+#ifndef VCR_BUFFER_WHOLE_FILE
index = 0;
+#endif
} else {
#ifndef VCR_BUFFER_WHOLE_FILE
al_assert(index == packets);
diff --git a/src/libsink/desktop.c b/src/libsink/desktop.c
index 2bbe906..a2d02c9 100644
--- a/src/libsink/desktop.c
+++ b/src/libsink/desktop.c
@@ -8,8 +8,8 @@
#else
#include "../mixer/audio_miniaudio.h"
#endif
-#if defined CAMU_RENDERER_TIGER
-#include "../render/renderer_tiger.h"
+#if defined CAMU_RENDERER_MOMO
+#include "../render/renderer_momo.h"
#elif defined CAMU_RENDERER_LIBPLACEBO
#include "../render/renderer_libplacebo.h"
#endif
@@ -111,8 +111,9 @@ static u8 sink_callback(void *userdata, u8 op, u8 type, void *opaque)
}
static char status[64];
-static void log_playback_pos(struct camu_sink *sink)
+static void log_sink_status(struct camu_desktop *c)
{
+ struct camu_sink *sink = &c->sink;
struct camu_sink_entry *current = camu_sink_get_current(sink);
if (!current) {
camu_sink_return_current(sink);
@@ -140,10 +141,10 @@ static void log_playback_pos(struct camu_sink *sink)
offset += al_snprintf(status + offset, sizeof(status) - offset, "]");
status[offset] = '\0';
- log_info("%s", status);
+ log_info("%s, window size: %ux%u", status, c->scr.width, c->scr.height);
return;
notplaying:
- log_info("Not playing.");
+ log_info("Not playing, window size: %ux%u", c->scr.width, c->scr.height);
}
static void screen_callback(void *userdata, u8 op, void *opaque)
@@ -175,7 +176,7 @@ static void screen_callback(void *userdata, u8 op, void *opaque)
camu_sink_shuffle(&c->sink);
break;
case CAMU_SCREEN_STATUS:
- log_playback_pos(&c->sink);
+ log_sink_status(c);
break;
#ifdef CAMU_SCREEN_DEBUG_KEY
case CAMU_SCREEN_DEBUG:
@@ -199,8 +200,8 @@ bool camu_desktop_open(struct camu_desktop *c, const char *window_name)
if (!camu_screen_init(&c->scr) || !camu_screen_create_window(&c->scr, window_name)) {
return false;
}
-#if defined CAMU_RENDERER_TIGER
- c->renderer = camu_renderer_tiger_create();
+#if defined CAMU_RENDERER_MOMO
+ c->renderer = camu_renderer_momo_create();
#elif defined CAMU_RENDERER_LIBPLACEBO
c->renderer = camu_renderer_lp_create();
#endif
diff --git a/src/libsink/sink.c b/src/libsink/sink.c
index 07bb604..56be556 100644
--- a/src/libsink/sink.c
+++ b/src/libsink/sink.c
@@ -468,18 +468,17 @@ static void mixer_callback(void *userdata, u8 op)
struct camu_sink *sink = (struct camu_sink *)userdata;
if (op == CAMU_MIXER_EMPTY) {
log_info("Mixer empty.");
-#ifndef LIANA_LIST_SCUFFED_LOOP
// We need to sync with do_add_entry() because the order of
// the START/STOP's in the queue matters.
nn_mutex_lock(&sink->lock);
- queue_cmd(sink, (struct camu_sink_cmd){
- .op = STOP,
- .value.i = CAMU_SINK_AUDIO
- });
+ // This feels a bit too loose.
+ if (!(sink->current && AUDIO_STATE(sink->current) == BUFFER_ADDED)) {
+ queue_cmd(sink, (struct camu_sink_cmd){
+ .op = STOP,
+ .value.i = CAMU_SINK_AUDIO
+ });
+ }
nn_mutex_unlock(&sink->lock);
-#else
- (void)sink;
-#endif
}
}
@@ -1526,11 +1525,15 @@ static struct nn_rpc_command commands[] = {
{ .op = CAMU_SINK_SEEK, .callback = seek_command_callback, .userdata = NULL }
};
+// @TODO: Send sink id from list.
static void identify_callback(void *userdata, struct nn_rpc_connection *conn, struct nn_packet *packet)
{
struct camu_sink *sink = (struct camu_sink *)userdata;
- (void)sink;
- // @TODO: Send sink id from list.
+ if (sink->type == NNWT_SOCKET_UNIX) {
+ log_info("Sink connected to %.*s.", al_str_x(&sink->addr));
+ } else {
+ log_info("Sink connected to %.*s:%hu.", al_str_x(&sink->addr), sink->port);
+ }
nn_packet_stream_return_packet(conn->stream, packet);
}
diff --git a/src/mixer/audio_miniaudio.c b/src/mixer/audio_miniaudio.c
index 7e31abf..a0db3f3 100644
--- a/src/mixer/audio_miniaudio.c
+++ b/src/mixer/audio_miniaudio.c
@@ -27,6 +27,9 @@ static ma_backend backends[] = {
#ifdef MA_ENABLE_WASAPI
ma_backend_wasapi,
#endif
+#ifdef MA_ENABLE_DSOUND
+ ma_backend_dsound,
+#endif
#ifdef MA_ENABLE_AAUDIO
ma_backend_aaudio,
#endif
@@ -142,7 +145,7 @@ static void audio_miniaudio_pick_format(struct camu_audio *audio, struct camu_re
fmt->req.sample_rate = ma->device.playback.internalSampleRate;
u32 channels = ma->device.playback.channels;
#ifdef CAMU_HAVE_FFMPEG
- av_channel_layout_default(&fmt->req.channel_layout, channels);
+ camu_default_channel_layout(&fmt->req.channel_layout, channels);
#endif
fmt->req.channel_count = channels;
}
@@ -162,7 +165,7 @@ static void data_callback(ma_device *device, void *output, const void *input, u3
#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 8
#else
#define DEFAULT_PERIODS 3
-#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 48
+#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 64
#endif
static bool audio_miniaudio_configure_stream(struct camu_audio *audio, void *opaque)
diff --git a/src/mixer/audio_null.c b/src/mixer/audio_null.c
index a6eeea3..2fa5ddb 100644
--- a/src/mixer/audio_null.c
+++ b/src/mixer/audio_null.c
@@ -15,7 +15,7 @@ static void audio_null_pick_format(struct camu_audio *audio, struct camu_resampl
fmt->req.format = fmt->in.format;
fmt->req.channel_count = fmt->in.channel_count;
#ifdef CAMU_HAVE_FFMPEG
- av_channel_layout_default(&fmt->req.channel_layout, fmt->in.channel_count);
+ camu_default_channel_layout(&fmt->req.channel_layout, fmt->in.channel_count);
#endif
fmt->req.sample_rate = fmt->in.sample_rate;
}
diff --git a/src/mixer/meson.build b/src/mixer/meson.build
index c09f779..e4840c1 100644
--- a/src/mixer/meson.build
+++ b/src/mixer/meson.build
@@ -22,7 +22,11 @@ if use_miniaudio
mixer_deps += [libpulse, alsa]
mixer_args += ['-DMA_ENABLE_ALSA', '-DMA_ENABLE_PULSEAUDIO', '-DMA_NO_RUNTIME_LINKING']
elif is_windows
- mixer_args += ['-DMA_ENABLE_WASAPI']
+ if get_option('win32-compat')
+ mixer_args += ['-DMA_ENABLE_DSOUND']
+ else
+ mixer_args += ['-DMA_ENABLE_WASAPI']
+ endif
elif is_android
mixer_args += ['-DMA_ENABLE_AAUDIO']
endif
diff --git a/src/render/meson.build b/src/render/meson.build
index 98b86ec..7e3e394 100644
--- a/src/render/meson.build
+++ b/src/render/meson.build
@@ -2,23 +2,20 @@ render_src = []
render_deps = []
render_args = []
-if get_option('renderer') == 'tiger'
- render_src += ['renderer_tiger.c', 'queue_tiger.c']
- linmath_h = subproject('linmath.h').get_variable('linmath_h')
- render_deps += [linmath_h]
- libm = compiler.find_library('m', required: false)
- if libm.found()
- render_deps += [libm]
- endif
- render_args += ['-DCAMU_RENDERER_TIGER']
+if get_option('renderer') == 'momo'
+ render_src += ['renderer_momo.c', 'queue_momo.c']
+ subdir('momo')
+ render_deps += [momo]
+ render_args += ['-DCAMU_RENDERER_MOMO']
elif get_option('renderer') == 'libplacebo'
libplacebo_opts = ['warning_level=2', 'demos=false', 'tests=false', 'bench=false', 'fuzz=false',
'glslang=disabled',
'gl-proc-addr=disabled',
'vk-proc-addr=disabled',
- 'lcms=disabled',
- 'dovi=disabled',
- 'libdovi=disabled'
+ 'lcms=auto',
+ 'dovi=auto',
+ 'libdovi=auto',
+ 'xxhash=auto'
]
if get_option('renderer-api') == 'vulkan' or get_option('renderer-api') == 'dx11'
@@ -27,12 +24,19 @@ elif get_option('renderer') == 'libplacebo'
render_deps += [shaderc]
else
shaderc_opts = cmake.subproject_options()
+ shaderc_opts.set_override_option('warning_level', '0') # Doesn't work.
reltype = is_minsize ? 'MinSizeRel' : 'Release'
shaderc_opts.add_cmake_defines({ 'CMAKE_BUILD_TYPE': is_debug ? 'Debug' : reltype })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_INSTALL': true })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_TESTS': true })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_EXAMPLES': true })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_COPYRIGHT_CHECK': true })
+ shaderc_opts.add_cmake_defines({ 'ENABLE_GLSLANG_BINARIES': false })
+ shaderc_opts.add_cmake_defines({ 'ENABLE_SPVREMAPPER': false })
+ shaderc_opts.add_cmake_defines({ 'ENABLE_HLSL': false })
+ spirv_optimizer = true
+ shaderc_opts.add_cmake_defines({ 'ENABLE_OPT': spirv_optimizer })
+ shaderc_opts.add_cmake_defines({ 'ENABLE_EXCEPTIONS_ON_MSVC': false })
shaderc_proj = cmake.subproject('shaderc', options: shaderc_opts)
shaderc = shaderc_proj.dependency('shaderc')
meson.override_dependency('shaderc', shaderc)
@@ -43,20 +47,31 @@ elif get_option('renderer') == 'libplacebo'
shaderc_proj.dependency('OSDependent'),
shaderc_proj.dependency('GenericCodeGen'),
shaderc_proj.dependency('SPIRV'),
- shaderc_proj.dependency('SPIRV-Tools-opt'),
shaderc_proj.dependency('SPIRV-Tools-static')
]
+ if spirv_optimizer
+ render_deps += [
+ shaderc_proj.dependency('SPIRV-Tools-opt'),
+ ]
+ endif
endif
#glslang = dependency('glslang', required: false, allow_fallback: false)
#if glslang.found()
# render_deps += [glslang]
#else
+ # #spirv_tools_opts = cmake.subproject_options()
+ # #spirv_tools_opts.set_override_option('warning_level', '0')
+ # #reltype = is_minsize ? 'MinSizeRel' : 'Release'
+ # #spirv_tools_opts.add_cmake_defines({ 'CMAKE_BUILD_TYPE': is_debug ? 'Debug' : reltype })
+ # #spirv_tools_proj = cmake.subproject('SPIRV-Tools', options: spirv_tools_opts)
# glslang_opts = cmake.subproject_options()
+ # glslang_opts.set_override_option('warning_level', '0')
# reltype = is_minsize ? 'MinSizeRel' : 'Release'
# glslang_opts.add_cmake_defines({ 'CMAKE_BUILD_TYPE': is_debug ? 'Debug' : reltype })
+ # #glslang_opts.add_cmake_defines({ 'ALLOW_EXTERNAL_SPIRV_TOOLS': true })
# glslang_opts.add_cmake_defines({ 'ENABLE_OPT': '0' })
# glslang_proj = cmake.subproject('glslang', options: glslang_opts)
- # message('CMake targets:\n - ' + '\n - '.join(glslang_proj.target_list()))
+ # #message('CMake targets:\n - ' + '\n - '.join(glslang_proj.target_list()))
# glslang = glslang_proj.dependency('glslang')
# spirv = glslang_proj.dependency('SPIRV')
# glslang_default_resource_limits = glslang_proj.dependency('glslang-default-resource-limits')
@@ -118,22 +133,27 @@ if get_option('subtitles').enabled()
default_options: [
'doc=disabled',
'nls=disabled',
- 'tests=disabled',
'tools=disabled',
'cache-build=disabled'
])
+ else
+ libass_opts += ['directwrite=enabled']
endif
# libass(e46aede):meson.build:84
# fontconfig(72b9a48):meson.build:28
freetype = dependency('freetype2',
version: '>=9.17.3',
default_options: [
- 'harfbuzz=disabled'
+ 'warning_level=0',
+ 'harfbuzz=disabled',
+ 'png=disabled'
])
# libass(e46aede):meson.build:90
fribidi = dependency('fribidi',
version: '>=0.19.1',
default_options: [
+ 'warning_level=0',
+ 'c_args=-Wno-stringop-overflow', # This doesn't work.
'docs=false',
'tests=false',
'bin=false'
@@ -143,7 +163,6 @@ if get_option('subtitles').enabled()
version: '>=2.0.0',
default_options: [
'freetype=disabled',
- 'tests=disabled',
'introspection=disabled',
'docs=disabled',
'utilities=disabled',
diff --git a/src/render/momo/meson.build b/src/render/momo/meson.build
new file mode 100644
index 0000000..092293a
--- /dev/null
+++ b/src/render/momo/meson.build
@@ -0,0 +1,12 @@
+momo_src = ['momo.c']
+momo_deps = []
+momo_args = []
+
+libm = compiler.find_library('m', required: false)
+if libm.found()
+ momo_deps += [libm]
+endif
+linmath_h = subproject('linmath.h').get_variable('linmath_h')
+momo_deps += [linmath_h]
+
+momo = declare_dependency(sources: momo_src, dependencies: momo_deps, compile_args: momo_args)
diff --git a/src/render/momo/momo.c b/src/render/momo/momo.c
new file mode 100644
index 0000000..5239efd
--- /dev/null
+++ b/src/render/momo/momo.c
@@ -0,0 +1,35 @@
+#define AL_LOG_SECTION "momo"
+#include <al/log.h>
+
+#include "momo.h"
+
+bool MOMO_Init(MOMO_Renderer *mmr,
+#ifdef STELA_API_OPENGL
+ bool (*MakeCurrent)(void *),
+ void (*ReleaseCurrent)(void *),
+ void (*SwapBuffers)(void *),
+#endif
+ void *Private)
+{
+ mmr->Private = Private;
+#ifdef STELA_API_OPENGL
+ mmr->GL.MakeCurrent = MakeCurrent;
+ mmr->GL.ReleaseCurrent = ReleaseCurrent;
+ mmr->GL.SwapBuffers = SwapBuffers;
+ mmr->GL.MakeCurrent(mmr->Private);
+ const char *gl_version = (const char *)glGetString(GL_VERSION);
+ if (gl_version) {
+ log_info("GL context version: %s.", gl_version);
+ } else {
+ log_warn("Somehow failed to retrive GL_VERSION.");
+ }
+#endif
+ return true;
+}
+
+void MOMO_Render(MOMO_Renderer *mmr)
+{
+#ifdef STELA_API_OPENGL
+ mmr->GL.SwapBuffers(mmr->Private);
+#endif
+}
diff --git a/src/render/momo/momo.h b/src/render/momo/momo.h
new file mode 100644
index 0000000..76686ba
--- /dev/null
+++ b/src/render/momo/momo.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <al/types.h>
+
+#ifdef STELA_API_OPENGL
+#include <stl/gl.h>
+#endif
+
+typedef struct {
+ struct {
+ bool (*MakeCurrent)(void *);
+ void (*ReleaseCurrent)(void *);
+ void (*SwapBuffers)(void *);
+ } GL;
+ void *Private;
+} MOMO_Renderer;
+
+bool MOMO_Init(MOMO_Renderer *mmr,
+#ifdef STELA_API_OPENGL
+ bool (*MakeCurrent)(void *),
+ void (*ReleaseCurrent)(void *),
+ void (*SwapBuffers)(void *),
+#endif
+ void *Private);
+void MOMO_Render(MOMO_Renderer *mmr);
diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c
index 7fe9258..5932944 100644
--- a/src/render/queue_libplacebo.c
+++ b/src/render/queue_libplacebo.c
@@ -30,6 +30,7 @@ static bool queue_lp_configure_subtitles(struct camu_frame_queue *queue, u32 wid
ass_set_frame_size(lq->ass_renderer, width, height);
ass_set_storage_size(lq->ass_renderer, width, height);
ass_set_fonts(lq->ass_renderer, NULL, NULL, ASS_FONTPROVIDER_AUTODETECT, NULL, 0);
+ ass_set_hinting(lq->ass_renderer, ASS_HINTING_NONE);
AVCodecParameters *codecpar = stream->av.stream->codecpar;
ass_process_codec_private(lq->ass_track, (const char *)codecpar->extradata,
codecpar->extradata_size);
diff --git a/src/render/queue_momo.c b/src/render/queue_momo.c
new file mode 100644
index 0000000..8e8d7e3
--- /dev/null
+++ b/src/render/queue_momo.c
@@ -0,0 +1,68 @@
+#include "queue_momo.h"
+
+static void queue_momo_push(struct camu_frame_queue *queue, struct camu_codec_frame *frame, f64 pts)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)queue;
+ (void)mq;
+ (void)pts;
+ camu_codec_frame_discard(frame);
+}
+
+#ifdef CAMU_HAVE_FFMPEG
+static void queue_momo_push_av_frame(struct camu_frame_queue *queue, AVFrame *frame, f64 pts)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)queue;
+ (void)mq;
+ (void)pts;
+ av_frame_free(&frame);
+}
+#endif
+
+static void queue_momo_flush(struct camu_frame_queue *queue)
+{
+ (void)queue;
+}
+
+static s32 queue_momo_count(struct camu_frame_queue *queue)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)queue;
+ (void)mq;
+ return 1;
+}
+
+static u8 queue_momo_read(struct camu_frame_queue *queue, f64 pts, void *out)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)queue;
+ (void)mq;
+ (void)pts;
+ (void)out;
+ return CAMU_QUEUE_OK;
+}
+
+static void queue_momo_reset(struct camu_frame_queue *queue)
+{
+ struct camu_frame_queue_momo *tq = (struct camu_frame_queue_momo *)queue;
+ (void)tq;
+}
+
+static void queue_momo_free(struct camu_frame_queue **queue)
+{
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)*queue;
+ al_free(mq);
+ *queue = NULL;
+}
+
+struct camu_frame_queue *camu_frame_queue_momo_create(void)
+{
+ struct camu_frame_queue_momo *mq = al_alloc_object(struct camu_frame_queue_momo);
+ mq->q.push = queue_momo_push;
+#ifdef CAMU_HAVE_FFMPEG
+ mq->q.push_av_frame = queue_momo_push_av_frame;
+#endif
+ mq->q.flush = queue_momo_flush;
+ mq->q.count = queue_momo_count;
+ mq->q.read = queue_momo_read;
+ mq->q.reset = queue_momo_reset;
+ mq->q.free = queue_momo_free;
+ return (struct camu_frame_queue *)mq;
+}
diff --git a/src/render/queue_momo.h b/src/render/queue_momo.h
new file mode 100644
index 0000000..c4bf5d1
--- /dev/null
+++ b/src/render/queue_momo.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "../buffer/frame_queue.h"
+
+struct camu_frame_queue_momo {
+ struct camu_frame_queue q;
+};
+
+struct camu_frame_queue *camu_frame_queue_momo_create(void);
diff --git a/src/render/queue_tiger.c b/src/render/queue_tiger.c
deleted file mode 100644
index df072d2..0000000
--- a/src/render/queue_tiger.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <al/lib.h>
-#include <stl/gl.h>
-
-#include "queue_tiger.h"
-
-#define GL_UNPACK_ROW_LENGTH 0x0CF2
-
-static void upload_texture(struct camu_frame_queue_tiger *tq, u8 *data, u32 width, u32 height, s32 format, s32 linesize)
-{
- glGenTextures(1, &tq->texture_id);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, tq->texture_id);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- //if (frame->flags & CAMU_FRAME_DEVICE_ALLOCATED) {
- // glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tq->tr->texture_buffer);
- //}
- glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 0);
- switch (format) {
- case CAMU_PIXEL_FORMAT_RGBA:
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
- 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
- break;
- case CAMU_PIXEL_FORMAT_RGB:
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
- 0, GL_RGB, GL_UNSIGNED_BYTE, data);
- break;
- default:
- al_assert(false);
- }
- //glGenerateMipmap(GL_TEXTURE_2D);
-}
-
-static void queue_tiger_push(struct camu_frame_queue *queue, struct camu_codec_frame *frame, f64 pts)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)pts;
- tq->queued_frame = frame;
-}
-
-#ifdef CAMU_HAVE_FFMPEG
-static void queue_tiger_push_av_frame(struct camu_frame_queue *queue, AVFrame *frame, f64 pts)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)pts;
- tq->queued_av_frame = frame;
-}
-#endif
-
-static void queue_tiger_flush(struct camu_frame_queue *queue)
-{
- (void)queue;
-}
-
-static s32 queue_tiger_count(struct camu_frame_queue *queue)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)tq;
- return 1;
-}
-
-static u8 queue_tiger_read(struct camu_frame_queue *queue, f64 pts, void *out)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)pts;
- if (tq->queued_frame) {
- struct camu_codec_frame *frame = tq->queued_frame;
- s32 linesize = frame->video.width;
- upload_texture(tq, frame->data, frame->video.width, frame->video.height, frame->format, linesize);
- camu_codec_frame_discard(frame);
- tq->queued_frame = NULL;
- tq->uploaded = true;
- }
-#ifdef CAMU_HAVE_FFMPEG
- if (tq->queued_av_frame) {
- AVFrame *frame = tq->queued_av_frame;
- s32 linesize = frame->linesize[0];
- switch (frame->format) {
- case CAMU_PIXEL_FORMAT_RGBA:
- linesize /= 4;
- break;
- case CAMU_PIXEL_FORMAT_RGB:
- linesize /= 3;
- break;
- }
- upload_texture(tq, frame->data[0], frame->width, frame->height, frame->format, linesize);
- av_frame_free(&frame);
- tq->queued_av_frame = NULL;
- tq->uploaded = true;
- }
-#endif
- if (!tq->uploaded) return CAMU_QUEUE_MORE;
- *((GLuint *)out) = tq->texture_id;
- return CAMU_QUEUE_OK;
-}
-
-static void queue_tiger_reset(struct camu_frame_queue *queue)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)queue;
- (void)tq;
-}
-
-static void queue_tiger_free(struct camu_frame_queue **queue)
-{
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)*queue;
- glDeleteTextures(1, &tq->texture_id);
- al_free(tq);
- *queue = NULL;
-}
-
-struct camu_frame_queue *camu_frame_queue_tiger_create(void)
-{
- struct camu_frame_queue_tiger *tq = al_alloc_object(struct camu_frame_queue_tiger);
- tq->queued_frame = NULL;
- tq->queued_av_frame = NULL;
- tq->uploaded = false;
- tq->q.push = queue_tiger_push;
-#ifdef CAMU_HAVE_FFMPEG
- tq->q.push_av_frame = queue_tiger_push_av_frame;
-#endif
- tq->q.flush = queue_tiger_flush;
- tq->q.count = queue_tiger_count;
- tq->q.read = queue_tiger_read;
- tq->q.reset = queue_tiger_reset;
- tq->q.free = queue_tiger_free;
- return (struct camu_frame_queue *)tq;
-}
diff --git a/src/render/queue_tiger.h b/src/render/queue_tiger.h
deleted file mode 100644
index af0e229..0000000
--- a/src/render/queue_tiger.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include <stl/gl.h>
-
-#include "../buffer/frame_queue.h"
-
-struct camu_frame_queue_tiger {
- struct camu_frame_queue q;
- GLuint texture_id;
- struct camu_renderer_tiger *tr;
- struct camu_codec_frame *queued_frame;
-#ifdef CAMU_HAVE_FFMPEG
- struct AVFrame *queued_av_frame;
-#endif
- bool uploaded;
-};
-
-struct camu_frame_queue *camu_frame_queue_tiger_create(void);
diff --git a/src/render/renderer.h b/src/render/renderer.h
index 1e6ffc0..d2590b1 100644
--- a/src/render/renderer.h
+++ b/src/render/renderer.h
@@ -7,14 +7,9 @@
#endif
#if defined STELA_API_OPENGL
-#define CAMU_RENDERER_OPENGL
#ifdef STELA_USE_EGL
#include <stl/egl.h>
#endif
-#elif defined STELA_API_VULKAN
-#define CAMU_RENDERER_VULKAN
-#elif defined STELA_API_DX11
-#define CAMU_RENDERER_DX11
#endif
#include "../codec/codec.h"
@@ -24,28 +19,32 @@ enum {
CAMU_SCALING_NEAREST
};
+enum {
+ CAMU_BACKGROUND_DEFAULT = 0,
+ CAMU_BACKGROUND_TRANSPARENT
+};
+
struct camu_frame_queue;
struct camu_screen;
struct camu_renderer {
bool (*create_renderer)(
struct camu_renderer *, u32 *, u32 *,
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *),
VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *),
const char *const *(*vk_get_extensions)(u32 *),
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
HWND win32_window,
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
#ifdef STELA_USE_EGL
EGLDisplay display,
EGLContext context,
#endif
- void (*get_gl_proc_address(char const *procname))(void),
+ void (*get_gl_proc_address(char const *))(void),
bool (*gl_load_loader)(void *),
bool (*gl_make_current)(void *),
void (*gl_release_current)(void *),
void (*gl_swap_buffers)(void *),
-#elif defined CAMU_RENDERER_DX11
#endif
void *priv);
struct camu_frame_queue *(*create_queue)(struct camu_renderer *);
@@ -54,6 +53,7 @@ struct camu_renderer {
void (*resize)(struct camu_renderer *, u32 *, u32 *);
void (*set_fullscreen)(struct camu_renderer *, bool);
void (*set_scaling)(struct camu_renderer *, u8);
+ void (*set_background)(struct camu_renderer *, u8);
void (*render)(struct camu_renderer *, struct camu_screen *, bool);
#ifdef CAMU_HAVE_FFMPEG
s32 (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, s32 flags);
diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c
index a2105d6..bfe8c47 100644
--- a/src/render/renderer_libplacebo.c
+++ b/src/render/renderer_libplacebo.c
@@ -9,7 +9,7 @@
#include "../screen/screen.h"
#include "../util/color_palette.h"
-#ifdef CAMU_RENDERER_DX11
+#ifdef STELA_API_DX11
#include <nnwt/windows.h>
#define COBJMACROS
#include <libplacebo/d3d11.h>
@@ -42,7 +42,7 @@ static void renderer_lp_resize(struct camu_renderer *renderer, u32 *width, u32 *
}
}
-#ifdef CAMU_RENDERER_DX11
+#ifdef STELA_API_DX11
static void renderer_lp_set_fullscreen(struct camu_renderer *renderer, bool fullscreen)
{
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
@@ -69,6 +69,21 @@ static void renderer_lp_set_scaling(struct camu_renderer *renderer, u8 mode)
}
}
+static void renderer_lp_set_background(struct camu_renderer *renderer, u8 mode)
+{
+ struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
+ switch (mode) {
+ case CAMU_BACKGROUND_DEFAULT:
+ clear_color[3] = 1.f;
+ lr->params.background = PL_CLEAR_TILES;
+ break;
+ case CAMU_BACKGROUND_TRANSPARENT:
+ clear_color[3] = 0.f;
+ lr->params.background = PL_CLEAR_SKIP;
+ break;
+ }
+}
+
static void log_callback(void *userdata, enum pl_log_level level, const char *message)
{
(void)userdata;
@@ -79,19 +94,34 @@ static void log_callback(void *userdata, enum pl_log_level level, const char *me
}
}
+#ifdef CAMU_HAVE_SUBTITLES
+// level = 0(FATAL)-7(VERBOSE).
+static void ass_log_callback(s32 level, const char *fmt, va_list args, void *userdata)
+{
+ (void)userdata;
+ if (level <= 1) {
+ al_logv(AL_LOG_ERROR, "ass", fmt, args);
+ } else {
+#ifdef AL_DEBUG
+ al_logv(AL_LOG_DEBUG, "ass", fmt, args);
+#endif
+ }
+}
+#endif
+
static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *width, u32 *height,
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *),
VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *),
const char *const *(*vk_get_extensions)(u32 *),
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
HWND win32_window,
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
#ifdef STELA_USE_EGL
EGLDisplay display,
EGLContext context,
#endif
- void (*get_gl_proc_address(char const *procname))(void),
+ void (*get_gl_proc_address(char const *))(void),
bool (*gl_load_loader)(void *),
bool (*gl_make_current)(void *),
void (*gl_release_current)(void *),
@@ -111,13 +141,18 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
clear_color[2] = 255.f;
*/
+//#define LIBPLACEBO_LOG_TRACE
lr->logger = pl_log_create(PL_API_VER, pl_log_params(
.log_cb = log_callback,
.log_priv = NULL,
+#ifdef LIBPLACEBO_LOG_TRACE
+ .log_level = PL_LOG_TRACE
+#else
.log_level = PL_LOG_INFO
+#endif
));
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
VkResult err;
u32 num;
@@ -153,6 +188,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
lr->swapchain = pl_vulkan_create_swapchain(lr->vk, pl_vulkan_swapchain_params(
.surface = lr->surface,
.present_mode = VK_PRESENT_MODE_FIFO_KHR
+ //.present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR
));
if (!lr->swapchain) {
log_error("Failed to create vulkan swapchain.");
@@ -162,7 +198,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
lr->gpu = lr->vk->gpu;
log_info("Using Vulkan.");
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
(void)priv;
lr->d3d11 = pl_d3d11_create(lr->logger, pl_d3d11_params(
.debug = false
@@ -183,7 +219,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
lr->gpu = lr->d3d11->gpu;
log_info("Using DirectX 11.");
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
(void)gl_load_loader;
lr->gl = pl_opengl_create(lr->logger, pl_opengl_params(
.debug = false,
@@ -230,8 +266,17 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
// Clear manually so we can draw multiple images per frame.
lr->params.border = PL_CLEAR_SKIP;
+ lr->params.background = PL_CLEAR_TILES;
+ /*
+ lr->params.background_color[0] = clear_color[0];
+ lr->params.background_color[1] = clear_color[1];
+ lr->params.background_color[2] = clear_color[2];
+ lr->params.background_transparency = clear_color[3];
+ */
+
// Prioritize a more consistent image.
lr->params.correct_subpixel_offsets = true;
+ //lr->params.distort_params = pl_distort_params(.unscaled = false);
#if 0
struct nn_file file;
@@ -254,6 +299,7 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, u32 *wid
#ifdef CAMU_HAVE_SUBTITLES
lr->ass = ass_library_init();
+ ass_set_message_cb(lr->ass, ass_log_callback, lr);
#endif
lr->last_render_tick = nn_get_tick();
@@ -339,7 +385,7 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
if (mix.frames) {
// weighted is only set when read() returns QUEUE_OK.
do_gpu_finish |= weighted;
- // Terrible hack. Let's us distinguish single frames with the same dimensions.
+ // Terrible hack. Lets us distinguish single frames with the same dimensions.
// Tied to a libplacebo patch to consider info_priv in the hash.
// Also, add in reset_pts to account for buffer resets. This is a completely
// broken "hash" of the f64 pts value but hopefully it works for now.
@@ -413,8 +459,8 @@ void renderer_lp_free(struct camu_renderer **renderer)
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)*renderer;
if (lr->renderer) pl_renderer_destroy(&lr->renderer);
if (lr->swapchain) pl_swapchain_destroy(&lr->swapchain);
-#if defined CAMU_RENDERER_VULKAN
-#elif defined CAMU_RENDERER_OPENGL
+#if defined STELA_API_VULKAN
+#elif defined STELA_API_OPENGL
if (lr->gl) pl_opengl_destroy(&lr->gl);
#endif
if (lr->logger) pl_log_destroy(&lr->logger);
@@ -433,12 +479,13 @@ struct camu_renderer *camu_renderer_lp_create(void)
lr->r.add_font = renderer_lp_add_font;
lr->r.get_latency = renderer_lp_get_latency;
lr->r.resize = renderer_lp_resize;
-#ifdef CAMU_RENDERER_DX11
+#ifdef STELA_API_DX11
lr->r.set_fullscreen = renderer_lp_set_fullscreen;
#else
lr->r.set_fullscreen = NULL;
#endif
lr->r.set_scaling = renderer_lp_set_scaling;
+ lr->r.set_background = renderer_lp_set_background;
lr->r.render = renderer_lp_render;
lr->r.free = renderer_lp_free;
return (struct camu_renderer *)lr;
diff --git a/src/render/renderer_libplacebo.h b/src/render/renderer_libplacebo.h
index 7b1cfa2..a0125ba 100644
--- a/src/render/renderer_libplacebo.h
+++ b/src/render/renderer_libplacebo.h
@@ -10,23 +10,23 @@
#include "renderer.h"
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
#include <libplacebo/vulkan.h>
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
#include <libplacebo/d3d11.h>
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
#include <libplacebo/opengl.h>
#endif
struct camu_renderer_lp {
struct camu_renderer r;
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
VkSurfaceKHR surface;
pl_vulkan vk;
pl_vk_inst vk_inst;
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
pl_d3d11 d3d11;
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
pl_opengl gl;
#endif
pl_gpu gpu;
diff --git a/src/render/renderer_momo.c b/src/render/renderer_momo.c
new file mode 100644
index 0000000..9f217bf
--- /dev/null
+++ b/src/render/renderer_momo.c
@@ -0,0 +1,97 @@
+#define AL_LOG_SECTION "renderer_momo"
+#include <al/log.h>
+
+#include "renderer_momo.h"
+#include "queue_momo.h"
+
+static void renderer_momo_resize(struct camu_renderer *renderer, u32 *width, u32 *height)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)renderer;
+ (void)mr;
+ (void)width;
+ (void)height;
+}
+
+static bool renderer_momo_create_renderer(struct camu_renderer *renderer, u32 *width, u32 *height,
+#if defined STELA_API_OPENGL
+#ifdef STELA_USE_EGL
+ EGLDisplay display,
+ EGLContext context,
+#endif
+ void (*get_gl_proc_address(char const *))(void),
+ bool (*gl_load_loader)(void *),
+ bool (*gl_make_current)(void *),
+ void (*gl_release_current)(void *),
+ void (*gl_swap_buffers)(void *),
+#endif
+ void *priv)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)renderer;
+ (void)width;
+ (void)height;
+#if defined STELA_API_OPENGL
+#ifdef STELA_USE_EGL
+ (void)display;
+ (void)context;
+#endif
+ (void)get_gl_proc_address;
+ (void)gl_load_loader;
+ MOMO_Init(&mr->mmr, gl_make_current, gl_release_current, gl_swap_buffers, priv);
+#endif
+#ifdef CAMU_HAVE_SUBTITLES
+ mr->ass = ass_library_init();
+ // Just to keep these linked in the exe for platform testing.
+ ASS_Renderer *ar = ass_renderer_init(mr->ass);
+ ASS_Track *at = ass_new_track(mr->ass);
+ (void)at;
+ u32 w = *width, h = *height;
+ ass_set_frame_size(ar, w, h);
+ ass_set_storage_size(ar, w, h);
+ ass_set_fonts(ar, NULL, NULL, ASS_FONTPROVIDER_AUTODETECT, NULL, 0);
+ ass_set_hinting(ar, ASS_HINTING_NONE);
+#endif
+ return true;
+}
+
+static struct camu_frame_queue *renderer_momo_create_queue(struct camu_renderer *renderer)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)renderer;
+ struct camu_frame_queue *q = camu_frame_queue_momo_create();
+ struct camu_frame_queue_momo *mq = (struct camu_frame_queue_momo *)q;
+ (void)mr;
+ (void)mq;
+ return q;
+}
+
+static u32 renderer_momo_get_latency(struct camu_renderer *renderer)
+{
+ (void)renderer;
+ return 0;
+}
+
+static void renderer_momo_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)renderer;
+ (void)scr;
+ (void)force;
+ MOMO_Render(&mr->mmr);
+}
+
+static void renderer_momo_free(struct camu_renderer **renderer)
+{
+ struct camu_renderer_momo *mr = (struct camu_renderer_momo *)*renderer;
+ al_free(mr);
+ *renderer = NULL;
+}
+
+struct camu_renderer *camu_renderer_momo_create(void)
+{
+ struct camu_renderer_momo *mr = al_alloc_object(struct camu_renderer_momo);
+ mr->r.create_renderer = renderer_momo_create_renderer;
+ mr->r.create_queue = renderer_momo_create_queue;
+ mr->r.get_latency = renderer_momo_get_latency;
+ mr->r.resize = renderer_momo_resize;
+ mr->r.render = renderer_momo_render;
+ mr->r.free = renderer_momo_free;
+ return (struct camu_renderer *)mr;
+}
diff --git a/src/render/renderer_momo.h b/src/render/renderer_momo.h
new file mode 100644
index 0000000..3b9084b
--- /dev/null
+++ b/src/render/renderer_momo.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#ifdef CAMU_HAVE_SUBTITLES
+#include <ass/ass.h>
+#endif
+
+#include "momo/momo.h"
+
+#include "renderer.h"
+
+struct camu_renderer_momo {
+ struct camu_renderer r;
+ MOMO_Renderer mmr;
+#ifdef CAMU_HAVE_SUBTITLES
+ ASS_Library *ass;
+#endif
+};
+
+struct camu_renderer *camu_renderer_momo_create(void);
diff --git a/src/render/renderer_tiger.c b/src/render/renderer_tiger.c
deleted file mode 100644
index eb99e0c..0000000
--- a/src/render/renderer_tiger.c
+++ /dev/null
@@ -1,320 +0,0 @@
-#define AL_LOG_SECTION "renderer_tiger"
-#include <al/log.h>
-#include <al/lib.h>
-#include <linmath.h>
-
-#include "../screen/view.h"
-#include "../screen/screen.h"
-#include "../util/color_palette.h"
-
-#include "renderer_tiger.h"
-#include "queue_tiger.h"
-
-#ifdef CAMU_RENDERER_OPENGL
-static const GLfloat default_vertices[] = {
- 0.f, 0.f, 0.f, 0.f, 0.f,
- 0.f, 1.f, 0.f, 0.f, 1.f,
- 1.f, 0.f, 0.f, 1.f, 0.f,
- 1.f, 0.f, 0.f, 1.f, 0.f,
- 0.f, 1.f, 0.f, 0.f, 1.f,
- 1.f, 1.f, 0.f, 1.f, 1.f
-};
-
-static GLfloat clear_color[4] = { 0.f, 0.f, 0.f, 1.f };
-
-static const GLchar *default_vs = \
- "#version 100\n" \
- "attribute vec3 a_Position;\n" \
- "attribute vec2 a_TexCoord;\n" \
- "varying vec2 v_TexCoord;\n" \
- "uniform mat4 g_ModelViewProjectionMatrix;\n" \
- "void main() {\n" \
- " gl_Position = g_ModelViewProjectionMatrix * vec4(a_Position, 1.0);\n" \
- " v_TexCoord = a_TexCoord;\n" \
- "}";
-
-static const GLchar *default_fs = \
- "#version 100\n" \
- "precision mediump float;\n" \
- "varying vec2 v_TexCoord;\n" \
- "uniform sampler2D g_Texture0;\n" \
- "void main() {\n" \
- " gl_FragColor = texture2D(g_Texture0, v_TexCoord);\n" \
- "}";
-
-static bool compile(GLuint shader, const GLchar *source, GLchar *error)
-{
- glShaderSource(shader, 1, &source, 0);
- glCompileShader(shader);
-
- GLint status;
-
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
-
- if (status == GL_FALSE) {
- glGetShaderInfoLog(shader, 256, NULL, error);
- return false;
- }
-
- return true;
-}
-
-static bool compile_shaders(struct camu_renderer_tiger *tr)
-{
- tr->program = glCreateProgram();
-
- GLchar error[256];
-
- GLuint vs_shader = glCreateShader(GL_VERTEX_SHADER);
- if (!compile(vs_shader, default_vs, error)) {
- log_error("Failed to compile vertex shader (%.*s)", sizeof(error), error);
- return false;
- }
-
- GLuint fs_shader = glCreateShader(GL_FRAGMENT_SHADER);
- if (!compile(fs_shader, default_fs, error)) {
- log_error("Failed to compile fragment shader (%.*s)", sizeof(error), error);
- return false;
- }
-
- glAttachShader(tr->program, vs_shader);
- glAttachShader(tr->program, fs_shader);
- glLinkProgram(tr->program);
-
- return true;
-}
-#endif
-
-static void renderer_tiger_resize(struct camu_renderer *renderer, u32 *width, u32 *height)
-{
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- (void)tr;
- (void)width;
- (void)height;
-}
-
-static bool renderer_tiger_create_renderer(struct camu_renderer *renderer, u32 *width, u32 *height,
-#if defined CAMU_RENDERER_VULKAN
- VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *),
- void (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *),
- const char *const *(*vk_get_extensions)(u32 *),
-#elif defined CAMU_RENDERER_OPENGL
-#ifdef STELA_USE_EGL
- EGLDisplay display,
- EGLContext context,
-#endif
- void (*get_gl_proc_address(char const *procname))(void),
- bool (*gl_load_loader)(void *),
- bool (*gl_make_current)(void *),
- void (*gl_release_current)(void *),
- void (*gl_swap_buffers)(void *),
-#endif
- void *priv)
-{
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- (void)width;
- (void)height;
-#ifdef CAMU_RENDERER_OPENGL
- (void)display;
- (void)context;
- (void)get_gl_proc_address;
-
- tr->load_loader = gl_load_loader;
- tr->make_current = gl_make_current;
- tr->release_current = gl_release_current;
- tr->swap_buffers = gl_swap_buffers;
- tr->priv = priv;
-
- tr->make_current(tr->priv);
-
- if (!tr->load_loader(tr->priv)) {
- return false;
- }
-
- clear_color[0] = ((global_color_palette.colors[0] >> 16) & 0xff) / 255.f;
- clear_color[1] = ((global_color_palette.colors[0] >> 8) & 0xff) / 255.f;
- clear_color[2] = ((global_color_palette.colors[0]) & 0xff) / 255.f;
-
- glClearColor(clear_color[0], clear_color[1], clear_color[2], 1.f);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glGenBuffers(1, &tr->vbo);
- glBindBuffer(GL_ARRAY_BUFFER, tr->vbo);
- glBufferData(GL_ARRAY_BUFFER, sizeof(default_vertices), default_vertices, GL_STATIC_DRAW);
-
- if (!compile_shaders(tr)) return false;
-
- glUseProgram(tr->program);
-
- GLint pos = glGetAttribLocation(tr->program, "a_Position");
- glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)0);
- if (stl_gl_check_error()) {
- log_error("glVertexAttribPointer returned error, use GLES context.");
- al_assert_and_return(false);
- }
- glEnableVertexAttribArray(pos);
- GLint texcoord = glGetAttribLocation(tr->program, "a_TexCoord");
- glVertexAttribPointer(texcoord, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void *)12);
- glEnableVertexAttribArray(texcoord);
-
- //glGenBuffers(1, &tr->texture_buffer);
-#endif
-
-#ifdef CAMU_HAVE_FFMPEG
- tr->r.get_buffer2 = NULL;
- tr->r.opaque = NULL;
-#endif
-
- return true;
-}
-
-static struct camu_frame_queue *renderer_tiger_create_queue(struct camu_renderer *renderer)
-{
-#ifdef CAMU_RENDERER_OPENGL
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- struct camu_frame_queue *q = camu_frame_queue_tiger_create();
- struct camu_frame_queue_tiger *tq = (struct camu_frame_queue_tiger *)q;
- tq->tr = tr;
- return q;
-#endif
-}
-
-static u32 renderer_tiger_get_latency(struct camu_renderer *renderer)
-{
- (void)renderer;
- return 0;
-}
-
-static void set_uniform(struct camu_renderer_tiger *tr, const GLchar *name,
- u8 type, void *value)
-{
-#ifdef CAMU_RENDERER_OPENGL
- GLint loc = glGetUniformLocation(tr->program, name);
- if (loc == -1) return;
-
- switch (type)
- {
- case TYPE_FLOAT:
- glUniform1f(loc, *((GLfloat *)value));
- break;
- case TYPE_SAMPLER2D:
- glUniform1i(loc, (GLuint)(*((GLfloat *)value)));
- break;
- case TYPE_VEC2:
- glUniform2fv(loc, 1, (GLfloat *)value);
- break;
- case TYPE_VEC3:
- glUniform3fv(loc, 1, (GLfloat *)value);
- break;
- case TYPE_VEC4:
- glUniform4fv(loc, 1, (GLfloat *)value);
- break;
- case TYPE_MAT4:
- glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat *)value);
- break;
- case TYPE_MAT3:
- glUniformMatrix3fv(loc, 1, GL_FALSE, (GLfloat *)value);
- break;
- case TYPE_INVALID:
- break;
- }
-#endif
-}
-
-static void renderer_tiger_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
-{
-#ifdef CAMU_RENDERER_OPENGL
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- (void)force;
-
- tr->make_current(tr->priv);
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- glUseProgram(tr->program);
- glBindBuffer(GL_ARRAY_BUFFER, tr->vbo);
- glActiveTexture(GL_TEXTURE0);
-
-#ifdef CAMU_SCREEN_THREADED
- if (al_atomic_load(u8)(&scr->queued, AL_ATOMIC_RELAXED)) {
- camu_screen_run_queue(scr);
- }
-#endif
-
- if (scr->videos.count > 0) {
- struct camu_screen_video *video = &al_array_last(scr->videos);
-
- GLuint texture_id;
- bool weighted;
- if (camu_video_buffer_read(video->buf, &texture_id, &weighted)) {
- glBindTexture(GL_TEXTURE_2D, texture_id);
-
- mat4x4 model;
- mat4x4_identity(model);
- mat4x4_ortho(model, 0.f, (f32)scr->width, (f32)scr->height, 0.f, -1.f, 1.f);
- mat4x4_translate_in_place(model, (f32)video->view.x_offset, (f32)video->view.y_offset, 0.f);
- mat4x4_scale_aniso(model, model, (f32)video->view.zoom, (f32)video->view.zoom, 1.f);
- mat4x4_scale_aniso(model, model, (f32)video->view.width, (f32)video->view.height, 1.f);
- set_uniform(tr, "g_ModelViewProjectionMatrix", TYPE_MAT4, model);
-
- GLuint texture0 = 0;
- set_uniform(tr, "g_Texture0", TYPE_SAMPLER2D, &texture0);
-
- glViewport(0, 0, scr->width, scr->height);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- }
- }
-
- tr->swap_buffers(tr->priv);
-#endif
-
- tr->release_current(tr->priv);
-}
-
-/*
-static void *renderer_tiger_get_device_ptr(struct camu_renderer *renderer, size_t length)
-{
- (void)renderer;
- (void)length;
- return NULL;
-#ifdef CAMU_RENDERER_OPENGL
- //struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- //glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tr->texture_buffer);
- //glBufferData(GL_PIXEL_UNPACK_BUFFER, length, NULL, GL_STREAM_DRAW);
- //return glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, length, GL_MAP_WRITE_BIT);
-#endif
-}
-
-static void renderer_tiger_commit_device_ptr(struct camu_renderer *renderer)
-{
- (void)renderer;
-#ifdef CAMU_RENDERER_OPENGL
- //struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
- //glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tr->texture_buffer);
- //glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
-#endif
-}
-*/
-
-static void renderer_tiger_free(struct camu_renderer **renderer)
-{
- struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)*renderer;
- glDeleteProgram(tr->program);
- glDeleteBuffers(1, &tr->vbo);
- al_free(tr);
- *renderer = NULL;
-}
-
-struct camu_renderer *camu_renderer_tiger_create(void)
-{
- struct camu_renderer_tiger *tr = al_alloc_object(struct camu_renderer_tiger);
- tr->r.create_renderer = renderer_tiger_create_renderer;
- tr->r.create_queue = renderer_tiger_create_queue;
- tr->r.get_latency = renderer_tiger_get_latency;
- tr->r.resize = renderer_tiger_resize;
- tr->r.render = renderer_tiger_render;
- tr->r.free = renderer_tiger_free;
- return (struct camu_renderer *)tr;
-}
diff --git a/src/render/renderer_tiger.h b/src/render/renderer_tiger.h
deleted file mode 100644
index 5891c20..0000000
--- a/src/render/renderer_tiger.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-#include <stl/gl.h>
-
-#include "renderer.h"
-
-enum {
- TYPE_INVALID = 0,
- TYPE_FLOAT,
- TYPE_VEC4,
- TYPE_VEC3,
- TYPE_VEC2,
- TYPE_MAT4,
- TYPE_MAT3,
- TYPE_SAMPLER2D
-};
-
-struct camu_renderer_tiger {
- struct camu_renderer r;
- GLuint vao;
- GLuint vbo;
- GLuint program;
- GLuint texture_buffer;
- bool (*load_loader)(void *);
- bool (*make_current)(void *);
- void (*release_current)(void *);
- void (*swap_buffers)(void *);
- void *priv;
-};
-
-struct camu_renderer *camu_renderer_tiger_create(void);
diff --git a/src/screen/screen.c b/src/screen/screen.c
index 23afa7e..0ff5eec 100644
--- a/src/screen/screen.c
+++ b/src/screen/screen.c
@@ -51,7 +51,7 @@ static void do_resize(struct camu_screen *scr, u32 width, u32 height)
camu_view_calculate(&video->view, scr->width, scr->height);
}
// No buffers resize.
- al_atomic_store(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
+ al_atomic_add(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
}
static void resize_callback(void *userdata, u32 width, u32 height)
@@ -309,6 +309,18 @@ static bool key_callback(void *userdata, u8 state, u16 button)
log_info("Scaling filters enabled.");
}
return true;
+ case STELA_KEY_C:
+ scr->transparent_background = !scr->transparent_background;
+ if (scr->transparent_background) {
+ scr->renderer->set_background(scr->renderer, CAMU_BACKGROUND_TRANSPARENT);
+ log_info("Background transparent.");
+ } else {
+ scr->renderer->set_background(scr->renderer, CAMU_BACKGROUND_DEFAULT);
+ log_info("Background solid.");
+ }
+ // Force refresh for if there's no video buffer.
+ al_atomic_add(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
+ return true;
default:
break;
}
@@ -402,6 +414,7 @@ bool camu_screen_create_window(struct camu_screen *scr, const char *name)
scr->height = scr->window->height;
scr->fullscreen = false;
scr->scaling_disabled = false;
+ scr->transparent_background = false;
#ifdef STELA_EVENT_BUFFER
nn_thread_create(&scr->thread, event_thread, scr);
#endif
@@ -412,13 +425,13 @@ bool camu_screen_create_renderer(struct camu_screen *scr, struct camu_renderer *
{
scr->renderer = renderer;
return renderer->create_renderer(renderer, &scr->width, &scr->height,
-#if defined CAMU_RENDERER_VULKAN
+#if defined STELA_API_VULKAN
scr->window->get_vk_proc_address,
scr->window->vk_create_surface,
scr->window->vk_get_extensions,
-#elif defined CAMU_RENDERER_DX11
+#elif defined STELA_API_DX11
scr->window->win32_window,
-#elif defined CAMU_RENDERER_OPENGL
+#elif defined STELA_API_OPENGL
#ifdef STELA_USE_EGL
scr->window->egl_display,
scr->window->egl_context,
@@ -587,14 +600,14 @@ void camu_screen_set_state(struct camu_screen *scr, s32 state)
if (al_atomic_load(s32)(&scr->state, AL_ATOMIC_ACQUIRE) != CAMU_SCREEN_STOPPED) {
al_atomic_store(s32)(&scr->state, state, AL_ATOMIC_RELEASE);
if (state == CAMU_SCREEN_PAUSED) {
- al_atomic_store(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
+ al_atomic_add(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
}
}
}
void camu_screen_force_refresh(struct camu_screen *scr)
{
- al_atomic_store(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
+ al_atomic_add(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELAXED);
camu_screen_wake(scr);
}
@@ -622,13 +635,15 @@ bool camu_screen_tick(struct camu_screen *scr, bool *force)
{
s32 state = al_atomic_load(s32)(&scr->state, AL_ATOMIC_RELAXED);
al_assert(state != CAMU_SCREEN_STOPPED);
- bool paused = state == CAMU_SCREEN_PAUSED;
- bool do_render = camu_screen_poll(scr, paused) || !paused;
u32 force_refresh = al_atomic_load(u32)(&scr->force_refresh, AL_ATOMIC_ACQUIRE);
+ bool paused = state == CAMU_SCREEN_PAUSED && force_refresh == 0;
+ bool do_render = camu_screen_poll(scr, paused) || !paused;
+ // Should be AL_ATOMIC_ACQ_REL.
+ force_refresh = al_atomic_load(u32)(&scr->force_refresh, AL_ATOMIC_ACQUIRE);
do_render |= force_refresh > 0;
*force = force_refresh > 0;
if (force_refresh > 0) {
- al_atomic_store(u32)(&scr->force_refresh, 0, AL_ATOMIC_RELEASE);
+ al_atomic_sub(u32)(&scr->force_refresh, 1, AL_ATOMIC_RELEASE);
}
return do_render;
}
diff --git a/src/screen/screen.h b/src/screen/screen.h
index 4ba07c2..afd2dee 100644
--- a/src/screen/screen.h
+++ b/src/screen/screen.h
@@ -64,6 +64,7 @@ struct camu_screen {
u32 height;
bool fullscreen;
bool scaling_disabled;
+ bool transparent_background;
u64 last_click_ts;
f64 last_mouse_y;
f64 last_mouse_x;
diff --git a/src/server/server.c b/src/server/server.c
index 6f8da78..ec99921 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -616,6 +616,7 @@ static u8 parse_resource_type(str *line)
return CAMU_RESOURCE_HTTP;
#else
if (0) {
+ (void)line;
#endif
#if CACHE_HAVE_CDIO
} else if (al_str_cmp(line, &al_str_c("cdda://"), 0, 7) == 0) {
@@ -812,7 +813,7 @@ static void connection_closed_callback(void *userdata, struct nn_rpc_connection
struct camu_server_sink *sink;
al_array_foreach(server->sinks, i, sink) {
if (sink->conn == conn) {
- log_info("Sink removed.");
+ log_info("Sink \"%.*s\" removed.", al_str_x(&sink->name));
struct lia_list *list;
al_array_foreach(server->lists, j, list) {
lia_list_remove_sink(list, sink);
diff --git a/subprojects/SPIRV-Cross.wrap b/subprojects/SPIRV-Cross.wrap
index 672cb44..a74d4be 100644
--- a/subprojects/SPIRV-Cross.wrap
+++ b/subprojects/SPIRV-Cross.wrap
@@ -4,3 +4,5 @@ url = https://github.com/KhronosGroup/SPIRV-Cross.git
revision = ccff428086b625241de9f225dab0a53269b4d12c
depth = 1
method = cmake
+patch_directory = SPIRV-Cross
+diff_files = SPIRV-Cross/msvc_static_build.diff
diff --git a/subprojects/SPIRV-Tools.wrap b/subprojects/SPIRV-Tools.wrap
new file mode 100644
index 0000000..dc6fe56
--- /dev/null
+++ b/subprojects/SPIRV-Tools.wrap
@@ -0,0 +1,6 @@
+[wrap-git]
+directory = SPIRV-Tools-v2025.1
+url = https://github.com/KhronosGroup/SPIRV-Tools.git
+revision = v2025.1
+depth = 1
+method = cmake
diff --git a/subprojects/ffmpeg-compat.wrap b/subprojects/ffmpeg-compat.wrap
new file mode 100644
index 0000000..dc3402b
--- /dev/null
+++ b/subprojects/ffmpeg-compat.wrap
@@ -0,0 +1,7 @@
+[wrap-file]
+directory = ffmpeg-3.4.14
+source_url = https://ffmpeg.org/releases/ffmpeg-3.4.14.tar.gz
+source_filename = ffmpeg-3.4.14.tar.gz
+source_hash = 61e255e824341e62fbc83365d84eb754fa558f53985d28ad610d13aeee895d5a
+patch_directory = ffmpeg-compat
+diff_files = ffmpeg/msvc_build_conform.diff, ffmpeg-compat/ffmpeg.git-effadce6c756247ea8bae32dc13bb3e6f464f0eb.patch
diff --git a/subprojects/ffmpeg.wrap b/subprojects/ffmpeg.wrap
index fdd551c..21eaac9 100644
--- a/subprojects/ffmpeg.wrap
+++ b/subprojects/ffmpeg.wrap
@@ -40,3 +40,4 @@ source_hash = 9a6e57a446b671012612aaeb9df5126794d5ac8f2015ca220934f99a6a4e0601
#source_hash = 77e0eedd8ebeafde5807011e700fdea82b306b9f76fe469b4abc5dfefd9579bd
patch_directory = ffmpeg
+diff_files = ffmpeg/msvc_build_conform.diff
diff --git a/subprojects/fontconfig.wrap b/subprojects/fontconfig.wrap
index a71b13e..16ea256 100644
--- a/subprojects/fontconfig.wrap
+++ b/subprojects/fontconfig.wrap
@@ -1,7 +1,7 @@
[wrap-git]
-directory = fontconfig-2.15.0
+directory = fontconfig-2.16.2
url = https://gitlab.freedesktop.org/fontconfig/fontconfig.git
-revision = 2.15.0
+revision = 2.16.2
depth = 1
[provide]
diff --git a/subprojects/glslang.wrap b/subprojects/glslang.wrap
index 275f439..7f4eae4 100644
--- a/subprojects/glslang.wrap
+++ b/subprojects/glslang.wrap
@@ -1,6 +1,6 @@
[wrap-git]
-directory = glslang-ef5207f
+directory = glslang-15.3.0
url = https://github.com/KhronosGroup/glslang.git
-revision = ef5207f9f8cce5097568efb15d3297d8b5d13014
+revision = 15.3.0
depth = 1
method = cmake
diff --git a/subprojects/harfbuzz.wrap b/subprojects/harfbuzz.wrap
index 97107b5..59a132d 100644
--- a/subprojects/harfbuzz.wrap
+++ b/subprojects/harfbuzz.wrap
@@ -1,5 +1,5 @@
[wrap-git]
-directory = harfbuzz-10.1.0
+directory = harfbuzz-11.2.1
url = https://github.com/harfbuzz/harfbuzz.git
-revision = 10.1.0
+revision = 11.2.1
depth = 1
diff --git a/subprojects/libalabaster.wrap b/subprojects/libalabaster.wrap
index 6ab8612..2a0e3f4 100644
--- a/subprojects/libalabaster.wrap
+++ b/subprojects/libalabaster.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/libalabaster
-revision = 34a5e136b6c79092eee73857bbad25892fe8047a
+revision = 92d5840e1440fe45a150079fab5a39877589c20f
depth = 1
diff --git a/subprojects/libnaunet.wrap b/subprojects/libnaunet.wrap
index c6bd17a..f068c57 100644
--- a/subprojects/libnaunet.wrap
+++ b/subprojects/libnaunet.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/libnaunet
-revision = ef86574ec5d859727695da65f683f0774a3b4460
+revision = 9fb3646511998310fc8c967c239803f38b2bdc5b
depth = 1
diff --git a/subprojects/miniaudio.wrap b/subprojects/miniaudio.wrap
index bf46443..4d577fa 100644
--- a/subprojects/miniaudio.wrap
+++ b/subprojects/miniaudio.wrap
@@ -1,7 +1,7 @@
[wrap-git]
-directory = miniaudio-29c17fc
+directory = miniaudio-47020e4
url = https://github.com/mackron/miniaudio.git
-revision = 29c17fcb22933c17f4cd375fdf49ecd8f5a4f924
+revision = 47020e4092ddf7cc9dd464fa7c1f7bd462e39a40
depth = 1
patch_directory = miniaudio
-diff_files = miniaudio/miniaudio_pulse_flush.diff
+diff_files = miniaudio/miniaudio_pulse_flush.diff, miniaudio/miniaudio_wasapi_drain_tweak.diff
diff --git a/subprojects/msvc-wine.wrap b/subprojects/msvc-wine.wrap
new file mode 100644
index 0000000..b80ca16
--- /dev/null
+++ b/subprojects/msvc-wine.wrap
@@ -0,0 +1,7 @@
+[wrap-git]
+directory = msvc-wine
+url = https://github.com/mstorsjo/msvc-wine.git
+revision = 44dc13b5e62ecc2373fbe7e4727a525001f403f4
+depth = 1
+patch_directory = msvc-wine
+diff_files = msvc-wine/msvc-wine-shebang-nixos.diff
diff --git a/subprojects/packagefiles/SPIRV-Cross/msvc_static_build.diff b/subprojects/packagefiles/SPIRV-Cross/msvc_static_build.diff
new file mode 100644
index 0000000..5047537
--- /dev/null
+++ b/subprojects/packagefiles/SPIRV-Cross/msvc_static_build.diff
@@ -0,0 +1,17 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index b2ab5ed..49d7d5a 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -31,6 +31,12 @@ endif()
+ # Avoid error on Android NDK 27+'s CMake files
+ cmake_policy(SET CMP0057 NEW)
+
++# https://github.com/KhronosGroup/SPIRV-Cross/issues/2341
++if (POLICY CMP0091)
++ cmake_policy(SET CMP0091 NEW)
++endif()
++set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
++
+ project(SPIRV-Cross LANGUAGES CXX C)
+ enable_testing()
+
diff --git a/subprojects/packagefiles/ffmpeg-compat/ffmpeg.git-effadce6c756247ea8bae32dc13bb3e6f464f0eb.patch b/subprojects/packagefiles/ffmpeg-compat/ffmpeg.git-effadce6c756247ea8bae32dc13bb3e6f464f0eb.patch
new file mode 100644
index 0000000..b4fec43
--- /dev/null
+++ b/subprojects/packagefiles/ffmpeg-compat/ffmpeg.git-effadce6c756247ea8bae32dc13bb3e6f464f0eb.patch
@@ -0,0 +1,73 @@
+From: Rémi Denis-Courmont <remi@remlab.net>
+Date: Sun, 16 Jul 2023 15:18:02 +0000 (+0300)
+Subject: avcodec/x86/mathops: clip constants used with shift instructions within inline assembly
+X-Git-Tag: n6.1~1007
+X-Git-Url: http://git.ffmpeg.org/gitweb/ffmpeg.git/commitdiff_plain/effadce6c756247ea8bae32dc13bb3e6f464f0eb
+
+avcodec/x86/mathops: clip constants used with shift instructions within inline assembly
+
+Fixes assembling with binutil as >= 2.41
+
+Signed-off-by: James Almer <jamrial@gmail.com>
+---
+
+diff --git a/libavcodec/x86/mathops.h b/libavcodec/x86/mathops.h
+index 6298f5ed19..ca7e2dffc1 100644
+--- a/libavcodec/x86/mathops.h
++++ b/libavcodec/x86/mathops.h
+@@ -35,12 +35,20 @@
+ static av_always_inline av_const int MULL(int a, int b, unsigned shift)
+ {
+ int rt, dummy;
++ if (__builtin_constant_p(shift))
+ __asm__ (
+ "imull %3 \n\t"
+ "shrdl %4, %%edx, %%eax \n\t"
+ :"=a"(rt), "=d"(dummy)
+- :"a"(a), "rm"(b), "ci"((uint8_t)shift)
++ :"a"(a), "rm"(b), "i"(shift & 0x1F)
+ );
++ else
++ __asm__ (
++ "imull %3 \n\t"
++ "shrdl %4, %%edx, %%eax \n\t"
++ :"=a"(rt), "=d"(dummy)
++ :"a"(a), "rm"(b), "c"((uint8_t)shift)
++ );
+ return rt;
+ }
+
+@@ -113,19 +121,31 @@ __asm__ volatile(\
+ // avoid +32 for shift optimization (gcc should do that ...)
+ #define NEG_SSR32 NEG_SSR32
+ static inline int32_t NEG_SSR32( int32_t a, int8_t s){
++ if (__builtin_constant_p(s))
+ __asm__ ("sarl %1, %0\n\t"
+ : "+r" (a)
+- : "ic" ((uint8_t)(-s))
++ : "i" (-s & 0x1F)
+ );
++ else
++ __asm__ ("sarl %1, %0\n\t"
++ : "+r" (a)
++ : "c" ((uint8_t)(-s))
++ );
+ return a;
+ }
+
+ #define NEG_USR32 NEG_USR32
+ static inline uint32_t NEG_USR32(uint32_t a, int8_t s){
++ if (__builtin_constant_p(s))
+ __asm__ ("shrl %1, %0\n\t"
+ : "+r" (a)
+- : "ic" ((uint8_t)(-s))
++ : "i" (-s & 0x1F)
+ );
++ else
++ __asm__ ("shrl %1, %0\n\t"
++ : "+r" (a)
++ : "c" ((uint8_t)(-s))
++ );
+ return a;
+ }
+
diff --git a/subprojects/packagefiles/ffmpeg-compat/meson.build b/subprojects/packagefiles/ffmpeg-compat/meson.build
new file mode 100644
index 0000000..7aeeb71
--- /dev/null
+++ b/subprojects/packagefiles/ffmpeg-compat/meson.build
@@ -0,0 +1,197 @@
+project('ffmpeg', 'c', version: '3.4.14', meson_version: '>=0.57.0')
+
+ffmpeg_version_string = meson.project_version()
+
+compiler = meson.get_compiler('c')
+
+cpu = target_machine.cpu_family()
+is_64bit = (cpu == 'x86_64' or cpu == 'aarch64')
+is_debug = get_option('debug')
+is_minsize = get_option('optimization') == 's'
+is_linux = host_machine.system() == 'linux'
+is_windows = host_machine.system() == 'windows'
+is_msvc = compiler.get_id() == 'msvc' or compiler.get_id() == 'clang-cl'
+is_mingw = is_windows and not is_msvc
+is_android = host_machine.system() == 'android'
+
+extra_options = []
+
+if not is_debug
+ extra_options += ['--disable-debug']
+endif
+
+if is_minsize
+ extra_options += ['--enable-small']
+endif
+
+extra_options += ['--arch=' + cpu]
+extra_options += ['--cc=' + compiler.cmd_array()[0]]
+if meson.is_cross_build()
+ if is_msvc
+ extra_options += ['--ld=' + compiler.get_linker_id()]
+ endif
+ extra_options += ['--ar=' + meson.get_external_property('ar', 'ar')]
+ extra_options += ['--nm=' + meson.get_external_property('nm', 'nm')]
+endif
+
+if cpu == 'x86_64' or cpu == 'x86'
+ extra_options += ['--enable-x86asm']
+endif
+
+if is_windows
+ extra_options += ['--extra-cflags=-D_WIN32_WINNT=0x0502'] # Windows Server 2003 with SP1, Windows XP with SP2.
+ if is_64bit
+ extra_options += ['--target-os=win64']
+ else
+ extra_options += ['--target-os=win32']
+ endif
+ if is_msvc
+ extra_options += ['--toolchain=msvc']
+ endif
+ extra_options += ['--enable-w32threads']
+elif is_android
+ extra_options += ['--target-os=android']
+endif
+
+#'--extra-ldflags=-Lbuild/subprojects/libalabaster -l:libalabaster.a',
+#'--malloc-prefix=al_',
+
+decoders = 'flac,mp3,mp3float,aac,opus,vorbis,h264,hevc,av1,vp9'
+decoders += ',pcm_s32be,pcm_s32le,pcm_s24be,pcm_s24le,pcm_s16be,pcm_s16le'
+#decoders += ',pcm_f32be,pcm_f32le,pcm_s32le_planar,pcm_s16be_planar,pcm_s16le_planar'
+decoders += ',dca,eac3'
+decoders += ',pcm_dvd,mpegvideo,mpeg2video'
+#decoders += ',ass,srt'
+
+demuxers = ''
+parsers = ''
+if not get_option('sink-only')
+ demuxers += 'flac,mp3,aac,wav,matroska,mov,avi'
+ demuxers += ',pcm_s32be,pcm_s32le,pcm_s24be,pcm_s24le,pcm_s16be,pcm_s16le'
+ #demuxers += ',pcm_f32be,pcm_f32le,pcm_s32le_planar,pcm_s16be_planar,pcm_s16le_planar'
+ demuxers += ',eac3'
+ demuxers += ',mpegts,mpegtsraw,mpegps,mpegvideo'
+ #demuxers += ',ass,srt'
+ parsers += 'aac,opus,h264,hevc,av1,vp9'
+ parsers += ',dca'
+ parsers += ',mpegaudio,mpegvideo,dvd_nav'
+ extra_options += ['--enable-bzlib'] # matroska
+endif
+
+extra_options += ['--enable-zlib']
+decoders += ',png,apng,mjpeg,jpeg2000,gif,'
+if not get_option('sink-only')
+ demuxers += ',image_png_pipe,image2,mjpeg,image2pipe,image_jpeg_pipe,gif'
+ parsers += ',png,mjpeg,jpeg2000,gif'
+endif
+
+bsfs = ''
+if not get_option('sink-only')
+ bsfs += 'extract_extradata,mp3_header_decompress'
+endif
+
+hwaccels = ''
+if get_option('codec-hwaccel').enabled()
+ if get_option('renderer-api') == 'vulkan'
+ extra_options += ['--enable-vulkan']
+ hwaccels += 'h264_vulkan,hevc_vulkan,av1_vulkan,vp9_vulkan'
+ elif is_windows
+ extra_options += ['--enable-d3d11va']
+ hwaccels += 'h264_d3d11va,hevc_d3d11va,av1_d3d11va,vp9_d3d11va'
+ hwaccels += ',h264_d3d11va2,hevc_d3d11va2,av1_d3d11va2,vp9_d3d11va2'
+ #extra_options += ['--enable-dxva2']
+ #hwaccels += ',h264_dxva2,hevc_dxva2,av1_dxva2,vp9_dxva2'
+ elif is_android
+ extra_options += ['--enable-jni', '--enable-mediacodec']
+ decoders += ',h264_mediacodec,hevc_mediacodec,av1_mediacodec,vp9_mediacodec'
+ elif is_linux
+ extra_options += ['--enable-vaapi']
+ endif
+else
+ extra_options += ['--disable-hwaccels']
+endif
+
+protocols = ''
+if not get_option('sink-only')
+ protocols += 'cache'
+endif
+
+if decoders != ''
+ extra_options += ['--enable-decoder=' + decoders]
+endif
+
+if demuxers != ''
+ extra_options += ['--enable-demuxer=' + demuxers]
+endif
+
+if parsers != ''
+ extra_options += ['--enable-parser=' + parsers]
+endif
+
+if bsfs != ''
+ extra_options += ['--enable-bsf=' + bsfs]
+endif
+
+if protocols != ''
+ extra_options += ['--enable-protocol=' + protocols]
+endif
+
+if hwaccels != ''
+ extra_options += ['--enable-hwaccel=' + hwaccels]
+endif
+
+if is_linux or is_mingw
+ extra_options += ['--enable-libsoxr']
+endif
+
+ext_proj = import('unstable-external_project')
+
+proj = ext_proj.add_project('configure',
+ configure_options: [
+ '--prefix=@PREFIX@',
+ '--libdir=@PREFIX@/@LIBDIR@',
+ '--incdir=@PREFIX@/@INCLUDEDIR@',
+ '--enable-pic',
+ '--enable-static',
+ '--disable-shared',
+ '--disable-logging',
+ '--disable-all',
+ '--disable-autodetect',
+ '--disable-everything',
+ '--disable-programs',
+ '--disable-doc',
+ '--disable-htmlpages',
+ '--disable-manpages',
+ '--disable-podpages',
+ '--disable-txtpages',
+ '--disable-safe-bitstream-reader',
+ '--disable-schannel',
+ '--disable-network',
+ '--disable-securetransport',
+ #'--disable-iconv',
+ '--enable-gpl',
+ '--enable-version3',
+ '--disable-nonfree',
+ '--enable-runtime-cpudetect',
+ '--enable-asm',
+ '--enable-inline-asm',
+ '--enable-avutil',
+ '--enable-avformat',
+ '--enable-avcodec',
+ #'--enable-avdevice',
+ '--enable-swresample',
+ '--enable-swscale',
+ '--disable-indevs',
+ '--disable-outdevs',
+ extra_options
+ ],
+ cross_configure_options: ['--enable-cross-compile'],
+ verbose: true)
+
+avutil = proj.dependency('avutil')
+avformat = proj.dependency('avformat')
+avcodec = proj.dependency('avcodec')
+#avdevice = proj.dependency('avdevice')
+swresample = proj.dependency('swresample')
+swscale = proj.dependency('swscale')
+ffmpeg_include = declare_dependency(include_directories: include_directories('.', 'build/'))
diff --git a/subprojects/packagefiles/ffmpeg/meson.build b/subprojects/packagefiles/ffmpeg/meson.build
index 0ecae9e..8bcce34 100644
--- a/subprojects/packagefiles/ffmpeg/meson.build
+++ b/subprojects/packagefiles/ffmpeg/meson.build
@@ -24,11 +24,14 @@ if is_minsize
extra_options += ['--enable-small']
endif
-extra_options += ['--cc=' + compiler.cmd_array()[0]]
extra_options += ['--arch=' + cpu]
+extra_options += ['--cc=' + compiler.cmd_array()[0]]
if meson.is_cross_build()
- extra_options += ['--nm=' + meson.get_external_property('nm', 'nm')]
+ if is_msvc
+ extra_options += ['--ld=' + compiler.get_linker_id()]
+ endif
extra_options += ['--ar=' + meson.get_external_property('ar', 'ar')]
+ extra_options += ['--nm=' + meson.get_external_property('nm', 'nm')]
endif
if cpu == 'x86_64' or cpu == 'x86'
@@ -52,32 +55,45 @@ endif
#'--extra-ldflags=-Lbuild/subprojects/libalabaster -l:libalabaster.a',
#'--malloc-prefix=al_',
-decoders = 'flac,mp3,mp3float,aac,opus,vorbis,alac,mjpeg,jpeg2000,gif,h264,hevc,av1,vp9,vp8'
-decoders += ',pcm_f32be,pcm_s32be,pcm_s32le,pcm_s32le_planar,pcm_f32le,pcm_s24be,pcm_s24le,pcm_s16be,pcm_s16be_planar,pcm_s16le,pcm_s16le_planar'
-decoders += ',dca'
-#decoders += ',pcm_dvd,mpegvideo,mpeg2video'
+decoders = 'flac,mp3,mp3float,aac,opus,vorbis,h264,hevc,av1,vp9'
+decoders += ',pcm_s32be,pcm_s32le,pcm_s24be,pcm_s24le,pcm_s16be,pcm_s16le'
+#decoders += ',pcm_f32be,pcm_f32le,pcm_s32le_planar,pcm_s16be_planar,pcm_s16le_planar'
+decoders += ',dca,eac3'
+decoders += ',pcm_dvd,mpegvideo,mpeg2video'
#decoders += ',ass,srt'
-demuxers = 'flac,mp3,aac,wav,image2,mjpeg,image2pipe,image_jpeg_pipe,gif,matroska,mov,avi'
-#demuxers += ',mpegts,mpegtsraw,mpegps,mpegvideo'
-#demuxers += ',ass,srt'
-
-parsers = 'aac,opus,mjpeg,jpeg2000,gif,h264,hevc,av1,vp9,vp8'
-parsers += ',dca'
-#parsers += ',mpegaudio,mpegvideo,dvd_nav'
+demuxers = ''
+parsers = ''
+if not get_option('sink-only')
+ demuxers += 'flac,mp3,aac,wav,matroska,mov,avi'
+ demuxers += ',pcm_s32be,pcm_s32le,pcm_s24be,pcm_s24le,pcm_s16be,pcm_s16le'
+ #demuxers += ',pcm_f32be,pcm_f32le,pcm_s32le_planar,pcm_s16be_planar,pcm_s16le_planar'
+ demuxers += ',eac3'
+ demuxers += ',mpegts,mpegtsraw,mpegps,mpegvideo'
+ #demuxers += ',ass,srt'
+ parsers += 'aac,opus,h264,hevc,av1,vp9'
+ parsers += ',dca'
+ parsers += ',mpegaudio,mpegvideo,dvd_nav'
+ extra_options += ['--enable-bzlib'] # matroska
+endif
extra_options += ['--enable-zlib']
-decoders += ',png,apng'
-demuxers += ',image_png_pipe'
-parsers += ',png'
+decoders += ',png,apng,mjpeg,jpeg2000,gif,'
+if not get_option('sink-only')
+ demuxers += ',image_png_pipe,image2,mjpeg,image2pipe,image_jpeg_pipe,gif'
+ parsers += ',png,mjpeg,jpeg2000,gif'
+endif
-bsfs = 'extract_extradata,mp3_header_decompress'
+bsfs = ''
+if not get_option('sink-only')
+ bsfs += 'extract_extradata,mp3_header_decompress'
+endif
hwaccels = ''
if get_option('codec-hwaccel').enabled()
if get_option('renderer-api') == 'vulkan'
extra_options += ['--enable-vulkan']
- hwaccels += 'h264_vulkan,hevc_vulkan,av1_vulkan'
+ hwaccels += 'h264_vulkan,hevc_vulkan,av1_vulkan,vp9_vulkan'
elif is_windows
extra_options += ['--enable-d3d11va']
hwaccels += 'h264_d3d11va,hevc_d3d11va,av1_d3d11va,vp9_d3d11va'
@@ -90,14 +106,39 @@ if get_option('codec-hwaccel').enabled()
elif is_linux
extra_options += ['--enable-vaapi']
endif
+else
+ extra_options += ['--disable-hwaccels']
+endif
+
+protocols = ''
+if not get_option('sink-only')
+ protocols += 'cache'
+endif
+
+if decoders != ''
+ extra_options += ['--enable-decoder=' + decoders]
+endif
+
+if demuxers != ''
+ extra_options += ['--enable-demuxer=' + demuxers]
+endif
+
+if parsers != ''
+ extra_options += ['--enable-parser=' + parsers]
+endif
+
+if bsfs != ''
+ extra_options += ['--enable-bsf=' + bsfs]
+endif
+
+if protocols != ''
+ extra_options += ['--enable-protocol=' + protocols]
endif
if hwaccels != ''
extra_options += ['--enable-hwaccel=' + hwaccels]
endif
-protocols = 'cache'
-
if is_linux or is_mingw
extra_options += ['--enable-libsoxr']
endif
@@ -122,17 +163,11 @@ proj = ext_proj.add_project('configure',
'--disable-manpages',
'--disable-podpages',
'--disable-txtpages',
- '--disable-bzlib',
- '--disable-error-resilience',
- '--disable-iconv',
+ '--disable-safe-bitstream-reader',
'--disable-schannel',
'--disable-network',
'--disable-securetransport',
- '--disable-sdl2',
- '--disable-symver',
- '--disable-faan',
- '--disable-alsa',
- '--disable-xlib',
+ #'--disable-iconv',
'--enable-gpl',
'--enable-version3',
'--disable-nonfree',
@@ -142,16 +177,11 @@ proj = ext_proj.add_project('configure',
'--enable-avutil',
'--enable-avformat',
'--enable-avcodec',
- '--enable-avdevice',
+ #'--enable-avdevice',
'--enable-swresample',
'--enable-swscale',
'--disable-indevs',
'--disable-outdevs',
- '--enable-demuxer=' + demuxers,
- '--enable-decoder=' + decoders,
- '--enable-parser=' + parsers,
- '--enable-bsf=' + bsfs,
- '--enable-protocol=' + protocols,
extra_options
],
cross_configure_options: ['--enable-cross-compile'],
@@ -160,7 +190,7 @@ proj = ext_proj.add_project('configure',
avutil = proj.dependency('avutil')
avformat = proj.dependency('avformat')
avcodec = proj.dependency('avcodec')
-avdevice = proj.dependency('avdevice')
+#avdevice = proj.dependency('avdevice')
swresample = proj.dependency('swresample')
swscale = proj.dependency('swscale')
ffmpeg_include = declare_dependency(include_directories: include_directories('.', 'build/'))
diff --git a/subprojects/packagefiles/ffmpeg/msvc_build_conform.diff b/subprojects/packagefiles/ffmpeg/msvc_build_conform.diff
new file mode 100644
index 0000000..3aff7e9
--- /dev/null
+++ b/subprojects/packagefiles/ffmpeg/msvc_build_conform.diff
@@ -0,0 +1,20 @@
+--- a/configure 2025-03-02 19:22:08.000000000 -0500
++++ b/configure 2025-05-17 18:43:08.854727216 -0400
+@@ -5184,7 +5184,7 @@
+ DEPCCFLAGS=$_flags
+ fi
+
+-if $ar 2>&1 | grep -q Microsoft; then
++if $ar 2>&1 | grep -q Microsoft || [ "$ar" == "llvm-lib" ]; then
+ arflags="-nologo"
+ ar_o='-out:$@'
+ elif $ar 2>&1 | grep -q "\[D\] "; then
+@@ -5878,6 +5878,8 @@
+ enabled x86_32 && check_ldflags -LARGEADDRESSAWARE
+ add_cppflags -DWIN32_LEAN_AND_MEAN
+ shlibdir_default="$bindir_default"
++ LIBPREF=""
++ LIBSUF=".lib"
+ SLIBPREF=""
+ SLIBSUF=".dll"
+ SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)'
diff --git a/subprojects/packagefiles/libplacebo/max_align_msvc.diff b/subprojects/packagefiles/libplacebo/max_align_msvc.diff
new file mode 100644
index 0000000..13df154
--- /dev/null
+++ b/subprojects/packagefiles/libplacebo/max_align_msvc.diff
@@ -0,0 +1,14 @@
+diff --git a/src/pl_alloc.h b/src/pl_alloc.h
+index 78df08a..29718eb 100644
+--- a/src/pl_alloc.h
++++ b/src/pl_alloc.h
+@@ -83,6 +83,9 @@ char *pl_strndup0(void *parent, const char *str, size_t size);
+ // `priv` at the address of `pub` + sizeof(pub), rounded up to the maximum
+ // alignment requirements.
+
++#if defined(_MSC_VER)
++typedef double max_align_t;
++#endif
+ #define PL_ALIGN_MEM(size) PL_ALIGN2(size, alignof(max_align_t))
+
+ #define PL_PRIV(pub) \
diff --git a/subprojects/packagefiles/miniaudio/meson.build b/subprojects/packagefiles/miniaudio/meson.build
index c980787..3c9e4c2 100644
--- a/subprojects/packagefiles/miniaudio/meson.build
+++ b/subprojects/packagefiles/miniaudio/meson.build
@@ -1,2 +1,2 @@
-project('miniaudio', 'c', version: 'git-29c17fc')
+project('miniaudio', 'c', version: 'git-47020e4')
miniaudio = declare_dependency(include_directories: include_directories('.'))
diff --git a/subprojects/packagefiles/miniaudio/miniaudio_wasapi_drain_tweak.diff b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_drain_tweak.diff
new file mode 100644
index 0000000..56da73b
--- /dev/null
+++ b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_drain_tweak.diff
@@ -0,0 +1,13 @@
+diff --git a/miniaudio.h b/miniaudio.h
+index c12ba87..4d9bbb0 100644
+--- a/miniaudio.h
++++ b/miniaudio.h
+@@ -24501,7 +24501,7 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice)
+ */
+ if (ma_atomic_bool32_get(&pDevice->wasapi.isStartedPlayback)) {
+ /* We need to make sure we put a timeout here or else we'll risk getting stuck in a deadlock in some cases. */
+- DWORD waitTime = (pDevice->wasapi.actualBufferSizeInFramesPlayback * 1000) / pDevice->playback.internalSampleRate;
++ DWORD waitTime = ma_calculate_buffer_size_in_milliseconds_from_frames(pDevice->wasapi.actualBufferSizeInFramesPlayback, pDevice->playback.internalSampleRate);
+
+ if (pDevice->playback.shareMode == ma_share_mode_exclusive) {
+ WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, waitTime);
diff --git a/subprojects/packagefiles/msvc-wine/msvc-wine-shebang-nixos.diff b/subprojects/packagefiles/msvc-wine/msvc-wine-shebang-nixos.diff
new file mode 100644
index 0000000..37295a9
--- /dev/null
+++ b/subprojects/packagefiles/msvc-wine/msvc-wine-shebang-nixos.diff
@@ -0,0 +1,405 @@
+https://github.com/mstorsjo/msvc-wine/pull/187
+
+diff --git a/fixinclude b/fixinclude
+index 4a8c733..bd5280c 100755
+--- a/fixinclude
++++ b/fixinclude
+@@ -1,4 +1,4 @@
+-#!/usr/bin/perl
++#!/usr/bin/env perl
+ #
+ # Copyright (c) 2019 Martin Storsjo
+ #
+diff --git a/install.sh b/install.sh
+index ac00d9f..039922f 100755
+--- a/install.sh
++++ b/install.sh
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/usr/bin/env sh
+ #
+ # Copyright (c) 2019 Martin Storsjo
+ #
+diff --git a/lowercase b/lowercase
+index ee10cc7..32902f7 100755
+--- a/lowercase
++++ b/lowercase
+@@ -1,4 +1,4 @@
+-#!/usr/bin/perl
++#!/usr/bin/env perl
+ #
+ # Copyright (c) 2019 Martin Storsjo
+ #
+diff --git a/msvcenv-native.sh b/msvcenv-native.sh
+index e83c687..f3a99f1 100755
+--- a/msvcenv-native.sh
++++ b/msvcenv-native.sh
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/usr/bin/env sh
+ #
+ # Copyright (c) 2019 Martin Storsjo
+ #
+@@ -33,9 +33,9 @@ else
+ if [ ! -f "$ENV" ]; then
+ echo $ENV doesn\'t exist
+ else
+- export INCLUDE="$(bash -c ". $ENV && /bin/echo \"\$INCLUDE\"" | sed s/z://g | sed 's/\\/\//g')"
+- export LIB="$(bash -c ". $ENV && /bin/echo \"\$LIB\"" | sed s/z://g | sed 's/\\/\//g')"
+- MSVCARCH="$(bash -c ". $ENV && /bin/echo \"\$ARCH\"")"
++ export INCLUDE="$(bash -c ". $ENV && /usr/bin/env echo \"\$INCLUDE\"" | sed s/z://g | sed 's/\\/\//g')"
++ export LIB="$(bash -c ". $ENV && /usr/bin/env echo \"\$LIB\"" | sed s/z://g | sed 's/\\/\//g')"
++ MSVCARCH="$(bash -c ". $ENV && /usr/bin/env echo \"\$ARCH\"")"
+ case $MSVCARCH in
+ x86) TARGET_ARCH=i686 ;;
+ x64) TARGET_ARCH=x86_64 ;;
+diff --git a/test/test-asm.sh b/test/test-asm.sh
+index 5774c02..ba9511b 100755
+--- a/test/test-asm.sh
++++ b/test/test-asm.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Martin Storsjo
+ #
+diff --git a/test/test-cl.sh b/test/test-cl.sh
+index 250f092..41fe51b 100755
+--- a/test/test-cl.sh
++++ b/test/test-cl.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Huang Qinjin
+ #
+diff --git a/test/test-clang-cl-cmds.sh b/test/test-clang-cl-cmds.sh
+index 885835b..9409d2b 100755
+--- a/test/test-clang-cl-cmds.sh
++++ b/test/test-clang-cl-cmds.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Martin Storsjo
+ #
+diff --git a/test/test-clang-cl.sh b/test/test-clang-cl.sh
+index ba7f82d..f99b745 100755
+--- a/test/test-clang-cl.sh
++++ b/test/test-clang-cl.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Martin Storsjo
+ #
+diff --git a/test/test-cmake-clang-cl.sh b/test/test-cmake-clang-cl.sh
+index 78485ab..4a6ce3f 100755
+--- a/test/test-cmake-clang-cl.sh
++++ b/test/test-cmake-clang-cl.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Martin Storsjo
+ #
+diff --git a/test/test-cmake.sh b/test/test-cmake.sh
+index 6beface..994d07d 100755
+--- a/test/test-cmake.sh
++++ b/test/test-cmake.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Huang Qinjin
+ #
+diff --git a/test/test-dumpbin.sh b/test/test-dumpbin.sh
+index 68608d4..dd3841d 100755
+--- a/test/test-dumpbin.sh
++++ b/test/test-dumpbin.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Huang Qinjin
+ #
+diff --git a/test/test-mc.sh b/test/test-mc.sh
+index 836a210..2e7d8ab 100755
+--- a/test/test-mc.sh
++++ b/test/test-mc.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2024 Mark Harmstone
+ #
+diff --git a/test/test-meson.sh b/test/test-meson.sh
+index 68ac271..bfd6d6d 100755
+--- a/test/test-meson.sh
++++ b/test/test-meson.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Martin Storsjo
+ #
+diff --git a/test/test-midl.sh b/test/test-midl.sh
+index 45d9f92..8f9319e 100755
+--- a/test/test-midl.sh
++++ b/test/test-midl.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Martin Storsjo
+ #
+diff --git a/test/test-msbuild.sh b/test/test-msbuild.sh
+index 00f03c6..faf284a 100755
+--- a/test/test-msbuild.sh
++++ b/test/test-msbuild.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2024 Sergey Kvachonok
+ #
+diff --git a/test/test-mt.sh b/test/test-mt.sh
+index 5f1881b..eda11ab 100755
+--- a/test/test-mt.sh
++++ b/test/test-mt.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Huang Qinjin
+ #
+diff --git a/test/test-vcpkg.sh b/test/test-vcpkg.sh
+index dc3d3ce..79ebe51 100755
+--- a/test/test-vcpkg.sh
++++ b/test/test-vcpkg.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2024 Huang Qinjin
+ #
+diff --git a/test/test-wdk-msbuild.sh b/test/test-wdk-msbuild.sh
+index b37b3de..90f4189 100755
+--- a/test/test-wdk-msbuild.sh
++++ b/test/test-wdk-msbuild.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2024 Sergey Kvachonok
+ #
+diff --git a/test/test.sh b/test/test.sh
+index 1825216..ad9f9c1 100755
+--- a/test/test.sh
++++ b/test/test.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2023 Huang Qinjin
+ #
+diff --git a/vsdownload.py b/vsdownload.py
+index d9b4dcf..7598eec 100755
+--- a/vsdownload.py
++++ b/vsdownload.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/python3
++#!/usr/bin/env python3
+ #
+ # Copyright (c) 2019 Martin Storsjo
+ #
+diff --git a/wdk-download.sh b/wdk-download.sh
+index e0ea631..7fa8bf0 100755
+--- a/wdk-download.sh
++++ b/wdk-download.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2024 Sergey Kvachonok
+ #
+diff --git a/wrappers/armasm b/wrappers/armasm
+index 3797431..bf8ea5a 100755
+--- a/wrappers/armasm
++++ b/wrappers/armasm
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/armasm64 b/wrappers/armasm64
+index fdfdb38..eb1553f 100755
+--- a/wrappers/armasm64
++++ b/wrappers/armasm64
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/cl b/wrappers/cl
+index 35c1b23..6ca6a56 100755
+--- a/wrappers/cl
++++ b/wrappers/cl
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/cmd b/wrappers/cmd
+index 88a39f0..a7ab236 100755
+--- a/wrappers/cmd
++++ b/wrappers/cmd
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/dumpbin b/wrappers/dumpbin
+index c6f7f9e..18c5591 100755
+--- a/wrappers/dumpbin
++++ b/wrappers/dumpbin
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/findstr b/wrappers/findstr
+index 1146022..136ac0e 100755
+--- a/wrappers/findstr
++++ b/wrappers/findstr
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2024 Huang Qinjin
+ #
+diff --git a/wrappers/lib b/wrappers/lib
+index 143da0c..3967675 100755
+--- a/wrappers/lib
++++ b/wrappers/lib
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/link b/wrappers/link
+index dba1774..53920d4 100755
+--- a/wrappers/link
++++ b/wrappers/link
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/mc b/wrappers/mc
+index c1c5d80..bf71882 100755
+--- a/wrappers/mc
++++ b/wrappers/mc
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/midl b/wrappers/midl
+index dd34988..adddcfa 100755
+--- a/wrappers/midl
++++ b/wrappers/midl
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/ml b/wrappers/ml
+index db671c7..a5d537b 100755
+--- a/wrappers/ml
++++ b/wrappers/ml
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/ml64 b/wrappers/ml64
+index 0708ebe..df65803 100755
+--- a/wrappers/ml64
++++ b/wrappers/ml64
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/msbuild b/wrappers/msbuild
+index 65bbf8f..53fdd8f 100755
+--- a/wrappers/msbuild
++++ b/wrappers/msbuild
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2024 Sergey Kvachonok
+ #
+diff --git a/wrappers/msvcenv.sh b/wrappers/msvcenv.sh
+index 101e9bb..2d2a918 100755
+--- a/wrappers/msvcenv.sh
++++ b/wrappers/msvcenv.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/mt b/wrappers/mt
+index edebd75..ed92f96 100755
+--- a/wrappers/mt
++++ b/wrappers/mt
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/nmake b/wrappers/nmake
+index 88102d1..3eaf0f5 100755
+--- a/wrappers/nmake
++++ b/wrappers/nmake
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/rc b/wrappers/rc
+index f7b8d97..7afb1ad 100755
+--- a/wrappers/rc
++++ b/wrappers/rc
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
+diff --git a/wrappers/wine-msvc.sh b/wrappers/wine-msvc.sh
+index a267283..bb08891 100755
+--- a/wrappers/wine-msvc.sh
++++ b/wrappers/wine-msvc.sh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/usr/bin/env bash
+ #
+ # Copyright (c) 2018 Martin Storsjo
+ #
diff --git a/subprojects/packagefiles/shaderc/no_hlsl_compile.diff b/subprojects/packagefiles/shaderc/no_hlsl_compile.diff
new file mode 100644
index 0000000..ef96592
--- /dev/null
+++ b/subprojects/packagefiles/shaderc/no_hlsl_compile.diff
@@ -0,0 +1,13 @@
+diff --git a/libshaderc_util/src/compiler.cc b/libshaderc_util/src/compiler.cc
+index 9bf9a43..507e669 100644
+--- a/libshaderc_util/src/compiler.cc
++++ b/libshaderc_util/src/compiler.cc
+@@ -286,7 +286,7 @@ std::tuple<bool, std::vector<uint32_t>, size_t> Compiler::Compile(
+ bases[static_cast<int>(UniformKind::StorageBuffer)]);
+ shader.setShiftUavBinding(
+ bases[static_cast<int>(UniformKind::UnorderedAccessView)]);
+- shader.setHlslIoMapping(hlsl_iomap_);
++ //shader.setHlslIoMapping(hlsl_iomap_);
+ shader.setResourceSetBinding(
+ hlsl_explicit_bindings_[static_cast<int>(used_shader_stage)]);
+ shader.setEnvClient(target_client_info.client,
diff --git a/subprojects/shaderc.wrap b/subprojects/shaderc.wrap
index 575308b..5be87c2 100644
--- a/subprojects/shaderc.wrap
+++ b/subprojects/shaderc.wrap
@@ -1,8 +1,8 @@
[wrap-git]
-directory = shaderc-0ab6bf5
+directory = shaderc-v2025.2
url = https://github.com/google/shaderc.git
-revision = 0ab6bf5cefea23cf985ce6296a293170132984ae
+revision = v2025.2
depth = 1
method = cmake
patch_directory = shaderc
-diff_files = shaderc/third_party_fix_build.diff
+diff_files = shaderc/third_party_fix_build.diff, shaderc/no_hlsl_compile.diff
diff --git a/subprojects/stela.wrap b/subprojects/stela.wrap
index c8a8139..9282a6d 100644
--- a/subprojects/stela.wrap
+++ b/subprojects/stela.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/stela
-revision = 7d4434ea4ceb1fa5c75f372a73ac6dfe5cb05b1d
+revision = 1f1b60ed59cd3b3d594cf16c51cb835cb912fb12
depth = 1