251 lines
11 KiB
C
251 lines
11 KiB
C
#ifndef XTC_PROJECT_H
|
|
#define XTC_PROJECT_H
|
|
|
|
#include "xtc_engine.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define XTC_PROJECT_FORMAT_VERSION 15U
|
|
#define XTC_PROJECT_MAX_TRACKS 64U
|
|
#define XTC_PROJECT_MAX_CLIPS 1024U
|
|
#define XTC_PROJECT_NAME_BYTES 64U
|
|
#define XTC_ASSET_PATH_BYTES 512U
|
|
#define XTC_TICKS_PER_QUARTER 960U
|
|
#define XTC_PROJECT_MAX_TICK UINT64_C(38400000)
|
|
typedef struct xtc_project xtc_project;
|
|
/* Control-thread edits, transactional validation; duplicate retains complete
|
|
* source notes/trim/media references, allocates fresh IDs, copies no audio. */
|
|
xtc_result xtc_project_duplicate_clip(xtc_project *project, uint64_t clip, uint64_t track, uint64_t start, uint64_t *out);
|
|
xtc_result xtc_project_rename_track(xtc_project *project, uint64_t track, const char *name);
|
|
xtc_result xtc_project_rename_clip(xtc_project *project, uint64_t clip, const char *name);
|
|
xtc_result xtc_project_move_track(xtc_project *project, uint64_t track, size_t index);
|
|
|
|
typedef struct {
|
|
uint64_t id;
|
|
char name[XTC_PROJECT_NAME_BYTES];
|
|
float gain, pan;
|
|
int mute, solo;
|
|
int is_bus; /* One-level summing bus; no clips, routes only to master. */
|
|
uint64_t bus_id; /* UINT64_MAX = master, otherwise an existing bus ID. */
|
|
} xtc_track_info;
|
|
|
|
/* Arrangement region: empty asset_path means silent metadata.
|
|
* All musical positions are integer ticks, constant tempo and 4/4 meter. */
|
|
typedef struct {
|
|
uint64_t id, track_id, start_tick, length_tick, offset_tick, source_length_tick;
|
|
char name[XTC_PROJECT_NAME_BYTES];
|
|
char asset_path[XTC_ASSET_PATH_BYTES];
|
|
float gain; /* Audio-only, linear 0..4; default 1. */
|
|
uint64_t fade_in_tick, fade_out_tick; /* Audio-only linear boundary fades. */
|
|
int midi; /* 0 silent/audio region, 1 MIDI clip; no asset path in MIDI. */
|
|
} xtc_clip_info;
|
|
|
|
/* Single control-thread ownership. Names: nonempty UTF-8, <=63 bytes, no ASCII controls.
|
|
* IDs are monotonic, never reused, UINT64_MAX reserved. Snapshots are copies. */
|
|
/**
|
|
* @brief Allocates an empty project with an output-only graph policy and 120 BPM tempo.
|
|
*
|
|
* @param out_project Receives the newly allocated project; caller owns it on success.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_create(xtc_project **out_project);
|
|
/**
|
|
* @brief Releases a project and its graph; accepts NULL.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
*/
|
|
void xtc_project_destroy(xtc_project *project);
|
|
/**
|
|
* @brief Allocates an independent copy of project metadata and its graph.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param out_project Receives the newly allocated project; caller owns it on success.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_clone(const xtc_project *project, xtc_project **out_project);
|
|
/**
|
|
* @brief Copies the current track and clip counts.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param out_tracks Receives the tracks.
|
|
* @param out_clips Receives the clips.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_get_counts(const xtc_project *project, size_t *out_tracks, size_t *out_clips);
|
|
/**
|
|
* @brief Copies a track snapshot selected by dense list index.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param index Zero-based index in the dense list.
|
|
* @param out_track Receives the track.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_get_track(const xtc_project *project, size_t index, xtc_track_info *out_track);
|
|
/**
|
|
* @brief Copies a clip snapshot selected by dense list index.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param index Zero-based index in the dense list.
|
|
* @param out_clip Receives the clip.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_get_clip(const xtc_project *project, size_t index, xtc_clip_info *out_clip);
|
|
/**
|
|
* @brief Copies a clip snapshot selected by stable identifier.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param id Stable identifier of the object to find or edit.
|
|
* @param out_clip Receives the clip.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_find_clip(const xtc_project *project, uint64_t id, xtc_clip_info *out_clip);
|
|
/**
|
|
* @brief Appends a track with unity gain and a new stable identifier.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param name NUL-terminated name.
|
|
* @param out_id Receives the id.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_add_track(xtc_project *project, const char *name, uint64_t *out_id);
|
|
/* Removing a track also removes its clips. */
|
|
/**
|
|
* @brief Removes a track and its clips, notes, and automation.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param id Stable identifier of the object to find or edit.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_remove_track(xtc_project *project, uint64_t id);
|
|
/**
|
|
* @brief Appends a silent region on an existing track with a new stable identifier.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param track_id Stable destination track identifier.
|
|
* @param name NUL-terminated name.
|
|
* @param start_tick Start position in musical ticks.
|
|
* @param length_tick Duration in musical ticks.
|
|
* @param out_id Receives the id.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_add_clip(xtc_project *project, uint64_t track_id, const char *name, uint64_t start_tick,
|
|
uint64_t length_tick, uint64_t *out_id);
|
|
/**
|
|
* @brief Removes a clip and its notes.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param id Stable identifier of the object to find or edit.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_remove_clip(xtc_project *project, uint64_t id);
|
|
/* Atomic move/trim: source bounds remain unchanged, no destructive edits. */
|
|
/**
|
|
* @brief Atomically moves or trims a clip within its existing source bounds.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param id Stable identifier of the object to find or edit.
|
|
* @param track_id Stable destination track identifier.
|
|
* @param start_tick Start position in musical ticks.
|
|
* @param length_tick Duration in musical ticks.
|
|
* @param offset_tick Offset into the clip source in ticks.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_edit_clip(xtc_project *project, uint64_t id, uint64_t track_id, uint64_t start_tick,
|
|
uint64_t length_tick, uint64_t offset_tick);
|
|
/* Borrowed opaque graph valid until project mutation/destruction. set_graph
|
|
* copies before replacing; max 64 nodes, preserving IDs, edges and output policy. */
|
|
/**
|
|
* @brief Returns the project's borrowed graph, or NULL for a NULL project.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @return Borrowed graph valid until project mutation or destruction, or NULL for NULL.
|
|
*/
|
|
const xtc_graph *xtc_project_graph(const xtc_project *project);
|
|
/**
|
|
* @brief Copies and validates a graph before replacing the project's graph.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param graph Graph model; borrowed for this call.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_set_graph(xtc_project *project, const xtc_graph *graph);
|
|
/* Constant tempo in milli-BPM: 20000..300000, default 120000. */
|
|
/**
|
|
* @brief Returns the constant tempo in milli-BPM, or zero for a NULL project.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @return Tempo in milli-BPM, or zero for NULL.
|
|
*/
|
|
unsigned int xtc_project_tempo(const xtc_project *project);
|
|
/**
|
|
* @brief Sets the constant tempo within the range 20000 to 300000 milli-BPM.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param milli_bpm Tempo in thousandths of a beat per minute.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_set_tempo(xtc_project *project, unsigned int milli_bpm);
|
|
/* Floor conversion, no accumulated drift. Rate: 1..768000. Tick <= MAX_TICK.
|
|
* Excess sample/tick positions return capacity; outputs unchanged on error. */
|
|
/**
|
|
* @brief Converts a musical tick to an absolute sample position, rounding down.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param tick Musical position in ticks.
|
|
* @param sample_rate Sample rate in hertz.
|
|
* @param out_sample Receives the sample.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_tick_to_sample(const xtc_project *project, uint64_t tick, unsigned int sample_rate,
|
|
uint64_t *out_sample);
|
|
/**
|
|
* @brief Converts an absolute sample position to a musical tick, rounding down.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param sample Absolute sample position.
|
|
* @param sample_rate Sample rate in hertz.
|
|
* @param out_tick Receives the tick.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_sample_to_tick(const xtc_project *project, uint64_t sample, unsigned int sample_rate,
|
|
uint64_t *out_tick);
|
|
/* Control-thread I/O. Versioned, bounded format; see docs/PROJECT_FORMAT.md.
|
|
* Load is transactional. Save fsyncs a same-directory temporary and renames it;
|
|
* failures before rename preserve the previous destination. No asset I/O. v7+ saves local media paths relative to the project folder; load
|
|
* resolves them to absolute references. Post-rename directory-sync failure can
|
|
* report IO with the complete new document already published. */
|
|
/**
|
|
* @brief Saves a versioned project through a synced temporary file and atomic rename.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param path NUL-terminated file or asset path.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_save(const xtc_project *project, const char *path);
|
|
/* Optional copied control-thread diagnostics. line is 1-based for syntax errors,
|
|
* 0 for I/O/whole-model validation; record identifies the expected record or
|
|
* validation stage, never untrusted file text. format_version is 0 if unknown.
|
|
* No media/plugin loading, engine creation or mutation on load failure. */
|
|
typedef struct {
|
|
xtc_result result;
|
|
uint64_t format_version;
|
|
size_t line;
|
|
char record[32], message[192];
|
|
} xtc_project_diagnostic;
|
|
xtc_result xtc_project_load_diagnostic(xtc_project *project, const char *path, xtc_project_diagnostic *diagnostic);
|
|
/**
|
|
* @brief Loads and validates a project before transactionally replacing the current state.
|
|
*
|
|
* @param project Project model; borrowed for this call.
|
|
* @param path NUL-terminated file or asset path.
|
|
* @return XTC_OK on success, or an error code describing the failure.
|
|
*/
|
|
xtc_result xtc_project_load(xtc_project *project, const char *path);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|