From 89def9d075d7626cdf9f6b73e49b7014f97ab842 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 01:24:49 +0200 Subject: [PATCH 01/78] build: start working on proper static mpv build --- mpv/build.sh | 41 +++ mpv/subprojects/ffmpeg.wrap | 9 + mpv/subprojects/libass.wrap | 4 + mpv/subprojects/libdbus.wrap.disabled | 8 + mpv/subprojects/libjpeg-turbo.wrap | 11 + mpv/subprojects/libpipewire-0.3.wrap.disabled | 8 + mpv/subprojects/libplacebo.wrap | 5 + .../packagefiles/ffmpeg/collect_versions.sh | 9 + .../packagefiles/ffmpeg/meson.build | 26 ++ .../libjpeg-turbo-3.1.2/LICENSE.build | 19 + .../libjpeg-turbo-3.1.2/meson.build | 150 ++++++++ .../libjpeg-turbo-3.1.2/meson_options.txt | 20 ++ .../libjpeg-turbo-3.1.2/simd/arm/meson.build | 6 + .../libjpeg-turbo-3.1.2/simd/meson.build | 338 ++++++++++++++++++ .../libjpeg-turbo-3.1.2/src/meson.build | 265 ++++++++++++++ 15 files changed, 919 insertions(+) create mode 100644 mpv/build.sh create mode 100644 mpv/subprojects/ffmpeg.wrap create mode 100644 mpv/subprojects/libass.wrap create mode 100644 mpv/subprojects/libdbus.wrap.disabled create mode 100644 mpv/subprojects/libjpeg-turbo.wrap create mode 100644 mpv/subprojects/libpipewire-0.3.wrap.disabled create mode 100644 mpv/subprojects/libplacebo.wrap create mode 100644 mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh create mode 100644 mpv/subprojects/packagefiles/ffmpeg/meson.build create mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build create mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build create mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt create mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build create mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build create mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build diff --git a/mpv/build.sh b/mpv/build.sh new file mode 100644 index 0000000..b182e55 --- /dev/null +++ b/mpv/build.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -eo pipefail + +sudo apt-get update +sudo apt-get upgrade -y +sudo apt-get install -y build-essential git pkg-config cmake nasm clang curl python3-pip python3-wheel ninja-build +sudo apt-get install -y libfontconfig-dev libva-dev libdrm-dev libuchardet-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev + +sudo pip3 install meson + +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sudo -i sh -s -- -y +sudo -i rustup default stable +sudo -i cargo install cargo-c + +sudo rm -rf dovi_tool && git clone -b 2.3.1 https://github.com/quietvoid/dovi_tool.git +pushd dovi_tool/dolby_vision +sudo -i bash -c "cd $(pwd) && cargo cinstall --release --prefix /usr" +popd + +rm -rf mpv && git clone https://github.com/mpv-player/mpv.git --depth=1 mpv +pushd mpv + +mkdir -p subprojects +meson wrap update-db +meson wrap install expat +meson wrap install harfbuzz +meson wrap install libpng +meson wrap install zlib +meson wrap install libjpeg-turbo +meson wrap install openal-soft + +git clone -b VER-2-14-1 https://gitlab.freedesktop.org/freetype/freetype.git --depth=1 --recursive subprojects/freetype2 +git clone -b v1.0.16 https://github.com/fribidi/fribidi.git --depth=1 --recursive subprojects/fribidi +git clone -b 0.3.0 https://gitlab.freedesktop.org/emersion/libdisplay-info.git --depth=1 subprojects/libdisplay-info +cp -r ../subprojects/* subprojects/ + +export CFLAGS="-fPIC" +export CXXFLAGS="-fPIC" +meson setup build -Dlibmpv=true -Ddrm=enabled -Ddefault_library=static -Dopenal=enabled -Dprefer_static=true --force-fallback-for=ffmpeg,libjpeg,openal +meson compile -C build diff --git a/mpv/subprojects/ffmpeg.wrap b/mpv/subprojects/ffmpeg.wrap new file mode 100644 index 0000000..5c29551 --- /dev/null +++ b/mpv/subprojects/ffmpeg.wrap @@ -0,0 +1,9 @@ +[wrap-file] +directory = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0 +source_url = https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz +source_filename = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz +source_hash = 6e32fab45ad71841de03e796124b7c1c06a8b42a53860525a44aa007b28757a8 +patch_directory = ffmpeg + +[provide] +dependency_names = libavcodec, libavfilter, libavformat, libavutil, libswresample, libswscale diff --git a/mpv/subprojects/libass.wrap b/mpv/subprojects/libass.wrap new file mode 100644 index 0000000..580d48a --- /dev/null +++ b/mpv/subprojects/libass.wrap @@ -0,0 +1,4 @@ +[wrap-git] +revision = master +url = https://github.com/libass/libass +depth = 1 diff --git a/mpv/subprojects/libdbus.wrap.disabled b/mpv/subprojects/libdbus.wrap.disabled new file mode 100644 index 0000000..6e6b101 --- /dev/null +++ b/mpv/subprojects/libdbus.wrap.disabled @@ -0,0 +1,8 @@ +[wrap-git] +url = https://gitlab.freedesktop.org/dbus/dbus.git +revision = dbus-1.16.2 +depth = 1 +clone-recursive = true + +[provide] +dependency_names = dbus-1 diff --git a/mpv/subprojects/libjpeg-turbo.wrap b/mpv/subprojects/libjpeg-turbo.wrap new file mode 100644 index 0000000..c0ca6d0 --- /dev/null +++ b/mpv/subprojects/libjpeg-turbo.wrap @@ -0,0 +1,11 @@ +[wrap-file] +directory = libjpeg-turbo-3.1.2 +source_url = https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.1.2/libjpeg-turbo-3.1.2.tar.gz +source_filename = libjpeg-turbo-3.1.2.tar.gz +source_hash = 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf +patch_directory = libjpeg-turbo-3.1.2 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libjpeg-turbo_3.1.2-1/libjpeg-turbo-3.1.2.tar.gz +wrapdb_version = 3.1.2-1 + +[provide] +dependency_names = libjpeg, libturbojpeg diff --git a/mpv/subprojects/libpipewire-0.3.wrap.disabled b/mpv/subprojects/libpipewire-0.3.wrap.disabled new file mode 100644 index 0000000..4691d10 --- /dev/null +++ b/mpv/subprojects/libpipewire-0.3.wrap.disabled @@ -0,0 +1,8 @@ +[wrap-git] +url = https://gitlab.freedesktop.org/pipewire/pipewire.git +revision = 1.4.9 +depth = 1 +clone-recursive = true + +[provide] +dependency_names = libpipewire-0.3 diff --git a/mpv/subprojects/libplacebo.wrap b/mpv/subprojects/libplacebo.wrap new file mode 100644 index 0000000..dc08964 --- /dev/null +++ b/mpv/subprojects/libplacebo.wrap @@ -0,0 +1,5 @@ +[wrap-git] +url = https://github.com/haasn/libplacebo +revision = master +depth = 1 +clone-recursive = true diff --git a/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh b/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh new file mode 100644 index 0000000..c620567 --- /dev/null +++ b/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +for shared_object in "${MESON_SOURCE_ROOT}/${MESON_SUBDIR}"/lib/*.so.*.*.*; do + filename=$(basename "$shared_object") + lib_name=$(basename "${filename//\.so.*/}") + lib_name="${lib_name//lib/}" + lib_version=${filename//*.so\./} + echo "${lib_name}:${lib_version}" +done diff --git a/mpv/subprojects/packagefiles/ffmpeg/meson.build b/mpv/subprojects/packagefiles/ffmpeg/meson.build new file mode 100644 index 0000000..791782c --- /dev/null +++ b/mpv/subprojects/packagefiles/ffmpeg/meson.build @@ -0,0 +1,26 @@ +project('ffmpeg', 'c') + +cc = meson.get_compiler('c') + +versions_command = run_command('bash', 'collect_versions.sh', capture : true, check : true) +versions = versions_command.stdout().strip().split('\n') + +library_names = ['avcodec', 'avfilter', 'avformat', 'avutil', 'swresample', 'swscale'] + +foreach lib_name : library_names + foreach version : versions + version_name = version.split(':')[0].strip() + version_value = version.split(':')[1].strip() + + if version_name == lib_name + message(version) + dep = declare_dependency( + version : version_value, + dependencies : cc.find_library(lib_name, dirs : meson.current_source_dir() + '/lib'), + include_directories : include_directories('include'), + ) + meson.override_dependency('lib' + lib_name, dep) + break + endif + endforeach +endforeach diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build new file mode 100644 index 0000000..b59833d --- /dev/null +++ b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build @@ -0,0 +1,19 @@ +Copyright (c) 2021 The Meson development team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build new file mode 100644 index 0000000..e84a024 --- /dev/null +++ b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build @@ -0,0 +1,150 @@ +project( + 'libjpeg-turbo', + 'c', + version : '3.1.2', + license : 'BSD-3-Clause AND IJG', + meson_version : '>= 0.64.0', +) + +add_project_arguments('-D_POSIX_C_SOURCE=200809L', language : 'c') +add_project_arguments('-D_DEFAULT_SOURCE', language : 'c') + +pkg = import('pkgconfig') +python = import('python').find_installation() + +cc = meson.get_compiler('c') +host_system = host_machine.system() +host_cpu = host_machine.cpu_family() + +cdata = configuration_data() +cdata.set('CMAKE_PROJECT_NAME', meson.project_name()) +cdata.set('VERSION', meson.project_version()) +cdata.set('COPYRIGHT_YEAR', '1991-2025') + +jpeg_lib_version = 80 +so_major = jpeg_lib_version / 10 +so_age = 3 +so_minor = 2 +so_version = '@0@.@1@.@2@'.format(so_major, so_age, so_minor) +vs_defs = files('win/jpeg8.def')[0] + +version_arr = meson.project_version().split('.') +version_major = version_arr[0] +version_minor = version_arr[1] +version_revision = version_arr[2] + +# Add padding to build an integer: 2.1.0 -> 2001000 +if version_major.to_int() < 10 + version_major += '00' +elif version_major.to_int() < 100 + version_major += '0' +endif + +if version_minor.to_int() < 10 + version_minor += '00' +elif version_minor.to_int() < 100 + version_minor += '0' +endif + +cdata.set('JPEG_LIB_VERSION', jpeg_lib_version) +cdata.set( + 'LIBJPEG_TURBO_VERSION_NUMBER', + version_major + version_minor + version_revision, +) + +cdata.set('C_ARITH_CODING_SUPPORTED', true) +cdata.set('D_ARITH_CODING_SUPPORTED', true) + +check_headers = ['local.h', 'stddef.h', 'stdlib.h', 'sys/types.h'] +if cc.get_id() == 'msvc' + check_headers += 'intrin.h' +endif + +foreach header : check_headers + have_header = cc.has_header(header) + cdata.set('HAVE_' + header.underscorify().to_upper(), have_header) + cdata.set('NEED_' + header.underscorify().to_upper(), have_header) +endforeach + +has_memset = cc.has_header_symbol('string.h', 'memset') +has_memcpy = cc.has_header_symbol('string.h', 'memcpy') +cdata.set('NEED_BSD_STRINGS', not has_memset or not has_memcpy) + +size_t = cc.sizeof('size_t') +unsigned_long = cc.sizeof('unsigned long') +cdata.set('SIZE_T', size_t) +cdata.set('HAVE_UNSIGNED_CHAR', cc.sizeof('unsigned char') != -1) +cdata.set('HAVE_UNSIGNED_SHORT', cc.sizeof('unsigned short') != -1) +if size_t == unsigned_long + cdata.set('HAVE_BUILTIN_CTZL', cc.has_function('__builtin_ctzl')) +endif + +code = 'int main(void) { typedef struct undefined_structure *undef_struct_ptr; undef_struct_ptr ptr = 0; return ptr != 0; }' +cdata.set('INCOMPLETE_TYPES_BROKEN', not cc.links(code)) + +if meson.can_run_host_binaries() + code = ''' + #include + #include + static int is_shifting_signed (long arg) { + long res = arg >> 4; + if (res == -0x7F7E80CL) + return 1; /* right shift is signed */ + /* see if unsigned-shift hack will fix it. */ + /* we can't just test exact value since it depends on width of long... */ + res |= 0xFFFFFFFFL << (32-4); + if (res == -0x7F7E80CL) + return 0; /* right shift is unsigned */ + printf(\"Right shift isn't acting as I expect it to.\\\\n\"); + printf(\"I fear the JPEG software will not work at all.\\\\n\\\\n\"); + return 0; /* try it with unsigned anyway */ + } + int main (void) { + exit(is_shifting_signed(-0x7F7E80B1L)); + } + ''' + cdata.set('RIGHT_SHIFT_IS_UNSIGNED', cc.run(code).returncode() == 0) +else + cdata.set('RIGHT_SHIFT_IS_UNSIGNED', false) +endif + +p = run_command( + python, + '-c', + 'import datetime; print(datetime.datetime.now().strftime("%Y%m%d"))', + check : true, +) +cdata.set('BUILD', p.stdout().strip()) + +if cc.get_id() == 'msvc' + cdata.set('THREAD_LOCAL', '__declspec(thread)') +else + cdata.set('THREAD_LOCAL', '__thread') +endif + +cdata.set('HIDDEN', cc.has_function_attribute('visibility:hidden') ? '__attribute__((visibility("hidden")))' + : '') + +if get_option('force_inline') + if cc.get_id() == 'msvc' + cdata.set('INLINE', '__forceinline') + else + cdata.set('INLINE', 'inline __attribute__((always_inline))') + endif +else + cdata.set('INLINE', 'inline') +endif + +if host_system == 'windows' + add_project_arguments( + '-DDLLDEFINE', + language : 'c', + ) +endif + +incdir = include_directories('src') + +subdir('simd') +cdata.set('WITH_SIMD', have_simd) + +subdir('src') diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt new file mode 100644 index 0000000..41ed4bb --- /dev/null +++ b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt @@ -0,0 +1,20 @@ +option( + 'force_inline', + type : 'boolean', +) +option( + 'turbojpeg', + type : 'feature', +) +option( + 'simd', + type : 'feature', +) +option( + 'tests', + type : 'feature', +) +option( + 'neon-intrinsics', + type : 'feature', +) diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build new file mode 100644 index 0000000..124b74a --- /dev/null +++ b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build @@ -0,0 +1,6 @@ +neon_compat_h = configure_file( + input : 'neon-compat.h.in', + output : 'neon-compat.h', + format : 'cmake', + configuration : cdata_neon, +) diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build new file mode 100644 index 0000000..7c2306d --- /dev/null +++ b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build @@ -0,0 +1,338 @@ +simd_src_x86_64 = [ + 'x86_64/jccolor-avx2.asm', + 'x86_64/jccolor-sse2.asm', + 'x86_64/jcgray-avx2.asm', + 'x86_64/jcgray-sse2.asm', + 'x86_64/jchuff-sse2.asm', + 'x86_64/jcphuff-sse2.asm', + 'x86_64/jcsample-avx2.asm', + 'x86_64/jcsample-sse2.asm', + 'x86_64/jdcolor-avx2.asm', + 'x86_64/jdcolor-sse2.asm', + 'x86_64/jdmerge-avx2.asm', + 'x86_64/jdmerge-sse2.asm', + 'x86_64/jdsample-avx2.asm', + 'x86_64/jdsample-sse2.asm', + 'x86_64/jfdctflt-sse.asm', + 'x86_64/jfdctfst-sse2.asm', + 'x86_64/jfdctint-avx2.asm', + 'x86_64/jfdctint-sse2.asm', + 'x86_64/jidctflt-sse2.asm', + 'x86_64/jidctfst-sse2.asm', + 'x86_64/jidctint-avx2.asm', + 'x86_64/jidctint-sse2.asm', + 'x86_64/jidctred-sse2.asm', + 'x86_64/jquantf-sse2.asm', + 'x86_64/jquanti-avx2.asm', + 'x86_64/jquanti-sse2.asm', + 'x86_64/jsimdcpu.asm', +] + +simd_src_i386 = [ + 'i386/jccolor-avx2.asm', + 'i386/jccolor-mmx.asm', + 'i386/jccolor-sse2.asm', + 'i386/jcgray-avx2.asm', + 'i386/jcgray-mmx.asm', + 'i386/jcgray-sse2.asm', + 'i386/jchuff-sse2.asm', + 'i386/jcphuff-sse2.asm', + 'i386/jcsample-avx2.asm', + 'i386/jcsample-mmx.asm', + 'i386/jcsample-sse2.asm', + 'i386/jdcolor-avx2.asm', + 'i386/jdcolor-mmx.asm', + 'i386/jdcolor-sse2.asm', + 'i386/jdmerge-avx2.asm', + 'i386/jdmerge-mmx.asm', + 'i386/jdmerge-sse2.asm', + 'i386/jdsample-avx2.asm', + 'i386/jdsample-mmx.asm', + 'i386/jdsample-sse2.asm', + 'i386/jfdctflt-3dn.asm', + 'i386/jfdctflt-sse.asm', + 'i386/jfdctfst-mmx.asm', + 'i386/jfdctfst-sse2.asm', + 'i386/jfdctint-avx2.asm', + 'i386/jfdctint-mmx.asm', + 'i386/jfdctint-sse2.asm', + 'i386/jidctflt-3dn.asm', + 'i386/jidctflt-sse2.asm', + 'i386/jidctflt-sse.asm', + 'i386/jidctfst-mmx.asm', + 'i386/jidctfst-sse2.asm', + 'i386/jidctint-avx2.asm', + 'i386/jidctint-mmx.asm', + 'i386/jidctint-sse2.asm', + 'i386/jidctred-mmx.asm', + 'i386/jidctred-sse2.asm', + 'i386/jquant-3dn.asm', + 'i386/jquantf-sse2.asm', + 'i386/jquanti-avx2.asm', + 'i386/jquanti-sse2.asm', + 'i386/jquant-mmx.asm', + 'i386/jquant-sse.asm', + 'i386/jsimdcpu.asm', +] + +simd_src_arm = files( + 'arm/jcgray-neon.c', + 'arm/jcphuff-neon.c', + 'arm/jcsample-neon.c', + 'arm/jdmerge-neon.c', + 'arm/jdsample-neon.c', + 'arm/jfdctfst-neon.c', + 'arm/jidctred-neon.c', + 'arm/jquanti-neon.c', +) + +simd_opt = get_option('simd') +have_simd = false +simd = [] + +if host_cpu in ['x86', 'x86_64'] + have_simd = add_languages( + 'nasm', + required : simd_opt, + native : false, + ) + if have_simd + add_project_arguments( + '-DPIC', + language : 'nasm', + ) + x64 = host_cpu == 'x86_64' + # simulate upstream's "is ELF" check by excluding non-ELF OSes + if x64 and host_machine.system() not in ['cygwin', 'darwin', 'windows'] + if cc.compiles( + ''' + #if (__CET__ & 3) == 0 + #error \"CET not enabled\" + #endif + int main(void) { return 0; } + ''', + ) + add_project_arguments( + '-D__CET__', + language : 'nasm', + ) + endif + endif + dir = x64 ? 'x86_64' : 'i386' + simd_src = x64 ? simd_src_x86_64 : simd_src_i386 + simd = static_library( + 'simd', + dir / 'jsimd.c', + simd_src, + include_directories : [incdir, 'nasm', dir], + pic : get_option('default_library') != 'static', + ) + endif +elif host_cpu in ['arm', 'aarch64'] + aarch = host_cpu == 'aarch64' ? 'aarch64' : 'aarch32' + dir = 'arm' / aarch + cdata_neon = configuration_data() + + needs_softfp_for_intrinsics = host_cpu == 'arm' and cc.compiles( + ''' + #if defined(__ARM_NEON__) || (!defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)) + #error \"Neon run-time auto-detection will not be used\" + #endif + #if __ARM_PCS_VFP == 1 + #error \"float ABI = hard\" + #endif + #if __SOFTFP__ != 1 + #error \"float ABI = softfp\" + #endif + int main(void) { return 0; }" + ''', + name : 'does not need softfp for Neon intrinsics', + ) + neon_flags = [] + if host_cpu == 'arm' + neon_flags += ['-mfpu=neon'] + endif + if needs_softfp_for_intrinsics + neon_flags += ['-mfloatabi=softfp'] + endif + if host_cpu == 'arm' + have_simd = cc.compiles( + '''#include + int main(int argc, char **argv) { + uint16x8_t input = vdupq_n_u16((uint16_t)argc); + uint8x8_t output = vmovn_u16(input); + return (int)output[0]; + }''', + args : neon_flags, + name : 'supports Neon', + ) + if not have_simd + if simd_opt.enabled() + error('SIMD extensions not available for this architecture') + else + warning('SIMD extensions not available for this architecture') + endif + endif + else + have_simd = true + endif + + if have_simd + cdata_neon.set( + 'HAVE_VLD1_S16_X3', + cc.compiles( + '''#include + int main(int argc, char **argv) { + int16_t input[12]; + int16x4x3_t output; + int i; + for (i = 0; i < 12; i++) input[i] = (int16_t)argc; + output = vld1_s16_x3(input); + vst3_s16(input, output); + return (int)input[0]; + }''', + args : neon_flags, + name : 'supports vld1_s16_x3 intrinsic', + ), + ) + cdata_neon.set( + 'HAVE_VLD1_U16_X2', + cc.compiles( + ''' + #include + int main(int argc, char **argv) { + uint16_t input[8]; + uint16x4x2_t output; + int i; + for (i = 0; i < 8; i++) input[i] = (uint16_t)argc; + output = vld1_u16_x2(input); + vst2_u16(input, output); + return (int)input[0]; + }''', + args : neon_flags, + name : 'supports vld1_u16_x2 intrinsic', + ), + ) + cdata_neon.set( + 'HAVE_VLD1Q_U8_X4', + cc.compiles( + ''' + #include + int main(int argc, char **argv) { + uint8_t input[64]; + uint8x16x4_t output; + int i; + for (i = 0; i < 64; i++) input[i] = (uint8_t)argc; + output = vld1q_u8_x4(input); + vst4q_u8(input, output); + return (int)input[0]; + }''', + args : neon_flags, + name : 'supports vld1q_u8_x4 intrinsic', + ), + ) + + subdir('arm') + simd_src_arm += [neon_compat_h] + + # GCC 11 and earlier and some older versions of Clang do not have a full or + # optimal set of Neon intrinsics, so for performance reasons, when using those + # compilers, we default to using the older GAS implementation of the Neon SIMD + # extensions for certain algorithms. The presence or absence of the three + # intrinsics we tested above is a reasonable proxy for this, except with GCC 10 + # and 11. + + default_neon_intrinsics = cdata_neon.get('HAVE_VLD1_S16_X3') and cdata_neon.get( + 'HAVE_VLD1_U16_X2', + ) and cdata_neon.get( + 'HAVE_VLD1Q_U8_X4', + ) and ( + cc.get_id() != 'gcc' or cc.version().version_compare('>= 12.0.0') + ) + + neon_intrinsics = get_option('neon-intrinsics').disable_auto_if( + not default_neon_intrinsics, + ).allowed() + + # It is possible to run compile checks on generated files, however, + # Meson versions earlier than 1.2.0 do not set the lookup path + # correctly, causing Python to fail opening it. + # https://github.com/mesonbuild/meson/issues/11983 + if meson.version().version_compare('>= 1.2.0') and not neon_intrinsics + if (host_cpu == 'armv7') + gastest = ''' + .text + .fpu neon + .arch armv7a + .object_arch armv4 + .arm + pld [r0] + vmovn.u16 d0, q0 + ''' + else + gastest = ''' + .text + MYVAR .req x0 + movi v0.16b, #100 + mov MYVAR, #100 + .unreq MYVAR + ''' + endif + # cc.compiles() can't pass inline assembly to the C compiler + # https://github.com/mesonbuild/meson/issues/12395 + f = configure_file( + command : [ + python, + '-c', + 'import sys; print(sys.argv[1])', + '@0@'.format(gastest), + ], + output : 'gastest.S', + capture : true, + ) + if not cc.compiles( + f, + args : neon_flags, + name : 'can use the partial Neon SIMD intrinsics implementation', + ) + neon_intrinsics = true + endif + endif + + summary('Neon SIMD intrinsics', neon_intrinsics ? 'full' : 'partial') + + if neon_intrinsics + add_project_arguments( + '-DNEON_INTRINSICS', + language : 'c', + ) + simd_src_arm += files('arm/jccolor-neon.c', 'arm/jidctint-neon.c') + endif + + if neon_intrinsics or host_cpu == 'aarch64' + simd_src_arm += files('arm/jidctfst-neon.c') + endif + + if neon_intrinsics or host_cpu == 'arm' + simd_src_arm += files( + dir / 'jchuff-neon.c', + 'arm/jdcolor-neon.c', + 'arm/jfdctint-neon.c', + ) + endif + + if not neon_intrinsics + simd_src_arm += files(dir / 'jsimd_neon.S') + endif + + simd = static_library( + 'simd', + simd_src_arm + files(dir / 'jsimd.c'), + pic : get_option('default_library') != 'static', + include_directories : [incdir, 'arm', dir], + c_args : neon_flags, + ) + endif +elif simd_opt.enabled() + error('SIMD enabled, but CPU family not supported') +endif diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build new file mode 100644 index 0000000..b03a0f8 --- /dev/null +++ b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build @@ -0,0 +1,265 @@ +jconfig_h = configure_file( + input : 'jconfig.h.in', + output : 'jconfig.h', + format : 'cmake@', + configuration : cdata, +) + +configure_file( + input : 'jconfigint.h.in', + output : 'jconfigint.h', + format : 'cmake@', + configuration : cdata, +) + +configure_file( + input : 'jversion.h.in', + output : 'jversion.h', + format : 'cmake@', + configuration : cdata, +) + +install_headers('jmorecfg.h', 'jerror.h', 'jpeglib.h', jconfig_h) + +sources = files( + 'jcapimin.c', + 'jchuff.c', + 'jcicc.c', + 'jcinit.c', + 'jclhuff.c', + 'jcmarker.c', + 'jcmaster.c', + 'jcomapi.c', + 'jcparam.c', + 'jcphuff.c', + 'jctrans.c', + 'jdapimin.c', + 'jdatadst.c', + 'jdatasrc.c', + 'jdhuff.c', + 'jdicc.c', + 'jdinput.c', + 'jdlhuff.c', + 'jdmarker.c', + 'jdmaster.c', + 'jdphuff.c', + 'jdtrans.c', + 'jerror.c', + 'jfdctflt.c', + 'jmemmgr.c', + 'jmemnobs.c', + 'jpeg_nbits.c', + 'wrapper/jcapistd-12.c', + 'wrapper/jcapistd-16.c', + 'wrapper/jcapistd-8.c', + 'wrapper/jccoefct-12.c', + 'wrapper/jccoefct-8.c', + 'wrapper/jccolor-12.c', + 'wrapper/jccolor-16.c', + 'wrapper/jccolor-8.c', + 'wrapper/jcdctmgr-12.c', + 'wrapper/jcdctmgr-8.c', + 'wrapper/jcdiffct-12.c', + 'wrapper/jcdiffct-16.c', + 'wrapper/jcdiffct-8.c', + 'wrapper/jclossls-12.c', + 'wrapper/jclossls-16.c', + 'wrapper/jclossls-8.c', + 'wrapper/jcmainct-12.c', + 'wrapper/jcmainct-16.c', + 'wrapper/jcmainct-8.c', + 'wrapper/jcprepct-12.c', + 'wrapper/jcprepct-16.c', + 'wrapper/jcprepct-8.c', + 'wrapper/jcsample-12.c', + 'wrapper/jcsample-16.c', + 'wrapper/jcsample-8.c', + 'wrapper/jdapistd-12.c', + 'wrapper/jdapistd-16.c', + 'wrapper/jdapistd-8.c', + 'wrapper/jdcoefct-12.c', + 'wrapper/jdcoefct-8.c', + 'wrapper/jdcolor-12.c', + 'wrapper/jdcolor-16.c', + 'wrapper/jdcolor-8.c', + 'wrapper/jddctmgr-12.c', + 'wrapper/jddctmgr-8.c', + 'wrapper/jddiffct-12.c', + 'wrapper/jddiffct-16.c', + 'wrapper/jddiffct-8.c', + 'wrapper/jdlossls-12.c', + 'wrapper/jdlossls-16.c', + 'wrapper/jdlossls-8.c', + 'wrapper/jdmainct-12.c', + 'wrapper/jdmainct-16.c', + 'wrapper/jdmainct-8.c', + 'wrapper/jdmerge-12.c', + 'wrapper/jdmerge-8.c', + 'wrapper/jdpostct-12.c', + 'wrapper/jdpostct-16.c', + 'wrapper/jdpostct-8.c', + 'wrapper/jdsample-12.c', + 'wrapper/jdsample-16.c', + 'wrapper/jdsample-8.c', + 'wrapper/jfdctfst-12.c', + 'wrapper/jfdctfst-8.c', + 'wrapper/jfdctint-12.c', + 'wrapper/jfdctint-8.c', + 'wrapper/jidctflt-12.c', + 'wrapper/jidctflt-8.c', + 'wrapper/jidctfst-12.c', + 'wrapper/jidctfst-8.c', + 'wrapper/jidctint-12.c', + 'wrapper/jidctint-8.c', + 'wrapper/jidctred-12.c', + 'wrapper/jidctred-8.c', + 'wrapper/jquant1-12.c', + 'wrapper/jquant1-8.c', + 'wrapper/jquant2-12.c', + 'wrapper/jquant2-8.c', + 'wrapper/jutils-12.c', + 'wrapper/jutils-16.c', + 'wrapper/jutils-8.c', +) + +sources += files( + # TODO: `with_arith_dec` / `with_arith_enc` only. + 'jaricom.c', + # TODO: `with_arith_enc` only + 'jcarith.c', + # TODO: `with_arith_dec` only + 'jdarith.c', +) + +jpeg = library( + 'jpeg', + sources, + link_whole : simd, + soversion : so_version, + vs_module_defs : vs_defs, + install : true, +) + +pkg.generate( + jpeg, + description : 'A SIMD-accelerated JPEG codec that provides the libjpeg API', + name : 'libjpeg', +) + +jpeg_dep = declare_dependency( + include_directories : incdir, + link_with : jpeg, +) +meson.override_dependency('libjpeg', jpeg_dep) + +if get_option('turbojpeg').allowed() + install_headers('turbojpeg.h') + + turbojpeg = library( + 'turbojpeg', + sources, + files( + 'jdatadst-tj.c', + 'jdatasrc-tj.c', + 'rdbmp.c', + 'transupp.c', + 'turbojpeg.c', + 'wrapper/rdppm-12.c', + 'wrapper/rdppm-16.c', + 'wrapper/rdppm-8.c', + 'wrapper/wrppm-12.c', + 'wrapper/wrppm-16.c', + 'wrapper/wrppm-8.c', + 'wrbmp.c', + ), + c_args : ['-DBMP_SUPPORTED', '-DPPM_SUPPORTED'], + install : true, + link_whole : simd, + soversion : '0.4.0', + ) + + pkg.generate( + turbojpeg, + description : 'A SIMD-accelerated JPEG codec that provides the TurboJPEG API', + name : 'libturbojpeg', + ) + + turbojpeg_dep = declare_dependency( + include_directories : incdir, + link_with : turbojpeg, + ) + meson.override_dependency('libturbojpeg', turbojpeg_dep) +endif + +if get_option('tests').require( + get_option('turbojpeg').allowed(), + error_message : 'turbojpeg feature needed', +).allowed() + tjunittest = executable( + 'tjunittest', + ['tjunittest.c', 'tjutil.c', 'md5/md5.c', 'md5/md5hl.c'], + dependencies : turbojpeg_dep, + ) + + foreach _test, _args : { + 'tjunittest' : '', + 'tjunittest-alloc' : '-alloc', + 'tjunittest-yuv' : '-yuv', + 'tjunittest-yuv-alloc' : '-yuv -alloc', + 'tjunittest-yuv-nopad' : '-yuv -noyuvpad', + 'tjunittest-lossless' : '-lossless', + 'tjunittest-lossless-alloc' : '-lossless -alloc', + 'tjunittest-bmp' : '-bmp', + 'tjunittest12' : '-precision 12', + 'tjunittest12-alloc' : '-precision 12 -alloc', + 'tjunittest12-lossless' : '-precision 12 -lossless', + 'tjunittest12-lossless-alloc' : '-precision 12 -lossless -alloc', + 'tjunittest12-bmp' : '-precision 12 -bmp', + 'tjunittest2-lossless' : '-precision 2', + 'tjunittest2-lossless-alloc' : '-precision 2 -alloc', + 'tjunittest2-bmp' : '-precision 2 -bmp', + 'tjunittest3-lossless' : '-precision 3', + 'tjunittest3-lossless-alloc' : '-precision 3 -alloc', + 'tjunittest3-bmp' : '-precision 3 -bmp', + 'tjunittest4-lossless' : '-precision 4', + 'tjunittest4-lossless-alloc' : '-precision 4 -alloc', + 'tjunittest4-bmp' : '-precision 4 -bmp', + 'tjunittest5-lossless' : '-precision 5', + 'tjunittest5-lossless-alloc' : '-precision 5 -alloc', + 'tjunittest5-bmp' : '-precision 5 -bmp', + 'tjunittest6-lossless' : '-precision 6', + 'tjunittest6-lossless-alloc' : '-precision 6 -alloc', + 'tjunittest6-bmp' : '-precision 6 -bmp', + 'tjunittest7-lossless' : '-precision 7', + 'tjunittest7-lossless-alloc' : '-precision 7 -alloc', + 'tjunittest7-bmp' : '-precision 7 -bmp', + 'tjunittest9-lossless' : '-precision 9', + 'tjunittest9-lossless-alloc' : '-precision 9 -alloc', + 'tjunittest9-bmp' : '-precision 9 -bmp', + 'tjunittest10-lossless' : '-precision 10', + 'tjunittest10-lossless-alloc' : '-precision 10 -alloc', + 'tjunittest10-bmp' : '-precision 10 -bmp', + 'tjunittest11-lossless' : '-precision 11', + 'tjunittest11-lossless-alloc' : '-precision 11 -alloc', + 'tjunittest11-bmp' : '-precision 11 -bmp', + 'tjunittest13-lossless' : '-precision 13', + 'tjunittest13-lossless-alloc' : '-precision 13 -alloc', + 'tjunittest13-bmp' : '-precision 13 -bmp', + 'tjunittest14-lossless' : '-precision 14', + 'tjunittest14-lossless-alloc' : '-precision 14 -alloc', + 'tjunittest14-bmp' : '-precision 14 -bmp', + 'tjunittest15-lossless' : '-precision 15', + 'tjunittest15-lossless-alloc' : '-precision 15 -alloc', + 'tjunittest15-bmp' : '-precision 15 -bmp', + 'tjunittest16-lossless' : '-precision 16', + 'tjunittest16-lossless-alloc' : '-precision 16 -alloc', + 'tjunittest16-bmp' : '-precision 16 -bmp', + } + test( + _test, + tjunittest, + args : _args.split(), + timeout : 120, + ) + endforeach +endif From a5f3121eb75550a92e213ed9392edffd7aa872be Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 15:33:45 +0200 Subject: [PATCH 02/78] build: start working on replacing cmake with meson for native build --- native/.gitignore | 7 +- native/CMakeLists.txt | 97 ----- native/build.gradle.kts | 76 ++-- native/meson.build | 19 + native/src/{cpp => }/helper/errors.cpp | 0 native/src/{cpp => }/helper/errors.hpp | 0 native/src/meson.build | 14 + native/src/{cpp => }/mpv/MPV.cpp | 10 +- native/src/{cpp => }/util/Errors.cpp | 0 native/subprojects/mpv.wrap | 5 + .../packagefiles/mpv/subprojects/expat.wrap | 13 + .../packagefiles/mpv/subprojects/ffmpeg.wrap | 9 + .../mpv/subprojects/harfbuzz.wrap | 10 + .../packagefiles/mpv/subprojects/libass.wrap | 4 + .../mpv/subprojects/libdbus.wrap.disabled | 8 + .../mpv/subprojects/libjpeg-turbo.wrap | 11 + .../subprojects/libpipewire-0.3.wrap.disabled | 8 + .../mpv/subprojects/libplacebo.wrap | 5 + .../packagefiles/mpv/subprojects/libpng.wrap | 13 + .../mpv/subprojects/openal-soft.wrap | 13 + .../packagefiles/ffmpeg/collect_versions.sh | 9 + .../packagefiles/ffmpeg/meson.build | 26 ++ .../libjpeg-turbo-3.1.2/LICENSE.build | 19 + .../libjpeg-turbo-3.1.2/meson.build | 150 ++++++++ .../libjpeg-turbo-3.1.2/meson_options.txt | 20 ++ .../libjpeg-turbo-3.1.2/simd/arm/meson.build | 6 + .../libjpeg-turbo-3.1.2/simd/meson.build | 338 ++++++++++++++++++ .../libjpeg-turbo-3.1.2/src/meson.build | 265 ++++++++++++++ .../packagefiles/mpv/subprojects/zlib.wrap | 13 + native/thirdparty/ffmpeg.cmake | 71 ---- native/thirdparty/mpv.cmake | 46 --- 31 files changed, 1030 insertions(+), 255 deletions(-) delete mode 100644 native/CMakeLists.txt create mode 100644 native/meson.build rename native/src/{cpp => }/helper/errors.cpp (100%) rename native/src/{cpp => }/helper/errors.hpp (100%) create mode 100644 native/src/meson.build rename native/src/{cpp => }/mpv/MPV.cpp (98%) rename native/src/{cpp => }/util/Errors.cpp (100%) create mode 100644 native/subprojects/mpv.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/expat.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/harfbuzz.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/libass.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/libdbus.wrap.disabled create mode 100644 native/subprojects/packagefiles/mpv/subprojects/libjpeg-turbo.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/libpipewire-0.3.wrap.disabled create mode 100644 native/subprojects/packagefiles/mpv/subprojects/libplacebo.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/libpng.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/openal-soft.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh create mode 100644 native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/meson.build create mode 100644 native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build create mode 100644 native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build create mode 100644 native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt create mode 100644 native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build create mode 100644 native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build create mode 100644 native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build create mode 100644 native/subprojects/packagefiles/mpv/subprojects/zlib.wrap delete mode 100644 native/thirdparty/ffmpeg.cmake delete mode 100644 native/thirdparty/mpv.cmake diff --git a/native/.gitignore b/native/.gitignore index db5c42d..6ca1186 100644 --- a/native/.gitignore +++ b/native/.gitignore @@ -1,3 +1,8 @@ .idea/ *.iml -cmake-build-*/ \ No newline at end of file +cmake-build-*/ +/subprojects/* +!/subprojects/*.wrap +!/subprojects/packagefiles +!/subprojects/packagefiles/* +buildDir/ diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt deleted file mode 100644 index 4c82b27..0000000 --- a/native/CMakeLists.txt +++ /dev/null @@ -1,97 +0,0 @@ -cmake_minimum_required(VERSION 3.16) -if (NOT DEFINED PROJECT_NAME) - set(PROJECT_NAME "compose-av") -endif () -if (NOT DEFINED NATIVE_PLATFORM) - message(FATAL_ERROR "NATIVE_PLATFORM must be defined") -else () - message(STATUS "NATIVE_PLATFORM: ${NATIVE_PLATFORM}") -endif () -if (NOT DEFINED FFMPEG_VERSION) - message(FATAL_ERROR "FFMPEG_VERSION must be defined") -else () - message(STATUS "FFMPEG_VERSION: ${FFMPEG_VERSION}") -endif () -if (NOT DEFINED MPV_VERSION) - message(FATAL_ERROR "MPV_VERSION must be defined") -else () - message(STATUS "MPV_VERSION: ${MPV_VERSION}") -endif () -if (NOT DEFINED JAVA_HOME) - message(FATAL_ERROR "JAVA_HOME must be defined") -else () - message(STATUS "JAVA_HOME: ${JAVA_HOME}") -endif () - -project(${PROJECT_NAME} LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -option(USE_SYSTEM_FFMPEG "Link dynamically against system ffmpeg instead of using static prebuilt libraries" OFF) -option(USE_SYSTEM_MPV "Link dynamically against system mpv instead of using static prebuilt libraries" OFF) - -include(ExternalProject) -if (NOT USE_SYSTEM_FFMPEG) - include(thirdparty/ffmpeg.cmake) -endif () -if (NOT USE_SYSTEM_MPV) - include(thirdparty/mpv.cmake) -endif () - -set(SOURCES - src/cpp/util/Errors.cpp - src/cpp/helper/errors.hpp - src/cpp/helper/errors.cpp - src/cpp/mpv/MPV.cpp -) - -if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - if (NOT DEFINED JAVA_HOME) - set(JAVA_HOME "/usr/lib/jvm/java-11-openjdk") - endif () - -# list(APPEND SOURCES) -elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows") -endif () - -add_library(${PROJECT_NAME} SHARED ${SOURCES}) -target_include_directories(${PROJECT_NAME} PRIVATE "src/cpp/") - -message(STATUS "JAVA_HOME: ${JAVA_HOME}") -target_include_directories(${PROJECT_NAME} PUBLIC "${JAVA_HOME}/include") -if (NOT USE_SYSTEM_FFMPEG) - target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--push-state,--whole-archive,--allow-multiple-definition ffmpeg -Wl,--pop-state) -endif () -if (NOT USE_SYSTEM_MPV) - target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--push-state,--whole-archive,--allow-multiple-definition mpv -Wl,--pop-state) -endif () -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND objcopy --localize-hidden --strip-all --strip-unneeded $) - -if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_compile_definitions(${PROJECT_NAME} PRIVATE -D_LINUX) - find_package(PkgConfig REQUIRED) - pkg_check_modules(GL REQUIRED IMPORTED_TARGET egl glx) - target_link_libraries(${PROJECT_NAME} PUBLIC PkgConfig::GL) - target_include_directories(${PROJECT_NAME} PUBLIC "${JAVA_HOME}/include/linux") - add_compile_options(-static -static-libstdc++ -static-libgcc) - add_link_options(-static -static-libstdc++ -static-libgcc) - if (USE_SYSTEM_FFMPEG) - pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET libavcodec libavformat libavutil libswscale libavfilter) - target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::FFMPEG) - endif () - if (USE_SYSTEM_MPV) - pkg_check_modules(MPV REQUIRED IMPORTED_TARGET mpv) - target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::MPV) - endif () -elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows") - target_compile_definitions(${PROJECT_NAME} PRIVATE -D_WINDOWS) - target_link_libraries(${PROJECT_NAME} PUBLIC opengl32 dxgi d3d11 d3dcompiler) - target_include_directories(${PROJECT_NAME} PUBLIC "${JAVA_HOME}/include/win32") -endif () - -#add_executable(test main.cpp) -#target_link_libraries(test PRIVATE PkgConfig::FFMPEG) -#target_link_libraries(test PRIVATE ${PROJECT_NAME}) -#target_link_libraries(test PRIVATE X11 GLX xcb va va-glx va-x11) -#target_include_directories(test PRIVATE "src/cpp/") diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 4129e56..58b6565 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -1,6 +1,7 @@ import dev.silenium.libs.jni.NativeLoader import dev.silenium.libs.jni.NativePlatform import dev.silenium.libs.jni.Platform +import org.jetbrains.kotlin.gradle.dsl.JvmTarget buildscript { repositories { @@ -26,55 +27,47 @@ val platformExtension = "-gpl".takeIf { withGPL }.orEmpty() val platformString = findProperty("ffmpeg.platform")?.toString() val platform = platformString?.let { Platform(it, platformExtension) } ?: NativePlatform.platform(platformExtension) -val cmakeExe = findProperty("cmake.executable") as? String ?: "cmake" +val mesonExe = findProperty("meson.executable") as? String ?: "meson" +val targetDir = layout.buildDirectory.dir("meson").get().asFile.apply { mkdirs() } val generateMakefile = tasks.register("generateMakefile") { - workingDir = layout.buildDirectory.dir("cmake").get().asFile.apply { mkdirs() } - val additionalFlags = mutableListOf( - "-DJAVA_HOME=${System.getProperty("java.home")}", - "-DPROJECT_NAME=${libName}", - "-DNATIVE_PLATFORM=${platform.osArch}", - "-DFFMPEG_PLATFORM_EXTENSION=${platform.extension}", - "-DFFMPEG_VERSION=${libs.ffmpeg.natives.get().version}", - "-DMPV_VERSION=${libs.mpv.natives.get().version}", + workingDir = layout.projectDirectory.asFile + + doFirst { + delete(targetDir) + } + + environment( + "CFLAGS" to "-fPIC", + "CXXFLAGS" to "-fPIC", ) + commandLine( - cmakeExe, - *additionalFlags.toTypedArray(), - layout.projectDirectory.asFile.absolutePath, + mesonExe, "setup", + targetDir.absolutePath, + "--force-fallback-for=ffmpeg,libjpeg,openal,libass,harfbuzz,expat,libplacebo,libpng,zlib", ) - inputs.file(layout.projectDirectory.file("CMakeLists.txt")) - inputs.properties( - "JAVA_HOME" to System.getProperty("java.home"), - "PROJECT_NAME" to libName, - "NATIVE_PLATFORM" to platform.osArch, - "FFMPEG_PLATFORM_EXTENSION" to platform.extension, - "FFMPEG_VERSION" to libs.ffmpeg.natives.get().version, - "MPV_VERSION" to libs.mpv.natives.get().version, - ) - outputs.dir(workingDir) + inputs.file(layout.projectDirectory.file("meson.build")) + inputs.file(layout.projectDirectory.file("src/meson.build")) + outputs.dir(targetDir) standardOutput = System.out } val compileNative = tasks.register("compileNative") { - workingDir = layout.buildDirectory.dir("cmake").get().asFile - commandLine(cmakeExe, "--build", ".", "-j", Runtime.getRuntime().availableProcessors().toString()) + commandLine(mesonExe, "compile", "-C", targetDir) dependsOn(generateMakefile) + environment( + "CFLAGS" to "-fPIC", + "CXXFLAGS" to "-fPIC", + ) + standardOutput = System.out val fileNameTemplate = NativeLoader.fileNameTemplate(platform) - when (platform.os) { - Platform.OS.WINDOWS -> { - outputs.files(layout.buildDirectory.file("cmake/Debug/${fileNameTemplate.format(libName)}")) - } - - Platform.OS.LINUX, Platform.OS.DARWIN -> { - outputs.files(layout.buildDirectory.file("cmake/${fileNameTemplate.format(libName)}")) - } - } - inputs.file(layout.buildDirectory.file("cmake/CMakeCache.txt")) + outputs.files(layout.buildDirectory.file("meson/src/${fileNameTemplate.format(libName)}")) + inputs.file(layout.buildDirectory.file("meson/build.ninja")) inputs.dir(layout.projectDirectory.dir("src")) - inputs.file(layout.projectDirectory.file("CMakeLists.txt")) + inputs.file(layout.projectDirectory.file("meson.build")) outputs.cacheIf { true } } @@ -94,6 +87,19 @@ tasks.processResources { } } +kotlin { + compilerOptions { + freeCompilerArgs.add("-Xcontext-receivers") + jvmTarget = JvmTarget.JVM_11 + } + jvmToolchain(11) +} + +java { + withSourcesJar() + withJavadocJar() +} + publishing { publications { if (deployNative) { diff --git a/native/meson.build b/native/meson.build new file mode 100644 index 0000000..cc41a75 --- /dev/null +++ b/native/meson.build @@ -0,0 +1,19 @@ +project('compose-av', + 'cpp', 'java', + default_options : { + 'cpp_std' : 'c++20', + } +) +add_global_arguments('-fPIC', language : 'c') +add_global_arguments('-fPIC', language : 'cpp') +mpv = subproject('mpv', + default_options : { + 'libmpv' : true, + 'drm' : 'enabled', + 'openal' : 'enabled', + 'force_fallback_for' : ['expat', 'ffmpeg', 'libjpeg', 'libass', 'libplacebo', 'libpng', 'openal', 'zlib'], + 'default_library' : 'static', + 'prefer_static' : true, + } +) +subdir('src') diff --git a/native/src/cpp/helper/errors.cpp b/native/src/helper/errors.cpp similarity index 100% rename from native/src/cpp/helper/errors.cpp rename to native/src/helper/errors.cpp diff --git a/native/src/cpp/helper/errors.hpp b/native/src/helper/errors.hpp similarity index 100% rename from native/src/cpp/helper/errors.hpp rename to native/src/helper/errors.hpp diff --git a/native/src/meson.build b/native/src/meson.build new file mode 100644 index 0000000..25e9831 --- /dev/null +++ b/native/src/meson.build @@ -0,0 +1,14 @@ +mpv_dep = mpv.get_variable('libmpv') +jni = dependency('jni') +egl = dependency('egl') +glx = dependency('glx') +x11 = dependency('X11') + +shared_library('compose-av', + 'util/Errors.cpp', + 'helper/errors.hpp', + 'helper/errors.cpp', + 'mpv/MPV.cpp', + dependencies : [jni, egl, glx, x11], + link_with : [mpv_dep], +) diff --git a/native/src/cpp/mpv/MPV.cpp b/native/src/mpv/MPV.cpp similarity index 98% rename from native/src/cpp/mpv/MPV.cpp rename to native/src/mpv/MPV.cpp index 547eeb6..1b002c3 100644 --- a/native/src/cpp/mpv/MPV.cpp +++ b/native/src/mpv/MPV.cpp @@ -566,11 +566,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createRend Display *display{nullptr}; if (const auto glxDisplay = glXGetCurrentDisplay(); glxDisplay != nullptr) { - params.emplace_back(MPV_RENDER_PARAM_X11_DISPLAY, glxDisplay); + params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, glxDisplay}); } else if (const auto eglDisplay = eglGetCurrentDisplay(); eglDisplay != EGL_NO_DISPLAY) { // Compose always runs on X11 display = XOpenDisplay(nullptr); - params.emplace_back(MPV_RENDER_PARAM_X11_DISPLAY, display); + params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, display}); } JavaVM *jvm; @@ -604,10 +604,10 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createRend }), .get_proc_address_ctx = object, }; - params.emplace_back(MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_params); + params.push_back({MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_params}); int advControl = advancedControl ? 1 : 0; - params.emplace_back(MPV_RENDER_PARAM_ADVANCED_CONTROL, &advControl); - params.emplace_back(MPV_RENDER_PARAM_INVALID, nullptr); + params.push_back({MPV_RENDER_PARAM_ADVANCED_CONTROL, &advControl}); + params.push_back({MPV_RENDER_PARAM_INVALID, nullptr}); mpv_render_context *handle{nullptr}; if (const auto ret = mpv_render_context_create(&handle, reinterpret_cast(mpvHandle), params.data()); ret < 0) { diff --git a/native/src/cpp/util/Errors.cpp b/native/src/util/Errors.cpp similarity index 100% rename from native/src/cpp/util/Errors.cpp rename to native/src/util/Errors.cpp diff --git a/native/subprojects/mpv.wrap b/native/subprojects/mpv.wrap new file mode 100644 index 0000000..4cf1e12 --- /dev/null +++ b/native/subprojects/mpv.wrap @@ -0,0 +1,5 @@ +[wrap-git] +revision = master +url = https://github.com/mpv-player/mpv.git +depth = 1 +patch_directory = mpv diff --git a/native/subprojects/packagefiles/mpv/subprojects/expat.wrap b/native/subprojects/packagefiles/mpv/subprojects/expat.wrap new file mode 100644 index 0000000..d16ba7a --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/expat.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = expat-2.7.3 +source_url = https://github.com/libexpat/libexpat/releases/download/R_2_7_3/expat-2.7.3.tar.xz +source_filename = expat-2.7.3.tar.bz2 +source_hash = 71df8f40706a7bb0a80a5367079ea75d91da4f8c65c58ec59bcdfbf7decdab9f +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/expat_2.7.3-1/expat-2.7.3.tar.bz2 +patch_filename = expat_2.7.3-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/expat_2.7.3-1/get_patch +patch_hash = e870eb4b2e3c142ce1d18ed24309aa40e07c6c911a4625fa1c6fc493ba18153a +wrapdb_version = 2.7.3-1 + +[provide] +expat = expat_dep diff --git a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap new file mode 100644 index 0000000..5c29551 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap @@ -0,0 +1,9 @@ +[wrap-file] +directory = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0 +source_url = https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz +source_filename = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz +source_hash = 6e32fab45ad71841de03e796124b7c1c06a8b42a53860525a44aa007b28757a8 +patch_directory = ffmpeg + +[provide] +dependency_names = libavcodec, libavfilter, libavformat, libavutil, libswresample, libswscale diff --git a/native/subprojects/packagefiles/mpv/subprojects/harfbuzz.wrap b/native/subprojects/packagefiles/mpv/subprojects/harfbuzz.wrap new file mode 100644 index 0000000..a53e504 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/harfbuzz.wrap @@ -0,0 +1,10 @@ +[wrap-file] +directory = harfbuzz-12.1.0 +source_url = https://github.com/harfbuzz/harfbuzz/releases/download/12.1.0/harfbuzz-12.1.0.tar.xz +source_filename = harfbuzz-12.1.0.tar.xz +source_hash = e5c81b7f6e0b102dfb000cfa424538b8e896ab78a2f4b8a5ec8cae62ab43369e +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/harfbuzz_12.1.0-1/harfbuzz-12.1.0.tar.xz +wrapdb_version = 12.1.0-1 + +[provide] +dependency_names = harfbuzz, harfbuzz-cairo, harfbuzz-gobject, harfbuzz-icu, harfbuzz-subset diff --git a/native/subprojects/packagefiles/mpv/subprojects/libass.wrap b/native/subprojects/packagefiles/mpv/subprojects/libass.wrap new file mode 100644 index 0000000..580d48a --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/libass.wrap @@ -0,0 +1,4 @@ +[wrap-git] +revision = master +url = https://github.com/libass/libass +depth = 1 diff --git a/native/subprojects/packagefiles/mpv/subprojects/libdbus.wrap.disabled b/native/subprojects/packagefiles/mpv/subprojects/libdbus.wrap.disabled new file mode 100644 index 0000000..6e6b101 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/libdbus.wrap.disabled @@ -0,0 +1,8 @@ +[wrap-git] +url = https://gitlab.freedesktop.org/dbus/dbus.git +revision = dbus-1.16.2 +depth = 1 +clone-recursive = true + +[provide] +dependency_names = dbus-1 diff --git a/native/subprojects/packagefiles/mpv/subprojects/libjpeg-turbo.wrap b/native/subprojects/packagefiles/mpv/subprojects/libjpeg-turbo.wrap new file mode 100644 index 0000000..c0ca6d0 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/libjpeg-turbo.wrap @@ -0,0 +1,11 @@ +[wrap-file] +directory = libjpeg-turbo-3.1.2 +source_url = https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.1.2/libjpeg-turbo-3.1.2.tar.gz +source_filename = libjpeg-turbo-3.1.2.tar.gz +source_hash = 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf +patch_directory = libjpeg-turbo-3.1.2 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libjpeg-turbo_3.1.2-1/libjpeg-turbo-3.1.2.tar.gz +wrapdb_version = 3.1.2-1 + +[provide] +dependency_names = libjpeg, libturbojpeg diff --git a/native/subprojects/packagefiles/mpv/subprojects/libpipewire-0.3.wrap.disabled b/native/subprojects/packagefiles/mpv/subprojects/libpipewire-0.3.wrap.disabled new file mode 100644 index 0000000..4691d10 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/libpipewire-0.3.wrap.disabled @@ -0,0 +1,8 @@ +[wrap-git] +url = https://gitlab.freedesktop.org/pipewire/pipewire.git +revision = 1.4.9 +depth = 1 +clone-recursive = true + +[provide] +dependency_names = libpipewire-0.3 diff --git a/native/subprojects/packagefiles/mpv/subprojects/libplacebo.wrap b/native/subprojects/packagefiles/mpv/subprojects/libplacebo.wrap new file mode 100644 index 0000000..dc08964 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/libplacebo.wrap @@ -0,0 +1,5 @@ +[wrap-git] +url = https://github.com/haasn/libplacebo +revision = master +depth = 1 +clone-recursive = true diff --git a/native/subprojects/packagefiles/mpv/subprojects/libpng.wrap b/native/subprojects/packagefiles/mpv/subprojects/libpng.wrap new file mode 100644 index 0000000..dc64f96 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/libpng.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = libpng-1.6.50 +source_url = https://github.com/pnggroup/libpng/archive/v1.6.50.tar.gz +source_filename = libpng-1.6.50.tar.gz +source_hash = 71158e53cfdf2877bc99bcab33641d78df3f48e6e0daad030afe9cb8c031aa46 +patch_filename = libpng_1.6.50-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/libpng_1.6.50-2/get_patch +patch_hash = a9c9362bb8cbb422c864807a174977dec3868cdff8ca380e27bab6ee1caa22ea +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libpng_1.6.50-2/libpng-1.6.50.tar.gz +wrapdb_version = 1.6.50-2 + +[provide] +libpng = libpng_dep diff --git a/native/subprojects/packagefiles/mpv/subprojects/openal-soft.wrap b/native/subprojects/packagefiles/mpv/subprojects/openal-soft.wrap new file mode 100644 index 0000000..d657c24 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/openal-soft.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = openal-soft-1.24.3 +source_url = https://github.com/kcat/openal-soft/archive/refs/tags/1.24.3.tar.gz +source_filename = openal-soft-1.24.3.tar.gz +source_hash = 7e1fecdeb45e7f78722b776c5cf30bd33934b961d7fd2a11e0494e064cc631ce +patch_filename = openal-soft_1.24.3-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/openal-soft_1.24.3-1/get_patch +patch_hash = 9a6c16622cc7ddb08a81afaa9c44925e547518c9485f29a68d1502e0ebe54d16 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/openal-soft_1.24.3-1/openal-soft-1.24.3.tar.gz +wrapdb_version = 1.24.3-1 + +[provide] +openal = openal_dep diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh new file mode 100644 index 0000000..c620567 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +for shared_object in "${MESON_SOURCE_ROOT}/${MESON_SUBDIR}"/lib/*.so.*.*.*; do + filename=$(basename "$shared_object") + lib_name=$(basename "${filename//\.so.*/}") + lib_name="${lib_name//lib/}" + lib_version=${filename//*.so\./} + echo "${lib_name}:${lib_version}" +done diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/meson.build b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/meson.build new file mode 100644 index 0000000..791782c --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/meson.build @@ -0,0 +1,26 @@ +project('ffmpeg', 'c') + +cc = meson.get_compiler('c') + +versions_command = run_command('bash', 'collect_versions.sh', capture : true, check : true) +versions = versions_command.stdout().strip().split('\n') + +library_names = ['avcodec', 'avfilter', 'avformat', 'avutil', 'swresample', 'swscale'] + +foreach lib_name : library_names + foreach version : versions + version_name = version.split(':')[0].strip() + version_value = version.split(':')[1].strip() + + if version_name == lib_name + message(version) + dep = declare_dependency( + version : version_value, + dependencies : cc.find_library(lib_name, dirs : meson.current_source_dir() + '/lib'), + include_directories : include_directories('include'), + ) + meson.override_dependency('lib' + lib_name, dep) + break + endif + endforeach +endforeach diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build new file mode 100644 index 0000000..b59833d --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build @@ -0,0 +1,19 @@ +Copyright (c) 2021 The Meson development team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build new file mode 100644 index 0000000..e84a024 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build @@ -0,0 +1,150 @@ +project( + 'libjpeg-turbo', + 'c', + version : '3.1.2', + license : 'BSD-3-Clause AND IJG', + meson_version : '>= 0.64.0', +) + +add_project_arguments('-D_POSIX_C_SOURCE=200809L', language : 'c') +add_project_arguments('-D_DEFAULT_SOURCE', language : 'c') + +pkg = import('pkgconfig') +python = import('python').find_installation() + +cc = meson.get_compiler('c') +host_system = host_machine.system() +host_cpu = host_machine.cpu_family() + +cdata = configuration_data() +cdata.set('CMAKE_PROJECT_NAME', meson.project_name()) +cdata.set('VERSION', meson.project_version()) +cdata.set('COPYRIGHT_YEAR', '1991-2025') + +jpeg_lib_version = 80 +so_major = jpeg_lib_version / 10 +so_age = 3 +so_minor = 2 +so_version = '@0@.@1@.@2@'.format(so_major, so_age, so_minor) +vs_defs = files('win/jpeg8.def')[0] + +version_arr = meson.project_version().split('.') +version_major = version_arr[0] +version_minor = version_arr[1] +version_revision = version_arr[2] + +# Add padding to build an integer: 2.1.0 -> 2001000 +if version_major.to_int() < 10 + version_major += '00' +elif version_major.to_int() < 100 + version_major += '0' +endif + +if version_minor.to_int() < 10 + version_minor += '00' +elif version_minor.to_int() < 100 + version_minor += '0' +endif + +cdata.set('JPEG_LIB_VERSION', jpeg_lib_version) +cdata.set( + 'LIBJPEG_TURBO_VERSION_NUMBER', + version_major + version_minor + version_revision, +) + +cdata.set('C_ARITH_CODING_SUPPORTED', true) +cdata.set('D_ARITH_CODING_SUPPORTED', true) + +check_headers = ['local.h', 'stddef.h', 'stdlib.h', 'sys/types.h'] +if cc.get_id() == 'msvc' + check_headers += 'intrin.h' +endif + +foreach header : check_headers + have_header = cc.has_header(header) + cdata.set('HAVE_' + header.underscorify().to_upper(), have_header) + cdata.set('NEED_' + header.underscorify().to_upper(), have_header) +endforeach + +has_memset = cc.has_header_symbol('string.h', 'memset') +has_memcpy = cc.has_header_symbol('string.h', 'memcpy') +cdata.set('NEED_BSD_STRINGS', not has_memset or not has_memcpy) + +size_t = cc.sizeof('size_t') +unsigned_long = cc.sizeof('unsigned long') +cdata.set('SIZE_T', size_t) +cdata.set('HAVE_UNSIGNED_CHAR', cc.sizeof('unsigned char') != -1) +cdata.set('HAVE_UNSIGNED_SHORT', cc.sizeof('unsigned short') != -1) +if size_t == unsigned_long + cdata.set('HAVE_BUILTIN_CTZL', cc.has_function('__builtin_ctzl')) +endif + +code = 'int main(void) { typedef struct undefined_structure *undef_struct_ptr; undef_struct_ptr ptr = 0; return ptr != 0; }' +cdata.set('INCOMPLETE_TYPES_BROKEN', not cc.links(code)) + +if meson.can_run_host_binaries() + code = ''' + #include + #include + static int is_shifting_signed (long arg) { + long res = arg >> 4; + if (res == -0x7F7E80CL) + return 1; /* right shift is signed */ + /* see if unsigned-shift hack will fix it. */ + /* we can't just test exact value since it depends on width of long... */ + res |= 0xFFFFFFFFL << (32-4); + if (res == -0x7F7E80CL) + return 0; /* right shift is unsigned */ + printf(\"Right shift isn't acting as I expect it to.\\\\n\"); + printf(\"I fear the JPEG software will not work at all.\\\\n\\\\n\"); + return 0; /* try it with unsigned anyway */ + } + int main (void) { + exit(is_shifting_signed(-0x7F7E80B1L)); + } + ''' + cdata.set('RIGHT_SHIFT_IS_UNSIGNED', cc.run(code).returncode() == 0) +else + cdata.set('RIGHT_SHIFT_IS_UNSIGNED', false) +endif + +p = run_command( + python, + '-c', + 'import datetime; print(datetime.datetime.now().strftime("%Y%m%d"))', + check : true, +) +cdata.set('BUILD', p.stdout().strip()) + +if cc.get_id() == 'msvc' + cdata.set('THREAD_LOCAL', '__declspec(thread)') +else + cdata.set('THREAD_LOCAL', '__thread') +endif + +cdata.set('HIDDEN', cc.has_function_attribute('visibility:hidden') ? '__attribute__((visibility("hidden")))' + : '') + +if get_option('force_inline') + if cc.get_id() == 'msvc' + cdata.set('INLINE', '__forceinline') + else + cdata.set('INLINE', 'inline __attribute__((always_inline))') + endif +else + cdata.set('INLINE', 'inline') +endif + +if host_system == 'windows' + add_project_arguments( + '-DDLLDEFINE', + language : 'c', + ) +endif + +incdir = include_directories('src') + +subdir('simd') +cdata.set('WITH_SIMD', have_simd) + +subdir('src') diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt new file mode 100644 index 0000000..41ed4bb --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt @@ -0,0 +1,20 @@ +option( + 'force_inline', + type : 'boolean', +) +option( + 'turbojpeg', + type : 'feature', +) +option( + 'simd', + type : 'feature', +) +option( + 'tests', + type : 'feature', +) +option( + 'neon-intrinsics', + type : 'feature', +) diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build new file mode 100644 index 0000000..124b74a --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build @@ -0,0 +1,6 @@ +neon_compat_h = configure_file( + input : 'neon-compat.h.in', + output : 'neon-compat.h', + format : 'cmake', + configuration : cdata_neon, +) diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build new file mode 100644 index 0000000..7c2306d --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build @@ -0,0 +1,338 @@ +simd_src_x86_64 = [ + 'x86_64/jccolor-avx2.asm', + 'x86_64/jccolor-sse2.asm', + 'x86_64/jcgray-avx2.asm', + 'x86_64/jcgray-sse2.asm', + 'x86_64/jchuff-sse2.asm', + 'x86_64/jcphuff-sse2.asm', + 'x86_64/jcsample-avx2.asm', + 'x86_64/jcsample-sse2.asm', + 'x86_64/jdcolor-avx2.asm', + 'x86_64/jdcolor-sse2.asm', + 'x86_64/jdmerge-avx2.asm', + 'x86_64/jdmerge-sse2.asm', + 'x86_64/jdsample-avx2.asm', + 'x86_64/jdsample-sse2.asm', + 'x86_64/jfdctflt-sse.asm', + 'x86_64/jfdctfst-sse2.asm', + 'x86_64/jfdctint-avx2.asm', + 'x86_64/jfdctint-sse2.asm', + 'x86_64/jidctflt-sse2.asm', + 'x86_64/jidctfst-sse2.asm', + 'x86_64/jidctint-avx2.asm', + 'x86_64/jidctint-sse2.asm', + 'x86_64/jidctred-sse2.asm', + 'x86_64/jquantf-sse2.asm', + 'x86_64/jquanti-avx2.asm', + 'x86_64/jquanti-sse2.asm', + 'x86_64/jsimdcpu.asm', +] + +simd_src_i386 = [ + 'i386/jccolor-avx2.asm', + 'i386/jccolor-mmx.asm', + 'i386/jccolor-sse2.asm', + 'i386/jcgray-avx2.asm', + 'i386/jcgray-mmx.asm', + 'i386/jcgray-sse2.asm', + 'i386/jchuff-sse2.asm', + 'i386/jcphuff-sse2.asm', + 'i386/jcsample-avx2.asm', + 'i386/jcsample-mmx.asm', + 'i386/jcsample-sse2.asm', + 'i386/jdcolor-avx2.asm', + 'i386/jdcolor-mmx.asm', + 'i386/jdcolor-sse2.asm', + 'i386/jdmerge-avx2.asm', + 'i386/jdmerge-mmx.asm', + 'i386/jdmerge-sse2.asm', + 'i386/jdsample-avx2.asm', + 'i386/jdsample-mmx.asm', + 'i386/jdsample-sse2.asm', + 'i386/jfdctflt-3dn.asm', + 'i386/jfdctflt-sse.asm', + 'i386/jfdctfst-mmx.asm', + 'i386/jfdctfst-sse2.asm', + 'i386/jfdctint-avx2.asm', + 'i386/jfdctint-mmx.asm', + 'i386/jfdctint-sse2.asm', + 'i386/jidctflt-3dn.asm', + 'i386/jidctflt-sse2.asm', + 'i386/jidctflt-sse.asm', + 'i386/jidctfst-mmx.asm', + 'i386/jidctfst-sse2.asm', + 'i386/jidctint-avx2.asm', + 'i386/jidctint-mmx.asm', + 'i386/jidctint-sse2.asm', + 'i386/jidctred-mmx.asm', + 'i386/jidctred-sse2.asm', + 'i386/jquant-3dn.asm', + 'i386/jquantf-sse2.asm', + 'i386/jquanti-avx2.asm', + 'i386/jquanti-sse2.asm', + 'i386/jquant-mmx.asm', + 'i386/jquant-sse.asm', + 'i386/jsimdcpu.asm', +] + +simd_src_arm = files( + 'arm/jcgray-neon.c', + 'arm/jcphuff-neon.c', + 'arm/jcsample-neon.c', + 'arm/jdmerge-neon.c', + 'arm/jdsample-neon.c', + 'arm/jfdctfst-neon.c', + 'arm/jidctred-neon.c', + 'arm/jquanti-neon.c', +) + +simd_opt = get_option('simd') +have_simd = false +simd = [] + +if host_cpu in ['x86', 'x86_64'] + have_simd = add_languages( + 'nasm', + required : simd_opt, + native : false, + ) + if have_simd + add_project_arguments( + '-DPIC', + language : 'nasm', + ) + x64 = host_cpu == 'x86_64' + # simulate upstream's "is ELF" check by excluding non-ELF OSes + if x64 and host_machine.system() not in ['cygwin', 'darwin', 'windows'] + if cc.compiles( + ''' + #if (__CET__ & 3) == 0 + #error \"CET not enabled\" + #endif + int main(void) { return 0; } + ''', + ) + add_project_arguments( + '-D__CET__', + language : 'nasm', + ) + endif + endif + dir = x64 ? 'x86_64' : 'i386' + simd_src = x64 ? simd_src_x86_64 : simd_src_i386 + simd = static_library( + 'simd', + dir / 'jsimd.c', + simd_src, + include_directories : [incdir, 'nasm', dir], + pic : get_option('default_library') != 'static', + ) + endif +elif host_cpu in ['arm', 'aarch64'] + aarch = host_cpu == 'aarch64' ? 'aarch64' : 'aarch32' + dir = 'arm' / aarch + cdata_neon = configuration_data() + + needs_softfp_for_intrinsics = host_cpu == 'arm' and cc.compiles( + ''' + #if defined(__ARM_NEON__) || (!defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)) + #error \"Neon run-time auto-detection will not be used\" + #endif + #if __ARM_PCS_VFP == 1 + #error \"float ABI = hard\" + #endif + #if __SOFTFP__ != 1 + #error \"float ABI = softfp\" + #endif + int main(void) { return 0; }" + ''', + name : 'does not need softfp for Neon intrinsics', + ) + neon_flags = [] + if host_cpu == 'arm' + neon_flags += ['-mfpu=neon'] + endif + if needs_softfp_for_intrinsics + neon_flags += ['-mfloatabi=softfp'] + endif + if host_cpu == 'arm' + have_simd = cc.compiles( + '''#include + int main(int argc, char **argv) { + uint16x8_t input = vdupq_n_u16((uint16_t)argc); + uint8x8_t output = vmovn_u16(input); + return (int)output[0]; + }''', + args : neon_flags, + name : 'supports Neon', + ) + if not have_simd + if simd_opt.enabled() + error('SIMD extensions not available for this architecture') + else + warning('SIMD extensions not available for this architecture') + endif + endif + else + have_simd = true + endif + + if have_simd + cdata_neon.set( + 'HAVE_VLD1_S16_X3', + cc.compiles( + '''#include + int main(int argc, char **argv) { + int16_t input[12]; + int16x4x3_t output; + int i; + for (i = 0; i < 12; i++) input[i] = (int16_t)argc; + output = vld1_s16_x3(input); + vst3_s16(input, output); + return (int)input[0]; + }''', + args : neon_flags, + name : 'supports vld1_s16_x3 intrinsic', + ), + ) + cdata_neon.set( + 'HAVE_VLD1_U16_X2', + cc.compiles( + ''' + #include + int main(int argc, char **argv) { + uint16_t input[8]; + uint16x4x2_t output; + int i; + for (i = 0; i < 8; i++) input[i] = (uint16_t)argc; + output = vld1_u16_x2(input); + vst2_u16(input, output); + return (int)input[0]; + }''', + args : neon_flags, + name : 'supports vld1_u16_x2 intrinsic', + ), + ) + cdata_neon.set( + 'HAVE_VLD1Q_U8_X4', + cc.compiles( + ''' + #include + int main(int argc, char **argv) { + uint8_t input[64]; + uint8x16x4_t output; + int i; + for (i = 0; i < 64; i++) input[i] = (uint8_t)argc; + output = vld1q_u8_x4(input); + vst4q_u8(input, output); + return (int)input[0]; + }''', + args : neon_flags, + name : 'supports vld1q_u8_x4 intrinsic', + ), + ) + + subdir('arm') + simd_src_arm += [neon_compat_h] + + # GCC 11 and earlier and some older versions of Clang do not have a full or + # optimal set of Neon intrinsics, so for performance reasons, when using those + # compilers, we default to using the older GAS implementation of the Neon SIMD + # extensions for certain algorithms. The presence or absence of the three + # intrinsics we tested above is a reasonable proxy for this, except with GCC 10 + # and 11. + + default_neon_intrinsics = cdata_neon.get('HAVE_VLD1_S16_X3') and cdata_neon.get( + 'HAVE_VLD1_U16_X2', + ) and cdata_neon.get( + 'HAVE_VLD1Q_U8_X4', + ) and ( + cc.get_id() != 'gcc' or cc.version().version_compare('>= 12.0.0') + ) + + neon_intrinsics = get_option('neon-intrinsics').disable_auto_if( + not default_neon_intrinsics, + ).allowed() + + # It is possible to run compile checks on generated files, however, + # Meson versions earlier than 1.2.0 do not set the lookup path + # correctly, causing Python to fail opening it. + # https://github.com/mesonbuild/meson/issues/11983 + if meson.version().version_compare('>= 1.2.0') and not neon_intrinsics + if (host_cpu == 'armv7') + gastest = ''' + .text + .fpu neon + .arch armv7a + .object_arch armv4 + .arm + pld [r0] + vmovn.u16 d0, q0 + ''' + else + gastest = ''' + .text + MYVAR .req x0 + movi v0.16b, #100 + mov MYVAR, #100 + .unreq MYVAR + ''' + endif + # cc.compiles() can't pass inline assembly to the C compiler + # https://github.com/mesonbuild/meson/issues/12395 + f = configure_file( + command : [ + python, + '-c', + 'import sys; print(sys.argv[1])', + '@0@'.format(gastest), + ], + output : 'gastest.S', + capture : true, + ) + if not cc.compiles( + f, + args : neon_flags, + name : 'can use the partial Neon SIMD intrinsics implementation', + ) + neon_intrinsics = true + endif + endif + + summary('Neon SIMD intrinsics', neon_intrinsics ? 'full' : 'partial') + + if neon_intrinsics + add_project_arguments( + '-DNEON_INTRINSICS', + language : 'c', + ) + simd_src_arm += files('arm/jccolor-neon.c', 'arm/jidctint-neon.c') + endif + + if neon_intrinsics or host_cpu == 'aarch64' + simd_src_arm += files('arm/jidctfst-neon.c') + endif + + if neon_intrinsics or host_cpu == 'arm' + simd_src_arm += files( + dir / 'jchuff-neon.c', + 'arm/jdcolor-neon.c', + 'arm/jfdctint-neon.c', + ) + endif + + if not neon_intrinsics + simd_src_arm += files(dir / 'jsimd_neon.S') + endif + + simd = static_library( + 'simd', + simd_src_arm + files(dir / 'jsimd.c'), + pic : get_option('default_library') != 'static', + include_directories : [incdir, 'arm', dir], + c_args : neon_flags, + ) + endif +elif simd_opt.enabled() + error('SIMD enabled, but CPU family not supported') +endif diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build new file mode 100644 index 0000000..b03a0f8 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build @@ -0,0 +1,265 @@ +jconfig_h = configure_file( + input : 'jconfig.h.in', + output : 'jconfig.h', + format : 'cmake@', + configuration : cdata, +) + +configure_file( + input : 'jconfigint.h.in', + output : 'jconfigint.h', + format : 'cmake@', + configuration : cdata, +) + +configure_file( + input : 'jversion.h.in', + output : 'jversion.h', + format : 'cmake@', + configuration : cdata, +) + +install_headers('jmorecfg.h', 'jerror.h', 'jpeglib.h', jconfig_h) + +sources = files( + 'jcapimin.c', + 'jchuff.c', + 'jcicc.c', + 'jcinit.c', + 'jclhuff.c', + 'jcmarker.c', + 'jcmaster.c', + 'jcomapi.c', + 'jcparam.c', + 'jcphuff.c', + 'jctrans.c', + 'jdapimin.c', + 'jdatadst.c', + 'jdatasrc.c', + 'jdhuff.c', + 'jdicc.c', + 'jdinput.c', + 'jdlhuff.c', + 'jdmarker.c', + 'jdmaster.c', + 'jdphuff.c', + 'jdtrans.c', + 'jerror.c', + 'jfdctflt.c', + 'jmemmgr.c', + 'jmemnobs.c', + 'jpeg_nbits.c', + 'wrapper/jcapistd-12.c', + 'wrapper/jcapistd-16.c', + 'wrapper/jcapistd-8.c', + 'wrapper/jccoefct-12.c', + 'wrapper/jccoefct-8.c', + 'wrapper/jccolor-12.c', + 'wrapper/jccolor-16.c', + 'wrapper/jccolor-8.c', + 'wrapper/jcdctmgr-12.c', + 'wrapper/jcdctmgr-8.c', + 'wrapper/jcdiffct-12.c', + 'wrapper/jcdiffct-16.c', + 'wrapper/jcdiffct-8.c', + 'wrapper/jclossls-12.c', + 'wrapper/jclossls-16.c', + 'wrapper/jclossls-8.c', + 'wrapper/jcmainct-12.c', + 'wrapper/jcmainct-16.c', + 'wrapper/jcmainct-8.c', + 'wrapper/jcprepct-12.c', + 'wrapper/jcprepct-16.c', + 'wrapper/jcprepct-8.c', + 'wrapper/jcsample-12.c', + 'wrapper/jcsample-16.c', + 'wrapper/jcsample-8.c', + 'wrapper/jdapistd-12.c', + 'wrapper/jdapistd-16.c', + 'wrapper/jdapistd-8.c', + 'wrapper/jdcoefct-12.c', + 'wrapper/jdcoefct-8.c', + 'wrapper/jdcolor-12.c', + 'wrapper/jdcolor-16.c', + 'wrapper/jdcolor-8.c', + 'wrapper/jddctmgr-12.c', + 'wrapper/jddctmgr-8.c', + 'wrapper/jddiffct-12.c', + 'wrapper/jddiffct-16.c', + 'wrapper/jddiffct-8.c', + 'wrapper/jdlossls-12.c', + 'wrapper/jdlossls-16.c', + 'wrapper/jdlossls-8.c', + 'wrapper/jdmainct-12.c', + 'wrapper/jdmainct-16.c', + 'wrapper/jdmainct-8.c', + 'wrapper/jdmerge-12.c', + 'wrapper/jdmerge-8.c', + 'wrapper/jdpostct-12.c', + 'wrapper/jdpostct-16.c', + 'wrapper/jdpostct-8.c', + 'wrapper/jdsample-12.c', + 'wrapper/jdsample-16.c', + 'wrapper/jdsample-8.c', + 'wrapper/jfdctfst-12.c', + 'wrapper/jfdctfst-8.c', + 'wrapper/jfdctint-12.c', + 'wrapper/jfdctint-8.c', + 'wrapper/jidctflt-12.c', + 'wrapper/jidctflt-8.c', + 'wrapper/jidctfst-12.c', + 'wrapper/jidctfst-8.c', + 'wrapper/jidctint-12.c', + 'wrapper/jidctint-8.c', + 'wrapper/jidctred-12.c', + 'wrapper/jidctred-8.c', + 'wrapper/jquant1-12.c', + 'wrapper/jquant1-8.c', + 'wrapper/jquant2-12.c', + 'wrapper/jquant2-8.c', + 'wrapper/jutils-12.c', + 'wrapper/jutils-16.c', + 'wrapper/jutils-8.c', +) + +sources += files( + # TODO: `with_arith_dec` / `with_arith_enc` only. + 'jaricom.c', + # TODO: `with_arith_enc` only + 'jcarith.c', + # TODO: `with_arith_dec` only + 'jdarith.c', +) + +jpeg = library( + 'jpeg', + sources, + link_whole : simd, + soversion : so_version, + vs_module_defs : vs_defs, + install : true, +) + +pkg.generate( + jpeg, + description : 'A SIMD-accelerated JPEG codec that provides the libjpeg API', + name : 'libjpeg', +) + +jpeg_dep = declare_dependency( + include_directories : incdir, + link_with : jpeg, +) +meson.override_dependency('libjpeg', jpeg_dep) + +if get_option('turbojpeg').allowed() + install_headers('turbojpeg.h') + + turbojpeg = library( + 'turbojpeg', + sources, + files( + 'jdatadst-tj.c', + 'jdatasrc-tj.c', + 'rdbmp.c', + 'transupp.c', + 'turbojpeg.c', + 'wrapper/rdppm-12.c', + 'wrapper/rdppm-16.c', + 'wrapper/rdppm-8.c', + 'wrapper/wrppm-12.c', + 'wrapper/wrppm-16.c', + 'wrapper/wrppm-8.c', + 'wrbmp.c', + ), + c_args : ['-DBMP_SUPPORTED', '-DPPM_SUPPORTED'], + install : true, + link_whole : simd, + soversion : '0.4.0', + ) + + pkg.generate( + turbojpeg, + description : 'A SIMD-accelerated JPEG codec that provides the TurboJPEG API', + name : 'libturbojpeg', + ) + + turbojpeg_dep = declare_dependency( + include_directories : incdir, + link_with : turbojpeg, + ) + meson.override_dependency('libturbojpeg', turbojpeg_dep) +endif + +if get_option('tests').require( + get_option('turbojpeg').allowed(), + error_message : 'turbojpeg feature needed', +).allowed() + tjunittest = executable( + 'tjunittest', + ['tjunittest.c', 'tjutil.c', 'md5/md5.c', 'md5/md5hl.c'], + dependencies : turbojpeg_dep, + ) + + foreach _test, _args : { + 'tjunittest' : '', + 'tjunittest-alloc' : '-alloc', + 'tjunittest-yuv' : '-yuv', + 'tjunittest-yuv-alloc' : '-yuv -alloc', + 'tjunittest-yuv-nopad' : '-yuv -noyuvpad', + 'tjunittest-lossless' : '-lossless', + 'tjunittest-lossless-alloc' : '-lossless -alloc', + 'tjunittest-bmp' : '-bmp', + 'tjunittest12' : '-precision 12', + 'tjunittest12-alloc' : '-precision 12 -alloc', + 'tjunittest12-lossless' : '-precision 12 -lossless', + 'tjunittest12-lossless-alloc' : '-precision 12 -lossless -alloc', + 'tjunittest12-bmp' : '-precision 12 -bmp', + 'tjunittest2-lossless' : '-precision 2', + 'tjunittest2-lossless-alloc' : '-precision 2 -alloc', + 'tjunittest2-bmp' : '-precision 2 -bmp', + 'tjunittest3-lossless' : '-precision 3', + 'tjunittest3-lossless-alloc' : '-precision 3 -alloc', + 'tjunittest3-bmp' : '-precision 3 -bmp', + 'tjunittest4-lossless' : '-precision 4', + 'tjunittest4-lossless-alloc' : '-precision 4 -alloc', + 'tjunittest4-bmp' : '-precision 4 -bmp', + 'tjunittest5-lossless' : '-precision 5', + 'tjunittest5-lossless-alloc' : '-precision 5 -alloc', + 'tjunittest5-bmp' : '-precision 5 -bmp', + 'tjunittest6-lossless' : '-precision 6', + 'tjunittest6-lossless-alloc' : '-precision 6 -alloc', + 'tjunittest6-bmp' : '-precision 6 -bmp', + 'tjunittest7-lossless' : '-precision 7', + 'tjunittest7-lossless-alloc' : '-precision 7 -alloc', + 'tjunittest7-bmp' : '-precision 7 -bmp', + 'tjunittest9-lossless' : '-precision 9', + 'tjunittest9-lossless-alloc' : '-precision 9 -alloc', + 'tjunittest9-bmp' : '-precision 9 -bmp', + 'tjunittest10-lossless' : '-precision 10', + 'tjunittest10-lossless-alloc' : '-precision 10 -alloc', + 'tjunittest10-bmp' : '-precision 10 -bmp', + 'tjunittest11-lossless' : '-precision 11', + 'tjunittest11-lossless-alloc' : '-precision 11 -alloc', + 'tjunittest11-bmp' : '-precision 11 -bmp', + 'tjunittest13-lossless' : '-precision 13', + 'tjunittest13-lossless-alloc' : '-precision 13 -alloc', + 'tjunittest13-bmp' : '-precision 13 -bmp', + 'tjunittest14-lossless' : '-precision 14', + 'tjunittest14-lossless-alloc' : '-precision 14 -alloc', + 'tjunittest14-bmp' : '-precision 14 -bmp', + 'tjunittest15-lossless' : '-precision 15', + 'tjunittest15-lossless-alloc' : '-precision 15 -alloc', + 'tjunittest15-bmp' : '-precision 15 -bmp', + 'tjunittest16-lossless' : '-precision 16', + 'tjunittest16-lossless-alloc' : '-precision 16 -alloc', + 'tjunittest16-bmp' : '-precision 16 -bmp', + } + test( + _test, + tjunittest, + args : _args.split(), + timeout : 120, + ) + endforeach +endif diff --git a/native/subprojects/packagefiles/mpv/subprojects/zlib.wrap b/native/subprojects/packagefiles/mpv/subprojects/zlib.wrap new file mode 100644 index 0000000..e2f2958 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/zlib.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = zlib-1.3.1 +source_url = http://zlib.net/fossils/zlib-1.3.1.tar.gz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/zlib_1.3.1-2/zlib-1.3.1.tar.gz +source_filename = zlib-1.3.1.tar.gz +source_hash = 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23 +patch_filename = zlib_1.3.1-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/zlib_1.3.1-2/get_patch +patch_hash = 9cacea02e1119964bc51e92dd2359b14df723a36cfe0df1c78d55d9c9f2763ae +wrapdb_version = 1.3.1-2 + +[provide] +zlib = zlib_dep diff --git a/native/thirdparty/ffmpeg.cmake b/native/thirdparty/ffmpeg.cmake deleted file mode 100644 index cc8da95..0000000 --- a/native/thirdparty/ffmpeg.cmake +++ /dev/null @@ -1,71 +0,0 @@ -set(FFMPEG_URL "https://reposilite.silenium.dev/releases/dev/silenium/libs/ffmpeg/ffmpeg-natives-${NATIVE_PLATFORM}${FFMPEG_PLATFORM_EXTENSION}/${FFMPEG_VERSION}/ffmpeg-natives-${NATIVE_PLATFORM}${FFMPEG_PLATFORM_EXTENSION}-${FFMPEG_VERSION}.zip") -set(FFMPEG_URL_SHA256 "https://reposilite.silenium.dev/releases/dev/silenium/libs/ffmpeg/ffmpeg-natives-${NATIVE_PLATFORM}${FFMPEG_PLATFORM_EXTENSION}/${FFMPEG_VERSION}/ffmpeg-natives-${NATIVE_PLATFORM}${FFMPEG_PLATFORM_EXTENSION}-${FFMPEG_VERSION}.zip.sha256") -set(FFMPEG_PREFIX "${CMAKE_BINARY_DIR}/ffmpeg") -message(STATUS "Downloading ffmpeg from ${FFMPEG_URL}") - -file(DOWNLOAD "${FFMPEG_URL_SHA256}" "${CMAKE_BINARY_DIR}/ffmpeg.zip.sha256") -file(READ "${CMAKE_BINARY_DIR}/ffmpeg.zip.sha256" FFMPEG_SHA256) -file(DOWNLOAD "${FFMPEG_URL}" "${CMAKE_BINARY_DIR}/ffmpeg.zip" EXPECTED_HASH SHA256=${FFMPEG_SHA256} SHOW_PROGRESS) -file(ARCHIVE_EXTRACT INPUT "${CMAKE_BINARY_DIR}/ffmpeg.zip" DESTINATION "${FFMPEG_PREFIX}") - -set(FFMPEG_INCLUDE_DIR "${FFMPEG_PREFIX}/include") -set(FFMPEG_LIB_DIR "${FFMPEG_PREFIX}/lib") -set(FFMPEG_LIBRARIES - aom - crypto - freetype - mp3lame - opencore-amrnb - opencore-amrwb - openh264 - opus - sharpyuv - speex - srt - ssl - SvtAv1Dec - SvtAv1Enc - vo-amrwbenc - vpx - webp - webpdemux - webpmux - x264 - x265 - xml2 - z - zimg - avcodec - avdevice - avfilter - avformat - avutil - postproc - swresample - swscale) -add_library(ffmpeg STATIC IMPORTED) - -set(FFMPEG_MRI "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg.mri") -file(WRITE "${FFMPEG_MRI}" "CREATE libffmpeg.a\n") -message(STATUS "Checking for ffmpeg libraries") -foreach (FFMPEG_LIBRARY ${FFMPEG_LIBRARIES}) - set(LIB_PATH "${FFMPEG_LIB_DIR}/lib${FFMPEG_LIBRARY}.a") - if (NOT EXISTS ${LIB_PATH}) - message(STATUS " ${FFMPEG_LIBRARY} not found") - continue() - endif () - message(STATUS " Found ${FFMPEG_LIBRARY}") - file(APPEND "${FFMPEG_MRI}" "ADDLIB ${LIB_PATH}\n") -endforeach () -file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg.mri" "SAVE\nEND\n") - -add_custom_target(ffmpeg_custom - COMMAND ar -M < "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg.mri" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/libffmpeg.a -) -add_dependencies(ffmpeg ffmpeg_custom) -set_target_properties(ffmpeg PROPERTIES IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/libffmpeg.a") - -target_include_directories(ffmpeg INTERFACE "${FFMPEG_INCLUDE_DIR}") -target_link_options(ffmpeg INTERFACE "-Wl,-Bsymbolic") diff --git a/native/thirdparty/mpv.cmake b/native/thirdparty/mpv.cmake deleted file mode 100644 index 53612b2..0000000 --- a/native/thirdparty/mpv.cmake +++ /dev/null @@ -1,46 +0,0 @@ -set(MPV_URL "https://reposilite.silenium.dev/releases/dev/silenium/libs/mpv/mpv-natives-${NATIVE_PLATFORM}/${MPV_VERSION}/mpv-natives-${NATIVE_PLATFORM}-${MPV_VERSION}.zip") -set(MPV_URL_SHA256 "https://reposilite.silenium.dev/releases/dev/silenium/libs/mpv/mpv-natives-${NATIVE_PLATFORM}/${MPV_VERSION}/mpv-natives-${NATIVE_PLATFORM}-${MPV_VERSION}.zip.sha256") -set(MPV_PREFIX "${CMAKE_BINARY_DIR}/mpv") -message(STATUS "Downloading mpv from ${MPV_URL}") - -file(DOWNLOAD "${MPV_URL_SHA256}" "${CMAKE_BINARY_DIR}/mpv.zip.sha256") -file(READ "${CMAKE_BINARY_DIR}/mpv.zip.sha256" MPV_SHA256) -file(DOWNLOAD "${MPV_URL}" "${CMAKE_BINARY_DIR}/mpv.zip" EXPECTED_HASH SHA256=${MPV_SHA256} SHOW_PROGRESS) -file(ARCHIVE_EXTRACT INPUT "${CMAKE_BINARY_DIR}/mpv.zip" DESTINATION "${MPV_PREFIX}") - -set(MPV_INCLUDE_DIR "${MPV_PREFIX}/include") -set(MPV_LIB_DIR "${MPV_PREFIX}/lib") -set(MPV_LIBRARIES - mpv - ass - placebo) -add_library(mpv STATIC IMPORTED) - -set(MPV_MRI "${CMAKE_CURRENT_BINARY_DIR}/mpv.mri") -file(WRITE "${MPV_MRI}" "CREATE libmpv.a\n") -message(STATUS "Checking for mpv libraries") -foreach (MPV_LIBRARY ${MPV_LIBRARIES}) - set(LIB_PATH "${MPV_LIB_DIR}/lib${MPV_LIBRARY}.a") - if (NOT EXISTS ${LIB_PATH}) - message(STATUS " ${MPV_LIBRARY} not found") - continue() - endif () - message(STATUS " Found ${MPV_LIBRARY}") - file(APPEND "${MPV_MRI}" "ADDLIB ${LIB_PATH}\n") -endforeach () -file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/mpv.mri" "SAVE\nEND\n") - -add_custom_target(mpv_custom - COMMAND ar -M < "${CMAKE_CURRENT_BINARY_DIR}/mpv.mri" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/libmpv.a -) -add_dependencies(mpv mpv_custom) -set_target_properties(mpv PROPERTIES IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/libmpv.a") - -target_include_directories(mpv INTERFACE "${MPV_INCLUDE_DIR}") -target_link_options(mpv INTERFACE "-Wl,-Bsymbolic") - -find_package(PkgConfig REQUIRED) -pkg_check_modules(MPV_deps REQUIRED IMPORTED_TARGET libva libva-drm libdrm libva-glx libva-x11 libpipewire-0.3) -target_link_libraries(mpv INTERFACE PkgConfig::MPV_deps) From e1aef7d962373b3eb47aed3cb6f9f284ed2e14ab Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 15:34:12 +0200 Subject: [PATCH 03/78] chore: update dependencies --- .gitignore | 1 - build.gradle.kts | 32 ++---------------------- gradle.properties | 1 - gradle/libs.versions.toml | 29 ++++++++------------- gradle/wrapper/gradle-wrapper.properties | 2 +- 5 files changed, 13 insertions(+), 52 deletions(-) diff --git a/.gitignore b/.gitignore index f87be73..ce97ea7 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ texture.png va_surface.png textures/ - ### IntelliJ IDEA ### .idea/ *.iws diff --git a/build.gradle.kts b/build.gradle.kts index cec5232..68dad54 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.gradle.ext.ProjectSettings import org.jetbrains.gradle.ext.TaskTriggersConfig import org.jetbrains.kotlin.gradle.dsl.JvmTarget @@ -14,14 +13,9 @@ plugins { val deployNative = (findProperty("deploy.native") as String?)?.toBoolean() ?: true val deployKotlin = (findProperty("deploy.kotlin") as String?)?.toBoolean() ?: true -val skikoEGL = (findProperty("skiko.egl") as String?)?.toBoolean() ?: false dependencies { - // Note, if you develop a library, you should use compose.desktop.common. - // compose.desktop.currentOs should be used in launcher-sourceSet - // (in a separate module for demo project and in testMain). - // With compose.desktop.common you will also lose @Preview functionality - implementation(compose.desktop.currentOs) + implementation(compose.desktop.common) implementation(compose.material3) implementation(compose.materialIconsExtended) implementation("androidx.annotation:annotation-jvm:1.9.1") @@ -35,36 +29,14 @@ dependencies { implementation(project(":native")) } implementation(kotlin("reflect")) - if (skikoEGL) { - implementation(libs.bundles.skiko) { - version { - strictly(libs.skiko.awt.runtime.linux.x64.get().version!!) - } - } - } + testImplementation(compose.desktop.currentOs) testImplementation(compose.materialIconsExtended) testImplementation(libs.bundles.kotest) testImplementation(libs.mockk) testImplementation(libs.logback.classic) } -configurations.all { - resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) -} - -compose.desktop { - application { - mainClass = "MainKt" - - nativeDistributions { - targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) - packageName = "gl-demo" - packageVersion = "1.0.0" - } - } -} - val templateSrc = layout.projectDirectory.dir("src/main/templates") val templateDst = layout.buildDirectory.dir("generated/templates") val templateProps = mapOf( diff --git a/gradle.properties b/gradle.properties index 815b4ff..2ddb726 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,2 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 kotlin.code.style=official -skiko.egl=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2e0310c..569e0c4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,23 +1,22 @@ [versions] -kotlin = "2.1.0" +kotlin = "2.2.20" -kotlinx-coroutines = "1.10.1" -kotlinx-serialization = "1.8.0" +kotlinx-coroutines = "1.10.2" +kotlinx-serialization = "1.9.0" kotlinx-datetime = "0.6.1" -compose = "1.7.3" -compose-gl = "0.7.4" +compose = "1.10.0-alpha02" +compose-gl = "0.8.0" jni-utils = "0.1.6" -skiko = "0.8.19-egl" jna = "5.16.0" -slf4j = "2.0.16" -logback = "1.5.16" +slf4j = "2.0.17" +logback = "1.5.19" -kotest = "5.9.1" -mockk = "1.13.14" +kotest = "6.0.3" +mockk = "1.14.6" -idea-ext = "1.1.9" +idea-ext = "1.3" [libraries] kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } @@ -39,9 +38,6 @@ mpv-natives = { group = "dev.silenium.libs", name = "ffmpeg-natives", version = jni-utils = { group = "dev.silenium.libs.jni", name = "jni-utils", version.ref = "jni-utils" } jna = { group = "net.java.dev.jna", name = "jna", version.ref = "jna" } -skiko-awt = { group = "org.jetbrains.skiko", name = "skiko-awt", version.ref = "skiko" } -skiko-awt-runtime-linux-x64 = { group = "org.jetbrains.skiko", name = "skiko-awt-runtime-linux-x64", version.ref = "skiko" } - slf4j-api = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" } logback-classic = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logback" } @@ -78,8 +74,3 @@ kotest = [ "kotest-assertions-core", "kotest-assertions-json", ] - -skiko = [ - "skiko-awt", - "skiko-awt-runtime-linux-x64", -] diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1e2fbf0..d706aba 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From ee6435b693fb4adb2e523d2e7d70dfd8ba2f53b4 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 18:32:45 +0200 Subject: [PATCH 04/78] build: add fribidi, freetype and libdisplay-info as wraps --- native/subprojects/packagefiles/mpv/subprojects/freetype.wrap | 4 ++++ native/subprojects/packagefiles/mpv/subprojects/fribidi.wrap | 4 ++++ .../packagefiles/mpv/subprojects/libdisplay-info.wrap | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 native/subprojects/packagefiles/mpv/subprojects/freetype.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/fribidi.wrap create mode 100644 native/subprojects/packagefiles/mpv/subprojects/libdisplay-info.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/freetype.wrap b/native/subprojects/packagefiles/mpv/subprojects/freetype.wrap new file mode 100644 index 0000000..3cc45f4 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/freetype.wrap @@ -0,0 +1,4 @@ +[wrap-git] +revision = VER-2-14-1 +url = https://gitlab.freedesktop.org/freetype/freetype.git +depth = 1 diff --git a/native/subprojects/packagefiles/mpv/subprojects/fribidi.wrap b/native/subprojects/packagefiles/mpv/subprojects/fribidi.wrap new file mode 100644 index 0000000..c196eec --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/fribidi.wrap @@ -0,0 +1,4 @@ +[wrap-git] +revision = v1.0.16 +url = https://github.com/fribidi/fribidi.git +depth = 1 diff --git a/native/subprojects/packagefiles/mpv/subprojects/libdisplay-info.wrap b/native/subprojects/packagefiles/mpv/subprojects/libdisplay-info.wrap new file mode 100644 index 0000000..085f879 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/libdisplay-info.wrap @@ -0,0 +1,4 @@ +[wrap-git] +revision = 0.3.0 +url = https://gitlab.freedesktop.org/emersion/libdisplay-info.git +depth = 1 From b48b7aae9f9cb9516bf97d408921013627ae109e Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 18:34:49 +0200 Subject: [PATCH 05/78] build: update to java 17 --- build.gradle.kts | 4 ++-- native/build.gradle.kts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 68dad54..dabc986 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -69,9 +69,9 @@ tasks { kotlin { compilerOptions { freeCompilerArgs.add("-Xcontext-receivers") - jvmTarget = JvmTarget.JVM_11 + jvmTarget = JvmTarget.JVM_17 } - jvmToolchain(11) + jvmToolchain(17) } sourceSets.main { diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 58b6565..e5565fe 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -90,9 +90,9 @@ tasks.processResources { kotlin { compilerOptions { freeCompilerArgs.add("-Xcontext-receivers") - jvmTarget = JvmTarget.JVM_11 + jvmTarget = JvmTarget.JVM_17 } - jvmToolchain(11) + jvmToolchain(17) } java { From c171a526035b350b17f2e9c26a6bb1f3a9895d96 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 18:35:43 +0200 Subject: [PATCH 06/78] build: remove jvmToolchain() calls --- build.gradle.kts | 3 +-- native/build.gradle.kts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index dabc986..f842a8c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -69,9 +69,8 @@ tasks { kotlin { compilerOptions { freeCompilerArgs.add("-Xcontext-receivers") - jvmTarget = JvmTarget.JVM_17 + jvmTarget = JvmTarget.JVM_11 } - jvmToolchain(17) } sourceSets.main { diff --git a/native/build.gradle.kts b/native/build.gradle.kts index e5565fe..49156f0 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -90,9 +90,8 @@ tasks.processResources { kotlin { compilerOptions { freeCompilerArgs.add("-Xcontext-receivers") - jvmTarget = JvmTarget.JVM_17 + jvmTarget = JvmTarget.JVM_11 } - jvmToolchain(17) } java { From a7c7148d3307231cbf7ff8af482545facd76ba89 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 18:42:10 +0200 Subject: [PATCH 07/78] build: use fixed ffmpeg build --- native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap index 5c29551..c97d8ee 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap +++ b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap @@ -1,8 +1,8 @@ [wrap-file] directory = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0 -source_url = https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz -source_filename = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz -source_hash = 6e32fab45ad71841de03e796124b7c1c06a8b42a53860525a44aa007b28757a8 +source_url = https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2025-10-12-13-57/ffmpeg-n8.0-19-gdd00a614e1-linux64-gpl-shared-8.0.tar.xz +source_filename = ffmpeg-n8.0-19-gdd00a614e1-linux64-gpl-shared-8.0.tar.xz +source_hash = bc4f302c7d063434eb1089f34f004e2683a96eaea7b81012ba8d408c273c15e6 patch_directory = ffmpeg [provide] From bddfbcd3657ab1ce8a48345770602c0d19d8c1e2 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 18:44:35 +0200 Subject: [PATCH 08/78] build: use fixed ffmpeg build (2) --- native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap index c97d8ee..fbbe54c 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap +++ b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap @@ -1,5 +1,5 @@ [wrap-file] -directory = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0 +directory = ffmpeg-n8.0-19-gdd00a614e1-linux64-gpl-shared-8.0 source_url = https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2025-10-12-13-57/ffmpeg-n8.0-19-gdd00a614e1-linux64-gpl-shared-8.0.tar.xz source_filename = ffmpeg-n8.0-19-gdd00a614e1-linux64-gpl-shared-8.0.tar.xz source_hash = bc4f302c7d063434eb1089f34f004e2683a96eaea7b81012ba8d408c273c15e6 From 8de2099b92c51ea53fe2006380912cbceb25d80d Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 18:53:09 +0200 Subject: [PATCH 09/78] build: add fmt wrap --- native/subprojects/packagefiles/mpv/subprojects/fmt.wrap | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 native/subprojects/packagefiles/mpv/subprojects/fmt.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/fmt.wrap b/native/subprojects/packagefiles/mpv/subprojects/fmt.wrap new file mode 100644 index 0000000..02c3f4b --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/fmt.wrap @@ -0,0 +1,8 @@ +[wrap-git] +url = https://github.com/fmtlib/fmt.git +revision = 12.0.0 +depth = 1 +method = cmake + +[provide] +fmt = libfmt.a From e89669cbee981fe2e1220d8ed6de5b5830b7ccef Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 18:56:04 +0200 Subject: [PATCH 10/78] build: add fmt wrap --- native/subprojects/packagefiles/mpv/subprojects/fmt.wrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/subprojects/packagefiles/mpv/subprojects/fmt.wrap b/native/subprojects/packagefiles/mpv/subprojects/fmt.wrap index 02c3f4b..5c1f6dd 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/fmt.wrap +++ b/native/subprojects/packagefiles/mpv/subprojects/fmt.wrap @@ -5,4 +5,4 @@ depth = 1 method = cmake [provide] -fmt = libfmt.a +fmt = fmt_dep From e7ed9b2557658f1f8ea2e63d4c5220f259ff67ea Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:03:12 +0200 Subject: [PATCH 11/78] fix: link with mpv --- native/src/meson.build | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/native/src/meson.build b/native/src/meson.build index 25e9831..9eef248 100644 --- a/native/src/meson.build +++ b/native/src/meson.build @@ -1,4 +1,4 @@ -mpv_dep = mpv.get_variable('libmpv') +mpv_dep = mpv.get_variable('libmpv_dep') jni = dependency('jni') egl = dependency('egl') glx = dependency('glx') @@ -9,6 +9,5 @@ shared_library('compose-av', 'helper/errors.hpp', 'helper/errors.cpp', 'mpv/MPV.cpp', - dependencies : [jni, egl, glx, x11], - link_with : [mpv_dep], + dependencies : [jni, egl, glx, x11, mpv_dep], ) From c7cfc666eaf964537f78347d443c1001d2442021 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:06:27 +0200 Subject: [PATCH 12/78] build: try forcing static libs --- native/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 49156f0..14c4688 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -45,6 +45,10 @@ val generateMakefile = tasks.register("generateMakefile") { mesonExe, "setup", targetDir.absolutePath, "--force-fallback-for=ffmpeg,libjpeg,openal,libass,harfbuzz,expat,libplacebo,libpng,zlib", + "-Ddefault_library=static", + "-Dprefer_static=true", + "-Ddrm=enabled", + "-Dopenal=enabled", ) inputs.file(layout.projectDirectory.file("meson.build")) From 6f4810dfe9de6b28919558e031bd0fded4c0caaf Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:07:00 +0200 Subject: [PATCH 13/78] build: try forcing static libs --- native/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 14c4688..9a592ef 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -44,11 +44,11 @@ val generateMakefile = tasks.register("generateMakefile") { commandLine( mesonExe, "setup", targetDir.absolutePath, - "--force-fallback-for=ffmpeg,libjpeg,openal,libass,harfbuzz,expat,libplacebo,libpng,zlib", + "--force-fallback-for=mpv,ffmpeg,libjpeg,openal,libass,harfbuzz,expat,libplacebo,libpng,zlib", "-Ddefault_library=static", "-Dprefer_static=true", - "-Ddrm=enabled", - "-Dopenal=enabled", + "-Dmpv:drm=enabled", + "-Dmpv:openal=enabled", ) inputs.file(layout.projectDirectory.file("meson.build")) From dfa3e66caf4aaca30a17042ac3d34c84a651e3ef Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:12:05 +0200 Subject: [PATCH 14/78] build: add uchardet wrap --- .../packagefiles/mpv/subprojects/libuchardet.wrap | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 native/subprojects/packagefiles/mpv/subprojects/libuchardet.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/libuchardet.wrap b/native/subprojects/packagefiles/mpv/subprojects/libuchardet.wrap new file mode 100644 index 0000000..d81e4b7 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/libuchardet.wrap @@ -0,0 +1,7 @@ +[wrap-git] +revision = 0.0.8 +url = https://gitlab.freedesktop.org/uchardet/uchardet.git +depth = 1 + +[provide] +uchardet = libuchardet_dep From 0eb3876cde3f161f51a002be6a99d3fd12fe664b Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:13:19 +0200 Subject: [PATCH 15/78] build: try fixing freetype wrap --- mpv/build.sh | 2 +- native/subprojects/packagefiles/mpv/subprojects/freetype.wrap | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mpv/build.sh b/mpv/build.sh index b182e55..b906664 100644 --- a/mpv/build.sh +++ b/mpv/build.sh @@ -5,7 +5,7 @@ set -eo pipefail sudo apt-get update sudo apt-get upgrade -y sudo apt-get install -y build-essential git pkg-config cmake nasm clang curl python3-pip python3-wheel ninja-build -sudo apt-get install -y libfontconfig-dev libva-dev libdrm-dev libuchardet-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev +sudo apt-get install -y libfontconfig-dev libva-dev libdrm-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev sudo pip3 install meson diff --git a/native/subprojects/packagefiles/mpv/subprojects/freetype.wrap b/native/subprojects/packagefiles/mpv/subprojects/freetype.wrap index 3cc45f4..938af11 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/freetype.wrap +++ b/native/subprojects/packagefiles/mpv/subprojects/freetype.wrap @@ -2,3 +2,6 @@ revision = VER-2-14-1 url = https://gitlab.freedesktop.org/freetype/freetype.git depth = 1 + +[provide] +dependency_names = freetype2 From 4fcba027900f2580b5a1965a16c9f68921f58658 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:15:50 +0200 Subject: [PATCH 16/78] build: add fontconfig wrap --- .../packagefiles/mpv/subprojects/libfontconfig.wrap | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 native/subprojects/packagefiles/mpv/subprojects/libfontconfig.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/libfontconfig.wrap b/native/subprojects/packagefiles/mpv/subprojects/libfontconfig.wrap new file mode 100644 index 0000000..9061598 --- /dev/null +++ b/native/subprojects/packagefiles/mpv/subprojects/libfontconfig.wrap @@ -0,0 +1,7 @@ +[wrap-git] +revision = 2.17.1 +url = https://gitlab.freedesktop.org/fontconfig/fontconfig.git +depth = 1 + +[provide] +dependency_names = fontconfig From 58662efcbd8be064d92ee5f356fff4dd25c5d168 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:17:58 +0200 Subject: [PATCH 17/78] build: try fixing fontconfig wrap --- native/subprojects/packagefiles/mpv/subprojects/libass.wrap | 1 + .../{ => packagefiles/libass/subprojects}/libfontconfig.wrap | 0 2 files changed, 1 insertion(+) rename native/subprojects/packagefiles/mpv/subprojects/{ => packagefiles/libass/subprojects}/libfontconfig.wrap (100%) diff --git a/native/subprojects/packagefiles/mpv/subprojects/libass.wrap b/native/subprojects/packagefiles/mpv/subprojects/libass.wrap index 580d48a..f56c044 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/libass.wrap +++ b/native/subprojects/packagefiles/mpv/subprojects/libass.wrap @@ -2,3 +2,4 @@ revision = master url = https://github.com/libass/libass depth = 1 +patch_directory = libass diff --git a/native/subprojects/packagefiles/mpv/subprojects/libfontconfig.wrap b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/libfontconfig.wrap rename to native/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap From 7c45186699966d1c1e058dd6e2c835794d73f93b Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:21:43 +0200 Subject: [PATCH 18/78] build: try fixing fontconfig wrap --- .../mpv/subprojects/{freetype.wrap => freetype2.wrap} | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename native/subprojects/packagefiles/mpv/subprojects/{freetype.wrap => freetype2.wrap} (70%) diff --git a/native/subprojects/packagefiles/mpv/subprojects/freetype.wrap b/native/subprojects/packagefiles/mpv/subprojects/freetype2.wrap similarity index 70% rename from native/subprojects/packagefiles/mpv/subprojects/freetype.wrap rename to native/subprojects/packagefiles/mpv/subprojects/freetype2.wrap index 938af11..4fb98f8 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/freetype.wrap +++ b/native/subprojects/packagefiles/mpv/subprojects/freetype2.wrap @@ -1,5 +1,6 @@ [wrap-git] -revision = VER-2-14-1 +directory = freetype-2.13.3 +revision = VER-2-13-3 url = https://gitlab.freedesktop.org/freetype/freetype.git depth = 1 From f87a8d4a8969dce5f457abcdf5e4b18a0e4fd4ba Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:21:55 +0200 Subject: [PATCH 19/78] build: try fixing fontconfig wrap --- native/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 9a592ef..9e3eb6f 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -44,7 +44,7 @@ val generateMakefile = tasks.register("generateMakefile") { commandLine( mesonExe, "setup", targetDir.absolutePath, - "--force-fallback-for=mpv,ffmpeg,libjpeg,openal,libass,harfbuzz,expat,libplacebo,libpng,zlib", + "--force-fallback-for=mpv,ffmpeg,libjpeg,openal,libass,harfbuzz,expat,libplacebo,libpng,zlib,fontconfig", "-Ddefault_library=static", "-Dprefer_static=true", "-Dmpv:drm=enabled", From 81e863b2026a0f3ef9e9ac1e10e1a6f20df9a25e Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:30:09 +0200 Subject: [PATCH 20/78] build: try fixing fontconfig wrap --- .../packagefiles/libass/subprojects/libfontconfig.wrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap index 9061598..04fbbb7 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap +++ b/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap @@ -4,4 +4,4 @@ url = https://gitlab.freedesktop.org/fontconfig/fontconfig.git depth = 1 [provide] -dependency_names = fontconfig +fontconfig = fontconfig_dep From c05d8b953f6b2d1a2fb0d3186b2be6950839242f Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 19:31:48 +0200 Subject: [PATCH 21/78] build: disable vulkan support for mpv --- native/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 9e3eb6f..632833a 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -49,6 +49,7 @@ val generateMakefile = tasks.register("generateMakefile") { "-Dprefer_static=true", "-Dmpv:drm=enabled", "-Dmpv:openal=enabled", + "-Dmpv:vulkan=disabled", ) inputs.file(layout.projectDirectory.file("meson.build")) From 6ed390041f2a9cadd723f272e67cfc05febecfbf Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 21:26:44 +0200 Subject: [PATCH 22/78] build: static link against libgcc and libstdc++, set forcefallback --- native/build.gradle.kts | 2 +- native/meson.build | 8 +++++++- native/src/meson.build | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 632833a..7df3840 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -44,7 +44,7 @@ val generateMakefile = tasks.register("generateMakefile") { commandLine( mesonExe, "setup", targetDir.absolutePath, - "--force-fallback-for=mpv,ffmpeg,libjpeg,openal,libass,harfbuzz,expat,libplacebo,libpng,zlib,fontconfig", + "-Dwrap_mode=forcefallback", "-Ddefault_library=static", "-Dprefer_static=true", "-Dmpv:drm=enabled", diff --git a/native/meson.build b/native/meson.build index cc41a75..b76e29b 100644 --- a/native/meson.build +++ b/native/meson.build @@ -2,16 +2,22 @@ project('compose-av', 'cpp', 'java', default_options : { 'cpp_std' : 'c++20', + 'wrap_mode' : 'forcefallback', } ) add_global_arguments('-fPIC', language : 'c') add_global_arguments('-fPIC', language : 'cpp') +add_global_link_arguments( + '-static-libgcc', + '-static-libstdc++', + language : 'cpp', +) mpv = subproject('mpv', default_options : { 'libmpv' : true, 'drm' : 'enabled', 'openal' : 'enabled', - 'force_fallback_for' : ['expat', 'ffmpeg', 'libjpeg', 'libass', 'libplacebo', 'libpng', 'openal', 'zlib'], + 'wrap_mode' : 'forcefallback', 'default_library' : 'static', 'prefer_static' : true, } diff --git a/native/src/meson.build b/native/src/meson.build index 9eef248..9670be9 100644 --- a/native/src/meson.build +++ b/native/src/meson.build @@ -9,5 +9,5 @@ shared_library('compose-av', 'helper/errors.hpp', 'helper/errors.cpp', 'mpv/MPV.cpp', - dependencies : [jni, egl, glx, x11, mpv_dep], + dependencies : [jni, egl, glx, x11, mpv_dep], ) From dc1a4aa5a0d9e40dda4a3fcff04fbd7b37f41a58 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 21:26:52 +0200 Subject: [PATCH 23/78] ci: update ci setup --- .github/workflows/build.yaml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3ce3379..7bbcf39 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,10 +20,23 @@ jobs: runs-on: ubuntu-24.04 steps: - shell: bash - name: "Install mpv" + name: "Setup build environment" run: | - sudo apt-get update -y - sudo apt-get install -y libmpv-dev libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libavdevice-dev libavfilter-dev libswresample-dev libpostproc-dev libpipewire-0.3-dev + sudo apt-get update + sudo apt-get upgrade -y + sudo apt-get install -y build-essential git pkg-config cmake nasm clang curl python3-pip python3-wheel ninja-build + sudo apt-get install -y libfontconfig-dev libva-dev libdrm-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev + + sudo pip3 install meson + + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sudo -i sh -s -- -y + sudo -i rustup default stable + sudo -i cargo install cargo-c + + sudo rm -rf dovi_tool && git clone -b 2.3.1 https://github.com/quietvoid/dovi_tool.git + pushd dovi_tool/dolby_vision + sudo -i bash -c "cd $(pwd) && cargo cinstall --release --prefix /usr" + popd - uses: silenium-dev/actions/jni-natives/ubuntu@main with: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} From c2a186959ace40301f3fd71227330340f34e5965 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 21:29:02 +0200 Subject: [PATCH 24/78] ci: remove libfontconfig-dev and uninstall libz3-dev --- .github/workflows/build.yaml | 3 ++- mpv/build.sh | 41 ------------------------------------ 2 files changed, 2 insertions(+), 42 deletions(-) delete mode 100644 mpv/build.sh diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7bbcf39..7d03a18 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -25,7 +25,8 @@ jobs: sudo apt-get update sudo apt-get upgrade -y sudo apt-get install -y build-essential git pkg-config cmake nasm clang curl python3-pip python3-wheel ninja-build - sudo apt-get install -y libfontconfig-dev libva-dev libdrm-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev + sudo apt-get install -y libva-dev libdrm-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev + sudo apt-get remove -y libz3-dev sudo pip3 install meson diff --git a/mpv/build.sh b/mpv/build.sh deleted file mode 100644 index b906664..0000000 --- a/mpv/build.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env bash - -set -eo pipefail - -sudo apt-get update -sudo apt-get upgrade -y -sudo apt-get install -y build-essential git pkg-config cmake nasm clang curl python3-pip python3-wheel ninja-build -sudo apt-get install -y libfontconfig-dev libva-dev libdrm-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev - -sudo pip3 install meson - -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sudo -i sh -s -- -y -sudo -i rustup default stable -sudo -i cargo install cargo-c - -sudo rm -rf dovi_tool && git clone -b 2.3.1 https://github.com/quietvoid/dovi_tool.git -pushd dovi_tool/dolby_vision -sudo -i bash -c "cd $(pwd) && cargo cinstall --release --prefix /usr" -popd - -rm -rf mpv && git clone https://github.com/mpv-player/mpv.git --depth=1 mpv -pushd mpv - -mkdir -p subprojects -meson wrap update-db -meson wrap install expat -meson wrap install harfbuzz -meson wrap install libpng -meson wrap install zlib -meson wrap install libjpeg-turbo -meson wrap install openal-soft - -git clone -b VER-2-14-1 https://gitlab.freedesktop.org/freetype/freetype.git --depth=1 --recursive subprojects/freetype2 -git clone -b v1.0.16 https://github.com/fribidi/fribidi.git --depth=1 --recursive subprojects/fribidi -git clone -b 0.3.0 https://gitlab.freedesktop.org/emersion/libdisplay-info.git --depth=1 subprojects/libdisplay-info -cp -r ../subprojects/* subprojects/ - -export CFLAGS="-fPIC" -export CXXFLAGS="-fPIC" -meson setup build -Dlibmpv=true -Ddrm=enabled -Ddefault_library=static -Dopenal=enabled -Dprefer_static=true --force-fallback-for=ffmpeg,libjpeg,openal -meson compile -C build From c179bd285c8f6b53fed069f93a66f8bc58b6fa72 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 21:30:27 +0200 Subject: [PATCH 25/78] ci: update java to 17 --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7d03a18..d842cc4 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -46,7 +46,7 @@ jobs: repo-username: ${{ secrets.REPOSILITE_USERNAME }} repo-password: ${{ secrets.REPOSILITE_PASSWORD }} tests: true - java-version: 11 + java-version: 17 platform: ${{ github.job }} kotlin: runs-on: ubuntu-24.04 @@ -59,4 +59,4 @@ jobs: repo-username: ${{ secrets.REPOSILITE_USERNAME }} repo-password: ${{ secrets.REPOSILITE_PASSWORD }} tests: false - java-version: 11 + java-version: 17 From d24567e3a2c6dcf4832cd4a5ea9387cb5097e524 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 21:30:54 +0200 Subject: [PATCH 26/78] ci: remove upgrade --- .github/workflows/build.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d842cc4..80387f3 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -23,7 +23,6 @@ jobs: name: "Setup build environment" run: | sudo apt-get update - sudo apt-get upgrade -y sudo apt-get install -y build-essential git pkg-config cmake nasm clang curl python3-pip python3-wheel ninja-build sudo apt-get install -y libva-dev libdrm-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev sudo apt-get remove -y libz3-dev From 6db879fda3b4c76342bd8e1f4d663b1aed19ec5d Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 21:39:25 +0200 Subject: [PATCH 27/78] build: fix issue with gradle java and kotlin target versions --- build.gradle.kts | 3 +++ native/build.gradle.kts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index f842a8c..fc6bb7b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -80,6 +80,9 @@ sourceSets.main { } java { + sourceCompatibility = kotlin.compilerOptions.jvmTarget.map { JavaVersion.toVersion(it.target) }.get() + targetCompatibility = sourceCompatibility + withSourcesJar() withJavadocJar() } diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 7df3840..109cb1c 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -100,6 +100,9 @@ kotlin { } java { + sourceCompatibility = kotlin.compilerOptions.jvmTarget.map { JavaVersion.toVersion(it.target) }.get() + targetCompatibility = sourceCompatibility + withSourcesJar() withJavadocJar() } From 6a390828c65f7ed9d4614d5b838bff8e205fdb0c Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Sun, 12 Oct 2025 21:41:24 +0200 Subject: [PATCH 28/78] ci: try fixing permissions issue --- .github/workflows/build.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 80387f3..1404101 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -22,6 +22,7 @@ jobs: - shell: bash name: "Setup build environment" run: | + sudo rm -rf dovi_tool/ || true sudo apt-get update sudo apt-get install -y build-essential git pkg-config cmake nasm clang curl python3-pip python3-wheel ninja-build sudo apt-get install -y libva-dev libdrm-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev @@ -37,6 +38,7 @@ jobs: pushd dovi_tool/dolby_vision sudo -i bash -c "cd $(pwd) && cargo cinstall --release --prefix /usr" popd + sudo rm -rf dovi_tool/ - uses: silenium-dev/actions/jni-natives/ubuntu@main with: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} From 14ba4977cc28cfa5bb8556f272fe386b1cdcdb16 Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Mon, 13 Oct 2025 22:14:33 +0200 Subject: [PATCH 29/78] feat: start working on rewrite against new compose-gl --- build.gradle.kts | 2 +- gradle/libs.versions.toml | 4 +- native/.gitignore | 2 +- native/src/mpv/MPV.cpp | 1 + .../multimedia/compose/player/VideoPlayer.kt | 19 +-- .../multimedia/compose/player/VideoSurface.kt | 108 +++++++++--------- .../compose/player/VideoSurfaceEvents.kt | 7 +- .../compose/player/VideoSurfaceStats.kt | 6 +- .../player/VideoSurfaceWithControls.kt | 2 + .../dev/silenium/multimedia/compose/Main.kt | 9 +- .../silenium/multimedia/simple/VideoPlayer.kt | 9 +- 11 files changed, 88 insertions(+), 81 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index fc6bb7b..0f5dcec 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -69,7 +69,7 @@ tasks { kotlin { compilerOptions { freeCompilerArgs.add("-Xcontext-receivers") - jvmTarget = JvmTarget.JVM_11 + jvmTarget = JvmTarget.JVM_17 } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 569e0c4..e0fd448 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ kotlinx-serialization = "1.9.0" kotlinx-datetime = "0.6.1" compose = "1.10.0-alpha02" -compose-gl = "0.8.0" +compose-gl = "0.9.0" jni-utils = "0.1.6" jna = "5.16.0" @@ -32,7 +32,7 @@ kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx- kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinx-datetime" } compose-gl = { group = "dev.silenium.compose.gl", name = "compose-gl", version.ref = "compose-gl" } -compose-gl-natives = { group = "dev.silenium.compose.gl", name = "compose-gl-natives-linux-x86_64", version.ref = "compose-gl" } +compose-gl-natives = { group = "dev.silenium.compose.gl", name = "compose-gl-natives-all", version.ref = "compose-gl" } ffmpeg-natives = { group = "dev.silenium.libs", name = "ffmpeg-natives", version = "7.1+0.2.0" } mpv-natives = { group = "dev.silenium.libs", name = "ffmpeg-natives", version = "0.39.0+0.1.2" } jni-utils = { group = "dev.silenium.libs.jni", name = "jni-utils", version.ref = "jni-utils" } diff --git a/native/.gitignore b/native/.gitignore index 6ca1186..0168cd3 100644 --- a/native/.gitignore +++ b/native/.gitignore @@ -2,7 +2,7 @@ *.iml cmake-build-*/ /subprojects/* -!/subprojects/*.wrap +!/subprojects/mpv.wrap !/subprojects/packagefiles !/subprojects/packagefiles/* buildDir/ diff --git a/native/src/mpv/MPV.cpp b/native/src/mpv/MPV.cpp index 1b002c3..5b2f3ed 100644 --- a/native/src/mpv/MPV.cpp +++ b/native/src/mpv/MPV.cpp @@ -220,6 +220,7 @@ void handle_mpv_events(void *ctx) { extern "C" { // Client JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createN(JNIEnv *env, jobject thiz) { + setlocale(LC_NUMERIC, "C"); const auto handle = mpv_create(); if (handle == nullptr) { return mpvResultFailure(env, "mpv_create", MPV_ERROR_NOMEM); diff --git a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayer.kt b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayer.kt index 1d7dcc5..e4d6fe6 100644 --- a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayer.kt +++ b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayer.kt @@ -1,9 +1,8 @@ package dev.silenium.multimedia.compose.player import androidx.compose.runtime.* -import dev.silenium.compose.gl.surface.GLDrawScope -import dev.silenium.compose.gl.surface.GLSurface -import dev.silenium.compose.gl.surface.GLSurfaceState +import dev.silenium.compose.gl.canvas.GLCanvasState +import dev.silenium.compose.gl.canvas.GLDrawScope import dev.silenium.multimedia.compose.util.deferredFlowStateOf import dev.silenium.multimedia.compose.util.mapState import dev.silenium.multimedia.core.annotation.InternalMultimediaApi @@ -19,7 +18,6 @@ class VideoPlayer(hwdec: Boolean = false) : AutoCloseable { val config: Config = Config() - internal var surface: GLSurface? = null private var initialized = false @PublishedApi @@ -68,21 +66,21 @@ class VideoPlayer(hwdec: Boolean = false) : AutoCloseable { return mpv } - private fun initialize(state: GLSurfaceState) { + private fun initialize(state: GLCanvasState, onInitialized: () -> Unit) { if (initialized) return render = mpv.createRender(advancedControl = true, state::requestUpdate) initialized = true + onInitialized() } - fun onRender(scope: GLDrawScope, state: GLSurfaceState) { - initialize(state) + fun onRender(scope: GLDrawScope, state: GLCanvasState, onInitialized: () -> Unit = {}) { + initialize(state, onInitialized) // TODO: fix render block if screen is disconnected and reconnected glClearColor(0f, 0f, 0f, 0f) glClear(GL_COLOR_BUFFER_BIT) render?.render(scope.fbo)?.getOrThrow() - scope.redrawAfter(null) } override fun close() { @@ -90,6 +88,11 @@ class VideoPlayer(hwdec: Boolean = false) : AutoCloseable { mpv.close() } + fun onCanvasDispose() { + render?.close() + render = null + } + companion object { private val defaultOptions = mapOf( "terminal" to "yes", diff --git a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurface.kt b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurface.kt index 428f50f..6a0071b 100644 --- a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurface.kt +++ b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurface.kt @@ -5,49 +5,50 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import dev.silenium.compose.gl.surface.* -import dev.silenium.multimedia.core.annotation.InternalMultimediaApi +import dev.silenium.compose.gl.canvas.GLCanvas +import dev.silenium.compose.gl.canvas.rememberGLCanvasState import org.jetbrains.skia.Paint -@Composable -private fun createGLSurface( - player: VideoPlayer, - surfaceState: GLSurfaceState = rememberGLSurfaceState(), - onInitialized: () -> Unit = {}, -): GLSurface { - var initialized by remember { mutableStateOf(false) } - - @OptIn(InternalMultimediaApi::class) - val dwidth by player.property("dwidth") - - @OptIn(InternalMultimediaApi::class) - val dheight by player.property("dheight") - val fboSizeOverride = remember(player.config.pixelPerfect, dwidth, dheight) { - if (!player.config.pixelPerfect) return@remember null - dwidth?.let { w -> - dheight?.let { h -> - FBOSizeOverride(w.toInt(), h.toInt()) - } - } - } - return rememberGLSurface( - surfaceState, - presentMode = GLSurface.PresentMode.MAILBOX, - swapChainSize = 3, - fboSizeOverride = fboSizeOverride, - draw = { - player.onRender(this, surfaceState) - if (!initialized) { - initialized = true - onInitialized() - } - } - ) -} +//@Composable +//private fun createGLSurface( +// player: VideoPlayer, +// surfaceState: GLSurfaceState = rememberGLSurfaceState(), +// onInitialized: () -> Unit = {}, +//): GLSurface { +// var initialized by remember { mutableStateOf(false) } +// +// @OptIn(InternalMultimediaApi::class) +// val dwidth by player.property("dwidth") +// +// @OptIn(InternalMultimediaApi::class) +// val dheight by player.property("dheight") +// val fboSizeOverride = remember(player.config.pixelPerfect, dwidth, dheight) { +// if (!player.config.pixelPerfect) return@remember null +// dwidth?.let { w -> +// dheight?.let { h -> +// FBOSizeOverride(w.toInt(), h.toInt()) +// } +// } +// } +// return rememberGLSurface( +// surfaceState, +// presentMode = GLSurface.PresentMode.MAILBOX, +// swapChainSize = 3, +// fboSizeOverride = fboSizeOverride, +// draw = { +// player.onRender(this, surfaceState) +// if (!initialized) { +// initialized = true +// onInitialized() +// } +// } +// ) +//} @Composable fun VideoSurface( @@ -55,14 +56,17 @@ fun VideoSurface( showStats: Boolean = false, modifier: Modifier = Modifier, paint: Paint = Paint(), + onInitialized: () -> Unit = {}, ) { - val surfaceState = rememberGLSurfaceState() + val surfaceState = rememberGLCanvasState() BoxWithConstraints(modifier = modifier) { - GLSurfaceView( - surface = player.surface!!, + GLCanvas( modifier = Modifier.matchParentSize(), - paint = paint, - ) + state = surfaceState, +// onDispose = player::onCanvasDispose, + ) { + player.onRender(this, surfaceState, onInitialized) + } if (showStats) { Surface( modifier = Modifier.padding(6.dp).width(360.dp), @@ -77,19 +81,17 @@ fun VideoSurface( @Composable fun rememberVideoPlayer( - surfaceState: GLSurfaceState = rememberGLSurfaceState(), hwdec: Boolean = true, - onInitialized: () -> Unit = {}, ): VideoPlayer { val player = remember { VideoPlayer(hwdec) } - val surface = createGLSurface(player, surfaceState, onInitialized) +// val surface = createGLSurface(player, surfaceState, onInitialized) - DisposableEffect(player, surface) { - player.surface = surface - onDispose { - player.surface = null - player.close() - } - } +// DisposableEffect(player, surface) { +// player.surface = surface +// onDispose { +// player.surface = null +// player.close() +// } +// } return player } diff --git a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceEvents.kt b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceEvents.kt index bf10d46..d385653 100644 --- a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceEvents.kt +++ b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceEvents.kt @@ -13,11 +13,12 @@ import dev.silenium.multimedia.core.annotation.InternalMultimediaApi import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import kotlinx.datetime.Clock -import kotlinx.datetime.Instant +import kotlin.time.Clock import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.ExperimentalTime +import kotlin.time.Instant -@OptIn(ExperimentalComposeUiApi::class, InternalMultimediaApi::class) +@OptIn(ExperimentalComposeUiApi::class, InternalMultimediaApi::class, ExperimentalTime::class) @Composable fun Modifier.handleInputs(player: VideoPlayer, focusRequester: FocusRequester? = null): Modifier { val coroutineScope = rememberCoroutineScope() diff --git a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceStats.kt b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceStats.kt index 57990eb..523cd5c 100644 --- a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceStats.kt +++ b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceStats.kt @@ -9,13 +9,13 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp -import dev.silenium.compose.gl.surface.GLSurfaceState -import dev.silenium.compose.gl.surface.Stats +import dev.silenium.compose.gl.canvas.GLCanvasState +import dev.silenium.compose.gl.canvas.Stats import dev.silenium.multimedia.compose.format.format import dev.silenium.multimedia.compose.util.deferredFlowStateOf @Composable -fun VideoSurfaceStats(player: VideoPlayer, state: GLSurfaceState, textColor: Color = Color.White) { +fun VideoSurfaceStats(player: VideoPlayer, state: GLCanvasState, textColor: Color = Color.White) { Column(modifier = Modifier.padding(6.dp)) { val position by deferredFlowStateOf(player::position) val duration by deferredFlowStateOf(player::duration) diff --git a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceWithControls.kt b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceWithControls.kt index f237708..4dbb176 100644 --- a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceWithControls.kt +++ b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoSurfaceWithControls.kt @@ -15,6 +15,7 @@ fun VideoSurfaceWithControls( showStats: Boolean = false, controlFocusRequester: FocusRequester? = null, paint: Paint = Paint(), + onInitialized: () -> Unit = {}, ) { BoxWithConstraints(modifier) { VideoSurface( @@ -26,6 +27,7 @@ fun VideoSurfaceWithControls( maxHeight = maxHeight, ), paint = paint, + onInitialized = onInitialized, ) VideoSurfaceControls(player, Modifier.matchParentSize(), controlFocusRequester) } diff --git a/src/test/kotlin/dev/silenium/multimedia/compose/Main.kt b/src/test/kotlin/dev/silenium/multimedia/compose/Main.kt index e20ec19..05a65cf 100644 --- a/src/test/kotlin/dev/silenium/multimedia/compose/Main.kt +++ b/src/test/kotlin/dev/silenium/multimedia/compose/Main.kt @@ -40,11 +40,7 @@ fun App() { } var ready by remember { mutableStateOf(false) } val coroutineScope = rememberCoroutineScope() - val player = rememberVideoPlayer( - onInitialized = { - ready = true - }, - ) + val player = rememberVideoPlayer() DisposableEffect(Unit) { onDispose { ready = false @@ -94,6 +90,9 @@ fun App() { modifier = Modifier.fillParentMaxSize().animateItem(), showStats = true, controlFocusRequester = remember { FocusRequester() }, + onInitialized = { + ready = true + }, ) DisposableEffect(Unit) { coroutineScope.launch { diff --git a/src/test/kotlin/dev/silenium/multimedia/simple/VideoPlayer.kt b/src/test/kotlin/dev/silenium/multimedia/simple/VideoPlayer.kt index 272feb3..1490934 100644 --- a/src/test/kotlin/dev/silenium/multimedia/simple/VideoPlayer.kt +++ b/src/test/kotlin/dev/silenium/multimedia/simple/VideoPlayer.kt @@ -2,9 +2,8 @@ package dev.silenium.multimedia.simple import androidx.compose.runtime.* import androidx.compose.ui.Modifier -import dev.silenium.compose.gl.surface.GLSurface -import dev.silenium.compose.gl.surface.GLSurfaceView -import dev.silenium.compose.gl.surface.rememberGLSurfaceState +import dev.silenium.compose.gl.canvas.GLCanvas +import dev.silenium.compose.gl.canvas.rememberGLCanvasState import dev.silenium.multimedia.core.mpv.MPV import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -42,8 +41,8 @@ fun VideoPlayer(file: Path, suspend: Boolean = false, modifier: Modifier = Modif mpv.commandAsync("set", "pause", if (suspend) "yes" else "no").getOrThrow() } } - val state = rememberGLSurfaceState() - GLSurfaceView(state, modifier = modifier, presentMode = GLSurface.PresentMode.MAILBOX, swapChainSize = 3) { + val state = rememberGLCanvasState() + GLCanvas(state, modifier = modifier) { if (!ready) { render = mpv.createRender(advancedControl = true, state::requestUpdate) ready = true From 6322485a9d09ffa77d09bcb558e31d8e06b993fc Mon Sep 17 00:00:00 2001 From: Silas Della Contrada Date: Mon, 13 Oct 2025 23:12:01 +0200 Subject: [PATCH 30/78] ci: disable tests in linux-x86_64 build Signed-off-by: Silas Della Contrada --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1404101..585892b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -46,7 +46,7 @@ jobs: release-repo-url: "https://reposilite.silenium.dev/releases" repo-username: ${{ secrets.REPOSILITE_USERNAME }} repo-password: ${{ secrets.REPOSILITE_PASSWORD }} - tests: true + tests: false java-version: 17 platform: ${{ github.job }} kotlin: From b33ae8edf39cfa272680ca4a6e7000d0a0ff2b19 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Mon, 23 Feb 2026 14:54:27 +0100 Subject: [PATCH 31/78] chore: update dependencies --- build.gradle.kts | 10 ++++----- gradle/libs.versions.toml | 27 ++++++++++++++---------- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0f5dcec..420d0cd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,10 +15,10 @@ val deployNative = (findProperty("deploy.native") as String?)?.toBoolean() ?: tr val deployKotlin = (findProperty("deploy.kotlin") as String?)?.toBoolean() ?: true dependencies { - implementation(compose.desktop.common) - implementation(compose.material3) - implementation(compose.materialIconsExtended) - implementation("androidx.annotation:annotation-jvm:1.9.1") + implementation(libs.compose.desktop.common) + implementation(libs.compose.material3) + implementation(libs.compose.material.icons.extended) + implementation(libs.androidx.annotation) implementation(libs.compose.gl) implementation(libs.compose.gl.natives) implementation(libs.jni.utils) @@ -31,7 +31,7 @@ dependencies { implementation(kotlin("reflect")) testImplementation(compose.desktop.currentOs) - testImplementation(compose.materialIconsExtended) + testImplementation(libs.compose.material.icons.extended) testImplementation(libs.bundles.kotest) testImplementation(libs.mockk) testImplementation(libs.logback.classic) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e0fd448..b9feb3e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,22 +1,22 @@ [versions] -kotlin = "2.2.20" +kotlin = "2.3.10" kotlinx-coroutines = "1.10.2" -kotlinx-serialization = "1.9.0" -kotlinx-datetime = "0.6.1" +kotlinx-serialization = "1.10.0" +kotlinx-datetime = "0.7.1" -compose = "1.10.0-alpha02" -compose-gl = "0.9.0" -jni-utils = "0.1.6" -jna = "5.16.0" +compose = "1.11.0-alpha02" +compose-gl = "0.9.1" +jni-utils = "0.1.7" +jna = "5.18.1" slf4j = "2.0.17" -logback = "1.5.19" +logback = "1.5.32" -kotest = "6.0.3" -mockk = "1.14.6" +kotest = "6.1.3" +mockk = "1.14.9" -idea-ext = "1.3" +idea-ext = "1.4.1" [libraries] kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } @@ -31,6 +31,11 @@ kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx- kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinx-datetime" } +compose-desktop-common = { group = "org.jetbrains.compose.desktop", name = "desktop", version.ref = "compose" } +compose-material3 = { group = "org.jetbrains.compose.material3", name = "material3", version.ref = "compose" } +compose-material-icons-extended = { group = "org.jetbrains.compose.material", name = "material-icons-extended", version = "1.7.3" } +androidx-annotation = { group = "androidx.annotation", name = "annotation", version = "1.9.1" } + compose-gl = { group = "dev.silenium.compose.gl", name = "compose-gl", version.ref = "compose-gl" } compose-gl-natives = { group = "dev.silenium.compose.gl", name = "compose-gl-natives-all", version.ref = "compose-gl" } ffmpeg-natives = { group = "dev.silenium.libs", name = "ffmpeg-natives", version = "7.1+0.2.0" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d706aba..2f2958b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From be535b48ccc174c5578efa018774f654b0634cc8 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Mon, 23 Feb 2026 21:13:45 +0100 Subject: [PATCH 32/78] fix: disable static libstdc++ and use event loop thread to avoid mpv calls in wakeup Signed-off-by: silenium-dev --- native/build.gradle.kts | 5 + native/meson.build | 2 - native/src/meson.build | 14 +- native/src/mpv/MPV.cpp | 304 ++++++++++++------ .../packagefiles/mpv/subprojects/ffmpeg.wrap | 8 +- .../dev/silenium/multimedia/core/mpv/MPV.kt | 1 + 6 files changed, 223 insertions(+), 111 deletions(-) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 109cb1c..b64563b 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -27,6 +27,8 @@ val platformExtension = "-gpl".takeIf { withGPL }.orEmpty() val platformString = findProperty("ffmpeg.platform")?.toString() val platform = platformString?.let { Platform(it, platformExtension) } ?: NativePlatform.platform(platformExtension) +val javac = tasks.withType().first().javaCompiler.map(JavaCompiler::getExecutablePath) +val javaHome = javac.map { it.asFile.parentFile.parentFile.absolutePath } val mesonExe = findProperty("meson.executable") as? String ?: "meson" val targetDir = layout.buildDirectory.dir("meson").get().asFile.apply { mkdirs() } val generateMakefile = tasks.register("generateMakefile") { @@ -39,7 +41,9 @@ val generateMakefile = tasks.register("generateMakefile") { environment( "CFLAGS" to "-fPIC", "CXXFLAGS" to "-fPIC", + "JAVA_HOME" to javaHome.get(), ) + logger.lifecycle("JAVA_HOME: ${javaHome.get()}") commandLine( mesonExe, "setup", @@ -65,6 +69,7 @@ val compileNative = tasks.register("compileNative") { environment( "CFLAGS" to "-fPIC", "CXXFLAGS" to "-fPIC", + "JAVA_HOME" to javaHome.get(), ) standardOutput = System.out diff --git a/native/meson.build b/native/meson.build index b76e29b..f87e35d 100644 --- a/native/meson.build +++ b/native/meson.build @@ -8,8 +8,6 @@ project('compose-av', add_global_arguments('-fPIC', language : 'c') add_global_arguments('-fPIC', language : 'cpp') add_global_link_arguments( - '-static-libgcc', - '-static-libstdc++', language : 'cpp', ) mpv = subproject('mpv', diff --git a/native/src/meson.build b/native/src/meson.build index 9670be9..b860e92 100644 --- a/native/src/meson.build +++ b/native/src/meson.build @@ -4,10 +4,12 @@ egl = dependency('egl') glx = dependency('glx') x11 = dependency('X11') -shared_library('compose-av', - 'util/Errors.cpp', - 'helper/errors.hpp', - 'helper/errors.cpp', - 'mpv/MPV.cpp', - dependencies : [jni, egl, glx, x11, mpv_dep], +shared_library( + 'compose-av', + 'util/Errors.cpp', + 'helper/errors.hpp', + 'helper/errors.cpp', + 'mpv/MPV.cpp', + dependencies : [jni, egl, glx, x11, mpv_dep], + cpp_args : ['-Wimplicit-fallthrough'], ) diff --git a/native/src/mpv/MPV.cpp b/native/src/mpv/MPV.cpp index 5b2f3ed..cc82388 100644 --- a/native/src/mpv/MPV.cpp +++ b/native/src/mpv/MPV.cpp @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include #include @@ -28,7 +31,7 @@ auto fnptr_(Callable &&c, Ret (*)(Args...)) { if (used) { using type = decltype(storage); storage.~type(); - new (&storage) type(std::forward(c)); + new(&storage) type(std::forward(c)); } used = true; @@ -49,6 +52,12 @@ struct MpvContext { mpv_handle *handle; jobject object; jmethodID method; + + std::thread eventLoop; + std::mutex mtx; + std::condition_variable cv; + std::atomic wakeup{false}; + std::atomic running{true}; }; jobject eventDataToJava(JNIEnv *env, mpv_event_property *prop) { @@ -126,6 +135,7 @@ void eventCallback(JNIEnv *env, const mpv_event *event, jobject callback) { return; } env->CallVoidMethod(callback, method, name, value); + break; } case MPV_EVENT_GET_PROPERTY_REPLY: { const auto prop = static_cast(event->data); @@ -152,6 +162,7 @@ void eventCallback(JNIEnv *env, const mpv_event *event, jobject callback) { return; } env->CallVoidMethod(callback, method, static_cast(event->reply_userdata), value); + break; } case MPV_EVENT_SET_PROPERTY_REPLY: { jobject value = nullptr; @@ -172,6 +183,7 @@ void eventCallback(JNIEnv *env, const mpv_event *event, jobject callback) { return; } env->CallVoidMethod(callback, method, static_cast(event->reply_userdata), value); + break; } case MPV_EVENT_COMMAND_REPLY: { // const auto reply = static_cast(event->data); @@ -193,26 +205,60 @@ void eventCallback(JNIEnv *env, const mpv_event *event, jobject callback) { return; } env->CallVoidMethod(callback, method, static_cast(event->reply_userdata), value); + break; } default: break; } } -void handle_mpv_events(void *ctx) { +// void handle_mpv_events(void *ctx) { +// const auto context = static_cast(ctx); +// JNIEnv *env; +// const auto res = context->jvm->AttachCurrentThread(reinterpret_cast(&env), nullptr); +// if (res != JNI_OK) { +// std::cerr << "Failed to attach current thread" << std::endl; +// return; +// } +// while (true) { +// const auto event = mpv_wait_event(context->handle, 0); +// if (event->event_id == MPV_EVENT_NONE) { +// break; +// } +// eventCallback(env, event, context->object); +// } +// context->jvm->DetachCurrentThread(); +// } + +void handle_mpv_wakeup(void *ctx) { const auto context = static_cast(ctx); + { + std::lock_guard lock(context->mtx); + context->wakeup = true; + } + context->cv.notify_one(); +} + +void mpv_event_loop(MpvContext *context) { JNIEnv *env; const auto res = context->jvm->AttachCurrentThread(reinterpret_cast(&env), nullptr); if (res != JNI_OK) { std::cerr << "Failed to attach current thread" << std::endl; return; } - while (true) { - const auto event = mpv_wait_event(context->handle, 0); - if (event->event_id == MPV_EVENT_NONE) { - break; + while (context->running) { + std::unique_lock lock(context->mtx); + context->cv.wait(lock, [&] { return context->wakeup.load() || !context->running.load(); }); + context->wakeup = false; + lock.unlock(); + + if (!context->running.load()) break; + + while (context->running) { + const auto event = mpv_wait_event(context->handle, 0); + if (event->event_id == MPV_EVENT_NONE) break; + eventCallback(env, event, context->object); } - eventCallback(env, event, context->object); } context->jvm->DetachCurrentThread(); } @@ -228,11 +274,13 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createN(JN return resultSuccess(env, reinterpret_cast(handle)); } -JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_destroyN(JNIEnv *env, jobject thiz, const jlong handle) { +JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_destroyN( + JNIEnv *env, jobject thiz, const jlong handle) { mpv_terminate_destroy(reinterpret_cast(handle)); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setOptionStringN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, jstring value) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setOptionStringN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, jstring value) { const char *nameStr = env->GetStringUTFChars(name, nullptr); const char *valueStr = env->GetStringUTFChars(value, nullptr); const auto ret = mpv_set_option_string(reinterpret_cast(handle), nameStr, valueStr); @@ -244,7 +292,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setOptionS return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setCallbackN(JNIEnv *env, jobject thiz, const jlong handle_, jobject callback) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setCallbackN( + JNIEnv *env, jobject thiz, const jlong handle_, jobject callback) { const auto handle = reinterpret_cast(handle_); JavaVM *jvm; if (const auto ret = env->GetJavaVM(&jvm); ret != JNI_OK) { @@ -252,18 +301,27 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setCallbac return mpvResultFailure(env, "GetJavaVM", MPV_ERROR_GENERIC); } const auto ctx = new MpvContext{jvm, handle, env->NewGlobalRef(callback)}; - mpv_set_wakeup_callback(handle, handle_mpv_events, ctx); + mpv_set_wakeup_callback(handle, handle_mpv_wakeup, ctx); + // mpv_set_wakeup_callback(handle, handle_mpv_events, ctx); + + std::thread eventLoopThread{mpv_event_loop, ctx}; + ctx->eventLoop = std::move(eventLoopThread); return resultSuccess(env, reinterpret_cast(ctx)); } -JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_unsetCallbackN(JNIEnv *env, jobject thiz, const jlong ctx) { +JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_unsetCallbackN( + JNIEnv *env, jobject thiz, const jlong ctx) { const auto context = reinterpret_cast(ctx); + context->running = false; + context->cv.notify_all(); + context->eventLoop.join(); mpv_set_wakeup_callback(context->handle, nullptr, nullptr); env->DeleteGlobalRef(context->object); delete context; } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_commandAsyncN(JNIEnv *env, jobject thiz, const jlong handle, jobjectArray args, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_commandAsyncN( + JNIEnv *env, jobject thiz, const jlong handle, jobjectArray args, const jlong replyUserdata) { const auto size = env->GetArrayLength(args); std::vector argv(size + 1); for (auto i = 0; i < size; i++) { @@ -283,7 +341,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_commandAsy return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_commandN(JNIEnv *env, jobject thiz, const jlong handle, jobjectArray args) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_commandN( + JNIEnv *env, jobject thiz, const jlong handle, jobjectArray args) { const auto size = env->GetArrayLength(args); std::vector argv(size + 1); for (auto i = 0; i < size; i++) { @@ -306,7 +365,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_commandN(J return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_commandStringN(JNIEnv *env, jobject thiz, const jlong handle, jstring command) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_commandStringN( + JNIEnv *env, jobject thiz, const jlong handle, jstring command) { const char *commandStr = env->GetStringUTFChars(command, nullptr); const auto ret = mpv_command_string(reinterpret_cast(handle), commandStr); env->ReleaseStringUTFChars(command, commandStr); @@ -316,9 +376,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_commandStr return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyStringAsyncN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyStringAsyncN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_get_property_async(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_STRING); + const auto ret = mpv_get_property_async(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_STRING); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_get_property_async string", ret); @@ -326,9 +388,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyLongAsyncN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyLongAsyncN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_get_property_async(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_INT64); + const auto ret = mpv_get_property_async(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_INT64); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_get_property_async int64", ret); @@ -336,9 +400,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyDoubleAsyncN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyDoubleAsyncN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_get_property_async(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_DOUBLE); + const auto ret = mpv_get_property_async(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_DOUBLE); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_get_property_async double", ret); @@ -346,9 +412,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyFlagAsyncN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyFlagAsyncN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_get_property_async(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_FLAG); + const auto ret = mpv_get_property_async(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_FLAG); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_get_property_async flag", ret); @@ -357,7 +425,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyStringN(JNIEnv *env, jobject thiz, const jlong handle, jstring name) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyStringN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name) { const char *nameStr = env->GetStringUTFChars(name, nullptr); char *value; const auto ret = mpv_get_property(reinterpret_cast(handle), nameStr, MPV_FORMAT_STRING, &value); @@ -373,7 +442,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert return result; } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyLongN(JNIEnv *env, jobject thiz, const jlong handle, jstring name) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyLongN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name) { const char *nameStr = env->GetStringUTFChars(name, nullptr); long value; const auto ret = mpv_get_property(reinterpret_cast(handle), nameStr, MPV_FORMAT_INT64, &value); @@ -387,7 +457,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert return resultSuccess(env, value); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyDoubleN(JNIEnv *env, jobject thiz, const jlong handle, jstring name) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyDoubleN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name) { const char *nameStr = env->GetStringUTFChars(name, nullptr); double value; const auto ret = mpv_get_property(reinterpret_cast(handle), nameStr, MPV_FORMAT_DOUBLE, &value); @@ -401,7 +472,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert return resultSuccess(env, value); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyFlagN(JNIEnv *env, jobject thiz, const jlong handle, jstring name) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyFlagN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name) { const char *nameStr = env->GetStringUTFChars(name, nullptr); bool value; const auto ret = mpv_get_property(reinterpret_cast(handle), nameStr, MPV_FORMAT_FLAG, &value); @@ -415,10 +487,12 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert return resultSuccess(env, value); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyStringAsyncN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, jstring value, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyStringAsyncN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, jstring value, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); auto valueStr = const_cast(env->GetStringUTFChars(value, nullptr)); - const auto ret = mpv_set_property_async(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_STRING, &valueStr); + const auto ret = mpv_set_property_async(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_STRING, &valueStr); env->ReleaseStringUTFChars(name, nameStr); env->ReleaseStringUTFChars(value, valueStr); if (ret < 0) { @@ -427,9 +501,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyLongAsyncN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, jlong value, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyLongAsyncN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, jlong value, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_set_property_async(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_INT64, &value); + const auto ret = mpv_set_property_async(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_INT64, &value); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_set_property_async int64", ret); @@ -437,9 +513,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyDoubleAsyncN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, jdouble value, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyDoubleAsyncN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, jdouble value, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_set_property_async(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_DOUBLE, &value); + const auto ret = mpv_set_property_async(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_DOUBLE, &value); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_set_property_async double", ret); @@ -447,9 +525,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyFlagAsyncN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, jboolean value, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyFlagAsyncN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, jboolean value, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_set_property_async(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_FLAG, &value); + const auto ret = mpv_set_property_async(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_FLAG, &value); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_set_property_async flag", ret); @@ -457,7 +537,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyStringN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, jstring value) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyStringN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, jstring value) { const char *nameStr = env->GetStringUTFChars(name, nullptr); const char *valueStr = env->GetStringUTFChars(value, nullptr); const auto ret = mpv_set_property_string(reinterpret_cast(handle), nameStr, valueStr); @@ -469,7 +550,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyLongN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, jlong value) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyLongN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, jlong value) { const char *nameStr = env->GetStringUTFChars(name, nullptr); const auto ret = mpv_set_property(reinterpret_cast(handle), nameStr, MPV_FORMAT_INT64, &value); env->ReleaseStringUTFChars(name, nameStr); @@ -479,7 +561,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyDoubleN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, jdouble value) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyDoubleN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, jdouble value) { const char *nameStr = env->GetStringUTFChars(name, nullptr); const auto ret = mpv_set_property(reinterpret_cast(handle), nameStr, MPV_FORMAT_DOUBLE, &value); env->ReleaseStringUTFChars(name, nameStr); @@ -489,7 +572,8 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyFlagN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, jboolean value) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropertyFlagN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, jboolean value) { const char *nameStr = env->GetStringUTFChars(name, nullptr); const auto ret = mpv_set_property(reinterpret_cast(handle), nameStr, MPV_FORMAT_FLAG, &value); env->ReleaseStringUTFChars(name, nameStr); @@ -499,9 +583,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setPropert return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePropertyStringN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePropertyStringN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_observe_property(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_STRING); + const auto ret = mpv_observe_property(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_STRING); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_observe_property", ret); @@ -509,9 +595,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePro return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePropertyLongN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePropertyLongN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_observe_property(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_INT64); + const auto ret = mpv_observe_property(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_INT64); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_observe_property", ret); @@ -519,9 +607,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePro return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePropertyDoubleN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePropertyDoubleN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_observe_property(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_DOUBLE); + const auto ret = mpv_observe_property(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_DOUBLE); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_observe_property", ret); @@ -529,9 +619,11 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePro return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePropertyFlagN(JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePropertyFlagN( + JNIEnv *env, jobject thiz, const jlong handle, jstring name, const jlong replyUserdata) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - const auto ret = mpv_observe_property(reinterpret_cast(handle), replyUserdata, nameStr, MPV_FORMAT_FLAG); + const auto ret = mpv_observe_property(reinterpret_cast(handle), replyUserdata, nameStr, + MPV_FORMAT_FLAG); env->ReleaseStringUTFChars(name, nameStr); if (ret < 0) { return mpvResultFailure(env, "mpv_observe_property", ret); @@ -539,14 +631,16 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_observePro return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_unobservePropertyN(JNIEnv *env, jobject thiz, const jlong handle, const jlong replyUserdata) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_unobservePropertyN( + JNIEnv *env, jobject thiz, const jlong handle, const jlong replyUserdata) { if (const auto ret = mpv_unobserve_property(reinterpret_cast(handle), replyUserdata); ret < 0) { return mpvResultFailure(env, "mpv_unobserve_property", ret); } return resultSuccess(env); } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_initializeN(JNIEnv *env, jobject thiz, const jlong handle) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_initializeN( + JNIEnv *env, jobject thiz, const jlong handle) { if (const auto ret = mpv_initialize(reinterpret_cast(handle)); ret < 0) { return mpvResultFailure(env, "mpv_initialize", ret); } @@ -560,18 +654,24 @@ struct RenderContext { }; // Rendering -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createRenderN(JNIEnv *env, jobject thiz, const jlong mpvHandle, jobject self, const jboolean advancedControl) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createRenderN( + JNIEnv *env, jobject thiz, const jlong mpvHandle, jobject self, const jboolean advancedControl) { std::vector params{ - {MPV_RENDER_PARAM_API_TYPE, const_cast(MPV_RENDER_API_TYPE_OPENGL)}, + {MPV_RENDER_PARAM_API_TYPE, const_cast(MPV_RENDER_API_TYPE_OPENGL)}, }; + const auto test = 12323; + std::cerr << "Creating render context" << test << std::endl; + Display *display{nullptr}; if (const auto glxDisplay = glXGetCurrentDisplay(); glxDisplay != nullptr) { params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, glxDisplay}); + std::cerr << "Using GLX display" << reinterpret_cast(display) << std::endl; } else if (const auto eglDisplay = eglGetCurrentDisplay(); eglDisplay != EGL_NO_DISPLAY) { // Compose always runs on X11 display = XOpenDisplay(nullptr); params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, display}); + std::cerr << "Using X11 display" << reinterpret_cast(display) << std::endl; } JavaVM *jvm; @@ -582,28 +682,29 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createRend const auto object = env->NewGlobalRef(self); mpv_opengl_init_params gl_params{ - .get_proc_address = fnptr([jvm](void *opaque, const char *name) -> void * { - const auto javaRender = static_cast(opaque); - JNIEnv *jni_env; - const auto res = jvm->AttachCurrentThread(reinterpret_cast(&jni_env), nullptr); - if (res != JNI_OK) { - std::cerr << "Failed to attach current thread" << std::endl; - return nullptr; - } + .get_proc_address = fnptr([jvm](void *opaque, const char *name) -> void * { + const auto javaRender = static_cast(opaque); + JNIEnv *jni_env; + const auto res = jvm->AttachCurrentThread(reinterpret_cast(&jni_env), nullptr); + if (res != JNI_OK) { + std::cerr << "Failed to attach current thread" << std::endl; + return nullptr; + } - const auto glProcMethod = jni_env->GetMethodID(jni_env->GetObjectClass(javaRender), "getGlProc", "(Ljava/lang/String;)J"); - if (glProcMethod == nullptr) { - std::cerr << "Method not found: getGlProc" << std::endl; - return nullptr; - } + const auto glProcMethod = jni_env->GetMethodID(jni_env->GetObjectClass(javaRender), "getGlProc", + "(Ljava/lang/String;)J"); + if (glProcMethod == nullptr) { + std::cerr << "Method not found: getGlProc" << std::endl; + return nullptr; + } - const auto nameStr = jni_env->NewStringUTF(name); - const auto ret = jni_env->CallLongMethod(javaRender, glProcMethod, nameStr); - jni_env->DeleteLocalRef(nameStr); - jvm->DetachCurrentThread(); - return reinterpret_cast(ret); - }), - .get_proc_address_ctx = object, + const auto nameStr = jni_env->NewStringUTF(name); + const auto ret = jni_env->CallLongMethod(javaRender, glProcMethod, nameStr); + jni_env->DeleteLocalRef(nameStr); + jvm->DetachCurrentThread(); + return reinterpret_cast(ret); + }), + .get_proc_address_ctx = object, }; params.push_back({MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_params}); int advControl = advancedControl ? 1 : 0; @@ -611,34 +712,37 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createRend params.push_back({MPV_RENDER_PARAM_INVALID, nullptr}); mpv_render_context *handle{nullptr}; - if (const auto ret = mpv_render_context_create(&handle, reinterpret_cast(mpvHandle), params.data()); ret < 0) { + if (const auto ret = mpv_render_context_create(&handle, reinterpret_cast(mpvHandle), params.data()); + ret < 0) { env->DeleteGlobalRef(object); return mpvResultFailure(env, "mpv_render_context_create", ret); } const auto ctx = new RenderContext{handle, object, display}; mpv_render_context_set_update_callback( - handle, - fnptr([jvm](void *opaque) { - const auto render_context = static_cast(opaque); - JNIEnv *jni_env; - const auto res = jvm->AttachCurrentThread(reinterpret_cast(&jni_env), nullptr); - if (res != JNI_OK) { - std::cerr << "Failed to attach current thread" << std::endl; - return; - } - const auto updateMethod = jni_env->GetMethodID(jni_env->GetObjectClass(render_context->gref), "requestUpdate", "()V"); - if (updateMethod == nullptr) { - std::cerr << "Method not found: requestUpdate" << std::endl; - return; - } - jni_env->CallVoidMethod(render_context->gref, updateMethod); - jvm->DetachCurrentThread(); - }), - ctx); + handle, + fnptr([jvm](void *opaque) { + const auto render_context = static_cast(opaque); + JNIEnv *jni_env; + const auto res = jvm->AttachCurrentThread(reinterpret_cast(&jni_env), nullptr); + if (res != JNI_OK) { + std::cerr << "Failed to attach current thread" << std::endl; + return; + } + const auto updateMethod = jni_env->GetMethodID(jni_env->GetObjectClass(render_context->gref), + "requestUpdate", "()V"); + if (updateMethod == nullptr) { + std::cerr << "Method not found: requestUpdate" << std::endl; + return; + } + jni_env->CallVoidMethod(render_context->gref, updateMethod); + jvm->DetachCurrentThread(); + }), + ctx); return resultSuccess(env, reinterpret_cast(ctx)); } -JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_destroyRenderN(JNIEnv *env, jobject thiz, const jlong handle) { +JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_destroyRenderN( + JNIEnv *env, jobject thiz, const jlong handle) { const auto context = reinterpret_cast(handle); mpv_render_context_free(context->handle); env->DeleteGlobalRef(context->gref); @@ -648,21 +752,23 @@ JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_destroyRender delete context; } -JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_renderN(JNIEnv *env, jobject thiz, const jlong handle, const GLint fbo, const jint width, const jint height, const jint glInternalFormat) { +JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_renderN( + JNIEnv *env, jobject thiz, const jlong handle, const GLint fbo, const jint width, const jint height, + const jint glInternalFormat) { const auto context = reinterpret_cast(handle); const auto flags = mpv_render_context_update(context->handle); if (flags & MPV_RENDER_UPDATE_FRAME) { mpv_opengl_fbo fboData{ - .fbo = fbo, - .w = width, - .h = height, - .internal_format = glInternalFormat, + .fbo = fbo, + .w = width, + .h = height, + .internal_format = glInternalFormat, }; int flipY{0}; mpv_render_param params[]{ - {MPV_RENDER_PARAM_OPENGL_FBO, &fboData}, - {MPV_RENDER_PARAM_FLIP_Y, &flipY}, - {MPV_RENDER_PARAM_INVALID, nullptr}, + {MPV_RENDER_PARAM_OPENGL_FBO, &fboData}, + {MPV_RENDER_PARAM_FLIP_Y, &flipY}, + {MPV_RENDER_PARAM_INVALID, nullptr}, }; if (const auto ret = mpv_render_context_render(context->handle, params); ret < 0) { return mpvResultFailure(env, "mpv_render_context_render", ret); diff --git a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap index fbbe54c..f64a0ef 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap +++ b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap @@ -1,8 +1,8 @@ [wrap-file] -directory = ffmpeg-n8.0-19-gdd00a614e1-linux64-gpl-shared-8.0 -source_url = https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2025-10-12-13-57/ffmpeg-n8.0-19-gdd00a614e1-linux64-gpl-shared-8.0.tar.xz -source_filename = ffmpeg-n8.0-19-gdd00a614e1-linux64-gpl-shared-8.0.tar.xz -source_hash = bc4f302c7d063434eb1089f34f004e2683a96eaea7b81012ba8d408c273c15e6 +directory = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0 +source_url = https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz +source_filename = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz +source_hash = 3d7825a52264635213daf92601d368a04e688f364c1d67f69482ba094fd98e75 patch_directory = ffmpeg [provide] diff --git a/src/main/kotlin/dev/silenium/multimedia/core/mpv/MPV.kt b/src/main/kotlin/dev/silenium/multimedia/core/mpv/MPV.kt index 055c1aa..de6b5b6 100644 --- a/src/main/kotlin/dev/silenium/multimedia/core/mpv/MPV.kt +++ b/src/main/kotlin/dev/silenium/multimedia/core/mpv/MPV.kt @@ -400,6 +400,7 @@ class MPV : NativeCleanable, MPVAsyncListener { } override fun close() { + callback?.let(::unsetCallbackN) initialized.set(false) super.close() } From c0aa7aea022db7082f2843697f61993351477203 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Mon, 23 Feb 2026 21:16:21 +0100 Subject: [PATCH 33/78] build: add nix flake for build environment --- flake.lock | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 17 +++++++++++++++ shell.nix | 45 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 shell.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..af8f58f --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1771369470, + "narHash": "sha256-0NBlEBKkN3lufyvFegY4TYv5mCNHbi5OmBDrzihbBMQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "0182a361324364ae3f436a63005877674cf45efb", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..f75c280 --- /dev/null +++ b/flake.nix @@ -0,0 +1,17 @@ +{ + description = "compose-gl build environment"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem + (system: + let pkgs = nixpkgs.legacyPackages.${system}; in + { + devShells.default = import ./shell.nix { inherit pkgs; }; + } + ); +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..59c56d3 --- /dev/null +++ b/shell.nix @@ -0,0 +1,45 @@ +{ pkgs ? import { } }: + +pkgs.mkShell { + strictDeps = true; + nativeBuildInputs = with pkgs; [ + # Java Development + jdk21 + gradle_9 + + # C/C++ Build Toolchain + cmake + pkgsCross.aarch64-multiplatform.gcc + pkgsCross.aarch64-multiplatform.binutils-unwrapped + ninja + pkg-config + meson + + # Additional utilities + git + python3 + ]; + buildInputs = with pkgs; [ + # Libraries + libGL + mesa-gl-headers + libdrm + hwdata + libx11 + libva + mesa + ]; + + shellHook = '' + echo "Development environment loaded" + echo "Java version: $(java -version 2>&1 | head -n 1)" + echo "Gradle version: $(gradle --version | grep Gradle)" + echo "CMake version: $(cmake --version | head -n 1)" + echo "GCC version: $(gcc --version | head -n 1)" + echo "Ninja version: $(ninja --version)" + ''; + + # Set environment variables + JAVA_HOME = "${pkgs.jdk21}"; + CMAKE_GENERATOR = "Ninja"; +} From 29d0e558e9258524db1285d412db89314696aee7 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Tue, 24 Feb 2026 22:34:10 +0100 Subject: [PATCH 34/78] chore: remove obsolete files --- mpv/subprojects/ffmpeg.wrap | 9 - mpv/subprojects/libass.wrap | 4 - mpv/subprojects/libdbus.wrap.disabled | 8 - mpv/subprojects/libjpeg-turbo.wrap | 11 - mpv/subprojects/libpipewire-0.3.wrap.disabled | 8 - mpv/subprojects/libplacebo.wrap | 5 - .../packagefiles/ffmpeg/collect_versions.sh | 9 - .../packagefiles/ffmpeg/meson.build | 26 -- .../libjpeg-turbo-3.1.2/LICENSE.build | 19 - .../libjpeg-turbo-3.1.2/meson.build | 150 -------- .../libjpeg-turbo-3.1.2/meson_options.txt | 20 -- .../libjpeg-turbo-3.1.2/simd/arm/meson.build | 6 - .../libjpeg-turbo-3.1.2/simd/meson.build | 338 ------------------ .../libjpeg-turbo-3.1.2/src/meson.build | 265 -------------- 14 files changed, 878 deletions(-) delete mode 100644 mpv/subprojects/ffmpeg.wrap delete mode 100644 mpv/subprojects/libass.wrap delete mode 100644 mpv/subprojects/libdbus.wrap.disabled delete mode 100644 mpv/subprojects/libjpeg-turbo.wrap delete mode 100644 mpv/subprojects/libpipewire-0.3.wrap.disabled delete mode 100644 mpv/subprojects/libplacebo.wrap delete mode 100644 mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh delete mode 100644 mpv/subprojects/packagefiles/ffmpeg/meson.build delete mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build delete mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build delete mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt delete mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build delete mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build delete mode 100644 mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build diff --git a/mpv/subprojects/ffmpeg.wrap b/mpv/subprojects/ffmpeg.wrap deleted file mode 100644 index 5c29551..0000000 --- a/mpv/subprojects/ffmpeg.wrap +++ /dev/null @@ -1,9 +0,0 @@ -[wrap-file] -directory = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0 -source_url = https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz -source_filename = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz -source_hash = 6e32fab45ad71841de03e796124b7c1c06a8b42a53860525a44aa007b28757a8 -patch_directory = ffmpeg - -[provide] -dependency_names = libavcodec, libavfilter, libavformat, libavutil, libswresample, libswscale diff --git a/mpv/subprojects/libass.wrap b/mpv/subprojects/libass.wrap deleted file mode 100644 index 580d48a..0000000 --- a/mpv/subprojects/libass.wrap +++ /dev/null @@ -1,4 +0,0 @@ -[wrap-git] -revision = master -url = https://github.com/libass/libass -depth = 1 diff --git a/mpv/subprojects/libdbus.wrap.disabled b/mpv/subprojects/libdbus.wrap.disabled deleted file mode 100644 index 6e6b101..0000000 --- a/mpv/subprojects/libdbus.wrap.disabled +++ /dev/null @@ -1,8 +0,0 @@ -[wrap-git] -url = https://gitlab.freedesktop.org/dbus/dbus.git -revision = dbus-1.16.2 -depth = 1 -clone-recursive = true - -[provide] -dependency_names = dbus-1 diff --git a/mpv/subprojects/libjpeg-turbo.wrap b/mpv/subprojects/libjpeg-turbo.wrap deleted file mode 100644 index c0ca6d0..0000000 --- a/mpv/subprojects/libjpeg-turbo.wrap +++ /dev/null @@ -1,11 +0,0 @@ -[wrap-file] -directory = libjpeg-turbo-3.1.2 -source_url = https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/3.1.2/libjpeg-turbo-3.1.2.tar.gz -source_filename = libjpeg-turbo-3.1.2.tar.gz -source_hash = 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf -patch_directory = libjpeg-turbo-3.1.2 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/libjpeg-turbo_3.1.2-1/libjpeg-turbo-3.1.2.tar.gz -wrapdb_version = 3.1.2-1 - -[provide] -dependency_names = libjpeg, libturbojpeg diff --git a/mpv/subprojects/libpipewire-0.3.wrap.disabled b/mpv/subprojects/libpipewire-0.3.wrap.disabled deleted file mode 100644 index 4691d10..0000000 --- a/mpv/subprojects/libpipewire-0.3.wrap.disabled +++ /dev/null @@ -1,8 +0,0 @@ -[wrap-git] -url = https://gitlab.freedesktop.org/pipewire/pipewire.git -revision = 1.4.9 -depth = 1 -clone-recursive = true - -[provide] -dependency_names = libpipewire-0.3 diff --git a/mpv/subprojects/libplacebo.wrap b/mpv/subprojects/libplacebo.wrap deleted file mode 100644 index dc08964..0000000 --- a/mpv/subprojects/libplacebo.wrap +++ /dev/null @@ -1,5 +0,0 @@ -[wrap-git] -url = https://github.com/haasn/libplacebo -revision = master -depth = 1 -clone-recursive = true diff --git a/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh b/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh deleted file mode 100644 index c620567..0000000 --- a/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -for shared_object in "${MESON_SOURCE_ROOT}/${MESON_SUBDIR}"/lib/*.so.*.*.*; do - filename=$(basename "$shared_object") - lib_name=$(basename "${filename//\.so.*/}") - lib_name="${lib_name//lib/}" - lib_version=${filename//*.so\./} - echo "${lib_name}:${lib_version}" -done diff --git a/mpv/subprojects/packagefiles/ffmpeg/meson.build b/mpv/subprojects/packagefiles/ffmpeg/meson.build deleted file mode 100644 index 791782c..0000000 --- a/mpv/subprojects/packagefiles/ffmpeg/meson.build +++ /dev/null @@ -1,26 +0,0 @@ -project('ffmpeg', 'c') - -cc = meson.get_compiler('c') - -versions_command = run_command('bash', 'collect_versions.sh', capture : true, check : true) -versions = versions_command.stdout().strip().split('\n') - -library_names = ['avcodec', 'avfilter', 'avformat', 'avutil', 'swresample', 'swscale'] - -foreach lib_name : library_names - foreach version : versions - version_name = version.split(':')[0].strip() - version_value = version.split(':')[1].strip() - - if version_name == lib_name - message(version) - dep = declare_dependency( - version : version_value, - dependencies : cc.find_library(lib_name, dirs : meson.current_source_dir() + '/lib'), - include_directories : include_directories('include'), - ) - meson.override_dependency('lib' + lib_name, dep) - break - endif - endforeach -endforeach diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build deleted file mode 100644 index b59833d..0000000 --- a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2021 The Meson development team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build deleted file mode 100644 index e84a024..0000000 --- a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build +++ /dev/null @@ -1,150 +0,0 @@ -project( - 'libjpeg-turbo', - 'c', - version : '3.1.2', - license : 'BSD-3-Clause AND IJG', - meson_version : '>= 0.64.0', -) - -add_project_arguments('-D_POSIX_C_SOURCE=200809L', language : 'c') -add_project_arguments('-D_DEFAULT_SOURCE', language : 'c') - -pkg = import('pkgconfig') -python = import('python').find_installation() - -cc = meson.get_compiler('c') -host_system = host_machine.system() -host_cpu = host_machine.cpu_family() - -cdata = configuration_data() -cdata.set('CMAKE_PROJECT_NAME', meson.project_name()) -cdata.set('VERSION', meson.project_version()) -cdata.set('COPYRIGHT_YEAR', '1991-2025') - -jpeg_lib_version = 80 -so_major = jpeg_lib_version / 10 -so_age = 3 -so_minor = 2 -so_version = '@0@.@1@.@2@'.format(so_major, so_age, so_minor) -vs_defs = files('win/jpeg8.def')[0] - -version_arr = meson.project_version().split('.') -version_major = version_arr[0] -version_minor = version_arr[1] -version_revision = version_arr[2] - -# Add padding to build an integer: 2.1.0 -> 2001000 -if version_major.to_int() < 10 - version_major += '00' -elif version_major.to_int() < 100 - version_major += '0' -endif - -if version_minor.to_int() < 10 - version_minor += '00' -elif version_minor.to_int() < 100 - version_minor += '0' -endif - -cdata.set('JPEG_LIB_VERSION', jpeg_lib_version) -cdata.set( - 'LIBJPEG_TURBO_VERSION_NUMBER', - version_major + version_minor + version_revision, -) - -cdata.set('C_ARITH_CODING_SUPPORTED', true) -cdata.set('D_ARITH_CODING_SUPPORTED', true) - -check_headers = ['local.h', 'stddef.h', 'stdlib.h', 'sys/types.h'] -if cc.get_id() == 'msvc' - check_headers += 'intrin.h' -endif - -foreach header : check_headers - have_header = cc.has_header(header) - cdata.set('HAVE_' + header.underscorify().to_upper(), have_header) - cdata.set('NEED_' + header.underscorify().to_upper(), have_header) -endforeach - -has_memset = cc.has_header_symbol('string.h', 'memset') -has_memcpy = cc.has_header_symbol('string.h', 'memcpy') -cdata.set('NEED_BSD_STRINGS', not has_memset or not has_memcpy) - -size_t = cc.sizeof('size_t') -unsigned_long = cc.sizeof('unsigned long') -cdata.set('SIZE_T', size_t) -cdata.set('HAVE_UNSIGNED_CHAR', cc.sizeof('unsigned char') != -1) -cdata.set('HAVE_UNSIGNED_SHORT', cc.sizeof('unsigned short') != -1) -if size_t == unsigned_long - cdata.set('HAVE_BUILTIN_CTZL', cc.has_function('__builtin_ctzl')) -endif - -code = 'int main(void) { typedef struct undefined_structure *undef_struct_ptr; undef_struct_ptr ptr = 0; return ptr != 0; }' -cdata.set('INCOMPLETE_TYPES_BROKEN', not cc.links(code)) - -if meson.can_run_host_binaries() - code = ''' - #include - #include - static int is_shifting_signed (long arg) { - long res = arg >> 4; - if (res == -0x7F7E80CL) - return 1; /* right shift is signed */ - /* see if unsigned-shift hack will fix it. */ - /* we can't just test exact value since it depends on width of long... */ - res |= 0xFFFFFFFFL << (32-4); - if (res == -0x7F7E80CL) - return 0; /* right shift is unsigned */ - printf(\"Right shift isn't acting as I expect it to.\\\\n\"); - printf(\"I fear the JPEG software will not work at all.\\\\n\\\\n\"); - return 0; /* try it with unsigned anyway */ - } - int main (void) { - exit(is_shifting_signed(-0x7F7E80B1L)); - } - ''' - cdata.set('RIGHT_SHIFT_IS_UNSIGNED', cc.run(code).returncode() == 0) -else - cdata.set('RIGHT_SHIFT_IS_UNSIGNED', false) -endif - -p = run_command( - python, - '-c', - 'import datetime; print(datetime.datetime.now().strftime("%Y%m%d"))', - check : true, -) -cdata.set('BUILD', p.stdout().strip()) - -if cc.get_id() == 'msvc' - cdata.set('THREAD_LOCAL', '__declspec(thread)') -else - cdata.set('THREAD_LOCAL', '__thread') -endif - -cdata.set('HIDDEN', cc.has_function_attribute('visibility:hidden') ? '__attribute__((visibility("hidden")))' - : '') - -if get_option('force_inline') - if cc.get_id() == 'msvc' - cdata.set('INLINE', '__forceinline') - else - cdata.set('INLINE', 'inline __attribute__((always_inline))') - endif -else - cdata.set('INLINE', 'inline') -endif - -if host_system == 'windows' - add_project_arguments( - '-DDLLDEFINE', - language : 'c', - ) -endif - -incdir = include_directories('src') - -subdir('simd') -cdata.set('WITH_SIMD', have_simd) - -subdir('src') diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt deleted file mode 100644 index 41ed4bb..0000000 --- a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt +++ /dev/null @@ -1,20 +0,0 @@ -option( - 'force_inline', - type : 'boolean', -) -option( - 'turbojpeg', - type : 'feature', -) -option( - 'simd', - type : 'feature', -) -option( - 'tests', - type : 'feature', -) -option( - 'neon-intrinsics', - type : 'feature', -) diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build deleted file mode 100644 index 124b74a..0000000 --- a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build +++ /dev/null @@ -1,6 +0,0 @@ -neon_compat_h = configure_file( - input : 'neon-compat.h.in', - output : 'neon-compat.h', - format : 'cmake', - configuration : cdata_neon, -) diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build deleted file mode 100644 index 7c2306d..0000000 --- a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build +++ /dev/null @@ -1,338 +0,0 @@ -simd_src_x86_64 = [ - 'x86_64/jccolor-avx2.asm', - 'x86_64/jccolor-sse2.asm', - 'x86_64/jcgray-avx2.asm', - 'x86_64/jcgray-sse2.asm', - 'x86_64/jchuff-sse2.asm', - 'x86_64/jcphuff-sse2.asm', - 'x86_64/jcsample-avx2.asm', - 'x86_64/jcsample-sse2.asm', - 'x86_64/jdcolor-avx2.asm', - 'x86_64/jdcolor-sse2.asm', - 'x86_64/jdmerge-avx2.asm', - 'x86_64/jdmerge-sse2.asm', - 'x86_64/jdsample-avx2.asm', - 'x86_64/jdsample-sse2.asm', - 'x86_64/jfdctflt-sse.asm', - 'x86_64/jfdctfst-sse2.asm', - 'x86_64/jfdctint-avx2.asm', - 'x86_64/jfdctint-sse2.asm', - 'x86_64/jidctflt-sse2.asm', - 'x86_64/jidctfst-sse2.asm', - 'x86_64/jidctint-avx2.asm', - 'x86_64/jidctint-sse2.asm', - 'x86_64/jidctred-sse2.asm', - 'x86_64/jquantf-sse2.asm', - 'x86_64/jquanti-avx2.asm', - 'x86_64/jquanti-sse2.asm', - 'x86_64/jsimdcpu.asm', -] - -simd_src_i386 = [ - 'i386/jccolor-avx2.asm', - 'i386/jccolor-mmx.asm', - 'i386/jccolor-sse2.asm', - 'i386/jcgray-avx2.asm', - 'i386/jcgray-mmx.asm', - 'i386/jcgray-sse2.asm', - 'i386/jchuff-sse2.asm', - 'i386/jcphuff-sse2.asm', - 'i386/jcsample-avx2.asm', - 'i386/jcsample-mmx.asm', - 'i386/jcsample-sse2.asm', - 'i386/jdcolor-avx2.asm', - 'i386/jdcolor-mmx.asm', - 'i386/jdcolor-sse2.asm', - 'i386/jdmerge-avx2.asm', - 'i386/jdmerge-mmx.asm', - 'i386/jdmerge-sse2.asm', - 'i386/jdsample-avx2.asm', - 'i386/jdsample-mmx.asm', - 'i386/jdsample-sse2.asm', - 'i386/jfdctflt-3dn.asm', - 'i386/jfdctflt-sse.asm', - 'i386/jfdctfst-mmx.asm', - 'i386/jfdctfst-sse2.asm', - 'i386/jfdctint-avx2.asm', - 'i386/jfdctint-mmx.asm', - 'i386/jfdctint-sse2.asm', - 'i386/jidctflt-3dn.asm', - 'i386/jidctflt-sse2.asm', - 'i386/jidctflt-sse.asm', - 'i386/jidctfst-mmx.asm', - 'i386/jidctfst-sse2.asm', - 'i386/jidctint-avx2.asm', - 'i386/jidctint-mmx.asm', - 'i386/jidctint-sse2.asm', - 'i386/jidctred-mmx.asm', - 'i386/jidctred-sse2.asm', - 'i386/jquant-3dn.asm', - 'i386/jquantf-sse2.asm', - 'i386/jquanti-avx2.asm', - 'i386/jquanti-sse2.asm', - 'i386/jquant-mmx.asm', - 'i386/jquant-sse.asm', - 'i386/jsimdcpu.asm', -] - -simd_src_arm = files( - 'arm/jcgray-neon.c', - 'arm/jcphuff-neon.c', - 'arm/jcsample-neon.c', - 'arm/jdmerge-neon.c', - 'arm/jdsample-neon.c', - 'arm/jfdctfst-neon.c', - 'arm/jidctred-neon.c', - 'arm/jquanti-neon.c', -) - -simd_opt = get_option('simd') -have_simd = false -simd = [] - -if host_cpu in ['x86', 'x86_64'] - have_simd = add_languages( - 'nasm', - required : simd_opt, - native : false, - ) - if have_simd - add_project_arguments( - '-DPIC', - language : 'nasm', - ) - x64 = host_cpu == 'x86_64' - # simulate upstream's "is ELF" check by excluding non-ELF OSes - if x64 and host_machine.system() not in ['cygwin', 'darwin', 'windows'] - if cc.compiles( - ''' - #if (__CET__ & 3) == 0 - #error \"CET not enabled\" - #endif - int main(void) { return 0; } - ''', - ) - add_project_arguments( - '-D__CET__', - language : 'nasm', - ) - endif - endif - dir = x64 ? 'x86_64' : 'i386' - simd_src = x64 ? simd_src_x86_64 : simd_src_i386 - simd = static_library( - 'simd', - dir / 'jsimd.c', - simd_src, - include_directories : [incdir, 'nasm', dir], - pic : get_option('default_library') != 'static', - ) - endif -elif host_cpu in ['arm', 'aarch64'] - aarch = host_cpu == 'aarch64' ? 'aarch64' : 'aarch32' - dir = 'arm' / aarch - cdata_neon = configuration_data() - - needs_softfp_for_intrinsics = host_cpu == 'arm' and cc.compiles( - ''' - #if defined(__ARM_NEON__) || (!defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)) - #error \"Neon run-time auto-detection will not be used\" - #endif - #if __ARM_PCS_VFP == 1 - #error \"float ABI = hard\" - #endif - #if __SOFTFP__ != 1 - #error \"float ABI = softfp\" - #endif - int main(void) { return 0; }" - ''', - name : 'does not need softfp for Neon intrinsics', - ) - neon_flags = [] - if host_cpu == 'arm' - neon_flags += ['-mfpu=neon'] - endif - if needs_softfp_for_intrinsics - neon_flags += ['-mfloatabi=softfp'] - endif - if host_cpu == 'arm' - have_simd = cc.compiles( - '''#include - int main(int argc, char **argv) { - uint16x8_t input = vdupq_n_u16((uint16_t)argc); - uint8x8_t output = vmovn_u16(input); - return (int)output[0]; - }''', - args : neon_flags, - name : 'supports Neon', - ) - if not have_simd - if simd_opt.enabled() - error('SIMD extensions not available for this architecture') - else - warning('SIMD extensions not available for this architecture') - endif - endif - else - have_simd = true - endif - - if have_simd - cdata_neon.set( - 'HAVE_VLD1_S16_X3', - cc.compiles( - '''#include - int main(int argc, char **argv) { - int16_t input[12]; - int16x4x3_t output; - int i; - for (i = 0; i < 12; i++) input[i] = (int16_t)argc; - output = vld1_s16_x3(input); - vst3_s16(input, output); - return (int)input[0]; - }''', - args : neon_flags, - name : 'supports vld1_s16_x3 intrinsic', - ), - ) - cdata_neon.set( - 'HAVE_VLD1_U16_X2', - cc.compiles( - ''' - #include - int main(int argc, char **argv) { - uint16_t input[8]; - uint16x4x2_t output; - int i; - for (i = 0; i < 8; i++) input[i] = (uint16_t)argc; - output = vld1_u16_x2(input); - vst2_u16(input, output); - return (int)input[0]; - }''', - args : neon_flags, - name : 'supports vld1_u16_x2 intrinsic', - ), - ) - cdata_neon.set( - 'HAVE_VLD1Q_U8_X4', - cc.compiles( - ''' - #include - int main(int argc, char **argv) { - uint8_t input[64]; - uint8x16x4_t output; - int i; - for (i = 0; i < 64; i++) input[i] = (uint8_t)argc; - output = vld1q_u8_x4(input); - vst4q_u8(input, output); - return (int)input[0]; - }''', - args : neon_flags, - name : 'supports vld1q_u8_x4 intrinsic', - ), - ) - - subdir('arm') - simd_src_arm += [neon_compat_h] - - # GCC 11 and earlier and some older versions of Clang do not have a full or - # optimal set of Neon intrinsics, so for performance reasons, when using those - # compilers, we default to using the older GAS implementation of the Neon SIMD - # extensions for certain algorithms. The presence or absence of the three - # intrinsics we tested above is a reasonable proxy for this, except with GCC 10 - # and 11. - - default_neon_intrinsics = cdata_neon.get('HAVE_VLD1_S16_X3') and cdata_neon.get( - 'HAVE_VLD1_U16_X2', - ) and cdata_neon.get( - 'HAVE_VLD1Q_U8_X4', - ) and ( - cc.get_id() != 'gcc' or cc.version().version_compare('>= 12.0.0') - ) - - neon_intrinsics = get_option('neon-intrinsics').disable_auto_if( - not default_neon_intrinsics, - ).allowed() - - # It is possible to run compile checks on generated files, however, - # Meson versions earlier than 1.2.0 do not set the lookup path - # correctly, causing Python to fail opening it. - # https://github.com/mesonbuild/meson/issues/11983 - if meson.version().version_compare('>= 1.2.0') and not neon_intrinsics - if (host_cpu == 'armv7') - gastest = ''' - .text - .fpu neon - .arch armv7a - .object_arch armv4 - .arm - pld [r0] - vmovn.u16 d0, q0 - ''' - else - gastest = ''' - .text - MYVAR .req x0 - movi v0.16b, #100 - mov MYVAR, #100 - .unreq MYVAR - ''' - endif - # cc.compiles() can't pass inline assembly to the C compiler - # https://github.com/mesonbuild/meson/issues/12395 - f = configure_file( - command : [ - python, - '-c', - 'import sys; print(sys.argv[1])', - '@0@'.format(gastest), - ], - output : 'gastest.S', - capture : true, - ) - if not cc.compiles( - f, - args : neon_flags, - name : 'can use the partial Neon SIMD intrinsics implementation', - ) - neon_intrinsics = true - endif - endif - - summary('Neon SIMD intrinsics', neon_intrinsics ? 'full' : 'partial') - - if neon_intrinsics - add_project_arguments( - '-DNEON_INTRINSICS', - language : 'c', - ) - simd_src_arm += files('arm/jccolor-neon.c', 'arm/jidctint-neon.c') - endif - - if neon_intrinsics or host_cpu == 'aarch64' - simd_src_arm += files('arm/jidctfst-neon.c') - endif - - if neon_intrinsics or host_cpu == 'arm' - simd_src_arm += files( - dir / 'jchuff-neon.c', - 'arm/jdcolor-neon.c', - 'arm/jfdctint-neon.c', - ) - endif - - if not neon_intrinsics - simd_src_arm += files(dir / 'jsimd_neon.S') - endif - - simd = static_library( - 'simd', - simd_src_arm + files(dir / 'jsimd.c'), - pic : get_option('default_library') != 'static', - include_directories : [incdir, 'arm', dir], - c_args : neon_flags, - ) - endif -elif simd_opt.enabled() - error('SIMD enabled, but CPU family not supported') -endif diff --git a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build b/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build deleted file mode 100644 index b03a0f8..0000000 --- a/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build +++ /dev/null @@ -1,265 +0,0 @@ -jconfig_h = configure_file( - input : 'jconfig.h.in', - output : 'jconfig.h', - format : 'cmake@', - configuration : cdata, -) - -configure_file( - input : 'jconfigint.h.in', - output : 'jconfigint.h', - format : 'cmake@', - configuration : cdata, -) - -configure_file( - input : 'jversion.h.in', - output : 'jversion.h', - format : 'cmake@', - configuration : cdata, -) - -install_headers('jmorecfg.h', 'jerror.h', 'jpeglib.h', jconfig_h) - -sources = files( - 'jcapimin.c', - 'jchuff.c', - 'jcicc.c', - 'jcinit.c', - 'jclhuff.c', - 'jcmarker.c', - 'jcmaster.c', - 'jcomapi.c', - 'jcparam.c', - 'jcphuff.c', - 'jctrans.c', - 'jdapimin.c', - 'jdatadst.c', - 'jdatasrc.c', - 'jdhuff.c', - 'jdicc.c', - 'jdinput.c', - 'jdlhuff.c', - 'jdmarker.c', - 'jdmaster.c', - 'jdphuff.c', - 'jdtrans.c', - 'jerror.c', - 'jfdctflt.c', - 'jmemmgr.c', - 'jmemnobs.c', - 'jpeg_nbits.c', - 'wrapper/jcapistd-12.c', - 'wrapper/jcapistd-16.c', - 'wrapper/jcapistd-8.c', - 'wrapper/jccoefct-12.c', - 'wrapper/jccoefct-8.c', - 'wrapper/jccolor-12.c', - 'wrapper/jccolor-16.c', - 'wrapper/jccolor-8.c', - 'wrapper/jcdctmgr-12.c', - 'wrapper/jcdctmgr-8.c', - 'wrapper/jcdiffct-12.c', - 'wrapper/jcdiffct-16.c', - 'wrapper/jcdiffct-8.c', - 'wrapper/jclossls-12.c', - 'wrapper/jclossls-16.c', - 'wrapper/jclossls-8.c', - 'wrapper/jcmainct-12.c', - 'wrapper/jcmainct-16.c', - 'wrapper/jcmainct-8.c', - 'wrapper/jcprepct-12.c', - 'wrapper/jcprepct-16.c', - 'wrapper/jcprepct-8.c', - 'wrapper/jcsample-12.c', - 'wrapper/jcsample-16.c', - 'wrapper/jcsample-8.c', - 'wrapper/jdapistd-12.c', - 'wrapper/jdapistd-16.c', - 'wrapper/jdapistd-8.c', - 'wrapper/jdcoefct-12.c', - 'wrapper/jdcoefct-8.c', - 'wrapper/jdcolor-12.c', - 'wrapper/jdcolor-16.c', - 'wrapper/jdcolor-8.c', - 'wrapper/jddctmgr-12.c', - 'wrapper/jddctmgr-8.c', - 'wrapper/jddiffct-12.c', - 'wrapper/jddiffct-16.c', - 'wrapper/jddiffct-8.c', - 'wrapper/jdlossls-12.c', - 'wrapper/jdlossls-16.c', - 'wrapper/jdlossls-8.c', - 'wrapper/jdmainct-12.c', - 'wrapper/jdmainct-16.c', - 'wrapper/jdmainct-8.c', - 'wrapper/jdmerge-12.c', - 'wrapper/jdmerge-8.c', - 'wrapper/jdpostct-12.c', - 'wrapper/jdpostct-16.c', - 'wrapper/jdpostct-8.c', - 'wrapper/jdsample-12.c', - 'wrapper/jdsample-16.c', - 'wrapper/jdsample-8.c', - 'wrapper/jfdctfst-12.c', - 'wrapper/jfdctfst-8.c', - 'wrapper/jfdctint-12.c', - 'wrapper/jfdctint-8.c', - 'wrapper/jidctflt-12.c', - 'wrapper/jidctflt-8.c', - 'wrapper/jidctfst-12.c', - 'wrapper/jidctfst-8.c', - 'wrapper/jidctint-12.c', - 'wrapper/jidctint-8.c', - 'wrapper/jidctred-12.c', - 'wrapper/jidctred-8.c', - 'wrapper/jquant1-12.c', - 'wrapper/jquant1-8.c', - 'wrapper/jquant2-12.c', - 'wrapper/jquant2-8.c', - 'wrapper/jutils-12.c', - 'wrapper/jutils-16.c', - 'wrapper/jutils-8.c', -) - -sources += files( - # TODO: `with_arith_dec` / `with_arith_enc` only. - 'jaricom.c', - # TODO: `with_arith_enc` only - 'jcarith.c', - # TODO: `with_arith_dec` only - 'jdarith.c', -) - -jpeg = library( - 'jpeg', - sources, - link_whole : simd, - soversion : so_version, - vs_module_defs : vs_defs, - install : true, -) - -pkg.generate( - jpeg, - description : 'A SIMD-accelerated JPEG codec that provides the libjpeg API', - name : 'libjpeg', -) - -jpeg_dep = declare_dependency( - include_directories : incdir, - link_with : jpeg, -) -meson.override_dependency('libjpeg', jpeg_dep) - -if get_option('turbojpeg').allowed() - install_headers('turbojpeg.h') - - turbojpeg = library( - 'turbojpeg', - sources, - files( - 'jdatadst-tj.c', - 'jdatasrc-tj.c', - 'rdbmp.c', - 'transupp.c', - 'turbojpeg.c', - 'wrapper/rdppm-12.c', - 'wrapper/rdppm-16.c', - 'wrapper/rdppm-8.c', - 'wrapper/wrppm-12.c', - 'wrapper/wrppm-16.c', - 'wrapper/wrppm-8.c', - 'wrbmp.c', - ), - c_args : ['-DBMP_SUPPORTED', '-DPPM_SUPPORTED'], - install : true, - link_whole : simd, - soversion : '0.4.0', - ) - - pkg.generate( - turbojpeg, - description : 'A SIMD-accelerated JPEG codec that provides the TurboJPEG API', - name : 'libturbojpeg', - ) - - turbojpeg_dep = declare_dependency( - include_directories : incdir, - link_with : turbojpeg, - ) - meson.override_dependency('libturbojpeg', turbojpeg_dep) -endif - -if get_option('tests').require( - get_option('turbojpeg').allowed(), - error_message : 'turbojpeg feature needed', -).allowed() - tjunittest = executable( - 'tjunittest', - ['tjunittest.c', 'tjutil.c', 'md5/md5.c', 'md5/md5hl.c'], - dependencies : turbojpeg_dep, - ) - - foreach _test, _args : { - 'tjunittest' : '', - 'tjunittest-alloc' : '-alloc', - 'tjunittest-yuv' : '-yuv', - 'tjunittest-yuv-alloc' : '-yuv -alloc', - 'tjunittest-yuv-nopad' : '-yuv -noyuvpad', - 'tjunittest-lossless' : '-lossless', - 'tjunittest-lossless-alloc' : '-lossless -alloc', - 'tjunittest-bmp' : '-bmp', - 'tjunittest12' : '-precision 12', - 'tjunittest12-alloc' : '-precision 12 -alloc', - 'tjunittest12-lossless' : '-precision 12 -lossless', - 'tjunittest12-lossless-alloc' : '-precision 12 -lossless -alloc', - 'tjunittest12-bmp' : '-precision 12 -bmp', - 'tjunittest2-lossless' : '-precision 2', - 'tjunittest2-lossless-alloc' : '-precision 2 -alloc', - 'tjunittest2-bmp' : '-precision 2 -bmp', - 'tjunittest3-lossless' : '-precision 3', - 'tjunittest3-lossless-alloc' : '-precision 3 -alloc', - 'tjunittest3-bmp' : '-precision 3 -bmp', - 'tjunittest4-lossless' : '-precision 4', - 'tjunittest4-lossless-alloc' : '-precision 4 -alloc', - 'tjunittest4-bmp' : '-precision 4 -bmp', - 'tjunittest5-lossless' : '-precision 5', - 'tjunittest5-lossless-alloc' : '-precision 5 -alloc', - 'tjunittest5-bmp' : '-precision 5 -bmp', - 'tjunittest6-lossless' : '-precision 6', - 'tjunittest6-lossless-alloc' : '-precision 6 -alloc', - 'tjunittest6-bmp' : '-precision 6 -bmp', - 'tjunittest7-lossless' : '-precision 7', - 'tjunittest7-lossless-alloc' : '-precision 7 -alloc', - 'tjunittest7-bmp' : '-precision 7 -bmp', - 'tjunittest9-lossless' : '-precision 9', - 'tjunittest9-lossless-alloc' : '-precision 9 -alloc', - 'tjunittest9-bmp' : '-precision 9 -bmp', - 'tjunittest10-lossless' : '-precision 10', - 'tjunittest10-lossless-alloc' : '-precision 10 -alloc', - 'tjunittest10-bmp' : '-precision 10 -bmp', - 'tjunittest11-lossless' : '-precision 11', - 'tjunittest11-lossless-alloc' : '-precision 11 -alloc', - 'tjunittest11-bmp' : '-precision 11 -bmp', - 'tjunittest13-lossless' : '-precision 13', - 'tjunittest13-lossless-alloc' : '-precision 13 -alloc', - 'tjunittest13-bmp' : '-precision 13 -bmp', - 'tjunittest14-lossless' : '-precision 14', - 'tjunittest14-lossless-alloc' : '-precision 14 -alloc', - 'tjunittest14-bmp' : '-precision 14 -bmp', - 'tjunittest15-lossless' : '-precision 15', - 'tjunittest15-lossless-alloc' : '-precision 15 -alloc', - 'tjunittest15-bmp' : '-precision 15 -bmp', - 'tjunittest16-lossless' : '-precision 16', - 'tjunittest16-lossless-alloc' : '-precision 16 -alloc', - 'tjunittest16-bmp' : '-precision 16 -bmp', - } - test( - _test, - tjunittest, - args : _args.split(), - timeout : 120, - ) - endforeach -endif From d389a82a1cfdc8dfb9d249ac44402861c58892af Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Tue, 24 Feb 2026 22:34:26 +0100 Subject: [PATCH 35/78] chore: remove debug logs --- native/src/mpv/MPV.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/native/src/mpv/MPV.cpp b/native/src/mpv/MPV.cpp index cc82388..158a650 100644 --- a/native/src/mpv/MPV.cpp +++ b/native/src/mpv/MPV.cpp @@ -660,18 +660,13 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createRend {MPV_RENDER_PARAM_API_TYPE, const_cast(MPV_RENDER_API_TYPE_OPENGL)}, }; - const auto test = 12323; - std::cerr << "Creating render context" << test << std::endl; - Display *display{nullptr}; if (const auto glxDisplay = glXGetCurrentDisplay(); glxDisplay != nullptr) { params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, glxDisplay}); - std::cerr << "Using GLX display" << reinterpret_cast(display) << std::endl; } else if (const auto eglDisplay = eglGetCurrentDisplay(); eglDisplay != EGL_NO_DISPLAY) { // Compose always runs on X11 display = XOpenDisplay(nullptr); params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, display}); - std::cerr << "Using X11 display" << reinterpret_cast(display) << std::endl; } JavaVM *jvm; From 00c85a3833d62d3d4a0204768b6252cc8763b48c Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Tue, 24 Feb 2026 22:38:08 +0100 Subject: [PATCH 36/78] fix: make simple test actually simple --- src/test/kotlin/dev/silenium/multimedia/simple/Main.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/test/kotlin/dev/silenium/multimedia/simple/Main.kt b/src/test/kotlin/dev/silenium/multimedia/simple/Main.kt index 0b02a94..8ceb98e 100644 --- a/src/test/kotlin/dev/silenium/multimedia/simple/Main.kt +++ b/src/test/kotlin/dev/silenium/multimedia/simple/Main.kt @@ -20,9 +20,6 @@ suspend fun main() = awaitApplication { } Window(onCloseRequest = this::exitApplication) { - val state = rememberPagerState { 1000 } - VerticalPager(state = state, modifier = Modifier.fillMaxSize(), beyondViewportPageCount = 2) { - VideoPlayer(file = file, suspend = state.currentPage != it, modifier = Modifier.fillMaxSize()) - } + VideoPlayer(file = file, modifier = Modifier.fillMaxSize()) } } From b9119c6c41c320277325499b68828ea3325c235e Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Tue, 24 Feb 2026 22:50:06 +0100 Subject: [PATCH 37/78] build: use fixed ffmpeg build --- .../subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap index f64a0ef..0fce2e1 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap +++ b/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap @@ -1,8 +1,8 @@ [wrap-file] -directory = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0 -source_url = https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz -source_filename = ffmpeg-n8.0-latest-linux64-gpl-shared-8.0.tar.xz -source_hash = 3d7825a52264635213daf92601d368a04e688f364c1d67f69482ba094fd98e75 +directory = ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0 +source_url = https://repoflow.silenium.dev/api/universal/personal/github-releases/BtbN/FFmpeg-Builds/autobuild-2026-02-24-16-00/ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0.tar.xz +source_filename = ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0.tar.xz +source_hash = 10726cb09596035917ec53180d1bf891730aa300a17f4b05020c08f13ad2145e patch_directory = ffmpeg [provide] From 17cbed5469f803877d7632550370997e360676de Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Tue, 24 Feb 2026 22:50:35 +0100 Subject: [PATCH 38/78] build: use nix shell from gradle to avoid having to run entire build inside nix --- native/build.gradle.kts | 36 +++++++++++++++++++++++++-------- flake.lock => native/flake.lock | 6 +++--- flake.nix => native/flake.nix | 4 +++- shell.nix => native/shell.nix | 1 - 4 files changed, 34 insertions(+), 13 deletions(-) rename flake.lock => native/flake.lock (88%) rename flake.nix => native/flake.nix (84%) rename shell.nix => native/shell.nix (99%) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index b64563b..fe48959 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -2,6 +2,7 @@ import dev.silenium.libs.jni.NativeLoader import dev.silenium.libs.jni.NativePlatform import dev.silenium.libs.jni.Platform import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import java.io.Serializable buildscript { repositories { @@ -31,6 +32,21 @@ val javac = tasks.withType().first().javaCompiler.map(JavaCompiler: val javaHome = javac.map { it.asFile.parentFile.parentFile.absolutePath } val mesonExe = findProperty("meson.executable") as? String ?: "meson" val targetDir = layout.buildDirectory.dir("meson").get().asFile.apply { mkdirs() } + +val cleanSubprojects = tasks.register("cleanSubprojects") { + val excludes = setOf("mpv.wrap", "packagefiles") + val subprojectsDir = layout.projectDirectory.dir("subprojects") + doFirst { + val entries = subprojectsDir.asFile.listFiles { it.name !in excludes } ?: emptyArray() + delete(entries) + didWork = entries.isNotEmpty() + } +} + +tasks.clean { + dependsOn(cleanSubprojects) +} + val generateMakefile = tasks.register("generateMakefile") { workingDir = layout.projectDirectory.asFile @@ -39,13 +55,12 @@ val generateMakefile = tasks.register("generateMakefile") { } environment( - "CFLAGS" to "-fPIC", - "CXXFLAGS" to "-fPIC", "JAVA_HOME" to javaHome.get(), ) logger.lifecycle("JAVA_HOME: ${javaHome.get()}") + logger.lifecycle("Meson: $mesonExe") - commandLine( + val mesonCommand = arrayOf( mesonExe, "setup", targetDir.absolutePath, "-Dwrap_mode=forcefallback", @@ -55,20 +70,25 @@ val generateMakefile = tasks.register("generateMakefile") { "-Dmpv:openal=enabled", "-Dmpv:vulkan=disabled", ) + commandLine("nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", *mesonCommand) - inputs.file(layout.projectDirectory.file("meson.build")) - inputs.file(layout.projectDirectory.file("src/meson.build")) + inputs.files("meson.build", "src/main/cpp/meson.build") + inputs.files("flake.nix", "flake.lock", "shell.nix") outputs.dir(targetDir) standardOutput = System.out } val compileNative = tasks.register("compileNative") { - commandLine(mesonExe, "compile", "-C", targetDir) + val mesonCommand = arrayOf( + mesonExe, + "compile", + "-C", + targetDir, + ) + commandLine("nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", *mesonCommand) dependsOn(generateMakefile) environment( - "CFLAGS" to "-fPIC", - "CXXFLAGS" to "-fPIC", "JAVA_HOME" to javaHome.get(), ) diff --git a/flake.lock b/native/flake.lock similarity index 88% rename from flake.lock rename to native/flake.lock index af8f58f..5bbb065 100644 --- a/flake.lock +++ b/native/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1771369470, - "narHash": "sha256-0NBlEBKkN3lufyvFegY4TYv5mCNHbi5OmBDrzihbBMQ=", + "lastModified": 1771848320, + "narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0182a361324364ae3f436a63005877674cf45efb", + "rev": "2fc6539b481e1d2569f25f8799236694180c0993", "type": "github" }, "original": { diff --git a/flake.nix b/native/flake.nix similarity index 84% rename from flake.nix rename to native/flake.nix index f75c280..980b7c9 100644 --- a/flake.nix +++ b/native/flake.nix @@ -9,7 +9,9 @@ outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: - let pkgs = nixpkgs.legacyPackages.${system}; in + let + pkgs = nixpkgs.legacyPackages.${system}; + in { devShells.default = import ./shell.nix { inherit pkgs; }; } diff --git a/shell.nix b/native/shell.nix similarity index 99% rename from shell.nix rename to native/shell.nix index 59c56d3..fc35169 100644 --- a/shell.nix +++ b/native/shell.nix @@ -27,7 +27,6 @@ pkgs.mkShell { hwdata libx11 libva - mesa ]; shellHook = '' From c656eb799ac6f627bd33c1b6f53420b06d8f8999 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Tue, 24 Feb 2026 22:53:39 +0100 Subject: [PATCH 39/78] ci: add missing checkout --- .github/workflows/build.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 585892b..1e034a2 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -19,6 +19,7 @@ jobs: linux-x86_64: runs-on: ubuntu-24.04 steps: + - uses: actions/checkout@v6 - shell: bash name: "Setup build environment" run: | @@ -52,6 +53,7 @@ jobs: kotlin: runs-on: ubuntu-24.04 steps: + - uses: actions/checkout@v6 - uses: silenium-dev/actions/kotlin@main with: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} From 73ec0690cd7982b547e9ebc1c5d487b9180ba9ea Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Tue, 24 Feb 2026 23:05:31 +0100 Subject: [PATCH 40/78] build: replace ci manual dependency install with nix --- .github/workflows/build.yaml | 20 -------------------- native/shell.nix | 12 ++++++++++++ 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1e034a2..083b354 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,26 +20,6 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 - - shell: bash - name: "Setup build environment" - run: | - sudo rm -rf dovi_tool/ || true - sudo apt-get update - sudo apt-get install -y build-essential git pkg-config cmake nasm clang curl python3-pip python3-wheel ninja-build - sudo apt-get install -y libva-dev libdrm-dev libpipewire-0.3-dev libasound-dev libpulse-dev libgl-dev libglx-dev libegl-dev libssl-dev hwdata libsystemd-dev - sudo apt-get remove -y libz3-dev - - sudo pip3 install meson - - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sudo -i sh -s -- -y - sudo -i rustup default stable - sudo -i cargo install cargo-c - - sudo rm -rf dovi_tool && git clone -b 2.3.1 https://github.com/quietvoid/dovi_tool.git - pushd dovi_tool/dolby_vision - sudo -i bash -c "cd $(pwd) && cargo cinstall --release --prefix /usr" - popd - sudo rm -rf dovi_tool/ - uses: silenium-dev/actions/jni-natives/ubuntu@main with: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} diff --git a/native/shell.nix b/native/shell.nix index fc35169..c8e9132 100644 --- a/native/shell.nix +++ b/native/shell.nix @@ -27,6 +27,18 @@ pkgs.mkShell { hwdata libx11 libva + dovi-tool + libdovi + libdrm + libva + pipewire.lib + alsa-lib + libpulseaudio + libGL + egl-wayland + openssl + hwdata + systemdLibs ]; shellHook = '' From 0a651e95ae141ea380165d15e671060c9e7db1b8 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 00:41:20 +0100 Subject: [PATCH 41/78] build: first working native build via gradle --- .run/desktop.run.xml | 21 --- build-logic/build.gradle.kts | 33 ++++ build-logic/settings.gradle.kts | 13 ++ .../silenium/compose/av/build/DownloadFile.kt | 52 +++++++ .../compose/av/build/MesonCompileTask.kt | 65 ++++++++ .../compose/av/build/MesonSetupTask.kt | 69 +++++++++ .../compose/av/build/NativesExtension.kt | 10 ++ .../compose/av/build/NativesPlugin.kt | 63 ++++++++ .../av/build/PrepareSubprojectsTask.kt | 139 +++++++++++++++++ .../compose/av/build/ProjectExtensions.kt | 7 + gradle.properties | 2 + gradle/libs.versions.toml | 18 ++- native/.gitignore | 5 +- native/build.gradle.kts | 144 +----------------- native/cross/linux-arm64.txt | 13 ++ native/cross/linux-x86_64.txt | 12 ++ native/cross/windows-x86_64.txt | 13 ++ native/meson.build | 23 +-- native/shell.nix | 15 +- native/src/helper/errors.cpp | 16 +- native/src/helper/errors.hpp | 15 +- native/src/meson.build | 27 +++- native/src/mpv/MPV.cpp | 31 ++-- native/src/mpv/mpv_linux.cpp | 31 ++++ native/src/mpv/mpv_platform.hpp | 16 ++ native/src/mpv/mpv_windows.cpp | 12 ++ .../linux}/mpv.wrap | 0 .../packagefiles/mpv/subprojects/expat.wrap | 0 .../packagefiles/mpv/subprojects/ffmpeg.wrap | 4 +- .../packagefiles/mpv/subprojects/fmt.wrap | 1 + .../mpv/subprojects/freetype2.wrap | 0 .../packagefiles/mpv/subprojects/fribidi.wrap | 0 .../mpv/subprojects/harfbuzz.wrap | 0 .../packagefiles/mpv/subprojects/libass.wrap | 0 .../mpv/subprojects/libdbus.wrap.disabled | 0 .../mpv/subprojects/libdisplay-info.wrap | 1 + .../mpv/subprojects/libjpeg-turbo.wrap | 0 .../subprojects/libpipewire-0.3.wrap.disabled | 0 .../mpv/subprojects/libplacebo.wrap | 0 .../packagefiles/mpv/subprojects/libpng.wrap | 0 .../mpv/subprojects/libuchardet.wrap | 2 +- .../mpv/subprojects/openal-soft.wrap | 0 .../packagefiles/ffmpeg/collect_versions.sh | 0 .../packagefiles/ffmpeg/meson.build | 0 .../subprojects/packagefiles/fmt/pic.patch | 13 ++ .../libass/subprojects/libfontconfig.wrap | 0 .../packagefiles/libdisplay-info/hwdata.patch | 13 ++ .../libjpeg-turbo-3.1.2/LICENSE.build | 0 .../libjpeg-turbo-3.1.2/meson.build | 0 .../libjpeg-turbo-3.1.2/meson_options.txt | 0 .../libjpeg-turbo-3.1.2/simd/arm/meson.build | 0 .../libjpeg-turbo-3.1.2/simd/meson.build | 0 .../libjpeg-turbo-3.1.2/src/meson.build | 0 .../packagefiles/mpv/subprojects/zlib.wrap | 0 .../windows/packagefiles/mpv/meson.build | 10 ++ .../windows/packagefiles/mpv/meson.options | 3 + settings.gradle.kts | 16 ++ 57 files changed, 705 insertions(+), 223 deletions(-) delete mode 100644 .run/desktop.run.xml create mode 100644 build-logic/build.gradle.kts create mode 100644 build-logic/settings.gradle.kts create mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/DownloadFile.kt create mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt create mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt create mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt create mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt create mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt create mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/ProjectExtensions.kt create mode 100644 native/cross/linux-arm64.txt create mode 100644 native/cross/linux-x86_64.txt create mode 100644 native/cross/windows-x86_64.txt create mode 100644 native/src/mpv/mpv_linux.cpp create mode 100644 native/src/mpv/mpv_platform.hpp create mode 100644 native/src/mpv/mpv_windows.cpp rename native/{subprojects => subprojects.tpl/linux}/mpv.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/expat.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/ffmpeg.wrap (73%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/fmt.wrap (81%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/freetype2.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/fribidi.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/harfbuzz.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/libass.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/libdbus.wrap.disabled (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/libdisplay-info.wrap (71%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/libjpeg-turbo.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/libpipewire-0.3.wrap.disabled (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/libplacebo.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/libpng.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/libuchardet.wrap (86%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/openal-soft.wrap (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/packagefiles/ffmpeg/meson.build (100%) create mode 100644 native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/fmt/pic.patch rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap (100%) create mode 100644 native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libdisplay-info/hwdata.patch rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build (100%) rename native/{subprojects => subprojects.tpl/linux}/packagefiles/mpv/subprojects/zlib.wrap (100%) create mode 100644 native/subprojects.tpl/windows/packagefiles/mpv/meson.build create mode 100644 native/subprojects.tpl/windows/packagefiles/mpv/meson.options diff --git a/.run/desktop.run.xml b/.run/desktop.run.xml deleted file mode 100644 index 40830f1..0000000 --- a/.run/desktop.run.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - true - - - diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts new file mode 100644 index 0000000..9c64596 --- /dev/null +++ b/build-logic/build.gradle.kts @@ -0,0 +1,33 @@ +plugins { + `kotlin-dsl` + `java-gradle-plugin` +} + +repositories { + maven("https://reposilite.silenium.dev/releases") { + name = "silenium-releases" + } + google() + mavenCentral() + gradlePluginPortal() +} + +dependencies { + implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) + api(libs.bundles.gradle.plugins) + libs.bundles.kotlin.plugins.get().forEach { + api(variantOf(provider { it }) { + classifier("gradle813") + }) + } + api(libs.jni.utils) +} + +gradlePlugin { + plugins { + register("natives") { + id = "av-natives" + implementationClass = "dev.silenium.compose.av.build.NativesPlugin" + } + } +} diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 0000000..792f951 --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,13 @@ +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } + + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/DownloadFile.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/DownloadFile.kt new file mode 100644 index 0000000..d1500bb --- /dev/null +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/DownloadFile.kt @@ -0,0 +1,52 @@ +package dev.silenium.compose.av.build + +import org.gradle.api.logging.Logger +import org.gradle.internal.logging.progress.ProgressLogger +import java.io.OutputStream +import java.net.URI +import kotlin.time.Clock +import kotlin.time.Duration.Companion.seconds +import kotlin.time.ExperimentalTime + +@OptIn(ExperimentalTime::class) +fun downloadFile(progressLogger: ProgressLogger, logger: Logger, uri: URI, outputStream: OutputStream) { + try { + val conn = uri.toURL().openConnection() + conn.connect() + val size = conn.contentLengthLong + progressLogger.progress("${size.toMB()} MB") + + var downloaded = 0L + var lastLog = Clock.System.now() + val buf = ByteArray(1024) + conn.inputStream.use { input -> + while (true) { + if (Thread.currentThread().isInterrupted) { + throw InterruptedException("Download interrupted") + } + val read = input.read(buf) + if (read == -1) break + outputStream.write(buf, 0, read) + + downloaded += read + if (downloaded > 0) { + progressLogger.progress("${downloaded.toMB()} MB / ${size.toMB()} MB (${downloaded partOf size}%)") + } else { + progressLogger.progress("${size.toMB()} MB") + } + val now = Clock.System.now() + if (now - lastLog > 1.seconds) { + lastLog = now + logger.lifecycle("${progressLogger.description}: ${downloaded.toMB()} MB / ${size.toMB()} MB (${downloaded partOf size}%)") + } + } + } + progressLogger.completed() + logger.lifecycle("${progressLogger.description}: ${downloaded.toMB()} MB / ${size.toMB()} MB (${downloaded partOf size}%)") + } catch (e: Exception) { + progressLogger.completed(e.message ?: "Unknown error", true) + } +} + +private fun Long.toMB() = this / 1024 / 1024 +private infix fun Long.partOf(full: Long) = (this * 100) / full diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt new file mode 100644 index 0000000..8f39bf4 --- /dev/null +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt @@ -0,0 +1,65 @@ +package dev.silenium.compose.av.build + +import dev.silenium.libs.jni.NativeLoader +import dev.silenium.libs.jni.Platform +import org.gradle.api.file.Directory +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFile +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.internal.file.FileFactory +import org.gradle.api.internal.file.FilePropertyFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Exec +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.OutputFile +import org.gradle.kotlin.dsl.environment +import java.io.File +import javax.inject.Inject + +abstract class MesonCompileTask : Exec() { + @get:Inject + abstract val fileFactory: FileFactory + + @get:Input + abstract val targetDir: Property + + @get:InputDirectory + abstract val sourceDir: DirectoryProperty + + @get:Input + abstract val javaHome: Property + + @get:Input + abstract val platform: Property + + @get:Input + abstract val libName: Property + + @get:OutputFile + abstract val libPath: RegularFileProperty + + init { + libPath.convention( + targetDir.zip( + platform.zip(libName) { platform, libName -> + val fileNameTemplate = NativeLoader.fileNameTemplate(platform) + "src/${fileNameTemplate.format(libName)}" + } + ) { targetDir, path -> targetDir.resolve(path) } + .map(fileFactory::file)) + inputs.file(targetDir.map { it.resolve("build.ninja") }) + outputs.file(libPath) + } + + override fun exec() { + environment( + "JAVA_HOME" to javaHome.get().absolutePath, + ) + commandLine( + "nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", + "meson", "compile", "-C", targetDir.get().absolutePath, libName.get(), + ) + super.exec() + } +} diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt new file mode 100644 index 0000000..cae6179 --- /dev/null +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt @@ -0,0 +1,69 @@ +package dev.silenium.compose.av.build + +import dev.silenium.libs.jni.NativePlatform +import dev.silenium.libs.jni.Platform +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Exec +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputDirectory +import org.gradle.kotlin.dsl.environment +import java.io.File +import java.io.Serializable + +abstract class MesonSetupTask : Exec() { + @get:Input + abstract val targetDir: Property + + @get:Input + abstract val javaHome: Property + + @get:Input + abstract val platform: Property + + init { + inputs.file("meson.build") + val outputDirs = listOf( + "meson-info", + ) + val outputFiles = listOf( + "build.ninja", + "platform.txt", + ) + outputFiles.forEach { file -> + outputs.file(targetDir.map { it.resolve(file) }) + } + outputDirs.forEach { dir -> + outputs.dir(targetDir.map { it.resolve(dir) }) + } + } + + override fun exec() { + logger.lifecycle("JAVA_HOME: ${javaHome.get()}") + environment( + "JAVA_HOME" to javaHome.get().absolutePath, + ) + + val platformFile = targetDir.get().resolve("platform.txt") + if (platformFile.exists() && platformFile.readText() != platform.get().full) { + targetDir.get().deleteRecursively() + } + + val crossArgs = arrayOf("--cross-file", "cross/${platform.get().osArch}.txt") + + val mesonCommand = arrayOf( + "nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", + "meson", "setup", + "--wipe", + targetDir.get().absolutePath, + *crossArgs, + ) + commandLine(*mesonCommand) + + logger.lifecycle("Executing Meson setup: ${commandLine.joinToString()}") + + super.exec() + + platformFile.writeText(platform.get().full) + } +} diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt new file mode 100644 index 0000000..16af2a8 --- /dev/null +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt @@ -0,0 +1,10 @@ +package dev.silenium.compose.av.build + +import dev.silenium.libs.jni.Platform +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property + +interface NativesExtension { + val platform: Property + val libName: Property +} diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt new file mode 100644 index 0000000..10c3c6d --- /dev/null +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt @@ -0,0 +1,63 @@ +package dev.silenium.compose.av.build + +import dev.silenium.libs.jni.NativePlatform +import org.gradle.api.JavaVersion +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.file.Directory +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.jvm.toolchain.JavaCompiler +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.register +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmExtension +import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper + +class NativesPlugin : Plugin { + override fun apply(target: Project) { + target.apply() + target.configure { + compilerOptions.jvmTarget.set(JvmTarget.JVM_17) + } + target.configure { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + val ext = target.extensions.create("natives", NativesExtension::class.java) + ext.platform.convention(target.provider(NativePlatform::platform)) + val tmpDir = target.layout.buildDirectory.dir("tmp/natives") + val targetDir = target.layout.buildDirectory.dir("natives") + val prepareSubprojects = target.tasks.register("prepareSubprojects") { + doFirst { + tmpDir.get().asFile.deleteRecursively() + tmpDir.get().asFile.mkdirs() + } + downloadDir.set(tmpDir) + platform.set(ext.platform) + } + + val javac = target.tasks.withType().first().javaCompiler.map(JavaCompiler::getExecutablePath) + val javaHome = javac.map { it.asFile.parentFile.parentFile } + val mesonSetup = target.tasks.register("mesonSetup") { + dependsOn(prepareSubprojects) + this.targetDir.set(targetDir.map(Directory::getAsFile)) + this.platform.set(ext.platform) + this.javaHome.set(javaHome) + + inputs.dir(target.layout.projectDirectory.dir("subprojects.tpl")) + } + + val mesonCompile = target.tasks.register("mesonCompile") { + dependsOn(mesonSetup) + this.targetDir.set(targetDir.map(Directory::getAsFile)) + this.platform.set(ext.platform) + this.libName.set(ext.libName) + this.javaHome.set(javaHome) + this.sourceDir.set(target.layout.projectDirectory.dir("src")) + } + } +} diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt new file mode 100644 index 0000000..9a9036a --- /dev/null +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt @@ -0,0 +1,139 @@ +package dev.silenium.compose.av.build + +import dev.silenium.libs.jni.Platform +import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.FileSystemOperations +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import org.gradle.internal.logging.progress.ProgressLoggerFactory +import org.gradle.internal.operations.BuildOperationDescriptor +import org.gradle.process.ExecOperations +import org.jetbrains.kotlin.org.apache.commons.codec.digest.DigestUtils +import java.net.URI +import java.nio.file.Files +import javax.inject.Inject +import kotlin.io.path.deleteIfExists + +abstract class PrepareSubprojectsTask : DefaultTask() { + @get:Inject + abstract val execOps: ExecOperations + + @get:Inject + abstract val fsOps: FileSystemOperations + + @get:Inject + abstract val progressLoggerFactory: ProgressLoggerFactory + + @get:Input + abstract val platform: Property + + @get:Internal + abstract val downloadDir: DirectoryProperty + + @get:Internal + abstract val mpvDlFile: RegularFileProperty + + @get:OutputDirectory + abstract val subprojectDir: DirectoryProperty + + @get:Internal + abstract val packageCacheDir: DirectoryProperty + + @get:InputDirectory + abstract val subprojectTplDir: DirectoryProperty + + init { + mpvDlFile.convention(downloadDir.zip(platform) { dir, p -> dir.file("mpv-win-${p.arch}.7z") }) + subprojectDir.convention(project.layout.projectDirectory.dir("subprojects")) + subprojectTplDir.convention(project.layout.projectDirectory.dir("subprojects.tpl")) + packageCacheDir.convention(project.layout.buildDirectory.dir("packagecache")) + +// outputs.file(platform.map { p -> mpvDlFile.takeIf { p.os == Platform.OS.WINDOWS } }) + outputs.dir(subprojectDir) + inputs.dir(subprojectTplDir) + } + + @TaskAction + fun prepare() { + val cacheLink = subprojectDir.get().asFile.toPath().resolve("packagecache") + cacheLink.deleteIfExists() + downloadDir.get().asFile.mkdirs() + subprojectDir.get().asFile.deleteRecursively() + subprojectDir.get().asFile.mkdirs() + when (platform.get().os) { + Platform.OS.WINDOWS -> { + downloadMpvWindows() + extractMpvSubproject() + configureMpvSubproject() + } + + Platform.OS.LINUX -> { + copySubprojects(platform.get()) + } + + else -> Unit + } + packageCacheDir.get().asFile.mkdirs() + Files.createSymbolicLink(cacheLink, packageCacheDir.get().asFile.toPath()) + } + + private fun copySubprojects(platform: Platform) { + fsOps.copy { + from(subprojectTplDir.dir(platform.os.toString())) + into(subprojectDir) + } + } + + private fun downloadMpvWindows() { + val meta = mpvWindows[platform.get().arch] ?: error("Unsupported platform: ${platform.get().arch}") + val file = mpvDlFile.get().asFile + if (file.exists() && file.inputStream().use(DigestUtils::sha256Hex) == meta.fileHash) { + return logger.lifecycle("MPV Windows binaries are up-to-date") + } + + val progressLogger = progressLoggerFactory.newOperation(PrepareSubprojectsTask::class.java) + progressLogger.start("Downloading MPV Windows binaries", "") + + file.outputStream().use { output -> + downloadFile(progressLogger, logger, meta.uri, output) + } + } + + private fun extractMpvSubproject() { + execOps.exec { + commandLine( + "nix-shell", "-p", "p7zip", "--command", + "7z x -o${subprojectDir.dir("mpv").get().asFile.absolutePath} ${mpvDlFile.get().asFile.absolutePath}", + ) + }.assertNormalExitValue() + } + + private fun configureMpvSubproject() { + fsOps.copy { + from(subprojectTplDir.dir("${platform.get().os}/packagefiles/mpv")) + into(subprojectDir.dir("mpv")) + } + } +} + +internal data class MpvWindowsMetadata(val arch: String, val fileHash: String) { + val uri: URI by lazy { URI.create("https://github.com/shinchiro/mpv-winbuild-cmake/releases/download/20260225/mpv-dev-${arch}-20260225-git-92ed2d2.7z") } +} + +internal val mpvWindows = mapOf( + Platform.Arch.X86 to MpvWindowsMetadata("i686", "c3f25283f7c5ec3eb718fb9a1b686f714744c04559e8aaa2e691bc8e49552c71"), + Platform.Arch.ARM64 to MpvWindowsMetadata( + "aarch64", + "783b60c8ca94eda76596f2b355f860f35dffe6f56aa2e3762f2fc7fd3f7304d2" + ), + Platform.Arch.X86_64 to MpvWindowsMetadata( + "x86_64", + "5d266a6899b8bb175a6857c93c53679f040953167a2bed65b83edb03e0b48b65" + ), +) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/ProjectExtensions.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/ProjectExtensions.kt new file mode 100644 index 0000000..13291e6 --- /dev/null +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/ProjectExtensions.kt @@ -0,0 +1,7 @@ +package dev.silenium.compose.av.build + +import org.gradle.accessors.dm.LibrariesForLibs +import org.gradle.api.Project +import org.gradle.kotlin.dsl.the + +val Project.libs get() = the() diff --git a/gradle.properties b/gradle.properties index 2ddb726..39eede6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,4 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 kotlin.code.style=official +org.gradle.configuration-cache=true +org.gradle.caching=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b9feb3e..53db166 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kotlinx-datetime = "0.7.1" compose = "1.11.0-alpha02" compose-gl = "0.9.1" -jni-utils = "0.1.7" +jni-utils = "0.1.8" jna = "5.18.1" slf4j = "2.0.17" @@ -53,6 +53,12 @@ kotest-assertions-json = { group = "io.kotest", name = "kotest-assertions-json", mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } +compose-gradle-plugin = { group = "org.jetbrains.compose", name = "compose-gradle-plugin", version.ref = "compose" } +kotlin-jvm-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } +kotlin-compose-gradle-plugin = { group = "org.jetbrains.kotlin", name = "compose-compiler-gradle-plugin", version.ref = "kotlin" } +kotlin-serialization-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-serialization", version.ref = "kotlin" } +idea-ext = { group = "org.jetbrains.gradle.plugin.idea-ext", name = "org.jetbrains.gradle.plugin.idea-ext.gradle.plugin", version.ref = "idea-ext" } + [plugins] kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } @@ -79,3 +85,13 @@ kotest = [ "kotest-assertions-core", "kotest-assertions-json", ] + +kotlin-plugins = [ + "kotlin-jvm-gradle-plugin", + "kotlin-compose-gradle-plugin", + "kotlin-serialization-gradle-plugin", +] +gradle-plugins = [ + "compose-gradle-plugin", + "idea-ext", +] diff --git a/native/.gitignore b/native/.gitignore index 0168cd3..c4988be 100644 --- a/native/.gitignore +++ b/native/.gitignore @@ -1,8 +1,5 @@ .idea/ *.iml cmake-build-*/ -/subprojects/* -!/subprojects/mpv.wrap -!/subprojects/packagefiles -!/subprojects/packagefiles/* +/subprojects buildDir/ diff --git a/native/build.gradle.kts b/native/build.gradle.kts index fe48959..65df6fd 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -1,144 +1,10 @@ -import dev.silenium.libs.jni.NativeLoader import dev.silenium.libs.jni.NativePlatform -import dev.silenium.libs.jni.Platform -import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import java.io.Serializable - -buildscript { - repositories { - maven("https://reposilite.silenium.dev/releases") { - name = "silenium-releases" - } - } - dependencies { - classpath(libs.jni.utils) - } -} plugins { - alias(libs.plugins.kotlin) - `maven-publish` -} - -val libName = rootProject.name -val deployNative = (findProperty("deploy.native") as String?)?.toBoolean() ?: true - -val withGPL: Boolean = findProperty("ffmpeg.gpl").toString().toBoolean() -val platformExtension = "-gpl".takeIf { withGPL }.orEmpty() -val platformString = findProperty("ffmpeg.platform")?.toString() -val platform = platformString?.let { Platform(it, platformExtension) } ?: NativePlatform.platform(platformExtension) - -val javac = tasks.withType().first().javaCompiler.map(JavaCompiler::getExecutablePath) -val javaHome = javac.map { it.asFile.parentFile.parentFile.absolutePath } -val mesonExe = findProperty("meson.executable") as? String ?: "meson" -val targetDir = layout.buildDirectory.dir("meson").get().asFile.apply { mkdirs() } - -val cleanSubprojects = tasks.register("cleanSubprojects") { - val excludes = setOf("mpv.wrap", "packagefiles") - val subprojectsDir = layout.projectDirectory.dir("subprojects") - doFirst { - val entries = subprojectsDir.asFile.listFiles { it.name !in excludes } ?: emptyArray() - delete(entries) - didWork = entries.isNotEmpty() - } -} - -tasks.clean { - dependsOn(cleanSubprojects) -} - -val generateMakefile = tasks.register("generateMakefile") { - workingDir = layout.projectDirectory.asFile - - doFirst { - delete(targetDir) - } - - environment( - "JAVA_HOME" to javaHome.get(), - ) - logger.lifecycle("JAVA_HOME: ${javaHome.get()}") - logger.lifecycle("Meson: $mesonExe") - - val mesonCommand = arrayOf( - mesonExe, "setup", - targetDir.absolutePath, - "-Dwrap_mode=forcefallback", - "-Ddefault_library=static", - "-Dprefer_static=true", - "-Dmpv:drm=enabled", - "-Dmpv:openal=enabled", - "-Dmpv:vulkan=disabled", - ) - commandLine("nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", *mesonCommand) - - inputs.files("meson.build", "src/main/cpp/meson.build") - inputs.files("flake.nix", "flake.lock", "shell.nix") - outputs.dir(targetDir) - standardOutput = System.out -} - -val compileNative = tasks.register("compileNative") { - val mesonCommand = arrayOf( - mesonExe, - "compile", - "-C", - targetDir, - ) - commandLine("nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", *mesonCommand) - dependsOn(generateMakefile) - - environment( - "JAVA_HOME" to javaHome.get(), - ) - - standardOutput = System.out - val fileNameTemplate = NativeLoader.fileNameTemplate(platform) - outputs.files(layout.buildDirectory.file("meson/src/${fileNameTemplate.format(libName)}")) - inputs.file(layout.buildDirectory.file("meson/build.ninja")) - inputs.dir(layout.projectDirectory.dir("src")) - inputs.file(layout.projectDirectory.file("meson.build")) - outputs.cacheIf { true } -} - -tasks.processResources { - dependsOn(compileNative) - // Required for configuration cache - val libName = rootProject.name - val platformString = findProperty("ffmpeg.platform")?.toString() - val withGPL: Boolean = findProperty("ffmpeg.gpl").toString().toBoolean() - val platformExtension = "-gpl".takeIf { withGPL }.orEmpty() - val platform = platformString?.let { Platform(it, platformExtension) } ?: NativePlatform.platform(platformExtension) - - from(compileNative.get().outputs.files) { - rename { - NativeLoader.libPath(libName, platform = platform) - } - } -} - -kotlin { - compilerOptions { - freeCompilerArgs.add("-Xcontext-receivers") - jvmTarget = JvmTarget.JVM_11 - } + id("av-natives") } -java { - sourceCompatibility = kotlin.compilerOptions.jvmTarget.map { JavaVersion.toVersion(it.target) }.get() - targetCompatibility = sourceCompatibility - - withSourcesJar() - withJavadocJar() -} - -publishing { - publications { - if (deployNative) { - create("natives${platform.capitalized}") { - from(components["java"]) - artifactId = "$libName-natives-$platform" - } - } - } -} +natives { + libName = "compose-av" + platform = NativePlatform.platform() +} \ No newline at end of file diff --git a/native/cross/linux-arm64.txt b/native/cross/linux-arm64.txt new file mode 100644 index 0000000..01749f7 --- /dev/null +++ b/native/cross/linux-arm64.txt @@ -0,0 +1,13 @@ +[binaries] +c = 'aarch64-unknown-linux-gcc' +cpp = 'aarch64-unknown-linux-g++' +ar = 'aarch64-unknown-linux-gnu-ar' +windres = 'aarch64-unknown-linux-gnu-windres' +strip = 'aarch64-unknown-linux-gnu-strip' +exe_wrapper = 'qemu-aarch64' + +[host_machine] +system = 'linux' +cpu_family = 'aarch64' +cpu = 'aarch64' +endian = 'little' diff --git a/native/cross/linux-x86_64.txt b/native/cross/linux-x86_64.txt new file mode 100644 index 0000000..682ed1d --- /dev/null +++ b/native/cross/linux-x86_64.txt @@ -0,0 +1,12 @@ +[binaries] +c = 'gcc' +cpp = 'g++' +ar = 'ar' +strip = 'strip' +pkgconfig = 'pkg-config' + +[host_machine] +system = 'linux' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' diff --git a/native/cross/windows-x86_64.txt b/native/cross/windows-x86_64.txt new file mode 100644 index 0000000..22bee5b --- /dev/null +++ b/native/cross/windows-x86_64.txt @@ -0,0 +1,13 @@ +[binaries] +c = 'x86_64-w64-mingw32-gcc' +cpp = 'x86_64-w64-mingw32-g++' +ar = 'x86_64-w64-mingw32-ar' +windres = 'x86_64-w64-mingw32-windres' +strip = 'x86_64-w64-mingw32-strip' +exe_wrapper = 'wine64' + +[host_machine] +system = 'windows' +cpu_family = 'x86_64' +cpu = 'x86_64' +endian = 'little' diff --git a/native/meson.build b/native/meson.build index f87e35d..627707b 100644 --- a/native/meson.build +++ b/native/meson.build @@ -1,23 +1,26 @@ project('compose-av', 'cpp', 'java', default_options : { - 'cpp_std' : 'c++20', - 'wrap_mode' : 'forcefallback', - } + 'cpp_std' : 'c++20', + 'wrap_mode' : 'forcefallback', + }, + meson_version : '>=1.2.0', ) + add_global_arguments('-fPIC', language : 'c') add_global_arguments('-fPIC', language : 'cpp') add_global_link_arguments( - language : 'cpp', + language : 'cpp', ) + mpv = subproject('mpv', default_options : { - 'libmpv' : true, - 'drm' : 'enabled', - 'openal' : 'enabled', - 'wrap_mode' : 'forcefallback', - 'default_library' : 'static', - 'prefer_static' : true, + 'libmpv' : true, + 'drm' : 'enabled', + 'openal' : 'enabled', + 'wrap_mode' : 'forcefallback', + 'default_library' : 'static', + 'prefer_static' : true, } ) subdir('src') diff --git a/native/shell.nix b/native/shell.nix index c8e9132..5c413e1 100644 --- a/native/shell.nix +++ b/native/shell.nix @@ -9,6 +9,12 @@ pkgs.mkShell { # C/C++ Build Toolchain cmake + gcc + gdb + binutils-unwrapped + pkgsCross.mingwW64.gcc + pkgsCross.mingwW64.gdb + pkgsCross.mingwW64.binutils-unwrapped pkgsCross.aarch64-multiplatform.gcc pkgsCross.aarch64-multiplatform.binutils-unwrapped ninja @@ -18,27 +24,29 @@ pkgs.mkShell { # Additional utilities git python3 + wineWow64Packages.staging + qemu-user + perl ]; buildInputs = with pkgs; [ # Libraries libGL mesa-gl-headers libdrm - hwdata libx11 libva dovi-tool libdovi libdrm libva - pipewire.lib + pipewire alsa-lib libpulseaudio libGL egl-wayland openssl - hwdata systemdLibs + hwdata ]; shellHook = '' @@ -52,5 +60,6 @@ pkgs.mkShell { # Set environment variables JAVA_HOME = "${pkgs.jdk21}"; + HWDATA_PATH = "${pkgs.hwdata}"; CMAKE_GENERATOR = "Ninja"; } diff --git a/native/src/helper/errors.cpp b/native/src/helper/errors.cpp index 3774fdf..3ff14d9 100644 --- a/native/src/helper/errors.cpp +++ b/native/src/helper/errors.cpp @@ -8,25 +8,25 @@ #include #include -jobject boxedLong(JNIEnv *env, const long value) { +jobject boxedLong(JNIEnv *env, const jlong value) { const auto boxedClass = env->FindClass("java/lang/Long"); const auto constructor = env->GetMethodID(boxedClass, "", "(J)V"); return env->NewObject(boxedClass, constructor, value); } -jobject boxedDouble(JNIEnv *env, const double value) { +jobject boxedDouble(JNIEnv *env, const jdouble value) { const auto boxedClass = env->FindClass("java/lang/Double"); const auto constructor = env->GetMethodID(boxedClass, "", "(D)V"); return env->NewObject(boxedClass, constructor, value); } -jobject boxedBool(JNIEnv *env, const bool value) { +jobject boxedBool(JNIEnv *env, const jboolean value) { const auto boxedClass = env->FindClass("java/lang/Boolean"); const auto constructor = env->GetMethodID(boxedClass, "", "(Z)V"); return env->NewObject(boxedClass, constructor, value); } -jobject boxedInt(JNIEnv *env, const int value) { +jobject boxedInt(JNIEnv *env, const jint value) { const auto boxedClass = env->FindClass("java/lang/Integer"); const auto constructor = env->GetMethodID(boxedClass, "", "(I)V"); return env->NewObject(boxedClass, constructor, value); @@ -38,13 +38,13 @@ jobject pair(JNIEnv *env, jobject first, jobject second) { return env->NewObject(pairClass, constructor, first, second); } -jobject resultSuccess(JNIEnv *env, const long value, const long secondValue) { +jobject resultSuccess(JNIEnv *env, const jlong value, const jlong secondValue) { const auto boxed = boxedLong(env, value); const auto boxed2 = boxedLong(env, secondValue); return pair(env, boxed, boxed2); } -jobject resultSuccess(JNIEnv *env, const long value) { +jobject resultSuccess(JNIEnv *env, const jlong value) { const auto boxed = boxedLong(env, value); return boxed; } @@ -53,12 +53,12 @@ jobject resultSuccess(JNIEnv *env, const char *value) { return env->NewStringUTF(value); } -jobject resultSuccess(JNIEnv *env, const double value) { +jobject resultSuccess(JNIEnv *env, const jdouble value) { const auto boxed = boxedDouble(env, value); return boxed; } -jobject resultSuccess(JNIEnv *env, const bool value) { +jobject resultSuccess(JNIEnv *env, const jboolean value) { const auto boxed = boxedBool(env, value); return boxed; } diff --git a/native/src/helper/errors.hpp b/native/src/helper/errors.hpp index 397aab5..f9dac0a 100644 --- a/native/src/helper/errors.hpp +++ b/native/src/helper/errors.hpp @@ -7,24 +7,25 @@ #include #include +#include std::string avErrorString(int error); -jobject boxedLong(JNIEnv *env, long value); +jobject boxedLong(JNIEnv *env, jlong value); -jobject boxedInt(JNIEnv *env, int value); +jobject boxedInt(JNIEnv *env, jint value); jobject pair(JNIEnv *env, jobject first, jobject second); -jobject resultSuccess(JNIEnv *env, long value, long secondValue); -jobject resultSuccess(JNIEnv *env, long value); +jobject resultSuccess(JNIEnv *env, jlong value, jlong secondValue); +jobject resultSuccess(JNIEnv *env, jlong value); jobject resultSuccess(JNIEnv *env, const char *value); -jobject resultSuccess(JNIEnv *env, double value); -jobject resultSuccess(JNIEnv *env, bool value); +jobject resultSuccess(JNIEnv *env, jdouble value); +jobject resultSuccess(JNIEnv *env, jboolean value); jobject resultSuccess(JNIEnv *env); jobject resultSuccessNull(); jobject eglResultFailure(JNIEnv *env, const char *operation, long returnCode); -jobject glResultFailure(JNIEnv *env, const char *operation, uint returnCode); +jobject glResultFailure(JNIEnv *env, const char *operation, GLenum returnCode); jobject vaResultFailure(JNIEnv *env, const char *operation, int returnCode); diff --git a/native/src/meson.build b/native/src/meson.build index b860e92..0a4595e 100644 --- a/native/src/meson.build +++ b/native/src/meson.build @@ -1,15 +1,32 @@ mpv_dep = mpv.get_variable('libmpv_dep') jni = dependency('jni') -egl = dependency('egl') -glx = dependency('glx') -x11 = dependency('X11') -shared_library( +deps = [jni, mpv_dep] + +sources = [ 'compose-av', 'util/Errors.cpp', 'helper/errors.hpp', 'helper/errors.cpp', 'mpv/MPV.cpp', - dependencies : [jni, egl, glx, x11, mpv_dep], + 'mpv/mpv_platform.hpp', +] + +os = host_machine.system() +if os == 'linux' + egl = dependency('egl') + glx = dependency('glx') + x11 = dependency('x11') + deps += [egl, glx, x11] + sources += ['mpv/mpv_linux.cpp'] +elif os == 'windows' + sources += ['mpv/mpv_windows.cpp'] + gl = dependency('OpenGL32') + deps += [gl] +endif + +shared_library( + sources, + dependencies : deps, cpp_args : ['-Wimplicit-fallthrough'], ) diff --git a/native/src/mpv/MPV.cpp b/native/src/mpv/MPV.cpp index 158a650..2d36b76 100644 --- a/native/src/mpv/MPV.cpp +++ b/native/src/mpv/MPV.cpp @@ -3,12 +3,9 @@ // #include "helper/errors.hpp" +#include "mpv_platform.hpp" - -#include #include -#include -#include #include #include #include @@ -20,7 +17,6 @@ #include #include -#include #include #include @@ -271,7 +267,7 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createN(JN if (handle == nullptr) { return mpvResultFailure(env, "mpv_create", MPV_ERROR_NOMEM); } - return resultSuccess(env, reinterpret_cast(handle)); + return resultSuccess(env, reinterpret_cast(handle)); } JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_destroyN( @@ -306,7 +302,7 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_setCallbac std::thread eventLoopThread{mpv_event_loop, ctx}; ctx->eventLoop = std::move(eventLoopThread); - return resultSuccess(env, reinterpret_cast(ctx)); + return resultSuccess(env, reinterpret_cast(ctx)); } JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_unsetCallbackN( @@ -445,7 +441,7 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyLongN( JNIEnv *env, jobject thiz, const jlong handle, jstring name) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - long value; + jlong value; const auto ret = mpv_get_property(reinterpret_cast(handle), nameStr, MPV_FORMAT_INT64, &value); env->ReleaseStringUTFChars(name, nameStr); if (ret == MPV_ERROR_PROPERTY_UNAVAILABLE) { @@ -475,7 +471,7 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropert JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_getPropertyFlagN( JNIEnv *env, jobject thiz, const jlong handle, jstring name) { const char *nameStr = env->GetStringUTFChars(name, nullptr); - bool value; + jboolean value; const auto ret = mpv_get_property(reinterpret_cast(handle), nameStr, MPV_FORMAT_FLAG, &value); env->ReleaseStringUTFChars(name, nameStr); if (ret == MPV_ERROR_PROPERTY_UNAVAILABLE) { @@ -650,7 +646,7 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_initialize struct RenderContext { mpv_render_context *handle; jobject gref; - Display *display; + std::shared_ptr platformContext; }; // Rendering @@ -660,14 +656,7 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createRend {MPV_RENDER_PARAM_API_TYPE, const_cast(MPV_RENDER_API_TYPE_OPENGL)}, }; - Display *display{nullptr}; - if (const auto glxDisplay = glXGetCurrentDisplay(); glxDisplay != nullptr) { - params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, glxDisplay}); - } else if (const auto eglDisplay = eglGetCurrentDisplay(); eglDisplay != EGL_NO_DISPLAY) { - // Compose always runs on X11 - display = XOpenDisplay(nullptr); - params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, display}); - } + const auto platformContext = populatePlatformMpvParams(env, params); JavaVM *jvm; if (const auto ret = env->GetJavaVM(&jvm); ret != JNI_OK) { @@ -712,7 +701,7 @@ JNIEXPORT jobject JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_createRend env->DeleteGlobalRef(object); return mpvResultFailure(env, "mpv_render_context_create", ret); } - const auto ctx = new RenderContext{handle, object, display}; + const auto ctx = new RenderContext{handle, object, std::move(platformContext)}; mpv_render_context_set_update_callback( handle, fnptr([jvm](void *opaque) { @@ -741,9 +730,7 @@ JNIEXPORT void JNICALL Java_dev_silenium_multimedia_core_mpv_MPVKt_destroyRender const auto context = reinterpret_cast(handle); mpv_render_context_free(context->handle); env->DeleteGlobalRef(context->gref); - if (context->display != nullptr) { - XCloseDisplay(context->display); - } + context->platformContext.reset(); delete context; } diff --git a/native/src/mpv/mpv_linux.cpp b/native/src/mpv/mpv_linux.cpp new file mode 100644 index 0000000..abe29cd --- /dev/null +++ b/native/src/mpv/mpv_linux.cpp @@ -0,0 +1,31 @@ +#include "mpv_platform.hpp" + +#include +#include + +class LinuxMpvPlatformContext : public MpvPlatformContext { +public: + explicit LinuxMpvPlatformContext(Display *x_display) : display(x_display) { + } + + ~LinuxMpvPlatformContext() override { + if (display != nullptr) { + XCloseDisplay(display); + } + } + +private: + Display *display; +}; + +std::shared_ptr populatePlatformMpvParams(JNIEnv *env, std::vector ¶ms) { + Display *display{nullptr}; + if (const auto glxDisplay = glXGetCurrentDisplay(); glxDisplay != nullptr) { + params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, glxDisplay}); + } else if (const auto eglDisplay = eglGetCurrentDisplay(); eglDisplay != EGL_NO_DISPLAY) { + // Compose always runs on X11 + display = XOpenDisplay(nullptr); + params.push_back({MPV_RENDER_PARAM_X11_DISPLAY, display}); + } + return std::make_shared(display); +} diff --git a/native/src/mpv/mpv_platform.hpp b/native/src/mpv/mpv_platform.hpp new file mode 100644 index 0000000..51e6818 --- /dev/null +++ b/native/src/mpv/mpv_platform.hpp @@ -0,0 +1,16 @@ +#ifndef NATIVE_MPV_PLATFORM_HPP +#define NATIVE_MPV_PLATFORM_HPP + +#include +#include +#include +#include + +class MpvPlatformContext { +public: + virtual ~MpvPlatformContext() = default; +}; + +std::shared_ptr populatePlatformMpvParams(JNIEnv *env, std::vector ¶ms); + +#endif //NATIVE_MPV_PLATFORM_HPP diff --git a/native/src/mpv/mpv_windows.cpp b/native/src/mpv/mpv_windows.cpp new file mode 100644 index 0000000..5fac235 --- /dev/null +++ b/native/src/mpv/mpv_windows.cpp @@ -0,0 +1,12 @@ +#include "mpv_platform.hpp" + +class WindowsMpvPlatformContext : public MpvPlatformContext { +public: + WindowsMpvPlatformContext() = default; + + ~WindowsMpvPlatformContext() override = default; +}; + +std::shared_ptr populatePlatformMpvParams(JNIEnv *env, std::vector ¶ms) { + return std::make_shared(); +} diff --git a/native/subprojects/mpv.wrap b/native/subprojects.tpl/linux/mpv.wrap similarity index 100% rename from native/subprojects/mpv.wrap rename to native/subprojects.tpl/linux/mpv.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/expat.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/expat.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/expat.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/expat.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/ffmpeg.wrap similarity index 73% rename from native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/ffmpeg.wrap index 0fce2e1..73f7e2c 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/ffmpeg.wrap +++ b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/ffmpeg.wrap @@ -1,8 +1,8 @@ [wrap-file] directory = ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0 -source_url = https://repoflow.silenium.dev/api/universal/personal/github-releases/BtbN/FFmpeg-Builds/autobuild-2026-02-24-16-00/ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0.tar.xz +source_url = https://repoflow.silenium.dev/api/universal/personal/github-releases/BtbN/FFmpeg-Builds/autobuild-2026-02-25-13-05/ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0.tar.xz source_filename = ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0.tar.xz -source_hash = 10726cb09596035917ec53180d1bf891730aa300a17f4b05020c08f13ad2145e +source_hash = bb09d1cad8016c92e3ce323481144f18bef41ffd5de81efa41a1d071dbcbb52f patch_directory = ffmpeg [provide] diff --git a/native/subprojects/packagefiles/mpv/subprojects/fmt.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/fmt.wrap similarity index 81% rename from native/subprojects/packagefiles/mpv/subprojects/fmt.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/fmt.wrap index 5c1f6dd..f411b4c 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/fmt.wrap +++ b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/fmt.wrap @@ -3,6 +3,7 @@ url = https://github.com/fmtlib/fmt.git revision = 12.0.0 depth = 1 method = cmake +diff_files = fmt/pic.patch [provide] fmt = fmt_dep diff --git a/native/subprojects/packagefiles/mpv/subprojects/freetype2.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/freetype2.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/freetype2.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/freetype2.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/fribidi.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/fribidi.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/fribidi.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/fribidi.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/harfbuzz.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/harfbuzz.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/harfbuzz.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/harfbuzz.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/libass.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libass.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/libass.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libass.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/libdbus.wrap.disabled b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libdbus.wrap.disabled similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/libdbus.wrap.disabled rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libdbus.wrap.disabled diff --git a/native/subprojects/packagefiles/mpv/subprojects/libdisplay-info.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libdisplay-info.wrap similarity index 71% rename from native/subprojects/packagefiles/mpv/subprojects/libdisplay-info.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libdisplay-info.wrap index 085f879..74c4327 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/libdisplay-info.wrap +++ b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libdisplay-info.wrap @@ -2,3 +2,4 @@ revision = 0.3.0 url = https://gitlab.freedesktop.org/emersion/libdisplay-info.git depth = 1 +diff_files = libdisplay-info/hwdata.patch diff --git a/native/subprojects/packagefiles/mpv/subprojects/libjpeg-turbo.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libjpeg-turbo.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/libjpeg-turbo.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libjpeg-turbo.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/libpipewire-0.3.wrap.disabled b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libpipewire-0.3.wrap.disabled similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/libpipewire-0.3.wrap.disabled rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libpipewire-0.3.wrap.disabled diff --git a/native/subprojects/packagefiles/mpv/subprojects/libplacebo.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libplacebo.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/libplacebo.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libplacebo.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/libpng.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libpng.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/libpng.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libpng.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/libuchardet.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libuchardet.wrap similarity index 86% rename from native/subprojects/packagefiles/mpv/subprojects/libuchardet.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libuchardet.wrap index d81e4b7..b02f746 100644 --- a/native/subprojects/packagefiles/mpv/subprojects/libuchardet.wrap +++ b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/libuchardet.wrap @@ -1,5 +1,5 @@ [wrap-git] -revision = 0.0.8 +revision = v0.0.8 url = https://gitlab.freedesktop.org/uchardet/uchardet.git depth = 1 diff --git a/native/subprojects/packagefiles/mpv/subprojects/openal-soft.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/openal-soft.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/openal-soft.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/openal-soft.wrap diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/ffmpeg/collect_versions.sh diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/meson.build b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/ffmpeg/meson.build similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/packagefiles/ffmpeg/meson.build rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/ffmpeg/meson.build diff --git a/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/fmt/pic.patch b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/fmt/pic.patch new file mode 100644 index 0000000..eca72f8 --- /dev/null +++ b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/fmt/pic.patch @@ -0,0 +1,13 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3c05513..5306154 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -5,6 +5,8 @@ if (${CMAKE_VERSION} VERSION_LESS 3.12) + cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) + endif () + ++set(CMAKE_POSITION_INDEPENDENT_CODE ON) ++ + # Determine if fmt is built as a subproject (using add_subdirectory) + # or if it is the master project. + if (NOT DEFINED FMT_MASTER_PROJECT) diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/libfontconfig.wrap diff --git a/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libdisplay-info/hwdata.patch b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libdisplay-info/hwdata.patch new file mode 100644 index 0000000..5eed955 --- /dev/null +++ b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libdisplay-info/hwdata.patch @@ -0,0 +1,13 @@ +diff --git a/meson.build b/meson.build +index 4012669..7bcf805 100644 +--- a/meson.build ++++ b/meson.build +@@ -16,7 +16,7 @@ version_major = version.split('.')[0] + version_minor = version.split('.')[1] + assert(version_major == '0') + +-dep_hwdata = dependency('hwdata', required: false, native: true) ++dep_hwdata = dependency('hwdata', required: false) + if dep_hwdata.found() + hwdata_dir = dep_hwdata.get_variable(pkgconfig: 'pkgdatadir') + pnp_ids = files(hwdata_dir / 'pnp.ids') diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/LICENSE.build diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson.build diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/meson_options.txt diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/arm/meson.build diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/simd/meson.build diff --git a/native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libjpeg-turbo-3.1.2/src/meson.build diff --git a/native/subprojects/packagefiles/mpv/subprojects/zlib.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/zlib.wrap similarity index 100% rename from native/subprojects/packagefiles/mpv/subprojects/zlib.wrap rename to native/subprojects.tpl/linux/packagefiles/mpv/subprojects/zlib.wrap diff --git a/native/subprojects.tpl/windows/packagefiles/mpv/meson.build b/native/subprojects.tpl/windows/packagefiles/mpv/meson.build new file mode 100644 index 0000000..edafeda --- /dev/null +++ b/native/subprojects.tpl/windows/packagefiles/mpv/meson.build @@ -0,0 +1,10 @@ +project('mpv', 'c') + +cc = meson.get_compiler('c') + +libmpv_dep = declare_dependency( + version : '2', + dependencies : cc.find_library('mpv', dirs : meson.current_source_dir()), + include_directories : include_directories('include'), +) +meson.override_dependency('libmpv', libmpv_dep) diff --git a/native/subprojects.tpl/windows/packagefiles/mpv/meson.options b/native/subprojects.tpl/windows/packagefiles/mpv/meson.options new file mode 100644 index 0000000..811b382 --- /dev/null +++ b/native/subprojects.tpl/windows/packagefiles/mpv/meson.options @@ -0,0 +1,3 @@ +option('libmpv', type: 'boolean', value: true) +option('drm', type: 'feature', value: 'auto') +option('openal', type: 'feature', value: 'auto') diff --git a/settings.gradle.kts b/settings.gradle.kts index d7fceb0..1da32b9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,17 @@ +import org.gradle.kotlin.dsl.mavenCentral +import org.gradle.kotlin.dsl.repositories + +pluginManagement { + repositories { + maven("https://reposilite.silenium.dev/releases") { + name = "silenium-releases" + } + google() + mavenCentral() + gradlePluginPortal() + } +} + plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0" } @@ -10,3 +24,5 @@ if (deployNative) { } rootProject.name = "compose-av" + +includeBuild("build-logic") From 48f30a0638a00f14269a8c529e670a742a464434 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 01:59:23 +0100 Subject: [PATCH 42/78] fix: rethrow exception from downloadFile method --- .../main/kotlin/dev/silenium/compose/av/build/DownloadFile.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/DownloadFile.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/DownloadFile.kt index d1500bb..ae7286a 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/DownloadFile.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/DownloadFile.kt @@ -45,6 +45,7 @@ fun downloadFile(progressLogger: ProgressLogger, logger: Logger, uri: URI, outpu logger.lifecycle("${progressLogger.description}: ${downloaded.toMB()} MB / ${size.toMB()} MB (${downloaded partOf size}%)") } catch (e: Exception) { progressLogger.completed(e.message ?: "Unknown error", true) + throw e } } From 118d8e53195a88f399f7eeaa24c8cfc97c6f7dfa Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 01:59:38 +0100 Subject: [PATCH 43/78] build: add meson clean task --- .../compose/av/build/MesonCleanTask.kt | 36 +++++++++++++++++++ .../compose/av/build/NativesPlugin.kt | 16 +++++++++ 2 files changed, 52 insertions(+) create mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt new file mode 100644 index 0000000..a716a04 --- /dev/null +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt @@ -0,0 +1,36 @@ +package dev.silenium.compose.av.build + +import dev.silenium.libs.jni.Platform +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Exec +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import java.io.File +import java.io.Serializable + +abstract class MesonCleanTask : Exec() { + @get:Input + abstract val targetDir: Property + + @get:Input + abstract val platform: Property + + @TaskAction + override fun exec() { + val platformFile = targetDir.get().resolve("platform.txt") + if (!platformFile.exists() || platformFile.readText() != platform.get().full) { + targetDir.get().deleteRecursively() // Completely delete target dir on platform mismatch + return + } + + val mesonCommand = arrayOf( + "nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", + "ninja", + "-C", targetDir.get().absolutePath, + "clean", + ) + commandLine(*mesonCommand) + + super.exec() + } +} \ No newline at end of file diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt index 10c3c6d..faf2429 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt @@ -27,11 +27,23 @@ class NativesPlugin : Plugin { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } + val ext = target.extensions.create("natives", NativesExtension::class.java) ext.platform.convention(target.provider(NativePlatform::platform)) val tmpDir = target.layout.buildDirectory.dir("tmp/natives") val targetDir = target.layout.buildDirectory.dir("natives") + + val mesonClean = target.tasks.register("mesonClean") { + this.targetDir.set(targetDir.map(Directory::getAsFile)) + this.platform.set(ext.platform) + } + target.tasks.named("clean") { + dependsOn(mesonClean) + } + val prepareSubprojects = target.tasks.register("prepareSubprojects") { + mustRunAfter(mesonClean) + doFirst { tmpDir.get().asFile.deleteRecursively() tmpDir.get().asFile.mkdirs() @@ -44,6 +56,8 @@ class NativesPlugin : Plugin { val javaHome = javac.map { it.asFile.parentFile.parentFile } val mesonSetup = target.tasks.register("mesonSetup") { dependsOn(prepareSubprojects) + mustRunAfter(mesonClean) + this.targetDir.set(targetDir.map(Directory::getAsFile)) this.platform.set(ext.platform) this.javaHome.set(javaHome) @@ -53,6 +67,8 @@ class NativesPlugin : Plugin { val mesonCompile = target.tasks.register("mesonCompile") { dependsOn(mesonSetup) + mustRunAfter(mesonClean) + this.targetDir.set(targetDir.map(Directory::getAsFile)) this.platform.set(ext.platform) this.libName.set(ext.libName) From ba98e7b644aa432549f29014b80d13cb19509a8b Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 01:59:49 +0100 Subject: [PATCH 44/78] build: reduce minimum jvm version to 11 --- .../kotlin/dev/silenium/compose/av/build/NativesPlugin.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt index faf2429..b642b0d 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt @@ -21,11 +21,11 @@ class NativesPlugin : Plugin { override fun apply(target: Project) { target.apply() target.configure { - compilerOptions.jvmTarget.set(JvmTarget.JVM_17) + compilerOptions.jvmTarget.set(JvmTarget.JVM_11) } target.configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } val ext = target.extensions.create("natives", NativesExtension::class.java) From ad85faa632fd112e8411a0e085a66ed1803d80d1 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 02:00:13 +0100 Subject: [PATCH 45/78] fix: platform file check and update --- .../kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt index cae6179..0261537 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt @@ -45,7 +45,7 @@ abstract class MesonSetupTask : Exec() { ) val platformFile = targetDir.get().resolve("platform.txt") - if (platformFile.exists() && platformFile.readText() != platform.get().full) { + if (!platformFile.exists() || platformFile.readText() != platform.get().full) { targetDir.get().deleteRecursively() } @@ -60,8 +60,6 @@ abstract class MesonSetupTask : Exec() { ) commandLine(*mesonCommand) - logger.lifecycle("Executing Meson setup: ${commandLine.joinToString()}") - super.exec() platformFile.writeText(platform.get().full) From b787d47e92e156ea2f10b5da922670bc63836abf Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 02:00:28 +0100 Subject: [PATCH 46/78] fix: linux arm64 cross file --- native/cross/linux-arm64.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/native/cross/linux-arm64.txt b/native/cross/linux-arm64.txt index 01749f7..b3a3ce2 100644 --- a/native/cross/linux-arm64.txt +++ b/native/cross/linux-arm64.txt @@ -1,8 +1,7 @@ [binaries] -c = 'aarch64-unknown-linux-gcc' -cpp = 'aarch64-unknown-linux-g++' +c = 'aarch64-unknown-linux-gnu-gcc' +cpp = 'aarch64-unknown-linux-gnu-g++' ar = 'aarch64-unknown-linux-gnu-ar' -windres = 'aarch64-unknown-linux-gnu-windres' strip = 'aarch64-unknown-linux-gnu-strip' exe_wrapper = 'qemu-aarch64' From 6a9351caaf31c5ee69d705fca56878fb23816d93 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 02:00:42 +0100 Subject: [PATCH 47/78] fix: use correct way to resolve libs for windows --- native/src/meson.build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/src/meson.build b/native/src/meson.build index 0a4595e..2b7c7be 100644 --- a/native/src/meson.build +++ b/native/src/meson.build @@ -21,7 +21,8 @@ if os == 'linux' sources += ['mpv/mpv_linux.cpp'] elif os == 'windows' sources += ['mpv/mpv_windows.cpp'] - gl = dependency('OpenGL32') + cc = meson.get_compiler('cpp') + gl = cc.find_library('opengl32') deps += [gl] endif From 06e75d0132fff5488372914035543237c346cc65 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 02:00:54 +0100 Subject: [PATCH 48/78] build: set minimum meson version --- .../windows/packagefiles/mpv/meson.build | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/native/subprojects.tpl/windows/packagefiles/mpv/meson.build b/native/subprojects.tpl/windows/packagefiles/mpv/meson.build index edafeda..7c12e24 100644 --- a/native/subprojects.tpl/windows/packagefiles/mpv/meson.build +++ b/native/subprojects.tpl/windows/packagefiles/mpv/meson.build @@ -1,10 +1,13 @@ -project('mpv', 'c') +project( + 'mpv', 'c', + meson_version : '>=1.2.0', +) cc = meson.get_compiler('c') libmpv_dep = declare_dependency( - version : '2', - dependencies : cc.find_library('mpv', dirs : meson.current_source_dir()), - include_directories : include_directories('include'), + version : '2', + dependencies : cc.find_library('mpv', dirs : meson.current_source_dir()), + include_directories : include_directories('include'), ) meson.override_dependency('libmpv', libmpv_dep) From 677b424bea5883a986471db8f74be6a68f8095ae Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 02:01:32 +0100 Subject: [PATCH 49/78] build: add pkg-config for linux-arm64 --- native/cross/linux-arm64.txt | 1 + native/shell.nix | 1 + 2 files changed, 2 insertions(+) diff --git a/native/cross/linux-arm64.txt b/native/cross/linux-arm64.txt index b3a3ce2..9ead381 100644 --- a/native/cross/linux-arm64.txt +++ b/native/cross/linux-arm64.txt @@ -3,6 +3,7 @@ c = 'aarch64-unknown-linux-gnu-gcc' cpp = 'aarch64-unknown-linux-gnu-g++' ar = 'aarch64-unknown-linux-gnu-ar' strip = 'aarch64-unknown-linux-gnu-strip' +pkgconfig = 'aarch64-unknown-linux-gnu-pkg-config' exe_wrapper = 'qemu-aarch64' [host_machine] diff --git a/native/shell.nix b/native/shell.nix index 5c413e1..1061125 100644 --- a/native/shell.nix +++ b/native/shell.nix @@ -17,6 +17,7 @@ pkgs.mkShell { pkgsCross.mingwW64.binutils-unwrapped pkgsCross.aarch64-multiplatform.gcc pkgsCross.aarch64-multiplatform.binutils-unwrapped + pkgsCross.aarch64-multiplatform.pkg-config ninja pkg-config meson From 440a4b09c5a76f32bff807b6530159dc1edd6ef9 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 02:01:44 +0100 Subject: [PATCH 50/78] build: use native platform from gradle property --- native/build.gradle.kts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 65df6fd..751019a 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -1,4 +1,5 @@ import dev.silenium.libs.jni.NativePlatform +import dev.silenium.libs.jni.Platform plugins { id("av-natives") @@ -6,5 +7,7 @@ plugins { natives { libName = "compose-av" - platform = NativePlatform.platform() + platform = providers.gradleProperty("native.platform") + .map(Platform.Companion::invoke) + .orElse(NativePlatform.platform()) } \ No newline at end of file From 7d8267af3ea9dc5ab9a7f7c1b3fa2ec115b56896 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 02:02:00 +0100 Subject: [PATCH 51/78] build: start working on architecture specific downloads for linux ffmpeg --- .../av/build/PrepareSubprojectsTask.kt | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt index 9a9036a..cd8fd15 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt @@ -6,19 +6,16 @@ import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileSystemOperations import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputDirectory -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.* import org.gradle.internal.logging.progress.ProgressLoggerFactory -import org.gradle.internal.operations.BuildOperationDescriptor import org.gradle.process.ExecOperations import org.jetbrains.kotlin.org.apache.commons.codec.digest.DigestUtils import java.net.URI import java.nio.file.Files import javax.inject.Inject +import kotlin.io.path.createParentDirectories import kotlin.io.path.deleteIfExists +import kotlin.io.path.relativeTo abstract class PrepareSubprojectsTask : DefaultTask() { @get:Inject @@ -52,9 +49,8 @@ abstract class PrepareSubprojectsTask : DefaultTask() { mpvDlFile.convention(downloadDir.zip(platform) { dir, p -> dir.file("mpv-win-${p.arch}.7z") }) subprojectDir.convention(project.layout.projectDirectory.dir("subprojects")) subprojectTplDir.convention(project.layout.projectDirectory.dir("subprojects.tpl")) - packageCacheDir.convention(project.layout.buildDirectory.dir("packagecache")) + packageCacheDir.convention(project.rootProject.layout.projectDirectory.dir(".gradle/meson-cache/packagecache")) -// outputs.file(platform.map { p -> mpvDlFile.takeIf { p.os == Platform.OS.WINDOWS } }) outputs.dir(subprojectDir) inputs.dir(subprojectTplDir) } @@ -80,10 +76,11 @@ abstract class PrepareSubprojectsTask : DefaultTask() { else -> Unit } packageCacheDir.get().asFile.mkdirs() - Files.createSymbolicLink(cacheLink, packageCacheDir.get().asFile.toPath()) + Files.createSymbolicLink(cacheLink, packageCacheDir.get().asFile.toPath().relativeTo(cacheLink.parent)) } private fun copySubprojects(platform: Platform) { + // TODO: Template url and hash for linux fsOps.copy { from(subprojectTplDir.dir(platform.os.toString())) into(subprojectDir) @@ -100,6 +97,7 @@ abstract class PrepareSubprojectsTask : DefaultTask() { val progressLogger = progressLoggerFactory.newOperation(PrepareSubprojectsTask::class.java) progressLogger.start("Downloading MPV Windows binaries", "") + file.toPath().createParentDirectories() file.outputStream().use { output -> downloadFile(progressLogger, logger, meta.uri, output) } @@ -123,11 +121,10 @@ abstract class PrepareSubprojectsTask : DefaultTask() { } internal data class MpvWindowsMetadata(val arch: String, val fileHash: String) { - val uri: URI by lazy { URI.create("https://github.com/shinchiro/mpv-winbuild-cmake/releases/download/20260225/mpv-dev-${arch}-20260225-git-92ed2d2.7z") } + val uri: URI by lazy { URI.create("https://repoflow.silenium.dev/api/universal/personal/github-releases/shinchiro/mpv-winbuild-cmake/20260225/mpv-dev-${arch}-20260225-git-92ed2d2.7z") } } internal val mpvWindows = mapOf( - Platform.Arch.X86 to MpvWindowsMetadata("i686", "c3f25283f7c5ec3eb718fb9a1b686f714744c04559e8aaa2e691bc8e49552c71"), Platform.Arch.ARM64 to MpvWindowsMetadata( "aarch64", "783b60c8ca94eda76596f2b355f860f35dffe6f56aa2e3762f2fc7fd3f7304d2" @@ -137,3 +134,18 @@ internal val mpvWindows = mapOf( "5d266a6899b8bb175a6857c93c53679f040953167a2bed65b83edb03e0b48b65" ), ) + +internal data class MpvLinuxMetadata(val arch: String, val fileHash: String) { + val uri: URI by lazy { URI.create("https://repoflow.silenium.dev/api/universal/personal/github-releases/BtbN/FFmpeg-Builds/autobuild-2026-02-25-13-05/ffmpeg-n8.0.1-64-g15504610b0-${arch}-gpl-shared-8.0.tar.xz") } +} + +internal val mpvLinux = mapOf( + Platform.Arch.X86_64 to MpvLinuxMetadata( + "linux64", + "bb09d1cad8016c92e3ce323481144f18bef41ffd5de81efa41a1d071dbcbb52f" + ), + Platform.Arch.ARM64 to MpvLinuxMetadata( + "linuxarm64", + "b4ad73f547a77da7b9d94661962a6d5d312a945f4bcb3f82c790b2730ce2c52f" + ), +) From c0a920f4642e1b3a62f65f49ba49efbbbfac223c Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 19:06:09 +0100 Subject: [PATCH 52/78] build: working cross-compile for linux-arm64/-x86_64 and windows-x86_64, add guards for egl --- .../compose/av/build/MesonCleanTask.kt | 2 +- .../compose/av/build/MesonCompileTask.kt | 2 +- .../compose/av/build/MesonSetupTask.kt | 2 +- .../av/build/PrepareSubprojectsTask.kt | 30 +++++++++++---- native/flake.nix | 28 ++++++++++++-- native/{shell.nix => shell-linux-arm64.nix} | 37 ++----------------- native/shell-linux-x86_64.nix | 37 +++++++++++++++++++ native/shell-windows-x86_64.nix | 33 +++++++++++++++++ native/src/helper/errors.cpp | 6 +++ native/src/helper/errors.hpp | 3 ++ native/src/meson.build | 2 + native/src/util/Errors.cpp | 2 + .../packagefiles/mpv/subprojects/ffmpeg.wrap | 8 ++-- 13 files changed, 140 insertions(+), 52 deletions(-) rename native/{shell.nix => shell-linux-arm64.nix} (55%) create mode 100644 native/shell-linux-x86_64.nix create mode 100644 native/shell-windows-x86_64.nix diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt index a716a04..cb5f7c6 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt @@ -24,7 +24,7 @@ abstract class MesonCleanTask : Exec() { } val mesonCommand = arrayOf( - "nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", + "nix", "develop", ".#${platform.get().osArch}", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", "ninja", "-C", targetDir.get().absolutePath, "clean", diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt index 8f39bf4..6a02f1d 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt @@ -57,7 +57,7 @@ abstract class MesonCompileTask : Exec() { "JAVA_HOME" to javaHome.get().absolutePath, ) commandLine( - "nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", + "nix", "develop", ".#${platform.get().osArch}", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", "meson", "compile", "-C", targetDir.get().absolutePath, libName.get(), ) super.exec() diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt index 0261537..793bc39 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt @@ -52,7 +52,7 @@ abstract class MesonSetupTask : Exec() { val crossArgs = arrayOf("--cross-file", "cross/${platform.get().osArch}.txt") val mesonCommand = arrayOf( - "nix", "develop", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", + "nix", "develop", ".#${platform.get().osArch}", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", "meson", "setup", "--wipe", targetDir.get().absolutePath, diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt index cd8fd15..3a7ac72 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt @@ -8,6 +8,7 @@ import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.* import org.gradle.internal.logging.progress.ProgressLoggerFactory +import org.gradle.kotlin.dsl.expand import org.gradle.process.ExecOperations import org.jetbrains.kotlin.org.apache.commons.codec.digest.DigestUtils import java.net.URI @@ -70,7 +71,7 @@ abstract class PrepareSubprojectsTask : DefaultTask() { } Platform.OS.LINUX -> { - copySubprojects(platform.get()) + copyLinuxSubprojects(platform.get()) } else -> Unit @@ -79,12 +80,25 @@ abstract class PrepareSubprojectsTask : DefaultTask() { Files.createSymbolicLink(cacheLink, packageCacheDir.get().asFile.toPath().relativeTo(cacheLink.parent)) } - private fun copySubprojects(platform: Platform) { - // TODO: Template url and hash for linux + private fun copyLinuxSubprojects(platform: Platform) { + val ffmpegWrap = "packagefiles/mpv/subprojects/ffmpeg.wrap" + val meta = ffmpegLinux[platform.arch] ?: error("Unsupported platform: ${platform.osArch}") fsOps.copy { - from(subprojectTplDir.dir(platform.os.toString())) + from(subprojectTplDir.dir(platform.os.toString())) { + exclude(ffmpegWrap) + } into(subprojectDir) } + fsOps.copy { + from(subprojectTplDir.file("${platform.os}/${ffmpegWrap}")) + into(subprojectDir.file(ffmpegWrap.substringBeforeLast("/"))) + expand( + "ffmpeg_source_url" to meta.uri.toString(), + "ffmpeg_source_hash" to meta.fileHash, + "ffmpeg_source_filename" to meta.uri.path.substringAfterLast('/'), + "ffmpeg_directory" to meta.uri.path.substringAfterLast('/').removeSuffix(".tar.xz"), + ) + } } private fun downloadMpvWindows() { @@ -135,16 +149,16 @@ internal val mpvWindows = mapOf( ), ) -internal data class MpvLinuxMetadata(val arch: String, val fileHash: String) { +internal data class FFmpegLinuxMetadata(val arch: String, val fileHash: String) { val uri: URI by lazy { URI.create("https://repoflow.silenium.dev/api/universal/personal/github-releases/BtbN/FFmpeg-Builds/autobuild-2026-02-25-13-05/ffmpeg-n8.0.1-64-g15504610b0-${arch}-gpl-shared-8.0.tar.xz") } } -internal val mpvLinux = mapOf( - Platform.Arch.X86_64 to MpvLinuxMetadata( +internal val ffmpegLinux = mapOf( + Platform.Arch.X86_64 to FFmpegLinuxMetadata( "linux64", "bb09d1cad8016c92e3ce323481144f18bef41ffd5de81efa41a1d071dbcbb52f" ), - Platform.Arch.ARM64 to MpvLinuxMetadata( + Platform.Arch.ARM64 to FFmpegLinuxMetadata( "linuxarm64", "b4ad73f547a77da7b9d94661962a6d5d312a945f4bcb3f82c790b2730ce2c52f" ), diff --git a/native/flake.nix b/native/flake.nix index 980b7c9..dc7bf9d 100644 --- a/native/flake.nix +++ b/native/flake.nix @@ -9,11 +9,31 @@ outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: - let - pkgs = nixpkgs.legacyPackages.${system}; - in + let + pkgs = nixpkgs.legacyPackages.${system}; + buildDeps = pkgBase: with pkgBase; [ + # Libraries + libGL + mesa-gl-headers + libdrm + libx11 + libva + libdovi + libdrm + libva + systemdLibs + hwdata + ]; + buildTools = pkgBase: with pkgBase; [ + gcc + binutils + pkg-config + ]; + in { - devShells.default = import ./shell.nix { inherit pkgs; }; + devShells.linux-arm64 = import ./shell-linux-arm64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; + devShells.linux-x86_64 = import ./shell-linux-x86_64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; + devShells.windows-x86_64 = import ./shell-windows-x86_64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; } ); } diff --git a/native/shell.nix b/native/shell-linux-arm64.nix similarity index 55% rename from native/shell.nix rename to native/shell-linux-arm64.nix index 1061125..4906076 100644 --- a/native/shell.nix +++ b/native/shell-linux-arm64.nix @@ -1,5 +1,4 @@ -{ pkgs ? import { } }: - +{ pkgs, buildTools, buildDeps }: pkgs.mkShell { strictDeps = true; nativeBuildInputs = with pkgs; [ @@ -9,17 +8,7 @@ pkgs.mkShell { # C/C++ Build Toolchain cmake - gcc - gdb - binutils-unwrapped - pkgsCross.mingwW64.gcc - pkgsCross.mingwW64.gdb - pkgsCross.mingwW64.binutils-unwrapped - pkgsCross.aarch64-multiplatform.gcc - pkgsCross.aarch64-multiplatform.binutils-unwrapped - pkgsCross.aarch64-multiplatform.pkg-config ninja - pkg-config meson # Additional utilities @@ -28,27 +17,9 @@ pkgs.mkShell { wineWow64Packages.staging qemu-user perl - ]; - buildInputs = with pkgs; [ - # Libraries - libGL - mesa-gl-headers - libdrm - libx11 - libva - dovi-tool - libdovi - libdrm - libva - pipewire - alsa-lib - libpulseaudio - libGL - egl-wayland - openssl - systemdLibs - hwdata - ]; + ] ++ (buildTools pkgs.pkgsCross.aarch64-multiplatform); + + buildInputs = (buildDeps pkgs.pkgsCross.aarch64-multiplatform); shellHook = '' echo "Development environment loaded" diff --git a/native/shell-linux-x86_64.nix b/native/shell-linux-x86_64.nix new file mode 100644 index 0000000..9d422c2 --- /dev/null +++ b/native/shell-linux-x86_64.nix @@ -0,0 +1,37 @@ +{ pkgs, buildTools, buildDeps }: +pkgs.mkShell { + strictDeps = true; + nativeBuildInputs = with pkgs; [ + # Java Development + jdk21 + gradle_9 + + # C/C++ Build Toolchain + cmake + ninja + meson + + # Additional utilities + git + python3 + wineWow64Packages.staging + qemu-user + perl + ] ++ (buildTools pkgs); + + buildInputs = (buildDeps pkgs); + + shellHook = '' + echo "Development environment loaded" + echo "Java version: $(java -version 2>&1 | head -n 1)" + echo "Gradle version: $(gradle --version | grep Gradle)" + echo "CMake version: $(cmake --version | head -n 1)" + echo "GCC version: $(gcc --version | head -n 1)" + echo "Ninja version: $(ninja --version)" + ''; + + # Set environment variables + JAVA_HOME = "${pkgs.jdk21}"; + HWDATA_PATH = "${pkgs.hwdata}"; + CMAKE_GENERATOR = "Ninja"; +} diff --git a/native/shell-windows-x86_64.nix b/native/shell-windows-x86_64.nix new file mode 100644 index 0000000..9e6eac6 --- /dev/null +++ b/native/shell-windows-x86_64.nix @@ -0,0 +1,33 @@ +{ pkgs, buildTools, buildDeps }: +pkgs.mkShell { + strictDeps = true; + nativeBuildInputs = with pkgs; [ + # Java Development + jdk21 + gradle_9 + + # C/C++ Build Toolchain + cmake + ninja + meson + + # Additional utilities + git + python3 + wineWow64Packages.staging + ] ++ (buildTools pkgs.pkgsCross.mingwW64); + + shellHook = '' + echo "Development environment loaded" + echo "Java version: $(java -version 2>&1 | head -n 1)" + echo "Gradle version: $(gradle --version | grep Gradle)" + echo "CMake version: $(cmake --version | head -n 1)" + echo "GCC version: $(gcc --version | head -n 1)" + echo "Ninja version: $(ninja --version)" + ''; + + # Set environment variables + JAVA_HOME = "${pkgs.jdk21}"; + HWDATA_PATH = "${pkgs.hwdata}"; + CMAKE_GENERATOR = "Ninja"; +} diff --git a/native/src/helper/errors.cpp b/native/src/helper/errors.cpp index 3ff14d9..39bc062 100644 --- a/native/src/helper/errors.cpp +++ b/native/src/helper/errors.cpp @@ -4,7 +4,10 @@ #include "errors.hpp" +#ifdef TARGET_LINUX #include +#endif + #include #include @@ -75,6 +78,7 @@ jobject resultSuccessNull() { return nullptr; } +#ifdef TARGET_LINUX jobject eglResultFailure(JNIEnv *env, const char *operation, const long returnCode) { const auto resultClass = env->FindClass("kotlin/Result$Failure"); const auto errorClass = env->FindClass("dev/silenium/multimedia/core/util/EGLException"); @@ -90,6 +94,7 @@ jobject eglResultFailure(JNIEnv *env, const char *operation, const long returnCo const auto errorResult = env->NewObject(resultClass, resultConstructor, error); return errorResult; } +#endif jobject glResultFailure(JNIEnv *env, const char *operation, const GLenum returnCode) { const auto resultClass = env->FindClass("kotlin/Result$Failure"); @@ -106,6 +111,7 @@ jobject glResultFailure(JNIEnv *env, const char *operation, const GLenum returnC const auto errorResult = env->NewObject(resultClass, resultConstructor, error); return errorResult; } + jobject vaResultFailure(JNIEnv *env, const char *operation, const int returnCode) { const auto resultClass = env->FindClass("kotlin/Result$Failure"); const auto errorClass = env->FindClass("dev/silenium/multimedia/core/util/VAException"); diff --git a/native/src/helper/errors.hpp b/native/src/helper/errors.hpp index f9dac0a..f21c8ae 100644 --- a/native/src/helper/errors.hpp +++ b/native/src/helper/errors.hpp @@ -24,7 +24,10 @@ jobject resultSuccess(JNIEnv *env, jboolean value); jobject resultSuccess(JNIEnv *env); jobject resultSuccessNull(); +#ifdef TARGET_LINUX jobject eglResultFailure(JNIEnv *env, const char *operation, long returnCode); +#endif + jobject glResultFailure(JNIEnv *env, const char *operation, GLenum returnCode); jobject vaResultFailure(JNIEnv *env, const char *operation, int returnCode); diff --git a/native/src/meson.build b/native/src/meson.build index 2b7c7be..eb16cb8 100644 --- a/native/src/meson.build +++ b/native/src/meson.build @@ -19,11 +19,13 @@ if os == 'linux' x11 = dependency('x11') deps += [egl, glx, x11] sources += ['mpv/mpv_linux.cpp'] + add_project_arguments('-DTARGET_LINUX', language: 'cpp') elif os == 'windows' sources += ['mpv/mpv_windows.cpp'] cc = meson.get_compiler('cpp') gl = cc.find_library('opengl32') deps += [gl] + add_project_arguments('-DTARGET_WINDOWS', language: 'cpp') endif shared_library( diff --git a/native/src/util/Errors.cpp b/native/src/util/Errors.cpp index 3627694..951324c 100644 --- a/native/src/util/Errors.cpp +++ b/native/src/util/Errors.cpp @@ -27,8 +27,10 @@ JNIEXPORT jstring JNICALL Java_dev_silenium_multimedia_core_util_ErrorsKt_glErro return env->NewStringUTF("GL_INVALID_VALUE"); case GL_INVALID_OPERATION: return env->NewStringUTF("GL_INVALID_OPERATION"); +#ifdef GL_INVALID_FRAMEBUFFER_OPERATION case GL_INVALID_FRAMEBUFFER_OPERATION: return env->NewStringUTF("GL_INVALID_FRAMEBUFFER_OPERATION"); +#endif case GL_OUT_OF_MEMORY: return env->NewStringUTF("GL_OUT_OF_MEMORY"); case GL_STACK_UNDERFLOW: diff --git a/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/ffmpeg.wrap b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/ffmpeg.wrap index 73f7e2c..c4f956c 100644 --- a/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/ffmpeg.wrap +++ b/native/subprojects.tpl/linux/packagefiles/mpv/subprojects/ffmpeg.wrap @@ -1,8 +1,8 @@ [wrap-file] -directory = ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0 -source_url = https://repoflow.silenium.dev/api/universal/personal/github-releases/BtbN/FFmpeg-Builds/autobuild-2026-02-25-13-05/ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0.tar.xz -source_filename = ffmpeg-n8.0.1-64-g15504610b0-linux64-gpl-shared-8.0.tar.xz -source_hash = bb09d1cad8016c92e3ce323481144f18bef41ffd5de81efa41a1d071dbcbb52f +directory = ${ffmpeg_directory} +source_url = ${ffmpeg_source_url} +source_filename = ${ffmpeg_source_filename} +source_hash = ${ffmpeg_source_hash} patch_directory = ffmpeg [provide] From e7e711966fcbb2f2e6986226345c6a4e4cf7b243 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 20:43:22 +0100 Subject: [PATCH 53/78] fix: cleanup some obsolete stuff, add missing native functions --- native/src/helper/errors.cpp | 6 -- native/src/helper/errors.hpp | 2 + native/src/meson.build | 3 +- native/src/util/Errors.cpp | 61 +++++++++++++++++-- .../silenium/multimedia/core/util/Errors.kt | 25 ++------ .../silenium/multimedia/core/util/Results.kt | 7 --- 6 files changed, 64 insertions(+), 40 deletions(-) delete mode 100644 src/main/kotlin/dev/silenium/multimedia/core/util/Results.kt diff --git a/native/src/helper/errors.cpp b/native/src/helper/errors.cpp index 39bc062..c23ba83 100644 --- a/native/src/helper/errors.cpp +++ b/native/src/helper/errors.cpp @@ -4,10 +4,6 @@ #include "errors.hpp" -#ifdef TARGET_LINUX -#include -#endif - #include #include @@ -78,7 +74,6 @@ jobject resultSuccessNull() { return nullptr; } -#ifdef TARGET_LINUX jobject eglResultFailure(JNIEnv *env, const char *operation, const long returnCode) { const auto resultClass = env->FindClass("kotlin/Result$Failure"); const auto errorClass = env->FindClass("dev/silenium/multimedia/core/util/EGLException"); @@ -94,7 +89,6 @@ jobject eglResultFailure(JNIEnv *env, const char *operation, const long returnCo const auto errorResult = env->NewObject(resultClass, resultConstructor, error); return errorResult; } -#endif jobject glResultFailure(JNIEnv *env, const char *operation, const GLenum returnCode) { const auto resultClass = env->FindClass("kotlin/Result$Failure"); diff --git a/native/src/helper/errors.hpp b/native/src/helper/errors.hpp index f21c8ae..5a7c3e7 100644 --- a/native/src/helper/errors.hpp +++ b/native/src/helper/errors.hpp @@ -12,7 +12,9 @@ std::string avErrorString(int error); jobject boxedLong(JNIEnv *env, jlong value); +jobject boxedDouble(JNIEnv *env, jdouble value); +jobject boxedBool(JNIEnv *env, jboolean value); jobject boxedInt(JNIEnv *env, jint value); jobject pair(JNIEnv *env, jobject first, jobject second); diff --git a/native/src/meson.build b/native/src/meson.build index eb16cb8..2f8be65 100644 --- a/native/src/meson.build +++ b/native/src/meson.build @@ -17,7 +17,8 @@ if os == 'linux' egl = dependency('egl') glx = dependency('glx') x11 = dependency('x11') - deps += [egl, glx, x11] + va = dependency('libva') + deps += [egl, glx, x11, va] sources += ['mpv/mpv_linux.cpp'] add_project_arguments('-DTARGET_LINUX', language: 'cpp') elif os == 'windows' diff --git a/native/src/util/Errors.cpp b/native/src/util/Errors.cpp index 951324c..381c3c3 100644 --- a/native/src/util/Errors.cpp +++ b/native/src/util/Errors.cpp @@ -6,18 +6,48 @@ #include #include +#ifdef TARGET_LINUX +#include +#include +#define CASE_STR(value) case value: return #value; + +const char *eglGetErrorString(const long error) { + switch (error) { + CASE_STR(EGL_SUCCESS) + CASE_STR(EGL_NOT_INITIALIZED) + CASE_STR(EGL_BAD_ACCESS) + CASE_STR(EGL_BAD_ALLOC) + CASE_STR(EGL_BAD_ATTRIBUTE) + CASE_STR(EGL_BAD_CONTEXT) + CASE_STR(EGL_BAD_CONFIG) + CASE_STR(EGL_BAD_CURRENT_SURFACE) + CASE_STR(EGL_BAD_DISPLAY) + CASE_STR(EGL_BAD_SURFACE) + CASE_STR(EGL_BAD_MATCH) + CASE_STR(EGL_BAD_PARAMETER) + CASE_STR(EGL_BAD_NATIVE_PIXMAP) + CASE_STR(EGL_BAD_NATIVE_WINDOW) + CASE_STR(EGL_CONTEXT_LOST) + default: + return "Unknown"; + } +} + +#undef CASE_STR +#endif + extern "C" { JNIEXPORT jstring JNICALL Java_dev_silenium_multimedia_core_util_ErrorsKt_mpvErrorStringN( - JNIEnv *env, - jobject thiz, - const jint error) { + JNIEnv *env, + jobject thiz, + const jint error) { return env->NewStringUTF(mpv_error_string(error)); } JNIEXPORT jstring JNICALL Java_dev_silenium_multimedia_core_util_ErrorsKt_glErrorStringN( - JNIEnv *env, - jobject thiz, - const jint error) { + JNIEnv *env, + jobject thiz, + const jint error) { switch (error) { case GL_NO_ERROR: return env->NewStringUTF("GL_NO_ERROR"); @@ -41,4 +71,23 @@ JNIEXPORT jstring JNICALL Java_dev_silenium_multimedia_core_util_ErrorsKt_glErro return env->NewStringUTF("Unknown"); } } + +#ifdef TARGET_LINUX + +JNIEXPORT jstring JNICALL Java_dev_silenium_multimedia_util_ErrorsKt_eglErrorStringN( + JNIEnv *env, + jobject thiz, + jint error +) { + return env->NewStringUTF(eglGetErrorString(error)); +} + +JNIEXPORT jstring JNICALL Java_dev_silenium_multimedia_util_ErrorsKt_vaErrorStringN( + JNIEnv *env, + jobject thiz, + jint error +) { + return env->NewStringUTF(vaErrorStr(error)); +} +#endif } diff --git a/src/main/kotlin/dev/silenium/multimedia/core/util/Errors.kt b/src/main/kotlin/dev/silenium/multimedia/core/util/Errors.kt index 9b328db..ae16746 100644 --- a/src/main/kotlin/dev/silenium/multimedia/core/util/Errors.kt +++ b/src/main/kotlin/dev/silenium/multimedia/core/util/Errors.kt @@ -1,8 +1,5 @@ package dev.silenium.multimedia.core.util -class AVException(val operation: String, val error: Int) : - Exception("FFmpeg error during $operation: ${error.asAVErrorString()}") - class EGLException(val operation: String, val error: Long) : Exception("EGL error during $operation: ${error.asEGLErrorString()}") @@ -15,31 +12,19 @@ class VAException(val operation: String, val error: Int) : class MPVException(val operation: String, val error: Int) : Exception("MPV error during $operation: ${error.asMPVErrorString()}") -fun Int.asAVError(operation: String = "ffmpeg call"): Exception = AVException(operation, this) -fun Int.asAVErrorString(): String = avErrorStringN(this) fun Long.asEGLError(operation: String = "EGL call"): Exception = EGLException(operation, this) fun Long.asEGLErrorString(): String = eglErrorStringN(this) + fun Int.asGLError(operation: String = "GL call"): Exception = GLException(operation, this) fun Int.asGLErrorString(): String = glErrorStringN(this) + fun Int.asVAError(operation: String = "VA call"): Exception = VAException(operation, this) fun Int.asVAErrorString(): String = vaErrorStringN(this) + fun Int.asMPVError(operation: String = "MPV call"): Exception = MPVException(operation, this) fun Int.asMPVErrorString(): String = mpvErrorStringN(this) -private external fun avErrorStringN(error: Int): String -private external fun eglErrorStringN(error: Long): String +private external fun mpvErrorStringN(error: Int): String private external fun glErrorStringN(error: Int): String +private external fun eglErrorStringN(error: Long): String private external fun vaErrorStringN(error: Int): String -private external fun mpvErrorStringN(error: Int): String - -val Throwable.shouldIgnore - get() = when (this) { - is AVException -> when (error) { - -11 -> true // EAGAIN - -12 -> true // ENOMEM - -541478725 -> true // AVERROR_EOF - else -> false - } - - else -> false - } diff --git a/src/main/kotlin/dev/silenium/multimedia/core/util/Results.kt b/src/main/kotlin/dev/silenium/multimedia/core/util/Results.kt deleted file mode 100644 index 6ed07d0..0000000 --- a/src/main/kotlin/dev/silenium/multimedia/core/util/Results.kt +++ /dev/null @@ -1,7 +0,0 @@ -package dev.silenium.multimedia.core.util - -fun Int.asUnitResult() = if (this != 0) { - Result.failure(this.asAVError()) -} else { - Result.success(Unit) -} From d50d0d8bfbc14d0286bcc8a7448b724e2c140a0b Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 20:44:10 +0100 Subject: [PATCH 54/78] chore: move shell definitions to subdir --- native/flake.nix | 6 +++--- native/{shell-linux-arm64.nix => shells/linux-arm64.nix} | 0 native/{shell-linux-x86_64.nix => shells/linux-x86_64.nix} | 0 .../{shell-windows-x86_64.nix => shells/windows-x86_64.nix} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename native/{shell-linux-arm64.nix => shells/linux-arm64.nix} (100%) rename native/{shell-linux-x86_64.nix => shells/linux-x86_64.nix} (100%) rename native/{shell-windows-x86_64.nix => shells/windows-x86_64.nix} (100%) diff --git a/native/flake.nix b/native/flake.nix index dc7bf9d..067e13f 100644 --- a/native/flake.nix +++ b/native/flake.nix @@ -31,9 +31,9 @@ ]; in { - devShells.linux-arm64 = import ./shell-linux-arm64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; - devShells.linux-x86_64 = import ./shell-linux-x86_64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; - devShells.windows-x86_64 = import ./shell-windows-x86_64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; + devShells.linux-arm64 = import ./shells/linux-arm64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; + devShells.linux-x86_64 = import ./shells/linux-x86_64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; + devShells.windows-x86_64 = import ./shells/windows-x86_64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; } ); } diff --git a/native/shell-linux-arm64.nix b/native/shells/linux-arm64.nix similarity index 100% rename from native/shell-linux-arm64.nix rename to native/shells/linux-arm64.nix diff --git a/native/shell-linux-x86_64.nix b/native/shells/linux-x86_64.nix similarity index 100% rename from native/shell-linux-x86_64.nix rename to native/shells/linux-x86_64.nix diff --git a/native/shell-windows-x86_64.nix b/native/shells/windows-x86_64.nix similarity index 100% rename from native/shell-windows-x86_64.nix rename to native/shells/windows-x86_64.nix From 449e4d261162e4c9a78f94f98458ff84fd55138a Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 20:47:52 +0100 Subject: [PATCH 55/78] ci: install nix --- .github/workflows/build.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 083b354..bf03417 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,6 +20,10 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 + - uses: cachix/install-nix-action@v31 + with: + nix_path: nixpkgs=channel:nixos-unstable + github_access_token: ${{ secrets.GITHUB_TOKEN }} - uses: silenium-dev/actions/jni-natives/ubuntu@main with: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} @@ -34,6 +38,10 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 + - uses: cachix/install-nix-action@v31 + with: + nix_path: nixpkgs=channel:nixos-unstable + github_access_token: ${{ secrets.GITHUB_TOKEN }} - uses: silenium-dev/actions/kotlin@main with: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} From 48fa72d445eec6e4aeea844561f371840bd1fbce Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 20:51:55 +0100 Subject: [PATCH 56/78] fix: correct native platform property name --- native/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 751019a..a3547a3 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -7,7 +7,7 @@ plugins { natives { libName = "compose-av" - platform = providers.gradleProperty("native.platform") + platform = providers.gradleProperty("deploy.platform") .map(Platform.Companion::invoke) .orElse(NativePlatform.platform()) } \ No newline at end of file From 83e6896379e4062542af4877cc54a94239774945 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 21:03:15 +0100 Subject: [PATCH 57/78] fix: remove duplicate output file registration --- .../kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt index 6a02f1d..bcd8025 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt @@ -49,7 +49,6 @@ abstract class MesonCompileTask : Exec() { ) { targetDir, path -> targetDir.resolve(path) } .map(fileFactory::file)) inputs.file(targetDir.map { it.resolve("build.ninja") }) - outputs.file(libPath) } override fun exec() { From e07b047574ab35714f961b53e036622063a52544 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 21:03:42 +0100 Subject: [PATCH 58/78] build: add native library in resources processing --- .../silenium/compose/av/build/NativesPlugin.kt | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt index b642b0d..b8fbacb 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt @@ -1,5 +1,6 @@ package dev.silenium.compose.av.build +import dev.silenium.libs.jni.NativeLoader import dev.silenium.libs.jni.NativePlatform import org.gradle.api.JavaVersion import org.gradle.api.Plugin @@ -8,13 +9,10 @@ import org.gradle.api.file.Directory import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.tasks.compile.JavaCompile import org.gradle.jvm.toolchain.JavaCompiler -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.register -import org.gradle.kotlin.dsl.withType +import org.gradle.kotlin.dsl.* +import org.gradle.language.jvm.tasks.ProcessResources import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinJvmExtension -import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper class NativesPlugin : Plugin { @@ -75,5 +73,15 @@ class NativesPlugin : Plugin { this.javaHome.set(javaHome) this.sourceDir.set(target.layout.projectDirectory.dir("src")) } + + target.afterEvaluate { + tasks.named("processResources") { + from(mesonCompile.map { it.outputs.files }) { + rename { + NativeLoader.libPath(ext.libName.get(), platform = ext.platform.get()) + } + } + } + } } } From f25bf8e6d26635cfeec4b49fc423e10fd98381ca Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 21:06:39 +0100 Subject: [PATCH 59/78] build: add native library publication --- native/build.gradle.kts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index a3547a3..71351f5 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -5,9 +5,24 @@ plugins { id("av-natives") } +val deployNative = (findProperty("deploy.native") as String?)?.toBoolean() ?: true + natives { - libName = "compose-av" + libName = rootProject.name platform = providers.gradleProperty("deploy.platform") .map(Platform.Companion::invoke) .orElse(NativePlatform.platform()) -} \ No newline at end of file +} + +publishing { + publications { + if (deployNative) { + val platform = natives.platform.get() + val libName = rootProject.name + create("natives${platform.capitalized}") { + from(components["java"]) + artifactId = "$libName-natives-$platform" + } + } + } +} From 24536f87856c46d02dacf7739630d155ad82975e Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 21:12:28 +0100 Subject: [PATCH 60/78] ci: try fixing branch trigger --- .github/workflows/build.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index bf03417..2658f02 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -3,11 +3,6 @@ on: push: branches: - '*' - tags-ignore: - - '*' - paths-ignore: - - '*.md' - - 'docs/**' pull_request: workflow_dispatch: release: From e9b6e79831ded8cdf6022e1b4c74948f9b2a1435 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 27 Feb 2026 21:32:25 +0100 Subject: [PATCH 61/78] ci: build all currently supported natives --- .github/workflows/build.yaml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2658f02..3471270 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -11,8 +11,14 @@ permissions: pull-requests: write contents: write jobs: - linux-x86_64: + natives: runs-on: ubuntu-24.04 + strategy: + matrix: + platform: + - 'linux-x86_64' + - 'linux-arm64' + - 'windows-x86_64' steps: - uses: actions/checkout@v6 - uses: cachix/install-nix-action@v31 @@ -28,7 +34,7 @@ jobs: repo-password: ${{ secrets.REPOSILITE_PASSWORD }} tests: false java-version: 17 - platform: ${{ github.job }} + platform: ${{ matrix.platform }} kotlin: runs-on: ubuntu-24.04 steps: From ecb9462f286ace72149d99e7325ab23f668b6d42 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Tue, 3 Mar 2026 22:32:39 +0100 Subject: [PATCH 62/78] ci: publish to repoflow instead of reposilite --- .github/workflows/build.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3471270..2a99163 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -28,10 +28,10 @@ jobs: - uses: silenium-dev/actions/jni-natives/ubuntu@main with: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - snapshot-repo-url: "https://reposilite.silenium.dev/snapshots" - release-repo-url: "https://reposilite.silenium.dev/releases" - repo-username: ${{ secrets.REPOSILITE_USERNAME }} - repo-password: ${{ secrets.REPOSILITE_PASSWORD }} + snapshot-repo-url: "https://repoflow.silenium.dev/api/maven/public/maven-snapshots" + release-repo-url: "https://repoflow.silenium.dev/api/maven/public/maven-releases" + repo-username: ${{ secrets.REPOFLOW_USERNAME }} + repo-password: ${{ secrets.REPOFLOW_PASSWORD }} tests: false java-version: 17 platform: ${{ matrix.platform }} @@ -46,9 +46,9 @@ jobs: - uses: silenium-dev/actions/kotlin@main with: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - snapshot-repo-url: "https://reposilite.silenium.dev/snapshots" - release-repo-url: "https://reposilite.silenium.dev/releases" - repo-username: ${{ secrets.REPOSILITE_USERNAME }} - repo-password: ${{ secrets.REPOSILITE_PASSWORD }} + snapshot-repo-url: "https://repoflow.silenium.dev/api/maven/public/maven-snapshots" + release-repo-url: "https://repoflow.silenium.dev/api/maven/public/maven-releases" + repo-username: ${{ secrets.REPOFLOW_USERNAME }} + repo-password: ${{ secrets.REPOFLOW_PASSWORD }} tests: false java-version: 17 From 8927dbe83575c1302595d3ee1604596d5fcb1fdd Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Tue, 3 Mar 2026 22:37:35 +0100 Subject: [PATCH 63/78] build: start working on nix build powered native build --- .gitignore | 1 + native/cross/linux-arm64.txt | 13 ---- native/cross/linux-x86_64.txt | 12 ---- native/cross/windows-x86_64.txt | 13 ---- native/ffmpeg-config.nix | 20 ++++++ native/flake.lock | 78 ++++++++++++++++------- native/flake.nix | 104 ++++++++++++++++++++++--------- native/mpv-config.nix | 20 ++++++ native/shells/linux-arm64.nix | 37 ----------- native/shells/linux-x86_64.nix | 37 ----------- native/shells/windows-x86_64.nix | 33 ---------- 11 files changed, 171 insertions(+), 197 deletions(-) delete mode 100644 native/cross/linux-arm64.txt delete mode 100644 native/cross/linux-x86_64.txt delete mode 100644 native/cross/windows-x86_64.txt create mode 100644 native/ffmpeg-config.nix create mode 100644 native/mpv-config.nix delete mode 100644 native/shells/linux-arm64.nix delete mode 100644 native/shells/linux-x86_64.nix delete mode 100644 native/shells/windows-x86_64.nix diff --git a/.gitignore b/.gitignore index ce97ea7..4f5bfca 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ rgb.png texture.png va_surface.png textures/ +native/result ### IntelliJ IDEA ### .idea/ diff --git a/native/cross/linux-arm64.txt b/native/cross/linux-arm64.txt deleted file mode 100644 index 9ead381..0000000 --- a/native/cross/linux-arm64.txt +++ /dev/null @@ -1,13 +0,0 @@ -[binaries] -c = 'aarch64-unknown-linux-gnu-gcc' -cpp = 'aarch64-unknown-linux-gnu-g++' -ar = 'aarch64-unknown-linux-gnu-ar' -strip = 'aarch64-unknown-linux-gnu-strip' -pkgconfig = 'aarch64-unknown-linux-gnu-pkg-config' -exe_wrapper = 'qemu-aarch64' - -[host_machine] -system = 'linux' -cpu_family = 'aarch64' -cpu = 'aarch64' -endian = 'little' diff --git a/native/cross/linux-x86_64.txt b/native/cross/linux-x86_64.txt deleted file mode 100644 index 682ed1d..0000000 --- a/native/cross/linux-x86_64.txt +++ /dev/null @@ -1,12 +0,0 @@ -[binaries] -c = 'gcc' -cpp = 'g++' -ar = 'ar' -strip = 'strip' -pkgconfig = 'pkg-config' - -[host_machine] -system = 'linux' -cpu_family = 'x86_64' -cpu = 'x86_64' -endian = 'little' diff --git a/native/cross/windows-x86_64.txt b/native/cross/windows-x86_64.txt deleted file mode 100644 index 22bee5b..0000000 --- a/native/cross/windows-x86_64.txt +++ /dev/null @@ -1,13 +0,0 @@ -[binaries] -c = 'x86_64-w64-mingw32-gcc' -cpp = 'x86_64-w64-mingw32-g++' -ar = 'x86_64-w64-mingw32-ar' -windres = 'x86_64-w64-mingw32-windres' -strip = 'x86_64-w64-mingw32-strip' -exe_wrapper = 'wine64' - -[host_machine] -system = 'windows' -cpu_family = 'x86_64' -cpu = 'x86_64' -endian = 'little' diff --git a/native/ffmpeg-config.nix b/native/ffmpeg-config.nix new file mode 100644 index 0000000..7de6270 --- /dev/null +++ b/native/ffmpeg-config.nix @@ -0,0 +1,20 @@ +{ pkgs +}: +let + ffmpeg = { arch, hash }: rec { + ffmpeg_source_url = "https://repoflow.silenium.dev/api/universal/personal/github-releases/BtbN/FFmpeg-Builds/autobuild-2026-02-25-13-05/ffmpeg-n8.0.1-64-g15504610b0-${arch}-gpl-shared-8.0.tar.xz"; + ffmpeg_source_hash = hash; + ffmpeg_source_filename = pkgs.lib.lists.last (pkgs.lib.strings.split "/" ffmpeg_source_url); + ffmpeg_directory = builtins.elemAt (pkgs.lib.strings.split "." ffmpeg_source_filename) 0; + }; +in +{ + "x86_64-linux" = ffmpeg { + arch = "linux64"; + hash = "sha256-uwnRytgBbJLjzjI0gRRPGL70H/1d6B76QaHQcdvLtS8="; + }; + "aarch64-linux" = { + arch = "linuxarm64"; + hash = "sha256-tK1z9Uenfae52UZhliptXTEqlF9Lyz+Cx5CycwzixS8="; + }; +} diff --git a/native/flake.lock b/native/flake.lock index 5bbb065..52b606a 100644 --- a/native/flake.lock +++ b/native/flake.lock @@ -1,20 +1,40 @@ { "nodes": { - "flake-utils": { + "flake-parts": { "inputs": { - "systems": "systems" + "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "lastModified": 1772408722, + "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3", "type": "github" }, "original": { - "owner": "numtide", - "repo": "flake-utils", + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "jni-utils": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1772573394, + "narHash": "sha256-SyV26rgUNGGkYF7dD9KWz13hiPwMIDisQRY0rgDR8as=", + "owner": "silenium-dev", + "repo": "jni-utils", + "rev": "9776168d34656fc5460227cf5dd7632083efa1f5", + "type": "github" + }, + "original": { + "owner": "silenium-dev", + "ref": "nix-base", + "repo": "jni-utils", "type": "github" } }, @@ -34,26 +54,42 @@ "type": "github" } }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" + "nixpkgs-lib": { + "locked": { + "lastModified": 1772328832, + "narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" } }, - "systems": { + "nixpkgs_2": { "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "lastModified": 1772542754, + "narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "8c809a146a140c5c8806f13399592dbcb1bb5dc4", "type": "github" }, "original": { - "owner": "nix-systems", - "repo": "default", + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", "type": "github" } + }, + "root": { + "inputs": { + "jni-utils": "jni-utils", + "nixpkgs": "nixpkgs_2" + } } }, "root": "root", diff --git a/native/flake.nix b/native/flake.nix index 067e13f..71fdb4e 100644 --- a/native/flake.nix +++ b/native/flake.nix @@ -1,39 +1,81 @@ { - description = "compose-gl build environment"; + description = "jni build environment"; inputs = { nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; - flake-utils.url = "github:numtide/flake-utils"; + jni-utils.url = "github:silenium-dev/jni-utils?ref=nix-base"; }; - outputs = { self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem - (system: - let - pkgs = nixpkgs.legacyPackages.${system}; - buildDeps = pkgBase: with pkgBase; [ - # Libraries - libGL - mesa-gl-headers - libdrm - libx11 - libva - libdovi - libdrm - libva - systemdLibs - hwdata - ]; - buildTools = pkgBase: with pkgBase; [ - gcc - binutils - pkg-config + outputs = { nixpkgs, jni-utils, ... }: + let + pkgs = nixpkgs.legacyPackages."x86_64-linux"; + in + { + packages."x86_64-linux" = jni-utils.lib.buildJNILib { + name = "compose-av"; + mesonTarget = "compose-av"; + libName = "compose-av"; + libDir = "src"; + + additionalNativeInputs = [ pkgs.p7zip ]; + sources = targetSystem: + let + mpv = import ./mpv-config.nix { inherit pkgs; }; + in + [ + (builtins.fetchurl { + url = mpv.${targetSystem}.mpv_source_url; + sha256 = mpv.${targetSystem}.mpv_source_hash; + name = "mpv.7z"; + }) + (builtins.path { + path = ./.; + name = "compose-av"; + }) ]; - in - { - devShells.linux-arm64 = import ./shells/linux-arm64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; - devShells.linux-x86_64 = import ./shells/linux-x86_64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; - devShells.windows-x86_64 = import ./shells/windows-x86_64.nix { inherit pkgs; inherit buildTools; inherit buildDeps; }; - } - ); + + unpack = targetSystem: '' + runHook preUnpack + + # Process each source + for src in $srcs; do + srcName=$(stripHash "$src") + + case "$src" in + *.7z) + dirName="''${srcName%.7z}" + echo "Extracting 7z archive into: $dirName" + mkdir -p "$dirName" + 7z x -o"$dirName" "$src" + ;; + *) + echo "Copying: $srcName" + cp -r "$src" "$srcName" + chmod -R +w "$srcName" + ;; + esac + done + + runHook postUnpack + ''; + + patch = targetSystem: '' + ls -la compose-av + case "${targetSystem}" in + *-linux) + echo "todo" + exit 1 + ;; + *-windows) + mkdir -p compose-av/subprojects + cp -r mpv compose-av/subprojects/mpv + cp compose-av/subprojects.tpl/windows/packagefiles/mpv/* compose-av/subprojects/mpv/ + ;; + esac + + sourceRoot="compose-av" + cd $sourceRoot + ''; + }; + }; } diff --git a/native/mpv-config.nix b/native/mpv-config.nix new file mode 100644 index 0000000..4cd3a47 --- /dev/null +++ b/native/mpv-config.nix @@ -0,0 +1,20 @@ +{ pkgs +}: +let + mpv = { arch, hash }: rec { + mpv_source_url = "https://repoflow.silenium.dev/api/universal/personal/github-releases/shinchiro/mpv-winbuild-cmake/20260225/mpv-dev-${arch}-20260225-git-92ed2d2.7z"; + mpv_source_hash = hash; + mpv_source_filename = pkgs.lib.lists.last (pkgs.lib.strings.split "/" mpv_source_url); + mpv_directory = builtins.elemAt (pkgs.lib.strings.split "." mpv_source_filename) 0; + }; +in +{ + "x86_64-windows" = mpv { + arch = "x86_64"; + hash = "sha256-XSZqaJm4uxdaaFfJPFNnnwQJUxZ6K+1luD7bA+C0i2U="; + }; + "aarch64-windows" = { + arch = "aarch64"; + hash = "sha256-eDtgyMqU7adllvKzVfhg813/5vVqouN2Ly/H/T9zBNI="; + }; +} diff --git a/native/shells/linux-arm64.nix b/native/shells/linux-arm64.nix deleted file mode 100644 index 4906076..0000000 --- a/native/shells/linux-arm64.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ pkgs, buildTools, buildDeps }: -pkgs.mkShell { - strictDeps = true; - nativeBuildInputs = with pkgs; [ - # Java Development - jdk21 - gradle_9 - - # C/C++ Build Toolchain - cmake - ninja - meson - - # Additional utilities - git - python3 - wineWow64Packages.staging - qemu-user - perl - ] ++ (buildTools pkgs.pkgsCross.aarch64-multiplatform); - - buildInputs = (buildDeps pkgs.pkgsCross.aarch64-multiplatform); - - shellHook = '' - echo "Development environment loaded" - echo "Java version: $(java -version 2>&1 | head -n 1)" - echo "Gradle version: $(gradle --version | grep Gradle)" - echo "CMake version: $(cmake --version | head -n 1)" - echo "GCC version: $(gcc --version | head -n 1)" - echo "Ninja version: $(ninja --version)" - ''; - - # Set environment variables - JAVA_HOME = "${pkgs.jdk21}"; - HWDATA_PATH = "${pkgs.hwdata}"; - CMAKE_GENERATOR = "Ninja"; -} diff --git a/native/shells/linux-x86_64.nix b/native/shells/linux-x86_64.nix deleted file mode 100644 index 9d422c2..0000000 --- a/native/shells/linux-x86_64.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ pkgs, buildTools, buildDeps }: -pkgs.mkShell { - strictDeps = true; - nativeBuildInputs = with pkgs; [ - # Java Development - jdk21 - gradle_9 - - # C/C++ Build Toolchain - cmake - ninja - meson - - # Additional utilities - git - python3 - wineWow64Packages.staging - qemu-user - perl - ] ++ (buildTools pkgs); - - buildInputs = (buildDeps pkgs); - - shellHook = '' - echo "Development environment loaded" - echo "Java version: $(java -version 2>&1 | head -n 1)" - echo "Gradle version: $(gradle --version | grep Gradle)" - echo "CMake version: $(cmake --version | head -n 1)" - echo "GCC version: $(gcc --version | head -n 1)" - echo "Ninja version: $(ninja --version)" - ''; - - # Set environment variables - JAVA_HOME = "${pkgs.jdk21}"; - HWDATA_PATH = "${pkgs.hwdata}"; - CMAKE_GENERATOR = "Ninja"; -} diff --git a/native/shells/windows-x86_64.nix b/native/shells/windows-x86_64.nix deleted file mode 100644 index 9e6eac6..0000000 --- a/native/shells/windows-x86_64.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ pkgs, buildTools, buildDeps }: -pkgs.mkShell { - strictDeps = true; - nativeBuildInputs = with pkgs; [ - # Java Development - jdk21 - gradle_9 - - # C/C++ Build Toolchain - cmake - ninja - meson - - # Additional utilities - git - python3 - wineWow64Packages.staging - ] ++ (buildTools pkgs.pkgsCross.mingwW64); - - shellHook = '' - echo "Development environment loaded" - echo "Java version: $(java -version 2>&1 | head -n 1)" - echo "Gradle version: $(gradle --version | grep Gradle)" - echo "CMake version: $(cmake --version | head -n 1)" - echo "GCC version: $(gcc --version | head -n 1)" - echo "Ninja version: $(ninja --version)" - ''; - - # Set environment variables - JAVA_HOME = "${pkgs.jdk21}"; - HWDATA_PATH = "${pkgs.hwdata}"; - CMAKE_GENERATOR = "Ninja"; -} From 208f7529dd6f128c1b36c93e4b091aa067b49823 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Thu, 5 Mar 2026 20:45:19 +0100 Subject: [PATCH 64/78] build: working pure nix build for natives --- native/ffmpeg-config.nix | 20 --- native/flake.lock | 12 +- native/flake.nix | 164 ++++++++++++++--- native/hack/assemble-deps.sh | 74 ++++++++ native/mpv-config.nix | 20 --- native/nix/ffmpeg-config.nix | 20 +++ native/nix/linux-sources.nix | 170 ++++++++++++++++++ native/nix/mpv-config.nix | 20 +++ native/subprojects.tpl/linux/mpv.wrap | 8 +- .../packagefiles/mpv/subprojects/expat.wrap | 12 +- .../packagefiles/mpv/subprojects/ffmpeg.wrap | 7 +- .../packagefiles/mpv/subprojects/fmt.wrap | 8 +- .../mpv/subprojects/freetype2.wrap | 8 +- .../packagefiles/mpv/subprojects/fribidi.wrap | 7 +- .../mpv/subprojects/google-brotli.wrap | 9 + .../mpv/subprojects/harfbuzz.wrap | 9 +- .../packagefiles/mpv/subprojects/libass.wrap | 7 +- .../mpv/subprojects/libdisplay-info.wrap | 7 +- .../mpv/subprojects/libjpeg-turbo.wrap | 10 +- .../mpv/subprojects/libplacebo.wrap | 8 +- .../packagefiles/mpv/subprojects/libpng.wrap | 11 +- .../mpv/subprojects/libuchardet.wrap | 7 +- .../mpv/subprojects/openal-soft.wrap | 11 +- .../harfbuzz/subprojects/icu.wrap | 3 + .../libass/subprojects/libfontconfig.wrap | 9 +- .../libfontconfig/subprojects/gperf.wrap | 7 + .../libfontconfig/subprojects/libxml2.wrap | 7 + .../LICENSE.build | 0 .../meson.build | 0 .../meson_options.txt | 0 .../simd/arm/meson.build | 0 .../simd/meson.build | 0 .../src/meson.build | 0 .../packagefiles/mpv/subprojects/zlib.wrap | 11 +- 34 files changed, 501 insertions(+), 165 deletions(-) delete mode 100644 native/ffmpeg-config.nix create mode 100644 native/hack/assemble-deps.sh delete mode 100644 native/mpv-config.nix create mode 100644 native/nix/ffmpeg-config.nix create mode 100644 native/nix/linux-sources.nix create mode 100644 native/nix/mpv-config.nix create mode 100644 native/subprojects.tpl/linux/packagefiles/mpv/subprojects/google-brotli.wrap create mode 100644 native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/harfbuzz/subprojects/icu.wrap create mode 100644 native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/packagefiles/libfontconfig/subprojects/gperf.wrap create mode 100644 native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/packagefiles/libfontconfig/subprojects/libxml2.wrap rename native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/{libjpeg-turbo-3.1.2 => libjpeg-turbo}/LICENSE.build (100%) rename native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/{libjpeg-turbo-3.1.2 => libjpeg-turbo}/meson.build (100%) rename native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/{libjpeg-turbo-3.1.2 => libjpeg-turbo}/meson_options.txt (100%) rename native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/{libjpeg-turbo-3.1.2 => libjpeg-turbo}/simd/arm/meson.build (100%) rename native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/{libjpeg-turbo-3.1.2 => libjpeg-turbo}/simd/meson.build (100%) rename native/subprojects.tpl/linux/packagefiles/mpv/subprojects/packagefiles/{libjpeg-turbo-3.1.2 => libjpeg-turbo}/src/meson.build (100%) diff --git a/native/ffmpeg-config.nix b/native/ffmpeg-config.nix deleted file mode 100644 index 7de6270..0000000 --- a/native/ffmpeg-config.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ pkgs -}: -let - ffmpeg = { arch, hash }: rec { - ffmpeg_source_url = "https://repoflow.silenium.dev/api/universal/personal/github-releases/BtbN/FFmpeg-Builds/autobuild-2026-02-25-13-05/ffmpeg-n8.0.1-64-g15504610b0-${arch}-gpl-shared-8.0.tar.xz"; - ffmpeg_source_hash = hash; - ffmpeg_source_filename = pkgs.lib.lists.last (pkgs.lib.strings.split "/" ffmpeg_source_url); - ffmpeg_directory = builtins.elemAt (pkgs.lib.strings.split "." ffmpeg_source_filename) 0; - }; -in -{ - "x86_64-linux" = ffmpeg { - arch = "linux64"; - hash = "sha256-uwnRytgBbJLjzjI0gRRPGL70H/1d6B76QaHQcdvLtS8="; - }; - "aarch64-linux" = { - arch = "linuxarm64"; - hash = "sha256-tK1z9Uenfae52UZhliptXTEqlF9Lyz+Cx5CycwzixS8="; - }; -} diff --git a/native/flake.lock b/native/flake.lock index 52b606a..89a5171 100644 --- a/native/flake.lock +++ b/native/flake.lock @@ -24,11 +24,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1772573394, - "narHash": "sha256-SyV26rgUNGGkYF7dD9KWz13hiPwMIDisQRY0rgDR8as=", + "lastModified": 1772739475, + "narHash": "sha256-tjBJd0irZOg6zsDgqaVdp+o7MFb2gCrdVYgMtG7fqyc=", "owner": "silenium-dev", "repo": "jni-utils", - "rev": "9776168d34656fc5460227cf5dd7632083efa1f5", + "rev": "8be0e61d0a2ec9ac6af731a4004740e017bf5c99", "type": "github" }, "original": { @@ -71,11 +71,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1772542754, - "narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=", + "lastModified": 1772624091, + "narHash": "sha256-QKyJ0QGWBn6r0invrMAK8dmJoBYWoOWy7lN+UHzW1jc=", "owner": "nixos", "repo": "nixpkgs", - "rev": "8c809a146a140c5c8806f13399592dbcb1bb5dc4", + "rev": "80bdc1e5ce51f56b19791b52b2901187931f5353", "type": "github" }, "original": { diff --git a/native/flake.nix b/native/flake.nix index 71fdb4e..5fd9604 100644 --- a/native/flake.nix +++ b/native/flake.nix @@ -10,24 +10,36 @@ let pkgs = nixpkgs.legacyPackages."x86_64-linux"; in - { + rec { packages."x86_64-linux" = jni-utils.lib.buildJNILib { name = "compose-av"; mesonTarget = "compose-av"; + buildType = "release"; libName = "compose-av"; libDir = "src"; - additionalNativeInputs = [ pkgs.p7zip ]; + additionalNativeInputs = [ pkgs.p7zip pkgs.curl pkgs.cacert pkgs.python3 ]; sources = targetSystem: let - mpv = import ./mpv-config.nix { inherit pkgs; }; + mpv = import ./nix/mpv-config.nix { inherit pkgs; }; + ffmpeg = import ./nix/ffmpeg-config.nix { inherit pkgs; }; in - [ + (if targetSystem == "x86_64-windows" then + [ + (builtins.fetchurl { + url = mpv.${targetSystem}.source_url; + sha256 = mpv.${targetSystem}.source_hash; + name = "mpv.7z"; + }) + ] + else [ + (import ./nix/linux-sources.nix { inherit pkgs; }) (builtins.fetchurl { - url = mpv.${targetSystem}.mpv_source_url; - sha256 = mpv.${targetSystem}.mpv_source_hash; - name = "mpv.7z"; + url = ffmpeg.${targetSystem}.source_url; + sha256 = ffmpeg.${targetSystem}.source_hash; + name = "ffmpeg.tar.xz"; }) + ]) ++ [ (builtins.path { path = ./.; name = "compose-av"; @@ -42,40 +54,136 @@ srcName=$(stripHash "$src") case "$src" in + *.tar.gz|*.tar.xz) + dirName="''${srcName%.tar.*}" + echo "Extracting tar archive into: $dirName" + mkdir -p "$dirName" + tar xf "$src" -C "$dirName" + + # Check if archive only contained one directory + shopt -s nullglob dotglob + contents=("$dirName"/*) + if [ ''${#contents[@]} -eq 1 ] && [ -d "''${contents[0]}" ]; then + echo "Flattening single directory structure" + mv "''${contents[0]}"/* "$dirName"/ + rmdir "''${contents[0]}" + fi + + chmod -R +w "$dirName" + + for i in "$dirName"/**/*.py "$dirName"/*.py; do + echo "patching shebangs in $i" + patchShebangs --build "$i" + done + + tar cf "$dirName.tar" -C "$dirName" . + rm -rf "$dirName" + ;; + *.zip) + dirName="''${srcName%.zip}" + echo "Extracting tar archive into: $dirName" + mkdir -p "$dirName" + 7z x -o"$dirName" "$src" + + # Check if archive only contained one directory + shopt -s nullglob dotglob + contents=("$dirName"/*) + if [ ''${#contents[@]} -eq 1 ] && [ -d "''${contents[0]}" ]; then + echo "Flattening single directory structure" + mv "''${contents[0]}"/* "$dirName"/ + rmdir "''${contents[0]}" + fi + + chmod -R +w "$dirName" + + for i in "$dirName"/**/*.py "$dirName"/*.py; do + echo "patching shebangs in $i" + patchShebangs --build "$i" + done + + tar cf "$dirName.tar" -C "$dirName" . + rm -rf "$dirName" + ;; *.7z) - dirName="''${srcName%.7z}" - echo "Extracting 7z archive into: $dirName" - mkdir -p "$dirName" - 7z x -o"$dirName" "$src" - ;; - *) - echo "Copying: $srcName" - cp -r "$src" "$srcName" - chmod -R +w "$srcName" - ;; + dirName="''${srcName%.7z}" + echo "Extracting 7z archive into: $dirName" + mkdir -p "$dirName" + 7z x -o"$dirName" "$src" + + chmod -R +w "$dirName" + tar cf "$dirName.tar" -C "$dirName" . + ;; + *compose-av) + echo "Copying: $srcName" + cp -r "$src" "$srcName" + chmod -R +w "$srcName" + ;; + *) + dirName="''${srcName}" + echo "Compressing: $srcName" + cp -r "$src" "$srcName" + chmod -R +w "$srcName" + + for i in "$dirName"/**/*.py "$dirName"/*.py; do + echo "patching shebangs in $i" + patchShebangs --build "$i" + done + + tar cf "$dirName.tar" -C "$srcName" . + rm -rf "$srcName" + ;; esac done runHook postUnpack ''; - - patch = targetSystem: '' - ls -la compose-av + postUnpackPhase = targetSystem : '' + shopt -s globstar case "${targetSystem}" in - *-linux) - echo "todo" - exit 1 - ;; *-windows) - mkdir -p compose-av/subprojects - cp -r mpv compose-av/subprojects/mpv + mkdir -p compose-av/subprojects/mpv + tar xf mpv.tar -C compose-av/subprojects/mpv/ cp compose-av/subprojects.tpl/windows/packagefiles/mpv/* compose-av/subprojects/mpv/ ;; + *-linux) + for p in ./*-patch.tar; do + echo "patching ''${p%-patch.tar}" + tar --concatenate --file="''${p%-patch.tar}.tar" "$p" + rm "$p" + done + + mkdir -p compose-av/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/packagefiles + mkdir -p compose-av/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/packagefiles/libfontconfig/subprojects/packagefiles + mv libfontconfig.tar compose-av/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/packagefiles + mv libxml2.tar compose-av/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/packagefiles/libfontconfig/subprojects/packagefiles + mv gperf.tar compose-av/subprojects/packagefiles/mpv/subprojects/packagefiles/libass/subprojects/packagefiles/libfontconfig/subprojects/packagefiles + + mkdir -p compose-av/subprojects/packagefiles/mpv/subprojects/packagefiles/harfbuzz/subprojects/packagefiles + mv icu.tar compose-av/subprojects/packagefiles/mpv/subprojects/packagefiles/harfbuzz/subprojects/packagefiles + + mv mpv.tar compose-av/subprojects/packagefiles + + mv *.tar compose-av/subprojects/packagefiles/mpv/subprojects/packagefiles + + for i in compose-av/subprojects.tpl/linux/**/*; do + if [ -d "$i" ]; then + echo "creating dir $i" + mkdir -p "compose-av/subprojects/''${i#compose-av/subprojects.tpl/linux/}" + else + echo "Expanding $i:" + cat "$i" \ + | sed 's,''${cav_archive_base},'"$(pwd)"',g' \ + > "compose-av/subprojects/''${i#compose-av/subprojects.tpl/linux/}" + fi + done + ;; esac - sourceRoot="compose-av" - cd $sourceRoot + sourceRoot="$(pwd)/compose-av" + echo "changing source root: $sourceRoot" + cd "$sourceRoot" ''; }; + checks = packages; }; } diff --git a/native/hack/assemble-deps.sh b/native/hack/assemble-deps.sh new file mode 100644 index 0000000..38be9c7 --- /dev/null +++ b/native/hack/assemble-deps.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +function assemble_deps() { + local wrap_file="$1" + depName=$(basename "$wrap_file" .wrap) + dir=$(dirname "$wrap_file") + wrap_type=$(grep -oP '(?<=\[wrap-)[^\]]+(?=\])' "$wrap_file") + case "$wrap_type" in + file) + file_url=$(grep -oP '(?<=source_url = )[^\n]+' "$wrap_file") + file_name=$(grep -oP '(?<=source_filename = )[^\n]+' "$wrap_file") + file_hash=sha256:$(grep -oP '(?<=source_hash = )[^\n]+' "$wrap_file") + if ! file_hash_nix=$(nix hash convert "$file_hash" 2>/dev/null); then + return + fi + file_ext="${file_name##*.}" + cat </dev/null) + if [ -z "$patch_hash_nix" ]; then + echo "Failed to convert patch hash: $patch_hash" + return + fi + cat < Date: Thu, 5 Mar 2026 21:09:18 +0100 Subject: [PATCH 65/78] build: update jni-utils flake --- native/flake.lock | 6 +++--- native/flake.nix | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/native/flake.lock b/native/flake.lock index 89a5171..0b92934 100644 --- a/native/flake.lock +++ b/native/flake.lock @@ -24,11 +24,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1772739475, - "narHash": "sha256-tjBJd0irZOg6zsDgqaVdp+o7MFb2gCrdVYgMtG7fqyc=", + "lastModified": 1772741310, + "narHash": "sha256-29fwLX6xInceSXDsIabjToPWARQ2f2O3i4cDTWtg1RM=", "owner": "silenium-dev", "repo": "jni-utils", - "rev": "8be0e61d0a2ec9ac6af731a4004740e017bf5c99", + "rev": "6573af12e4996fdedef0d176e4037c4a0256f0dd", "type": "github" }, "original": { diff --git a/native/flake.nix b/native/flake.nix index 5fd9604..0f95f83 100644 --- a/native/flake.nix +++ b/native/flake.nix @@ -184,6 +184,5 @@ cd "$sourceRoot" ''; }; - checks = packages; }; } From e5dcea411bdd231371ee5e1941450c21983ae1cb Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Thu, 5 Mar 2026 21:28:21 +0100 Subject: [PATCH 66/78] build: update jni-utils flake and copy over binary dependencies (ffmpeg on linux, mpv on windows) to output --- native/flake.lock | 6 +++--- native/flake.nix | 13 ++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/native/flake.lock b/native/flake.lock index 0b92934..988b69d 100644 --- a/native/flake.lock +++ b/native/flake.lock @@ -24,11 +24,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1772741310, - "narHash": "sha256-29fwLX6xInceSXDsIabjToPWARQ2f2O3i4cDTWtg1RM=", + "lastModified": 1772742428, + "narHash": "sha256-V2Lf4VLYIB38iCSpaQ8+uMcV6sS5WZ9XBDLEr7OT5uc=", "owner": "silenium-dev", "repo": "jni-utils", - "rev": "6573af12e4996fdedef0d176e4037c4a0256f0dd", + "rev": "210e6380d2fa35201477f4e6244dafbcb9fe52f4", "type": "github" }, "original": { diff --git a/native/flake.nix b/native/flake.nix index 0f95f83..f4f04ce 100644 --- a/native/flake.nix +++ b/native/flake.nix @@ -137,7 +137,7 @@ runHook postUnpack ''; - postUnpackPhase = targetSystem : '' + postUnpackPhase = targetSystem: '' shopt -s globstar case "${targetSystem}" in *-windows) @@ -183,6 +183,17 @@ echo "changing source root: $sourceRoot" cd "$sourceRoot" ''; + + postInstallPhase = targetSystem: '' + case "${targetSystem}" in + *-linux) + cp -d subprojects/ffmpeg/lib/{libavcodec,libavdevice,libavfilter,libavformat,libavutil,libswresample,libswscale}.so* $out/lib + ;; + *-windows) + cp subprojects/mpv/libmpv-2.dll $out/lib + ;; + esac + ''; }; }; } From 2a945919da04ce14fc592eacc633972c0ccb8c77 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 00:20:52 +0100 Subject: [PATCH 67/78] build: integrate nix build with gradle --- .../compose/av/build/MesonCleanTask.kt | 36 ---- .../compose/av/build/MesonCompileTask.kt | 64 ------- .../compose/av/build/MesonSetupTask.kt | 67 ------- .../compose/av/build/NativesExtension.kt | 8 +- .../compose/av/build/NativesPlugin.kt | 92 +++++----- .../silenium/compose/av/build/NixBuildTask.kt | 24 +++ .../av/build/PrepareSubprojectsTask.kt | 165 ------------------ native/build.gradle.kts | 16 +- native/flake.lock | 6 +- native/flake.nix | 19 +- .../silenium/multimedia/core/util/Natives.kt | 23 +++ 11 files changed, 122 insertions(+), 398 deletions(-) delete mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt delete mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt delete mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt create mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/NixBuildTask.kt delete mode 100644 build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt deleted file mode 100644 index cb5f7c6..0000000 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCleanTask.kt +++ /dev/null @@ -1,36 +0,0 @@ -package dev.silenium.compose.av.build - -import dev.silenium.libs.jni.Platform -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Exec -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.TaskAction -import java.io.File -import java.io.Serializable - -abstract class MesonCleanTask : Exec() { - @get:Input - abstract val targetDir: Property - - @get:Input - abstract val platform: Property - - @TaskAction - override fun exec() { - val platformFile = targetDir.get().resolve("platform.txt") - if (!platformFile.exists() || platformFile.readText() != platform.get().full) { - targetDir.get().deleteRecursively() // Completely delete target dir on platform mismatch - return - } - - val mesonCommand = arrayOf( - "nix", "develop", ".#${platform.get().osArch}", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", - "ninja", - "-C", targetDir.get().absolutePath, - "clean", - ) - commandLine(*mesonCommand) - - super.exec() - } -} \ No newline at end of file diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt deleted file mode 100644 index bcd8025..0000000 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonCompileTask.kt +++ /dev/null @@ -1,64 +0,0 @@ -package dev.silenium.compose.av.build - -import dev.silenium.libs.jni.NativeLoader -import dev.silenium.libs.jni.Platform -import org.gradle.api.file.Directory -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.file.RegularFile -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.internal.file.FileFactory -import org.gradle.api.internal.file.FilePropertyFactory -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Exec -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputDirectory -import org.gradle.api.tasks.OutputFile -import org.gradle.kotlin.dsl.environment -import java.io.File -import javax.inject.Inject - -abstract class MesonCompileTask : Exec() { - @get:Inject - abstract val fileFactory: FileFactory - - @get:Input - abstract val targetDir: Property - - @get:InputDirectory - abstract val sourceDir: DirectoryProperty - - @get:Input - abstract val javaHome: Property - - @get:Input - abstract val platform: Property - - @get:Input - abstract val libName: Property - - @get:OutputFile - abstract val libPath: RegularFileProperty - - init { - libPath.convention( - targetDir.zip( - platform.zip(libName) { platform, libName -> - val fileNameTemplate = NativeLoader.fileNameTemplate(platform) - "src/${fileNameTemplate.format(libName)}" - } - ) { targetDir, path -> targetDir.resolve(path) } - .map(fileFactory::file)) - inputs.file(targetDir.map { it.resolve("build.ninja") }) - } - - override fun exec() { - environment( - "JAVA_HOME" to javaHome.get().absolutePath, - ) - commandLine( - "nix", "develop", ".#${platform.get().osArch}", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", - "meson", "compile", "-C", targetDir.get().absolutePath, libName.get(), - ) - super.exec() - } -} diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt deleted file mode 100644 index 793bc39..0000000 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/MesonSetupTask.kt +++ /dev/null @@ -1,67 +0,0 @@ -package dev.silenium.compose.av.build - -import dev.silenium.libs.jni.NativePlatform -import dev.silenium.libs.jni.Platform -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Exec -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.OutputDirectory -import org.gradle.kotlin.dsl.environment -import java.io.File -import java.io.Serializable - -abstract class MesonSetupTask : Exec() { - @get:Input - abstract val targetDir: Property - - @get:Input - abstract val javaHome: Property - - @get:Input - abstract val platform: Property - - init { - inputs.file("meson.build") - val outputDirs = listOf( - "meson-info", - ) - val outputFiles = listOf( - "build.ninja", - "platform.txt", - ) - outputFiles.forEach { file -> - outputs.file(targetDir.map { it.resolve(file) }) - } - outputDirs.forEach { dir -> - outputs.dir(targetDir.map { it.resolve(dir) }) - } - } - - override fun exec() { - logger.lifecycle("JAVA_HOME: ${javaHome.get()}") - environment( - "JAVA_HOME" to javaHome.get().absolutePath, - ) - - val platformFile = targetDir.get().resolve("platform.txt") - if (!platformFile.exists() || platformFile.readText() != platform.get().full) { - targetDir.get().deleteRecursively() - } - - val crossArgs = arrayOf("--cross-file", "cross/${platform.get().osArch}.txt") - - val mesonCommand = arrayOf( - "nix", "develop", ".#${platform.get().osArch}", "--ignore-env", "--keep-env-var", "JAVA_HOME", "--command", - "meson", "setup", - "--wipe", - targetDir.get().absolutePath, - *crossArgs, - ) - commandLine(*mesonCommand) - - super.exec() - - platformFile.writeText(platform.get().full) - } -} diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt index 16af2a8..2e571c4 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt @@ -1,10 +1,14 @@ package dev.silenium.compose.av.build -import dev.silenium.libs.jni.Platform +import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property interface NativesExtension { - val platform: Property + val sourceFiles: ConfigurableFileCollection val libName: Property + val libVersion: Property + + val nixFlake: RegularFileProperty + val nixFlakeLock: RegularFileProperty } diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt index b8fbacb..8db9e24 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt @@ -1,15 +1,16 @@ package dev.silenium.compose.av.build import dev.silenium.libs.jni.NativeLoader -import dev.silenium.libs.jni.NativePlatform +import dev.silenium.libs.jni.Platform import org.gradle.api.JavaVersion import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.file.Directory import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.jvm.toolchain.JavaCompiler -import org.gradle.kotlin.dsl.* +import org.gradle.api.tasks.Delete +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.named +import org.gradle.kotlin.dsl.register import org.gradle.language.jvm.tasks.ProcessResources import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinJvmExtension @@ -27,58 +28,55 @@ class NativesPlugin : Plugin { } val ext = target.extensions.create("natives", NativesExtension::class.java) - ext.platform.convention(target.provider(NativePlatform::platform)) - val tmpDir = target.layout.buildDirectory.dir("tmp/natives") - val targetDir = target.layout.buildDirectory.dir("natives") + ext.libVersion.convention(target.version.toString()) + ext.libName.convention(target.name) + ext.nixFlakeLock.convention(target.layout.file(ext.nixFlake.map { it.asFile.resolveSibling("flake.lock") })) + val nixResultDir = target.layout.buildDirectory.dir("nix-result") - val mesonClean = target.tasks.register("mesonClean") { - this.targetDir.set(targetDir.map(Directory::getAsFile)) - this.platform.set(ext.platform) + val nixClean = target.tasks.register("nixClean") { + delete(nixResultDir) } - target.tasks.named("clean") { - dependsOn(mesonClean) + target.tasks.named("clean").configure { + dependsOn(nixClean) } - val prepareSubprojects = target.tasks.register("prepareSubprojects") { - mustRunAfter(mesonClean) - + val nixBuild = target.tasks.register("nixBuild") { doFirst { - tmpDir.get().asFile.deleteRecursively() - tmpDir.get().asFile.mkdirs() + nixResultDir.get().asFile.deleteRecursively() } - downloadDir.set(tmpDir) - platform.set(ext.platform) - } - - val javac = target.tasks.withType().first().javaCompiler.map(JavaCompiler::getExecutablePath) - val javaHome = javac.map { it.asFile.parentFile.parentFile } - val mesonSetup = target.tasks.register("mesonSetup") { - dependsOn(prepareSubprojects) - mustRunAfter(mesonClean) - - this.targetDir.set(targetDir.map(Directory::getAsFile)) - this.platform.set(ext.platform) - this.javaHome.set(javaHome) - - inputs.dir(target.layout.projectDirectory.dir("subprojects.tpl")) - } - - val mesonCompile = target.tasks.register("mesonCompile") { - dependsOn(mesonSetup) - mustRunAfter(mesonClean) - - this.targetDir.set(targetDir.map(Directory::getAsFile)) - this.platform.set(ext.platform) - this.libName.set(ext.libName) - this.javaHome.set(javaHome) - this.sourceDir.set(target.layout.projectDirectory.dir("src")) + group = "build" + inputs.files(ext.sourceFiles) + inputs.files(ext.nixFlake, ext.nixFlakeLock) + libName.set(ext.libName) + resultDir.set(nixResultDir) } target.afterEvaluate { tasks.named("processResources") { - from(mesonCompile.map { it.outputs.files }) { - rename { - NativeLoader.libPath(ext.libName.get(), platform = ext.platform.get()) + val out = nixBuild.flatMap { it.resultDir.asFile } + val targets = mapOf( + Platform(Platform.OS.LINUX, Platform.Arch.X86_64) to "x86_64-linux", + Platform(Platform.OS.LINUX, Platform.Arch.ARM64) to "aarch64-linux", + Platform(Platform.OS.WINDOWS, Platform.Arch.X86_64) to "x86_64-windows", + ) + targets.forEach { (platform, target) -> + val src = out.map { out -> + out.resolve("${ext.libName.get()}-${target}-${ext.libVersion.get()}").resolve("lib") + } + val platformFormat = NativeLoader.fileNameTemplate(platform) + from(src) { + include("*.so") + include("*.dll") + include("*.dylib") + rename { + val matches = platformFormat + .replace(".", "\\.") + .replace("%s", "(.*)") + .toRegex() + .find(it) ?: error("library name does not match platform pattern: $it") + + NativeLoader.libPath(matches.groupValues[1], platform = platform) + } } } } diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NixBuildTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NixBuildTask.kt new file mode 100644 index 0000000..904a82d --- /dev/null +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NixBuildTask.kt @@ -0,0 +1,24 @@ +package dev.silenium.compose.av.build + +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Exec +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputDirectory + +// Never cache as read-only outputs break cache restore +// Caching will instead happen on nix level +abstract class NixBuildTask : Exec() { + @get:Input + abstract val libName: Property + + @get:OutputDirectory + abstract val resultDir: DirectoryProperty + + override fun exec() { + commandLine("nix", "build", "-o", resultDir.get().asFile.absolutePath, ".#${libName.get()}") + standardOutput = System.out + errorOutput = System.out + super.exec() + } +} diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt deleted file mode 100644 index 3a7ac72..0000000 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/PrepareSubprojectsTask.kt +++ /dev/null @@ -1,165 +0,0 @@ -package dev.silenium.compose.av.build - -import dev.silenium.libs.jni.Platform -import org.gradle.api.DefaultTask -import org.gradle.api.file.DirectoryProperty -import org.gradle.api.file.FileSystemOperations -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.* -import org.gradle.internal.logging.progress.ProgressLoggerFactory -import org.gradle.kotlin.dsl.expand -import org.gradle.process.ExecOperations -import org.jetbrains.kotlin.org.apache.commons.codec.digest.DigestUtils -import java.net.URI -import java.nio.file.Files -import javax.inject.Inject -import kotlin.io.path.createParentDirectories -import kotlin.io.path.deleteIfExists -import kotlin.io.path.relativeTo - -abstract class PrepareSubprojectsTask : DefaultTask() { - @get:Inject - abstract val execOps: ExecOperations - - @get:Inject - abstract val fsOps: FileSystemOperations - - @get:Inject - abstract val progressLoggerFactory: ProgressLoggerFactory - - @get:Input - abstract val platform: Property - - @get:Internal - abstract val downloadDir: DirectoryProperty - - @get:Internal - abstract val mpvDlFile: RegularFileProperty - - @get:OutputDirectory - abstract val subprojectDir: DirectoryProperty - - @get:Internal - abstract val packageCacheDir: DirectoryProperty - - @get:InputDirectory - abstract val subprojectTplDir: DirectoryProperty - - init { - mpvDlFile.convention(downloadDir.zip(platform) { dir, p -> dir.file("mpv-win-${p.arch}.7z") }) - subprojectDir.convention(project.layout.projectDirectory.dir("subprojects")) - subprojectTplDir.convention(project.layout.projectDirectory.dir("subprojects.tpl")) - packageCacheDir.convention(project.rootProject.layout.projectDirectory.dir(".gradle/meson-cache/packagecache")) - - outputs.dir(subprojectDir) - inputs.dir(subprojectTplDir) - } - - @TaskAction - fun prepare() { - val cacheLink = subprojectDir.get().asFile.toPath().resolve("packagecache") - cacheLink.deleteIfExists() - downloadDir.get().asFile.mkdirs() - subprojectDir.get().asFile.deleteRecursively() - subprojectDir.get().asFile.mkdirs() - when (platform.get().os) { - Platform.OS.WINDOWS -> { - downloadMpvWindows() - extractMpvSubproject() - configureMpvSubproject() - } - - Platform.OS.LINUX -> { - copyLinuxSubprojects(platform.get()) - } - - else -> Unit - } - packageCacheDir.get().asFile.mkdirs() - Files.createSymbolicLink(cacheLink, packageCacheDir.get().asFile.toPath().relativeTo(cacheLink.parent)) - } - - private fun copyLinuxSubprojects(platform: Platform) { - val ffmpegWrap = "packagefiles/mpv/subprojects/ffmpeg.wrap" - val meta = ffmpegLinux[platform.arch] ?: error("Unsupported platform: ${platform.osArch}") - fsOps.copy { - from(subprojectTplDir.dir(platform.os.toString())) { - exclude(ffmpegWrap) - } - into(subprojectDir) - } - fsOps.copy { - from(subprojectTplDir.file("${platform.os}/${ffmpegWrap}")) - into(subprojectDir.file(ffmpegWrap.substringBeforeLast("/"))) - expand( - "ffmpeg_source_url" to meta.uri.toString(), - "ffmpeg_source_hash" to meta.fileHash, - "ffmpeg_source_filename" to meta.uri.path.substringAfterLast('/'), - "ffmpeg_directory" to meta.uri.path.substringAfterLast('/').removeSuffix(".tar.xz"), - ) - } - } - - private fun downloadMpvWindows() { - val meta = mpvWindows[platform.get().arch] ?: error("Unsupported platform: ${platform.get().arch}") - val file = mpvDlFile.get().asFile - if (file.exists() && file.inputStream().use(DigestUtils::sha256Hex) == meta.fileHash) { - return logger.lifecycle("MPV Windows binaries are up-to-date") - } - - val progressLogger = progressLoggerFactory.newOperation(PrepareSubprojectsTask::class.java) - progressLogger.start("Downloading MPV Windows binaries", "") - - file.toPath().createParentDirectories() - file.outputStream().use { output -> - downloadFile(progressLogger, logger, meta.uri, output) - } - } - - private fun extractMpvSubproject() { - execOps.exec { - commandLine( - "nix-shell", "-p", "p7zip", "--command", - "7z x -o${subprojectDir.dir("mpv").get().asFile.absolutePath} ${mpvDlFile.get().asFile.absolutePath}", - ) - }.assertNormalExitValue() - } - - private fun configureMpvSubproject() { - fsOps.copy { - from(subprojectTplDir.dir("${platform.get().os}/packagefiles/mpv")) - into(subprojectDir.dir("mpv")) - } - } -} - -internal data class MpvWindowsMetadata(val arch: String, val fileHash: String) { - val uri: URI by lazy { URI.create("https://repoflow.silenium.dev/api/universal/personal/github-releases/shinchiro/mpv-winbuild-cmake/20260225/mpv-dev-${arch}-20260225-git-92ed2d2.7z") } -} - -internal val mpvWindows = mapOf( - Platform.Arch.ARM64 to MpvWindowsMetadata( - "aarch64", - "783b60c8ca94eda76596f2b355f860f35dffe6f56aa2e3762f2fc7fd3f7304d2" - ), - Platform.Arch.X86_64 to MpvWindowsMetadata( - "x86_64", - "5d266a6899b8bb175a6857c93c53679f040953167a2bed65b83edb03e0b48b65" - ), -) - -internal data class FFmpegLinuxMetadata(val arch: String, val fileHash: String) { - val uri: URI by lazy { URI.create("https://repoflow.silenium.dev/api/universal/personal/github-releases/BtbN/FFmpeg-Builds/autobuild-2026-02-25-13-05/ffmpeg-n8.0.1-64-g15504610b0-${arch}-gpl-shared-8.0.tar.xz") } -} - -internal val ffmpegLinux = mapOf( - Platform.Arch.X86_64 to FFmpegLinuxMetadata( - "linux64", - "bb09d1cad8016c92e3ce323481144f18bef41ffd5de81efa41a1d071dbcbb52f" - ), - Platform.Arch.ARM64 to FFmpegLinuxMetadata( - "linuxarm64", - "b4ad73f547a77da7b9d94661962a6d5d312a945f4bcb3f82c790b2730ce2c52f" - ), -) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 71351f5..2510b44 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -1,6 +1,3 @@ -import dev.silenium.libs.jni.NativePlatform -import dev.silenium.libs.jni.Platform - plugins { id("av-natives") } @@ -9,19 +6,16 @@ val deployNative = (findProperty("deploy.native") as String?)?.toBoolean() ?: tr natives { libName = rootProject.name - platform = providers.gradleProperty("deploy.platform") - .map(Platform.Companion::invoke) - .orElse(NativePlatform.platform()) + libVersion = "0.1.0" + nixFlake = file("flake.nix") + sourceFiles.from("src", "meson.build", "subprojects.tpl") } publishing { publications { if (deployNative) { - val platform = natives.platform.get() - val libName = rootProject.name - create("natives${platform.capitalized}") { - from(components["java"]) - artifactId = "$libName-natives-$platform" + create("maven") { + from(components["kotlin"]) } } } diff --git a/native/flake.lock b/native/flake.lock index 988b69d..6931c16 100644 --- a/native/flake.lock +++ b/native/flake.lock @@ -24,11 +24,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1772742428, - "narHash": "sha256-V2Lf4VLYIB38iCSpaQ8+uMcV6sS5WZ9XBDLEr7OT5uc=", + "lastModified": 1772752807, + "narHash": "sha256-/j59dcF9R1pwmBLTnODWx88kS+sp+92fnAb7InVYMEM=", "owner": "silenium-dev", "repo": "jni-utils", - "rev": "210e6380d2fa35201477f4e6244dafbcb9fe52f4", + "rev": "a7698b4c08eaa05bc2f490c911bc9b1f111e4d2c", "type": "github" }, "original": { diff --git a/native/flake.nix b/native/flake.nix index f4f04ce..ee23a5a 100644 --- a/native/flake.nix +++ b/native/flake.nix @@ -9,20 +9,30 @@ outputs = { nixpkgs, jni-utils, ... }: let pkgs = nixpkgs.legacyPackages."x86_64-linux"; + fs = nixpkgs.lib.fileset; in - rec { + { packages."x86_64-linux" = jni-utils.lib.buildJNILib { name = "compose-av"; + version = "0.1.0"; mesonTarget = "compose-av"; buildType = "release"; libName = "compose-av"; libDir = "src"; - additionalNativeInputs = [ pkgs.p7zip pkgs.curl pkgs.cacert pkgs.python3 ]; + additionalNativeInputs = targetSystem: pkgs: [ pkgs.p7zip pkgs.curl pkgs.cacert pkgs.python3 ]; + additionalInputs = targetSystem: pkgs: + if targetSystem == "x86_64-windows" then [ ] + else [ pkgs.libxcb pkgs.libxau pkgs.libxdmcp ]; sources = targetSystem: let mpv = import ./nix/mpv-config.nix { inherit pkgs; }; ffmpeg = import ./nix/ffmpeg-config.nix { inherit pkgs; }; + sourceFiles = fs.unions [ + ./src + ./meson.build + ./subprojects.tpl + ]; in (if targetSystem == "x86_64-windows" then [ @@ -41,7 +51,10 @@ }) ]) ++ [ (builtins.path { - path = ./.; + path = fs.toSource { + root = ./.; + fileset = sourceFiles; + }; name = "compose-av"; }) ]; diff --git a/src/main/kotlin/dev/silenium/multimedia/core/util/Natives.kt b/src/main/kotlin/dev/silenium/multimedia/core/util/Natives.kt index b4a5cce..44e748d 100644 --- a/src/main/kotlin/dev/silenium/multimedia/core/util/Natives.kt +++ b/src/main/kotlin/dev/silenium/multimedia/core/util/Natives.kt @@ -1,15 +1,38 @@ package dev.silenium.multimedia.core.util import dev.silenium.libs.jni.NativeLoader +import dev.silenium.libs.jni.Platform import dev.silenium.multimedia.build.BuildConstants object Natives { private var loaded = false + private val platformDeps = mapOf( + Platform.OS.LINUX to setOf( + "avcodec", + "avdevice", + "avfilter", + "avformat", + "avutil", + "compose-av", + "swresample", + "swscale", + ), + Platform.OS.WINDOWS to setOf( + "compose-av", + "libmpv-2", + ), + ) + @Synchronized fun ensureLoaded() { if (!loaded) { + val deps = platformDeps[NativeLoader.nativePlatform.os] + ?: error("Unsupported platform: ${NativeLoader.nativePlatform}") + deps.forEach { + NativeLoader.loadLibraryFromClasspath(it).getOrThrow() + } NativeLoader.loadLibraryFromClasspath(BuildConstants.LIBRARY_NAME).getOrThrow() loaded = true } From 19f2060e05239ad4452787c6ec394da79ba57c1f Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 00:21:09 +0100 Subject: [PATCH 68/78] chore: remove deprecated preview annotation --- .../dev/silenium/multimedia/compose/player/VideoPlayer.kt | 1 + .../silenium/multimedia/compose/player/VideoPlayerControls.kt | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayer.kt b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayer.kt index e4d6fe6..1e1cec3 100644 --- a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayer.kt +++ b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayer.kt @@ -11,6 +11,7 @@ import org.lwjgl.opengl.GL30.* import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds +@Stable class VideoPlayer(hwdec: Boolean = false) : AutoCloseable { class Config(pixelPerfect: Boolean = false) { var pixelPerfect by mutableStateOf(pixelPerfect) diff --git a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayerControls.kt b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayerControls.kt index cf71d97..ffb913c 100644 --- a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayerControls.kt +++ b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayerControls.kt @@ -4,7 +4,6 @@ import androidx.compose.animation.AnimatedContent import androidx.compose.animation.ContentTransform import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.foundation.clickable import androidx.compose.foundation.focusable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -29,7 +28,6 @@ import kotlinx.coroutines.launch import kotlin.time.Duration.Companion.seconds @OptIn(InternalMultimediaApi::class) -@Preview @Composable fun VideoSurfaceControls( player: VideoPlayer, From 24b2b25a5cce7f7e934a916696de2fa80d65021f Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 00:21:21 +0100 Subject: [PATCH 69/78] chore: remove deprecated context-receivers --- build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 420d0cd..0dfaa6f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -68,7 +68,6 @@ tasks { kotlin { compilerOptions { - freeCompilerArgs.add("-Xcontext-receivers") jvmTarget = JvmTarget.JVM_17 } } From e4339ff9bf14d37175fbeb0db6a55f62ff52cbf9 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 00:23:20 +0100 Subject: [PATCH 70/78] chore: small cleanup --- .../kotlin/dev/silenium/compose/av/build/NativesPlugin.kt | 1 + .../silenium/multimedia/compose/player/VideoPlayerControls.kt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt index 8db9e24..2cf3b21 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinJvmExtension import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper +@Suppress("unused") // used as plugin entrypoint class NativesPlugin : Plugin { override fun apply(target: Project) { target.apply() diff --git a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayerControls.kt b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayerControls.kt index ffb913c..9ad74c3 100644 --- a/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayerControls.kt +++ b/src/main/kotlin/dev/silenium/multimedia/compose/player/VideoPlayerControls.kt @@ -113,7 +113,7 @@ fun VideoSurfaceControls( ) { AnimatedContent(paused, transitionSpec = { ContentTransform(fadeIn(), fadeOut()) - }) { it -> + }) { if (it != false) { Icon( Icons.Default.PlayArrow, @@ -175,7 +175,7 @@ fun VideoSurfaceControls( ) { AnimatedContent(fullscreenProvider.isFullscreen, transitionSpec = { ContentTransform(fadeIn(), fadeOut()) - }) { it -> + }) { if (it) { Icon( Icons.Default.FullscreenExit, From 9631b5d3f4e9217307ca9c93b062b0ec43d8f1b7 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 00:35:37 +0100 Subject: [PATCH 71/78] fix: demos --- .../dev/silenium/multimedia/compose/Main.kt | 17 ++++++++--------- .../dev/silenium/multimedia/simple/Main.kt | 6 ++---- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/test/kotlin/dev/silenium/multimedia/compose/Main.kt b/src/test/kotlin/dev/silenium/multimedia/compose/Main.kt index 05a65cf..39296b0 100644 --- a/src/test/kotlin/dev/silenium/multimedia/compose/Main.kt +++ b/src/test/kotlin/dev/silenium/multimedia/compose/Main.kt @@ -15,7 +15,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window -import androidx.compose.ui.window.awaitApplication +import androidx.compose.ui.window.application import dev.silenium.multimedia.compose.player.VideoSurfaceWithControls import dev.silenium.multimedia.compose.player.rememberVideoPlayer import dev.silenium.multimedia.compose.util.LocalFullscreenProvider @@ -25,7 +25,6 @@ import java.nio.file.Files import kotlin.io.path.absolutePathString import kotlin.io.path.outputStream import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.seconds @OptIn(InternalMultimediaApi::class) @Composable @@ -59,12 +58,12 @@ fun App() { ) { var visible by remember { mutableStateOf(true) } var wasPaused by remember { mutableStateOf("no") } - LaunchedEffect(Unit) { - while (isActive) { - delay(2.seconds) - visible = !visible - } - } +// LaunchedEffect(Unit) { +// while (isActive) { +// delay(2.seconds) +// visible = !visible +// } +// } val modifier = when { fullscreen -> Modifier.size( this@BoxWithConstraints.maxWidth, @@ -146,7 +145,7 @@ fun App() { } } -suspend fun main(): Unit = awaitApplication { +fun main(): Unit = application { val state = LocalFullscreenProvider.current.windowState Window(state = state, onCloseRequest = ::exitApplication) { App() diff --git a/src/test/kotlin/dev/silenium/multimedia/simple/Main.kt b/src/test/kotlin/dev/silenium/multimedia/simple/Main.kt index 8ceb98e..4594a7e 100644 --- a/src/test/kotlin/dev/silenium/multimedia/simple/Main.kt +++ b/src/test/kotlin/dev/silenium/multimedia/simple/Main.kt @@ -1,16 +1,14 @@ package dev.silenium.multimedia.simple import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.pager.VerticalPager -import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.window.Window -import androidx.compose.ui.window.awaitApplication +import androidx.compose.ui.window.application import java.nio.file.Files import kotlin.io.path.outputStream -suspend fun main() = awaitApplication { +fun main() = application { val file = remember { val videoFile = Files.createTempFile("video", ".webm") Thread.currentThread().contextClassLoader.getResourceAsStream("1080p.webm").use { From c2463aa5076eab74c825015247487a60c1430656 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 11:22:36 +0100 Subject: [PATCH 72/78] ci: remove dedicated native build step as all natives are build at once via nix --- .github/workflows/build.yaml | 46 +++++++++++++++++------------------- build.gradle.kts | 5 +--- native/build.gradle.kts | 4 ++-- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2a99163..ae7a311 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -11,38 +11,36 @@ permissions: pull-requests: write contents: write jobs: - natives: + build-publish: runs-on: ubuntu-24.04 - strategy: - matrix: - platform: - - 'linux-x86_64' - - 'linux-arm64' - - 'windows-x86_64' steps: - uses: actions/checkout@v6 - uses: cachix/install-nix-action@v31 with: nix_path: nixpkgs=channel:nixos-unstable github_access_token: ${{ secrets.GITHUB_TOKEN }} - - uses: silenium-dev/actions/jni-natives/ubuntu@main + - name: Restore and save Nix store + uses: nix-community/cache-nix-action@v7 with: - gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - snapshot-repo-url: "https://repoflow.silenium.dev/api/maven/public/maven-snapshots" - release-repo-url: "https://repoflow.silenium.dev/api/maven/public/maven-releases" - repo-username: ${{ secrets.REPOFLOW_USERNAME }} - repo-password: ${{ secrets.REPOFLOW_PASSWORD }} - tests: false - java-version: 17 - platform: ${{ matrix.platform }} - kotlin: - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v6 - - uses: cachix/install-nix-action@v31 - with: - nix_path: nixpkgs=channel:nixos-unstable - github_access_token: ${{ secrets.GITHUB_TOKEN }} + # restore and save a cache using this key + primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} + # if there's no cache hit, restore a cache by this prefix + restore-prefixes-first-match: nix-${{ runner.os }}- + # collect garbage until the Nix store size (in bytes) is at most this number + # before trying to save a new cache + # 1G = 1073741824 + gc-max-store-size-linux: 4G + # do purge caches + purge: true + # purge all versions of the cache + purge-prefixes: nix-${{ runner.os }}- + # created more than this number of seconds ago + purge-created: 0 + # or last accessed this duration (ISO 8601 duration format) + # before the start of the `Post Restore and save Nix store` phase + purge-last-accessed: P7D + # except any version with the key that is the same as the `primary-key` + purge-primary-key: never - uses: silenium-dev/actions/kotlin@main with: gradle-cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} diff --git a/build.gradle.kts b/build.gradle.kts index 0dfaa6f..4a4ac09 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,6 @@ plugins { `maven-publish` } -val deployNative = (findProperty("deploy.native") as String?)?.toBoolean() ?: true val deployKotlin = (findProperty("deploy.kotlin") as String?)?.toBoolean() ?: true dependencies { @@ -25,9 +24,7 @@ dependencies { implementation(libs.jna) implementation(libs.bundles.kotlinx) implementation(libs.slf4j.api) // for logging - if (deployNative) { - implementation(project(":native")) - } + implementation(project(":native")) implementation(kotlin("reflect")) testImplementation(compose.desktop.currentOs) diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 2510b44..e5a2334 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("av-natives") } -val deployNative = (findProperty("deploy.native") as String?)?.toBoolean() ?: true +val deployKotlin = (findProperty("deploy.kotlin") as String?)?.toBoolean() ?: true natives { libName = rootProject.name @@ -13,7 +13,7 @@ natives { publishing { publications { - if (deployNative) { + if (deployKotlin) { create("maven") { from(components["kotlin"]) } From 000bfe875673475915e4357b23caadca2ac88841 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 11:27:29 +0100 Subject: [PATCH 73/78] fix: use deploy.kotlin instead of deploy.native --- settings.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 1da32b9..d54ba52 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -16,10 +16,10 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0" } -val deployNative = if (extra.has("deploy.native")) { - extra.get("deploy.native")?.toString()?.toBoolean() ?: true +val deployKotlin = if (extra.has("deploy.kotlin")) { + extra.get("deploy.kotlin")?.toString()?.toBoolean() ?: true } else true -if (deployNative) { +if (deployKotlin) { include(":native") } From 4060758e391c9a09300a5e98dfa01d116ff436ed Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 11:28:31 +0100 Subject: [PATCH 74/78] chore: cleanup --- settings.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index d54ba52..43c8ba3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,3 @@ -import org.gradle.kotlin.dsl.mavenCentral -import org.gradle.kotlin.dsl.repositories - pluginManagement { repositories { maven("https://reposilite.silenium.dev/releases") { From 5deef2d2daca24f4a0553f5e47a5b982bccf683c Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 11:29:14 +0100 Subject: [PATCH 75/78] ci: try fixing branch triggers --- .github/workflows/build.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ae7a311..84000f3 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,8 +1,6 @@ name: "Build and Test" on: push: - branches: - - '*' pull_request: workflow_dispatch: release: From d8b30662d21603b81239beb00c88dc7e9401be64 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 11:45:19 +0100 Subject: [PATCH 76/78] build: show nix build logs in ci --- .../dev/silenium/compose/av/build/NativesExtension.kt | 1 + .../kotlin/dev/silenium/compose/av/build/NixBuildTask.kt | 6 +++++- native/build.gradle.kts | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt index 2e571c4..9c01a8d 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesExtension.kt @@ -11,4 +11,5 @@ interface NativesExtension { val nixFlake: RegularFileProperty val nixFlakeLock: RegularFileProperty + val showLogs: Property } diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NixBuildTask.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NixBuildTask.kt index 904a82d..c95553f 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NixBuildTask.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NixBuildTask.kt @@ -12,11 +12,15 @@ abstract class NixBuildTask : Exec() { @get:Input abstract val libName: Property + @get:Input + abstract val showLogs: Property + @get:OutputDirectory abstract val resultDir: DirectoryProperty override fun exec() { - commandLine("nix", "build", "-o", resultDir.get().asFile.absolutePath, ".#${libName.get()}") + val logArgs = arrayOf("--print-build-logs").takeIf { showLogs.get() } ?: arrayOf() + commandLine("nix", "build", "-o", resultDir.get().asFile.absolutePath, *logArgs, ".#${libName.get()}") standardOutput = System.out errorOutput = System.out super.exec() diff --git a/native/build.gradle.kts b/native/build.gradle.kts index e5a2334..0cbd48f 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -9,6 +9,7 @@ natives { libVersion = "0.1.0" nixFlake = file("flake.nix") sourceFiles.from("src", "meson.build", "subprojects.tpl") + showLogs = providers.environmentVariable("CI").orElse("false").map { it != "false" } } publishing { From c482dcb2d6f740d8a6d4345c2dc6d240b8b09284 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 11:48:43 +0100 Subject: [PATCH 77/78] fix: add missing passthrough --- .../main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt index 2cf3b21..1cefd54 100644 --- a/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt +++ b/build-logic/src/main/kotlin/dev/silenium/compose/av/build/NativesPlugin.kt @@ -50,6 +50,7 @@ class NativesPlugin : Plugin { inputs.files(ext.nixFlake, ext.nixFlakeLock) libName.set(ext.libName) resultDir.set(nixResultDir) + showLogs.set(ext.showLogs) } target.afterEvaluate { From 5a2e8d9d5a31860f5146e486486ee66149478557 Mon Sep 17 00:00:00 2001 From: silenium-dev Date: Fri, 6 Mar 2026 20:37:47 +0100 Subject: [PATCH 78/78] ci: add snapshot and release builds --- .teamcity/settings.kts | 86 +++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/.teamcity/settings.kts b/.teamcity/settings.kts index e51dbe2..7c90879 100644 --- a/.teamcity/settings.kts +++ b/.teamcity/settings.kts @@ -1,35 +1,18 @@ -import jetbrains.buildServer.configs.kotlin.* +import jetbrains.buildServer.configs.kotlin.BuildType import jetbrains.buildServer.configs.kotlin.buildFeatures.perfmon +import jetbrains.buildServer.configs.kotlin.buildFeatures.pullRequests +import jetbrains.buildServer.configs.kotlin.buildSteps.gradle +import jetbrains.buildServer.configs.kotlin.project import jetbrains.buildServer.configs.kotlin.projectFeatures.githubConnection +import jetbrains.buildServer.configs.kotlin.triggers.VcsTrigger import jetbrains.buildServer.configs.kotlin.triggers.vcs - -/* -The settings script is an entry point for defining a TeamCity -project hierarchy. The script should contain a single call to the -project() function with a Project instance or an init function as -an argument. - -VcsRoots, BuildTypes, Templates, and subprojects can be -registered inside the project using the vcsRoot(), buildType(), -template(), and subProject() methods respectively. - -To debug settings scripts in command-line, run the - - mvnDebug org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate - -command and attach your debugger to the port 8000. - -To debug in IntelliJ Idea, open the 'Maven Projects' tool window (View --> Tool Windows -> Maven Projects), find the generate task node -(Plugins -> teamcity-configs -> teamcity-configs:generate), the -'Debug' option is available in the context menu for the task. -*/ +import jetbrains.buildServer.configs.kotlin.version version = "2025.11" project { - - buildType(Build) + buildType(BuildSnapshot) + buildType(BuildRelease) features { githubConnection { @@ -41,16 +24,65 @@ project { } } -object Build : BuildType({ - name = "Build" +abstract class Build( + val publishRepository: String, + val publishUsername: String, + val publishPassword: String, + val publishVersion: String, + val trigger: VcsTrigger.() -> Unit, +) : BuildType({ + name = "Build and Publish" triggers { vcs { + branchFilter = "+:refs/heads/*" } } features { perfmon { } + + pullRequests { + provider = github { + authType = vcsRoot() + ignoreDrafts = true + } + } + } + + requirements { + exists("system.nix.store") + } + + steps { + gradle { + tasks = "build publish" + gradleParams = "-Pdeploy.version=${publishVersion} -Pdeploy.kotlin=true" + incremental = true + param("env.MAVEN_REPO_URL", publishRepository) + param("env.MAVEN_REPO_USERNAME", publishUsername) + param("env.MAVEN_REPO_PASSWORD", publishPassword) + } } }) + +object BuildSnapshot : Build( + publishRepository = "https://repoflow.silenium.dev/api/maven/public/maven-snapshots", + publishUsername = "teamcitypublic", + publishPassword = "credentialsJSON:c8524851-3a17-4ea4-ac26-49a99c5c387c", + publishVersion = "%build.vcs.number%", + trigger = { + branchFilter = "+:refs/heads/*" + } +) + +object BuildRelease : Build( + publishRepository = "https://repoflow.silenium.dev/api/maven/public/maven-releases", + publishUsername = "teamcitypublic", + publishPassword = "credentialsJSON:c8524851-3a17-4ea4-ac26-49a99c5c387c", + publishVersion = "%build.vcs.number%", + trigger = { + branchFilter = "+:refs/tags/*" + } +)