当 UWP 进入后台时保持 MiDi 输出播放

Keep MiDi output playing when UWP goes into background

我正在尝试构建一个能够在后台 运行 的节拍器应用程序。作为起点,我决定创建一些简单的东西,一个 class 有一个定时器(节拍器本身),一个 class 负责获取 MIDI 输出设备和一个 class 来播放声音。我对如何在后台制作这个 运行 有困难。此外,还有一个问题是节拍器需要在单击应用程序按钮时执行(在主进程中)。

节拍器Class:

public class Metronome
{
    private DispatcherTimer timer = new DispatcherTimer();

    private MidiDeviceSelector deviceSelector = new MidiDeviceSelector();

    private void TimerStart()
    {
        timer.Start();
        timer.Tick += timer_Tick;
    }

    private void timer_Tick(object sender, object e)
    {
        AudioPlayback.Beep1();
    }

    public void Start(int bpm)
    {
        double interval = (double)60.000f / (bpm);
        timer.Interval = TimeSpan.FromSeconds(interval);

        TimerStart();
    }

    public void Stop()
    {
        timer.Stop();
    }
}

MidiDeviceSelector:

class MidiDeviceSelector
{
    public MidiDeviceSelector()
    {
        GetOutputMidiDevice();
    }

    public async void GetOutputMidiDevice()
    {
        IMidiOutPort currentMidiOutputDevice;

        DeviceInformation devInfo;
        DeviceInformationCollection devInfoCollection;

        string devInfoId;

        devInfoCollection = await DeviceInformation.FindAllAsync(MidiOutPort.GetDeviceSelector());

        if (devInfoCollection == null)
        {
            //notify the user that any device was found.
            System.Diagnostics.Debug.WriteLine("Any device was found.");
        }

        devInfo = devInfoCollection[0];

        if (devInfo == null)
        {
            //Notify the User that the device not found
            System.Diagnostics.Debug.WriteLine("Device not found.");
        }


        devInfoId = devInfo.Id.ToString();
        currentMidiOutputDevice = await MidiOutPort.FromIdAsync(devInfoId);

        if (currentMidiOutputDevice == null)
        {
            //Notify the User that wasn't possible to create MidiOutputPort for the device.
            System.Diagnostics.Debug.WriteLine("It was not possible to create the OutPort for the device.");
        }

        MidiDevice.midiDevice = currentMidiOutputDevice;
    }

Class 持有 MidiDevice:

class MidiDevice
{
    public static IMidiOutPort midiDevice; //Bad practice i know.
}

Class 播放 "toc" 声音:

class AudioPlayback
{
    static IMidiMessage beep1 = new MidiNoteOnMessage(9, 76, 90);

    //static IMidiOutPort midiOutputDevice = (IMidiOutPort)MidiDeviceSelector.GetOutputMidiDevice();


    public static void Beep1()
    {
        try
        {
            MidiDevice.midiDevice.SendMessage(beep1);
        }
        catch (Exception e)
        {
            System.Diagnostics.Debug.WriteLine(e.Message);
        }
    }
}

每个 class 都包含在不同的文件中。如您所见,这是一个非常简单的代码,如果您看到任何糟糕的编程习惯,我深表歉意,我没有太多经验。

我正在看文档,但是,我没有成功。如何在后台注册一个 activity 并与应用程序的用户界面进行交互(一个用于停止和启动节拍器的按钮)。

抱歉英语不好,不是我的母语。

谢谢。

要使此方案有效,您需要添加两件事:

  1. 添加 "backgroundMediaPlayback" 功能,如下所述:https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/background-audio

  2. 由于您使用的是 MiDI API,因此您需要明确集成 SystemMediaTransportControls 以防止在最小化时静音

我已经更新了您的重现样本并验证了它在添加这两个东西后可以正常工作。

在此分享给大家参考:https://1drv.ms/u/s!AovTwKUMywTNl9QJTeecnDzCf0WWyQ