Giter VIP home page Giter VIP logo

dubyadude / windowsmediacontroller Goto Github PK

View Code? Open in Web Editor NEW
122.0 4.0 9.0 406 KB

Allows developers to more easily get information from and interact with the Windows 10/11 OS media interface. (Also referred to Windows System Media Transport Controls (SMTC))

Home Page: https://nuget.org/packages/Dubya.WindowsMediaController

License: MIT License

C# 100.00%
music music-player windows-10 windows-11 windows c-sharp dotnet mtc csharp nuget

windowsmediacontroller's Introduction

Windows Media Controller

NuGet

This repository provides a wrapper for developers to more easily get information from and interact with the Windows 10/11 OS media interface (Also referred to Windows System Media Transport Controls (SMTC)).

Windows 10 Media Interface

This allows for a better understanding and control of the Media Sessions and can have many different applications. Some features include:

  • Control playback on individual Media Sessions (Spotify, Chrome, etc)
  • Get media information of currently playing (Song, Author, Thumbnail, etc)

Requirements

  • Windows 10 (Build 17763+) or Windows 11
  • The ability to talk to Windows Runtime. (In a majority of cases, this will not be an issue)
  • .NET Framework 4.6.1+ or .NET 5+
  • May need to be able to interact with the desktop
    • In situations such as being run through Windows Task Scheduler, the application will need an active window to start with, you can hide it afterward.

NET Framework:

For .NET Framework, I've seen people encountering issues with how the package gets imported. This is caused by using an older format of .NET projects (you can see the newer format being used in Sample.CMD). If you have this issue, add the package by adding this to the .csproj file.
(replacing '2.5.5' with the preferred NuGet version)

<ItemGroup>
  <PackageReference Include="Dubya.WindowsMediaController">
    <Version>2.5.5</Version>
  </PackageReference>
</ItemGroup>

NET 5+:

NET 5 brought along a lot of changes in how WinRT is meant to be accessed. More of that info can be found here.

If you're doing a GUI app you should be good to go and be able to just import the lib.

However, for other cases, your TargetFramework in the .csproj file needs to be modified before importing the package.
(replacing net6.0 with desired .NET version)

<TargetFramework>net6.0-windows10.0.22000.0</TargetFramework>

How To Use

Initialization:

mediaManager = new MediaManager();

mediaManager.OnAnySessionOpened += MediaManager_OnAnySessionOpened;
mediaManager.OnAnySessionClosed += MediaManager_OnAnySessionClosed;
mediaManager.OnFocusedSessionChanged += MediaManager_OnFocusedSessionChanged;
mediaManager.OnAnyMediaPropertyChanged += MediaManager_OnAnyMediaPropertyChanged;
mediaManager.OnAnyPlaybackStateChanged += MediaManager_OnAnyPlaybackStateChanged;
mediaManager.OnAnyTimelinePropertyChanged += MediaManager_OnAnyTimelinePropertyChanged;

mediaManager.Start();
OR
await mediaManager.StartAsync();

Class Structure:

MediaManager:

ReadOnlyDictionary<string, MediaSession> CurrentMediaSessions;
bool IsStarted { get; }
GlobalSystemMediaTransportControlsSessionManager WindowsSessionManager { get; }

void Start();
async Task StartAsync();
MediaSession GetFocusedSession();
void ForceUpdate();

delegate void OnAnySessionOpened(MediaManager.MediaSession session);
delegate void OnAnySessionClosed(MediaManager.MediaSession session);
delegate void OnFocusedSessionChanged(MediaManager.MediaSession session);
delegate void OnAnyMediaPropertyChanged(MediaManager.MediaSession sender, GlobalSystemMediaTransportControlsSessionMediaProperties args);
delegate void OnAnyPlaybackStateChanged(MediaManager.MediaSession sender, GlobalSystemMediaTransportControlsSessionPlaybackInfo args);
delegate void OnAnyTimelinePropertyChanged(MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties timelineProperties);

MediaManager.MediaSession:

readonly string Id;
GlobalSystemMediaTransportControlsSession ControlSession { get; }

delegate void OnSessionClosed(MediaManager.MediaSession session);
delegate void OnMediaPropertyChanged(MediaManager.MediaSession sender, GlobalSystemMediaTransportControlsSessionMediaProperties args);
delegate void OnPlaybackStateChanged(MediaManager.MediaSession sender, GlobalSystemMediaTransportControlsSessionPlaybackInfo args);
delegate void OnTimelinePropertyChanged(MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties timelineProperties);

Getting Some Info:

  • Getting PlaybackInfo (Seeing what actions are available/Is paused or playing, etc)

    • Returns: GlobalSystemMediaTransportControlsSessionPlaybackInfo
    • mediaSession.ControlSession.GetPlaybackInfo()
  • Getting current MediaProperties (Currently playing title, author, thumbnail, etc)

    • Returns: GlobalSystemMediaTransportControlsSessionMediaProperties
    • await mediaSession.ControlSession.TryGetMediaPropertiesAsync()

Useful Microsoft Documentations:

Samples

  • Sample.CMD - A very barebone console application for developers to get a feel of how their use-case might act.

Sample.CMD

  • Sample.UI - A WPF media controller

Sample.UI

Credit

  • Luca Marini (Stack Overflow) - Helped me understand the Windows API
  • Google (materialui) - Utilizing their play icon to create our icon
  • Kinnara (ModernWpf) - Utilized the ModernWpf library to create the UI sample

windowsmediacontroller's People

Contributors

dubyadude avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

windowsmediacontroller's Issues

Optimization issue with CurrentMediaSessions

Currently, grabbing CurrentMediaSessions creates a new ReadOnlyDictionary.
This can cause massive memory/general optimization issues for anything that calls CurrentMediaSessions.

Need to create a class to handle both an internally usable Dictionary, and an externally usable ReadOnlyDictionary. Keeping 2 dictionaries in sync should be much more efficient than creating a new dictionary every CurrentMediaSessions get.

How to use this wrapper.

There is no information regarding how to use this wrapper. Could you update the readme please as I'd love to use this.

currentSession is null to control session

I just got acquainted with this package and I tried to make an app with the help of the example, but I had a problem skipping or stopping the media.
I noticed that currentSession is null and I don't know why.
I'm using .NET Core 3.1

Code:

private readonly MediaManager mediaManager = new MediaManager();
private MediaSession? currentSession = null;

//some code...

private async void controlerPlay_Click(object sender, EventArgs e)
        {
            var controlsInfo = currentSession?.ControlSession.GetPlaybackInfo().Controls;

            if (controlsInfo?.IsPauseEnabled == true)
            {
                await currentSession?.ControlSession.TryPauseAsync();
            }
            else if (controlsInfo?.IsPlayEnabled == true)
            {
                await currentSession?.ControlSession.TryPlayAsync();
            }
        }

        private async void ControlerNext_Click(object sender, EventArgs e)
        {
            await currentSession?.ControlSession.TrySkipNextAsync();
        }

Error:

System.ArgumentNullException: Value cannot be null. (Parameter 'source')
   at System.WindowsRuntimeSystemExtensions.AsTask[TResult](IAsyncOperation`1 source, CancellationToken cancellationToken)
   at System.WindowsRuntimeSystemExtensions.AsTask[TResult](IAsyncOperation`1 source)
   at System.WindowsRuntimeSystemExtensions.GetAwaiter[TResult](IAsyncOperation`1 source)

Using WindowsMediaController as a DLL in Unity

I've been trying to create a DLL to use WindowsMediaController in Unity x64 standalone build without success. I assume this is Unity Mono issue but thought I'd ask anyway.

This was my attempt but Unity throws al sort of issues with the imported support DLLs. Maybe there is a different approach I should be taking?

Here is my minimal attempt:
`using System;
using Windows.Media.Control;
using WindowsMediaController;
using static WindowsMediaController.MediaManager;

namespace MediaTrackInfo
{
public class MediaTrack : IDisposable
{
private MediaManager mediaManager;
private string currentTrackName;

    public MediaTrack()
    {
        mediaManager = new MediaManager();

        mediaManager.OnAnyMediaPropertyChanged += MediaManager_OnAnyMediaPropertyChanged;

        mediaManager.Start();
    }

    private void MediaManager_OnAnyMediaPropertyChanged(MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties)
    {
        currentTrackName = $"{mediaProperties.Artist} - {mediaProperties.Title}";
    }

    public string GetCurrentMediaTrack()
    {
        return currentTrackName;
    }

    public void Dispose()
    {
        mediaManager?.Dispose();
    }
}

}
`

Add/Change Windows targets to Windows 10

Current windows targets (windows10.0.22000.0) are for windows 11, minimum windows 10 target is windows10.0.17763.0
Because of this I have to build my own dll for the plugin I'm using for Artemis (it uses windows10.0.17763.0 dlls)

Target framework versioning is confusing, yes. I also made this mistake thinking I was targeting my plugin for w10 but it was actually w11

Help: System.Exception: The specified service does not exist as an installed service.

How to run this lib through Task Scheduler?

It works perfectly if starting manually via compiled exe or calling the exe via cmd/powershell.

But in Task Scheduler Returns below error: "mediaManager.Start()"

System.Exception: The specified service does not exist as an installed service.
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at SystemWebMonitorInterface.MediaManager.Start() in C:\Projects\SystemMonitorWebInterface\bin\SystemWebMonitorInterface\SystemWebMonitorInterface\MediaManager.cs:line 63
at SystemWebMonitorInterface.Program.<>c.<

b__12_2>d.MoveNext() in C:\Projects\SystemMonitorWebInterface\bin\SystemWebMonitorInterface\SystemWebMonitorInterface\Program.cs:line 213
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()

.NET 6 support

Hey @DubyaDude,

This is a great library, however, using it on .NET 6 gives the following error:

WindowsMediaController.dll cannot be referenced because it uses built-in support for WinRT, which is no longer supported in .NET 5 and higher. 
An updated version of the component supporting .NET 5 is needed. For more information, see https://aka.ms/netsdk1149

Do you think it would be possible to achieve this functionality without WinRT?

Thanks!

Unhandled exception

Running Spotify, then closing it after around 5/10+ seconds and after using the controls, this error gets thrown.

Unhandled exception. System.Runtime.InteropServices.COMException (0x800706BA): The RPC server is unavailable. (0x800706BA)
   at WindowsMediaController.MediaManager.MediaSession.OnSongChange(GlobalSystemMediaTransportControlsSession controlSession, MediaPropertiesChangedEventArgs args)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
   at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
   at System.Threading.Thread.StartCallback()

RPC_E_CALL_CANCELED when mediaManager Start or StartAsync

Hello,

I'm getting this error when trying to call Start or StartAsync on MediaManager.
System.Exception: 'Call was canceled by the message filter. (Exception from HRESULT: 0x80010002 (RPC_E_CALL_CANCELED))'

Once I was able to trigger everything right however since then every run of my app crashes with this exception. Try/Catch is not solution as it crashes every single time.

Did you experienced the same issue? Thanks a lot!

MediaManager.Dispose: InvalidOperationException: Collection was modified; enumeration operation may not execute.

I'm experiencing this error both in my own application, and the provided sample applications
It seems that .Dispose() on sessions modifies the keys being iterated in MediaManager.Dispose

Unhandled Exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.KeyCollection.Enumerator.MoveNext()
   at WindowsMediaController.MediaManager.Dispose() in /_/WindowsMediaController/Main.cs:line 253
   at Sample.CMD.Program.Main() in D:\a\WindowsMediaController\WindowsMediaController\Sample.CMD\Program.cs:line 32

GetFocussedSession crash

When using Chrome and YouTube (presumed to be similar on other browsers) when the video changes GetFocussedSession() is wrong as Chrome removes itself as a media source when unloading the page and re-adds itself as a media source when loading which results in an exception.

System.Collections.Generic.KeyNotFoundException: The given key 'chrome.exe' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at WindowsMediaController.MediaManager.GetFocusedSession(GlobalSystemMediaTransportControlsSessionManager sender)

I'd probably expect that if no focussed sessions were found, I.E, there are none present or the one trying to be found is null, it tries to default to another session or just returns a null controller.

MediaMuted Information (if possible)

Hello, I'm the current maintainer of Aurora-RGB and also making a plugin for Artemis-RGB. I will also reference this repository on those projects.
https://github.com/Aurora-RGB/Aurora
https://github.com/Aytackydln/Artemis.MediaInfo
https://github.com/Artemis-RGB/Artemis

Thanks for the library, RGB devices will be able to react depending on media :)

I wanted to add media muted information too but library didn't expose that. I also noticed playback information updates whenever I mute/unmute media so I thought it would be possible to add to this library.

MTC SessionsChanged and CurrentSessionChanged (FocusedSession) not triggering

I tried the example project in the repository, I am using Windows 10 Pro 21H2 build 19044.2006.

  • OnAnySessionOpened event is raised only when you launch the program, any new media source can not be detected while the program is running.
  • When you close media source (spotify or chrome for example) the OnAnySessionClosed event is not raised and instead the OnAnyPlaybackStateChanged event is being called multiple times:
    image
    If you try to reopen the closed media source, it is not detected neither.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.