private async void SendSysExFile_Click(object sender, RoutedEventArgs e) { CloseAllTips(); // validate the user-entered parameters uint transferDelayBetweenBuffers = 0; if ((!uint.TryParse(EnteredTransferDelay.Text, out transferDelayBetweenBuffers)) || transferDelayBetweenBuffers < 0) { var dlg = new MessageDialog("For the send delay, please enter a positive whole number. This is the delay between buffers sent over MIDI."); await dlg.ShowAsync(); return; } // validate, open the port, and then send the file if (_inputFile != null) { if (_outputPortDeviceInformation != null) { // open the MIDI port var outputPort = await MidiOutPort.FromIdAsync(_outputPortDeviceInformation.Id); if (outputPort != null) { // open the file var stream = await _inputFile.OpenReadAsync(); if (stream != null && stream.CanRead) { // validate the file var validationStatus = await MidiSysExSender.MeasureAndValidateSysExFile(stream); if (validationStatus.Status != MidiSysExSender.MidiSysExFileValidationStatus.OK) { // TODO: log failure var dlg = new MessageDialog(validationStatus.GetStatusDescription()); dlg.Title = "Invalid SysEx file"; await dlg.ShowAsync(); return; } // Show statistics from the file FileInformationPanel.Visibility = Visibility.Visible; CalculatedBufferSize.Text = string.Format("{0:n0}", validationStatus.BufferSize); CalculatedSysExMessageCount.Text = string.Format("{0:n0}", validationStatus.MessageCount); CalculatedFileSize.Text = string.Format("{0:n0}", validationStatus.FileSize); // send the bytes _transferOperation = MidiSysExSender.SendSysExStreamAsyncWithProgress( stream, outputPort, validationStatus.BufferSize, transferDelayBetweenBuffers); // show progress of the operation. This is updated async ProgressPanel.Visibility = Visibility.Visible; Cancel.IsEnabled = true; //report progress _transferOperation.Progress = (result, progress) => { SysExSendProgressBar.Value = (double)progress.BytesRead; ProgressBytes.Text = string.Format("{0:n0}", progress.BytesRead); PercentComplete.Text = Math.Round(((double)progress.BytesRead / _fileSizeInBytes) * 100, 0) + "%"; TransferOperationInProgress.Text = MidiSysExSender.GetStageDescription(progress.Stage); }; // handle completion _transferOperation.Completed = async(result, progress) => { // no need for cancel anymore Cancel.IsEnabled = false; // nuke the stream stream.Dispose(); stream = null; // close the MIDI port outputPort = null; // show completion message, depending on what type of completion we have if (result.Status == AsyncStatus.Canceled) { TransferOperationInProgress.Text = "Canceled"; Statistics.TotalCancelCount += 1; Analytics.LogEvent(AnalyticsEvent.TransferCancel); var dlg = new MessageDialog("Transfer canceled."); await dlg.ShowAsync(); } else if (result.Status == AsyncStatus.Error) { TransferOperationInProgress.Text = "Error"; Statistics.TotalErrorCount += 1; Analytics.LogEvent(AnalyticsEvent.TransferError); var dlg = new MessageDialog("Transfer error. You may need to close and re-open this app, and likely also reboot your device."); await dlg.ShowAsync(); } else { SysExSendProgressBar.Value = (double)_fileSizeInBytes; ProgressBytes.Text = string.Format("{0:N0}", _fileSizeInBytes); PercentComplete.Text = "100%"; TransferOperationInProgress.Text = "Completed"; // save the user-entered settings, since they worked //Settings.TransferBufferSize = transferBufferSize; Settings.TransferDelayBetweenBuffers = transferDelayBetweenBuffers; //Settings.F0Delay = f0Delay; // update user stats (for local use and display) Statistics.TotalFilesTransferred += 1; Statistics.TotalBytesTransferred += _fileSizeInBytes; Analytics.LogEvent(AnalyticsEvent.TransferSuccess); NotificationManager.NotifySuccess(_fileSizeInBytes, _inputFile.Name); } }; } else { // TODO: log failure // stream is null or CanRead is false var dlg = new MessageDialog("Could not open file '" + _inputFile.Name + "' for reading."); await dlg.ShowAsync(); } } else { // TODO: log failure // outputPort is null var dlg = new MessageDialog("Could not open MIDI output port '" + _outputPortDeviceInformation.Name + "'"); await dlg.ShowAsync(); } } else { // TODO: log failure // _outputPortDeviceInformation is null var dlg = new MessageDialog("No MIDI output port selected'"); await dlg.ShowAsync(); } } else { // TODO: log failure // _inputFile is null var dlg = new MessageDialog("No SysEx input file selected'"); await dlg.ShowAsync(); } }