diff --git a/ProjectManager/ProjectManager.Designer.cs b/ProjectManager/ProjectManager.Designer.cs
index 83bb101c..d1d28e43 100644
--- a/ProjectManager/ProjectManager.Designer.cs
+++ b/ProjectManager/ProjectManager.Designer.cs
@@ -38,14 +38,15 @@ private void InitializeComponent()
this.label1 = new System.Windows.Forms.Label();
this.buttonProjectDetails = new System.Windows.Forms.Button();
this.buttonExportRenoise = new System.Windows.Forms.Button();
+ this.buttonExportReaper = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// buttonOpenProject
//
- this.buttonOpenProject.Location = new System.Drawing.Point(32, 29);
- this.buttonOpenProject.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
+ this.buttonOpenProject.Location = new System.Drawing.Point(16, 15);
+ this.buttonOpenProject.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.buttonOpenProject.Name = "buttonOpenProject";
- this.buttonOpenProject.Size = new System.Drawing.Size(277, 55);
+ this.buttonOpenProject.Size = new System.Drawing.Size(138, 28);
this.buttonOpenProject.TabIndex = 0;
this.buttonOpenProject.Text = "Open Project";
this.buttonOpenProject.UseVisualStyleBackColor = true;
@@ -54,10 +55,10 @@ private void InitializeComponent()
// buttonSaveHeader
//
this.buttonSaveHeader.Enabled = false;
- this.buttonSaveHeader.Location = new System.Drawing.Point(32, 329);
- this.buttonSaveHeader.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
+ this.buttonSaveHeader.Location = new System.Drawing.Point(16, 170);
+ this.buttonSaveHeader.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.buttonSaveHeader.Name = "buttonSaveHeader";
- this.buttonSaveHeader.Size = new System.Drawing.Size(277, 55);
+ this.buttonSaveHeader.Size = new System.Drawing.Size(138, 28);
this.buttonSaveHeader.TabIndex = 0;
this.buttonSaveHeader.Text = "Save C++ Header";
this.buttonSaveHeader.UseVisualStyleBackColor = true;
@@ -66,10 +67,10 @@ private void InitializeComponent()
// buttonSaveBinary
//
this.buttonSaveBinary.Enabled = false;
- this.buttonSaveBinary.Location = new System.Drawing.Point(32, 398);
- this.buttonSaveBinary.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
+ this.buttonSaveBinary.Location = new System.Drawing.Point(16, 205);
+ this.buttonSaveBinary.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.buttonSaveBinary.Name = "buttonSaveBinary";
- this.buttonSaveBinary.Size = new System.Drawing.Size(277, 55);
+ this.buttonSaveBinary.Size = new System.Drawing.Size(138, 28);
this.buttonSaveBinary.TabIndex = 0;
this.buttonSaveBinary.Text = "Save Binary Song";
this.buttonSaveBinary.UseVisualStyleBackColor = true;
@@ -78,10 +79,10 @@ private void InitializeComponent()
// buttonPlaySong
//
this.buttonPlaySong.Enabled = false;
- this.buttonPlaySong.Location = new System.Drawing.Point(32, 215);
- this.buttonPlaySong.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
+ this.buttonPlaySong.Location = new System.Drawing.Point(16, 111);
+ this.buttonPlaySong.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.buttonPlaySong.Name = "buttonPlaySong";
- this.buttonPlaySong.Size = new System.Drawing.Size(277, 55);
+ this.buttonPlaySong.Size = new System.Drawing.Size(138, 28);
this.buttonPlaySong.TabIndex = 0;
this.buttonPlaySong.Text = "Play Song";
this.buttonPlaySong.UseVisualStyleBackColor = true;
@@ -90,10 +91,10 @@ private void InitializeComponent()
// buttonExportWav
//
this.buttonExportWav.Enabled = false;
- this.buttonExportWav.Location = new System.Drawing.Point(32, 467);
- this.buttonExportWav.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
+ this.buttonExportWav.Location = new System.Drawing.Point(16, 241);
+ this.buttonExportWav.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.buttonExportWav.Name = "buttonExportWav";
- this.buttonExportWav.Size = new System.Drawing.Size(277, 55);
+ this.buttonExportWav.Size = new System.Drawing.Size(138, 28);
this.buttonExportWav.TabIndex = 0;
this.buttonExportWav.Text = "Export Wav";
this.buttonExportWav.UseVisualStyleBackColor = true;
@@ -104,31 +105,31 @@ private void InitializeComponent()
this.textBoxOutput.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
- this.textBoxOutput.Location = new System.Drawing.Point(325, 67);
- this.textBoxOutput.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
+ this.textBoxOutput.Location = new System.Drawing.Point(162, 35);
+ this.textBoxOutput.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.textBoxOutput.Multiline = true;
this.textBoxOutput.Name = "textBoxOutput";
this.textBoxOutput.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
- this.textBoxOutput.Size = new System.Drawing.Size(1135, 655);
+ this.textBoxOutput.Size = new System.Drawing.Size(570, 402);
this.textBoxOutput.TabIndex = 2;
//
// label1
//
this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(325, 29);
- this.label1.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
+ this.label1.Location = new System.Drawing.Point(162, 15);
+ this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(286, 32);
+ this.label1.Size = new System.Drawing.Size(143, 17);
this.label1.TabIndex = 3;
this.label1.Text = "Conversion Warnings";
//
// buttonProjectDetails
//
this.buttonProjectDetails.Enabled = false;
- this.buttonProjectDetails.Location = new System.Drawing.Point(29, 98);
- this.buttonProjectDetails.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
+ this.buttonProjectDetails.Location = new System.Drawing.Point(14, 51);
+ this.buttonProjectDetails.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.buttonProjectDetails.Name = "buttonProjectDetails";
- this.buttonProjectDetails.Size = new System.Drawing.Size(277, 55);
+ this.buttonProjectDetails.Size = new System.Drawing.Size(138, 28);
this.buttonProjectDetails.TabIndex = 4;
this.buttonProjectDetails.Text = "Project Details";
this.buttonProjectDetails.UseVisualStyleBackColor = true;
@@ -137,23 +138,36 @@ private void InitializeComponent()
// buttonExportRenoise
//
this.buttonExportRenoise.Enabled = false;
- this.buttonExportRenoise.Location = new System.Drawing.Point(32, 636);
- this.buttonExportRenoise.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
+ this.buttonExportRenoise.Location = new System.Drawing.Point(16, 341);
+ this.buttonExportRenoise.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.buttonExportRenoise.Name = "buttonExportRenoise";
- this.buttonExportRenoise.Size = new System.Drawing.Size(277, 86);
+ this.buttonExportRenoise.Size = new System.Drawing.Size(138, 44);
this.buttonExportRenoise.TabIndex = 0;
this.buttonExportRenoise.Text = "Export Renoise Patch Song";
this.buttonExportRenoise.UseVisualStyleBackColor = true;
this.buttonExportRenoise.Click += new System.EventHandler(this.buttonExportRenoise_Click);
//
+ // buttonExportReaper
+ //
+ this.buttonExportReaper.Enabled = false;
+ this.buttonExportReaper.Location = new System.Drawing.Point(16, 393);
+ this.buttonExportReaper.Margin = new System.Windows.Forms.Padding(4);
+ this.buttonExportReaper.Name = "buttonExportReaper";
+ this.buttonExportReaper.Size = new System.Drawing.Size(138, 44);
+ this.buttonExportReaper.TabIndex = 0;
+ this.buttonExportReaper.Text = "Export Reaper Patch Song";
+ this.buttonExportReaper.UseVisualStyleBackColor = true;
+ this.buttonExportReaper.Click += new System.EventHandler(this.buttonExportReaper_Click);
+ //
// ProjectManager
//
- this.AutoScaleDimensions = new System.Drawing.SizeF(16F, 31F);
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(1499, 756);
+ this.ClientSize = new System.Drawing.Size(750, 452);
this.Controls.Add(this.buttonProjectDetails);
this.Controls.Add(this.label1);
this.Controls.Add(this.textBoxOutput);
+ this.Controls.Add(this.buttonExportReaper);
this.Controls.Add(this.buttonExportRenoise);
this.Controls.Add(this.buttonExportWav);
this.Controls.Add(this.buttonPlaySong);
@@ -161,7 +175,7 @@ private void InitializeComponent()
this.Controls.Add(this.buttonSaveHeader);
this.Controls.Add(this.buttonOpenProject);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
- this.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
+ this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.Name = "ProjectManager";
this.Text = "Project Manager";
this.ResumeLayout(false);
@@ -180,6 +194,7 @@ private void InitializeComponent()
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button buttonProjectDetails;
private System.Windows.Forms.Button buttonExportRenoise;
+ private System.Windows.Forms.Button buttonExportReaper;
}
}
diff --git a/ProjectManager/ProjectManager.cs b/ProjectManager/ProjectManager.cs
index 32252e52..bb091e98 100644
--- a/ProjectManager/ProjectManager.cs
+++ b/ProjectManager/ProjectManager.cs
@@ -42,8 +42,7 @@ private void OpenProject(string projectFile)
catch (Exception err)
{
MessageBox.Show(err.Message);
- }
-
+ }
}
private void OnLogEvent(object sender, EventArgs e)
@@ -60,6 +59,7 @@ private void Enable()
buttonExportWav.Enabled = true;
buttonProjectDetails.Enabled = true;
buttonExportRenoise.Enabled = true;
+ buttonExportReaper.Enabled = true;
}
private void buttonSaveHeader_Click(object sender, EventArgs e)
@@ -176,5 +176,26 @@ private void buttonExportRenoise_Click(object sender, EventArgs e)
MessageBox.Show(err.Message);
}
}
+
+ private void buttonExportReaper_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ var inject = new ReaperInject();
+ var project = inject.InjectPatches(song, logger);
+
+ var sfd = new SaveFileDialog();
+ sfd.Filter = "Reaper Song File|*.rpp";
+ sfd.FileName = fileName;
+ if (sfd.ShowDialog() == DialogResult.OK)
+ {
+ File.WriteAllText(sfd.FileName, project);
+ }
+ }
+ catch (Exception err)
+ {
+ MessageBox.Show(err.Message);
+ }
+ }
}
}
diff --git a/WaveSabreConvert/Properties/Resources.Designer.cs b/WaveSabreConvert/Properties/Resources.Designer.cs
index 2610829e..4ab27425 100644
--- a/WaveSabreConvert/Properties/Resources.Designer.cs
+++ b/WaveSabreConvert/Properties/Resources.Designer.cs
@@ -19,7 +19,7 @@ namespace WaveSabreConvert.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -60,6 +60,36 @@ internal Resources() {
}
}
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] ReaperDevices {
+ get {
+ object obj = ResourceManager.GetObject("ReaperDevices", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] ReaperProject {
+ get {
+ object obj = ResourceManager.GetObject("ReaperProject", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] ReaperTrack {
+ get {
+ object obj = ResourceManager.GetObject("ReaperTrack", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Byte[].
///
diff --git a/WaveSabreConvert/Properties/Resources.resx b/WaveSabreConvert/Properties/Resources.resx
index 775e2cba..e3f5c30d 100644
--- a/WaveSabreConvert/Properties/Resources.resx
+++ b/WaveSabreConvert/Properties/Resources.resx
@@ -118,6 +118,15 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ ..\resources\reaperdevices.rpp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\resources\reaperproject.rpp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\resources\reapertrack.rpp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
..\Resources\template.xrns;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
diff --git a/WaveSabreConvert/ReaperInject.cs b/WaveSabreConvert/ReaperInject.cs
new file mode 100644
index 00000000..c482f37d
--- /dev/null
+++ b/WaveSabreConvert/ReaperInject.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace WaveSabreConvert
+{
+ public class ReaperInject
+ {
+ ILog logger;
+ private Dictionary _devices;
+
+ public string InjectPatches(Song song, ILog logger)
+ {
+ this.logger = logger;
+
+ CreateDevices();
+
+ var project = Encoding.UTF8.GetString(WaveSabreConvert.Properties.Resources.ReaperProject);
+
+ var sb = new StringBuilder();
+
+ foreach (var track in song.Tracks)
+ {
+ if (track.Events.Count > 0)
+ {
+ logger.WriteLine(string.Format("Converting track: {0}", track.Name));
+ sb.Append(CreateTrack(track));
+ }
+ }
+
+ project = project.Replace("~Tracks~", sb.ToString());
+
+ return project;
+ }
+
+ private void CreateDevices()
+ {
+ _devices = new Dictionary();
+ var devices = Encoding.UTF8.GetString(WaveSabreConvert.Properties.Resources.ReaperDevices);
+ using (StringReader reader = new StringReader(devices))
+ {
+ var line = "";
+ while (line != null)
+ {
+ line = reader.ReadLine();
+ if (line != null && line.Contains(".dll"))
+ {
+ var sb = new StringBuilder();
+ sb.AppendLine(line);
+ var items = SplitData(line);
+ line = reader.ReadLine();
+ while (!line.Contains(">"))
+ {
+ sb.AppendLine(line);
+ line = reader.ReadLine();
+ }
+ sb.AppendLine(line);
+ _devices.Add(items[2], sb.ToString());
+ }
+ }
+ }
+ }
+
+ private List SplitData(string data)
+ {
+ return Regex.Matches(data, @"[\""].+?[\""]|[^ ]+")
+ .Cast()
+ .Select(m => m.Value)
+ .ToList();
+ }
+
+ private string CreateTrack(Song.Track track)
+ {
+ var reaperTrack = Encoding.UTF8.GetString(WaveSabreConvert.Properties.Resources.ReaperTrack).Replace("~TrackName~", track.Name);
+
+ var sb = new StringBuilder();
+ foreach (var device in track.Devices)
+ {
+ sb.Append(CreateDevice(device));
+ }
+ reaperTrack = reaperTrack.Replace("~Devices~", sb.ToString());
+
+ return reaperTrack;
+ }
+
+ private string CreateDevice(Song.Device device)
+ {
+ var reaperDevice = "";
+ var injected = "";
+
+ var deviceId = device.Id.ToString() + ".dll";
+
+ _devices.TryGetValue(deviceId, out reaperDevice);
+
+ if (string.IsNullOrEmpty(reaperDevice))
+ {
+ // Whoops
+ logger.WriteLine(string.Format("Device {0} not found", deviceId));
+ }
+ else
+ {
+ injected = InjectDevice(reaperDevice, device.Chunk);
+ }
+
+ return injected;
+ }
+
+ private string InjectDevice(string reaperDevice, byte[] deviceChunk)
+ {
+ var chunkList = new List();
+
+ var header = "";
+ var footer = "";
+
+ // compile all base64 strings to one bin chunk
+ using (var reader = new StringReader(reaperDevice))
+ {
+ var line = reader.ReadLine();
+ while (line != null)
+ {
+ line = line.TrimStart();
+ if (line.StartsWith("<"))
+ {
+ header = line;
+ }
+ else if (line.StartsWith(">"))
+ {
+ footer = line;
+ }
+ else
+ {
+ chunkList.AddRange(Convert.FromBase64String(line).ToList());
+ }
+
+ line = reader.ReadLine();
+ }
+ }
+
+ var headerChunk = new BinaryWriter(new MemoryStream());
+ var footerChunk = new BinaryWriter(new MemoryStream());
+
+ // vst chunk
+ using (var reader = new BinaryReader(new MemoryStream(chunkList.ToArray())))
+ {
+ headerChunk.Write(reader.ReadChars(4));
+ headerChunk.Write(reader.ReadInt32());
+ var inputChannels = reader.ReadInt32();
+ headerChunk.Write(inputChannels);
+ headerChunk.Write(reader.ReadBytes(inputChannels * 8));
+
+ var outputChannels = reader.ReadInt32();
+ headerChunk.Write(outputChannels);
+ headerChunk.Write(reader.ReadBytes(outputChannels * 8));
+
+ var chunkLength = reader.ReadInt32();
+ headerChunk.Write(deviceChunk.Length);
+ var val1 = reader.ReadInt32();
+ var val2 = reader.ReadInt32();
+
+ headerChunk.Write(val1);
+ headerChunk.Write(val2);
+
+ reader.ReadBytes(chunkLength);
+ int leftover = (int)reader.BaseStream.Length - (int)reader.BaseStream.Position;
+ footerChunk.Write(reader.ReadBytes(leftover));
+ }
+
+ var sb = new StringBuilder();
+ var headerMs = (MemoryStream)headerChunk.BaseStream;
+ var footerMs = (MemoryStream)footerChunk.BaseStream;
+ var baseChunks = SplitInParts(Convert.ToBase64String(deviceChunk), 128);
+
+
+ sb.AppendLine(header);
+ sb.AppendLine(Convert.ToBase64String(headerMs.ToArray()));
+ foreach (var chunk in baseChunks)
+ {
+ sb.AppendLine(chunk);
+ }
+ sb.AppendLine(Convert.ToBase64String(footerMs.ToArray()));
+ sb.AppendLine(footer);
+
+ return sb.ToString();
+
+ }
+
+ private IEnumerable SplitInParts(string s, Int32 partLength)
+ {
+ if (s == null)
+ throw new ArgumentNullException("s");
+ if (partLength <= 0)
+ throw new ArgumentException("Part length has to be positive.", "partLength");
+
+ for (var i = 0; i < s.Length; i += partLength)
+ yield return s.Substring(i, Math.Min(partLength, s.Length - i));
+ }
+ }
+}
diff --git a/WaveSabreConvert/Resources/ReaperDevices.rpp b/WaveSabreConvert/Resources/ReaperDevices.rpp
new file mode 100644
index 00000000..e33bc4dd
--- /dev/null
+++ b/WaveSabreConvert/Resources/ReaperDevices.rpp
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WaveSabreConvert/Resources/ReaperProject.rpp b/WaveSabreConvert/Resources/ReaperProject.rpp
new file mode 100644
index 00000000..85455945
--- /dev/null
+++ b/WaveSabreConvert/Resources/ReaperProject.rpp
@@ -0,0 +1,87 @@
+
+
+ RENDER_FILE ""
+ RENDER_PATTERN ""
+ RENDER_FMT 0 2 0
+ RENDER_1X 0
+ RENDER_RANGE 1 0 0 18 1000
+ RENDER_RESAMPLE 3 0 1
+ RENDER_ADDTOPROJ 0
+ RENDER_STEMS 0
+ RENDER_DITHER 0
+ TIMELOCKMODE 1
+ TEMPOENVLOCKMODE 1
+ ITEMMIX 0
+ DEFPITCHMODE 589824 0
+ TAKELANE 1
+ SAMPLERATE 44100 0 0
+
+ LOCK 1
+
+ GLOBAL_AUTO -1
+ TEMPO 120 4 4
+ PLAYRATE 1 0 0.25 4
+ SELECTION 0 1.5
+ SELECTION2 0 1.5
+ MASTERAUTOMODE 0
+ MASTERTRACKHEIGHT 0 0
+ MASTERPEAKCOL 16576
+ MASTERMUTESOLO 0
+ MASTERTRACKVIEW 0 0.6667 0.5 0.5 0 0 0
+ MASTERHWOUT 0 0 1 0 0 0 0 -1
+ MASTER_NCH 2 2
+ MASTER_VOLUME 1 0 -1 -1 1
+ MASTER_FX 1
+ MASTER_SEL 0
+
+
+
+~Tracks~
+>
diff --git a/WaveSabreConvert/Resources/reapertrack.rpp b/WaveSabreConvert/Resources/reapertrack.rpp
new file mode 100644
index 00000000..de9763a3
--- /dev/null
+++ b/WaveSabreConvert/Resources/reapertrack.rpp
@@ -0,0 +1,28 @@
+