C++/winRT:使用 MediaPlayer API

问题描述 投票:0回答:1

我正在尝试以最简单的方式使用MediaPlayer API。我想做的就是播放音频文件(并且可能在完成后收到通知)。

不幸的是,这迫使我使用我不太熟悉的winRT和异步操作。因此,我对打开文件并将其传递到媒体播放器的简单任务感到绝望。我投入了很多时间并尝试了各种方法,但仍然不起作用。

这是我目前得到的:

using namespace winrt::Windows;
auto async = Storage::StorageFile::GetFileFromPathAsync(filename);
async.Completed([] (auto const & res, Foundation::AsyncStatus const status) {
    if (status == Foundation::AsyncStatus::Completed) {
        auto source = Media::Core::MediaSource::CreateFromStorageFile(res.GetResults());
        Media::Playback::MediaPlayer player;
        player.Source(source);
        player.Play();
    }
});

请注意,我实际上并不关心异步操作。在这种情况下,等待一秒钟打开文件就可以了。但是在调试版本和 IIRC 中简单的 async.get() 或 wait_for() 断言可能会在发布版本中产生问题。

当上面的代码编译并运行时,播放永远不会开始。观察全局 Windows 错误变量,我从 MediaSource::CreateFromStorageFile() 收到各种错误,具体取决于我尝试打开的文件:1008(“尝试引用不存在的令牌。”)和 14007 (“在任何活动的激活上下文中都找不到请求的查找密钥。”)。非常神秘。

所以我的问题实际上是双重的:我是否正确打开文件,或者是否有更好/更简单的方法?这些错误是怎么回事以及如何成功打开本地音频文件?

更新: 我对所有 winRT 异步内容感到非常困惑,以至于在上面的代码中犯了一个愚蠢的错误。当我在启动 MediaPlayer 后没有立即将其扔掉时,播放实际上可以正常工作......并且尽管存在一些神秘的错误,它仍然可以工作。

我仍然保留这个问题,因为我仍然对打开文件的正确方法感兴趣。

media-player c++-winrt winrt-async
1个回答
0
投票

C++/WinRT 中的异步是通过协程完成的:

winrt::fire_and_forget
Control::Button_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
    auto file = co_await Storage::StorageFile::GetFileFromPathAsync(filename);
    auto source = Media::Core::MediaSource::CreateFromStorageFile(file);
    Media::Playback::MediaPlayer player;
    player.Source(source);
    player.Play();
    co_await winrt::resume_after(std::chrono::seconds(10));
    // player will go out of scope now and stop playing
}

有时您可能想阻止。只需移至后台线程即可:

winrt::fire_and_forget
Control::Button_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
    co_await winrt::resume_background();
    // now we can block
    auto file = Storage::StorageFile::GetFileFromPathAsync(filename).get();
}

或者没有协程

void Control::Button_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
    winrt::Windows::System::Threading::ThreadPool::RunAsync([](auto&&...){
        // now we can block
        auto file = Storage::StorageFile::GetFileFromPathAsync(filename).get();
    });
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.