1

I want to get information about all currently active media playbacks. I found a way to read out all media sessions here:

using Windows.Media.Control;

namespace ConsoleApp1 {
    public class Program {
        [STAThread]
        static void Main(string[] args) {
            var gsmtcsm = GlobalSystemMediaTransportControlsSessionManager.RequestAsync().GetAwaiter().GetResult().GetSessions();

            foreach (var session in gsmtcsm) {
                var mediaProperties = session.TryGetMediaPropertiesAsync().GetAwaiter().GetResult();
                Console.WriteLine("{0} - {1}", mediaProperties.Artist, mediaProperties.Title);
            }

            Console.ReadKey();
        }
    }
}

Now I want to get the corresponding programs for these sessions. Also, I want to get the window of the program if it exists. My goal is to programmatically move the window if it exists to another screen. The program handle is just used as an identifier.

For example: I open a random .mp4 file. By default, it is played by Windows Films & TV. Now I want to get the session, program, and window (Films & TV has a window) and move it to another screen (by code)

Another example: I watch a video on Youtube. Now I want to get the window of the browser I opened Youtube in.

Ken White
  • 123,280
  • 14
  • 225
  • 444
Kaskorian
  • 426
  • 3
  • 18

1 Answers1

1

You can find the main window for the app that is running the media session with

var gsmtcsm = GlobalSystemMediaTransportControlsSessionManager.RequestAsync().GetAwaiter().GetResult().GetSessions();
foreach (var session in gsmtcsm)
{
    string modelId = session.SourceAppUserModelId;
    // Get all processes
    Process[] processlist = Process.GetProcesses();
    // Create and array to hold matched processes
    List<Process> modelProcesslist = new List<Process>();
    // Using a direct filter on the Process.GetProcesses() call will raise an exception, you will need to cycle through them 
    // to find a process that has the same filename as reported by the media session
    // The filename may be different to the process name
    foreach (Process p in processlist)
    {
        try
        {
            if (p.MainModule.FileName.Contains(modelId) && p.MainWindowHandle != IntPtr.Zero)
            {
                modelProcesslist.Add(p);
            }
        }
        catch(System.Exception)
        {
            // Couldn't look at the MainModule of this process, move on
        }
    }
    foreach (Process p in modelProcesslist)
    {
        IntPtr windowHandle = p.MainWindowHandle;
        // The main window(s) for apps that have the same name as the source app for the media session
    }
}

One big issue will be if the main window is owned by chrome.exe (or any tabbed browser), then the media player is in one of the sub tabs, finding content within a tab of the browser is a whole new level of headache.

Also if you have multiple browser windows open, they will all have the same executable name and get picked up by the above code.

If the app is a dedicated media player, you should be able to use the handle to move the window.

Xavier
  • 1,383
  • 7
  • 6
  • Thanks a lot. I'll implement it and then I'll see how to find the correct window containing the tab. The next level would be focusing this Tab ;) – Kaskorian Nov 08 '20 at 01:54
  • On additional question. Is there a reason why one program cannot have multiple media sessions? So if I open two youtube videos inside chrome only one is read out. Also, Firefox has no session although I open a video – Kaskorian Nov 08 '20 at 02:03
  • 1
    The GlobalSystemMediaTransportControlsSessionManager will only list playback sessions that have integrated with SystemMediaTransportControls, if an app has an independent/un-integrated media player, than it will not be listed. – Xavier Nov 08 '20 at 02:41
  • Okay. But one youtube video is listed. But not the other one inside the same browser (tested for chrome and edge; firefox none is listed) although it should be the same type of player – Kaskorian Nov 08 '20 at 02:46
  • I'm not sure on that one, I will have to look into it, I suspect that chrome is only integrating one of the sessions at a time, i.e. the one that has focus, if you switch tabs does the artist info change? – Xavier Nov 08 '20 at 03:15
  • In either Chrome or Edge, the session contains information about the last updated playback. Example: I play Video 1 and the ad starts. The session now contains Ad 1. I start Video 2 and the ad starts. The session now contains As 2. The first ad finishes and the second ad or the video begins. The session is updated to the ad or the video. and so on. Play, pause, skip time, ... counts as an update – Kaskorian Nov 08 '20 at 03:19
  • If you are playing both videos at the same time, do you got both sessions? – Xavier Nov 08 '20 at 03:23
  • No, only the video that I played last – Kaskorian Nov 08 '20 at 03:24
  • Or when the other one updates the other one, for example after a switch from ad the video – Kaskorian Nov 08 '20 at 03:25