PinkConnection2/Legacy Tools/PC2Player.Old/PC2Player/MainForm.cs

308 lines
9.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Ports;
using System.Timers;
using Eto.Forms;
using Eto.Drawing;
namespace PC2Player
{
public partial class MainForm : Form
{
SerialPort Port = null;
string[] Signals;
System.Timers.Timer FrameTimer;
long Index = 0;
int FrameSkip = 6;
byte[] AudioData;
Process MPVProcess;
int SkipSeconds = 0;
string ShowtapeName = "";
string ShowtapeStageType = "";
string ShowtapeCharacter = "";
string ShowtapeBits = "";
string ShowtapeFormattedLength = "";
string ControllerCharacter = "";
string ControllerBits = "";
string ControllerHeader = "";
bool ControllerConnected = false;
bool ShowtapeLoaded = false;
bool Playing = false;
DropDown SerialPortDropDown = new DropDown();
Label ShowtapeNameLabel = new Label { Text = "Show Name: Not Loaded" };
Label ShowtapeStageTypeLabel = new Label { Text = "Stage Type: Not Loaded" };
Label ShowtapeCharacterLabel = new Label { Text = "Character: Not Loaded" };
Label ShowtapeBitsLabel = new Label { Text = "Bits: Not Loaded" };
Label ShowtapeLengthLabel = new Label { Text = "Length: Not Loaded" };
Label ControllerCharacterLabel = new Label { Text = "Character: Disconnected" };
Label ControllerBitsLabel = new Label { Text = "Bits: Disconnected" };
Button RefreshPortsButton = new Button { Text = "Refresh Ports", Width = 150 };
Button LoadShowtapeButton = new Button { Text = "Load Showtape", Width = 150 };
Button PlayButton = new Button { Text = "Play" };
Button StopButton = new Button { Text = "Stop" };
public MainForm()
{
Title = "PinkConnection2 Showtape Player";
Size = new Size(500, 450);
Maximizable = false;
Resizable = false;
foreach (string s in SerialPort.GetPortNames())
{
SerialPortDropDown.Items.Add(s);
}
SerialPortDropDown.SelectedValueChanged += (sender, e) => Event_SelectSerialPort();
MPVProcess = new Process();
MPVProcess.StartInfo.FileName = "mpv";
MPVProcess.StartInfo.Arguments = $"--start={SkipSeconds} tmp.wav";
FrameTimer = new System.Timers.Timer((1000d/60d)*FrameSkip);
FrameTimer.Elapsed += Event_FrameTimerTick;
FrameTimer.AutoReset = true;
PlayButton.Enabled = false;
StopButton.Enabled = false;
PlayButton.Command = new Command( (sender, e) => Event_PlayButton() );
StopButton.Command = new Command( (sender, e) => Event_StopButton() );
RefreshPortsButton.Command = new Command( (sender, e) => Event_RefreshPortsButton() );
LoadShowtapeButton.Command = new Command( (sender, e) => Event_LoadShowtapeButton() );
Content = BuildLayout();
}
DynamicLayout BuildLayout()
{
GroupBox showtapeInfoGroupBox = new GroupBox{ Text = "Showtape" };
DynamicLayout showtapeInfoGroupLayout = new DynamicLayout { DefaultSpacing = new Size(5, 5), DefaultPadding = new Padding(5, 5, 5, 5) };
showtapeInfoGroupLayout.AddRow(ShowtapeNameLabel);
showtapeInfoGroupLayout.AddRow(ShowtapeStageTypeLabel);
showtapeInfoGroupLayout.AddRow(ShowtapeCharacterLabel);
showtapeInfoGroupLayout.AddRow(ShowtapeBitsLabel);
showtapeInfoGroupLayout.AddRow(ShowtapeLengthLabel);
showtapeInfoGroupBox.Content = showtapeInfoGroupLayout;
GroupBox controllerInfoGroupBox = new GroupBox{ Text = "Controller" };
DynamicLayout controllerInfoGroupLayout = new DynamicLayout { DefaultSpacing = new Size(5, 5), DefaultPadding = new Padding(5, 5, 5, 5) };
controllerInfoGroupLayout.AddRow(ControllerCharacterLabel);
controllerInfoGroupLayout.AddRow(ControllerBitsLabel);
controllerInfoGroupBox.Content = controllerInfoGroupLayout;
DynamicLayout layout = new DynamicLayout { DefaultSpacing = new Size(10, 10), DefaultPadding = new Padding(5, 5, 5, 5) };
layout.BeginVertical();
layout.BeginHorizontal();
layout.Add(PlayButton, true);
layout.Add(StopButton, true);
layout.EndHorizontal();
layout.EndVertical();
layout.BeginVertical();
layout.BeginHorizontal();
layout.Add(new Label { Text = "Serial Port" });
layout.EndHorizontal();
layout.BeginHorizontal();
layout.Add(SerialPortDropDown, true);
layout.EndHorizontal();
layout.BeginHorizontal();
layout.Add(showtapeInfoGroupBox, true);
layout.EndHorizontal();
layout.BeginHorizontal();
layout.Add(controllerInfoGroupBox, true);
layout.EndHorizontal();
layout.EndVertical();
layout.BeginVertical();
layout.BeginHorizontal();
layout.Add(null, true);
layout.Add(RefreshPortsButton);
layout.Add(LoadShowtapeButton);
layout.EndHorizontal();
layout.EndVertical();
layout.BeginVertical();
layout.Add(null, true);
layout.EndVertical();
return layout;
}
void CheckReady()
{
if (ControllerConnected && ShowtapeLoaded)
{
PlayButton.Enabled = true;
StopButton.Enabled = true;
}
else
{
PlayButton.Enabled = false;
StopButton.Enabled = false;
}
}
void Event_SelectSerialPort()
{
if (Port != null) Port.Close();
Port = new SerialPort((string)SerialPortDropDown.SelectedKey, 9600, Parity.None, 8, StopBits.One);
Port.DataReceived += new SerialDataReceivedEventHandler(Event_PortRecievedData);
ControllerHeader = "";
ControllerCharacterLabel.Text = "Character: Disconnected";
ControllerBitsLabel.Text = "Bits: Disconnected";
ControllerConnected = false;
CheckReady();
Port.Open();
}
void Event_PortRecievedData(object sender, SerialDataReceivedEventArgs e)
{
ControllerHeader += Port.ReadExisting();
if (ControllerHeader.EndsWith(",END"))
{
ControllerBits = ControllerHeader.Split(',')[1];
ControllerCharacter = ControllerHeader.Split(',')[2];
ControllerCharacterLabel.Text = $"Character: {ControllerCharacter}";
ControllerBitsLabel.Text = $"Bits: {ControllerBits}";
ControllerConnected = true;
CheckReady();
}
}
void Event_RefreshPortsButton()
{
foreach (string s in SerialPort.GetPortNames())
{
SerialPortDropDown.Items.Add(s);
}
}
void Event_LoadShowtapeButton()
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Filters.Add(new FileFilter("UST Files (.ust)", new string[]{ ".ust" }));
fileDialog.Title = "Select Show File.";
fileDialog.ShowDialog(this);
string tempUSTData = File.ReadAllText(fileDialog.FileName);
if (!tempUSTData.StartsWith("UST,1,"))
{
MessageBox.Show("This is not a UST Version 1 showtape.");
return;
}
string[] headerData = tempUSTData.Split(';')[0].Split(',');
string[] stringyBits = tempUSTData.Split(';')[1].Split(',');
AudioData = Convert.FromBase64String(tempUSTData.Split(';')[2]);
ShowtapeName = headerData[2];
ShowtapeBits = headerData[3];
ShowtapeStageType = headerData[4];
ShowtapeCharacter = headerData[5];
if (headerData[3] == "256")
{
MessageBox.Show("Can't load a full stage showtape right now!");
return;
}
TimeSpan time = TimeSpan.FromSeconds(stringyBits.Length/60);
ShowtapeFormattedLength = time.ToString(@"hh\:mm\:ss");
ShowtapeNameLabel.Text = $"Show Name: {ShowtapeName}";
ShowtapeStageTypeLabel.Text = $"Stage Type: {ShowtapeStageType}";
ShowtapeCharacterLabel.Text = $"Character: {ShowtapeCharacter}";
ShowtapeBitsLabel.Text = $"Bits: {ShowtapeBits}";
ShowtapeLengthLabel.Text = $"Length: {ShowtapeFormattedLength}";
List<string> tmpOut = new List<string>();
foreach (string frame in stringyBits)
{
int b = int.Parse(frame, NumberStyles.HexNumber);
char[] bytesOut = new char[8];
int bytes = int.Parse(ShowtapeBits)/4;
for (int i = 0; i < bytes; i++)
{
int offset = 4 * i;
int mask = 0b1111 << offset;
int masked_value = (b & mask) >> offset;
bytesOut[i] = (char)(64 | masked_value);
}
tmpOut.Add(new string(bytesOut));
}
Signals = tmpOut.ToArray();
ShowtapeLoaded = true;
CheckReady();
}
void Event_PlayButton()
{
if (Playing) return;
if (ShowtapeBits != ControllerBits)
{
MessageBox.Show("This showtape does not have the correct amount of bits for your controller.");
return;
}
File.WriteAllBytes("tmp.wav", AudioData);
Index = SkipSeconds*60;
MPVProcess.StartInfo.Arguments = $"--start={SkipSeconds} tmp.wav";
MPVProcess.Start();
FrameTimer.Start();
Playing = true;
PlayButton.Enabled = false;
RefreshPortsButton.Enabled = false;
LoadShowtapeButton.Enabled = false;
SerialPortDropDown.Enabled = false;
}
void Event_StopButton()
{
FrameTimer.Stop();
MPVProcess.Kill();
File.Delete("tmp.wav");
Playing = false;
PlayButton.Enabled = true;
RefreshPortsButton.Enabled = true;
LoadShowtapeButton.Enabled = true;
SerialPortDropDown.Enabled = true;
Index = 0;
}
void Event_FrameTimerTick(Object sender, ElapsedEventArgs e)
{
if (Index >= Signals.Length)
{
Event_StopButton();
return;
}
Port.Write(Signals[Index]);
Index += FrameSkip;
}
}
}