Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,20 @@ jobs:
emsdk-master/emsdk install latest
emsdk-master/emsdk activate latest

- name: Pre-build zlib port
run: |
source emsdk-master/emsdk_env.sh
embuilder build zlib

- name: Build
run: |
source emsdk-master/emsdk_env.sh
mkdir build-web
cd build-web
emcmake cmake ..
emcmake cmake .. \
-DCMAKE_C_FLAGS="-sUSE_ZLIB=1" \
-DCMAKE_CXX_FLAGS="-sUSE_ZLIB=1" \
-DCMAKE_EXE_LINKER_FLAGS="-sUSE_ZLIB=1"
cmake --build . --parallel 4

- name: Check Product
Expand All @@ -117,13 +125,18 @@ jobs:
name: raven-web.zip
path: build-web/raven-web.zip
Windows:
runs-on: windows-latest
runs-on: windows-2022
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 1
submodules: recursive

- name: Install ZLIB
run: |
vcpkg install zlib:x64-windows
echo "CMAKE_PREFIX_PATH=C:/vcpkg/installed/x64-windows" >> $env:GITHUB_ENV

- name: Build
run: |
mkdir build_win64
Expand All @@ -132,6 +145,15 @@ jobs:
cmake --build . --config Debug --parallel 4
cmake --build . --config Release --parallel 4

# vcpkg's zlib port renames the Windows DLL to z.dll (not zlib1.dll).
# raven.exe links against it, so bundle it into the archive next to
# raven.exe so users who download the artifact can actually run it.
- name: Bundle ZLIB DLL for archive
shell: pwsh
run: |
Copy-Item "C:/vcpkg/installed/x64-windows/bin/*.dll" "build_win64/Debug/"
Copy-Item "C:/vcpkg/installed/x64-windows/bin/*.dll" "build_win64/Release/"

- name: Check Product
shell: bash
run: |
Expand All @@ -155,17 +177,22 @@ jobs:
strategy:
matrix:
python-version: ["3.9"]
os: [ ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-13, macos-latest ]
os: [ ubuntu-latest, ubuntu-24.04-arm, windows-2022, macos-14, macos-latest ]
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 1
submodules: recursive
- name: Install Dependencies
- name: Install Dependencies (Linux)
run: |
sudo apt-get update
sudo apt-get install -y libglfw3-dev libgtk-3-dev
if: matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm'
- name: Install ZLIB (Windows)
if: matrix.os == 'windows-2022'
run: |
vcpkg install zlib:x64-windows
echo "CMAKE_PREFIX_PATH=C:/vcpkg/installed/x64-windows" >> $env:GITHUB_ENV
- name: Install UV
uses: astral-sh/setup-uv@v7
with:
Expand Down Expand Up @@ -205,4 +232,4 @@ jobs:
uses: actions/upload-artifact@v5
with:
name: sdist
path: dist/*.tar.gz
path: dist/*.tar.gz
65 changes: 46 additions & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,29 @@ include_directories(
${PROJECT_SOURCE_DIR}/libs/nativefiledialog/src/include
)

set(OTIO_SHARED_LIBS OFF)
add_subdirectory("libs/opentimelineio")
include_directories(
${PROJECT_SOURCE_DIR}/libs/opentimelineio/src
${PROJECT_SOURCE_DIR}/libs/opentimelineio/src/deps
${PROJECT_SOURCE_DIR}/libs/opentimelineio/src/deps/Imath/src
${PROJECT_BINARY_DIR}/libs/opentimelineio/src
)

if(NOT EMSCRIPTEN AND NOT WIN32)
set(GLFW_BUILD_EXAMPLES OFF)
set(GLFW_BUILD_TESTS OFF)
set(GLFW_BUILD_DOCS OFF)
set(BUILD_SHARED_LIBS OFF)
add_subdirectory("libs/glfw")
endif()

# -----------------------------------------------------------------------------
# minizip-ng
#
# raven owns this dependency directly rather than relying on OTIO's vendored
# copy. Two reasons:
#
# 1. raven's previous pin (362b091) builds cleanly under Emscripten, while
# OTIO's current pin (d69cb0a5) does not: minizip-ng's CMake configure
# calls check_type_size("DIR*") during cross-compile, that returns
# false, and mz_os.h then declares `typedef struct DIR DIR;` which
# collides with Emscripten musl's `typedef struct __dirstream DIR;`
# from <dirent.h>. (See upstream issue: TODO.)
#
# 2. This exercises OTIO's OTIO_FIND_MINIZIP_NG=ON code path, which lets
# downstream projects supply their own minizip-ng. That path landed in
# OTIO's C++ bundle work but hasn't had a real-world consumer yet.
#
# The MZ_* settings mirror raven's previous configuration, minus features
# OTIO's bundle.cpp doesn't need.
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(MZ_FETCH_LIBS ON)
set(MZ_ZLIB ON)
# OTIOZ doesn't need any of these
set(MZ_BZIP2 OFF)
set(MZ_LZMA OFF)
set(MZ_ZSTD OFF)
Expand All @@ -90,6 +90,34 @@ set(MZ_LIBBSD OFF)
set(MZ_ICONV OFF)
add_subdirectory("libs/minizip-ng")

# Let OTIO's find_package(minizip-ng REQUIRED) resolve to the copy we just
# built via add_subdirectory. See cmake/Findminizip-ng.cmake.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

# Tell OTIO to find minizip-ng rather than use its own vendored copy, and
# don't let OTIO run `git submodule update` during configure (submodules
# are already fetched by actions/checkout with submodules: recursive, and
# letting OTIO re-fetch them would reset any local checkouts).
set(OTIO_FIND_MINIZIP_NG ON)
set(OTIO_AUTOMATIC_SUBMODULES OFF)

set(OTIO_SHARED_LIBS OFF)
add_subdirectory("libs/opentimelineio")
include_directories(
${PROJECT_SOURCE_DIR}/libs/opentimelineio/src
${PROJECT_SOURCE_DIR}/libs/opentimelineio/src/deps
${PROJECT_SOURCE_DIR}/libs/opentimelineio/src/deps/Imath/src
${PROJECT_BINARY_DIR}/libs/opentimelineio/src
)

if(NOT EMSCRIPTEN AND NOT WIN32)
set(GLFW_BUILD_EXAMPLES OFF)
set(GLFW_BUILD_TESTS OFF)
set(GLFW_BUILD_DOCS OFF)
set(BUILD_SHARED_LIBS OFF)
add_subdirectory("libs/glfw")
endif()

if(NOT EMSCRIPTEN)
add_custom_command(
OUTPUT "${PROJECT_SOURCE_DIR}/fonts/embedded_font.inc"
Expand All @@ -105,7 +133,6 @@ target_compile_definitions(raven
target_link_libraries(raven PUBLIC
OTIO::opentimelineio
IMGUI
MINIZIP::minizip
)

if (APPLE)
Expand Down
105 changes: 9 additions & 96 deletions app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,11 @@

#include "widgets.h"

#ifndef EMSCRIPTEN
#ifndef __EMSCRIPTEN__
#include "nfd.h"
#endif

#include "mz.h"
#include "mz_zip.h"
#include "mz_strm.h"
#include "mz_zip_rw.h"

#include <opentimelineio/bundle.h>
#include <opentimelineio/clip.h>
#include <opentimelineio/gap.h>
#include <opentimelineio/transition.h>
Expand Down Expand Up @@ -325,90 +321,7 @@ otio::SerializableObjectWithMetadata* LoadOTIOFile(std::string path) {
}

otio::SerializableObjectWithMetadata* LoadOTIOZFile(std::string path) {
otio::SerializableObjectWithMetadata* root = nullptr;

void *zip_reader = mz_zip_reader_create();

auto status = mz_zip_reader_open_file(zip_reader, path.c_str());
if (status != MZ_OK) {
ErrorMessage(
"Error opening \"%s\": %d",
path.c_str(),
status);
} else {
status = mz_zip_reader_locate_entry(zip_reader, "content.otio", 1);
if (status != MZ_OK) {
ErrorMessage(
"Invalid OTIOZ: \"%s\": \"content.otio\" not found in archive.",
path.c_str());
} else {
mz_zip_file *file_info = NULL;
status = mz_zip_reader_entry_get_info(zip_reader, &file_info);
if (status != MZ_OK) {
ErrorMessage(
"Invalid OTIOZ: \"%s\": Error getting entry info: %d",
path.c_str(),
status);
} else {
status = mz_zip_reader_entry_open(zip_reader);
if (status != MZ_OK) {
ErrorMessage(
"Invalid OTIOZ: \"%s\": Unable to open entry: %d",
path.c_str(),
status);
} else {
char* buf = (char*)malloc(file_info->uncompressed_size + 1);
char* buf_cursor = buf;
int64_t bytes_remaining = file_info->uncompressed_size;
int32_t bytes_read = 0;
while (bytes_remaining > 0) {
int32_t chunk_size = bytes_remaining < INT32_MAX ? bytes_remaining : INT32_MAX;
bytes_read = mz_zip_reader_entry_read(zip_reader, buf_cursor, chunk_size);
if (bytes_read > 0) {
bytes_remaining -= bytes_read;
buf_cursor += bytes_read;
} else {
break;
}
}
if (bytes_remaining != 0) {
ErrorMessage(
"Invalid OTIOZ: \"%s\": Error reading entry: %ld",
path.c_str(),
bytes_remaining);
} else {
// Add a null terminator
buf[file_info->uncompressed_size] = '\0';
std::string json(buf);
otio::ErrorStatus error_status;
root = dynamic_cast<otio::SerializableObjectWithMetadata*>(
otio::SerializableObjectWithMetadata::from_json_string(json, &error_status));
if (otio::is_error(error_status)) {
ErrorMessage(
"Invalid OTIOZ: \"%s\": %s",
path.c_str(),
otio_error_string(error_status).c_str());
// Set root to nullptr rather than returning so we can still clean up
// the zip reader
root = nullptr;
} else if (!root) {
ErrorMessage(
"Invalid OTIOZ: \"%s\": Unable to extract OTIO data from input",
path.c_str());
}
}
free(buf);
mz_zip_reader_entry_close(zip_reader);
}
}
}

mz_zip_reader_close(zip_reader);
}

mz_zip_reader_delete(&zip_reader);

return root;
return dynamic_cast<otio::SerializableObjectWithMetadata*>(otio::bundle::read_otioz(path));
}

std::string FileExtension(std::string path) {
Expand Down Expand Up @@ -707,21 +620,21 @@ void MainGui() {
auto viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
ImGui::SetNextWindowSize(viewport->Size);
#ifndef EMSCRIPTEN
#ifndef __EMSCRIPTEN__
ImGui::GetPlatformIO().Platform_SetWindowTitle(viewport, window_title);
#endif

ImGui::Begin(
window_id,
#ifndef EMSCRIPTEN
#ifndef __EMSCRIPTEN__
&appState.show_main_window,
#else
NULL,
#endif
ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoResize |
#ifndef EMSCRIPTEN
#ifndef __EMSCRIPTEN__
// With Emscripten, we show the Dear ImGui titlebar,
// but on desktop, the outer platform window has a titlebar already
ImGuiWindowFlags_NoTitleBar |
Expand Down Expand Up @@ -967,7 +880,7 @@ void SaveTheme() {
}

std::string OpenFileDialog() {
#ifdef EMSCRIPTEN
#ifdef __EMSCRIPTEN__
return "";
#else
nfdchar_t* outPath = NULL;
Expand All @@ -986,7 +899,7 @@ std::string OpenFileDialog() {
}

std::string SaveFileDialog() {
#ifdef EMSCRIPTEN
#ifdef __EMSCRIPTEN__
return "";
#else
nfdchar_t* outPath = NULL;
Expand Down Expand Up @@ -1025,7 +938,7 @@ void DrawMenu() {
if (ImGui::MenuItem("Close Tab", NULL, false, GetActiveRoot())) {
CloseTab(appState.active_tab);
}
#ifndef EMSCRIPTEN
#ifndef __EMSCRIPTEN__
// You can't exit(0) from a web page
// but you can on Desktop platforms.
if (ImGui::MenuItem("Exit", "Alt+F4")) {
Expand Down
2 changes: 1 addition & 1 deletion app.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include <opentimelineio/timeline.h>
#include <opentimelineio/serializableObjectWithMetadata.h>
namespace otio = opentimelineio::OPENTIMELINEIO_VERSION;
namespace otio = opentimelineio::OPENTIMELINEIO_VERSION_NS;

enum AppThemeCol_ {
AppThemeCol_Background,
Expand Down
25 changes: 25 additions & 0 deletions cmake/Findminizip-ng.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Findminizip-ng.cmake
#
# Raven-local shim for OTIO's `find_package(minizip-ng REQUIRED)`, which
# it calls when OTIO_FIND_MINIZIP_NG=ON. Rather than requiring an
# installed minizip-ng-config.cmake, we build minizip-ng ourselves via
# add_subdirectory(libs/minizip-ng) and report success here as long as
# the MINIZIP::minizip target (created inside minizip-ng's own
# CMakeLists.txt during add_subdirectory) is present.
#
# This is what makes the OTIO_FIND_MINIZIP_NG=ON path usable from
# projects that vendor minizip-ng via add_subdirectory. Distros and
# vcpkg users hit find_package's normal Config mode with an installed
# minizip-ng, which does not need this shim.

if(TARGET MINIZIP::minizip)
set(minizip-ng_FOUND TRUE)
set(minizip-ng_CONFIG "provided by raven via add_subdirectory(libs/minizip-ng)")
else()
set(minizip-ng_FOUND FALSE)
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(minizip-ng
REQUIRED_VARS minizip-ng_FOUND
)
Loading
Loading