Skip to content

Commit

Permalink
Add cancel button to task queue (#464)
Browse files Browse the repository at this point in the history
* Add cancel button to task queue, add finalizers to some classes, add offline checkbox to chatrender

* Finalize on non-queue tasks too

* Separate emote data into dedicated functions, add null check to 7tv response

* forgot to stage

* Add cancellation token to TwitchHelper.GetThirdPartyEmotes[Data]()
  • Loading branch information
ScrubN authored Dec 13, 2022
1 parent ebdf8bf commit 54989c2
Show file tree
Hide file tree
Showing 24 changed files with 423 additions and 291 deletions.
2 changes: 2 additions & 0 deletions TwitchDownloaderCore/ChatDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@ public async Task DownloadAsync(IProgress<ProgressReport> progress, Cancellation
List<TwitchEmote> firstPartyEmotes = await TwitchHelper.GetEmotes(comments, downloadOptions.TempFolder);
List<ChatBadge> twitchBadges = await TwitchHelper.GetChatBadges(chatRoot.streamer.id, downloadOptions.TempFolder);
List<CheerEmote> twitchBits = await TwitchHelper.GetBits(downloadOptions.TempFolder, chatRoot.streamer.id.ToString());

cancellationToken.ThrowIfCancellationRequested();

foreach (TwitchEmote emote in thirdPartyEmotes)
{
Expand Down
49 changes: 36 additions & 13 deletions TwitchDownloaderCore/ChatRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public sealed class ChatRenderer
private List<TwitchEmote> emoteThirdList = new List<TwitchEmote>();
private List<CheerEmote> cheermotesList = new List<CheerEmote>();
private Dictionary<string, SKBitmap> emojiCache = new Dictionary<string, SKBitmap>();
private readonly ConcurrentDictionary<int, SKPaint> fallbackCache = new ConcurrentDictionary<int, SKPaint>();
private readonly SKFontManager fontManager = SKFontManager.CreateDefault();
private ConcurrentDictionary<int, SKPaint> fallbackCache = new ConcurrentDictionary<int, SKPaint>();
private SKFontManager fontManager = SKFontManager.CreateDefault();
private SKPaint messageFont = new SKPaint();
private SKPaint nameFont = new SKPaint();
private SKPaint outlinePaint = new SKPaint();
Expand All @@ -52,7 +52,7 @@ public async Task RenderVideoAsync(IProgress<ProgressReport> progress, Cancellat

Task<List<ChatBadge>> badgeTask = TwitchHelper.GetChatBadges(chatRoot.streamer.id, renderOptions.TempFolder, chatRoot.embeddedData, renderOptions.Offline);
Task<List<TwitchEmote>> emoteTask = TwitchHelper.GetEmotes(chatRoot.comments, renderOptions.TempFolder, chatRoot.embeddedData, renderOptions.Offline);
Task<List<TwitchEmote>> emoteThirdTask = TwitchHelper.GetThirdPartyEmotes(chatRoot.streamer.id, renderOptions.TempFolder, chatRoot.embeddedData, renderOptions.BttvEmotes, renderOptions.FfzEmotes, renderOptions.StvEmotes, renderOptions.Offline);
Task<List<TwitchEmote>> emoteThirdTask = TwitchHelper.GetThirdPartyEmotes(chatRoot.streamer.id, renderOptions.TempFolder, chatRoot.embeddedData, renderOptions.BttvEmotes, renderOptions.FfzEmotes, renderOptions.StvEmotes, renderOptions.Offline, cancellationToken);
Task<List<CheerEmote>> cheerTask = TwitchHelper.GetBits(renderOptions.TempFolder, chatRoot.streamer.id.ToString(), chatRoot.embeddedData, renderOptions.Offline);
Task<Dictionary<string, SKBitmap>> emojiTask = TwitchHelper.GetTwitterEmojis(renderOptions.TempFolder);

Expand Down Expand Up @@ -101,14 +101,22 @@ public async Task RenderVideoAsync(IProgress<ProgressReport> progress, Cancellat
progress.Report(new ProgressReport(ReportType.StatusInfo, "Rendering Video: 0%"));
(Process ffmpegProcess, string ffmpegSavePath) = GetFfmpegProcess(0, false);

if (renderOptions.GenerateMask)
try
{
(Process maskProcess, string maskSavePath) = GetFfmpegProcess(0, true);
await Task.Run(() => RenderVideoSection(startTick, startTick + totalTicks, ffmpegProcess, maskProcess, progress), cancellationToken);
if (renderOptions.GenerateMask)
{
(Process maskProcess, string maskSavePath) = GetFfmpegProcess(0, true);
await Task.Run(() => RenderVideoSection(startTick, startTick + totalTicks, ffmpegProcess, maskProcess, progress, cancellationToken));
}
else
{
await Task.Run(() => RenderVideoSection(startTick, startTick + totalTicks, ffmpegProcess, maskProcess: null, progress, cancellationToken));
}
}
else
catch (OperationCanceledException)
{
await Task.Run(() => RenderVideoSection(startTick, startTick + totalTicks, ffmpegProcess, progress: progress), cancellationToken);
GC.Collect();
throw;
}
}

Expand Down Expand Up @@ -147,7 +155,7 @@ private static SKTypeface GetInterTypeface(SKFontStyle fontStyle)
}
}

private void RenderVideoSection(int startTick, int endTick, Process ffmpegProcess, Process maskProcess = null, IProgress<ProgressReport> progress = null)
private void RenderVideoSection(int startTick, int endTick, Process ffmpegProcess, Process maskProcess = null, IProgress<ProgressReport> progress = null, CancellationToken cancellationToken = new())
{
UpdateFrame latestUpdate = null;
BinaryWriter ffmpegStream = new BinaryWriter(ffmpegProcess.StandardInput.BaseStream);
Expand All @@ -164,6 +172,8 @@ private void RenderVideoSection(int startTick, int endTick, Process ffmpegProces

for (int currentTick = startTick; currentTick < endTick; currentTick++)
{
cancellationToken.ThrowIfCancellationRequested();

if (currentTick % renderOptions.UpdateFrame == 0)
{
latestUpdate = GenerateUpdateFrame(currentTick, sampleTextBounds.Height, latestUpdate);
Expand Down Expand Up @@ -520,7 +530,7 @@ private void DrawMessage(Comment comment, List<SKBitmap> sectionImages, List<(Po
{
// Old LINQ method. Leaving this for reference
//List<SingleEmoji> emojiMatches = Emoji.All.Where(x => fragmentString.StartsWith(x.ToString()) && fragmentString.Contains(x.Sequence.AsString.Trim('\uFE0F'))).ToList();

List<SingleEmoji> emojiMatches = new List<SingleEmoji>();
foreach (var emoji in Emoji.All)
{
Expand Down Expand Up @@ -560,14 +570,12 @@ private void DrawMessage(Comment comment, List<SKBitmap> sectionImages, List<(Po
}

drawPos.X += emojiImage.Width + renderOptions.EmoteSpacing;

fragmentString = fragmentString.Substring(selectedEmoji.Sequence.AsString.Trim('\uFE0F').Length);
}
else
{
DrawText(fragmentString[0].ToString(), messageFont, false, sectionImages, ref drawPos, defaultPos);
fragmentString = fragmentString.Substring(1);
}
fragmentString = fragmentString[1..];
}
}
else if (new StringInfo(fragmentString).LengthInTextElements < fragmentString.Length || !messageFont.ContainsGlyphs(fragmentString))
Expand Down Expand Up @@ -1073,5 +1081,20 @@ public async Task<ChatRoot> ParseJsonAsync()

return chatRoot;
}

~ChatRenderer()
{
chatRoot = null;
badgeList = null;
emoteList = null;
emoteThirdList = null;
cheermotesList = null;
emojiCache = null;
fallbackCache = null;
fontManager.Dispose();
outlinePaint.Dispose();
nameFont.Dispose();
messageFont.Dispose();
}
}
}
8 changes: 8 additions & 0 deletions TwitchDownloaderCore/ChatUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public async Task UpdateAsync(IProgress<ProgressReport> progress, CancellationTo
};

await Task.WhenAll(chatCropTasks);
cancellationToken.ThrowIfCancellationRequested();

// If the comment count didn't change, it probably failed so don't report the counts
if (inputCommentCount != chatRoot.comments.Count)
Expand All @@ -104,6 +105,8 @@ public async Task UpdateAsync(IProgress<ProgressReport> progress, CancellationTo
};

await Task.WhenAll(embedTasks);
cancellationToken.ThrowIfCancellationRequested();

}

// Finally save the output to file!
Expand Down Expand Up @@ -361,5 +364,10 @@ public async Task<ChatRoot> ParseJsonAsync()

return chatRoot;
}

~ChatUpdater()
{
chatRoot = null;
}
}
}
5 changes: 4 additions & 1 deletion TwitchDownloaderCore/ClipDownloader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Newtonsoft.Json.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using TwitchDownloaderCore.Options;
Expand All @@ -15,7 +16,7 @@ public ClipDownloader(ClipDownloadOptions DownloadOptions)
downloadOptions = DownloadOptions;
}

public async Task DownloadAsync()
public async Task DownloadAsync(CancellationToken cancellationToken = new())
{
JArray taskLinks = await TwitchHelper.GetClipLinks(downloadOptions.Id);

Expand All @@ -31,6 +32,8 @@ public async Task DownloadAsync()
downloadUrl = taskLinks[0]["data"]["clip"]["videoQualities"].First["sourceURL"].ToString();

downloadUrl += "?sig=" + taskLinks[0]["data"]["clip"]["playbackAccessToken"]["signature"] + "&token=" + HttpUtility.UrlEncode(taskLinks[0]["data"]["clip"]["playbackAccessToken"]["value"].ToString());

cancellationToken.ThrowIfCancellationRequested();

using (WebClient client = new WebClient())
await client.DownloadFileTaskAsync(downloadUrl, downloadOptions.Filename);
Expand Down
Loading

0 comments on commit 54989c2

Please sign in to comment.