diff --git a/MatterControl.csproj b/MatterControl.csproj
index 7991a46e8..795325f9c 100644
--- a/MatterControl.csproj
+++ b/MatterControl.csproj
@@ -226,6 +226,7 @@
+
diff --git a/PrinterCommunication/Io/MacroProcessingStream.cs b/PrinterCommunication/Io/MacroProcessingStream.cs
new file mode 100644
index 000000000..024bdf8bb
--- /dev/null
+++ b/PrinterCommunication/Io/MacroProcessingStream.cs
@@ -0,0 +1,264 @@
+/*
+Copyright (c) 2015, Lars Brubaker
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those
+of the authors and should not be interpreted as representing official policies,
+either expressed or implied, of the FreeBSD Project.
+*/
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Threading;
+using MatterHackers.Agg.Image;
+using MatterHackers.Agg.PlatformAbstract;
+using MatterHackers.Agg.UI;
+using MatterHackers.MatterControl.PrinterControls;
+using MatterHackers.MatterControl.SlicerConfiguration;
+
+namespace MatterHackers.MatterControl.PrinterCommunication.Io
+{
+ public class MacroProcessingStream : GCodeStreamProxy
+ {
+ public const string MacroPrefix = "; host.";
+ private List commandsToRepeat = new List();
+ private object locker = new object();
+ private double maxTimeToWaitForOk = 0;
+ private int repeatCommandIndex = 0;
+ private bool runningMacro = false;
+ private double startingBedTemp = 0;
+ private List startingExtruderTemps = new List();
+ private Stopwatch timeHaveBeenWaiting = new Stopwatch();
+ private bool waitingForUserInput = false;
+ private PrinterConnection printerConnection;
+ QueuedCommandsStream queuedCommandsStream;
+
+ public MacroProcessingStream(QueuedCommandsStream queuedCommandsStream, PrinterConnection printerConnection)
+ : base(queuedCommandsStream)
+ {
+ this.queuedCommandsStream = queuedCommandsStream;
+ this.printerConnection = printerConnection;
+ }
+
+ public void Cancel()
+ {
+ Reset();
+ }
+
+ public void Continue()
+ {
+ waitingForUserInput = false;
+ timeHaveBeenWaiting.Reset();
+ maxTimeToWaitForOk = 0;
+ commandsToRepeat.Clear();
+ }
+
+ public ImageBuffer LoadImageAsset(string uri)
+ {
+ string filePath = Path.Combine("Images", "Macros", uri);
+ bool imageOnDisk = false;
+ if (uri.IndexOfAny(Path.GetInvalidFileNameChars()) == -1)
+ {
+ try
+ {
+ imageOnDisk = StaticData.Instance.FileExists(filePath);
+ }
+ catch
+ {
+ imageOnDisk = false;
+ }
+ }
+
+ if (imageOnDisk)
+ {
+ return StaticData.Instance.LoadImage(filePath);
+ }
+ else
+ {
+ var imageBuffer = new ImageBuffer(320, 10);
+
+ ApplicationController.Instance.DownloadToImageAsync(imageBuffer, uri, true);
+
+ return imageBuffer;
+ }
+ }
+
+ public override string ReadLine()
+ {
+ string lineToSend = null;
+
+ if (waitingForUserInput)
+ {
+ lineToSend = "";
+ Thread.Sleep(100);
+
+ if (timeHaveBeenWaiting.IsRunning
+ && timeHaveBeenWaiting.Elapsed.TotalSeconds > maxTimeToWaitForOk)
+ {
+ if (commandsToRepeat.Count > 0)
+ {
+ // We timed out without the user responding. Cancel the operation.
+ Reset();
+ }
+ else
+ {
+ // everything normal continue after time waited
+ Continue();
+ }
+ }
+
+ if (maxTimeToWaitForOk > 0
+ && timeHaveBeenWaiting.Elapsed.TotalSeconds < maxTimeToWaitForOk
+ && commandsToRepeat.Count > 0)
+ {
+ lineToSend = commandsToRepeat[repeatCommandIndex % commandsToRepeat.Count];
+ repeatCommandIndex++;
+ }
+ }
+ else
+ {
+ lineToSend = base.ReadLine();
+
+ if (lineToSend != null)
+ {
+ if (lineToSend.StartsWith(MacroPrefix) && lineToSend.TrimEnd().EndsWith(")"))
+ {
+ if (!runningMacro)
+ {
+ runningMacro = true;
+ int extruderCount = printerConnection.PrinterSettings.GetValue(SettingsKey.extruder_count);
+ for (int i = 0; i < extruderCount; i++)
+ {
+ startingExtruderTemps.Add(printerConnection.GetTargetExtruderTemperature(i));
+ }
+
+ if (printerConnection.PrinterSettings.GetValue(SettingsKey.has_heated_bed))
+ {
+ startingBedTemp = printerConnection.TargetBedTemperature;
+ }
+ }
+ int parensAfterCommand = lineToSend.IndexOf('(', MacroPrefix.Length);
+ string command = "";
+ if (parensAfterCommand > 0)
+ {
+ command = lineToSend.Substring(MacroPrefix.Length, parensAfterCommand - MacroPrefix.Length);
+ }
+
+ RunningMacroPage.MacroCommandData macroData = new RunningMacroPage.MacroCommandData();
+
+ string value = "";
+ if (TryGetAfterString(lineToSend, "title", out value))
+ {
+ macroData.title = value;
+ }
+ if (TryGetAfterString(lineToSend, "expire", out value))
+ {
+ double.TryParse(value, out macroData.expireTime);
+ maxTimeToWaitForOk = macroData.expireTime;
+ }
+ if (TryGetAfterString(lineToSend, "count_down", out value))
+ {
+ double.TryParse(value, out macroData.countDown);
+ }
+ if (TryGetAfterString(lineToSend, "image", out value))
+ {
+ macroData.image = LoadImageAsset(value);
+ }
+ if (TryGetAfterString(lineToSend, "wait_ok", out value))
+ {
+ macroData.waitOk = value == "true";
+ }
+ if (TryGetAfterString(lineToSend, "repeat_gcode", out value))
+ {
+ foreach (string line in value.Split('|'))
+ {
+ commandsToRepeat.Add(line);
+ }
+ }
+
+ switch (command)
+ {
+ case "choose_material":
+ waitingForUserInput = true;
+ macroData.showMaterialSelector = true;
+ macroData.waitOk = true;
+ UiThread.RunOnIdle(() => RunningMacroPage.Show(macroData));
+ break;
+
+ case "close":
+ runningMacro = false;
+ UiThread.RunOnIdle(() => WizardWindow.Close("Macro"));
+ break;
+
+ case "ding":
+ MatterControlApplication.Instance.PlaySound("timer-done.wav");
+ break;
+
+ case "show_message":
+ waitingForUserInput = macroData.waitOk | macroData.expireTime > 0;
+ UiThread.RunOnIdle(() => RunningMacroPage.Show(macroData));
+ break;
+
+ default:
+ // Don't know the command. Print to terminal log?
+ break;
+ }
+ }
+ }
+ }
+
+ return lineToSend;
+ }
+
+ public void Reset()
+ {
+ if (runningMacro)
+ {
+ runningMacro = false;
+ for (int i = 0; i < startingExtruderTemps.Count; i++)
+ {
+ printerConnection.SetTargetExtruderTemperature(i, startingExtruderTemps[i]);
+ }
+
+ if (printerConnection.PrinterSettings.GetValue(SettingsKey.has_heated_bed))
+ {
+ printerConnection.TargetBedTemperature = startingBedTemp;
+ }
+ }
+ waitingForUserInput = false;
+ timeHaveBeenWaiting.Reset();
+ maxTimeToWaitForOk = 0;
+ UiThread.RunOnIdle(() => WizardWindow.Close("Macro"));
+ }
+
+ private bool TryGetAfterString(string macroLine, string variableName, out string value)
+ {
+ var macroMatch = Regex.Match(macroLine, variableName + ":\"([^\"]+)");
+ value = macroMatch.Success ? macroMatch.Groups[1].Value : null;
+
+ return macroMatch.Success;
+ }
+ }
+}
\ No newline at end of file
diff --git a/PrinterCommunication/Io/PrintRecoveryStream.cs b/PrinterCommunication/Io/PrintRecoveryStream.cs
index 847b53c0d..e8c579849 100644
--- a/PrinterCommunication/Io/PrintRecoveryStream.cs
+++ b/PrinterCommunication/Io/PrintRecoveryStream.cs
@@ -43,7 +43,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
private double percentDone;
double recoverFeedRate;
PrinterMove lastDestination;
- QueuedCommandsStream queuedCommands;
+ QueuedCommandsStream queuedCommands;
RectangleDouble boundsOfSkippedLayers = RectangleDouble.ZeroIntersection;
RecoveryState recoveryState = RecoveryState.RemoveHeating;
diff --git a/PrinterCommunication/Io/QueuedCommandsStream.cs b/PrinterCommunication/Io/QueuedCommandsStream.cs
index 9525f2314..c1d2b01ef 100644
--- a/PrinterCommunication/Io/QueuedCommandsStream.cs
+++ b/PrinterCommunication/Io/QueuedCommandsStream.cs
@@ -42,17 +42,8 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
{
public class QueuedCommandsStream : GCodeStreamProxy
{
- public const string MacroPrefix = "; host.";
private List commandQueue = new List();
- private List commandsToRepeat = new List();
private object locker = new object();
- private double maxTimeToWaitForOk = 0;
- private int repeatCommandIndex = 0;
- private bool runningMacro = false;
- private double startingBedTemp = 0;
- private List startingExtruderTemps = new List();
- private Stopwatch timeHaveBeenWaiting = new Stopwatch();
- private bool waitingForUserInput = false;
public QueuedCommandsStream(GCodeStream internalStream)
: base(internalStream)
@@ -80,14 +71,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
Reset();
}
- public void Continue()
- {
- waitingForUserInput = false;
- timeHaveBeenWaiting.Reset();
- maxTimeToWaitForOk = 0;
- commandsToRepeat.Clear();
- }
-
public ImageBuffer LoadImageAsset(string uri)
{
string filePath = Path.Combine("Images", "Macros", uri);
@@ -122,35 +105,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
{
string lineToSend = null;
- if (waitingForUserInput)
- {
- lineToSend = "";
- Thread.Sleep(100);
-
- if (timeHaveBeenWaiting.IsRunning
- && timeHaveBeenWaiting.Elapsed.TotalSeconds > maxTimeToWaitForOk)
- {
- if (commandsToRepeat.Count > 0)
- {
- // We timed out without the user responding. Cancel the operation.
- Reset();
- }
- else
- {
- // everything normal continue after time waited
- Continue();
- }
- }
-
- if (maxTimeToWaitForOk > 0
- && timeHaveBeenWaiting.Elapsed.TotalSeconds < maxTimeToWaitForOk
- && commandsToRepeat.Count > 0)
- {
- lineToSend = commandsToRepeat[repeatCommandIndex % commandsToRepeat.Count];
- repeatCommandIndex++;
- }
- }
- else
{
// lock queue
lock (locker)
@@ -163,93 +117,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
}
}
- if (lineToSend != null)
- {
- if (lineToSend.StartsWith(MacroPrefix) && lineToSend.TrimEnd().EndsWith(")"))
- {
- if (!runningMacro)
- {
- runningMacro = true;
- int extruderCount = ActiveSliceSettings.Instance.GetValue(SettingsKey.extruder_count);
- for (int i = 0; i < extruderCount; i++)
- {
- startingExtruderTemps.Add(PrinterConnection.Instance.GetTargetExtruderTemperature(i));
- }
-
- if (ActiveSliceSettings.Instance.GetValue(SettingsKey.has_heated_bed))
- {
- startingBedTemp = PrinterConnection.Instance.TargetBedTemperature;
- }
- }
- int parensAfterCommand = lineToSend.IndexOf('(', MacroPrefix.Length);
- string command = "";
- if (parensAfterCommand > 0)
- {
- command = lineToSend.Substring(MacroPrefix.Length, parensAfterCommand - MacroPrefix.Length);
- }
-
- RunningMacroPage.MacroCommandData macroData = new RunningMacroPage.MacroCommandData();
-
- string value = "";
- if (TryGetAfterString(lineToSend, "title", out value))
- {
- macroData.title = value;
- }
- if (TryGetAfterString(lineToSend, "expire", out value))
- {
- double.TryParse(value, out macroData.expireTime);
- maxTimeToWaitForOk = macroData.expireTime;
- }
- if (TryGetAfterString(lineToSend, "count_down", out value))
- {
- double.TryParse(value, out macroData.countDown);
- }
- if (TryGetAfterString(lineToSend, "image", out value))
- {
- macroData.image = LoadImageAsset(value);
- }
- if (TryGetAfterString(lineToSend, "wait_ok", out value))
- {
- macroData.waitOk = value == "true";
- }
- if (TryGetAfterString(lineToSend, "repeat_gcode", out value))
- {
- foreach (string line in value.Split('|'))
- {
- commandsToRepeat.Add(line);
- }
- }
-
- switch (command)
- {
- case "choose_material":
- waitingForUserInput = true;
- macroData.showMaterialSelector = true;
- macroData.waitOk = true;
- UiThread.RunOnIdle(() => RunningMacroPage.Show(macroData));
- break;
-
- case "close":
- runningMacro = false;
- UiThread.RunOnIdle(() => WizardWindow.Close("Macro"));
- break;
-
- case "ding":
- MatterControlApplication.Instance.PlaySound("timer-done.wav");
- break;
-
- case "show_message":
- waitingForUserInput = macroData.waitOk | macroData.expireTime > 0;
- UiThread.RunOnIdle(() => RunningMacroPage.Show(macroData));
- break;
-
- default:
- // Don't know the command. Print to terminal log?
- break;
- }
- }
- }
- else
+ if (lineToSend == null)
{
lineToSend = base.ReadLine();
}
@@ -264,32 +132,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
{
commandQueue.Clear();
}
-
- if (runningMacro)
- {
- runningMacro = false;
- for (int i = 0; i < startingExtruderTemps.Count; i++)
- {
- PrinterConnection.Instance.SetTargetExtruderTemperature(i, startingExtruderTemps[i]);
- }
-
- if (ActiveSliceSettings.Instance.GetValue(SettingsKey.has_heated_bed))
- {
- PrinterConnection.Instance.TargetBedTemperature = startingBedTemp;
- }
- }
- waitingForUserInput = false;
- timeHaveBeenWaiting.Reset();
- maxTimeToWaitForOk = 0;
- UiThread.RunOnIdle(() => WizardWindow.Close("Macro"));
- }
-
- private bool TryGetAfterString(string macroLine, string variableName, out string value)
- {
- var macroMatch = Regex.Match(macroLine, variableName + ":\"([^\"]+)");
- value = macroMatch.Success ? macroMatch.Groups[1].Value : null;
-
- return macroMatch.Success;
}
}
}
\ No newline at end of file
diff --git a/PrinterCommunication/PrinterConnection.cs b/PrinterCommunication/PrinterConnection.cs
index d03c9912d..f6d807bf2 100644
--- a/PrinterCommunication/PrinterConnection.cs
+++ b/PrinterCommunication/PrinterConnection.cs
@@ -220,14 +220,15 @@ namespace MatterHackers.MatterControl.PrinterCommunication
private GCodeFileStream gCodeFileStream0 = null;
private PauseHandlingStream pauseHandlingStream1 = null;
private QueuedCommandsStream queuedCommandStream2 = null;
- private RelativeToAbsoluteStream relativeToAbsoluteStream3 = null;
- private PrintLevelingStream printLevelingStream4 = null;
- private WaitForTempStream waitForTempStream5 = null;
- private BabyStepsStream babyStepsStream6 = null;
- private ExtrusionMultiplyerStream extrusionMultiplyerStream7 = null;
- private FeedRateMultiplyerStream feedrateMultiplyerStream8 = null;
- private RequestTemperaturesStream requestTemperaturesStream9 = null;
- private ProcessWriteRegexStream processWriteRegExStream10 = null;
+ private MacroProcessingStream macroProcessingStream3 = null;
+ private RelativeToAbsoluteStream relativeToAbsoluteStream4 = null;
+ private PrintLevelingStream printLevelingStream5 = null;
+ private WaitForTempStream waitForTempStream6 = null;
+ private BabyStepsStream babyStepsStream7 = null;
+ private ExtrusionMultiplyerStream extrusionMultiplyerStream8 = null;
+ private FeedRateMultiplyerStream feedrateMultiplyerStream9 = null;
+ private RequestTemperaturesStream requestTemperaturesStream10 = null;
+ private ProcessWriteRegexStream processWriteRegExStream11 = null;
private GCodeStream totalGCodeStream = null;
@@ -2328,20 +2329,21 @@ namespace MatterHackers.MatterControl.PrinterCommunication
}
queuedCommandStream2 = new QueuedCommandsStream(firstStream);
- relativeToAbsoluteStream3 = new RelativeToAbsoluteStream(queuedCommandStream2);
- printLevelingStream4 = new PrintLevelingStream(relativeToAbsoluteStream3, true);
- waitForTempStream5 = new WaitForTempStream(printLevelingStream4);
- babyStepsStream6 = new BabyStepsStream(waitForTempStream5, gcodeFilename == null ? 2000 : 1);
+ macroProcessingStream3 = new MacroProcessingStream(queuedCommandStream2, this);
+ relativeToAbsoluteStream4 = new RelativeToAbsoluteStream(macroProcessingStream3);
+ printLevelingStream5 = new PrintLevelingStream(relativeToAbsoluteStream4, true);
+ waitForTempStream6 = new WaitForTempStream(printLevelingStream5);
+ babyStepsStream7 = new BabyStepsStream(waitForTempStream6, gcodeFilename == null ? 2000 : 1);
if (activePrintTask != null)
{
// make sure we are in the position we were when we stopped printing
- babyStepsStream6.Offset = new Vector3(activePrintTask.PrintingOffsetX, activePrintTask.PrintingOffsetY, activePrintTask.PrintingOffsetZ);
+ babyStepsStream7.Offset = new Vector3(activePrintTask.PrintingOffsetX, activePrintTask.PrintingOffsetY, activePrintTask.PrintingOffsetZ);
}
- extrusionMultiplyerStream7 = new ExtrusionMultiplyerStream(babyStepsStream6);
- feedrateMultiplyerStream8 = new FeedRateMultiplyerStream(extrusionMultiplyerStream7);
- requestTemperaturesStream9 = new RequestTemperaturesStream(feedrateMultiplyerStream8);
- processWriteRegExStream10 = new ProcessWriteRegexStream(requestTemperaturesStream9, queuedCommandStream2);
- totalGCodeStream = processWriteRegExStream10;
+ extrusionMultiplyerStream8 = new ExtrusionMultiplyerStream(babyStepsStream7);
+ feedrateMultiplyerStream9 = new FeedRateMultiplyerStream(extrusionMultiplyerStream8);
+ requestTemperaturesStream10 = new RequestTemperaturesStream(feedrateMultiplyerStream9);
+ processWriteRegExStream11 = new ProcessWriteRegexStream(requestTemperaturesStream10, queuedCommandStream2);
+ totalGCodeStream = processWriteRegExStream11;
// Get the current position of the printer any time we reset our streams
ReadPosition();
@@ -2467,11 +2469,11 @@ namespace MatterHackers.MatterControl.PrinterCommunication
{
PrintingState = DetailedPrintingState.HomingAxis;
}
- else if (waitForTempStream5?.HeatingBed ?? false)
+ else if (waitForTempStream6?.HeatingBed ?? false)
{
PrintingState = DetailedPrintingState.HeatingBed;
}
- else if (waitForTempStream5?.HeatingExtruder ?? false)
+ else if (waitForTempStream6?.HeatingExtruder ?? false)
{
PrintingState = DetailedPrintingState.HeatingExtruder;
}
@@ -2567,13 +2569,13 @@ namespace MatterHackers.MatterControl.PrinterCommunication
// Only update the amount done if it is greater than what is recorded.
// We don't want to mess up the resume before we actually resume it.
if (activePrintTask != null
- && babyStepsStream6 != null
+ && babyStepsStream7 != null
&& activePrintTask.PercentDone < currentDone)
{
activePrintTask.PercentDone = currentDone;
- activePrintTask.PrintingOffsetX = (float)babyStepsStream6.Offset.x;
- activePrintTask.PrintingOffsetY = (float)babyStepsStream6.Offset.y;
- activePrintTask.PrintingOffsetZ = (float)babyStepsStream6.Offset.z;
+ activePrintTask.PrintingOffsetX = (float)babyStepsStream7.Offset.x;
+ activePrintTask.PrintingOffsetY = (float)babyStepsStream7.Offset.y;
+ activePrintTask.PrintingOffsetZ = (float)babyStepsStream7.Offset.z;
try
{
Task.Run(() => activePrintTask.Commit());
@@ -2772,14 +2774,14 @@ namespace MatterHackers.MatterControl.PrinterCommunication
public void MacroCancel()
{
- babyStepsStream6?.CancelMoves();
- waitForTempStream5?.Cancel();
+ babyStepsStream7?.CancelMoves();
+ waitForTempStream6?.Cancel();
queuedCommandStream2?.Cancel();
}
public void MacroContinue()
{
- queuedCommandStream2?.Continue();
+ macroProcessingStream3?.Continue();
}
public class ReadThread
diff --git a/SlicerConfiguration/Settings/GCodeMacro.cs b/SlicerConfiguration/Settings/GCodeMacro.cs
index 98e051364..9e15b812a 100644
--- a/SlicerConfiguration/Settings/GCodeMacro.cs
+++ b/SlicerConfiguration/Settings/GCodeMacro.cs
@@ -68,9 +68,9 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
{
PrinterConnection.Instance.MacroStart();
SendCommandToPrinter(GCode);
- if (GCode.Contains(QueuedCommandsStream.MacroPrefix))
+ if (GCode.Contains(MacroProcessingStream.MacroPrefix))
{
- SendCommandToPrinter("\n" + QueuedCommandsStream.MacroPrefix + "close()");
+ SendCommandToPrinter("\n" + MacroProcessingStream.MacroPrefix + "close()");
}
}
}
diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp
index de4578e53..c4d79959c 160000
--- a/Submodules/agg-sharp
+++ b/Submodules/agg-sharp
@@ -1 +1 @@
-Subproject commit de4578e53b9fc874a04056ddf104a75505445999
+Subproject commit c4d79959c335a5e773520e60b3236b211a5a76f7