diff --git a/Configuration/UserConfig.cs b/Configuration/UserConfig.cs index 0fc8b38a..6c982d3a 100644 --- a/Configuration/UserConfig.cs +++ b/Configuration/UserConfig.cs @@ -83,8 +83,8 @@ static UserConfig(){ public Size CustomNotificationSize { get; set; } = Size.Empty; public int NotificationScrollSpeed { get; set; } = 100; - public int NotificationSoundVolume { get; set; } = 100; private string _notificationSoundPath; + private int _notificationSoundVolume = 100; public string CustomCefArgs { get; set; } = null; public string CustomBrowserCSS { get; set; } = null; @@ -94,12 +94,18 @@ static UserConfig(){ public bool IsCustomNotificationPositionSet => CustomNotificationPosition != ControlExtensions.InvisibleLocation; public bool IsCustomNotificationSizeSet => CustomNotificationSize != Size.Empty; + public bool IsCustomSoundNotificationSet => NotificationSoundPath != string.Empty; public TwitterUtils.ImageQuality TwitterImageQuality => BestImageQuality ? TwitterUtils.ImageQuality.Orig : TwitterUtils.ImageQuality.Default; public string NotificationSoundPath{ - get => string.IsNullOrEmpty(_notificationSoundPath) ? string.Empty : _notificationSoundPath; - set => _notificationSoundPath = value; + get => _notificationSoundPath ?? string.Empty; + set => UpdatePropertyWithEvent(ref _notificationSoundPath, value, SoundNotificationChanged); + } + + public int NotificationSoundVolume{ + get => _notificationSoundVolume; + set => UpdatePropertyWithEvent(ref _notificationSoundVolume, value, SoundNotificationChanged); } public bool MuteNotifications{ @@ -122,6 +128,7 @@ public TrayIcon.Behavior TrayBehavior{ public event EventHandler MuteToggled; public event EventHandler ZoomLevelChanged; public event EventHandler TrayBehaviorChanged; + public event EventHandler SoundNotificationChanged; // END OF CONFIG diff --git a/Core/Bridge/PropertyBridge.cs b/Core/Bridge/PropertyBridge.cs index e43800c2..cfcbafdf 100644 --- a/Core/Bridge/PropertyBridge.cs +++ b/Core/Bridge/PropertyBridge.cs @@ -19,7 +19,6 @@ public static string GenerateScript(Environment environment){ build.Append("x.openSearchInFirstColumn=").Append(Bool(Program.UserConfig.OpenSearchInFirstColumn)); build.Append("x.keepLikeFollowDialogsOpen=").Append(Bool(Program.UserConfig.KeepLikeFollowDialogsOpen)); build.Append("x.muteNotifications=").Append(Bool(Program.UserConfig.MuteNotifications)); - build.Append("x.hasCustomNotificationSound=").Append(Bool(Program.UserConfig.NotificationSoundPath.Length > 0)); build.Append("x.notificationMediaPreviews=").Append(Bool(Program.UserConfig.NotificationMediaPreviews)); build.Append("x.translationTarget=").Append(Str(Program.UserConfig.TranslationTarget)); } diff --git a/Core/Bridge/TweetDeckBridge.cs b/Core/Bridge/TweetDeckBridge.cs index aa376266..48b95893 100644 --- a/Core/Bridge/TweetDeckBridge.cs +++ b/Core/Bridge/TweetDeckBridge.cs @@ -126,7 +126,7 @@ public void OnTweetPopup(string columnId, string chirpId, string columnName, str public void OnTweetSound(){ form.InvokeAsyncSafe(() => { form.OnTweetNotification(); - form.PlayNotificationSound(); + form.OnTweetSound(); }); } diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs index ed964d6c..0e437218 100644 --- a/Core/FormBrowser.cs +++ b/Core/FormBrowser.cs @@ -15,7 +15,6 @@ using TweetDuck.Plugins; using TweetDuck.Plugins.Events; using TweetDuck.Updates; -using TweetLib.Audio; namespace TweetDuck.Core{ sealed partial class FormBrowser : Form{ @@ -50,7 +49,6 @@ public bool IsWaiting{ private FormWindowState prevState; private TweetScreenshotManager notificationScreenshotManager; - private SoundNotification soundNotification; private VideoPlayer videoPlayer; private AnalyticsManager analytics; @@ -82,7 +80,6 @@ public FormBrowser(UpdaterSettings updaterSettings){ contextMenu.Dispose(); notificationScreenshotManager?.Dispose(); - soundNotification?.Dispose(); videoPlayer?.Dispose(); analytics?.Dispose(); }; @@ -291,22 +288,6 @@ private void updates_UpdateDismissed(object sender, UpdateEventArgs e){ }); } - private void soundNotification_PlaybackError(object sender, PlaybackErrorEventArgs e){ - e.Ignore = true; - - using(FormMessage form = new FormMessage("Notification Sound Error", "Could not play custom notification sound.\n"+e.Message, MessageBoxIcon.Error)){ - form.AddButton(FormMessage.Ignore, ControlType.Cancel | ControlType.Focused); - - Button btnOpenSettings = form.AddButton("View Options"); - btnOpenSettings.Width += 16; - btnOpenSettings.Location = new Point(btnOpenSettings.Location.X-16, btnOpenSettings.Location.Y); - - if (form.ShowDialog() == DialogResult.OK && form.ClickedButton == btnOpenSettings){ - OpenSettings(typeof(TabSettingsSounds)); - } - } - } - protected override void WndProc(ref Message m){ if (isLoaded && m.Msg == Program.WindowRestoreMessage){ if (WindowsUtils.CurrentProcessID == m.WParam.ToInt32()){ @@ -357,6 +338,10 @@ public void ReloadColumns(){ browser.ReloadColumns(); } + public void PlaySoundNotification(){ + browser.PlaySoundNotification(); + } + public void ApplyROT13(){ browser.ApplyROT13(); } @@ -459,19 +444,7 @@ public void OpenPlugins(){ } } - public void PlayNotificationSound(){ - if (Config.NotificationSoundPath.Length == 0){ - return; - } - - if (soundNotification == null){ - soundNotification = new SoundNotification(); - soundNotification.PlaybackError += soundNotification_PlaybackError; - } - - soundNotification.SetVolume(Config.NotificationSoundVolume); - soundNotification.Play(Config.NotificationSoundPath); - + public void OnTweetSound(){ TriggerAnalyticsEvent(AnalyticsFile.Event.SoundNotification); } diff --git a/Core/Notification/FormNotificationBase.cs b/Core/Notification/FormNotificationBase.cs index 86b5c055..67e119a7 100644 --- a/Core/Notification/FormNotificationBase.cs +++ b/Core/Notification/FormNotificationBase.cs @@ -139,8 +139,7 @@ protected FormNotificationBase(FormBrowser owner, bool enableContextMenu){ DpiScale = this.GetDPIScale(); - DefaultResourceHandlerFactory handlerFactory = (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory; - handlerFactory.RegisterHandler(TwitterUtils.TweetDeckURL, this.resourceHandler); + browser.GetHandlerFactory().RegisterHandler(TwitterUtils.TweetDeckURL, this.resourceHandler); Controls.Add(browser); diff --git a/Core/Notification/SoundNotification.cs b/Core/Notification/SoundNotification.cs index 2d6f1436..ca563cc5 100644 --- a/Core/Notification/SoundNotification.cs +++ b/Core/Notification/SoundNotification.cs @@ -1,32 +1,53 @@ -using System; -using TweetLib.Audio; +using System.Drawing; +using System.IO; +using System.Windows.Forms; +using CefSharp; +using TweetDuck.Core.Controls; +using TweetDuck.Core.Other; +using TweetDuck.Core.Other.Settings; namespace TweetDuck.Core.Notification{ - sealed class SoundNotification : IDisposable{ - public string SupportedFormats => player.SupportedFormats; - public event EventHandler<PlaybackErrorEventArgs> PlaybackError; + static class SoundNotification{ + public const string SupportedFormats = "*.wav;*.ogg;*.flac;*.opus;*.weba;*.webm"; // TODO add mp3 when supported + + public static IResourceHandler CreateFileHandler(string path){ + string mimeType; - private readonly AudioPlayer player; + switch(Path.GetExtension(path)){ + case ".weba": + case ".webm": mimeType = "audio/webm"; break; + case ".wav": mimeType = "audio/wav"; break; + case ".ogg": mimeType = "audio/ogg"; break; + case ".flac": mimeType = "audio/flac"; break; + case ".opus": mimeType = "audio/ogg; codecs=opus"; break; + case ".mp3": TryShowError("MP3 sound notifications are temporarily unsupported, please convert the file to another format, such as .ogg, .wav, or .flac."); return null; + default: mimeType = null; break; + } - public SoundNotification(){ - this.player = AudioPlayer.New(); - this.player.PlaybackError += Player_PlaybackError; + try{ + return ResourceHandler.FromFilePath(path, mimeType); + }catch{ + TryShowError("Could not find custom notification sound file:\n"+path); + return null; + } } - public void Play(string file){ - player.Play(file); - } + private static void TryShowError(string message){ + FormBrowser browser = FormManager.TryFind<FormBrowser>(); - public bool SetVolume(int volume){ - return player.SetVolume(volume); - } + browser?.InvokeAsyncSafe(() => { + using(FormMessage form = new FormMessage("Sound Notification Error", message, MessageBoxIcon.Error)){ + form.AddButton(FormMessage.Ignore, ControlType.Cancel | ControlType.Focused); + + Button btnViewOptions = form.AddButton("View Options"); + btnViewOptions.Width += 16; + btnViewOptions.Location = new Point(btnViewOptions.Location.X-16, btnViewOptions.Location.Y); - private void Player_PlaybackError(object sender, PlaybackErrorEventArgs e){ - PlaybackError?.Invoke(this, e); - } - - public void Dispose(){ - player.Dispose(); + if (form.ShowDialog() == DialogResult.OK && form.ClickedButton == btnViewOptions){ + browser.OpenSettings(typeof(TabSettingsSounds)); + } + } + }); } } } diff --git a/Core/Other/FormSettings.cs b/Core/Other/FormSettings.cs index 60ae3b9a..38fd460d 100644 --- a/Core/Other/FormSettings.cs +++ b/Core/Other/FormSettings.cs @@ -40,7 +40,7 @@ public FormSettings(FormBrowser browser, PluginManager plugins, UpdateHandler up AddButton("Locales", () => new TabSettingsLocales()); AddButton("System Tray", () => new TabSettingsTray()); AddButton("Notifications", () => new TabSettingsNotifications(new FormNotificationExample(this.browser, this.plugins))); - AddButton("Sounds", () => new TabSettingsSounds()); + AddButton("Sounds", () => new TabSettingsSounds(this.browser.PlaySoundNotification)); AddButton("Feedback", () => new TabSettingsFeedback(analytics, AnalyticsReportGenerator.ExternalInfo.From(this.browser), this.plugins)); AddButton("Advanced", () => new TabSettingsAdvanced(this.browser.ReinjectCustomCSS)); diff --git a/Core/Other/Settings/TabSettingsSounds.Designer.cs b/Core/Other/Settings/TabSettingsSounds.Designer.cs index d3784de1..b5bf2596 100644 --- a/Core/Other/Settings/TabSettingsSounds.Designer.cs +++ b/Core/Other/Settings/TabSettingsSounds.Designer.cs @@ -36,6 +36,7 @@ private void InitializeComponent() { this.trackBarVolume = new System.Windows.Forms.TrackBar(); this.flowPanel = new System.Windows.Forms.FlowLayoutPanel(); this.panelVolume = new System.Windows.Forms.Panel(); + this.volumeUpdateTimer = new System.Windows.Forms.Timer(this.components); this.panelSoundNotification.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).BeginInit(); this.flowPanel.SuspendLayout(); @@ -170,6 +171,11 @@ private void InitializeComponent() { this.panelVolume.Size = new System.Drawing.Size(322, 36); this.panelVolume.TabIndex = 2; // + // volumeUpdateTimer + // + this.volumeUpdateTimer.Interval = 250; + this.volumeUpdateTimer.Tick += new System.EventHandler(this.volumeUpdateTimer_Tick); + // // TabSettingsSounds // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -201,5 +207,6 @@ private void InitializeComponent() { private System.Windows.Forms.TrackBar trackBarVolume; private System.Windows.Forms.FlowLayoutPanel flowPanel; private System.Windows.Forms.Panel panelVolume; + private System.Windows.Forms.Timer volumeUpdateTimer; } } diff --git a/Core/Other/Settings/TabSettingsSounds.cs b/Core/Other/Settings/TabSettingsSounds.cs index 8cb3c45b..759fd8ba 100644 --- a/Core/Other/Settings/TabSettingsSounds.cs +++ b/Core/Other/Settings/TabSettingsSounds.cs @@ -4,25 +4,18 @@ using System.Windows.Forms; using TweetDuck.Core.Controls; using TweetDuck.Core.Notification; -using TweetLib.Audio; namespace TweetDuck.Core.Other.Settings{ sealed partial class TabSettingsSounds : BaseTabSettings{ - private readonly SoundNotification soundNotification; - private readonly bool supportsChangingVolume; + private readonly Action playSoundNotification; - public TabSettingsSounds(){ + public TabSettingsSounds(Action playSoundNotification){ InitializeComponent(); - soundNotification = new SoundNotification(); - soundNotification.PlaybackError += sound_PlaybackError; - Disposed += (sender, args) => soundNotification.Dispose(); + this.playSoundNotification = playSoundNotification; - supportsChangingVolume = soundNotification.SetVolume(Config.NotificationSoundVolume); - toolTip.SetToolTip(tbCustomSound, "When empty, the default TweetDeck sound notification is used."); - - trackBarVolume.Enabled = supportsChangingVolume && !string.IsNullOrEmpty(Config.NotificationSoundPath); + trackBarVolume.SetValueSafe(Config.NotificationSoundVolume); labelVolumeValue.Text = trackBarVolume.Value+"%"; @@ -39,22 +32,29 @@ public override void OnReady(){ public override void OnClosing(){ Config.NotificationSoundPath = tbCustomSound.Text; + Config.NotificationSoundVolume = trackBarVolume.Value; + } + + private bool RefreshCanPlay(){ + bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text); + bool canPlay = isEmpty || File.Exists(tbCustomSound.Text); + + tbCustomSound.ForeColor = canPlay ? SystemColors.WindowText : Color.Red; + btnPlaySound.Enabled = canPlay; + btnResetSound.Enabled = !isEmpty; + return canPlay; } private void tbCustomSound_TextChanged(object sender, EventArgs e){ - bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text); - tbCustomSound.ForeColor = isEmpty || File.Exists(tbCustomSound.Text) ? SystemColors.WindowText : Color.Red; - btnPlaySound.Enabled = !isEmpty; - btnResetSound.Enabled = !isEmpty; - trackBarVolume.Enabled = supportsChangingVolume && !isEmpty; + RefreshCanPlay(); } private void btnPlaySound_Click(object sender, EventArgs e){ - soundNotification.Play(tbCustomSound.Text); - } - - private void sound_PlaybackError(object sender, PlaybackErrorEventArgs e){ - FormMessage.Error("Notification Sound Error", "Could not play custom notification sound.\n"+e.Message, FormMessage.OK); + if (RefreshCanPlay()){ + Config.NotificationSoundPath = tbCustomSound.Text; + Config.NotificationSoundVolume = trackBarVolume.Value; + playSoundNotification(); + } } private void btnBrowseSound_Click(object sender, EventArgs e){ @@ -62,7 +62,7 @@ private void btnBrowseSound_Click(object sender, EventArgs e){ AutoUpgradeEnabled = true, DereferenceLinks = true, Title = "Custom Notification Sound", - Filter = "Sound file ("+soundNotification.SupportedFormats+")|"+soundNotification.SupportedFormats+"|All files (*.*)|*.*" + Filter = $"Sound file ({SoundNotification.SupportedFormats})|{SoundNotification.SupportedFormats}|All files (*.*)|*.*" }){ if (dialog.ShowDialog() == DialogResult.OK){ tbCustomSound.Text = dialog.FileName; @@ -75,9 +75,14 @@ private void btnResetSound_Click(object sender, EventArgs e){ } private void trackBarVolume_ValueChanged(object sender, EventArgs e){ + volumeUpdateTimer.Stop(); + volumeUpdateTimer.Start(); + labelVolumeValue.Text = trackBarVolume.Value+"%"; + } + + private void volumeUpdateTimer_Tick(object sender, EventArgs e){ Config.NotificationSoundVolume = trackBarVolume.Value; - soundNotification.SetVolume(Config.NotificationSoundVolume); - labelVolumeValue.Text = Config.NotificationSoundVolume+"%"; + volumeUpdateTimer.Stop(); } } } diff --git a/Core/TweetDeckBrowser.cs b/Core/TweetDeckBrowser.cs index 0b0623a4..47fb7ab6 100644 --- a/Core/TweetDeckBrowser.cs +++ b/Core/TweetDeckBrowser.cs @@ -7,6 +7,7 @@ using TweetDuck.Core.Controls; using TweetDuck.Core.Handling; using TweetDuck.Core.Handling.General; +using TweetDuck.Core.Notification; using TweetDuck.Core.Utils; using TweetDuck.Plugins; using TweetDuck.Plugins.Enums; @@ -36,6 +37,8 @@ public bool IsTweetDeckWebsite{ private readonly ChromiumWebBrowser browser; private readonly PluginManager plugins; + private string prevSoundNotificationPath = null; + public TweetDeckBrowser(FormBrowser owner, PluginManager plugins, TweetDeckBridge bridge){ this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){ DialogHandler = new FileDialogHandler(), @@ -70,6 +73,7 @@ public TweetDeckBrowser(FormBrowser owner, PluginManager plugins, TweetDeckBridg Program.UserConfig.MuteToggled += UserConfig_MuteToggled; Program.UserConfig.ZoomLevelChanged += UserConfig_ZoomLevelChanged; + Program.UserConfig.SoundNotificationChanged += UserConfig_SoundNotificationInfoChanged; } // setup and management @@ -91,6 +95,7 @@ public void Dispose(){ Program.UserConfig.MuteToggled -= UserConfig_MuteToggled; Program.UserConfig.ZoomLevelChanged -= UserConfig_ZoomLevelChanged; + Program.UserConfig.SoundNotificationChanged -= UserConfig_SoundNotificationInfoChanged; browser.Dispose(); } @@ -129,6 +134,7 @@ private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){ ScriptLoader.ExecuteFile(e.Frame, "code.js"); InjectBrowserCSS(); ReinjectCustomCSS(Program.UserConfig.CustomBrowserCSS); + UserConfig_SoundNotificationInfoChanged(null, EventArgs.Empty); plugins.ExecutePlugins(e.Frame, PluginEnvironment.Browser); TweetDeckBridge.ResetStaticProperties(); @@ -167,6 +173,27 @@ private void UserConfig_ZoomLevelChanged(object sender, EventArgs e){ BrowserUtils.SetZoomLevel(browser.GetBrowser(), Program.UserConfig.ZoomLevel); } + private void UserConfig_SoundNotificationInfoChanged(object sender, EventArgs e){ + const string soundUrl = "https://ton.twimg.com/tduck/updatesnd"; + bool hasCustomSound = Program.UserConfig.IsCustomSoundNotificationSet; + + if (prevSoundNotificationPath != Program.UserConfig.NotificationSoundPath){ + DefaultResourceHandlerFactory handlerFactory = browser.GetHandlerFactory(); + IResourceHandler resourceHandler = hasCustomSound ? SoundNotification.CreateFileHandler(Program.UserConfig.NotificationSoundPath) : null; + + if (resourceHandler != null){ + handlerFactory.RegisterHandler(soundUrl, resourceHandler); + } + else{ + handlerFactory.UnregisterHandler(soundUrl); + } + + prevSoundNotificationPath = Program.UserConfig.NotificationSoundPath; + } + + browser.ExecuteScriptAsync("TDGF_setSoundNotificationData", hasCustomSound, Program.UserConfig.NotificationSoundVolume); + } + // external handling public UpdateHandler CreateUpdateHandler(UpdaterSettings settings){ @@ -215,6 +242,10 @@ public void ReloadColumns(){ browser.ExecuteScriptAsync("TDGF_reloadColumns()"); } + public void PlaySoundNotification(){ + browser.ExecuteScriptAsync("TDGF_playSoundNotification()"); + } + public void ApplyROT13(){ browser.ExecuteScriptAsync("TDGF_applyROT13()"); } diff --git a/Core/Utils/BrowserUtils.cs b/Core/Utils/BrowserUtils.cs index 7109ce36..90789a68 100644 --- a/Core/Utils/BrowserUtils.cs +++ b/Core/Utils/BrowserUtils.cs @@ -35,6 +35,10 @@ public static ChromiumWebBrowser AsControl(this IWebBrowser browserControl){ return (ChromiumWebBrowser)browserControl; } + public static DefaultResourceHandlerFactory GetHandlerFactory(this ChromiumWebBrowser browser){ + return (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory; + } + private const string TwitterTrackingUrl = "t.co"; public enum UrlCheckResult{ diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js index d3526bbf..1d66c8c4 100644 --- a/Resources/Scripts/code.js +++ b/Resources/Scripts/code.js @@ -507,10 +507,35 @@ // // Block: Hook into the notification sound effect. // + HTMLAudioElement.prototype.play = prependToFunction(HTMLAudioElement.prototype.play, function(){ - return $TDX.muteNotifications || $TDX.hasCustomNotificationSound; + return $TDX.muteNotifications; }); + window.TDGF_setSoundNotificationData = function(custom, volume){ + let audio = document.getElementById("update-sound"); + audio.volume = volume/100; + + const sourceId = "tduck-custom-sound-source"; + let source = document.getElementById(sourceId); + + if (custom && !source){ + source = document.createElement("source"); + source.id = sourceId; + source.src = "https://ton.twimg.com/tduck/updatesnd"; + audio.prepend(source); + } + else if (!custom && source){ + audio.removeChild(source); + } + + audio.load(); + }; + + window.TDGF_playSoundNotification = function(){ + document.getElementById("update-sound").play(); + }; + // // Block: Update highlighted column and tweet for context menu and other functionality. // diff --git a/TweetDuck.csproj b/TweetDuck.csproj index 23423925..038ed7f3 100644 --- a/TweetDuck.csproj +++ b/TweetDuck.csproj @@ -378,10 +378,6 @@ <Content Include="Resources\Scripts\update.js" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="lib\TweetLib.Audio\TweetLib.Audio.csproj"> - <Project>{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}</Project> - <Name>TweetLib.Audio</Name> - </ProjectReference> <ProjectReference Include="subprocess\TweetDuck.Browser.csproj"> <Project>{b10b0017-819e-4f71-870f-8256b36a26aa}</Project> <Name>TweetDuck.Browser</Name> diff --git a/TweetDuck.sln b/TweetDuck.sln index 95c0b692..f4155fbc 100644 --- a/TweetDuck.sln +++ b/TweetDuck.sln @@ -8,8 +8,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Browser", "subpro EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "tests\UnitTests.csproj", "{A958FA7A-4A2C-42A7-BFA0-159343483F4E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Audio", "lib\TweetLib.Audio\TweetLib.Audio.csproj", "{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Video", "video\TweetDuck.Video.csproj", "{278B2D11-402D-44B6-B6A1-8FA67DB65565}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Communication", "lib\TweetLib.Communication\TweetLib.Communication.csproj", "{72473763-4B9D-4FB6-A923-9364B2680F06}" @@ -32,10 +30,6 @@ Global {A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.ActiveCfg = Debug|x86 {A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.Build.0 = Debug|x86 {A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Release|x86.ActiveCfg = Release|x86 - {E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Debug|x86.ActiveCfg = Debug|x86 - {E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Debug|x86.Build.0 = Debug|x86 - {E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Release|x86.ActiveCfg = Release|x86 - {E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Release|x86.Build.0 = Release|x86 {278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.ActiveCfg = Debug|x86 {278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.Build.0 = Debug|x86 {278B2D11-402D-44B6-B6A1-8FA67DB65565}.Release|x86.ActiveCfg = Release|x86 diff --git a/bld/gen_upd.iss b/bld/gen_upd.iss index fa3b0d18..eba60747 100644 --- a/bld/gen_upd.iss +++ b/bld/gen_upd.iss @@ -59,6 +59,7 @@ Type: filesandordirs; Name: "{localappdata}\{#MyAppName}\Cache" Type: filesandordirs; Name: "{localappdata}\{#MyAppName}\GPUCache" [InstallDelete] +Type: files; Name: "{app}\TweetLib.Audio.dll" Type: filesandordirs; Name: "{app}\plugins\official" Type: files; Name: "{app}\locales\am.pak" Type: files; Name: "{app}\locales\ar.pak" diff --git a/lib/TweetLib.Audio/AudioPlayer.cs b/lib/TweetLib.Audio/AudioPlayer.cs deleted file mode 100644 index 29879ec8..00000000 --- a/lib/TweetLib.Audio/AudioPlayer.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using TweetLib.Audio.Impl; - -namespace TweetLib.Audio{ - public abstract class AudioPlayer : IDisposable{ - private static bool? IsWMPAvailable; - - public static AudioPlayer New(){ - if (IsWMPAvailable.HasValue){ - if (IsWMPAvailable.Value){ - return new SoundPlayerImplWMP(); - } - else{ - return new SoundPlayerImplFallback(); - } - } - - try{ - SoundPlayerImplWMP implWMP = new SoundPlayerImplWMP(); - IsWMPAvailable = true; - return implWMP; - }catch(COMException){ - IsWMPAvailable = false; - return new SoundPlayerImplFallback(); - } - } - - public abstract string SupportedFormats { get; } - public abstract event EventHandler<PlaybackErrorEventArgs> PlaybackError; - - public abstract void Play(string file); - public abstract bool SetVolume(int volume); - protected abstract void Dispose(bool disposing); - - public void Dispose(){ - Dispose(true); - GC.SuppressFinalize(this); - } - } -} diff --git a/lib/TweetLib.Audio/Impl/SoundPlayerImplFallback.cs b/lib/TweetLib.Audio/Impl/SoundPlayerImplFallback.cs deleted file mode 100644 index e13021ce..00000000 --- a/lib/TweetLib.Audio/Impl/SoundPlayerImplFallback.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.IO; -using System.Media; - -namespace TweetLib.Audio.Impl{ - sealed class SoundPlayerImplFallback : AudioPlayer{ - public override string SupportedFormats => "*.wav"; - - public override event EventHandler<PlaybackErrorEventArgs> PlaybackError; - - private readonly SoundPlayer player; - private bool ignorePlaybackError; - - public SoundPlayerImplFallback(){ - player = new SoundPlayer{ - LoadTimeout = 5000 - }; - } - - public override void Play(string file){ - if (player.SoundLocation != file){ - player.SoundLocation = file; - ignorePlaybackError = false; - } - - try{ - player.Play(); - }catch(FileNotFoundException e){ - OnNotificationSoundError("File not found: "+e.FileName); - }catch(InvalidOperationException){ - OnNotificationSoundError("File format was not recognized."); - }catch(TimeoutException){ - OnNotificationSoundError("File took too long to load."); - } - } - - public override bool SetVolume(int volume){ - return false; - } - - protected override void Dispose(bool disposing){ - player.Dispose(); - } - - private void OnNotificationSoundError(string message){ - if (!ignorePlaybackError){ - PlaybackErrorEventArgs args = new PlaybackErrorEventArgs(message); - PlaybackError?.Invoke(this, args); - ignorePlaybackError = args.Ignore; - } - } - } -} diff --git a/lib/TweetLib.Audio/Impl/SoundPlayerImplWMP.cs b/lib/TweetLib.Audio/Impl/SoundPlayerImplWMP.cs deleted file mode 100644 index b68376aa..00000000 --- a/lib/TweetLib.Audio/Impl/SoundPlayerImplWMP.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Windows.Forms; -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 Form owner; - private readonly ControlWMP wmp; - private bool wasTryingToPlay; - private bool ignorePlaybackError; - - private WindowsMediaPlayer Player => wmp.Ocx; - - public SoundPlayerImplWMP(){ - owner = new Form(); - wmp = new ControlWMP(); - wmp.BeginInit(); - owner.Controls.Add(wmp); - wmp.EndInit(); - - Player.uiMode = "none"; - Player.settings.autoStart = false; - Player.settings.enableErrorDialogs = false; - Player.settings.invokeURLs = false; - Player.settings.volume = 0; - 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 bool SetVolume(int volume){ - Player.settings.volume = volume; - return true; - } - - protected override void Dispose(bool disposing){ - wmp.Dispose(); - owner.Dispose(); - } - - 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){ - PlaybackErrorEventArgs args = new PlaybackErrorEventArgs(message); - PlaybackError?.Invoke(this, args); - ignorePlaybackError = args.Ignore; - } - } - } - - [Clsid("{6bf52a52-394a-11d3-b153-00c04f79faa6}")] - private sealed class ControlWMP : AxHost{ - public WindowsMediaPlayer Ocx { get; private set; } - - public ControlWMP() : base("6bf52a52-394a-11d3-b153-00c04f79faa6"){} - - protected override void AttachInterfaces(){ - Ocx = (WindowsMediaPlayer)GetOcx(); - } - } - } -} diff --git a/lib/TweetLib.Audio/PlaybackErrorEventArgs.cs b/lib/TweetLib.Audio/PlaybackErrorEventArgs.cs deleted file mode 100644 index f8f07325..00000000 --- a/lib/TweetLib.Audio/PlaybackErrorEventArgs.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace TweetLib.Audio{ - public sealed class PlaybackErrorEventArgs : EventArgs{ - public string Message { get; } - public bool Ignore { get; set; } - - public PlaybackErrorEventArgs(string message){ - this.Message = message; - this.Ignore = false; - } - } -} diff --git a/lib/TweetLib.Audio/Properties/AssemblyInfo.cs b/lib/TweetLib.Audio/Properties/AssemblyInfo.cs deleted file mode 100644 index c38326d2..00000000 --- a/lib/TweetLib.Audio/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("TweetDuck Audio Library")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("TweetDuck Audio Library")] -[assembly: AssemblyCopyright("")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("e9e1fd1b-f480-45b7-9970-be2ecfd309ac")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.1.0")] -[assembly: AssemblyFileVersion("1.1.1.0")] diff --git a/lib/TweetLib.Audio/TweetLib.Audio.csproj b/lib/TweetLib.Audio/TweetLib.Audio.csproj deleted file mode 100644 index 69adb783..00000000 --- a/lib/TweetLib.Audio/TweetLib.Audio.csproj +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">x86</Platform> - <ProjectGuid>{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}</ProjectGuid> - <OutputType>Library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>TweetLib.Audio</RootNamespace> - <AssemblyName>TweetLib.Audio</AssemblyName> - <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - <ResolveComReferenceSilent>True</ResolveComReferenceSilent> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> - <PlatformTarget>x86</PlatformTarget> - <OutputPath>bin\x86\Debug\</OutputPath> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> - <PlatformTarget>x86</PlatformTarget> - <OutputPath>bin\x86\Release\</OutputPath> - <Optimize>true</Optimize> - </PropertyGroup> - <ItemGroup> - <Reference Include="System" /> - <Reference Include="System.Core" /> - <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Windows.Forms" /> - </ItemGroup> - <ItemGroup> - <Compile Include="AudioPlayer.cs" /> - <Compile Include="PlaybackErrorEventArgs.cs" /> - <Compile Include="Impl\SoundPlayerImplFallback.cs" /> - <Compile Include="Impl\SoundPlayerImplWMP.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - </ItemGroup> - <ItemGroup> - <COMReference Include="WMPLib"> - <Guid>{6BF52A50-394A-11D3-B153-00C04F79FAA6}</Guid> - <VersionMajor>1</VersionMajor> - <VersionMinor>0</VersionMinor> - <Lcid>0</Lcid> - <WrapperTool>tlbimp</WrapperTool> - <Isolated>False</Isolated> - <EmbedInteropTypes>True</EmbedInteropTypes> - </COMReference> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> -</Project> \ No newline at end of file