[0.1.28] macOS phase 4: videos through FFmpeg 6.0 for macOS, an LGPL build made by build_macos.jai
This commit is contained in:
parent
a66928b223
commit
3e353c77d8
2
.gitignore
vendored
2
.gitignore
vendored
@ -27,5 +27,7 @@ Thumbs.db
|
||||
/modules/Labels/models/
|
||||
# Segmentation: exported by tools/export_mask2former.py, not committed
|
||||
/modules/Segment/models/
|
||||
# FFmpeg for macOS: the source, build and headers modules/ffmpeg/build_macos.jai makes (its libraries in macos/ are kept)
|
||||
/modules/ffmpeg/macos-build/
|
||||
# Releases: made by release.jai
|
||||
/release/
|
||||
|
||||
@ -269,7 +269,7 @@ What becomes of each file:
|
||||
- **Animated GIFs** are images; their thumbnail is marked **GIF**, and the Capture window says how
|
||||
long they run and opens them in the default viewer.
|
||||
- **Videos** (MP4, MOV, M4V, 3GP, MKV, WebM, AVI, WMV, MPEG, MTS and M2TS, FLV), read with FFmpeg
|
||||
(`modules/ffmpeg`, Windows only): an `.mcap` holding the file exactly as it was, of any size (it is
|
||||
(`modules/ffmpeg`; Windows and macOS, not Linux): an `.mcap` holding the file exactly as it was, of any size (it is
|
||||
copied a few MB at a time, never read whole), and a frame from it a tenth of the way in (at most 3
|
||||
seconds), turned the right way up, which is what the grid, the Capture window, OCR and labels see.
|
||||
The date is the phone's (Apple's creation date), else one in its name, else the video's own
|
||||
|
||||
@ -49,7 +49,7 @@ APP_NAME :: "mcap";
|
||||
APP_FOLDER_NAME :: "mcap";
|
||||
GIT_BRANCH :: "check";
|
||||
GIT_HASH :: "-";
|
||||
VERSION :: "0.1.27";
|
||||
VERSION :: "0.1.28";
|
||||
BUILD_DATE :: "-";
|
||||
DEBUG :: true;
|
||||
COMPILE_TESTS :: true;
|
||||
|
||||
11
first.jai
11
first.jai
@ -8,7 +8,7 @@ APP_NAME :: "mcap";
|
||||
APP_FOLDER_NAME :: "mcap";
|
||||
APP_BUNDLE_IDENTIFIER :: "com.example.mcap";
|
||||
|
||||
VERSION :: "0.1.27";
|
||||
VERSION :: "0.1.28";
|
||||
// Where everything goes: bin/, or bin-headless/ for builds made with no_crash_dialog, so automated
|
||||
// builds never write over the ones you run by hand.
|
||||
build_directory := "bin";
|
||||
@ -215,7 +215,7 @@ finish_main_build :: (build: Pending_Build) {
|
||||
MACOS_BUNDLE_DYLIBS :: string.["libSDL3.0.dylib"];
|
||||
|
||||
// mcap.app for the release build, mcap-debug.app for the debug one, with an identifier of its own
|
||||
// so that its permissions are granted apart. Each holds the executable, SDL3 beside it,
|
||||
// so that its permissions are granted apart. Each holds the executable, SDL3 and FFmpeg beside it,
|
||||
// onnxruntime in Contents/Frameworks, and the icon, Info.plist and models in Contents/Resources.
|
||||
// The app finds data/, logs/ and images/ in the folder holding the bundle (see
|
||||
// app_install_directory), and the models in Contents/Resources (app_resource_directory).
|
||||
@ -241,6 +241,8 @@ finish_main_build :: (build: Pending_Build) {
|
||||
|
||||
copied := copy_file(tprint("%/%", build_directory, executable_name), tprint("%/%", executable_folder, executable_name));
|
||||
for MACOS_BUNDLE_DYLIBS copied &&= copy_file(tprint("assets/%", it), tprint("%/%", executable_folder, it));
|
||||
// FFmpeg, linked against, so beside the executable as SDL3 is (@loader_path).
|
||||
for file_list("modules/ffmpeg/macos") if ends_with(it, ".dylib") copied &&= copy_file(it, tprint("%/%", executable_folder, path_filename(it)));
|
||||
if !copied {
|
||||
log_error("ERROR: Couldn't copy the executable and its dylibs into %\n", app);
|
||||
return;
|
||||
@ -368,9 +370,12 @@ copy_assets :: () {
|
||||
log("OCR: the models have not been fetched; run jai fetch_models.jai in modules/OCR for OCR.");
|
||||
}
|
||||
|
||||
// Videos: FFmpeg's DLLs beside the executable (modules/ffmpeg/windows, in git), the same way.
|
||||
// Videos: FFmpeg's libraries beside the executable (modules/ffmpeg/windows and macos, in git), the
|
||||
// same way. The executable finds the dylibs there through its @loader_path rpath.
|
||||
#if OS == .WINDOWS {
|
||||
for file_list("modules/ffmpeg/windows") if ends_with(it, ".dll") copy_if_changed(it, tprint("%/%", build_directory, path_filename(it)));
|
||||
} else #if OS == .MACOS {
|
||||
for file_list("modules/ffmpeg/macos") if ends_with(it, ".dylib") copy_if_changed(it, tprint("%/%", build_directory, path_filename(it)));
|
||||
}
|
||||
|
||||
// Labels: its models in bin/label-models, the same way.
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
// the camera RAW formats that are TIFF inside: image_kind_from_name tells those apart.
|
||||
//
|
||||
// Videos (video.jai) are told apart here too, by their first bytes or their extension; video_poster
|
||||
// reads a frame from one with FFmpeg, on Windows, and gif_info counts an animated GIF's frames.
|
||||
// reads a frame from one with FFmpeg, on Windows and macOS, and gif_info counts an animated GIF's frames.
|
||||
//
|
||||
// Thread-safe: every call stands alone, and WIC is set up and released on the calling thread; ImageIO
|
||||
// needs no setting up.
|
||||
@ -266,7 +266,7 @@ png_size :: (png: [] u8) -> width: s64, height: s64, ok: bool {
|
||||
#load "video.jai";
|
||||
#if OS == .WINDOWS #load "wic.jai";
|
||||
#if OS == .MACOS #load "imageio.jai";
|
||||
#if OS == .WINDOWS #load "video_ffmpeg.jai";
|
||||
#if OS == .WINDOWS || OS == .MACOS #load "video_ffmpeg.jai";
|
||||
|
||||
#scope_module
|
||||
|
||||
|
||||
@ -24,9 +24,9 @@ Video_Info :: struct {
|
||||
// start with; the first frame of a clip shorter than a second.
|
||||
VIDEO_POSTER_MAX_SECONDS :: 3.0;
|
||||
|
||||
#if OS != .WINDOWS {
|
||||
#if OS == .LINUX {
|
||||
video_poster :: (path: string) -> Image, Video_Info, ok: bool, error: string {
|
||||
return .{}, .{}, false, "videos are only read on Windows";
|
||||
return .{}, .{}, false, "videos are only read on Windows and macOS";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// video_poster on Windows, with FFmpeg (modules/ffmpeg). See video.jai.
|
||||
// video_poster on Windows and macOS, with FFmpeg (modules/ffmpeg). See video.jai.
|
||||
|
||||
video_poster :: (path: string) -> Image, Video_Info, ok: bool, error: string {
|
||||
image: Image;
|
||||
|
||||
@ -2,6 +2,19 @@
|
||||
|
||||
FFmpeg bindings for jai and some examples decoding and play videos.
|
||||
|
||||
## In mcap
|
||||
|
||||
FFmpeg 6.0 on both systems, so the two sets of bindings match:
|
||||
|
||||
- **Windows:** `windows/` holds the DLLs and import libraries of a GPL "full" build from gyan.dev
|
||||
(`windows/LICENSE-BUILD.txt`), and `windows.jai` the bindings made from its headers (Setup below).
|
||||
- **macOS:** `macos/` holds `libavcodec`, `libavformat`, `libavutil`, `libswresample` and `libswscale`,
|
||||
an LGPL build for Apple silicon made from the release's source by `jai build_macos.jai` (about a
|
||||
minute; `macos/LICENSE-BUILD.txt` has its configure options). It also installs the headers in
|
||||
`macos-build/` (not in git), from which `jai generate.jai` on a Mac makes `macos.jai`. The libraries
|
||||
are linked with `no_dll`, so the compiler does not load them, and copied beside the executable,
|
||||
where its `@loader_path` rpath finds them.
|
||||
|
||||
## Setup
|
||||
|
||||
The FFmpeg libaries and header files are not included in this repo as I didn't want to have to deal with license
|
||||
|
||||
117
modules/ffmpeg/build_macos.jai
Normal file
117
modules/ffmpeg/build_macos.jai
Normal file
@ -0,0 +1,117 @@
|
||||
// Builds the FFmpeg 6.0 libraries mcap uses on macOS (avformat, avcodec, avutil, swscale and
|
||||
// swresample) from the release's source, its SHA-256 checked, and puts them in macos/ with the
|
||||
// headers the bindings are made from (generate.jai) in macos-build/install/include. The same version
|
||||
// as the Windows DLLs (windows/), so the two sets of bindings match.
|
||||
//
|
||||
// cd modules/ffmpeg && jai build_macos.jai
|
||||
//
|
||||
// An LGPL build: no GPL parts (the Windows DLLs are a GPL build with libx264), nothing from outside
|
||||
// macOS (--disable-autodetect, pkg-config pointed nowhere, so nothing from Homebrew is linked), and
|
||||
// VideoToolbox and AudioToolbox for the hardware codecs. Needs Apple's command line tools: curl,
|
||||
// tar, make and clang. A few minutes on Apple silicon.
|
||||
|
||||
FFMPEG_VERSION :: "6.0";
|
||||
FFMPEG_ARCHIVE :: "ffmpeg-6.0.tar.xz";
|
||||
FFMPEG_SHA256 :: "57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082";
|
||||
|
||||
BUILD_FOLDER :: "macos-build"; // the source, the build and the installed headers; not in git
|
||||
OUTPUT_FOLDER :: "macos"; // the libraries, in git as windows/ is
|
||||
|
||||
// Each library as its major version names it, which is how they find each other (@rpath/...).
|
||||
LIBRARIES :: string.["libavcodec.60.dylib", "libavformat.60.dylib", "libavutil.58.dylib", "libswresample.4.dylib", "libswscale.7.dylib"];
|
||||
|
||||
CONFIGURE_OPTIONS :: string.[
|
||||
"--install-name-dir=@rpath",
|
||||
"--enable-shared", "--disable-static",
|
||||
"--disable-programs", "--disable-doc",
|
||||
"--disable-avdevice", "--disable-avfilter", "--disable-postproc", "--disable-network",
|
||||
"--disable-autodetect",
|
||||
"--enable-videotoolbox", "--enable-audiotoolbox", "--enable-zlib", "--enable-bzlib",
|
||||
"--extra-cflags=-mmacosx-version-min=14.0", "--extra-ldflags=-mmacosx-version-min=14.0",
|
||||
];
|
||||
|
||||
#run,stallable {
|
||||
set_build_options_dc(.{do_output = false});
|
||||
#if OS != .MACOS {
|
||||
log_error("build_macos.jai builds on a Mac only.");
|
||||
return;
|
||||
}
|
||||
if !build() compiler_set_workspace_status(.FAILED);
|
||||
}
|
||||
|
||||
build :: () -> bool {
|
||||
here := get_working_directory();
|
||||
build_folder := tprint("%/%", here, BUILD_FOLDER);
|
||||
make_directory_if_it_does_not_exist(build_folder);
|
||||
|
||||
archive := tprint("%/%", build_folder, FFMPEG_ARCHIVE);
|
||||
if !file_exists(archive) || sha256_of(archive) != FFMPEG_SHA256 {
|
||||
url := tprint("https://ffmpeg.org/releases/%", FFMPEG_ARCHIVE);
|
||||
log("Downloading %...", url);
|
||||
result := run_command("curl", "-L", "--fail", "--progress-bar", "-o", archive, url);
|
||||
if result.exit_code != 0 { log_error("curl failed (exit code %).", result.exit_code); return false; }
|
||||
hash := sha256_of(archive);
|
||||
if hash != FFMPEG_SHA256 {
|
||||
log_error("% has SHA-256 %, expected %; it was not used.", archive, hash, FFMPEG_SHA256);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
source := tprint("%/ffmpeg-%", build_folder, FFMPEG_VERSION);
|
||||
install := tprint("%/install", build_folder);
|
||||
run_command("rm", "-rf", source, install);
|
||||
result := run_command("tar", "xf", archive, "-C", build_folder);
|
||||
if result.exit_code != 0 { log_error("tar could not unpack %.", archive); return false; }
|
||||
|
||||
log("Configuring...");
|
||||
arguments: [..] string;
|
||||
array_add(*arguments, "env", "PKG_CONFIG_LIBDIR=", "PKG_CONFIG_PATH=", "./configure", tprint("--prefix=%", install));
|
||||
array_add(*arguments, ..CONFIGURE_OPTIONS);
|
||||
result = run_command(..arguments, working_directory = source);
|
||||
if result.exit_code != 0 { log_error("configure failed; see %/ffbuild/config.log.", source); return false; }
|
||||
|
||||
log("Building...");
|
||||
cpus := get_number_of_processors();
|
||||
result = run_command("make", tprint("-j%", cpus), working_directory = source);
|
||||
if result.exit_code != 0 { log_error("make failed."); return false; }
|
||||
result = run_command("make", "install", working_directory = source);
|
||||
if result.exit_code != 0 { log_error("make install failed."); return false; }
|
||||
|
||||
output := tprint("%/%", here, OUTPUT_FOLDER);
|
||||
run_command("rm", "-rf", output);
|
||||
make_directory_if_it_does_not_exist(output);
|
||||
for LIBRARIES {
|
||||
// The major-version name is a link to the full one; the file itself is copied under that name.
|
||||
if !copy_file(tprint("%/lib/%", install, it), tprint("%/%", output, it)) { log_error("Could not copy %.", it); return false; }
|
||||
run_command("strip", "-x", tprint("%/%", output, it));
|
||||
}
|
||||
write_entire_file(tprint("%/LICENSE-BUILD.txt", output), tprint(LICENSE_TEXT, FFMPEG_VERSION, FFMPEG_ARCHIVE, FFMPEG_SHA256, join(..CONFIGURE_OPTIONS, "\n ")));
|
||||
log("Put % libraries in % and the headers in %/include (FFmpeg %, LGPL).", LIBRARIES.count, output, install, FFMPEG_VERSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
LICENSE_TEXT :: #string TEXT
|
||||
FFmpeg % shared libraries for macOS on Apple silicon, built by modules/ffmpeg/build_macos.jai.
|
||||
|
||||
Source: https://ffmpeg.org/releases/%
|
||||
SHA-256: %
|
||||
|
||||
License: LGPL version 2.1 or later (no GPL or non-free parts). The source is at the address above;
|
||||
the libraries are built from it unchanged, with these configure options:
|
||||
%
|
||||
TEXT
|
||||
|
||||
// Lowercase hex, or "" when it could not be worked out.
|
||||
sha256_of :: (path: string) -> string {
|
||||
result, output := run_command("shasum", "-a", "256", path, capture_and_return_output = true);
|
||||
if result.exit_code != 0 return "";
|
||||
return to_lower_copy(trim(split(output, " ")[0]));
|
||||
}
|
||||
|
||||
#import "Basic";
|
||||
#import "Compiler";
|
||||
#import "File";
|
||||
#import "File_Utilities";
|
||||
#import "Process";
|
||||
#import "String";
|
||||
#import "System";
|
||||
@ -46,10 +46,13 @@ FOOTER :: #string DONE
|
||||
|
||||
DONE
|
||||
|
||||
INCLUDE_PATH :: "src";
|
||||
// Windows: the headers of the downloaded build, copied to src. macOS: those build_macos.jai installs.
|
||||
#if OS == .MACOS INCLUDE_PATH :: "macos-build/install/include";
|
||||
else INCLUDE_PATH :: "src";
|
||||
|
||||
generate_bindings :: () -> bool {
|
||||
output_filename := "windows.jai";
|
||||
#if OS == .MACOS output_filename := "macos.jai";
|
||||
else output_filename := "windows.jai";
|
||||
|
||||
opts: Generate_Bindings_Options;
|
||||
{
|
||||
@ -67,19 +70,31 @@ generate_bindings :: () -> bool {
|
||||
// doesn't work, just get a load of __UnknownLib dont you :roll:.
|
||||
// strip_flags &= ~.SYMBOLS_WITH_UNKNOWN_FOREIGN_LIBS;
|
||||
|
||||
array_add(*libpaths, "windows");
|
||||
|
||||
libraries := string.[
|
||||
"avcodec-60",
|
||||
"avdevice-60",
|
||||
"avfilter-9",
|
||||
"avformat-60",
|
||||
"avutil-58",
|
||||
"postproc-57",
|
||||
"swresample-4",
|
||||
"swscale-7",
|
||||
];
|
||||
for libraries array_add(*libnames, it);
|
||||
#if OS == .MACOS {
|
||||
// The five libraries build_macos.jai makes, as their major versions name them; with the
|
||||
// extension, since the generator takes a name with a dot in it for a whole file name.
|
||||
array_add(*libpaths, "macos");
|
||||
library_names :: string.[
|
||||
"libavcodec.60.dylib",
|
||||
"libavformat.60.dylib",
|
||||
"libavutil.58.dylib",
|
||||
"libswresample.4.dylib",
|
||||
"libswscale.7.dylib",
|
||||
];
|
||||
} else {
|
||||
array_add(*libpaths, "windows");
|
||||
library_names :: string.[
|
||||
"avcodec-60",
|
||||
"avdevice-60",
|
||||
"avfilter-9",
|
||||
"avformat-60",
|
||||
"avutil-58",
|
||||
"postproc-57",
|
||||
"swresample-4",
|
||||
"swscale-7",
|
||||
];
|
||||
}
|
||||
for library_names array_add(*libnames, it);
|
||||
|
||||
array_add(*include_paths, INCLUDE_PATH);
|
||||
|
||||
@ -89,7 +104,7 @@ generate_bindings :: () -> bool {
|
||||
// pick the headers I want!
|
||||
#if false {
|
||||
dirs_to_visit: [..] string;
|
||||
for libraries array_add(*dirs_to_visit, tprint("%/lib%", INCLUDE_PATH, it));
|
||||
for library_names array_add(*dirs_to_visit, tprint("%/lib%", INCLUDE_PATH, it));
|
||||
|
||||
file_visitor :: (info: *File_Visit_Info, source_files : *[..] string) {
|
||||
assert(info != null, "info (%) != null", info);
|
||||
@ -121,7 +136,7 @@ generate_bindings :: () -> bool {
|
||||
array_add(*source_files, tprint("%/libavformat/avformat.h", INCLUDE_PATH));
|
||||
array_add(*source_files, tprint("%/libswscale/swscale.h", INCLUDE_PATH));
|
||||
|
||||
array_add(*system_include_paths, GENERATOR_DEFAULT_SYSTEM_INCLUDE_PATH);
|
||||
// system_include_paths left empty: the generator fills in this system's own.
|
||||
|
||||
builder: String_Builder;
|
||||
append(*builder, HEADER);
|
||||
@ -134,6 +149,14 @@ generate_bindings :: () -> bool {
|
||||
print("Generating ffmpeg bindings...\n");
|
||||
result := generate_bindings(opts, output_filename);
|
||||
|
||||
// The compiler loads each #library to run code at compile time, but there the dylibs cannot find
|
||||
// each other through @rpath; nothing of FFmpeg's is run then, so none is loaded (no_dll).
|
||||
#if OS == .MACOS if result {
|
||||
text, ok := read_entire_file(output_filename);
|
||||
if !ok return false;
|
||||
result = write_entire_file(output_filename, replace(text, " :: #library \"macos/", " :: #library,no_dll \"macos/"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -243,7 +266,7 @@ generate_error_codes :: (b: *String_Builder) {
|
||||
for info_struct.members longest_name_length = max(longest_name_length, it.name.count);
|
||||
for info_struct.members {
|
||||
slot := cast (*u8) *dummy + it.offset_in_bytes;
|
||||
value := << cast(*s32) slot;
|
||||
value := (cast(*s32) slot).*;
|
||||
append(b, it.name);
|
||||
num_spaces := longest_name_length - it.name.count;
|
||||
for 1..num_spaces append(b, " ");
|
||||
|
||||
12947
modules/ffmpeg/macos.jai
Normal file
12947
modules/ffmpeg/macos.jai
Normal file
File diff suppressed because it is too large
Load Diff
23
modules/ffmpeg/macos/LICENSE-BUILD.txt
Normal file
23
modules/ffmpeg/macos/LICENSE-BUILD.txt
Normal file
@ -0,0 +1,23 @@
|
||||
FFmpeg 6.0 shared libraries for macOS on Apple silicon, built by modules/ffmpeg/build_macos.jai.
|
||||
|
||||
Source: https://ffmpeg.org/releases/ffmpeg-6.0.tar.xz
|
||||
SHA-256: 57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082
|
||||
|
||||
License: LGPL version 2.1 or later (no GPL or non-free parts). The source is at the address above;
|
||||
the libraries are built from it unchanged, with these configure options:
|
||||
--install-name-dir=@rpath
|
||||
--enable-shared
|
||||
--disable-static
|
||||
--disable-programs
|
||||
--disable-doc
|
||||
--disable-avdevice
|
||||
--disable-avfilter
|
||||
--disable-postproc
|
||||
--disable-network
|
||||
--disable-autodetect
|
||||
--enable-videotoolbox
|
||||
--enable-audiotoolbox
|
||||
--enable-zlib
|
||||
--enable-bzlib
|
||||
--extra-cflags=-mmacosx-version-min=14.0
|
||||
--extra-ldflags=-mmacosx-version-min=14.0
|
||||
BIN
modules/ffmpeg/macos/libavcodec.60.dylib
Normal file
BIN
modules/ffmpeg/macos/libavcodec.60.dylib
Normal file
Binary file not shown.
BIN
modules/ffmpeg/macos/libavformat.60.dylib
Normal file
BIN
modules/ffmpeg/macos/libavformat.60.dylib
Normal file
Binary file not shown.
BIN
modules/ffmpeg/macos/libavutil.58.dylib
Normal file
BIN
modules/ffmpeg/macos/libavutil.58.dylib
Normal file
Binary file not shown.
BIN
modules/ffmpeg/macos/libswresample.4.dylib
Normal file
BIN
modules/ffmpeg/macos/libswresample.4.dylib
Normal file
Binary file not shown.
BIN
modules/ffmpeg/macos/libswscale.7.dylib
Normal file
BIN
modules/ffmpeg/macos/libswscale.7.dylib
Normal file
Binary file not shown.
@ -7,7 +7,9 @@ size_t :: u64;
|
||||
|
||||
#if OS == .WINDOWS {
|
||||
#load "windows.jai";
|
||||
} else #if OS == .MACOS {
|
||||
#load "macos.jai"; // generated from build_macos.jai's headers; its libraries are in macos/
|
||||
} else {
|
||||
#assert false, "Only windows has bindings atm, sorry bros!";
|
||||
#assert false, "FFmpeg has bindings for Windows and macOS only.";
|
||||
}
|
||||
|
||||
|
||||
@ -376,7 +376,7 @@ import_file :: (path: string) -> Import_Outcome, text: string, new_path: string
|
||||
|
||||
// A video: hashed and copied into its .mcap a few MB at a time, so it can be larger than memory.
|
||||
import_video_file :: (path: string, name: string, head: [] u8, size: s64, modified: Apollo_Time) -> Import_Outcome, text: string, new_path: string {
|
||||
if OS != .WINDOWS return .SKIPPED, "video (Windows only)", "";
|
||||
if OS == .LINUX return .SKIPPED, "video (Windows and macOS only)", "";
|
||||
|
||||
hash, hashed := import_hash_file(.{path = path, offset = 0, size = size});
|
||||
if !hashed return .FAILED, "cannot be read", "";
|
||||
|
||||
@ -254,7 +254,7 @@ open_file_proc :: (thread: *Thread) -> s64 {
|
||||
}
|
||||
|
||||
case .VIDEO;
|
||||
#if OS == .WINDOWS {
|
||||
#if OS == .WINDOWS || OS == .MACOS {
|
||||
image, video, ok, poster_error := video_poster(path);
|
||||
if !ok { error = poster_error; }
|
||||
else {
|
||||
@ -265,7 +265,7 @@ open_file_proc :: (thread: *Thread) -> s64 {
|
||||
}
|
||||
to_hash = .{path = path, offset = 0, size = open_file.size};
|
||||
} else {
|
||||
error = "videos are read on Windows only";
|
||||
error = "videos are read on Windows and macOS only";
|
||||
}
|
||||
|
||||
case;
|
||||
@ -492,7 +492,7 @@ open_file_library_ui :: (stage: Open_File_Stage) { using ImGui;
|
||||
return;
|
||||
}
|
||||
if open_file.kind == .UNKNOWN { TextColored(app_theme.palette.warning, "mcap does not import this kind of file."); return; }
|
||||
if OS != .WINDOWS && open_file.kind == .VIDEO { TextColored(app_theme.palette.warning, "Videos are imported on Windows only."); return; }
|
||||
if OS == .LINUX && open_file.kind == .VIDEO { TextColored(app_theme.palette.warning, "Videos are imported on Windows and macOS only."); return; }
|
||||
|
||||
if open_file.importing {
|
||||
if importer.phase == .INDEXING Text("Indexing the library (once; this finds duplicates): %", ocr_scan_progress_text(importer.index_done, importer.index_total));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user