165 lines
7.9 KiB
C#
165 lines
7.9 KiB
C#
#nullable enable
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using T3.Editor.Gui.Interaction.Midi.CommandProcessing;
|
|
using T3.Editor.Gui.Interaction.Variations;
|
|
using T3.Editor.Gui.Interaction.Variations.Model;
|
|
|
|
namespace T3.Editor.Gui.Interaction.Midi.CompatibleDevices;
|
|
|
|
[SuppressMessage("ReSharper", "UnusedMember.Local")]
|
|
|
|
[MidiDeviceProduct("APC MINI")]
|
|
public sealed class ApcMini : CompatibleMidiDevice
|
|
{
|
|
public ApcMini()
|
|
{
|
|
CommandTriggerCombinations
|
|
= new List<CommandTriggerCombination>
|
|
{
|
|
new(SnapshotActions.ActivateOrCreateSnapshotAtIndex, InputModes.Default, new[] { SceneTrigger1To64 },
|
|
CommandTriggerCombination.ExecutesAt.SingleRangeButtonPressed),
|
|
new(SnapshotActions.SaveSnapshotAtIndex, InputModes.Save, new[] { SceneTrigger1To64 },
|
|
CommandTriggerCombination.ExecutesAt.SingleRangeButtonPressed),
|
|
|
|
new(SnapshotActions.RemoveSnapshotAtIndex, InputModes.Delete, new[] { SceneTrigger1To64 },
|
|
CommandTriggerCombination.ExecutesAt.SingleRangeButtonPressed),
|
|
|
|
new(BlendActions.StartBlendingSnapshots, InputModes.Default, new[] { SceneTrigger1To64 },
|
|
CommandTriggerCombination.ExecutesAt.AllCombinedButtonsReleased),
|
|
|
|
|
|
new(BlendActions.StartBlendingTowardsSnapshot,
|
|
requiredInputMode: InputModes.BlendTo,
|
|
new[] { SceneTrigger1To64 },
|
|
CommandTriggerCombination.ExecutesAt.SingleRangeButtonPressed),
|
|
|
|
// Sadly this is not triggered.
|
|
// new(BlendActions.StopBlendingTowards, InputModes.BlendTo, new[] { Shift },
|
|
// CommandTriggerCombination.ExecutesAt.ModeButtonReleased),
|
|
|
|
new(BlendActions.StopBlendingTowards, InputModes.Default, new[] { SceneLaunch8ClipStopAll },
|
|
CommandTriggerCombination.ExecutesAt.SingleActionButtonPressed),
|
|
|
|
new(BlendActions.UpdateBlendingTowardsProgress, InputModes.Default, new[] { Slider9 },
|
|
CommandTriggerCombination.ExecutesAt.ControllerChange),
|
|
|
|
new(BlendActions.UpdateBlendValues, InputModes.Default, new[] { Sliders1To8 },
|
|
CommandTriggerCombination.ExecutesAt.ControllerChange),
|
|
|
|
// A first stub for parameter collection control.
|
|
// new(ParamCollectionActions.SetParamGroupControl, InputModes.Default, new[] { Sliders1To8 },
|
|
// CommandTriggerCombination.ExecutesAt.ControllerChange),
|
|
|
|
// new(SnapshotActions.SaveSnapshotAtNextFreeSlot, InputModes.Default, new[] { SceneLaunch8ClipStopAll },
|
|
// CommandTriggerCombination.ExecutesAt.SingleActionButtonPressed),
|
|
|
|
//new CommandTriggerCombination(VariationHandling.ActivateGroupAtIndex, InputModes.Default, new[] { ChannelButtons1To8 }, CommandTriggerCombination.ExecutesAt.SingleRangeButtonPressed),
|
|
};
|
|
|
|
ModeButtons = new List<ModeButton>
|
|
{
|
|
new(Shift, InputModes.BlendTo),
|
|
new(SceneLaunch1ClipStop, InputModes.Delete),
|
|
};
|
|
}
|
|
|
|
protected override void UpdateVariationVisualization()
|
|
{
|
|
_updateCount++;
|
|
|
|
UpdateRangeLeds(SceneTrigger1To64,
|
|
mappedIndex =>
|
|
{
|
|
var color = ApcButtonColor.Off;
|
|
if (!SymbolVariationPool.TryGetSnapshot(mappedIndex, out var variation))
|
|
{
|
|
return (int)color;
|
|
}
|
|
|
|
if (variation.State == Variation.States.Active)
|
|
{
|
|
return (int)ApcButtonColor.Red;
|
|
}
|
|
|
|
switch (variation.State)
|
|
{
|
|
case Variation.States.Undefined:
|
|
color = ApcButtonColor.Off;
|
|
break;
|
|
case Variation.States.InActive:
|
|
color = ApcButtonColor.Green;
|
|
break;
|
|
case Variation.States.Active:
|
|
color = ApcButtonColor.Red;
|
|
break;
|
|
case Variation.States.Modified:
|
|
color = ApcButtonColor.YellowBlinking;
|
|
break;
|
|
case Variation.States.IsBlended:
|
|
color = ApcButtonColor.RedBlinking;
|
|
break;
|
|
}
|
|
|
|
return AddModeHighlight(mappedIndex, (int)color);
|
|
});
|
|
}
|
|
|
|
private int AddModeHighlight(int index, int orgColor)
|
|
{
|
|
var indicatedStatus = (_updateCount + index / 8) % 30 < 4;
|
|
if (!indicatedStatus)
|
|
{
|
|
return orgColor;
|
|
}
|
|
|
|
return ActiveMode switch
|
|
{
|
|
InputModes.Save => (int)ApcButtonColor.Yellow,
|
|
InputModes.BlendTo => (int)ApcButtonColor.Yellow,
|
|
InputModes.Delete => (int)ApcButtonColor.Red,
|
|
_ => orgColor
|
|
};
|
|
}
|
|
|
|
private int _updateCount;
|
|
|
|
private enum ApcButtonColor
|
|
{
|
|
Undefined = -1,
|
|
Off,
|
|
Green,
|
|
GreenBlinking,
|
|
Red,
|
|
RedBlinking,
|
|
Yellow,
|
|
YellowBlinking,
|
|
}
|
|
|
|
// The APC Mini numbers its clip pads row-major from the bottom (note 0 = bottom-left), but the
|
|
// snapshot index is canonical: 0 = top-left, reading order. Flip rows so the top-left pad is index 0.
|
|
// The transform feeds both LED output and button input, keeping lights and presses in sync.
|
|
private static readonly ButtonRange SceneTrigger1To64 = new(0, 63, mapToIndex: position => (8 - 1 - position / 8) * 8 + position % 8);
|
|
private static readonly ButtonRange Sliders1To9 = new(48, 48 + 8);
|
|
private static readonly ButtonRange Sliders1To8 = new(48, 48 + 7);
|
|
private static readonly ButtonRange Slider9 = new(48 + 8, 48 + 8);
|
|
|
|
private static readonly ButtonRange ChannelButtons1To8 = new(64, 71);
|
|
private static readonly ButtonRange ButtonUp = new(64);
|
|
private static readonly ButtonRange ButtonDown = new(65);
|
|
private static readonly ButtonRange ButtonLeft = new(66);
|
|
private static readonly ButtonRange ButtonRight = new(67);
|
|
private static readonly ButtonRange ButtonVolume = new(68);
|
|
private static readonly ButtonRange ButtonPan = new(69);
|
|
private static readonly ButtonRange ButtonSend = new(70);
|
|
private static readonly ButtonRange ButtonDevice = new(71);
|
|
|
|
private static readonly ButtonRange SceneLaunch1To8 = new(82, 89);
|
|
private static readonly ButtonRange SceneLaunch1ClipStop = new(82);
|
|
private static readonly ButtonRange SceneLaunch2ClipSolo = new(83);
|
|
private static readonly ButtonRange SceneLaunch3ClipRecArm = new(84);
|
|
private static readonly ButtonRange SceneLaunch4ClipMute = new(85);
|
|
private static readonly ButtonRange SceneLaunch5ClipSelect = new(86);
|
|
private static readonly ButtonRange SceneLaunch8ClipStopAll = new(89);
|
|
|
|
private static readonly ButtonRange Shift = new(98);
|
|
} |