Telvi.Player.V3/Host/PlayerHost.csC#
// HARD START: wait until exact start moment
var now = DateTime.Now;
if (current.StartType == MediaStartTimeTypes.Hard
&& now < current.StartTime)
await Task.Delay(current.StartTime - now, hostCt)
.ConfigureAwait(false);
var (offset, hardStopUtc) = ComputeTiming(current);
// FOLLOW end: preempt when next normal item has HARD start
DateTime? followPreemptLocal = null;
if (current.EndType == MediaEndTimeTypes.Follow)
followPreemptLocal = PeekNextNormalHardStartTimeLocal();
// Run playback with its own CTS so we can preempt it
using var playCts =
CancellationTokenSource.CreateLinkedTokenSource(hostCt);
var playTask = Task.Run(() => _engine.PlayAsync(
current, offset, hardStopUtc, playCts.Token), playCts.Token);
Evental.Routing/VideohubClient.csC#
public async Task RouteAsync(int output, int input, CancellationToken ct)
{
await _out.WriteAsync($"VIDEO OUTPUT ROUTING:\n{output} {input}\n\n");
List<string> reply; // other clients' updates may arrive first
do reply = await ReadBlockAsync(ct);
while (reply is not (["ACK"] or ["NAK"]));
if (reply is ["NAK"])
throw new VideohubException($"Hub refused {input} -> {output}");
}
PptSync.Server/Web/WebApi.csC#
public async Task<(int Status, object Body)> HandleControlAsync(
HttpRequest request)
{
var config = _model.Settings.Web;
if (!config.AllowControl)
return Unpack(Fail(403, "HTTP control is switched off."));
if (!Authorised(request, config.ApiKey))
return Unpack(Fail(401, "Missing or wrong API key."));
var args = request.Segments.Skip(1).Select(s => s.Trim()).ToList();
// Same methods as the buttons, on the UI thread: a press from
// Companion and a press on a tile can never disagree.
var result = await _model.Dispatcher.InvokeAsync(
() => Dispatch(args, request));
return Unpack(result);
}
PptSync.Core/Protocol/FrameStream.csC#
/// Writes are serialised through a semaphore so a preview frame
/// can never interleave with a control message.
private async Task WriteRawAsync(byte[] payload, CancellationToken ct)
{
await _writeLock.WaitAsync(ct).ConfigureAwait(false);
try
{
var prefix = new byte[4];
BinaryPrimitives.WriteInt32BigEndian(prefix, payload.Length);
await _stream.WriteAsync(prefix, ct).ConfigureAwait(false);
await _stream.WriteAsync(payload, ct).ConfigureAwait(false);
await _stream.FlushAsync(ct).ConfigureAwait(false);
}
finally
{
_writeLock.Release();
}
}
narrowcast/src/feed.tsTypeScript
const posts: WpPost[] = await res.json();
return posts
.map((p): Slide => {
const body = stripHtml(p.content.rendered);
return {
id: p.id,
title: decodeEntities(p.title.rendered),
body,
seconds: clamp(body.length / cfg.cps, cfg.min, cfg.max),
breaking: p.tags.includes(cfg.tagBreaking),
};
})
// stable sort: breaking news first, otherwise newest first
.sort((a, b) => Number(b.breaking) - Number(a.breaking));