Remarque
L’accès à cette page requiert une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page requiert une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article explique comment énumérer les appareils MIDI (Musical Instrument Digital Interface) et envoyer et recevoir des messages MIDI à partir d’une application WinUI. Windows prend en charge le MIDI via USB (périphériques conformes à la classe et la plupart des pilotes propriétaires), le MIDI via Bluetooth LE et, via des produits tiers disponibles gratuitement, le MIDI via Ethernet et le MIDI routé.
Créer une classe utilitaire de surveillance des appareils
L’espace de noms Windows.Devices.Enumeration fournit le DeviceWatcher, qui peut informer votre application si des périphériques sont ajoutés au système ou supprimés de celui-ci, ou si les informations concernant un périphérique sont mises à jour. Étant donné que les applications compatibles MIDI sont généralement intéressées par les appareils d’entrée et de sortie, cet exemple crée une classe d’assistance qui implémente le modèle DeviceWatcher , afin que le même code puisse être utilisé pour les appareils d’entrée MIDI et de sortie MIDI, sans avoir besoin de duplication.
Ajoutez une nouvelle classe à votre projet pour servir d’observateur de périphérique. Dans cet exemple, la classe est nommée MidiDeviceWatcher. Le reste du code de cette section est utilisé pour implémenter la classe d’assistance.
Ajoutez des variables membres à la classe :
- Objet DeviceWatcher qui surveillera les modifications de l’appareil.
- Chaîne de sélection de périphérique qui contiendra, pour une instance, la chaîne de sélection du port d’entrée MIDI et, pour une autre instance, la chaîne de sélection du port de sortie MIDI.
- Contrôle ListBox qui sera rempli avec les noms des appareils disponibles.
- Un DispatcherQueue nécessaire pour mettre à jour l’interface utilisateur depuis un fil d’exécution autre que le fil d’exécution de l’interface utilisateur.
DeviceWatcher deviceWatcher;
string deviceSelectorString;
ListBox deviceListBox;
DispatcherQueue dispatcherQueue;
Ajoutez une propriété DeviceInformationCollection utilisée pour accéder à la liste actuelle des appareils en dehors de la classe d’assistance.
public DeviceInformationCollection? DeviceInformationCollection { get; set; }
Dans le constructeur de la classe, l’appelant transmet la chaîne du sélecteur de périphérique MIDI, la ListBox servant à répertorier les périphériques, ainsi que la DispatcherQueue nécessaire à la mise à jour de l’interface utilisateur.
Appelez DeviceInformation.CreateWatcher pour créer une instance de la classe DeviceWatcher, en passant la chaîne du sélecteur de périphérique MIDI.
Inscrivez des gestionnaires pour les gestionnaires d’événements de l’observateur.
public MidiDeviceWatcher(string midiDeviceSelectorString, ListBox midiDeviceListBox, DispatcherQueue dispatcher)
{
deviceListBox = midiDeviceListBox;
dispatcherQueue = dispatcher;
deviceSelectorString = midiDeviceSelectorString;
deviceWatcher = DeviceInformation.CreateWatcher(deviceSelectorString);
deviceWatcher.Added += DeviceWatcher_Added;
deviceWatcher.Removed += DeviceWatcher_Removed;
deviceWatcher.Updated += DeviceWatcher_Updated;
deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
}
DeviceWatcher a les événements suivants :
- Ajouté : déclenché lorsqu’un nouvel appareil est ajouté au système.
- Supprimé : déclenché lorsqu’un appareil est supprimé du système.
- Mise à jour : déclenché lorsque les informations associées à un appareil existant sont mises à jour.
- ÉnumérationCompleted : déclenché lorsque l’observateur a terminé son énumération du type d’appareil demandé.
Dans le gestionnaire d’événements pour chacun de ces événements, une méthode d’assistance, UpdateDevices, est appelée pour mettre à jour listBox avec la liste actuelle des appareils. Étant donné que UpdateDevices met à jour les éléments de l’interface utilisateur et que ces gestionnaires d’événements ne sont pas appelés sur le thread d’interface utilisateur, chaque appel doit être encapsulé dans un appel à DispatcherQueue.TryEnqueue.
private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
{
dispatcherQueue.TryEnqueue(() =>
{
UpdateDevices();
});
}
private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
dispatcherQueue.TryEnqueue(() =>
{
UpdateDevices();
});
}
private void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
{
dispatcherQueue.TryEnqueue(() =>
{
UpdateDevices();
});
}
private void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate args)
{
dispatcherQueue.TryEnqueue(() =>
{
UpdateDevices();
});
}
La méthode d’assistance UpdateDevices appelle DeviceInformation.FindAllAsync et met à jour ListBox avec les noms des appareils retournés, comme décrit précédemment dans cet article.
private async void UpdateDevices()
{
// Get a list of all MIDI devices
this.DeviceInformationCollection = await DeviceInformation.FindAllAsync(deviceSelectorString);
deviceListBox.Items.Clear();
if (!this.DeviceInformationCollection.Any())
{
deviceListBox.Items.Add("No MIDI devices found!");
}
foreach (var deviceInformation in this.DeviceInformationCollection)
{
deviceListBox.Items.Add(deviceInformation.Name);
}
}
Ajoutez des méthodes pour démarrer l’observateur, à l’aide de la méthode Start de l’objet DeviceWatcher et pour arrêter l’observateur, à l’aide de la méthode Stop.
public void StartWatcher()
{
deviceWatcher.Start();
}
public void StopWatcher()
{
deviceWatcher.Stop();
}
Créez un destructeur pour désinscrire les gestionnaires d’événements de l’observateur de périphérique et définir celui-ci sur null.
~MidiDeviceWatcher()
{
deviceWatcher.Added -= DeviceWatcher_Added;
deviceWatcher.Removed -= DeviceWatcher_Removed;
deviceWatcher.Updated -= DeviceWatcher_Updated;
deviceWatcher.EnumerationCompleted -= DeviceWatcher_EnumerationCompleted;
}
Créer des ports MIDI pour envoyer et recevoir des messages
Dans le code-behind de votre fenêtre, déclarez des variables membres destinées à stocker deux instances de la classe utilitaire MidiDeviceWatcher, l’une pour les périphériques d’entrée et l’autre pour les périphériques de sortie.
MidiDeviceWatcher? inputDeviceWatcher;
MidiDeviceWatcher? outputDeviceWatcher;
Déclarez également des variables membres pour les objets de port d’entrée et de sortie MIDI.
MidiInPort? midiInPort;
IMidiOutPort? midiOutPort;
Créez une nouvelle instance des classes d’assistance du moniteur, en lui transmettant la chaîne du sélecteur de périphérique, la ListBox à remplir et l’objet DispatcherQueue. Ensuite, appelez la méthode pour démarrer DeviceWatcher de chaque objet.
Peu après le démarrage de chaque DeviceWatcher , il termine l’énumération des appareils actuels connectés au système et déclenche son événement EnumerationCompleted , ce qui entraîne la mise à jour de chaque ListBox avec les appareils MIDI actuels.
inputDeviceWatcher =
new MidiDeviceWatcher(MidiInPort.GetDeviceSelector(), midiInPortListBox, DispatcherQueue);
inputDeviceWatcher.StartWatcher();
outputDeviceWatcher =
new MidiDeviceWatcher(MidiOutPort.GetDeviceSelector(), midiOutPortListBox, DispatcherQueue);
outputDeviceWatcher.StartWatcher();
Lorsque l’utilisateur sélectionne un élément dans le ListBox d’entrée MIDI, l’événement SelectionChanged est déclenché. Dans le gestionnaire de cet événement, accédez à la propriété DeviceInformationCollection de la classe d’assistance pour obtenir la liste actuelle des appareils. S’il existe des entrées dans la liste, sélectionnez l’objet DeviceInformation avec l’index correspondant à SelectedIndex du contrôle ListBox.
Créez l’objet MidiInPort représentant l’appareil d’entrée sélectionné en appelant MidiInPort.FromIdAsync, passage de la propriété Id de l’appareil sélectionné.
Inscrivez un gestionnaire pour l’événement MessageReceived , qui est déclenché chaque fois qu’un message MIDI est reçu via l’appareil spécifié.
private async void midiInPortListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var deviceInformationCollection = inputDeviceWatcher?.DeviceInformationCollection;
if (deviceInformationCollection == null)
{
return;
}
DeviceInformation devInfo = deviceInformationCollection[midiInPortListBox.SelectedIndex];
if (devInfo == null)
{
return;
}
midiInPort = await MidiInPort.FromIdAsync(devInfo.Id);
if (midiInPort == null)
{
System.Diagnostics.Debug.WriteLine("Unable to create MidiInPort from input device");
return;
}
midiInPort.MessageReceived += MidiInPort_MessageReceived;
}
Lorsque le gestionnaire MessageReceived est appelé, le message est contenu dans la propriété Message de la propriété MidiMessageReceivedEventArgs. Le Type de l’objet de message est une valeur de l’énumération MidiMessageType indiquant le type de message reçu. Les données du message dépendent du type du message. Cet exemple vérifie si le message est un message Note On et, le cas échéant, affiche le canal MIDI, la note et la vélocité du message.
private void MidiInPort_MessageReceived(MidiInPort sender, MidiMessageReceivedEventArgs args)
{
IMidiMessage receivedMidiMessage = args.Message;
System.Diagnostics.Debug.WriteLine(receivedMidiMessage.Timestamp.ToString());
if (receivedMidiMessage.Type == MidiMessageType.NoteOn)
{
System.Diagnostics.Debug.WriteLine(((MidiNoteOnMessage)receivedMidiMessage).Channel);
System.Diagnostics.Debug.WriteLine(((MidiNoteOnMessage)receivedMidiMessage).Note);
System.Diagnostics.Debug.WriteLine(((MidiNoteOnMessage)receivedMidiMessage).Velocity);
}
}
Le gestionnaire SelectionChanged pour le listBox de périphérique de sortie fonctionne de la même façon que le gestionnaire pour les appareils d’entrée, sauf qu’aucun gestionnaire d’événements n’est inscrit.
private async void midiOutPortListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var deviceInformationCollection = outputDeviceWatcher?.DeviceInformationCollection;
if (deviceInformationCollection == null)
{
return;
}
DeviceInformation devInfo = deviceInformationCollection[midiOutPortListBox.SelectedIndex];
if (devInfo == null)
{
return;
}
midiOutPort = await MidiOutPort.FromIdAsync(devInfo.Id);
if (midiOutPort == null)
{
System.Diagnostics.Debug.WriteLine("Unable to create MidiOutPort from output device");
return;
}
}
Une fois l’appareil de sortie créé, vous pouvez envoyer un message en créant un nouveau message IMidiMessage pour le type de message que vous souhaitez envoyer. Dans cet exemple, le message est un NoteOnMessage. La méthode SendMessage de l’objet IMidiOutPort est appelée pour envoyer le message.
byte channel = 0;
byte note = 60;
byte velocity = 127;
IMidiMessage midiMessageToSend = new MidiNoteOnMessage(channel, note, velocity);
midiOutPort.SendMessage(midiMessageToSend);
Lorsque votre application se ferme, veillez à nettoyer les ressources de votre application. Désinscrivez vos gestionnaires d’événements et définissez les objets de port d’entrée MIDI et de port de sortie sur null. Arrêtez les observateurs d’appareils et affectez-leur la valeur null.
inputDeviceWatcher?.StopWatcher();
inputDeviceWatcher = null;
outputDeviceWatcher?.StopWatcher();
outputDeviceWatcher = null;
if (midiInPort != null)
{
midiInPort.MessageReceived -= MidiInPort_MessageReceived;
midiInPort.Dispose();
midiInPort = null;
}
if (midiOutPort != null)
{
midiOutPort.Dispose();
midiOutPort = null;
}
Utilisation du synthétiseur General MIDI intégré de Windows
Lorsque vous énumérez des appareils MIDI de sortie à l’aide de la technique décrite ci-dessus, votre application découvre un appareil MIDI appelé « Microsoft GS Wavetable Synth ». Il s’agit d’un synthétiseur General MIDI intégré que vous pouvez jouer depuis votre application.
Le SDK d’extension UWP pour le midi général (« Microsoft DLS MIDI général pour les applications de Windows universelles ») n’est pas disponible dans les projets WinUI 3. L’ancienne boîte de dialogue Ajouter des extensions de référence > était spécifique à UWP. Toutefois, pour la plupart des scénarios de bureau, le GS Wavetable Synth fonctionne sans le SDK d’extension, car les applications de bureau peuvent accéder directement à la banque audio du gm.dls système. Si vous constatez que la sortie MIDI ne produit aucun son, vérifiez qu’un appareil de sortie MIDI est sélectionné et que votre sortie audio est configurée correctement.
Rubriques connexes
Windows developer