7 Commits
5 changed files with 435 additions and 565 deletions
+91 -84
View File
@@ -43,11 +43,14 @@
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.time_data_label = new System.Windows.Forms.Label();
this.label9 = new System.Windows.Forms.Label();
this.time_label = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.album_data = new System.Windows.Forms.Label();
this.artist_data = new System.Windows.Forms.Label();
this.title_data = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
@@ -58,9 +61,6 @@
this.profile_drop_box = new System.Windows.Forms.ComboBox();
this.profile_label = new System.Windows.Forms.Label();
this.load_profile_button = new System.Windows.Forms.Button();
this.time_label = new System.Windows.Forms.Label();
this.label9 = new System.Windows.Forms.Label();
this.time_data_label = new System.Windows.Forms.Label();
this.statusStrip1.SuspendLayout();
this.menuStrip2.SuspendLayout();
this.groupBox1.SuspendLayout();
@@ -74,9 +74,9 @@
this.toolStripStatusLabel2,
this.toolStripStatusLabel4,
this.toolStripStatusLabel3});
this.statusStrip1.Location = new System.Drawing.Point(0, 362);
this.statusStrip1.Location = new System.Drawing.Point(0, 309);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(612, 26);
this.statusStrip1.Size = new System.Drawing.Size(780, 26);
this.statusStrip1.TabIndex = 0;
this.statusStrip1.Text = "statusStrip1";
//
@@ -99,7 +99,7 @@
//
this.toolStripStatusLabel4.Font = new System.Drawing.Font("Segoe UI", 11.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.toolStripStatusLabel4.Name = "toolStripStatusLabel4";
this.toolStripStatusLabel4.Size = new System.Drawing.Size(260, 21);
this.toolStripStatusLabel4.Size = new System.Drawing.Size(344, 21);
this.toolStripStatusLabel4.Spring = true;
this.toolStripStatusLabel4.Text = "Profile:";
this.toolStripStatusLabel4.Click += new System.EventHandler(this.toolStripStatusLabel4_Click);
@@ -107,7 +107,7 @@
// toolStripStatusLabel3
//
this.toolStripStatusLabel3.Name = "toolStripStatusLabel3";
this.toolStripStatusLabel3.Size = new System.Drawing.Size(260, 21);
this.toolStripStatusLabel3.Size = new System.Drawing.Size(344, 21);
this.toolStripStatusLabel3.Spring = true;
this.toolStripStatusLabel3.Text = "Song Changed Updateing";
this.toolStripStatusLabel3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
@@ -119,7 +119,7 @@
this.aboutToolStripMenuItem});
this.menuStrip2.Location = new System.Drawing.Point(0, 0);
this.menuStrip2.Name = "menuStrip2";
this.menuStrip2.Size = new System.Drawing.Size(612, 25);
this.menuStrip2.Size = new System.Drawing.Size(780, 25);
this.menuStrip2.TabIndex = 2;
this.menuStrip2.Text = "menuStrip2";
//
@@ -183,28 +183,59 @@
this.groupBox1.Controls.Add(this.time_label);
this.groupBox1.Controls.Add(this.label8);
this.groupBox1.Controls.Add(this.label7);
this.groupBox1.Controls.Add(this.label6);
this.groupBox1.Controls.Add(this.label5);
this.groupBox1.Controls.Add(this.label4);
this.groupBox1.Controls.Add(this.album_data);
this.groupBox1.Controls.Add(this.artist_data);
this.groupBox1.Controls.Add(this.title_data);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.groupBox1.Location = new System.Drawing.Point(199, 37);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(390, 205);
this.groupBox1.Size = new System.Drawing.Size(569, 205);
this.groupBox1.TabIndex = 4;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Song Info";
//
// time_data_label
//
this.time_data_label.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.time_data_label.Location = new System.Drawing.Point(101, 159);
this.time_data_label.Name = "time_data_label";
this.time_data_label.Size = new System.Drawing.Size(437, 21);
this.time_data_label.TabIndex = 10;
this.time_data_label.Text = "No Data";
this.time_data_label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(17, 144);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(539, 16);
this.label9.TabIndex = 9;
this.label9.Text = "――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――";
this.label9.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
//
// time_label
//
this.time_label.AutoSize = true;
this.time_label.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.time_label.Location = new System.Drawing.Point(20, 157);
this.time_label.Name = "time_label";
this.time_label.Size = new System.Drawing.Size(63, 24);
this.time_label.TabIndex = 8;
this.time_label.Text = "Time:";
this.time_label.Click += new System.EventHandler(this.label9_Click);
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(20, 103);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(357, 16);
this.label8.Size = new System.Drawing.Size(539, 16);
this.label8.TabIndex = 7;
this.label8.Text = "――――――――――――――――――――――――――――――――――――――――――――――――――";
this.label8.Text = "――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――";
this.label8.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
//
// label7
@@ -212,39 +243,46 @@
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(19, 61);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(357, 16);
this.label7.Size = new System.Drawing.Size(539, 16);
this.label7.TabIndex = 6;
this.label7.Text = "――――――――――――――――――――――――――――――――――――――――――――――――――";
this.label7.Text = "――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――";
this.label7.Click += new System.EventHandler(this.label7_Click_1);
//
// label6
// album_data
//
this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label6.Location = new System.Drawing.Point(99, 121);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(266, 17);
this.label6.TabIndex = 5;
this.label6.Text = "No album";
this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.album_data.AutoEllipsis = true;
this.album_data.AutoSize = false;
this.album_data.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.album_data.Location = new System.Drawing.Point(100, 119);
this.album_data.Name = "album_data";
this.album_data.Size = new System.Drawing.Size(443, 19);
this.album_data.TabIndex = 5;
this.album_data.Text = "No album";
this.album_data.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label5
// artist_data
//
this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label5.Location = new System.Drawing.Point(99, 76);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(266, 17);
this.label5.TabIndex = 4;
this.label5.Text = "No artist";
this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.artist_data.AutoEllipsis = true;
this.artist_data.AutoSize = false;
this.artist_data.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.artist_data.Location = new System.Drawing.Point(99, 76);
this.artist_data.Name = "artist_data";
this.artist_data.Size = new System.Drawing.Size(433, 23);
this.artist_data.TabIndex = 4;
this.artist_data.Text = "No artist";
this.artist_data.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label4
// title_data
//
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label4.Location = new System.Drawing.Point(99, 33);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(266, 16);
this.label4.TabIndex = 3;
this.label4.Text = "No title";
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.title_data.AutoEllipsis = true;
this.title_data.AutoSize = false;
this.title_data.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.title_data.Location = new System.Drawing.Point(97, 33);
this.title_data.Name = "title_data";
this.title_data.Size = new System.Drawing.Size(443, 20);
this.title_data.TabIndex = 3;
this.title_data.Text = "No title";
this.title_data.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// label3
//
@@ -278,7 +316,7 @@
//
// button1
//
this.button1.Location = new System.Drawing.Point(62, 281);
this.button1.Location = new System.Drawing.Point(425, 254);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(99, 42);
this.button1.TabIndex = 5;
@@ -288,7 +326,7 @@
//
// button2
//
this.button2.Location = new System.Drawing.Point(180, 281);
this.button2.Location = new System.Drawing.Point(577, 253);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(99, 42);
this.button2.TabIndex = 6;
@@ -299,7 +337,7 @@
// uicolor
//
this.uicolor.Image = global::RadioDJViewer.Properties.Resources.MdiWeatherNight;
this.uicolor.Location = new System.Drawing.Point(572, 327);
this.uicolor.Location = new System.Drawing.Point(740, 262);
this.uicolor.Name = "uicolor";
this.uicolor.Size = new System.Drawing.Size(28, 23);
this.uicolor.TabIndex = 7;
@@ -316,7 +354,7 @@
// profile_drop_box
//
this.profile_drop_box.FormattingEnabled = true;
this.profile_drop_box.Location = new System.Drawing.Point(62, 329);
this.profile_drop_box.Location = new System.Drawing.Point(62, 268);
this.profile_drop_box.Name = "profile_drop_box";
this.profile_drop_box.Size = new System.Drawing.Size(217, 21);
this.profile_drop_box.TabIndex = 8;
@@ -324,7 +362,7 @@
// profile_label
//
this.profile_label.AutoSize = true;
this.profile_label.Location = new System.Drawing.Point(12, 332);
this.profile_label.Location = new System.Drawing.Point(12, 272);
this.profile_label.Name = "profile_label";
this.profile_label.Size = new System.Drawing.Size(44, 13);
this.profile_label.TabIndex = 9;
@@ -333,49 +371,18 @@
//
// load_profile_button
//
this.load_profile_button.Location = new System.Drawing.Point(285, 327);
this.load_profile_button.Location = new System.Drawing.Point(292, 267);
this.load_profile_button.Name = "load_profile_button";
this.load_profile_button.Size = new System.Drawing.Size(75, 23);
this.load_profile_button.TabIndex = 10;
this.load_profile_button.Text = "Load Profile";
this.load_profile_button.UseVisualStyleBackColor = true;
//
// time_label
//
this.time_label.AutoSize = true;
this.time_label.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline))), System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.time_label.Location = new System.Drawing.Point(20, 157);
this.time_label.Name = "time_label";
this.time_label.Size = new System.Drawing.Size(63, 24);
this.time_label.TabIndex = 8;
this.time_label.Text = "Time:";
this.time_label.Click += new System.EventHandler(this.label9_Click);
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(17, 144);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(357, 16);
this.label9.TabIndex = 9;
this.label9.Text = "――――――――――――――――――――――――――――――――――――――――――――――――――";
this.label9.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
//
// time_data_label
//
this.time_data_label.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.time_data_label.Location = new System.Drawing.Point(97, 160);
this.time_data_label.Name = "time_data_label";
this.time_data_label.Size = new System.Drawing.Size(266, 17);
this.time_data_label.TabIndex = 10;
this.time_data_label.Text = "No Data";
this.time_data_label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(612, 388);
this.ClientSize = new System.Drawing.Size(780, 335);
this.Controls.Add(this.load_profile_button);
this.Controls.Add(this.profile_label);
this.Controls.Add(this.profile_drop_box);
@@ -415,9 +422,9 @@
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label album_data;
private System.Windows.Forms.Label artist_data;
private System.Windows.Forms.Label title_data;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
+295 -335
View File
@@ -25,6 +25,8 @@ namespace RadioDJViewer
{
private string _currentTrackKey = string.Empty;
private string _playbackTrackKey = string.Empty;
private string _previousToastTitle = string.Empty;
private string _previousToastArtist = string.Empty;
private double _playbackElapsedSeconds = 0;
private double _playbackDurationSeconds = 0;
private bool _playbackPaused = true;
@@ -32,10 +34,13 @@ namespace RadioDJViewer
private string selectedFolderPath = string.Empty;
private string outputFolderPath = string.Empty;
private bool isConnected = false;
private bool _isDisconnecting = false;
private CancellationTokenSource _connectionCts = new CancellationTokenSource();
private string currentProfile = "Default";
private string currentSongImagePath = string.Empty; // Path to the current song image
private string defaultImagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "default.jpg");
private string mainImagesFolderPath = string.Empty; // New field for main images folder path
private string _lastToastImagePath = string.Empty;
private Profile loadedProfile = null; // Field to store the loaded profile
private WidgetServer widgetServer = null; // Local widget HTTP server
private bool widgetRunning = false;
@@ -46,23 +51,6 @@ namespace RadioDJViewer
private System.Windows.Forms.Timer playbackTimer;
private string lastApiXml = null;
private System.Windows.Forms.Timer marqueeTimerTitle;
private System.Windows.Forms.Timer marqueeTimerArtist;
private System.Windows.Forms.Timer marqueeTimerAlbum;
private int marqueeOffsetTitle = 0;
private int marqueeOffsetArtist = 0;
private int marqueeOffsetAlbum = 0;
private string marqueeTextTitle = "";
private string marqueeTextArtist = "";
private string marqueeTextAlbum = "";
private System.Windows.Forms.Timer pauseTimerTitle;
private System.Windows.Forms.Timer pauseTimerArtist;
private System.Windows.Forms.Timer pauseTimerAlbum;
private int marqueeScrollSpeed = 100; // Default to Medium
private int marqueePauseTime = 6000; // Default to 6 seconds
private string marqueeSeparator = " | "; // Default separator
private bool loggingEnabled = false;
private string logFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "RadioDJViewer.log");
@@ -79,23 +67,24 @@ namespace RadioDJViewer
playbackTimer = new System.Windows.Forms.Timer();
playbackTimer.Interval = 250;
playbackTimer.Tick += PlaybackTimer_Tick;
// Marquee timers for each label
marqueeTimerTitle = new System.Windows.Forms.Timer();
marqueeTimerTitle.Interval = marqueeScrollSpeed;
marqueeTimerTitle.Tick += MarqueeTimerTitle_Tick;
marqueeTimerArtist = new System.Windows.Forms.Timer();
marqueeTimerArtist.Interval = marqueeScrollSpeed;
marqueeTimerArtist.Tick += MarqueeTimerArtist_Tick;
marqueeTimerAlbum = new System.Windows.Forms.Timer();
marqueeTimerAlbum.Interval = marqueeScrollSpeed;
marqueeTimerAlbum.Tick += MarqueeTimerAlbum_Tick;
// Wire up dark mode button
this.uicolor.Click += Uicolor_Click;
this.load_profile_button.Click += load_profile_button_Click;
PopulateProfileDropBox();
UpdateTheme();
// Auto-load profiles if profiles.json exists
AutoLoadProfiles();
}
public void SetSongMetadataLabels(string title, string artist, string album)
{
if (InvokeRequired)
{
BeginInvoke((Action)(() => SetSongMetadataLabels(title, artist, album)));
return;
}
title_data.Text = title;
artist_data.Text = artist;
album_data.Text = album;
}
private void EnsureDefaultImageExists()
@@ -111,32 +100,6 @@ namespace RadioDJViewer
}
}
public void SetMarqueeScrollSpeed(string speed)
{
switch (speed)
{
case "Very Slow": marqueeScrollSpeed = 300; break;
case "Slow": marqueeScrollSpeed = 200; break;
case "Medium": marqueeScrollSpeed = 100; break;
case "Fast": marqueeScrollSpeed = 60; break;
case "Very Fast": marqueeScrollSpeed = 30; break;
default: marqueeScrollSpeed = 100; break;
}
marqueeTimerTitle.Interval = marqueeScrollSpeed;
marqueeTimerArtist.Interval = marqueeScrollSpeed;
marqueeTimerAlbum.Interval = marqueeScrollSpeed;
}
public void SetMarqueePauseTime(int seconds)
{
marqueePauseTime = seconds * 1000;
}
public void SetMarqueeSeparator(string separator)
{
marqueeSeparator = separator;
}
private void LogMessage(string message)
{
if (!loggingEnabled) return;
@@ -147,121 +110,6 @@ namespace RadioDJViewer
catch { }
}
private int GetVisibleChars(Label label)
{
// Use the label's actual width and font to estimate visible characters
using (Graphics g = label.CreateGraphics())
{
// Use the full label width for measurement
SizeF size = g.MeasureString("W", label.Font);
int chars = (int)(label.Width / size.Width);
// If the label is single-line, ensure we use the full width
return Math.Max(chars, 1);
}
}
private void SetLabelTextFull(Label label, string text)
{
// Always set the full text, and let marquee logic handle scrolling
label.Text = text;
}
private void MarqueeTimerTitle_Tick(object sender, EventArgs e)
{
int visibleChars = GetVisibleChars(label4);
if (marqueeTextTitle.Length > visibleChars)
{
string separator = string.IsNullOrEmpty(marqueeSeparator) ? "" : marqueeSeparator;
string scrollText = marqueeTextTitle + separator;
string repeatedScrollText = scrollText + scrollText;
marqueeOffsetTitle = (marqueeOffsetTitle + 1) % scrollText.Length;
label4.Text = repeatedScrollText.Substring(marqueeOffsetTitle, visibleChars);
LogMessage($"MarqueeTitle: separator='{separator}', scrollText='{scrollText}', offset={marqueeOffsetTitle}");
if (marqueeOffsetTitle == 0)
{
marqueeTimerTitle.Stop();
if (pauseTimerTitle == null)
{
pauseTimerTitle = new System.Windows.Forms.Timer();
pauseTimerTitle.Tick += (s, args) => {
pauseTimerTitle.Stop();
marqueeTimerTitle.Start();
};
}
pauseTimerTitle.Interval = marqueePauseTime;
pauseTimerTitle.Start();
}
}
else
{
SetLabelTextFull(label4, marqueeTextTitle);
}
}
private void MarqueeTimerArtist_Tick(object sender, EventArgs e)
{
int visibleChars = GetVisibleChars(label5);
if (marqueeTextArtist.Length > visibleChars)
{
string separator = string.IsNullOrEmpty(marqueeSeparator) ? "" : marqueeSeparator;
string scrollText = marqueeTextArtist + separator;
string repeatedScrollText = scrollText + scrollText;
marqueeOffsetArtist = (marqueeOffsetArtist + 1) % scrollText.Length;
label5.Text = repeatedScrollText.Substring(marqueeOffsetArtist, visibleChars);
LogMessage($"MarqueeArtist: separator='{separator}', scrollText='{scrollText}', offset={marqueeOffsetArtist}");
if (marqueeOffsetArtist == 0)
{
marqueeTimerArtist.Stop();
if (pauseTimerArtist == null)
{
pauseTimerArtist = new System.Windows.Forms.Timer();
pauseTimerArtist.Tick += (s, args) => {
pauseTimerArtist.Stop();
marqueeTimerArtist.Start();
};
}
pauseTimerArtist.Interval = marqueePauseTime;
pauseTimerArtist.Start();
}
}
else
{
SetLabelTextFull(label5, marqueeTextArtist);
}
}
private void MarqueeTimerAlbum_Tick(object sender, EventArgs e)
{
int visibleChars = GetVisibleChars(label6);
if (marqueeTextAlbum.Length > visibleChars)
{
string separator = string.IsNullOrEmpty(marqueeSeparator) ? "" : marqueeSeparator;
string scrollText = marqueeTextAlbum + separator;
string repeatedScrollText = scrollText + scrollText;
marqueeOffsetAlbum = (marqueeOffsetAlbum + 1) % scrollText.Length;
label6.Text = repeatedScrollText.Substring(marqueeOffsetAlbum, visibleChars);
LogMessage($"MarqueeAlbum: separator='{separator}', scrollText='{scrollText}', offset={marqueeOffsetAlbum}");
if (marqueeOffsetAlbum == 0)
{
marqueeTimerAlbum.Stop();
if (pauseTimerAlbum == null)
{
pauseTimerAlbum = new System.Windows.Forms.Timer();
pauseTimerAlbum.Tick += (s, args) => {
pauseTimerAlbum.Stop();
marqueeTimerAlbum.Start();
};
}
pauseTimerAlbum.Interval = marqueePauseTime;
pauseTimerAlbum.Start();
}
}
else
{
SetLabelTextFull(label6, marqueeTextAlbum);
}
}
private void ApiTimer_Tick(object sender, EventArgs e)
{
if (isConnected)
@@ -272,7 +120,7 @@ namespace RadioDJViewer
private async Task PollRestApi()
{
if (loadedProfile == null) return;
if (loadedProfile == null || _isDisconnecting || _connectionCts.IsCancellationRequested) return;
string url = loadedProfile.UrlFormat;
if (!string.IsNullOrWhiteSpace(url))
{
@@ -286,67 +134,25 @@ namespace RadioDJViewer
}
try
{
var client = new System.Net.Http.HttpClient();
using (var client = new System.Net.Http.HttpClient())
{
var response = await client.GetAsync(url);
if (_isDisconnecting || _connectionCts.IsCancellationRequested || !isConnected)
return;
if (response.IsSuccessStatusCode)
{
var xml = await response.Content.ReadAsStringAsync();
if (_isDisconnecting || _connectionCts.IsCancellationRequested || !isConnected)
return;
lastApiXml = xml;
ParseAndDisplaySongInfo(xml);
try
{
var newKey = $"{marqueeTextArtist}|{marqueeTextTitle}";
if (!string.Equals(newKey, _currentTrackKey, StringComparison.Ordinal))
{
_currentTrackKey = newKey;
ShowTemporaryStatus("Song Change Detected", 2000);
bool toastEnabled = IsToastEnabledForActiveProfile();
#if DEBUG
System.Diagnostics.Debug.WriteLine($"[Toast] Track changed. Enabled={toastEnabled}, Profile={loadedProfile?.Name ?? "(null)"}");
#endif
if (toastEnabled)
{
try
{
string outputImagePath = GetProfileOutputImagePath();
#if DEBUG
System.Diagnostics.Debug.WriteLine($"[Toast] Trigger with title='{marqueeTextTitle}', artist='{marqueeTextArtist}', imagePath='{outputImagePath}'");
#endif
ShowTrackChangeToast(marqueeTextTitle, marqueeTextArtist, outputImagePath);
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Debug.WriteLine($"[Toast] Trigger error: {ex}");
MessageBox.Show($"Toast trigger failed: {ex.Message}", "Toast Debug", MessageBoxButtons.OK, MessageBoxIcon.Warning);
#endif
}
}
}
}
catch { }
}
}
catch { }
}
private void AutoLoadProfiles()
{
string profilesPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "profiles.json");
if (File.Exists(profilesPath))
{
var profileNames = ProfileStorage.GetProfileNames();
if (profileNames.Count > 0)
{
// Optionally, load the first profile by default
var profile = ProfileStorage.LoadProfile(profileNames[0]);
if (profile != null)
{
LoadProfile(profile);
}
}
}
}
private async void button1_Click(object sender, EventArgs e)
{
@@ -364,7 +170,9 @@ namespace RadioDJViewer
private void button2_Click(object sender, EventArgs e)
{
// Disconnect
_isDisconnecting = true;
isConnected = false;
try { _connectionCts.Cancel(); } catch { }
apiTimer.Stop();
playbackTimer.Stop();
_playbackElapsedSeconds = 0;
@@ -386,6 +194,8 @@ namespace RadioDJViewer
catch { }
ClearStatusMessage();
UpdateStatusBar();
_isDisconnecting = false;
_connectionCts = new CancellationTokenSource();
}
private async Task ConnectToRestApi()
@@ -414,15 +224,24 @@ namespace RadioDJViewer
}
try
{
var client = new System.Net.Http.HttpClient();
_isDisconnecting = false;
_connectionCts = new CancellationTokenSource();
using (var client = new System.Net.Http.HttpClient())
{
var response = await client.GetAsync(url);
if (_isDisconnecting || _connectionCts.IsCancellationRequested)
return;
if (response.IsSuccessStatusCode)
{
var xml = await response.Content.ReadAsStringAsync();
if (_isDisconnecting || _connectionCts.IsCancellationRequested)
return;
ParseAndDisplaySongInfo(xml);
try
{
_currentTrackKey = $"{marqueeTextArtist}|{marqueeTextTitle}";
_currentTrackKey = $"{_previousToastArtist}|{_previousToastTitle}";
}
catch { }
isConnected = true;
@@ -437,6 +256,7 @@ namespace RadioDJViewer
isConnected = false;
}
}
}
catch (Exception ex)
{
MessageBox.Show($"Error connecting to REST API: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
@@ -445,7 +265,6 @@ namespace RadioDJViewer
UpdateStatusBar();
}
// Call this method after parsing song info, assuming image path is available from profile or API
private void UpdateCurrentSongImage(string imageName)
{
string imagePath = string.Empty;
@@ -465,18 +284,16 @@ namespace RadioDJViewer
}
if (useFallback)
{
// Use fallback PNG from resources
var fallbackImg = Properties.Resources.fallback;
if (fallbackImg != null)
{
var resized = new Bitmap(fallbackImg, pictureBox1.Size);
pictureBox1.Image = resized;
currentSongImagePath = defaultImagePath;
// Save fallback image to output folder as PNG
if (!string.IsNullOrEmpty(outputFolderPath) && !string.IsNullOrEmpty(outputImageName))
{
string destPath = Path.Combine(outputFolderPath, Path.ChangeExtension(outputImageName, ".png"));
resized.Save(destPath, System.Drawing.Imaging.ImageFormat.Png);
SaveImageAsPng(resized, destPath);
}
}
else
@@ -493,17 +310,15 @@ namespace RadioDJViewer
var resized = new Bitmap(img, pictureBox1.Size);
pictureBox1.Image = resized;
currentSongImagePath = imagePath;
// Save to output folder as PNG
if (!string.IsNullOrEmpty(outputFolderPath) && !string.IsNullOrEmpty(outputImageName))
{
string destPath = Path.Combine(outputFolderPath, Path.ChangeExtension(outputImageName, ".png"));
resized.Save(destPath, System.Drawing.Imaging.ImageFormat.Png);
SaveImageAsPng(resized, destPath);
}
}
}
catch
{
// If loading image fails, fallback
var fallbackImg = Properties.Resources.fallback;
if (fallbackImg != null)
{
@@ -513,7 +328,7 @@ namespace RadioDJViewer
if (!string.IsNullOrEmpty(outputFolderPath) && !string.IsNullOrEmpty(outputImageName))
{
string destPath = Path.Combine(outputFolderPath, Path.ChangeExtension(outputImageName, ".png"));
resized.Save(destPath, System.Drawing.Imaging.ImageFormat.Png);
SaveImageAsPng(resized, destPath);
}
}
else
@@ -524,21 +339,129 @@ namespace RadioDJViewer
}
}
private void StartMarqueeTimers()
private void SaveImageAsPng(Image image, string destinationPath)
{
marqueeOffsetTitle = 0;
marqueeOffsetArtist = 0;
marqueeOffsetAlbum = 0;
marqueeTimerTitle.Start();
marqueeTimerArtist.Start();
marqueeTimerAlbum.Start();
if (image == null || string.IsNullOrWhiteSpace(destinationPath))
return;
string directory = Path.GetDirectoryName(destinationPath);
if (!string.IsNullOrWhiteSpace(directory))
Directory.CreateDirectory(directory);
string tempPath = destinationPath + ".tmp";
using (var fileStream = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.Read))
{
image.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png);
fileStream.Flush(true);
}
private void StopMarqueeTimers()
if (File.Exists(destinationPath))
File.Delete(destinationPath);
File.Move(tempPath, destinationPath);
}
private string BuildToastImagePath()
{
marqueeTimerTitle.Stop();
marqueeTimerArtist.Stop();
marqueeTimerAlbum.Stop();
try
{
string sourcePath = currentSongImagePath;
if (string.IsNullOrWhiteSpace(sourcePath) || !File.Exists(sourcePath))
sourcePath = GetProfileOutputImagePath();
if (string.IsNullOrWhiteSpace(sourcePath) || !File.Exists(sourcePath))
return string.Empty;
string toastDirectory = Path.Combine(Path.GetTempPath(), "RadioDJViewer", "ToastImages");
Directory.CreateDirectory(toastDirectory);
string toastPath = Path.Combine(toastDirectory, $"Album-Art-Hero-{DateTime.UtcNow.Ticks}.png");
using (var sourceStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var memoryStream = new MemoryStream())
{
sourceStream.CopyTo(memoryStream);
memoryStream.Position = 0;
using (var sourceImage = Image.FromStream(memoryStream))
using (var heroImage = CreateToastHeroCanvas(sourceImage))
using (var fileStream = new FileStream(toastPath, FileMode.Create, FileAccess.Write, FileShare.Read))
{
heroImage.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png);
fileStream.Flush(true);
}
}
if (!string.IsNullOrWhiteSpace(_lastToastImagePath) && !string.Equals(_lastToastImagePath, toastPath, StringComparison.OrdinalIgnoreCase))
{
try
{
if (File.Exists(_lastToastImagePath))
File.Delete(_lastToastImagePath);
}
catch { }
}
_lastToastImagePath = toastPath;
#if DEBUG
System.Diagnostics.Debug.WriteLine($"[Toast] Prepared 16:9 hero image '{toastPath}' from '{sourcePath}'");
#endif
return toastPath;
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Debug.WriteLine($"[Toast] Failed to prepare toast image: {ex}");
#endif
return string.Empty;
}
}
private Bitmap CreateToastHeroCanvas(Image sourceImage)
{
const double targetAspectRatio = 16d / 9d;
int sourceWidth = Math.Max(sourceImage.Width, 1);
int sourceHeight = Math.Max(sourceImage.Height, 1);
double sourceAspectRatio = (double)sourceWidth / sourceHeight;
if (sourceWidth >= sourceHeight && Math.Abs(sourceAspectRatio - targetAspectRatio) < 0.01d)
return new Bitmap(sourceImage);
int canvasWidth;
int canvasHeight;
if (sourceAspectRatio < targetAspectRatio)
{
canvasHeight = sourceHeight;
canvasWidth = (int)Math.Ceiling(canvasHeight * targetAspectRatio);
}
else
{
canvasWidth = sourceWidth;
canvasHeight = (int)Math.Ceiling(canvasWidth / targetAspectRatio);
}
canvasWidth = Math.Max(canvasWidth, sourceWidth);
canvasHeight = Math.Max(canvasHeight, sourceHeight);
var heroCanvas = new Bitmap(canvasWidth, canvasHeight, PixelFormat.Format32bppArgb);
using (var graphics = Graphics.FromImage(heroCanvas))
{
graphics.Clear(Color.Black);
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
int x = (canvasWidth - sourceWidth) / 2;
int y = (canvasHeight - sourceHeight) / 2;
graphics.DrawImage(sourceImage, new Rectangle(x, y, sourceWidth, sourceHeight));
}
#if DEBUG
System.Diagnostics.Debug.WriteLine($"[Toast] Hero canvas created: source={sourceWidth}x{sourceHeight}, canvas={canvasWidth}x{canvasHeight}");
#endif
return heroCanvas;
}
private void PlaybackTimer_Tick(object sender, EventArgs e)
@@ -621,6 +544,9 @@ namespace RadioDJViewer
{
try
{
if (_isDisconnecting || _connectionCts.IsCancellationRequested || IsDisposed)
return;
var doc = new XmlDocument();
doc.LoadXml(xml);
// Parse title, artist, album from XML (case-insensitive)
@@ -632,26 +558,29 @@ namespace RadioDJViewer
string elapsed = doc.SelectSingleNode("//*[translate(local-name(), 'ELAPSED', 'elapsed')='elapsed']")?.InnerText;
string duration = doc.SelectSingleNode("//*[translate(local-name(), 'DURATION', 'duration')='duration']")?.InnerText;
marqueeTextTitle = !string.IsNullOrWhiteSpace(title) ? title : "No title";
marqueeTextArtist = !string.IsNullOrWhiteSpace(artist) ? artist : "No artist";
marqueeTextAlbum = !string.IsNullOrWhiteSpace(album) ? album : "No album";
StartMarqueeTimers();
string titleText = !string.IsNullOrWhiteSpace(title) ? title : "No title";
string artistText = !string.IsNullOrWhiteSpace(artist) ? artist : "No artist";
string albumText = !string.IsNullOrWhiteSpace(album) ? album : "No album";
bool trackChanged = !string.Equals(titleText, _previousToastTitle, StringComparison.OrdinalIgnoreCase)
|| !string.Equals(artistText, _previousToastArtist, StringComparison.OrdinalIgnoreCase);
UpdatePlaybackState($"{marqueeTextArtist}|{marqueeTextTitle}", elapsed, duration);
SetSongMetadataLabels(titleText, artistText, albumText);
UpdatePlaybackState($"{artistText}|{titleText}", elapsed, duration);
// Write to output files
if (!string.IsNullOrEmpty(outputFolderPath))
{
File.WriteAllText(Path.Combine(outputFolderPath, "title.txt"), marqueeTextTitle);
File.WriteAllText(Path.Combine(outputFolderPath, "artist.txt"), marqueeTextArtist);
File.WriteAllText(Path.Combine(outputFolderPath, "album.txt"), marqueeTextAlbum);
File.WriteAllText(Path.Combine(outputFolderPath, "title.txt"), titleText);
File.WriteAllText(Path.Combine(outputFolderPath, "artist.txt"), artistText);
File.WriteAllText(Path.Combine(outputFolderPath, "album.txt"), albumText);
}
// Update in-memory cache for widget server
try
{
WidgetServer.CachedArtist = marqueeTextArtist ?? string.Empty;
WidgetServer.CachedTitle = marqueeTextTitle ?? string.Empty;
WidgetServer.CachedArtist = artistText ?? string.Empty;
WidgetServer.CachedTitle = titleText ?? string.Empty;
byte[] imgBytes = null;
// Prefer album art from main images folder
@@ -700,13 +629,25 @@ namespace RadioDJViewer
{
UpdateCurrentSongImage(null);
}
if (trackChanged)
{
#if DEBUG
System.Diagnostics.Debug.WriteLine($"[Toast] Track change detected. newTitle='{titleText}', newArtist='{artistText}'");
#endif
HandleToastForTrackChange(titleText, artistText);
_previousToastTitle = titleText;
_previousToastArtist = artistText;
}
}
catch
{
marqueeTextTitle = "No title";
marqueeTextArtist = "No artist";
marqueeTextAlbum = "No album";
StartMarqueeTimers();
if (_isDisconnecting || _connectionCts.IsCancellationRequested || IsDisposed)
return;
SetSongMetadataLabels("No title", "No artist", "No album");
_previousToastTitle = "No title";
_previousToastArtist = "No artist";
playbackTimer.Stop();
_playbackElapsedSeconds = 0;
_playbackDurationSeconds = 0;
@@ -802,7 +743,7 @@ namespace RadioDJViewer
if (widgetServer == null)
{
int port = loadedProfile.WebServerPort > 0 ? loadedProfile.WebServerPort : 8080;
widgetServer = new WidgetServer(port, () => marqueeTextArtist, () => marqueeTextTitle, () => this.currentSongImagePath ?? this.defaultImagePath);
widgetServer = new WidgetServer(port, () => _previousToastArtist, () => _previousToastTitle, () => this.currentSongImagePath ?? this.defaultImagePath);
}
widgetServer.Start();
widgetRunning = true;
@@ -827,9 +768,7 @@ namespace RadioDJViewer
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var versionAttr = assembly.GetCustomAttributes(typeof(System.Reflection.AssemblyFileVersionAttribute), false)
.OfType<System.Reflection.AssemblyFileVersionAttribute>().FirstOrDefault();
string version = versionAttr != null ? versionAttr.Version : assembly.GetName().Version.ToString();
string version = assembly.GetName().Version.ToString();
string message = $"RadioDJViewer\nVersion: {version}\nGitHub: https://git.smartcraft.me/minster586/RadioDJViewer";
MessageBox.Show(message, "About RadioDJViewer", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
@@ -852,19 +791,41 @@ namespace RadioDJViewer
loadedProfile = profile;
int pollingRate = profile.PollingRateSeconds > 0 ? profile.PollingRateSeconds : 3;
apiTimer.Interval = pollingRate * 1000;
SetMarqueeScrollSpeed(profile.MarqueeScrollSpeed ?? "Medium");
SetMarqueePauseTime(profile.MarqueePauseTime > 0 ? profile.MarqueePauseTime : 6);
SetMarqueeSeparator(profile.MarqueeSeparator ?? " | ");
if (pauseTimerTitle != null) pauseTimerTitle.Interval = marqueePauseTime;
if (pauseTimerArtist != null) pauseTimerArtist.Interval = marqueePauseTime;
if (pauseTimerAlbum != null) pauseTimerAlbum.Interval = marqueePauseTime;
marqueeTimerTitle.Interval = marqueeScrollSpeed;
marqueeTimerArtist.Interval = marqueeScrollSpeed;
marqueeTimerAlbum.Interval = marqueeScrollSpeed;
WidgetServer.CachedClockVisibility = profile.ClockVisibilityEnabled;
UpdateStatusBar();
}
private void PopulateProfileDropBox()
{
profile_drop_box.Items.Clear();
var profileNames = ProfileStorage.GetProfileNames();
profile_drop_box.Items.AddRange(profileNames.ToArray());
string currentProfile = GetCurrentProfileName();
if (!string.IsNullOrEmpty(currentProfile) && profileNames.Contains(currentProfile))
profile_drop_box.SelectedItem = currentProfile;
else if (profile_drop_box.Items.Count > 0)
profile_drop_box.SelectedIndex = 0;
}
private void load_profile_button_Click(object sender, EventArgs e)
{
if (profile_drop_box.SelectedItem != null)
{
var profile = ProfileStorage.LoadProfile(profile_drop_box.SelectedItem.ToString());
if (profile != null)
{
LoadProfile(profile);
UpdateStatusBar();
MessageBox.Show($"Profile '{profile.Name}' loaded.", "Profile Loaded", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
public string GetCurrentProfileName()
{
return currentProfile;
}
private void Uicolor_Click(object sender, EventArgs e)
{
isDarkMode = !isDarkMode;
@@ -921,80 +882,21 @@ namespace RadioDJViewer
}
}
private void label7_Click(object sender, EventArgs e)
{
}
private void label9_Click(object sender, EventArgs e)
{
}
public string GetCurrentProfileName()
{
return currentProfile;
}
private void PopulateProfileDropBox()
{
profile_drop_box.Items.Clear();
var profileNames = ProfileStorage.GetProfileNames();
profile_drop_box.Items.AddRange(profileNames.ToArray());
string currentProfile = GetCurrentProfileName();
if (!string.IsNullOrEmpty(currentProfile) && profileNames.Contains(currentProfile))
profile_drop_box.SelectedItem = currentProfile;
else if (profile_drop_box.Items.Count > 0)
profile_drop_box.SelectedIndex = 0;
}
private void load_profile_button_Click(object sender, EventArgs e)
{
if (profile_drop_box.SelectedItem != null)
{
var profile = ProfileStorage.LoadProfile(profile_drop_box.SelectedItem.ToString());
if (profile != null)
{
LoadProfile(profile);
UpdateStatusBar();
MessageBox.Show($"Profile '{profile.Name}' loaded.", "Profile Loaded", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
private string FormatTimeDisplay(string elapsedSeconds, string durationSeconds)
{
double elapsed;
double duration;
if (!TryParseSeconds(elapsedSeconds, out elapsed) || !TryParseSeconds(durationSeconds, out duration))
{
return "No Data";
}
return FormatTimeDisplay(elapsed, duration);
}
private string FormatTimeDisplay(double elapsed, double duration)
{
// If duration is zero or negative, show "No Data"
if (duration <= 0)
{
return "No Data";
}
// Clamp elapsed to [0, duration]
if (elapsed < 0)
elapsed = 0;
if (elapsed > duration)
elapsed = duration;
// Convert to integers (seconds only)
int elapsedInt = (int)elapsed;
int durationInt = (int)duration;
// Convert seconds to MM:SS format
string elapsedFormatted = FormatSeconds(elapsedInt);
string durationFormatted = FormatSeconds(durationInt);
return $"{elapsedFormatted} / {durationFormatted}";
return $"{FormatSeconds(elapsedInt)} / {FormatSeconds(durationInt)}";
}
private string FormatSeconds(int seconds)
@@ -1009,6 +911,30 @@ namespace RadioDJViewer
return loadedProfile != null && loadedProfile.ToastNotificationsEnabled;
}
private static string NormalizeTrackMetadata(string value)
{
return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim();
}
private static bool HasValidTrackMetadata(string title, string artist)
{
return IsValidToastValue(title) && IsValidToastValue(artist);
}
private static bool IsValidToastValue(string value)
{
if (string.IsNullOrWhiteSpace(value))
return false;
string normalized = value.Trim();
return !normalized.Equals("No Title", StringComparison.OrdinalIgnoreCase)
&& !normalized.Equals("No Artist", StringComparison.OrdinalIgnoreCase)
&& !normalized.Equals("Unknown", StringComparison.OrdinalIgnoreCase)
&& !normalized.Equals("No title", StringComparison.OrdinalIgnoreCase)
&& !normalized.Equals("No artist", StringComparison.OrdinalIgnoreCase)
&& !normalized.Equals("unknown", StringComparison.OrdinalIgnoreCase);
}
private string GetProfileOutputImagePath()
{
if (string.IsNullOrWhiteSpace(outputFolderPath) || string.IsNullOrWhiteSpace(loadedProfile?.OutputImageName))
@@ -1017,8 +943,7 @@ namespace RadioDJViewer
try
{
string imageName = Path.ChangeExtension(loadedProfile.OutputImageName, ".png");
string fullPath = Path.GetFullPath(Path.Combine(outputFolderPath, imageName));
return fullPath;
return Path.GetFullPath(Path.Combine(outputFolderPath, imageName));
}
catch
{
@@ -1028,22 +953,57 @@ namespace RadioDJViewer
private void ShowTrackChangeToast(string title, string artist, string outputImagePath)
{
if (IsDisposed || _isDisconnecting || !isConnected)
return;
string safeTitle = string.IsNullOrWhiteSpace(title) ? "No title" : title;
string safeArtist = string.IsNullOrWhiteSpace(artist) ? "No artist" : artist;
DateTime now = DateTime.Now;
string attribution = $"Date: {now:MM/dd/yyyy} | Time: {now:hh:mm tt}";
string toastImagePath = BuildToastImagePath();
ToastNotificationService.ShowTrackChangeToast(safeTitle, safeArtist, attribution, string.IsNullOrWhiteSpace(toastImagePath) ? outputImagePath : toastImagePath);
}
private void HandleToastForTrackChange(string title, string artist)
{
if (IsDisposed || _isDisconnecting || !isConnected)
return;
string normalizedTitle = NormalizeTrackMetadata(title);
string normalizedArtist = NormalizeTrackMetadata(artist);
if (!IsToastEnabledForActiveProfile())
return;
if (!HasValidTrackMetadata(normalizedTitle, normalizedArtist))
return;
try
{
ToastNotificationService.ShowTrackChangeToast(safeTitle, safeArtist, attribution, outputImagePath);
string outputImagePath = GetProfileOutputImagePath();
System.Diagnostics.Debug.WriteLine($"[Toast] Firing toast. title='{normalizedTitle}', artist='{normalizedArtist}', imagePath='{outputImagePath}'");
ShowTrackChangeToast(normalizedTitle, normalizedArtist, outputImagePath);
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Debug.WriteLine($"[Toast] ShowTrackChangeToast failed: {ex}");
MessageBox.Show($"Toast display failed: {ex.Message}", "Toast Debug", MessageBoxButtons.OK, MessageBoxIcon.Warning);
System.Diagnostics.Debug.WriteLine($"[Toast] Trigger error: {ex}");
MessageBox.Show($"Toast trigger failed: {ex.Message}", "Toast Debug", MessageBoxButtons.OK, MessageBoxIcon.Warning);
#endif
}
}
private void label9_Click(object sender, EventArgs e)
{
}
private void label7_Click(object sender, EventArgs e)
{
}
private void label7_Click_1(object sender, EventArgs e)
{
}
}
internal static class ToastNotificationService
@@ -1177,7 +1137,7 @@ namespace RadioDJViewer
string safeImage = SecurityElement.Escape(imageUri);
string imageNode = string.IsNullOrWhiteSpace(safeImage)
? string.Empty
: $"<image placement='appLogoOverride' hint-crop='none' src='{safeImage}'/>";
: $"<image placement='hero' src='{safeImage}' hint-crop='none'/>";
#if DEBUG
System.Diagnostics.Debug.WriteLine($"[Toast] Image URI used: '{imageUri}'");
+2 -2
View File
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.14.0")]
[assembly: AssemblyFileVersion("1.14.0")]
[assembly: AssemblyVersion("1.14.5")]
[assembly: AssemblyFileVersion("1.14.5")]
+22 -107
View File
@@ -54,7 +54,7 @@
this.button6 = new System.Windows.Forms.Button();
this.label6 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.textBox7 = new System.Windows.Forms.TextBox();
this.polling_rate_textbox = new System.Windows.Forms.TextBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.toast_box_group_box = new System.Windows.Forms.GroupBox();
this.toast_check_box_enable = new System.Windows.Forms.CheckBox();
@@ -66,13 +66,6 @@
this.web_server_port_label = new System.Windows.Forms.Label();
this.web_server_label = new System.Windows.Forms.Label();
this.web_server_checkbox = new System.Windows.Forms.CheckBox();
this.label13 = new System.Windows.Forms.Label();
this.comboBoxScrollSpeed = new System.Windows.Forms.ComboBox();
this.textBoxPauseTime = new System.Windows.Forms.TextBox();
this.separatingcharacterformatbox = new System.Windows.Forms.TextBox();
this.textBox9 = new System.Windows.Forms.TextBox();
this.label9 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.label12 = new System.Windows.Forms.Label();
this.groupBox1.SuspendLayout();
this.groupBox3.SuspendLayout();
@@ -110,7 +103,7 @@
//
// ok_button_master
//
this.ok_button_master.Location = new System.Drawing.Point(54, 729);
this.ok_button_master.Location = new System.Drawing.Point(54, 684);
this.ok_button_master.Name = "ok_button_master";
this.ok_button_master.Size = new System.Drawing.Size(157, 23);
this.ok_button_master.TabIndex = 1;
@@ -119,7 +112,7 @@
//
// button2
//
this.button2.Location = new System.Drawing.Point(302, 729);
this.button2.Location = new System.Drawing.Point(301, 684);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(157, 23);
this.button2.TabIndex = 2;
@@ -193,7 +186,7 @@
//
// button3
//
this.button3.Location = new System.Drawing.Point(71, 535);
this.button3.Location = new System.Drawing.Point(66, 537);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(120, 30);
this.button3.TabIndex = 8;
@@ -202,7 +195,7 @@
//
// button4
//
this.button4.Location = new System.Drawing.Point(316, 535);
this.button4.Location = new System.Drawing.Point(279, 537);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(120, 30);
this.button4.TabIndex = 9;
@@ -215,9 +208,9 @@
this.groupBox3.Controls.Add(this.labelOutputFolderPath);
this.groupBox3.Controls.Add(this.textBox5);
this.groupBox3.Controls.Add(this.label10);
this.groupBox3.Location = new System.Drawing.Point(22, 413);
this.groupBox3.Location = new System.Drawing.Point(26, 368);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(482, 115);
this.groupBox3.Size = new System.Drawing.Size(476, 115);
this.groupBox3.TabIndex = 12;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Output Setting";
@@ -274,17 +267,17 @@
//
// button6
//
this.button6.Location = new System.Drawing.Point(23, 269);
this.button6.Location = new System.Drawing.Point(91, 234);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(140, 23);
this.button6.TabIndex = 18;
this.button6.Text = "Select Main Image Folder";
this.button6.Text = "Main Image Folder";
this.button6.UseVisualStyleBackColor = true;
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(169, 274);
this.label6.Location = new System.Drawing.Point(306, 239);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(93, 13);
this.label6.TabIndex = 19;
@@ -299,27 +292,20 @@
this.label7.TabIndex = 20;
this.label7.Text = "Polling Rate (in seconds)";
//
// textBox7
// polling_rate_textbox
//
this.textBox7.Location = new System.Drawing.Point(150, 208);
this.textBox7.Name = "textBox7";
this.textBox7.Size = new System.Drawing.Size(63, 20);
this.textBox7.TabIndex = 21;
this.polling_rate_textbox.Location = new System.Drawing.Point(150, 208);
this.polling_rate_textbox.Name = "polling_rate_textbox";
this.polling_rate_textbox.Size = new System.Drawing.Size(49, 20);
this.polling_rate_textbox.TabIndex = 21;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.toast_box_group_box);
this.groupBox2.Controls.Add(this.web_server_settings_groupbox);
this.groupBox2.Controls.Add(this.label13);
this.groupBox2.Controls.Add(this.comboBoxScrollSpeed);
this.groupBox2.Controls.Add(this.textBoxPauseTime);
this.groupBox2.Controls.Add(this.separatingcharacterformatbox);
this.groupBox2.Controls.Add(this.textBox6);
this.groupBox2.Controls.Add(this.label11);
this.groupBox2.Controls.Add(this.textBox9);
this.groupBox2.Controls.Add(this.label9);
this.groupBox2.Controls.Add(this.label8);
this.groupBox2.Controls.Add(this.textBox7);
this.groupBox2.Controls.Add(this.polling_rate_textbox);
this.groupBox2.Controls.Add(this.label7);
this.groupBox2.Controls.Add(this.label6);
this.groupBox2.Controls.Add(this.button6);
@@ -336,7 +322,7 @@
this.groupBox2.Controls.Add(this.comboBox1);
this.groupBox2.Location = new System.Drawing.Point(12, 100);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(519, 623);
this.groupBox2.Size = new System.Drawing.Size(519, 578);
this.groupBox2.TabIndex = 3;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Profiles";
@@ -345,7 +331,7 @@
//
this.toast_box_group_box.Controls.Add(this.toast_check_box_enable);
this.toast_box_group_box.Controls.Add(this.toast_label);
this.toast_box_group_box.Location = new System.Drawing.Point(133, 575);
this.toast_box_group_box.Location = new System.Drawing.Point(120, 489);
this.toast_box_group_box.Name = "toast_box_group_box";
this.toast_box_group_box.Size = new System.Drawing.Size(248, 42);
this.toast_box_group_box.TabIndex = 4;
@@ -379,9 +365,9 @@
this.web_server_settings_groupbox.Controls.Add(this.web_server_port_label);
this.web_server_settings_groupbox.Controls.Add(this.web_server_label);
this.web_server_settings_groupbox.Controls.Add(this.web_server_checkbox);
this.web_server_settings_groupbox.Location = new System.Drawing.Point(31, 308);
this.web_server_settings_groupbox.Location = new System.Drawing.Point(26, 263);
this.web_server_settings_groupbox.Name = "web_server_settings_groupbox";
this.web_server_settings_groupbox.Size = new System.Drawing.Size(471, 99);
this.web_server_settings_groupbox.Size = new System.Drawing.Size(476, 99);
this.web_server_settings_groupbox.TabIndex = 35;
this.web_server_settings_groupbox.TabStop = false;
this.web_server_settings_groupbox.Text = "Web Server Settings";
@@ -440,70 +426,6 @@
this.web_server_checkbox.Text = "Enabled";
this.web_server_checkbox.UseVisualStyleBackColor = true;
//
// label13
//
this.label13.AutoSize = true;
this.label13.Location = new System.Drawing.Point(20, 240);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(142, 13);
this.label13.TabIndex = 32;
this.label13.Text = "Separating Character Format";
//
// comboBoxScrollSpeed
//
this.comboBoxScrollSpeed.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxScrollSpeed.FormattingEnabled = true;
this.comboBoxScrollSpeed.Items.AddRange(new object[] {
"Very Slow",
"Slow",
"Medium",
"Fast",
"Very Fast"});
this.comboBoxScrollSpeed.Location = new System.Drawing.Point(382, 207);
this.comboBoxScrollSpeed.Name = "comboBoxScrollSpeed";
this.comboBoxScrollSpeed.Size = new System.Drawing.Size(97, 21);
this.comboBoxScrollSpeed.TabIndex = 29;
//
// textBoxPauseTime
//
this.textBoxPauseTime.Location = new System.Drawing.Point(382, 237);
this.textBoxPauseTime.Name = "textBoxPauseTime";
this.textBoxPauseTime.Size = new System.Drawing.Size(97, 20);
this.textBoxPauseTime.TabIndex = 30;
//
// separatingcharacterformatbox
//
this.separatingcharacterformatbox.Location = new System.Drawing.Point(164, 237);
this.separatingcharacterformatbox.Name = "separatingcharacterformatbox";
this.separatingcharacterformatbox.Size = new System.Drawing.Size(49, 20);
this.separatingcharacterformatbox.TabIndex = 31;
//
// textBox9
//
this.textBox9.Location = new System.Drawing.Point(382, 237);
this.textBox9.Name = "textBox9";
this.textBox9.Size = new System.Drawing.Size(97, 20);
this.textBox9.TabIndex = 25;
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(239, 240);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(119, 13);
this.label9.TabIndex = 24;
this.label9.Text = "Pause time (in seconds)";
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(239, 211);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(127, 13);
this.label8.TabIndex = 22;
this.label8.Text = "Scroll Speed (in Main UI)";
this.label8.Click += new System.EventHandler(this.label8_Click);
//
// label12
//
this.label12.AutoSize = true;
@@ -517,7 +439,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(553, 764);
this.ClientSize = new System.Drawing.Size(542, 716);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.button2);
this.Controls.Add(this.ok_button_master);
@@ -566,18 +488,11 @@
private System.Windows.Forms.Button button6;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.TextBox textBox7;
private System.Windows.Forms.TextBox polling_rate_textbox;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.TextBox textBox9;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.ComboBox comboBox2;
private System.Windows.Forms.TextBox textBox8;
private System.Windows.Forms.Label label12;
private System.Windows.Forms.ComboBox comboBoxScrollSpeed;
private System.Windows.Forms.TextBox textBoxPauseTime;
private System.Windows.Forms.TextBox separatingcharacterformatbox;
private System.Windows.Forms.Label label13;
private System.Windows.Forms.GroupBox web_server_settings_groupbox;
private System.Windows.Forms.Label web_server_label;
private System.Windows.Forms.CheckBox web_server_checkbox;
+5 -17
View File
@@ -20,15 +20,6 @@ namespace RadioDJViewer
{
InitializeComponent();
textBox4.UseSystemPasswordChar = true; // Obscure password field
comboBoxScrollSpeed.Items.Clear();
comboBoxScrollSpeed.Items.AddRange(new object[] {
"Very Slow",
"Slow",
"Medium",
"Fast",
"Very Fast"
});
comboBoxScrollSpeed.SelectedItem = "Medium";
this.buttonSelectOutputFolder.Click += ButtonSelectOutputFolder_Click;
this.button6.Click += ButtonSelectMainImagesFolder_Click;
this.button3.Click += button3_Click;
@@ -74,10 +65,7 @@ namespace RadioDJViewer
textBox5.Text = profile.OutputImageName;
textBox1.Text = profile.UrlFormat;
// Default polling rate to 3 if missing or zero
textBox7.Text = (profile.PollingRateSeconds > 0 ? profile.PollingRateSeconds : 3).ToString();
comboBoxScrollSpeed.SelectedItem = profile.MarqueeScrollSpeed ?? "Medium";
textBoxPauseTime.Text = profile.MarqueePauseTime > 0 ? profile.MarqueePauseTime.ToString() : "6";
separatingcharacterformatbox.Text = profile.MarqueeSeparator ?? " | ";
polling_rate_textbox.Text = (profile.PollingRateSeconds > 0 ? profile.PollingRateSeconds : 3).ToString();
// Web server settings
try
{
@@ -125,7 +113,7 @@ namespace RadioDJViewer
return;
}
int pollingRate = 3;
int.TryParse(textBox7.Text, out pollingRate);
int.TryParse(polling_rate_textbox.Text, out pollingRate);
var profile = new Profile
{
Name = textBox6.Text,
@@ -137,9 +125,9 @@ namespace RadioDJViewer
OutputImageName = textBox5.Text,
UrlFormat = textBox1.Text,
PollingRateSeconds = pollingRate,
MarqueeScrollSpeed = comboBoxScrollSpeed.SelectedItem?.ToString() ?? "Medium",
MarqueePauseTime = int.TryParse(textBoxPauseTime.Text, out int pt) ? pt : 6,
MarqueeSeparator = separatingcharacterformatbox.Text,
MarqueeScrollSpeed = "Medium",
MarqueePauseTime = 6,
MarqueeSeparator = " | ",
// Web server settings
WebServerEnabled = web_server_checkbox.Checked,
WebServerPort = int.TryParse(web_server_port_textbox.Text, out int wp) ? wp : 8080,