Skip to content

Commit a2c37c9

Browse files
authored
Merge pull request #1 from BarRaider/dev
v1.4 features
2 parents b961281 + 8335f13 commit a2c37c9

24 files changed

+890
-1929
lines changed

README.md

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,21 @@ A set of tools for manipulating text files through the Elgato Stream Deck. Usefu
44

55
**Author's website and contact information:** [https://barraider.com](https://barraider.com)
66

7-
## New in v1.3
8-
- `Last Word Display` action now supports splitting long words into multiple lines on the key.
9-
- `Text File Updater` action now supports appending data (instead of only overwriting like before).
10-
- Updated input textbox in `Text File Updater` to support multiple lines of text
11-
12-
13-
## New in v1.2
14-
- `Last Word Display` action can now alert if the text equals a preset value. This works great with the `CountDown Timer` if you're saving the timer to a file and want to show it/alert on it from a different profile.
15-
- `Last Word Display` now supports modifying the Title settings from the Title properties menu
16-
- Added Multi-Action support to all actions
17-
18-
19-
## New in v1.1.5
20-
- Random Line action now supports `Sending Enter` key at the end of the line. Useful if using for things like Chat, and you want the random line to be sent automatically.
7+
## New in 1.4
8+
- New `Next Line` action cycles through a text file and output the next line on every keypress
9+
- Both `Next Line` and `Random Line` actions now support outputting to clipboard
10+
- New `Regex Display` action parses a text file for a regex and displays the match on key.
11+
- Both `Regex Display` and `Last Word Display` support Auto Stopping the Flashing Alert when the text no longer matches.
2112

2213
## Current Features
2314
* Text File Updater - Overwrites the contents of a text file with a predefined string. Use to change overlay text during Stream
2415
* Last Word Display - Shows the last word of a text file on your Stream Deck
16+
- Can alert if the text equals a preset value. This works great with the `CountDown Timer` if you're saving the timer to a file and want to show it/alert on it from a different profile.
2517
* Random Line Writer - Sends a random line from a text file to your keyboard, useful for giveaways or just sending a random 'hello' message in chat.
26-
18+
* Next Line - cycles through a text file and output the next line on every keypress
19+
- Regex Display - parses a text file for a regex and displays the match on key.
20+
- Both `Regex Display` and `Last Word Display` support Auto Stopping the Flashing Alert when the text no longer matches.
21+
- Both `Next Line` and `Random Line` actions now support outputting to clipboard
2722

2823
### Download
2924

@@ -38,3 +33,20 @@ Please contact the developer. Contact information is available at https://barrai
3833
## Dependencies
3934
* Uses StreamDeck-Tools by BarRaider: [![NuGet](https://img.shields.io/nuget/v/streamdeck-tools.svg?style=flat)](https://www.nuget.org/packages/streamdeck-tools)
4035
* Uses [Easy-PI](https://github.com/BarRaider/streamdeck-easypi) by BarRaider - Provides seamless integration with the Stream Deck PI (Property Inspector)
36+
37+
## Change Log
38+
39+
## New in v1.3
40+
- `Last Word Display` action now supports splitting long words into multiple lines on the key.
41+
- `Text File Updater` action now supports appending data (instead of only overwriting like before).
42+
- Updated input textbox in `Text File Updater` to support multiple lines of text
43+
44+
45+
## New in v1.2
46+
- `Last Word Display` action can now alert if the text equals a preset value. This works great with the `CountDown Timer` if you're saving the timer to a file and want to show it/alert on it from a different profile.
47+
- `Last Word Display` now supports modifying the Title settings from the Title properties menu
48+
- Added Multi-Action support to all actions
49+
50+
51+
## New in v1.1.5
52+
- Random Line action now supports `Sending Enter` key at the end of the line. Useful if using for things like Chat, and you want the random line to be sent automatically.

streamdeck-textfiletools/LastWordDisplayAction.cs renamed to streamdeck-textfiletools/Actions/LastWordDisplayAction.cs

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
using System.Threading.Tasks;
1212
using WindowsInput;
1313

14-
namespace BarRaider.TextFileUpdater
14+
namespace BarRaider.TextFileUpdater.Actions
1515
{
1616
[PluginActionId("com.barraider.textfiletools.lastworddisplay")]
1717
public class LastWordDisplayAction : PluginBase
@@ -26,7 +26,9 @@ public static PluginSettings CreateDefaultSettings()
2626
AlertText = String.Empty,
2727
AlertColor = DEFAULT_ALERT_COLOR,
2828
BackgroundFile = String.Empty,
29-
SplitLongWord = false
29+
SplitLongWord = false,
30+
TitlePrefix = String.Empty,
31+
AutoStopAlert = false
3032
};
3133
return instance;
3234
}
@@ -47,15 +49,20 @@ public static PluginSettings CreateDefaultSettings()
4749

4850
[JsonProperty(PropertyName = "splitLongWord")]
4951
public bool SplitLongWord { get; set; }
52+
53+
[JsonProperty(PropertyName = "titlePrefix")]
54+
public string TitlePrefix { get; set; }
55+
56+
[JsonProperty(PropertyName = "autoStopAlert")]
57+
public bool AutoStopAlert { get; set; }
5058

59+
5160
}
5261

5362
#region Private Members
5463
private const string DEFAULT_ALERT_COLOR = "#FF0000";
5564
private const int TOTAL_ALERT_STAGES = 4;
5665
private const double POINTS_TO_PIXEL_CONVERT = 1.3;
57-
private const int STRING_SPLIT_SIZE = 7;
58-
5966

6067
private readonly PluginSettings settings;
6168
private readonly InputSimulator iis = new InputSimulator();
@@ -91,46 +98,64 @@ private void Connection_OnTitleParametersDidChange(object sender, SdTools.Wrappe
9198
public override void Dispose()
9299
{
93100
Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called");
101+
tmrAlert.Stop();
94102
Connection.OnTitleParametersDidChange -= Connection_OnTitleParametersDidChange;
95103
}
96104

97105
public async override void KeyPressed(KeyPayload payload)
98106
{
99-
Logger.Instance.LogMessage(TracingLevel.INFO, "Key Pressed");
107+
Logger.Instance.LogMessage(TracingLevel.INFO, $"Key Pressed. Alert: {isAlerting}");
100108

101109
if (isAlerting)
102110
{
103-
isAlerting = false;
104-
tmrAlert.Stop();
105-
await Connection.SetImageAsync((string)null);
111+
await StopAlert();
106112
return;
107113
}
108114

109-
iis.Keyboard.TextEntry(ReadLastWordFromFile());
115+
var result = ReadLastWordFromFile();
116+
if (!String.IsNullOrEmpty(result))
117+
{
118+
iis.Keyboard.TextEntry(result);
119+
}
110120
}
111121

112122
public override void KeyReleased(KeyPayload payload) { }
113123

114124
public async override void OnTick()
115125
{
116126
string lastWord = ReadLastWordFromFile();
117-
if (settings.SplitLongWord)
127+
if (String.IsNullOrEmpty(lastWord))
118128
{
119-
lastWord = SplitLongWord(lastWord);
129+
return;
120130
}
121131

122132
if (!String.IsNullOrEmpty(settings.AlertText) && !isAlerting && settings.AlertText == lastWord)
123133
{
134+
Logger.Instance.LogMessage(TracingLevel.INFO, $"Alerting, last word is {lastWord}");
135+
await Connection.SetTitleAsync(null);
124136
// Start the alert
125137
isAlerting = true;
126138
tmrAlert.Start();
127139
}
128140

129141
if (isAlerting)
130142
{
143+
if (settings.AutoStopAlert && settings.AlertText != lastWord)
144+
{
145+
Logger.Instance.LogMessage(TracingLevel.INFO, $"Stopping alert, word changed to: {lastWord}");
146+
await StopAlert();
147+
}
131148
return;
132149
}
133150

151+
if (settings.SplitLongWord)
152+
{
153+
lastWord = Tools.SplitStringToFit(lastWord, titleParameters);
154+
}
155+
156+
// Add TitlePrefix
157+
lastWord = $"{settings.TitlePrefix?.Replace(@"\n", "\n") ?? ""}{lastWord}";
158+
134159
if (String.IsNullOrEmpty(settings.BackgroundFile))
135160
{
136161
await Connection.SetImageAsync((string)null);
@@ -164,8 +189,17 @@ private String ReadLastWordFromFile()
164189
return "No File";
165190
}
166191

167-
string[] words = File.ReadAllText(settings.FileName).Replace("*", "").Trim().Split(' ');
168-
return words.LastOrDefault();
192+
try
193+
{
194+
string[] words = File.ReadAllText(settings.FileName).Replace("*", "").Trim().Split(' ');
195+
return words.LastOrDefault();
196+
}
197+
catch (Exception ex)
198+
{
199+
200+
Logger.Instance.LogMessage(TracingLevel.ERROR, $"{this.GetType()} ReadLastWordFromFile Exception: {ex}");
201+
return null;
202+
}
169203
}
170204

171205
private Task SaveSettings()
@@ -207,7 +241,7 @@ private void TmrAlert_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
207241
// Background
208242
var bgBrush = new SolidBrush(GenerateStageColor(settings.AlertColor, alertStage, TOTAL_ALERT_STAGES));
209243
graphics.FillRectangle(bgBrush, 0, 0, width, height);
210-
Tools.AddTextPathToGraphics(graphics, titleParameters, img.Height, img.Width, settings.AlertText);
244+
graphics.AddTextPath(titleParameters, img.Height, img.Width, settings.AlertText);
211245
Connection.SetImageAsync(img);
212246

213247
alertStage = (alertStage + 1) % TOTAL_ALERT_STAGES;
@@ -232,24 +266,18 @@ private async Task DrawImage(string text)
232266
}
233267
}
234268

235-
Tools.AddTextPathToGraphics(graphics, titleParameters, img.Height, img.Width, text);
269+
graphics.AddTextPath(titleParameters, img.Height, img.Width, text);
236270
await Connection.SetImageAsync(img);
237271
graphics.Dispose();
238272
}
239273
}
240274

241-
private string SplitLongWord(string word)
275+
private async Task StopAlert()
242276
{
243-
// Split up to 4 lines
244-
for (int idx = 0; idx < 3; idx++)
245-
{
246-
int cutSize = STRING_SPLIT_SIZE * (idx + 1);
247-
if (word.Length > cutSize)
248-
{
249-
word = $"{word.Substring(0, cutSize)}\n{word.Substring(cutSize)}";
250-
}
251-
}
252-
return word;
277+
Logger.Instance.LogMessage(TracingLevel.INFO, "Stopping Alert");
278+
tmrAlert.Stop();
279+
isAlerting = false;
280+
await Connection.SetImageAsync((string)null);
253281
}
254282

255283
#endregion
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
using BarRaider.SdTools;
2+
using Newtonsoft.Json;
3+
using Newtonsoft.Json.Linq;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading;
10+
using System.Threading.Tasks;
11+
using System.Windows.Forms;
12+
using WindowsInput;
13+
14+
namespace BarRaider.TextFileUpdater.Actions
15+
{
16+
[PluginActionId("com.barraider.textfiletools.nextline")]
17+
public class NextLineAction : PluginBase
18+
{
19+
private class PluginSettings
20+
{
21+
public static PluginSettings CreateDefaultSettings()
22+
{
23+
PluginSettings instance = new PluginSettings
24+
{
25+
FileName = String.Empty,
26+
SendEnterAtEnd = false,
27+
UseClipboard = false
28+
};
29+
return instance;
30+
}
31+
32+
[FilenameProperty]
33+
[JsonProperty(PropertyName = "fileName")]
34+
public string FileName { get; set; }
35+
36+
[JsonProperty(PropertyName = "sendEnterAtEnd")]
37+
public bool SendEnterAtEnd { get; set; }
38+
39+
[JsonProperty(PropertyName = "useClipboard")]
40+
public bool UseClipboard { get; set; }
41+
}
42+
43+
44+
#region Private Members
45+
46+
private readonly PluginSettings settings;
47+
private readonly InputSimulator iis = new InputSimulator();
48+
int currentLine = 0;
49+
50+
#endregion
51+
public NextLineAction(SDConnection connection, InitialPayload payload) : base(connection, payload)
52+
{
53+
if (payload.Settings == null || payload.Settings.Count == 0)
54+
{
55+
this.settings = PluginSettings.CreateDefaultSettings();
56+
}
57+
else
58+
{
59+
this.settings = payload.Settings.ToObject<PluginSettings>();
60+
}
61+
}
62+
63+
public override void Dispose()
64+
{
65+
Logger.Instance.LogMessage(TracingLevel.INFO, $"Destructor called");
66+
}
67+
68+
public override void KeyPressed(KeyPayload payload)
69+
{
70+
Logger.Instance.LogMessage(TracingLevel.INFO, "Key Pressed");
71+
string randomLine = ReadNextLineFromFile();
72+
if (!string.IsNullOrEmpty(randomLine))
73+
{
74+
if (settings.UseClipboard)
75+
{
76+
SetClipboard(randomLine);
77+
}
78+
else
79+
{
80+
iis.Keyboard.TextEntry(randomLine);
81+
if (settings.SendEnterAtEnd)
82+
{
83+
iis.Keyboard.KeyDown(WindowsInput.Native.VirtualKeyCode.RETURN);
84+
}
85+
}
86+
}
87+
}
88+
89+
public override void KeyReleased(KeyPayload payload) { }
90+
91+
public override void OnTick()
92+
{
93+
}
94+
95+
public override void ReceivedSettings(ReceivedSettingsPayload payload)
96+
{
97+
Tools.AutoPopulateSettings(settings, payload.Settings);
98+
SaveSettings();
99+
}
100+
101+
public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload) { }
102+
103+
#region Private Methods
104+
105+
private String ReadNextLineFromFile()
106+
{
107+
if (String.IsNullOrEmpty(settings.FileName))
108+
{
109+
return null;
110+
}
111+
112+
if (!File.Exists(settings.FileName))
113+
{
114+
115+
Logger.Instance.LogMessage(TracingLevel.ERROR, $"{this.GetType()} ReadNextLineFromFile: File not found {settings.FileName}");
116+
return null;
117+
}
118+
119+
string[] lines = File.ReadAllLines(settings.FileName);
120+
if (currentLine >= lines.Length)
121+
{
122+
currentLine = 0;
123+
}
124+
return lines[currentLine++];
125+
}
126+
127+
private Task SaveSettings()
128+
{
129+
return Connection.SetSettingsAsync(JObject.FromObject(settings));
130+
}
131+
132+
private void SetClipboard(string text)
133+
{
134+
Thread staThread = new Thread(
135+
delegate ()
136+
{
137+
try
138+
{
139+
Clipboard.SetText(text);
140+
}
141+
142+
catch (Exception ex)
143+
{
144+
Logger.Instance.LogMessage(TracingLevel.ERROR, $"GetSongInfo ReadFromClipboard exception: {ex}");
145+
}
146+
});
147+
staThread.SetApartmentState(ApartmentState.STA);
148+
staThread.Start();
149+
staThread.Join();
150+
}
151+
152+
#endregion
153+
}
154+
}

0 commit comments

Comments
 (0)