diff --git a/RadioDJViewer/Main.cs b/RadioDJViewer/Main.cs
index d3599ef..d4c5d26 100644
--- a/RadioDJViewer/Main.cs
+++ b/RadioDJViewer/Main.cs
@@ -21,6 +21,8 @@ using System.Security;
namespace RadioDJViewer
{
+ using System;
+
public partial class Main : Form
{
private string _currentTrackKey = string.Empty;
@@ -59,6 +61,7 @@ namespace RadioDJViewer
public Main()
{
InitializeComponent();
+ EnsureDefaultImageExists();
UpdateStatusBar();
// Set up timer for polling API every 3 seconds
apiTimer = new System.Windows.Forms.Timer();
@@ -70,6 +73,7 @@ namespace RadioDJViewer
// Wire up dark mode button
this.uicolor.Click += Uicolor_Click;
this.load_profile_button.Click += load_profile_button_Click;
+ this.FormClosed += Main_FormClosed;
PopulateProfileDropBox();
UpdateTheme();
}
@@ -184,6 +188,7 @@ namespace RadioDJViewer
WidgetServer.CachedDuration = "0";
WidgetServer.CachedTime = "No Data";
WidgetServer.CachedPaused = true;
+ SmtcService.Disable();
// Stop widget server when disconnecting
try
{
@@ -581,7 +586,7 @@ namespace RadioDJViewer
{
WidgetServer.CachedArtist = artistText ?? string.Empty;
WidgetServer.CachedTitle = titleText ?? string.Empty;
-
+
byte[] imgBytes = null;
// Prefer album art from main images folder
if (!string.IsNullOrEmpty(albumArt) && !string.IsNullOrEmpty(mainImagesFolderPath))
@@ -630,6 +635,24 @@ namespace RadioDJViewer
UpdateCurrentSongImage(null);
}
+ if (IsSmtcEnabledForActiveProfile())
+ {
+ if (HasValidSmtcMetadata(titleText, artistText))
+ {
+ string smtcImagePath = ResolveSmtcImagePath();
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[SMTC] Resolved artwork path: '{smtcImagePath}' (exists={(!string.IsNullOrWhiteSpace(smtcImagePath) && File.Exists(smtcImagePath))})");
+#endif
+ SmtcService.PublishNowPlaying(titleText, artistText, smtcImagePath, _playbackPaused);
+ }
+ else
+ SmtcService.Disable();
+ }
+ else
+ {
+ SmtcService.Disable();
+ }
+
if (trackChanged)
{
#if DEBUG
@@ -658,130 +681,10 @@ namespace RadioDJViewer
WidgetServer.CachedTime = "No Data";
WidgetServer.CachedPaused = true;
pictureBox1.Image = null;
+ SmtcService.Disable();
}
}
- private void UpdateStatusBar()
- {
- try
- {
- if (!isConnected)
- {
- toolStripStatusLabel2.BackColor = Color.Red;
- }
- else
- {
- if (isConnected && widgetRunning)
- toolStripStatusLabel2.BackColor = Color.Blue;
- else
- toolStripStatusLabel2.BackColor = Color.Green;
- }
- }
- catch { }
-
- toolStripStatusLabel4.Text = $"Profile: {currentProfile}";
- if (statusCts == null)
- {
- toolStripStatusLabel3.Text = isConnected ? "Connected to API" : "Disconnected";
- }
- }
-
- private void ShowTemporaryStatus(string message, int milliseconds)
- {
- try
- {
- statusCts?.Cancel();
- }
- catch { }
- statusCts = null;
-
- if (milliseconds <= 0)
- {
- var persistent = new CancellationTokenSource();
- statusCts = persistent;
- toolStripStatusLabel3.Text = message;
- return;
- }
-
- var cts = new CancellationTokenSource();
- statusCts = cts;
- toolStripStatusLabel3.Text = message;
-
- Task.Run(async () =>
- {
- try
- {
- await Task.Delay(milliseconds, cts.Token);
- if (!cts.IsCancellationRequested)
- {
- statusCts = null;
- this.BeginInvoke((Action)(() => {
- toolStripStatusLabel3.Text = isConnected ? "Connected to API" : "Disconnected";
- }));
- }
- }
- catch { }
- });
- }
-
- private void ClearStatusMessage()
- {
- try { statusCts?.Cancel(); } catch { }
- statusCts = null;
- try { toolStripStatusLabel3.Text = isConnected ? "Connected to API" : "Disconnected"; } catch { }
- }
-
- private void StartWidgetServerIfEnabled()
- {
- if (loadedProfile == null || !loadedProfile.WebServerEnabled)
- return;
-
- try
- {
- WidgetServer.CachedClockVisibility = loadedProfile.ClockVisibilityEnabled;
-
- if (widgetServer == null)
- {
- int port = loadedProfile.WebServerPort > 0 ? loadedProfile.WebServerPort : 8080;
- widgetServer = new WidgetServer(port, () => _previousToastArtist, () => _previousToastTitle, () => this.currentSongImagePath ?? this.defaultImagePath);
- }
- widgetServer.Start();
- widgetRunning = true;
- UpdateStatusBar();
- ShowTemporaryStatus($"Web: Running on {loadedProfile.WebServerPort}", 5000);
- }
- catch (Exception ex)
- {
- widgetRunning = false;
- UpdateStatusBar();
- ShowTemporaryStatus($"Web server error: {ex.Message}", 5000);
- }
- }
-
- private void restAPISettingToolStripMenuItem_Click(object sender, EventArgs e)
- {
- var settingsForm = new Form1();
- settingsForm.ApplyTheme(isDarkMode);
- settingsForm.ShowDialog();
- }
-
- private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
- {
- var assembly = System.Reflection.Assembly.GetExecutingAssembly();
- 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);
- }
-
- private void exitToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Application.Exit();
- }
-
- private void toolStripStatusLabel4_Click(object sender, EventArgs e)
- {
- }
-
public void LoadProfile(Profile profile)
{
currentProfile = profile.Name;
@@ -792,6 +695,8 @@ namespace RadioDJViewer
int pollingRate = profile.PollingRateSeconds > 0 ? profile.PollingRateSeconds : 3;
apiTimer.Interval = pollingRate * 1000;
WidgetServer.CachedClockVisibility = profile.ClockVisibilityEnabled;
+ if (!profile.SmtcEnabled)
+ SmtcService.Disable();
UpdateStatusBar();
}
@@ -911,6 +816,22 @@ namespace RadioDJViewer
return loadedProfile != null && loadedProfile.ToastNotificationsEnabled;
}
+ private bool IsSmtcEnabledForActiveProfile()
+ {
+ return loadedProfile != null && loadedProfile.SmtcEnabled;
+ }
+
+ private static bool HasValidSmtcMetadata(string title, string artist)
+ {
+ if (string.IsNullOrWhiteSpace(title) || string.IsNullOrWhiteSpace(artist))
+ return false;
+
+ string t = title.Trim();
+ string a = artist.Trim();
+ return !t.Equals("No title", StringComparison.OrdinalIgnoreCase)
+ && !a.Equals("No artist", StringComparison.OrdinalIgnoreCase);
+ }
+
private static string NormalizeTrackMetadata(string value)
{
return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim();
@@ -951,6 +872,26 @@ namespace RadioDJViewer
}
}
+ private string ResolveSmtcImagePath()
+ {
+ try
+ {
+ string outputImage = GetProfileOutputImagePath();
+ if (!string.IsNullOrWhiteSpace(outputImage) && File.Exists(outputImage))
+ return outputImage;
+
+ if (!string.IsNullOrWhiteSpace(currentSongImagePath) && File.Exists(currentSongImagePath))
+ return Path.GetFullPath(currentSongImagePath);
+
+ EnsureDefaultImageExists();
+ if (File.Exists(defaultImagePath))
+ return Path.GetFullPath(defaultImagePath);
+ }
+ catch { }
+
+ return string.Empty;
+ }
+
private void ShowTrackChangeToast(string title, string artist, string outputImagePath)
{
if (IsDisposed || _isDisconnecting || !isConnected)
@@ -1004,6 +945,623 @@ namespace RadioDJViewer
private void label7_Click_1(object sender, EventArgs e)
{
}
+
+ private void UpdateStatusBar()
+ {
+ try
+ {
+ if (!isConnected)
+ {
+ toolStripStatusLabel2.BackColor = Color.Red;
+ }
+ else
+ {
+ if (isConnected && widgetRunning)
+ toolStripStatusLabel2.BackColor = Color.Blue;
+ else
+ toolStripStatusLabel2.BackColor = Color.Green;
+ }
+ }
+ catch { }
+
+ toolStripStatusLabel4.Text = $"Profile: {currentProfile}";
+ if (statusCts == null)
+ {
+ toolStripStatusLabel3.Text = isConnected ? "Connected to API" : "Disconnected";
+ }
+ }
+
+ private void ShowTemporaryStatus(string message, int milliseconds)
+ {
+ try
+ {
+ statusCts?.Cancel();
+ }
+ catch { }
+ statusCts = null;
+
+ if (milliseconds <= 0)
+ {
+ var persistent = new CancellationTokenSource();
+ statusCts = persistent;
+ toolStripStatusLabel3.Text = message;
+ return;
+ }
+
+ var cts = new CancellationTokenSource();
+ statusCts = cts;
+ toolStripStatusLabel3.Text = message;
+
+ Task.Run(async () =>
+ {
+ try
+ {
+ await Task.Delay(milliseconds, cts.Token);
+ if (!cts.IsCancellationRequested)
+ {
+ statusCts = null;
+ this.BeginInvoke((Action)(() => {
+ toolStripStatusLabel3.Text = isConnected ? "Connected to API" : "Disconnected";
+ }));
+ }
+ }
+ catch { }
+ });
+ }
+
+ private void ClearStatusMessage()
+ {
+ try { statusCts?.Cancel(); } catch { }
+ statusCts = null;
+ try { toolStripStatusLabel3.Text = isConnected ? "Connected to API" : "Disconnected"; } catch { }
+ }
+
+ private void StartWidgetServerIfEnabled()
+ {
+ if (loadedProfile == null || !loadedProfile.WebServerEnabled)
+ return;
+
+ try
+ {
+ WidgetServer.CachedClockVisibility = loadedProfile.ClockVisibilityEnabled;
+
+ if (widgetServer == null)
+ {
+ int port = loadedProfile.WebServerPort > 0 ? loadedProfile.WebServerPort : 8080;
+ widgetServer = new WidgetServer(port, () => _previousToastArtist, () => _previousToastTitle, () => this.currentSongImagePath ?? this.defaultImagePath);
+ }
+ widgetServer.Start();
+ widgetRunning = true;
+ UpdateStatusBar();
+ ShowTemporaryStatus($"Web: Running on {loadedProfile.WebServerPort}", 5000);
+ }
+ catch (Exception ex)
+ {
+ widgetRunning = false;
+ UpdateStatusBar();
+ ShowTemporaryStatus($"Web server error: {ex.Message}", 5000);
+ }
+ }
+
+ private void restAPISettingToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var settingsForm = new Form1();
+ settingsForm.ApplyTheme(isDarkMode);
+ settingsForm.ShowDialog();
+ }
+
+ private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var assembly = System.Reflection.Assembly.GetExecutingAssembly();
+ 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);
+ }
+
+ private void exitToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Application.Exit();
+ }
+
+ private void toolStripStatusLabel4_Click(object sender, EventArgs e)
+ {
+ }
+
+ private void Main_FormClosed(object sender, FormClosedEventArgs e)
+ {
+ try
+ {
+ if (!string.IsNullOrWhiteSpace(_lastToastImagePath) && File.Exists(_lastToastImagePath))
+ File.Delete(_lastToastImagePath);
+ }
+ catch { }
+
+ try
+ {
+ string toastDir = Path.Combine(Path.GetTempPath(), "RadioDJViewer", "ToastImages");
+ if (Directory.Exists(toastDir))
+ {
+ foreach (var file in Directory.GetFiles(toastDir, "*.*", SearchOption.TopDirectoryOnly))
+ {
+ try { File.Delete(file); } catch { }
+ }
+ }
+ }
+ catch { }
+
+ try { SmtcService.CleanupTempArtwork(); } catch { }
+ }
+ }
+
+ internal static class SmtcService
+ {
+ private static object _mediaPlayer;
+ private static object _smtc;
+ private static string _lastThumbnailTempPath;
+
+ public static void CleanupTempArtwork()
+ {
+ try
+ {
+ string tempDir = Path.Combine(Path.GetTempPath(), "RadioDJViewer", "SmtcArt");
+ if (!Directory.Exists(tempDir))
+ return;
+
+ foreach (var file in Directory.GetFiles(tempDir, "*.*", SearchOption.TopDirectoryOnly))
+ {
+ try { File.Delete(file); } catch { }
+ }
+ }
+ catch { }
+ }
+
+ public static void PublishNowPlaying(string title, string artist, string imagePath, bool paused)
+ {
+ try
+ {
+ if (!EnsureInitialized())
+ return;
+
+ SetPropertyIfExists(_smtc, "IsEnabled", true);
+ SetPropertyIfExists(_smtc, "IsPlayEnabled", true);
+ SetPropertyIfExists(_smtc, "IsPauseEnabled", true);
+ SetPropertyIfExists(_smtc, "IsStopEnabled", true);
+ SetPropertyIfExists(_smtc, "IsNextEnabled", false);
+ SetPropertyIfExists(_smtc, "IsPreviousEnabled", false);
+ SetPlaybackStatus(paused ? "Paused" : "Playing");
+
+ object updater = GetPropertyValue(_smtc, "DisplayUpdater");
+ if (updater == null)
+ return;
+
+ SetPropertyIfExists(updater, "AppMediaId", "RadioDJViewer.NowPlaying");
+
+ Type mediaPlaybackType = Type.GetType("Windows.Media.MediaPlaybackType, Windows, ContentType=WindowsRuntime");
+ if (mediaPlaybackType != null)
+ {
+ object musicValue = Enum.Parse(mediaPlaybackType, "Music");
+ SetPropertyIfExists(updater, "Type", musicValue);
+ }
+
+ object musicProperties = GetPropertyValue(updater, "MusicProperties");
+ if (musicProperties != null)
+ {
+ SetPropertyIfExists(musicProperties, "Title", title);
+ SetPropertyIfExists(musicProperties, "Artist", artist);
+ }
+
+ TrySetThumbnail(updater, imagePath);
+ InvokeIfExists(updater, "Update");
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Publish failed: " + ex);
+#endif
+ }
+ }
+
+ public static void Disable()
+ {
+ try
+ {
+ if (_smtc != null)
+ {
+ SetPlaybackStatus("Stopped");
+ SetPropertyIfExists(_smtc, "IsEnabled", false);
+ object updater = GetPropertyValue(_smtc, "DisplayUpdater");
+ if (updater != null)
+ {
+ InvokeIfExists(updater, "ClearAll");
+ InvokeIfExists(updater, "Update");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Disable failed: " + ex);
+#endif
+ }
+ }
+
+ private static bool EnsureInitialized()
+ {
+ if (_mediaPlayer != null && _smtc != null)
+ return true;
+
+ try
+ {
+ Type mediaPlayerType = Type.GetType("Windows.Media.Playback.MediaPlayer, Windows, ContentType=WindowsRuntime");
+ if (mediaPlayerType == null)
+ return false;
+
+ _mediaPlayer = Activator.CreateInstance(mediaPlayerType);
+ if (_mediaPlayer == null)
+ return false;
+
+ object commandManager = GetPropertyValue(_mediaPlayer, "CommandManager");
+ if (commandManager != null)
+ SetPropertyIfExists(commandManager, "IsEnabled", true);
+
+ _smtc = GetPropertyValue(_mediaPlayer, "SystemMediaTransportControls");
+ return _smtc != null;
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Init failed: " + ex);
+#endif
+ return false;
+ }
+ }
+
+ private static void SetPlaybackStatus(string statusName)
+ {
+ try
+ {
+ Type playbackStatusType = Type.GetType("Windows.Media.MediaPlaybackStatus, Windows, ContentType=WindowsRuntime");
+ if (playbackStatusType == null)
+ return;
+
+ object statusValue = Enum.Parse(playbackStatusType, statusName);
+ SetPropertyIfExists(_smtc, "PlaybackStatus", statusValue);
+ }
+ catch { }
+ }
+
+ private static string CreateSmtcThumbnailTempFile(string sourcePath)
+ {
+ try
+ {
+ string ext = Path.GetExtension(sourcePath);
+ if (string.IsNullOrWhiteSpace(ext))
+ ext = ".png";
+
+ string tempDir = Path.Combine(Path.GetTempPath(), "RadioDJViewer", "SmtcArt");
+ Directory.CreateDirectory(tempDir);
+ string tempPath = Path.Combine(tempDir, $"art-{DateTime.UtcNow.Ticks}{ext}");
+
+ using (var src = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ using (var dst = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.Read))
+ {
+ src.CopyTo(dst);
+ dst.Flush(true);
+ }
+
+ _lastThumbnailTempPath = tempPath;
+ CleanupOldTempArtwork(tempDir, keepCount: 10);
+ return tempPath;
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Temp art copy failed: " + ex);
+#endif
+ return sourcePath;
+ }
+ }
+
+ private static void CleanupOldTempArtwork(string tempDir, int keepCount)
+ {
+ try
+ {
+ var files = new DirectoryInfo(tempDir)
+ .GetFiles("*.*", SearchOption.TopDirectoryOnly)
+ .OrderByDescending(f => f.CreationTimeUtc)
+ .ToList();
+
+ foreach (var file in files.Skip(Math.Max(keepCount, 1)))
+ {
+ try { file.Delete(); } catch { }
+ }
+ }
+ catch { }
+ }
+
+ private static object WaitForAsyncOperation(object asyncOp)
+ {
+ if (asyncOp == null)
+ return null;
+
+ try
+ {
+ MethodInfo getResults = asyncOp.GetType().GetMethod("GetResults", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
+ if (getResults == null)
+ return null;
+
+ // First, quick poll
+ for (int i = 0; i < 40; i++)
+ {
+ object statusObj = GetPropertyValue(asyncOp, "Status");
+ string statusText = statusObj != null ? statusObj.ToString() : string.Empty;
+ if (string.Equals(statusText, "Completed", StringComparison.OrdinalIgnoreCase) || (statusObj != null && statusObj.ToString() == "1"))
+ return getResults.Invoke(asyncOp, null);
+
+ if (string.Equals(statusText, "Canceled", StringComparison.OrdinalIgnoreCase) || string.Equals(statusText, "Error", StringComparison.OrdinalIgnoreCase))
+ break;
+
+ System.Threading.Thread.Sleep(25);
+ }
+
+ // Then wait on Completed event (more reliable for WinRT async interop)
+ EventInfo completedEvent = asyncOp.GetType().GetEvent("Completed");
+ if (completedEvent != null)
+ {
+ using (var waitHandle = new System.Threading.ManualResetEvent(false))
+ {
+ Delegate handler = BuildCompletedHandler(completedEvent.EventHandlerType, waitHandle);
+ if (handler != null)
+ {
+ completedEvent.AddEventHandler(asyncOp, handler);
+ waitHandle.WaitOne(2000);
+ completedEvent.RemoveEventHandler(asyncOp, handler);
+ }
+ }
+ }
+
+ try
+ {
+ object result = getResults.Invoke(asyncOp, null);
+ if (result != null)
+ return result;
+ }
+ catch { }
+
+#if DEBUG
+ object finalStatus = GetPropertyValue(asyncOp, "Status");
+ System.Diagnostics.Debug.WriteLine($"[SMTC] Async operation did not yield result. FinalStatus={finalStatus}");
+#endif
+ return null;
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] WaitForAsyncOperation failed: " + ex.Message);
+#endif
+ return null;
+ }
+ }
+
+ private static Delegate BuildCompletedHandler(Type handlerType, System.Threading.ManualResetEvent waitHandle)
+ {
+ try
+ {
+ MethodInfo invoke = handlerType.GetMethod("Invoke");
+ if (invoke == null)
+ return null;
+
+ var parameters = invoke.GetParameters();
+ var paramExpr = new System.Linq.Expressions.ParameterExpression[parameters.Length];
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ paramExpr[i] = System.Linq.Expressions.Expression.Parameter(parameters[i].ParameterType, parameters[i].Name);
+ }
+
+ var setMethod = typeof(System.Threading.ManualResetEvent).GetMethod("Set", Type.EmptyTypes);
+ var body = System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression.Constant(waitHandle), setMethod);
+ var lambda = System.Linq.Expressions.Expression.Lambda(handlerType, body, paramExpr);
+ return lambda.Compile();
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ private static object GetPropertyValue(object instance, string propertyName)
+ {
+ if (instance == null)
+ return null;
+
+ PropertyInfo property = instance.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
+ if (property == null)
+ return null;
+
+ return property.GetValue(instance, null);
+ }
+
+ private static void SetPropertyIfExists(object instance, string propertyName, object value)
+ {
+ if (instance == null)
+ return;
+
+ PropertyInfo property = instance.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
+ if (property == null || !property.CanWrite)
+ return;
+
+ property.SetValue(instance, value, null);
+ }
+
+ private static object InvokeIfExists(object instance, string methodName)
+ {
+ if (instance == null)
+ return null;
+
+ MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
+ if (method == null)
+ return null;
+
+ return method.Invoke(instance, null);
+ }
+
+ private static void TrySetThumbnail(object updater, string imagePath)
+ {
+ try
+ {
+ if (updater == null || string.IsNullOrWhiteSpace(imagePath))
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Thumbnail skipped: updater null or image path empty.");
+#endif
+ return;
+ }
+
+ string fullPath = Path.GetFullPath(imagePath);
+ if (!File.Exists(fullPath))
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[SMTC] Thumbnail file missing: '{fullPath}'");
+#endif
+ return;
+ }
+
+ string smtcTempPath = CreateSmtcThumbnailTempFile(fullPath);
+ if (string.IsNullOrWhiteSpace(smtcTempPath) || !File.Exists(smtcTempPath))
+ return;
+
+ Type randomAccessType = Type.GetType("Windows.Storage.Streams.RandomAccessStreamReference, Windows, ContentType=WindowsRuntime");
+ if (randomAccessType == null)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Thumbnail failed: RandomAccessStreamReference type unavailable.");
+#endif
+ return;
+ }
+
+ object streamRef = null;
+ string source = "Unknown";
+
+ try
+ {
+ streamRef = CreateThumbnailFromMemory(randomAccessType, smtcTempPath);
+ if (streamRef != null)
+ source = "CreateFromStream";
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] CreateFromStream path failed: " + ex.Message);
+#endif
+ }
+
+ if (streamRef == null)
+ {
+ try
+ {
+ Type storageFileType = Type.GetType("Windows.Storage.StorageFile, Windows, ContentType=WindowsRuntime");
+ MethodInfo getFileMethod = storageFileType?.GetMethod("GetFileFromPathAsync", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null);
+ MethodInfo createFromFileMethod = randomAccessType.GetMethod("CreateFromFile", BindingFlags.Public | BindingFlags.Static);
+ if (getFileMethod != null && createFromFileMethod != null)
+ {
+ object op = getFileMethod.Invoke(null, new object[] { smtcTempPath });
+ object storageFile = WaitForAsyncOperation(op);
+ if (storageFile != null)
+ {
+ streamRef = createFromFileMethod.Invoke(null, new[] { storageFile });
+ if (streamRef != null) source = "CreateFromFile";
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Thumbnail stream created via CreateFromFile.");
+#endif
+ }
+#if DEBUG
+ else
+ {
+ System.Diagnostics.Debug.WriteLine("[SMTC] CreateFromFile path: StorageFile result was null.");
+ }
+#endif
+ }
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] CreateFromFile path failed: " + ex.Message);
+#endif
+ }
+ }
+
+ if (streamRef == null)
+ {
+ MethodInfo createFromUriMethod = randomAccessType.GetMethod("CreateFromUri", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(Uri) }, null);
+ if (createFromUriMethod == null)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Thumbnail failed: CreateFromUri method unavailable.");
+#endif
+ return;
+ }
+
+ var fileUri = new Uri(smtcTempPath);
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[SMTC] Thumbnail URI: '{fileUri.AbsoluteUri}'");
+#endif
+ streamRef = createFromUriMethod.Invoke(null, new object[] { fileUri });
+ if (streamRef != null) source = "CreateFromUri";
+ }
+
+ if (streamRef != null)
+ {
+ SetPropertyIfExists(updater, "Thumbnail", streamRef);
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"[SMTC] Thumbnail assigned to DisplayUpdater. Source={source}");
+#endif
+ }
+ else
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Thumbnail streamRef is null.");
+#endif
+ }
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine("[SMTC] Thumbnail failed: " + ex);
+#endif
+ }
+ }
+
+ private static object CreateThumbnailFromMemory(Type randomAccessType, string filePath)
+ {
+ byte[] bytes = File.ReadAllBytes(filePath);
+ if (bytes == null || bytes.Length == 0)
+ return null;
+
+ Type memoryStreamType = Type.GetType("Windows.Storage.Streams.InMemoryRandomAccessStream, Windows, ContentType=WindowsRuntime");
+ Type dataWriterType = Type.GetType("Windows.Storage.Streams.DataWriter, Windows, ContentType=WindowsRuntime");
+ if (memoryStreamType == null || dataWriterType == null)
+ return null;
+
+ object memoryStream = Activator.CreateInstance(memoryStreamType);
+ MethodInfo getOutputStreamAt = memoryStreamType.GetMethod("GetOutputStreamAt", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(ulong) }, null);
+ object outputStream = getOutputStreamAt?.Invoke(memoryStream, new object[] { 0UL });
+ if (outputStream == null)
+ return null;
+
+ object writer = Activator.CreateInstance(dataWriterType, new[] { outputStream });
+ dataWriterType.GetMethod("WriteBytes", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(byte[]) }, null)?.Invoke(writer, new object[] { bytes });
+
+ object storeOp = dataWriterType.GetMethod("StoreAsync", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null)?.Invoke(writer, null);
+ WaitForAsyncOperation(storeOp);
+ object flushOp = dataWriterType.GetMethod("FlushAsync", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null)?.Invoke(writer, null);
+ WaitForAsyncOperation(flushOp);
+
+ dataWriterType.GetMethod("DetachStream", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null)?.Invoke(writer, null);
+ memoryStreamType.GetMethod("Seek", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(ulong) }, null)?.Invoke(memoryStream, new object[] { 0UL });
+
+ MethodInfo createFromStream = randomAccessType.GetMethod("CreateFromStream", BindingFlags.Public | BindingFlags.Static);
+ return createFromStream?.Invoke(null, new[] { memoryStream });
+ }
}
internal static class ToastNotificationService
diff --git a/RadioDJViewer/ProfileStorage.cs b/RadioDJViewer/ProfileStorage.cs
index 76100b5..ec15559 100644
--- a/RadioDJViewer/ProfileStorage.cs
+++ b/RadioDJViewer/ProfileStorage.cs
@@ -26,6 +26,7 @@ namespace RadioDJViewer
// Clock visibility setting
public bool ClockVisibilityEnabled { get; set; }
public bool ToastNotificationsEnabled { get; set; }
+ public bool SmtcEnabled { get; set; }
}
public static class ProfileStorage
diff --git a/RadioDJViewer/Properties/AssemblyInfo.cs b/RadioDJViewer/Properties/AssemblyInfo.cs
index 3342d4d..2ac9191 100644
--- a/RadioDJViewer/Properties/AssemblyInfo.cs
+++ b/RadioDJViewer/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
-[assembly: AssemblyVersion("1.14.5")]
-[assembly: AssemblyFileVersion("1.14.5")]
+[assembly: AssemblyVersion("1.15.0")]
+[assembly: AssemblyFileVersion("1.15.0")]
diff --git a/RadioDJViewer/radiodj-restapi-template.Designer.cs b/RadioDJViewer/radiodj-restapi-template.Designer.cs
index 45728b0..a11bf20 100644
--- a/RadioDJViewer/radiodj-restapi-template.Designer.cs
+++ b/RadioDJViewer/radiodj-restapi-template.Designer.cs
@@ -67,11 +67,29 @@
this.web_server_label = new System.Windows.Forms.Label();
this.web_server_checkbox = new System.Windows.Forms.CheckBox();
this.label12 = new System.Windows.Forms.Label();
+ this.tab_controls = new System.Windows.Forms.TabControl();
+ this.settings_tab_page = new System.Windows.Forms.TabPage();
+ this.output_settings_tab_page = new System.Windows.Forms.TabPage();
+ this.connection_settings_box = new System.Windows.Forms.GroupBox();
+ this.notice_one = new System.Windows.Forms.Label();
+ this.misc_tab_page = new System.Windows.Forms.TabPage();
+ this.groupBox4 = new System.Windows.Forms.GroupBox();
+ this.smtc_enable_label = new System.Windows.Forms.Label();
+ this.smtc_check_box = new System.Windows.Forms.CheckBox();
+ this.notice_two = new System.Windows.Forms.Label();
+ this.loaded_profile_label = new System.Windows.Forms.Label();
+ this.profile_loaded_data = new System.Windows.Forms.Label();
this.groupBox1.SuspendLayout();
this.groupBox3.SuspendLayout();
this.groupBox2.SuspendLayout();
this.toast_box_group_box.SuspendLayout();
this.web_server_settings_groupbox.SuspendLayout();
+ this.tab_controls.SuspendLayout();
+ this.settings_tab_page.SuspendLayout();
+ this.output_settings_tab_page.SuspendLayout();
+ this.connection_settings_box.SuspendLayout();
+ this.misc_tab_page.SuspendLayout();
+ this.groupBox4.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
@@ -139,7 +157,7 @@
// label3
//
this.label3.AutoSize = true;
- this.label3.Location = new System.Drawing.Point(20, 100);
+ this.label3.Location = new System.Drawing.Point(20, 27);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(57, 13);
this.label3.TabIndex = 2;
@@ -147,41 +165,41 @@
//
// textBox2
//
- this.textBox2.Location = new System.Drawing.Point(120, 97);
+ this.textBox2.Location = new System.Drawing.Point(103, 24);
this.textBox2.Name = "textBox2";
- this.textBox2.Size = new System.Drawing.Size(290, 20);
+ this.textBox2.Size = new System.Drawing.Size(122, 20);
this.textBox2.TabIndex = 3;
//
// label4
//
this.label4.AutoSize = true;
- this.label4.Location = new System.Drawing.Point(20, 135);
+ this.label4.Location = new System.Drawing.Point(20, 60);
this.label4.Name = "label4";
- this.label4.Size = new System.Drawing.Size(26, 13);
+ this.label4.Size = new System.Drawing.Size(29, 13);
this.label4.TabIndex = 4;
- this.label4.Text = "Port";
+ this.label4.Text = "Port:";
//
// textBox3
//
- this.textBox3.Location = new System.Drawing.Point(120, 132);
+ this.textBox3.Location = new System.Drawing.Point(103, 54);
this.textBox3.Name = "textBox3";
- this.textBox3.Size = new System.Drawing.Size(290, 20);
+ this.textBox3.Size = new System.Drawing.Size(122, 20);
this.textBox3.TabIndex = 5;
//
// label5
//
this.label5.AutoSize = true;
- this.label5.Location = new System.Drawing.Point(20, 170);
+ this.label5.Location = new System.Drawing.Point(20, 88);
this.label5.Name = "label5";
- this.label5.Size = new System.Drawing.Size(53, 13);
+ this.label5.Size = new System.Drawing.Size(56, 13);
this.label5.TabIndex = 6;
- this.label5.Text = "Password";
+ this.label5.Text = "Password:";
//
// textBox4
//
- this.textBox4.Location = new System.Drawing.Point(120, 167);
+ this.textBox4.Location = new System.Drawing.Point(103, 83);
this.textBox4.Name = "textBox4";
- this.textBox4.Size = new System.Drawing.Size(290, 20);
+ this.textBox4.Size = new System.Drawing.Size(122, 20);
this.textBox4.TabIndex = 7;
//
// button3
@@ -204,20 +222,21 @@
//
// groupBox3
//
+ this.groupBox3.Controls.Add(this.notice_one);
this.groupBox3.Controls.Add(this.buttonSelectOutputFolder);
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(26, 368);
+ this.groupBox3.Location = new System.Drawing.Point(74, 127);
this.groupBox3.Name = "groupBox3";
- this.groupBox3.Size = new System.Drawing.Size(476, 115);
+ this.groupBox3.Size = new System.Drawing.Size(256, 229);
this.groupBox3.TabIndex = 12;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Output Setting";
//
// buttonSelectOutputFolder
//
- this.buttonSelectOutputFolder.Location = new System.Drawing.Point(20, 36);
+ this.buttonSelectOutputFolder.Location = new System.Drawing.Point(63, 58);
this.buttonSelectOutputFolder.Name = "buttonSelectOutputFolder";
this.buttonSelectOutputFolder.Size = new System.Drawing.Size(140, 23);
this.buttonSelectOutputFolder.TabIndex = 17;
@@ -227,23 +246,24 @@
// labelOutputFolderPath
//
this.labelOutputFolderPath.AutoSize = true;
- this.labelOutputFolderPath.Location = new System.Drawing.Point(166, 41);
+ this.labelOutputFolderPath.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.labelOutputFolderPath.Location = new System.Drawing.Point(78, 89);
this.labelOutputFolderPath.Name = "labelOutputFolderPath";
- this.labelOutputFolderPath.Size = new System.Drawing.Size(93, 13);
+ this.labelOutputFolderPath.Size = new System.Drawing.Size(111, 13);
this.labelOutputFolderPath.TabIndex = 16;
this.labelOutputFolderPath.Text = "No folder selected";
//
// textBox5
//
- this.textBox5.Location = new System.Drawing.Point(149, 80);
+ this.textBox5.Location = new System.Drawing.Point(159, 29);
this.textBox5.Name = "textBox5";
- this.textBox5.Size = new System.Drawing.Size(247, 20);
+ this.textBox5.Size = new System.Drawing.Size(83, 20);
this.textBox5.TabIndex = 16;
//
// label10
//
this.label10.AutoSize = true;
- this.label10.Location = new System.Drawing.Point(17, 83);
+ this.label10.Location = new System.Drawing.Point(19, 32);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(126, 13);
this.label10.TabIndex = 15;
@@ -267,7 +287,7 @@
//
// button6
//
- this.button6.Location = new System.Drawing.Point(91, 234);
+ this.button6.Location = new System.Drawing.Point(53, 149);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(140, 23);
this.button6.TabIndex = 18;
@@ -277,7 +297,7 @@
// label6
//
this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(306, 239);
+ this.label6.Location = new System.Drawing.Point(78, 181);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(93, 13);
this.label6.TabIndex = 19;
@@ -286,38 +306,28 @@
// label7
//
this.label7.AutoSize = true;
- this.label7.Location = new System.Drawing.Point(20, 211);
+ this.label7.Location = new System.Drawing.Point(20, 117);
this.label7.Name = "label7";
- this.label7.Size = new System.Drawing.Size(124, 13);
+ this.label7.Size = new System.Drawing.Size(127, 13);
this.label7.TabIndex = 20;
- this.label7.Text = "Polling Rate (in seconds)";
+ this.label7.Text = "Polling Rate (in seconds):";
//
// polling_rate_textbox
//
- this.polling_rate_textbox.Location = new System.Drawing.Point(150, 208);
+ this.polling_rate_textbox.Location = new System.Drawing.Point(176, 114);
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.profile_loaded_data);
+ this.groupBox2.Controls.Add(this.loaded_profile_label);
+ this.groupBox2.Controls.Add(this.tab_controls);
this.groupBox2.Controls.Add(this.textBox6);
this.groupBox2.Controls.Add(this.label11);
- 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);
- this.groupBox2.Controls.Add(this.groupBox3);
this.groupBox2.Controls.Add(this.button4);
this.groupBox2.Controls.Add(this.button3);
- this.groupBox2.Controls.Add(this.textBox4);
- this.groupBox2.Controls.Add(this.label5);
- this.groupBox2.Controls.Add(this.textBox3);
- this.groupBox2.Controls.Add(this.label4);
- this.groupBox2.Controls.Add(this.textBox2);
- this.groupBox2.Controls.Add(this.label3);
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.comboBox1);
this.groupBox2.Location = new System.Drawing.Point(12, 100);
@@ -331,7 +341,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(120, 489);
+ this.toast_box_group_box.Location = new System.Drawing.Point(20, 22);
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;
@@ -365,9 +375,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(26, 263);
+ this.web_server_settings_groupbox.Location = new System.Drawing.Point(80, 26);
this.web_server_settings_groupbox.Name = "web_server_settings_groupbox";
- this.web_server_settings_groupbox.Size = new System.Drawing.Size(476, 99);
+ this.web_server_settings_groupbox.Size = new System.Drawing.Size(236, 95);
this.web_server_settings_groupbox.TabIndex = 35;
this.web_server_settings_groupbox.TabStop = false;
this.web_server_settings_groupbox.Text = "Web Server Settings";
@@ -375,7 +385,7 @@
// clock_visibility_checkBox
//
this.clock_visibility_checkBox.AutoSize = true;
- this.clock_visibility_checkBox.Location = new System.Drawing.Point(119, 55);
+ this.clock_visibility_checkBox.Location = new System.Drawing.Point(156, 67);
this.clock_visibility_checkBox.Name = "clock_visibility_checkBox";
this.clock_visibility_checkBox.Size = new System.Drawing.Size(65, 17);
this.clock_visibility_checkBox.TabIndex = 38;
@@ -385,7 +395,7 @@
// clock_label
//
this.clock_label.AutoSize = true;
- this.clock_label.Location = new System.Drawing.Point(44, 56);
+ this.clock_label.Location = new System.Drawing.Point(44, 68);
this.clock_label.Name = "clock_label";
this.clock_label.Size = new System.Drawing.Size(76, 13);
this.clock_label.TabIndex = 37;
@@ -393,7 +403,7 @@
//
// web_server_port_textbox
//
- this.web_server_port_textbox.Location = new System.Drawing.Point(246, 19);
+ this.web_server_port_textbox.Location = new System.Drawing.Point(139, 42);
this.web_server_port_textbox.Name = "web_server_port_textbox";
this.web_server_port_textbox.Size = new System.Drawing.Size(77, 20);
this.web_server_port_textbox.TabIndex = 36;
@@ -401,7 +411,7 @@
// web_server_port_label
//
this.web_server_port_label.AutoSize = true;
- this.web_server_port_label.Location = new System.Drawing.Point(211, 23);
+ this.web_server_port_label.Location = new System.Drawing.Point(45, 46);
this.web_server_port_label.Name = "web_server_port_label";
this.web_server_port_label.Size = new System.Drawing.Size(29, 13);
this.web_server_port_label.TabIndex = 35;
@@ -419,7 +429,7 @@
// web_server_checkbox
//
this.web_server_checkbox.AutoSize = true;
- this.web_server_checkbox.Location = new System.Drawing.Point(111, 23);
+ this.web_server_checkbox.Location = new System.Drawing.Point(154, 23);
this.web_server_checkbox.Name = "web_server_checkbox";
this.web_server_checkbox.Size = new System.Drawing.Size(65, 17);
this.web_server_checkbox.TabIndex = 34;
@@ -435,6 +445,140 @@
this.label12.TabIndex = 27;
this.label12.Text = "Separating character format";
//
+ // tab_controls
+ //
+ this.tab_controls.Controls.Add(this.settings_tab_page);
+ this.tab_controls.Controls.Add(this.output_settings_tab_page);
+ this.tab_controls.Controls.Add(this.misc_tab_page);
+ this.tab_controls.Location = new System.Drawing.Point(42, 133);
+ this.tab_controls.Name = "tab_controls";
+ this.tab_controls.SelectedIndex = 0;
+ this.tab_controls.Size = new System.Drawing.Size(423, 398);
+ this.tab_controls.TabIndex = 22;
+ //
+ // settings_tab_page
+ //
+ this.settings_tab_page.Controls.Add(this.connection_settings_box);
+ this.settings_tab_page.Location = new System.Drawing.Point(4, 22);
+ this.settings_tab_page.Name = "settings_tab_page";
+ this.settings_tab_page.Padding = new System.Windows.Forms.Padding(3);
+ this.settings_tab_page.Size = new System.Drawing.Size(415, 372);
+ this.settings_tab_page.TabIndex = 0;
+ this.settings_tab_page.Text = "Profile Settings";
+ this.settings_tab_page.UseVisualStyleBackColor = true;
+ //
+ // output_settings_tab_page
+ //
+ this.output_settings_tab_page.Controls.Add(this.web_server_settings_groupbox);
+ this.output_settings_tab_page.Controls.Add(this.groupBox3);
+ this.output_settings_tab_page.Location = new System.Drawing.Point(4, 22);
+ this.output_settings_tab_page.Name = "output_settings_tab_page";
+ this.output_settings_tab_page.Padding = new System.Windows.Forms.Padding(3);
+ this.output_settings_tab_page.Size = new System.Drawing.Size(415, 372);
+ this.output_settings_tab_page.TabIndex = 1;
+ this.output_settings_tab_page.Text = "Output Settings";
+ this.output_settings_tab_page.UseVisualStyleBackColor = true;
+ //
+ // connection_settings_box
+ //
+ this.connection_settings_box.Controls.Add(this.textBox2);
+ this.connection_settings_box.Controls.Add(this.label3);
+ this.connection_settings_box.Controls.Add(this.label4);
+ this.connection_settings_box.Controls.Add(this.label6);
+ this.connection_settings_box.Controls.Add(this.polling_rate_textbox);
+ this.connection_settings_box.Controls.Add(this.button6);
+ this.connection_settings_box.Controls.Add(this.textBox3);
+ this.connection_settings_box.Controls.Add(this.label7);
+ this.connection_settings_box.Controls.Add(this.label5);
+ this.connection_settings_box.Controls.Add(this.textBox4);
+ this.connection_settings_box.Location = new System.Drawing.Point(74, 82);
+ this.connection_settings_box.Name = "connection_settings_box";
+ this.connection_settings_box.Size = new System.Drawing.Size(248, 215);
+ this.connection_settings_box.TabIndex = 13;
+ this.connection_settings_box.TabStop = false;
+ this.connection_settings_box.Text = "Connection Settings";
+ //
+ // notice_one
+ //
+ this.notice_one.AutoSize = true;
+ this.notice_one.Location = new System.Drawing.Point(53, 117);
+ this.notice_one.Name = "notice_one";
+ this.notice_one.Size = new System.Drawing.Size(182, 65);
+ this.notice_one.TabIndex = 18;
+ this.notice_one.Text = "It is asking for an image file name.\r\nThis is what you would use\r\nto put a name o" +
+ "f what\r\nthe saved image will be outputted as.\r\nFor example, it might be img.png";
+ //
+ // misc_tab_page
+ //
+ this.misc_tab_page.Controls.Add(this.groupBox4);
+ this.misc_tab_page.Controls.Add(this.toast_box_group_box);
+ this.misc_tab_page.Location = new System.Drawing.Point(4, 22);
+ this.misc_tab_page.Name = "misc_tab_page";
+ this.misc_tab_page.Padding = new System.Windows.Forms.Padding(3);
+ this.misc_tab_page.Size = new System.Drawing.Size(415, 372);
+ this.misc_tab_page.TabIndex = 2;
+ this.misc_tab_page.Text = "Misc Settings";
+ this.misc_tab_page.UseVisualStyleBackColor = true;
+ //
+ // groupBox4
+ //
+ this.groupBox4.Controls.Add(this.notice_two);
+ this.groupBox4.Controls.Add(this.smtc_check_box);
+ this.groupBox4.Controls.Add(this.smtc_enable_label);
+ this.groupBox4.Location = new System.Drawing.Point(20, 92);
+ this.groupBox4.Name = "groupBox4";
+ this.groupBox4.Size = new System.Drawing.Size(370, 155);
+ this.groupBox4.TabIndex = 4;
+ this.groupBox4.TabStop = false;
+ this.groupBox4.Text = "SMTC Control";
+ //
+ // smtc_enable_label
+ //
+ this.smtc_enable_label.AutoSize = true;
+ this.smtc_enable_label.Location = new System.Drawing.Point(115, 27);
+ this.smtc_enable_label.Name = "smtc_enable_label";
+ this.smtc_enable_label.Size = new System.Drawing.Size(73, 13);
+ this.smtc_enable_label.TabIndex = 0;
+ this.smtc_enable_label.Text = "SMTC Enable";
+ //
+ // smtc_check_box
+ //
+ this.smtc_check_box.AutoSize = true;
+ this.smtc_check_box.Location = new System.Drawing.Point(194, 27);
+ this.smtc_check_box.Name = "smtc_check_box";
+ this.smtc_check_box.Size = new System.Drawing.Size(59, 17);
+ this.smtc_check_box.TabIndex = 2;
+ this.smtc_check_box.Text = "Enable";
+ this.smtc_check_box.UseVisualStyleBackColor = true;
+ //
+ // notice_two
+ //
+ this.notice_two.AutoSize = true;
+ this.notice_two.Location = new System.Drawing.Point(52, 62);
+ this.notice_two.Name = "notice_two";
+ this.notice_two.Size = new System.Drawing.Size(274, 78);
+ this.notice_two.TabIndex = 3;
+ this.notice_two.Text = resources.GetString("notice_two.Text");
+ //
+ // loaded_profile_label
+ //
+ this.loaded_profile_label.AutoSize = true;
+ this.loaded_profile_label.Location = new System.Drawing.Point(134, 103);
+ this.loaded_profile_label.Name = "loaded_profile_label";
+ this.loaded_profile_label.Size = new System.Drawing.Size(77, 13);
+ this.loaded_profile_label.TabIndex = 23;
+ this.loaded_profile_label.Text = "Loaded profile:";
+ //
+ // profile_loaded_data
+ //
+ this.profile_loaded_data.AutoSize = true;
+ this.profile_loaded_data.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.profile_loaded_data.Location = new System.Drawing.Point(218, 102);
+ this.profile_loaded_data.Name = "profile_loaded_data";
+ this.profile_loaded_data.Size = new System.Drawing.Size(104, 13);
+ this.profile_loaded_data.TabIndex = 24;
+ this.profile_loaded_data.Text = "No profile loaded";
+ //
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -457,6 +601,14 @@
this.toast_box_group_box.PerformLayout();
this.web_server_settings_groupbox.ResumeLayout(false);
this.web_server_settings_groupbox.PerformLayout();
+ this.tab_controls.ResumeLayout(false);
+ this.settings_tab_page.ResumeLayout(false);
+ this.output_settings_tab_page.ResumeLayout(false);
+ this.connection_settings_box.ResumeLayout(false);
+ this.connection_settings_box.PerformLayout();
+ this.misc_tab_page.ResumeLayout(false);
+ this.groupBox4.ResumeLayout(false);
+ this.groupBox4.PerformLayout();
this.ResumeLayout(false);
}
@@ -503,5 +655,17 @@
private System.Windows.Forms.GroupBox toast_box_group_box;
private System.Windows.Forms.CheckBox toast_check_box_enable;
private System.Windows.Forms.Label toast_label;
+ private System.Windows.Forms.TabControl tab_controls;
+ private System.Windows.Forms.TabPage settings_tab_page;
+ private System.Windows.Forms.TabPage output_settings_tab_page;
+ private System.Windows.Forms.GroupBox connection_settings_box;
+ private System.Windows.Forms.Label notice_one;
+ private System.Windows.Forms.TabPage misc_tab_page;
+ private System.Windows.Forms.GroupBox groupBox4;
+ private System.Windows.Forms.Label notice_two;
+ private System.Windows.Forms.CheckBox smtc_check_box;
+ private System.Windows.Forms.Label smtc_enable_label;
+ private System.Windows.Forms.Label profile_loaded_data;
+ private System.Windows.Forms.Label loaded_profile_label;
}
}
\ No newline at end of file
diff --git a/RadioDJViewer/radiodj-restapi-template.cs b/RadioDJViewer/radiodj-restapi-template.cs
index c760578..8e411b4 100644
--- a/RadioDJViewer/radiodj-restapi-template.cs
+++ b/RadioDJViewer/radiodj-restapi-template.cs
@@ -64,6 +64,7 @@ namespace RadioDJViewer
label6.Text = mainImagesFolderPath;
textBox5.Text = profile.OutputImageName;
textBox1.Text = profile.UrlFormat;
+ profile_loaded_data.Text = profile.Name;
// Default polling rate to 3 if missing or zero
polling_rate_textbox.Text = (profile.PollingRateSeconds > 0 ? profile.PollingRateSeconds : 3).ToString();
// Web server settings
@@ -74,10 +75,14 @@ namespace RadioDJViewer
// Clock visibility setting
clock_visibility_checkBox.Checked = profile.ClockVisibilityEnabled;
toast_check_box_enable.Checked = profile.ToastNotificationsEnabled;
+ smtc_check_box.Checked = profile.SmtcEnabled;
}
catch { }
+ return;
}
}
+
+ profile_loaded_data.Text = "No profile loaded";
}
private void ButtonSelectOutputFolder_Click(object sender, EventArgs e)
@@ -133,13 +138,16 @@ namespace RadioDJViewer
WebServerPort = int.TryParse(web_server_port_textbox.Text, out int wp) ? wp : 8080,
// Clock visibility setting
ClockVisibilityEnabled = clock_visibility_checkBox.Checked,
- ToastNotificationsEnabled = toast_check_box_enable.Checked
+ ToastNotificationsEnabled = toast_check_box_enable.Checked,
+ SmtcEnabled = smtc_check_box.Checked
};
ProfileStorage.SaveProfile(profile);
// Refresh profile list
comboBox1.Items.Clear();
var names = ProfileStorage.GetProfileNames();
comboBox1.Items.AddRange(names.ToArray());
+ comboBox1.SelectedItem = profile.Name;
+ profile_loaded_data.Text = profile.Name;
MessageBox.Show("Profile saved successfully.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
@@ -148,10 +156,15 @@ namespace RadioDJViewer
// Remove Profile (Remove Profile button)
if (comboBox1.SelectedItem != null)
{
- ProfileStorage.DeleteProfile(comboBox1.SelectedItem.ToString());
+ string removed = comboBox1.SelectedItem.ToString();
+ ProfileStorage.DeleteProfile(removed);
comboBox1.Items.Clear();
var names = ProfileStorage.GetProfileNames();
comboBox1.Items.AddRange(names.ToArray());
+ if (comboBox1.Items.Count > 0)
+ comboBox1.SelectedIndex = 0;
+ else
+ profile_loaded_data.Text = "No profile loaded";
}
}
diff --git a/RadioDJViewer/radiodj-restapi-template.resx b/RadioDJViewer/radiodj-restapi-template.resx
index 8ee15e7..1fe0a6a 100644
--- a/RadioDJViewer/radiodj-restapi-template.resx
+++ b/RadioDJViewer/radiodj-restapi-template.resx
@@ -117,6 +117,14 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ With this option, it will enable the output
+to Simple Media Transport Control Protocol (AKA SMTC).
+You will not be able to control Radio DJ,
+but you will get push notifications
+or it will be pushed out to the SMTC protocol
+with the ability to use it with other applications.
+