using System; using System.Runtime.InteropServices; using TweetLib.Audio.Utils; using WMPLib; namespace TweetLib.Audio.Impl{ sealed class SoundPlayerImplWMP : AudioPlayer{ public override string SupportedFormats => "*.wav;*.mp3;*.mp2;*.m4a;*.mid;*.midi;*.rmi;*.wma;*.aif;*.aifc;*.aiff;*.snd;*.au"; public override event EventHandler<PlaybackErrorEventArgs> PlaybackError; private readonly WindowsMediaPlayer player; private bool wasTryingToPlay; private bool ignorePlaybackError; // changing the player volume also affects the value in the Windows mixer // however, the initial value is always 50 or some other stupid shit // so we have to tell the player to set its volume to whatever the mixer is set to // using the most code required for the least functionality with a sorry excuse for an API // thanks, Microsoft public SoundPlayerImplWMP(){ player = new WindowsMediaPlayer(); player.settings.autoStart = false; player.settings.enableErrorDialogs = false; player.settings.invokeURLs = false; player.settings.volume = (int)Math.Floor(100.0*NativeCoreAudio.GetMixerVolumeForCurrentProcess()); player.MediaChange += player_MediaChange; player.MediaError += player_MediaError; } public override void Play(string file){ wasTryingToPlay = true; try{ if (player.URL != file){ player.close(); player.URL = file; ignorePlaybackError = false; } else{ player.controls.stop(); } player.controls.play(); }catch(Exception e){ OnNotificationSoundError("An error occurred in Windows Media Player: "+e.Message); } } public override void Stop(){ try{ player.controls.stop(); }catch{ // ignore } } protected override void Dispose(bool disposing){ player.close(); Marshal.ReleaseComObject(player); } private void player_MediaChange(object item){ IWMPMedia2 media = item as IWMPMedia2; if (media == null){ OnNotificationSoundError("Unknown error."); return; } // ReSharper disable once CompareOfFloatsByEqualityOperator else if (media.Error == null && media.duration == 0.0){ OnNotificationSoundError("File does not contain an audio track."); } else if (media.Error != null){ OnNotificationSoundError(media.Error); } Marshal.ReleaseComObject(media); } private void player_MediaError(object pMediaObject){ IWMPMedia2 media = pMediaObject as IWMPMedia2; if (media == null){ OnNotificationSoundError("Unknown error."); return; } else if (media.Error != null){ OnNotificationSoundError(media.Error); } Marshal.ReleaseComObject(media); } private void OnNotificationSoundError(IWMPErrorItem error){ OnNotificationSoundError(error.errorCode == -1072885353 ? "Invalid media file." : error.errorDescription); Marshal.ReleaseComObject(error); } private void OnNotificationSoundError(string message){ if (wasTryingToPlay){ wasTryingToPlay = false; if (!ignorePlaybackError && PlaybackError != null){ PlaybackErrorEventArgs args = new PlaybackErrorEventArgs(message); PlaybackError(this, args); ignorePlaybackError = args.Ignore; } } } } }