Skip to content
This repository was archived by the owner on Sep 28, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/BuildClientAPI/BuildClientAPI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />

<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />

<PackageReference Include="X.PagedList" Version="10.5.7" />
</ItemGroup>
<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions src/StreamMaster.API/StreamMaster.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<PackageReference Include="NJsonSchema" Version="11.1.0" />
<PackageReference Include="NSwag.AspNetCore" Version="14.2.0" />
<PackageReference Include="Reinforced.Typings" Version="1.6.5" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.text.regularexpressions" Version="4.3.1" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.2" />
<PackageReference Include="Npgsql" Version="9.0.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
<PackageReference Include="Svg" Version="3.4.7" />
<PackageReference Include="X.PagedList" Version="10.5.7" />
</ItemGroup>
Expand Down
38 changes: 38 additions & 0 deletions src/StreamMaster.Domain/Common/FileUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public static bool IsFilePathValidAndExists(string filePath)
{
return IsValidFilePath(filePath) && File.Exists(filePath);
}

/// <summary>
/// Searches for the specified executable name in predefined directories.
/// </summary>
Expand Down Expand Up @@ -116,6 +117,43 @@ public static bool IsFilePathValidAndExists(string filePath)
}
}

// If nothing found, attempt to use .NET Process to locate the executable.
try
{
using Process process = new();

// Set up process to just get the path without actually running the program
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
process.StartInfo.FileName = "where";
process.StartInfo.Arguments = executableName;
}
else
{
process.StartInfo.FileName = "which";
process.StartInfo.Arguments = executableName;
}

process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;

if (process.Start())
{
string? output = process.StandardOutput.ReadLine();
process.WaitForExit();

if (!string.IsNullOrEmpty(output) && File.Exists(output))
{
return output;
}
}
}
catch
{
// Silently fail if the process approach doesn't work
}

return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
<OutputType>Exe</OutputType>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StreamMaster.Infrastructure.EF.PGSQL\StreamMaster.Infrastructure.EF.PGSQL.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.2" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="9.0.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.0.2" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="9.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.2">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />

<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />

<PackageReference Include="X.PagedList" Version="10.5.7" />
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
<PackageReference Include="Svg" Version="3.4.7" />

<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.4.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</ItemGroup>
<ItemGroup>

<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.7" />
<PackageReference Include="System.Text.Json" Version="9.0.2" />
<PackageReference Include="X.PagedList" Version="10.5.7" />
</ItemGroup>
Expand Down
33 changes: 30 additions & 3 deletions src/StreamMaster.Streams/Broadcasters/SourceBroadcaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ public class SourceBroadcaster(ILogger<ISourceBroadcaster> logger, StreamConnect

/// <inheritdoc/>
public StreamHandlerMetrics Metrics => StreamMetricsRecorder.Metrics;

public bool IsMultiView { get; set; }
public CancellationToken CancellationToken { get; } = cancellationToken;

/// <inheritdoc/>
public ConcurrentDictionary<string, IStreamDataToClients> ChannelBroadcasters { get; } = new();

Expand Down Expand Up @@ -72,6 +74,7 @@ public bool RemoveChannelBroadcaster(string Id)
{
return ChannelBroadcasters.TryRemove(Id, out _);
}

public async Task<long> SetSourceMultiViewStreamAsync(IChannelBroadcaster channelBroadcaster, CancellationToken cancellationToken)
{
logger.LogInformation("Setting source stream {Name} to {StreamName}", Name, SMStreamInfo.Name);
Expand Down Expand Up @@ -106,20 +109,21 @@ public async Task<long> SetSourceStreamAsync(SMStreamInfo SMStreamInfo, Cancella

this.SMStreamInfo = SMStreamInfo;

// Start a new streaming task
_cancellationTokenSource = new CancellationTokenSource();

Stopwatch stopwatch = Stopwatch.StartNew();
try
{
(Stream? stream, int processId, ProxyStreamError? error) =
await streamFactory.GetStream(SMStreamInfo, cancellationToken).ConfigureAwait(false);
await streamFactory.GetStream(SMStreamInfo, _cancellationTokenSource.Token).ConfigureAwait(false);
stopwatch.Stop();
if (stream == null || error != null)
{
logger.LogError("Could not create source stream for channel broadcaster: {Id} {Name} {Error}", SMStreamInfo.Id, SMStreamInfo.Name, error?.Message);
return 0;
}

// Start a new streaming task
_cancellationTokenSource = new CancellationTokenSource();
_streamingTask = Task.Run(() => RunPipelineAsync(stream, SMStreamInfo.Name, cancellationToken: _cancellationTokenSource.Token), _cancellationTokenSource.Token);
return stopwatch.ElapsedMilliseconds;
}
Expand Down Expand Up @@ -193,6 +197,11 @@ private async Task RunPipelineAsync(Stream sourceStream, string name, int buffer
timeoutCts?.Dispose();
}

if (cancellationToken.IsCancellationRequested)
{
break;
}

if (bytesRead == 0)
{
if (!hasReadData)
Expand Down Expand Up @@ -263,6 +272,7 @@ private async Task RunPipelineAsync(Stream sourceStream, string name, int buffer
public async Task StopAsync()
{
await _stopLock.WaitAsync().ConfigureAwait(false);
Task? taskToAwait = null;
try
{
if (Interlocked.CompareExchange(ref _isStopped, 1, 0) == 0)
Expand All @@ -271,12 +281,29 @@ public async Task StopAsync()
{
_cancellationTokenSource?.Cancel();
}
taskToAwait = _streamingTask;
}
}
finally
{
_stopLock.Release();
}

if (taskToAwait != null)
{
try
{
await taskToAwait.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
logger.LogDebug("Task was already cancelled");
}
catch (Exception ex)
{
logger.LogError(ex, "Error during SourceBroadcaster streaming task completion wait.");
}
}
}

/// <inheritdoc/>
Expand Down
Loading