nint8835 / iTunesRichPresence

Bring iTunes now playing information to Discord using Rich Presence
https://itunesrichpresence.com
MIT License
273 stars 44 forks source link

Gracefully handle iTunes close and don't re-open automatically #94

Open DanTheMan827 opened 2 years ago

DanTheMan827 commented 2 years ago

iTunes lib has several events that can be used for player status along with the ability to gracefully terminate the COM interface without displaying the message about the scripting interface being used.

I've made a simple program to demonstrate this.

using iTunesLib;
using System.Runtime.InteropServices;
using System.Diagnostics;

public static class Program
{
    public static iTunesApp? iApp;
    public static void Main(string[] args)
    {
        AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
        InitCOM(true);

        Console.ReadLine();
    }

    private static void CurrentDomain_ProcessExit(object? sender, EventArgs e)
    {
        IApp_OnAboutToPromptUserToQuitEvent();
    }

    static bool InitCOM(bool force = false)
    {
        if (iApp == null)
        {
            if(force || Process.GetProcessesByName("itunes").Length > 0)
            {
                try
                {
                    iApp = new iTunesApp();

                    if (iApp != null)
                    {
                        iApp.OnPlayerPlayEvent += IApp_OnPlayerPlayEvent;
                        iApp.OnPlayerStopEvent += IApp_OnPlayerStopEvent;
                        iApp.OnPlayerPlayingTrackChangedEvent += IApp_OnPlayerPlayingTrackChangedEvent;
                        iApp.OnAboutToPromptUserToQuitEvent += IApp_OnAboutToPromptUserToQuitEvent;

                        Console.WriteLine("Initialized iTunes COM interface");
                        return true;
                    }
                    return false;
                } 
                catch(Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
            else
            {
                Console.WriteLine("iTunes not running");
                return false;
            }
        }

        return true;
    }

    private static void IApp_OnAboutToPromptUserToQuitEvent()
    {
        if (iApp != null)
        {
            iApp.OnPlayerPlayEvent -= IApp_OnPlayerPlayEvent;
            iApp.OnPlayerStopEvent -= IApp_OnPlayerStopEvent;
            iApp.OnPlayerPlayingTrackChangedEvent -= IApp_OnPlayerPlayingTrackChangedEvent;
            iApp.OnAboutToPromptUserToQuitEvent -= IApp_OnAboutToPromptUserToQuitEvent;
            _ = Marshal.ReleaseComObject(iApp);
            iApp = null;

            Console.WriteLine("iTunes COM interface closed");

            return;
        }
    }

    private static void IApp_OnPlayerPlayingTrackChangedEvent(object iTrack)
    {
        Console.WriteLine($"Track Changed\r\n  Artist: {iApp?.CurrentTrack.Artist}\r\n  Name: {iApp?.CurrentTrack.Name}\r\n");
    }

    private static void IApp_OnPlayerStopEvent(object iTrack)
    {
        Console.WriteLine("Player Stopped");
    }

    private static void IApp_OnPlayerPlayEvent(object iTrack)
    {
        Console.WriteLine($"Player Started\r\n  Artist: {iApp?.CurrentTrack.Artist}\r\n  Name: {iApp?.CurrentTrack.Name}\r\n");
    }
}

You could put the InitCOM(); call in your timer for example and it would only initialize the COM interface if itunes.exe is running.