Skip to content

Commit f98038c

Browse files
committed
Added ShowLeadingZero toggle
1 parent c4b675a commit f98038c

5 files changed

Lines changed: 104 additions & 32 deletions

File tree

Clock.cs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using CppSharp.AST;
12
using Microsoft.VisualBasic;
23
using Newtonsoft.Json;
34
using Newtonsoft.Json.Linq;
@@ -14,13 +15,19 @@ namespace StreamStartingTimer {
1415
public partial class Clock : Form {
1516
public int SecondsToGo { get; set; }
1617
private Binding bndTestTime;
17-
private ClockSpout ImageClock;
18+
private ClockSpout ImageClock = null;
1819
private Task ImageClockUpdaterTask;
1920
public bool TimerRunning;
2021

2122
private void TimeSpanToString(object sender, ConvertEventArgs cevent) {
23+
string TimeText;
2224
if (cevent.DesiredType != typeof(string)) return;
23-
cevent.Value = ((TimeSpan)cevent.Value).ToString(Shared.TimeFormat);
25+
TimeText = ((TimeSpan)cevent.Value).ToString(Shared.TimeFormat);
26+
if (!Shared.CurSettings.ShowLeadingZero && TimeText[0] == '0') {
27+
TimeText = ' ' + TimeText.Substring(1);
28+
}
29+
30+
cevent.Value = TimeText;
2431
}
2532

2633
public Clock(int StartTime, string EventsFile) {
@@ -35,7 +42,7 @@ public Clock(int StartTime, string EventsFile) {
3542
lblCountdown.DataBindings.Add(bndTestTime);
3643

3744
if (StartTime > 0) {
38-
StartTimer(StartTime);
45+
SecondsToGo = StartTime;
3946
QuitWhenDone = true;
4047
} else {
4148
QuitWhenDone = false;
@@ -123,7 +130,11 @@ public void StartCountdown(int CountdownTime) {
123130
}
124131

125132
private void UpdateClock(TimeSpan SecondsToGo) {
126-
lblCountdown.Text = SecondsToGo.ToString(Shared.TimeFormat);
133+
string TimeText = SecondsToGo.ToString(Shared.TimeFormat);
134+
if (!Shared.CurSettings.ShowLeadingZero && TimeText[0] == '0') {
135+
TimeText = ' ' + TimeText.Substring(1);
136+
}
137+
lblCountdown.Text = TimeText;
127138
if (Shared.CurSettings.SpoutEnabled) { ImageClock.UpdateTexture(); }
128139
}
129140
private void UpdateClock(int SecondsToGo) {
@@ -241,6 +252,10 @@ private void btnAdd60s_Click(object sender, EventArgs e) {
241252

242253
private void Clock_Shown(object sender, EventArgs e) {
243254
Connect();
255+
OpenGLHandler.InitGL();
256+
if (SecondsToGo > 0) {
257+
StartTimer(SecondsToGo);
258+
}
244259
}
245260

246261
private void btnConfig_Click(object sender, EventArgs e) {
@@ -264,7 +279,8 @@ private void btnConfig_Click(object sender, EventArgs e) {
264279
}
265280

266281
private void Clock_FormClosing(object sender, FormClosingEventArgs e) {
267-
ImageClock.Dispose();
282+
if (ImageClock != null) { ImageClock.Dispose(); }
283+
OpenGLHandler.CloseGL();
268284
GC.Collect();
269285
GC.WaitForPendingFinalizers();
270286
}

ClockSpout.cs

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
using Silk.NET.Core.Contexts;
2-
using Silk.NET.Core.Loader;
3-
using Silk.NET.Maths;
1+
//using Silk.NET.Core.Contexts;
2+
//using Silk.NET.Core.Loader;
3+
//using TerraFX.Interop.Windows;
4+
//using static TerraFX.Interop.Windows.Windows;
45
using Spout.Interop;
56
using System;
67
using System.Collections.Generic;
78
using System.Diagnostics;
9+
using System.Diagnostics.Eventing.Reader;
810
using System.Drawing;
911
using System.Drawing.Imaging;
1012
using System.Drawing.Text;
@@ -17,31 +19,38 @@
1719
using System.Threading.Tasks;
1820
using System.Windows.Forms;
1921
using System.Xml.Linq;
20-
using TerraFX.Interop.DirectX;
21-
using TerraFX.Interop.Windows;
2222
using static System.Net.Mime.MediaTypeNames;
2323
using static System.Runtime.InteropServices.JavaScript.JSType;
2424
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
25-
using static TerraFX.Interop.Windows.Windows;
25+
2626

2727

2828

2929
namespace StreamStartingTimer {
3030

31-
public static class OpenGLHandler {
31+
/*public static class OpenGLHandler {
3232
static bool GLInitialised = false;
3333
static IntPtr Handle = Process.GetCurrentProcess().MainWindowHandle;
34+
static HDC dc;
35+
static HGLRC gctx;
36+
static Silk.NET.OpenGL.GL gl;
3437
3538
public static void InitGL() {
36-
if (GLInitialised) return;
39+
if (GLInitialised) return;
3740
GLInitialised = true;
3841
SetOpenglPixelFormat((HWND)Handle);
39-
var dc = GetDC((HWND)Handle);
40-
var gctx = wglCreateContext(dc);
42+
dc = GetDC((HWND)Handle);
43+
gctx = wglCreateContext(dc);
4144
wglMakeCurrent(dc, gctx);
4245
ReleaseDC((HWND)Handle, dc);
43-
var gl = new Silk.NET.OpenGL.GL(new WindowsGlNativeContext());
46+
gl = new Silk.NET.OpenGL.GL(new WindowsGlNativeContext());
47+
}
48+
49+
public static void CloseGL() {
50+
if (!GLInitialised) return;
51+
gl.Dispose();
4452
}
53+
4554
static unsafe void SetOpenglPixelFormat(HWND window) {
4655
// Contains desired pixel format characteristics
4756
PIXELFORMATDESCRIPTOR pfd = new();
@@ -114,6 +123,21 @@ public unsafe bool TryGetProcAddress(string proc, out nint addr, int? slot = nul
114123
return false;
115124
}
116125
}
126+
}*/
127+
128+
public static class OpenGLHandler {
129+
static bool GLInitialised = false;
130+
static OpenTK.GLControl.GLControl GL;
131+
public static void InitGL() {
132+
if (GLInitialised) { return; }
133+
GL = new OpenTK.GLControl.GLControl();
134+
GL.MakeCurrent();
135+
GLInitialised = true;
136+
}
137+
public static void CloseGL() {
138+
if (!GLInitialised) { return; }
139+
GL.Dispose();
140+
}
117141
}
118142

119143
public class ClockSpout : IDisposable {
@@ -142,11 +166,12 @@ public void GetImageFromTime(int SecondsToGo, nint pClockTexture) {
142166
ColonFix = 0;
143167

144168
for (int Digit = 0; Digit < 5; Digit++) {
145-
if (Digit == 2) {
169+
if (!Shared.CurSettings.ShowLeadingZero && (Digit == 0) && (CurTime[Digit]=='0')) {
170+
CurDigit = 11;
171+
} else if (Digit == 2) {
146172
ColonFix = ColonWidth - NumberWidth;
147173
CurDigit = 10;
148-
} else { }
149-
if (CurTime[Digit] == ' ') {
174+
} else if (CurTime[Digit] == ' ') {
150175
CurDigit = 11;
151176
} else {
152177
CurDigit = CurTime[Digit] - 48;
@@ -164,7 +189,6 @@ public void GetImageFromTime(int SecondsToGo, nint pClockTexture) {
164189

165190
}
166191
}
167-
//return ClockTexture;
168192
}
169193

170194
public ClockSpout(string FontDir) {
@@ -188,17 +212,10 @@ public ClockSpout(string FontDir) {
188212
ClockArraySize = (ClockWidth * NumberHeight) * 4;
189213

190214
pClockTexture = Marshal.AllocHGlobal(ClockArraySize);
191-
192-
OpenGLHandler.InitGL();
193-
spoutSender = new SpoutSender();
194-
spoutSender.CreateSender(Shared.CurSettings.SpoutName, (uint)ClockWidth, (uint)NumberHeight, 0);
195-
}
196-
197-
public unsafe async void UpdateTexture() {
198-
199215
Int32[] TempLine = new Int32[ColonWidth];
200216
UInt32 TempPixel;
201217

218+
// Add the : to the clock texture now. It never needs copying again
202219
for (int y = 0; y < NumberHeight; y++) {
203220
for (int x = 0; x < ColonWidth; x++) {
204221
TempPixel = (UInt32)ClockFont[10].GetPixel(x, y).ToArgb();
@@ -208,6 +225,13 @@ public unsafe async void UpdateTexture() {
208225
Marshal.Copy(TempLine, 0, pClockTexture + (y * ClockWidth * 4) + (((2 * NumberWidth)) * 4), ColonWidth);
209226
}
210227

228+
OpenGLHandler.InitGL();
229+
spoutSender = new SpoutSender();
230+
spoutSender.CreateSender(Shared.CurSettings.SpoutName, (uint)ClockWidth, (uint)NumberHeight, 0);
231+
}
232+
233+
public unsafe void UpdateTexture() {
234+
211235
int i = 0;
212236
GetImageFromTime(Shared.frmClock.SecondsToGo, pClockTexture);
213237
Console.WriteLine($"Sending (i = {i})");
@@ -219,7 +243,8 @@ public unsafe async void UpdateTexture() {
219243
}
220244

221245
public void Dispose() {
222-
if (spoutSender != null) {
246+
if (spoutSender != null) {
247+
spoutSender.ReleaseSender();
223248
spoutSender.Dispose();
224249
Marshal.FreeHGlobal(pClockTexture);
225250
}

Program.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ namespace StreamStartingTimer
2222
public static class Shared {
2323
public static CSettings CurSettings = new CSettings();
2424
public static List<TimerEvent> TimerEvents = new();
25-
public const string Version = "v0.3";
25+
public const string Version = "v0.5";
2626
public const string TimeFormat = @"mm\:ss";
27+
public const string MutexName = "uk.lum.streamstartingtimer";
2728
public static bool VNyanConnected = false;
2829
public static bool MixItUpConnected = false;
2930

@@ -32,6 +33,7 @@ public static class Shared {
3233
public static HttpClient client = new HttpClient();
3334
public static ConcurrentDictionary<String, String> miuCommands = new ConcurrentDictionary<string, string>();
3435
public static Clock frmClock;
36+
public static Mutex Mutex;
3537

3638
public static bool InitMIU(string URL) {
3739
miuCommands.Clear();
@@ -131,6 +133,16 @@ void OnTimerElapsed(object state) {
131133
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
132134
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
133135
}
136+
public static bool IsSingleInstance() {
137+
try {
138+
Mutex.OpenExisting(Shared.MutexName);
139+
} catch {
140+
Shared.Mutex = new Mutex(true, Shared.MutexName);
141+
return true;
142+
}
143+
// More than one instance.
144+
return false;
145+
}
134146
}
135147

136148
class Options {
@@ -152,6 +164,10 @@ static void Main(string[] args) {
152164
// To customize application configuration such as set high DPI settings or default font,
153165
// see https://aka.ms/applicationconfiguration.
154166
ApplicationConfiguration.Initialize();
167+
while (!Shared.IsSingleInstance()) {
168+
MessageBox.Show("Another copy of this program is already running", "Mutex Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
169+
return;
170+
}
155171
int StartTime = 0;
156172
string ConfigFile = Application.StartupPath + "DefaultConfig.json";
157173
string EventsFile = Application.StartupPath + "DefaultEvents.json";

Settings.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ static class Defaults {
2020
public static readonly Color FGCol = Color.Black;
2121
public static readonly Color BGCol = Color.Lime;
2222
public static readonly Font Font = new Font("Arial", 128);
23+
public const bool ShowLeadingZero = true;
2324
public static readonly TimeSpan TestTime = TimeSpan.FromMinutes(5);
2425
public static readonly Size Dimensions = new Size(600, 300);
2526
public static readonly Point Location = new Point((Screen.PrimaryScreen.Bounds.Size.Width - Dimensions.Width) / 2 + Screen.PrimaryScreen.Bounds.X ,
@@ -53,6 +54,10 @@ public class Settings {
5354
[DisplayName("Text alignment")]
5455
public virtual ContentAlignment Alignment { get; set; }
5556

57+
[CategoryAttribute("Clock Appearance"), DescriptionAttribute("Display 04:20 or 4:20")]
58+
[DisplayName("Show Leading Zero")]
59+
public virtual bool ShowLeadingZero { get; set; }
60+
5661
[Browsable(false)]
5762
public virtual Point Location { get; set; }
5863

@@ -89,6 +94,7 @@ private void Init() {
8994
BGCol = Defaults.BGCol;
9095
FGCol = Defaults.FGCol;
9196
Alignment = Defaults.Alignment;
97+
ShowLeadingZero = Defaults.ShowLeadingZero;
9298
VNyanURL = Defaults.VNyanURL;
9399
MixItUpURL = Defaults.MixItUpURL;
94100
MixItUpPlatform = Defaults.MixItUpPlatform;
@@ -118,6 +124,7 @@ public void LoadConfig(string ConfigFile) {
118124
try { FGCol = ColorTranslator.FromHtml((string)Config.ForegroundColor); } catch { }
119125
try { Alignment = (ContentAlignment)Enum.Parse(typeof(ContentAlignment), (string)Config.Alignment); } catch { }
120126
try { Font = new Font((string)Config.FontName, (int)Config.FontSize, (FontStyle)Config.FontStyle); } catch { }
127+
try { ShowLeadingZero = Config.ShowLeadingZero; } catch { }
121128
try { VNyanURL = Config.VNyanURL; } catch { }
122129
try { MixItUpURL = Config.MixItUpURL; } catch { }
123130
try { MixItUpPlatform = (MIUPlatforms)Enum.Parse(typeof(MIUPlatforms), (string)Config.MixItUpPlatform);} catch { }
@@ -140,6 +147,7 @@ public void SaveConfig(string ConfigFile, Point Location, Size Dimensions) {
140147
new JProperty("Y", Location.Y),
141148
new JProperty("Width", Dimensions.Width),
142149
new JProperty("Height", Dimensions.Height),
150+
new JProperty("ShowLeadingZero", ShowLeadingZero),
143151
new JProperty("VNyanURL", VNyanURL),
144152
new JProperty("MixItUpURL", MixItUpURL),
145153
new JProperty("MixItUpPlatform", MixItUpPlatform.ToString()),
@@ -218,6 +226,14 @@ public override Color BGCol {
218226
RaisePropertyChanged("BGCol");
219227
}
220228
}
229+
public override bool ShowLeadingZero {
230+
get { return _Settings.ShowLeadingZero; }
231+
set {
232+
if (_Settings.ShowLeadingZero == value) return;
233+
_Settings.ShowLeadingZero = value;
234+
RaisePropertyChanged("BGCol");
235+
}
236+
}
221237
public override ContentAlignment Alignment {
222238
get { return _Settings.Alignment; }
223239
set {

StreamStartingTimer.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313
<ItemGroup>
1414
<PackageReference Include="CommandLineParser" Version="2.9.1" />
1515
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
16-
<PackageReference Include="Silk.NET.OpenGL" Version="2.22.0" />
16+
<PackageReference Include="OpenTK.GLControl" Version="4.0.2" />
1717
<PackageReference Include="Spout.NETCore" Version="2.7.16" />
18-
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.26100.2" />
1918
<PackageReference Include="WatsonWebsocket" Version="4.1.5" />
2019
</ItemGroup>
2120

0 commit comments

Comments
 (0)