refactor(common): de-Qt oakcommon and wrap it in a pure C ABI

- de-Qt all classes under src/common (std::string/vector/mutex,
  std::filesystem, expat-based XmlStreamReader/Writer)
- add pure C ABI in include/common + src/common/c_api: opaque handles,
  init returns NULL on failure, free(NULL) is a no-op, out-params with
  negative OAKCOMMON_E_* error codes (include/common/error.h)
- remove single-consumer classes from oakcommon (html, jobtime,
  otioutils, playbackaudioclock, tohex, util, avframeptr,
  crashpadinterface/crashpadutils, autoscroll, digit, range); their
  destinations are recorded in docs/zh/plans/riir/notes.md
- add gtest suites under src/common/tests (127 cases), standalone
  build driver in src/common/standalone
This commit is contained in:
2026-08-05 17:20:19 +08:00
parent bb09872a2f
commit bad52feda3
73 changed files with 8851 additions and 2 deletions
+193
View File
@@ -0,0 +1,193 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_COMMANDLINEPARSER_H
#define OAK_EDITOR_COMMANDLINEPARSER_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Opaque handle to a command-line parser instance.
*/
typedef struct OakCommonCommandLineParser OakCommonCommandLineParser;
/**
* @brief Opaque handle to a registered command-line option.
*
* The handle wrapper is freed with oakcommon_commandlineoption_free();
* the underlying option is owned by the parser and stays valid until
* the parser is freed.
*/
typedef struct OakCommonCommandLineOption OakCommonCommandLineOption;
/**
* @brief Opaque handle to a registered positional argument.
*
* The handle wrapper is freed with
* oakcommon_commandlinepositionalargument_free(); the underlying argument
* is owned by the parser and stays valid until the parser is freed.
*/
typedef struct OakCommonCommandLinePositionalArgument
OakCommonCommandLinePositionalArgument;
/**
* @brief Create a command-line parser.
*
* @return Parser handle, or NULL on allocation failure.
*/
OakCommonCommandLineParser *oakcommon_commandlineparser_init(void);
/**
* @brief Destroy a command-line parser.
*
* Destroys all option and positional-argument handles created from it.
* NULL is a no-op.
*/
void oakcommon_commandlineparser_free(OakCommonCommandLineParser *parser);
/**
* @brief Set the application name/version shown by print_help.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlineparser_set_app_info(OakCommonCommandLineParser *parser,
const char *name,
const char *version);
/**
* @brief Register an option with one or more name strings.
*
* @param names Array of option name strings (without leading dash).
* @param name_count Number of entries in names. Must be > 0.
* @param description Help text, may be NULL.
* @param takes_arg Non-zero if the option consumes the following argument.
* @param arg_placeholder Placeholder shown in help, may be NULL.
* @param hidden Non-zero to omit from help output.
* @param out_option Receives the option handle. May be NULL if unused.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlineparser_add_option(
OakCommonCommandLineParser *parser, const char *const *names, int name_count,
const char *description, int takes_arg, const char *arg_placeholder,
int hidden, OakCommonCommandLineOption **out_option);
/**
* @brief Register a positional argument.
*
* @param out_argument Receives the argument handle. May be NULL if unused.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlineparser_add_positional_argument(
OakCommonCommandLineParser *parser, const char *name,
const char *description, int required,
OakCommonCommandLinePositionalArgument **out_argument);
/**
* @brief Parse an argv-style argument list.
*
* argv[0] is skipped as the program name, matching C main() convention.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlineparser_process(OakCommonCommandLineParser *parser,
const char *const *argv, int argc);
/**
* @brief Print usage/help text to stdout.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlineparser_print_help(OakCommonCommandLineParser *parser,
const char *filename);
/**
* @brief Query whether an option was present on the command line.
*
* @param is_set Receives the result. Must not be NULL.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlineoption_is_set(OakCommonCommandLineOption *option,
bool *is_set);
/**
* @brief Free an option handle wrapper.
*
* Does not unregister the option from the parser. NULL is a no-op.
*/
void oakcommon_commandlineoption_free(OakCommonCommandLineOption *option);
/**
* @brief Get an option's argument value (two-stage string getter).
*
* @return Required buffer size in bytes including the terminating NUL
* (non-negative), or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlineoption_get_setting(OakCommonCommandLineOption *option,
char *buf, int buf_size);
/**
* @brief Set an option's argument value.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlineoption_set_setting(OakCommonCommandLineOption *option,
const char *value);
/**
* @brief Get a positional argument's value (two-stage string getter).
*
* @return Required buffer size in bytes including the terminating NUL
* (non-negative), or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlinepositionalargument_get_setting(
OakCommonCommandLinePositionalArgument *argument, char *buf, int buf_size);
/**
* @brief Set a positional argument's value.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_commandlinepositionalargument_set_setting(
OakCommonCommandLinePositionalArgument *argument, const char *value);
/**
* @brief Free a positional argument handle wrapper.
*
* Does not unregister the argument from the parser. NULL is a no-op.
*/
void oakcommon_commandlinepositionalargument_free(
OakCommonCommandLinePositionalArgument *argument);
#ifdef __cplusplus
}
#endif
#endif //OAK_EDITOR_COMMANDLINEPARSER_H
+107
View File
@@ -0,0 +1,107 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_CURRENT_H
#define OAK_EDITOR_CURRENT_H
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OakCommonCurrent OakCommonCurrent;
/**
* @brief Destructor callback for objects handed to Current slots.
*
* Called when the slot is overwritten or cleared. May be NULL if the
* caller keeps ownership of the object.
*/
typedef void (*OakCommonDestroyFn)(void *obj);
/**
* @brief Return a handle to the process-wide Current singleton.
*
* The returned handle is borrowed: it is valid for the lifetime of the
* process and must not be freed with oakcommon_current_free() more
* than out of symmetry (free is a no-op for the singleton).
*/
OakCommonCurrent *oakcommon_current_instance(void);
/**
* @brief Release a Current handle.
*
* No-op: the underlying object is a singleton. Safe to call with NULL.
*/
void oakcommon_current_free(OakCommonCurrent *self);
/**
* @brief Store a pointer in a Current slot, taking over destruction.
*
* Passing NULL for obj clears the slot (destroy is ignored). If a
* previous object with a destroy callback was stored, it is destroyed.
*
* @param self Handle from oakcommon_current_instance().
* @param obj Opaque pointer to the external object (e.g. a
* VideoParams), or NULL to clear.
* @param destroy Optional destructor invoked when the slot is replaced.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if self is NULL.
*/
int oakcommon_current_set_video_params(OakCommonCurrent *self, void *obj,
OakCommonDestroyFn destroy);
int oakcommon_current_set_audio_params(OakCommonCurrent *self, void *obj,
OakCommonDestroyFn destroy);
int oakcommon_current_set_plugin_host(OakCommonCurrent *self, void *obj,
OakCommonDestroyFn destroy);
int oakcommon_current_set_plugin_cache(OakCommonCurrent *self, void *obj,
OakCommonDestroyFn destroy);
/**
* @brief Fetch the raw pointer currently stored in a slot.
*
* The returned pointer is borrowed and remains valid until the slot is
* overwritten or cleared. *out is set to NULL when the slot is empty.
*
* @param self Handle from oakcommon_current_instance().
* @param out Receives the stored pointer.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if self or out
* is NULL.
*/
int oakcommon_current_get_video_params(OakCommonCurrent *self, void **out);
int oakcommon_current_get_audio_params(OakCommonCurrent *self, void **out);
int oakcommon_current_get_plugin_host(OakCommonCurrent *self, void **out);
int oakcommon_current_get_plugin_cache(OakCommonCurrent *self, void **out);
/**
* @brief Query whether the session is interactive.
*
* @param self Handle from oakcommon_current_instance().
* @param out Receives 1 for interactive, 0 otherwise.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if self or out
* is NULL.
*/
int oakcommon_current_is_interactive(OakCommonCurrent *self, int *out);
#ifdef __cplusplus
}
#endif
#endif // OAK_EDITOR_CURRENT_H
+75
View File
@@ -0,0 +1,75 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_DEBUG_H
#define OAK_EDITOR_DEBUG_H
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Severity levels for oakcommon debug output.
*
* Mirrors olive::DebugLevel in src/common/src/debug.h.
*/
enum OakCommonDebugLevel {
OAKCOMMON_DEBUG_DEBUG = 0, /**< Verbose debug message. */
OAKCOMMON_DEBUG_INFO = 1, /**< Informational message. */
OAKCOMMON_DEBUG_WARNING = 2, /**< Warning message. */
OAKCOMMON_DEBUG_ERROR = 3, /**< Error message. */
OAKCOMMON_DEBUG_FATAL = 4 /**< Fatal error message. */
};
/**
* @brief Print a debug message to stderr, prefixed with its level.
*
* De-Qt replacement for the old Qt message handler. The line is
* flushed immediately.
*
* @param level One of OakCommonDebugLevel; out-of-range values print
* as "UNKNOWN".
* @param msg NUL-terminated message; NULL is treated as an empty
* string.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if msg is NULL.
*/
int oakcommon_debug_log(int level, const char *msg);
/**
* @brief Copy the printable name of a debug level into buf.
*
* Two-segment string getter: if buf is NULL or buf_size is too small,
* nothing is written.
*
* @param level One of OakCommonDebugLevel.
* @param buf Destination buffer, may be NULL to query the size.
* @param buf_size Size of buf in bytes.
* @return Required buffer size in bytes including the terminating NUL
* (non-negative).
*/
int oakcommon_debug_level_name(int level, char *buf, int buf_size);
#ifdef __cplusplus
}
#endif
#endif // OAK_EDITOR_DEBUG_H
+73
View File
@@ -0,0 +1,73 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_DROPWORKFLOWBEHAVIOR_H
#define OAK_EDITOR_DROPWORKFLOWBEHAVIOR_H
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Behavior when media is dropped onto a timeline without a
* sequence.
*
* Mirrors olive::DropWithoutSequenceBehavior in
* src/common/src/dropworkflowbehavior.h; enumerator order and values
* must stay identical because the config layer persists them as ints.
*/
enum OakCommonDropWorkflowBehavior {
OAKCOMMON_DWS_ASK = 0, /**< Ask the user every time. */
OAKCOMMON_DWS_AUTO = 1, /**< Automatically create a sequence. */
OAKCOMMON_DWS_MANUAL = 2, /**< Never create; import manually. */
OAKCOMMON_DWS_DISABLE = 3 /**< Disable dropping entirely. */
};
/**
* @brief Check whether value is a valid OakCommonDropWorkflowBehavior.
*
* @param value Integer behavior value (e.g. read from config).
* @return 1 if valid, 0 otherwise (this is a predicate, not a status
* code).
*/
int oakcommon_drop_workflow_behavior_is_valid(int value);
/**
* @brief Copy the printable name of a behavior into buf.
*
* Two-segment string getter: if buf is NULL or buf_size is too small,
* nothing is written. Invalid values yield "UNKNOWN".
*
* @param value One of OakCommonDropWorkflowBehavior.
* @param buf Destination buffer, may be NULL to query the size.
* @param buf_size Size of buf in bytes.
* @return Required buffer size in bytes including the terminating NUL
* (non-negative).
*/
int oakcommon_drop_workflow_behavior_name(int value, char *buf,
int buf_size);
#ifdef __cplusplus
}
#endif
#endif // OAK_EDITOR_DROPWORKFLOWBEHAVIOR_H
+41
View File
@@ -0,0 +1,41 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_ERROR_H
#define OAK_EDITOR_ERROR_H
/**
* @brief Status and error codes shared by all oakcommon C API families.
*
* Return-code convention (mirrors engine/include/oakengine/init.h):
* 0 (OAKCOMMON_OK) on success, a negative OAKCOMMON_E_* error code on
* failure. String getters return the required buffer size in bytes
* (including the terminating NUL) as a non-negative value instead.
*/
#define OAKCOMMON_OK 0 /**< Success. */
#define OAKCOMMON_E_INVALID (-1) /**< NULL handle or invalid argument. */
#define OAKCOMMON_E_STATE (-2) /**< Call not valid in the current state. */
#define OAKCOMMON_E_FAILED (-3) /**< The underlying operation failed. */
#define OAKCOMMON_E_NOT_FOUND (-4) /**< Index out of range / entry not found. */
#define OAKCOMMON_E_NOMEM (-5) /**< Allocation failed. */
#define SUCCESS OAKCOMMON_OK /**< @deprecated Use OAKCOMMON_OK. */
#endif //OAK_EDITOR_ERROR_H
+116
View File
@@ -0,0 +1,116 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_FFMPEGUTILS_H
#define OAK_EDITOR_FFMPEGUTILS_H
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Stateless mappings between native pixel/sample formats and the
* opaque FBPixelFormat / FBSampleFormat constants of ffmpeg_bridge
*
* All functions are pure format conversions; there is no handle to create
* or free. Native pixel/sample formats are passed as plain ints matching
* the olive::core::PixelFormat::Format / SampleFormat::Format enum values
* (invalid = -1). Bridge formats are the fb_pix_fmt_* / fb_sample_fmt_*
* constants from ffmpeg_bridge/ffmpeg_bridge.h.
*/
/**
* @brief RGB / RGBA channel counts (flattened from VideoParams)
*/
#define OAKCOMMON_RGB_CHANNEL_COUNT 3
#define OAKCOMMON_RGBA_CHANNEL_COUNT 4
/**
* @brief Returns a bridge pixel format that a frame can be converted to
* with minimal data loss, clamped to a maximum native precision
*
* @param pix_fmt bridge pixel format to find a compatible conversion for
* @param maximum_pix_fmt maximum native pixel format, or -1 for no limit
* @param out receives the chosen bridge pixel format
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out is NULL
*/
int oakcommon_ffmpegutils_get_compatible_bridge_pixel_format(
int pix_fmt, int maximum_pix_fmt, int *out);
/**
* @brief Returns a native pixel format usable to convert from a native
* frame to a bridge frame with minimal data loss
*
* @param pix_fmt native pixel format
* @param out receives the compatible native pixel format (-1 if none)
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out is NULL
*/
int oakcommon_ffmpegutils_get_compatible_pixel_format(int pix_fmt,
int *out);
/**
* @brief Returns a bridge pixel format for a given native pixel format
*
* @param pix_fmt native pixel format
* @param channel_count OAKCOMMON_RGB_CHANNEL_COUNT or
* OAKCOMMON_RGBA_CHANNEL_COUNT
* @param out receives the bridge pixel format (fb_pix_fmt_none if none)
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out is NULL
*/
int oakcommon_ffmpegutils_get_ffmpeg_pixel_format(int pix_fmt,
int channel_count,
int *out);
/**
* @brief Returns a native sample format for a given bridge sample format
*
* @param smp_fmt bridge sample format
* @param out receives the native sample format (-1 if unknown)
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out is NULL
*/
int oakcommon_ffmpegutils_get_native_sample_format(int smp_fmt, int *out);
/**
* @brief Returns a bridge sample format for a given native sample format
*
* @param smp_fmt native sample format
* @param out receives the bridge sample format (fb_sample_fmt_none if none)
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out is NULL
*/
int oakcommon_ffmpegutils_get_ffmpeg_sample_format(int smp_fmt, int *out);
/**
* @brief Converts a "JPEG" full-range bridge pixel format to its regular
* counterpart
*
* @param pix_fmt bridge pixel format
* @param out receives the regular-range format (unchanged if not JPEG)
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out is NULL
*/
int oakcommon_ffmpegutils_convert_jpeg_space_to_regular_space(int pix_fmt,
int *out);
#ifdef __cplusplus
}
#endif
#endif //OAK_EDITOR_FFMPEGUTILS_H
+153
View File
@@ -0,0 +1,153 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_FILEFUNCTIONS_H
#define OAK_EDITOR_FILEFUNCTIONS_H
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Opaque handle for the filefunctions family
*
* File functions are stateless; the handle only exists to keep the C API
* shape uniform across oakcommon families.
*/
typedef struct OakCommonFileFunctions OakCommonFileFunctions;
/**
* @brief Creates a filefunctions handle
*
* @return A new handle, or NULL on failure.
*/
OakCommonFileFunctions *oakcommon_filefunctions_init(void);
/**
* @brief Destroys a filefunctions handle (NULL is a no-op)
*/
void oakcommon_filefunctions_free(OakCommonFileFunctions *self);
/**
* @brief Returns a deterministic identifier string for a file
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKCOMMON_E_* error code. Returns an empty string (required size 1) if
* the file does not exist.
*/
int oakcommon_filefunctions_get_unique_file_identifier(
OakCommonFileFunctions *self, const char *filename, char *buf,
int buf_size);
int oakcommon_filefunctions_get_configuration_location(
OakCommonFileFunctions *self, char *buf, int buf_size);
int oakcommon_filefunctions_get_application_path(
OakCommonFileFunctions *self, char *buf, int buf_size);
int oakcommon_filefunctions_get_temp_file_path(
OakCommonFileFunctions *self, char *buf, int buf_size);
int oakcommon_filefunctions_get_auto_recovery_root(
OakCommonFileFunctions *self, char *buf, int buf_size);
/**
* @brief Checks whether `source` can be copied to `dest` without
* overwriting anything
*
* @param out Receives 1 (safe) or 0 (would overwrite).
*/
int oakcommon_filefunctions_can_copy_directory_without_overwriting(
OakCommonFileFunctions *self, const char *source, const char *dest,
int *out);
/**
* @brief Recursively copies a directory
*/
int oakcommon_filefunctions_copy_directory(OakCommonFileFunctions *self,
const char *source,
const char *dest, int overwrite);
/**
* @brief Checks whether a directory exists, optionally creating it
*
* @param out Receives 1 (valid) or 0 (invalid).
*/
int oakcommon_filefunctions_directory_is_valid(
OakCommonFileFunctions *self, const char *dir,
int try_to_create_if_not_exists, int *out);
/**
* @brief Ensures a filename ends with the given extension (no dot)
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKCOMMON_E_* error code.
*/
int oakcommon_filefunctions_ensure_filename_extension(
OakCommonFileFunctions *self, const char *filename,
const char *extension, char *buf, int buf_size);
/**
* @brief Reads an entire file into a string
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKCOMMON_E_* error code. Returns an empty string (required size 1) if
* the file cannot be read.
*/
int oakcommon_filefunctions_read_file_as_string(
OakCommonFileFunctions *self, const char *filename, char *buf,
int buf_size);
/**
* @brief Returns a non-existing temporary variant of `original`
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKCOMMON_E_* error code.
*/
int oakcommon_filefunctions_get_safe_temporary_filename(
OakCommonFileFunctions *self, const char *original, char *buf,
int buf_size);
/**
* @brief Renames `from` to `to`, deleting `to` first if it exists
*
* @param out Receives 1 (renamed) or 0 (failed).
*/
int oakcommon_filefunctions_rename_file_allow_overwrite(
OakCommonFileFunctions *self, const char *from, const char *to,
int *out);
/**
* @brief Appends the platform executable suffix (".exe" on Windows)
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKCOMMON_E_* error code.
*/
int oakcommon_filefunctions_get_formatted_executable_for_platform(
OakCommonFileFunctions *self, const char *unformatted, char *buf,
int buf_size);
#ifdef __cplusplus
}
#endif
#endif // OAK_EDITOR_FILEFUNCTIONS_H
+117
View File
@@ -0,0 +1,117 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_MISCUTILS_H
#define OAK_EDITOR_MISCUTILS_H
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Minimum decibel value used by the editor (-200.0 dB).
*
* In basically all circumstances, this calculates to 0.0 linear.
*/
#define OAKCOMMON_DECIBEL_MINIMUM (-200.0)
/**
* @brief Convert a linear amplitude to decibels.
*
* A linear value of 0.0 (or anything yielding an infinite result) returns
* OAKCOMMON_DECIBEL_MINIMUM.
*
* @param linear Linear amplitude.
* @param out_db Receives the decibel value. Must not be NULL.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out_db is NULL.
*/
int oakcommon_decibel_from_linear(double linear, double *out_db);
/**
* @brief Convert decibels to a linear amplitude.
*
* Results below 1e-6 are clamped to 0.0.
*
* @param db Decibel value.
* @param out_linear Receives the linear amplitude. Must not be NULL.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out_linear is NULL.
*/
int oakcommon_decibel_to_linear(double db, double *out_linear);
/**
* @brief Convert a logarithmic slider position (0..1) to decibels.
*
* @param logarithmic Logarithmic position.
* @param out_db Receives the decibel value. Must not be NULL.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out_db is NULL.
*/
int oakcommon_decibel_from_logarithmic(double logarithmic, double *out_db);
/**
* @brief Convert decibels to a logarithmic slider position (0..1).
*
* @param db Decibel value.
* @param out_logarithmic Receives the logarithmic position. Must not be NULL.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out_logarithmic
* is NULL.
*/
int oakcommon_decibel_to_logarithmic(double db, double *out_logarithmic);
/**
* @brief Convert a linear amplitude directly to a logarithmic position.
*
* @param linear Linear amplitude.
* @param out_logarithmic Receives the logarithmic position. Must not be NULL.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out_logarithmic
* is NULL.
*/
int oakcommon_decibel_linear_to_logarithmic(double linear,
double *out_logarithmic);
/**
* @brief Convert a logarithmic position directly to a linear amplitude.
*
* @param logarithmic Logarithmic position.
* @param out_linear Receives the linear amplitude. Must not be NULL.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out_linear is NULL.
*/
int oakcommon_decibel_logarithmic_to_linear(double logarithmic,
double *out_linear);
/**
* @brief Linearly interpolate between a and b using t.
*
* t should be between 0.0 and 1.0: 0.0 returns a, 1.0 returns b.
*
* @param a Start value.
* @param b End value.
* @param t Interpolation factor.
* @param out_value Receives the interpolated value. Must not be NULL.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out_value is NULL.
*/
int oakcommon_lerp(double a, double b, double t, double *out_value);
#ifdef __cplusplus
}
#endif
#endif //OAK_EDITOR_MISCUTILS_H
+88
View File
@@ -0,0 +1,88 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_OCIOUTILS_H
#define OAK_EDITOR_OCIOUTILS_H
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Native pixel format codes, mirroring olive::core::PixelFormat
*
* The numeric values must stay in sync with
* olive/core/render/pixelformat.h (Format enum).
*/
enum OakCommonPixelFormat {
OAKCOMMON_PIXEL_FORMAT_INVALID = -1, /**< Invalid/unknown format. */
OAKCOMMON_PIXEL_FORMAT_U8 = 0, /**< 8-bit unsigned integer. */
OAKCOMMON_PIXEL_FORMAT_U10 = 1, /**< 10-bit unsigned integer. */
OAKCOMMON_PIXEL_FORMAT_U16 = 2, /**< 16-bit unsigned integer. */
OAKCOMMON_PIXEL_FORMAT_F16 = 3, /**< 16-bit float (half). */
OAKCOMMON_PIXEL_FORMAT_F32 = 4, /**< 32-bit float. */
OAKCOMMON_PIXEL_FORMAT_COUNT = 5 /**< Sentinel, not a valid format. */
};
/**
* @brief OpenColorIO bit depth codes, matching OCIO::BitDepth
*
* Returned through the out parameter of
* oakcommon_ocioutils_get_ocio_bit_depth_from_pixel_format() as a plain
* int so that callers never see OCIO types. Values match the OCIO
* BitDepth enum: 0 = unknown, 1 = uint8, 2 = uint10, 3 = uint12,
* 4 = uint14, 5 = uint16, 6 = uint32, 7 = f16, 8 = f32 (OCIO v2).
*/
typedef struct OakCommonOCIOUtils OakCommonOCIOUtils;
/**
* @brief Creates an OCIOUtils handle
*
* The object is stateless; the handle exists only to satisfy the C API
* lifetime contract. Returns NULL on failure.
*/
OakCommonOCIOUtils *oakcommon_ocioutils_init(void);
/**
* @brief Destroys an OCIOUtils handle; no-op on NULL
*/
void oakcommon_ocioutils_free(OakCommonOCIOUtils *self);
/**
* @brief Maps a native pixel format to an OCIO bit depth
*
* @param self handle from oakcommon_ocioutils_init()
* @param pixel_format one of the OakCommonPixelFormat values
* @param out_bit_depth receives the OCIO bit depth as an int (see the
* OakCommonOCIOUtils typedef documentation); set to 0
* (BIT_DEPTH_UNKNOWN) for invalid formats
* @return OAKCOMMON_OK, or OAKCOMMON_E_INVALID if self or
* out_bit_depth is NULL or pixel_format is not a known code
*/
int oakcommon_ocioutils_get_ocio_bit_depth_from_pixel_format(
OakCommonOCIOUtils *self, int pixel_format, int *out_bit_depth);
#ifdef __cplusplus
}
#endif
#endif // OAK_EDITOR_OCIOUTILS_H
+109
View File
@@ -0,0 +1,109 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_OIIOUTILS_H
#define OAK_EDITOR_OIIOUTILS_H
#include "common/error.h"
/* Reuses the OakCommonPixelFormat enum (mirroring
* olive::core::PixelFormat) rather than redefining it here. */
#include "common/ocioutils.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief OIIO base type codes, matching OIIO::TypeDesc::BASETYPE
*
* Passed through the C API as plain ints so callers never see OIIO
* types. Values match the OIIO TypeDesc::BASETYPE enum: 0 = UNKNOWN,
* 1 = NONE, 2 = UINT8, 3 = INT8, 4 = UINT16, 5 = INT16, 6 = UINT32,
* 7 = INT32, 8 = UINT64, 9 = INT64, 10 = HALF, 11 = FLOAT, 12 = DOUBLE,
* 13 = STRING, 14 = PTR. OIIO >= 2.5 adds 15 = USTRINGHASH and shifts
* LASTBASE, so the exact LASTBASE value is version-dependent.
*/
typedef struct OakCommonOIIOUtils OakCommonOIIOUtils;
/**
* @brief Creates an OIIOUtils handle
*
* The object is stateless; the handle exists only to satisfy the C API
* lifetime contract. Returns NULL on failure.
*/
OakCommonOIIOUtils *oakcommon_oiioutils_init(void);
/**
* @brief Destroys an OIIOUtils handle; no-op on NULL
*/
void oakcommon_oiioutils_free(OakCommonOIIOUtils *self);
/**
* @brief Maps a native pixel format to an OIIO base type
*
* @param self handle from oakcommon_oiioutils_init()
* @param pixel_format one of the OakCommonPixelFormat values
* @param out_base_type receives the OIIO base type as an int (see the
* OakCommonOIIOUtils typedef documentation); set to 0
* (TypeDesc::UNKNOWN) for invalid or unmappable formats
* @return OAKCOMMON_OK, or OAKCOMMON_E_INVALID if self or out_base_type
* is NULL or pixel_format is not a known code
*/
int oakcommon_oiioutils_get_oiio_base_type_from_format(
OakCommonOIIOUtils *self, int pixel_format, int *out_base_type);
/**
* @brief Maps an OIIO base type to a native pixel format
*
* @param self handle from oakcommon_oiioutils_init()
* @param base_type an OIIO TypeDesc::BASETYPE value as an int
* @param out_pixel_format receives one of the OakCommonPixelFormat
* values; set to OAKCOMMON_PIXEL_FORMAT_INVALID for unknown or
* unmappable base types
* @return OAKCOMMON_OK, or OAKCOMMON_E_INVALID if self or
* out_pixel_format is NULL or base_type is negative
*/
int oakcommon_oiioutils_get_format_from_oiio_basetype(
OakCommonOIIOUtils *self, int base_type, int *out_pixel_format);
/**
* @brief Converts a PixelAspectRatio attribute value to a rational
*
* Flattened form of the former ImageSpec-based helper: the caller reads
* the "PixelAspectRatio" float attribute from the OIIO::ImageSpec
* (defaulting to 1.0 when absent) and passes it here.
*
* @param self handle from oakcommon_oiioutils_init()
* @param pixel_aspect_ratio the PixelAspectRatio attribute value
* @param out_numerator receives the rational numerator
* @param out_denominator receives the rational denominator
* @return OAKCOMMON_OK, or OAKCOMMON_E_INVALID if self, out_numerator
* or out_denominator is NULL
*/
int oakcommon_oiioutils_get_pixel_aspect_ratio(
OakCommonOIIOUtils *self, double pixel_aspect_ratio, int *out_numerator,
int *out_denominator);
#ifdef __cplusplus
}
#endif
#endif // OAK_EDITOR_OIIOUTILS_H
+58
View File
@@ -0,0 +1,58 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_POWER_H
#define OAK_EDITOR_POWER_H
#include <stdint.h>
#include "error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Round `value` up to the next power of two
*
* Stateless pure function, no handle required. Writes the result to `out`.
*
* @param value Input value.
* @param out Receives the rounded value. Must not be NULL.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if `out` is NULL.
*/
int oakcommon_power_ceil_to_power_of_2(uint32_t value, uint32_t *out);
/**
* @brief Round `value` down to the nearest power of two
*
* Stateless pure function, no handle required. Writes the result to `out`.
*
* @param value Input value.
* @param out Receives the rounded value. Must not be NULL.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if `out` is NULL.
*/
int oakcommon_power_floor_to_power_of_2(uint32_t value, uint32_t *out);
#ifdef __cplusplus
}
#endif
#endif //OAK_EDITOR_POWER_H
+67
View File
@@ -0,0 +1,67 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_COMMON_QTUTILS_H
#define OAK_COMMON_QTUTILS_H
#include <stdint.h>
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Convert a pointer to an integer value
*
* @param ptr Pointer to convert (may be NULL, yielding 0).
* @param out_value Receives the integer representation of ptr.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out_value is NULL.
*/
int oakcommon_qtutils_ptr_to_value(void *ptr, uint64_t *out_value);
/**
* @brief Convert an integer produced by oakcommon_qtutils_ptr_to_value() back to a pointer
*
* @param value Integer representation of a pointer.
* @param out_ptr Receives the decoded pointer.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID if out_ptr is NULL.
*/
int oakcommon_qtutils_value_to_ptr(uint64_t value, void **out_ptr);
/**
* @brief Get the creation (birth) time of a file as seconds since the Unix epoch
*
* Falls back to the last metadata change time when the filesystem does not
* record birth times.
*
* @param path NUL-terminated filesystem path.
* @param out_secs Receives the creation time in seconds since the epoch.
* @return OAKCOMMON_OK on success, OAKCOMMON_E_INVALID for NULL arguments,
* OAKCOMMON_E_NOT_FOUND if the file does not exist or cannot be stat'ed.
*/
int oakcommon_qtutils_get_creation_date(const char *path, int64_t *out_secs);
#ifdef __cplusplus
}
#endif
#endif // OAK_COMMON_QTUTILS_H
+156
View File
@@ -0,0 +1,156 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_XMLUTILS_H
#define OAK_EDITOR_XMLUTILS_H
#include "common/error.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct OakCommonXmlReader OakCommonXmlReader;
typedef struct OakCommonXmlWriter OakCommonXmlWriter;
/**
* @brief Create a streaming XML reader over a complete document.
*
* @param data NUL-terminated XML text. Must not be NULL.
* @return A new reader, or NULL on failure (NULL data, out of memory).
*/
OakCommonXmlReader *oakcommon_xml_reader_init(const char *data);
/**
* @brief Destroy a reader. No-op on NULL.
*/
void oakcommon_xml_reader_free(OakCommonXmlReader *reader);
/**
* @brief Advance until the next start element, an end element, or the end
* of the document.
*
* @param reader Reader handle.
* @param found Out: 1 if positioned on a start element, 0 otherwise.
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_xml_reader_read_next_start_element(OakCommonXmlReader *reader,
int *found);
/**
* @brief Name of the current element token.
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKCOMMON_E_* error code.
*/
int oakcommon_xml_reader_name(OakCommonXmlReader *reader, char *buf,
int buf_size);
/**
* @brief Read the concatenated character data of the current element.
*
* Must be called on a start element; consumes up to the matching end
* element.
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKCOMMON_E_* error code.
*/
int oakcommon_xml_reader_read_element_text(OakCommonXmlReader *reader,
char *buf, int buf_size);
/**
* @brief Skip the current element and all of its children.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_xml_reader_skip_current_element(OakCommonXmlReader *reader);
/**
* @brief Number of attributes on the current start element.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_xml_reader_attribute_count(OakCommonXmlReader *reader,
int *count);
/**
* @brief Name of the attribute at @p index on the current start element.
*
* @return Required buffer size in bytes (including NUL), OAKCOMMON_E_NOT_FOUND
* if @p index is out of range, or another negative OAKCOMMON_E_* code.
*/
int oakcommon_xml_reader_attribute_name(OakCommonXmlReader *reader, int index,
char *buf, int buf_size);
/**
* @brief Value of the attribute at @p index on the current start element.
*
* @return Required buffer size in bytes (including NUL), OAKCOMMON_E_NOT_FOUND
* if @p index is out of range, or another negative OAKCOMMON_E_* code.
*/
int oakcommon_xml_reader_attribute_value(OakCommonXmlReader *reader,
int index, char *buf, int buf_size);
/**
* @brief Whether the document failed to parse.
*
* @return OAKCOMMON_OK or a negative OAKCOMMON_E_* error code.
*/
int oakcommon_xml_reader_has_error(OakCommonXmlReader *reader,
int *has_error);
/**
* @brief Create a streaming XML writer.
*
* @return A new writer, or NULL on failure.
*/
OakCommonXmlWriter *oakcommon_xml_writer_init(void);
/**
* @brief Destroy a writer. No-op on NULL.
*/
void oakcommon_xml_writer_free(OakCommonXmlWriter *writer);
int oakcommon_xml_writer_write_start_element(OakCommonXmlWriter *writer,
const char *name);
int oakcommon_xml_writer_write_attribute(OakCommonXmlWriter *writer,
const char *name, const char *value);
int oakcommon_xml_writer_write_characters(OakCommonXmlWriter *writer,
const char *text);
int oakcommon_xml_writer_write_text_element(OakCommonXmlWriter *writer,
const char *name,
const char *text);
int oakcommon_xml_writer_write_end_element(OakCommonXmlWriter *writer);
int oakcommon_xml_writer_write_end_document(OakCommonXmlWriter *writer);
/**
* @brief The document written so far.
*
* @return Required buffer size in bytes (including NUL), or a negative
* OAKCOMMON_E_* error code.
*/
int oakcommon_xml_writer_output(OakCommonXmlWriter *writer, char *buf,
int buf_size);
#ifdef __cplusplus
}
#endif
#endif // OAK_EDITOR_XMLUTILS_H