Starting the terminal settings but I don't know if it's going to work Removed the list to allow users to control piano bar through exact commands
This commit is contained in:
Generated
+66
-62
@@ -1,4 +1,4 @@
|
||||
namespace PainoBar_Helper
|
||||
namespace PainoBar_Helper
|
||||
{
|
||||
partial class StationForm
|
||||
{
|
||||
@@ -29,74 +29,41 @@
|
||||
private void InitializeComponent()
|
||||
{
|
||||
station_list_group_box = new GroupBox();
|
||||
lstStations = new ListBox();
|
||||
textBox1 = new TextBox();
|
||||
search_label = new Label();
|
||||
refresh_button = new Button();
|
||||
btnSelectStation = new Button();
|
||||
ok_button = new Button();
|
||||
btnCancelStation = new Button();
|
||||
terminal_box = new RichTextBox();
|
||||
input_label = new Label();
|
||||
command_input_box = new TextBox();
|
||||
submit_button = new Button();
|
||||
station_list_group_box.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// station_list_group_box
|
||||
//
|
||||
station_list_group_box.Controls.Add(lstStations);
|
||||
station_list_group_box.Controls.Add(textBox1);
|
||||
station_list_group_box.Controls.Add(search_label);
|
||||
station_list_group_box.Controls.Add(submit_button);
|
||||
station_list_group_box.Controls.Add(command_input_box);
|
||||
station_list_group_box.Controls.Add(input_label);
|
||||
station_list_group_box.Controls.Add(terminal_box);
|
||||
station_list_group_box.Location = new Point(12, 22);
|
||||
station_list_group_box.Name = "station_list_group_box";
|
||||
station_list_group_box.Size = new Size(391, 263);
|
||||
station_list_group_box.Size = new Size(584, 333);
|
||||
station_list_group_box.TabIndex = 0;
|
||||
station_list_group_box.TabStop = false;
|
||||
station_list_group_box.Text = "Available Stations";
|
||||
station_list_group_box.Text = "Terminal window";
|
||||
//
|
||||
// lstStations
|
||||
// ok_button
|
||||
//
|
||||
lstStations.FormattingEnabled = true;
|
||||
lstStations.Location = new Point(26, 65);
|
||||
lstStations.Name = "lstStations";
|
||||
lstStations.Size = new Size(332, 174);
|
||||
lstStations.TabIndex = 2;
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
textBox1.Location = new Point(85, 32);
|
||||
textBox1.Name = "textBox1";
|
||||
textBox1.Size = new Size(273, 24);
|
||||
textBox1.TabIndex = 1;
|
||||
textBox1.TextChanged += textBox1_TextChanged;
|
||||
//
|
||||
// search_label
|
||||
//
|
||||
search_label.AutoSize = true;
|
||||
search_label.Location = new Point(26, 32);
|
||||
search_label.Name = "search_label";
|
||||
search_label.Size = new Size(50, 17);
|
||||
search_label.TabIndex = 0;
|
||||
search_label.Text = "Search:";
|
||||
//
|
||||
// refresh_button
|
||||
//
|
||||
refresh_button.Location = new Point(13, 307);
|
||||
refresh_button.Name = "refresh_button";
|
||||
refresh_button.Size = new Size(117, 23);
|
||||
refresh_button.TabIndex = 1;
|
||||
refresh_button.Text = "Refresh stations";
|
||||
refresh_button.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// btnSelectStation
|
||||
//
|
||||
btnSelectStation.Location = new Point(205, 307);
|
||||
btnSelectStation.Name = "btnSelectStation";
|
||||
btnSelectStation.Size = new Size(117, 23);
|
||||
btnSelectStation.TabIndex = 2;
|
||||
btnSelectStation.Text = "Select Station";
|
||||
btnSelectStation.UseVisualStyleBackColor = true;
|
||||
btnSelectStation.Click += btnSelectStation_Click;
|
||||
ok_button.Location = new Point(29, 389);
|
||||
ok_button.Name = "ok_button";
|
||||
ok_button.Size = new Size(117, 23);
|
||||
ok_button.TabIndex = 2;
|
||||
ok_button.Text = "Ok";
|
||||
ok_button.UseVisualStyleBackColor = true;
|
||||
ok_button.Click += btnSelectStation_Click;
|
||||
//
|
||||
// btnCancelStation
|
||||
//
|
||||
btnCancelStation.Location = new Point(328, 307);
|
||||
btnCancelStation.Location = new Point(521, 389);
|
||||
btnCancelStation.Name = "btnCancelStation";
|
||||
btnCancelStation.Size = new Size(86, 23);
|
||||
btnCancelStation.TabIndex = 3;
|
||||
@@ -104,14 +71,50 @@
|
||||
btnCancelStation.UseVisualStyleBackColor = true;
|
||||
btnCancelStation.Click += btnCancelStation_Click;
|
||||
//
|
||||
// terminal_box
|
||||
//
|
||||
terminal_box.BackColor = SystemColors.MenuText;
|
||||
terminal_box.ForeColor = SystemColors.Window;
|
||||
terminal_box.Location = new Point(17, 35);
|
||||
terminal_box.Name = "terminal_box";
|
||||
terminal_box.ReadOnly = true;
|
||||
terminal_box.Size = new Size(551, 231);
|
||||
terminal_box.TabIndex = 0;
|
||||
terminal_box.Text = "";
|
||||
//
|
||||
// input_label
|
||||
//
|
||||
input_label.AutoSize = true;
|
||||
input_label.Location = new Point(28, 294);
|
||||
input_label.Name = "input_label";
|
||||
input_label.Size = new Size(59, 17);
|
||||
input_label.TabIndex = 1;
|
||||
input_label.Text = "Command:";
|
||||
//
|
||||
// command_input_box
|
||||
//
|
||||
command_input_box.Location = new Point(91, 290);
|
||||
command_input_box.Name = "command_input_box";
|
||||
command_input_box.Size = new Size(244, 24);
|
||||
command_input_box.TabIndex = 2;
|
||||
//
|
||||
// submit_button
|
||||
//
|
||||
submit_button.Location = new Point(449, 290);
|
||||
submit_button.Name = "submit_button";
|
||||
submit_button.Size = new Size(75, 23);
|
||||
submit_button.TabIndex = 3;
|
||||
submit_button.Text = "Submit";
|
||||
submit_button.UseVisualStyleBackColor = true;
|
||||
submit_button.Click += submit_button_Click;
|
||||
//
|
||||
// StationForm
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 17F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new Size(426, 351);
|
||||
ClientSize = new Size(631, 434);
|
||||
Controls.Add(btnCancelStation);
|
||||
Controls.Add(btnSelectStation);
|
||||
Controls.Add(refresh_button);
|
||||
Controls.Add(ok_button);
|
||||
Controls.Add(station_list_group_box);
|
||||
Name = "StationForm";
|
||||
Text = "StationForm";
|
||||
@@ -123,11 +126,12 @@
|
||||
#endregion
|
||||
|
||||
private GroupBox station_list_group_box;
|
||||
private ListBox lstStations;
|
||||
private TextBox textBox1;
|
||||
private Label search_label;
|
||||
private Button refresh_button;
|
||||
private Button btnSelectStation;
|
||||
private Button ok_button;
|
||||
private Button btnCancelStation;
|
||||
private RichTextBox terminal_box;
|
||||
private Button submit_button;
|
||||
private TextBox command_input_box;
|
||||
private Label input_label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+87
-198
@@ -1,279 +1,168 @@
|
||||
using System.Text;
|
||||
using System.Text;
|
||||
|
||||
namespace PainoBar_Helper
|
||||
{
|
||||
public partial class StationForm : Form
|
||||
{
|
||||
private readonly PianobarManager _pianobarManager;
|
||||
private List<StationItem> _stations;
|
||||
private List<StationItem> _filteredStations;
|
||||
private bool _stationsLoaded = false;
|
||||
private bool _stationEntriesStarted = false;
|
||||
|
||||
private sealed class StationItem
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public override string ToString() => Name;
|
||||
}
|
||||
private readonly StringBuilder _outputBuffer = new StringBuilder();
|
||||
|
||||
public StationForm(PianobarManager pianobarManager)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_pianobarManager = pianobarManager;
|
||||
_stations = new List<StationItem>();
|
||||
_filteredStations = new List<StationItem>();
|
||||
|
||||
// Subscribe to output BEFORE controls are initialized
|
||||
_pianobarManager.OutputReceived += PianobarManager_TerminalOutputReceived;
|
||||
|
||||
// Handle form load to display buffered output
|
||||
this.Load += StationForm_Load;
|
||||
|
||||
InitializeControls();
|
||||
}
|
||||
|
||||
private void StationForm_Load(object? sender, EventArgs e)
|
||||
{
|
||||
// Display any buffered output when form loads
|
||||
if (terminal_box != null && _outputBuffer.Length > 0)
|
||||
{
|
||||
terminal_box.Text = _outputBuffer.ToString();
|
||||
terminal_box.SelectionStart = terminal_box.Text.Length;
|
||||
terminal_box.ScrollToCaret();
|
||||
}
|
||||
}
|
||||
|
||||
#region Initialization
|
||||
|
||||
private void InitializeControls()
|
||||
{
|
||||
// Uses textBox1 (search box) and lstStations from the Designer
|
||||
// Uses btnSelectStation from the Designer
|
||||
|
||||
if (lstStations != null)
|
||||
// Wire up terminal output and command input
|
||||
if (terminal_box != null)
|
||||
{
|
||||
lstStations.DoubleClick += LstStations_DoubleClick;
|
||||
terminal_box.ReadOnly = true;
|
||||
terminal_box.Font = new System.Drawing.Font("Consolas", 9F);
|
||||
terminal_box.WordWrap = false;
|
||||
}
|
||||
|
||||
if (refresh_button != null)
|
||||
if (submit_button != null)
|
||||
{
|
||||
refresh_button.Click += refresh_button_Click;
|
||||
submit_button.Click += submit_button_Click;
|
||||
}
|
||||
|
||||
if (command_input_box != null)
|
||||
{
|
||||
command_input_box.KeyDown += command_input_box_KeyDown;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnShown(EventArgs e)
|
||||
#endregion
|
||||
|
||||
#region Terminal Output
|
||||
|
||||
private void PianobarManager_TerminalOutputReceived(object? sender, string e)
|
||||
{
|
||||
base.OnShown(e);
|
||||
if (string.IsNullOrEmpty(e))
|
||||
return;
|
||||
|
||||
if (!_stationsLoaded)
|
||||
LoadStations();
|
||||
}
|
||||
string lineWithNewline = e + "\n";
|
||||
|
||||
private void LoadStations(bool forceRefresh = false)
|
||||
{
|
||||
_filteredStations.Clear();
|
||||
_stationsLoaded = false;
|
||||
_stationEntriesStarted = false;
|
||||
// Buffer output even before form is shown
|
||||
_outputBuffer.Append(lineWithNewline);
|
||||
|
||||
if (forceRefresh)
|
||||
_stations.Clear();
|
||||
|
||||
var knownStations = _pianobarManager.GetKnownStationEntries();
|
||||
if (knownStations.Count > 0)
|
||||
// Thread-safe UI update
|
||||
if (terminal_box != null)
|
||||
{
|
||||
_stations = knownStations
|
||||
.Select(s => new StationItem { Index = s.Index, Name = s.Name })
|
||||
.OrderBy(s => s.Index)
|
||||
.ToList();
|
||||
|
||||
_stationEntriesStarted = true;
|
||||
if (lstStations != null)
|
||||
UpdateStationList();
|
||||
}
|
||||
|
||||
_pianobarManager.OutputReceived -= PianobarManager_OutputReceived;
|
||||
_pianobarManager.OutputReceived += PianobarManager_OutputReceived;
|
||||
|
||||
// Only request station list on explicit refresh.
|
||||
if (forceRefresh)
|
||||
{
|
||||
try
|
||||
if (terminal_box.InvokeRequired)
|
||||
{
|
||||
_pianobarManager.ShowStations();
|
||||
|
||||
if (lstStations != null && _stations.Count == 0)
|
||||
terminal_box.Invoke(() =>
|
||||
{
|
||||
lstStations.Items.Clear();
|
||||
lstStations.Items.Add("Loading stations...");
|
||||
}
|
||||
AppendTerminalText(lineWithNewline);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
MessageBox.Show($"Failed to load stations:\n{ex.Message}", "Error",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
AppendTerminalText(lineWithNewline);
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
private void AppendTerminalText(string text)
|
||||
{
|
||||
if (terminal_box != null && !terminal_box.IsDisposed)
|
||||
{
|
||||
_stationsLoaded = true;
|
||||
if (_stations.Count == 0 && lstStations != null)
|
||||
{
|
||||
lstStations.Items.Clear();
|
||||
lstStations.Items.Add("No cached stations. Click Refresh stations.");
|
||||
}
|
||||
terminal_box.AppendText(text);
|
||||
terminal_box.SelectionStart = terminal_box.Text.Length;
|
||||
terminal_box.ScrollToCaret();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Station Loading
|
||||
#region Command Input
|
||||
|
||||
private void PianobarManager_OutputReceived(object? sender, string e)
|
||||
public void submit_button_Click(object? sender, EventArgs e)
|
||||
{
|
||||
var line = StripAnsiCodes(e).Trim();
|
||||
if (string.IsNullOrEmpty(line))
|
||||
return;
|
||||
SubmitCommand();
|
||||
}
|
||||
|
||||
var match = System.Text.RegularExpressions.Regex.Match(line, @"^\s*(\d+)\)\s*(?:[qQ]\s+)?(.+?)\s*$");
|
||||
if (match.Success)
|
||||
private void command_input_box_KeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Enter)
|
||||
{
|
||||
_stationEntriesStarted = true;
|
||||
int stationIndex = int.Parse(match.Groups[1].Value);
|
||||
string stationName = match.Groups[2].Value.Trim();
|
||||
|
||||
var existing = _stations.FirstOrDefault(s => s.Index == stationIndex);
|
||||
if (existing == null)
|
||||
{
|
||||
_stations.Add(new StationItem { Index = stationIndex, Name = stationName });
|
||||
_stations = _stations.OrderBy(s => s.Index).ToList();
|
||||
if (!IsDisposed && IsHandleCreated)
|
||||
BeginInvoke(() => UpdateStationList());
|
||||
}
|
||||
else if (!string.Equals(existing.Name, stationName, StringComparison.Ordinal))
|
||||
{
|
||||
existing.Name = stationName;
|
||||
if (!IsDisposed && IsHandleCreated)
|
||||
BeginInvoke(() => UpdateStationList());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Detect end of station list only after we started receiving entries
|
||||
if (_stationEntriesStarted &&
|
||||
(line.Contains("Select station:", StringComparison.OrdinalIgnoreCase) || line == "[?]"))
|
||||
{
|
||||
_stationsLoaded = true;
|
||||
_pianobarManager.OutputReceived -= PianobarManager_OutputReceived;
|
||||
if (!IsDisposed && IsHandleCreated)
|
||||
BeginInvoke(() => FinalizeStationList());
|
||||
e.SuppressKeyPress = true;
|
||||
SubmitCommand();
|
||||
}
|
||||
}
|
||||
|
||||
private static string StripAnsiCodes(string value)
|
||||
private void SubmitCommand()
|
||||
{
|
||||
return System.Text.RegularExpressions.Regex.Replace(value, @"\x1B\[[0-9;]*[A-Za-z]", string.Empty);
|
||||
}
|
||||
|
||||
private void UpdateStationList()
|
||||
{
|
||||
if (lstStations == null)
|
||||
if (command_input_box == null || string.IsNullOrWhiteSpace(command_input_box.Text))
|
||||
return;
|
||||
|
||||
lstStations.Items.Clear();
|
||||
|
||||
foreach (var station in _filteredStations.Any() ? _filteredStations : _stations)
|
||||
{
|
||||
lstStations.Items.Add(station);
|
||||
}
|
||||
}
|
||||
|
||||
private void FinalizeStationList()
|
||||
{
|
||||
if (lstStations != null)
|
||||
{
|
||||
if (_stations.Count == 0)
|
||||
{
|
||||
lstStations.Items.Clear();
|
||||
lstStations.Items.Add("No stations available");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Search
|
||||
|
||||
// Wire this to textBox1.TextChanged in the Designer
|
||||
public void textBox1_TextChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is not TextBox txtSearch)
|
||||
return;
|
||||
|
||||
string searchText = txtSearch.Text.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(searchText))
|
||||
{
|
||||
_filteredStations.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
_filteredStations = _stations
|
||||
.Where(s => s.Name.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
UpdateStationList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Station Selection
|
||||
|
||||
// Wire this to btnSelectStation.Click in the Designer
|
||||
public async void btnSelectStation_Click(object? sender, EventArgs e)
|
||||
{
|
||||
await SelectCurrentStationAsync();
|
||||
}
|
||||
|
||||
private async void LstStations_DoubleClick(object? sender, EventArgs e)
|
||||
{
|
||||
await SelectCurrentStationAsync();
|
||||
}
|
||||
|
||||
private async Task SelectCurrentStationAsync()
|
||||
{
|
||||
if (lstStations == null)
|
||||
return;
|
||||
|
||||
if (lstStations.SelectedIndex < 0)
|
||||
{
|
||||
MessageBox.Show("Please select a station.", "No Selection",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lstStations.SelectedItem is not StationItem selectedStation)
|
||||
return;
|
||||
string command = command_input_box.Text.Trim();
|
||||
|
||||
try
|
||||
{
|
||||
await _pianobarManager.SelectStationAsync(selectedStation.Index);
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
// Echo the command to the terminal (simulating user input display)
|
||||
AppendTerminalText($"> {command}\n");
|
||||
|
||||
// Send command to Pianobar with newline and flush
|
||||
_pianobarManager.SendCommand(command);
|
||||
|
||||
command_input_box.Clear();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Failed to select station:\n{ex.Message}", "Error",
|
||||
MessageBox.Show($"Failed to send command:\n{ex.Message}", "Command Error",
|
||||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public void refresh_button_Click(object? sender, EventArgs e)
|
||||
{
|
||||
LoadStations(forceRefresh: true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cancel
|
||||
#region Close
|
||||
|
||||
// Wire this to btnCancelStation.Click in the Designer (or Cancel button)
|
||||
public void btnCancelStation_Click(object? sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
}
|
||||
|
||||
public void btnSelectStation_Click(object? sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cleanup
|
||||
|
||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||
{
|
||||
_pianobarManager.OutputReceived -= PianobarManager_OutputReceived;
|
||||
_pianobarManager.OutputReceived -= PianobarManager_TerminalOutputReceived;
|
||||
base.OnFormClosing(e);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user