GUI support to re-locate missing external (abs-path) files
[ardour.git] / tools / omf / omftool.cc
index fca1071ae0ab95a48d8beff9842cc341400516be..68fc6bd83c653e87d7e46efb51c6f1e23263c5f7 100644 (file)
@@ -2,25 +2,25 @@
     but based on ...
  */
 
-/*  REAPER OMF plug-in 
+/*  REAPER OMF plug-in
     Copyright (C) 2009 Hannes Breul
 
     Provides OMF import.
-    
+
     Based on the m3u example included in the Reaper SDK,
     Copyright (C) 2005-2008 Cockos Incorporated
-    
+
     Original source available at:
     http://www.reaper.fm/sdk/plugin/plugin.php#ext_dl
-    
+
     This software is provided 'as-is', without any express or implied
     warranty.  In no event will the authors be held liable for any damages
     arising from the use of this software.
-    
+
     Permission is granted to anyone to use this software for any purpose,
     including commercial applications, and to alter it and redistribute it
     freely, subject to the following restrictions:
-    
+
     1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
@@ -53,7 +53,7 @@
 #include "omftool.h"
 
 //#define DEBUG(fmt,...) fprintf (stderr, fmt, ## __VA_ARGS__)
-#define DEBUG(fmt,...) 
+#define DEBUG(fmt,...)
 #define INFO(fmt,...) fprintf (stdout, fmt, ## __VA_ARGS__)
 
 using namespace std;
@@ -84,11 +84,11 @@ OMF::OMF ()
        options = new XMLNode ("RouteGroups");
 
        /* add master, default 2in/2out */
-       
+
        XMLNode* master = new_route_node ();
        master->add_property ("name", "master");
        set_route_node_channels (master, 2, 2, false);
-       
+
        XMLNode* tempo_map = new XMLNode ("TempoMap");
        XMLNode* tempo = new XMLNode ("Tempo");
        tempo->add_property ("start", "1|1|0");
@@ -125,7 +125,7 @@ OMF::OMF ()
        connection = new XMLNode ("Connection");
        connection->add_property ("other", "system:playback_2");
        port->add_child_nocopy (*connection);
-               
+
        session->add_child_nocopy (*options);
        session->add_child_nocopy (*sources);
        session->add_child_nocopy (*regions);
@@ -175,7 +175,7 @@ OMF::init ()
        audiofile_path_vector.push_back ("interchange");
        audiofile_path_vector.push_back (session_name);
        audiofile_path_vector.push_back ("audiofiles");
-       
+
        dir = Glib::build_filename (audiofile_path_vector);
        g_mkdir_with_parents (dir.c_str(), 0775);
 
@@ -223,7 +223,7 @@ OMF::get_audio_info (const std::string& path)
 
        XMLNode* source = new_source_node();
 
-       known_sources.insert (pair<string,SourceInfo*> 
+       known_sources.insert (pair<string,SourceInfo*>
                              (Glib::path_get_basename (path),
                               new SourceInfo (sf_info.channels,
                                               sf_info.samplerate,
@@ -253,7 +253,7 @@ OMF::new_playlist_node ()
        add_id (playlist);
        playlist->add_property ("type", "audio");
        playlist->add_property ("frozen", "no");
-       
+
        return playlist;
 }
 
@@ -266,7 +266,7 @@ OMF::new_diskstream_node ()
        diskstream->add_property ("flags", "Recordable");
        diskstream->add_property ("speed", "1");
        diskstream->add_property ("channels", "1");
-       
+
        return diskstream;
 }
 void
@@ -302,7 +302,7 @@ OMF::set_route_node_channels (XMLNode* route, int in, int out, bool send_to_mast
        XMLNode* output_io;
        char sbuf[256];
        string name = route->property ("name")->value();
-       
+
        legalize_name (name);
 
        output_io = new XMLNode ("IO");
@@ -311,7 +311,7 @@ OMF::set_route_node_channels (XMLNode* route, int in, int out, bool send_to_mast
        add_id (output_io);
        output_io->add_property ("direction", "Output");
        output_io->add_property ("default-type", "audio");
-       
+
        input_io = new XMLNode ("IO");
        route->add_child_nocopy (*input_io);
        input_io->add_property ("name", name);
@@ -323,9 +323,9 @@ OMF::set_route_node_channels (XMLNode* route, int in, int out, bool send_to_mast
                XMLNode* port = new XMLNode ("Port");
                output_io->add_child_nocopy (*port);
                port->add_property ("type", "audio");
-               
+
                snprintf (sbuf, sizeof (sbuf), "%s/audio_out %d", name.c_str(), i+1);
-               
+
                port->add_property ("name", sbuf);
                XMLNode* connection = new XMLNode ("Connection");
 
@@ -342,7 +342,7 @@ OMF::set_route_node_channels (XMLNode* route, int in, int out, bool send_to_mast
                                snprintf (sbuf, sizeof (sbuf), "system:playback_1");
                        }
                }
-                               
+
                connection->add_property ("other", sbuf);
                port->add_child_nocopy (*connection);
        }
@@ -351,9 +351,9 @@ OMF::set_route_node_channels (XMLNode* route, int in, int out, bool send_to_mast
                XMLNode* port = new XMLNode ("Port");
                input_io->add_child_nocopy (*port);
                port->add_property ("type", "audio");
-               
+
                snprintf (sbuf, sizeof (sbuf), "%s/audio_out %d", name.c_str(), i+1);
-               
+
                port->add_property ("name", sbuf);
                XMLNode* connection = new XMLNode ("Connection");
 
@@ -379,12 +379,12 @@ OMF::set_route_node_channels (XMLNode* route, int in, int out, bool send_to_mast
        outs->add_property ("output", name);
        outs->add_property ("type", "main-outs");
        outs->add_property ("role", "Main");
-       
+
        /* Panner setup */
 
        XMLNode* panner = new XMLNode ("Panner");
        outs->add_child_nocopy (*panner);
-       
+
        panner->add_property ("linked", "no");
        panner->add_property ("link-direction", "SameDirection");
        panner->add_property ("bypassed", "no");
@@ -403,7 +403,7 @@ OMF::set_route_node_channels (XMLNode* route, int in, int out, bool send_to_mast
                spanner->add_property ("type", "Equal Power Stereo");
                spanner->add_property ("muted", "no");
                spanner->add_property ("mono", "no");
-               
+
                XMLNode* spc = new XMLNode ("Controllable");
                spanner->add_child_nocopy (*spc);
                add_id (spc);
@@ -466,7 +466,7 @@ OMF::new_route_node ()
        route->add_child_nocopy (*extra);
        XMLNode* gui = new XMLNode ("GUI");
        extra->add_child_nocopy (*gui);
-       snprintf (sbuf, sizeof (sbuf), "%d:%d:%d", 
+       snprintf (sbuf, sizeof (sbuf), "%d:%d:%d",
                  random() % 65536,
                  random() % 65536,
                  random() % 65536);
@@ -488,9 +488,9 @@ OMF::new_region_node ()
 
        region_extra->add_child_nocopy (*gui_extra);
        region->add_child_nocopy (*region_extra);
-       
+
        /* boilerplate */
-       
+
        region->add_property ("ancestral-start", "0");
        region->add_property ("ancestral-start", "0");
        region->add_property ("ancestral-length", "0");
@@ -520,9 +520,9 @@ OMF::new_source_node ()
        add_id (source);
        source->add_property ("type", "audio");
        source->add_property ("flags", "CanRename");
-               
+
        sources->add_child_nocopy (*source);
-       
+
        return source;
 }
 
@@ -533,7 +533,7 @@ OMF::get_known_source (const char* name)
        KnownSources::iterator i = known_sources.find (s);
        if (i != known_sources.end()) {
                return i->second;
-       } 
+       }
        return 0;
 }
 
@@ -585,7 +585,7 @@ OMF::create_xml ()
        int major;
        int minor;
        int micro;
-       
+
        major = version / 1000;
        minor = version - (major * 1000);
        micro = version - (major * 1000) - (minor * 100);
@@ -674,6 +674,7 @@ OMF::create_xml ()
                        denom = e32(denom);
                        fread(&num, 4, 1, file);
                        num = e32(num);
+                       INFO ("Rate = %d / %d\n", num, denom);
                        if (frame_rate == 0) {
                                frame_rate = (double) num / (double) denom;
                        }
@@ -689,7 +690,7 @@ OMF::create_xml ()
                }
 
                sqlite3_free_table(rate);
-               
+
                char **items;
                int itemCount;
                //sqlite3_get_table(db, sqlite3_mprintf("SELECT d3.value FROM data d1, data d2, data d3 WHERE d1.object LIKE '%s' AND d1.property LIKE 'OMFI:MSLT:Segment' AND d2.object LIKE d1.value AND d2.property LIKE 'OMFI:SEQU:Components' AND d3.object LIKE d2.value", tracks[i]), &items, &itemCount, 0, 0);
@@ -706,7 +707,7 @@ OMF::create_xml ()
                        int lenCount;
                        double length = 0.0;
                        int lenFrames = 0;
-                       
+
                        region = 0;
 
                        sqlite3_get_table(db, sqlite3_mprintf("SELECT value FROM data WHERE object = %s AND property = 'OMFI:CPNT:Length' LIMIT 1", items[j]), &len, &lenCount, 0, 0);
@@ -729,7 +730,7 @@ OMF::create_xml ()
 
                        lenFrames = atoi(len[1]);
                        length = lenFrames * frame_rate;
-                       
+
                        if (!strcmp(type[1], "TRAN")) {
 
                                position -= length;
@@ -795,15 +796,15 @@ OMF::create_xml ()
                                if (sourceFileCount > 0) {
                                        uint32_t sfOffs;
                                        uint32_t sfLen;
-       
+
                                        if (get_offset_and_length (sourceFile[2], sourceFile[3], sfOffs, sfLen)) {
                                                char *sfBuf = read_name (sfOffs, sfLen);
-                                                                       
+
                                                if ((sinfo = get_known_source (sfBuf)) == 0) {
                                                        cerr << "Reference to unknown source [" << sfBuf << "]1" << endl;
                                                        return -1;
                                                }
-                                                                       
+
                                                free (sfBuf);
                                        } else {
                                                cerr << "offs/len illegal\n";
@@ -818,20 +819,20 @@ OMF::create_xml ()
                                                        cerr << "Reference to unknown source [" << fallbackFile[1] << "]2" << endl;
                                                        return -1;
                                                }
-                                                                       
+
                                        } else {
                                                cerr << "no fallback file\n";
                                        }
 
                                        sqlite3_free_table(fallbackFile);
                                }
-              
-                                       
+
+
                                if (sinfo) {
-                                       
+
                                        region = new_region_node ();
                                        playlist->add_child_nocopy (*region);
-                                       
+
                                        snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (position * sample_rate));
                                        region->add_property ("position", sbuf);
                                        snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (length * sample_rate));
@@ -839,7 +840,7 @@ OMF::create_xml ()
                                        snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (start * frame_rate * sample_rate));
                                        region->add_property ("start", sbuf);
                                        set_region_sources (region, sinfo);
-                                       
+
                                        route_max_channels = max (route_max_channels, sinfo->channels);
                                }
 
@@ -863,14 +864,14 @@ OMF::create_xml ()
                                sqlite3_get_table(db, sqlite3_mprintf("SELECT value FROM data WHERE object = %s AND property = 'OMFI:SCLP:StartTime' LIMIT 1", items[j]), &startTime, &startTimeCount, 0, 0);
                                if (startTimeCount > 0) {
                                        start = atoi(startTime[1]);
-                               } 
+                               }
                                sqlite3_free_table(startTime);
 
                                char **sourceFile;
                                int sourceFileCount;
                                //sqlite3_get_table(db, sqlite3_mprintf("SELECT d10.offset, d10.length FROM data d3, data d4, data d5, data d6, data d7, data d8, data d9, data d10 WHERE d3.object LIKE '%s' AND d3.property LIKE 'OMFI:SCLP:SourceID' AND d4.value LIKE d3.value AND d4.property LIKE 'OMFI:MOBJ:MobID' AND d5.object LIKE d4.object AND d5.property LIKE 'OMFI:MOBJ:Slots' AND d6.object LIKE d5.value AND d7.object LIKE d6.value AND d7.property LIKE 'OMFI:MSLT:Segment' AND d8.object LIKE d7.value AND d8.property LIKE 'OMFI:SCLP:SourceID' AND d9.value LIKE d8.value AND d9.property LIKE 'OMFI:MOBJ:MobID' AND d10.object LIKE d9.object AND d10.property LIKE 'OMFI:MOBJ:Name' LIMIT 1", items[j]), &sourceFile, &sourceFileCount, 0, 0);
                                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 IN (SELECT value FROM data WHERE object IN (SELECT value FROM data WHERE object IN (SELECT value FROM data WHERE object IN (SELECT object FROM data WHERE value IN (SELECT value FROM data WHERE object = %s AND property = 'OMFI:SCLP:SourceID' LIMIT 1) AND property = 'OMFI:MOBJ:MobID' LIMIT 1) AND property = 'OMFI:MOBJ:Slots' LIMIT 1) LIMIT 1) AND property = 'OMFI:MSLT:Segment' LIMIT 1) AND property = 'OMFI:SCLP:SourceID' LIMIT 1) AND property = 'OMFI:MOBJ:MobID' LIMIT 1) AND property LIKE 'OMFI:MOBJ:Name' LIMIT 1", items[j]), &sourceFile, &sourceFileCount, 0, 0);
-              
+
                                if (sourceFileCount > 0) {
                                        uint32_t sfOffs;
                                        uint32_t sfLen;
@@ -878,7 +879,7 @@ OMF::create_xml ()
                                        if (get_offset_and_length (sourceFile[2], sourceFile[3], sfOffs, sfLen)) {
                                                cerr << "get source file from " << sfOffs << " + " << sfLen << endl;
                                                char *sfBuf = read_name (sfOffs, sfLen);
-                                                                       
+
                                                if ((sinfo = get_known_source (sfBuf)) == 0) {
                                                        cerr << "Reference to unknown source [" << sfBuf << ']' << endl;
                                                        return -1;
@@ -902,12 +903,12 @@ OMF::create_xml ()
                                        }
                                        sqlite3_free_table(fallbackFile);
                                }
-              
+
                                if (sinfo) {
 
                                        region = new_region_node ();
                                        playlist->add_child_nocopy (*region);
-                                       
+
                                        snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (position * sample_rate));
                                        region->add_property ("position", sbuf);
                                        snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (length * sample_rate));
@@ -915,7 +916,7 @@ OMF::create_xml ()
                                        snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (start * frame_rate * sample_rate));
                                        region->add_property ("start", sbuf);
                                        set_region_sources (region, sinfo);
-                                       
+
                                        route_max_channels = max (route_max_channels, sinfo->channels);
                                }
 
@@ -929,9 +930,9 @@ OMF::create_xml ()
                }
 
                /* finalize route information */
-               
+
                cerr << "Set up track with " << route_max_channels << " channels" << endl;
-               set_route_node_channels (route, route_max_channels, route_max_channels, true);          
+               set_route_node_channels (route, route_max_channels, route_max_channels, true);
                sqlite3_free_table(items);
        }
 
@@ -940,6 +941,8 @@ OMF::create_xml ()
        id_counter++;
        snprintf (sbuf, sizeof (sbuf), "%" PRId64, id_counter);
        session->add_property ("id-counter", sbuf);
+       snprintf (sbuf, sizeof (sbuf), "%" PRId32, sample_rate);
+       session->add_property ("sample-rate", sbuf);
 
        XMLTree xml;
 
@@ -956,13 +959,14 @@ OMF::create_xml ()
 }
 
 
-static void 
+static void
 print_help (const char* execname)
 {
-       cout << execname 
+       cout << execname
             << " [ -r sample-rate ]"
             << " [ -n session-name ]"
             << " [ -v ardour-session-version ]"
+            << " OMF2_session_file"
             << endl;
        exit (1);
 }
@@ -973,16 +977,16 @@ main (int argc, char* argv[])
        const char *execname = strrchr (argv[0], '/');
        const char* optstring = "r:n:v:h";
        const char* session_name = 0;
-       int         sample_rate = 44100;
-       int         version = 3000;
+       int         sample_rate = 0;
+       int         version = 0;
 
        const struct option longopts[] = {
                { "rate", 1, 0, 'r' },
                { "name", 1, 0, 'n' },
                { "version", 1, 0, 'v' },
-               { "help", 1, 0, 'h' },
+               { "help", 0, 0, 'h' },
                { 0, 0, 0, 0 }
-       };      
+       };
 
 
        int option_index = 0;
@@ -1019,11 +1023,16 @@ main (int argc, char* argv[])
                print_help (execname);
                /*NOTREACHED*/
        }
-       
+
        OMF omf;
 
-       omf.set_version (version);
-       omf.set_sample_rate (sample_rate);
+       if (version) {
+               omf.set_version (version);
+       }
+
+       if (sample_rate) {
+               omf.set_sample_rate (sample_rate);
+       }
 
        if (session_name) {
                omf.set_session_name (session_name);