private void pollTimer_Tick(object sender, EventArgs e)
        {
            if (_iTunes.CurrentTrack == null)
            {
                return;
            }
            if (_currentArtist == _iTunes.CurrentTrack.Artist && _currentTitle == _iTunes.CurrentTrack.Name && _currentState == _iTunes.PlayerState)
            {
                return;
            }
            _currentArtist = _iTunes.CurrentTrack.Artist;
            _currentTitle  = _iTunes.CurrentTrack.Name;
            _currentState  = _iTunes.PlayerState;

            UpdatePresence();
        }
        public void Get()
        {
            this.Volume = this.app.SoundVolume;
            IITTrack currentTrack = this.app.CurrentTrack;

            if (currentTrack == null)
            {
                return;
            }

            ITPlayerState t = ITPlayerState.ITPlayerStateFastForward;

            if (currentPlayState != this.app.PlayerState)
            {
                currentPlayState = this.app.PlayerState;
                TrackPlayStateChanged?.Invoke(currentPlayState switch
                {
                    ITPlayerState.ITPlayerStatePlaying => PlayState.Play,
                    _ => PlayState.Pause
                });
        /// <summary>
        /// Initializes the bridge and connects it to DiscordRPC
        /// </summary>
        /// <param name="applicationId">The Discord application ID for rich presence</param>
        public DiscordBridge(string applicationId)
        {
            var handlers = new DiscordRpc.EventHandlers();

            DiscordRpc.Initialize(applicationId, ref handlers, true, null);

            Tokens = AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes()).Where(p => typeof(IToken).IsAssignableFrom(p) && p.IsClass).Select(Activator.CreateInstance).Select(i => (IToken)i).ToList();

            _iTunes = new iTunesApp();

            _timer = new DispatcherTimer {
                Interval = TimeSpan.FromSeconds(15)
            };
            _timer.Tick += Timer_OnTick;
            _timer.Start();

            _currentArtist   = "";
            _currentTitle    = "";
            _currentState    = ITPlayerState.ITPlayerStateStopped;
            _currentPosition = 0;
        }
        private void UpdateStatus()
        {
            if (_started == false)
            {
                return;
            }
            if (_iTunesApplication == null)
            {
                return;
            }

            TimeSpan ts = DateTime.Now - _updateTimer;

            if (ts.TotalSeconds >= 1 || _duration < 0 || _started == false)
            {
                _playerState     = _iTunesApplication.PlayerState;
                _duration        = _iTunesApplication.CurrentTrack.Duration;
                _currentPosition = (double)_iTunesApplication.PlayerPosition;
                _updateTimer     = DateTime.Now;
            }
        }
Exemple #5
0
        private void AllProps(iTunesAppClass itunes)
        {
            bool                  acmpEnabled = itunes.AppCommandMessageProcessingEnabled;
            IITEncoder            encoder     = itunes.CurrentEncoder;
            IITEQPreset           eqPreset    = itunes.CurrentEQPreset;
            IITPlaylist           playlist    = itunes.CurrentPlaylist;
            string                streamTitle = itunes.CurrentStreamTitle;
            string                streamURL   = itunes.CurrentStreamURL;
            IITTrack              track       = itunes.CurrentTrack;
            IITVisual             visual      = itunes.CurrentVisual;
            IITEncoderCollection  encoders    = itunes.Encoders;
            bool                  eqEnabled   = itunes.EQEnabled;
            IITEQPresetCollection eqPresets   = itunes.EQPresets;

            // this always seems to raise a COM exception, whether playing or stopped...
            //IITWindow eqWindow = itunes.EQWindow;

            bool fgOnDialog = itunes.ForceToForegroundOnDialog;
            bool fsVisuals  = itunes.FullScreenVisuals;
            IITLibraryPlaylist libPlaylist = itunes.LibraryPlaylist;
            IITSource          libSource   = itunes.LibrarySource;
            string             libXmlPath  = itunes.LibraryXMLPath;
            bool mute = itunes.Mute;

            // this will raise a COM exception when iTunes first started
            //int position = itunes.PlayerPosition;

            ITPlayerState      state          = itunes.PlayerState;
            IITTrackCollection selectedTracks = itunes.SelectedTracks;
            int  volume                        = itunes.SoundVolume;
            bool volEnabled                    = itunes.SoundVolumeControlEnabled;
            IITSourceCollection sources        = itunes.Sources;
            string version                     = itunes.Version;
            IITVisualCollection visuals        = itunes.Visuals;
            bool                visualsEnabled = itunes.VisualsEnabled;
            ITVisualSize        visualSize     = itunes.VisualSize;
            IITWindowCollection windows        = itunes.Windows;
        }
        /// <summary>
        /// Handles checking for playing status changes and pushing out presence updates
        /// </summary>
        /// <param name="sender">Sender of this event</param>
        /// <param name="e">Args of this event</param>
        private void Timer_OnTick(object sender, EventArgs e)
        {
            try {
                if (_iTunes == null)
                {
                    _iTunes = new iTunesApp();
                }
                if (_iTunes.CurrentTrack == null)
                {
                    DiscordRpc.ClearPresence();
                    return;
                }
            }
            catch (COMException) {
                _iTunes = null;
                var newPresence = new DiscordRpc.RichPresence {
                    largeImageKey = "itunes_logo_big",
                    details       = "Error connecting to iTunes",
                    state         = "Playback information unavailable"
                };
                DiscordRpc.UpdatePresence(newPresence);
                return;
            }


            if (_currentArtist == _iTunes.CurrentTrack.Artist && _currentTitle == _iTunes.CurrentTrack.Name &&
                _currentState == _iTunes.PlayerState && _currentPosition == _iTunes.PlayerPosition)
            {
                return;
            }

            _currentArtist   = _iTunes.CurrentTrack.Artist;
            _currentTitle    = _iTunes.CurrentTrack.Name;
            _currentState    = _iTunes.PlayerState;
            _currentPosition = _iTunes.PlayerPosition;

            var presence = new DiscordRpc.RichPresence {
                largeImageKey = "itunes_logo_big"
            };

            if (_currentState != ITPlayerState.ITPlayerStatePlaying)
            {
                presence.details = TruncateString(RenderString(Settings.Default.PausedTopLine));
                presence.state   = TruncateString(RenderString(Settings.Default.PausedBottomLine));
            }
            else
            {
                presence.details = TruncateString(RenderString(Settings.Default.PlayingTopLine));
                presence.state   = TruncateString(RenderString(Settings.Default.PlayingBottomLine));
                if (Settings.Default.DisplayPlaybackDuration)
                {
                    presence.startTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds() - _currentPosition;
                    presence.endTimestamp   = DateTimeOffset.Now.ToUnixTimeSeconds() +
                                              (_iTunes.CurrentTrack.Duration - _currentPosition);
                }
            }

            try {
                DiscordRpc.UpdatePresence(presence);
            }
            catch (Exception exception) {
                exception.Data.Add("CurrentArtist", _currentArtist);
                exception.Data.Add("CurrentTitle", _currentTitle);
                exception.Data.Add("CurrentState", _currentState.ToString());
                exception.Data.Add("CurrentPosition", _currentPosition.ToString());
                exception.Data.Add("Details", presence.details);
                exception.Data.Add("State", presence.state);
                Globals.RavenClient.Capture(new SentryEvent(exception));
                Globals.Log($"An unhandled exception has occurred and been reported to Sentry: {exception.Message}");
            }
        }
Exemple #7
0
        /// <summary>
        /// Handles checking for playing status changes and pushing out presence updates
        /// </summary>
        /// <param name="sender">Sender of this event</param>
        /// <param name="e">Args of this event</param>
        private void Timer_OnTick(object sender, EventArgs e)
        {
            try {
                if (ITunes == null)
                {
                    ITunes = new iTunesApp();
                }

                if (ITunes.CurrentTrack == null || (Settings.Default.ClearOnPause && ITunes.PlayerState != ITPlayerState.ITPlayerStatePlaying))
                {
                    DiscordRpc.ClearPresence();
                    return;
                }
            }
            catch (COMException) {
                ITunes = null;
                var newPresence = new DiscordRpc.RichPresence {
                    largeImageKey = "itunes_logo_big",
                    details       = "Error connecting to iTunes",
                    state         = "Playback information unavailable"
                };
                DiscordRpc.UpdatePresence(newPresence);
                return;
            }
            catch (EntryPointNotFoundException) {
                var newPresence = new DiscordRpc.RichPresence {
                    largeImageKey = "itunes_logo_big",
                    details       = "No song playing",
                    state         = "Re-install iTunesRichPresence to clear this message"
                };
                DiscordRpc.UpdatePresence(newPresence);
                return;
            }


            if (_currentArtist == ITunes.CurrentTrack.Artist && _currentTitle == ITunes.CurrentTrack.Name &&
                _currentState == ITunes.PlayerState && _currentPosition == ITunes.PlayerPosition)
            {
                return;
            }

            _currentArtist   = ITunes.CurrentTrack.Artist;
            _currentTitle    = ITunes.CurrentTrack.Name;
            _currentState    = ITunes.PlayerState;
            _currentPosition = ITunes.PlayerPosition;
            int    _currentAlbumCoverCount = ITunes.CurrentTrack.Artwork.Count;
            string PREFIX = "itlps-";

            foreach (var artT in ITunes.CurrentTrack.Artwork)
            {
                var    art = artT as IITArtwork;
                string ext = ".tmp";
                switch (art.Format)
                {
                case ITArtworkFormat.ITArtworkFormatBMP:
                    ext = ".bmp";
                    break;

                case ITArtworkFormat.ITArtworkFormatJPEG:
                    ext = ".jpg";
                    break;

                case ITArtworkFormat.ITArtworkFormatPNG:
                    ext = ".png";
                    break;
                }

                string path = Path.Combine(Path.GetTempPath(), PREFIX + Path.GetRandomFileName() + ext);
                art.SaveArtworkToFile(path);
                //Debug.WriteLine(path);
            }

            Debug.WriteLine("DB ID: " + ITunes.CurrentTrack.TrackDatabaseID);
            Debug.WriteLine("Track ID: " + ITunes.CurrentTrack.trackID);
            Debug.WriteLine("Artwork: " + ITunes.CurrentTrack.Artwork);

            var presence = new DiscordRpc.RichPresence {
                largeImageKey = path
            };

            if (_currentState != ITPlayerState.ITPlayerStatePlaying)
            {
                presence.details = TruncateString(RenderString(Settings.Default.PausedTopLine));
                presence.state   = TruncateString(RenderString(Settings.Default.PausedBottomLine));
            }
            else
            {
                presence.details = "[" + _currentArtist + "](https://google.co.uk)"; //Embed top line
                presence.state   = _currentTitle;                                    //Embed bottom line.
                if (Settings.Default.DisplayPlaybackDuration)
                {
                    presence.startTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds() - _currentPosition;
                    presence.endTimestamp   = DateTimeOffset.Now.ToUnixTimeSeconds() +
                                              (ITunes.CurrentTrack.Duration - _currentPosition);
                }
            }

            try {
                DiscordRpc.UpdatePresence(presence);
            }
            catch (Exception exception) {
                exception.Data.Add("CurrentArtist", _currentArtist);
                exception.Data.Add("CurrentTitle", _currentTitle);
                exception.Data.Add("CurrentState", _currentState.ToString());
                exception.Data.Add("CurrentPosition", _currentPosition.ToString());
                exception.Data.Add("Details", presence.details);
                exception.Data.Add("State", presence.state);
                Globals.RavenClient.Capture(new SentryEvent(exception));
                Globals.Log($"An unhandled exception has occurred and been reported to Sentry: {exception.Message}");
            }
        }
        public override bool Play(string strFile)
        {
            try
            {
                if (_iTunesApplication == null)
                {
                    _iTunesApplication = new iTunesAppClass();
                    _iTunesApplication.OnPlayerPlayEvent +=
                        new _IiTunesEvents_OnPlayerPlayEventEventHandler(_iTunesApplication_OnPlayerPlayEvent);
                    _iTunesApplication.OnPlayerStopEvent +=
                        new _IiTunesEvents_OnPlayerStopEventEventHandler(_iTunesApplication_OnPlayerStopEvent);
                    _iTunesApplication.OnPlayerPlayingTrackChangedEvent +=
                        new _IiTunesEvents_OnPlayerPlayingTrackChangedEventEventHandler(
                            _iTunesApplication_OnPlayerPlayingTrackChangedEvent);
                    IITPlaylist playList = null;
                    foreach (IITPlaylist pl in _iTunesApplication.LibrarySource.Playlists)
                    {
                        if (pl.Name.Equals("MediaPortalTemporaryPlaylist"))
                        {
                            playList = pl;
                            break;
                        }
                    }
                    if (playList == null)
                    {
                        _playList = (IITUserPlaylist)_iTunesApplication.CreatePlaylist("MediaPortalTemporaryPlaylist");
                    }
                    else
                    {
                        _playList = (IITUserPlaylist)playList;
                    }
                    _playList.SongRepeat = ITPlaylistRepeatMode.ITPlaylistRepeatModeOff;
                }

                // stop other media which might be active until now.
                if (g_Player.Playing)
                {
                    g_Player.Stop();
                }

                GUIMessage msg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_PLAYBACK_STARTED, 0, 0, 0, 0, 0, null);
                msg.Label = strFile;
                GUIWindowManager.SendThreadMessage(msg);

                _started = false;
                _ended   = false;
                foreach (IITTrack track in _playList.Tracks)
                {
                    track.Delete();
                }
                _playList.AddFile(strFile);
                _playList.PlayFirstTrack();

                _playerIsPaused  = false;
                _currentFile     = strFile;
                _duration        = -1;
                _currentPosition = -1;
                _playerState     = ITPlayerState.ITPlayerStateStopped;
                _updateTimer     = DateTime.MinValue;

                UpdateStatus();
                _notifyPlaying = true;
                return(true);
            }
            catch (Exception ex)
            {
                Log.Error("ITunesPlugin.Play: Exception");
                Log.Error(ex);
                _notifyPlaying     = false;
                _iTunesApplication = null;
            }
            return(false);
        }
Exemple #9
0
        private void DumpState(iTunesAppClass itunes)
        {
            IITPlaylist playlist = itunes.CurrentPlaylist;

            Debug.WriteLine("itunes.CurrentPlaylist");
            if (itunes.CurrentPlaylist == null)
            {
                Debug.WriteLine("... NULL");
            }
            else
            {
                Debug.WriteLine(String.Format("... Kind [{0}]", itunes.CurrentPlaylist.Kind));
                Debug.WriteLine(String.Format("... Name [{0}]", itunes.CurrentPlaylist.Name));
                Debug.WriteLine(String.Format("... Tracks.Count [{0}]", itunes.CurrentPlaylist.Tracks.Count));
            }

            string streamTitle = itunes.CurrentStreamTitle;

            Debug.WriteLine(String.Format("iTunes.CurrentStreamTitle [{0}]", itunes.CurrentStreamTitle));

            string streamURL = itunes.CurrentStreamURL;

            Debug.WriteLine(String.Format("iTunes.CurrentStreamURL [{0}]", itunes.CurrentStreamURL));

            IITTrack currentTrack = itunes.CurrentTrack;

            Debug.WriteLine("itunes.CurrentTrack");
            if (itunes.CurrentTrack == null)
            {
                Debug.WriteLine("... NULL");
            }
            else
            {
                Debug.WriteLine(String.Format("... Album [{0}]", currentTrack.Album));
                Debug.WriteLine(String.Format("... Artist [{0}]", currentTrack.Artist));
                Debug.WriteLine(String.Format("... Kind [{0}]", currentTrack.Kind));
                Debug.WriteLine(String.Format("... Name [{0}]", currentTrack.Name));
                Debug.WriteLine(String.Format("... trackID [{0}]", currentTrack.trackID));
            }

            int position = itunes.PlayerPosition;

            Debug.WriteLine(String.Format("iTunes.PlayerPosition [{0}]", itunes.PlayerPosition));

            ITPlayerState state = itunes.PlayerState;

            Debug.WriteLine(String.Format("iTunes.PlayerState [{0}]", itunes.PlayerState));

            IITTrackCollection selectedTracks = itunes.SelectedTracks;

            Debug.WriteLine("itunes.SelectedTracks");
            if (itunes.SelectedTracks == null)
            {
                Debug.WriteLine("... NULL");
            }
            else
            {
                foreach (IITTrack track in itunes.SelectedTracks)
                {
                    Debug.WriteLine("... track");
                    Debug.WriteLine(String.Format("... Album [{0}]", itunes.CurrentTrack.Album));
                    Debug.WriteLine(String.Format("... Artist [{0}]", itunes.CurrentTrack.Artist));
                    Debug.WriteLine(String.Format("... Kind [{0}]", itunes.CurrentTrack.Kind));
                    Debug.WriteLine(String.Format("... Name [{0}]", itunes.CurrentTrack.Name));
                    Debug.WriteLine(String.Format("... trackID [{0}]", itunes.CurrentTrack.trackID));
                }
            }
        }
Exemple #10
0
    private void UpdateStatus()
    {
      if (_started == false)
      {
        return;
      }
      if (_iTunesApplication == null)
      {
        return;
      }

      TimeSpan ts = DateTime.Now - _updateTimer;

      if (ts.TotalSeconds >= 1 || _duration < 0 || _started == false)
      {
        _playerState = _iTunesApplication.PlayerState;
        _duration = _iTunesApplication.CurrentTrack.Duration;
        _currentPosition = (double)_iTunesApplication.PlayerPosition;
        _updateTimer = DateTime.Now;
      }
    }
Exemple #11
0
    public override bool Play(string strFile)
    {
      try
      {
        if (_iTunesApplication == null)
        {
          _iTunesApplication = new iTunesAppClass();
          _iTunesApplication.OnPlayerPlayEvent +=
            new _IiTunesEvents_OnPlayerPlayEventEventHandler(_iTunesApplication_OnPlayerPlayEvent);
          _iTunesApplication.OnPlayerStopEvent +=
            new _IiTunesEvents_OnPlayerStopEventEventHandler(_iTunesApplication_OnPlayerStopEvent);
          _iTunesApplication.OnPlayerPlayingTrackChangedEvent +=
            new _IiTunesEvents_OnPlayerPlayingTrackChangedEventEventHandler(
              _iTunesApplication_OnPlayerPlayingTrackChangedEvent);
          IITPlaylist playList = null;
          foreach (IITPlaylist pl in _iTunesApplication.LibrarySource.Playlists)
          {
            if (pl.Name.Equals("MediaPortalTemporaryPlaylist"))
            {
              playList = pl;
              break;
            }
          }
          if (playList == null)
          {
            _playList = (IITUserPlaylist)_iTunesApplication.CreatePlaylist("MediaPortalTemporaryPlaylist");
          }
          else
          {
            _playList = (IITUserPlaylist)playList;
          }
          _playList.SongRepeat = ITPlaylistRepeatMode.ITPlaylistRepeatModeOff;
        }

        // stop other media which might be active until now.
        if (g_Player.Playing)
        {
          g_Player.Stop();
        }

        GUIMessage msg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_PLAYBACK_STARTED, 0, 0, 0, 0, 0, null);
        msg.Label = strFile;
        GUIWindowManager.SendThreadMessage(msg);

        _started = false;
        _ended = false;
        foreach (IITTrack track in _playList.Tracks)
        {
          track.Delete();
        }
        _playList.AddFile(strFile);
        _playList.PlayFirstTrack();

        _playerIsPaused = false;
        _currentFile = strFile;
        _duration = -1;
        _currentPosition = -1;
        _playerState = ITPlayerState.ITPlayerStateStopped;
        _updateTimer = DateTime.MinValue;

        UpdateStatus();
        _notifyPlaying = true;
        return true;
      }
      catch (Exception ex)
      {
        Log.Error("ITunesPlugin.Play: Exception");
        Log.Error(ex);
        _notifyPlaying = false;
        _iTunesApplication = null;
      }
      return false;
    }
        // Plugin intialization function
        public void InitializeSource(int minimumScrobbleSeconds, TrackMonitoringStarted onTrackMonitoringStarted, TrackMonitoring onTrackMonitoring, TrackMonitoringEnded onTrackMonitoringEnded, ScrobbleTrack onScrobbleTrack)
        {
            _minimumScrobbleSeconds = minimumScrobbleSeconds;

            _onTrackMonitoringStarted = onTrackMonitoringStarted;
            _onTrackMonitoring        = onTrackMonitoring;
            _onTrackMonitoringEnded   = onTrackMonitoringEnded;
            _onScrobbleTrack          = onScrobbleTrack;

            _isIntialized = true;

            try
            {
                // Create a new scrobbler timer, to fire at the specified number of seconds
                _scrobbleTimer          = new Timer();
                _scrobbleTimer.Interval = 1000 * _timerInterval;

                // The ananoymous delegate event that occurs every time the timer fires (elapses)
                _scrobbleTimer.Elapsed += async(o, e) =>
                {
                    // Stop the timer to prevent multiple executions at the same time
                    _scrobbleTimer.Stop();

                    // Check for the iTunes process to ensure it's running.
                    // If we don't check for it, the plugin would end up launching it when we connect, which we don't want
                    Process[] iTunesProcesses = Process.GetProcessesByName("iTunes");

                    if (iTunesProcesses.Length > 0)
                    {
                        try
                        {
                            if (_isEnabled)
                            {
                                iTunesApp iTunesApp = new iTunesApp();

                                    #if DebugiTunes
                                Console.WriteLine("iTunes Plugin successfully connected to iTunes COM library.");
                                Console.WriteLine("iTunes Plugin checking media state...");
                                    #endif

                                // Get the current media from iTunes itself (using our helper function)
                                MediaItem mediaDetail = await GetMediaDetail(iTunesApp).ConfigureAwait(false);

                                ITPlayerState playerState    = ITPlayerState.ITPlayerStateStopped;
                                double        playerPosition = 0;

                                try
                                {
                                    // Get the iTunes media player state
                                    playerState    = iTunesApp?.PlayerState ?? ITPlayerState.ITPlayerStateStopped;
                                    playerPosition = iTunesApp?.PlayerPosition ?? 0;
                                }
                                catch (COMException comEx)
                                {
                                    // If the player is in an invalid state, this is going to happen!
                                }

                                // Determine if there is any media loaded
                                bool hasMedia = mediaDetail != null;

                                // Determine if the current track is deemed to have 'ended' as it's been fully listened to
                                bool hasReachedTrackEnd = hasMedia && (int)playerPosition + _timerInterval >= (int)mediaDetail?.TrackLength && mediaDetail?.TrackLength > 0;

                                // Determine if the current track playing isn't the last one we knew about
                                bool hasTrackChanged = _currentMediaItem?.TrackName != mediaDetail?.TrackName;

                                // Determine if the media player is in the 'Playing' state
                                bool isPlaying = playerState == ITPlayerState.ITPlayerStatePlaying;

                                // Determine if the media player is in the 'Stopped' (paused) state
                                bool isPaused = playerState == ITPlayerState.ITPlayerStateStopped;

                                // Determine if the current media item is scrobbleable
                                bool canScrobble = _currentMediaTrackingTime >= _minimumScrobbleSeconds &&
                                                   (_currentMediaTrackingTime >= Convert.ToInt32(Math.Min(Convert.ToInt32(_currentMediaItem?.TrackLength) / 2, 4 * 60)) && !_currentMediaWasScrobbled);

#if DebugiTunes
                                Console.WriteLine($"iTunes Media Player Plugin: Position {playerPosition} of { mediaDetail?.TrackLength }, Tracker time: {_currentMediaTrackingTime}...");
#endif

                                // If we have reached the point where the item has been tracked beyond the minimum number of tracking seconds
                                // and the item hasn't already been added to the scrobble queue
                                if (canScrobble && !_currentMediaWasScrobbled)
                                {
                                    // Safely add the media item to the scrobble queue
                                    lock (_mediaLock)
                                    {
                                        _mediaToScrobble.Add(_currentMediaItem);
                                    }

                                    // Fire the 'we are still tracking this item' event
                                    _onTrackMonitoring?.BeginInvoke(_currentMediaItem, (int)playerPosition, null, null);

                                    // Mark the item as having been added to the scrobble queue
                                    //(potential improvement, move this property to _currentMediaItem and remove the local variable)
                                    _currentMediaWasScrobbled = true;

                                    Console.WriteLine($"Track {mediaDetail.TrackName} queued for Scrobbling.");
                                }

                                // If the media player is still playing and the track has changed, or the current media has reached it's end (and therefore the media player has stopped)
                                if ((isPlaying && hasMedia && hasTrackChanged) || hasReachedTrackEnd)
                                {
                                    // Reset the last paused state
                                    _lastStatePaused = false;

                                    // Reset the current tracking time to the default number of timer seconds
                                    _currentMediaTrackingTime = _timerInterval;

                                    // If we knew about a media item before we got here
                                    if (_currentMediaItem != null)
                                    {
                                        // Fire the 'track monitoring has ended' event for the previous item
                                        _onTrackMonitoringEnded?.BeginInvoke(_currentMediaItem, null, null);

                                        // Fire the 'scrobble the item' event for the previous item
                                        _onScrobbleTrack?.BeginInvoke(_currentMediaItem, null, null);
                                    }

                                    Console.WriteLine("iTunes: Raising Track Change Method.");

                                    // If the reason we are here is because there is a new track being monitored
                                    if (hasTrackChanged)
                                    {
                                        // Set the current monitor item, to what the media player has told us is playing
                                        _currentMediaItem = mediaDetail;

                                        // Fire the 'track monitoring has started' even for the new item
                                        _onTrackMonitoringStarted?.BeginInvoke(mediaDetail, false, null, null);

                                        // Track when we started monitoring the new item (to pass to the Last.fm API)
                                        mediaDetail.StartedPlaying = DateTime.Now;
                                    }

                                    // Otherwise if we got here because the current item has ended, and no new item is playing
                                    else if (hasReachedTrackEnd)
                                    {
                                        // Clear the currently tracked media item, so that if the user starts playing it again, it is treated
                                        // as an entirely new scrobble
                                        _currentMediaItem = null;
                                    }

                                    // Reset the flag determining if the current item has been added to the Scrobble queue
                                    _currentMediaWasScrobbled = false;
                                }
                                // The media player is playing, and is still playing the same track
                                else if (isPlaying && !hasTrackChanged)
                                {
                                    // If the media player wasn't last in the paused state
                                    if (_lastStatePaused)
                                    {
                                        // Fire the 'we started monitoring this item' event
                                        _onTrackMonitoringStarted?.BeginInvoke(_currentMediaItem, _lastStatePaused, null, null);

                                        // Reset the pause state flag
                                        _lastStatePaused = false;
                                    }

                                    // Fire the 'we are still monitoring this item event' (possibly should be inside an else, although won't hurt
                                    // where it is)
                                    _onTrackMonitoring?.BeginInvoke(_currentMediaItem, (int)playerPosition, null, null);

                                    // Update the current media tracking time
                                    _currentMediaTrackingTime += _timerInterval;
                                }
                                // The media player is not playing
                                else if (!isPlaying)
                                {
                                    // If we had been playing, invoke the Track Ended callback
                                    if (_currentMediaTrackingTime > _timerInterval && !_lastStatePaused)
                                    {
                                        // Fire the 'we've stopped tracking this item' event
                                        _onTrackMonitoringEnded?.BeginInvoke(mediaDetail, null, null);
                                    }

                                    // Set the persisted pause state
                                    _lastStatePaused = isPaused;

                                    // If we're not paused (FF, Rewind)
                                    if (!isPaused)
                                    {
                                        // Reset the state tracking how long we played this track for
                                        _lastStatePaused          = false;
                                        _currentMediaTrackingTime = 0;
                                        _currentMediaWasScrobbled = false;
                                    }
                                }

                                // Release the iTunes COM library, so that the user _might_ be able to exit iTunes without getting a warning
                                if (iTunesApp != null)
                                {
                                    Marshal.ReleaseComObject(iTunesApp);
                                    iTunesApp = null;
                                }
                                System.GC.Collect();
                            }
#if DebugiTunes
                            Console.WriteLine("iTunes Plugin checking media state complete.");
#endif
                        }
                        catch (COMException cEx)
                        {
                            // Ignore the COM exception, the library is either trying to communicate with a property
                            // that isn't available.  IE PlayerPosition is not available when the player is stopped.

                            // It might also be tearing down
                        }
                        catch (Exception)
                        {
                            // Some other exception occured, at some point consider logging it...?
                        }
                    }
                    else if (iTunesProcesses.Length == 0 && _currentMediaItem != null)
                    {
                        _onTrackMonitoringEnded?.BeginInvoke(_currentMediaItem, null, null);
                        _currentMediaItem         = null;
                        _currentMediaWasScrobbled = false;
                        Console.WriteLine("iTunes process not detected.  Waiting for iTunes process to start...");
                    }


                    _scrobbleTimer?.Start();
                };
            }
            catch (Exception ex)
            {
                try
                {
                    // If an unexpected error occured, don't let that stop us from performing any tracking,
                    // as the error might only be temporary
                    _scrobbleTimer?.Start();
                }
                catch (Exception exception)
                {
                    // Can occur if you close the application as it's starting up
                }
            }
        }