Add Some Error Checking

This commit is contained in:
bmgjet 2024-12-24 23:27:06 +13:00 committed by GitHub
parent 9c2a7994a4
commit 48984f7be8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 1370 additions and 1175 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>

File diff suppressed because it is too large Load Diff

View File

@ -1,326 +1,398 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Ruyi_GUI
{
public partial class Form1 : Form
{
public static List<string> LogMessages = new List<string>();
public string PythonCode;
public bool DoingJobs = false;
public bool Not100 = true;
public Form1()
{
InitializeComponent();
PythonCode = Encoding.UTF8.GetString(Convert.FromBase64String(Decompress(Convert.FromBase64String("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"))));
if (File.Exists("Config.cfg")) { LoadSettings(File.ReadAllText("Config.cfg")); }
else
{
FrameRate.SelectedIndex = 0;
AspectRatio.SelectedIndex = 0;
Resolution.SelectedIndex = 0;
Direction.SelectedIndex = 0;
Motion.SelectedIndex = 0;
Scheduler.SelectedIndex = 0;
SaveSettings();
}
}
private string SettingsString() { return Img1.Text + "|" + Img2.Text + "|" + VideoOut.Text + "|" + FrameRate.SelectedIndex + "|" + AspectRatio.SelectedIndex + "|" + Resolution.SelectedIndex + "|" + Direction.SelectedIndex + "|" + Motion.SelectedIndex + "|" + GPUOffload.Text + "|" + LowMemoryMode.Checked + "|" + Steps.Text + "|" + Cfg.Text + "|" + Seed.Text + "|" + Scheduler.SelectedIndex; }
private void SaveSettings() { File.WriteAllText("Config.cfg", SettingsString()); }
private void LoadSettings(string Settings)
{
string[] SSettings = Settings.Split('|');
Img1.Text = SSettings[0];
Img2.Text = SSettings[1];
VideoOut.Text = SSettings[2];
FrameRate.SelectedIndex = int.Parse(SSettings[3]);
AspectRatio.SelectedIndex = int.Parse(SSettings[4]);
Resolution.SelectedIndex = int.Parse(SSettings[5]);
Direction.SelectedIndex = int.Parse(SSettings[6]);
Motion.SelectedIndex = int.Parse(SSettings[7]);
GPUOffload.Text = SSettings[8];
LowMemoryMode.Checked = bool.Parse(SSettings[9]);
Steps.Text = SSettings[10];
Cfg.Text = SSettings[11];
Seed.Text = SSettings[12];
Scheduler.SelectedIndex = int.Parse(SSettings[13]);
if (File.Exists(Img1.Text)) { pictureBox1.BackgroundImage = new Bitmap(Img1.Text); }
if (File.Exists(Img2.Text)) { pictureBox2.BackgroundImage = new Bitmap(Img2.Text); }
else { pictureBox2.BackgroundImage = null; }
}
private string GetTimestamp()
{
DateTime currentTime = DateTime.UtcNow;
long unixTime = ((DateTimeOffset)currentTime).ToUnixTimeSeconds();
return unixTime.ToString();
}
private void AppendTextBox(string value)
{
if (InvokeRequired)
{
this.Invoke(new Action<string>(AppendTextBox), new object[] { value });
return;
}
this.Text = "Ruyi-GUI " + value;
}
private string AssemblyDirectory()
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
public byte[] GetHash(string inputString)
{
using (HashAlgorithm algorithm = SHA256.Create()) { return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString)); }
}
public string GetHashString(string inputString)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in GetHash(inputString)) { sb.Append(b.ToString("X2")); }
return sb.ToString();
}
private void LogFiltered(string message)
{
if (string.IsNullOrEmpty(message)) { return; }
LogMessages.Add(message);
if (message.Contains("%")) { AppendTextBox(message); }
if (message.Contains("100%") && Not100) { Not100 = false; return; }
if (message.Contains("100%"))
{
Not100 = true;
AppendTextBox("Saving Mp4...");
GenerateButton.BeginInvoke(new Action(() => { GenerateButton.Enabled = true; }));
panel1.BeginInvoke(new Action(() => { panel1.Enabled = true; }));
if (DoingJobs)
{
while (!File.Exists(VideoOut.Text)) { Thread.Sleep(1000); }
DoingJobs = false;
string Job = Path.Combine("Jobs", JobList.Items[0].ToString());
if (File.Exists(Job)) { File.Delete(Job); }
JobList.Items.RemoveAt(0);
return;
}
Task.Run(() =>
{
while (!File.Exists(VideoOut.Text)) { Thread.Sleep(1000); }
AppendTextBox("");
});
}
}
public static string Decompress(byte[] data)
{
MemoryStream input = new MemoryStream(data);
MemoryStream output = new MemoryStream();
using (DeflateStream dstream = new DeflateStream(input, CompressionMode.Decompress))
{
dstream.CopyTo(output);
}
return Convert.ToBase64String(output.ToArray());
}
private void GenerateButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(VideoOut.Text)) { MessageBox.Show("You Must Select A Video Output", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
if (string.IsNullOrEmpty(Img1.Text)) { MessageBox.Show("You Must Select A Input Image", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
ExecuteCommand();
}
private void ExecuteCommand()
{
string Image2 = string.IsNullOrEmpty(Img2.Text) ? "None" : @"""" + Img2.Text.Replace(@"\", @"\\") + @"""";
string CallCode = PythonCode.Replace("{$IMAGE1}", Img1.Text.Replace(@"\", @"\\")).Replace("{$IMAGE2}", Image2).Replace("{$VIDEO}", VideoOut.Text.Replace(@"\", @"\\")).Replace("{$FRAMES}", FrameRate.Text).Replace("{$RES}", Resolution.Text).Replace("{$ASPECT}", AspectRatio.Text).Replace("{$MOTION}", Motion.Text).Replace("{$DIRECTION}", Direction.Text).Replace("{$STEPS}", Steps.Text).Replace("{$CFG}", Cfg.Text).Replace("{$SCHEDULER}", Scheduler.Text).Replace("{$LOWMEM}", LowMemoryMode.Checked.ToString()).Replace("{$OFFLOAD}", GPUOffload.Text).Replace("{$SEED}", Seed.Text);
File.WriteAllText(Path.Combine("Ruyi-Models", "i2v.py"), CallCode);
if (File.Exists(VideoOut.Text)) { File.Move(VideoOut.Text, VideoOut.Text.Replace(".mp4", "-" + GetTimestamp() + ".mp4")); }
Task.Run(() =>
{
GenerateButton.BeginInvoke(new Action(() => { GenerateButton.Enabled = false; }));
panel1.BeginInvoke(new Action(() => { panel1.Enabled = false; }));
AppendTextBox("Loading AI Please Wait...");
var processInfo = new ProcessStartInfo("cmd.exe", "/c call " + Path.Combine(AssemblyDirectory(), "environment.bat") + " && cd " + Path.Combine(AssemblyDirectory(), "Ruyi-Models") + " && python i2v.py %*");
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
var process = Process.Start(processInfo);
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => LogFiltered(e.Data);
process.BeginOutputReadLine();
process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => LogFiltered(e.Data);
process.BeginErrorReadLine();
process.WaitForExit();
process.Close();
});
}
private string SelectImageButton()
{
string path = "";
var dialog = new OpenFileDialog();
dialog.Title = "Open Image";
dialog.Filter = "Image Files (*.jpg;*.jpeg,*.png)|*.JPG;*.JPEG;*.PNG";
if (dialog.ShowDialog() == DialogResult.OK) { path = dialog.FileName; }
dialog.Dispose();
return path;
}
private void SelectImg1_Click(object sender, EventArgs e)
{
Img1.Text = SelectImageButton();
if (string.IsNullOrEmpty(Img1.Text))
{
pictureBox1.BackgroundImage = null;
return;
}
pictureBox1.BackgroundImage = new Bitmap(Img1.Text);
}
private void SelectImg2_Click(object sender, EventArgs e)
{
Img2.Text = SelectImageButton();
if (string.IsNullOrEmpty(Img2.Text))
{
pictureBox2.BackgroundImage = null;
return;
}
pictureBox2.BackgroundImage = new Bitmap(Img2.Text);
}
private void SelectVideoOut_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Video Output|*.mp4";
saveFileDialog1.Title = "Save an Video File";
saveFileDialog1.ShowDialog();
VideoOut.Text = saveFileDialog1.FileName;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { SaveSettings(); }
private void PlayVideo_Click(object sender, EventArgs e)
{
if (File.Exists(VideoOut.Text))
{
System.Diagnostics.Process.Start(VideoOut.Text);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (File.Exists(VideoOut.Text)) { PlayVideo.Enabled = true; }
else { PlayVideo.Enabled = false; }
if (LogMessages.Count > 0)
{
File.AppendAllLines("log.txt", LogMessages);
LogMessages.Clear();
}
}
private void AddJob_Click(object sender, EventArgs e)
{
string Settings = SettingsString();
string Job = GetHashString(Settings);
if (JobList.Items.Contains(Job)) { return; }
if (!Directory.Exists("Jobs")) { Directory.CreateDirectory("Jobs"); }
File.WriteAllText(Path.Combine("Jobs", Job), Settings);
JobList.Items.Add(Job);
}
private void RemoveJob_Click(object sender, EventArgs e)
{
if (JobList.SelectedIndex == -1) return;
string Job = Path.Combine("Jobs", JobList.Items[JobList.SelectedIndex].ToString());
if (File.Exists(Job)) { File.Delete(Job); }
JobList.Items.RemoveAt(JobList.SelectedIndex);
}
private void RunJobs_Click(object sender, EventArgs e)
{
timer2.Enabled = true;
RunJobs.Enabled = false;
JobList.Enabled = false;
AddJob.Enabled = false;
RemoveJob.Enabled = false;
JobList.SelectedIndex = -1;
}
private void timer2_Tick(object sender, EventArgs e)
{
if (DoingJobs) { return; }
if (JobList.Items.Count > 0)
{
DoingJobs = true;
UpdateJobList(true);
this.Update();
ExecuteCommand();
}
else
{
AppendTextBox("");
RunJobs.Enabled = true;
JobList.Enabled = true;
AddJob.Enabled = true;
RemoveJob.Enabled = true;
timer2.Enabled = false;
DoingJobs = false;
return;
}
}
private void UpdateJobList(bool Force = false)
{
if (JobList.SelectedIndex == -1 && !Force) { return; }
int index = (JobList.SelectedIndex == -1) ? 0 : JobList.SelectedIndex;
if (File.Exists(Path.Combine("Jobs", JobList.Items[index].ToString())))
{
LoadSettings(File.ReadAllText(Path.Combine("Jobs", JobList.Items[index].ToString())));
}
}
private void JobList_SelectedIndexChanged(object sender, EventArgs e) { UpdateJobList(); }
private void Batch_Click(object sender, EventArgs e)
{
if (this.Width == 810) { this.Width = 575; JobList.Items.Clear(); }
else
{
if (Directory.Exists("Jobs"))
{
DirectoryInfo d = new DirectoryInfo("Jobs");
FileInfo[] Files = d.GetFiles("*"); //Getting Text files
foreach (FileInfo file in Files)
{
if (file.Name.Length == 64)
{
if (!JobList.Items.Contains(file.Name))
{
JobList.Items.Add(file.Name);
}
}
}
}
this.Width = 810;
}
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Ruyi_GUI
{
public partial class Form1 : Form
{
public static List<string> LogMessages = new List<string>();
public string PythonCode;
public bool DoingJobs = false;
public bool Not100 = true;
public Form1()
{
InitializeComponent();
PythonCode = Encoding.UTF8.GetString(Convert.FromBase64String(Decompress(Convert.FromBase64String("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"))));
if (File.Exists("Config.cfg")) { LoadSettings(File.ReadAllText("Config.cfg")); }
else { SaveSettings(); }
if(!File.Exists("environment.bat"))
{
MessageBox.Show("environment.bat file missing, Is this exe being ran from Forge Install folder?","Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
private string SettingsString() { return Img1.Text + "|" + Img2.Text + "|" + VideoOut.Text + "|" + FrameRate.Text + "|" + AspectRatio.Text + "|" + Resolution.Text + "|" + Direction.Text + "|" + Motion.Text + "|" + GPUOffload.Text + "|" + LowMemoryMode.Checked + "|" + Steps.Text + "|" + Cfg.Text + "|" + Seed.Text + "|" + Scheduler.Text + "|" + VideoRes.Text + "|" + Loratxt.Text + "|" + Weighttxt.Text; }
private void SaveSettings() { File.WriteAllText("Config.cfg", SettingsString()); }
private void LoadSettings(string Settings)
{
try
{
string[] SSettings = Settings.Split('|');
Img1.Text = SSettings[0];
Img2.Text = SSettings[1];
VideoOut.Text = SSettings[2];
FrameRate.Text = SSettings[3];
AspectRatio.Text = SSettings[4];
Resolution.Text = SSettings[5];
Direction.Text = SSettings[6];
Motion.Text = SSettings[7];
GPUOffload.Text = SSettings[8];
LowMemoryMode.Checked = bool.Parse(SSettings[9]);
Steps.Text = SSettings[10];
Cfg.Text = SSettings[11];
Seed.Text = SSettings[12];
Scheduler.Text = SSettings[13];
VideoRes.Text = SSettings[14];
Loratxt.Text = SSettings[15];
Weighttxt.Text = SSettings[16];
}
catch
{
MessageBox.Show("Fault loading Config.cfg, Maybe Try Delete it so it can regenerate.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
if (File.Exists(Img1.Text)) { pictureBox1.BackgroundImage = new Bitmap(Img1.Text); }
if (File.Exists(Img2.Text)) { pictureBox2.BackgroundImage = new Bitmap(Img2.Text); }
else { pictureBox2.BackgroundImage = null; }
}
private string GetTimestamp()
{
DateTime currentTime = DateTime.UtcNow;
long unixTime = ((DateTimeOffset)currentTime).ToUnixTimeSeconds();
return unixTime.ToString();
}
private void AppendTextBox(string value)
{
if (InvokeRequired)
{
this.Invoke(new Action<string>(AppendTextBox), new object[] { value });
return;
}
this.Text = "Ruyi-GUI " + value;
}
private string AssemblyDirectory()
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
public byte[] GetHash(string inputString)
{
using (HashAlgorithm algorithm = SHA256.Create()) { return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString)); }
}
public string GetHashString(string inputString)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in GetHash(inputString)) { sb.Append(b.ToString("X2")); }
return sb.ToString();
}
private void LogFiltered(string message)
{
if (string.IsNullOrEmpty(message)) { return; }
LogMessages.Add(message);
if (message.Contains("%")) { AppendTextBox(message); }
if (message.Contains("100%") && Not100) { Not100 = false; return; }
if (message.Contains("100%"))
{
Not100 = true;
AppendTextBox("Saving Mp4...");
GenerateButton.BeginInvoke(new Action(() => { GenerateButton.Enabled = true; }));
panel1.BeginInvoke(new Action(() => { panel1.Enabled = true; }));
if (DoingJobs)
{
while (!File.Exists(VideoOut.Text)) { Thread.Sleep(1000); }
DoingJobs = false;
string Job = Path.Combine("Jobs", JobList.Items[0].ToString());
if (File.Exists(Job)) { File.Delete(Job); }
JobList.Items.RemoveAt(0);
return;
}
Task.Run(() =>
{
while (!File.Exists(VideoOut.Text)) { Thread.Sleep(1000); }
AppendTextBox("");
});
}
}
public static string Decompress(byte[] data)
{
MemoryStream input = new MemoryStream(data);
MemoryStream output = new MemoryStream();
using (DeflateStream dstream = new DeflateStream(input, CompressionMode.Decompress))
{
dstream.CopyTo(output);
}
return Convert.ToBase64String(output.ToArray());
}
private void GenerateButton_Click(object sender, EventArgs e)
{
if (ValidateInOut())
{
if (this.Width == 810) { this.Width = 575; JobList.Items.Clear(); }
ExecuteCommand();
}
}
private void ExecuteCommand()
{
if (!Directory.Exists("Ruyi-Models"))
{
MessageBox.Show("Missing Ruyi-Models Folder", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string Image2 = string.IsNullOrEmpty(Img2.Text) ? "None" : @"""" + Img2.Text.Replace(@"\", @"\\") + @"""";
string Lora = string.IsNullOrEmpty(Loratxt.Text) ? "None" : @"""" + Loratxt.Text.Replace(@"\", @"\\") + @"""";
string CallCode = PythonCode.Replace("{$IMAGE1}", Img1.Text.Replace(@"\", @"\\")).Replace("{$IMAGE2}", Image2).Replace("{$VIDEO}", VideoOut.Text.Replace(@"\", @"\\")).Replace("{$FRAMES}", FrameRate.Text).Replace("{$RES}", Resolution.Text).Replace("{$ASPECT}", AspectRatio.Text).Replace("{$MOTION}", Motion.Text).Replace("{$DIRECTION}", Direction.Text).Replace("{$STEPS}", Steps.Text).Replace("{$CFG}", Cfg.Text).Replace("{$SCHEDULER}", Scheduler.Text).Replace("{$LOWMEM}", LowMemoryMode.Checked.ToString()).Replace("{$OFFLOAD}", GPUOffload.Text).Replace("{$SEED}", Seed.Text).Replace("video_size = None", "video_size = " + VideoRes.Text.Replace("auto","None")).Replace("lora_path = None", "lora_path = " + Lora).Replace("lora_weight = 1.0", "lora_weight = " + Weighttxt.Text);
File.WriteAllText(Path.Combine("Ruyi-Models", "i2v.py"), CallCode);
if (File.Exists(VideoOut.Text)) { File.Move(VideoOut.Text, VideoOut.Text.Replace(".mp4", "-" + GetTimestamp() + ".mp4")); }
Task.Run(() =>
{
GenerateButton.BeginInvoke(new Action(() => { GenerateButton.Enabled = false; }));
panel1.BeginInvoke(new Action(() => { panel1.Enabled = false; }));
AppendTextBox("Loading AI Please Wait...");
var processInfo = new ProcessStartInfo("cmd.exe", "/c call " + Path.Combine(AssemblyDirectory(), "environment.bat") + " && cd " + Path.Combine(AssemblyDirectory(), "Ruyi-Models") + " && python i2v.py %*");
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
var process = Process.Start(processInfo);
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => LogFiltered(e.Data);
process.BeginOutputReadLine();
process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => LogFiltered(e.Data);
process.BeginErrorReadLine();
process.WaitForExit();
process.Close();
});
}
private string SelectImageButton()
{
string path = "";
var dialog = new OpenFileDialog();
dialog.Title = "Open Image";
dialog.Filter = "Image Files (*.jpg;*.jpeg,*.png)|*.JPG;*.JPEG;*.PNG";
if (dialog.ShowDialog() == DialogResult.OK) { path = dialog.FileName; }
dialog.Dispose();
return path;
}
private void SelectImg1_Click(object sender, EventArgs e)
{
Img1.Text = SelectImageButton();
if (string.IsNullOrEmpty(Img1.Text))
{
pictureBox1.BackgroundImage = null;
return;
}
pictureBox1.BackgroundImage = new Bitmap(Img1.Text);
}
private void SelectImg2_Click(object sender, EventArgs e)
{
Img2.Text = SelectImageButton();
if (string.IsNullOrEmpty(Img2.Text))
{
pictureBox2.BackgroundImage = null;
return;
}
pictureBox2.BackgroundImage = new Bitmap(Img2.Text);
}
private void SelectVideoOut_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Video Output|*.mp4";
saveFileDialog1.Title = "Save an Video File";
saveFileDialog1.ShowDialog();
VideoOut.Text = saveFileDialog1.FileName;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { SaveSettings(); }
private void PlayVideo_Click(object sender, EventArgs e)
{
if (File.Exists(VideoOut.Text))
{
System.Diagnostics.Process.Start(VideoOut.Text);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (File.Exists(VideoOut.Text)) { PlayVideo.Enabled = true; }
else { PlayVideo.Enabled = false; }
if (LogMessages.Count > 0)
{
File.AppendAllLines("log.txt", LogMessages);
LogMessages.Clear();
}
}
private bool ValidateInOut()
{
if (string.IsNullOrEmpty(VideoOut.Text)) { MessageBox.Show("You Must Select A Video Output", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(Img1.Text)) { MessageBox.Show("You Must Select A Input Image", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(FrameRate.Text)) { MessageBox.Show("Frame Rate Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(AspectRatio.Text)) { MessageBox.Show("Aspect Ratio Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(Resolution.Text)) { MessageBox.Show("Resolution Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(Direction.Text)) { MessageBox.Show("Direction Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(Motion.Text)) { MessageBox.Show("Motion Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(VideoRes.Text)) { MessageBox.Show("Mp4 Resolution Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(GPUOffload.Text)) { MessageBox.Show("GPU Offload Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(Steps.Text)) { MessageBox.Show("Steps Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(Cfg.Text)) { MessageBox.Show("Cfg Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(Seed.Text)) { MessageBox.Show("Seed Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(Scheduler.Text)) { MessageBox.Show("Scheduler Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (string.IsNullOrEmpty(Weighttxt.Text)) { MessageBox.Show("Lora Weight Can't Be Null", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if(!AspectRatio.Text.Contains(":")){ MessageBox.Show("Aspect Ratio Not Valid Format", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
if (!VideoRes.Text.Contains(", ") && !VideoRes.Text.Contains("None")) { MessageBox.Show("Mp4 Resolution Not Valid Format", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; }
return true;
}
private void AddJob_Click(object sender, EventArgs e)
{
if (ValidateInOut())
{
string Settings = SettingsString();
string Job = GetHashString(Settings);
if (JobList.Items.Contains(Job)) { return; }
if (!Directory.Exists("Jobs")) { Directory.CreateDirectory("Jobs"); }
File.WriteAllText(Path.Combine("Jobs", Job), Settings);
JobList.Items.Add(Job);
}
}
private void RemoveJob_Click(object sender, EventArgs e)
{
if (JobList.SelectedIndex == -1) return;
string Job = Path.Combine("Jobs", JobList.Items[JobList.SelectedIndex].ToString());
if (File.Exists(Job)) { File.Delete(Job); }
JobList.Items.RemoveAt(JobList.SelectedIndex);
}
private void RunJobs_Click(object sender, EventArgs e)
{
timer2.Enabled = true;
RunJobs.Enabled = false;
JobList.Enabled = false;
AddJob.Enabled = false;
RemoveJob.Enabled = false;
JobList.SelectedIndex = -1;
}
private void timer2_Tick(object sender, EventArgs e)
{
if (DoingJobs) { return; }
if (JobList.Items.Count > 0)
{
DoingJobs = true;
UpdateJobList(true);
this.Update();
ExecuteCommand();
}
else
{
AppendTextBox("");
RunJobs.Enabled = true;
JobList.Enabled = true;
AddJob.Enabled = true;
RemoveJob.Enabled = true;
timer2.Enabled = false;
DoingJobs = false;
return;
}
}
private void UpdateJobList(bool Force = false)
{
if (JobList.SelectedIndex == -1 && !Force) { return; }
int index = (JobList.SelectedIndex == -1) ? 0 : JobList.SelectedIndex;
if (File.Exists(Path.Combine("Jobs", JobList.Items[index].ToString())))
{
LoadSettings(File.ReadAllText(Path.Combine("Jobs", JobList.Items[index].ToString())));
}
}
private void JobList_SelectedIndexChanged(object sender, EventArgs e) { UpdateJobList(); }
private void Batch_Click(object sender, EventArgs e)
{
if (this.Width == 810) { this.Width = 575; JobList.Items.Clear(); GenerateButton.Enabled = true; }
else
{
GenerateButton.Enabled = false;
if (Directory.Exists("Jobs"))
{
DirectoryInfo d = new DirectoryInfo("Jobs");
FileInfo[] Files = d.GetFiles("*"); //Getting Text files
foreach (FileInfo file in Files)
{
if (file.Name.Length == 64)
{
if (!JobList.Items.Contains(file.Name))
{
JobList.Items.Add(file.Name);
}
}
}
}
this.Width = 810;
}
}
private void AspectRatio_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar) && e.KeyChar != ':';
}
private void NumberOnly(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);
}
private void Cfg_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar) && e.KeyChar != '.';
}
private void NumberAndAuto(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar) && e.KeyChar != 'a' && e.KeyChar != 'u' && e.KeyChar != 't' && e.KeyChar != 'o';
}
private void VideoRes_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar) && e.KeyChar != ',' && e.KeyChar != ' ' && e.KeyChar != 'N' && e.KeyChar != 'o' && e.KeyChar != 'n' && e.KeyChar != 'e' && e.KeyChar != 'a' && e.KeyChar != 'u' && e.KeyChar != 't';
}
private void LoraButton_Click(object sender, EventArgs e)
{
var dialog = new OpenFileDialog();
dialog.Title = "Select Lora File";
dialog.Filter = "safetensors (*.safetensors)|*.safetensors";
if (dialog.ShowDialog() == DialogResult.OK) { Loratxt.Text = dialog.FileName; }
dialog.Dispose();
}
}
}

View File

@ -1,203 +1,203 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="timer2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>105, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEgwAaVVVADEp
JQg2LSoXNi4sGjQtKxozKykbMSknHC4nJR4tJSMfLCQhHi0kIB0tJCAeLCMgHywjHx0qIh4dJx8bFyAb
FwZCNjMACAcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtKSIAQzc1ADsy
LRg+NDFrQDYytj41MtY7MzDaOjEw2zkwLts5Ly3cNy0r3TUrKd4zKSfeMygl3TMoJN4yJyTfMick3jEn
JN0xJyTWMikmsjQrJ2w0LCcYNywpACspIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMysnAEY6
NwA+NDA1QTczw0E2M/1IOzr/VEpI/1RLSf9LQkH/Qzo5/zwzMf88MjD/OjAt/zkuLP85Liv/OCwp/zcr
Kf83Kyn/PDEv/z80Mf85Ly3/OjAt/TsxLsI6MC00PzQyADEsJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAsJ
BwBANTIAPzQwJkE3NM5BNzT/YVdU/pyUk/6spqf+raiq/oV+gP5eU1L+Wk5N/l9SUf5oWln+XE5N/k9B
QP5BNTL+PDAu/kg7Ov5hU1D9cWNf/WRWUv5IPDn+PjMx/z0zMM07MS0kOzIuABghFAAAAAAAAAAAAAAA
AAAAAAAAOjAsADMpJgNBNjKXQTYz/2hdXP6gmZj+bGVm/mZfY/5+d3v9f3R1/m1fXf6Kenb+mImI/p2Q
kv6HeHf+eWdh/m9fWf5NQD7+XlBN/lhMS/5VTE3+eXBw/H5ycPtNQT3+PTMw/z0zL5I2LScCOzEtAAAA
AAAAAAAAAAAAAAAAAABAMi8APzEvKkE1MuRPREL/m5SU/oF7gP1sZGn+g3l+/piNj/6DdG/+d2hl/qeb
mv6mm5v+p5ye/pOGhv6Le3f+kH93/nVlYP5/bmn+YFBL/kg+P/5lXGH9l5KZ+ntvbv1CNjP/PDIv3zsx
LSQ7MS4AAAAAAAAAAAAAAAAAAAAAAEEyMAA/Mi9ZPzIw/HRqaf16dHf4YFlg/XVsdP6XkJj+rKSr/oR3
eP5wZmf+u7a6/sbCx/63sbb+rKSo/qacnf6UhoX+dmpr/pmMiv16Z17+W0xK/llQVf6XlJ77npmg/FpN
TP48MS76PDEuUDwxLwAAAAAAAAAAAAAAAAAAAAAAPTIvAD4yMHM9MTD/hHp792ljZvFXTlP+aWJo/rKw
uv7Cvsj+n5ef/omCiP6tqKz+pKGk/oiDiP5+d3v+h31//oJ2dv56bnD+qaGn/Ip5c/xlU0z9XVRZ/ndw
d/ydm6X5dm1w/DwxLv88MS5rPTIvAAAAAAAAAAAAAAAAAAAAAAA5LywAPTIwdjswLv9ZUFDwa2Vo721l
av59eID+u7rH/sC/y/6uqbT+qaOq/mpjZ/5JQkf+QztA/jIqLf43MDP+VkxM/oBwa/6QgH79hXNt/GhV
TfxZTU79bGVq/I2Kk/l8dnv7PTIv/zwxLnI+Mi8AAAAAAAAAAAAAAAAAAAAAADctKwA7MS51OS8s/0xD
ROdzbXHme3R6+5KRm/vMztv+u7nF/qGZof5nX2T+V1BY/n11fP55b3P+ZFdV/VpOTv04LzH+UUI+/oVz
bP2Bb2n8c2BX/FNGRP1PRkn+bGVq+3dvc/o+Mi//PDEucj4yMAAAAAAAAAAAAAAAAAAAAAAANy0rADow
LnQ4Ly3/TUVF3GplaOJ8d336WlZd866vuP2inqn+g3p+/ldPVv5/d379hX2A/oyDg/6JfXv+ZldV/kU2
Nf43Kyr+dGRg/mVXVf1iUkr9QDY2/lBHSv5tZ2v7gnyB9T4yMP87MC1zPTEvAAAAAAAAAAAAAAAAAAAA
AAA4KysAOy8udDgtLf9MRETXamVp142MmvtSTVn1l5ag/IiDi/5nXmP+f3mA+5+Xmf1zZ2b+X1NQ/nFm
Y/6ajoz+Xk5K/jUrKv5rX17+ZVla/lVGQv5IP0L+XVVb/lxSU/1dU1T8PDEv/zkvLXM7MS4AAAAAAAAA
AAAAAAAAAAAAADcrKwA6Ly50Ny0t/1BJS9dsZ23XlJOh+WBaZvnCwsr9yMbL/mJXXP6Lho38d21s/jsv
K/4uIx7+Myci/mxgXf5vYVz+RDc1/nx1eP6wp6n9bl9a/ltRVf5sYWf+UkZF/lxSUf47Mi//OTAtczox
LgAAAAAAAAAAAAAAAAAAAAAANisrADovL3Q1Kyv/Ylpd8ZOQmfWWlKH5Y15p+sTEzf3Y1tv+cmlv/peU
mv57cXH+VEpJ/iofHP4kGRX+Qjcz/nBjX/5QQkD+iIGE/raur/1vYFv+YVhc/nFlav5XSEf+VUlI/Tsx
L/85MC10OTAtAAAAAAAAAAAAAAAAAAAAAAA2KisAOi4vdDUrK/9mYGTtnpyr7qqpuPhcWWz5mZej/b66
wf6JgYj+ioaM/rKsrf7Cvbz+RTs5/iAVEv5WTEr+aVpW/ks/P/6gmZz+fHFu/lBCPf5qY2r+iICL/lpO
Uv5KPz/9OjEu/zkvLXU5MC0AAAAAAAAAAAAAAAAAAAAAADUoKgA5LS50NSkr/1BKTvOMiZPvgoGQ7EpH
VfilpK7+4+Hm/qOdov5oYmf+p6Cj/pWLif5uY1/+cGVj/o2Cgv5jU0/+XFNU/q2kpP6KenT+UkQ//kxG
TP5mYGz+Z1xg/FFGRvg5Lyz/OS8sdTguLAAAAAAAAAAAAAAAAAAAAAAANScpADotL3Q1KCv/Vk5R9pKP
mPWAeoH2gXqD+bi4xv309vr+z8vQ/oqEiv6zrrH+raao/qegoP6poaL+pZyc/nFmZf6YkZP9rKGf/pGA
ef5qWlf+U0VD/U5APf5YTEr+UEZH/DguLP83LSt2NywqAAAAAAAAAAAAAAAAAAAAAAA0JykAOS4vczIn
KP9uZ2r1wcDF9srJzfbAvsPksrG79ODh5/6xrbL8lI+T/ODf4PzOysr839zc/cXAv/yaj477d2xt/JWP
k/2tpKT8lIV//XhpZviJfHjqdGNc+Hhsavx1bW76Nywr/zYsKnY2KyoAAAAAAAAAAAAAAAAAAAAAADQo
KQA7MDB0MSYn/0xERvucmZz4vLm7+sLAw+zNy83v4+Pm/dHO0v6po6f9q6ep/be0tfySjY38gXp5/G1l
ZPuAd3r7q6Om/Ly0tPykmZb9jYF/75SKiOeIe3j3mI+O+WBXV/s0Kin/NSsqdjYrKwAAAAAAAAAAAAAA
AAAAAAAAPjI0AEI3OHAzJyn/PTQ2/Y2Iivaln6H7ramr9JWQkPjCwML+6Obo/uro6f7V0tT+trO2/oeC
hv1xaWv9kYeH/b+4t/zQycj8y8TE/qSbmv6MgoD4oZeW+IyDgvdyamv3QTc3/DQpKf8zKSluNSoqAAAA
AAAAAAAAAAAAAAAAAABLQUMASkBBUjkvMfouJCb+ZF1f97Gtr/aVkJH3lJCP7aWhofOkn6H82tfZ/uzq
6v7V09b+kouP/ntwcP6jmJX+xLy6/bWtrP2lnZz+o5qY/o6Dgf6BeHf9YFZV/EI4OPwzKCn+NCgp+DMo
KE0zKCgAAAAAAAAAAAAAAAAAAAAAAEtDRABPR0gcSD5A1TAnKP80Kyz9f3l79ZCMj9t7dnbKkYyM67+8
vfXU0NL+9/X1/vHv8P7Lx8j7xsHB++Le3v7EvLr8rKKi/bWtrf6gl5b8bWRj/VlQUPxNQkL9Ny0t/jIn
Kf8zKCnONSoqGDUpKgAAAAAAAAAAAAAAAAAAAAAAUEhKAHdvbQBcVVZuSkFC+i8lJf8zKCr9RDw86kM8
O9ZeV1fwgXt66aumpvHW1NP+2dfW/aynpt6no6Ld0M3M/qylovyIfXv5joWE+JKKie5fVlX5Qjg4/Tcs
Lf4xJij/NSor9jcsLWI0KCkAOjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAeXJzAHx1dw10bW2XXFNT+z0y
M/8wJSb/MSYn/zQqKf0zKCf7OC4t+0I5OP9COTj/OS8u+zcuLPtBODf/PjU0/zctLP42Kyr+OzEw/DQq
Kf8xJyf/Niss/0A0NfREODmCPTIyCD80NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlY+PAJ6X
lw6LhYVwfXV0zmphYPFeU1L3WU9N91dNSvVVSkjzU0hG8FJHRO5TSEXsU0hF7FNIRetTSUbrVElG7FRJ
RuxUSUbuVUpH8FVKSedWSUm4U0hHVU5EQgdQRUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAzsvKAPLz8gGpo6EVmJGPOIuCf0Z9dXFFcmpmQmhgXD5eVVI5WlBNM1tRTTBeVE8uYFVRLmJX
Ui1iV1MuYldSL2JYUzFjWVU0YVdUKFpRTgtuXl8AREY9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/////////////////wAA//wAAD/4AAAf8AAAD+AAAAfgAAAH4AAAB+AA
AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AA
AA/wAAAP+AAAH/wAAH////////////////8=
</value>
</data>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="timer2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>105, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVEgwAaVVVADEp
JQg2LSoXNi4sGjQtKxozKykbMSknHC4nJR4tJSMfLCQhHi0kIB0tJCAeLCMgHywjHx0qIh4dJx8bFyAb
FwZCNjMACAcDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtKSIAQzc1ADsy
LRg+NDFrQDYytj41MtY7MzDaOjEw2zkwLts5Ly3cNy0r3TUrKd4zKSfeMygl3TMoJN4yJyTfMick3jEn
JN0xJyTWMikmsjQrJ2w0LCcYNywpACspIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMysnAEY6
NwA+NDA1QTczw0E2M/1IOzr/VEpI/1RLSf9LQkH/Qzo5/zwzMf88MjD/OjAt/zkuLP85Liv/OCwp/zcr
Kf83Kyn/PDEv/z80Mf85Ly3/OjAt/TsxLsI6MC00PzQyADEsJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAsJ
BwBANTIAPzQwJkE3NM5BNzT/YVdU/pyUk/6spqf+raiq/oV+gP5eU1L+Wk5N/l9SUf5oWln+XE5N/k9B
QP5BNTL+PDAu/kg7Ov5hU1D9cWNf/WRWUv5IPDn+PjMx/z0zMM07MS0kOzIuABghFAAAAAAAAAAAAAAA
AAAAAAAAOjAsADMpJgNBNjKXQTYz/2hdXP6gmZj+bGVm/mZfY/5+d3v9f3R1/m1fXf6Kenb+mImI/p2Q
kv6HeHf+eWdh/m9fWf5NQD7+XlBN/lhMS/5VTE3+eXBw/H5ycPtNQT3+PTMw/z0zL5I2LScCOzEtAAAA
AAAAAAAAAAAAAAAAAABAMi8APzEvKkE1MuRPREL/m5SU/oF7gP1sZGn+g3l+/piNj/6DdG/+d2hl/qeb
mv6mm5v+p5ye/pOGhv6Le3f+kH93/nVlYP5/bmn+YFBL/kg+P/5lXGH9l5KZ+ntvbv1CNjP/PDIv3zsx
LSQ7MS4AAAAAAAAAAAAAAAAAAAAAAEEyMAA/Mi9ZPzIw/HRqaf16dHf4YFlg/XVsdP6XkJj+rKSr/oR3
eP5wZmf+u7a6/sbCx/63sbb+rKSo/qacnf6UhoX+dmpr/pmMiv16Z17+W0xK/llQVf6XlJ77npmg/FpN
TP48MS76PDEuUDwxLwAAAAAAAAAAAAAAAAAAAAAAPTIvAD4yMHM9MTD/hHp792ljZvFXTlP+aWJo/rKw
uv7Cvsj+n5ef/omCiP6tqKz+pKGk/oiDiP5+d3v+h31//oJ2dv56bnD+qaGn/Ip5c/xlU0z9XVRZ/ndw
d/ydm6X5dm1w/DwxLv88MS5rPTIvAAAAAAAAAAAAAAAAAAAAAAA5LywAPTIwdjswLv9ZUFDwa2Vo721l
av59eID+u7rH/sC/y/6uqbT+qaOq/mpjZ/5JQkf+QztA/jIqLf43MDP+VkxM/oBwa/6QgH79hXNt/GhV
TfxZTU79bGVq/I2Kk/l8dnv7PTIv/zwxLnI+Mi8AAAAAAAAAAAAAAAAAAAAAADctKwA7MS51OS8s/0xD
ROdzbXHme3R6+5KRm/vMztv+u7nF/qGZof5nX2T+V1BY/n11fP55b3P+ZFdV/VpOTv04LzH+UUI+/oVz
bP2Bb2n8c2BX/FNGRP1PRkn+bGVq+3dvc/o+Mi//PDEucj4yMAAAAAAAAAAAAAAAAAAAAAAANy0rADow
LnQ4Ly3/TUVF3GplaOJ8d336WlZd866vuP2inqn+g3p+/ldPVv5/d379hX2A/oyDg/6JfXv+ZldV/kU2
Nf43Kyr+dGRg/mVXVf1iUkr9QDY2/lBHSv5tZ2v7gnyB9T4yMP87MC1zPTEvAAAAAAAAAAAAAAAAAAAA
AAA4KysAOy8udDgtLf9MRETXamVp142MmvtSTVn1l5ag/IiDi/5nXmP+f3mA+5+Xmf1zZ2b+X1NQ/nFm
Y/6ajoz+Xk5K/jUrKv5rX17+ZVla/lVGQv5IP0L+XVVb/lxSU/1dU1T8PDEv/zkvLXM7MS4AAAAAAAAA
AAAAAAAAAAAAADcrKwA6Ly50Ny0t/1BJS9dsZ23XlJOh+WBaZvnCwsr9yMbL/mJXXP6Lho38d21s/jsv
K/4uIx7+Myci/mxgXf5vYVz+RDc1/nx1eP6wp6n9bl9a/ltRVf5sYWf+UkZF/lxSUf47Mi//OTAtczox
LgAAAAAAAAAAAAAAAAAAAAAANisrADovL3Q1Kyv/Ylpd8ZOQmfWWlKH5Y15p+sTEzf3Y1tv+cmlv/peU
mv57cXH+VEpJ/iofHP4kGRX+Qjcz/nBjX/5QQkD+iIGE/raur/1vYFv+YVhc/nFlav5XSEf+VUlI/Tsx
L/85MC10OTAtAAAAAAAAAAAAAAAAAAAAAAA2KisAOi4vdDUrK/9mYGTtnpyr7qqpuPhcWWz5mZej/b66
wf6JgYj+ioaM/rKsrf7Cvbz+RTs5/iAVEv5WTEr+aVpW/ks/P/6gmZz+fHFu/lBCPf5qY2r+iICL/lpO
Uv5KPz/9OjEu/zkvLXU5MC0AAAAAAAAAAAAAAAAAAAAAADUoKgA5LS50NSkr/1BKTvOMiZPvgoGQ7EpH
VfilpK7+4+Hm/qOdov5oYmf+p6Cj/pWLif5uY1/+cGVj/o2Cgv5jU0/+XFNU/q2kpP6KenT+UkQ//kxG
TP5mYGz+Z1xg/FFGRvg5Lyz/OS8sdTguLAAAAAAAAAAAAAAAAAAAAAAANScpADotL3Q1KCv/Vk5R9pKP
mPWAeoH2gXqD+bi4xv309vr+z8vQ/oqEiv6zrrH+raao/qegoP6poaL+pZyc/nFmZf6YkZP9rKGf/pGA
ef5qWlf+U0VD/U5APf5YTEr+UEZH/DguLP83LSt2NywqAAAAAAAAAAAAAAAAAAAAAAA0JykAOS4vczIn
KP9uZ2r1wcDF9srJzfbAvsPksrG79ODh5/6xrbL8lI+T/ODf4PzOysr839zc/cXAv/yaj477d2xt/JWP
k/2tpKT8lIV//XhpZviJfHjqdGNc+Hhsavx1bW76Nywr/zYsKnY2KyoAAAAAAAAAAAAAAAAAAAAAADQo
KQA7MDB0MSYn/0xERvucmZz4vLm7+sLAw+zNy83v4+Pm/dHO0v6po6f9q6ep/be0tfySjY38gXp5/G1l
ZPuAd3r7q6Om/Ly0tPykmZb9jYF/75SKiOeIe3j3mI+O+WBXV/s0Kin/NSsqdjYrKwAAAAAAAAAAAAAA
AAAAAAAAPjI0AEI3OHAzJyn/PTQ2/Y2Iivaln6H7ramr9JWQkPjCwML+6Obo/uro6f7V0tT+trO2/oeC
hv1xaWv9kYeH/b+4t/zQycj8y8TE/qSbmv6MgoD4oZeW+IyDgvdyamv3QTc3/DQpKf8zKSluNSoqAAAA
AAAAAAAAAAAAAAAAAABLQUMASkBBUjkvMfouJCb+ZF1f97Gtr/aVkJH3lJCP7aWhofOkn6H82tfZ/uzq
6v7V09b+kouP/ntwcP6jmJX+xLy6/bWtrP2lnZz+o5qY/o6Dgf6BeHf9YFZV/EI4OPwzKCn+NCgp+DMo
KE0zKCgAAAAAAAAAAAAAAAAAAAAAAEtDRABPR0gcSD5A1TAnKP80Kyz9f3l79ZCMj9t7dnbKkYyM67+8
vfXU0NL+9/X1/vHv8P7Lx8j7xsHB++Le3v7EvLr8rKKi/bWtrf6gl5b8bWRj/VlQUPxNQkL9Ny0t/jIn
Kf8zKCnONSoqGDUpKgAAAAAAAAAAAAAAAAAAAAAAUEhKAHdvbQBcVVZuSkFC+i8lJf8zKCr9RDw86kM8
O9ZeV1fwgXt66aumpvHW1NP+2dfW/aynpt6no6Ld0M3M/qylovyIfXv5joWE+JKKie5fVlX5Qjg4/Tcs
Lf4xJij/NSor9jcsLWI0KCkAOjAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAeXJzAHx1dw10bW2XXFNT+z0y
M/8wJSb/MSYn/zQqKf0zKCf7OC4t+0I5OP9COTj/OS8u+zcuLPtBODf/PjU0/zctLP42Kyr+OzEw/DQq
Kf8xJyf/Niss/0A0NfREODmCPTIyCD80NQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlY+PAJ6X
lw6LhYVwfXV0zmphYPFeU1L3WU9N91dNSvVVSkjzU0hG8FJHRO5TSEXsU0hF7FNIRetTSUbrVElG7FRJ
RuxUSUbuVUpH8FVKSedWSUm4U0hHVU5EQgdQRUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAzsvKAPLz8gGpo6EVmJGPOIuCf0Z9dXFFcmpmQmhgXD5eVVI5WlBNM1tRTTBeVE8uYFVRLmJX
Ui1iV1MuYldSL2JYUzFjWVU0YVdUKFpRTgtuXl8AREY9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/////////////////wAA//wAAD/4AAAf8AAAD+AAAAfgAAAH4AAAB+AA
AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AA
AA/wAAAP+AAAH/wAAH////////////////8=
</value>
</data>
</root>