Fix windows builds, rename icons following 4e96285ba5
[ardour.git] / tools / omf / loader.cc
1 /*  Rewritten for Ardour by Paul Davis <paul@linuxaudiosystems.com>, Feb 2010
2     but based on ...
3  */
4
5 /*  REAPER OMF plug-in
6     Copyright (C) 2009 Hannes Breul
7
8     Provides OMF import.
9
10     Based on the m3u example included in the Reaper SDK,
11     Copyright (C) 2005-2008 Cockos Incorporated
12
13     Original source available at:
14     http://www.reaper.fm/sdk/plugin/plugin.php#ext_dl
15
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.
19
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:
23
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.
31 */
32
33 #ifndef __STDC_FORMAT_MACROS
34 #define __STDC_FORMAT_MACROS /* PRI<foo>; C++ requires explicit requesting of these */
35 #endif
36
37 #include <iostream>
38
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>
50
51 #include "pbd/xml++.h"
52 #include "pbd/basename.h"
53 #include "omftool.h"
54
55 using namespace std;
56 using namespace PBD;
57
58 //#define DEBUG(fmt,...) fprintf (stderr, fmt, ## __VA_ARGS__)
59 #define DEBUG(fmt,...)
60 #define INFO(fmt,...) fprintf (stdout, fmt, ## __VA_ARGS__)
61
62 #define MB_OK 0
63 void
64 MessageBox (FILE* /*ignored*/, const char* msg, const char* title, int status)
65 {
66         fprintf (stderr, msg);
67 }
68
69 void
70 OMF::name_types ()
71 {
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);
115
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);
119 }
120
121 int
122 OMF::load (const string& path)
123 {
124         if ((file = fopen(path.c_str(), "rb")) == 0) {
125                 MessageBox(NULL, "Cannot open file","OMF Error", MB_OK);
126                 return -1;
127         }
128
129         /* --------------- */
130         char *fname = (char*) malloc (path.size()+5);
131
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;
141         }
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);
145
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;
152         }
153
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;
166         }
167
168         uint32_t tocStart, tocSize;
169         fseek(file, -14, SEEK_END);
170         fread(&bSize, 2, 1, file);
171         bSize = e16(bSize);
172
173         fseek(file, -8, SEEK_END);
174         fread(&tocStart, 4, 1, file);
175         tocStart = e32(tocStart);
176
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);
181
182
183         /* Calculate number of TOC blocks */
184         uint32_t tocBlocks = tocSize / (bSize * 1024) + 1;
185         DEBUG ("toc blocks: %d\n", tocBlocks);
186         /* ------------------------------ */
187
188         time_t globalstart, starttime, endtime;
189         time(&globalstart);
190         starttime = globalstart;
191         INFO ("Parsing TOC... ");
192
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);
208
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
226                         }
227                         /* ---------- */
228
229
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;
242                         }
243                         /* ------------ */
244
245
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;
254                         }
255                         /* -------- */
256
257
258                         /* (unused) */
259                         else if (cByte == 4) {
260                                 currentPos += 4;
261                         }
262                         /* -------- */
263
264
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);
286                                         }
287                                         DEBUG("   offset: %d\n", dataOffset);
288                                         DEBUG("   length: %d\n", dataLength);
289
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);
314                                                 }
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);
319                                         }
320                                 }
321                                 if ((cByte == 5) | (cByte == 6)) {
322                                         currentPos += 8;
323                                 } else {
324                                         currentPos += 16;
325                                 }
326                         }
327                         /* ----------------------------------------------------- */
328
329
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");
337                                 }
338                         }
339                         /* --------------- */
340
341
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);
353
354                                 }
355                                 currentPos += 4;
356                         }
357                         /* --------------- */
358
359
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;
372                         }
373                         /* -------------- */
374                         else {
375                                 break;
376                         }
377
378                 }
379         }
380         /* --------------------- */
381         time(&endtime);
382         INFO("done. (%ld seconds)\n", endtime - starttime);
383         starttime = endtime;
384
385         INFO("Assigning type and property names... ");
386         name_types ();
387         time(&endtime);
388         INFO("done. (%ld seconds)\n", endtime - starttime);
389         starttime = endtime;
390
391         bool isAvid = false;
392
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);
419                         }
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);
422                 }
423         }
424         sqlite3_free_table(arrays);
425         time(&endtime);
426         INFO("done. (%ld seconds)\n", endtime - starttime);
427         starttime = endtime;
428         /* -------------------- */
429
430
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");
449           }
450           sqlite3_free_table(target);
451           }
452           sqlite3_free_table(refs);
453           printf("temporary table deleted\n"); */
454
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;
466
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);
473                 }
474                 sqlite3_free_table(refs);
475         }
476         DEBUG("temporary table deleted\n");
477
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]);
482           }
483           sqlite3_free_table(refs);
484           }*/
485
486
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            * --------------- */
501
502         time(&endtime);
503         INFO("done. (%ld seconds)\n", endtime - starttime);
504         starttime = endtime;
505
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);
521         }
522         sqlite3_free_table(mobID);
523         /* ------------ */
524
525         time(&endtime);
526         INFO("done. (%ld seconds)\n", endtime - starttime);
527         starttime = endtime;
528
529         //return -1;
530
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';
551
552                                 audiofile_path_vector.push_back (fnBuf);
553                                 full_path = Glib::build_filename (audiofile_path_vector);
554                                 audiofile_path_vector.pop_back ();
555
556                                 fd = fopen(full_path.c_str(), "wb");
557
558                         } else {
559                                 INFO ("Skip unnamed media file\n");
560                                 continue;
561                         }
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());
568                 }
569
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]);
579                 }
580                 uint32_t foffset;
581                 uint32_t flength;
582
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);
592                         }
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);
597
598                         get_audio_info (full_path);
599                 }
600                 sqlite3_free_table(fileName);
601         }
602         sqlite3_free_table(objects);
603         /* ------------------ */
604
605         time(&endtime);
606         INFO("done. (%ld seconds)\n", endtime - starttime);
607         starttime = endtime;
608
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);
626
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);
628         }
629         sqlite3_free_table(classID);
630         /* ---------------- */
631
632         sqlite3_exec(db, "COMMIT", 0, 0, 0);
633
634         time(&endtime);
635         INFO("done. (%ld seconds)\n", endtime - starttime);
636         starttime = endtime;
637
638         /*time(&endtime);
639           printf("Took %ld seconds\n", endtime - starttime);
640           starttime = endtime;*/
641
642
643         time(&endtime);
644         INFO("done. (%ld seconds)\n", endtime - starttime);
645         INFO("Overall time: %ld seconds\n", endtime - globalstart);
646
647         return 0;
648         /* -------- */
649 }