Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek ukazuje, jak vytvořit výčet zařízení MIDI (Musical Instrument Digital Interface) a odesílat a přijímat zprávy MIDI z aplikace WinUI. Windows podporuje MIDI přes USB (zařízení kompatibilní se standardní třídou USB a většinu proprietárních ovladačů), MIDI přes Bluetooth LE a prostřednictvím volně dostupných produktů třetích stran také MIDI přes Ethernet a routované MIDI.
Vytvořte pomocnou třídu pro sledování zařízení
Obor názvů Windows.Devices.Enumeration poskytuje DeviceWatcher, který může vaši aplikaci upozornit, když jsou do systému přidána nebo z něj odebrána zařízení nebo když jsou aktualizovány informace o zařízení. Vzhledem k tomu, že aplikace s podporou MIDI mají obvykle zájem o vstupní i výstupní zařízení, tento příklad vytvoří pomocnou třídu, která implementuje model DeviceWatcher , takže stejný kód lze použít pro vstupní i výstupní zařízení MIDI, aniž by bylo nutné duplikovat.
Přidejte do projektu novou třídu, která bude sloužit ke sledování zařízení. V tomto příkladu má třída název MidiDeviceWatcher. Zbytek kódu v této části slouží k implementaci pomocné třídy.
Přidejte do třídy některé členské proměnné:
- Objekt DeviceWatcher, který bude monitorovat změny zařízení.
- Řetězec selektoru zařízení, který bude v jednom případě obsahovat řetězec selektoru vstupního portu MIDI a v jiném případě řetězec selektoru výstupního portu MIDI.
- Ovládací prvek ListBox , který se naplní názvy dostupných zařízení.
- DispatcherQueue, která se vyžaduje k aktualizaci uživatelského rozhraní z jiného vlákna než z vlákna UI.
DeviceWatcher deviceWatcher;
string deviceSelectorString;
ListBox deviceListBox;
DispatcherQueue dispatcherQueue;
Přidejte vlastnost DeviceInformationCollection, která se používá pro přístup k aktuálnímu seznamu zařízení mimo pomocnou třídu.
public DeviceInformationCollection? DeviceInformationCollection { get; set; }
V konstruktoru třídy volající předá řetězec pro výběr zařízení MIDI, ListBox pro zobrazení zařízení a DispatcherQueue, která je potřeba k aktualizaci uživatelského rozhraní.
Zavolejte DeviceInformation.CreateWatcher k vytvoření nové instance DeviceWatcher třídy, která předává řetězec selektoru zařízení MIDI.
Zaregistrujte obslužné rutiny pro události sledovače.
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 má následující události:
- Přidáno – vyvolána při přidání nového zařízení do systému.
- Odebráno - Vyvolá se při odebrání zařízení ze systému.
- Aktualizováno – Vyvolá se při aktualizaci informací přidružených k existujícímu zařízení.
- EnumerationCompleted – vyvolána, když sledovací objekt dokončí výčet požadovaného typu zařízení.
V obslužné rutině události pro každou z těchto událostí je volána pomocná metoda UpdateDevices, která aktualizuje ListBox s aktuálním seznamem zařízení. Protože UpdateDevices aktualizuje prvky uživatelského rozhraní a tyto obslužné rutiny událostí nejsou volány ve vlákně uživatelského rozhraní, každé volání musí být zabaleno do volání 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();
});
}
Pomocná metoda UpdateDevices volá DeviceInformation.FindAllAsync a aktualizuje ListBox názvy vrácených zařízení, jak je popsáno výše v tomto článku.
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);
}
}
Přidejte metody pro spuštění sledovacího programu, pomocí metody Start objektu DeviceWatcher a zastavte sledovací proces pomocí metody Stop.
public void StartWatcher()
{
deviceWatcher.Start();
}
public void StopWatcher()
{
deviceWatcher.Stop();
}
Zadejte destruktor, který zruší registraci obslužných rutin událostí sledovacího prvku a nastaví sledovací proces zařízení na hodnotu null.
~MidiDeviceWatcher()
{
deviceWatcher.Added -= DeviceWatcher_Added;
deviceWatcher.Removed -= DeviceWatcher_Removed;
deviceWatcher.Updated -= DeviceWatcher_Updated;
deviceWatcher.EnumerationCompleted -= DeviceWatcher_EnumerationCompleted;
}
Vytvoření portů MIDI pro odesílání a příjem zpráv
V kódu za oknem deklarujte členské proměnné, které mají obsahovat dvě instance pomocné třídy MidiDeviceWatcher , jednu pro vstupní zařízení a jednu pro výstupní zařízení.
MidiDeviceWatcher? inputDeviceWatcher;
MidiDeviceWatcher? outputDeviceWatcher;
Deklarujte také členské proměnné pro vstupní a výstupní objekty portu MIDI.
MidiInPort? midiInPort;
IMidiOutPort? midiOutPort;
Vytvořte novou instanci pomocných tříd watcheru s předáním řetězce selektoru zařízení, objektu ListBox, který se má vyplnit, a objektu DispatcherQueue. Potom zavolejte metodu, která spustí DeviceWatcher každého objektu.
Krátce po spuštění jednotlivých zařízení DeviceWatcher dokončí výčet aktuálních zařízení připojených k systému a vyvolá událost EnumerationCompleted , která způsobí aktualizaci jednotlivých zařízení ListBox s aktuálními zařízeními MIDI.
inputDeviceWatcher =
new MidiDeviceWatcher(MidiInPort.GetDeviceSelector(), midiInPortListBox, DispatcherQueue);
inputDeviceWatcher.StartWatcher();
outputDeviceWatcher =
new MidiDeviceWatcher(MidiOutPort.GetDeviceSelector(), midiOutPortListBox, DispatcherQueue);
outputDeviceWatcher.StartWatcher();
Když uživatel vybere položku ve vstupním poli ListBox MIDI, vyvolá se událost SelectionChanged . V obsluze této události přistupujte k vlastnosti pomocné třídy DeviceInformationCollection, abyste získali aktuální seznam zařízení. Pokud jsou v seznamu položky, vyberte DeviceInformation objekt s indexem odpovídající ListBox ovládacího prvku SelectedIndex.
Vytvořte objekt MidiInPort představující vybrané vstupní zařízení voláním MidiInPort.FromIdAsync; předání vlastnosti Id vybraného zařízení.
Zaregistrujte obslužnou rutinu události MessageReceived , která se vyvolá při každém přijetí zprávy MIDI přes zadané zařízení.
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;
}
Když je volána obslužná rutina MessageReceived zpráva je obsažena ve vlastnosti Message vlastnosti MidiMessageReceivedEventArgs. Type objektu zprávy je hodnota z MidiMessageType označující typ přijaté zprávy. Data zprávy závisí na typu zprávy. Tento příklad zkontroluje, jestli je zpráva poznámkou ke zprávě, a pokud ano, vypíše midi kanál, poznámku a rychlost zprávy.
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);
}
}
Obslužná rutina SelectionChanged pro výstupní zařízení ListBox funguje stejně jako obslužná rutina pro vstupní zařízení s výjimkou žádné obslužné rutiny událostí není registrována.
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;
}
}
Po vytvoření výstupního zařízení můžete odeslat zprávu vytvořením nového IMidiMessage pro typ zprávy, kterou chcete odeslat. V tomto příkladu je zpráva NoteOnMessage. K odeslání zprávy se volá metoda SendMessageIMidiOutPort objekt.
byte channel = 0;
byte note = 60;
byte velocity = 127;
IMidiMessage midiMessageToSend = new MidiNoteOnMessage(channel, note, velocity);
midiOutPort.SendMessage(midiMessageToSend);
Po zavření aplikace nezapomeňte vyčistit prostředky aplikace. Zrušte registraci obslužných rutin událostí a nastavte objekty vstupního a výstupního portu MIDI na hodnotu null. Zastavte sledovací moduly zařízení a nastavte je na hodnotu 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;
}
Použití integrovaného syntetizátoru General MIDI v systému Windows
Když vytvoříte výčet výstupních zařízení MIDI pomocí výše popsané techniky, vaše aplikace zjistí zařízení MIDI s názvem "Microsoft GS Wavetable Synth". Jedná se o integrovaný syntetizátor General MIDI, který si můžete přehrát z aplikace.
Rozšiřující sada SDK UWP pro General MIDI („Microsoft General MIDI DLS for Universal Windows Apps“) není v projektech WinUI 3 k dispozici. Původní dialogové okno Přidat referenční > rozšíření bylo specifické pro UPW. Ve většině desktopových scénářů ale GS Wavetable Synth funguje bez sady SDK rozšíření, protože desktopové aplikace mají přímý přístup ke zvukové bance systému gm.dls . Pokud zjistíte, že výstup MIDI nevygeneruje žádný zvuk, ověřte, že je vybrané výstupní zařízení MIDI a že je výstup zvuku správně nakonfigurovaný.
Příbuzná témata
Windows developer