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
#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;
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");
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);
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);
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,
add_id (playlist);
playlist->add_property ("type", "audio");
playlist->add_property ("frozen", "no");
-
+
return playlist;
}
diskstream->add_property ("flags", "Recordable");
diskstream->add_property ("speed", "1");
diskstream->add_property ("channels", "1");
-
+
return diskstream;
}
void
XMLNode* output_io;
char sbuf[256];
string name = route->property ("name")->value();
-
+
legalize_name (name);
output_io = new XMLNode ("IO");
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);
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");
snprintf (sbuf, sizeof (sbuf), "system:playback_1");
}
}
-
+
connection->add_property ("other", sbuf);
port->add_child_nocopy (*connection);
}
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");
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");
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);
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);
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");
add_id (source);
source->add_property ("type", "audio");
source->add_property ("flags", "CanRename");
-
+
sources->add_child_nocopy (*source);
-
+
return source;
}
KnownSources::iterator i = known_sources.find (s);
if (i != known_sources.end()) {
return i->second;
- }
+ }
return 0;
}
int major;
int minor;
int micro;
-
+
major = version / 1000;
minor = version - (major * 1000);
micro = version - (major * 1000) - (minor * 100);
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;
}
}
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);
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);
lenFrames = atoi(len[1]);
length = lenFrames * frame_rate;
-
+
if (!strcmp(type[1], "TRAN")) {
position -= length;
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";
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));
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);
}
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;
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;
}
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));
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);
}
}
/* 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);
}
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;
}
-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);
}
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;
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);