Skip to content
Merged
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
4 changes: 2 additions & 2 deletions Samples/Media SDK/MediaPlayerSample/MediaPlayerSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ void DecreasePlaySpeed()

void OpenFile()
{
OpenFileDialog openFileDialog = new() { Filter = "Video files (*.mp4;*..g64;*..g64x)|*.mp4;*.g64;*..g64x|All files (*.*)|*.*" };
OpenFileDialog openFileDialog = new() { Filter = "Video files (*.mp4;*.g64;*.g64x)|*.mp4;*.g64;*.g64x|All files (*.*)|*.*" };
if (openFileDialog.ShowDialog().GetValueOrDefault())
{
player.OpenFile(openFileDialog.FileName);
Expand Down Expand Up @@ -365,4 +365,4 @@ void DisplayControls()
Console.WriteLine(" I: Toggle statistics overlay");
Console.WriteLine();
}
}
}
14 changes: 9 additions & 5 deletions Samples/Media SDK/OverlaySample/OverlayExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@

namespace Genetec.Dap.CodeSamples;

using System.Threading;
using System.Threading.Tasks;
using Sdk.Media.Overlay;

public static class OverlayExtensions
{
public static async Task WaitUntilReadyForUpdate(this Overlay overlay)
public static async Task WaitUntilReadyForUpdate(this Overlay overlay, CancellationToken cancellationToken = default)
{
var completion = new TaskCompletionSource<object>();
var completion = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);

overlay.StateChange += OnStateChange;
try
Expand All @@ -20,7 +21,10 @@ public static async Task WaitUntilReadyForUpdate(this Overlay overlay)
return;
}

await completion.Task;
using (cancellationToken.Register(() => completion.TrySetCanceled(cancellationToken)))
{
await completion.Task;
}
}
finally
{
Expand All @@ -31,8 +35,8 @@ void OnStateChange(object sender, OverlayStatusEventArgs e)
{
if (e.CanPropagateUpdate)
{
completion.SetResult(null);
completion.TrySetResult(null);
}
}
}
}
}
12 changes: 6 additions & 6 deletions Samples/Media SDK/OverlaySample/OverlaySample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private async Task DrawBouncingBall(Guid cameraId, CancellationToken token)
{
const string layerId = "69A64ACE-6DDC-4142-AD04-06690D8591B3"; // Replace with a unique layer ID for your overlay. Layer ID must be unique and deterministic

Overlay overlay = await InitializeOverlay(cameraId, "Bouncing ball");
Overlay overlay = await InitializeOverlay(cameraId, "Bouncing ball", token);
Layer layer = overlay.CreateLayer(new Guid(layerId), "Bouncing ball");

var bouncingBall = new BouncingBall(50, 50, 50, 50, 25) { CanvasHeight = s_canvasHeight, CanvasWidth = s_canvasWidth };
Expand All @@ -73,7 +73,7 @@ private async Task DrawTimecode(Guid cameraId, CancellationToken token)
{
const string layerId = "92AEA5CA-E0F5-4122-872A-DB9A9F7437F7"; // Replace with a unique layer ID for your overlay. Layer ID must be unique and deterministic

Overlay overlay = await InitializeOverlay(cameraId, "Timecode");
Overlay overlay = await InitializeOverlay(cameraId, "Timecode", token);
Layer layer = overlay.CreateLayer(new Guid(layerId), "Timecode");

var timeDisplay = new TimeDisplay();
Expand All @@ -95,7 +95,7 @@ private async Task DrawRecordingStatus(Camera camera, CancellationToken token)
{
const string layerId = "A1B2C3D4-E5F6-7890-1234-567890ABCDEF"; // Replace with a unique layer ID for your overlay. Layer ID must be unique and deterministic

Overlay overlay = await InitializeOverlay(camera.Guid, "Recording Status");
Overlay overlay = await InitializeOverlay(camera.Guid, "Recording Status", token);
Layer layer = overlay.CreateLayer(new Guid(layerId), "Recording Status");

var recordingStatus = new RecordingStatus(camera);
Expand All @@ -113,7 +113,7 @@ private async Task DrawRecordingStatus(Camera camera, CancellationToken token)
}
}

private async Task<Overlay> InitializeOverlay(Guid camera, string overlayName)
private async Task<Overlay> InitializeOverlay(Guid camera, string overlayName, CancellationToken token)
{
Overlay overlay = OverlayFactory.Get(camera, overlayName);

Expand All @@ -122,7 +122,7 @@ private async Task<Overlay> InitializeOverlay(Guid camera, string overlayName)
overlay.Initialize(s_canvasHeight, s_canvasWidth);
}

await overlay.WaitUntilReadyForUpdate();
await overlay.WaitUntilReadyForUpdate(token);
return overlay;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ protected override async Task RunAsync(Engine engine, CancellationToken token)

private async Task<byte[]> GetCameraSnapshot(Engine engine, Guid camera)
{
var completion = new TaskCompletionSource<byte[]>();
var completion = new TaskCompletionSource<byte[]>(TaskCreationOptions.RunContinuationsAsynchronously);

using (var videoSourceFilter = new VideoSourceFilter())
{
Expand All @@ -52,6 +52,7 @@ private async Task<byte[]> GetCameraSnapshot(Engine engine, Guid camera)
finally
{
videoSourceFilter.FrameDecoded -= OnFrameDecoded;
videoSourceFilter.PlayerStateChanged -= OnPlayerStateChanged;
videoSourceFilter.Stop();
}
}
Expand All @@ -75,7 +76,8 @@ void OnFrameDecoded(object sender, FrameDecodedEventArgs args)
}
catch (Exception ex)
{
completion.SetException(ex);
completion.TrySetException(ex);
return;
}

memoryStream.Position = 0;
Expand All @@ -100,4 +102,4 @@ void OnPlayerStateChanged(object sender, PlayerStateChangedEventArgs e)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ public class AccessVerifierSample : SampleBase
protected override async Task RunAsync(Engine engine, CancellationToken token)
{
// Load the specified entity types into the entity cache
await LoadEntities(engine, token, EntityType.Credential, EntityType.AccessPoint, EntityType.Schedule, EntityType.AccessRule);
await LoadEntities(engine, token, EntityType.Credential, EntityType.AccessPoint, EntityType.Schedule, EntityType.AccessRule, EntityType.Door);

List<Guid> doorGuids = engine.GetEntities(EntityType.Door).Select(door => door.Guid).ToList();
if (doorGuids.Count == 0)
{
Console.WriteLine("No doors were found. The access matrix cannot be generated.");
return;
}

DateTime currentTime = DateTime.UtcNow;

Expand Down Expand Up @@ -63,4 +68,4 @@ static void GenerateAccessMatrixCsv(IEngine engine, ICollection<(AccessPoint Acc
textWriter.WriteLine();
}
}
}
}
25 changes: 21 additions & 4 deletions Samples/Platform SDK/VideoUnitSample/VideoUnitSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ private void PrintProductCapability(ProductCapability capability)

private async Task<Guid> AddVideoUnit(IVideoUnitManager videoUnitManager, AddVideoUnitInfo videoUnitInfo, Guid archiver, IProgress<EnrollmentResult> progress = default)
{
var completion = new TaskCompletionSource<Guid>();
var completion = new TaskCompletionSource<Guid>(TaskCreationOptions.RunContinuationsAsynchronously);

videoUnitManager.EnrollmentStatusChanged += OnEnrollmentStatusChanged;
try
Expand All @@ -136,19 +136,36 @@ private async Task<Guid> AddVideoUnit(IVideoUnitManager videoUnitManager, AddVid

void OnEnrollmentStatusChanged(object sender, UnitEnrolledEventArgs e)
{
if (!IsEnrollmentForRequestedUnit(e))
{
return;
}

progress?.Report(e.EnrollmentResult);

if (e.EnrollmentResult != EnrollmentResult.Connecting)
{
if (e.Unit != Guid.Empty)
{
completion.SetResult(e.Unit);
completion.TrySetResult(e.Unit);
}
else
{
completion.SetException(new Exception($"Unable to enroll the video unit: {e.EnrollmentResult}"));
completion.TrySetException(new Exception($"Unable to enroll the video unit: {e.EnrollmentResult}"));
}
}
}

bool IsEnrollmentForRequestedUnit(UnitEnrolledEventArgs e)
{
string expectedAddress = videoUnitInfo.Hostname ?? videoUnitInfo.IPEndPoint?.Address.ToString();
if (!string.IsNullOrWhiteSpace(expectedAddress) && !string.Equals(e.Address, expectedAddress, StringComparison.OrdinalIgnoreCase))
{
return false;
}

int expectedPort = videoUnitInfo.Port;
return expectedPort < 0 || e.Port == expectedPort;
}
}
}
}
33 changes: 20 additions & 13 deletions Samples/Plugin SDK/CustomReportSample/AsyncEnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

namespace Genetec.Dap.CodeSamples;

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

public static class AsyncEnumerableExtensions
{
Expand All @@ -16,25 +18,30 @@ public static class AsyncEnumerableExtensions
/// <param name="source">The source <see cref="IAsyncEnumerable{T}"/> to buffer.</param>
/// <param name="bufferSize">The size of each buffer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>An <see cref="IAsyncEnumerable{T}"/> of <see cref="IAsyncEnumerable{T}"/> representing the buffered elements.</returns>
public static async IAsyncEnumerable<IAsyncEnumerable<T>> Buffer<T>(this IAsyncEnumerable<T> source, int bufferSize, [EnumeratorCancellation] CancellationToken cancellationToken = default)
/// <returns>An <see cref="IAsyncEnumerable{T}"/> of <see cref="IReadOnlyList{T}"/> representing the buffered elements.</returns>
public static async IAsyncEnumerable<IReadOnlyList<T>> Buffer<T>(this IAsyncEnumerable<T> source, int bufferSize, [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await using IAsyncEnumerator<T> enumerator = source.GetAsyncEnumerator(cancellationToken);
while (await enumerator.MoveNextAsync())
if (bufferSize <= 0)
{
yield return BufferInternal();
throw new ArgumentOutOfRangeException(nameof(bufferSize));
}

async IAsyncEnumerable<T> BufferInternal()
var batch = new List<T>(bufferSize);

await foreach (T item in source.WithCancellation(cancellationToken))
{
for (var i = 0; i < bufferSize; i++)
{
cancellationToken.ThrowIfCancellationRequested();
batch.Add(item);

yield return enumerator.Current;
if (!await enumerator.MoveNextAsync())
yield break;
if (batch.Count == bufferSize)
{
yield return batch;
batch = new List<T>(bufferSize);
}
}

if (batch.Count > 0)
{
yield return batch;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public ActivityTrailsReportHandler(IEngine engine, Role role) : base(engine, rol
{
}

protected override async Task ProcessBatch(DataTable table, IAsyncEnumerable<ActivityTrailRow> batch)
protected override void ProcessBatch(DataTable table, IReadOnlyList<ActivityTrailRow> batch)
{
await foreach (ActivityTrailRow row in batch)
foreach (ActivityTrailRow row in batch)
{
table.AddIRow(row);
}
Expand Down Expand Up @@ -68,4 +68,4 @@ protected override async IAsyncEnumerable<ActivityTrailRow> GetRecordsAsync(Acti
.SetInitiatorApplication(ApplicationType.SecurityDesk, "Security Desk", Environment.MachineName);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public AuditTrailsReportHandler(IEngine engine, Role role) : base(engine, role)
{
}

protected override async Task ProcessBatch(DataTable table, IAsyncEnumerable<AuditTrailRow> batch)
protected override void ProcessBatch(DataTable table, IReadOnlyList<AuditTrailRow> batch)
{
await foreach (AuditTrailRow row in batch)
foreach (AuditTrailRow row in batch)
{
table.AddIRow(row);
}
Expand Down Expand Up @@ -70,4 +70,4 @@ protected override async IAsyncEnumerable<AuditTrailRow> GetRecordsAsync(AuditTr
.SetInitiatorApplication(ApplicationType.SecurityDesk, "Security Desk", Environment.MachineName);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ public async Task<ReportError> HandleAsync(ReportQueryReceivedEventArgs args, Ca
int totalSent = 0;
int maxResults = args.Query.MaximumResultCount;

await foreach (IAsyncEnumerable<TRecord> batch in records.Buffer(GetBatchSize()).WithCancellation(token))
await foreach (IReadOnlyList<TRecord> batch in records.Buffer(GetBatchSize()).WithCancellation(token))
{
token.ThrowIfCancellationRequested();

DataTable table = CreateDataTable(query);
await ProcessBatch(table, batch);
ProcessBatch(table, batch);
SendQueryResult(args, table);

totalSent += table.Rows.Count;
Expand All @@ -72,9 +72,9 @@ protected virtual DataTable CreateDataTable(TQuery query)
return query.GetNewDataTables().First();
}

protected virtual async Task ProcessBatch(DataTable table, IAsyncEnumerable<TRecord> batch)
protected virtual void ProcessBatch(DataTable table, IReadOnlyList<TRecord> batch)
{
await foreach (TRecord record in batch)
foreach (TRecord record in batch)
{
if (record is IRow row)
{
Expand Down Expand Up @@ -121,4 +121,4 @@ protected virtual void Dispose(bool disposing)
Logger.Dispose();
}
}
}
}
Loading