Skip to content

Commit

Permalink
Track program by default in Playback
Browse files Browse the repository at this point in the history
  • Loading branch information
melanchall committed Jan 20, 2025
1 parent 20d37b0 commit 71c3b55
Show file tree
Hide file tree
Showing 11 changed files with 729 additions and 351 deletions.
92 changes: 91 additions & 1 deletion DryWetMidi.Tests/Multimedia/Playback/PlaybackTests.Asserts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,102 @@
using Melanchall.DryWetMidi.Tests.Utilities;
using NUnit.Framework;
using Melanchall.DryWetMidi.Tests.Common;
using System.Diagnostics;

namespace Melanchall.DryWetMidi.Tests.Multimedia
{
[TestFixture]
public sealed partial class PlaybackTests
{
private void CheckPlayback(
bool useOutputDevice,
ICollection<ITimedObject> initialPlaybackObjects,
PlaybackChangerBase[] actions,
ICollection<ReceivedEvent> expectedReceivedEvents,
Action<Playback> setupPlayback = null,
int? repeatsCount = null) => CheckPlayback(
useOutputDevice,
outpuDevice => new Playback(initialPlaybackObjects, TempoMap.Default, outpuDevice),
actions,
expectedReceivedEvents,
setupPlayback,
repeatsCount);

private void CheckPlayback(
bool useOutputDevice,
Func<IOutputDevice, Playback> createPlayback,
PlaybackChangerBase[] actions,
ICollection<ReceivedEvent> expectedReceivedEvents,
Action<Playback> setupPlayback = null,
int? repeatsCount = null)
{
var outputDevice = useOutputDevice
? (IOutputDevice)OutputDevice.GetByName(SendReceiveUtilities.DeviceToTestOnName)
: new EmptyOutputDevice();

var stopwatch = new Stopwatch();
var receivedEvents = new List<ReceivedEvent>();

using (outputDevice)
{
if (useOutputDevice)
SendReceiveUtilities.WarmUpDevice((OutputDevice)outputDevice);

outputDevice.EventSent += (_, e) => receivedEvents.Add(new ReceivedEvent(e.Event, stopwatch.Elapsed));

using (var playback = createPlayback(outputDevice))
{
setupPlayback?.Invoke(playback);

if (repeatsCount > 0)
playback.Loop = true;

var actualRepeatsCount = 0;
playback.RepeatStarted += (_, __) =>
{
actualRepeatsCount++;
if (actualRepeatsCount == repeatsCount)
playback.Loop = false;
};

var actionsExecutedCount = 0;

stopwatch.Start();
playback.Start();

foreach (var action in actions)
{
var waitStopwatch = Stopwatch.StartNew();

while (waitStopwatch.ElapsedMilliseconds < action.PeriodMs)
{
}

action.Action(playback);
actionsExecutedCount++;
}

var timeout = TimeSpan.FromSeconds(10);
var stopped = WaitOperations.Wait(() => !playback.IsRunning, timeout);
Assert.IsTrue(stopped, $"Playback is running after {timeout}.");

WaitOperations.Wait(SendReceiveUtilities.MaximumEventSendReceiveDelay);

Assert.AreEqual(
actions.Length,
actionsExecutedCount,
"Invalid number of actions executed.");

CompareReceivedEvents(
receivedEvents,
expectedReceivedEvents.ToList(),
sendReceiveTimeDelta: useOutputDevice
? SendReceiveUtilities.MaximumEventSendReceiveDelay
: TimeSpan.FromMilliseconds(10));
}
}
}

private IEnumerable<SnapPoint> GetActiveSnapPoints(Playback playback)
{
return playback.Snapping.GetActiveSnapPoints().ToList();
Expand Down Expand Up @@ -721,7 +811,7 @@ private void CompareSentReceivedEvents(
Assert.LessOrEqual(
offsetFromExpectedTime,
SendReceiveUtilities.MaximumEventSendReceiveDelay,
$"Event was sent at wrong time ({sentEvent.Time}; expected is {expectedTime}).");
$"Event '{sentEvent.Event}' was sent at wrong time ({sentEvent.Time}; expected is {expectedTime}).");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1936,7 +1936,7 @@ private void CheckTrackProgramWithMetadata(
(MidiEvent, object)[] expectedMetadata)
{
CheckTrackDataWithMetadata(
p => p.TrackProgram = true,
p => { },
midiFile,
moveFrom,
moveTo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,7 @@ public void CheckPlaybackDataChangesOnTheFly_AddProgramChangeWithinNote_AfterCur
new ReceivedEvent(new NoteOnEvent((SevenBitNumber)70, Note.DefaultVelocity), TimeSpan.Zero),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(700)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1000)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand All @@ -214,8 +213,7 @@ public void CheckPlaybackDataChangesOnTheFly_AddProgramChangeWithinNote_AfterCur
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(700)),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)50), TimeSpan.FromMilliseconds(900)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1000)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand All @@ -242,8 +240,7 @@ public void CheckPlaybackDataChangesOnTheFly_AddProgramChangeWithinNote_AfterCur
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(700)),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70) { Channel = (FourBitNumber)4 }, TimeSpan.FromMilliseconds(900)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1000)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand Down Expand Up @@ -272,8 +269,7 @@ public void CheckPlaybackDataChangesOnTheFly_AddProgramChangeWithinNote_AfterCur
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(700)),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)50), TimeSpan.FromMilliseconds(900)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1000)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand All @@ -298,8 +294,7 @@ public void CheckPlaybackDataChangesOnTheFly_AddProgramChangeWithinNote_BeforeCu
new ReceivedEvent(new NoteOnEvent((SevenBitNumber)70, Note.DefaultVelocity), TimeSpan.Zero),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(500)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1000)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand All @@ -325,8 +320,7 @@ public void CheckPlaybackDataChangesOnTheFly_AddProgramChangeWithinNote_BeforeCu
new ReceivedEvent(new NoteOnEvent((SevenBitNumber)70, Note.DefaultVelocity), TimeSpan.Zero),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)50), TimeSpan.FromMilliseconds(500)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1000)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand All @@ -353,8 +347,7 @@ public void CheckPlaybackDataChangesOnTheFly_AddProgramChangeWithinNote_BeforeCu
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(500)),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70) { Channel = (FourBitNumber)4 }, TimeSpan.FromMilliseconds(500)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1000)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand Down Expand Up @@ -383,8 +376,7 @@ public void CheckPlaybackDataChangesOnTheFly_AddProgramChangeWithinNote_MoveToTi
new ReceivedEvent(new NoteOnEvent((SevenBitNumber)70, Note.DefaultVelocity), TimeSpan.Zero),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(500)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(800)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand Down Expand Up @@ -422,8 +414,7 @@ public void CheckPlaybackDataChangesOnTheFly_AddProgramChangeWithinNote_MoveToTi
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)50), TimeSpan.FromMilliseconds(600)),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(800)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1200)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand Down Expand Up @@ -1401,7 +1392,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_AddProgramChangeWithinNote_Aft
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(900)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1200)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1434,7 +1424,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_AddProgramChangeWithinNote_Aft
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)50), TimeSpan.FromMilliseconds(1100)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1200)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1467,7 +1456,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_AddProgramChangeWithinNote_Aft
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70) { Channel = (FourBitNumber)4 }, TimeSpan.FromMilliseconds(1100)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1200)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1502,7 +1490,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_AddProgramChangeWithinNote_Aft
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)50), TimeSpan.FromMilliseconds(1100)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1200)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1532,7 +1519,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_AddProgramChangeWithinNote_Bef
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(900)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1200)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1564,7 +1550,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_AddProgramChangeWithinNote_Bef
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)50), TimeSpan.FromMilliseconds(1000)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1200)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1597,7 +1582,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_AddProgramChangeWithinNote_Bef
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70) { Channel = (FourBitNumber)4 }, TimeSpan.FromMilliseconds(1000)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1200)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1631,7 +1615,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_AddProgramChangeWithinNote_Mov
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(800)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1000)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1675,7 +1658,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_AddProgramChangeWithinNote_Mov
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(1800)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(2200)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ public void CheckPlaybackDataChangesOnTheFly_ChangeObject_ProgramChange_1()
new ReceivedEvent(new NoteOnEvent((SevenBitNumber)70, Note.DefaultVelocity), TimeSpan.Zero),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)71), TimeSpan.FromMilliseconds(300)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(700)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand Down Expand Up @@ -137,8 +136,7 @@ public void CheckPlaybackDataChangesOnTheFly_ChangeObject_ProgramChange_2()
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)50), TimeSpan.FromMilliseconds(500)),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(600)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(700)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand Down Expand Up @@ -171,8 +169,7 @@ public void CheckPlaybackDataChangesOnTheFly_ChangeObject_ProgramChange_3()
new ReceivedEvent(new NoteOnEvent((SevenBitNumber)50, Note.DefaultVelocity), TimeSpan.FromMilliseconds(700)),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)80), TimeSpan.FromMilliseconds(800)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)50, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(900)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand Down Expand Up @@ -207,8 +204,7 @@ public void CheckPlaybackDataChangesOnTheFly_ChangeObject_ProgramChange_4()
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(300)),
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70) { Channel = (FourBitNumber)4 }, TimeSpan.FromMilliseconds(500)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(700)),
},
setupPlayback: playback => playback.TrackProgram = true);
});
}

[Retry(OnTheFlyChecksRetriesNumber)]
Expand Down Expand Up @@ -1189,7 +1185,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_ChangeObject_ProgramChange_1()
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)71), TimeSpan.FromMilliseconds(800)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1400)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1231,7 +1226,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_ChangeObject_ProgramChange_2()
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(900)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1400)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1271,7 +1265,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_ChangeObject_ProgramChange_3()
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)80), TimeSpan.FromMilliseconds(1700)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)50, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1800)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down Expand Up @@ -1312,7 +1305,6 @@ public void CheckPlaybackDataChangesOnTheFly_Loop_ChangeObject_ProgramChange_4()
new ReceivedEvent(new ProgramChangeEvent((SevenBitNumber)70), TimeSpan.FromMilliseconds(900)),
new ReceivedEvent(new NoteOffEvent((SevenBitNumber)70, Note.DefaultOffVelocity), TimeSpan.FromMilliseconds(1400)),
},
setupPlayback: playback => playback.TrackProgram = true,
repeatsCount: 1);
}

Expand Down
Loading

0 comments on commit 71c3b55

Please sign in to comment.