狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

.NET App 與Windows系統(tǒng)媒體控制(SMTC)交互

freeflydom
2024年9月11日 0:36 本文熱度 1095

當你使用Edge等瀏覽器或系統(tǒng)軟件播放媒體時,Windows控制中心就會出現(xiàn)相應的媒體信息以及控制播放的功能,如圖。

    SMTC (SystemMediaTransportControls) 是一個Windows App SDK (舊為UWP) 中提供的一個API,用于與系統(tǒng)媒體交互。接入SMTC的好處在于,將媒體控制和媒體信息共享給系統(tǒng),使用通用的特性(例如接受鍵盤快捷鍵的播放暫停、接受藍牙設備的控制),便于與其它支持SMTC的應用交互等。

   在UWP App中使用它很簡單,只需要調(diào)用SystemMediaTransportControls.GetForCurrentView()方法即可,但是該方法僅限在有效的UWP App中調(diào)用,否則將拋出“Invalid window handle”異常。實際上,在官方文檔中提到所有XXXForCurrentView方法均不適用于UWP App以外的程序調(diào)用。

  這些 XxxForCurrentView 方法對 ApplicationView 類型具有隱式依賴關系,桌面應用不支持該類型。由于桌面應用不支持 ApplicationView,因此也不支持任何 XxxForCurrentView 方法。

  此外官方文檔還給出一個可替代的接口ISystemMediaTransportControlsInterop,然而這個接口在給的SDK中有保護性,無法訪問。

  至此,直接創(chuàng)建SMTC的方法走不通。但是我發(fā)現(xiàn)一個奇怪的地方,UWP提供的在Windows.Media.Playback命名空間下的MediaPlayer可以和SMTC自動集成,并且可以通過SystemMediaTransportControls屬性直接拿到SMTC對象。MediaPlayer內(nèi)部通過某種COM組件直接創(chuàng)建了該NativeObject,而沒有走API提供的GetForCurrentView或FromAbi方法。也就是說,SMTC組件其實不需要使用合法的UWP Window句柄來創(chuàng)建,只不過可能為了某些特性而加上了該限制(后文將提到)。幸運的是,MediaPlayer幫我們繞過了這點。

  下文講解手動與SMTC交互而不是直接使用MediaPlayer進行播放,你的項目可能已經(jīng)有了其它的解碼器(如WPF版本的MediaPlayer、Bass.Net解碼器、NAudio等),則只需要將交互部分接入SMTC而不更換解碼器。

  文末提供了我封裝好的SMTCCreator和SMTCListener,可以直接使用。

一、引用WinRT API到項目

  最便捷的方法是直接修改目標框架到win10,這樣就能自動引入WinRT API:

<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>

  或者一些其他的方法,可以參考這篇博客:如何在WPF中調(diào)用Windows 10/11 API(UWP/WinRT) - zhaotianff - 博客園 (cnblogs.com)

二、通過MediaPlayer獲取SMTC對象

using Windows.Media;

using Windows.Storage.Streams;

...

private readonly Windows.Media.Playback.MediaPlayer _player = new();

private readonly SystemMediaTransportControls _smtc;

...

//先禁用系統(tǒng)播放器的命令

_player.CommandManager.IsEnabled = false;

//直接創(chuàng)建SystemMediaTransportControls對象被平臺限制,神奇的是MediaPlayer對象可以創(chuàng)建該NativeObject

_smtc = _player.SystemMediaTransportControls;

//啟用smtc以進行自定義

_smtc.IsEnabled = true;

  拿到SMTC對象之后的操作與UWP中無異,這里簡單看一下:

1.設置可交互性

_smtc.IsPlayEnabled = true;

_smtc.IsPauseEnabled = true;

_smtc.IsNextEnabled = true;

_smtc.IsPreviousEnabled = true;

2.設置媒體信息

var updater = _smtc.DisplayUpdater;

updater.AppMediaId = "xxx"; //用于區(qū)分不同來源的媒體

updater.Type = MediaPlaybackType.Music; //必須指定媒體類型否則拋異常

updater.MusicProperties.Title = “Title”;//標題

/*...省略相同的字段設置...*/

updater.Thumbnail = RandomAccessStreamReference.CreateFromUri(new Uri(ImgUrl));//設置封面圖

updater.Update();//最后調(diào)用以生效

播放狀態(tài)需要單獨設置:

_smtc.PlaybackStatus = MediaPlaybackStatus.Playing; //Paused \ Stopped

//直接設置無需更新


3.響應SMTC交互

_smtc.ButtonPressed += _smtc_ButtonPressed;

...

 private void _smtc_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)

        {

            switch(args.Button)

            {

                case SystemMediaTransportControlsButton.Play:

                    //Play

                    break;

                case SystemMediaTransportControlsButton.Pause:

                    //Pause

                    break;

                case SystemMediaTransportControlsButton.Next:

                    //Next

                    break;

                case SystemMediaTransportControlsButton.Previous:

                    //Previous

                    break;

            }

        }

注意,文中所有SMTC的事件均由系統(tǒng)觸發(fā),意味著非同一線程,需要用Dispatcher來操作UI

三、獲取和控制系統(tǒng)媒體

  好消息是,負責這部分的模塊GlobalSystemMediaTransportControlsSession公開可以任意使用,不受UWP平臺限制。

1.獲取媒體信息

var gsmtcsm = await GlobalSystemMediaTransportControlsSessionManager.RequestAsync();//獲取SMTC會話管理器

gsmtcsm.CurrentSessionChanged += xxx; //當前會話改變或退出時發(fā)生,微軟對CurrentSession的解釋是用戶可能最希望控制的媒體會話,實測為Windows控制中心頂部顯示的媒體,當有多個媒體時用戶可以在此選擇切換

...

var session = gsmtcsm.GetCurrentSession();

if(session == null)

    return; //當前沒有注冊的SMTC會話


//接下來操作session即可,下面僅提供參考信息


//媒體信息改變時發(fā)生,奇怪的是這些事件提供的參數(shù)e并沒有任何信息

session.MediaPropertiesChanged += async (sender, e)=>{

    //觸發(fā)事件時主動拉取信息

    var info = await _globalSMTCSession.TryGetMediaPropertiesAsync();

};

//播放狀態(tài)改變時發(fā)生

session.PlaybackInfoChanged +=(sender,e)=>{

    var status = globalSMTCSession.GetPlaybackInfo().PlaybackStatus;

};

2.控制媒體播放

await session.TryPauseAsync();

await session.TryPlayAsync();

await session.TrySkipPreviousAsync();

await session.TrySkipNextAsync();

四、一些奇怪的地方

1.無法顯示媒體來源,并且不會清空上一個來源的信息

  可能是因為沒有提供合法的UWP句柄,Windows雖然能確定是哪個exe調(diào)用的SMTC,但是拒絕直接顯示exe的信息。邏輯上來說這個來源信息會被空覆蓋掉,但是并沒有。

 2.信息更新不一致和延時

   系統(tǒng)顯示的會話以及提供GlobalSMTCSessionMng.獲取的信息有時會不一致,二者都有可能和應用真實在播放的不一致,后者獲取的封面圖有時也會不一致。此外,MusicProperty的更新有時并不會實時反饋到GlobalSMTCSession的Changed事件,我測試的時候當系統(tǒng)內(nèi)存爆滿(98% 我開了一堆瀏覽器標簽頁和4個vs)的時候,更新丟失的概率在70%左右,而資源充足時可以做到幾乎即時更新。

3.暫未實現(xiàn)點擊跳轉(zhuǎn)到App

  正統(tǒng)UWP App的SMTC會話是可以點擊跳轉(zhuǎn)到App播放界面的,但是我并沒有找到相關的事件。

4.奇怪的MediaId

  Windows系統(tǒng)似乎通過這個來區(qū)分不同的媒體來源(明明可以獲得調(diào)用者- -),神奇的是如果你為兩個應用設置了同樣的MediaId,那么只有兩個都關閉時,SMTC會話才會釋放。此外通過GlobalSMTCSession.SourceAppUserModelId并不能獲得你設置的MediaId,而是調(diào)用者的文件名"xxx.exe"。

五、使用我封裝的庫

  Demo和庫已經(jīng)開源:TwilightLemon/MediaTest: .NET 8 WPF using SMTC (github.com)

   簡單地將現(xiàn)有的解碼器接入SMTC:

SMTCCreator? _smtcCreator = null;

...

 _smtcCreator ??= new SMTCCreator("MediaTest");

//修改播放狀態(tài)

_smtcCreator.SetMediaStatus(SMTCMediaStatus.Playing);

//設置媒體信息

_smtcCreator.Info.SetAlbumTitle("AlbumTitle")

                    .SetArtist("Taylor Swift")

                    .SetTitle("Dancing With Our Hands Tied")

                    .SetThumbnail("https://y.qq.com/music/photo_new/T002R300x300M000003OK4yP2MBOip_1.jpg?max_age=2592000")

                    .Update();

//注冊交互響應

_smtcCreator.PlayOrPause += _smtcCreator_PlayOrPause;

_smtcCreator.Previous += _smtcCreator_Previous;

_smtcCreator.Next += _smtcCreator_Next;//合適的時候調(diào)用釋放資源_smtcCreator.Dispose();

簡單地控制系統(tǒng)媒體:

SMTCListener _smtcListener = null;

...

_smtcListener = await SMTCListener.CreateInstance();

_smtcListener.MediaPropertiesChanged += _smtcListener_MediaPropertiesChanged;

_smtcListener.PlaybackInfoChanged += _smtcListener_PlaybackInfoChanged;

_smtcListener.SessionExited += _smtcListener_SessionExited;

...

//媒體退出

 private void _smtcListener_SessionExited(object? sender, EventArgs e) { }


//播放狀態(tài)改變

private void _smtcListener_PlaybackInfoChanged(object? sender, EventArgs e)

{

    Dispatcher.Invoke(() =>

    {

        var info = _smtcListener.GetPlaybackStatus();

        if (info == null) return;

        StatusTb.Text = info.ToString();

    });

}

//媒體信息改變

private void _smtcListener_MediaPropertiesChanged(object? sender, EventArgs e)

{

    Dispatcher.Invoke(async () =>

    {

        var info = await _smtcListener.GetMediaInfoAsync();

        if (info == null) return;

        TitleTb.Text = info.Title;

        ArtistTb.Text = info.Artist;

        AlbumTitleTb.Text = info.AlbumTitle;

        //獲取封面圖的方法

        if (info.Thumbnail != null)

        {

            var img = new BitmapImage();

            img.BeginInit();

            img.StreamSource = (await info.Thumbnail.OpenReadAsync()).AsStream();

            img.EndInit();

            ThumbnailImg.Source = img;

        }

    });

}

...

//控制播放

await _smtcListener.Previous();

await _smtcListener.Next();

await _smtcListener.Pause();

await _smtcListener.Play();

六、寫在最后

  參考資料:

1)SystemMediaTransportControls 類 (Windows.Media) - Windows UWP applications | Microsoft Learn

2)桌面應用中不支持 Windows 運行時 API - Windows 應用 |Microsoft學習 --- Windows Runtime APIs not supported in desktop apps - Windows apps | Microsoft Learn

3)GlobalSystemMediaTransportControlsSessionManager Class (Windows.Media.Control) - Windows UWP applications | Microsoft Learn

 

  打個小廣告,我的頂部欄項目正在開發(fā)中,現(xiàn)已集成SMTC和眾多小功能,歡迎支持:TwilightLemon/MyToolBar: 為Surface Pro而生的頂部工具欄 支持觸控和筆快捷方式 (github.com)

   全局媒體播放控制:

   未來將支持更多插件:

 

  本作品采用 知識共享署名-非商業(yè)性使用-相同方式共享 4.0 國際許可協(xié)議 進行許可。歡迎轉(zhuǎn)載、使用、重新發(fā)布,但務必保留文章署名TwilightLemon,不得用于商業(yè)目的,基于本文修改后的作品務必以相同的許可發(fā)布。



該文章在 2024/9/13 9:01:21 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務費用、相關報表等業(yè)務管理,結(jié)合碼頭的業(yè)務特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved