public async Task <int> InvokeAsync(InvocationContext context) { var console = context.Console.Out; var(client, schema) = await DeviceDetection.DetectDeviceAsync(console); if (client is null) { return(1); } using (client) { var channel = context.ParseResult.ValueForOption <int>("channel"); var keys = context.ParseResult.ValueForOption <string>("keys"); var targetKit = context.ParseResult.ValueForOption <int>("kit"); if (targetKit < 1 || targetKit + 1 > schema.KitRoots.Count) { console.WriteLine($"Kit {targetKit} is out of range for {schema.Identifier.Name} for this command."); console.WriteLine("Note that one extra kit is required after the specified one."); return(1); } // Detect the current kit // TODO: Stop assuming current kit is at address 0, although it is for TD-17, TD-50 and TD-27... var data = await client.RequestDataAsync(0, 1, new CancellationTokenSource(TimeSpan.FromSeconds(1)).Token); var currentKit = data[0] + 1; // Copy current kit to target kit and target kit + 1 var kit = await KitUtilities.ReadKit(schema, client, currentKit, console); await KitUtilities.WriteKit(client, kit, targetKit, console); await KitUtilities.WriteKit(client, kit, targetKit + 1, console); SetCurrentKit(targetKit); var programChangeCommand = (byte)(0xc0 | (channel - 1)); // Now listen for the foot switch... client.MessageReceived += (sender, message) => { if (message.Data.Length == 2 && message.Data[0] == programChangeCommand) { console.WriteLine("Turning the page..."); System.Windows.Forms.SendKeys.SendWait(keys); SetCurrentKit(targetKit); } }; console.WriteLine("Listening for foot switch"); await Task.Delay(TimeSpan.FromHours(1)); } return(0); void SetCurrentKit(int newKitNumber) => client.SendData(0, new[] { (byte)(newKitNumber - 1) }); }
public async Task <int> InvokeAsync(InvocationContext context) { var console = context.Console.Out; var kit = context.ParseResult.ValueForOption <int>("kit"); var file = context.ParseResult.ValueForOption <string>("file"); var(client, schema) = await DeviceDetection.DetectDeviceAsync(console); if (client == null) { return(1); } using (client) { if (!schema.KitRoots.TryGetValue(kit, out _)) { console.WriteLine($"Kit {kit} out of range"); return(1); } ; // Allow up to 30 seconds in total, and 1 second per container. var overallToken = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; try { Stopwatch sw = Stopwatch.StartNew(); var kitToSave = await KitUtilities.ReadKit(schema, client, kit, console); console.WriteLine($"Finished loading in {(int) sw.Elapsed.TotalSeconds} seconds"); using (var stream = File.Create(file)) { kitToSave.Save(stream); } console.WriteLine($"Saved kit to {file}"); } catch (OperationCanceledException) { console.WriteLine("Data loading from device was cancelled"); return(1); } catch (Exception ex) { console.WriteLine($"Error loading data from device: {ex}"); return(1); } } return(0); }
public async Task <int> InvokeAsync(InvocationContext context) { var console = context.Console.Out; if (!SendKeysUtilities.HasSendKeys) { console.WriteLine($"SendKeys not detected; this command can only be run on Windows."); return(1); } var(client, schema) = await DeviceDetection.DetectDeviceAsync(console); if (client is null) { return(1); } using (client) { var channel = context.ParseResult.ValueForOption <int>("channel"); var keys = context.ParseResult.ValueForOption <string>("keys"); var midiNote = context.ParseResult.ValueForOption <int>("note"); var noteOn = (byte)(0x90 | (channel - 1)); // Now listen for the foot switch... client.MessageReceived += (sender, message) => { if (message.Data.Length == 3 && message.Data[0] == noteOn && message.Data[1] == midiNote) { console.WriteLine("Turning the page..."); SendKeysUtilities.SendWait(keys); } }; console.WriteLine("Listening for MIDI note"); await Task.Delay(TimeSpan.FromHours(1)); } return(0); }
public async Task <int> InvokeAsync(InvocationContext context) { var console = context.Console.Out; var kit = context.ParseResult.ValueForOption <int>("kit"); var file = context.ParseResult.ValueForOption <string>("file"); var(client, schema) = await DeviceDetection.DetectDeviceAsync(console); if (client == null) { return(1); } if (!schema.KitRoots.TryGetValue(kit, out var kitRoot)) { console.WriteLine($"Kit {kit} out of range"); return(1); } ; var moduleData = new ModuleData(); // Note: a lot of this logic is copied from SoundRecorderDialog. It should go in a model. var instrumentRoot = kitRoot.DescendantNodesAndSelf().FirstOrDefault(node => node.InstrumentNumber == 1); if (instrumentRoot == null) { console.WriteLine($"No instrument root available. Please email a bug report to [email protected]"); return(1); } List <FixedContainer> instrumentContainers = instrumentRoot.DescendantNodesAndSelf() .SelectMany(node => node.Details) .Select(detail => detail.Container) .Where(fc => fc != null) .Distinct() .ToList(); var originalData = await LoadContainers(); var predictedData = originalData.Clone(); var differences = new List <Difference>(); using (client) { var(instrumentFieldContext, instrumentField) = (from ct in instrumentContainers orderby ct.Address from field in ct.Container.Fields where field is InstrumentField select(ct, (InstrumentField)field)).FirstOrDefault(); if (instrumentFieldContext == null) { console.WriteLine($"No instrument field available. Please email a bug report to [email protected]"); return(1); } try { foreach (var instrument in schema.PresetInstruments) { predictedData.Snapshot(); // Make the change on the real module and load the data. await RawSetInstrument(instrumentFieldContext, instrumentField, instrument); var realData = await LoadContainers(); // Make the change in the model. instrumentField.SetInstrument(instrumentFieldContext, predictedData, instrument); // Compare the two. bool anyDifferences = false; foreach (var container in instrumentContainers) { foreach (var field in container.GetChildren(realData).OfType <NumericField>()) { var realValue = field.GetRawValue(container, realData); var predictedValue = field.GetRawValue(container, predictedData); if (realValue != predictedValue) { anyDifferences = true; differences.Add(new Difference(instrument, container, field, realValue, predictedValue)); } } } console.Write(anyDifferences ? "!" : "."); predictedData.RevertSnapshot(); } } finally { await RestoreData(); } } foreach (var difference in differences) { console.WriteLine(difference.ToString()); } console.WriteLine($"Total differences: {differences.Count}"); return(0); async Task <ModuleData> LoadContainers() { var data = new ModuleData(); foreach (var container in instrumentContainers) { await LoadContainerAsync(data, container); } return(data); } async Task LoadContainerAsync(ModuleData data, FixedContainer context) { var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(1)).Token; var segment = await client.RequestDataAsync(context.Address.Value, context.Container.Size, cancellationToken); data.Populate(context.Address, segment); } async Task RestoreData() { console.WriteLine(); console.WriteLine("Restoring original data"); foreach (var segment in originalData.GetSegments()) { client.SendData(segment.Start.Value, segment.CopyData()); await Task.Delay(40); } } // Sets the instrument directly in the module, setting *only* that field. async Task RawSetInstrument(FixedContainer context, InstrumentField field, Instrument instrument) { var address = context.Address + field.Offset; byte[] bytes = { (byte)((instrument.Id >> 12) & 0xf), (byte)((instrument.Id >> 8) & 0xf), (byte)((instrument.Id >> 4) & 0xf), (byte)((instrument.Id >> 0) & 0xf) }; client.SendData(address.Value, bytes); await Task.Delay(40); } }
public async Task <int> InvokeAsync(InvocationContext context) { var console = context.Console.Out; var kit = context.ParseResult.ValueForOption <int>("kit"); var file = context.ParseResult.ValueForOption <string>("file"); var(client, schema) = await DeviceDetection.DetectDeviceAsync(console); if (client == null) { return(1); } var moduleData = new ModuleData(); using (client) { if (!schema.KitRoots.TryGetValue(kit, out var kitRoot)) { console.WriteLine($"Kit {kit} out of range"); return(1); } ; // Allow up to 30 seconds in total, and 1 second per container. var overallToken = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token; try { Stopwatch sw = Stopwatch.StartNew(); var containers = kitRoot.Context.AnnotateDescendantsAndSelf().Where(c => c.Container.Loadable).ToList(); console.WriteLine($"Loading {containers.Count} containers from device {schema.Identifier.Name}"); foreach (var container in containers) { await PopulateSegment(moduleData, container, overallToken); } console.WriteLine($"Finished loading in {(int) sw.Elapsed.TotalSeconds} seconds"); var clonedData = kitRoot.Context.CloneData(moduleData, schema.KitRoots[1].Context.Address); var kitToSave = new Kit(schema, clonedData, kit); using (var stream = File.Create(file)) { kitToSave.Save(stream); } console.WriteLine($"Saved kit to {file}"); } catch (OperationCanceledException) { console.WriteLine("Data loading from device was cancelled"); return(1); } catch (Exception ex) { console.WriteLine($"Error loading data from device: {ex}"); return(1); } } return(0); async Task PopulateSegment(ModuleData data, AnnotatedContainer annotatedContainer, CancellationToken token) { var timerToken = new CancellationTokenSource(TimeSpan.FromSeconds(1)).Token; var effectiveToken = CancellationTokenSource.CreateLinkedTokenSource(token, timerToken).Token; try { var segment = await client.RequestDataAsync(annotatedContainer.Context.Address.Value, annotatedContainer.Container.Size, effectiveToken); data.Populate(annotatedContainer.Context.Address, segment); } catch (OperationCanceledException) when(timerToken.IsCancellationRequested) { console.WriteLine($"Device didn't respond for container {annotatedContainer.Path}; skipping."); } } }