Mercurial > libedl
diff src/edl.c @ 8:0c98b46eaf73 v2.0
*: update API to 2.0, big changes
all APIs now use pointers to an EDL object. it is up to the
user to make sure that the pointer is valid.
additionally, many things have been separated into new files
to make it easier to digest
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Sun, 03 Mar 2024 17:56:58 -0500 |
parents | 7137fbac0b85 |
children | 0cc2555db371 |
line wrap: on
line diff
--- a/src/edl.c Mon Jan 15 06:42:30 2024 -0500 +++ b/src/edl.c Sun Mar 03 17:56:58 2024 -0500 @@ -3,273 +3,229 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> + #include "edl.h" #include "str.h" - -#define strnchr(haystack, needle, length) (char*)memchr(haystack, needle, strnlen(haystack, length)) - -static uint32_t EDL_internal_crcn32b(const unsigned char* restrict message, size_t length) { - uint32_t crc = 0xFFFFFFFF; +#include "datatypes.h" +#include "util.h" +/* CRC32 hashes of EDL headers */ +#define EDL_HEADER_ID 0x1541c503 +#define EDL_HEADER_TRACK 0x4b211812 +#define EDL_HEADER_STARTTIME 0xbb46516f +#define EDL_HEADER_LENGTH 0xaeac5df7 +#define EDL_HEADER_PLAYRATE 0x03834606 +#define EDL_HEADER_LOCKED 0x0c2083d3 +#define EDL_HEADER_NORMALIZED 0xe60c8b1d +#define EDL_HEADER_STRETCHMETHOD 0xbe5802c9 +#define EDL_HEADER_LOOPED 0x4ec8be4c +#define EDL_HEADER_ONRULER 0xe6cb84d1 +#define EDL_HEADER_MEDIATYPE 0x035f84c2 +#define EDL_HEADER_FILENAME 0x379d32c5 +#define EDL_HEADER_STREAM 0x9f334738 +#define EDL_HEADER_STREAMSTART 0x07b4e0e7 +#define EDL_HEADER_STREAMLENGTH 0x8f16c7b8 +#define EDL_HEADER_FADETIMEIN 0xd2edd7e4 +#define EDL_HEADER_FADETIMEOUT 0x792e8c40 +#define EDL_HEADER_SUSTAINGAIN 0x98374657 +#define EDL_HEADER_CURVEIN 0x3e998b1f +#define EDL_HEADER_GAININ 0x82fb09c4 +#define EDL_HEADER_CURVEOUT 0x53add388 +#define EDL_HEADER_GAINOUT 0x4210ba56 +#define EDL_HEADER_LAYER 0x89c4df6c +#define EDL_HEADER_COLOR 0xadf2f1a3 +#define EDL_HEADER_CURVEINR 0xa56b43e1 +#define EDL_HEADER_CURVEOUTR 0xcb6d715e +#define EDL_HEADER_PLAYPITCH 0x9da1b9ed +#define EDL_HEADER_LOCKPITCH 0x2bda6ed4 +#define EDL_HEADER_FIRSTCHANNEL 0x3071a4c6 +#define EDL_HEADER_CHANNELS 0xe94981a4 + +/* use a CRC32 hash function to process the headers */ +static uint32_t EDL_internal_crcn32b(const unsigned char* message, size_t length) { + uint32_t crc = 0xffffffff; size_t i; + for (i = 0; i < length && message[i]; i++) { + size_t j; + crc = crc ^ message[i]; - size_t j; for (j = 0; j < 8; j++) - crc = (crc >> 1) ^ (0xEDB88320 & -(crc & 1)); + crc = (crc >> 1) ^ (0xedb88320 & -(crc & 1)); } return ~crc; } -/* This parses the first line of the EDL and - * creates an array with CRC32 hashes in - * the order of the strings. +static size_t EDL_internal_size_t_min(size_t a, size_t b) { + return (a < b) ? a : b; +} + +/* This parses the header of the EDL and creates an array with CRC32 hashes + * in the order of the strings. */ -static uint32_t* EDL_internal_parse_first_line(const char* data, size_t* restrict length) { - size_t hashes_size = 32, current_hash = 0; +static uint32_t* EDL_internal_parse_header(const char* data, size_t* length) { + /* */ + const size_t newline = EDL_internal_size_t_min(strchr(data, '\n') - data, strchr(data, '\r') - data); + + size_t current_hash = 0, hashes_size = 32; uint32_t* hashes = malloc(hashes_size * sizeof(uint32_t)); - size_t len_until_newline = strchr(data, '\n') - data, len_until_cr = strchr(data, '\r') - data; - size_t i, b; - for (i = 0, b = 0; i <= len_until_newline && i <= len_until_cr; i++, b++) { - if (data[i] == ';' || data[i] == ':' || data[i] == '\r' || data[i] == '\n') { - if (current_hash >= hashes_size) + /* overall iterates over the entire line, + * column stores the length of the current column */ + size_t overall, column; + + for (overall = 0, column = 0; overall <= newline; overall++) { + if (data[overall] == ';' || data[overall] == ':') { + /* process the current column */ + if (hashes_size < current_hash) hashes = realloc(hashes, (hashes_size *= 2) * sizeof(uint32_t)); - hashes[current_hash++] = EDL_internal_crcn32b((const unsigned char*)&data[i - b], b); - b = -1; // ew - } + + hashes[current_hash++] = EDL_internal_crcn32b((const unsigned char*)&data[overall - column], column); + column = 0; /* reset */ + } else column++; } - *length = current_hash; // wtf? + *length = current_hash; return hashes; } -/* -- Functions to extract different datatypes -- */ - -static size_t EDL_internal_append_offset(const char* input, size_t offset, size_t length) { - size_t s = 0; - - s += strchr(&input[offset + s], ';') - &input[offset]; - if (s + offset > length) - return s; - - s += strspn(&input[offset + s], ";\t "); - if (s + offset > length) - return s; - - return s; -} - -static size_t EDL_internal_get_int(const char* input, size_t offset, size_t length, int* int_return) { - if (offset > length) - return 0; - - { - char* ptr_return; - *int_return = strtol(&input[offset], &ptr_return, 10); - - if (!ptr_return) - return 0; - } - - return EDL_internal_append_offset(input, offset, length); -} - -static size_t EDL_internal_get_double(const char* input, size_t offset, size_t length, double* double_return) { - if (offset > length) - return 0; - - { - char* ptr_return; - *double_return = strtod(&input[offset], &ptr_return); - - if (!ptr_return) - return 0; - } - - return EDL_internal_append_offset(input, offset, length); -} - -static size_t EDL_internal_get_bool(const char* input, size_t offset, size_t length, bool* bool_return) { - if (offset > length) +int EDL_reallocate(EDL* edl, size_t new_capacity) { + edl->arr = realloc(edl->arr, new_capacity * sizeof(EDL_line)); + if (!edl->arr) return 0; - if (!strncmp(&input[offset], "TRUE", 4)) - *bool_return = true; - else if (!strncmp(&input[offset], "FALSE", 5)) - *bool_return = false; - - return EDL_internal_append_offset(input, offset, length); -} - -static size_t EDL_internal_get_media_type(const char* input, size_t offset, size_t length, MediaType* media_return) { - if (offset > length) - return 0; - - if (!strncmp(&input[offset], "VIDEO", 5)) - *media_return = MEDIATYPE_VIDEO; - else if (!strncmp(&input[offset], "AUDIO", 5)) - *media_return = MEDIATYPE_AUDIO; - else - *media_return = MEDIATYPE_UNKNOWN; - - return EDL_internal_append_offset(input, offset, length); -} - -static size_t EDL_internal_get_string(const char* input, size_t offset, size_t length, char** string_return) { - /* Windows filenames will *NEVER* include double quotes. - This might break with EDL files created with Reaper on Linux. */ - if (offset > length) - return 0; + if (new_capacity > edl->capacity) + memset(&edl->arr[edl->capacity], 0, (new_capacity - edl->capacity) * sizeof(EDL_line)); - size_t start = strchr(&input[offset], '\"') - &input[offset] + 1; - if (start + offset > length) - return 0; - - size_t s_length = strchr(&input[offset + start], '\"') - &input[offset] - start; - if (start + s_length + offset > length) - return 0; - - *string_return = malloc((s_length + 1) * sizeof(char)); - if (!*string_return) - return 0; - - memcpy(*string_return, &input[offset + start], s_length); - (*string_return)[s_length] = '\0'; - - return EDL_internal_append_offset(input, offset, length); -} - -/* memory management routines */ - -int EDL_reallocate(EDL* input, size_t new_capacity) { - input->arr = realloc(input->arr, new_capacity * sizeof(EDL_line)); - if (!input->arr) - return 0; - - if (new_capacity > input->capacity) - memset(&input->arr[input->capacity], 0, (new_capacity - input->capacity) * sizeof(EDL_line)); - - input->capacity = new_capacity; + edl->capacity = new_capacity; return 1; } -/* the important function */ -EDL EDL_parse(const char* data, size_t length) { - EDL edl = {0}; - if (!EDL_reallocate(&edl, 16)) - return edl; +int EDL_append(EDL* edl, EDL_line line) { + if (edl->size + 1 < edl->capacity && !EDL_reallocate(edl, edl->capacity)) + return 0; + edl->arr[++edl->size] = line; + return 1; +} + +/* the big important function */ +EDL_parse_error_t EDL_parse(EDL* edl, const char* data, size_t length) { size_t order_size = 0; - uint32_t* order = EDL_internal_parse_first_line(data, &order_size); - + uint32_t* order = NULL; size_t offset = 0; - while ((offset = strnchr(&data[offset], '\n', length - offset) - data + 1) < length) { - size_t local_offset = offset; // this is so our original offset stays intact + + if (!EDL_reallocate(edl, 16)) + return EDL_PARSE_ERROR_OUT_OF_MEMORY; + + order = EDL_internal_parse_header(data, &order_size); + while ((offset = EDL_internal_strnchr(&data[offset], '\n', length - offset) - data + 1) < length) { + size_t local_offset = offset; /* original offset stays intact */ bool ok = true; + int i; - for (int i = 0; i < order_size; i++) { + for (i = 0; i < order_size; i++) { #define ADD_TO_OFFSET(x, a) \ { \ - size_t o = a(data, local_offset, length, &edl.arr[edl.size].x); \ + size_t o = a(data, local_offset, length, &edl->arr[edl->size].x); \ if (!o) \ ok = false; \ local_offset += o; \ } switch (order[i]) { - case 0x1541c503: /* ID */ - ADD_TO_OFFSET(id, EDL_internal_get_int); + case EDL_HEADER_ID: + ADD_TO_OFFSET(id, EDL_internal_parse_int); break; - case 0x4b211812: /* Track */ - ADD_TO_OFFSET(track, EDL_internal_get_int); + case EDL_HEADER_TRACK: + ADD_TO_OFFSET(track, EDL_internal_parse_int); break; - case 0xbb46516f: /* StartTime */ - ADD_TO_OFFSET(start_time, EDL_internal_get_double); + case EDL_HEADER_STARTTIME: + ADD_TO_OFFSET(start_time, EDL_internal_parse_double); break; - case 0xaeac5df7: /* Length */ - ADD_TO_OFFSET(length, EDL_internal_get_double); + case EDL_HEADER_LENGTH: + ADD_TO_OFFSET(length, EDL_internal_parse_double); break; - case 0x03834606: /* PlayRate */ - ADD_TO_OFFSET(play_rate, EDL_internal_get_double); + case EDL_HEADER_PLAYRATE: + ADD_TO_OFFSET(play_rate, EDL_internal_parse_double); break; - case 0x0c2083d3: /* Locked */ - ADD_TO_OFFSET(locked, EDL_internal_get_bool); + case EDL_HEADER_LOCKED: + ADD_TO_OFFSET(locked, EDL_internal_parse_bool); break; - case 0xe60c8b1d: /* Normalized */ - ADD_TO_OFFSET(normalized, EDL_internal_get_bool); + case EDL_HEADER_NORMALIZED: + ADD_TO_OFFSET(normalized, EDL_internal_parse_bool); break; - case 0xbe5802c9: /* StretchMethod */ - ADD_TO_OFFSET(stretch_method, EDL_internal_get_int); + case EDL_HEADER_STRETCHMETHOD: + ADD_TO_OFFSET(stretch_method, EDL_internal_parse_int); break; - case 0x4ec8be4c: /* Looped */ - ADD_TO_OFFSET(looped, EDL_internal_get_bool); + case EDL_HEADER_LOOPED: + ADD_TO_OFFSET(looped, EDL_internal_parse_bool); break; - case 0xe6cb84d1: /* OnRuler */ - ADD_TO_OFFSET(on_ruler, EDL_internal_get_bool); + case EDL_HEADER_ONRULER: + ADD_TO_OFFSET(on_ruler, EDL_internal_parse_bool); break; - case 0x035f84c2: /* MediaType */ - ADD_TO_OFFSET(media_type, EDL_internal_get_media_type); + case EDL_HEADER_MEDIATYPE: + ADD_TO_OFFSET(media_type, EDL_internal_parse_media_type); break; - case 0x379d32c5: /* FileName */ - ADD_TO_OFFSET(filename, EDL_internal_get_string); + case EDL_HEADER_FILENAME: + ADD_TO_OFFSET(filename, EDL_internal_parse_string); break; - case 0x9f334738: /* Stream */ - ADD_TO_OFFSET(stream, EDL_internal_get_int); + case EDL_HEADER_STREAM: + ADD_TO_OFFSET(stream, EDL_internal_parse_int); break; - case 0x07b4e0e7: /* StreamStart */ - ADD_TO_OFFSET(stream_start, EDL_internal_get_double); + case EDL_HEADER_STREAMSTART: + ADD_TO_OFFSET(stream_start, EDL_internal_parse_double); break; - case 0x8f16c7b8: /* StreamLength */ - ADD_TO_OFFSET(stream_length, EDL_internal_get_double); + case EDL_HEADER_STREAMLENGTH: + ADD_TO_OFFSET(stream_length, EDL_internal_parse_double); break; - case 0xd2edd7e4: /* FadeTimeIn */ - ADD_TO_OFFSET(fade_time_in, EDL_internal_get_double); + case EDL_HEADER_FADETIMEIN: + ADD_TO_OFFSET(fade_time_in, EDL_internal_parse_double); break; - case 0x792e8c40: /* FadeTimeOut */ - ADD_TO_OFFSET(fade_time_out, EDL_internal_get_double); + case EDL_HEADER_FADETIMEOUT: + ADD_TO_OFFSET(fade_time_out, EDL_internal_parse_double); break; - case 0x98374657: /* SustainGain */ - ADD_TO_OFFSET(sustain_gain, EDL_internal_get_double); + case EDL_HEADER_SUSTAINGAIN: + ADD_TO_OFFSET(sustain_gain, EDL_internal_parse_double); break; - case 0x3e998b1f: /* CurveIn */ - ADD_TO_OFFSET(curve_in, EDL_internal_get_int); + case EDL_HEADER_CURVEIN: + ADD_TO_OFFSET(curve_in, EDL_internal_parse_int); break; - case 0x82fb09c4: /* GainIn */ - ADD_TO_OFFSET(gain_in, EDL_internal_get_double); + case EDL_HEADER_GAININ: + ADD_TO_OFFSET(gain_in, EDL_internal_parse_double); break; - case 0x53add388: /* CurveOut */ - ADD_TO_OFFSET(curve_out, EDL_internal_get_int); + case EDL_HEADER_CURVEOUT: + ADD_TO_OFFSET(curve_out, EDL_internal_parse_int); break; - case 0x4210ba56: /* GainOut */ - ADD_TO_OFFSET(gain_out, EDL_internal_get_double); + case EDL_HEADER_GAINOUT: + ADD_TO_OFFSET(gain_out, EDL_internal_parse_double); break; - case 0x89c4df6c: /* Layer */ - ADD_TO_OFFSET(layer, EDL_internal_get_int); + case EDL_HEADER_LAYER: + ADD_TO_OFFSET(layer, EDL_internal_parse_int); break; - case 0xadf2f1a3: /* Color */ - ADD_TO_OFFSET(color, EDL_internal_get_int); + case EDL_HEADER_COLOR: + ADD_TO_OFFSET(color, EDL_internal_parse_int); break; - case 0xa56b43e1: /* CurveInR */ - ADD_TO_OFFSET(curve_in_r, EDL_internal_get_int); + case EDL_HEADER_CURVEINR: + ADD_TO_OFFSET(curve_in_r, EDL_internal_parse_int); break; - case 0xcb6d715e: /* CurveOutR */ - ADD_TO_OFFSET(curve_out_r, EDL_internal_get_int); + case EDL_HEADER_CURVEOUTR: + ADD_TO_OFFSET(curve_out_r, EDL_internal_parse_int); break; - case 0x9da1b9ed: /* PlayPitch */ - ADD_TO_OFFSET(play_pitch, EDL_internal_get_double); + case EDL_HEADER_PLAYPITCH: + ADD_TO_OFFSET(play_pitch, EDL_internal_parse_double); break; - case 0x2bda6ed4: /* LockPitch */ - ADD_TO_OFFSET(lock_pitch, EDL_internal_get_bool); + case EDL_HEADER_LOCKPITCH: + ADD_TO_OFFSET(lock_pitch, EDL_internal_parse_bool); break; - case 0x3071a4c6: /* FirstChannel */ - ADD_TO_OFFSET(first_channel, EDL_internal_get_int); + case EDL_HEADER_FIRSTCHANNEL: + ADD_TO_OFFSET(first_channel, EDL_internal_parse_int); break; - case 0xe94981a4: /* Channels */ - ADD_TO_OFFSET(channels, EDL_internal_get_int); + case EDL_HEADER_CHANNELS: + ADD_TO_OFFSET(channels, EDL_internal_parse_int); break; default: /* ... what */ @@ -281,145 +237,119 @@ if (!ok) break; - if (++edl.size >= edl.capacity) - EDL_reallocate(&edl, edl.capacity * 2); + if (++edl->size >= edl->capacity) + EDL_reallocate(edl, edl->capacity * 2); } - EDL_reallocate(&edl, edl.size); + /* put on the shrinkwrap */ + EDL_reallocate(edl, edl->size); free(order); - return edl; -} - -static char* EDL_internal_integer_to_string(int value) { - char out[256] = {0}; // this ought to be enough. - snprintf(out, 256, "%d", value); - out[255] = '\0'; - return strdup(out); -} - -static char* EDL_internal_double_to_string(double value) { - char out[256] = {0}; - snprintf(out, 256, "%.6f", value); - out[255] = '\0'; - return strdup(out); + return EDL_PARSE_ERROR_SUCCESS; } -static char* EDL_internal_bool_to_string(bool value) { - return strdup(value ? "TRUE" : "FALSE"); -} +static void EDL_dump_line(EDL_internal_string* str, const EDL_line* line, const uint32_t* order, const size_t order_len) { + size_t i; -static char* EDL_internal_media_type_to_string(MediaType value) { - switch (value) { - case MEDIATYPE_AUDIO: - return strdup("AUDIO"); - case MEDIATYPE_VIDEO: - case MEDIATYPE_UNKNOWN: - default: - return strdup("VIDEO"); - } -} - -static void EDL_dump_line(EDL_internal_string* str, EDL_line line, const uint32_t* order, const size_t order_len) { - for (size_t i = 0; i < order_len; i++) { + for (i = 0; i < order_len; i++) { switch (order[i]) { #define APPEND_ITEM(a, x) \ { \ - char* tstr = x(line.a); \ + char* tstr = x(line->a); \ EDL_internal_string_append(str, tstr, strlen(tstr)); \ free(tstr); \ } - case 0x1541c503: /* ID */ + case EDL_HEADER_ID: APPEND_ITEM(id, EDL_internal_integer_to_string); break; - case 0x4b211812: /* Track */ + case EDL_HEADER_TRACK: APPEND_ITEM(track, EDL_internal_integer_to_string); break; - case 0xbb46516f: /* StartTime */ + case EDL_HEADER_STARTTIME: APPEND_ITEM(start_time, EDL_internal_double_to_string); break; - case 0xaeac5df7: /* Length */ + case EDL_HEADER_LENGTH: APPEND_ITEM(length, EDL_internal_double_to_string); break; - case 0x03834606: /* PlayRate */ + case EDL_HEADER_PLAYRATE: APPEND_ITEM(play_rate, EDL_internal_double_to_string); break; - case 0x0c2083d3: /* Locked */ + case EDL_HEADER_LOCKED: APPEND_ITEM(locked, EDL_internal_bool_to_string); break; - case 0xe60c8b1d: /* Normalized */ + case EDL_HEADER_NORMALIZED: APPEND_ITEM(normalized, EDL_internal_bool_to_string); break; - case 0xbe5802c9: /* StretchMethod */ + case EDL_HEADER_STRETCHMETHOD: APPEND_ITEM(stretch_method, EDL_internal_integer_to_string); break; - case 0x4ec8be4c: /* Looped */ + case EDL_HEADER_LOOPED: APPEND_ITEM(looped, EDL_internal_bool_to_string); break; - case 0xe6cb84d1: /* OnRuler */ + case EDL_HEADER_ONRULER: APPEND_ITEM(on_ruler, EDL_internal_bool_to_string); break; - case 0x035f84c2: /* MediaType */ + case EDL_HEADER_MEDIATYPE: APPEND_ITEM(media_type, EDL_internal_media_type_to_string); break; - case 0x379d32c5: /* FileName */ + case EDL_HEADER_FILENAME: EDL_internal_string_append(str, "\"", 1); - EDL_internal_string_append(str, line.filename, strlen(line.filename)); + EDL_internal_string_append(str, line->filename, strlen(line->filename)); EDL_internal_string_append(str, "\"", 1); break; - case 0x9f334738: /* Stream */ + case EDL_HEADER_STREAM: APPEND_ITEM(stream, EDL_internal_integer_to_string); break; - case 0x07b4e0e7: /* StreamStart */ + case EDL_HEADER_STREAMSTART: APPEND_ITEM(stream_start, EDL_internal_double_to_string); break; - case 0x8f16c7b8: /* StreamLength */ + case EDL_HEADER_STREAMLENGTH: APPEND_ITEM(stream_length, EDL_internal_double_to_string); break; - case 0xd2edd7e4: /* FadeTimeIn */ + case EDL_HEADER_FADETIMEIN: APPEND_ITEM(fade_time_in, EDL_internal_double_to_string); break; - case 0x792e8c40: /* FadeTimeOut */ + case EDL_HEADER_FADETIMEOUT: APPEND_ITEM(fade_time_out, EDL_internal_double_to_string); break; - case 0x98374657: /* SustainGain */ + case EDL_HEADER_SUSTAINGAIN: APPEND_ITEM(sustain_gain, EDL_internal_double_to_string); break; - case 0x3e998b1f: /* CurveIn */ + case EDL_HEADER_CURVEIN: APPEND_ITEM(curve_in, EDL_internal_integer_to_string); break; - case 0x82fb09c4: /* GainIn */ + case EDL_HEADER_GAININ: APPEND_ITEM(gain_in, EDL_internal_double_to_string); break; - case 0x53add388: /* CurveOut */ + case EDL_HEADER_CURVEOUT: APPEND_ITEM(curve_out, EDL_internal_integer_to_string); break; - case 0x4210ba56: /* GainOut */ + case EDL_HEADER_GAINOUT: APPEND_ITEM(gain_out, EDL_internal_double_to_string); break; - case 0x89c4df6c: /* Layer */ + case EDL_HEADER_LAYER: APPEND_ITEM(layer, EDL_internal_integer_to_string); break; - case 0xadf2f1a3: /* Color */ + case EDL_HEADER_COLOR: APPEND_ITEM(color, EDL_internal_integer_to_string); break; - case 0xa56b43e1: /* CurveInR */ + case EDL_HEADER_CURVEINR: APPEND_ITEM(curve_in_r, EDL_internal_integer_to_string); break; - case 0xcb6d715e: /* CurveOutR */ + case EDL_HEADER_CURVEOUTR: APPEND_ITEM(curve_out_r, EDL_internal_integer_to_string); break; - case 0x9da1b9ed: /* PlayPitch */ + case EDL_HEADER_PLAYPITCH: APPEND_ITEM(play_pitch, EDL_internal_double_to_string); break; - case 0x2bda6ed4: /* LockPitch */ + case EDL_HEADER_LOCKPITCH: APPEND_ITEM(lock_pitch, EDL_internal_bool_to_string); break; - case 0x3071a4c6: /* FirstChannel */ + case EDL_HEADER_FIRSTCHANNEL: APPEND_ITEM(first_channel, EDL_internal_integer_to_string); break; - case 0xe94981a4: /* Channels */ + case EDL_HEADER_CHANNELS: APPEND_ITEM(channels, EDL_internal_integer_to_string); break; default: @@ -437,32 +367,38 @@ EDL_internal_string_append(str, "\n", 1); } -char* EDL_dump(EDL edl) { +/* this gets progressively slower and slower... oops */ +char* EDL_dump(const EDL* edl) { + static const char order_str[] = + "\"ID\";\"Track\";\"StartTime\";\"Length\";\"PlayRate\";\"Locked\";\"Normalized\";\"StretchMethod\";" + "\"Looped\";\"OnRuler\";\"MediaType\";\"FileName\";\"Stream\";\"StreamStart\";\"StreamLength\";" + "\"FadeTimeIn\";\"FadeTimeOut\";\"SustainGain\";\"CurveIn\";\"GainIn\";\"CurveOut\";\"GainOut\";" + "\"Layer\";\"Color\";\"CurveInR\";\"CurveOutR\":\"PlayPitch\";\"LockPitch\";\"FirstChannel\";\"Channels\"\n"; + EDL_internal_string ret; EDL_internal_string_init(&ret); - static const char order_str[] = "\"ID\";\"Track\";\"StartTime\";\"Length\";\"PlayRate\";\"Locked\";\"Normalized\";\"StretchMethod\";\"Looped\";\"OnRuler\";\"MediaType\";\"FileName\";\"Stream\";\"StreamStart\";\"StreamLength\";\"FadeTimeIn\";\"FadeTimeOut\";\"SustainGain\";\"CurveIn\";\"GainIn\";\"CurveOut\";\"GainOut\";\"Layer\";\"Color\";\"CurveInR\";\"CurveOutR\":\"PlayPitch\";\"LockPitch\";\"FirstChannel\";\"Channels\"\n"; EDL_internal_string_append(&ret, order_str, strlen(order_str)); - size_t order_len; - uint32_t* order = EDL_internal_parse_first_line(order_str, &order_len); + { + size_t order_len; + uint32_t* order = EDL_internal_parse_header(order_str, &order_len); - size_t i; - for (i = 0; i < edl.size; i++) - EDL_dump_line(&ret, edl.arr[i], order, order_len); + size_t i; + for (i = 0; i < edl->size; i++) + EDL_dump_line(&ret, &edl->arr[i], order, order_len); - free(order); - - EDL_internal_string_allocate(&ret, ret.size); + free(order); + } return ret.data; } -void EDL_free(EDL edl) { +void EDL_free(EDL* edl) { size_t i; - for (i = 0; i < edl.size; i++) { - if (edl.arr[i].filename) - free(edl.arr[i].filename); + for (i = 0; i < edl->size; i++) { + if (edl->arr[i].filename) + free(edl->arr[i].filename); } - free(edl.arr); + free(edl->arr); }