private void CheckPlayback_TickGenerator(CreateTickGeneratorCallback createTickGeneratorCallback, TimeSpan maximumEventSendReceiveDelay) { var eventsToSend = new[] { new EventToSend(new NoteOnEvent((SevenBitNumber)100, (SevenBitNumber)20) { Channel = (FourBitNumber)5 }, TimeSpan.Zero), new EventToSend(new NoteOffEvent((SevenBitNumber)100, (SevenBitNumber)10) { Channel = (FourBitNumber)5 }, TimeSpan.FromSeconds(2)), new EventToSend(new NoteOnEvent(), TimeSpan.FromSeconds(1)), new EventToSend(new NoteOnEvent((SevenBitNumber)30, (SevenBitNumber)50), TimeSpan.Zero), new EventToSend(new NoteOffEvent(), TimeSpan.FromSeconds(3)), new EventToSend(new NoteOffEvent((SevenBitNumber)30, (SevenBitNumber)50), TimeSpan.Zero) }; CheckPlayback( eventsToSend, 1.0, beforePlaybackStarted: NoPlaybackAction, startPlayback: (context, playback) => playback.Start(), afterPlaybackStarted: (context, playback) => { Assert.LessOrEqual(context.Stopwatch.Elapsed, maximumEventSendReceiveDelay, "Playback blocks current thread."); Assert.IsTrue(playback.IsRunning, "Playback is not running after start."); }, waiting: (context, playback) => { var timeout = context.ExpectedTimes.Last() + maximumEventSendReceiveDelay; var areEventsReceived = SpinWait.SpinUntil(() => context.ReceivedEvents.Count == eventsToSend.Length, timeout); Assert.IsTrue(areEventsReceived, $"Events are not received for timeout {timeout}."); }, finalChecks: (context, playback) => { var playbackStopped = SpinWait.SpinUntil(() => !playback.IsRunning, maximumEventSendReceiveDelay); Assert.IsTrue(playbackStopped, "Playback is running after completed."); }, createTickGeneratorCallback: createTickGeneratorCallback); }
private void CheckPlayback( ICollection <EventToSend> eventsToSend, double speed, PlaybackAction beforePlaybackStarted, PlaybackAction startPlayback, PlaybackAction afterPlaybackStarted, PlaybackAction waiting, PlaybackAction finalChecks, CreateTickGeneratorCallback createTickGeneratorCallback = null) { var playbackContext = new PlaybackContext(); var receivedEvents = playbackContext.ReceivedEvents; var sentEvents = playbackContext.SentEvents; var stopwatch = playbackContext.Stopwatch; var tempoMap = playbackContext.TempoMap; var eventsForPlayback = new List <MidiEvent>(); var expectedTimes = playbackContext.ExpectedTimes; var currentTime = TimeSpan.Zero; foreach (var eventToSend in eventsToSend.Where(e => !(e.Event is MetaEvent))) { var midiEvent = eventToSend.Event.Clone(); midiEvent.DeltaTime = LengthConverter.ConvertFrom((MetricTimeSpan)eventToSend.Delay, (MetricTimeSpan)currentTime, tempoMap); currentTime += eventToSend.Delay; eventsForPlayback.Add(midiEvent); expectedTimes.Add(TimeSpan.FromTicks(MathUtilities.RoundToLong(currentTime.Ticks / speed))); } using (var outputDevice = OutputDevice.GetByName(SendReceiveUtilities.DeviceToTestOnName)) { SendReceiveUtilities.WarmUpDevice(outputDevice); outputDevice.EventSent += (_, e) => sentEvents.Add(new SentEvent(e.Event, stopwatch.Elapsed)); var clockSettings = createTickGeneratorCallback != null ? new MidiClockSettings { CreateTickGeneratorCallback = createTickGeneratorCallback } : null; using (var playback = new Playback(eventsForPlayback, tempoMap, outputDevice, clockSettings)) { playback.Speed = speed; beforePlaybackStarted(playbackContext, playback); using (var inputDevice = InputDevice.GetByName(SendReceiveUtilities.DeviceToTestOnName)) { inputDevice.EventReceived += (_, e) => { lock (playbackContext.ReceivedEventsLockObject) { receivedEvents.Add(new ReceivedEvent(e.Event, stopwatch.Elapsed)); } }; inputDevice.StartEventsListening(); stopwatch.Start(); startPlayback(playbackContext, playback); afterPlaybackStarted(playbackContext, playback); waiting(playbackContext, playback); stopwatch.Stop(); finalChecks(playbackContext, playback); } } } CompareSentReceivedEvents(sentEvents.Take(expectedTimes.Count).ToList(), receivedEvents.Take(expectedTimes.Count).ToList(), expectedTimes); }