Mercurial > libedl
comparison src/main.c @ 0:0ea1ec2da443
*: initial commit
| author | Paper <mrpapersonic@gmail.com> |
|---|---|
| date | Tue, 04 Jul 2023 22:44:41 -0400 |
| parents | |
| children | d00bc412900e |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:0ea1ec2da443 |
|---|---|
| 1 #include <string.h> | |
| 2 #include <stdbool.h> | |
| 3 #include <stdio.h> | |
| 4 #include <stdlib.h> | |
| 5 #include <stdint.h> | |
| 6 #include "edl.h" | |
| 7 | |
| 8 int strings_amt = -1; | |
| 9 | |
| 10 /* CRC32 hash function */ | |
| 11 uint32_t crc32b(unsigned char* restrict message) { | |
| 12 int32_t i, j; | |
| 13 uint32_t byte, crc, mask; | |
| 14 | |
| 15 crc = 0xFFFFFFFF; | |
| 16 for (i = 0; message[i] != 0; i++) { | |
| 17 byte = message[i]; // Get next byte. | |
| 18 crc = crc ^ byte; | |
| 19 for (j = 7; j >= 0; j--) { // Do eight times. | |
| 20 mask = -(crc & 1); | |
| 21 crc = (crc >> 1) ^ (0xEDB88320 & mask); | |
| 22 } | |
| 23 } | |
| 24 return ~crc; | |
| 25 } | |
| 26 | |
| 27 /* This parses the first line of the EDL and | |
| 28 creates an array with CRC32 hashes in | |
| 29 the order of the strings. */ | |
| 30 uint32_t* parse_first_line(char* first_line) { | |
| 31 uint32_t* hashes = calloc(32, sizeof(uint32_t)); | |
| 32 int i = 0; | |
| 33 char* token; | |
| 34 hashes[i++] = crc32b(strtok_r(first_line, ";", &token)); | |
| 35 for (;;i++) { | |
| 36 char* token = strtok_r(NULL, ";", &token); | |
| 37 if (token == NULL) | |
| 38 break; | |
| 39 hashes[i] = crc32b(token); | |
| 40 } | |
| 41 strings_amt = i; | |
| 42 free(first_line); | |
| 43 return hashes; | |
| 44 } | |
| 45 | |
| 46 /* -- Functions to extract different datatypes -- */ | |
| 47 | |
| 48 char* get_int(char* input, int* int_return) { | |
| 49 char* ptr_return; | |
| 50 *int_return = strtol(input, &ptr_return, 10); | |
| 51 return ptr_return + 2; | |
| 52 } | |
| 53 | |
| 54 char* get_double(char* input, double* double_return) { | |
| 55 char* ptr_return; | |
| 56 *double_return = strtod(input, &ptr_return); | |
| 57 return ptr_return + 2; | |
| 58 } | |
| 59 | |
| 60 char* get_bool(char* input, bool* bool_return) { | |
| 61 switch (input[0]) { | |
| 62 case 'T': | |
| 63 *bool_return = true; | |
| 64 return input + 6; | |
| 65 case 'F': | |
| 66 *bool_return = false; | |
| 67 return input + 7; | |
| 68 default: | |
| 69 /* what */ | |
| 70 return NULL; | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 char* get_media_type(char* input, MediaType* media_return) { | |
| 75 switch (input[0]) { | |
| 76 case 'V': | |
| 77 *media_return = video; | |
| 78 return input + 7; | |
| 79 case 'A': | |
| 80 *media_return = audio; | |
| 81 return input + 7; | |
| 82 default: | |
| 83 /* what */ | |
| 84 return NULL; | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 /* lenptr is optional */ | |
| 89 char* cut_string_at_match(char* input, char* match, int* lenptr) { | |
| 90 int length = strcspn(&input[1], match); | |
| 91 char* string = calloc(length+1, sizeof(char)); | |
| 92 memcpy(string, &input[1], length); | |
| 93 string[length] = '\0'; | |
| 94 if (lenptr != NULL) | |
| 95 *lenptr = length; | |
| 96 return string; | |
| 97 } | |
| 98 | |
| 99 char* get_string(char* input, char** string_return) { | |
| 100 /* Windows filenames will *NEVER* include double quotes. | |
| 101 This might break with EDL files created with Reaper on Linux. */ | |
| 102 int length; | |
| 103 char* string = cut_string_at_match(input, "\"", &length); | |
| 104 *string_return = string; | |
| 105 return input + length + 4; | |
| 106 } | |
| 107 | |
| 108 /* The memory manager for EDL_file. */ | |
| 109 void allocate_memory(EDL_file* input) { | |
| 110 if (input->size == 0) input->size = 16; | |
| 111 input->edl = realloc(input->edl, (input->size*2) * sizeof(EDL_line)); | |
| 112 input->size *= 2; | |
| 113 } | |
| 114 | |
| 115 /* This is the important function */ | |
| 116 EDL_file* parse_EDL(char* text) { | |
| 117 EDL_file edl; | |
| 118 memset(&edl, '\0', sizeof(edl)); | |
| 119 allocate_memory(&edl); | |
| 120 uint32_t* order = parse_first_line(strtok_r(text, "\n", NULL)); | |
| 121 char* line = strtok(text, "\n"); | |
| 122 while ((line = strtok(NULL, "\n")) != NULL) { | |
| 123 char* tmp_ptr = line; | |
| 124 for (int i = 0; i < strings_amt; i++) { | |
| 125 switch (order[i]) { | |
| 126 case 0x1541c503: /* ID */ | |
| 127 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].id); | |
| 128 break; | |
| 129 case 0x4b211812: /* Track */ | |
| 130 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].track); | |
| 131 break; | |
| 132 case 0xbb46516f: /* StartTime */ | |
| 133 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].start_time); | |
| 134 break; | |
| 135 case 0xaeac5df7: /* Length */ | |
| 136 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].length); | |
| 137 break; | |
| 138 case 0x03834606: /* PlayRate */ | |
| 139 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].play_rate); | |
| 140 break; | |
| 141 case 0x0c2083d3: /* Locked */ | |
| 142 tmp_ptr = get_bool(tmp_ptr, &edl.edl[edl.current].locked); | |
| 143 break; | |
| 144 case 0xe60c8b1d: /* Normalized */ | |
| 145 tmp_ptr = get_bool(tmp_ptr, &edl.edl[edl.current].normalized); | |
| 146 break; | |
| 147 case 0xbe5802c9: /* StretchMethod */ | |
| 148 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].stretch_method); | |
| 149 break; | |
| 150 case 0x4ec8be4c: /* Looped */ | |
| 151 tmp_ptr = get_bool(tmp_ptr, &edl.edl[edl.current].looped); | |
| 152 break; | |
| 153 case 0xe6cb84d1: /* OnRuler */ | |
| 154 tmp_ptr = get_bool(tmp_ptr, &edl.edl[edl.current].on_ruler); | |
| 155 break; | |
| 156 case 0x035f84c2: /* MediaType */ | |
| 157 tmp_ptr = get_media_type(tmp_ptr, &edl.edl[edl.current].media_type); | |
| 158 break; | |
| 159 case 0x379d32c5: /* FileName */ | |
| 160 tmp_ptr = get_string(tmp_ptr, &edl.edl[edl.current].file_name); | |
| 161 break; | |
| 162 case 0x9f334738: /* Stream */ | |
| 163 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].stream); | |
| 164 break; | |
| 165 case 0x07b4e0e7: /* StreamStart */ | |
| 166 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].stream_start); | |
| 167 break; | |
| 168 case 0x8f16c7b8: /* StreamLength */ | |
| 169 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].stream_length); | |
| 170 break; | |
| 171 case 0xd2edd7e4: /* FadeTimeIn */ | |
| 172 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].fade_time_in); | |
| 173 break; | |
| 174 case 0x792e8c40: /* FadeTimeOut */ | |
| 175 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].fade_time_out); | |
| 176 break; | |
| 177 case 0x98374657: /* SustainGain */ | |
| 178 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].sustain_gain); | |
| 179 break; | |
| 180 case 0x3e998b1f: /* CurveIn */ | |
| 181 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].curve_in); | |
| 182 break; | |
| 183 case 0x82fb09c4: /* GainIn */ | |
| 184 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].gain_in); | |
| 185 break; | |
| 186 case 0x53add388: /* CurveOut */ | |
| 187 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].curve_out); | |
| 188 break; | |
| 189 case 0x4210ba56: /* GainOut */ | |
| 190 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].gain_out); | |
| 191 break; | |
| 192 case 0x89c4df6c: /* Layer */ | |
| 193 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].layer); | |
| 194 break; | |
| 195 case 0xadf2f1a3: /* Color */ | |
| 196 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].color); | |
| 197 break; | |
| 198 case 0xa56b43e1: /* CurveInR */ | |
| 199 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].curve_in_r); | |
| 200 break; | |
| 201 case 0xcb6d715e: /* CurveOutR */ | |
| 202 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].curve_out_r); | |
| 203 break; | |
| 204 case 0x9da1b9ed: /* PlayPitch */ | |
| 205 tmp_ptr = get_double(tmp_ptr, &edl.edl[edl.current].play_pitch); | |
| 206 break; | |
| 207 case 0x2bda6ed4: /* LockPitch */ | |
| 208 tmp_ptr = get_bool(tmp_ptr, &edl.edl[edl.current].lock_pitch); | |
| 209 break; | |
| 210 case 0x3071a4c6: /* FirstChannel */ | |
| 211 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].first_channel); | |
| 212 break; | |
| 213 case 0x7de1bd40: /* Channels */ | |
| 214 tmp_ptr = get_int(tmp_ptr, &edl.edl[edl.current].channels); | |
| 215 break; | |
| 216 default: | |
| 217 /* ... what */ | |
| 218 break; | |
| 219 } | |
| 220 } | |
| 221 edl.current++; | |
| 222 if (edl.current >= edl.size) | |
| 223 allocate_memory(&edl); | |
| 224 } | |
| 225 } |
