SVG of thorsten's editor track/bus list icons
[ardour2.git] / tools / omf / loader.cc
blob0442377357209e9507b559b559f65541f654caed
1 /* Rewritten for Ardour by Paul Davis <paul@linuxaudiosystems.com>, Feb 2010
2 but based on ...
3 */
5 /* REAPER OMF plug-in
6 Copyright (C) 2009 Hannes Breul
8 Provides OMF import.
10 Based on the m3u example included in the Reaper SDK,
11 Copyright (C) 2005-2008 Cockos Incorporated
13 Original source available at:
14 http://www.reaper.fm/sdk/plugin/plugin.php#ext_dl
16 This software is provided 'as-is', without any express or implied
17 warranty. In no event will the authors be held liable for any damages
18 arising from the use of this software.
20 Permission is granted to anyone to use this software for any purpose,
21 including commercial applications, and to alter it and redistribute it
22 freely, subject to the following restrictions:
24 1. The origin of this software must not be misrepresented; you must not
25 claim that you wrote the original software. If you use this software
26 in a product, an acknowledgment in the product documentation would be
27 appreciated but is not required.
28 2. Altered source versions must be plainly marked as such, and must not be
29 misrepresented as being the original software.
30 3. This notice may not be removed or altered from any source distribution.
33 #ifndef __STDC_FORMAT_MACROS
34 #define __STDC_FORMAT_MACROS /* PRI<foo>; C++ requires explicit requesting of these */
35 #endif
37 #include <iostream>
39 #include <getopt.h>
40 #include <stdio.h>
41 #include <math.h>
42 #include <stdlib.h>
43 #include <stdarg.h>
44 #include <string.h>
45 #include <time.h>
46 #include <inttypes.h>
47 #include <sys/errno.h>
48 #include <sndfile.h>
49 #include <glibmm.h>
51 #include "pbd/xml++.h"
52 #include "pbd/basename.h"
53 #include "omftool.h"
55 using namespace std;
56 using namespace PBD;
58 //#define DEBUG(fmt,...) fprintf (stderr, fmt, ## __VA_ARGS__)
59 #define DEBUG(fmt,...)
60 #define INFO(fmt,...) fprintf (stdout, fmt, ## __VA_ARGS__)
62 #define MB_OK 0
63 void
64 MessageBox (FILE* /*ignored*/, const char* msg, const char* title, int status)
66 fprintf (stderr, msg);
69 void
70 OMF::name_types ()
72 /* Add built-in types */
73 sqlite3_exec(db, "INSERT INTO lookup VALUES (1, 'TOC property 1')", 0, 0, 0);
74 sqlite3_exec(db, "INSERT INTO lookup VALUES (2, 'TOC property 2')", 0, 0, 0);
75 sqlite3_exec(db, "INSERT INTO lookup VALUES (3, 'TOC property 3')", 0, 0, 0);
76 sqlite3_exec(db, "INSERT INTO lookup VALUES (4, 'TOC property 4')", 0, 0, 0);
77 sqlite3_exec(db, "INSERT INTO lookup VALUES (5, 'TOC property 5')", 0, 0, 0);
78 sqlite3_exec(db, "INSERT INTO lookup VALUES (6, 'TOC property 6')", 0, 0, 0);
79 sqlite3_exec(db, "INSERT INTO lookup VALUES (7, '(Type 7)')", 0, 0, 0);
80 sqlite3_exec(db, "INSERT INTO lookup VALUES (8, '(Type 8)')", 0, 0, 0);
81 sqlite3_exec(db, "INSERT INTO lookup VALUES (9, '(Type 9)')", 0, 0, 0);
82 sqlite3_exec(db, "INSERT INTO lookup VALUES (10, '(Type 10)')", 0, 0, 0);
83 sqlite3_exec(db, "INSERT INTO lookup VALUES (11, '(Type 11)')", 0, 0, 0);
84 sqlite3_exec(db, "INSERT INTO lookup VALUES (12, '(Type 12)')", 0, 0, 0);
85 sqlite3_exec(db, "INSERT INTO lookup VALUES (13, '(Type 13)')", 0, 0, 0);
86 sqlite3_exec(db, "INSERT INTO lookup VALUES (14, '(Type 14)')", 0, 0, 0);
87 sqlite3_exec(db, "INSERT INTO lookup VALUES (15, '(Type 15)')", 0, 0, 0);
88 sqlite3_exec(db, "INSERT INTO lookup VALUES (16, '(Type 16)')", 0, 0, 0);
89 sqlite3_exec(db, "INSERT INTO lookup VALUES (17, '(Type 17)')", 0, 0, 0);
90 sqlite3_exec(db, "INSERT INTO lookup VALUES (18, '(Type 18)')", 0, 0, 0);
91 sqlite3_exec(db, "INSERT INTO lookup VALUES (19, 'TOC Value')", 0, 0, 0);
92 sqlite3_exec(db, "INSERT INTO lookup VALUES (20, '(Type 20)')", 0, 0, 0);
93 sqlite3_exec(db, "INSERT INTO lookup VALUES (21, 'String')", 0, 0, 0);
94 sqlite3_exec(db, "INSERT INTO lookup VALUES (22, '(Type 22)')", 0, 0, 0);
95 sqlite3_exec(db, "INSERT INTO lookup VALUES (23, 'Type Name')", 0, 0, 0);
96 sqlite3_exec(db, "INSERT INTO lookup VALUES (24, 'Property Name')", 0, 0, 0);
97 sqlite3_exec(db, "INSERT INTO lookup VALUES (25, '(Type 25)')", 0, 0, 0);
98 sqlite3_exec(db, "INSERT INTO lookup VALUES (26, '(Type 26)')", 0, 0, 0);
99 sqlite3_exec(db, "INSERT INTO lookup VALUES (27, '(Type 27)')", 0, 0, 0);
100 sqlite3_exec(db, "INSERT INTO lookup VALUES (28, '(Type 28)')", 0, 0, 0);
101 sqlite3_exec(db, "INSERT INTO lookup VALUES (29, '(Type 29)')", 0, 0, 0);
102 sqlite3_exec(db, "INSERT INTO lookup VALUES (30, '(Type 30)')", 0, 0, 0);
103 sqlite3_exec(db, "INSERT INTO lookup VALUES (31, 'Referenced Object')", 0, 0, 0);
104 sqlite3_exec(db, "INSERT INTO lookup VALUES (32, 'Object')", 0, 0, 0);
105 sqlite3_exec(db, "INSERT INTO lookup VALUES (33, '(Type 33)')", 0, 0, 0);
106 sqlite3_exec(db, "INSERT INTO lookup VALUES (34, '(Type 34)')", 0, 0, 0);
107 sqlite3_exec(db, "INSERT INTO lookup VALUES (35, '(Type 35)')", 0, 0, 0);
108 sqlite3_exec(db, "INSERT INTO lookup VALUES (36, '(Type 36)')", 0, 0, 0);
109 sqlite3_exec(db, "INSERT INTO lookup VALUES (37, '(Type 37)')", 0, 0, 0);
110 sqlite3_exec(db, "INSERT INTO lookup VALUES (38, '(Type 38)')", 0, 0, 0);
111 sqlite3_exec(db, "INSERT INTO lookup VALUES (39, '(Type 39)')", 0, 0, 0);
112 sqlite3_exec(db, "INSERT INTO lookup VALUES (40, '(Type 40)')", 0, 0, 0);
113 sqlite3_exec(db, "INSERT INTO lookup VALUES (41, '(Type 41)')", 0, 0, 0);
114 sqlite3_exec(db, "INSERT INTO lookup VALUES (42, '(Type 42)')", 0, 0, 0);
116 /* Assign type and property values to names */
117 sqlite3_exec(db, "UPDATE data SET property = (SELECT name FROM lookup WHERE property = key), type = (SELECT name FROM lookup WHERE type = key)", 0, 0, 0);
118 sqlite3_exec(db, "DROP TABLE lookup", 0, 0, 0);
121 int
122 OMF::load (const string& path)
124 if ((file = fopen(path.c_str(), "rb")) == 0) {
125 MessageBox(NULL, "Cannot open file","OMF Error", MB_OK);
126 return -1;
129 /* --------------- */
130 char *fname = (char*) malloc (path.size()+5);
132 strcpy(fname, path.c_str());
133 strcat(fname, ".db3");
134 //remove(fname);
135 if(sqlite3_open(":memory:", &db)) {
136 char error[512];
137 sprintf(error, "Can't open database: %s", sqlite3_errmsg(db));
138 MessageBox(NULL, error,"OMF Error", MB_OK);
139 sqlite3_close(db);
140 return -3;
142 sqlite3_exec(db, "BEGIN", 0, 0, 0);
143 sqlite3_exec(db, "CREATE TABLE data (object, property, type, value, offset, length)", 0, 0, 0);
144 sqlite3_exec(db, "CREATE TABLE lookup (key, name)", 0, 0, 0);
146 uint8_t magic[8];
147 fseek(file, -24, SEEK_END);
148 fread(magic, 8, 1, file);
149 if ((magic[0] != 0xa4) | (magic[1] != 0x43) | (magic[2] != 0x4d) | (magic[3] != 0xa5) | (magic[4] != 0x48) | (magic[5] != 0x64) | (magic[6] != 0x72) | (magic[7] != 0xd7)) {
150 MessageBox(NULL, "No valid OMF file.","OMF Error", MB_OK);
151 return -4;
154 uint16_t bSize, version;
155 fseek(file, -12, SEEK_END);
156 fread(&version, 2, 1, file);
157 bigEndian = false;
158 if ((version == 1) | (version == 256)) {
159 MessageBox(NULL, "You tried to open an OMF1 file.\nOMF1 is not supported.","OMF Error", MB_OK);
160 return -2;
161 } else if (version == 512) {
162 bigEndian = true;
163 } else if (version != 2) {
164 MessageBox(NULL, "You tried to open a corrupted file.","OMF Error", MB_OK);
165 return -2;
168 uint32_t tocStart, tocSize;
169 fseek(file, -14, SEEK_END);
170 fread(&bSize, 2, 1, file);
171 bSize = e16(bSize);
173 fseek(file, -8, SEEK_END);
174 fread(&tocStart, 4, 1, file);
175 tocStart = e32(tocStart);
177 fseek(file, -4, SEEK_END);
178 fread(&tocSize, 4, 1, file);
179 tocSize = e32(tocSize);
180 DEBUG ("block size: %d\n toc start: %d\n toc size: %d\n", bSize, tocStart, tocSize);
183 /* Calculate number of TOC blocks */
184 uint32_t tocBlocks = tocSize / (bSize * 1024) + 1;
185 DEBUG ("toc blocks: %d\n", tocBlocks);
186 /* ------------------------------ */
188 time_t globalstart, starttime, endtime;
189 time(&globalstart);
190 starttime = globalstart;
191 INFO ("Parsing TOC... ");
193 /* Go through TOC blocks */
194 uint32_t j;
195 uint32_t currentObj = 0;
196 uint32_t currentProp = 0;
197 uint32_t currentType = 0;
198 char skip = 0;
199 //uint64_t len = 0;
200 for (j = 0; j < tocBlocks; j++) {
201 uint32_t currentBlock = tocStart + j * 1024 * bSize; // Start at beginning of current block
202 uint32_t currentPos;
203 for (currentPos = currentBlock; currentPos < currentBlock + 1024 * bSize; currentPos++) {
204 if (currentPos > tocStart + tocSize) break; // Exit at end of TOC
205 char cByte; // TOC control byte
206 fseek(file, currentPos, SEEK_SET);
207 fread(&cByte, 1, 1, file);
209 /* New object */
210 if (cByte == 1) {
211 fseek(file, currentPos + 1, SEEK_SET);
212 fread(&currentObj, 4, 1, file);
213 currentObj = e32(currentObj);
214 fseek(file, currentPos + 5, SEEK_SET);
215 fread(&currentProp, 4, 1, file);
216 currentProp = e32(currentProp);
217 fseek(file, currentPos + 9, SEEK_SET);
218 fread(&currentType, 4, 1, file);
219 currentType = e32(currentType);
220 DEBUG("---------------------\n");
221 DEBUG(" object: 0x%x\n", currentObj);
222 DEBUG(" property: 0x%x\n", currentProp);
223 DEBUG(" type: 0x%x\n", currentType);
224 skip = 0;
225 currentPos += 12; // Skip the bytes that were just read
227 /* ---------- */
230 /* New property */
231 else if (cByte == 2) {
232 fseek(file, currentPos + 1, SEEK_SET);
233 fread(&currentProp, 4, 1, file);
234 currentProp = e32(currentProp);
235 fseek(file, currentPos + 5, SEEK_SET);
236 fread(&currentType, 4, 1, file);
237 currentType = e32(currentType);
238 DEBUG(" property: 0x%x\n", currentProp);
239 DEBUG(" type: 0x%x\n", currentType);
240 skip = 0;
241 currentPos += 8;
243 /* ------------ */
246 /* New type */
247 else if (cByte == 3) {
248 fseek(file, currentPos + 1, SEEK_SET);
249 fread(&currentType, 4, 1, file);
250 currentType = e32(currentType);
251 DEBUG(" type: 0x%x\n", currentType);
252 skip = 0;
253 currentPos += 4;
255 /* -------- */
258 /* (unused) */
259 else if (cByte == 4) {
260 currentPos += 4;
262 /* -------- */
265 /* Reference to a value - 4/8 byte offset, 4/8 byte size */
266 else if ((cByte == 5) | (cByte == 6) | (cByte == 7) | (cByte == 8)) {
267 if (!skip) {
268 uint32_t offset32 = 0;
269 uint32_t length32 = 0;
270 uint64_t dataOffset = 0;
271 uint64_t dataLength = 0;
272 if ((cByte == 5) | (cByte == 6)) {
273 fseek(file, currentPos + 1, SEEK_SET);
274 fread(&offset32, 4, 1, file);
275 fseek(file, currentPos + 5, SEEK_SET);
276 fread(&length32, 4, 1, file);
277 dataOffset = e32(offset32);
278 dataLength = e32(length32);
279 } else {
280 fseek(file, currentPos + 1, SEEK_SET);
281 fread(&dataOffset, 8, 1, file);
282 dataOffset = e64(dataOffset);
283 fseek(file, currentPos + 9, SEEK_SET);
284 fread(&dataLength, 8, 1, file);
285 dataLength = e64(dataLength);
287 DEBUG(" offset: %d\n", dataOffset);
288 DEBUG(" length: %d\n", dataLength);
290 if (currentType == 21) {
291 char* string = (char*) malloc((uint32_t) dataLength);
292 fseek(file, dataOffset, SEEK_SET);
293 fread(string, dataLength, 1, file);
294 char* query = sqlite3_mprintf("INSERT INTO lookup VALUES(%d, '%s')",currentObj, string);
295 sqlite3_exec(db, query, 0, 0, 0);
296 sqlite3_free(query);
297 } else if (currentType == 32){
298 uint32_t object = 0;
299 fseek(file, dataOffset, SEEK_SET);
300 fread(&object, 4, 1, file);
301 object = e32(object);
302 char* query = sqlite3_mprintf("INSERT INTO data VALUES(%d, %d, %d, %d, -1, -1)",currentObj, currentProp, currentType, object);
303 sqlite3_exec(db, query, 0, 0, 0);
304 sqlite3_free(query);
305 if (dataLength == 16) {
306 DEBUG(" offset: %lld\n", dataOffset + 8);
307 DEBUG(" length: %lld\n", dataLength);
308 fseek(file, dataOffset + 8, SEEK_SET);
309 fread(&object, 4, 1, file);
310 object = e32(object);
311 char* query2 = sqlite3_mprintf("INSERT INTO data VALUES(%d, %d, %d, %d, -1, -1)",currentObj, currentProp, currentType, object);
312 sqlite3_exec(db, query2, 0, 0, 0);
313 sqlite3_free(query2);
315 } else {
316 char* query = sqlite3_mprintf("INSERT INTO data VALUES(%d, %d, %d, '', %lld, %lld)",currentObj, currentProp, currentType, dataOffset, dataLength);
317 sqlite3_exec(db, query, 0, 0, 0);
318 sqlite3_free(query);
321 if ((cByte == 5) | (cByte == 6)) {
322 currentPos += 8;
323 } else {
324 currentPos += 16;
327 /* ----------------------------------------------------- */
330 /* Zero byte value */
331 else if (cByte == 9) {
332 if (!skip) {
333 char* query = sqlite3_mprintf("INSERT INTO data VALUES(%d, %d, %d, 'true', -1, -1)",currentObj, currentProp, currentType);
334 sqlite3_exec(db, query, 0, 0, 0);
335 sqlite3_free(query);
336 DEBUG(" value: true\n");
339 /* --------------- */
342 /* Immediate value */
343 else if ((cByte == 10) | (cByte == 11) | (cByte == 12) | (cByte == 13) | (cByte == 14)) {
344 if (!skip) {
345 uint32_t data = 0;
346 fseek(file, currentPos + 1, SEEK_SET);
347 fread(&data, 4, 1, file);
348 data = e32(data);
349 char* query = sqlite3_mprintf("INSERT INTO data VALUES(%d, %d, %d, %d, -1, -1)",currentObj, currentProp, currentType, data);
350 sqlite3_exec(db, query, 0, 0, 0);
351 sqlite3_free(query);
352 DEBUG(" value: %d\n", data);
355 currentPos += 4;
357 /* --------------- */
360 /* Reference list */
361 else if (cByte == 15) {
362 uint32_t data = 0;
363 fseek(file, currentPos + 1, SEEK_SET);
364 fread(&data, 4, 1, file);
365 data = e32(data);
366 char* query = sqlite3_mprintf("INSERT INTO data VALUES(%d, %d, %d, %d, -1, -1)",currentObj, currentProp, currentType, data);
367 sqlite3_exec(db, query, 0, 0, 0);
368 sqlite3_free(query);
369 DEBUG("reference: 0x%x\n", data);
370 skip = 1;
371 currentPos += 4;
373 /* -------------- */
374 else {
375 break;
380 /* --------------------- */
381 time(&endtime);
382 INFO("done. (%ld seconds)\n", endtime - starttime);
383 starttime = endtime;
385 INFO("Assigning type and property names... ");
386 name_types ();
387 time(&endtime);
388 INFO("done. (%ld seconds)\n", endtime - starttime);
389 starttime = endtime;
391 bool isAvid = false;
393 /* resolve ObjRefArrays */
394 char **arrays;
395 int arrayCount;
396 int l;
397 INFO("Resolving ObjRefArrays ");
398 sqlite3_get_table(db, "SELECT * FROM data WHERE type LIKE 'omfi:ObjRefArray' AND value = ''", &arrays, &arrayCount, 0, 0);
399 INFO("(%d to be processed)... ", arrayCount);
400 sqlite3_exec(db,"DELETE FROM data WHERE type LIKE 'omfi:ObjRefArray' AND value = ''",0,0,0);
401 for (l = 6; l <= arrayCount * 6; l+=6) {
402 uint16_t counter;
403 uint32_t arrOffs = atoi(arrays[l+4]);
404 uint32_t arrLen = atoi(arrays[l+5]);
405 fseek(file, arrOffs, SEEK_SET);
406 fread(&counter, 2, 1, file);
407 counter = e16(counter);
408 if (arrLen = 4 * counter + 2) {
409 isAvid = true;
410 currentObj++;
411 DEBUG("currentObj: %d - references:", currentObj);
412 for (counter = 2; counter < arrLen; counter += 4) {
413 uint32_t temp;
414 fseek(file, arrOffs + counter, SEEK_SET);
415 fread(&temp, 4, 1, file);
416 temp = e32(temp);
417 DEBUG(" %d", temp);
418 sqlite3_exec(db, sqlite3_mprintf("INSERT INTO data VALUES (%d, 'Referenced Object', 'Object', %d, -1, -1)", currentObj, temp), 0, 0, 0);
420 DEBUG("\nData: %s | %s | %s | %d | -1 | -1\n", arrays[l], arrays[l+1], arrays[l+2], currentObj);
421 sqlite3_exec(db, sqlite3_mprintf("INSERT INTO data VALUES (%s, '%s', '%s', %d, -1, -1)", arrays[l], arrays[l+1], arrays[l+2], currentObj), 0, 0, 0);
424 sqlite3_free_table(arrays);
425 time(&endtime);
426 INFO("done. (%ld seconds)\n", endtime - starttime);
427 starttime = endtime;
428 /* -------------------- */
431 //return -1;
432 /*char **refs;
433 int refCount;
434 int currentRef;
435 printf("Resolving ObjRefs...\n");
436 sqlite3_get_table(db,"SELECT object, property, value FROM data WHERE type = 'omfi:ObjRef'", &refs, &refCount, 0, 0);
437 printf("temporary table created\n");
438 for (currentRef = 3; currentRef <= refCount * 3; currentRef += 3) {
439 DEBUG("%d / %d\n", currentRef/3, refCount);
440 char **target;
441 int targetCount;
442 sqlite3_get_table(db, sqlite3_mprintf("SELECT value FROM data WHERE object = %s AND type = 'Object' LIMIT 1", refs[currentRef+2]), &target, &targetCount, 0, 0);
443 DEBUG("temporary table filled\n");
444 if (targetCount > 0) {
445 //sqlite3_exec(db,sqlite3_mprintf("DELETE FROM data WHERE object = %s", refs[currentRef+2]),0,0,0);
446 DEBUG("unused reference deleted\n");
447 sqlite3_exec(db,sqlite3_mprintf("UPDATE data SET value = %s WHERE object LIKE '%s' AND property LIKE '%s' LIMIT 1", target[1], refs[currentRef], refs[currentRef+1]),0,0,0);
448 printf("temporary data inserted\n");
450 sqlite3_free_table(target);
452 sqlite3_free_table(refs);
453 printf("temporary table deleted\n"); */
455 if (!isAvid) {
456 INFO("Resolving ObjRefs ");
457 sqlite3_exec(db,"CREATE TABLE reference (object1, property1, value1)",0,0,0);
458 sqlite3_exec(db,"INSERT INTO reference SELECT object, property, value FROM data WHERE type LIKE 'omfi:ObjRef'",0,0,0);
459 sqlite3_exec(db,"CREATE TABLE objects (object2, value2)",0,0,0);
460 sqlite3_exec(db,"INSERT INTO objects SELECT object, value FROM data WHERE type LIKE 'Object'",0,0,0);
461 sqlite3_exec(db,"UPDATE reference SET value1 = (SELECT value2 FROM objects WHERE object2 = value1)",0,0,0);
462 //sqlite3_exec(db,"UPDATE data SET value = (SELECT value1 FROM references WHERE object1 = object) WHERE ",0,0,0);
463 char **refs;
464 int refCount;
465 int currentRef;
467 sqlite3_get_table(db,"SELECT * FROM reference", &refs, &refCount, 0, 0);
468 INFO ("(%d to be processed)... ", refCount);
469 for (currentRef = 3; currentRef <= refCount * 3; currentRef += 3) {
470 DEBUG("%d / %d: object %s, property %s, value %s\n", currentRef/3, refCount, refs[currentRef], refs[currentRef+1], refs[currentRef+2]);
471 sqlite3_exec(db,sqlite3_mprintf("DELETE FROM data WHERE object = %s AND property = '%s'", refs[currentRef], refs[currentRef+1]),0,0,0);
472 sqlite3_exec(db,sqlite3_mprintf("INSERT INTO data VALUES (%s, '%s', 'omfi:ObjRef', %s, -1, -1)", refs[currentRef], refs[currentRef+1], refs[currentRef+2]),0,0,0);
474 sqlite3_free_table(refs);
476 DEBUG("temporary table deleted\n");
478 /*sqlite3_get_table(db,"SELECT object, property, value FROM data WHERE type LIKE 'omfi:ObjRef'", &refs, &refCount, 0, 0);
479 printf("%d\n", refCount);
480 for (currentRef = 3; currentRef <= refCount * 3; currentRef += 3) {
481 printf("%d / %d: object %s, property %s, value %s\n", currentRef/3, refCount, refs[currentRef], refs[currentRef+1], refs[currentRef+2]);
483 sqlite3_free_table(refs);
487 /* resolve ObjRefs *
488 printf("Resolving ObjRefs...\n");
489 sqlite3_exec(db,"CREATE TABLE temp (object, property, type, value, offset, length)",0,0,0);
490 printf("temporary table created\n");
491 sqlite3_exec(db,"INSERT INTO temp SELECT d1.object, d1.property, d1.type, d2.value, d1.offset, d1.length FROM data d1, data d2 WHERE d1.type = 'omfi:ObjRef' AND d1.value = d2.object AND d2.type = 'Object'",0,0,0);
492 printf("temporary table filled\n");
493 //sqlite3_exec(db,"DELETE FROM data WHERE object IN (SELECT value FROM data WHERE type LIKE 'omfi:ObjRef')",0,0,0);
494 sqlite3_exec(db,"DELETE FROM data WHERE object IN (SELECT object FROM temp) AND type = 'omfi:ObjRef'",0,0,0);
495 printf("unused referenced deleted\n");
496 sqlite3_exec(db,"INSERT INTO data SELECT * FROM temp",0,0,0);
497 printf("temporary data inserted\n");
498 sqlite3_exec(db,"DROP TABLE temp",0,0,0);
499 printf("temporary table deleted\n");
500 * --------------- */
502 time(&endtime);
503 INFO("done. (%ld seconds)\n", endtime - starttime);
504 starttime = endtime;
506 //return -1;
507 /* resolve UIDs */
508 INFO("Resolving UIDs... ");
509 char **mobID;
510 int mobIDCount;
511 int currentID;
512 sqlite3_get_table(db,"SELECT object, property, offset FROM data WHERE type LIKE 'omfi:UID'", &mobID, &mobIDCount, 0, 0);
513 sqlite3_exec(db,"DELETE FROM data WHERE type LIKE 'omfi:UID'",0,0,0);
514 for (currentID = 3; currentID <= mobIDCount * 3; currentID += 3) {
515 uint32_t mobIDoffs = atoi(mobID[currentID+2]);
516 //sscanf(mobID[currentID+2], "%d", &mobIDoffs);
517 int mobBuffer[3];
518 fseek(file, mobIDoffs, SEEK_SET);
519 fread(mobBuffer, 12, 1, file);
520 sqlite3_exec(db,sqlite3_mprintf("INSERT INTO data VALUES (%s, '%s', 'omfi:UID', '%d %d %d', -1, -1)", mobID[currentID], mobID[currentID + 1], mobBuffer[0], mobBuffer[1], mobBuffer[2]),0,0,0);
522 sqlite3_free_table(mobID);
523 /* ------------ */
525 time(&endtime);
526 INFO("done. (%ld seconds)\n", endtime - starttime);
527 starttime = endtime;
529 //return -1;
531 /* extract media data */
532 printf("Extracting media data...\n");
533 char **objects;
534 int objectsCount, k;
535 //sqlite3_exec(db,"CREATE TABLE names (UID, value)",0,0,0);
536 sqlite3_get_table(db, "SELECT object, offset, length FROM data WHERE object IN (SELECT value FROM data WHERE object IN (SELECT value FROM data WHERE property = 'OMFI:HEAD:MediaData' LIMIT 1)) AND type = 'omfi:DataValue'", &objects, &objectsCount, 0, 0);
537 for (k = 3; k <= objectsCount * 3; k += 3) {
538 char **fileName;
539 int fileNameCount;
540 FILE *fd;
541 std::string full_path;
542 sqlite3_get_table(db, sqlite3_mprintf("SELECT offset, length FROM data WHERE object IN (SELECT object FROM data WHERE value IN (SELECT value FROM data WHERE object = %s AND property = 'OMFI:MDAT:MobID' LIMIT 1) AND property = 'OMFI:MOBJ:MobID' LIMIT 1) AND property = 'OMFI:MOBJ:Name' LIMIT 1", objects[k]), &fileName, &fileNameCount, 0, 0);
543 if (fileNameCount > 0) {
544 uint32_t fnOffs = atoi(fileName[2]);
545 uint32_t fnLen = atoi(fileName[3]);
546 if (get_offset_and_length (fileName[2], fileName[3], fnOffs, fnLen)) {
547 char *fnBuf = (char*) malloc(fnLen+1);
548 fseek(file, fnOffs, SEEK_SET);
549 fread(fnBuf, fnLen, 1, file);
550 fnBuf[fnLen] = '\0';
552 audiofile_path_vector.push_back (fnBuf);
553 full_path = Glib::build_filename (audiofile_path_vector);
554 audiofile_path_vector.pop_back ();
556 fd = fopen(full_path.c_str(), "wb");
558 } else {
559 INFO ("Skip unnamed media file\n");
560 continue;
562 } else {
563 audiofile_path_vector.push_back (objects[k]);
564 full_path = Glib::build_filename (audiofile_path_vector);
565 audiofile_path_vector.pop_back ();
566 fd = fopen(full_path.c_str(), "wb");
567 INFO ("Direct file name used (%s)\n", full_path.c_str());
570 if(fd == NULL){
571 char error[255];
572 sprintf(error, "Can't create file [%s] (object %s)", full_path.c_str(), objects[k]);
573 MessageBox(NULL,error,"OMF Error", MB_OK);
574 sqlite3_exec(db, "COMMIT", 0, 0, 0);
575 sqlite3_close(db);
576 return 1;
577 } else {
578 INFO("Writing file %s (object %s): ", full_path.c_str(), objects[k]);
580 uint32_t foffset;
581 uint32_t flength;
583 if (get_offset_and_length (objects[k+1], objects[k+2], foffset, flength)) {
584 int blockSize = 1024;
585 uint32_t currentBlock;
586 uint32_t written = 0;
587 char* buffer = (char*) malloc(blockSize);
588 fseek(file, foffset, SEEK_SET);
589 for (currentBlock = 0; currentBlock < flength / blockSize; currentBlock++) {
590 fread(buffer, blockSize, 1, file);
591 written += fwrite(buffer, 1, blockSize, fd);
593 fread(buffer, flength % blockSize, 1, file);
594 written += fwrite(buffer, 1, flength % blockSize, fd);
595 INFO("%d of %d bytes\n", written, flength);
596 fclose(fd);
598 get_audio_info (full_path);
600 sqlite3_free_table(fileName);
602 sqlite3_free_table(objects);
603 /* ------------------ */
605 time(&endtime);
606 INFO("done. (%ld seconds)\n", endtime - starttime);
607 starttime = endtime;
609 /* resolve ClassIDs */
610 printf("Resolving ClassIDs ");
611 char **classID;
612 int classIDCount;
613 int currentClsID;
614 sqlite3_get_table(db,"SELECT object, property, value FROM data WHERE type = 'omfi:ClassID'", &classID, &classIDCount, 0, 0);
615 sqlite3_exec(db,"DELETE FROM data WHERE type = 'omfi:ClassID'",0,0,0);
616 INFO("(%d to be processed)... ", classIDCount);
617 for (currentClsID = 3; currentClsID <= classIDCount * 3; currentClsID += 3) {
618 //int clsID = (int) malloc(5);
619 int clsID = atoi(classID[currentClsID+2]);
620 clsID = e32(clsID);
621 //sscanf(classID[currentClsID+2], "%d", &clsID);
622 char clsString[5];
623 strncpy(clsString, (char *) &clsID, 4);
624 clsString[4] = 0;
625 DEBUG("%d -> %s\n", clsID, clsString);
627 sqlite3_exec(db,sqlite3_mprintf("INSERT INTO data VALUES (%s, '%s', 'omfi:ClassID', '%s', -1, -1)", classID[currentClsID], classID[currentClsID + 1], clsString),0,0,0);
629 sqlite3_free_table(classID);
630 /* ---------------- */
632 sqlite3_exec(db, "COMMIT", 0, 0, 0);
634 time(&endtime);
635 INFO("done. (%ld seconds)\n", endtime - starttime);
636 starttime = endtime;
638 /*time(&endtime);
639 printf("Took %ld seconds\n", endtime - starttime);
640 starttime = endtime;*/
643 time(&endtime);
644 INFO("done. (%ld seconds)\n", endtime - starttime);
645 INFO("Overall time: %ld seconds\n", endtime - globalstart);
647 return 0;
648 /* -------- */