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:
minster586
2026-08-15 02:31:31 -04:00
parent df5303e0ef
commit 8b58fc30c4
2 changed files with 153 additions and 260 deletions
+65 -61
View File
@@ -1,4 +1,4 @@
namespace PainoBar_Helper namespace PainoBar_Helper
{ {
partial class StationForm partial class StationForm
{ {
@@ -29,74 +29,41 @@
private void InitializeComponent() private void InitializeComponent()
{ {
station_list_group_box = new GroupBox(); station_list_group_box = new GroupBox();
lstStations = new ListBox(); ok_button = new Button();
textBox1 = new TextBox();
search_label = new Label();
refresh_button = new Button();
btnSelectStation = new Button();
btnCancelStation = 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(); station_list_group_box.SuspendLayout();
SuspendLayout(); SuspendLayout();
// //
// station_list_group_box // station_list_group_box
// //
station_list_group_box.Controls.Add(lstStations); station_list_group_box.Controls.Add(submit_button);
station_list_group_box.Controls.Add(textBox1); station_list_group_box.Controls.Add(command_input_box);
station_list_group_box.Controls.Add(search_label); 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.Location = new Point(12, 22);
station_list_group_box.Name = "station_list_group_box"; 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.TabIndex = 0;
station_list_group_box.TabStop = false; 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; ok_button.Location = new Point(29, 389);
lstStations.Location = new Point(26, 65); ok_button.Name = "ok_button";
lstStations.Name = "lstStations"; ok_button.Size = new Size(117, 23);
lstStations.Size = new Size(332, 174); ok_button.TabIndex = 2;
lstStations.TabIndex = 2; ok_button.Text = "Ok";
// ok_button.UseVisualStyleBackColor = true;
// textBox1 ok_button.Click += btnSelectStation_Click;
//
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;
// //
// btnCancelStation // btnCancelStation
// //
btnCancelStation.Location = new Point(328, 307); btnCancelStation.Location = new Point(521, 389);
btnCancelStation.Name = "btnCancelStation"; btnCancelStation.Name = "btnCancelStation";
btnCancelStation.Size = new Size(86, 23); btnCancelStation.Size = new Size(86, 23);
btnCancelStation.TabIndex = 3; btnCancelStation.TabIndex = 3;
@@ -104,14 +71,50 @@
btnCancelStation.UseVisualStyleBackColor = true; btnCancelStation.UseVisualStyleBackColor = true;
btnCancelStation.Click += btnCancelStation_Click; 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 // StationForm
// //
AutoScaleDimensions = new SizeF(7F, 17F); AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(426, 351); ClientSize = new Size(631, 434);
Controls.Add(btnCancelStation); Controls.Add(btnCancelStation);
Controls.Add(btnSelectStation); Controls.Add(ok_button);
Controls.Add(refresh_button);
Controls.Add(station_list_group_box); Controls.Add(station_list_group_box);
Name = "StationForm"; Name = "StationForm";
Text = "StationForm"; Text = "StationForm";
@@ -123,11 +126,12 @@
#endregion #endregion
private GroupBox station_list_group_box; private GroupBox station_list_group_box;
private ListBox lstStations;
private TextBox textBox1;
private Label search_label;
private Button refresh_button; private Button refresh_button;
private Button btnSelectStation; private Button ok_button;
private Button btnCancelStation; private Button btnCancelStation;
private RichTextBox terminal_box;
private Button submit_button;
private TextBox command_input_box;
private Label input_label;
} }
} }
+95 -206
View File
@@ -1,279 +1,168 @@
using System.Text;
using System.Text;
namespace PainoBar_Helper namespace PainoBar_Helper
{ {
public partial class StationForm : Form public partial class StationForm : Form
{ {
private readonly PianobarManager _pianobarManager; private readonly PianobarManager _pianobarManager;
private List<StationItem> _stations; private readonly StringBuilder _outputBuffer = new StringBuilder();
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;
}
public StationForm(PianobarManager pianobarManager) public StationForm(PianobarManager pianobarManager)
{ {
InitializeComponent(); InitializeComponent();
_pianobarManager = pianobarManager; _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(); 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 #region Initialization
private void InitializeControls() private void InitializeControls()
{ {
// Uses textBox1 (search box) and lstStations from the Designer // Wire up terminal output and command input
// Uses btnSelectStation from the Designer if (terminal_box != null)
if (lstStations != 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) string lineWithNewline = e + "\n";
LoadStations();
}
private void LoadStations(bool forceRefresh = false) // Buffer output even before form is shown
_outputBuffer.Append(lineWithNewline);
// Thread-safe UI update
if (terminal_box != null)
{ {
_filteredStations.Clear(); if (terminal_box.InvokeRequired)
_stationsLoaded = false;
_stationEntriesStarted = false;
if (forceRefresh)
_stations.Clear();
var knownStations = _pianobarManager.GetKnownStationEntries();
if (knownStations.Count > 0)
{ {
_stations = knownStations terminal_box.Invoke(() =>
.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 AppendTerminalText(lineWithNewline);
{ });
_pianobarManager.ShowStations();
if (lstStations != null && _stations.Count == 0)
{
lstStations.Items.Clear();
lstStations.Items.Add("Loading stations...");
}
}
catch (Exception ex)
{
MessageBox.Show($"Failed to load stations:\n{ex.Message}", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
} }
else else
{ {
_stationsLoaded = true; AppendTerminalText(lineWithNewline);
if (_stations.Count == 0 && lstStations != null)
{
lstStations.Items.Clear();
lstStations.Items.Add("No cached stations. Click Refresh stations.");
} }
} }
} }
private void AppendTerminalText(string text)
{
if (terminal_box != null && !terminal_box.IsDisposed)
{
terminal_box.AppendText(text);
terminal_box.SelectionStart = terminal_box.Text.Length;
terminal_box.ScrollToCaret();
}
}
#endregion #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(); SubmitCommand();
if (string.IsNullOrEmpty(line)) }
private void command_input_box_KeyDown(object? sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.SuppressKeyPress = true;
SubmitCommand();
}
}
private void SubmitCommand()
{
if (command_input_box == null || string.IsNullOrWhiteSpace(command_input_box.Text))
return; return;
var match = System.Text.RegularExpressions.Regex.Match(line, @"^\s*(\d+)\)\s*(?:[qQ]\s+)?(.+?)\s*$"); string command = command_input_box.Text.Trim();
if (match.Success)
{
_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());
}
}
private static string StripAnsiCodes(string value)
{
return System.Text.RegularExpressions.Regex.Replace(value, @"\x1B\[[0-9;]*[A-Za-z]", string.Empty);
}
private void UpdateStationList()
{
if (lstStations == null)
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;
try try
{ {
await _pianobarManager.SelectStationAsync(selectedStation.Index); // Echo the command to the terminal (simulating user input display)
DialogResult = DialogResult.OK; AppendTerminalText($"> {command}\n");
Close();
// Send command to Pianobar with newline and flush
_pianobarManager.SendCommand(command);
command_input_box.Clear();
} }
catch (Exception ex) 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); MessageBoxButtons.OK, MessageBoxIcon.Error);
} }
} }
public void refresh_button_Click(object? sender, EventArgs e)
{
LoadStations(forceRefresh: true);
}
#endregion #endregion
#region Cancel #region Close
// Wire this to btnCancelStation.Click in the Designer (or Cancel button)
public void btnCancelStation_Click(object? sender, EventArgs e) public void btnCancelStation_Click(object? sender, EventArgs e)
{ {
DialogResult = DialogResult.Cancel; DialogResult = DialogResult.Cancel;
Close(); Close();
} }
public void btnSelectStation_Click(object? sender, EventArgs e)
{
DialogResult = DialogResult.OK;
Close();
}
#endregion #endregion
#region Cleanup #region Cleanup
protected override void OnFormClosing(FormClosingEventArgs e) protected override void OnFormClosing(FormClosingEventArgs e)
{ {
_pianobarManager.OutputReceived -= PianobarManager_OutputReceived; _pianobarManager.OutputReceived -= PianobarManager_TerminalOutputReceived;
base.OnFormClosing(e); base.OnFormClosing(e);
} }