PageRenderTime 82ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/midi/cs/scenario2_receivemidimessages.xaml.cs

https://gitlab.com/Rockyspade/Windows-universal-samples
C# | 263 lines | 177 code | 26 blank | 60 comment | 14 complexity | b977ccef9d40c0024cdacd9bfcbf4561 MD5 | raw file
  1. //*********************************************************
  2. //
  3. // Copyright (c) Microsoft. All rights reserved.
  4. // This code is licensed under the Microsoft Public License.
  5. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  6. // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  7. // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  8. // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  9. //
  10. //*********************************************************
  11. using SDKTemplate;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Text;
  15. using Windows.Devices.Enumeration;
  16. using Windows.Devices.Midi;
  17. using Windows.Storage.Streams;
  18. using Windows.UI.Core;
  19. using Windows.UI.Xaml.Controls;
  20. using Windows.UI.Xaml.Navigation;
  21. // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
  22. namespace MIDI
  23. {
  24. /// <summary>
  25. /// An empty page that can be used on its own or navigated to within a Frame.
  26. /// </summary>
  27. public sealed partial class Scenario2_ReceiveMIDIMessages : Page
  28. {
  29. /// <summary>
  30. /// Main Page
  31. /// </summary>
  32. private MainPage rootPage;
  33. /// <summary>
  34. /// Collection of active MidiInPorts
  35. /// </summary>
  36. private List<MidiInPort> midiInPorts;
  37. /// <summary>
  38. /// Device watcher for MIDI in ports
  39. /// </summary>
  40. MidiDeviceWatcher midiInDeviceWatcher;
  41. /// <summary>
  42. /// Set the rootpage context when entering the scenario
  43. /// </summary>
  44. /// <param name="e">Event arguments</param>
  45. protected override void OnNavigatedTo(NavigationEventArgs e)
  46. {
  47. this.rootPage = MainPage.Current;
  48. }
  49. /// <summary>
  50. /// Stop the device watcher when leaving the scenario
  51. /// </summary>
  52. /// <param name="e">Event arguments</param>
  53. protected override void OnNavigatedFrom(NavigationEventArgs e)
  54. {
  55. base.OnNavigatedFrom(e);
  56. // Stop the input device watcher
  57. this.midiInDeviceWatcher.Stop();
  58. // Close all MidiInPorts
  59. foreach (MidiInPort inPort in this.midiInPorts)
  60. {
  61. inPort.Dispose();
  62. }
  63. this.midiInPorts.Clear();
  64. }
  65. /// <summary>
  66. /// Constructor: Start the device watcher
  67. /// </summary>
  68. public Scenario2_ReceiveMIDIMessages()
  69. {
  70. this.InitializeComponent();
  71. // Initialize the list of active MIDI input devices
  72. this.midiInPorts = new List<MidiInPort>();
  73. // Set up the MIDI input device watcher
  74. this.midiInDeviceWatcher = new MidiDeviceWatcher(MidiInPort.GetDeviceSelector(), Dispatcher, this.inputDevices);
  75. // Start watching for devices
  76. this.midiInDeviceWatcher.Start();
  77. }
  78. /// <summary>
  79. /// Change the input MIDI device from which to receive messages
  80. /// </summary>
  81. /// <param name="sender">Element that fired the event</param>
  82. /// <param name="e">Event arguments</param>
  83. private async void inputDevices_SelectionChanged(object sender, SelectionChangedEventArgs e)
  84. {
  85. // Get the selected input MIDI device
  86. int selectedInputDeviceIndex = (sender as ListBox).SelectedIndex;
  87. // Try to create a MidiInPort
  88. if (selectedInputDeviceIndex < 0)
  89. {
  90. // Clear input device messages
  91. this.inputDeviceMessages.Items.Clear();
  92. this.inputDeviceMessages.Items.Add("Select a MIDI input device to be able to see its messages");
  93. this.inputDeviceMessages.IsEnabled = false;
  94. this.rootPage.NotifyUser("Select a MIDI input device to be able to see its messages", NotifyType.StatusMessage);
  95. return;
  96. }
  97. DeviceInformationCollection devInfoCollection = this.midiInDeviceWatcher.GetDeviceInformationCollection();
  98. if (devInfoCollection == null)
  99. {
  100. this.inputDeviceMessages.Items.Clear();
  101. this.inputDeviceMessages.Items.Add("Device not found!");
  102. this.inputDeviceMessages.IsEnabled = false;
  103. this.rootPage.NotifyUser("Device not found!", NotifyType.ErrorMessage);
  104. return;
  105. }
  106. DeviceInformation devInfo = devInfoCollection[selectedInputDeviceIndex];
  107. if (devInfo == null)
  108. {
  109. this.inputDeviceMessages.Items.Clear();
  110. this.inputDeviceMessages.Items.Add("Device not found!");
  111. this.inputDeviceMessages.IsEnabled = false;
  112. this.rootPage.NotifyUser("Device not found!", NotifyType.ErrorMessage);
  113. return;
  114. }
  115. var currentMidiInputDevice = await MidiInPort.FromIdAsync(devInfo.Id);
  116. if (currentMidiInputDevice == null)
  117. {
  118. this.rootPage.NotifyUser("Unable to create MidiInPort from input device", NotifyType.ErrorMessage);
  119. return;
  120. }
  121. // We have successfully created a MidiInPort; add the device to the list of active devices, and set up message receiving
  122. if (!this.midiInPorts.Contains(currentMidiInputDevice))
  123. {
  124. this.midiInPorts.Add(currentMidiInputDevice);
  125. currentMidiInputDevice.MessageReceived += MidiInputDevice_MessageReceived;
  126. }
  127. // Clear any previous input messages
  128. this.inputDeviceMessages.Items.Clear();
  129. this.inputDeviceMessages.IsEnabled = true;
  130. this.rootPage.NotifyUser("Input Device selected successfully! Waiting for messages...", NotifyType.StatusMessage);
  131. }
  132. /// <summary>
  133. /// Display the received MIDI message in a readable format
  134. /// </summary>
  135. /// <param name="sender">Element that fired the event</param>
  136. /// <param name="args">The received message</param>
  137. private async void MidiInputDevice_MessageReceived(MidiInPort sender, MidiMessageReceivedEventArgs args)
  138. {
  139. IMidiMessage receivedMidiMessage = args.Message;
  140. // Build the received MIDI message into a readable format
  141. StringBuilder outputMessage = new StringBuilder();
  142. outputMessage.Append(receivedMidiMessage.Timestamp.ToString()).Append(", Type: ").Append(receivedMidiMessage.Type);
  143. // Add MIDI message parameters to the output, depending on the type of message
  144. switch (receivedMidiMessage.Type)
  145. {
  146. case MidiMessageType.NoteOff:
  147. var noteOffMessage = (MidiNoteOffMessage)receivedMidiMessage;
  148. outputMessage.Append(", Channel: ").Append(noteOffMessage.Channel).Append(", Note: ").Append(noteOffMessage.Note).Append(", Velocity: ").Append(noteOffMessage.Velocity);
  149. break;
  150. case MidiMessageType.NoteOn:
  151. var noteOnMessage = (MidiNoteOnMessage)receivedMidiMessage;
  152. outputMessage.Append(", Channel: ").Append(noteOnMessage.Channel).Append(", Note: ").Append(noteOnMessage.Note).Append(", Velocity: ").Append(noteOnMessage.Velocity);
  153. break;
  154. case MidiMessageType.PolyphonicKeyPressure:
  155. var polyphonicKeyPressureMessage = (MidiPolyphonicKeyPressureMessage)receivedMidiMessage;
  156. outputMessage.Append(", Channel: ").Append(polyphonicKeyPressureMessage.Channel).Append(", Note: ").Append(polyphonicKeyPressureMessage.Note).Append(", Pressure: ").Append(polyphonicKeyPressureMessage.Pressure);
  157. break;
  158. case MidiMessageType.ControlChange:
  159. var controlChangeMessage = (MidiControlChangeMessage)receivedMidiMessage;
  160. outputMessage.Append(", Channel: ").Append(controlChangeMessage.Channel).Append(", Controller: ").Append(controlChangeMessage.Controller).Append(", Value: ").Append(controlChangeMessage.ControlValue);
  161. break;
  162. case MidiMessageType.ProgramChange:
  163. var programChangeMessage = (MidiProgramChangeMessage)receivedMidiMessage;
  164. outputMessage.Append(", Channel: ").Append(programChangeMessage.Channel).Append(", Program: ").Append(programChangeMessage.Program);
  165. break;
  166. case MidiMessageType.ChannelPressure:
  167. var channelPressureMessage = (MidiChannelPressureMessage)receivedMidiMessage;
  168. outputMessage.Append(", Channel: ").Append(channelPressureMessage.Channel).Append(", Pressure: ").Append(channelPressureMessage.Pressure);
  169. break;
  170. case MidiMessageType.PitchBendChange:
  171. var pitchBendChangeMessage = (MidiPitchBendChangeMessage)receivedMidiMessage;
  172. outputMessage.Append(", Channel: ").Append(pitchBendChangeMessage.Channel).Append(", Bend: ").Append(pitchBendChangeMessage.Bend);
  173. break;
  174. case MidiMessageType.SystemExclusive:
  175. var systemExclusiveMessage = (MidiSystemExclusiveMessage)receivedMidiMessage;
  176. outputMessage.Append(", ");
  177. // Read the SysEx bufffer
  178. var sysExDataReader = DataReader.FromBuffer(systemExclusiveMessage.RawData);
  179. while (sysExDataReader.UnconsumedBufferLength > 0)
  180. {
  181. byte byteRead = sysExDataReader.ReadByte();
  182. // Pad with leading zero if necessary
  183. outputMessage.Append(byteRead.ToString("X2")).Append(" ");
  184. }
  185. break;
  186. case MidiMessageType.MidiTimeCode:
  187. var timeCodeMessage = (MidiTimeCodeMessage)receivedMidiMessage;
  188. outputMessage.Append(", FrameType: ").Append(timeCodeMessage.FrameType).Append(", Values: ").Append(timeCodeMessage.Values);
  189. break;
  190. case MidiMessageType.SongPositionPointer:
  191. var songPositionPointerMessage = (MidiSongPositionPointerMessage)receivedMidiMessage;
  192. outputMessage.Append(", Beats: ").Append(songPositionPointerMessage.Beats);
  193. break;
  194. case MidiMessageType.SongSelect:
  195. var songSelectMessage = (MidiSongSelectMessage)receivedMidiMessage;
  196. outputMessage.Append(", Song: ").Append(songSelectMessage.Song);
  197. break;
  198. case MidiMessageType.TuneRequest:
  199. var tuneRequestMessage = (MidiTuneRequestMessage)receivedMidiMessage;
  200. break;
  201. case MidiMessageType.TimingClock:
  202. var timingClockMessage = (MidiTimingClockMessage)receivedMidiMessage;
  203. break;
  204. case MidiMessageType.Start:
  205. var startMessage = (MidiStartMessage)receivedMidiMessage;
  206. break;
  207. case MidiMessageType.Continue:
  208. var continueMessage = (MidiContinueMessage)receivedMidiMessage;
  209. break;
  210. case MidiMessageType.Stop:
  211. var stopMessage = (MidiStopMessage)receivedMidiMessage;
  212. break;
  213. case MidiMessageType.ActiveSensing:
  214. var activeSensingMessage = (MidiActiveSensingMessage)receivedMidiMessage;
  215. break;
  216. case MidiMessageType.SystemReset:
  217. var systemResetMessage = (MidiSystemResetMessage)receivedMidiMessage;
  218. break;
  219. case MidiMessageType.None:
  220. throw new InvalidOperationException();
  221. default:
  222. break;
  223. }
  224. // Use the Dispatcher to update the messages on the UI thread
  225. await Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
  226. {
  227. // Skip TimingClock and ActiveSensing messages to avoid overcrowding the list. Commment this check out to see all messages
  228. if ((receivedMidiMessage.Type != MidiMessageType.TimingClock) && (receivedMidiMessage.Type != MidiMessageType.ActiveSensing))
  229. {
  230. this.inputDeviceMessages.Items.Add(outputMessage + "\n");
  231. this.inputDeviceMessages.ScrollIntoView(this.inputDeviceMessages.Items[this.inputDeviceMessages.Items.Count - 1]);
  232. this.rootPage.NotifyUser("Message received successfully!", NotifyType.StatusMessage);
  233. }
  234. });
  235. }
  236. }
  237. }