JD2022-TU1/main/tools/framework/JD.Application.TeaBox/Utils/TapeExtensions.cs

148 lines
4.8 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using JD.Application.View.PropertyGrid;
using JD.Asset.Types.Map;
using JD.Audio.Annotations;
using JD.Audio.Sound;
using JD.Kernel.Classes;
using JD.Kernel.Structs;
using JD.LogService;
using TeaBox;
using JD.Serialization;
namespace JD.Application.Utils
{
public static class TapeExtensions
{
#region Wave
public static void SetWave(this Tape tape, Wave wave)
{
tape.Extensions.wave = wave ?? _emptyWave;
tape.RaisePropertyChanged("Wave");
}
/// <summary>
/// Not a real TryGet, returns right Wave if found, else returns an empty Wave with test info
/// </summary>
/// <param name="tape"></param>
/// <returns></returns>
public static Wave TryGetWave(this Tape tape)
{
if (tape.Extensions.wave == null && tape.Extensions.triedToFindWave == null)
{
tape.Extensions.triedToFindWave = true;
tape.Extensions.wave = ResolveWaveFromTape(tape);
}
return tape.Extensions.wave ?? _emptyWave;
}
private static Wave ResolveWaveFromTape(Tape tape)
{
try
{
var map = Map.FromPath(tape.Id);
if (map.IsValid)
{
var musicTrackTpl = map.MusicTrack;
if (!string.IsNullOrEmpty(musicTrackTpl) && !File.Exists(musicTrackTpl))
{
throw new IOException($"Could not find the MusicTrackTpl file for map {map.Name} at location {musicTrackTpl}");
}
return Wave.LoadFromMusicTrackTpl(musicTrackTpl);
}
}
catch (Exception ex)
{
MessageService.MessageService.ShowBalloon(TimeSpan.FromSeconds(15), "No wave available", "Could not resolve the wave associated with tape " + tape.Id + ". Details : " + ex.Message, ToolTipIcon.Warning);
}
return null;
}
public static object GridWave(this Tape tape)
{
return tape.TryGetWave() != null ? new WaveGridView(tape.TryGetWave()) : null;
}
private static readonly Wave _emptyWave = CreateEmptyWave();
private static Wave CreateEmptyWave()
{
const int sampleCount = 10000;
const int emptyWaveLengthInMinutes = 3;
var channel = new Channel(sampleCount);
for (int i = 0; i < sampleCount; i++)
{
channel.Add(0);
}
var wave = new Wave(new[] { channel }, TimeSpan.FromMinutes(emptyWaveLengthInMinutes));
using (wave.Annotations.BeginUpdate())
{
const int bpm = 120;
double markerCount = wave.Duration.TotalMinutes * bpm;
for (int i = 0; i < markerCount; i++)
{
wave.Annotations.Markers.Add(new Beat(TimeSpan.FromMinutes((double)i / bpm),
(int)(((double)i / markerCount) * sampleCount), ""));
}
}
return wave;
}
#endregion
#region Replication
public static Scope ReplicationOperation(this Tape tape)
{
return tape.Extensions.IsReplicating ?? (tape.Extensions.IsReplicating = new Scope());
}
/// <summary>
/// The update operation is useful when the tape will be modified a lot.
/// </summary>
public static Scope UpdateOperation(this Tape tape)
{
return tape.Extensions.UpdateOperation ?? (tape.Extensions.UpdateOperation = new Scope());
}
#endregion
#region Validation
/// <summary>
/// Makes sure two clips are not wearing the same id.
/// </summary>
public static void SanitizeClipIds(this Tape tape, ILogger log)
{
var clipById = new Dictionary<uint, Clip>();
foreach (var clip in tape.Clips.ToArray())
{
Clip existingClip;
if (clipById.TryGetValue(clip.Id, out existingClip))
{
clip.Id = IdGenerator.Instance.Generate();
var location = new FileLocation(tape.Id, new List<uint> { existingClip.Id, clip.Id });
log.LogWarning(location, "Two clips are sharing the same id {0}. Second one was reassigned to a new one.", clip.Id);
}
else
{
clipById.Add(clip.Id, clip);
}
}
}
#endregion
}
}